From c454a99b08a3332539e634eacd8a10e7e97e8ef8 Mon Sep 17 00:00:00 2001 From: Zack Lee Date: Tue, 19 Nov 2024 13:18:49 -0500 Subject: [PATCH 1/5] Adding Specification section --- docs/guides/quickstart.mdx | 44 +++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/docs/guides/quickstart.mdx b/docs/guides/quickstart.mdx index 7091741..f120e19 100644 --- a/docs/guides/quickstart.mdx +++ b/docs/guides/quickstart.mdx @@ -70,28 +70,6 @@ flowchart LR All communication happens entirely on your machine - no data leaves your computer. The MCP protocol ensures that Claude Desktop can only perform approved database operations through well-defined interfaces. This gives you a secure way to let Claude analyze and interact with your local data while maintaining complete control over what it can access. -## MCP clients - -While this guide demonstrates MCP using Claude Desktop, several other applications support MCP integration: - - - - A high-performance, multiplayer code editor with built-in MCP support for AI-powered coding assistance - - - - Code intelligence platform featuring MCP integration for enhanced code search and analysis capabilities - - - -Each client may implement MCP features differently or support different capabilities. Check their respective documentation for specific setup instructions and supported features. - ## Prerequisites - macOS (Windows/Linux guides coming soon) @@ -286,6 +264,28 @@ Want to give Claude Desktop more local integration capabilities? Add these serve +## MCP clients + +While this guide demonstrates MCP using Claude Desktop, several other applications support MCP integration: + + + + A high-performance, multiplayer code editor with built-in MCP support for AI-powered coding assistance + + + + Code intelligence platform featuring MCP integration for enhanced code search and analysis capabilities + + + +Each client may implement MCP features differently or support different capabilities. Check their respective documentation for specific setup instructions and supported features. + ## Troubleshooting From 5f8e53eab4edd9f2256ec6301fde9b8a2eaeae53 Mon Sep 17 00:00:00 2001 From: Zack Lee Date: Tue, 19 Nov 2024 15:42:07 -0500 Subject: [PATCH 2/5] updating quickstart --- docs/guides/quickstart.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/guides/quickstart.mdx b/docs/guides/quickstart.mdx index f120e19..0cac428 100644 --- a/docs/guides/quickstart.mdx +++ b/docs/guides/quickstart.mdx @@ -3,7 +3,7 @@ title: "Quickstart" description: "Get started with MCP in less than 5 minutes" --- -MCP is a protocol that enables secure connections between clients, such as Claude Desktop app, and local services. In this quickstart guide, you'll learn how to: +MCP is a protocol that enables secure connections between clients, such as the Claude Desktop app, and local services. In this quickstart guide, you'll learn how to: - Set up a local SQLite database - Connect Claude Desktop to it through MCP From 80ed38558de78365be89ec651804fde4a0a8618f Mon Sep 17 00:00:00 2001 From: Zack Lee Date: Tue, 19 Nov 2024 16:15:09 -0500 Subject: [PATCH 3/5] migrated specs --- mint.json | 16 ++ specification/cancellation.mdx | 67 +++++ specification/completion.mdx | 188 ++++++++++++++ specification/jsonrpc.mdx | 166 ++++++++++++ specification/lifecycle.mdx | 202 +++++++++++++++ specification/logging.mdx | 175 +++++++++++++ specification/overview.mdx | 210 +++++++++++++++ specification/prompts.mdx | 299 ++++++++++++++++++++++ specification/resources.mdx | 452 +++++++++++++++++++++++++++++++++ specification/roots.mdx | 209 +++++++++++++++ specification/sampling.mdx | 236 +++++++++++++++++ specification/tools.mdx | 338 ++++++++++++++++++++++++ 12 files changed, 2558 insertions(+) create mode 100644 specification/cancellation.mdx create mode 100644 specification/completion.mdx create mode 100644 specification/jsonrpc.mdx create mode 100644 specification/lifecycle.mdx create mode 100644 specification/logging.mdx create mode 100644 specification/overview.mdx create mode 100644 specification/prompts.mdx create mode 100644 specification/resources.mdx create mode 100644 specification/roots.mdx create mode 100644 specification/sampling.mdx create mode 100644 specification/tools.mdx diff --git a/mint.json b/mint.json index 84964b2..b583f2d 100644 --- a/mint.json +++ b/mint.json @@ -104,6 +104,22 @@ "api-reference/typescript/class-reference", "api-reference/typescript/type-definitions" ] + }, + { + "group": "Specification", + "pages": [ + "specification/overview", + "specification/jsonrpc", + "specification/lifecycle", + "specification/prompts", + "specification/resources", + "specification/cancellation", + "specification/logging", + "specification/tools", + "specification/completion", + "specification/sampling", + "specification/roots" + ] } ], "footerSocials": { diff --git a/specification/cancellation.mdx b/specification/cancellation.mdx new file mode 100644 index 0000000..7a57dd5 --- /dev/null +++ b/specification/cancellation.mdx @@ -0,0 +1,67 @@ +--- +title: Cancellation +--- + +MCP supports request cancellation through a dedicated notification message. This allows either party to signal that they are no longer interested in the result of an in-flight request. + +## Cancellation Protocol + +When a party wants to cancel a request, they send a "cancelled" notification containing the ID of the request they wish to cancel: + +For example, initiating a request: + +```json +{ + "jsonrpc": "2.0", + "id": "abc123", + "method": "resources/read", + "params": { + "uri": "example://large-file" + } +} +``` + +… then some time later, cancelling that request: + +```json +{ + "jsonrpc": "2.0", + "method": "notifications/cancelled", + "params": { + "requestId": "abc123", + "reason": "User interrupted operation" + } +} +``` + +## Handling Cancellation + +Upon receiving a cancellation notification, the receiver SHOULD: + +1. Stop any processing related to the cancelled request +2. Free any resources associated with that request +3. Not send a response for the cancelled request (even if already computed) + +However, due to race conditions and message latency: + +- The notification may arrive after processing is complete +- A response may already be in transit when cancellation is received +- Multiple cancellation notifications for the same request ID may be received + +## Special Cases + +### Initialize Request + +The client MUST NOT attempt to cancel its `initialize` request. Cancelling initialization leaves the protocol in an undefined state. + +### Long-Running Operations + +For long-running operations that support progress notifications, progress notifications SHOULD stop being sent after receiving cancellation. + +## Best Practices + +1. Implement cancellation handlers for all long-running operations +2. Free resources promptly when receiving cancellation +3. Make cancellation handling idempotent +4. Include meaningful reason strings to aid debugging +5. Log cancellations appropriately for troubleshooting \ No newline at end of file diff --git a/specification/completion.mdx b/specification/completion.mdx new file mode 100644 index 0000000..3d765d1 --- /dev/null +++ b/specification/completion.mdx @@ -0,0 +1,188 @@ +--- +title: Argument Completion +--- +Argument Completion enables servers to provide argument completion for prompt and resource URI arguments. Clients can request completion options for specific arguments, and servers can return ranked suggestions. This allows clients to build rich user interfaces with intelligent argument completion for argument values. + +> **_NOTE:_** Argument Completion in MCP is similar to traditional IDE argument completion - it provides contextual suggestions based on available options, rather than AI-powered completion. The server maintains a fixed set of valid values for each argument and returns matching suggestions based on partial input. + +## Capabilities + +Support for argument completion is not indicated by a dedicated capability - servers that expose prompts or resources with arguments implicitly support argument completion for those arguments. Clients may attempt argument completion requests for any prompt or resource argument. + +## Concepts + +### Completion References + +When requesting completions, clients must specify what is being completed using a reference type: + +- `ref/prompt`: References a prompt by name +- `ref/resource`: References a resource by URI + +The reference identifies the context for completion suggestions. + +### Completion Results + +Servers return an array of completion values ranked by relevance, with a maximum of 100 items per response. If more results are available beyond the first 100, servers MUST set `hasMore: true` in the response to indicate that additional results can be retrieved with subsequent requests. The optional `total` field allows servers to specify the complete number of matches available, even if not all are returned in a single response. + +> **_NOTE:_** MCP does not currently support pagination of completion results - clients that need more than the first 100 matches must issue new completion requests with more specific argument values to narrow down the results. + +## Use Cases + +Common use cases for argument completion include: + +### Prompt Argument Completion + +A client requesting completion options for a prompt argument: + +```json +{ + "ref": { + "type": "ref/prompt", + "name": "code_review" + }, + "argument": { + "name": "language", + "value": "py" + } +} +``` + +The server might respond with language suggestions: + +```json +{ + "completion": { + "values": ["python", "pytorch", "pyside", "pyyaml"], + "total": 10, + "hasMore": true + } +} +``` + +### Resource URI Completion + +A client completing a path in a resource URI template: + +```json +{ + "ref": { + "type": "ref/resource", + "uri": "file://{path}" + }, + "argument": { + "name": "path", + "value": "/home/user/doc" + } +} +``` + +The server could respond with matching paths: + +```json +{ + "completion": { + "values": [ + "/home/user/documents", + "/home/user/docker", + "/home/user/downloads" + ], + "hasMore": false + } +} +``` + +## Diagram + +The following diagram visualizes a typical argument completion interaction between client and server: + +```mermaid +sequenceDiagram + participant Client + participant Server + + Note over Client,Server: Client requests completion options + Client->>Server: completion/complete + Server-->>Client: CompleteResult + + Note over Client,Server: Client may request more specific results + opt New completions requested + Client->>Server: completion/complete + Server-->>Client: CompleteResult + end +``` + +## Messages + +This section defines the protocol messages for argument completion in the Model Context Protocol (MCP). + +### Requesting Completions + +#### Request + +To get completion suggestions, the client MUST send a `completion/complete` request. + +Method: `completion/complete` +Params: + - `ref`: A `PromptReference` or `ResourceReference` indicating what is being completed + - `argument`: Object containing: + - `name`: The name of the argument being completed + - `value`: The current value to get completions for + +Example: +```json +{ + "jsonrpc": "2.0", + "id": 1, + "method": "completion/complete", + "params": { + "ref": { + "type": "ref/prompt", + "name": "code_review" + }, + "argument": { + "name": "language", + "value": "py" + } + } +} +``` + +#### Response + +The server MUST respond with a `CompleteResult` containing: + +- `completion`: Object containing: + - `values`: Array of completion suggestions (maximum 100) + - `total`: Optional total number of matches available + - `hasMore`: Optional boolean indicating if additional results exist + +Example: +```json +{ + "jsonrpc": "2.0", + "id": 1, + "result": { + "completion": { + "values": ["python", "pytorch", "pyside"], + "total": 10, + "hasMore": true + } + } +} +``` + +## Error Handling + +Servers MUST return appropriate errors if: +- The referenced prompt or resource does not exist +- The argument name is invalid +- Completion cannot be provided for other reasons + +Clients SHOULD be prepared to handle cases where completion is temporarily unavailable or returns errors. + +## Security Considerations + +Implementations MUST carefully consider: +- Rate limiting completion requests to prevent abuse +- Access control for sensitive completion suggestions +- Validation of completion inputs to prevent injection attacks \ No newline at end of file diff --git a/specification/jsonrpc.mdx b/specification/jsonrpc.mdx new file mode 100644 index 0000000..0d7f421 --- /dev/null +++ b/specification/jsonrpc.mdx @@ -0,0 +1,166 @@ +--- +title: Base Protocol +--- + +The Model Context Protocol (MCP) defines a set of JSON-RPC methods for communication between clients and servers in AI-assisted applications. MCP uses [JSON-RPC 2.0](https://www.jsonrpc.org/specification) as its base protocol. + +### Transport + +MCP client **SHOULD** use one of the following transport mechanisms, but are free to use alternative transports where applicable.: + +Standard Input/Output (STDIO) +: Communication occurs through the standard input and output streams. JSON-RPC + messages are sent as individual lines over these streams. Each message is a + complete JSON object serialized as a single line of text, terminated by a + newline character. The client writes requests to the server's standard input + and reads responses from the server's standard output. See [transports](transports.md) for more details. + +HTTP with Server-Sent Events (SSE) +: This transport uses HTTP (1.1 or above) as the underlying protocol. The client sends + requests to the server using standard HTTP POST requests with JSON-RPC + payloads. For server-to-client communication, Server-Sent Events (SSE) are + employed. The server keeps an open connection to the client and sends + messages as SSE events. See [transports](transports.md) for more details. + +### Message Format + +### Progress Notifications + +MCP supports progress tracking for long-running operations through out-of-band notifications. Progress notifications allow the sender of a request to provide updates about the operation's progress. + +To request progress notifications, include a `progressToken` in the request metadata: + +```json +{ + "jsonrpc": "2.0", + "id": 1, + "method": "some_method", + "params": { + "_meta": { + "progressToken": "abc123" + } + } +} +``` + +The receiver MAY then send progress notifications using the same token: + +```json +{ + "jsonrpc": "2.0", + "method": "notifications/progress", + "params": { + "progressToken": "abc123", + "progress": 50, + "total": 100 + } +} +``` + +### Pagination + +Many list operations in MCP support pagination using cursors. The server response will include a `nextCursor` if more results are available: + +```json +{ + "jsonrpc": "2.0", + "id": 1, + "result": { + "resources": [...], + "nextCursor": "next_page_token" + } +} +``` + +Clients can include a `cursor` parameter containing the opaque token from the server, +to obtain the next page starting from the cursor: + +```json +{ + "jsonrpc": "2.0", + "id": 1, + "method": "resources/list", + "params": { + "cursor": "some_opaque_token" + } +} +``` + + +Clients should continue making requests with the provided cursor until no `nextCursor` is returned. + +All messages in MCP **MUST** follow the [JSON-RPC 2.0](https://www.jsonrpc.org/specification) specification. The protocol defines three types of messages: + +1. Requests +2. Responses +3. Notifications + +#### Requests + +Requests are sent from the client to the server or vice versa. They **MUST** include a unique `id` and expect a response. + +#### Responses + +Responses are sent in reply to requests. They **MUST** include the same `id` as the corresponding request. + +#### Notifications + +Notifications are sent from the client to the server or vice versa. They do not expect a response and **MUST NOT** include an `id`. + +### Base Protocol + +The base protocol consists of the following JSON-RPC methods: + +- `initialize`: Sent from the client to the server to initialize the connection. +- `initialized`: Sent from the client to the server after initialization is complete. +- `ping`: Sent by either party to check if the other is still alive. + +Implementations **MUST** support these base protocol methods. + +### Model Context Protocol specific methods + +MCP defines methods based on JSON-RPC that clients and servers implement: + +- [Lifecycle](lifecycle.md) handling +- [Resource](resources.md) management +- [Prompt](prompts.md) handling +- [Tool](tools.md) execution +- [Logging](logging.md) +- [Sampling](sampling.md) + +### Authentication + +Authentication mechanisms are not part of the core MCP specification. Implementations **MAY** provide authentication based on the transport they use.. + +### Versioning + +The MCP version is declared in the `initialize` request and response. Clients and servers **MUST** agree on a compatible protocol version to proceed with communication. + +### Ping Messages + +Either party can send ping messages to check if the other is still alive and responsive: + +```json +{ + "jsonrpc": "2.0", + "id": 1, + "method": "ping" +} +``` + +The receiver MUST respond promptly with an empty result: + +```json +{ + "jsonrpc": "2.0", + "id": 1, + "result": {} +} +``` + +If the receiver fails to respond in a timely manner, the sender MAY disconnect. + +## Specification + +The conical specification can be found at [Model Context Protocol](http://github.com/modelcontextprotocol/spec/tree/main/spec/schema.ts). The specification of the data format +is available in TypeScript (source of truth) and JSON Schema format (generated). \ No newline at end of file diff --git a/specification/lifecycle.mdx b/specification/lifecycle.mdx new file mode 100644 index 0000000..b44a4ba --- /dev/null +++ b/specification/lifecycle.mdx @@ -0,0 +1,202 @@ +--- +title: Lifecycle Management +--- + +The Model Context Protocol defines a specific lifecycle for client-server interactions. This lifecycle consists of the following stages: + +Initialization +: The client sends an `initialize` request to the server, initiating the connection. + +Capability Exchange +: The client and server exchange information about their supported features and protocol versions. + +Normal Operation +: After successful initialization, the client and server can freely communicate using the agreed-upon protocol. + +Shutdown +: The connection is terminated, typically initiated by the client when it no longer needs the server's services. + +The initialization sequence in the Model Context Protocol follows these steps: + +```mermaid +sequenceDiagram + participant Client + participant Server + + Client->>Server: initialize request + Note over Client,Server: Includes protocol version, client capabilities + Server->>Client: InitializeResult + Note over Client,Server: Includes protocol version, server capabilities + Client->>Server: initialized notification + Note over Client,Server: Signals completion of initialization + rect rgb(200, 220, 240) + Note over Client,Server: Normal Operation + Client->>Server: Various requests (e.g., list resources, get prompts) + Server->>Client: Responses + Server->>Client: Requests (e.g., LLM sampling) + Client->>Server: Responses + end + Client->>Server: Shutdown (implementation-specific) +``` + +This sequence ensures that both parties are aware of each other's capabilities and agree on the protocol version to be used for further communication. + + +# Details + +## Initialization + +The initialization process **MUST** begin with the client sending an `initialize` request to the server. This request **MUST** include: + +- The *protocol version* supported by the client, as a string +- The client's capabilities +- Information about the client implementation + +Protocol versions are represented as strings in the format `YYYY-MM-DD` (year–month–day, all zero-padded), and can be lexicographically compared—for example, `2024-10-07` is greater than `2024-10-06`. + + + +```typescript +export interface InitializeRequest extends Request { + method: "initialize"; + params: { + protocolVersion: string; + capabilities: ClientCapabilities; + clientInfo: Implementation; + }; +} +``` + +```json +{ + "jsonrpc": "2.0", + "id": 1, + "method": "initialize", + "params": { + "protocolVersion": "2024-10-07", + "capabilities": { + "experimental": {}, + "sampling": {} + }, + "clientInfo": { + "name": "ExampleClient", + "version": "1.0.0" + } + } +} +``` + + + +The server **MUST** respond to the initialize request with an `InitializeResult`. This response **MUST** include: + +- The *protocol version* the server will use +- The server's capabilities +- Information about the server implementation + + + ```typescript + export interface InitializeResult extends Result { + protocolVersion: string; + capabilities: ServerCapabilities; + serverInfo: Implementation; + } + ``` + + ```json + { + "jsonrpc": "2.0", + "id": 1, + "result": { + "protocolVersion": "2024-10-07", + "capabilities": { + "experimental": {}, + "logging": {}, + "prompts": {}, + "resources": { + "subscribe": true + }, + "tools": {} + }, + "serverInfo": { + "name": "ExampleServer", + "version": "1.0.0" + } + } + } + ``` + + +The server may choose a different protocol version than the client has requested. In such cases, it is up to the client whether to proceed with the connection or abort. + +## Capability Exchange + +During the initialization process, both the client and server exchange their capabilities. This allows each party to understand what features and operations are supported by the other. + +The client's capabilities are sent in the `initialize` request: + +```typescript +export interface ClientCapabilities { + experimental?: { [key: string]: object }; + sampling?: {}; +} +``` + +The server's capabilities are sent in the `InitializeResult`: + +```typescript +export interface ServerCapabilities { + experimental?: { [key: string]: object }; + logging?: {}; + prompts?: {}; + resources?: { + subscribe?: boolean; + }; + tools?: {}; +} +``` + +Both parties **SHOULD** respect the capabilities declared by the other and **SHOULD NOT** attempt to use features that are not supported. + +### Capability Descriptions + +Client Capabilities: +- `experimental`: An object containing any experimental, non-standard capabilities supported by the client. +- `sampling`: If present, indicates that the client supports sampling from an LLM. + +Server Capabilities: +- `experimental`: An object containing any experimental, non-standard capabilities supported by the server. +- `logging`: If present, indicates that the server supports controlling logging from client side. +- `prompts`: If present, indicates that the server offers prompt templates. +- `resources`: If present, indicates that the server offers resources to read. The `subscribe` property within this object indicates whether the server supports subscribing to resource updates. +- `tools`: If present, indicates that the server offers tools to call. + +These capabilities allow the client and server to communicate their supported features, enabling them to adapt their behavior accordingly and utilize the full range of supported functionalities during their interaction. + +## Normal Operation + +After successful initialization, the client **MUST** send an `initialized` notification to the server: + +```typescript +export interface InitializedNotification extends Notification { + method: "notifications/initialized"; +} +``` + +Once the server receives this notification, both client and server can begin normal operation. During this phase: + +1. The client **MAY** send requests to the server for various operations such as listing resources, getting prompts, or calling tools. +2. The server **MAY** send requests to the client for operations like sampling from an LLM. +3. Either party **MAY** send notifications to the other as needed. + +Both parties **MUST** be prepared to handle requests and notifications at any time during normal operation. + +## Shutdown + +The Model Context Protocol does not define a specific shutdown procedure. However, implementations **SHOULD** consider the following guidelines: + +1. The client **SHOULD** initiate the shutdown process when it no longer needs the server's services. +2. The server **SHOULD** gracefully terminate any ongoing operations when a shutdown is initiated. +3. Both parties **SHOULD** ensure that any resources are properly released during shutdown. + +Throughout all stages of the lifecycle, both client and server **MUST** adhere to the JSON-RPC 2.0 specification for message formatting and error handling. \ No newline at end of file diff --git a/specification/logging.mdx b/specification/logging.mdx new file mode 100644 index 0000000..4d91cfc --- /dev/null +++ b/specification/logging.mdx @@ -0,0 +1,175 @@ +--- +title: Logging +description: "MCP protocol specification for server logging capabilities" +--- + +Logging enables servers to send log messages to clients in a structured way. Clients can control the verbosity of logging by setting the minimum log level they want to receive. Each log message includes a level indicating its severity, an optional logger name for organization, and arbitrary data that can be any JSON-serializable value. + +## Capabilities + +To indicate support for the Logging API, servers MUST include a `logging` capability in their `ServerCapabilities` during initialization. The `logging` capability SHOULD be an empty object: + +```json +{ + "capabilities": { + "logging": {} + } +} +``` + +Clients SHOULD check for this capability before attempting to set the log level. + +## Concepts + +### Log Levels + +MCP defines the following log levels in order of increasing severity: + +- `debug`: Detailed information for debugging +- `info`: General informational messages +- `notice`: Normal but significant events +- `warning`: Warning conditions +- `error`: Error conditions +- `critical`: Critical conditions +- `alert`: Action must be taken immediately +- `emergency`: System is unusable + +These levels correspond to syslog severity levels as defined in [RFC 5424](https://datatracker.ietf.org/doc/html/rfc5424#section-6.2.1). + +### Log Messages + +Each log message contains: +- A severity level +- Optional logger name for categorization +- Arbitrary data payload (any JSON-serializable value) + +## Use Cases + +Common use cases for logging include: + +### Informational Updates + +```json +{ + "level": "info", + "logger": "file_processor", + "data": "Processing file: example.txt" +} +``` + +### Transient errors + +{ + "level": "error", + "logger": "git_clone", + "data": { + "error": "Remote repository temporarily unreachable", + "details": { + "repository": "github.com/example/repo", + "attempt": 2, + "maxAttempts": 3, + "willRetry": true, + "retryIn": "5s" + } + } +} + +## Diagram + +The following diagram visualizes the logging interaction between client and server: + +```mermaid +sequenceDiagram + participant Client + participant Server + + Note over Client,Server: Configure logging + Client->>Server: logging/setLevel (info) + Server-->>Client: EmptyResult + + Note over Client,Server: Server sends log messages + Server--)Client: notifications/message (info) + Server--)Client: notifications/message (error) +``` + +## Messages + +This section defines the protocol messages for logging in the Model Context Protocol (MCP). + +### Setting Log Level + +#### Request + +To configure the minimum log level to receive, the client MUST send a `logging/setLevel` request. + +Method: `logging/setLevel` +Params: + - `level`: The minimum severity level of logs to receive (string, required) + +Example: +```json +{ + "jsonrpc": "2.0", + "id": 1, + "method": "logging/setLevel", + "params": { + "level": "info" + } +} +``` + +#### Response + +The server MUST respond with an empty result if successful: + +```json +{ + "jsonrpc": "2.0", + "id": 1, + "result": {} +} +``` + +### Log Message Notification + +The server sends log messages to the client using the `notifications/message` notification. + +Method: `notifications/message` +Params: + - `level`: The severity level of the message (string, required) + - `logger`: Optional name of the logger (string) + - `data`: The log message data (any JSON-serializable value, required) + +Example: +```json +{ + "jsonrpc": "2.0", + "method": "notifications/message", + "params": { + "level": "error", + "logger": "database", + "data": { + "error": "Connection failed", + "details": { + "host": "localhost", + "port": 5432 + } + } + } +} +``` + +## Error Handling + +Clients MUST be prepared to handle: +- Invalid log levels in setLevel requests +- Missing or malformed log message parameters +- Unexpected data types in log messages + +## Security Considerations + +Implementations MUST carefully consider: +- Sanitizing sensitive information from log messages +- Rate limiting log messages to prevent flooding +- Access control for log configuration +- Validation of log data to prevent injection attacks \ No newline at end of file diff --git a/specification/overview.mdx b/specification/overview.mdx new file mode 100644 index 0000000..5215929 --- /dev/null +++ b/specification/overview.mdx @@ -0,0 +1,210 @@ +--- +title: Overview +--- + +_**NOTE:** This is a very early draft. Feel free to discuss changes, requirements, etc._ + +# Goal +The Model Context Protocol (MCP) is an attempt to allow implementors to provide context to various LLM surfaces such as editors/IDEs, [claude.ai](https://claude.ai), etc., in a pluggable way. It separates the concerns of providing context from the LLM loop and its usage within. + +This makes it **much** easier for anyone to script LLM applications for accomplishing their custom workflows, without the application needing to directly offer a large number of integrations. + +# Terminology +The Model Context Protocol is inspired by Microsoft's [Language Server Protocol](https://microsoft.github.io/language-server-protocol/), with similar concepts: + +* **Server**: a process or service providing context via MCP. +* **Client**: the initiator and client connection to a single MCP server. A message sent through a client is always directed to its one corresponding server. +* **Host**: a process or service which runs any number of MCP clients. [For example, your editor might be a host, claude.ai might be a host, etc.](#example-hosts) +* **Session**: a stateful session established between one client and server. +* **Message**: a message refers to one of the following types of [JSON-RPC](https://www.jsonrpc.org/) object: + * **Request:** a request includes a `method` and `params`, and can be sent by either the server or the client, asking the other for some information or to perform some operation. + * **Response:** a response includes a `result` or an `error`, and is sent *back* after a request, once processing has finished (successfully or unsuccessfully). + * **Notification:** a special type of a request that does not expect a response, notifications are emitted by either the server or client to unilaterally inform the other of an event or state change. +* **Capability**: a feature that the client or server supports. When an MCP connection is initiated, the client and server negotiate the capabilities that they both support, which affects the rest of the interaction. + +## Primitives +On top of the base protocol, MCP introduces these unique primitives: + +* **Resources**: anything that can be loaded as context for an LLM. *Servers* expose a list of resources, identified with [URIs](https://en.wikipedia.org/wiki/Uniform_Resource_Identifier), which the *client* can choose to read or (if supported) subscribe to. Resources can be text or binary data—there are no restrictions on their content. +* **Prompts**: prompts or prompt templates that the *server* can provide to the *client*, which the client can easily surface in the UI (e.g., as some sort of slash command). +* **Tools**: functionality that the *client* can invoke on the *server*, to perform effectful operations. The client can choose to [expose these tools directly to the LLM](https://docs.anthropic.com/en/docs/build-with-claude/tool-use) too, allowing it to decide when and how to use them. +* **Sampling**: *servers* can ask the *client* to sample from the LLM, which allows servers to implement agentic behaviors without having to implement sampling themselves. This also allows the client to combine the sampling request with *all of the other context it has*, making it much more intelligent—while avoiding needlessly exfiltrating information to servers. + +Each primitive can be summarized in the following control hierarchy: + +| Primitive | Control | Description | Example | +|-----------|------------------------|----------------------------------------------------|------------------------------| +| Prompts | User-controlled | Interactive templates invoked by user choice | Slash commands, menu options | +| Resources | Application-controlled | Contextual data attached and managed by the client | File contents, git history | +| Tools | Model-controlled | Functions exposed to the LLM to take actions | API POST requests, file writing | +| Sampling | Server-initiated | LLM completion requests from server to client | Generating AI summaries | + +The communication flow between client and server: + +```mermaid +flowchart LR + server["Server\nScript on local machine, web service, etc."] + host["Host (client)\nEditors, claude.ai, etc."] + + host -->|"resource queries"| server + host -->|"invoke tools"| server + server -->|"sampling"| host + server -.->|"prompt templates"| host + server -.->|"resource contents"| host +``` + +## Control +In addition to basic primitives, MCP offers a set of control flow messages. + +* **Logging:** Anything related to how the server processes logs. +* **Completion**: Supports completion of server arguments on the client side. See + +## Error Codes + +MCP uses standard JSON-RPC error codes as well as protocol-specific codes: + +Standard JSON-RPC error codes: +- `-32700`: Parse error +- `-32600`: Invalid request +- `-32601`: Method not found +- `-32602`: Invalid params +- `-32603`: Internal error + +All error responses MUST include: +- A numeric error code +- A human-readable message +- Optional additional error data + +Example error response: +```json +{ + "jsonrpc": "2.0", + "id": 1, + "error": { + "code": -32602, + "message": "Required parameter missing", + "data": { + "parameter": "uri" + } + } +} +``` +# Use cases +Most use cases are around enabling people to build their own specific workflows and integrations. MCP enables engineers and teams to **tailor AI to their needs.** + +The beauty of the Model Context Protocol is that it's **extremely composable**. You can imagine mixing and matching *any number* of the example servers below with any one of the hosts. Each individual server can be quite simple and limited, but *composed together*, you can get a super-powered AI! + +## Example servers +* **File watcher**: read entire local directories, exposed as resources, and subscribe to changes. The server can provide a tool to write changes back to disk too! +* **Screen watcher**: follow along with the user, taking screenshots automatically, and exposing those as resources. The host can use this to automatically attach screen captures to LLM context. +* **Git integration**: could expose context like Git commit history, but probably *most* useful as a source of tools, like: "commit these changes," "merge this and resolve conflicts," etc. +* **GitHub integration**: read and expose GitHub resources: files, commits, pull requests, issues, etc. Could also expose one or more tools to modify GitHub resources, like "create a PR." +* **Asana integration**: similarly to GitHub—read/write Asana projects, tasks, etc. +* **Slack integration**: read context from Slack channels. Could also look for specially tagged messages, or invocations of [shortcuts](https://api.slack.com/interactivity/shortcuts), as sources of context. Could expose tools to post messages to Slack. +* **Google Workspace integration**: read and write emails, docs, etc. +* **IDEs and editors**: IDEs and editors can be [servers](#example-hosts-clients) as well as hosts! As servers, they can be a rich source of context like: output/status of tests, [ASTs](https://en.wikipedia.org/wiki/Abstract_syntax_tree) and parse trees, and "which files are currently open and being edited?" + +A key design principle of MCP is that it should be *as simple as possible* to implement a server. We want anyone to be able to write, e.g., a local Python script of 100 or fewer lines and get a fully functioning server, with capabilities comparable to any of the above. + +## Example hosts +* **IDEs and editors**: An MCP host inside an IDE or editor could support attaching any number of servers, which can be used to populate an in-editor LLM chat interface, as well as (e.g.) contextualize refactoring. In future, we could also imagine populating editors' command palette with all of the tools that MCP servers have made available. +* **claude.ai**: [Claude.ai](https://claude.ai) can become an MCP host, allowing users to connect any number of MCP servers. Resources from those servers could be automatically made available for attaching to any Project or Chat. Claude could also make use of the tools exposed by MCP servers to implement agentic behaviors, saving artifacts to disk or to web services, etc.! +* **Slack**: [Claude in Slack](https://www.anthropic.com/claude-in-slack) on steroids! Building an MCP host into Slack would open the door to much more complex interactions with LLMs via the platform—both in being able to read context from any number of places (for example, all the servers posited above), as well as being able to *take actions*, from Slack, via the tools that MCP servers expose. + +# Protocol +## Initialization +MCP [sessions](lifecycle) begin with an initialization phase, where the client and server identify each other, and exchange information about their respective [capabilities](lifecycle#capability-descriptions). + +The client can only begin requesting resources and invoking tools on the server, and the server can only begin requesting LLM sampling, after the client has issued the `initialized` notification: + +```mermaid +sequenceDiagram + participant client as Client + participant server as Server + + activate client + client -->>+ server: (connect over transport) + client -->> server: initialize + server -->> client: initialize_response + client --) server: initialized (notification) + + loop while connected + alt client to server + client -->> server: request + server -->> client: response + else + client --) server: notification + else server to client + server -->> client: request + client -->> server: response + else + server --) client: notification + end + end + + deactivate server + deactivate client +``` + +## Transports +An MCP server or client must implement one of the following transports. Different transports require different clients (but each can run within the same *host*). + +### stdio +The client spawns the server process and manages its lifetime, and writes messages to it on the server's stdin. The server writes messages back to the client on its stdout. + +Individual JSON-RPC messages are sent as newline-terminated JSON over the interface. + +Anything the server writes to stderr MAY be captured as logging, but the client is also allowed to ignore it completely. + +### SSE +A client can open a [Server-Sent Events](https://en.wikipedia.org/wiki/Server-sent_events) connection to a server, which the server will use to push all of its requests and responses to the client. + +Upon connection, the server MUST issue a `endpoint` event (which is specific to MCP, not a default SSE event). The `data` associated with an `endpoint` event MUST be a URI for the client to use. The endpoint can be a relative or an absolute URI, but MUST always point to the same server origin. Cross-origin endpoints are not allowed, for security. + +The client MUST issue individual JSON-RPC messages through the endpoint identified by the server, using HTTP POST requests—this allows the server to link these out-of-band messages with the ongoing SSE stream. + +In turn, `message` events on the SSE stream will contain individual JSON-RPC messages from the server. The server MUST NOT send a `message` event until after the `endpoint` event has been issued. + +This sequence diagram shows the MCP initialization flow over SSE, followed by open-ended communication between client and server, until ultimately the client disconnects: + +```mermaid +sequenceDiagram + participant client as MCP Client + participant server as MCP Server + + activate client + client->>+server: new EventSource("https://server/mcp") + server->>client: event: endpoint
data: /session?id=8cfc516c-… + + client-->>server: POST https://server/session?id=…
{InitializeRequest} + server->>client: event: message
data: {InitializeResponse} + + client--)server: POST https://server/session?id=…
{InitializedNotification} + + loop client requests and responses + client--)server: POST https://server/session?id=…
{…} + end + + loop server requests and responses + server-)client: event: message
data: {…} + end + + client -x server: EventSource.close() + + deactivate server + deactivate client +``` + +## Security and T&S considerations +This model, while making meaningful changes to productivity and product experience, is effectively a form of arbitrary data access and arbitrary code execution. + +**Every interaction between MCP host and server will need informed user consent.** For example: + +* Servers must only expose user data as [resources](resources) with the user's explicit consent. Hosts must not transmit that data elsewhere without the user's explicit consent. +* Hosts must not invoke tools on servers without the user's explicit consent, and understanding of what the tool will do. +* When a server initiates [sampling](sampling) via a host, the user must have control over: + * *Whether* sampling even occurs. (They may not want to be charged!) + * What the prompt that will actually be sampled is. + * *What the server sees* of the completion when sampling finishes. + +This latter point is why the sampling primitives do not permit MCP servers to see the whole prompt—instead, the host remains in control, and can censor or modify it at will. \ No newline at end of file diff --git a/specification/prompts.mdx b/specification/prompts.mdx new file mode 100644 index 0000000..6c744c3 --- /dev/null +++ b/specification/prompts.mdx @@ -0,0 +1,299 @@ +--- +title: Prompts +--- + +Prompts enable servers to provide templated conversations or instructions to clients in a structured way, specifically for interacting with language models. Clients can discover available prompts, retrieve their contents, and optionally provide arguments to customize them. Users may explicitly select prompts via the client UI, or clients can intelligently suggest appropriate prompts based on context. Each prompt is uniquely identified by a name. + +An example of a prompt as a slash command in the Zed editor: +![Slash Command Example](slash-command.png) + +## Capabilities + +To indicate support for the Prompts API, servers MUST include a `prompts` capability in their `ServerCapabilities` during initialization. The `prompts` capability SHOULD be an empty object: + +```json +{ + "capabilities": { + "prompts": {} + } +} +``` + +Clients SHOULD check for this capability before using the Prompts API. + +Servers MAY support notifications for changes to the prompt list. If a server supports this feature, it SHOULD include a `listChanged` property in its `prompts` capability: + +```json +{ + "capabilities": { + "prompts": { + "listChanged": true + } + } +} +``` + +If a server supports this capability, it MAY send `notifications/prompts/list_changed` notifications to inform the client about changes to the available prompts. + +## Concepts + +### Prompt + +A Prompt in the Model Context Protocol (MCP) represents a pre-defined set of messages or instructions that a server can provide to clients. Each Prompt is uniquely identified by a name and may have associated metadata such as a description and required arguments. Prompts can represent various types of interactions, including code reviews, data analysis tasks, or creative writing prompts. + +### Prompt Templates + +Prompt Templates are prompts that can be dynamically generated or customized based on provided arguments. They allow servers to expose a flexible set of prompts that can be tailored to specific use cases. Clients can use these templates by providing the required arguments when retrieving the prompt. + +### Embedded Resource Contents + +Prompts can include embedded resource contents from the MCP server. This allows servers to provide context-rich prompts that incorporate relevant data or files directly into the prompt structure. + +## Use Cases + +Common use cases for prompts include providing standardized instructions for code reviews, data analysis tasks, or creative writing exercises. Here are examples of kinds of prompts that an MCP server could expose: + +### Code Review + +A prompt template for conducting code reviews: + +```json +{ + "name": "code_review", + "description": "Analyze code quality and suggest improvements", + "arguments": [ + { + "name": "language", + "description": "Programming language of the code", + "required": true + }, + { + "name": "code", + "description": "The code snippet to review", + "required": true + } + ] +} +``` + +### Data Analysis + +A prompt for guiding data analysis tasks: + +```json +{ + "name": "data_analysis", + "description": "Provide step-by-step guidance for analyzing a dataset", + "arguments": [ + { + "name": "dataset_description", + "description": "Brief description of the dataset", + "required": true + }, + { + "name": "analysis_goal", + "description": "The main goal of the analysis", + "required": true + } + ] +} +``` + +## Diagram + +The following diagram visualizes a common interaction sequence between +client and server for using prompts: + +```mermaid +sequenceDiagram + participant Client + participant Server + + Note over Client,Server: List prompts + Client->>Server: prompts/list + Server-->>Client: ListPromptsResult + + Note over Client,Server: Client selects a prompt + Client->>Server: prompts/get (Prompt A) + Server-->>Client: GetPromptResult +``` + +## Messages + +This section defines the protocol messages for prompt management in the Model Context Protocol (MCP). + +### Listing Prompts + +The Listing Prompts operation allows clients to discover available prompts on the server. This operation is fundamental to the prompt management process in the Model Context Protocol (MCP). When a client sends a `prompts/list` request, the server responds with a comprehensive list of prompts and prompt templates it can provide. This list enables clients to understand what prompts are available, facilitating subsequent operations such as retrieving specific prompts. + +#### Request + +To retrieve a list of available prompts from the server, the client MUST send a `prompts/list` request. + +* Method: `prompts/list` +* Params: None + +Example request from a client to a server: +```json +{ + "jsonrpc": "2.0", + "id": 1, + "method": "prompts/list" +} +``` + +#### Response + +The server MUST respond with a `ListPromptsResult` containing: + +- `prompts`: An array of `Prompt` objects + +Example: +```json +{ + "jsonrpc": "2.0", + "id": 1, + "result": { + "prompts": [ + { + "name": "code_review", + "description": "Analyze code quality and suggest improvements", + "arguments": [ + { + "name": "language", + "description": "Programming language of the code", + "required": true + }, + { + "name": "code", + "description": "The code snippet to review", + "required": true + } + ] + }, + { + "name": "data_analysis", + "description": "Provide step-by-step guidance for analyzing a dataset", + "arguments": [ + { + "name": "dataset_description", + "description": "Brief description of the dataset", + "required": true + }, + { + "name": "analysis_goal", + "description": "The main goal of the analysis", + "required": true + } + ] + } + ] + } +} +``` + +### Getting a Prompt + +#### Request + +To retrieve the contents of a specific prompt, the client MUST send a `prompts/get` request. + +Method: `prompts/get` +Params: + - `name`: The name of the prompt to retrieve (string, required) + - `arguments`: An optional object containing argument values for prompt templates + +Example: +```json +{ + "jsonrpc": "2.0", + "id": 2, + "method": "prompts/get", + "params": { + "name": "code_review", + "arguments": { + "language": "Python", + "code": "def add(a, b):\n return a + b" + } + } +} +``` + +#### Response + +The server MUST respond with a `GetPromptResult` containing: + +- `description`: An optional string describing the prompt +- `messages`: An array of `PromptMessage` objects representing the prompt content, which may include embedded resource contents + +Example: +```json +{ + "jsonrpc": "2.0", + "id": 2, + "result": { + "description": "A prompt for analyzing code quality", + "messages": [ + { + "role": "user", + "content": { + "type": "text", + "text": "Please review the following Python code snippet and provide feedback on its quality and potential improvements:\n\ndef add(a, b):\n return a + b" + } + }, + { + "role": "assistant", + "content": { + "type": "text", + "text": "Certainly! I'd be happy to review the Python code snippet and provide feedback on its quality and potential improvements. Let's analyze it:" + } + }, + { + "role": "user", + "content": { + "type": "resource", + "resource": { + "uri": "file:///workspace/project/requirements.txt", + "mimeType": "text/plain", + "text": "flask==2.0.1\nnumpy==1.21.0\npandas==1.3.0\n" + } + } + }, + { + "role": "assistant", + "content": { + "type": "text", + "text": "I see you've also provided the contents of the requirements.txt file. This gives us additional context about the project environment. Let's consider these dependencies in our code review as well." + } + } + ] + } +} +``` + +### Prompt List Changed Notification + +If the server supports the `listChanged` capability for prompts, it MAY send a `notifications/prompts/list_changed` notification to inform the client that the list of available prompts has changed. + +#### Notification + +Method: `notifications/prompts/list_changed` +Params: None + +Example: +```json +{ + "jsonrpc": "2.0", + "method": "notifications/prompts/list_changed" +} +``` + +Upon receiving this notification, clients SHOULD request an updated prompt list using the `prompts/list` method to ensure they have the most up-to-date information about available prompts. + +## Error Handling + +Clients MUST be prepared to handle cases where listed prompts become unavailable between listing and retrieval attempts. Servers SHOULD provide appropriate error responses in such scenarios. + +## Security Considerations + +Implementations MUST carefully consider the security implications of exposing prompts, especially when dealing with sensitive data or customizable templates. Proper authentication and authorization mechanisms SHOULD be in place to prevent unauthorized access to prompts. \ No newline at end of file diff --git a/specification/resources.mdx b/specification/resources.mdx new file mode 100644 index 0000000..4513c5b --- /dev/null +++ b/specification/resources.mdx @@ -0,0 +1,452 @@ +--- +title: Resources +--- + + +Resources enable servers to expose arbitrary data to clients in a structured way, specifically for providing context to language models. Clients can discover available resources, read their contents, and optionally subscribe to updates. Users may explicitly attach resources via the client UI, or clients can intelligently select appropriate resources to add to the context. Each resource is uniquely identified by a [URI](https://datatracker.ietf.org/doc/html/rfc3986). + +## Capabilities + +To use resources, the server MUST include the `resources` capability in its `ServerCapabilities` object during the initialization process. The `resources` capability MAY include a `subscribe` field set to `true` if the server supports resource subscriptions. Additionally, the `resources` capability MAY include a `listChanged` field set to `true` if the server supports notifications for changes to the resource list. + +Clients intending to use resources SHOULD check for the presence of the `resources` capability in the server's capabilities before attempting to use any resource-related methods. If the capability is not present, the client MUST NOT attempt to use resource-related methods, as the server does not support them. + +Example of server capabilities with basic resource support: +```json +{ + "capabilities": { + "resources": {} + } +} +``` + +Example of server capabilities including resource support with subscriptions and list change notifications: + +```json +{ + "capabilities": { + "resources": { + "subscribe": true, + "listChanged": true + } + } +} +``` + +In this example, the server supports basic resource operations, subscriptions, and notifications for resource list changes. If `subscribe` is omitted or set to `false`, the server only supports basic resource operations without subscriptions. Similarly, if `listChanged` is omitted or set to `false`, the server does not support notifications for changes to the resource list. + +## Concepts +### Resource + +A Resource in the Model Context Protocol (MCP) represents a discrete unit of data that a server can provide to clients. Each Resource is uniquely identified by a URI and may have associated metadata such as a name and MIME type. Resources can represent various types of data, including files, database records, or application-specific information. + +### Resource Templates +To retrieve available resource templates from the server, the client MUST send a `resources/templates/list` request: + +```json +{ + "jsonrpc": "2.0", + "id": 1, + "method": "resources/templates/list" +} +``` + +The server MUST respond with a list of resource templates: + +```json +{ + "jsonrpc": "2.0", + "id": 1, + "result": { + "resourceTemplates": [ + { + "uriTemplate": "file:///{path}", + "name": "Local File", + "description": "Access local files", + "mimeType": "application/octet-stream" + } + ] + } +} +``` + +Resource templates use URI templates as defined in [RFC 6570](https://datatracker.ietf.org/doc/html/rfc6570) to specify parameterized resource URIs. + +Resource Templates are URI patterns that describe a class of resources that can be dynamically generated or accessed. They use URI templates as defined in [RFC 6570](https://datatracker.ietf.org/doc/html/rfc6570) to specify how clients can construct valid resource URIs. Templates allow servers to expose a potentially large or dynamic set of resources without explicitly listing each one. Clients can use these templates to generate specific resource URIs as needed. + +## Use Cases + +Common usecases for resources include file and folder access to provide code context, but can extend to any other form of model-relevant data. See [list of common URI schemes](#list-of-common-uri-schemas) for more information. Here are examples of kinds of resources that an MCP server could expose: + +### File Access +Resources can be used to expose file access to clients. The server should prefix any file-like resource +with the `file://` scheme, and ensure that the client is aware of how to interpret the file by providing +a correct MIME type. When the client issues a `resources/read` request, the server *MUST* ensure that it +returns the file in the correct encoding for the mime type (e.g., text if possible, or base64 for any binary data). + +```json +{ + "uri": "file:///home/user/documents/example.zip", + "name": "Example Text File", + "mimeType": "application/octet-stream" +} +``` + +### Database Schema + +Resources can also be used to provide specialized structured information. In the following example we are providing a database schema as a custom JSON format that the client is required to understand: + +```json +{ + "uri": "postgres://localhost/some_database/some_table/schema", + "name": "Database schema for some_database.some_table", + "mimeType": "application/json;format=MyApplication::DatabaseSchema" +} +``` + +If the client requests a schema, the server would respond with the custom database schema +JSON, for example + +```json +{ + "schema": "myschema", + "table": "test", + "owner": "a-user", + "definition": "..." +} +``` +## Diagram + +The following diagram visualizes a common intercation sequence between +client and server. This is an example. Clients are free to request any +method at any time. For instance, clients are not required to list resources +before reading them. + +```mermaid +sequenceDiagram + participant Client + participant Server + + Note over Client,Server: List resources + Client->>Server: resources/list + Server-->>Client: ListResourcesResult + + Note over Client,Server: Subscriptions + opt Subscribe to events + Client->>Server: resources/subscribe (Resource A) + Client->>Server: resources/subscribe (Resource Bs + end + Note over Client,Server: Reading a rescoures + Client->>Server: resources/read (Resource A) + Server-->>Client: ReadResourceResult + Note over Client,Server: Notification & Re-reading + opt Subscription notification + Server->>Client: notifications/resources/updated (Resource B) + end + Client->>Server: resources/read (Resource B) + Server-->>Client: ReadResourceResult +``` + +## Messages + +This section defines the protocol messages for resource management in the Model Context Protocol (MCP). Resources are identified by URIs and can represent various types of data exposed by the server. Clients can list available resources, read their contents, and optionally subscribe to updates. + +### Listing Resources +The Listing Resources operation allows clients to discover available resources on the server. This operation is fundamental to the resource management process in the Model Context Protocol (MCP). When a client sends a `resources/list` request, the server responds with a comprehensive list of resources and resource templates it can provide. This list enables clients to understand what data is available, facilitating subsequent operations such as reading resources or subscribing to updates. The response may include both concrete resources (with specific URIs) and resource templates (with URI patterns), giving clients flexibility in accessing and utilizing server-provided data. + +#### Request + +To retrieve a list of available resources from the server, the client MUST send a `resources/list` request. + +* Method: `resources/list` +* Params: None + +Example request from a client to a server: +```json +{ + "jsonrpc": "2.0", + "id": 1, + "method": "resources/list" +} +``` + +### Response + +The server MUST respond with a `ListResourcesResult` containing: + +- `resourceTemplates`: An optional array of `ResourceTemplate` objects +- `resources`: An optional array of `Resource` objects + +The response MAY be empty (i.e., both arrays may be omitted or empty). + +Example: +```json +{ + "jsonrpc": "2.0", + "id": 1, + "result": { + "resourceTemplates": [ + { + "uriTemplate": "file:///{path}", + "name": "Local File", + "description": "Access local files", + "mimeType": "application/octet-stream" + } + ], + "resources": [ + { + "uri": "file:///home/user/document.txt", + "name": "User Document", + "mimeType": "text/plain" + } + ] + } +} +``` + +### Error Handling + +Clients MUST be prepared to handle cases where listed resources become unavailable between listing and access attempts. Servers SHOULD provide appropriate error responses in such scenarios. + +## Reading a Resource + +### Request + +To retrieve the contents of a specific resource, the client MUST send a `resources/read` request. + +Method: `resources/read` +Params: + - `uri`: The URI of the resource to read (string, required) + +Example: +```json +{ + "jsonrpc": "2.0", + "id": 2, + "method": "resources/read", + "params": { + "uri": "file:///home/user/document.txt" + } +} +``` + +### Response + +The server MUST respond with a `ReadResourceResult` containing an array of `ResourceContents` objects. Each object MUST be either a `TextResourceContents` or a `BlobResourceContents`. + +Example (text content): +```json +{ + "jsonrpc": "2.0", + "id": 2, + "result": { + "contents": [ + { + "uri": "file:///home/user/document.txt", + "mimeType": "text/plain", + "text": "This is the content of the document." + } + ] + } +} +``` + +Example (binary content): +```json +{ + "jsonrpc": "2.0", + "id": 2, + "result": { + "contents": [ + { + "uri": "file:///home/user/image.png", + "mimeType": "image/png", + "blob": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACklEQVR4nGMAAQAABQABDQottAAAAABJRU5ErkJggg==" + } + ] + } +} +``` + +## Subscriptions + +The Model Context Protocol (MCP) offers an optional subscription mechanism for resources to enable real-time updates and efficient synchronization between clients and servers. This feature allows clients to receive notifications when specific resources they're interested in change, without the need for constant polling. + +Key aspects of resource subscriptions in MCP: + +1. Optional Feature: Subscriptions are not mandatory. Servers MAY support this feature, and clients MAY choose to use it when available. + +2. Real-time Updates: Subscriptions enable clients to receive immediate notifications when resources change, ensuring up-to-date information without delay. + +3. Efficiency: By subscribing only to relevant resources, clients can reduce unnecessary network traffic and processing overhead associated with frequent polling. + +Implementations should carefully consider the implications of supporting subscriptions, including potential increased complexity in server-side resource tracking and the need for robust error handling in case of connection issues or missed updates. + +### Subscribing to Resources +#### Request + +To subscribe to updates for a resource, the client MUST send a `resources/subscribe` request. + +Method: `resources/subscribe` +Params: + - `uri`: The URI of the resource to subscribe to (string, required) + +Example: +```json +{ + "jsonrpc": "2.0", + "id": 3, + "method": "resources/subscribe", + "params": { + "uri": "file:///home/user/document.txt" + } +} +``` + +### Response + +The server MUST respond with an empty result if the subscription is successful, or an error if it fails. + +Example (success): +```json +{ + "jsonrpc": "2.0", + "id": 3, + "result": {} +} +``` + +### Unsubscribing from Resources + +#### Request + +To unsubscribe from updates for a resource, the client MUST send a `resources/unsubscribe` request. + +Method: `resources/unsubscribe` +Params: + - `uri`: The URI of the resource to unsubscribe from (string, required) + +Example: +```json +{ + "jsonrpc": "2.0", + "id": 4, + "method": "resources/unsubscribe", + "params": { + "uri": "file:///home/user/document.txt" + } +} +``` + +#### Response + +The server MUST respond with an empty result if the unsubscription is successful, or an error if it fails. + +Example (success): +```json +{ + "jsonrpc": "2.0", + "id": 4, + "result": {} +} +``` + +### Resource Updated Notification + +When a subscribed resource is updated, the server MUST send a `notifications/resources/updated` notification to the client. + +Method: `notifications/resources/updated` +Params: + - `uri`: The URI of the updated resource (string, required) + +Example: +```json +{ + "jsonrpc": "2.0", + "method": "notifications/resources/updated", + "params": { + "uri": "file:///home/user/document.txt" + } +} +``` + +Servers MUST only send this notification for resources that clients have explicitly subscribed to. + +### Resource List Changed Notification + +If the server supports the `listChanged` capability for resources, it MAY send a `notifications/resources/list_changed` notification to inform the client that the list of available resources has changed. + +#### Notification + +Method: `notifications/resources/list_changed` +Params: None + +Example: +```json +{ + "jsonrpc": "2.0", + "method": "notifications/resources/list_changed" +} +``` + +Upon receiving this notification, clients SHOULD request an updated resource list using the `resources/list` method to ensure they have the most up-to-date information about available resources. + +## Security Considerations + +Implementations MUST carefully consider the security implications of exposing resources, especially when dealing with sensitive data or file systems. Proper authentication and authorization mechanisms SHOULD be in place to prevent unauthorized access to resources. + +## Error Handling + +Servers MUST provide appropriate error responses for all request types when issues occur, such as resource not found, permission denied, or internal server errors. Clients MUST be prepared to handle these error responses gracefully. + +Clients MUST also be prepared for resources to change or become unavailable between listing and reading operations. A resource that was present in a `resources/list` response may no longer exist or may have different contents when a subsequent `resources/read` request is made. Servers SHOULD return appropriate error responses in such cases, and clients SHOULD handle these scenarios gracefully, potentially by refreshing their resource list or retrying the operation. + +Example error response: +```json +{ + "jsonrpc": "2.0", + "id": 5, + "error": { + "code": -32001, + "message": "Resource not found", + "data": { + "uri": "file:///nonexistent/file.txt" + } + } +} +``` + + +## List of common URI schemas +Here are some common URI schemes used in the context of MCP resources: + +https:// +: Used to represent a resource available on the web +: Servers SHOULD use this scheme only when the client can fetch the resource directly +: For other cases, servers SHOULD prefer a different or custom scheme + +file:// +: Used to identify resources that behave like a filesystem +: Does not need to map to an actual physical filesystem +: Servers MAY use XDG MIME types like inode/directory for non-regular files + +s3:// +: Used for Amazon S3 or S3-compatible object storage resources + +gcs:// +: Use for Google Cloud object storage resources + +git:// +: Used to identify Git repositories or specific Git objects + +data: +: Used to embed small pieces of data directly in the URI +: Useful for simple, static resources + +zed:// +: Reserved for integration with the Zed editor. + - zed://prompt-library + : Prompts provided by MCP servers for the Zed prompt library + +If you would like to include a commonly used URI schema in this list, +please open an issue the [MCP Specification Github](https://github.com/modelcontextprotocol/specifications). \ No newline at end of file diff --git a/specification/roots.mdx b/specification/roots.mdx new file mode 100644 index 0000000..a700436 --- /dev/null +++ b/specification/roots.mdx @@ -0,0 +1,209 @@ +--- +title: Roots +description: "MCP protocol specification for root directory and file access" +--- + +Roots enable clients to provide a list of root directories or files that servers can operate on. This allows servers to understand which parts of the filesystem they have access to and should work with. Servers can request the list of roots from clients that support this capability, and clients can notify servers when the list of available roots changes. + +## Capabilities + +To indicate support for roots, clients MUST include a `roots` capability in their `ClientCapabilities` during initialization: + + + +```json +{ + "capabilities": { + "roots": { } + } +} +``` + +```json +{ + "capabilities": { + "roots": { + "listChanged": true + } + } +} +``` + + +The optional `listChanged` property indicates whether the client will send notifications when the root list changes. + +Servers SHOULD check for this capability before attempting to use any roots functionality. + +## Concepts + +### Root + +A Root in the Model Context Protocol (MCP) represents a directory or file that a server is allowed to operate on. Each Root is uniquely identified by a URI (currently restricted to file:// URIs) and may have an optional human-readable name. Roots define the boundaries of where servers can work within the filesystem. + + +Only URI's starting with **file://** are accepted. + + +## Use Cases + +Common use cases for roots include defining workspace directories, project repositories, or specific files that a server should analyze or modify. Here are some examples: + +### Project Directory + +A root representing a project workspace: + +```json +{ + "uri": "file:///home/user/projects/myproject", + "name": "My Project" +} +``` + +### Multiple Repositories + +Multiple roots for different Git repositories: + +```json +[ + { + "uri": "file:///home/user/repos/frontend", + "name": "Frontend Repository" + }, + { + "uri": "file:///home/user/repos/backend", + "name": "Backend Repository" + } +] +``` + +## Diagram + +The following diagram visualizes the interaction between client and server for roots: + +```mermaid +sequenceDiagram + participant Server + participant Client + + Note over Server,Client: Server requests roots list + Server->>Client: roots/list + Client-->>Server: ListRootsResult + + Note over Server,Client: Client updates roots + opt Roots Changed + Client-)Server: notifications/roots/list_changed + Server->>Client: roots/list + Client-->>Server: ListRootsResult + end +``` + +## Messages + +This section defines the protocol messages for root management in the Model Context Protocol (MCP). + +### Listing Roots + +#### Request + +To retrieve a list of available roots from the client, the server MUST send a `roots/list` request. + +Method: `roots/list` +Params: None + +Example: +```json +{ + "jsonrpc": "2.0", + "id": 1, + "method": "roots/list" +} +``` + +#### Response + +The client MUST respond with a `ListRootsResult` containing: + +- `roots`: An array of `Root` objects + +A `Root` object consists of: +- `uri`: A URI string identifying the root location. Currently only `file://` URIs are supported. This field is required. +- `name`: An optional string providing a human-readable name for the root. + +Example: +```json +{ + "jsonrpc": "2.0", + "id": 1, + "result": { + "roots": [ + { + "uri": "file:///home/user/projects/myproject", + "name": "My Project" + }, + { + "uri": "file:///home/user/repos/backend", + "name": "Backend Repository" + } + ] + } +} +``` + +### Root List Changed Notification + +If the client supports the `listChanged` capability for roots, it MUST send a `notifications/roots/list_changed` notification when the list of available roots changes. + +#### Notification + +Method: `notifications/roots/list_changed` +Params: None + +Example: +```json +{ + "jsonrpc": "2.0", + "method": "notifications/roots/list_changed" +} +``` + +Upon receiving this notification, servers SHOULD request an updated root list using the `roots/list` method to ensure they have the most up-to-date information. + +## Error Handling + +Servers MUST be prepared to handle cases where: +- The client does not support roots +- Listed roots become unavailable +- Access to roots is denied + +The client SHOULD return appropriate error responses in these cases. + +Example error response: +```json +{ + "jsonrpc": "2.0", + "id": 1, + "error": { + "code": -32601, + "message": "Roots not supported", + "data": { + "reason": "Client does not have roots capability" + } + } +} +``` + +## Security Considerations + +Implementations MUST carefully consider: + +- Access control for root directories and files +- Validation of root URIs to prevent path traversal attacks +- Scope limitations to prevent unauthorized access +- Permission checks before exposing roots +- Regular validation that roots remain accessible + +Clients SHOULD: +- Only expose roots that the server has permission to access +- Validate all root URIs before returning them +- Implement proper filesystem permission checks +- Monitor for changes in root accessibility \ No newline at end of file diff --git a/specification/sampling.mdx b/specification/sampling.mdx new file mode 100644 index 0000000..725ad31 --- /dev/null +++ b/specification/sampling.mdx @@ -0,0 +1,236 @@ +--- +title: Sampling +description: "MCP protocol specification for language model sampling and text generation" +--- + +Sampling enables servers to request generations from a language model via the client, enabling clients to have control over which model to use and what prompts are accepted. Clients can approve or reject incoming sampling requests, and control permissions around which servers can access which models. Servers can optionally request context from other MCP servers to be included in prompts. Because sampling requests go from server to client, this is the only request type in MCP that flows in this direction. + +## Capabilities + +Clients indicate support for sampling by including a `sampling` capability in their `ClientCapabilities` during initialization. The `sampling` capability SHOULD be an empty object: + +```json +{ + "capabilities": { + "sampling": {} + } +} +``` + +Servers SHOULD check for this capability before attempting to use sampling functionality. + +## Concepts + +### Sampling Request + +A Sampling Request in the Model Context Protocol (MCP) represents a request from a server to generate text from a language model via the client. Each request contains messages to send to the model, optional system prompts, and sampling parameters like temperature and maximum tokens. The client has full discretion over which model to use and whether to approve the request. + +### Message Content + +Message content can be either text or images, allowing for multimodal interactions where supported by the model. Text content is provided directly as strings, while image content must be base64 encoded with an appropriate MIME type. + +### Model Preferences + +Servers can express preferences for model selection using the `ModelPreferences` object. This allows servers to indicate priorities for factors like cost, speed, and intelligence, as well as provide hints for specific models. + +## Use Cases + +Common use cases for sampling include generating responses in chat interfaces, code completion, and content generation. Here are some example sampling scenarios: + +### Chat Response + +A server requesting a chat response with model preferences: + +```json +{ + "messages": [ + { + "role": "user", + "content": { + "type": "text", + "text": "What is the capital of France?" + } + } + ], + "maxTokens": 100, + "temperature": 0.7, + "modelPreferences": { + "hints": [ + { + "name": "claude-3-sonnet" + } + ], + "intelligencePriority": 0.8, + "speedPriority": 0.5 + } +} +``` + +### Image Analysis + +A server requesting analysis of an image: + +```json +{ + "messages": [ + { + "role": "user", + "content": { + "type": "image", + "data": "base64_encoded_image_data", + "mimeType": "image/jpeg" + } + }, + { + "role": "user", + "content": { + "type": "text", + "text": "Describe what you see in this image." + } + } + ], + "maxTokens": 200, + "modelPreferences": { + "hints": [ + { + "name": "claude-3-opus" + }, + { + "name": "claude-3-sonnet" + } + ], + "intelligencePriority": 1.0 + } +} +``` + +## Diagram + +The following diagram visualizes the sampling request flow between +server and client: + +```mermaid +sequenceDiagram + participant Server + participant Client + participant User + participant LLM + + Note over Server,Client: Server requests sampling + Server->>Client: sampling/createMessage + opt User approval + Client->>User: Request approval + User-->>Client: Approve request + end + Client->>LLM: Forward request + LLM-->>Client: Generated response + opt User approval + Client->>User: Review response + User-->>Client: Approve response + end + Client-->>Server: CreateMessageResult +``` + +## Messages + +This section defines the protocol messages for sampling in the Model Context Protocol (MCP). + +### Creating a Message + +#### Request + +To request sampling from an LLM via the client, the server MUST send a `sampling/createMessage` request. + +Method: `sampling/createMessage` +Params: + - `messages`: Array of `SamplingMessage` objects representing the conversation history + - `modelPreferences`: Optional `ModelPreferences` object to guide model selection + - `systemPrompt`: Optional system prompt to use + - `includeContext`: Optional request to include context from MCP servers + - `temperature`: Optional sampling temperature + - `maxTokens`: Maximum tokens to generate + - `stopSequences`: Optional array of sequences that will stop generation + - `metadata`: Optional provider-specific metadata + +Example: +```json +{ + "jsonrpc": "2.0", + "id": 1, + "method": "sampling/createMessage", + "params": { + "messages": [ + { + "role": "user", + "content": { + "type": "text", + "text": "What is the capital of France?" + } + } + ], + "systemPrompt": "You are a helpful assistant.", + "maxTokens": 100, + "temperature": 0.7, + "includeContext": "none", + "modelPreferences": { + "hints": [ + { + "name": "claude-3-sonnet" + }, + { + "name": "claude-3-opus" + } + ], + "intelligencePriority": 0.9, + "speedPriority": 0.6 + } + } +} +``` + +#### Response + +The client MUST respond with a `CreateMessageResult` containing: + +- `role`: The role of the message (always "assistant") +- `content`: The generated content +- `model`: The name of the model used +- `stopReason`: Why generation stopped + +Example: +```json +{ + "jsonrpc": "2.0", + "id": 1, + "result": { + "role": "assistant", + "content": { + "type": "text", + "text": "The capital of France is Paris." + }, + "model": "claude-3-sonnet-20240307", + "stopReason": "endTurn" + } +} +``` + +## Error Handling + +Clients MUST be prepared to handle both user rejection of sampling requests and model API errors. Common error scenarios include: + +- User denies the sampling request +- Model API is unavailable +- Invalid sampling parameters +- Context length exceeded + +The client SHOULD return appropriate error responses to the server in these cases. + +## Security Considerations + +Implementations MUST carefully consider the security implications of allowing servers to request model generations, including: + +- User consent and approval of sampling requests +- Permissions around which servers can access which models +- Content filtering and moderation +- Rate limiting to prevent abuse +- Privacy considerations around included context \ No newline at end of file diff --git a/specification/tools.mdx b/specification/tools.mdx new file mode 100644 index 0000000..bb7ff72 --- /dev/null +++ b/specification/tools.mdx @@ -0,0 +1,338 @@ +--- +title: Tools +--- + +Tool use enables servers to expose tools (also sometimes called functions) that can be invoked by language models through the client. This allows models to perform actions or retrieve information beyond their training data. Clients can discover available tools, retrieve their specifications, and invoke them on behalf of the model. Each tool is uniquely identified by a name. + +## Capabilities + +To indicate support for the Tools API, servers MUST include a `tools` capability in their `ServerCapabilities` during initialization. The `tools` capability MAY be an empty object: + +```json +{ + "capabilities": { + "tools": {} + } +} +``` + +Clients SHOULD check for this capability before attempting to use any Tools API methods. If the capability is not present, clients SHOULD assume that the server does not support tool functionality. + +Servers MAY support notifications for changes to the tool list. If a server supports this feature, it SHOULD include a `listChanged` property in its `tools` capability: + +```json +{ + "capabilities": { + "tools": { + "listChanged": true + } + } +} +``` + +If a server supports this capability, it MAY send [`notifications/tools/list_changed`](#tool-list-changed-notification) notifications to inform the client about changes to the available tools. +## Concepts + +### Tool + +A Tool in the Model Context Protocol (MCP) represents a function or action that can be invoked by a language model through the client. Each Tool is uniquely identified by a name and has associated metadata such as a description and input schema. Tools can represent various types of actions, including data retrieval, calculations, or external API calls. + +### Tool Specifications + +Tool Specifications describe the structure and expected inputs for each tool. They use JSON Schema to define the input parameters, allowing clients and models to understand how to properly invoke the tools. + +## Use Cases + +Common use cases for tools include data retrieval, performing calculations, or interacting with external services. Here are examples of kinds of tools that an MCP server could expose: + +### Weather Information + +A tool for retrieving current weather information: + +```json +{ + "name": "get_weather", + "description": "Get current weather information for a specific location", + "inputSchema": { + "type": "object", + "properties": { + "location": { + "type": "string", + "description": "City name or zip code" + }, + "units": { + "type": "string", + "enum": ["metric", "imperial"], + "default": "metric" + } + }, + "required": ["location"] + } +} +``` + +### Database Query + +A tool for querying a database: + +```json +{ + "name": "query_database", + "description": "Execute a SQL query on the database", + "inputSchema": { + "type": "object", + "properties": { + "query": { + "type": "string", + "description": "SQL query to execute" + }, + "database": { + "type": "string", + "enum": ["users", "products", "orders"], + "default": "users" + } + }, + "required": ["query"] + } +} +``` + +## Diagram + +The following diagram visualizes a common interaction sequence between +client, server, and language model for using tools: + +```mermaid +sequenceDiagram + participant Model + participant Client + participant Server + + Note over Client,Server: List tools + Client->>Server: tools/list + Server-->>Client: ListToolsResult + Client->>Model: Available tools + + Note over Model,Client: Model selects tool + Model->>Client: Use get_weather tool + Client->>Server: tools/call (get_weather) + Server-->>Client: CallToolResult + Client->>Model: Tool result + + Note over Model,Client: Model processes result + Model->>Client: Generated response +``` + +## Messages + +This section defines the protocol messages for tool management in the Model Context Protocol (MCP). + +### Listing Tools +The Listing Tools operation allows clients to discover available tools on the server. When a client sends a `tools/list` request, the server responds with a comprehensive list of tools it can provide. This list enables clients to understand what tools are available, facilitating subsequent operations such as tool invocation. + +> **_NOTE:_** Tools can change over time. In such cases, the server may send a [Tool List Changed Notification](#tool-list-changed-notification) to inform the client about updates to the available tools. + +#### Request + +To retrieve a list of available tools from the server, the client MUST send a `tools/list` request. + +* Method: `tools/list` +* Params: None + +Example request from a client to a server: +```json +{ + "jsonrpc": "2.0", + "id": 1, + "method": "tools/list" +} +``` + +#### Response + +The server MUST respond with a `ListToolsResult` containing: + +- `tools`: An array of `Tool` objects + +Example: +```json +{ + "jsonrpc": "2.0", + "id": 1, + "result": { + "tools": [ + { + "name": "get_weather", + "description": "Get current weather information for a specific location", + "inputSchema": { + "type": "object", + "properties": { + "location": { + "type": "string", + "description": "City name or zip code" + }, + "units": { + "type": "string", + "enum": ["metric", "imperial"], + "default": "metric" + } + }, + "required": ["location"] + } + }, + { + "name": "query_database", + "description": "Execute a SQL query on the database", + "inputSchema": { + "type": "object", + "properties": { + "query": { + "type": "string", + "description": "SQL query to execute" + }, + "database": { + "type": "string", + "enum": ["users", "products", "orders"], + "default": "users" + } + }, + "required": ["query"] + } + } + ] + } +} +``` + +### Calling a Tool + +#### Request + +To invoke a specific tool, the client MUST send a `tools/call` request. + +Method: `tools/call` +Params: + - `name`: The name of the tool to call (string, required) + - `arguments`: An object containing the tool's input parameters (object, optional) + +Example: +```json +{ + "jsonrpc": "2.0", + "id": 2, + "method": "tools/call", + "params": { + "name": "get_weather", + "arguments": { + "location": "New York", + "units": "imperial" + } + } +} +``` + +#### Response + +The server MUST respond with a `CallToolResult` containing: + +- `content`: An array of content items that can be text, images, or embedded resources +- `isError`: A boolean indicating whether this result represents an error state + +Example: +```json +{ + "jsonrpc": "2.0", + "id": 2, + "result": { + "content": [{ + "type": "text", + "text": "Current weather in New York:\nTemperature: 72°F\nHumidity: 65%\nConditions: Partly cloudy" + }], + "isError": false + } +} +``` + +### Tool List Changed Notification + +If the server supports the `listChanged` capability for tools, it MAY send a `notifications/tools/list_changed` notification to inform the client that the list of available tools has changed. + +#### Notification + +Method: `notifications/tools/list_changed` +Params: None + +Example: +```json +{ + "jsonrpc": "2.0", + "method": "notifications/tools/list_changed" +} +``` + +Upon receiving this notification, clients SHOULD request an updated tool list using the `tools/list` method to ensure they have the most up-to-date information about available tools. + +## Error Handling + +Error handling for tools follows two distinct paths depending on the type of error: + +1. Protocol-level errors (like unknown tools or invalid parameters) MUST be reported as JSON-RPC error responses +2. Tool execution errors SHOULD be reported inside successful CallToolResult responses + +For protocol-level errors, servers MUST return error responses when: +- An unknown tool is requested +- Invalid arguments are provided +- The server does not support tool calls + +Example protocol error response for invalid parameters: +```json +{ + "jsonrpc": "2.0", + "id": 3, + "error": { + "code": -32602, + "message": "Invalid params", + "data": { + "reason": "Missing required argument: location" + } + } +} +``` + +Example protocol error response for an unknown tool: +```json +{ + "jsonrpc": "2.0", + "id": 4, + "error": { + "code": -32602, + "message": "Invalid params", + "data": { + "reason": "Unknown tool: invalid_tool_name" + } + } +} +``` + +For errors that occur during tool execution (like API failures or invalid data), servers SHOULD return these as part of a successful `CallToolResult`. This allows the LLM to see and potentially handle the error condition: + +```json +{ + "jsonrpc": "2.0", + "id": 5, + "result": { + "toolResult": { + "error": "No search results found for query: 'widgets manufactured in 1972'", + "status": "empty_results" + } + } +} +``` + +## Security Considerations + +Implementations MUST carefully consider the security implications of exposing tools, especially when dealing with sensitive data or external services. Proper authentication and authorization mechanisms SHOULD be in place to prevent unauthorized access to tools. + +Clients SHOULD implement user permission prompts before executing tools, especially for tools that may have side effects or access sensitive information. This allows users to maintain control over the actions performed by the language model. + +Servers SHOULD implement rate limiting and input validation to prevent abuse of tool invocations. \ No newline at end of file From 81605d89183b84ecfd2ad5d97e54b93ed8a0cda2 Mon Sep 17 00:00:00 2001 From: Zack Lee Date: Tue, 19 Nov 2024 16:16:26 -0500 Subject: [PATCH 4/5] migrated specs --- specification/overview.mdx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/specification/overview.mdx b/specification/overview.mdx index 5215929..92e5e7a 100644 --- a/specification/overview.mdx +++ b/specification/overview.mdx @@ -2,14 +2,12 @@ title: Overview --- -_**NOTE:** This is a very early draft. Feel free to discuss changes, requirements, etc._ - -# Goal The Model Context Protocol (MCP) is an attempt to allow implementors to provide context to various LLM surfaces such as editors/IDEs, [claude.ai](https://claude.ai), etc., in a pluggable way. It separates the concerns of providing context from the LLM loop and its usage within. This makes it **much** easier for anyone to script LLM applications for accomplishing their custom workflows, without the application needing to directly offer a large number of integrations. # Terminology + The Model Context Protocol is inspired by Microsoft's [Language Server Protocol](https://microsoft.github.io/language-server-protocol/), with similar concepts: * **Server**: a process or service providing context via MCP. From 8609df65750c1a51ec9af10d15d9bf2017042cdb Mon Sep 17 00:00:00 2001 From: Zack Lee Date: Tue, 19 Nov 2024 22:00:50 -0500 Subject: [PATCH 5/5] big changes --- docs/{core => concepts}/architecture.mdx | 0 docs/{core => concepts}/prompts.mdx | 0 docs/{core => concepts}/resources.mdx | 0 docs/{core => concepts}/sampling.mdx | 0 docs/{core => concepts}/tools.mdx | 0 docs/{core => concepts}/transport.mdx | 0 docs/first-server/python.mdx | 750 +++++++++++++++++++ docs/first-server/typescript.mdx | 631 ++++++++++++++++ docs/guides/first-server-python.mdx | 422 ----------- docs/guides/first-server-ts.mdx | 533 ------------- docs/guides/integrating-with-llm.mdx | 385 ---------- docs/{guides => unused}/integrate-python.mdx | 4 +- docs/{guides => unused}/integrate-ts.mdx | 4 +- favicon.svg | 55 +- introduction.mdx | 77 +- mint.json | 23 +- docs/guides/quickstart.mdx => quickstart.mdx | 17 +- specification/logging.mdx | 2 + 18 files changed, 1429 insertions(+), 1474 deletions(-) rename docs/{core => concepts}/architecture.mdx (100%) rename docs/{core => concepts}/prompts.mdx (100%) rename docs/{core => concepts}/resources.mdx (100%) rename docs/{core => concepts}/sampling.mdx (100%) rename docs/{core => concepts}/tools.mdx (100%) rename docs/{core => concepts}/transport.mdx (100%) create mode 100644 docs/first-server/python.mdx create mode 100644 docs/first-server/typescript.mdx delete mode 100644 docs/guides/first-server-python.mdx delete mode 100644 docs/guides/first-server-ts.mdx delete mode 100644 docs/guides/integrating-with-llm.mdx rename docs/{guides => unused}/integrate-python.mdx (99%) rename docs/{guides => unused}/integrate-ts.mdx (99%) rename docs/guides/quickstart.mdx => quickstart.mdx (94%) diff --git a/docs/core/architecture.mdx b/docs/concepts/architecture.mdx similarity index 100% rename from docs/core/architecture.mdx rename to docs/concepts/architecture.mdx diff --git a/docs/core/prompts.mdx b/docs/concepts/prompts.mdx similarity index 100% rename from docs/core/prompts.mdx rename to docs/concepts/prompts.mdx diff --git a/docs/core/resources.mdx b/docs/concepts/resources.mdx similarity index 100% rename from docs/core/resources.mdx rename to docs/concepts/resources.mdx diff --git a/docs/core/sampling.mdx b/docs/concepts/sampling.mdx similarity index 100% rename from docs/core/sampling.mdx rename to docs/concepts/sampling.mdx diff --git a/docs/core/tools.mdx b/docs/concepts/tools.mdx similarity index 100% rename from docs/core/tools.mdx rename to docs/concepts/tools.mdx diff --git a/docs/core/transport.mdx b/docs/concepts/transport.mdx similarity index 100% rename from docs/core/transport.mdx rename to docs/concepts/transport.mdx diff --git a/docs/first-server/python.mdx b/docs/first-server/python.mdx new file mode 100644 index 0000000..a551d5f --- /dev/null +++ b/docs/first-server/python.mdx @@ -0,0 +1,750 @@ +--- +title: "Python" +description: "Create a simple MCP server in Python in 15 minutes" +--- + +Let's build your first MCP server in Python! We'll create a weather server that provides current weather data as a resource and lets Claude fetch forecasts using tools. + + +This guide uses the OpenWeatherMap API. You'll need a free API key from [OpenWeatherMap](https://openweathermap.org/api) to follow along. + + +## Prerequisites + + + + You'll need Python 3.9 or higher: + + ```bash + python --version # Should be 3.9 or higher + pip --version + ``` + + + + ```bash + mkdir weather-server + cd weather-server + python -m venv venv + source venv/bin/activate # On Windows use: venv\Scripts\activate + ``` + + + + ```bash + pip install modelcontextprotocol requests python-dotenv + ``` + + + + Create `.env`: + ```bash + OPENWEATHER_API_KEY=your-api-key-here + ``` + + + +## Create your server + + + + ```bash + touch weather_server.py + ``` + + + + In `weather_server.py`: + + ```python + import os + import json + from datetime import datetime + from typing import Any, Dict, List, Optional + + import requests + from dotenv import load_dotenv + from modelcontextprotocol import Server, StdioServerTransport + from modelcontextprotocol.types import ( + ListResourcesRequest, + ReadResourceRequest, + ListToolsRequest, + CallToolRequest, + ErrorCode, + McpError + ) + + load_dotenv() + + API_KEY = os.getenv("OPENWEATHER_API_KEY") + if not API_KEY: + raise ValueError("OPENWEATHER_API_KEY environment variable is required") + + API_CONFIG = { + "BASE_URL": "http://api.openweathermap.org/data/2.5", + "DEFAULT_CITY": "San Francisco", + "ENDPOINTS": { + "CURRENT": "weather", + "FORECAST": "forecast" + } + } + + class WeatherServer: + def __init__(self): + self.server = Server( + name="example-weather-server", + version="0.1.0" + ) + + self.session = requests.Session() + self.session.params = { + "appid": API_KEY, + "units": "metric" + } + + self.setup_handlers() + self.setup_error_handling() + + def setup_error_handling(self) -> None: + def on_error(error: Exception) -> None: + print("[MCP Error]", error, flush=True) + + self.server.onerror = on_error + + def setup_handlers(self) -> None: + self.server.set_request_handler( + ListResourcesRequest, self.handle_list_resources) + self.server.set_request_handler( + ReadResourceRequest, self.handle_read_resource) + self.server.set_request_handler( + ListToolsRequest, self.handle_list_tools) + self.server.set_request_handler( + CallToolRequest, self.handle_call_tool) + + async def run(self) -> None: + transport = StdioServerTransport() + await self.server.connect(transport) + print("Weather MCP server running on stdio", flush=True) + + # Handler implementations will continue in next sections +``` + + + + Add these methods to the `WeatherServer` class: + + ```python + async def handle_list_resources( + self, + request: ListResourcesRequest + ) -> Dict[str, Any]: + return { + "resources": [{ + "uri": f"weather://{API_CONFIG['DEFAULT_CITY']}/current", + "name": f"Current weather in {API_CONFIG['DEFAULT_CITY']}", + "mimeType": "application/json", + "description": "Real-time weather data including temperature, conditions, humidity, and wind speed" + }] + } + + async def handle_read_resource( + self, + request: ReadResourceRequest + ) -> Dict[str, Any]: + city = API_CONFIG["DEFAULT_CITY"] + if request.params.uri != f"weather://{city}/current": + raise McpError( + ErrorCode.INVALID_REQUEST, + f"Unknown resource: {request.params.uri}" + ) + + try: + response = self.session.get( + f"{API_CONFIG['BASE_URL']}/{API_CONFIG['ENDPOINTS']['CURRENT']}", + params={"q": city} + ) + response.raise_for_status() + data = response.json() + + weather_data = { + "temperature": data["main"]["temp"], + "conditions": data["weather"][0]["description"], + "humidity": data["main"]["humidity"], + "wind_speed": data["wind"]["speed"], + "timestamp": datetime.now().isoformat() + } + + return { + "contents": [{ + "uri": request.params.uri, + "mimeType": "application/json", + "text": json.dumps(weather_data, indent=2) + }] + } + except requests.RequestException as e: + raise McpError( + ErrorCode.INTERNAL_ERROR, + f"Weather API error: {str(e)}" + ) + ``` + + + + Add these methods to the `WeatherServer` class: + + ```python + async def handle_list_tools( + self, + request: ListToolsRequest + ) -> Dict[str, Any]: + return { + "tools": [{ + "name": "get_forecast", + "description": "Get weather forecast for a city", + "inputSchema": { + "type": "object", + "properties": { + "city": { + "type": "string", + "description": "City name" + }, + "days": { + "type": "number", + "description": "Number of days (1-5)", + "minimum": 1, + "maximum": 5 + } + }, + "required": ["city"] + } + }] + } + + async def handle_call_tool( + self, + request: CallToolRequest + ) -> Dict[str, Any]: + if request.params.name != "get_forecast": + raise McpError( + ErrorCode.METHOD_NOT_FOUND, + f"Unknown tool: {request.params.name}" + ) + + args = request.params.arguments + if not isinstance(args, dict) or "city" not in args: + raise McpError( + ErrorCode.INVALID_PARAMS, + "Invalid forecast arguments" + ) + + city = args["city"] + days = min(int(args.get("days", 3)), 5) + + try: + response = self.session.get( + f"{API_CONFIG['BASE_URL']}/{API_CONFIG['ENDPOINTS']['FORECAST']}", + params={ + "q": city, + "cnt": days * 8 # API returns 3-hour intervals + } + ) + response.raise_for_status() + data = response.json() + + forecasts = [] + for i in range(0, len(data["list"]), 8): + day_data = data["list"][i] + forecasts.append({ + "date": day_data["dt_txt"].split()[0], + "temperature": day_data["main"]["temp"], + "conditions": day_data["weather"][0]["description"] + }) + + return {"toolResult": forecasts} + except requests.RequestException as e: + raise McpError( + ErrorCode.INTERNAL_ERROR, + f"Weather API error: {str(e)}" + ) + ``` + + + + Add this to the end of `weather_server.py`: + + ```python + if __name__ == "__main__": + import asyncio + import signal + + async def main(): + server = WeatherServer() + + def signal_handler(sig, frame): + print("Shutting down...", flush=True) + asyncio.create_task(server.server.close()) + + signal.signal(signal.SIGINT, signal_handler) + await server.run() + + asyncio.run(main()) + ``` + + + + ```bash + chmod +x weather_server.py + pip install -e . + ``` + + Create `setup.py`: + ```python + from setuptools import setup + + setup( + name="weather-server", + version="0.1.0", + py_modules=["weather_server"], + entry_points={ + "console_scripts": [ + "weather-server=weather_server:main", + ], + }, + install_requires=[ + "modelcontextprotocol", + "requests", + "python-dotenv" + ], + ) + ``` + + + +## Understanding the code + + + + ```python + async def handle_read_resource( + self, + request: ReadResourceRequest + ) -> Dict[str, Any]: + # ... + ``` + Python type hints help catch errors early and improve code maintainability. + + + + ```python + async def handle_list_resources( + self, + request: ListResourcesRequest + ) -> Dict[str, Any]: + return { + "resources": [{ + "uri": f"weather://{DEFAULT_CITY}/current", + "name": f"Current weather in {DEFAULT_CITY}", + "mimeType": "application/json" + }] + } + ``` + Resources provide data that Claude can access as context. + + + + ```python + { + "name": "get_forecast", + "description": "Get weather forecast for a city", + "inputSchema": { + "type": "object", + "properties": { + "city": { "type": "string" }, + "days": { "type": "number" } + } + } + } + ``` + Tools let Claude take actions through your server with validated inputs. + + + +## Best practices + + + + ```python + try: + response = self.session.get(...) + response.raise_for_status() + except requests.RequestException as e: + raise McpError( + ErrorCode.INTERNAL_ERROR, + f"API error: {str(e)}" + ) + ``` + + + + ```python + if not isinstance(args, dict) or "city" not in args: + raise McpError( + ErrorCode.INVALID_PARAMS, + "Invalid forecast arguments" + ) + ``` + + + + ```python + if not API_KEY: + raise ValueError("OPENWEATHER_API_KEY is required") + ``` + + + + ```python + API_CONFIG = { + "BASE_URL": "...", + "ENDPOINTS": { + "CURRENT": "weather", + "FORECAST": "forecast" + } + } + ``` + + + +## Available Transports + +While this guide uses stdio transport, MCP supports multiple transport options: + +### WebSocket +```python +from modelcontextprotocol import WebSocketServerTransport +transport = WebSocketServerTransport() +``` + +### SSE (Server-Sent Events) +```python +from modelcontextprotocol import SSEServerTransport +transport = SSEServerTransport("/events", response) +``` + +## Troubleshooting + +### Installation Issues +```bash +# Check Python version +python --version + +# Reinstall dependencies +pip uninstall -r requirements.txt +pip install -r requirements.txt +``` + +### Runtime Errors +```bash +# Enable debug logging +export MCP_LOG_LEVEL=DEBUG +python weather_server.py +``` + +### Type Checking +```bash +# Install mypy +pip install mypy + +# Run type checker +mypy weather_server.py +``` + +## Connect to Claude Desktop + + + + Add to `claude_desktop_config.json`: + + ```json + { + "mcpServers": { + "weather": { + "command": "weather-server", + "env": { + "OPENWEATHER_API_KEY": "your-api-key", + } + } + } + } + ``` + + + + 1. Quit Claude completely + 2. Start Claude again + 3. Look for your weather server in the 🔌 menu + + + +## Try it out! + + + + Ask Claude: + ``` + What's the current weather in San Francisco? Can you analyze the conditions and tell me if it's a good day for outdoor activities? + ``` + + + + Ask Claude: + ``` + Can you get me a 5-day forecast for Tokyo and help me plan what clothes to pack for my trip? + ``` + + + + Ask Claude: + ``` + Can you analyze the forecast for both Tokyo and San Francisco and tell me which city would be better for outdoor photography this week? + ``` + + + +## Advanced Features + + + + ```python + from functools import lru_cache + from datetime import datetime, timedelta + + class WeatherServer: + def __init__(self): + self._cache_timeout = timedelta(minutes=15) + self._last_cache_time = None + self._cached_weather = None + + @lru_cache(maxsize=32) + async def _fetch_weather(self, city: str) -> Dict[str, Any]: + # Cache expires after 15 minutes + now = datetime.now() + if (self._cached_weather is None or + self._last_cache_time is None or + now - self._last_cache_time > self._cache_timeout): + + response = self.session.get(...) + self._cached_weather = response.json() + self._last_cache_time = now + + return self._cached_weather + ``` + + + + ```python + async def handle_call_tool( + self, + request: CallToolRequest + ) -> Dict[str, Any]: + if progress_token := request.params._meta.get("progressToken"): + # Send progress notifications + await self.server.notification({ + "method": "notifications/progress", + "params": { + "progress": 1, + "total": 2, + "progressToken": progress_token + } + }) + + # Fetch data... + + await self.server.notification({ + "method": "notifications/progress", + "params": { + "progress": 2, + "total": 2, + "progressToken": progress_token + } + }) + ``` + + + + ```python + import logging + + class WeatherServer: + def __init__(self): + self.logger = logging.getLogger("weather-server") + self.logger.setLevel(logging.INFO) + + # Set up logging handler + self.server.set_request_handler( + SetLevelRequest, + self.handle_set_log_level + ) + + async def handle_set_log_level( + self, + request: SetLevelRequest + ) -> Dict[str, Any]: + level = request.params.level.upper() + self.logger.setLevel(getattr(logging, level)) + + await self.server.notification({ + "method": "notifications/message", + "params": { + "level": "info", + "logger": "weather-server", + "data": f"Log level set to {level}" + } + }) + return {} + ``` + + + + ```python + async def handle_list_resources( + self, + request: ListResourcesRequest + ) -> Dict[str, Any]: + return { + "resources": [...], + "resourceTemplates": [{ + "uriTemplate": "weather://{city}/current", + "name": "Current weather for any city", + "mimeType": "application/json" + }] + } + ``` + + + +## Testing + + + + Create `test_weather_server.py`: + + ```python + import pytest + from unittest.mock import Mock, patch + from weather_server import WeatherServer + + @pytest.fixture + async def server(): + server = WeatherServer() + yield server + await server.server.close() + + @pytest.mark.asyncio + async def test_list_resources(server): + request = Mock() + result = await server.handle_list_resources(request) + assert len(result["resources"]) > 0 + assert result["resources"][0]["mimeType"] == "application/json" + + @pytest.mark.asyncio + async def test_get_forecast(): + with patch("requests.Session") as mock_session: + mock_session.return_value.get.return_value.json.return_value = { + "list": [{ + "dt_txt": "2024-01-01 12:00:00", + "main": {"temp": 20}, + "weather": [{"description": "sunny"}] + }] + } + + server = WeatherServer() + request = Mock() + request.params.name = "get_forecast" + request.params.arguments = {"city": "Tokyo", "days": 1} + + result = await server.handle_call_tool(request) + assert len(result["toolResult"]) == 1 + assert result["toolResult"][0]["temperature"] == 20 + ``` + + + + ```bash + pip install pytest pytest-asyncio + pytest test_weather_server.py -v + ``` + + + +## Deployment + + + + ```dockerfile + FROM python:3.11-slim + + WORKDIR /app + COPY requirements.txt . + RUN pip install -r requirements.txt + + COPY . . + + CMD ["python", "weather_server.py"] + ``` + + + + ```ini + [Unit] + Description=Weather MCP Server + After=network.target + + [Service] + ExecStart=/path/to/venv/bin/python /path/to/weather_server.py + Environment=OPENWEATHER_API_KEY=your-key-here + Restart=always + + [Install] + WantedBy=multi-user.target + ``` + + + +## Next steps + + + + Learn more about the MCP architecture + + + + Read more about the Python SDK + + \ No newline at end of file diff --git a/docs/first-server/typescript.mdx b/docs/first-server/typescript.mdx new file mode 100644 index 0000000..ecd06d8 --- /dev/null +++ b/docs/first-server/typescript.mdx @@ -0,0 +1,631 @@ +--- +title: "TypeScript" +description: "Create a simple MCP server in TypeScript in 15 minutes" +--- + +Let's build your first MCP server in TypeScript! We'll create a weather server that provides current weather data as a resource and lets Claude fetch forecasts using tools. + + +This guide uses the OpenWeatherMap API. You'll need a free API key from [OpenWeatherMap](https://openweathermap.org/api) to follow along. + + +## Prerequisites + + + + You'll need Node.js 18 or higher: + + ```bash + node --version # Should be v18 or higher + npm --version + ``` + + + + ```bash + mkdir weather-server + cd weather-server + npm init -y + ``` + + + + ```bash + npm install @modelcontextprotocol/sdk axios dotenv typescript @types/node + npm install --save-dev ts-node + ``` + + + + Create `tsconfig.json`: + ```json + { + "compilerOptions": { + "target": "ES2020", + "module": "ES2020", + "moduleResolution": "node", + "esModuleInterop": true, + "outDir": "./dist", + "rootDir": "./src", + "strict": true + }, + "include": ["src/**/*"] + } + ``` + + + + Create `.env`: + ```bash + OPENWEATHER_API_KEY=your-api-key-here + ``` + + + +## Create your server + + + + ```bash + mkdir src + touch src/index.ts + touch src/types.ts + ``` + + + + In `src/types.ts`: + + ```typescript + export interface OpenWeatherResponse { + main: { + temp: number; + humidity: number; + }; + weather: Array<{ + description: string; + }>; + wind: { + speed: number; + }; + dt_txt?: string; + } + + export interface WeatherData { + temperature: number; + conditions: string; + humidity: number; + wind_speed: number; + timestamp: string; + } + + export interface ForecastDay { + date: string; + temperature: number; + conditions: string; + } + + export interface GetForecastArgs { + city: string; + days?: number; + } + + // Type guard for forecast arguments + export function isValidForecastArgs(args: unknown): args is GetForecastArgs { + return ( + typeof args === "object" && + args !== null && + "city" in args && + typeof args.city === "string" && + (args.days === undefined || typeof args.days === "number") + ); + } + ``` + + + + In `src/index.ts`: + + ```typescript + import { Server } from "@modelcontextprotocol/sdk/server/index.js"; + import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; + import { + ListResourcesRequestSchema, + ReadResourceRequestSchema, + ListToolsRequestSchema, + CallToolRequestSchema, + ErrorCode, + McpError + } from "@modelcontextprotocol/sdk/types.js"; + import axios from "axios"; + import dotenv from "dotenv"; + import { + WeatherData, + ForecastDay, + GetForecastArgs, + OpenWeatherResponse, + isValidForecastArgs + } from "./types.js"; + + dotenv.config(); + + const API_KEY = process.env.OPENWEATHER_API_KEY; + if (!API_KEY) { + throw new Error("OPENWEATHER_API_KEY environment variable is required"); + } + + const API_CONFIG = { + BASE_URL: 'http://api.openweathermap.org/data/2.5', + DEFAULT_CITY: 'San Francisco', + ENDPOINTS: { + CURRENT: 'weather', + FORECAST: 'forecast' + } + } as const; + + class WeatherServer { + private server: Server; + private axiosInstance; + + constructor() { + this.server = new Server({ + name: "example-weather-server", + version: "0.1.0" + }); + + // Configure axios with defaults + this.axiosInstance = axios.create({ + baseURL: API_CONFIG.BASE_URL, + params: { + appid: API_KEY, + units: "metric" + } + }); + + this.setupHandlers(); + this.setupErrorHandling(); + } + + private setupErrorHandling(): void { + this.server.onerror = (error) => { + console.error("[MCP Error]", error); + }; + + process.on('SIGINT', async () => { + await this.server.close(); + process.exit(0); + }); + } + + private setupHandlers(): void { + this.setupResourceHandlers(); + this.setupToolHandlers(); + } + + private setupResourceHandlers(): void { + // Implementation continues in next section + } + + private setupToolHandlers(): void { + // Implementation continues in next section + } + + async run(): Promise { + const transport = new StdioServerTransport(); + await this.server.connect(transport); + console.log("Weather MCP server running on stdio"); + } + } + + const server = new WeatherServer(); + server.run().catch(console.error); + ``` + + + + Add this to the `setupHandlers` method: + + ```typescript + private setupResourceHandlers(): void { + this.server.setRequestHandler( + ListResourcesRequestSchema, + async () => ({ + resources: [{ + uri: `weather://${API_CONFIG.DEFAULT_CITY}/current`, + name: `Current weather in ${API_CONFIG.DEFAULT_CITY}`, + mimeType: "application/json", + description: "Real-time weather data including temperature, conditions, humidity, and wind speed" + }] + }) + ); + + this.server.setRequestHandler( + ReadResourceRequestSchema, + async (request) => { + const city = API_CONFIG.DEFAULT_CITY; + if (request.params.uri !== `weather://${city}/current`) { + throw new McpError( + ErrorCode.InvalidRequest, + `Unknown resource: ${request.params.uri}` + ); + } + + try { + const response = await this.axiosInstance.get( + API_CONFIG.ENDPOINTS.CURRENT, + { + params: { q: city } + } + ); + + const weatherData: WeatherData = { + temperature: response.data.main.temp, + conditions: response.data.weather[0].description, + humidity: response.data.main.humidity, + wind_speed: response.data.wind.speed, + timestamp: new Date().toISOString() + }; + + return { + contents: [{ + uri: request.params.uri, + mimeType: "application/json", + text: JSON.stringify(weatherData, null, 2) + }] + }; + } catch (error) { + if (axios.isAxiosError(error)) { + throw new McpError( + ErrorCode.InternalError, + `Weather API error: ${error.response?.data.message ?? error.message}` + ); + } + throw error; + } + } + ); + } + ``` + + + + Add these handlers to the `setupHandlers` method: + + ```typescript + private setupToolHandlers(): void { + this.server.setRequestHandler( + ListToolsRequestSchema, + async () => ({ + tools: [{ + name: "get_forecast", + description: "Get weather forecast for a city", + inputSchema: { + type: "object", + properties: { + city: { + type: "string", + description: "City name" + }, + days: { + type: "number", + description: "Number of days (1-5)", + minimum: 1, + maximum: 5 + } + }, + required: ["city"] + } + }] + }) + ); + + this.server.setRequestHandler( + CallToolRequestSchema, + async (request) => { + if (request.params.name !== "get_forecast") { + throw new McpError( + ErrorCode.MethodNotFound, + `Unknown tool: ${request.params.name}` + ); + } + + if (!isValidForecastArgs(request.params.arguments)) { + throw new McpError( + ErrorCode.InvalidParams, + "Invalid forecast arguments" + ); + } + + const city = request.params.arguments.city; + const days = Math.min(request.params.arguments.days || 3, 5); + + try { + const response = await this.axiosInstance.get<{ + list: OpenWeatherResponse[] + }>(API_CONFIG.ENDPOINTS.FORECAST, { + params: { + q: city, + cnt: days * 8 // API returns 3-hour intervals + } + }); + + const forecasts: ForecastDay[] = []; + for (let i = 0; i < response.data.list.length; i += 8) { + const dayData = response.data.list[i]; + forecasts.push({ + date: dayData.dt_txt?.split(' ')[0] ?? new Date().toISOString().split('T')[0], + temperature: dayData.main.temp, + conditions: dayData.weather[0].description + }); + } + + return { toolResult: forecasts }; + } catch (error) { + if (axios.isAxiosError(error)) { + throw new McpError( + ErrorCode.InternalError, + `Weather API error: ${error.response?.data.message ?? error.message}` + ); + } + throw error; + } + } + ); + } + ``` + + + + Add these scripts to `package.json`: + ```json + { + "scripts": { + "build": "tsc", + "start": "node dist/index.js", + "dev": "ts-node src/index.ts" + } + } + ``` + + Then run: + ```bash + npm run build + npm install -g . + ``` + + + +## Connect to Claude Desktop + + + + Add to `claude_desktop_config.json`: + + ```json + { + "mcpServers": { + "weather": { + "command": "weather-server", + "env": { + "OPENWEATHER_API_KEY": "your-api-key", + } + } + } + } + ``` + + + + 1. Quit Claude completely + 2. Start Claude again + 3. Look for your weather server in the 🔌 menu + + + +## Try it out! + + + + Ask Claude: + ``` + What's the current weather in San Francisco? Can you analyze the conditions? + ``` + + + + Ask Claude: + ``` + Can you get me a 5-day forecast for Tokyo and tell me if I should pack an umbrella? + ``` + + + + Ask Claude: + ``` + Can you analyze the forecast for both Tokyo and San Francisco and tell me which city will be warmer this week? + ``` + + + +## Understanding the code + + + + ```typescript + interface WeatherData { + temperature: number; + conditions: string; + humidity: number; + wind_speed: number; + timestamp: string; + } + ``` + TypeScript adds type safety to our MCP server, making it more reliable and easier to maintain. + + + + ```typescript + this.server.setRequestHandler( + ListResourcesRequestSchema, + async () => ({ + resources: [{ + uri: `weather://${DEFAULT_CITY}/current`, + name: `Current weather in ${DEFAULT_CITY}`, + mimeType: "application/json" + }] + }) + ); + ``` + Resources provide data that Claude can access as context. + + + + ```typescript + { + name: "get_forecast", + description: "Get weather forecast for a city", + inputSchema: { + type: "object", + properties: { + city: { type: "string" }, + days: { type: "number" } + } + } + } + ``` + Tools let Claude take actions through your server with type-safe inputs. + + + +## Best practices + + + + ```typescript + try { + const response = await this.axiosInstance.get(...); + } catch (error) { + if (axios.isAxiosError(error)) { + throw new McpError( + ErrorCode.InternalError, + `API error: ${error.response?.data.message}` + ); + } + throw error; + } + ``` + + + + ```typescript + function isValidForecastArgs(args: unknown): args is GetForecastArgs { + return ( + typeof args === "object" && + args !== null && + "city" in args && + typeof args.city === "string" + ); + } + ``` + + + + ```typescript + if (!process.env.OPENWEATHER_API_KEY) { + throw new Error("OPENWEATHER_API_KEY is required"); + } + ``` + + + + ```typescript + const API_CONFIG = { + BASE_URL: '...', + ENDPOINTS: { + CURRENT: 'weather', + FORECAST: 'forecast' + } + } as const; + ``` + + + +## Available Transports + +While this guide uses stdio transport, MCP supports multiple transport options: + +### WebSocket +```typescript +import { WebSocketServerTransport } from "@modelcontextprotocol/sdk/server/websocket.js"; +const transport = new WebSocketServerTransport(); +``` + +### SSE (Server-Sent Events) +```typescript +import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js"; +const transport = new SSEServerTransport("/events", response); +``` + +## Troubleshooting + +### Build Errors +```bash +# Check TypeScript version +npx tsc --version + +# Clean and rebuild +rm -rf dist/ +npm run build +``` + +### Runtime Errors +Look for detailed error messages in the Claude app logs: +```bash +# Launch Claude with logging +open /Applications/Claude.app --stdout ~/Claude.log --stderr ~/Claude.log + +# Monitor logs +tail -f ~/Claude.log +``` + +### Type Errors +```bash +# Check types without building +npx tsc --noEmit +``` + +## Next steps + + + + Learn more about the MCP architecture + + + + Read more about the TypeScript SDK + + + + +Need help? Ask Claude! Since it has access to the MCP SDK documentation, it can help you debug issues and suggest improvements to your server. + \ No newline at end of file diff --git a/docs/guides/first-server-python.mdx b/docs/guides/first-server-python.mdx deleted file mode 100644 index 3068ccb..0000000 --- a/docs/guides/first-server-python.mdx +++ /dev/null @@ -1,422 +0,0 @@ ---- -title: "Python" -description: "Create a simple MCP server in Python in 15 minutes" ---- - -Let's build your first MCP server in Python! We'll create a weather server that provides current weather data as a resource and lets Claude fetch forecasts using tools. - - -This guide uses the OpenWeatherMap API. You'll need a free API key from [OpenWeatherMap](https://openweathermap.org/api) to follow along. - - -## Prerequisites - - - - You'll need Python 3.8 or higher: - - ```bash - python3 --version # Should be 3.8 or higher - ``` - - - - ```bash - # Create and activate virtual environment - python3 -m venv mcp-weather - cd mcp-weather - source bin/activate # On Windows: .\Scripts\activate - ``` - - - - ```bash - pip install modelcontextprotocol-sdk requests - ``` - - - - 1. Sign up at [OpenWeatherMap](https://openweathermap.org/api) - 2. Copy your API key - 3. Set it as an environment variable: - ```bash - export OPENWEATHER_API_KEY='your-api-key' - ``` - - - -## Create your server - - - - ```bash - mkdir weather_server - cd weather_server - touch weather_server.py - ``` - - - - Open `weather_server.py` and add this starter code: - - ```python - from modelcontextprotocol.server import Server - from modelcontextprotocol.server.stdio import StdioServerTransport - from modelcontextprotocol.types import ( - ListResourcesRequestSchema, - ListToolsRequestSchema, - ReadResourceRequestSchema, - CallToolRequestSchema - ) - import os - import requests - import json - from datetime import datetime - - API_KEY = os.getenv('OPENWEATHER_API_KEY') - BASE_URL = 'http://api.openweathermap.org/data/2.5' - - class WeatherServer: - def __init__(self): - self.server = Server( - name="example-weather-server", - version="0.1.0" - ) - self.default_city = "San Francisco" - self.setup_handlers() - - def setup_handlers(self): - # We'll add handlers here - pass - - async def run(self): - transport = StdioServerTransport() - await self.server.connect(transport) - - if __name__ == "__main__": - import asyncio - server = WeatherServer() - asyncio.run(server.run()) - ``` - - - - Let's add handlers to expose current weather as a resource: - - ```python - def setup_handlers(self): - self.server.set_request_handler( - ListResourcesRequestSchema, - self.handle_list_resources - ) - self.server.set_request_handler( - ReadResourceRequestSchema, - self.handle_read_resource - ) - - async def handle_list_resources(self, request): - return { - "resources": [{ - "uri": f"weather://{self.default_city}/current", - "name": f"Current weather in {self.default_city}", - "mimeType": "application/json" - }] - } - - async def handle_read_resource(self, request): - city = self.default_city - if request.params.uri != f"weather://{city}/current": - raise ValueError(f"Unknown resource: {request.params.uri}") - - response = requests.get( - f"{BASE_URL}/weather", - params={ - "q": city, - "appid": API_KEY, - "units": "metric" - } - ) - data = response.json() - - return { - "contents": [{ - "uri": request.params.uri, - "mimeType": "application/json", - "text": json.dumps({ - "temperature": data["main"]["temp"], - "conditions": data["weather"][0]["description"], - "humidity": data["main"]["humidity"], - "wind_speed": data["wind"]["speed"], - "timestamp": datetime.now().isoformat() - }, indent=2) - }] - } - ``` - - - - Now let's add a tool to fetch weather forecasts: - - ```python - def setup_handlers(self): - # Add these lines to the existing method - self.server.set_request_handler( - ListToolsRequestSchema, - self.handle_list_tools - ) - self.server.set_request_handler( - CallToolRequestSchema, - self.handle_call_tool - ) - - async def handle_list_tools(self, request): - return { - "tools": [{ - "name": "get_forecast", - "description": "Get weather forecast for a city", - "inputSchema": { - "type": "object", - "properties": { - "city": { - "type": "string", - "description": "City name" - }, - "days": { - "type": "number", - "description": "Number of days (1-5)" - } - }, - "required": ["city"] - } - }] - } - - async def handle_call_tool(self, request): - if request.params.name != "get_forecast": - raise ValueError(f"Unknown tool: {request.params.name}") - - args = request.params.arguments - city = args.get("city", self.default_city) - days = min(int(args.get("days", 3)), 5) - - response = requests.get( - f"{BASE_URL}/forecast", - params={ - "q": city, - "appid": API_KEY, - "units": "metric", - "cnt": days * 8 # API returns 3-hour intervals - } - ) - data = response.json() - - # Process and return daily forecasts - forecasts = [] - for i in range(0, len(data["list"]), 8): # One day = 8 intervals - day_data = data["list"][i] - forecasts.append({ - "date": day_data["dt_txt"].split()[0], - "temperature": day_data["main"]["temp"], - "conditions": day_data["weather"][0]["description"] - }) - - return {"toolResult": forecasts} - ``` - - - - 1. Save all changes - 2. Run your server: - ```bash - python weather_server.py - ``` - - - -## Connect to Claude - - - - ```bash - # From your project directory - pip install -e . - ``` - - - - Add this to your `claude_desktop_config.json`: - - ```json - { - "mcpServers": { - "weather": { - "command": "python", - "args": ["-m", "weather_server"], - "env": { - "OPENWEATHER_API_KEY": "your-api-key", - "HOME": "/Users/YOUR_USERNAME" - } - } - } - } - ``` - - - - 1. Quit Claude completely - 2. Start Claude again - 3. Verify your weather server appears in the 🔌 menu - - - -## Try it out! - - - - Ask Claude: - ``` - What's the current weather in San Francisco? Can you analyze the conditions? - ``` - - Claude will: - 1. Access the weather resource - 2. Parse the JSON data - 3. Provide a natural language summary - - - - Ask Claude: - ``` - Can you get me a 5-day forecast for Tokyo and tell me if I should pack an umbrella? - ``` - - Claude will: - 1. Use the `get_forecast` tool - 2. Analyze the forecast data - 3. Give you packing advice - - - -## Understanding the code - -Let's break down the key MCP concepts used in this server: - - - - ```python - async def handle_list_resources(self, request): - return { - "resources": [{ - "uri": f"weather://{self.default_city}/current", - "name": f"Current weather in {self.default_city}", - "mimeType": "application/json" - }] - } - ``` - Resources provide data that Claude can access as context. In this case, we're exposing current weather data that Claude can read and analyze. - - - - ```python - async def handle_list_tools(self, request): - return { - "tools": [{ - "name": "get_forecast", - "description": "Get weather forecast for a city", - "inputSchema": { - "type": "object", - "properties": { - "city": {"type": "string"}, - "days": {"type": "number"} - } - } - }] - } - ``` - Tools let Claude take actions through your server. The `inputSchema` defines what parameters Claude can provide. - - - - ```python - async def run(self): - transport = StdioServerTransport() - await self.server.connect(transport) - ``` - The transport layer handles communication between Claude and your server. Here we're using stdio, but MCP also supports WebSocket and SSE. - - - -## Next steps - -Now that you've built your first MCP server, try these enhancements: - - - - - Air quality data - - Weather alerts - - Historical weather - - - - - Compare multiple cities - - Get detailed hourly forecasts - - Save favorite locations - - - - - Handle API errors gracefully - - Add input validation - - Rate limiting - - - - - Weather alerts - - Temperature changes - - Condition updates - - - -## Troubleshooting - - - - ```bash - pip install modelcontextprotocol-sdk --upgrade - ``` - Ensure you're using the latest SDK version. - - - - 1. Verify your API key is set: - ```bash - echo $OPENWEATHER_API_KEY - ``` - 2. Check the API response for error messages - 3. Ensure you're within free tier limits - - - - 1. Check Claude's logs: - ```bash - tail -f ~/Claude.log - ``` - 2. Verify your config JSON syntax - 3. Ensure Python path is correct in config - - - - -Remember: This is just the beginning! MCP servers can provide any type of data or functionality to Claude. Think about what unique capabilities you could add to Claude through MCP. - \ No newline at end of file diff --git a/docs/guides/first-server-ts.mdx b/docs/guides/first-server-ts.mdx deleted file mode 100644 index 2615856..0000000 --- a/docs/guides/first-server-ts.mdx +++ /dev/null @@ -1,533 +0,0 @@ ---- -title: "TypeScript" -description: "Create a simple MCP server in TypeScript in 15 minutes" ---- - -Let's build your first MCP server in TypeScript! We'll create a weather server that provides current weather data as a resource and lets Claude fetch forecasts using tools. - - -This guide uses the OpenWeatherMap API. You'll need a free API key from [OpenWeatherMap](https://openweathermap.org/api) to follow along. - - -## Prerequisites - - - - You'll need Node.js 16 or higher: - - ```bash - node --version # Should be v16 or higher - npm --version - ``` - - - - ```bash - mkdir weather-server - cd weather-server - npm init -y - ``` - - - - ```bash - npm install @modelcontextprotocol/sdk axios dotenv typescript @types/node - npm install --save-dev ts-node - ``` - - - - Create `tsconfig.json`: - ```json - { - "compilerOptions": { - "target": "ES2020", - "module": "ES2020", - "moduleResolution": "node", - "esModuleInterop": true, - "outDir": "./dist", - "rootDir": "./src", - "strict": true - }, - "include": ["src/**/*"] - } - ``` - - - - Create `.env`: - ```bash - OPENWEATHER_API_KEY=your-api-key-here - ``` - - - -## Create your server - - - - ```bash - mkdir src - touch src/index.ts - touch src/types.ts - ``` - - - - In `src/types.ts`: - - ```typescript - export interface WeatherData { - temperature: number; - conditions: string; - humidity: number; - wind_speed: number; - timestamp: string; - } - - export interface ForecastDay { - date: string; - temperature: number; - conditions: string; - } - - export interface GetForecastArgs { - city: string; - days?: number; - } - ``` - - - - In `src/index.ts`: - - ```typescript - import { Server } from "@modelcontextprotocol/sdk/server/index.js"; - import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; - import axios from "axios"; - import dotenv from "dotenv"; - import { WeatherData, ForecastDay, GetForecastArgs } from "./types.js"; - - dotenv.config(); - - const API_KEY = process.env.OPENWEATHER_API_KEY; - const BASE_URL = 'http://api.openweathermap.org/data/2.5'; - const DEFAULT_CITY = 'San Francisco'; - - class WeatherServer { - private server: Server; - - constructor() { - this.server = new Server({ - name: "example-weather-server", - version: "0.1.0" - }); - this.setupHandlers(); - } - - private setupHandlers(): void { - // We'll add handlers here - } - - async run(): Promise { - const transport = new StdioServerTransport(); - await this.server.connect(transport); - } - } - - const server = new WeatherServer(); - server.run().catch(console.error); - ``` - - - - Add this to the `setupHandlers` method: - - ```typescript - private setupHandlers(): void { - this.server.setRequestHandler( - ListResourcesRequestSchema, - async () => ({ - resources: [{ - uri: `weather://${DEFAULT_CITY}/current`, - name: `Current weather in ${DEFAULT_CITY}`, - mimeType: "application/json" - }] - }) - ); - - this.server.setRequestHandler( - ReadResourceRequestSchema, - async (request) => { - const city = DEFAULT_CITY; - if (request.params.uri !== `weather://${city}/current`) { - throw new Error(`Unknown resource: ${request.params.uri}`); - } - - const response = await axios.get(`${BASE_URL}/weather`, { - params: { - q: city, - appid: API_KEY, - units: "metric" - } - }); - - const weatherData: WeatherData = { - temperature: response.data.main.temp, - conditions: response.data.weather[0].description, - humidity: response.data.main.humidity, - wind_speed: response.data.wind.speed, - timestamp: new Date().toISOString() - }; - - return { - contents: [{ - uri: request.params.uri, - mimeType: "application/json", - text: JSON.stringify(weatherData, null, 2) - }] - }; - } - ); - } - ``` - - - - Add these handlers to the `setupHandlers` method: - - ```typescript - this.server.setRequestHandler( - ListToolsRequestSchema, - async () => ({ - tools: [{ - name: "get_forecast", - description: "Get weather forecast for a city", - inputSchema: { - type: "object", - properties: { - city: { - type: "string", - description: "City name" - }, - days: { - type: "number", - description: "Number of days (1-5)" - } - }, - required: ["city"] - } - }] - }) - ); - - this.server.setRequestHandler( - CallToolRequestSchema, - async (request) => { - if (request.params.name !== "get_forecast") { - throw new Error(`Unknown tool: ${request.params.name}`); - } - - const args = request.params.arguments as GetForecastArgs; - const city = args.city || DEFAULT_CITY; - const days = Math.min(args.days || 3, 5); - - const response = await axios.get(`${BASE_URL}/forecast`, { - params: { - q: city, - appid: API_KEY, - units: "metric", - cnt: days * 8 // API returns 3-hour intervals - } - }); - - const forecasts: ForecastDay[] = []; - for (let i = 0; i < response.data.list.length; i += 8) { - const dayData = response.data.list[i]; - forecasts.push({ - date: dayData.dt_txt.split(' ')[0], - temperature: dayData.main.temp, - conditions: dayData.weather[0].description - }); - } - - return { toolResult: forecasts }; - } - ); - ``` - - - - Add these scripts to `package.json`: - ```json - { - "scripts": { - "build": "tsc", - "start": "node dist/index.js", - "dev": "ts-node src/index.ts" - } - } - ``` - - Then run: - ```bash - npm run build - npm start - ``` - - - -## Connect to Claude - - - - ```bash - npm install -g - ``` - - - - Add to `claude_desktop_config.json`: - - ```json - { - "mcpServers": { - "weather": { - "command": "weather-server", - "env": { - "OPENWEATHER_API_KEY": "your-api-key", - "HOME": "/Users/YOUR_USERNAME" - } - } - } - } - ``` - - - - 1. Quit Claude completely - 2. Start Claude again - 3. Look for your weather server in the 🔌 menu - - - -## Try it out! - - - - Ask Claude: - ``` - What's the current weather in San Francisco? Can you analyze the conditions? - ``` - - - - Ask Claude: - ``` - Can you get me a 5-day forecast for Tokyo and tell me if I should pack an umbrella? - ``` - - - - Ask Claude: - ``` - Can you analyze the forecast for both Tokyo and San Francisco and tell me which city will be warmer this week? - ``` - - - -## Understanding the code - - - - ```typescript - interface WeatherData { - temperature: number; - conditions: string; - humidity: number; - wind_speed: number; - timestamp: string; - } - ``` - TypeScript adds type safety to our MCP server, making it more reliable and easier to maintain. - - - - ```typescript - this.server.setRequestHandler( - ListResourcesRequestSchema, - async () => ({ - resources: [{ - uri: `weather://${DEFAULT_CITY}/current`, - name: `Current weather in ${DEFAULT_CITY}`, - mimeType: "application/json" - }] - }) - ); - ``` - Resources provide data that Claude can access as context. - - - - ```typescript - { - name: "get_forecast", - description: "Get weather forecast for a city", - inputSchema: { - type: "object", - properties: { - city: { type: "string" }, - days: { type: "number" } - } - } - } - ``` - Tools let Claude take actions through your server with type-safe inputs. - - - -## Best practices - - - - ```typescript - try { - const response = await axios.get(url); - } catch (error) { - if (axios.isAxiosError(error)) { - throw new Error(`API error: ${error.response?.data.message}`); - } - throw error; - } - ``` - - - - ```typescript - function isValidForecastArgs(args: unknown): args is GetForecastArgs { - return typeof args === "object" && args !== null && - "city" in args; - } - ``` - - - - ```typescript - if (!process.env.OPENWEATHER_API_KEY) { - throw new Error("OPENWEATHER_API_KEY is required"); - } - ``` - - - - ```typescript - const API_ENDPOINTS = { - CURRENT: "weather", - FORECAST: "forecast" - } as const; - ``` - - - -## Enhancements - -Try adding these features to your server: - - - - Add dynamic city resources: - ```typescript - uriTemplate: "weather://{city}/current" - ``` - - - - Cache API responses: - ```typescript - import NodeCache from "node-cache" - ``` - - - - Add API rate limiting: - ```typescript - import rateLimit from "axios-rate-limit" - ``` - - - -## Troubleshooting - - - - ```bash - # Check TypeScript version - npx tsc --version - - # Clean and rebuild - rm -rf dist/ - npm run build - ``` - - - - Add better error logging: - ```typescript - server.onerror = (error) => { - console.error("[MCP Error]", error); - }; - ``` - - - - ```bash - # Check types without building - npx tsc --noEmit - ``` - - - -## Next steps - - - - Switch to real-time updates with WebSocket transport - - - - Add Jest tests for your MCP server - - - - -Need help? Ask Claude! Since it has access to the MCP SDK documentation, it can help you debug issues and suggest improvements to your server. - \ No newline at end of file diff --git a/docs/guides/integrating-with-llm.mdx b/docs/guides/integrating-with-llm.mdx deleted file mode 100644 index a801e53..0000000 --- a/docs/guides/integrating-with-llm.mdx +++ /dev/null @@ -1,385 +0,0 @@ ---- -title: "Integrating MCP into Your LLM Application" -description: 'Learn how to integrate the Model Context Protocol (MCP) into your LLM-powered applications' ---- - -The Model Context Protocol (MCP) enables seamless integration between LLM applications and various data sources and tools. This guide will walk you through integrating MCP into your own LLM-powered chatbot application. - -## Our Example Chatbot - -For this guide, we'll be working with a hypothetical customer service chatbot for a software company. Our chatbot currently: - -- Uses an LLM API (like Anthropic's Claude API) to generate responses -- Maintains conversation history in memory -- Has basic error handling and retry logic -- Runs as a web service that customers interact with through a REST API - -However, our chatbot faces some limitations: -- It can't access real-time product documentation or knowledge base articles -- It can't look up customer information or ticket history -- It can't perform actions like creating tickets or updating customer records -- It doesn't stay up-to-date with product changes and new features - -By integrating MCP, we'll enhance our chatbot to: -- Access documentation and knowledge base articles as contextual resources -- Look up customer information through a CRM integration -- Create and update support tickets through a ticketing system integration -- Get real-time updates when documentation or product information changes - -Let's get started! - -## Prerequisites - -1. Clone the example MCP servers: -```bash -git clone https://github.com/modelcontextprotocol/example-servers.git -cd example-servers -npm install -``` - -2. Install the MCP SDK in your chatbot project: -```bash -npm install @modelcontextprotocol/sdk -``` - -## Starting Point: Our Basic Chatbot - -Here's our starting chatbot implementation that we'll enhance with MCP: - -```typescript -interface Message { - role: 'user' | 'assistant'; - content: string; -} - -class CustomerServiceBot { - private conversation: Message[] = []; - private llmClient: LLMClient; // Your LLM API client - - constructor(llmClient: LLMClient) { - this.llmClient = llmClient; - } - - async handleMessage(message: string): Promise { - // Add user message to conversation - this.conversation.push({ role: 'user', content: message }); - - // Get LLM response - const response = await this.llmClient.complete({ - messages: this.conversation, - maxTokens: 1000 - }); - - // Add assistant response to conversation - this.conversation.push({ role: 'assistant', content: response }); - - return response; - } -} -``` - -## Step 1: Adding Documentation Context - -First, let's enhance our chatbot to incorporate product documentation. We'll use the example PostgreSQL server which can store and serve our docs. - -```typescript -import { Client } from "@modelcontextprotocol/sdk/client"; -import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio"; -import { - ListResourcesResultSchema, - ReadResourceResultSchema -} from "@modelcontextprotocol/sdk/types"; - -class EnhancedCustomerServiceBot { - private conversation: Message[] = []; - private llmClient: LLMClient; - private mcpClient: Client; - - constructor(llmClient: LLMClient) { - this.llmClient = llmClient; - - // Initialize MCP client - this.mcpClient = new Client({ - name: "customer-service-bot", - version: "1.0.0" - }); - } - - async initialize() { - // Connect to PostgreSQL server for documentation - const transport = new StdioClientTransport({ - command: "./example-servers/postgres/index.js", - args: ["postgres://localhost/docs"] // Your docs database - }); - await this.mcpClient.connect(transport); - } - - async getRelevantDocs(message: string): Promise { - // List available documentation resources - const { resources } = await this.mcpClient.request( - { method: "resources/list" }, - ListResourcesResultSchema - ); - - // Read each documentation resource - const docs = await Promise.all( - resources.map(async (resource) => { - const { contents } = await this.mcpClient.request( - { - method: "resources/read", - params: { uri: resource.uri } - }, - ReadResourceResultSchema - ); - return contents[0].text; - }) - ); - - return docs.join("\n\n"); - } - - async handleMessage(message: string): Promise { - // Get relevant documentation - const docs = await this.getRelevantDocs(message); - - // Build prompt with documentation context - const prompt = ` - Here is relevant documentation about our product: - ${docs} - - Please use this information to help answer the customer's question. - - Customer: ${message} - `; - - // Add user message to conversation - this.conversation.push({ role: 'user', content: message }); - - // Get LLM response with documentation context - const response = await this.llmClient.complete({ - messages: [...this.conversation, { role: 'user', content: prompt }], - maxTokens: 1000 - }); - - // Add assistant response to conversation - this.conversation.push({ role: 'assistant', content: response }); - - return response; - } -} -``` - -## Step 2: Adding Ticket Management - -Now let's add the ability to create and update support tickets. We'll use the example tools server for this: - -```typescript -import { CallToolResultSchema } from "@modelcontextprotocol/sdk/types"; - -interface Ticket { - id: string; - subject: string; - description: string; - status: 'open' | 'closed'; -} - -class EnhancedCustomerServiceBot { - // ... previous code ... - - async createTicket(subject: string, description: string): Promise { - const result = await this.mcpClient.request( - { - method: "tools/call", - params: { - name: "create_ticket", - arguments: { - subject, - description - } - } - }, - CallToolResultSchema - ); - - return result.toolResult as Ticket; - } - - async handleMessage(message: string): Promise { - // Get relevant documentation - const docs = await this.getRelevantDocs(message); - - // Build prompt with documentation context and ticket creation ability - const prompt = ` - Here is relevant documentation about our product: - ${docs} - - You can create support tickets when needed using the createTicket function. - Only create tickets for actual technical issues that need follow-up. - - Customer: ${message} - `; - - // Get LLM response - const response = await this.llmClient.complete({ - messages: [...this.conversation, { role: 'user', content: prompt }], - maxTokens: 1000, - tools: [{ - name: 'createTicket', - description: 'Create a support ticket for technical issues', - parameters: { - subject: 'string', - description: 'string' - } - }] - }); - - // Check if the LLM wants to create a ticket - if (response.toolCalls?.length > 0) { - const call = response.toolCalls[0]; - const ticket = await this.createTicket( - call.arguments.subject, - call.arguments.description - ); - - // Add ticket creation to conversation - this.conversation.push({ - role: 'system', - content: `Created ticket #${ticket.id}: ${ticket.subject}` - }); - } - - // Add messages to conversation - this.conversation.push({ role: 'user', content: message }); - this.conversation.push({ role: 'assistant', content: response.content }); - - return response.content; - } -} -``` - -## Step 3: Real-time Documentation Updates - -Finally, let's make our chatbot aware of documentation changes in real-time: - -```typescript -class EnhancedCustomerServiceBot { - // ... previous code ... - - async initialize() { - // Connect to PostgreSQL server - const transport = new StdioClientTransport({ - command: "./example-servers/postgres/index.js", - args: ["postgres://localhost/docs"] - }); - await this.mcpClient.connect(transport); - - // Subscribe to documentation updates - const { resources } = await this.mcpClient.request( - { method: "resources/list" }, - ListResourcesResultSchema - ); - - for (const resource of resources) { - await this.mcpClient.request( - { - method: "resources/subscribe", - params: { uri: resource.uri } - }, - EmptyResultSchema - ); - } - - // Handle update notifications - this.mcpClient.setNotificationHandler( - ResourceUpdatedNotificationSchema, - async (notification) => { - console.log(`Documentation updated: ${notification.params.uri}`); - // Optionally clear any cached documentation - } - ); - } -} -``` - -## Using the Enhanced Chatbot - -Here's how to use our enhanced chatbot: - -```typescript -const bot = new EnhancedCustomerServiceBot(llmClient); -await bot.initialize(); - -// Example conversation -const response1 = await bot.handleMessage( - "How do I reset my password?" -); -// Bot responds with information from documentation - -const response2 = await bot.handleMessage( - "I can't log in even after resetting my password" -); -// Bot creates a ticket and responds with next steps - -``` - -## Error Handling - -Add robust error handling around MCP operations: - -```typescript -class EnhancedCustomerServiceBot { - // ... previous code ... - - async getRelevantDocs(message: string): Promise { - try { - const { resources } = await this.mcpClient.request( - { method: "resources/list" }, - ListResourcesResultSchema - ); - - const docs = await Promise.all( - resources.map(async (resource) => { - try { - const { contents } = await this.mcpClient.request( - { - method: "resources/read", - params: { uri: resource.uri } - }, - ReadResourceResultSchema - ); - return contents[0].text; - } catch (error) { - console.error(`Failed to read resource ${resource.uri}:`, error); - return ""; // Skip failed resources - } - }) - ); - - return docs.join("\n\n"); - } catch (error) { - console.error("Failed to list resources:", error); - return ""; // Fallback to no documentation - } - } -} -``` - -## Next Steps - -Now that you've enhanced your chatbot with MCP, you can: - -1. Add more integrations: - - Connect to your actual documentation system - - Integrate with your production ticketing system - - Add CRM integration for customer context - -2. Improve the implementation: - - Add better documentation relevance filtering - - Implement more sophisticated prompt engineering - - Add authentication and access control - - Add monitoring and logging - - Implement caching for frequently accessed resources - -3. Consider building custom MCP servers for your specific needs - -The example servers repository includes other servers you can experiment with, and you can build your own servers to expose custom functionality to your chatbot. \ No newline at end of file diff --git a/docs/guides/integrate-python.mdx b/docs/unused/integrate-python.mdx similarity index 99% rename from docs/guides/integrate-python.mdx rename to docs/unused/integrate-python.mdx index e84e9de..1ca1919 100644 --- a/docs/guides/integrate-python.mdx +++ b/docs/unused/integrate-python.mdx @@ -32,8 +32,8 @@ We'll build an "AI Web Analyzer" that: ```bash # Install example MCP servers - git clone https://github.com/modelcontextprotocol/example-servers - cd example-servers + git clone https://github.com/modelcontextprotocol/servers + cd servers npm install npm run build npm install -g diff --git a/docs/guides/integrate-ts.mdx b/docs/unused/integrate-ts.mdx similarity index 99% rename from docs/guides/integrate-ts.mdx rename to docs/unused/integrate-ts.mdx index fdb3a2e..45dc832 100644 --- a/docs/guides/integrate-ts.mdx +++ b/docs/unused/integrate-ts.mdx @@ -40,8 +40,8 @@ We'll build an "AI Web Analyzer" that: ```bash # Install example MCP servers - git clone https://github.com/modelcontextprotocol/example-servers - cd example-servers + git clone https://github.com/modelcontextprotocol/servers + cd servers npm install npm run build npm install -g diff --git a/favicon.svg b/favicon.svg index 6a32332..03d9f85 100644 --- a/favicon.svg +++ b/favicon.svg @@ -1,49 +1,12 @@ - - - - - - - - - - - - - - + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + diff --git a/introduction.mdx b/introduction.mdx index ce585d0..5783886 100644 --- a/introduction.mdx +++ b/introduction.mdx @@ -9,120 +9,79 @@ The Model Context Protocol (MCP) is an open protocol that enables seamless integ Choose the path that best fits your needs: - + The fastest way to see MCP in action - connect example servers to Claude Desktop - - Create a simple MCP server in TypeScript to understand the basics - Create a simple MCP server in Python to understand the basics + + Create a simple MCP server in TypeScript to understand the basics + ## Explore MCP Dive deeper into MCP's core concepts and capabilities: - + Understand how MCP connects clients, servers, and LLMs Expose data and content from your servers to LLMs Create reusable prompt templates and workflows Enable LLMs to perform actions through your server Let your servers request completions from LLMs Learn about MCP's communication mechanisms -## Example Use Cases - -See what you can build with MCP: - - - - Connect your documentation, wikis, and internal knowledge bases to LLMs - - - Query databases and analyze results with natural language - - - Build AI-powered development tools with access to local files and git - - - Securely connect enterprise tools and data to AI interfaces - - - -## Security and Best Practices - -MCP is designed with security in mind, but requires careful implementation: - - - Learn about MCP's security model, best practices, and implementation guidelines - +## Contributing Want to contribute? Check out our [GitHub repository](https://github.com/modelcontextprotocol) or join our growing community of developers building with MCP. \ No newline at end of file diff --git a/mint.json b/mint.json index b583f2d..3f2df25 100644 --- a/mint.json +++ b/mint.json @@ -47,24 +47,21 @@ "navigation": [ { "group": "Get Started", - "pages": ["introduction", "docs/guides/quickstart"] + "pages": ["introduction", "quickstart"] }, { "group": "Your First MCP Server", - "pages": [ - "docs/guides/first-server-python", - "docs/guides/first-server-ts" - ] + "pages": ["docs/first-server/python", "docs/first-server/typescript"] }, { "group": "Concepts", "pages": [ - "docs/core/architecture", - "docs/core/resources", - "docs/core/prompts", - "docs/core/tools", - "docs/core/sampling", - "docs/core/transport" + "docs/concepts/architecture", + "docs/concepts/resources", + "docs/concepts/prompts", + "docs/concepts/tools", + "docs/concepts/sampling", + "docs/concepts/transport" ] }, { @@ -123,8 +120,6 @@ } ], "footerSocials": { - "x": "https://x.com/mintlify", - "github": "https://github.com/mintlify", - "linkedin": "https://linkedin.com/company/mintlify" + "github": "https://github.com/modelcontextprotocol" } } diff --git a/docs/guides/quickstart.mdx b/quickstart.mdx similarity index 94% rename from docs/guides/quickstart.mdx rename to quickstart.mdx index 0cac428..99d2da2 100644 --- a/docs/guides/quickstart.mdx +++ b/quickstart.mdx @@ -98,8 +98,8 @@ brew install node git sqlite3 ```bash # Clone the example servers - git clone https://github.com/modelcontextprotocol/example-servers - cd example-servers + git clone https://github.com/modelcontextprotocol/servers + cd servers # Install dependencies and build npm install @@ -325,17 +325,12 @@ Each client may implement MCP features differently or support different capabili ## Next steps - - - Create your own MCP servers to give Claude Desktop new capabilities. + + + Create your own MCP servers to give your LLM clients new capabilities. - + Browse our collection of example servers to see what's possible. - - - Share your MCP creations and connect with other developers. - [Join us →](/community) - \ No newline at end of file diff --git a/specification/logging.mdx b/specification/logging.mdx index 4d91cfc..62e56b9 100644 --- a/specification/logging.mdx +++ b/specification/logging.mdx @@ -59,6 +59,7 @@ Common use cases for logging include: ### Transient errors +```json { "level": "error", "logger": "git_clone", @@ -73,6 +74,7 @@ Common use cases for logging include: } } } +``` ## Diagram