Skip to content
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,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
44 changes: 36 additions & 8 deletions index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -313,10 +313,22 @@ export async function createElasticsearchMcpServer (config: ElasticsearchConfig)
}
)
.describe(
'Complete Elasticsearch query DSL object that can include query, size, from, sort, etc.'
)
"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 @@ -327,8 +339,10 @@ export async function createElasticsearchMcpServer (config: ElasticsearchConfig)

const searchRequest: estypes.SearchRequest = {
index,
...queryBody
}
...queryBody,
profile,
explain,
};

// Always do highlighting
if (indexMappings.properties != null) {
Expand Down Expand Up @@ -374,6 +388,10 @@ export async function createElasticsearchMcpServer (config: ElasticsearchConfig)
}
}

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 (config: ElasticsearchConfig)
}
: 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 != null)
? [metadataFragment, aggregationsFragment, ...contentFragments]
Expand Down Expand Up @@ -504,9 +532,9 @@ async function main (): Promise<void> {
// by requiring the stdio protocol (http will come later)
if (process.env.RUNNING_IN_CONTAINER === "true") {
if (process.argv.length != 3 || process.argv[2] !== "stdio" ) {
console.log("Missing protocol argument.");
console.log("Usage: npm start stdio");
process.exit(1);
console.log("Missing protocol argument.")
console.log("Usage: npm start stdio")
process.exit(1)
}
}

Expand Down