> ## Documentation Index
> Fetch the complete documentation index at: https://docs.monocle.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# @modelcontextprotocol/sdk

> Instrument your Model Context Protocol server for observability

This guide covers how to instrument an MCP server built with `@modelcontextprotocol/sdk`. You will learn how to:

* Install and configure the instrumentation
* Track tool calls, resources, and prompts
* Capture inputs and outputs

For the full list of required span attributes and what powers the MCP dashboard, see the [MCP feature page](/features/mcp-monitoring).

## Installation

```bash theme={"theme":"vesper"}
npm install @monocle.sh/instrumentation-mcp
```

**Peer dependency:** `@modelcontextprotocol/sdk >= 1.0.0`

## Usage

Call `instrumentMcpServer()` on your server instance before connecting a transport. This wraps the server's internal handlers to create spans for every incoming request, notification, and outgoing message.

```typescript title="server.ts" theme={"theme":"vesper"}
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { instrumentMcpServer } from "@monocle.sh/instrumentation-mcp";

const server = new McpServer({
  name: "my-mcp-server",
  version: "1.0.0",
});

instrumentMcpServer(server);

server.tool("search", { query: z.string() }, async ({ query }) => {
  const results = await searchDatabase(query);
  return { content: [{ type: "text", text: JSON.stringify(results) }] };
});

const transport = new StdioServerTransport();
await server.connect(transport);
```

## Configuration

```typescript theme={"theme":"vesper"}
instrumentMcpServer(server, {
  // Capture tool/prompt arguments in span attributes (default: false)
  recordInputs: true,

  // Capture tool results and prompt messages in span attributes (default: false)
  recordOutputs: true,

  // Override auto-detected server name/version
  serverName: "my-server",
  serverVersion: "1.0.0",
});
```

## Spans

The instrumentation creates spans for three categories of MCP activity.

### Request spans

A **SERVER** span is created for every incoming JSON-RPC request (`tools/call`, `resources/read`, `prompts/get`, `initialize`, etc.).

The span name includes the target when available: `tools/call search`, `resources/read config://app`, `prompts/get weather`.

### Notification spans

A **SERVER** span is created for incoming notifications (e.g., `notifications/initialized`, `resources/changed`).

### Outgoing notification spans

A **CLIENT** span is created for outgoing notifications sent by the server (e.g., `resources/changed`).

### Error spans

Transport errors produce an **INTERNAL** span named `mcp.transport.error` with the exception recorded. JSON-RPC errors set `rpc.jsonrpc.error_code` and `rpc.jsonrpc.error_message` on the request span.

## SDK-specific attributes

In addition to the [standard MCP attributes](/features/mcp-monitoring#span-attributes), this instrumentation emits these extra attributes when recording is enabled.

### Input attributes (when `recordInputs: true`)

Tool arguments are captured as `mcp.request.argument.{key}` (JSON-stringified per key).

### Output attributes (when `recordOutputs: true`)

| Attribute                          | Description                      |
| ---------------------------------- | -------------------------------- |
| `mcp.tool.result.content_count`    | Number of content items returned |
| `mcp.tool.result.{i}.content_type` | Content type of each item        |
| `mcp.tool.result.{i}.content`      | Content value of each item       |
| `mcp.prompt.result.description`    | Prompt description               |
| `mcp.prompt.result.message_count`  | Number of messages returned      |
| `mcp.prompt.result.{i}.role`       | Message role                     |
| `mcp.prompt.result.{i}.content`    | Message content                  |
