2025-11-11 05:39:40 +08:00
import z from "zod"
import { Tool } from "./tool"
import DESCRIPTION from "./codesearch.txt"
const API_CONFIG = {
BASE_URL : "https://mcp.exa.ai" ,
ENDPOINTS : {
CONTEXT : "/mcp" ,
} ,
} as const
interface McpCodeRequest {
jsonrpc : string
id : number
method : string
params : {
name : string
arguments : {
query : string
tokensNum : number
}
}
}
interface McpCodeResponse {
jsonrpc : string
result : {
content : Array < {
type : string
text : string
} >
}
}
export const CodeSearchTool = Tool . define ( "codesearch" , {
description : DESCRIPTION ,
parameters : z.object ( {
query : z
. string ( )
. describe (
"Search query to find relevant context for APIs, Libraries, and SDKs. For example, 'React useState hook examples', 'Python pandas dataframe filtering', 'Express.js middleware', 'Next js partial prerendering configuration'" ,
) ,
tokensNum : z
. number ( )
. min ( 1000 )
. max ( 50000 )
. default ( 5000 )
. describe (
"Number of tokens to return (1000-50000). Default is 5000 tokens. Adjust this value based on how much context you need - use lower values for focused queries and higher values for comprehensive documentation." ,
) ,
} ) ,
async execute ( params , ctx ) {
2026-01-02 06:54:11 +08:00
await ctx . ask ( {
permission : "codesearch" ,
patterns : [ params . query ] ,
always : [ "*" ] ,
metadata : {
query : params.query ,
tokensNum : params.tokensNum ,
} ,
} )
2025-11-11 05:39:40 +08:00
const codeRequest : McpCodeRequest = {
jsonrpc : "2.0" ,
id : 1 ,
method : "tools/call" ,
params : {
name : "get_code_context_exa" ,
arguments : {
query : params.query ,
tokensNum : params.tokensNum || 5000 ,
} ,
} ,
}
const controller = new AbortController ( )
const timeoutId = setTimeout ( ( ) = > controller . abort ( ) , 30000 )
try {
const headers : Record < string , string > = {
accept : "application/json, text/event-stream" ,
"content-type" : "application/json" ,
}
const response = await fetch ( ` ${ API_CONFIG . BASE_URL } ${ API_CONFIG . ENDPOINTS . CONTEXT } ` , {
method : "POST" ,
headers ,
body : JSON.stringify ( codeRequest ) ,
signal : AbortSignal.any ( [ controller . signal , ctx . abort ] ) ,
} )
clearTimeout ( timeoutId )
if ( ! response . ok ) {
const errorText = await response . text ( )
throw new Error ( ` Code search error ( ${ response . status } ): ${ errorText } ` )
}
const responseText = await response . text ( )
// Parse SSE response
const lines = responseText . split ( "\n" )
for ( const line of lines ) {
if ( line . startsWith ( "data: " ) ) {
const data : McpCodeResponse = JSON . parse ( line . substring ( 6 ) )
if ( data . result && data . result . content && data . result . content . length > 0 ) {
return {
output : data.result.content [ 0 ] . text ,
title : ` Code search: ${ params . query } ` ,
metadata : { } ,
}
}
}
}
return {
output :
"No code snippets or documentation found. Please try a different query, be more specific about the library or programming concept, or check the spelling of framework names." ,
title : ` Code search: ${ params . query } ` ,
metadata : { } ,
}
} catch ( error ) {
clearTimeout ( timeoutId )
if ( error instanceof Error && error . name === "AbortError" ) {
throw new Error ( "Code search request timed out" )
}
throw error
}
} ,
} )