diff --git a/README.md b/README.md index c9c00c8..ca4195e 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ This server connects agents to your Elasticsearch data using the Model Context P * `list_indices`: List all available Elasticsearch indices * `get_mappings`: Get field mappings for a specific Elasticsearch index -* `search`: Perform an Elasticsearch search with the provided query DSL +* `search`: Perform an Elasticsearch search with the provided query DSL. Supports highlighting, query profiling, and query explanation. * `get_shards`: Get shard information for all or specific indices ## Prerequisites diff --git a/index.ts b/index.ts index 69a2728..73a9452 100644 --- a/index.ts +++ b/index.ts @@ -233,8 +233,20 @@ export async function createElasticsearchMcpServer( .describe( "Complete Elasticsearch query DSL object that can include query, size, from, sort, etc." ), + + profile: z + .boolean() + .optional() + .default(false) + .describe("Whether to include query profiling information"), + + explain: z + .boolean() + .optional() + .default(false) + .describe("Whether to include explanation of how the query was executed"), }, - async ({ index, queryBody }) => { + async ({ index, queryBody, profile, explain }) => { try { // Get mappings to identify text fields for highlighting const mappingResponse = await esClient.indices.getMapping({ @@ -246,6 +258,8 @@ export async function createElasticsearchMcpServer( const searchRequest: estypes.SearchRequest = { index, ...queryBody, + profile: profile, + explain: explain, }; // Always do highlighting @@ -292,6 +306,10 @@ export async function createElasticsearchMcpServer( } } + if (explain && hit._explanation) { + content += `\nExplanation:\n${JSON.stringify(hit._explanation, null, 2)}`; + } + return { type: "text" as const, text: content.trim(), @@ -307,8 +325,18 @@ export async function createElasticsearchMcpServer( }, showing ${result.hits.hits.length} from position ${from}`, }; + const fragments = [metadataFragment, ...contentFragments]; + + if (profile && result.profile) { + const profileFragment = { + type: "text" as const, + text: `\nQuery Profile:\n${JSON.stringify(result.profile, null, 2)}`, + }; + fragments.push(profileFragment); + } + return { - content: [metadataFragment, ...contentFragments], + content: fragments, }; } catch (error) { console.error( @@ -421,4 +449,4 @@ main().catch((error) => { error instanceof Error ? error.message : String(error) ); process.exit(1); -}); +}); \ No newline at end of file