Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.sedata-ai.tech/llms.txt

Use this file to discover all available pages before exploring further.

The smallest possible end-to-end example: one tool, full instrumentation, graceful shutdown, no safety check.

server.ts

import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
import { instrumentServer } from '@sedata-ai/mcp'
import type { TelemetryConfig } from '@sedata-ai/mcp'
import { z } from 'zod'

const NAME = 'bmi-mcp'
const VERSION = '1.0.0'

const server = new McpServer({ name: NAME, version: VERSION })

const telemetryConfig: TelemetryConfig = {
  serverName: NAME,
  serverVersion: VERSION,
  exporterEndpoint: 'https://otel.sedata-ai.tech/v1',
  exporterAuth: { type: 'bearer', token: process.env.SEDATA_TOKEN! },
}

const telemetry = instrumentServer(server, telemetryConfig)

server.registerTool(
  'calculate-bmi',
  {
    title: 'BMI Calculator',
    description: 'Calculate Body Mass Index',
    inputSchema: { weightKg: z.number(), heightM: z.number() },
    outputSchema: { bmi: z.number() },
  },
  async ({ weightKg, heightM }) => {
    if (heightM <= 0) throw new RangeError('heightM must be > 0')
    const output = { bmi: weightKg / (heightM * heightM) }
    return {
      content: [{ type: 'text', text: JSON.stringify(output) }],
      structuredContent: output,
    }
  },
)

const stop = async (code = 0) => {
  await telemetry.shutdown()
  process.exit(code)
}
process.on('SIGINT', () => stop(0))
process.on('SIGTERM', () => stop(0))

const transport = new StdioServerTransport()
server.connect(transport)

Run

SEDATA_TOKEN=sk_live_xxx npx ts-node server.ts

What this demonstrates

Auto span on every call

Each call to calculate-bmi produces a tools/call calculate-bmi span with full attribute set.

Error attributes

The RangeError on bad input sets error.type, error.message, and mcp.operation.success: false.

Auto metrics

mcp.server.operation.duration and mcp.server.operation.count record automatically.

Graceful shutdown

SIGINT / SIGTERM trigger telemetry.shutdown() so the final metric batch flushes.

Trying error attribution

Send heightM: 0 and you’ll see a span with status ERROR and these attributes:
error.type             RangeError
error.message          heightM must be > 0
mcp.operation.success  false
The duration histogram is still recorded with mcp.operation.success: false, which is what you want for error-rate alerts.