Skip to content
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,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
Expand Down
32 changes: 30 additions & 2 deletions index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -315,8 +315,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({
Expand All @@ -328,6 +340,8 @@ export async function createElasticsearchMcpServer(
const searchRequest: estypes.SearchRequest = {
index,
...queryBody,
profile: profile,
explain: explain,
};

// Always do highlighting
Expand Down Expand Up @@ -374,6 +388,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(),
Expand All @@ -396,6 +414,16 @@ export async function createElasticsearchMcpServer(
}
: null;

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: aggregationsFragment
? [metadataFragment, aggregationsFragment, ...contentFragments]
Expand Down Expand Up @@ -516,4 +544,4 @@ main().catch((error) => {
error instanceof Error ? error.message : String(error)
);
process.exit(1);
});
});