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.

This is the canonical example shipped in the sedata-ai-packages repo at example-servers/typescript-mcp-server/. It instruments two tools:
  • calculate-bmi — pure math, no safety check.
  • text-summarizer — accepts free-form text, wrapped with safetyCheck.

Project setup

mkdir weather-mcp-server && cd weather-mcp-server
npm init -y
npm install @sedata-ai/mcp @modelcontextprotocol/sdk zod
npm install -D typescript ts-node @types/node
npx tsc --init
Set your token:
export SEDATA_TOKEN="sk_live_xxx"

server.ts

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

const NAME = 'weather-mcp-server'
const VERSION = '1.2.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)

// 1. Math tool — no safety needed
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 }) => {
    const output = { bmi: weightKg / (heightM * heightM) }
    return {
      content: [{ type: 'text', text: JSON.stringify(output) }],
      structuredContent: output,
    }
  },
)

// 2. Text tool — wrap with safetyCheck
server.registerTool(
  'text-summarizer',
  {
    title: 'Text Summarizer',
    description: 'Summarize text content',
    inputSchema: { text: z.string() },
    outputSchema: { summary: z.string() },
  },
  safetyCheck(
    async ({ text }: any) => {
      const summary = text.substring(0, 100) + '...'
      return {
        content: [{ type: 'text', text: JSON.stringify({ summary }) }],
        structuredContent: { summary },
      }
    },
    { parameterName: 'text', output_screen: true },
  ),
)

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

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

Run

npx ts-node server.ts
Drive it with any MCP client (Claude Desktop, Inspector, your agent runtime). After a few calls, traces appear at app.sedata-ai.tech within ~5 seconds.

What you’ll see

ToolSpanNotable attributes
calculate-bmitools/call calculate-bmimcp.tool.name, mcp.operation.duration
text-summarizertools/call text-summarizerAbove + mcp.safety_check.flagged, mcp.safety_check.latency_ms
If the safety API flags an input, the response includes structuredContent.summary === '🚫 CONTENT BLOCKED: ...' and the original handler is not called.

Variations

BMI calculator only

A minimal version with one tool, no safety.

Summarizer with safety

Focused walkthrough of the safety wrapper.