> ## 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.

# instrumentServer

> Patch an MCP server with OpenTelemetry tracing, metrics, and safety hooks.

```ts theme={null}
function instrumentServer(
  server: McpServer,
  config: TelemetryConfig,
): ObservabilityInstance
```

Constructs a `TelemetryManager`, wires up the OpenTelemetry Node SDK, then
calls `McpServerInstrumentation.instrument()` to patch
`server.registerTool` so every subsequent tool registration produces spans
and metrics automatically.

## Parameters

<ParamField path="server" type="McpServer" required>
  An instance of `McpServer` from `@modelcontextprotocol/sdk/server/mcp`.
  Must be passed before any tools are registered (instrumentation only
  applies to tools registered after this call).
</ParamField>

<ParamField path="config" type="TelemetryConfig" required>
  Configuration for the telemetry pipeline. See the
  [`TelemetryConfig` reference](/api-reference/types/telemetry-config) for
  every field.
</ParamField>

## Returns

<ResponseField name="instance" type="ObservabilityInstance">
  An object with helpers for custom instrumentation and shutdown:

  * `startActiveSpan(name, attributes, fn)`
  * `getHistogram(name, options)`
  * `getIncrementCounter(name, options)`
  * `processTelemetryAttributes(data)`
  * `shutdown(): Promise<void>`

  See [`ObservabilityInstance`](/api-reference/types/observability-instance).
</ResponseField>

## Example

```ts theme={null}
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'
import { instrumentServer } from '@sedata-ai/mcp'
import type { TelemetryConfig } from '@sedata-ai/mcp'

const server = new McpServer({ name: 'weather-mcp', version: '1.0.0' })

const telemetryConfig: TelemetryConfig = {
  serverName: 'weather-mcp',
  serverVersion: '1.0.0',
  exporterEndpoint: 'https://otel.sedata-ai.tech/v1',
  exporterAuth: {
    type: 'bearer',
    token: process.env.SEDATA_TOKEN!,
  },
  samplingRate: 0.25,
  enableArgumentCollection: false,
}

const telemetry = instrumentServer(server, telemetryConfig)
```

## Side effects

Calling `instrumentServer` does several things at once:

1. **Validates** the config via `ConfigValidator.validate(config)`. Throws on
   invalid input (missing endpoint, bad sampling rate, malformed auth).
2. **Stores the API key** for the safety-check API. The token from
   `exporterAuth.apiKey` or `exporterAuth.token` is forwarded.
3. **Starts the OpenTelemetry Node SDK** with trace + metric exporters,
   sampler, and resource detectors.
4. **Patches `server.registerTool`** to wrap every handler in an
   instrumented function.

## When to call it

Always immediately after constructing the `McpServer`, before any
`registerTool`:

```ts theme={null}
const server = new McpServer({ name: 'X', version: '1.0.0' })
const telemetry = instrumentServer(server, config) // ← here
server.registerTool('my-tool', /* ... */)         // ← instrumented
```

Tools registered before `instrumentServer` are **not** instrumented.

## Errors

| Error                                                      | Cause                                                             |
| ---------------------------------------------------------- | ----------------------------------------------------------------- |
| `exporterEndpoint is required`                             | `exporterEndpoint` missing and `exporterType` is not `'console'`. |
| `samplingRate must be between 0 and 1`                     | Out-of-range `samplingRate`.                                      |
| `metricExportIntervalMs must be >0`                        | Non-positive interval.                                            |
| `batchTimeout must be >=0`                                 | Non-positive timeout.                                             |
| `Bearer token is required when using bearer auth`          | `exporterAuth.type === 'bearer'` with no `token`.                 |
| `API key is required when using apiKey auth`               | `exporterAuth.type === 'apiKey'` with no `apiKey`.                |
| `Username and password are required when using basic auth` | `basic` auth with missing fields.                                 |

All thrown synchronously at the call site.

## See also

<CardGroup cols={2}>
  <Card title="TelemetryConfig" icon="sliders" href="/api-reference/types/telemetry-config">
    Every config field with defaults.
  </Card>

  <Card title="ObservabilityInstance" icon="cube" href="/api-reference/types/observability-instance">
    The object returned by this function.
  </Card>
</CardGroup>
