Skip to content

Conversation

@anuraaga
Copy link
Contributor

This is just a proposal since there was an idea about enabling OTel for the MCP server. Since the repo is experimental I figured it doesn't hurt to just send the PR - it's quite small so it also doesn't hurt to close if not ready for this yet.

With this, I can get a full trace from a vercel AI client with instrumentation set up as well. Note cat.indices being created by the ES SDK in this server.

image

/cc @codefromthecrypt @serenachou

const {createOpenAI} = require('@ai-sdk/openai');
const {StdioClientTransport} = require('@modelcontextprotocol/sdk/client/stdio.js');
const {experimental_createMCPClient, extractReasoningMiddleware, generateText, wrapLanguageModel} = require('ai');

const openai = createOpenAI({
    baseURL: process.env.OPENAI_BASE_URL || 'https://api.openai.com/v1'
});
const model = process.env.CHAT_MODEL || 'gpt-4o-mini';

/**
 * Runs the agent with the given tools.
 *
 * @param {import('ai').ToolSet} tools - The tools the LLM can use to answer the question.
 */
async function runAgent(tools) {
    const {text} = await generateText({
        // If using reasoning models, remove the format rewards from output. Non-reasoning models will not have
        // them making it effectively a no-op.
        model: wrapLanguageModel({
            model: openai(model),
            middleware: [extractReasoningMiddleware({ tagName: 'think' })],
        }),
        messages: [{role: 'user', content: "What indices do I have in my Elasticsearch cluster?"}],
        temperature: 0,
        tools,
        tool_choice: 'auto',
        maxSteps: 10,
        experimental_telemetry: {isEnabled: true},
    });

    console.log(text);
}

async function main() {
    const transport = new StdioClientTransport({
        command: "npx",
        args: ["tsx", "../../../mcp-server-elasticsearch/index.ts"],
        env: {
            PATH: process.env.PATH,
            ES_URL: "http://localhost:9200",
            ES_USERNAME: "elastic",
            ES_PASSWORD: "elastic",
            OTEL_SERVICE_NAME: "mcp-server-elasticsearch",
        },
    });
    const client = await experimental_createMCPClient({transport});
    try {
        const tools = await client.tools();
        await runAgent(tools);
    } finally {
        await client.close();
    }
}

main().catch(error => {
    console.error('Error:', error);
    process.exit(1);
});

@anuraaga anuraaga requested a review from a team as a code owner May 15, 2025 06:30
@codefromthecrypt
Copy link

cool. this approach is compatible with arize and MCP's official dotnet lib. It might make sense to try to get the official MCP typescript-sdk to include instrumentation like dotnet does. that might obviate the "manualInstrument" thing and make it simpler for others to try this out if this remains delayed or closed out.

@JoshMock JoshMock requested a review from a team as a code owner June 12, 2025 17:32
@JoshMock JoshMock enabled auto-merge (squash) June 12, 2025 17:35
@JoshMock
Copy link
Member

buildkite test this

@JoshMock JoshMock merged commit 02703f1 into elastic:main Jun 12, 2025
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants