One read of Model Context Protocol
205 pages moved out of 343 read.
docs/2024-11-05/develop/build-client New page · 2510 lines, new page
# Build an MCP client ## Next steps
A whole new page. There's nothing to diff it against, so here is what it says.
# Build an MCP client
> Get started building your own client that can integrate with all MCP servers.
In this tutorial, you'll learn how to build an LLM-powered chatbot client that connects to MCP servers.
Before you begin, it helps to have gone through our [Build an MCP Server](/docs/2024-11-05/develop/build-server) tutorial so you can understand how clients and servers communicate.
<Tabs>
<Tab title="Python">
[You can find the complete code for this tutorial here.](https://github.com/modelcontextprotocol/quickstart-resources/tree/main/mcp-client-python)
## System Requirements
Before starting, ensure your system meets these requirements:
* Mac or Windows computer
* Latest Python version installed
* Latest version of `uv` installed
## Setting Up Your Environment
First, create a new Python project with `uv`:
<CodeGroup>
```bash macOS/Linux theme={null}
# Create project directory
uv init mcp-client
cd mcp-client
# Create virtual environment
uv venv
# Activate virtual environment
source .venv/bin/activate
# Install required packages
uv add mcp anthropic python-dotenv
# Remove boilerplate files
rm main.py
# Create our main file
touch client.py
```
```powershell Windows theme={null}
# Create project directory
uv init mcp-client
cd mcp-client
# Create virtual environment
uv venv
# Activate virtual environment
.venv\Scripts\activate
# Install required packages
uv add mcp anthropic python-dotenv
# Remove boilerplate files
del main.py
# Create our main file
new-item client.py
```
</CodeGroup>
## Setting Up Your API Key
You'll need an Anthropic API key from the [Anthropic Console](https://console.anthropic.com/settings/keys).
Create a `.env` file to store it:
```bash theme={null}
echo "ANTHROPIC_API_KEY=your-api-key-goes-here" > .env
```
Add `.env` to your `.gitignore`:
```bash theme={null}
echo ".env" >> .gitignore
```
<Warning>
Make sure you keep your `ANTHROPIC_API_KEY` secure!
</Warning>
## Creating the Client
### Basic Client Structure
First, let's set up our imports and create the basic client class:
```python theme={null}
import asyncio
from typing import Optional
from contextlib import AsyncExitStack
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
from anthropic import Anthropic
from dotenv import load_dotenv
load_dotenv() # load environment variables from .env
class MCPClient:
def __init__(self):
# Initialize session and client objects
self.session: Optional[ClientSession] = None
self.exit_stack = AsyncExitStack()
self.anthropic = Anthropic()
# methods will go here
```
### Server Connection Management
Next, we'll implement the method to connect to an MCP server:
```python theme={null}
async def connect_to_server(self, server_script_path: str):
"""Connect to an MCP server
Args:
server_script_path: Path to the server script (.py or .js)
"""
is_python = server_script_path.endswith('.py')
is_js = server_script_path.endswith('.js')
if not (is_python or is_js):
raise ValueError("Server script must be a .py or .js file")
command = "python" if is_python else "node"
server_params = StdioServerParameters(
command=command,
args=[server_script_path],
env=None
)
stdio_transport = await self.exit_stack.enter_async_context(stdio_client(server_params))
self.stdio, self.write = stdio_transport
self.session = await self.exit_stack.enter_async_context(ClientSession(self.stdio, self.write))
await self.session.initialize()
# List available tools
response = await self.session.list_tools()
tools = response.tools
print("\nConnected to server with tools:", [tool.name for tool in tools])
```
### Query Processing Logic
Now let's add the core functionality for processing queries and handling tool calls:
```python theme={null}
async def process_query(self, query: str) -> str:
"""Process a query using Claude and available tools"""
messages = [
{
"role": "user",
"content": query
}
]
response = await self.session.list_tools()
available_tools = [{
"name": tool.name,
"description": tool.description,
"input_schema": tool.inputSchema
} for tool in response.tools]
# Initial Claude API call
response = self.anthropic.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1000,
messages=messages,
tools=available_tools
)
# Process response and handle tool calls
final_text = []
assistant_message_content = []
for content in response.content:
if content.type == 'text':
final_text.append(content.text)
assistant_message_content.append(content)
elif content.type == 'tool_use':
tool_name = content.name
tool_args = content.input
# Execute tool call
result = await self.session.call_tool(tool_name, tool_args)
final_text.append(f"[Calling tool {tool_name} with args {tool_args}]")
assistant_message_content.append(content)
messages.append({
"role": "assistant",
"content": assistant_message_content
})
messages.append({
"role": "user",
"content": [
{
"type": "tool_result",
"tool_use_id": content.id,
"content": result.content
}
]
})
# Get next response from Claude
response = self.anthropic.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1000,
messages=messages,
tools=available_tools
)
final_text.append(response.content[0].text)
return "\n".join(final_text)
```
### Interactive Chat Interface
Now we'll add the chat loop and cleanup functionality:
```python theme={null}
async def chat_loop(self):
"""Run an interactive chat loop"""
print("\nMCP Client Started!")
print("Type your queries or 'quit' to exit.")
while True:
try:
query = input("\nQuery: ").strip()
if query.lower() == 'quit':
break
response = await self.process_query(query)
print("\n" + response)
except Exception as e:
print(f"\nError: {str(e)}")
async def cleanup(self):
"""Clean up resources"""
await self.exit_stack.aclose()
```
### Main Entry Point
Finally, we'll add the main execution logic:
```python theme={null}
async def main():
if len(sys.argv) < 2:
print("Usage: python client.py <path_to_server_script>")
sys.exit(1)
client = MCPClient()
try:
await client.connect_to_server(sys.argv[1])
await client.chat_loop()
finally:
await client.cleanup()
if __name__ == "__main__":
import sys
asyncio.run(main())
```
You can find the complete `client.py` file [here](https://github.com/modelcontextprotocol/quickstart-resources/blob/main/mcp-client-python/client.py).
## Key Components Explained
### 1. Client Initialization
* The `MCPClient` class initializes with session management and API clients
* Uses `AsyncExitStack` for proper resource management
* Configures the Anthropic client for Claude interactions
### 2. Server Connection
* Supports both Python and Node.js servers
* Validates server script type
* Sets up proper communication channels
* Initializes the session and lists available tools
### 3. Query Processing
* Maintains conversation context
* Handles Claude's responses and tool calls
* Manages the message flow between Claude and tools
* Combines results into a coherent response
### 4. Interactive Interface
Cut at 300 lines. The page has the rest.
docs/2024-11-05/develop/build-server New page · 2997 lines, new page
# Build an MCP server ### What we'll be building ### Core MCP Concepts ### Test with commands ## What's happening under the hood ## Troubleshooting ## Next steps
A whole new page. There's nothing to diff it against, so here is what it says.
# Build an MCP server
> Get started building your own server to use in Claude for Desktop and other clients.
In this tutorial, we'll build a simple MCP weather server and connect it to a host, Claude for Desktop.
### What we'll be building
We'll build a server that exposes two tools: `get_alerts` and `get_forecast`. Then we'll connect the server to an MCP host (in this case, Claude for Desktop):
<Frame>
<img src="https://mintcdn.com/mcp/4ZXF1PrDkEaJvXpn/images/current-weather.png?fit=max&auto=format&n=4ZXF1PrDkEaJvXpn&q=85&s=dce7b2f8a06c20ba358e4bd2e75fa4c7" width="2780" height="1849" data-path="images/current-weather.png" />
</Frame>
<Note>
Servers can connect to any client. We've chosen Claude for Desktop here for simplicity, but we also have a guide on [building your own client](/docs/2024-11-05/develop/build-client).
</Note>
### Core MCP Concepts
MCP servers can provide three main types of capabilities:
1. **[Resources](/docs/2024-11-05/learn/server-concepts#resources)**: File-like data that can be read by clients (like API responses or file contents)
2. **[Tools](/docs/2024-11-05/learn/server-concepts#tools)**: Functions that can be called by the LLM (with user approval)
3. **[Prompts](/docs/2024-11-05/learn/server-concepts#prompts)**: Pre-written templates that help users accomplish specific tasks
This tutorial will primarily focus on tools.
<Tabs>
<Tab title="Python">
Let's get started with building our weather server! [You can find the complete code for what we'll be building here.](https://github.com/modelcontextprotocol/quickstart-resources/tree/main/weather-server-python)
### Prerequisite knowledge
This quickstart assumes you have familiarity with:
* Python
* LLMs like Claude
### Logging in MCP Servers
When implementing MCP servers, be careful about how you handle logging:
**For STDIO-based servers:** Never write to stdout. Writing to stdout will corrupt the JSON-RPC messages and break your server. The `print()` function writes to stdout by default, but can be used safely with `file=sys.stderr`.
**For HTTP-based servers:** Standard output logging is fine since it doesn't interfere with HTTP responses.
### Best Practices
* Use a logging library that writes to stderr or files.
### Quick Examples
```python theme={null}
import sys
import logging
# ❌ Bad (STDIO)
print("Processing request")
# ✅ Good (STDIO)
print("Processing request", file=sys.stderr)
# ✅ Good (STDIO)
logging.info("Processing request")
```
### System requirements
* Python 3.10 or higher installed.
* You must use the Python MCP SDK 1.2.0 or higher.
### Set up your environment
First, let's install `uv` and set up our Python project and environment:
<CodeGroup>
```bash macOS/Linux theme={null}
curl -LsSf https://astral.sh/uv/install.sh | sh
```
```powershell Windows theme={null}
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
```
</CodeGroup>
Make sure to restart your terminal afterwards to ensure that the `uv` command gets picked up.
Now, let's create and set up our project:
<CodeGroup>
```bash macOS/Linux theme={null}
# Create a new directory for our project
uv init weather
cd weather
# Create virtual environment and activate it
uv venv
source .venv/bin/activate
# Install dependencies
uv add "mcp[cli]" httpx
# Create our server file
touch weather.py
```
```powershell Windows theme={null}
# Create a new directory for our project
uv init weather
cd weather
# Create virtual environment and activate it
uv venv
.venv\Scripts\activate
# Install dependencies
uv add mcp[cli] httpx
# Create our server file
new-item weather.py
```
</CodeGroup>
Now let's dive into building your server.
## Building your server
### Importing packages and setting up the instance
Add these to the top of your `weather.py`:
```python theme={null}
from typing import Any
import httpx
from mcp.server.fastmcp import FastMCP
# Initialize FastMCP server
mcp = FastMCP("weather")
# Constants
NWS_API_BASE = "https://api.weather.gov"
USER_AGENT = "weather-app/1.0"
```
The FastMCP class uses Python type hints and docstrings to automatically generate tool definitions, making it easy to create and maintain MCP tools.
### Helper functions
Next, let's add our helper functions for querying and formatting the data from the National Weather Service API:
```python theme={null}
async def make_nws_request(url: str) -> dict[str, Any] | None:
"""Make a request to the NWS API with proper error handling."""
headers = {"User-Agent": USER_AGENT, "Accept": "application/geo+json"}
async with httpx.AsyncClient() as client:
try:
response = await client.get(url, headers=headers, timeout=30.0)
response.raise_for_status()
return response.json()
except Exception:
return None
def format_alert(feature: dict) -> str:
"""Format an alert feature into a readable string."""
props = feature["properties"]
return f"""
Event: {props.get("event", "Unknown")}
Area: {props.get("areaDesc", "Unknown")}
Severity: {props.get("severity", "Unknown")}
Description: {props.get("description", "No description available")}
Instructions: {props.get("instruction", "No specific instructions provided")}
"""
```
### Implementing tool execution
The tool execution handler is responsible for actually executing the logic of each tool. Let's add it:
```python theme={null}
@mcp.tool()
async def get_alerts(state: str) -> str:
"""Get weather alerts for a US state.
Args:
state: Two-letter US state code (e.g. CA, NY)
"""
url = f"{NWS_API_BASE}/alerts/active/area/{state}"
data = await make_nws_request(url)
if not data or "features" not in data:
return "Unable to fetch alerts or no alerts found."
if not data["features"]:
return "No active alerts for this state."
alerts = [format_alert(feature) for feature in data["features"]]
return "\n---\n".join(alerts)
@mcp.tool()
async def get_forecast(latitude: float, longitude: float) -> str:
"""Get weather forecast for a location.
Args:
latitude: Latitude of the location
longitude: Longitude of the location
"""
# First get the forecast grid endpoint
points_url = f"{NWS_API_BASE}/points/{latitude},{longitude}"
points_data = await make_nws_request(points_url)
if not points_data:
return "Unable to fetch forecast data for this location."
# Get the forecast URL from the points response
forecast_url = points_data["properties"]["forecast"]
forecast_data = await make_nws_request(forecast_url)
if not forecast_data:
return "Unable to fetch detailed forecast."
# Format the periods into a readable forecast
periods = forecast_data["properties"]["periods"]
forecasts = []
for period in periods[:5]: # Only show next 5 periods
forecast = f"""
{period["name"]}:
Temperature: {period["temperature"]}°{period["temperatureUnit"]}
Wind: {period["windSpeed"]} {period["windDirection"]}
Forecast: {period["detailedForecast"]}
"""
forecasts.append(forecast)
return "\n---\n".join(forecasts)
```
### Running the server
Finally, let's initialize and run the server:
```python theme={null}
def main():
# Initialize and run the server
mcp.run(transport="stdio")
if __name__ == "__main__":
main()
```
Your server is complete! Run `uv run weather.py` to start the MCP server, which will listen for messages from MCP hosts.
Let's now test your server from an existing MCP host, Claude for Desktop.
## Testing your server with Claude for Desktop
<Note>
Claude for Desktop is not yet available on Linux. Linux users can proceed to the [Building a client](/docs/2024-11-05/develop/build-client) tutorial to build an MCP client that connects to the server we just built.
</Note>
First, make sure you have Claude for Desktop installed. [You can install the latest version
here.](https://claude.ai/download) If you already have Claude for Desktop, **make sure it's updated to the latest version.**
We'll need to configure Claude for Desktop for whichever MCP servers you want to use. To do this, open your Claude for Desktop App configuration at `~/Library/Application Support/Claude/claude_desktop_config.json` in a text editor. Make sure to create the file if it doesn't exist.
For example, if you have [VS Code](https://code.visualstudio.com/) installed:
<CodeGroup>
```bash macOS/Linux theme={null}
code ~/Library/Application\ Support/Claude/claude_desktop_config.json
```
```powershell Windows theme={null}
code $env:AppData\Claude\claude_desktop_config.json
```
</CodeGroup>
You'll then add your servers in the `mcpServers` key. The MCP UI elements will only show up in Claude for Desktop if at least one server is properly configured.
In this case, we'll add our single weather server like so:
<CodeGroup>
```json macOS/Linux theme={null}
{
"mcpServers": {
"weather": {
"command": "uv",
"args": [
"--directory",
"/ABSOLUTE/PATH/TO/PARENT/FOLDER/weather",
"run",
"weather.py"
]
}
}
}
```
Cut at 300 lines. The page has the rest.
community/working-groups/triggers-events Changed · +1 / -1 lines
### Related Groups -* **Transports WG** — delivery and ordering guarantees depend on transport capabilities; callback semantics must be coherent across stdio, Streamable HTTP, and future transports. +* **[Transports WG](/community/working-groups/transports)** — delivery and ordering guarantees depend on transport capabilities; callback semantics must be coherent across stdio, Streamable HTTP, and future transports. * **Agents WG** — [SEP-1686 (Tasks)](https://github.com/modelcontextprotocol/modelcontextprotocol/issues/1686) identifies webhook-style task completion notifications as a future consideration; this WG owns that mechanism. ## Leadership
community/working-groups/transports New page · 150 lines, new page
# Transports Charter ## Group Type ## Mission Statement ## Scope ### In Scope ### Out of Scope ### Related Groups ## Leadership ## Authority & Decision Rights ## Membership ## Operations ## Resources ## Deliverables & Success Metrics ### Active Work Items ### Success Criteria ## Changelog
A whole new page. There's nothing to diff it against, so here is what it says.
# Transports Charter > Charter for the MCP Transports Working Group. ## Group Type **Working Group** ## Mission Statement The Transports Working Group evolves MCP transport bindings and transport-adjacent protocol architecture so implementations remain interoperable, scalable, reliable, and easy to operate across local and remote deployments. The WG produces transport proposals, SEPs, implementation evidence, and guidance. The [working group repository](https://github.com/modelcontextprotocol/transports-wg) and its [upstream charter](https://github.com/modelcontextprotocol/transports-wg/blob/main/CHARTER.md) maintain the WG's current technical focus, proposal strategy, and supporting detail within these boundaries. ## Scope ### In Scope * **Transport Bindings**: Framing, delivery, request and envelope metadata, cancellation and termination, connection lifecycle, backward compatibility, and the behavior of existing and future MCP transports. The current specification's [transport overview](/specification/draft/basic/transports) defines the boundary between a transport binding and core protocol semantics. * **Scalability and Reliability**: Transport-level connection management, resource efficiency, multiplexing, load distribution, error handling, reconnection, resumption, and the delivery and ordering guarantees offered by a binding. * **Transport-Adjacent Protocol Architecture**: Protocol-wide message-flow concerns required for scalable, interoperable bindings, including request association, per-request metadata, stateless operation, and migration from legacy initialization and transport-session models. * **Transport Security**: Binding and envelope security requirements such as Origin validation, TLS, mTLS, and certificate handling, coordinated with the Security IG. Credential carriage is coordinated with the Auth IG. * **Validation and Guidance**: Reference implementations, experiments, implementation evidence, and documentation needed to evaluate proposals and help implementers adopt agreed transport behavior. Supporting material is maintained in the upstream [documentation](https://github.com/modelcontextprotocol/transports-wg/tree/main/docs). The WG contributes transport scenarios and requirements to the Conformance Testing project, whose maintainers own the conformance suite. * **Cross-Cutting Coordination**: Transport implications of work owned by other MCP groups, without taking ownership of their application-layer features. The upstream [scope statement](https://github.com/modelcontextprotocol/transports-wg/blob/main/CHARTER.md#scope) provides supporting context but cannot expand the boundaries in this charter. ### Out of Scope * Application-layer behavior for MCP primitives such as tools, resources, prompts, tasks, agents, or events, including application state, application-session meaning, task lifecycle, and event or subscription semantics. The WG coordinates where those features depend on binding or message-flow behavior. * Domain-specific extensions and implementation-specific product or business concerns. * SDK APIs and implementation details unrelated to transports. * Authorization protocol mechanics, credential and token semantics, application identity, and authorization policy. The WG coordinates with the relevant groups on how bindings carry agreed authorization data. * Ownership of the MCP conformance suite. The WG contributes transport requirements and scenarios in coordination with its maintainers. ### Related Groups * **[SDK WG](/community/working-groups/sdk)**: Official SDKs implement transport changes; the groups coordinate on feasibility, reference implementations, and rollout sequencing. * **[Agents WG](/community/working-groups/agents)**: The Agents WG owns Tasks and durable execution; the groups coordinate where these depend on multi-round-trip requests, request association, stateless operation, or binding behavior. * **[Triggers and Events WG](/community/working-groups/triggers-events)**: Event callbacks, subscriptions, and application-level delivery semantics are owned by that group; Transports owns binding-specific carriage and guarantees. * **[Auth IG](/community/interest-groups/auth)** and **[Security IG](/community/interest-groups/security)**: The groups coordinate on credential carriage and transport wire security while authorization mechanics and broader security requirements remain with the respective IGs. ## Leadership The current WG Lead is [Kurtis Van Gent](https://github.com/kurtisvg). ## Authority & Decision Rights | Decision Type | Authority Level | | ----------------------------------- | ------------------------------------------------------ | | Meeting logistics & scheduling | WG Leads (autonomous) | | Proposal prioritization within WG | WG Leads (autonomous) | | SEP triage & closure (in scope) | WG Leads (autonomous, with documented rationale) | | Technical design within scope | WG consensus | | Spec changes (additive) | WG consensus → Core Maintainer approval | | Spec changes (breaking/fundamental) | WG consensus → Core Maintainer approval + wider review | | Scope expansion | Core Maintainer approval required | | WG Member approval | WG Member sponsors | ## Membership Current WG Members are listed in the upstream [group membership roster](https://github.com/modelcontextprotocol/transports-wg/blob/main/GOVERNANCE.md#members). ## Operations The WG holds a regular weekly meeting, with the current time and joining details listed at [meet.modelcontextprotocol.io](https://meet.modelcontextprotocol.io). Topics are discussed asynchronously in `#transports-wg` on the [MCP Discord](https://discord.gg/6CSzBmMkjX). Work follows a problem-first workflow: 1. Create a core problem statement in the [working group repository](https://github.com/modelcontextprotocol/transports-wg) to align the WG on the problem and its requirements. 2. Work with other interested participants to define a solution. 3. Review and iterate on the solution to address WG feedback. 4. After the WG reaches consensus under its decision-making process, present the solution to Core Maintainers as an SEP through the [SEP process](/community/sep-guidelines). ## Resources * [modelcontextprotocol/transports-wg](https://github.com/modelcontextprotocol/transports-wg) * [Proposals](https://github.com/modelcontextprotocol/transports-wg/tree/main/proposals) * [Supporting documentation and decision records](https://github.com/modelcontextprotocol/transports-wg/tree/main/docs) * [Meeting notes](https://github.com/modelcontextprotocol/transports-wg/tree/main/meetings) ## Deliverables & Success Metrics ### Active Work Items See [open pull requests](https://github.com/modelcontextprotocol/transports-wg/pulls) and the [`roadmaps/` directory](https://github.com/modelcontextprotocol/transports-wg/tree/main/roadmaps). ### Success Criteria * Adopted transport-agnostic protocol behavior remains consistent across transports, while binding-specific differences are explicit and validated by implementation evidence and applicable conformance scenarios. * Transport changes that affect official SDKs are coordinated with the SDK WG and have clear implementation guidance. * Decisions, proposal status, and supporting rationale remain publicly discoverable in or linked from the working group repository. ## Changelog | Date | Change | | ---------- | --------------- | | 2026-08-23 | Initial charter |
community/working-groups/sdk Changed · +1 / -1 lines
### Related Groups -* **Transports WG**: Transport implementations are a substantial part of every SDK. The SDK WG coordinates with the Transports WG on rollout sequencing when transport SEPs land. +* **[Transports WG](/community/working-groups/transports)**: Transport implementations are a substantial part of every SDK. The SDK WG coordinates with the Transports WG on rollout sequencing when transport SEPs land. * **Conformance Testing**: Tier assignments depend on conformance scores. The SDK WG consumes conformance results and feeds back gaps in test coverage. * **All specification-producing WGs**: The SDK WG is a downstream consumer of accepted SEPs and coordinates reference-implementation timing with the originating group.
community/working-groups/interceptors Changed · +1 / -1 lines
### Related Groups -* **Transports WG** — interceptors operate on MCP message flows whose delivery behavior depends on the transport; coordination needed on transport-level interception points. +* **[Transports WG](/community/working-groups/transports)** — interceptors operate on MCP message flows whose delivery behavior depends on the transport; coordination needed on transport-level interception points. * **Gateways IG** — gateways are a key deployment model for interceptors; coordination needed on gateway-based interceptor patterns and shared concerns around routing, policy, and observability. ## Leadership
community/working-groups/agents Changed · +1 / -1 lines
### Related Groups -* **[Transports WG](https://github.com/modelcontextprotocol/transports-wg)** - +* **[Transports WG](/community/working-groups/transports)** - Task polling, multi-round-trip requests, stateless operation, and request association depend on transport and message-flow semantics. * **[Triggers and Events WG](/community/working-groups/triggers-events)** -
docs/2024-11-05/develop/build-with-agent-skills New page · 98 lines, new page
# Build with Agent Skills ## Available skills ## Start a build ## Deployment paths ## Next steps
A whole new page. There's nothing to diff it against, so here is what it says.
# Build with Agent Skills
> Use agent skills to guide AI coding assistants through MCP server design and implementation
[Agent skills](https://agentskills.io/home) are portable instruction sets that
give AI coding assistants domain knowledge for a task. For MCP development,
they encode the design decisions (deployment model, tool patterns, auth) so
your agent can interrogate your use case and scaffold a server that fits.
## Available skills
A reference set of MCP development skills is available as the
[`mcp-server-dev` plugin](https://github.com/anthropics/claude-plugins-official/tree/main/plugins/mcp-server-dev).
It provides three composing skills:
| Skill | Purpose |
| ------------------ | ----------------------------------------------------------------------------------------------------------------------- |
| `build-mcp-server` | Entry point. Interrogates the use case, picks a deployment model and tool-design pattern, routes to specialized skills. |
| `build-mcp-app` | Adds interactive UI widgets (forms, pickers, dashboards) rendered inline in chat. |
| `build-mcpb` | Packages a local stdio server with its runtime so users can install it without Node or Python. |
Each skill ships a `SKILL.md` file plus a `references/` folder of supporting
material (auth flows, tool-design patterns, widget templates, manifest schemas)
that the agent reads on demand. The files follow the open format and work with
any agent that implements the standard. For example, to install them in Claude
Code:
```bash theme={null}
/plugin marketplace add anthropics/claude-plugins-official
/plugin install mcp-server-dev
```
For other agents, check your skills or extensions catalog, or clone the
[skill directories](https://github.com/anthropics/claude-plugins-official/tree/main/plugins/mcp-server-dev/skills)
(`SKILL.md` plus `references/`) into your agent's skills location.
## Start a build
With the skills installed, ask your agent to help you build an MCP server. The
entry skill triggers on natural-language requests, or you can invoke it
directly using your agent's skill-invocation syntax.
The skill runs a short discovery phase before writing any code. Expect
questions about:
* **What it connects to** — a cloud API, a local process, the filesystem, hardware
* **Who will use it** — just you, your team, or anyone who installs it
* **Action surface size** — a handful of operations versus wrapping a large API
* **User interaction needs** — plain text results or rich UI widgets
* **Upstream auth** — API keys, OAuth 2.0, or none
If your opening message already covers these, the agent skips ahead to the
recommendation.
## Deployment paths
Based on discovery, the skill recommends one of four paths and scaffolds
accordingly:
**Remote [HTTP with SSE](/specification/2024-11-05/basic/transports#http-with-sse)**
is the default for anything wrapping a cloud API. Zero install friction, one
deployment serves all users, and OAuth flows work properly because the server
can handle redirects and token storage. The reference skill includes scaffolds
for Cloudflare Workers and portable Express/FastMCP setups.
**[MCP apps](/extensions/apps/overview)** extend a server with interactive
widgets rendered in chat, such as searchable pickers, charts, and live
dashboards. The skill hands off to `build-mcp-app` when plain text output
doesn't fit.
**[MCP Bundles (MCPB)](https://github.com/modelcontextprotocol/mcpb)** package a
local server together with its runtime as a single `.mcpb` archive, so users
can install it without setting up Node or Python. Use this path when the server
must touch the user's machine: reading local files, driving desktop apps, or
talking to localhost services. The skill hands off to `build-mcpb`.
**Local [stdio](/specification/2024-11-05/basic/transports#stdio)** remains available
for prototyping, with a noted upgrade path to MCPB when you're ready to
distribute.
## Next steps
Once your agent scaffolds the server, iterate on tool descriptions and error
handling, then test and ship:
<CardGroup cols={2}>
<Card title="MCP Inspector" icon="magnifying-glass" href="/docs/2024-11-05/tools/inspector">
Test your server's tools, resources, and prompts interactively
</Card>
<Card title="Connect to a client" icon="plug" href="/docs/2024-11-05/develop/connect-local-servers">
Wire your server into an MCP client via local or remote configuration
</Card>
<Card title="Publish to the Registry" icon="box" href="/registry/quickstart">
Make your server discoverable in the MCP Registry
</Card>
</CardGroup>
docs/2024-11-05/develop/clients/client-best-practices New page · 292 lines, new page
# Client Best Practices ## Progressive Tool Discovery ### When to Use Progressive Discovery ### Choosing a Discovery Strategy ### Using Progressive Discovery ### Dynamic Server Management ### Implementation Guidelines ### Interaction with Prompt Caching ## Programmatic Tool Calling / Code Mode ### How It Works ### Choosing a Sandbox ### Execution Architecture ### Security Considerations ### Error Handling ## Combining Both Patterns
A whole new page. There's nothing to diff it against, so here is what it says.
# Client Best Practices
> Patterns for scaling MCP host applications across many servers and tools.
As MCP host applications, such as agents, connect to more MCP servers and accumulate access to hundreds or thousands of tools, naive approaches to tool management break down. Loading every tool definition into the model's context window upfront wastes tokens, increases latency, and degrades model performance. Passing large intermediate results through the model between sequential tool calls compounds the problem.
Two patterns address these challenges: **progressive discovery**, which controls *when* tool definitions enter context, and **programmatic tool calling**, which controls *how* tools are invoked.
## Progressive Tool Discovery
Naive MCP host implementations pass the tool definitions of every connected server directly to the model at the start of each conversation. For a handful of tools, this is perfectly reasonable. But when a host has access to dozens of servers exposing hundreds of tools, those definitions alone can consume the majority of the context window before the model has even read the user's message.
<img src="https://mintcdn.com/mcp/JXfd5cBmEUh_qPUI/images/progressive-discovery.svg?fit=max&auto=format&n=JXfd5cBmEUh_qPUI&q=85&s=db39f47006107f04af43b5eeae2d6022" alt="Comparison of loading all tools upfront versus discovering tools on demand. The upfront approach consumes ~150,000 tokens on definitions alone, while progressive discovery uses ~2,000 tokens by loading only what the task requires." width="760" height="440" data-path="images/progressive-discovery.svg" />
Progressive discovery avoids this:
* The host fetches tool definitions via `tools/list` as normal, but defers injecting them into the model's context.
* The host provides a lightweight `search_tools` meta-tool to the model.
* The host loads full definitions into context only as needed.
### When to Use Progressive Discovery
Progressive discovery is best used when tool definitions take large parts of the context window. For a small
set of tools with tool definitions taking up a small part of the context window, loading all tools is fine.
Once the tool definitions take up a significant part of the available context window, clients should switch to progressive discovery. We recommend that clients implement thresholds to determine when to switch:
* Implement a threshold as a percentage of the context window. For example, 1%-5%.
* Load tool definitions. Once the threshold is reached, switch to progressive discovery.
### Choosing a Discovery Strategy
Once the model invokes the `search_tools` tool, we need to choose a search strategy:
* **Keyword-based**: Keyword matching (BM25, regex). Simple and effective, particularly for descriptive tool names and descriptions.
* **Embedding-based**: Vector-similarity retrieval over tool descriptions. Handles synonyms and semantic matching better.
* **Subagent-based**: A secondary model, often a small and fast model such as Claude Haiku or Gemini Flash, selects tools for the task. This usually works very well but can be more costly than embedding-based or keyword-based solutions.
* **Hybrid**: Combine approaches. For example, by scoring across keyword and embedding rankings, or choosing
different strategies depending on use-case or query.
Some model providers already offer built-in tool search. For example, [OpenAI](https://developers.openai.com/api/docs/guides/tools-tool-search) and [Anthropic](https://platform.claude.com/docs/en/agents-and-tools/tool-use/tool-search-tool) support this natively; check your provider's documentation for an equivalent. When available, you may prefer the platform's tool search over a custom implementation. Build your own when the provider doesn't offer one or when you need specialized retrieval logic (e.g., domain-specific ranking or access-control filtering).
The three-layer pattern below illustrates a custom search-based approach in detail, but the layered principle (catalog, inspect, execute) applies regardless of retrieval mechanism.
### Using Progressive Discovery
One common implementation for progressive discovery uses a search-based three-layer approach:
**Layer 1: Catalog.** The host exposes a small set of meta-tools for searching available capabilities. A `search_tools` tool accepts a natural-language query and returns matching tool names with brief descriptions.
```typescript theme={null}
// The model calls a lightweight search tool
search_tools({ query: "update salesforce record" })
// Returns concise matches: names and one-line descriptions only
→ [
{ name: "salesforce_updateRecord", description: "Update fields on a Salesforce object" },
{ name: "salesforce_upsertRecord", description: "Insert or update based on external ID" }
]
```
**Layer 2: Inspect.** Once the model identifies a candidate, it fetches the full definition (input schema, documentation) for that tool only.
```typescript theme={null}
// The model inspects only the tool it needs
get_tool_details({ name: "salesforce_updateRecord" });
```
This returns the complete schema for a single tool:
```json theme={null}
{
"name": "salesforce_updateRecord",
"description": "Updates a record in Salesforce",
"inputSchema": {
"type": "object",
"properties": {
"objectType": {
"type": "string",
"description": "Salesforce object type"
},
"recordId": { "type": "string", "description": "Record ID to update" },
"data": { "type": "object", "description": "Fields to update" }
},
"required": ["objectType", "recordId", "data"]
}
}
```
**Layer 3: Execute.** The model calls the tool with full knowledge of its interface, having loaded only the definitions it needed.
This pattern reduces token usage dramatically and can improve tool selection accuracy: the model focuses on a few relevant tools rather than scanning hundreds of irrelevant ones. Other discovery strategies (embeddings, subagents, etc.) follow the same layered principle but substitute different retrieval mechanisms in the catalog layer.
### Dynamic Server Management
Progressive discovery extends beyond individual tools to entire servers. Rather than connecting to every configured server at startup, a host can:
1. Maintain a registry of available servers and their high-level descriptions.
2. Connect to a server only when the model determines it needs that server's capabilities.
3. Disconnect servers that are no longer relevant to the current task, freeing context.
```mermaid theme={null}
sequenceDiagram
participant Model
participant Host
participant Registry
participant Server
Model->>Host: search_available_servers("CRM")
Host->>Registry: Query available servers
Registry-->>Host: Salesforce server (not connected)
Host-->>Model: Salesforce server available
Model->>Host: enable_server("salesforce")
Host->>Server: Initialize connection
Server-->>Host: Server capabilities + tools
Host-->>Model: Salesforce server connected
Note over Model: Task complete
Model->>Host: disable_server("salesforce")
Host->>Server: Close connection
Host-->>Model: Server disconnected, context freed
```
This works especially well for general-purpose agents, where the user's intent isn't known upfront. The agent starts with a minimal set of always-on servers and connects others as needed. Combined with [agent skills](/docs/2024-11-05/develop/build-with-agent-skills), a skill file can declare which MCP servers it needs, and the host connects them only when that skill is invoked.
### Implementation Guidelines
When implementing progressive discovery:
| Guideline | Rationale |
| -------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Offer multiple detail levels** | Let the model choose between name-only, name-and-description, or full-schema responses. |
| **Cache tool definitions** | Once fetched from a server, memoize the definition host-side so re-injecting it later doesn't need another `tools/list` round trip. This is separate from what's currently in the model's context. |
| **Refresh on `list_changed`** | Re-index the search catalog when a server sends `notifications/tools/list_changed`. |
| **Group tools by server** | Present tools organized by their source server so the model can reason about related capabilities. |
### Interaction with Prompt Caching
Most providers cache the prompt prefix, including the `tools` array. Adding or removing tool
definitions mid-conversation invalidates that cache, and the resulting miss can cost more tokens
than the definitions you removed. To preserve caching:
* Append newly discovered definitions after the cache breakpoint rather than re-sorting the
`tools` array, or route every call through a single stable `call_tool({name, args})` meta-tool
so the array never changes.
* Treat server disconnection as a conversation-boundary operation rather than a per-turn one.
* Consult your provider's caching documentation alongside the tool-search links above.
## Programmatic Tool Calling / Code Mode
With direct tool calling, every tool invocation is a round trip: the model generates a tool call, the client executes it, and the full result flows back into the model's context. When a task requires chaining multiple tools (read a document, transform it, write it somewhere else), each intermediate result passes through the model, consuming tokens and adding latency even when it has nothing to do with them.
Programmatic tool calling (sometimes called "code mode") provides a way for clients to **compose tool calls** effectively. Instead of calling tools directly, the model writes code that calls tools. The code executes in a sandboxed environment, and only the final result returns to the model.
Programmatic tool calling is powerful and allows for more efficient use of MCP tools and resources, but requires
clients to implement a sandbox environment.
<img src="https://mintcdn.com/mcp/JXfd5cBmEUh_qPUI/images/programmatic-tool-calling.svg?fit=max&auto=format&n=JXfd5cBmEUh_qPUI&q=85&s=a2be82d097bb7cd7c7fd415918b1571d" alt="Comparison of direct tool calling versus programmatic tool calling. Direct calling passes every intermediate result through the model (~100K+ tokens). Programmatic calling sends a ~200-token script to a sandbox, which executes the tool calls and returns a ~15-token summary." width="900" height="900" data-path="images/programmatic-tool-calling.svg" />
### How It Works
The host converts MCP tool schemas into a typed API available inside a sandbox. When the model needs tools, it writes a script and executes it.
**Step 1: Generate a programmatic API from MCP schemas.** The host reads each server's tool definitions and produces typed functions based on each tool's arguments:
```typescript theme={null}
// Auto-generated from the Logging MCP server's tool schema
interface LogEntry {
timestamp: string;
message: string;
level: string;
}
function logging_getLogs(input: {
level: "error" | "warn" | "info";
since: number;
}): Promise<{ entries: LogEntry[] }> {
return mcp.callTool<{ entries: LogEntry[] }>("logging_getLogs", input);
}
// Auto-generated from the Ticketing MCP server's tool schema
function ticketing_createIssue(input: {
title: string;
body?: string;
priority: "low" | "medium" | "high";
}): Promise<{ issueId: string }> {
return mcp.callTool<{ issueId: string }>("ticketing_createIssue", input);
}
```
Tool definitions in this protocol version describe tool inputs only. Precise return types (like `LogEntry` above) have to come from server documentation or manual configuration.
When precise return types are unavailable, prefer the simple path:
* **Use a generic type and move on.** Accept `any` or `string` and handle the unstructured output downstream.
* **Extract a typed result using a fast model**, for single-shot calls outside loops. Expose a host-brokered `extract(value, ExpectedType)` helper through the same stub-interception path as MCP tool calls so the sandbox itself never opens a network connection. The helper routes to a small model (for example, Claude Haiku or Gemini Flash) to coerce the value into `ExpectedType`. This adds per-call latency and can hallucinate or drop fields, so validate the result against `ExpectedType` before use.
**Step 2: The model writes code against these APIs.** Rather than making separate tool calls with full results flowing through context between them, the model writes a single script. Consider a task like "find all error logs from the past hour and file a ticket for each unique error." With direct tool calling, thousands of log entries would flow through the model's context. With code, the model filters in the sandbox:
```typescript theme={null}
// Model-generated code, executes in sandbox
const logs = await logging_getLogs({
level: "error",
since: Date.now() - 3600000,
});
// Filter and deduplicate inside the sandbox, not in the model's context
const uniqueErrors = new Map<string, LogEntry>();
for (const log of logs.entries) {
if (!uniqueErrors.has(log.message)) {
uniqueErrors.set(log.message, log);
}
}
for (const [message, log] of uniqueErrors) {
await ticketing_createIssue({
title: `Error: ${message}`,
body: `First seen: ${log.timestamp}\nOccurrences: ${
logs.entries.filter((l) => l.message === message).length
}`,
priority: "high",
});
}
console.log(
`Filed ${uniqueErrors.size} tickets from ${logs.entries.length} error logs`,
);
```
**Step 3: The sandbox executes the code.** Function calls inside the sandbox are intercepted and routed back to the appropriate MCP server through the host broker. The log data and ticket creation flow directly between servers without ever entering the model's context. Only the `console.log` output, a single summary line, returns to the model.
### Choosing a Sandbox
The right sandbox depends on the language you want the model to write, your host application's language, and how much isolation you need. The table lists example runtimes rather than endorsements; evaluate maturity for your use case:
| Sandboxed language | Runtime / Library | Host language | Approach |
| ------------------ | ------------------------------------------------------------- | ----------------- | ----------------------------------------------------------------------------------------------- |
| **JavaScript** | [Deno](https://github.com/denoland/deno), `isolated-vm` | Rust / Node / CLI | V8-based runtimes with fine-grained permissions. Can disable all permissions for full lockdown. |
| **Python** | [Monty](https://github.com/pydantic/monty) *(experimental)* | Rust | Minimal Python interpreter built for AI use cases. No I/O by default. |
| **TypeScript** | [pctx](https://github.com/portofcontext/pctx) *(early-stage)* | Python / Rust | Incorporates code mode concepts as a library, with low-level Rust support. |
| **Any (via Wasm)** | [Wasmtime](https://github.com/bytecodealliance/wasmtime) | Rust / C / Go | Compile any language to Wasm and run it with capability-based security. |
Regardless of sandbox, the integration pattern is the same: the host injects function stubs, intercepts calls over an in-process or stdio channel (so network permissions can stay fully denied), and dispatches them as `tools/call` requests to MCP servers.
### Execution Architecture
The implementation has three components:
```mermaid theme={null}
flowchart LR
subgraph Host["MCP Host"]
A[LLM] -->|writes code| B[Sandbox]
B -->|function call| C[MCP Client]
C -->|return value| B
B -->|console output| A
end
C -->|tool call| D[MCP Server A]
C -->|tool call| E[MCP Server B]
D -->|result| C
E -->|result| C
```
**The sandbox** runs model-generated code in an isolated environment with no direct network access. Its only interface to the outside world is through the generated function stubs, which route calls back to the host.
**The host** acts as a broker. It receives function calls from the sandbox, maps them to the correct MCP server, executes the tool call, and returns the result to the sandbox. Authorization tokens and credentials are held by the host and never exposed to the generated code.
**The model** sees only what the sandbox returns, typically the output of `console.log` statements or a final return value. This gives the model (and the client developer) precise control over what enters the context window.
### Security Considerations
Programmatic tool calling introduces a code execution surface that requires careful sandboxing:
* **Per-call authorization**: The broker is still the MCP host for spec purposes. Apply the same human-in-the-loop confirmation policy to sandbox-originated calls that you apply to direct calls (see [Tools: Security](/specification/2024-11-05/server/tools#security-considerations)). Approving the script does not grant blanket approval for every tool call it makes at runtime; hosts may grant categorical approval (for example, "allow `ticketing_createIssue` for this script run") rather than prompting per iteration, but the broker must still evaluate each call against that grant.
* **Cross-server data flow**: Tool results from one server are untrusted input to another. The broker should apply the same input-review policy to brokered calls as to direct ones; output truncation alone does not prevent exfiltration.
* **Network isolation**: The sandbox should have no direct network access. All external communication flows through the host broker, which enforces authorization and access control.
* **No credential exposure**: API keys and tokens are held by the host. The generated code calls typed functions; the host adds authentication when forwarding to servers.
* **Resource limits**: Set timeouts and memory limits on sandbox execution to prevent runaway scripts.
* **Output filtering**: Validate and truncate sandbox console output before feeding it back to the model.
### Error Handling
MCP tool errors arrive as a successful response with
[`isError: true`](/specification/2024-11-05/server/tools#error-handling) rather than a transport
failure. Generated wrappers should convert this into a thrown exception so model-authored code
can use `try`/`catch`. If an uncaught error terminates the script, surface it as the script's
result so the model can self-correct; the model is responsible for reporting any partial side
effects already committed.
## Combining Both Patterns
Progressive discovery and programmatic tool calling work well together. The model uses discovery tools to identify which tools it needs, loads their schemas, and then writes a single script that calls multiple tools in one execution pass. This combination minimizes both the token cost of tool definitions *and* the token cost of tool results, keeping the model's context focused on reasoning rather than passing data through it.
docs/2024-11-05/develop/connect-local-servers New page · 283 lines, new page
# Connect to local MCP servers ## Prerequisites ### Claude Desktop ### Node.js ## Understanding MCP Servers ## Installing the Filesystem Server ## Using the Filesystem Server ### File Management Examples ### How Approval Works ## Troubleshooting ## Next Steps
A whole new page. There's nothing to diff it against, so here is what it says.
# Connect to local MCP servers
> Learn how to extend Claude Desktop with local MCP servers to enable file system access and other powerful integrations
Model Context Protocol (MCP) servers extend AI applications' capabilities by providing secure, controlled access to local resources and tools. Many clients support MCP, enabling diverse integration possibilities across different platforms and applications.
This guide demonstrates how to connect to local MCP servers using Claude Desktop as an example, one of the many clients that support MCP. While we focus on Claude Desktop's implementation, the concepts apply broadly to other MCP-compatible clients. By the end of this tutorial, Claude will be able to interact with files on your computer, create new documents, organize folders, and search through your file system—all with your explicit permission for each action.
<Frame>
<img src="https://mintcdn.com/mcp/4ZXF1PrDkEaJvXpn/images/quickstart-filesystem.png?fit=max&auto=format&n=4ZXF1PrDkEaJvXpn&q=85&s=629d7e754dc358d71a408d6ce970c1b1" alt="Claude Desktop with filesystem integration showing file management capabilities" width="1732" height="2060" data-path="images/quickstart-filesystem.png" />
</Frame>
## Prerequisites
Before starting this tutorial, ensure you have the following installed on your system:
### Claude Desktop
Download and install [Claude Desktop](https://claude.ai/download) for your operating system. Claude Desktop is available for macOS and Windows.
If you already have Claude Desktop installed, verify you're running the latest version by clicking the Claude menu and selecting "Check for Updates..."
### Node.js
The Filesystem Server and many other MCP servers require Node.js to run. Verify your Node.js installation by opening a terminal or command prompt and running:
```bash theme={null}
node --version
```
If Node.js is not installed, download it from [nodejs.org](https://nodejs.org/). We recommend the LTS (Long Term Support) version for stability.
## Understanding MCP Servers
MCP servers are programs that run on your computer and provide specific capabilities to Claude Desktop through a standardized protocol. Each server exposes tools that Claude can use to perform actions, with your approval. The Filesystem Server we'll install provides tools for:
* Reading file contents and directory structures
* Creating new files and directories
* Moving and renaming files
* Searching for files by name or content
All actions require your explicit approval before execution, ensuring you maintain full control over what Claude can access and modify.
## Installing the Filesystem Server
The process involves configuring Claude Desktop to automatically start the Filesystem Server whenever you launch the application. This configuration is done through a JSON file that tells Claude Desktop which servers to run and how to connect to them.
<Steps>
<Step title="Open Claude Desktop Settings">
Start by accessing the Claude Desktop settings. Click on the Claude menu in your system's menu bar (not the settings within the Claude window itself) and select "Settings..."
On macOS, this appears in the top menu bar:
<Frame style={{ textAlign: "center" }}>
<img src="https://mintcdn.com/mcp/4ZXF1PrDkEaJvXpn/images/quickstart-menu.png?fit=max&auto=format&n=4ZXF1PrDkEaJvXpn&q=85&s=0c8b57e0e17af3624b6762a3ea944c8e" width="400" alt="Claude Desktop menu showing Settings option" data-path="images/quickstart-menu.png" />
</Frame>
This opens the Claude Desktop configuration window, which is separate from your Claude account settings.
</Step>
<Step title="Access Developer Settings">
In the Settings window, navigate to the "Developer" tab in the left sidebar. This section contains options for configuring MCP servers and other developer features.
Click the "Edit Config" button to open the configuration file:
<Frame>
<img src="https://mintcdn.com/mcp/4ZXF1PrDkEaJvXpn/images/quickstart-developer.png?fit=max&auto=format&n=4ZXF1PrDkEaJvXpn&q=85&s=0fb595490a2f9e15c0301e771a57446c" alt="Developer settings showing Edit Config button" width="1688" height="534" data-path="images/quickstart-developer.png" />
</Frame>
This action creates a new configuration file if one doesn't exist, or opens your existing configuration. The file is located at:
* **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
* **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
</Step>
<Step title="Configure the Filesystem Server">
Replace the contents of the configuration file with the following JSON structure. This configuration tells Claude Desktop to start the Filesystem Server with access to specific directories:
<CodeGroup>
```json macOS theme={null}
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"/Users/username/Desktop",
"/Users/username/Downloads"
]
}
}
}
```
```json Windows theme={null}
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"C:\\Users\\username\\Desktop",
"C:\\Users\\username\\Downloads"
]
}
}
}
```
</CodeGroup>
Replace `username` with your actual computer username. The paths listed in the `args` array specify which directories the Filesystem Server can access. You can modify these paths or add additional directories as needed.
<Tip>
**Understanding the Configuration**
* `"filesystem"`: A friendly name for the server that appears in Claude Desktop
* `"command": "npx"`: Uses Node.js's npx tool to run the server
* `"-y"`: Automatically confirms the installation of the server package
* `"@modelcontextprotocol/server-filesystem"`: The package name of the Filesystem Server
* The remaining arguments: Directories the server is allowed to access
</Tip>
<Warning>
**Security Consideration**
Only grant access to directories you're comfortable with Claude reading and modifying. The server runs with your user account permissions, so it can perform any file operations you can perform manually.
</Warning>
</Step>
<Step title="Restart Claude Desktop">
After saving the configuration file, completely quit Claude Desktop and restart it. The application needs to restart to load the new configuration and start the MCP server.
Upon successful restart, click the "Add files, connectors and more" indicator <img src="https://mintcdn.com/mcp/cpXzQjUOzyH0mCNH/images/claude-add-files-connectors-and-more.png?fit=max&auto=format&n=cpXzQjUOzyH0mCNH&q=85&s=53acf21f6807dd5323b70b84b5d98d8a" style={{display: 'inline', margin: 0, height: '1.3em'}} width="33" height="33" data-path="images/claude-add-files-connectors-and-more.png" /> in the bottom-left corner of the conversation input box:
<Frame>
<img src="https://mintcdn.com/mcp/akpggzunDlIcY2im/images/quickstart-slider.png?fit=max&auto=format&n=akpggzunDlIcY2im&q=85&s=a1ebd4259cff2a7472171885f2edc035" alt="Claude Desktop interface showing MCP server indicator" width="1414" height="410" data-path="images/quickstart-slider.png" />
</Frame>
Click on this indicator, then scroll over "Connectors" and click "Manage connectors". Select "filesystem" from the connector list to view the the Filesystem Server's available tools:
<Frame style={{ textAlign: "center" }}>
<img src="https://mintcdn.com/mcp/cpXzQjUOzyH0mCNH/images/quickstart-tools.png?fit=max&auto=format&n=cpXzQjUOzyH0mCNH&q=85&s=212a63d76daba170d52db0d2f6f582be" width="400" alt="Available filesystem tools in Claude Desktop" data-path="images/quickstart-tools.png" />
</Frame>
If the Filesystem Server doesn't connect, refer to the [Troubleshooting](#troubleshooting) section for debugging steps.
</Step>
</Steps>
## Using the Filesystem Server
With the Filesystem Server connected, Claude can now interact with your file system. Try these example requests to explore the capabilities:
### File Management Examples
* **"Can you write a poem and save it to my desktop?"** - Claude will compose a poem and create a new text file on your desktop
* **"What work-related files are in my downloads folder?"** - Claude will scan your downloads and identify work-related documents
* **"Please organize all images on my desktop into a new folder called 'Images'"** - Claude will create a folder and move image files into it
### How Approval Works
Before executing any file system operation, Claude will request your approval. This ensures you maintain control over all actions:
<Frame style={{ textAlign: "center" }}>
<img src="https://mintcdn.com/mcp/4ZXF1PrDkEaJvXpn/images/quickstart-approve.png?fit=max&auto=format&n=4ZXF1PrDkEaJvXpn&q=85&s=98cc6e9dfe885fbd6e9bfae40601e494" width="500" alt="Claude requesting approval to perform a file operation" data-path="images/quickstart-approve.png" />
</Frame>
Review each request carefully before approving. You can always deny a request if you're not comfortable with the proposed action.
## Troubleshooting
If you encounter issues setting up or using the Filesystem Server, these solutions address common problems:
<AccordionGroup>
<Accordion title="Server not showing up in Claude / hammer icon missing">
1. Restart Claude Desktop completely
2. Check your `claude_desktop_config.json` file syntax
3. Make sure the file paths included in `claude_desktop_config.json` are valid and that they are absolute and not relative
4. Look at [logs](#getting-logs-from-claude-for-desktop) to see why the server is not connecting
5. In your command line, try manually running the server (replacing `username` as you did in `claude_desktop_config.json`) to see if you get any errors:
<CodeGroup>
```bash macOS/Linux theme={null}
npx -y @modelcontextprotocol/server-filesystem /Users/username/Desktop /Users/username/Downloads
```
```powershell Windows theme={null}
npx -y @modelcontextprotocol/server-filesystem C:\Users\username\Desktop C:\Users\username\Downloads
```
</CodeGroup>
</Accordion>
<Accordion title="Getting logs from Claude Desktop">
Claude.app logging related to MCP is written to log files in:
* macOS: `~/Library/Logs/Claude`
* Windows: `%APPDATA%\Claude\logs`
* `mcp.log` will contain general logging about MCP connections and connection failures.
* Files named `mcp-server-SERVERNAME.log` will contain error (stderr) logging from the named server.
You can run the following command to list recent logs and follow along with any new ones (on Windows, it will only show recent logs):
<CodeGroup>
```bash macOS/Linux theme={null}
tail -n 20 -f ~/Library/Logs/Claude/mcp*.log
```
```powershell Windows theme={null}
type "%APPDATA%\Claude\logs\mcp*.log"
```
</CodeGroup>
</Accordion>
<Accordion title="Tool calls failing silently">
If Claude attempts to use the tools but they fail:
1. Check Claude's logs for errors
2. Verify your server builds and runs without errors
3. Try restarting Claude Desktop
</Accordion>
<Accordion title="None of this is working. What do I do?">
Please refer to our [debugging guide](/docs/2024-11-05/tools/debugging) for better debugging tools and more detailed guidance.
</Accordion>
<Accordion title="ENOENT error and `${APPDATA}` in paths on Windows">
If your configured server fails to load, and you see within its logs an error referring to `${APPDATA}` within a path, you may need to add the expanded value of `%APPDATA%` to your `env` key in `claude_desktop_config.json`:
```json theme={null}
{
"brave-search": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-brave-search"],
"env": {
"APPDATA": "C:\\Users\\user\\AppData\\Roaming\\",
"BRAVE_API_KEY": "..."
}
}
}
```
With this change in place, launch Claude Desktop once again.
<Warning>
**npm should be installed globally**
The `npx` command may continue to fail if you have not installed npm globally. If npm is already installed globally, you will find `%APPDATA%\npm` exists on your system. If not, you can install npm globally by running the following command:
```bash theme={null}
npm install -g npm
```
</Warning>
</Accordion>
</AccordionGroup>
## Next Steps
Now that you've successfully connected Claude Desktop to a local MCP server, explore these options to expand your setup:
<CardGroup cols={2}>
<Card title="Explore other servers" icon="grid" href="https://github.com/modelcontextprotocol/servers">
Browse our collection of official and community-created MCP servers for
additional capabilities
</Card>
<Card title="Build your own server" icon="code" href="/docs/2024-11-05/develop/build-server">
Create custom MCP servers tailored to your specific workflows and
integrations
</Card>
<Card title="Connect to remote servers" icon="cloud" href="/docs/2024-11-05/develop/connect-remote-servers">
Learn how to connect Claude to remote MCP servers for cloud-based tools and
services
</Card>
<Card title="Understand the protocol" icon="book" href="/docs/2024-11-05/learn/architecture">
Dive deeper into how MCP works and its architecture
</Card>
</CardGroup>
docs/2024-11-05/develop/connect-remote-servers New page · 118 lines, new page
# Connect to remote MCP Servers ## Understanding Remote MCP Servers ## What are Custom Connectors? ## Connecting to a Remote MCP Server ## Best Practices for Using Remote MCP Servers ## Next Steps
A whole new page. There's nothing to diff it against, so here is what it says.
# Connect to remote MCP Servers
> Learn how to connect Claude to remote MCP servers and extend its capabilities with internet-hosted tools and data sources
Remote MCP servers extend AI applications' capabilities beyond your local environment, providing access to internet-hosted tools, services, and data sources. By connecting to remote MCP servers, you transform AI assistants from helpful tools into informed teammates capable of handling complex, multi-step projects with real-time access to external resources.
Many clients now support remote MCP servers, enabling a wide range of integration possibilities. This guide demonstrates how to connect to remote MCP servers using [Claude](https://claude.ai/) as an example, one of the many clients that support MCP. While we focus on Claude's implementation through Custom Connectors, the concepts apply broadly to other MCP-compatible clients.
## Understanding Remote MCP Servers
Remote MCP servers function similarly to local MCP servers but are hosted on the internet rather than your local machine. They expose tools, prompts, and resources that Claude can use to perform tasks on your behalf. These servers can integrate with various services such as project management tools, documentation systems, code repositories, and any other API-enabled service.
The key advantage of remote MCP servers is their accessibility. Unlike local servers that require installation and configuration on each device, remote servers are available from any MCP client with an internet connection. This makes them ideal for web-based AI applications, integrations that emphasize ease of use, and services that require server-side processing or authentication.
## What are Custom Connectors?
Custom Connectors serve as the bridge between Claude and remote MCP servers. They allow you to connect Claude directly to the tools and data sources that matter most to your workflows, enabling Claude to operate within your favorite software and draw insights from the complete context of your external tools.
With Custom Connectors, you can:
* [Connect Claude to existing remote MCP servers](https://support.anthropic.com/en/articles/11175166-getting-started-with-custom-connectors-using-remote-mcp) provided by third-party developers
* [Build your own remote MCP servers to connect with any tool](https://support.anthropic.com/en/articles/11503834-building-custom-connectors-via-remote-mcp-servers)
## Connecting to a Remote MCP Server
The process of connecting Claude to a remote MCP server involves adding a Custom Connector through the [Claude interface](https://claude.ai/). This establishes a secure connection between Claude and your chosen remote server.
<Steps>
<Step title="Navigate to Connector Settings">
Open Claude in your browser and navigate to the settings page. You can access this by clicking on your profile icon and selecting "Settings" from the dropdown menu. Once in settings, locate and click on the "Connectors" section in the sidebar.
This will display your currently configured connectors and provide options to add new ones.
</Step>
<Step title="Add a Custom Connector">
In the Connectors section, scroll to the bottom where you'll find the "Add custom connector" button. Click this button to begin the connection process.
<Frame>
<img src="https://mintcdn.com/mcp/4ZXF1PrDkEaJvXpn/images/quickstart-remote/1-add-connector.png?fit=max&auto=format&n=4ZXF1PrDkEaJvXpn&q=85&s=b5ae9b23164875bbaa3aff4c178cdc64" alt="Add custom connector button in Claude settings" width="1038" height="809" data-path="images/quickstart-remote/1-add-connector.png" />
</Frame>
A dialog will appear prompting you to enter the remote MCP server URL. This URL should be provided by the server developer or administrator. Enter the complete URL, ensuring it includes the proper protocol (https\://) and any necessary path components.
<Frame>
<img src="https://mintcdn.com/mcp/4ZXF1PrDkEaJvXpn/images/quickstart-remote/2-connect.png?fit=max&auto=format&n=4ZXF1PrDkEaJvXpn&q=85&s=0934f16d8e016cade8e560c8f89d011b" alt="Dialog for entering remote MCP server URL" width="1616" height="282" data-path="images/quickstart-remote/2-connect.png" />
</Frame>
After entering the URL, click "Add" to proceed with the connection.
</Step>
<Step title="Complete Authentication">
Most remote MCP servers require authentication to ensure secure access to their resources. The authentication process varies depending on the server implementation but commonly involves OAuth, API keys, or username/password combinations.
<Frame>
<img src="https://mintcdn.com/mcp/4ZXF1PrDkEaJvXpn/images/quickstart-remote/3-auth.png?fit=max&auto=format&n=4ZXF1PrDkEaJvXpn&q=85&s=89af6e1b85718637231388697cc7b015" alt="Authentication screen for remote MCP server" width="490" height="806" data-path="images/quickstart-remote/3-auth.png" />
</Frame>
Follow the authentication prompts provided by the server. This may redirect you to a third-party authentication provider or display a form within Claude. Once authentication is complete, Claude will establish a secure connection to the remote server.
</Step>
<Step title="Access Resources and Prompts">
After successful connection, the remote server's resources and prompts become available in your Claude conversations. You can access these by clicking the paperclip icon in the message input area, which opens the attachment menu.
<Frame>
<img src="https://mintcdn.com/mcp/cpXzQjUOzyH0mCNH/images/quickstart-remote/4-select-resources-menu.png?fit=max&auto=format&n=cpXzQjUOzyH0mCNH&q=85&s=e5fa85174f8acbadbd709bac66f42d5c" alt="Attachment menu showing available resources" width="735" height="378" data-path="images/quickstart-remote/4-select-resources-menu.png" />
</Frame>
The menu displays all available resources and prompts from your connected servers. Select the items you want to include in your conversation. These resources provide Claude with context and information from your external tools.
<Frame>
<img src="https://mintcdn.com/mcp/cpXzQjUOzyH0mCNH/images/quickstart-remote/5-select-prompts-resources.png?fit=max&auto=format&n=cpXzQjUOzyH0mCNH&q=85&s=68722669d9e18252756885c703e4f221" alt="Selecting specific resources and prompts from the menu" width="648" height="529" data-path="images/quickstart-remote/5-select-prompts-resources.png" />
</Frame>
</Step>
<Step title="Configure Tool Permissions">
Remote MCP servers often expose multiple tools with varying capabilities. You can control which tools Claude is allowed to use by configuring permissions in the connector settings. This ensures Claude only performs actions you've explicitly authorized.
<Frame>
<img src="https://mintcdn.com/mcp/cpXzQjUOzyH0mCNH/images/quickstart-remote/6-configure-tools.png?fit=max&auto=format&n=cpXzQjUOzyH0mCNH&q=85&s=5cfd8b2c5d06e7e3699eac24c68d090e" alt="Tool permission configuration interface" width="604" height="745" data-path="images/quickstart-remote/6-configure-tools.png" />
</Frame>
Navigate back to the Connectors settings and click on your connected server. Here you can enable or disable specific tools, set usage limits, and configure other security parameters according to your needs.
</Step>
</Steps>
## Best Practices for Using Remote MCP Servers
When working with remote MCP servers, consider these recommendations to ensure a secure and efficient experience:
**Security considerations**: Always verify the authenticity of remote MCP servers before connecting. Only connect to servers from trusted sources, and review the permissions requested during authentication. Be cautious about granting access to sensitive data or systems.
**Managing multiple connectors**: You can connect to multiple remote MCP servers simultaneously. Organize your connectors by purpose or project to maintain clarity. Regularly review and remove connectors you no longer use to keep your workspace organized and secure.
## Next Steps
Now that you've connected Claude to a remote MCP server, you can explore its capabilities in your conversations. Try using the connected tools to automate tasks, access external data, or integrate with your existing workflows.
<CardGroup cols={2}>
<Card title="Build your own remote server" icon="cloud" href="https://support.anthropic.com/en/articles/11503834-building-custom-connectors-via-remote-mcp-servers">
Create custom remote MCP servers to integrate with proprietary tools and
services
</Card>
<Card title="Explore available servers" icon="grid" href="https://github.com/modelcontextprotocol/servers">
Browse our collection of official and community-created MCP servers
</Card>
<Card title="Connect local servers" icon="computer" href="/docs/2024-11-05/develop/connect-local-servers">
Learn how to connect Claude Desktop to local MCP servers for direct system
access
</Card>
<Card title="Understand the architecture" icon="book" href="/docs/2024-11-05/learn/architecture">
Dive deeper into how MCP works and its architecture
</Card>
</CardGroup>
Remote MCP servers unlock powerful possibilities for extending Claude's capabilities. As you become familiar with these integrations, you'll discover new ways to streamline your workflows and accomplish complex tasks more efficiently.
docs/2024-11-05/getting-started/intro New page · 54 lines, new page
# What is the Model Context Protocol (MCP)? ## What can MCP enable? ## Why does MCP matter? ## Broad ecosystem support ## Start Building ## Learn more
A whole new page. There's nothing to diff it against, so here is what it says.
# What is the Model Context Protocol (MCP)?
MCP (Model Context Protocol) is an open-source standard for connecting AI applications to external systems.
Using MCP, AI applications like Claude or ChatGPT can connect to data sources (e.g. local files, databases), tools (e.g. search engines, calculators) and workflows (e.g. specialized prompts)—enabling them to access key information and perform tasks.
Think of MCP like a USB-C port for AI applications. Just as USB-C provides a standardized way to connect electronic devices, MCP provides a standardized way to connect AI applications to external systems.
<Frame>
<img src="https://mintcdn.com/mcp/bEUxYpZqie0DsluH/images/mcp-simple-diagram.png?fit=max&auto=format&n=bEUxYpZqie0DsluH&q=85&s=35268aa0ad50b8c385913810e7604550" width="3840" height="1500" data-path="images/mcp-simple-diagram.png" />
</Frame>
## What can MCP enable?
* Agents can access your Google Calendar and Notion, acting as a more personalized AI assistant.
* Claude Code can generate an entire web app using a Figma design.
* Enterprise chatbots can connect to multiple databases across an organization, empowering users to analyze data using chat.
* AI models can create 3D designs on Blender and print them out using a 3D printer.
## Why does MCP matter?
Depending on where you sit in the ecosystem, MCP can have a range of benefits.
* **Developers**: MCP reduces development time and complexity when building, or integrating with, an AI application or agent.
* **AI applications or agents**: MCP gives them access to an ecosystem of data sources, tools and apps, which enhances their capabilities and improves the end-user experience.
* **End-users**: MCP results in more capable AI applications or agents that can access user data and take actions on the user's behalf when necessary.
## Broad ecosystem support
MCP is an open protocol supported across a wide range of clients and servers. AI assistants like [Claude](https://claude.com/docs/connectors/building) and [ChatGPT](https://developers.openai.com/api/docs/mcp/), development tools like [Visual Studio Code](https://code.visualstudio.com/docs/copilot/chat/mcp-servers), [Cursor](https://cursor.com/docs/context/mcp), [MCPJam](https://docs.mcpjam.com/getting-started), and many others all support MCP — making it easy to build once and integrate everywhere.
## Start Building
<CardGroup cols={2}>
<Card title="Build servers" icon="server" href="/docs/2024-11-05/develop/build-server">
Create MCP servers to expose your data and tools
</Card>
<Card title="Build clients" icon="computer" href="/docs/2024-11-05/develop/build-client">
Develop applications that connect to MCP servers
</Card>
<Card title="Build MCP Apps" icon="puzzle-piece" href="/extensions/apps/overview">
Build interactive apps that run inside AI clients
</Card>
</CardGroup>
## Learn more
<CardGroup cols={2}>
<Card title="Understand concepts" icon="book" href="/docs/2024-11-05/learn/architecture">
Learn the core concepts and architecture of MCP
</Card>
</CardGroup>
docs/2024-11-05/learn/architecture New page · 459 lines, new page
# Architecture overview ## Scope ## Concepts of MCP ### Participants ### Layers #### Data layer #### Transport layer ### Data Layer Protocol #### Lifecycle management #### Primitives #### Notifications ## Example ### Data Layer
A whole new page. There's nothing to diff it against, so here is what it says.
# Architecture overview
This overview of the Model Context Protocol (MCP) discusses its [scope](#scope) and [core concepts](#concepts-of-mcp), and provides an [example](#example) demonstrating each core concept.
Because MCP SDKs abstract away many concerns, most developers will likely find the [data layer protocol](#data-layer-protocol) section to be the most useful. It discusses how MCP servers can provide context to an AI application.
For specific implementation details, please refer to the documentation for your [language-specific SDK](/docs/2024-11-05/sdk).
## Scope
The Model Context Protocol includes the following projects:
* [MCP Specification](https://modelcontextprotocol.io/specification/latest): A specification of MCP that outlines the implementation requirements for clients and servers.
* [MCP SDKs](/docs/2024-11-05/sdk): SDKs for different programming languages that implement MCP.
* **MCP Development Tools**: Tools for developing MCP servers and clients, including the [MCP Inspector](https://github.com/modelcontextprotocol/inspector)
* [MCP Reference Server Implementations](https://github.com/modelcontextprotocol/servers): Reference implementations of MCP servers.
<Note>
MCP focuses solely on the protocol for context exchange—it does not dictate
how AI applications use LLMs or manage the provided context.
</Note>
## Concepts of MCP
### Participants
MCP follows a client-server architecture where an MCP host — an AI application like [Claude Code](https://www.anthropic.com/claude-code) or [Claude Desktop](https://www.claude.ai/download) — establishes connections to one or more MCP servers. The MCP host accomplishes this by creating one MCP client for each MCP server. Each MCP client maintains a dedicated connection with its corresponding MCP server.
Local MCP servers that use the STDIO transport typically serve a single MCP client, whereas remote MCP servers that use the HTTP with SSE transport will typically serve many MCP clients.
The key participants in the MCP architecture are:
* **MCP Host**: The AI application that coordinates and manages one or multiple MCP clients
* **MCP Client**: A component that maintains a connection to an MCP server and obtains context from an MCP server for the MCP host to use
* **MCP Server**: A program that provides context to MCP clients
**For example**: Visual Studio Code acts as an MCP host. When Visual Studio Code establishes a connection to an MCP server, such as the [Sentry MCP server](https://docs.sentry.io/product/sentry-mcp/), the Visual Studio Code runtime instantiates an MCP client object that maintains the connection to the Sentry MCP server.
When Visual Studio Code subsequently connects to another MCP server, such as the [local filesystem server](https://github.com/modelcontextprotocol/servers/tree/main/src/filesystem), the Visual Studio Code runtime instantiates an additional MCP client object to maintain this connection.
```mermaid theme={null}
graph TB
subgraph "MCP Host (AI Application)"
Client1["MCP Client 1"]
Client2["MCP Client 2"]
Client3["MCP Client 3"]
Client4["MCP Client 4"]
end
ServerA["MCP Server A - Local<br/>(e.g. Filesystem)"]
ServerB["MCP Server B - Local<br/>(e.g. Database)"]
ServerC["MCP Server C - Remote<br/>(e.g. Sentry)"]
Client1 ---|"Dedicated<br/>connection"| ServerA
Client2 ---|"Dedicated<br/>connection"| ServerB
Client3 ---|"Dedicated<br/>connection"| ServerC
Client4 ---|"Dedicated<br/>connection"| ServerC
```
Note that **MCP server** refers to the program that serves context data, regardless of
where it runs. MCP servers can execute locally or remotely. For example, when
Claude Desktop launches the [filesystem
server](https://github.com/modelcontextprotocol/servers/tree/main/src/filesystem),
the server runs locally on the same machine because it uses the STDIO
transport. This is commonly referred to as a "local" MCP server. The official
[Sentry MCP server](https://docs.sentry.io/product/sentry-mcp/) runs on the
Sentry platform, and uses the HTTP with SSE transport. This is commonly
referred to as a "remote" MCP server.
### Layers
MCP consists of two layers:
* **Data layer**: Defines the JSON-RPC based protocol for client-server communication, including lifecycle management, and core primitives, such as tools, resources, prompts and notifications.
* **Transport layer**: Defines the communication mechanisms and channels that enable data exchange between clients and servers, including transport-specific connection establishment, message framing, and authorization.
Conceptually the data layer is the inner layer, while the transport layer is the outer layer.
#### Data layer
The data layer implements a [JSON-RPC 2.0](https://www.jsonrpc.org/) based exchange protocol that defines the message structure and semantics.
This layer includes:
* **Lifecycle management**: Handles connection initialization, capability negotiation, and connection termination between clients and servers
* **Server features**: Enables servers to provide core functionality including tools for AI actions, resources for context data, and prompts for interaction templates from and to the client
* **Client features**: Enables servers to ask the client to sample from the host LLM and log messages to the client
* **Utility features**: Supports additional capabilities like notifications for real-time updates and progress tracking for long-running operations
#### Transport layer
The transport layer manages communication channels and authentication between clients and servers. It handles connection establishment, message framing, and secure communication between MCP participants.
MCP supports two transport mechanisms:
* **Stdio transport**: Uses standard input/output streams for direct process communication between local processes on the same machine, providing optimal performance with no network overhead.
* **HTTP with SSE transport**: Uses Server-Sent Events for server-to-client messages and HTTP POST for client-to-server messages. This transport enables remote server communication and supports standard HTTP authentication methods including bearer tokens, API keys, and custom headers.
The transport layer abstracts communication details from the protocol layer, enabling the same JSON-RPC 2.0 message format across all transport mechanisms.
### Data Layer Protocol
A core part of MCP is defining the schema and semantics between MCP clients and MCP servers. Developers will likely find the data layer — in particular, the set of [primitives](#primitives) — to be the most interesting part of MCP. It is the part of MCP that defines the ways developers can share context from MCP servers to MCP clients.
MCP uses [JSON-RPC 2.0](https://www.jsonrpc.org/) as its underlying RPC protocol. Client and servers send requests to each other and respond accordingly. Notifications can be used when no response is required.
#### Lifecycle management
MCP is a stateful protocol that requires lifecycle management. The purpose of lifecycle management is to negotiate the <Tooltip tip="Features and operations that a client or server supports, such as tools, resources, or prompts">capabilities</Tooltip> that both client and server support. Detailed information can be found in the [specification](/specification/2024-11-05/basic/lifecycle), and the [example](#example) showcases the initialization sequence.
#### Primitives
MCP primitives are the most important concept within MCP. They define what clients and servers can offer each other. These primitives specify the types of contextual information that can be shared with AI applications and the range of actions that can be performed.
MCP defines three core primitives that *servers* can expose:
* **Tools**: Executable functions that AI applications can invoke to perform actions (e.g., file operations, API calls, database queries)
* **Resources**: Data sources that provide contextual information to AI applications (e.g., file contents, database records, API responses)
* **Prompts**: Reusable templates that help structure interactions with language models (e.g., system prompts, few-shot examples)
Each primitive type has associated methods for discovery (`*/list`), retrieval (`*/get`), and in some cases, execution (`tools/call`).
MCP clients will use the `*/list` methods to discover available primitives. For example, a client can first list all available tools (`tools/list`) and then execute them. This design allows listings to be dynamic.
As a concrete example, consider an MCP server that provides context about a database. It can expose tools for querying the database, a resource that contains the schema of the database, and a prompt that includes few-shot examples for interacting with the tools.
For more details about server primitives see [server concepts](./server-concepts).
MCP also defines primitives that *clients* can expose. These primitives allow MCP server authors to build richer interactions.
* **Sampling**: Allows servers to request language model completions from the client's AI application. This is useful when server authors want access to a language model, but want to stay model-independent and not include a language model SDK in their MCP server. They can use the `sampling/createMessage` method to request a language model completion from the client's AI application.
* **Logging**: Enables servers to send log messages to clients for debugging and monitoring purposes.
For more details about client primitives see [client concepts](./client-concepts).
Besides server and client primitives, the protocol offers cross-cutting utility primitives that augment how requests are executed:
* **Tasks (Experimental)**: Durable execution wrappers that enable deferred result retrieval and status tracking for MCP requests (e.g., expensive computations, workflow automation, batch processing, multi-step operations)
#### Notifications
The protocol supports real-time notifications to enable dynamic updates between servers and clients. For example, when a server's available tools change—such as when new functionality becomes available or existing tools are modified—the server can send tool update notifications to inform connected clients about these changes. Notifications are sent as JSON-RPC 2.0 notification messages (without expecting a response) and enable MCP servers to provide real-time updates to connected clients.
## Example
### Data Layer
This section provides a step-by-step walkthrough of an MCP client-server interaction, focusing on the data layer protocol. We'll demonstrate the lifecycle sequence, tool operations, and notifications using JSON-RPC 2.0 messages.
<Steps>
<Step title="Initialization (Lifecycle Management)">
MCP begins with lifecycle management through a capability negotiation handshake. As described in the [lifecycle management](#lifecycle-management) section, the client sends an `initialize` request to establish the connection and negotiate supported features.
<CodeGroup>
```json Initialize Request theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2024-11-05",
"capabilities": {
"sampling": {}
},
"clientInfo": {
"name": "example-client",
"version": "1.0.0"
}
}
}
```
```json Initialize Response theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"protocolVersion": "2024-11-05",
"capabilities": {
"tools": {
"listChanged": true
},
"resources": {}
},
"serverInfo": {
"name": "example-server",
"version": "1.0.0"
}
}
}
```
</CodeGroup>
#### Understanding the Initialization Exchange
The initialization process is a key part of MCP's lifecycle management and serves several critical purposes:
1. **Protocol Version Negotiation**: The `protocolVersion` field (e.g., "2024-11-05") ensures both client and server are using compatible protocol versions. This prevents communication errors that could occur when different versions attempt to interact. If a mutually compatible version is not negotiated, the connection should be terminated.
2. **Capability Discovery**: The `capabilities` object allows each party to declare what features they support, including which [primitives](#primitives) they can handle (tools, resources, prompts) and whether they support features like [notifications](#notifications). This enables efficient communication by avoiding unsupported operations.
3. **Identity Exchange**: The `clientInfo` and `serverInfo` objects provide identification and versioning information for debugging and compatibility purposes.
In this example, the capability negotiation demonstrates how MCP primitives are declared:
**Client Capabilities**:
* `"sampling": {}` - The client declares it can handle server sampling requests (can receive `sampling/createMessage` method calls)
**Server Capabilities**:
* `"tools": {"listChanged": true}` - The server supports the tools primitive AND can send `tools/list_changed` notifications when its tool list changes
* `"resources": {}` - The server also supports the resources primitive (can handle `resources/list` and `resources/read` methods)
After successful initialization, the client sends a notification to indicate it's ready:
```json Notification theme={null}
{
"jsonrpc": "2.0",
"method": "notifications/initialized"
}
```
#### How This Works in AI Applications
During initialization, the AI application's MCP client manager establishes connections to configured servers and stores their capabilities for later use. The application uses this information to determine which servers can provide specific types of functionality (tools, resources, prompts) and whether they support real-time updates.
```python Pseudo-code for AI application initialization theme={null}
# Pseudo Code
async with stdio_client(server_config) as (read, write):
async with ClientSession(read, write) as session:
init_response = await session.initialize()
if init_response.capabilities.tools:
app.register_mcp_server(session, supports_tools=True)
app.set_server_ready(session)
```
</Step>
<Step title="Tool Discovery (Primitives)">
Now that the connection is established, the client can discover available tools by sending a `tools/list` request. This request is fundamental to MCP's tool discovery mechanism — it allows clients to understand what tools are available on the server before attempting to use them.
<CodeGroup>
```json Tools List Request theme={null}
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/list"
}
```
```json Tools List Response theme={null}
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"tools": [
{
"name": "calculator_arithmetic",
"title": "Calculator",
"description": "Perform mathematical calculations including basic arithmetic, trigonometric functions, and algebraic operations",
"inputSchema": {
"type": "object",
"properties": {
"expression": {
"type": "string",
"description": "Mathematical expression to evaluate (e.g., '2 + 3 * 4', 'sin(30)', 'sqrt(16)')"
}
},
"required": ["expression"]
}
},
{
"name": "weather_current",
"title": "Weather Information",
"description": "Get current weather information for any location worldwide",
"inputSchema": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "City name, address, or coordinates (latitude,longitude)"
},
"units": {
"type": "string",
"enum": ["metric", "imperial", "kelvin"],
"description": "Temperature units to use in response",
"default": "metric"
}
},
"required": ["location"]
}
}
]
}
}
```
</CodeGroup>
#### Understanding the Tool Discovery Request
The `tools/list` request is simple, containing no parameters.
#### Understanding the Tool Discovery Response
Cut at 300 lines. The page has the rest.
docs/2024-11-05/learn/client-concepts New page · 146 lines, new page
# Understanding MCP clients ## Core Client Features ### Roots #### Overview #### Example: Travel Planning Workspace #### Design Philosophy #### User Interaction Model ### Sampling #### Overview #### Example: Flight Analysis Tool #### User Interaction Model
A whole new page. There's nothing to diff it against, so here is what it says.
# Understanding MCP clients
MCP clients are instantiated by host applications to communicate with particular MCP servers. The host application, like Claude.ai or an IDE, manages the overall user experience and coordinates multiple clients. Each client handles one direct communication with one server.
Understanding the distinction is important: the *host* is the application users interact with, while *clients* are the protocol-level components that enable server connections.
## Core Client Features
In addition to making use of context provided by servers, clients may provide several features to servers. These client features allow server authors to build richer interactions.
| Feature | Explanation | Example |
| ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| **Roots** | Roots allow clients to specify which directories servers should focus on, communicating intended scope through a coordination mechanism. | A server for booking travel may be given access to a specific directory, from which it can read a user's calendar. |
| **Sampling** | Sampling allows servers to request LLM completions through the client, enabling an agentic workflow. This approach puts the client in complete control of user permissions and security measures. | A server for booking travel may send a list of flights to an LLM and request that the LLM pick the best flight for the user. |
### Roots
Roots define filesystem boundaries for server operations, allowing clients to specify which directories servers should focus on.
#### Overview
Roots are a mechanism for clients to communicate filesystem access boundaries to servers. They consist of file URIs that indicate directories where servers can operate, helping servers understand the scope of available files and folders. While roots communicate intended boundaries, they do not enforce security restrictions. Actual security must be enforced at the operating system level, via file permissions and/or sandboxing.
**Root structure:**
```json theme={null}
{
"uri": "file:///Users/agent/travel-planning",
"name": "Travel Planning Workspace"
}
```
Roots are exclusively filesystem paths and always use the `file://` URI scheme. They help servers understand project boundaries, workspace organization, and accessible directories. The roots list can be updated dynamically as users work with different projects or folders, with servers receiving notifications through `roots/list_changed` when boundaries change.
#### Example: Travel Planning Workspace
A travel agent working with multiple client trips benefits from roots to organize filesystem access. Consider a workspace with different directories for various aspects of travel planning.
The client provides filesystem roots to the travel planning server:
* `file:///Users/agent/travel-planning` - Main workspace containing all travel files
* `file:///Users/agent/travel-templates` - Reusable itinerary templates and resources
* `file:///Users/agent/client-documents` - Client passports and travel documents
When the agent creates a Barcelona itinerary, well-behaved servers respect these boundaries—accessing templates, saving the new itinerary, and referencing client documents within the specified roots. Servers typically access files within roots by using relative paths from the root directories or by utilizing file search tools that respect the root boundaries.
If the agent opens an archive folder like `file:///Users/agent/archive/2023-trips`, the client updates the roots list via `roots/list_changed`.
For a complete implementation of a server that respects roots, see the [filesystem server](https://github.com/modelcontextprotocol/servers/tree/main/src/filesystem) in the official servers repository.
#### Design Philosophy
Roots serve as a coordination mechanism between clients and servers, not a security boundary. The specification requires that servers "SHOULD respect root boundaries," and not that they "MUST enforce" them, because servers run code the client cannot control.
Roots work best when servers are trusted or vetted, users understand their advisory nature, and the goal is preventing accidents rather than stopping malicious behavior. They excel at context scoping (telling servers where to focus), accident prevention (helping well-behaved servers stay in bounds), and workflow organization (such as managing project boundaries automatically).
#### User Interaction Model
Roots are typically managed automatically by host applications based on user actions, though some applications may expose manual root management:
**Automatic root detection**: When users open folders, clients automatically expose them as roots. Opening a travel workspace allows the client to expose that directory as a root, helping servers understand which itineraries and documents are in scope for the current work.
**Manual root configuration**: Advanced users can specify roots through configuration. For example, adding `/travel-templates` for reusable resources while excluding directories with financial records.
### Sampling
Sampling allows servers to request language model completions through the client, enabling agentic behaviors while maintaining security and user control.
#### Overview
Sampling enables servers to perform AI-dependent tasks without directly integrating with or paying for AI models. Instead, servers can request that the client—which already has AI model access—handle these tasks on their behalf. This approach puts the client in complete control of user permissions and security measures. Because sampling requests occur within the context of other operations—like a tool analyzing data—and are processed as separate model calls, they maintain clear boundaries between different contexts, allowing for more efficient use of the context window.
**Sampling flow:**
```mermaid theme={null}
sequenceDiagram
participant LLM
participant User
participant Client
participant Server
Note over Server,Client: Server initiates sampling
Server->>Client: sampling/createMessage
Note over Client,User: Human-in-the-loop review
Client->>User: Present request for approval
User-->>Client: Review and approve/modify
Note over Client,LLM: Model interaction
Client->>LLM: Forward approved request
LLM-->>Client: Return generation
Note over Client,User: Response review
Client->>User: Present response for approval
User-->>Client: Review and approve/modify
Note over Server,Client: Complete request
Client-->>Server: Return approved response
```
The flow ensures security through multiple human-in-the-loop checkpoints. Users review and can modify both the initial request and the generated response before it returns to the server.
**Request parameters example:**
```typescript theme={null}
{
messages: [
{
role: "user",
content: "Analyze these flight options and recommend the best choice:\n" +
"[47 flights with prices, times, airlines, and layovers]\n" +
"User preferences: morning departure, max 1 layover"
}
],
modelPreferences: {
hints: [{
name: "claude-sonnet-4-20250514" // Suggested model
}],
costPriority: 0.3, // Less concerned about API cost
speedPriority: 0.2, // Can wait for thorough analysis
intelligencePriority: 0.9 // Need complex trade-off evaluation
},
systemPrompt: "You are a travel expert helping users find the best flights based on their preferences",
maxTokens: 1500
}
```
#### Example: Flight Analysis Tool
Consider a travel booking server with a tool called `findBestFlight` that uses sampling to analyze available flights and recommend the optimal choice. When a user asks "Book me the best flight to Barcelona next month," the tool needs AI assistance to evaluate complex trade-offs.
The tool queries airline APIs and gathers 47 flight options. It then requests AI assistance to analyze these options: "Analyze these flight options and recommend the best choice: \[47 flights with prices, times, airlines, and layovers] User preferences: morning departure, max 1 layover."
The client initiates the sampling request, allowing the AI to evaluate trade-offs—like cheaper red-eye flights versus convenient morning departures. The tool uses this analysis to present the top three recommendations.
#### User Interaction Model
While not a requirement, sampling is designed to allow human-in-the-loop control. Users can maintain oversight through several mechanisms:
**Approval controls**: Sampling requests may require explicit user consent. Clients can show what the server wants to analyze and why. Users can approve, deny, or modify requests.
**Transparency features**: Clients can display the exact prompt, model selection, and token limits, allowing users to review AI responses before they return to the server.
**Configuration options**: Users can set model preferences, configure auto-approval for trusted operations, or require approval for everything. Clients may provide options to redact sensitive information.
**Security considerations**: Both clients and servers must handle sensitive data appropriately during sampling. Clients should implement rate limiting and validate all message content. The human-in-the-loop design ensures that server-initiated AI interactions cannot compromise security or access sensitive data without explicit user consent.
docs/2024-11-05/learn/server-concepts New page · 281 lines, new page
# Understanding MCP servers ## Core Server Features ### Tools #### How Tools Work #### Example: Travel Booking #### User Interaction Model ### Resources #### How Resources Work #### Example: Getting Travel Planning Context #### Parameter Completion #### User Interaction Model ### Prompts #### How Prompts Work #### Example: Streamlined Workflows #### User Interaction Model ## Bringing Servers Together ### Example: Multi-Server Travel Planning #### The Complete Flow
A whole new page. There's nothing to diff it against, so here is what it says.
# Understanding MCP servers
MCP servers are programs that expose specific capabilities to AI applications through standardized protocol interfaces.
Common examples include file system servers for document access, database servers for data queries, GitHub servers for code management, Slack servers for team communication, and calendar servers for scheduling.
## Core Server Features
Servers provide functionality through three building blocks:
| Feature | Explanation | Examples | Who controls it |
| ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------ | --------------- |
| **Tools** | Functions that your LLM can actively call, and decides when to use them based on user requests. Tools can write to databases, call external APIs, modify files, or trigger other logic. | Search flights<br />Send messages<br />Create calendar events | Model |
| **Resources** | Passive data sources that provide read-only access to information for context, such as file contents, database schemas, or API documentation. | Retrieve documents<br />Access knowledge bases<br />Read calendars | Application |
| **Prompts** | Pre-built instruction templates that tell the model to work with specific tools and resources. | Plan a vacation<br />Summarize my meetings<br />Draft an email | User |
We will use a hypothetical scenario to demonstrate the role of each of these features, and show how they can work together.
### Tools
Tools enable AI models to perform actions. Each tool defines a specific operation with typed inputs and outputs. The model requests tool execution based on context.
#### How Tools Work
Tools are schema-defined interfaces that LLMs can invoke. MCP uses JSON Schema for validation. Each tool performs a single operation with clearly defined inputs and outputs. Tools may require user consent prior to execution, helping to ensure users maintain control over actions taken by a model.
**Protocol operations:**
| Method | Purpose | Returns |
| ------------ | ------------------------ | -------------------------------------- |
| `tools/list` | Discover available tools | Array of tool definitions with schemas |
| `tools/call` | Execute a specific tool | Tool execution result |
**Example tool definition:**
```typescript theme={null}
{
name: "searchFlights",
description: "Search for available flights",
inputSchema: {
type: "object",
properties: {
origin: { type: "string", description: "Departure city" },
destination: { type: "string", description: "Arrival city" },
date: { type: "string", format: "date", description: "Travel date" }
},
required: ["origin", "destination", "date"]
}
}
```
#### Example: Travel Booking
Tools enable AI applications to perform actions on behalf of users. In a travel planning scenario, the AI application might use several tools to help book a vacation:
**Flight Search**
```
searchFlights(origin: "NYC", destination: "Barcelona", date: "2024-06-15")
```
Queries multiple airlines and returns structured flight options.
**Calendar Blocking**
```
createCalendarEvent(title: "Barcelona Trip", startDate: "2024-06-15", endDate: "2024-06-22")
```
Marks the travel dates in the user's calendar.
**Email notification**
```
sendEmail(to: "[email protected]", subject: "Out of Office", body: "...")
```
Sends an automated out-of-office message to colleagues.
#### User Interaction Model
Tools are model-controlled, meaning AI models can discover and invoke them automatically. However, MCP emphasizes human oversight through several mechanisms.
For trust and safety, applications can implement user control through various mechanisms, such as:
* Displaying available tools in the UI, enabling users to define whether a tool should be made available in specific interactions
* Approval dialogs for individual tool executions
* Permission settings for pre-approving certain safe operations
* Activity logs that show all tool executions with their results
### Resources
Resources provide structured access to information that the AI application can retrieve and provide to models as context.
#### How Resources Work
Resources expose data from files, APIs, databases, or any other source that an AI needs to understand context. Applications can access this information directly and decide how to use it - whether that's selecting relevant portions, searching with embeddings, or passing it all to the model.
Each resource has a unique URI (e.g., `file:///path/to/document.md`) and declares its MIME type for appropriate content handling.
Resources support two discovery patterns:
* **Direct Resources** - fixed URIs that point to specific data. Example: `calendar://events/2024` - returns calendar availability for 2024
* **Resource Templates** - dynamic URIs with parameters for flexible queries. Example:
* `travel://activities/{city}/{category}` - returns activities by city and category
* `travel://activities/barcelona/museums` - returns all museums in Barcelona
Resource Templates include metadata such as title, description, and expected MIME type, making them discoverable and self-documenting.
**Protocol operations:**
| Method | Purpose | Returns |
| -------------------------- | ------------------------------- | -------------------------------------- |
| `resources/list` | List available direct resources | Array of resource descriptors |
| `resources/templates/list` | Discover resource templates | Array of resource template definitions |
| `resources/read` | Retrieve resource contents | Resource data with metadata |
| `resources/subscribe` | Monitor resource changes | Subscription confirmation |
#### Example: Getting Travel Planning Context
Continuing with the travel planning example, resources provide the AI application with access to relevant information:
* **Calendar data** (`calendar://events/2024`) - Checks user availability
* **Travel documents** (`file:///Documents/Travel/passport.pdf`) - Accesses important documents
* **Previous itineraries** (`trips://history/barcelona-2023`) - References past trips and preferences
The AI application retrieves these resources and decides how to process them, whether selecting a subset of data using embeddings or keyword search, or passing raw data directly to the model.
In this case, it provides calendar data, weather information, and travel preferences to the model, enabling it to check availability, look up weather patterns, and reference past travel preferences.
**Resource Template Examples:**
```json theme={null}
{
"uriTemplate": "weather://forecast/{city}/{date}",
"name": "weather-forecast",
"title": "Weather Forecast",
"description": "Get weather forecast for any city and date",
"mimeType": "application/json"
}
{
"uriTemplate": "travel://flights/{origin}/{destination}",
"name": "flight-search",
"title": "Flight Search",
"description": "Search available flights between cities",
"mimeType": "application/json"
}
```
These templates enable flexible queries. For weather data, users can access forecasts for any city/date combination. For flights, they can search routes between any two airports. When a user has input "NYC" as the `origin` airport and begins to input "Bar" as the `destination` airport, the system can suggest "Barcelona (BCN)" or "Barbados (BGI)".
#### Parameter Completion
Dynamic resources support parameter completion. For example:
* Typing "Par" as input for `weather://forecast/{city}` might suggest "Paris" or "Park City"
* Typing "JFK" for `flights://search/{airport}` might suggest "JFK - John F. Kennedy International"
The system helps discover valid values without requiring exact format knowledge.
#### User Interaction Model
Resources are application-driven, giving them flexibility in how they retrieve, process, and present available context. Common interaction patterns include:
* Tree or list views for browsing resources in familiar folder-like structures
* Search and filter interfaces for finding specific resources
* Automatic context inclusion or smart suggestions based on heuristics or AI selection
* Manual or bulk selection interfaces for including single or multiple resources
Applications are free to implement resource discovery through any interface pattern that suits their needs. The protocol doesn't mandate specific UI patterns, allowing for resource pickers with preview capabilities, smart suggestions based on current conversation context, bulk selection for including multiple resources, or integration with existing file browsers and data explorers.
### Prompts
Prompts provide reusable templates. They allow MCP server authors to provide parameterized prompts for a domain, or showcase how to best use the MCP server.
#### How Prompts Work
Prompts are structured templates that define expected inputs and interaction patterns. They are user-controlled, requiring explicit invocation rather than automatic triggering. Prompts can be context-aware, referencing available resources and tools to create comprehensive workflows. Similar to resources, prompts support parameter completion to help users discover valid argument values.
**Protocol operations:**
| Method | Purpose | Returns |
| -------------- | -------------------------- | ------------------------------------- |
| `prompts/list` | Discover available prompts | Array of prompt descriptors |
| `prompts/get` | Retrieve prompt details | Full prompt definition with arguments |
#### Example: Streamlined Workflows
Prompts provide structured templates for common tasks. In the travel planning context:
**"Plan a vacation" prompt:**
```json theme={null}
{
"name": "plan-vacation",
"title": "Plan a vacation",
"description": "Guide through vacation planning process",
"arguments": [
{ "name": "destination", "type": "string", "required": true },
{ "name": "duration", "type": "number", "description": "days" },
{ "name": "budget", "type": "number", "required": false },
{ "name": "interests", "type": "array", "items": { "type": "string" } }
]
}
```
Rather than unstructured natural language input, the prompt system enables:
1. Selection of the "Plan a vacation" template
2. Structured input: Barcelona, 7 days, \$3000, \["beaches", "architecture", "food"]
3. Consistent workflow execution based on the template
#### User Interaction Model
Prompts are user-controlled, requiring explicit invocation. The protocol gives implementers freedom to design interfaces that feel natural within their application. Key principles include:
* Easy discovery of available prompts
* Clear descriptions of what each prompt does
* Natural argument input with validation
* Transparent display of the prompt's underlying template
Applications typically expose prompts through various UI patterns such as:
* Slash commands (typing "/" to see available prompts like /plan-vacation)
* Command palettes for searchable access
* Dedicated UI buttons for frequently used prompts
* Context menus that suggest relevant prompts
## Bringing Servers Together
The real power of MCP emerges when multiple servers work together, combining their specialized capabilities through a unified interface.
### Example: Multi-Server Travel Planning
Consider a personalized AI travel planner application, with three connected servers:
* **Travel Server** - Handles flights, hotels, and itineraries
* **Weather Server** - Provides climate data and forecasts
* **Calendar/Email Server** - Manages schedules and communications
#### The Complete Flow
1. **User invokes a prompt with parameters:**
```json theme={null}
{
"prompt": "plan-vacation",
"arguments": {
"destination": "Barcelona",
"departure_date": "2024-06-15",
"return_date": "2024-06-22",
"budget": 3000,
"travelers": 2
}
}
```
2. **User selects resources to include:**
* `calendar://my-calendar/June-2024` (from Calendar Server)
* `travel://preferences/europe` (from Travel Server)
* `travel://past-trips/Spain-2023` (from Travel Server)
3. **AI processes the request using tools:**
The AI first reads all selected resources to gather context - identifying available dates from the calendar, learning preferred airlines and hotel types from travel preferences, and discovering previously enjoyed locations from past trips.
Using this context, the AI then executes the prompt provided by the AI application. In our example, the AI application exposes the weather tools from the connected MCP weather server to the model. Because weather can affect travel plans, the AI chooses to call `checkWeather()` when interpreting the prompt.
As a result the AI executes a series of tools:
* `searchFlights()` - Queries airlines for NYC to Barcelona flights
* `checkWeather()` - Retrieves climate forecasts for travel dates
The AI then uses this information to create the booking and following steps, requesting approval from the user where necessary:
* `bookHotel()` - Finds hotels within the specified budget
* `createCalendarEvent()` - Adds the trip to the user's calendar
* `sendEmail()` - Sends confirmation with trip details
**The result:** Through multiple MCP servers, the user researched and booked a Barcelona trip tailored to their schedule. The "Plan a Vacation" prompt guided the AI to combine Resources (calendar availability and travel history) with Tools (searching flights, booking hotels, updating calendars) across different servers—gathering context and executing the booking. A task that could have taken hours was completed in minutes using MCP.
docs/2024-11-05/learn/versioning New page · 45 lines, new page
# Versioning ## Revisions ## Feature States ## Negotiation
A whole new page. There's nothing to diff it against, so here is what it says.
# Versioning The Model Context Protocol uses string-based version identifiers following the format `YYYY-MM-DD`, to indicate the last date backwards incompatible changes were made. <Info> The protocol version will *not* be incremented when the protocol is updated, as long as the changes maintain backwards compatibility. This allows for incremental improvements while preserving interoperability. </Info> ## Revisions Revisions may be marked as: * **Draft**: in-progress specifications, not yet ready for consumption. * **Current**: the current protocol version, which is ready for use and may continue to receive backwards compatible changes. * **Final**: past, complete specifications that will not be changed. The **current** protocol version is [**2025-11-25**](/specification/2025-11-25/). ## Feature States Individual features of the specification may additionally be marked as **Deprecated** under the [feature lifecycle and deprecation policy](/community/feature-lifecycle): the feature remains part of the specification, but is scheduled for removal. Deprecated features document a migration path (or state that none is required) and remain in the specification for at least twelve months, or at least ninety days under the policy's [expedited-removal exception](/community/feature-lifecycle#expedited-removal), before they become eligible for removal, after which they may be **Removed** in a future revision. ## Negotiation Version negotiation happens during [initialization](/specification/2024-11-05/basic/lifecycle#initialization). Clients and servers **MAY** support multiple protocol versions simultaneously, but they **MUST** agree on a single version to use for the session. The protocol provides appropriate error handling if version negotiation fails, allowing clients to gracefully terminate connections when they cannot find a version compatible with the server.
docs/2024-11-05/sdk New page · 47 lines, new page
# SDKs ## Available SDKs ## Getting Started ## Next Steps
A whole new page. There's nothing to diff it against, so here is what it says.
# SDKs
> Official SDKs for building with Model Context Protocol
Build MCP servers and clients using our official SDKs. SDKs are classified into tiers based on feature completeness, protocol support, and maintenance commitment. Learn more about [SDK tiers](/community/sdk-tiers).
## Available SDKs
| SDK | Repository | Tier |
| :----------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------- | ------------------------------------------------: |
| <Icon icon="square-js" size={24} /> [TypeScript](https://ts.sdk.modelcontextprotocol.io) | [modelcontextprotocol/typescript-sdk](https://github.com/modelcontextprotocol/typescript-sdk) | <Badge color="blue" shape="pill">Tier 1</Badge> |
| <Icon icon="python" size={24} /> [Python](https://py.sdk.modelcontextprotocol.io) | [modelcontextprotocol/python-sdk](https://github.com/modelcontextprotocol/python-sdk) | <Badge color="blue" shape="pill">Tier 1</Badge> |
| <Icon icon="square-c" size={24} /> [C#](https://csharp.sdk.modelcontextprotocol.io) | [modelcontextprotocol/csharp-sdk](https://github.com/modelcontextprotocol/csharp-sdk) | <Badge color="blue" shape="pill">Tier 1</Badge> |
| <Icon icon="golang" size={24} /> [Go](https://go.sdk.modelcontextprotocol.io) | [modelcontextprotocol/go-sdk](https://github.com/modelcontextprotocol/go-sdk) | <Badge color="blue" shape="pill">Tier 1</Badge> |
| <Icon icon="java" size={24} /> [Java](https://java.sdk.modelcontextprotocol.io) | [modelcontextprotocol/java-sdk](https://github.com/modelcontextprotocol/java-sdk) | <Badge color="purple" shape="pill">Tier 2</Badge> |
| <Icon icon="rust" size={24} /> [Rust](https://rust.sdk.modelcontextprotocol.io) | [modelcontextprotocol/rust-sdk](https://github.com/modelcontextprotocol/rust-sdk) | <Badge color="purple" shape="pill">Tier 2</Badge> |
| <Icon icon="swift" size={24} /> Swift | [modelcontextprotocol/swift-sdk](https://github.com/modelcontextprotocol/swift-sdk) | <Badge color="orange" shape="pill">Tier 3</Badge> |
| <Icon icon="gem" size={24} /> [Ruby](https://ruby.sdk.modelcontextprotocol.io) | [modelcontextprotocol/ruby-sdk](https://github.com/modelcontextprotocol/ruby-sdk) | <Badge color="orange" shape="pill">Tier 3</Badge> |
| <Icon icon="php" size={24} /> [PHP](https://php.sdk.modelcontextprotocol.io) | [modelcontextprotocol/php-sdk](https://github.com/modelcontextprotocol/php-sdk) | <Badge color="orange" shape="pill">Tier 3</Badge> |
| <Icon icon="square-k" size={24} /> [Kotlin](https://kotlin.sdk.modelcontextprotocol.io) | [modelcontextprotocol/kotlin-sdk](https://github.com/modelcontextprotocol/kotlin-sdk) | <Badge color="orange" shape="pill">Tier 3</Badge> |
See [SDK Tiering System](/community/sdk-tiers) for details on what each tier means.
## Getting Started
Each SDK provides the same functionality but follows the idioms and best practices of its language. All SDKs support:
* Creating MCP servers that expose tools, resources, and prompts
* Building MCP clients that can connect to any MCP server
* Local and remote transport protocols
* Protocol compliance with type safety
Visit the SDK page for your chosen language to find installation instructions, documentation, and examples.
## Next Steps
Ready to start building with MCP? Choose your path:
<CardGroup cols={2}>
<Card title="Build a Server" icon="server" href="/docs/2024-11-05/develop/build-server">
Learn how to create your first MCP server
</Card>
<Card title="Build a Client" icon="computer" href="/docs/2024-11-05/develop/build-client">
Create applications that connect to MCP servers
</Card>
</CardGroup>
docs/2024-11-05/tools/debugging New page · 345 lines, new page
# Debugging ## Debugging tools overview ## Implementing logging ### Server-side logging ## Common issues ### Working directory ### Environment variables ### Server initialization ### Connection problems ## Debugging in Claude Desktop ### Checking server status ### Viewing logs ### Using Chrome DevTools ## Debugging workflow ### Development cycle ### Testing changes ## Best practices ### Logging strategy ### Security considerations ## Getting help ## Next steps
A whole new page. There's nothing to diff it against, so here is what it says.
# Debugging
> A comprehensive guide to debugging Model Context Protocol (MCP) integrations
Effective debugging is essential when developing MCP servers or integrating
them with applications. This guide covers the debugging tools and approaches
available in the MCP ecosystem.
## Debugging tools overview
MCP provides several tools for debugging at different levels:
1. **[MCP Inspector](/docs/2024-11-05/tools/inspector)**: interactive, transport-agnostic
testing UI. Connect to stdio or HTTP with SSE servers, invoke
[tools](/specification/2024-11-05/server/tools),
[prompts](/specification/2024-11-05/server/prompts), and
[resources](/specification/2024-11-05/server/resources), and watch the
notification stream. This should be your first stop.
2. **Server logging**: structured logs to stderr (stdio transport) or via
[`notifications/message`](/specification/2024-11-05/server/utilities/logging#log-message-notifications)
(all transports).
3. **Client developer tools**: most MCP clients expose logs and connection
state. See [Debugging in Claude Desktop](#debugging-in-claude-desktop)
below for one example, or consult your client's documentation.
## Implementing logging
### Server-side logging
When building a server that uses the local
[stdio transport](/specification/2024-11-05/basic/transports#stdio), all messages
logged to stderr (standard error) will be captured by the host application
automatically.
<Warning>
Local MCP servers should not log messages to stdout (standard out), as this
will interfere with protocol operation.
</Warning>
For servers using the
[HTTP with SSE transport](/specification/2024-11-05/basic/transports#http-with-sse),
stderr is not captured by the client. Use the log message notifications below,
your own server-side log aggregation, or standard HTTP tooling (curl, browser
DevTools Network panel) to inspect requests and SSE streams.
For all [transports](/specification/2024-11-05/basic/transports), you can also
provide logging to the client by sending a log message notification:
<CodeGroup>
```python Python theme={null}
@server.tool()
async def my_tool(ctx: Context) -> str:
await ctx.session.send_log_message(
level="info",
data="Server started successfully",
)
return "done"
```
```typescript TypeScript theme={null}
await server.sendLoggingMessage({
level: "info",
data: "Server started successfully",
});
```
</CodeGroup>
MCP defines eight
[RFC 5424 severity levels](/specification/2024-11-05/server/utilities/logging#log-levels)
(`debug` through `emergency`). Clients can adjust the minimum level at runtime
via the
[`logging/setLevel`](/specification/2024-11-05/server/utilities/logging#setting-log-level)
request.
Important events to log:
* Initialization steps
* Resource access
* Tool execution
* Error conditions
* Performance metrics
## Common issues
The examples below use Claude Desktop's
[`claude_desktop_config.json`](/docs/2024-11-05/develop/connect-local-servers); the same
principles apply to any stdio-based MCP client.
### Working directory
When an MCP client launches a stdio server:
* The working directory for servers launched via the client's config may be
undefined (like `/` on macOS) since the client could be started from
anywhere
* Always use absolute paths in your configuration and `.env` files to ensure
reliable operation
* For testing servers directly via command line, the working directory will be
where you run the command
For example in `claude_desktop_config.json`, use:
```json theme={null}
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"/Users/username/data"
]
}
}
}
```
Instead of relative paths like `./data`
### Environment variables
MCP servers launched over stdio inherit only a limited subset of environment
variables automatically (the exact set is platform-dependent).
To override the default variables or provide your own, you can specify an
`env` key in `claude_desktop_config.json`:
```json theme={null}
{
"mcpServers": {
"myserver": {
"command": "mcp-server-myapp",
"env": {
"MYAPP_API_KEY": "some_key"
}
}
}
}
```
### Server initialization
Common initialization problems:
1. **Path Issues**
* Incorrect server executable path
* Missing required files
* Permission problems
* Try using an absolute path for `command`
2. **Configuration Errors**
* Invalid JSON syntax
* Missing required fields
* Type mismatches
3. **Environment Problems**
* Missing environment variables
* Incorrect variable values
* Permission restrictions
### Connection problems
When servers fail to connect:
1. Check client logs
2. Verify server process is running
3. Test standalone with [Inspector](/docs/2024-11-05/tools/inspector)
4. Verify
[protocol compatibility](/specification/2024-11-05/basic/lifecycle#version-negotiation)
5. Check
[capability negotiation](/specification/2024-11-05/basic/lifecycle#capability-negotiation):
error [`-32602`](/specification/2024-11-05/basic/lifecycle#error-handling) is
the standard JSON-RPC "Invalid params" code and is returned in many
contexts. One common cause is a server sending
[sampling](/specification/2024-11-05/client/sampling) requests to a
client that hasn't declared that capability. Inspect the
[`initialize` exchange](/specification/2024-11-05/basic/lifecycle#initialization)
to verify both sides declared what you expect
## Debugging in Claude Desktop
Claude Desktop is one of many MCP clients. It is available on
macOS and Windows.
### Checking server status
Click the "Add files, connectors, and more" plus icon in the chat input, then
hover over the **Connectors** menu to see connected servers and available
tools.
<img src="https://mintcdn.com/mcp/zNouQwo2h8cbxlDS/images/available-mcp-tools.png?fit=max&auto=format&n=zNouQwo2h8cbxlDS&q=85&s=e2ace1ac88895a5fe30ebd8d01456bc3" alt="Available MCP tools" width="437" height="244" data-path="images/available-mcp-tools.png" />
### Viewing logs
Log files are written to:
* macOS: `~/Library/Logs/Claude`
* Windows: `%APPDATA%\Claude\logs`
<CodeGroup>
```bash macOS theme={null}
tail -n 20 -F ~/Library/Logs/Claude/mcp*.log
```
```powershell Windows theme={null}
type "$env:AppData\Claude\logs\mcp*.log"
```
</CodeGroup>
The logs capture:
* Server connection events
* Configuration issues
* Runtime errors
* Message exchanges
### Using Chrome DevTools
Access Chrome's developer tools inside Claude Desktop to investigate
client-side errors:
1. Create a `developer_settings.json` file with `allowDevTools` set to true:
<CodeGroup>
```bash macOS theme={null}
echo '{"allowDevTools": true}' > ~/Library/Application\ Support/Claude/developer_settings.json
```
```powershell Windows theme={null}
'{"allowDevTools": true}' | Set-Content "$env:AppData\Claude\developer_settings.json"
```
</CodeGroup>
2. Open DevTools: `Command-Option-I` (macOS) or `Ctrl+Alt+I` (Windows)
Note: You'll see two DevTools windows:
* Main content window
* App title bar window
Use the Console panel to inspect client-side errors.
Use the Network panel to inspect:
* Message payloads
* Connection timing
## Debugging workflow
### Development cycle
1. Initial Development
* Use [Inspector](/docs/2024-11-05/tools/inspector) for basic testing
* Implement core functionality
* Add logging points
2. Integration Testing
* Test in your target MCP client
* Monitor logs
* Check error handling
### Testing changes
To test changes efficiently:
* **Configuration changes**: Restart the MCP client
* **Server code changes**: Restart the client (for Claude Desktop, fully quit
and reopen; closing the window is not enough)
* **Quick iteration**: Use [Inspector](/docs/2024-11-05/tools/inspector) during
development
## Best practices
### Logging strategy
1. **Structured Logging**
* Use consistent formats
* Include context
* Add timestamps
* Track request IDs
2. **Error Handling**
* Log stack traces
* Include error context
* Track error patterns
* Monitor recovery
3. **Performance Tracking**
* Log operation timing
* Monitor resource usage
* Track message sizes
* Measure latency
### Security considerations
When debugging:
1. **Sensitive Data**
* Sanitize logs
* Protect credentials
Cut at 300 lines. The page has the rest.
docs/2024-11-05/tools/inspector New page · 140 lines, new page
# MCP Inspector ## Getting started ### Installation and basic usage #### Inspecting servers from npm or PyPI #### Inspecting locally developed servers ## Feature overview ### Server connection pane ### Resources tab ### Prompts tab ### Tools tab ### Notifications pane ## Best practices ### Development workflow ## Next steps
A whole new page. There's nothing to diff it against, so here is what it says.
# MCP Inspector
> In-depth guide to using the MCP Inspector for testing and debugging Model Context Protocol servers
The [MCP Inspector](https://github.com/modelcontextprotocol/inspector) is an interactive developer tool for testing and debugging MCP servers. While the [Debugging Guide](/docs/2024-11-05/tools/debugging) covers the Inspector as part of the overall debugging toolkit, this document provides a detailed exploration of the Inspector's features and capabilities.
## Getting started
### Installation and basic usage
The Inspector runs directly through `npx` without requiring installation:
```bash theme={null}
npx @modelcontextprotocol/inspector <command>
```
```bash theme={null}
npx @modelcontextprotocol/inspector <command> <arg1> <arg2>
```
#### Inspecting servers from npm or PyPI
A common way to start server packages from [npm](https://npmjs.com) or [PyPI](https://pypi.org).
<Tabs>
<Tab title="npm package">
```bash theme={null}
npx -y @modelcontextprotocol/inspector npx <package-name> <args>
# For example
npx -y @modelcontextprotocol/inspector npx @modelcontextprotocol/server-filesystem /Users/username/Desktop
```
</Tab>
<Tab title="PyPI package">
```bash theme={null}
npx @modelcontextprotocol/inspector uvx <package-name> <args>
# For example
npx @modelcontextprotocol/inspector uvx mcp-server-git --repository ~/code/mcp/servers.git
```
</Tab>
</Tabs>
#### Inspecting locally developed servers
To inspect servers locally developed or downloaded as a repository, the most common
way is:
<Tabs>
<Tab title="TypeScript">
```bash theme={null}
npx @modelcontextprotocol/inspector node path/to/server/index.js args...
```
</Tab>
<Tab title="Python">
```bash theme={null}
npx @modelcontextprotocol/inspector \
uv \
--directory path/to/server \
run \
package-name \
args...
```
</Tab>
</Tabs>
Please carefully read any attached README for the most accurate instructions.
## Feature overview
<Frame caption="The MCP Inspector interface">
<img src="https://mintcdn.com/mcp/4ZXF1PrDkEaJvXpn/images/mcp-inspector.png?fit=max&auto=format&n=4ZXF1PrDkEaJvXpn&q=85&s=83b12e2a457c96ef4ad17c7357236290" width="2888" height="1761" data-path="images/mcp-inspector.png" />
</Frame>
The Inspector provides several features for interacting with your MCP server:
### Server connection pane
* Allows selecting the [transport](/specification/2024-11-05/basic/transports) for connecting to the server
* For local servers, supports customizing the command-line arguments and environment
### Resources tab
* Lists all available resources
* Shows resource metadata (MIME types, descriptions)
* Allows resource content inspection
* Supports subscription testing
### Prompts tab
* Displays available prompt templates
* Shows prompt arguments and descriptions
* Enables prompt testing with custom arguments
* Previews generated messages
### Tools tab
* Lists available tools
* Shows tool schemas and descriptions
* Enables tool testing with custom inputs
* Displays tool execution results
### Notifications pane
* Presents all logs recorded from the server
* Shows notifications received from the server
## Best practices
### Development workflow
1. Start Development
* Launch Inspector with your server
* Verify basic connectivity
* Check capability negotiation
2. Iterative testing
* Make server changes
* Rebuild the server
* Reconnect the Inspector
* Test affected features
* Monitor messages
3. Test edge cases
* Invalid inputs
* Missing prompt arguments
* Concurrent operations
* Verify error handling and error responses
## Next steps
<CardGroup cols={2}>
<Card title="Inspector Repository" icon="github" href="https://github.com/modelcontextprotocol/inspector">
Check out the MCP Inspector source code
</Card>
<Card title="Debugging Guide" icon="bug" href="/docs/2024-11-05/tools/debugging">
Learn about broader debugging strategies
</Card>
</CardGroup>
docs/2024-11-05/tutorials/security/authorization New page · 1057 lines, new page
# Understanding Authorization in MCP ## When Should You Use Authorization? ## The Authorization Flow: Step by Step ## Implementation Example ### Keycloak Setup ### MCP Server Setup ## Testing the MCP Server ## Common Pitfalls and How to Avoid Them ## Related Standards and Documentation
A whole new page. There's nothing to diff it against, so here is what it says.
# Understanding Authorization in MCP
> Learn how to implement secure authorization for MCP servers using OAuth 2.1 to protect sensitive resources and operations
Authorization in the Model Context Protocol (MCP) secures access to sensitive resources and operations exposed by MCP servers. If your MCP server handles user data or administrative actions, authorization ensures only permitted users can access its endpoints.
MCP uses standardized authorization flows to build trust between MCP clients and MCP servers. Its design doesn't focus on one specific authorization or identity system, but rather follows the conventions outlined for [OAuth 2.1](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-13). For detailed information, see the [Authorization specification](/specification/2025-03-26/basic/authorization).
## When Should You Use Authorization?
While authorization for MCP servers is **optional**, it is strongly recommended when:
* Your server accesses user-specific data (emails, documents, databases)
* You need to audit who performed which actions
* Your server grants access to its APIs that require user consent
* You're building for enterprise environments with strict access controls
* You want to implement rate limiting or usage tracking per user
<Tip>
**Authorization for Local MCP Servers**
For MCP servers using the [STDIO transport](/specification/2024-11-05/basic/transports#stdio), you can use environment-based credentials or credentials provided by third-party libraries embedded directly in the MCP server instead. Because a STDIO-built MCP server runs locally, it has access to a range of flexible options when it comes to acquiring user credentials that may or may not rely on in-browser authentication and authorization flows.
OAuth flows, in turn, are designed for HTTP-based transports where the MCP server is remotely-hosted and the client uses OAuth to establish that a user is authorized to access said remote server.
</Tip>
## The Authorization Flow: Step by Step
Let's walk through what happens when a client wants to connect to your protected MCP server:
<Steps>
<Step title="Initial Handshake">
When your MCP client first tries to connect, your server responds with a `401 Unauthorized` and tells the client where to find authorization information, captured in a [Protected Resource Metadata (PRM) document](https://datatracker.ietf.org/doc/html/rfc9728). The document is hosted by the MCP server, follows a predictable path pattern, and is provided to the client in the `resource_metadata` parameter within the `WWW-Authenticate` header.
```http theme={null}
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="mcp",
resource_metadata="https://your-server.com/.well-known/oauth-protected-resource"
```
This tells the client that authorization is required for the MCP server and where to get the necessary information to kickstart the authorization flow.
</Step>
<Step title="Protected Resource Metadata Discovery">
With the URI pointer to the PRM document, the client will fetch the metadata to learn about the authorization server, supported scopes, and other resource information. The data is typically encapsulated in a JSON blob, similar to the one below.
```json theme={null}
{
"resource": "https://your-server.com/mcp",
"authorization_servers": ["https://auth.your-server.com"],
"scopes_supported": ["mcp:tools", "mcp:resources"]
}
```
You can see a more comprehensive example in [RFC 9728 Section 3.2](https://datatracker.ietf.org/doc/html/rfc9728#name-protected-resource-metadata-r).
</Step>
<Step title="Authorization Server Discovery">
Next, the client discovers what the authorization server can do by fetching its metadata. If the PRM document lists more than one authorization server, the client can decide which one to use.
With an authorization server selected, the client will then construct a standard metadata URI and issue a request to the [OpenID Connect (OIDC) Discovery](https://openid.net/specs/openid-connect-discovery-1_0.html) or [OAuth 2.0 Auth Server Metadata](https://datatracker.ietf.org/doc/html/rfc8414) endpoints (depending on authorization server support)
and retrieve another set of metadata properties that will allow it to know the endpoints it needs to complete the authorization flow.
```json theme={null}
{
"issuer": "https://auth.your-server.com",
"authorization_endpoint": "https://auth.your-server.com/authorize",
"token_endpoint": "https://auth.your-server.com/token",
"registration_endpoint": "https://auth.your-server.com/register"
}
```
</Step>
<Step title="Client Registration">
With all the metadata out of the way, the client now needs to make sure that it's registered with the authorization server. This can be done in two ways.
First, the client can be **pre-registered** with a given authorization server, in which case it can have embedded client registration information that it uses to complete the authorization flow.
Alternatively, the client can use **Dynamic Client Registration** (DCR) to dynamically register itself with the authorization server. The latter scenario requires the authorization server to support DCR. If the authorization server does support DCR, the client will send a request to the `registration_endpoint` with its information:
```json theme={null}
{
"client_name": "My MCP Client",
"redirect_uris": ["http://localhost:3000/callback"],
"grant_types": ["authorization_code", "refresh_token"],
"response_types": ["code"]
}
```
If the registration succeeds, the authorization server will return a JSON blob with client registration information.
<Tip>
**No DCR or Pre-Registration**
In case an MCP client connects to an MCP server that doesn't use an authorization server that supports DCR and the client is not pre-registered with said authorization server, it's the responsibility of the client developer to provide an affordance for the end-user to enter client information manually.
</Tip>
</Step>
<Step title="User Authorization">
The client will now need to open a browser to the `/authorize` endpoint, where the user can log in and grant the required permissions. The authorization server will then redirect back to the client with an authorization code that the client exchanges for tokens:
```json theme={null}
{
"access_token": "eyJhbGciOiJSUzI1NiIs...",
"refresh_token": "def502...",
"token_type": "Bearer",
"expires_in": 3600
}
```
The access token is what the client will use to authenticate requests to the MCP server. This step follows standard [OAuth 2.1 authorization code with PKCE](https://oauth.net/2/grant-types/authorization-code/) conventions.
</Step>
<Step title="Making Authenticated Requests">
Finally, the client can make requests to your MCP server using the access token embedded in the `Authorization` header:
```http theme={null}
GET /mcp HTTP/1.1
Host: your-server.com
Authorization: Bearer eyJhbGciOiJSUzI1NiIs...
```
The MCP server will need to validate the token and process the request if the token is valid and has the required permissions.
</Step>
</Steps>
## Implementation Example
To get started with a practical implementation, we will use a [Keycloak](https://www.keycloak.org/) authorization server hosted in a Docker container. Keycloak is an open-source authorization server that can be easily deployed locally for testing and experimentation.
Make sure that you download and install [Docker Desktop](https://www.docker.com/products/docker-desktop/). We will need it to deploy Keycloak on our development machine.
### Keycloak Setup
From your terminal application, run the following command to start the Keycloak container:
```bash theme={null}
docker run -p 127.0.0.1:8080:8080 -e KC_BOOTSTRAP_ADMIN_USERNAME=admin -e KC_BOOTSTRAP_ADMIN_PASSWORD=admin quay.io/keycloak/keycloak start-dev
```
This command will pull the Keycloak container image locally and bootstrap the basic configuration. It will run on port `8080` and have an `admin` user with `admin` password.
<Warning>
**Not for Production**
The configuration above may be suitable for testing and experimentation; however, you should never use it in production. Refer to the [Configuring Keycloak for production](https://www.keycloak.org/server/configuration-production) guide for additional details on how to deploy the authorization server for scenarios that require reliability, security, and high availability.
</Warning>
You will be able to access the Keycloak authorization server from your browser at `http://localhost:8080`.
<Frame>
<img src="https://mintcdn.com/mcp/sAd4SGUO-cEUqgzn/images/tutorial-authorization/keycloak-browser.png?fit=max&auto=format&n=sAd4SGUO-cEUqgzn&q=85&s=cba689d986e113cbe937d732ac0558b6" alt="Keycloak admin dashboard authentication dialog." width="1834" height="1450" data-path="images/tutorial-authorization/keycloak-browser.png" />
</Frame>
When running with the default configuration, Keycloak will already support many of the capabilities that we need for MCP servers, including Dynamic Client Registration. You can check this by looking at the OIDC configuration, available at:
```http theme={null}
http://localhost:8080/realms/master/.well-known/openid-configuration
```
We will also need to set up Keycloak to support our scopes and allow our host (local machine) to dynamically register clients, as the default policies restrict anonymous dynamic client registration.
Go to **Client scopes** in the Keycloak dashboard and create a new `mcp:tools` scope. We will use this to access all of the tools on our MCP server.
<Frame>
<img src="https://mintcdn.com/mcp/sAd4SGUO-cEUqgzn/images/tutorial-authorization/keycloak-scopes.png?fit=max&auto=format&n=sAd4SGUO-cEUqgzn&q=85&s=3cd49dc2e070027609ae495751e0db58" alt="Configuring Keycloak scopes." width="1999" height="1710" data-path="images/tutorial-authorization/keycloak-scopes.png" />
</Frame>
After creating the scope, make sure that you assign its type to **Default** and have flipped the **Include in token scope** switch, as this will be needed for token validation.
Let's now also set up an **audience** for our Keycloak-issued tokens. An audience is important to configure because it embeds the intended destination directly into the issued access token. This helps your MCP server to verify that the token it got was actually meant for it rather than some other API. This is key to help avoid token passthrough scenarios.
To do this, open your `mcp:tools` client scope and click on **Mappers**, followed by **Configure a new mapper**. Select **Audience**.
<Frame>
<img src="https://mintcdn.com/mcp/sAd4SGUO-cEUqgzn/images/tutorial-authorization/scope-add-audience.gif?s=6ea9cf20c397f4c79c491c2e39019272" alt="Configuring an audience for a token in Keycloak." width="1080" height="921" data-path="images/tutorial-authorization/scope-add-audience.gif" />
</Frame>
For **Name**, use `audience-config`. Add a value for **Included Custom Audience**, set to `http://localhost:3000`. This will be the URI of our test server.
<Warning>
**Not for Production**
The audience configuration above is meant for testing. For production scenarios, additional set-up and configuration will be required to ensure that audiences are properly constrained for issued tokens. Specifically, the audience needs to be based on the resource parameter passed from the client, not a fixed value.
</Warning>
Now, navigate to **Clients**, then **Client registration**, and then **Trusted Hosts**. Disable the **Client URIs Must Match** setting and add the hosts from which you're testing. You can get your current host IP by running the `ifconfig` command on Linux or macOS, or `ipconfig` on Windows. You can see the IP address you need to add by looking at the keycloak logs for a line that looks like `Failed to verify remote host : 192.168.215.1`. Check that the IP address is associated with your host. This may be for a bridge network depending on your docker setup.
<Frame>
<img src="https://mintcdn.com/mcp/sAd4SGUO-cEUqgzn/images/tutorial-authorization/keycloak-client.gif?s=b5d40b36a5f1ea1e818821bb8ea77f6b" alt="Setting up client registration details in Keycloak." width="1199" height="1027" data-path="images/tutorial-authorization/keycloak-client.gif" />
</Frame>
<Warning>
**Getting the Host**
If you are running Keycloak from a container, you will also be able to see the host IP from the Terminal in the container logs.
</Warning>
Lastly, we need to register a new client that we can use with the **MCP server itself** to talk to Keycloak for things like [token introspection](https://oauth.net/2/token-introspection/). To do that:
1. Go to **Clients**.
2. Click **Create client**.
3. Give your client a unique **Client ID** and click **Next**.
4. Enable **Client authentication** and click **Next**.
5. Click **Save**.
Worth noting that token introspection is just *one of* the available approaches to validate tokens. This can also be done with the help of standalone libraries, specific to each language and platform.
When you open the client details, go to **Credentials** and take note of the **Client Secret**.
<Frame>
<img src="https://mintcdn.com/mcp/sAd4SGUO-cEUqgzn/images/tutorial-authorization/keycloak-client-auth.gif?s=7152c41a5746994fd399024bc4659e40" alt="Creating a new client in Keycloak." width="1200" height="1023" data-path="images/tutorial-authorization/keycloak-client-auth.gif" />
</Frame>
<Warning>
**Handling Secrets**
Never embed client credentials directly in your code. We recommend using environment variables or specialized solutions for secret storage.
</Warning>
With Keycloak configured, every time the authorization flow is triggered, your MCP server will receive a token like this:
```text theme={null}
eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI1TjcxMGw1WW5MWk13WGZ1VlJKWGtCS3ZZMzZzb3JnRG5scmlyZ2tlTHlzIn0.eyJleHAiOjE3NTU1NDA4MTcsImlhdCI6MTc1NTU0MDc1NywiYXV0aF90aW1lIjoxNzU1NTM4ODg4LCJqdGkiOiJvbnJ0YWM6YjM0MDgwZmYtODQwNC02ODY3LTgxYmUtMTIzMWI1MDU5M2E4IiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4MDgwL3JlYWxtcy9tYXN0ZXIiLCJhdWQiOiJodHRwOi8vbG9jYWxob3N0OjMwMDAiLCJzdWIiOiIzM2VkNmM2Yi1jNmUwLTQ5MjgtYTE2MS1mMmY2OWM3YTAzYjkiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiI3OTc1YTViNi04YjU5LTRhODUtOWNiYS04ZmFlYmRhYjg5NzQiLCJzaWQiOiI4ZjdlYzI3Ni0zNThmLTRjY2MtYjMxMy1kYjA4MjkwZjM3NmYiLCJzY29wZSI6Im1jcDp0b29scyJ9.P5xCRtXORly0R0EXjyqRCUx-z3J4uAOWNAvYtLPXroykZuVCCJ-K1haiQSwbURqfsVOMbL7jiV-sD6miuPzI1tmKOkN_Yct0Vp-azvj7U5rEj7U6tvPfMkg2Uj_jrIX0KOskyU2pVvGZ-5BgqaSvwTEdsGu_V3_E0xDuSBq2uj_wmhqiyTFm5lJ1WkM3Hnxxx1_AAnTj7iOKMFZ4VCwMmk8hhSC7clnDauORc0sutxiJuYUZzxNiNPkmNeQtMCGqWdP1igcbWbrfnNXhJ6NswBOuRbh97_QraET3hl-CNmyS6C72Xc0aOwR_uJ7xVSBTD02OaQ1JA6kjCATz30kGYg
```
Decoded, it will look like this:
```json theme={null}
{
"alg": "RS256",
"typ": "JWT",
"kid": "5N710l5YnLZMwXfuVRJXkBKvY36sorgDnlrirgkeLys"
}.{
"exp": 1755540817,
"iat": 1755540757,
"auth_time": 1755538888,
"jti": "onrtac:b34080ff-8404-6867-81be-1231b50593a8",
"iss": "http://localhost:8080/realms/master",
"aud": "http://localhost:3000",
"sub": "33ed6c6b-c6e0-4928-a161-f2f69c7a03b9",
"typ": "Bearer",
"azp": "7975a5b6-8b59-4a85-9cba-8faebdab8974",
"sid": "8f7ec276-358f-4ccc-b313-db08290f376f",
"scope": "mcp:tools"
}.[Signature]
```
<Warning>
**Embedded Audience**
Notice the `aud` claim embedded in the token - it's currently set to be the URI of the test MCP server and it's inferred from the scope that we've previously configured. This will be important in our implementation to validate.
</Warning>
### MCP Server Setup
We will now set up our MCP server to use the locally-running Keycloak authorization server. Depending on your programming language preference, you can use one of the supported [MCP SDKs](/docs/2024-11-05/sdk).
For our testing purposes, we will create an extremely simple MCP server that exposes two tools - one for addition and another for multiplication. The server will require authorization to access these.
<Tabs>
<Tab title="TypeScript">
You can see the complete TypeScript project in the [sample repository](https://github.com/localden/min-ts-mcp-auth).
Prior to running the code below, ensure that you have a `.env` file with the following content:
```env theme={null}
# Server host/port
HOST=localhost
PORT=3000
# Auth server location
AUTH_HOST=localhost
AUTH_PORT=8080
AUTH_REALM=master
# Keycloak OAuth client credentials
OAUTH_CLIENT_ID=<YOUR_SERVER_CLIENT_ID>
OAUTH_CLIENT_SECRET=<YOUR_SERVER_CLIENT_SECRET>
```
`OAUTH_CLIENT_ID` and `OAUTH_CLIENT_SECRET` are associated with the MCP server client we created earlier.
In addition to implementing the MCP authorization specification, the server below also does token introspection via Keycloak to make sure that the token it receives from the client is valid. It also implements basic logging to allow you to easily diagnose any issues.
```typescript theme={null}
import "dotenv/config";
import express from "express";
import { randomUUID } from "node:crypto";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
import { isInitializeRequest } from "@modelcontextprotocol/sdk/types.js";
import { z } from "zod";
import cors from "cors";
import {
mcpAuthMetadataRouter,
getOAuthProtectedResourceMetadataUrl,
} from "@modelcontextprotocol/sdk/server/auth/router.js";
import { requireBearerAuth } from "@modelcontextprotocol/sdk/server/auth/middleware/bearerAuth.js";
import { OAuthMetadata } from "@modelcontextprotocol/sdk/shared/auth.js";
Cut at 300 lines. The page has the rest.
docs/2024-11-05/tutorials/security/security_best_practices New page · 892 lines, new page
# Security Best Practices ## Introduction ### Purpose and Scope ## Attacks and Mitigations ### Confused Deputy Problem #### Terminology #### Vulnerable Conditions #### Architecture and Attack Flows ##### Normal OAuth proxy usage (preserves user consent) ##### Malicious OAuth proxy usage (skips user consent) #### Attack Description #### Mitigation ##### Consent Flow Implementation ##### Required Protections ### Token Passthrough #### Risks #### Mitigation ### Server-Side Request Forgery (SSRF) #### Attack Description #### Risks #### Mitigation #### Resources and Tools ### Session Hijacking #### Session Hijack Prompt Injection #### Session Hijack Impersonation #### Attack Description #### Mitigation ### Local MCP Server Compromise #### Attack Description #### Risks #### Mitigation ### OAuth Authorization URL Validation #### Attack Description #### Risks #### Mitigation ### stdio Transport Security in Proxy Scenarios #### Attack Description #### Risks #### Mitigation ### Scope Minimization #### Attack Description #### Risks #### Mitigation #### Common Mistakes
A whole new page. There's nothing to diff it against, so here is what it says.
# Security Best Practices
> Security considerations, attack vectors, and best practices for MCP implementations
## Introduction
### Purpose and Scope
This document provides security considerations for the Model Context
Protocol (MCP), complementing the
[MCP Authorization](/specification/2025-03-26/basic/authorization)
specification. This document identifies security risks, attack vectors,
and best practices specific to MCP implementations.
The primary audience for this document includes developers implementing
MCP authorization flows, MCP server operators, and security
professionals evaluating MCP-based systems. This document should be read
alongside the MCP Authorization specification and
[OAuth 2.0 security best practices](https://datatracker.ietf.org/doc/html/rfc9700).
## Attacks and Mitigations
This section gives a detailed description of attacks on MCP
implementations, along with potential countermeasures.
### Confused Deputy Problem
Attackers can exploit MCP proxy servers that connect to third-party
APIs, creating
"[confused deputy](https://en.wikipedia.org/wiki/Confused_deputy_problem)"
vulnerabilities. This attack allows malicious clients to obtain
authorization codes without proper user consent by exploiting the
combination of static client IDs, dynamic client registration, and
consent cookies.
#### Terminology
**MCP Proxy Server**
: An MCP server that connects MCP clients to third-party APIs, offering
MCP features while delegating operations and acting as a single OAuth
client to the third-party API server.
**Third-Party Authorization Server**
: Authorization server that protects the third-party API. It may lack
dynamic client registration support, requiring the MCP proxy to use a
static client ID for all requests.
**Third-Party API**
: The protected resource server that provides the actual API
functionality. Access to this API requires tokens issued by the
third-party authorization server.
**Static Client ID**
: A fixed OAuth 2.0 client identifier used by the MCP proxy server when
communicating with the third-party authorization server. This Client ID
refers to the MCP server acting as a client to the Third-Party API. It
is the same value for all MCP server to Third-Party API interactions
regardless of which MCP client initiated the request.
#### Vulnerable Conditions
This attack becomes possible when all of the following conditions are
present:
* MCP proxy server uses a **static client ID** with a third-party
authorization server
* MCP proxy server allows MCP clients to **dynamically register** (each
getting their own client\_id)
* The third-party authorization server sets a **consent cookie** after
the first authorization
* MCP proxy server does not implement proper per-client consent before
forwarding to third-party authorization
#### Architecture and Attack Flows
##### Normal OAuth proxy usage (preserves user consent)
```mermaid theme={null}
sequenceDiagram
participant UA as User-Agent (Browser)
participant MC as MCP Client
participant M as MCP Proxy Server
participant TAS as Third-Party Authorization Server
Note over UA,M: Initial Auth flow completed
Note over UA,TAS: Step 1: Legitimate user consent for Third Party Server
M->>UA: Redirect to third party authorization server
UA->>TAS: Authorization request (client_id: mcp-proxy)
TAS->>UA: Authorization consent screen
Note over UA: Review consent screen
UA->>TAS: Approve
TAS->>UA: Set consent cookie for client ID: mcp-proxy
TAS->>UA: 3P Authorization code + redirect to mcp-proxy-server.com
UA->>M: 3P Authorization code
Note over M,TAS: Exchange 3P code for 3P token
Note over M: Generate MCP authorization code
M->>UA: Redirect to MCP Client with MCP authorization code
Note over M,UA: Exchange code for token, etc.
```
##### Malicious OAuth proxy usage (skips user consent)
```mermaid theme={null}
sequenceDiagram
participant UA as User-Agent (Browser)
participant M as MCP Proxy Server
participant TAS as Third-Party Authorization Server
participant A as Attacker
Note over UA,A: Step 2: Attack (leveraging existing cookie, skipping consent)
A->>M: Dynamically register malicious client, redirect_uri: attacker.com
A->>UA: Sends malicious link
UA->>TAS: Authorization request (client_id: mcp-proxy) + consent cookie
rect rgba(255, 17, 0, 0.67)
TAS->>TAS: Cookie present, consent skipped
end
TAS->>UA: 3P Authorization code + redirect to mcp-proxy-server.com
UA->>M: 3P Authorization code
Note over M,TAS: Exchange 3P code for 3P token
Note over M: Generate MCP authorization code
M->>UA: Redirect to attacker.com with MCP Authorization code
UA->>A: MCP Authorization code delivered to attacker.com
Note over M,A: Attacker exchanges MCP code for MCP token
A->>M: Attacker impersonates user to MCP server
```
#### Attack Description
When an MCP proxy server uses a static client ID to authenticate with
a third-party authorization server, the following attack becomes
possible:
1. A user authenticates normally through the MCP proxy server to access
the third-party API
2. During this flow, the third-party authorization server sets a cookie
on the user agent indicating consent for the static client ID
3. An attacker later sends the user a malicious link containing a
crafted authorization request which contains a malicious redirect URI
along with a new dynamically registered client ID
4. When the user clicks the link, their browser still has the consent
cookie from the previous legitimate request
5. The third-party authorization server detects the cookie and skips the
consent screen
6. The MCP authorization code is redirected to the attacker's server
(specified in the malicious `redirect_uri` parameter during
[dynamic client registration](/specification/2025-03-26/basic/authorization#dynamic-client-registration))
7. The attacker exchanges the stolen authorization code for access
tokens for the MCP server without the user's explicit approval
8. The attacker now has access to the third-party API as the compromised
user
#### Mitigation
To prevent confused deputy attacks, MCP proxy servers **MUST** implement
per-client consent and proper security controls as detailed below.
##### Consent Flow Implementation
The following diagram shows how to properly implement per-client consent
that runs **before** the third-party authorization flow:
```mermaid theme={null}
sequenceDiagram
participant Client as MCP Client
participant Browser as User's Browser
participant MCP as MCP Server
participant ThirdParty as Third-Party AuthZ Server
Note over Client,ThirdParty: 1. Client Registration (Dynamic)
Client->>MCP: Register with redirect_uri
MCP-->>Client: client_id
Note over Client,ThirdParty: 2. Authorization Request
Client->>Browser: Open MCP server authorization URL
Browser->>MCP: GET /authorize?client_id=...&redirect_uri=...
alt Check MCP Server Consent
MCP->>MCP: Check consent for this client_id
Note over MCP: Not previously approved
end
MCP->>Browser: Show MCP server-owned consent page
Note over Browser: "Allow [Client Name] to access [Third-Party API]?"
Browser->>MCP: POST /consent (approve)
MCP->>MCP: Store consent decision for client_id
Note over Client,ThirdParty: 3. Forward to Third-Party
MCP->>Browser: Redirect to third-party /authorize
Note over MCP: Use static client_id for third-party
Browser->>ThirdParty: Authorization request (static client_id)
ThirdParty->>Browser: User authenticates & consents
ThirdParty->>Browser: Redirect with auth code
Browser->>MCP: Callback with third-party code
MCP->>ThirdParty: Exchange code for token (using static client_id)
MCP->>Browser: Redirect to client's registered redirect_uri
```
##### Required Protections
**Per-Client Consent Storage**
MCP proxy servers **MUST**:
* Maintain a registry of approved `client_id` values per user
* Check this registry **before** initiating the third-party
authorization flow
* Store consent decisions securely (server-side database, or server
specific cookies)
**Consent UI Requirements**
The MCP-level consent page **MUST**:
* Clearly identify the requesting MCP client by name
* Display the specific third-party API scopes being requested
* Show the registered `redirect_uri` where tokens will be sent
* Implement CSRF protection (e.g., state parameter, CSRF tokens)
* Prevent iframing via `frame-ancestors` CSP directive or
`X-Frame-Options: DENY` to prevent clickjacking
**Consent Cookie Security**
If using cookies to track consent decisions, they **MUST**:
* Use `__Host-` prefix for cookie names
* Set `Secure`, `HttpOnly`, and `SameSite=Lax` attributes
* Be cryptographically signed or use server-side sessions
* Bind to the specific `client_id` (not just "user has consented")
**Redirect URI Validation**
The MCP proxy server **MUST**:
* Validate that the `redirect_uri` in authorization requests exactly
matches the registered URI
* Reject requests if the `redirect_uri` has changed without
re-registration
* Use exact string matching (not pattern matching or wildcards)
**OAuth State Parameter Validation**
The OAuth `state` parameter is critical to prevent authorization code
interception and CSRF attacks. Proper state validation ensures that
consent approval at the authorization endpoint is enforced at the
callback endpoint.
MCP proxy servers implementing OAuth flows **MUST**:
* Generate a cryptographically secure random `state` value for each
authorization request
* Store the `state` value server-side (in a secure session store or
encrypted cookie) **only after** consent has been explicitly approved
* Set the `state` tracking cookie/session **immediately before**
redirecting to the third-party identity provider (not before consent
approval)
* Validate at the callback endpoint that the `state` query parameter
exactly matches the stored value in the callback request's cookies or
in the request's cookie-based session
* Reject any callback requests where the `state` parameter is missing
or does not match
* Ensure `state` values are single-use (delete after validation) and
have a short expiration time (e.g., 10 minutes)
The consent cookie or session containing the `state` value **MUST NOT**
be set until **after** the user has approved the consent screen at the
MCP server's authorization endpoint. Setting this cookie before consent
approval renders the consent screen ineffective, as an attacker could
bypass it by crafting a malicious authorization request.
### Token Passthrough
"Token passthrough" is an anti-pattern where an MCP server accepts
tokens from an MCP client without validating that the tokens were
properly issued *to the MCP server* and passes them through to the
downstream API.
#### Risks
Token passthrough is explicitly forbidden in the
[authorization specification](/specification/2025-03-26/basic/authorization)
as it introduces a number of security risks, that include:
* **Security Control Circumvention**
* The MCP Server or downstream APIs might implement important security
controls like rate limiting, request validation, or traffic
monitoring, that depend on the token audience or other credential
constraints. If clients can obtain and use tokens directly with the
downstream APIs without the MCP server validating them properly or
ensuring that the tokens are issued for the right service, they
bypass these controls.
* **Accountability and Audit Trail Issues**
* The MCP Server will be unable to identify or distinguish between MCP
Clients when clients are calling with an upstream-issued access token
Cut at 300 lines. The page has the rest.
docs/2025-03-26/develop/build-client New page · 2510 lines, new page
# Build an MCP client ## Next steps
A whole new page. There's nothing to diff it against, so here is what it says.
# Build an MCP client
> Get started building your own client that can integrate with all MCP servers.
In this tutorial, you'll learn how to build an LLM-powered chatbot client that connects to MCP servers.
Before you begin, it helps to have gone through our [Build an MCP Server](/docs/2025-03-26/develop/build-server) tutorial so you can understand how clients and servers communicate.
<Tabs>
<Tab title="Python">
[You can find the complete code for this tutorial here.](https://github.com/modelcontextprotocol/quickstart-resources/tree/main/mcp-client-python)
## System Requirements
Before starting, ensure your system meets these requirements:
* Mac or Windows computer
* Latest Python version installed
* Latest version of `uv` installed
## Setting Up Your Environment
First, create a new Python project with `uv`:
<CodeGroup>
```bash macOS/Linux theme={null}
# Create project directory
uv init mcp-client
cd mcp-client
# Create virtual environment
uv venv
# Activate virtual environment
source .venv/bin/activate
# Install required packages
uv add mcp anthropic python-dotenv
# Remove boilerplate files
rm main.py
# Create our main file
touch client.py
```
```powershell Windows theme={null}
# Create project directory
uv init mcp-client
cd mcp-client
# Create virtual environment
uv venv
# Activate virtual environment
.venv\Scripts\activate
# Install required packages
uv add mcp anthropic python-dotenv
# Remove boilerplate files
del main.py
# Create our main file
new-item client.py
```
</CodeGroup>
## Setting Up Your API Key
You'll need an Anthropic API key from the [Anthropic Console](https://console.anthropic.com/settings/keys).
Create a `.env` file to store it:
```bash theme={null}
echo "ANTHROPIC_API_KEY=your-api-key-goes-here" > .env
```
Add `.env` to your `.gitignore`:
```bash theme={null}
echo ".env" >> .gitignore
```
<Warning>
Make sure you keep your `ANTHROPIC_API_KEY` secure!
</Warning>
## Creating the Client
### Basic Client Structure
First, let's set up our imports and create the basic client class:
```python theme={null}
import asyncio
from typing import Optional
from contextlib import AsyncExitStack
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
from anthropic import Anthropic
from dotenv import load_dotenv
load_dotenv() # load environment variables from .env
class MCPClient:
def __init__(self):
# Initialize session and client objects
self.session: Optional[ClientSession] = None
self.exit_stack = AsyncExitStack()
self.anthropic = Anthropic()
# methods will go here
```
### Server Connection Management
Next, we'll implement the method to connect to an MCP server:
```python theme={null}
async def connect_to_server(self, server_script_path: str):
"""Connect to an MCP server
Args:
server_script_path: Path to the server script (.py or .js)
"""
is_python = server_script_path.endswith('.py')
is_js = server_script_path.endswith('.js')
if not (is_python or is_js):
raise ValueError("Server script must be a .py or .js file")
command = "python" if is_python else "node"
server_params = StdioServerParameters(
command=command,
args=[server_script_path],
env=None
)
stdio_transport = await self.exit_stack.enter_async_context(stdio_client(server_params))
self.stdio, self.write = stdio_transport
self.session = await self.exit_stack.enter_async_context(ClientSession(self.stdio, self.write))
await self.session.initialize()
# List available tools
response = await self.session.list_tools()
tools = response.tools
print("\nConnected to server with tools:", [tool.name for tool in tools])
```
### Query Processing Logic
Now let's add the core functionality for processing queries and handling tool calls:
```python theme={null}
async def process_query(self, query: str) -> str:
"""Process a query using Claude and available tools"""
messages = [
{
"role": "user",
"content": query
}
]
response = await self.session.list_tools()
available_tools = [{
"name": tool.name,
"description": tool.description,
"input_schema": tool.inputSchema
} for tool in response.tools]
# Initial Claude API call
response = self.anthropic.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1000,
messages=messages,
tools=available_tools
)
# Process response and handle tool calls
final_text = []
assistant_message_content = []
for content in response.content:
if content.type == 'text':
final_text.append(content.text)
assistant_message_content.append(content)
elif content.type == 'tool_use':
tool_name = content.name
tool_args = content.input
# Execute tool call
result = await self.session.call_tool(tool_name, tool_args)
final_text.append(f"[Calling tool {tool_name} with args {tool_args}]")
assistant_message_content.append(content)
messages.append({
"role": "assistant",
"content": assistant_message_content
})
messages.append({
"role": "user",
"content": [
{
"type": "tool_result",
"tool_use_id": content.id,
"content": result.content
}
]
})
# Get next response from Claude
response = self.anthropic.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1000,
messages=messages,
tools=available_tools
)
final_text.append(response.content[0].text)
return "\n".join(final_text)
```
### Interactive Chat Interface
Now we'll add the chat loop and cleanup functionality:
```python theme={null}
async def chat_loop(self):
"""Run an interactive chat loop"""
print("\nMCP Client Started!")
print("Type your queries or 'quit' to exit.")
while True:
try:
query = input("\nQuery: ").strip()
if query.lower() == 'quit':
break
response = await self.process_query(query)
print("\n" + response)
except Exception as e:
print(f"\nError: {str(e)}")
async def cleanup(self):
"""Clean up resources"""
await self.exit_stack.aclose()
```
### Main Entry Point
Finally, we'll add the main execution logic:
```python theme={null}
async def main():
if len(sys.argv) < 2:
print("Usage: python client.py <path_to_server_script>")
sys.exit(1)
client = MCPClient()
try:
await client.connect_to_server(sys.argv[1])
await client.chat_loop()
finally:
await client.cleanup()
if __name__ == "__main__":
import sys
asyncio.run(main())
```
You can find the complete `client.py` file [here](https://github.com/modelcontextprotocol/quickstart-resources/blob/main/mcp-client-python/client.py).
## Key Components Explained
### 1. Client Initialization
* The `MCPClient` class initializes with session management and API clients
* Uses `AsyncExitStack` for proper resource management
* Configures the Anthropic client for Claude interactions
### 2. Server Connection
* Supports both Python and Node.js servers
* Validates server script type
* Sets up proper communication channels
* Initializes the session and lists available tools
### 3. Query Processing
* Maintains conversation context
* Handles Claude's responses and tool calls
* Manages the message flow between Claude and tools
* Combines results into a coherent response
### 4. Interactive Interface
Cut at 300 lines. The page has the rest.
docs/2025-03-26/develop/build-server New page · 2997 lines, new page
# Build an MCP server ### What we'll be building ### Core MCP Concepts ### Test with commands ## What's happening under the hood ## Troubleshooting ## Next steps
A whole new page. There's nothing to diff it against, so here is what it says.
# Build an MCP server
> Get started building your own server to use in Claude for Desktop and other clients.
In this tutorial, we'll build a simple MCP weather server and connect it to a host, Claude for Desktop.
### What we'll be building
We'll build a server that exposes two tools: `get_alerts` and `get_forecast`. Then we'll connect the server to an MCP host (in this case, Claude for Desktop):
<Frame>
<img src="https://mintcdn.com/mcp/4ZXF1PrDkEaJvXpn/images/current-weather.png?fit=max&auto=format&n=4ZXF1PrDkEaJvXpn&q=85&s=dce7b2f8a06c20ba358e4bd2e75fa4c7" width="2780" height="1849" data-path="images/current-weather.png" />
</Frame>
<Note>
Servers can connect to any client. We've chosen Claude for Desktop here for simplicity, but we also have a guide on [building your own client](/docs/2025-03-26/develop/build-client).
</Note>
### Core MCP Concepts
MCP servers can provide three main types of capabilities:
1. **[Resources](/docs/2025-03-26/learn/server-concepts#resources)**: File-like data that can be read by clients (like API responses or file contents)
2. **[Tools](/docs/2025-03-26/learn/server-concepts#tools)**: Functions that can be called by the LLM (with user approval)
3. **[Prompts](/docs/2025-03-26/learn/server-concepts#prompts)**: Pre-written templates that help users accomplish specific tasks
This tutorial will primarily focus on tools.
<Tabs>
<Tab title="Python">
Let's get started with building our weather server! [You can find the complete code for what we'll be building here.](https://github.com/modelcontextprotocol/quickstart-resources/tree/main/weather-server-python)
### Prerequisite knowledge
This quickstart assumes you have familiarity with:
* Python
* LLMs like Claude
### Logging in MCP Servers
When implementing MCP servers, be careful about how you handle logging:
**For STDIO-based servers:** Never write to stdout. Writing to stdout will corrupt the JSON-RPC messages and break your server. The `print()` function writes to stdout by default, but can be used safely with `file=sys.stderr`.
**For HTTP-based servers:** Standard output logging is fine since it doesn't interfere with HTTP responses.
### Best Practices
* Use a logging library that writes to stderr or files.
### Quick Examples
```python theme={null}
import sys
import logging
# ❌ Bad (STDIO)
print("Processing request")
# ✅ Good (STDIO)
print("Processing request", file=sys.stderr)
# ✅ Good (STDIO)
logging.info("Processing request")
```
### System requirements
* Python 3.10 or higher installed.
* You must use the Python MCP SDK 1.2.0 or higher.
### Set up your environment
First, let's install `uv` and set up our Python project and environment:
<CodeGroup>
```bash macOS/Linux theme={null}
curl -LsSf https://astral.sh/uv/install.sh | sh
```
```powershell Windows theme={null}
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
```
</CodeGroup>
Make sure to restart your terminal afterwards to ensure that the `uv` command gets picked up.
Now, let's create and set up our project:
<CodeGroup>
```bash macOS/Linux theme={null}
# Create a new directory for our project
uv init weather
cd weather
# Create virtual environment and activate it
uv venv
source .venv/bin/activate
# Install dependencies
uv add "mcp[cli]" httpx
# Create our server file
touch weather.py
```
```powershell Windows theme={null}
# Create a new directory for our project
uv init weather
cd weather
# Create virtual environment and activate it
uv venv
.venv\Scripts\activate
# Install dependencies
uv add mcp[cli] httpx
# Create our server file
new-item weather.py
```
</CodeGroup>
Now let's dive into building your server.
## Building your server
### Importing packages and setting up the instance
Add these to the top of your `weather.py`:
```python theme={null}
from typing import Any
import httpx
from mcp.server.fastmcp import FastMCP
# Initialize FastMCP server
mcp = FastMCP("weather")
# Constants
NWS_API_BASE = "https://api.weather.gov"
USER_AGENT = "weather-app/1.0"
```
The FastMCP class uses Python type hints and docstrings to automatically generate tool definitions, making it easy to create and maintain MCP tools.
### Helper functions
Next, let's add our helper functions for querying and formatting the data from the National Weather Service API:
```python theme={null}
async def make_nws_request(url: str) -> dict[str, Any] | None:
"""Make a request to the NWS API with proper error handling."""
headers = {"User-Agent": USER_AGENT, "Accept": "application/geo+json"}
async with httpx.AsyncClient() as client:
try:
response = await client.get(url, headers=headers, timeout=30.0)
response.raise_for_status()
return response.json()
except Exception:
return None
def format_alert(feature: dict) -> str:
"""Format an alert feature into a readable string."""
props = feature["properties"]
return f"""
Event: {props.get("event", "Unknown")}
Area: {props.get("areaDesc", "Unknown")}
Severity: {props.get("severity", "Unknown")}
Description: {props.get("description", "No description available")}
Instructions: {props.get("instruction", "No specific instructions provided")}
"""
```
### Implementing tool execution
The tool execution handler is responsible for actually executing the logic of each tool. Let's add it:
```python theme={null}
@mcp.tool()
async def get_alerts(state: str) -> str:
"""Get weather alerts for a US state.
Args:
state: Two-letter US state code (e.g. CA, NY)
"""
url = f"{NWS_API_BASE}/alerts/active/area/{state}"
data = await make_nws_request(url)
if not data or "features" not in data:
return "Unable to fetch alerts or no alerts found."
if not data["features"]:
return "No active alerts for this state."
alerts = [format_alert(feature) for feature in data["features"]]
return "\n---\n".join(alerts)
@mcp.tool()
async def get_forecast(latitude: float, longitude: float) -> str:
"""Get weather forecast for a location.
Args:
latitude: Latitude of the location
longitude: Longitude of the location
"""
# First get the forecast grid endpoint
points_url = f"{NWS_API_BASE}/points/{latitude},{longitude}"
points_data = await make_nws_request(points_url)
if not points_data:
return "Unable to fetch forecast data for this location."
# Get the forecast URL from the points response
forecast_url = points_data["properties"]["forecast"]
forecast_data = await make_nws_request(forecast_url)
if not forecast_data:
return "Unable to fetch detailed forecast."
# Format the periods into a readable forecast
periods = forecast_data["properties"]["periods"]
forecasts = []
for period in periods[:5]: # Only show next 5 periods
forecast = f"""
{period["name"]}:
Temperature: {period["temperature"]}°{period["temperatureUnit"]}
Wind: {period["windSpeed"]} {period["windDirection"]}
Forecast: {period["detailedForecast"]}
"""
forecasts.append(forecast)
return "\n---\n".join(forecasts)
```
### Running the server
Finally, let's initialize and run the server:
```python theme={null}
def main():
# Initialize and run the server
mcp.run(transport="stdio")
if __name__ == "__main__":
main()
```
Your server is complete! Run `uv run weather.py` to start the MCP server, which will listen for messages from MCP hosts.
Let's now test your server from an existing MCP host, Claude for Desktop.
## Testing your server with Claude for Desktop
<Note>
Claude for Desktop is not yet available on Linux. Linux users can proceed to the [Building a client](/docs/2025-03-26/develop/build-client) tutorial to build an MCP client that connects to the server we just built.
</Note>
First, make sure you have Claude for Desktop installed. [You can install the latest version
here.](https://claude.ai/download) If you already have Claude for Desktop, **make sure it's updated to the latest version.**
We'll need to configure Claude for Desktop for whichever MCP servers you want to use. To do this, open your Claude for Desktop App configuration at `~/Library/Application Support/Claude/claude_desktop_config.json` in a text editor. Make sure to create the file if it doesn't exist.
For example, if you have [VS Code](https://code.visualstudio.com/) installed:
<CodeGroup>
```bash macOS/Linux theme={null}
code ~/Library/Application\ Support/Claude/claude_desktop_config.json
```
```powershell Windows theme={null}
code $env:AppData\Claude\claude_desktop_config.json
```
</CodeGroup>
You'll then add your servers in the `mcpServers` key. The MCP UI elements will only show up in Claude for Desktop if at least one server is properly configured.
In this case, we'll add our single weather server like so:
<CodeGroup>
```json macOS/Linux theme={null}
{
"mcpServers": {
"weather": {
"command": "uv",
"args": [
"--directory",
"/ABSOLUTE/PATH/TO/PARENT/FOLDER/weather",
"run",
"weather.py"
]
}
}
}
```
Cut at 300 lines. The page has the rest.
docs/2025-03-26/develop/build-with-agent-skills New page · 98 lines, new page
# Build with Agent Skills ## Available skills ## Start a build ## Deployment paths ## Next steps
A whole new page. There's nothing to diff it against, so here is what it says.
# Build with Agent Skills
> Use agent skills to guide AI coding assistants through MCP server design and implementation
[Agent skills](https://agentskills.io/home) are portable instruction sets that
give AI coding assistants domain knowledge for a task. For MCP development,
they encode the design decisions (deployment model, tool patterns, auth) so
your agent can interrogate your use case and scaffold a server that fits.
## Available skills
A reference set of MCP development skills is available as the
[`mcp-server-dev` plugin](https://github.com/anthropics/claude-plugins-official/tree/main/plugins/mcp-server-dev).
It provides three composing skills:
| Skill | Purpose |
| ------------------ | ----------------------------------------------------------------------------------------------------------------------- |
| `build-mcp-server` | Entry point. Interrogates the use case, picks a deployment model and tool-design pattern, routes to specialized skills. |
| `build-mcp-app` | Adds interactive UI widgets (forms, pickers, dashboards) rendered inline in chat. |
| `build-mcpb` | Packages a local stdio server with its runtime so users can install it without Node or Python. |
Each skill ships a `SKILL.md` file plus a `references/` folder of supporting
material (auth flows, tool-design patterns, widget templates, manifest schemas)
that the agent reads on demand. The files follow the open format and work with
any agent that implements the standard. For example, to install them in Claude
Code:
```bash theme={null}
/plugin marketplace add anthropics/claude-plugins-official
/plugin install mcp-server-dev
```
For other agents, check your skills or extensions catalog, or clone the
[skill directories](https://github.com/anthropics/claude-plugins-official/tree/main/plugins/mcp-server-dev/skills)
(`SKILL.md` plus `references/`) into your agent's skills location.
## Start a build
With the skills installed, ask your agent to help you build an MCP server. The
entry skill triggers on natural-language requests, or you can invoke it
directly using your agent's skill-invocation syntax.
The skill runs a short discovery phase before writing any code. Expect
questions about:
* **What it connects to** — a cloud API, a local process, the filesystem, hardware
* **Who will use it** — just you, your team, or anyone who installs it
* **Action surface size** — a handful of operations versus wrapping a large API
* **User interaction needs** — plain text results or rich UI widgets
* **Upstream auth** — API keys, OAuth 2.0, or none
If your opening message already covers these, the agent skips ahead to the
recommendation.
## Deployment paths
Based on discovery, the skill recommends one of four paths and scaffolds
accordingly:
**Remote [Streamable HTTP](/specification/2025-03-26/basic/transports#streamable-http)**
is the default for anything wrapping a cloud API. Zero install friction, one
deployment serves all users, and OAuth flows work properly because the server
can handle redirects and token storage. The reference skill includes scaffolds
for Cloudflare Workers and portable Express/FastMCP setups.
**[MCP apps](/extensions/apps/overview)** extend a server with interactive
widgets rendered in chat, such as searchable pickers, charts, and live
dashboards. The skill hands off to `build-mcp-app` when plain text output
doesn't fit.
**[MCP Bundles (MCPB)](https://github.com/modelcontextprotocol/mcpb)** package a
local server together with its runtime as a single `.mcpb` archive, so users
can install it without setting up Node or Python. Use this path when the server
must touch the user's machine: reading local files, driving desktop apps, or
talking to localhost services. The skill hands off to `build-mcpb`.
**Local [stdio](/specification/2025-03-26/basic/transports#stdio)** remains available
for prototyping, with a noted upgrade path to MCPB when you're ready to
distribute.
## Next steps
Once your agent scaffolds the server, iterate on tool descriptions and error
handling, then test and ship:
<CardGroup cols={2}>
<Card title="MCP Inspector" icon="magnifying-glass" href="/docs/2025-03-26/tools/inspector">
Test your server's tools, resources, and prompts interactively
</Card>
<Card title="Connect to a client" icon="plug" href="/docs/2025-03-26/develop/connect-local-servers">
Wire your server into an MCP client via local or remote configuration
</Card>
<Card title="Publish to the Registry" icon="box" href="/registry/quickstart">
Make your server discoverable in the MCP Registry
</Card>
</CardGroup>
docs/2025-03-26/develop/clients/client-best-practices New page · 292 lines, new page
# Client Best Practices ## Progressive Tool Discovery ### When to Use Progressive Discovery ### Choosing a Discovery Strategy ### Using Progressive Discovery ### Dynamic Server Management ### Implementation Guidelines ### Interaction with Prompt Caching ## Programmatic Tool Calling / Code Mode ### How It Works ### Choosing a Sandbox ### Execution Architecture ### Security Considerations ### Error Handling ## Combining Both Patterns
A whole new page. There's nothing to diff it against, so here is what it says.
# Client Best Practices
> Patterns for scaling MCP host applications across many servers and tools.
As MCP host applications, such as agents, connect to more MCP servers and accumulate access to hundreds or thousands of tools, naive approaches to tool management break down. Loading every tool definition into the model's context window upfront wastes tokens, increases latency, and degrades model performance. Passing large intermediate results through the model between sequential tool calls compounds the problem.
Two patterns address these challenges: **progressive discovery**, which controls *when* tool definitions enter context, and **programmatic tool calling**, which controls *how* tools are invoked.
## Progressive Tool Discovery
Naive MCP host implementations pass the tool definitions of every connected server directly to the model at the start of each conversation. For a handful of tools, this is perfectly reasonable. But when a host has access to dozens of servers exposing hundreds of tools, those definitions alone can consume the majority of the context window before the model has even read the user's message.
<img src="https://mintcdn.com/mcp/JXfd5cBmEUh_qPUI/images/progressive-discovery.svg?fit=max&auto=format&n=JXfd5cBmEUh_qPUI&q=85&s=db39f47006107f04af43b5eeae2d6022" alt="Comparison of loading all tools upfront versus discovering tools on demand. The upfront approach consumes ~150,000 tokens on definitions alone, while progressive discovery uses ~2,000 tokens by loading only what the task requires." width="760" height="440" data-path="images/progressive-discovery.svg" />
Progressive discovery avoids this:
* The host fetches tool definitions via `tools/list` as normal, but defers injecting them into the model's context.
* The host provides a lightweight `search_tools` meta-tool to the model.
* The host loads full definitions into context only as needed.
### When to Use Progressive Discovery
Progressive discovery is best used when tool definitions take large parts of the context window. For a small
set of tools with tool definitions taking up a small part of the context window, loading all tools is fine.
Once the tool definitions take up a significant part of the available context window, clients should switch to progressive discovery. We recommend that clients implement thresholds to determine when to switch:
* Implement a threshold as a percentage of the context window. For example, 1%-5%.
* Load tool definitions. Once the threshold is reached, switch to progressive discovery.
### Choosing a Discovery Strategy
Once the model invokes the `search_tools` tool, we need to choose a search strategy:
* **Keyword-based**: Keyword matching (BM25, regex). Simple and effective, particularly for descriptive tool names and descriptions.
* **Embedding-based**: Vector-similarity retrieval over tool descriptions. Handles synonyms and semantic matching better.
* **Subagent-based**: A secondary model, often a small and fast model such as Claude Haiku or Gemini Flash, selects tools for the task. This usually works very well but can be more costly than embedding-based or keyword-based solutions.
* **Hybrid**: Combine approaches. For example, by scoring across keyword and embedding rankings, or choosing
different strategies depending on use-case or query.
Some model providers already offer built-in tool search. For example, [OpenAI](https://developers.openai.com/api/docs/guides/tools-tool-search) and [Anthropic](https://platform.claude.com/docs/en/agents-and-tools/tool-use/tool-search-tool) support this natively; check your provider's documentation for an equivalent. When available, you may prefer the platform's tool search over a custom implementation. Build your own when the provider doesn't offer one or when you need specialized retrieval logic (e.g., domain-specific ranking or access-control filtering).
The three-layer pattern below illustrates a custom search-based approach in detail, but the layered principle (catalog, inspect, execute) applies regardless of retrieval mechanism.
### Using Progressive Discovery
One common implementation for progressive discovery uses a search-based three-layer approach:
**Layer 1: Catalog.** The host exposes a small set of meta-tools for searching available capabilities. A `search_tools` tool accepts a natural-language query and returns matching tool names with brief descriptions.
```typescript theme={null}
// The model calls a lightweight search tool
search_tools({ query: "update salesforce record" })
// Returns concise matches: names and one-line descriptions only
→ [
{ name: "salesforce_updateRecord", description: "Update fields on a Salesforce object" },
{ name: "salesforce_upsertRecord", description: "Insert or update based on external ID" }
]
```
**Layer 2: Inspect.** Once the model identifies a candidate, it fetches the full definition (input schema, documentation) for that tool only.
```typescript theme={null}
// The model inspects only the tool it needs
get_tool_details({ name: "salesforce_updateRecord" });
```
This returns the complete schema for a single tool:
```json theme={null}
{
"name": "salesforce_updateRecord",
"description": "Updates a record in Salesforce",
"inputSchema": {
"type": "object",
"properties": {
"objectType": {
"type": "string",
"description": "Salesforce object type"
},
"recordId": { "type": "string", "description": "Record ID to update" },
"data": { "type": "object", "description": "Fields to update" }
},
"required": ["objectType", "recordId", "data"]
}
}
```
**Layer 3: Execute.** The model calls the tool with full knowledge of its interface, having loaded only the definitions it needed.
This pattern reduces token usage dramatically and can improve tool selection accuracy: the model focuses on a few relevant tools rather than scanning hundreds of irrelevant ones. Other discovery strategies (embeddings, subagents, etc.) follow the same layered principle but substitute different retrieval mechanisms in the catalog layer.
### Dynamic Server Management
Progressive discovery extends beyond individual tools to entire servers. Rather than connecting to every configured server at startup, a host can:
1. Maintain a registry of available servers and their high-level descriptions.
2. Connect to a server only when the model determines it needs that server's capabilities.
3. Disconnect servers that are no longer relevant to the current task, freeing context.
```mermaid theme={null}
sequenceDiagram
participant Model
participant Host
participant Registry
participant Server
Model->>Host: search_available_servers("CRM")
Host->>Registry: Query available servers
Registry-->>Host: Salesforce server (not connected)
Host-->>Model: Salesforce server available
Model->>Host: enable_server("salesforce")
Host->>Server: Initialize connection
Server-->>Host: Server capabilities + tools
Host-->>Model: Salesforce server connected
Note over Model: Task complete
Model->>Host: disable_server("salesforce")
Host->>Server: Close connection
Host-->>Model: Server disconnected, context freed
```
This works especially well for general-purpose agents, where the user's intent isn't known upfront. The agent starts with a minimal set of always-on servers and connects others as needed. Combined with [agent skills](/docs/2025-03-26/develop/build-with-agent-skills), a skill file can declare which MCP servers it needs, and the host connects them only when that skill is invoked.
### Implementation Guidelines
When implementing progressive discovery:
| Guideline | Rationale |
| -------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Offer multiple detail levels** | Let the model choose between name-only, name-and-description, or full-schema responses. |
| **Cache tool definitions** | Once fetched from a server, memoize the definition host-side so re-injecting it later doesn't need another `tools/list` round trip. This is separate from what's currently in the model's context. |
| **Refresh on `list_changed`** | Re-index the search catalog when a server sends `notifications/tools/list_changed`. |
| **Group tools by server** | Present tools organized by their source server so the model can reason about related capabilities. |
### Interaction with Prompt Caching
Most providers cache the prompt prefix, including the `tools` array. Adding or removing tool
definitions mid-conversation invalidates that cache, and the resulting miss can cost more tokens
than the definitions you removed. To preserve caching:
* Append newly discovered definitions after the cache breakpoint rather than re-sorting the
`tools` array, or route every call through a single stable `call_tool({name, args})` meta-tool
so the array never changes.
* Treat server disconnection as a conversation-boundary operation rather than a per-turn one.
* Consult your provider's caching documentation alongside the tool-search links above.
## Programmatic Tool Calling / Code Mode
With direct tool calling, every tool invocation is a round trip: the model generates a tool call, the client executes it, and the full result flows back into the model's context. When a task requires chaining multiple tools (read a document, transform it, write it somewhere else), each intermediate result passes through the model, consuming tokens and adding latency even when it has nothing to do with them.
Programmatic tool calling (sometimes called "code mode") provides a way for clients to **compose tool calls** effectively. Instead of calling tools directly, the model writes code that calls tools. The code executes in a sandboxed environment, and only the final result returns to the model.
Programmatic tool calling is powerful and allows for more efficient use of MCP tools and resources, but requires
clients to implement a sandbox environment.
<img src="https://mintcdn.com/mcp/JXfd5cBmEUh_qPUI/images/programmatic-tool-calling.svg?fit=max&auto=format&n=JXfd5cBmEUh_qPUI&q=85&s=a2be82d097bb7cd7c7fd415918b1571d" alt="Comparison of direct tool calling versus programmatic tool calling. Direct calling passes every intermediate result through the model (~100K+ tokens). Programmatic calling sends a ~200-token script to a sandbox, which executes the tool calls and returns a ~15-token summary." width="900" height="900" data-path="images/programmatic-tool-calling.svg" />
### How It Works
The host converts MCP tool schemas into a typed API available inside a sandbox. When the model needs tools, it writes a script and executes it.
**Step 1: Generate a programmatic API from MCP schemas.** The host reads each server's tool definitions and produces typed functions based on each tool's arguments:
```typescript theme={null}
// Auto-generated from the Logging MCP server's tool schema
interface LogEntry {
timestamp: string;
message: string;
level: string;
}
function logging_getLogs(input: {
level: "error" | "warn" | "info";
since: number;
}): Promise<{ entries: LogEntry[] }> {
return mcp.callTool<{ entries: LogEntry[] }>("logging_getLogs", input);
}
// Auto-generated from the Ticketing MCP server's tool schema
function ticketing_createIssue(input: {
title: string;
body?: string;
priority: "low" | "medium" | "high";
}): Promise<{ issueId: string }> {
return mcp.callTool<{ issueId: string }>("ticketing_createIssue", input);
}
```
Tool definitions in this protocol version describe tool inputs only. Precise return types (like `LogEntry` above) have to come from server documentation or manual configuration.
When precise return types are unavailable, prefer the simple path:
* **Use a generic type and move on.** Accept `any` or `string` and handle the unstructured output downstream.
* **Extract a typed result using a fast model**, for single-shot calls outside loops. Expose a host-brokered `extract(value, ExpectedType)` helper through the same stub-interception path as MCP tool calls so the sandbox itself never opens a network connection. The helper routes to a small model (for example, Claude Haiku or Gemini Flash) to coerce the value into `ExpectedType`. This adds per-call latency and can hallucinate or drop fields, so validate the result against `ExpectedType` before use.
**Step 2: The model writes code against these APIs.** Rather than making separate tool calls with full results flowing through context between them, the model writes a single script. Consider a task like "find all error logs from the past hour and file a ticket for each unique error." With direct tool calling, thousands of log entries would flow through the model's context. With code, the model filters in the sandbox:
```typescript theme={null}
// Model-generated code, executes in sandbox
const logs = await logging_getLogs({
level: "error",
since: Date.now() - 3600000,
});
// Filter and deduplicate inside the sandbox, not in the model's context
const uniqueErrors = new Map<string, LogEntry>();
for (const log of logs.entries) {
if (!uniqueErrors.has(log.message)) {
uniqueErrors.set(log.message, log);
}
}
for (const [message, log] of uniqueErrors) {
await ticketing_createIssue({
title: `Error: ${message}`,
body: `First seen: ${log.timestamp}\nOccurrences: ${
logs.entries.filter((l) => l.message === message).length
}`,
priority: "high",
});
}
console.log(
`Filed ${uniqueErrors.size} tickets from ${logs.entries.length} error logs`,
);
```
**Step 3: The sandbox executes the code.** Function calls inside the sandbox are intercepted and routed back to the appropriate MCP server through the host broker. The log data and ticket creation flow directly between servers without ever entering the model's context. Only the `console.log` output, a single summary line, returns to the model.
### Choosing a Sandbox
The right sandbox depends on the language you want the model to write, your host application's language, and how much isolation you need. The table lists example runtimes rather than endorsements; evaluate maturity for your use case:
| Sandboxed language | Runtime / Library | Host language | Approach |
| ------------------ | ------------------------------------------------------------- | ----------------- | ----------------------------------------------------------------------------------------------- |
| **JavaScript** | [Deno](https://github.com/denoland/deno), `isolated-vm` | Rust / Node / CLI | V8-based runtimes with fine-grained permissions. Can disable all permissions for full lockdown. |
| **Python** | [Monty](https://github.com/pydantic/monty) *(experimental)* | Rust | Minimal Python interpreter built for AI use cases. No I/O by default. |
| **TypeScript** | [pctx](https://github.com/portofcontext/pctx) *(early-stage)* | Python / Rust | Incorporates code mode concepts as a library, with low-level Rust support. |
| **Any (via Wasm)** | [Wasmtime](https://github.com/bytecodealliance/wasmtime) | Rust / C / Go | Compile any language to Wasm and run it with capability-based security. |
Regardless of sandbox, the integration pattern is the same: the host injects function stubs, intercepts calls over an in-process or stdio channel (so network permissions can stay fully denied), and dispatches them as `tools/call` requests to MCP servers.
### Execution Architecture
The implementation has three components:
```mermaid theme={null}
flowchart LR
subgraph Host["MCP Host"]
A[LLM] -->|writes code| B[Sandbox]
B -->|function call| C[MCP Client]
C -->|return value| B
B -->|console output| A
end
C -->|tool call| D[MCP Server A]
C -->|tool call| E[MCP Server B]
D -->|result| C
E -->|result| C
```
**The sandbox** runs model-generated code in an isolated environment with no direct network access. Its only interface to the outside world is through the generated function stubs, which route calls back to the host.
**The host** acts as a broker. It receives function calls from the sandbox, maps them to the correct MCP server, executes the tool call, and returns the result to the sandbox. Authorization tokens and credentials are held by the host and never exposed to the generated code.
**The model** sees only what the sandbox returns, typically the output of `console.log` statements or a final return value. This gives the model (and the client developer) precise control over what enters the context window.
### Security Considerations
Programmatic tool calling introduces a code execution surface that requires careful sandboxing:
* **Per-call authorization**: The broker is still the MCP host for spec purposes. Apply the same human-in-the-loop confirmation policy to sandbox-originated calls that you apply to direct calls (see [Tools: Security](/specification/2025-03-26/server/tools#security-considerations)). Approving the script does not grant blanket approval for every tool call it makes at runtime; hosts may grant categorical approval (for example, "allow `ticketing_createIssue` for this script run") rather than prompting per iteration, but the broker must still evaluate each call against that grant.
* **Cross-server data flow**: Tool results from one server are untrusted input to another. The broker should apply the same input-review policy to brokered calls as to direct ones; output truncation alone does not prevent exfiltration.
* **Network isolation**: The sandbox should have no direct network access. All external communication flows through the host broker, which enforces authorization and access control.
* **No credential exposure**: API keys and tokens are held by the host. The generated code calls typed functions; the host adds authentication when forwarding to servers.
* **Resource limits**: Set timeouts and memory limits on sandbox execution to prevent runaway scripts.
* **Output filtering**: Validate and truncate sandbox console output before feeding it back to the model.
### Error Handling
MCP tool errors arrive as a successful response with
[`isError: true`](/specification/2025-03-26/server/tools#error-handling) rather than a transport
failure. Generated wrappers should convert this into a thrown exception so model-authored code
can use `try`/`catch`. If an uncaught error terminates the script, surface it as the script's
result so the model can self-correct; the model is responsible for reporting any partial side
effects already committed.
## Combining Both Patterns
Progressive discovery and programmatic tool calling work well together. The model uses discovery tools to identify which tools it needs, loads their schemas, and then writes a single script that calls multiple tools in one execution pass. This combination minimizes both the token cost of tool definitions *and* the token cost of tool results, keeping the model's context focused on reasoning rather than passing data through it.
docs/2025-03-26/develop/connect-local-servers New page · 283 lines, new page
# Connect to local MCP servers ## Prerequisites ### Claude Desktop ### Node.js ## Understanding MCP Servers ## Installing the Filesystem Server ## Using the Filesystem Server ### File Management Examples ### How Approval Works ## Troubleshooting ## Next Steps
A whole new page. There's nothing to diff it against, so here is what it says.
# Connect to local MCP servers
> Learn how to extend Claude Desktop with local MCP servers to enable file system access and other powerful integrations
Model Context Protocol (MCP) servers extend AI applications' capabilities by providing secure, controlled access to local resources and tools. Many clients support MCP, enabling diverse integration possibilities across different platforms and applications.
This guide demonstrates how to connect to local MCP servers using Claude Desktop as an example, one of the many clients that support MCP. While we focus on Claude Desktop's implementation, the concepts apply broadly to other MCP-compatible clients. By the end of this tutorial, Claude will be able to interact with files on your computer, create new documents, organize folders, and search through your file system—all with your explicit permission for each action.
<Frame>
<img src="https://mintcdn.com/mcp/4ZXF1PrDkEaJvXpn/images/quickstart-filesystem.png?fit=max&auto=format&n=4ZXF1PrDkEaJvXpn&q=85&s=629d7e754dc358d71a408d6ce970c1b1" alt="Claude Desktop with filesystem integration showing file management capabilities" width="1732" height="2060" data-path="images/quickstart-filesystem.png" />
</Frame>
## Prerequisites
Before starting this tutorial, ensure you have the following installed on your system:
### Claude Desktop
Download and install [Claude Desktop](https://claude.ai/download) for your operating system. Claude Desktop is available for macOS and Windows.
If you already have Claude Desktop installed, verify you're running the latest version by clicking the Claude menu and selecting "Check for Updates..."
### Node.js
The Filesystem Server and many other MCP servers require Node.js to run. Verify your Node.js installation by opening a terminal or command prompt and running:
```bash theme={null}
node --version
```
If Node.js is not installed, download it from [nodejs.org](https://nodejs.org/). We recommend the LTS (Long Term Support) version for stability.
## Understanding MCP Servers
MCP servers are programs that run on your computer and provide specific capabilities to Claude Desktop through a standardized protocol. Each server exposes tools that Claude can use to perform actions, with your approval. The Filesystem Server we'll install provides tools for:
* Reading file contents and directory structures
* Creating new files and directories
* Moving and renaming files
* Searching for files by name or content
All actions require your explicit approval before execution, ensuring you maintain full control over what Claude can access and modify.
## Installing the Filesystem Server
The process involves configuring Claude Desktop to automatically start the Filesystem Server whenever you launch the application. This configuration is done through a JSON file that tells Claude Desktop which servers to run and how to connect to them.
<Steps>
<Step title="Open Claude Desktop Settings">
Start by accessing the Claude Desktop settings. Click on the Claude menu in your system's menu bar (not the settings within the Claude window itself) and select "Settings..."
On macOS, this appears in the top menu bar:
<Frame style={{ textAlign: "center" }}>
<img src="https://mintcdn.com/mcp/4ZXF1PrDkEaJvXpn/images/quickstart-menu.png?fit=max&auto=format&n=4ZXF1PrDkEaJvXpn&q=85&s=0c8b57e0e17af3624b6762a3ea944c8e" width="400" alt="Claude Desktop menu showing Settings option" data-path="images/quickstart-menu.png" />
</Frame>
This opens the Claude Desktop configuration window, which is separate from your Claude account settings.
</Step>
<Step title="Access Developer Settings">
In the Settings window, navigate to the "Developer" tab in the left sidebar. This section contains options for configuring MCP servers and other developer features.
Click the "Edit Config" button to open the configuration file:
<Frame>
<img src="https://mintcdn.com/mcp/4ZXF1PrDkEaJvXpn/images/quickstart-developer.png?fit=max&auto=format&n=4ZXF1PrDkEaJvXpn&q=85&s=0fb595490a2f9e15c0301e771a57446c" alt="Developer settings showing Edit Config button" width="1688" height="534" data-path="images/quickstart-developer.png" />
</Frame>
This action creates a new configuration file if one doesn't exist, or opens your existing configuration. The file is located at:
* **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
* **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
</Step>
<Step title="Configure the Filesystem Server">
Replace the contents of the configuration file with the following JSON structure. This configuration tells Claude Desktop to start the Filesystem Server with access to specific directories:
<CodeGroup>
```json macOS theme={null}
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"/Users/username/Desktop",
"/Users/username/Downloads"
]
}
}
}
```
```json Windows theme={null}
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"C:\\Users\\username\\Desktop",
"C:\\Users\\username\\Downloads"
]
}
}
}
```
</CodeGroup>
Replace `username` with your actual computer username. The paths listed in the `args` array specify which directories the Filesystem Server can access. You can modify these paths or add additional directories as needed.
<Tip>
**Understanding the Configuration**
* `"filesystem"`: A friendly name for the server that appears in Claude Desktop
* `"command": "npx"`: Uses Node.js's npx tool to run the server
* `"-y"`: Automatically confirms the installation of the server package
* `"@modelcontextprotocol/server-filesystem"`: The package name of the Filesystem Server
* The remaining arguments: Directories the server is allowed to access
</Tip>
<Warning>
**Security Consideration**
Only grant access to directories you're comfortable with Claude reading and modifying. The server runs with your user account permissions, so it can perform any file operations you can perform manually.
</Warning>
</Step>
<Step title="Restart Claude Desktop">
After saving the configuration file, completely quit Claude Desktop and restart it. The application needs to restart to load the new configuration and start the MCP server.
Upon successful restart, click the "Add files, connectors and more" indicator <img src="https://mintcdn.com/mcp/cpXzQjUOzyH0mCNH/images/claude-add-files-connectors-and-more.png?fit=max&auto=format&n=cpXzQjUOzyH0mCNH&q=85&s=53acf21f6807dd5323b70b84b5d98d8a" style={{display: 'inline', margin: 0, height: '1.3em'}} width="33" height="33" data-path="images/claude-add-files-connectors-and-more.png" /> in the bottom-left corner of the conversation input box:
<Frame>
<img src="https://mintcdn.com/mcp/akpggzunDlIcY2im/images/quickstart-slider.png?fit=max&auto=format&n=akpggzunDlIcY2im&q=85&s=a1ebd4259cff2a7472171885f2edc035" alt="Claude Desktop interface showing MCP server indicator" width="1414" height="410" data-path="images/quickstart-slider.png" />
</Frame>
Click on this indicator, then scroll over "Connectors" and click "Manage connectors". Select "filesystem" from the connector list to view the the Filesystem Server's available tools:
<Frame style={{ textAlign: "center" }}>
<img src="https://mintcdn.com/mcp/cpXzQjUOzyH0mCNH/images/quickstart-tools.png?fit=max&auto=format&n=cpXzQjUOzyH0mCNH&q=85&s=212a63d76daba170d52db0d2f6f582be" width="400" alt="Available filesystem tools in Claude Desktop" data-path="images/quickstart-tools.png" />
</Frame>
If the Filesystem Server doesn't connect, refer to the [Troubleshooting](#troubleshooting) section for debugging steps.
</Step>
</Steps>
## Using the Filesystem Server
With the Filesystem Server connected, Claude can now interact with your file system. Try these example requests to explore the capabilities:
### File Management Examples
* **"Can you write a poem and save it to my desktop?"** - Claude will compose a poem and create a new text file on your desktop
* **"What work-related files are in my downloads folder?"** - Claude will scan your downloads and identify work-related documents
* **"Please organize all images on my desktop into a new folder called 'Images'"** - Claude will create a folder and move image files into it
### How Approval Works
Before executing any file system operation, Claude will request your approval. This ensures you maintain control over all actions:
<Frame style={{ textAlign: "center" }}>
<img src="https://mintcdn.com/mcp/4ZXF1PrDkEaJvXpn/images/quickstart-approve.png?fit=max&auto=format&n=4ZXF1PrDkEaJvXpn&q=85&s=98cc6e9dfe885fbd6e9bfae40601e494" width="500" alt="Claude requesting approval to perform a file operation" data-path="images/quickstart-approve.png" />
</Frame>
Review each request carefully before approving. You can always deny a request if you're not comfortable with the proposed action.
## Troubleshooting
If you encounter issues setting up or using the Filesystem Server, these solutions address common problems:
<AccordionGroup>
<Accordion title="Server not showing up in Claude / hammer icon missing">
1. Restart Claude Desktop completely
2. Check your `claude_desktop_config.json` file syntax
3. Make sure the file paths included in `claude_desktop_config.json` are valid and that they are absolute and not relative
4. Look at [logs](#getting-logs-from-claude-for-desktop) to see why the server is not connecting
5. In your command line, try manually running the server (replacing `username` as you did in `claude_desktop_config.json`) to see if you get any errors:
<CodeGroup>
```bash macOS/Linux theme={null}
npx -y @modelcontextprotocol/server-filesystem /Users/username/Desktop /Users/username/Downloads
```
```powershell Windows theme={null}
npx -y @modelcontextprotocol/server-filesystem C:\Users\username\Desktop C:\Users\username\Downloads
```
</CodeGroup>
</Accordion>
<Accordion title="Getting logs from Claude Desktop">
Claude.app logging related to MCP is written to log files in:
* macOS: `~/Library/Logs/Claude`
* Windows: `%APPDATA%\Claude\logs`
* `mcp.log` will contain general logging about MCP connections and connection failures.
* Files named `mcp-server-SERVERNAME.log` will contain error (stderr) logging from the named server.
You can run the following command to list recent logs and follow along with any new ones (on Windows, it will only show recent logs):
<CodeGroup>
```bash macOS/Linux theme={null}
tail -n 20 -f ~/Library/Logs/Claude/mcp*.log
```
```powershell Windows theme={null}
type "%APPDATA%\Claude\logs\mcp*.log"
```
</CodeGroup>
</Accordion>
<Accordion title="Tool calls failing silently">
If Claude attempts to use the tools but they fail:
1. Check Claude's logs for errors
2. Verify your server builds and runs without errors
3. Try restarting Claude Desktop
</Accordion>
<Accordion title="None of this is working. What do I do?">
Please refer to our [debugging guide](/docs/2025-03-26/tools/debugging) for better debugging tools and more detailed guidance.
</Accordion>
<Accordion title="ENOENT error and `${APPDATA}` in paths on Windows">
If your configured server fails to load, and you see within its logs an error referring to `${APPDATA}` within a path, you may need to add the expanded value of `%APPDATA%` to your `env` key in `claude_desktop_config.json`:
```json theme={null}
{
"brave-search": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-brave-search"],
"env": {
"APPDATA": "C:\\Users\\user\\AppData\\Roaming\\",
"BRAVE_API_KEY": "..."
}
}
}
```
With this change in place, launch Claude Desktop once again.
<Warning>
**npm should be installed globally**
The `npx` command may continue to fail if you have not installed npm globally. If npm is already installed globally, you will find `%APPDATA%\npm` exists on your system. If not, you can install npm globally by running the following command:
```bash theme={null}
npm install -g npm
```
</Warning>
</Accordion>
</AccordionGroup>
## Next Steps
Now that you've successfully connected Claude Desktop to a local MCP server, explore these options to expand your setup:
<CardGroup cols={2}>
<Card title="Explore other servers" icon="grid" href="https://github.com/modelcontextprotocol/servers">
Browse our collection of official and community-created MCP servers for
additional capabilities
</Card>
<Card title="Build your own server" icon="code" href="/docs/2025-03-26/develop/build-server">
Create custom MCP servers tailored to your specific workflows and
integrations
</Card>
<Card title="Connect to remote servers" icon="cloud" href="/docs/2025-03-26/develop/connect-remote-servers">
Learn how to connect Claude to remote MCP servers for cloud-based tools and
services
</Card>
<Card title="Understand the protocol" icon="book" href="/docs/2025-03-26/learn/architecture">
Dive deeper into how MCP works and its architecture
</Card>
</CardGroup>
docs/2025-03-26/develop/connect-remote-servers New page · 118 lines, new page
# Connect to remote MCP Servers ## Understanding Remote MCP Servers ## What are Custom Connectors? ## Connecting to a Remote MCP Server ## Best Practices for Using Remote MCP Servers ## Next Steps
A whole new page. There's nothing to diff it against, so here is what it says.
# Connect to remote MCP Servers
> Learn how to connect Claude to remote MCP servers and extend its capabilities with internet-hosted tools and data sources
Remote MCP servers extend AI applications' capabilities beyond your local environment, providing access to internet-hosted tools, services, and data sources. By connecting to remote MCP servers, you transform AI assistants from helpful tools into informed teammates capable of handling complex, multi-step projects with real-time access to external resources.
Many clients now support remote MCP servers, enabling a wide range of integration possibilities. This guide demonstrates how to connect to remote MCP servers using [Claude](https://claude.ai/) as an example, one of the many clients that support MCP. While we focus on Claude's implementation through Custom Connectors, the concepts apply broadly to other MCP-compatible clients.
## Understanding Remote MCP Servers
Remote MCP servers function similarly to local MCP servers but are hosted on the internet rather than your local machine. They expose tools, prompts, and resources that Claude can use to perform tasks on your behalf. These servers can integrate with various services such as project management tools, documentation systems, code repositories, and any other API-enabled service.
The key advantage of remote MCP servers is their accessibility. Unlike local servers that require installation and configuration on each device, remote servers are available from any MCP client with an internet connection. This makes them ideal for web-based AI applications, integrations that emphasize ease of use, and services that require server-side processing or authentication.
## What are Custom Connectors?
Custom Connectors serve as the bridge between Claude and remote MCP servers. They allow you to connect Claude directly to the tools and data sources that matter most to your workflows, enabling Claude to operate within your favorite software and draw insights from the complete context of your external tools.
With Custom Connectors, you can:
* [Connect Claude to existing remote MCP servers](https://support.anthropic.com/en/articles/11175166-getting-started-with-custom-connectors-using-remote-mcp) provided by third-party developers
* [Build your own remote MCP servers to connect with any tool](https://support.anthropic.com/en/articles/11503834-building-custom-connectors-via-remote-mcp-servers)
## Connecting to a Remote MCP Server
The process of connecting Claude to a remote MCP server involves adding a Custom Connector through the [Claude interface](https://claude.ai/). This establishes a secure connection between Claude and your chosen remote server.
<Steps>
<Step title="Navigate to Connector Settings">
Open Claude in your browser and navigate to the settings page. You can access this by clicking on your profile icon and selecting "Settings" from the dropdown menu. Once in settings, locate and click on the "Connectors" section in the sidebar.
This will display your currently configured connectors and provide options to add new ones.
</Step>
<Step title="Add a Custom Connector">
In the Connectors section, scroll to the bottom where you'll find the "Add custom connector" button. Click this button to begin the connection process.
<Frame>
<img src="https://mintcdn.com/mcp/4ZXF1PrDkEaJvXpn/images/quickstart-remote/1-add-connector.png?fit=max&auto=format&n=4ZXF1PrDkEaJvXpn&q=85&s=b5ae9b23164875bbaa3aff4c178cdc64" alt="Add custom connector button in Claude settings" width="1038" height="809" data-path="images/quickstart-remote/1-add-connector.png" />
</Frame>
A dialog will appear prompting you to enter the remote MCP server URL. This URL should be provided by the server developer or administrator. Enter the complete URL, ensuring it includes the proper protocol (https\://) and any necessary path components.
<Frame>
<img src="https://mintcdn.com/mcp/4ZXF1PrDkEaJvXpn/images/quickstart-remote/2-connect.png?fit=max&auto=format&n=4ZXF1PrDkEaJvXpn&q=85&s=0934f16d8e016cade8e560c8f89d011b" alt="Dialog for entering remote MCP server URL" width="1616" height="282" data-path="images/quickstart-remote/2-connect.png" />
</Frame>
After entering the URL, click "Add" to proceed with the connection.
</Step>
<Step title="Complete Authentication">
Most remote MCP servers require authentication to ensure secure access to their resources. The authentication process varies depending on the server implementation but commonly involves OAuth, API keys, or username/password combinations.
<Frame>
<img src="https://mintcdn.com/mcp/4ZXF1PrDkEaJvXpn/images/quickstart-remote/3-auth.png?fit=max&auto=format&n=4ZXF1PrDkEaJvXpn&q=85&s=89af6e1b85718637231388697cc7b015" alt="Authentication screen for remote MCP server" width="490" height="806" data-path="images/quickstart-remote/3-auth.png" />
</Frame>
Follow the authentication prompts provided by the server. This may redirect you to a third-party authentication provider or display a form within Claude. Once authentication is complete, Claude will establish a secure connection to the remote server.
</Step>
<Step title="Access Resources and Prompts">
After successful connection, the remote server's resources and prompts become available in your Claude conversations. You can access these by clicking the paperclip icon in the message input area, which opens the attachment menu.
<Frame>
<img src="https://mintcdn.com/mcp/cpXzQjUOzyH0mCNH/images/quickstart-remote/4-select-resources-menu.png?fit=max&auto=format&n=cpXzQjUOzyH0mCNH&q=85&s=e5fa85174f8acbadbd709bac66f42d5c" alt="Attachment menu showing available resources" width="735" height="378" data-path="images/quickstart-remote/4-select-resources-menu.png" />
</Frame>
The menu displays all available resources and prompts from your connected servers. Select the items you want to include in your conversation. These resources provide Claude with context and information from your external tools.
<Frame>
<img src="https://mintcdn.com/mcp/cpXzQjUOzyH0mCNH/images/quickstart-remote/5-select-prompts-resources.png?fit=max&auto=format&n=cpXzQjUOzyH0mCNH&q=85&s=68722669d9e18252756885c703e4f221" alt="Selecting specific resources and prompts from the menu" width="648" height="529" data-path="images/quickstart-remote/5-select-prompts-resources.png" />
</Frame>
</Step>
<Step title="Configure Tool Permissions">
Remote MCP servers often expose multiple tools with varying capabilities. You can control which tools Claude is allowed to use by configuring permissions in the connector settings. This ensures Claude only performs actions you've explicitly authorized.
<Frame>
<img src="https://mintcdn.com/mcp/cpXzQjUOzyH0mCNH/images/quickstart-remote/6-configure-tools.png?fit=max&auto=format&n=cpXzQjUOzyH0mCNH&q=85&s=5cfd8b2c5d06e7e3699eac24c68d090e" alt="Tool permission configuration interface" width="604" height="745" data-path="images/quickstart-remote/6-configure-tools.png" />
</Frame>
Navigate back to the Connectors settings and click on your connected server. Here you can enable or disable specific tools, set usage limits, and configure other security parameters according to your needs.
</Step>
</Steps>
## Best Practices for Using Remote MCP Servers
When working with remote MCP servers, consider these recommendations to ensure a secure and efficient experience:
**Security considerations**: Always verify the authenticity of remote MCP servers before connecting. Only connect to servers from trusted sources, and review the permissions requested during authentication. Be cautious about granting access to sensitive data or systems.
**Managing multiple connectors**: You can connect to multiple remote MCP servers simultaneously. Organize your connectors by purpose or project to maintain clarity. Regularly review and remove connectors you no longer use to keep your workspace organized and secure.
## Next Steps
Now that you've connected Claude to a remote MCP server, you can explore its capabilities in your conversations. Try using the connected tools to automate tasks, access external data, or integrate with your existing workflows.
<CardGroup cols={2}>
<Card title="Build your own remote server" icon="cloud" href="https://support.anthropic.com/en/articles/11503834-building-custom-connectors-via-remote-mcp-servers">
Create custom remote MCP servers to integrate with proprietary tools and
services
</Card>
<Card title="Explore available servers" icon="grid" href="https://github.com/modelcontextprotocol/servers">
Browse our collection of official and community-created MCP servers
</Card>
<Card title="Connect local servers" icon="computer" href="/docs/2025-03-26/develop/connect-local-servers">
Learn how to connect Claude Desktop to local MCP servers for direct system
access
</Card>
<Card title="Understand the architecture" icon="book" href="/docs/2025-03-26/learn/architecture">
Dive deeper into how MCP works and its architecture
</Card>
</CardGroup>
Remote MCP servers unlock powerful possibilities for extending Claude's capabilities. As you become familiar with these integrations, you'll discover new ways to streamline your workflows and accomplish complex tasks more efficiently.
docs/2025-03-26/getting-started/intro New page · 54 lines, new page
# What is the Model Context Protocol (MCP)? ## What can MCP enable? ## Why does MCP matter? ## Broad ecosystem support ## Start Building ## Learn more
A whole new page. There's nothing to diff it against, so here is what it says.
# What is the Model Context Protocol (MCP)?
MCP (Model Context Protocol) is an open-source standard for connecting AI applications to external systems.
Using MCP, AI applications like Claude or ChatGPT can connect to data sources (e.g. local files, databases), tools (e.g. search engines, calculators) and workflows (e.g. specialized prompts)—enabling them to access key information and perform tasks.
Think of MCP like a USB-C port for AI applications. Just as USB-C provides a standardized way to connect electronic devices, MCP provides a standardized way to connect AI applications to external systems.
<Frame>
<img src="https://mintcdn.com/mcp/bEUxYpZqie0DsluH/images/mcp-simple-diagram.png?fit=max&auto=format&n=bEUxYpZqie0DsluH&q=85&s=35268aa0ad50b8c385913810e7604550" width="3840" height="1500" data-path="images/mcp-simple-diagram.png" />
</Frame>
## What can MCP enable?
* Agents can access your Google Calendar and Notion, acting as a more personalized AI assistant.
* Claude Code can generate an entire web app using a Figma design.
* Enterprise chatbots can connect to multiple databases across an organization, empowering users to analyze data using chat.
* AI models can create 3D designs on Blender and print them out using a 3D printer.
## Why does MCP matter?
Depending on where you sit in the ecosystem, MCP can have a range of benefits.
* **Developers**: MCP reduces development time and complexity when building, or integrating with, an AI application or agent.
* **AI applications or agents**: MCP gives them access to an ecosystem of data sources, tools and apps, which enhances their capabilities and improves the end-user experience.
* **End-users**: MCP results in more capable AI applications or agents that can access user data and take actions on the user's behalf when necessary.
## Broad ecosystem support
MCP is an open protocol supported across a wide range of clients and servers. AI assistants like [Claude](https://claude.com/docs/connectors/building) and [ChatGPT](https://developers.openai.com/api/docs/mcp/), development tools like [Visual Studio Code](https://code.visualstudio.com/docs/copilot/chat/mcp-servers), [Cursor](https://cursor.com/docs/context/mcp), [MCPJam](https://docs.mcpjam.com/getting-started), and many others all support MCP — making it easy to build once and integrate everywhere.
## Start Building
<CardGroup cols={2}>
<Card title="Build servers" icon="server" href="/docs/2025-03-26/develop/build-server">
Create MCP servers to expose your data and tools
</Card>
<Card title="Build clients" icon="computer" href="/docs/2025-03-26/develop/build-client">
Develop applications that connect to MCP servers
</Card>
<Card title="Build MCP Apps" icon="puzzle-piece" href="/extensions/apps/overview">
Build interactive apps that run inside AI clients
</Card>
</CardGroup>
## Learn more
<CardGroup cols={2}>
<Card title="Understand concepts" icon="book" href="/docs/2025-03-26/learn/architecture">
Learn the core concepts and architecture of MCP
</Card>
</CardGroup>
docs/2025-03-26/learn/architecture New page · 459 lines, new page
# Architecture overview ## Scope ## Concepts of MCP ### Participants ### Layers #### Data layer #### Transport layer ### Data Layer Protocol #### Lifecycle management #### Primitives #### Notifications ## Example ### Data Layer
A whole new page. There's nothing to diff it against, so here is what it says.
# Architecture overview
This overview of the Model Context Protocol (MCP) discusses its [scope](#scope) and [core concepts](#concepts-of-mcp), and provides an [example](#example) demonstrating each core concept.
Because MCP SDKs abstract away many concerns, most developers will likely find the [data layer protocol](#data-layer-protocol) section to be the most useful. It discusses how MCP servers can provide context to an AI application.
For specific implementation details, please refer to the documentation for your [language-specific SDK](/docs/2025-03-26/sdk).
## Scope
The Model Context Protocol includes the following projects:
* [MCP Specification](https://modelcontextprotocol.io/specification/latest): A specification of MCP that outlines the implementation requirements for clients and servers.
* [MCP SDKs](/docs/2025-03-26/sdk): SDKs for different programming languages that implement MCP.
* **MCP Development Tools**: Tools for developing MCP servers and clients, including the [MCP Inspector](https://github.com/modelcontextprotocol/inspector)
* [MCP Reference Server Implementations](https://github.com/modelcontextprotocol/servers): Reference implementations of MCP servers.
<Note>
MCP focuses solely on the protocol for context exchange—it does not dictate
how AI applications use LLMs or manage the provided context.
</Note>
## Concepts of MCP
### Participants
MCP follows a client-server architecture where an MCP host — an AI application like [Claude Code](https://www.anthropic.com/claude-code) or [Claude Desktop](https://www.claude.ai/download) — establishes connections to one or more MCP servers. The MCP host accomplishes this by creating one MCP client for each MCP server. Each MCP client maintains a dedicated connection with its corresponding MCP server.
Local MCP servers that use the STDIO transport typically serve a single MCP client, whereas remote MCP servers that use the Streamable HTTP transport will typically serve many MCP clients.
The key participants in the MCP architecture are:
* **MCP Host**: The AI application that coordinates and manages one or multiple MCP clients
* **MCP Client**: A component that maintains a connection to an MCP server and obtains context from an MCP server for the MCP host to use
* **MCP Server**: A program that provides context to MCP clients
**For example**: Visual Studio Code acts as an MCP host. When Visual Studio Code establishes a connection to an MCP server, such as the [Sentry MCP server](https://docs.sentry.io/product/sentry-mcp/), the Visual Studio Code runtime instantiates an MCP client object that maintains the connection to the Sentry MCP server.
When Visual Studio Code subsequently connects to another MCP server, such as the [local filesystem server](https://github.com/modelcontextprotocol/servers/tree/main/src/filesystem), the Visual Studio Code runtime instantiates an additional MCP client object to maintain this connection.
```mermaid theme={null}
graph TB
subgraph "MCP Host (AI Application)"
Client1["MCP Client 1"]
Client2["MCP Client 2"]
Client3["MCP Client 3"]
Client4["MCP Client 4"]
end
ServerA["MCP Server A - Local<br/>(e.g. Filesystem)"]
ServerB["MCP Server B - Local<br/>(e.g. Database)"]
ServerC["MCP Server C - Remote<br/>(e.g. Sentry)"]
Client1 ---|"Dedicated<br/>connection"| ServerA
Client2 ---|"Dedicated<br/>connection"| ServerB
Client3 ---|"Dedicated<br/>connection"| ServerC
Client4 ---|"Dedicated<br/>connection"| ServerC
```
Note that **MCP server** refers to the program that serves context data, regardless of
where it runs. MCP servers can execute locally or remotely. For example, when
Claude Desktop launches the [filesystem
server](https://github.com/modelcontextprotocol/servers/tree/main/src/filesystem),
the server runs locally on the same machine because it uses the STDIO
transport. This is commonly referred to as a "local" MCP server. The official
[Sentry MCP server](https://docs.sentry.io/product/sentry-mcp/) runs on the
Sentry platform, and uses the Streamable HTTP transport. This is commonly
referred to as a "remote" MCP server.
### Layers
MCP consists of two layers:
* **Data layer**: Defines the JSON-RPC based protocol for client-server communication, including lifecycle management, and core primitives, such as tools, resources, prompts and notifications.
* **Transport layer**: Defines the communication mechanisms and channels that enable data exchange between clients and servers, including transport-specific connection establishment, message framing, and authorization.
Conceptually the data layer is the inner layer, while the transport layer is the outer layer.
#### Data layer
The data layer implements a [JSON-RPC 2.0](https://www.jsonrpc.org/) based exchange protocol that defines the message structure and semantics.
This layer includes:
* **Lifecycle management**: Handles connection initialization, capability negotiation, and connection termination between clients and servers
* **Server features**: Enables servers to provide core functionality including tools for AI actions, resources for context data, and prompts for interaction templates from and to the client
* **Client features**: Enables servers to ask the client to sample from the host LLM and log messages to the client
* **Utility features**: Supports additional capabilities like notifications for real-time updates and progress tracking for long-running operations
#### Transport layer
The transport layer manages communication channels and authentication between clients and servers. It handles connection establishment, message framing, and secure communication between MCP participants.
MCP supports two transport mechanisms:
* **Stdio transport**: Uses standard input/output streams for direct process communication between local processes on the same machine, providing optimal performance with no network overhead.
* **Streamable HTTP transport**: Uses HTTP POST for client-to-server messages with optional Server-Sent Events for streaming capabilities. This transport enables remote server communication and supports standard HTTP authentication methods including bearer tokens, API keys, and custom headers. MCP recommends using OAuth to obtain authentication tokens.
The transport layer abstracts communication details from the protocol layer, enabling the same JSON-RPC 2.0 message format across all transport mechanisms.
### Data Layer Protocol
A core part of MCP is defining the schema and semantics between MCP clients and MCP servers. Developers will likely find the data layer — in particular, the set of [primitives](#primitives) — to be the most interesting part of MCP. It is the part of MCP that defines the ways developers can share context from MCP servers to MCP clients.
MCP uses [JSON-RPC 2.0](https://www.jsonrpc.org/) as its underlying RPC protocol. Client and servers send requests to each other and respond accordingly. Notifications can be used when no response is required.
#### Lifecycle management
MCP is a <Tooltip tip="A subset of MCP can be made stateless using the Streamable HTTP transport">stateful protocol</Tooltip> that requires lifecycle management. The purpose of lifecycle management is to negotiate the <Tooltip tip="Features and operations that a client or server supports, such as tools, resources, or prompts">capabilities</Tooltip> that both client and server support. Detailed information can be found in the [specification](/specification/2025-03-26/basic/lifecycle), and the [example](#example) showcases the initialization sequence.
#### Primitives
MCP primitives are the most important concept within MCP. They define what clients and servers can offer each other. These primitives specify the types of contextual information that can be shared with AI applications and the range of actions that can be performed.
MCP defines three core primitives that *servers* can expose:
* **Tools**: Executable functions that AI applications can invoke to perform actions (e.g., file operations, API calls, database queries)
* **Resources**: Data sources that provide contextual information to AI applications (e.g., file contents, database records, API responses)
* **Prompts**: Reusable templates that help structure interactions with language models (e.g., system prompts, few-shot examples)
Each primitive type has associated methods for discovery (`*/list`), retrieval (`*/get`), and in some cases, execution (`tools/call`).
MCP clients will use the `*/list` methods to discover available primitives. For example, a client can first list all available tools (`tools/list`) and then execute them. This design allows listings to be dynamic.
As a concrete example, consider an MCP server that provides context about a database. It can expose tools for querying the database, a resource that contains the schema of the database, and a prompt that includes few-shot examples for interacting with the tools.
For more details about server primitives see [server concepts](./server-concepts).
MCP also defines primitives that *clients* can expose. These primitives allow MCP server authors to build richer interactions.
* **Sampling**: Allows servers to request language model completions from the client's AI application. This is useful when server authors want access to a language model, but want to stay model-independent and not include a language model SDK in their MCP server. They can use the `sampling/createMessage` method to request a language model completion from the client's AI application.
* **Logging**: Enables servers to send log messages to clients for debugging and monitoring purposes.
For more details about client primitives see [client concepts](./client-concepts).
Besides server and client primitives, the protocol offers cross-cutting utility primitives that augment how requests are executed:
* **Tasks (Experimental)**: Durable execution wrappers that enable deferred result retrieval and status tracking for MCP requests (e.g., expensive computations, workflow automation, batch processing, multi-step operations)
#### Notifications
The protocol supports real-time notifications to enable dynamic updates between servers and clients. For example, when a server's available tools change—such as when new functionality becomes available or existing tools are modified—the server can send tool update notifications to inform connected clients about these changes. Notifications are sent as JSON-RPC 2.0 notification messages (without expecting a response) and enable MCP servers to provide real-time updates to connected clients.
## Example
### Data Layer
This section provides a step-by-step walkthrough of an MCP client-server interaction, focusing on the data layer protocol. We'll demonstrate the lifecycle sequence, tool operations, and notifications using JSON-RPC 2.0 messages.
<Steps>
<Step title="Initialization (Lifecycle Management)">
MCP begins with lifecycle management through a capability negotiation handshake. As described in the [lifecycle management](#lifecycle-management) section, the client sends an `initialize` request to establish the connection and negotiate supported features.
<CodeGroup>
```json Initialize Request theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2025-03-26",
"capabilities": {
"sampling": {}
},
"clientInfo": {
"name": "example-client",
"version": "1.0.0"
}
}
}
```
```json Initialize Response theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"protocolVersion": "2025-03-26",
"capabilities": {
"tools": {
"listChanged": true
},
"resources": {}
},
"serverInfo": {
"name": "example-server",
"version": "1.0.0"
}
}
}
```
</CodeGroup>
#### Understanding the Initialization Exchange
The initialization process is a key part of MCP's lifecycle management and serves several critical purposes:
1. **Protocol Version Negotiation**: The `protocolVersion` field (e.g., "2025-03-26") ensures both client and server are using compatible protocol versions. This prevents communication errors that could occur when different versions attempt to interact. If a mutually compatible version is not negotiated, the connection should be terminated.
2. **Capability Discovery**: The `capabilities` object allows each party to declare what features they support, including which [primitives](#primitives) they can handle (tools, resources, prompts) and whether they support features like [notifications](#notifications). This enables efficient communication by avoiding unsupported operations.
3. **Identity Exchange**: The `clientInfo` and `serverInfo` objects provide identification and versioning information for debugging and compatibility purposes.
In this example, the capability negotiation demonstrates how MCP primitives are declared:
**Client Capabilities**:
* `"sampling": {}` - The client declares it can handle server sampling requests (can receive `sampling/createMessage` method calls)
**Server Capabilities**:
* `"tools": {"listChanged": true}` - The server supports the tools primitive AND can send `tools/list_changed` notifications when its tool list changes
* `"resources": {}` - The server also supports the resources primitive (can handle `resources/list` and `resources/read` methods)
After successful initialization, the client sends a notification to indicate it's ready:
```json Notification theme={null}
{
"jsonrpc": "2.0",
"method": "notifications/initialized"
}
```
#### How This Works in AI Applications
During initialization, the AI application's MCP client manager establishes connections to configured servers and stores their capabilities for later use. The application uses this information to determine which servers can provide specific types of functionality (tools, resources, prompts) and whether they support real-time updates.
```python Pseudo-code for AI application initialization theme={null}
# Pseudo Code
async with stdio_client(server_config) as (read, write):
async with ClientSession(read, write) as session:
init_response = await session.initialize()
if init_response.capabilities.tools:
app.register_mcp_server(session, supports_tools=True)
app.set_server_ready(session)
```
</Step>
<Step title="Tool Discovery (Primitives)">
Now that the connection is established, the client can discover available tools by sending a `tools/list` request. This request is fundamental to MCP's tool discovery mechanism — it allows clients to understand what tools are available on the server before attempting to use them.
<CodeGroup>
```json Tools List Request theme={null}
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/list"
}
```
```json Tools List Response theme={null}
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"tools": [
{
"name": "calculator_arithmetic",
"title": "Calculator",
"description": "Perform mathematical calculations including basic arithmetic, trigonometric functions, and algebraic operations",
"inputSchema": {
"type": "object",
"properties": {
"expression": {
"type": "string",
"description": "Mathematical expression to evaluate (e.g., '2 + 3 * 4', 'sin(30)', 'sqrt(16)')"
}
},
"required": ["expression"]
}
},
{
"name": "weather_current",
"title": "Weather Information",
"description": "Get current weather information for any location worldwide",
"inputSchema": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "City name, address, or coordinates (latitude,longitude)"
},
"units": {
"type": "string",
"enum": ["metric", "imperial", "kelvin"],
"description": "Temperature units to use in response",
"default": "metric"
}
},
"required": ["location"]
}
}
]
}
}
```
</CodeGroup>
#### Understanding the Tool Discovery Request
The `tools/list` request is simple, containing no parameters.
#### Understanding the Tool Discovery Response
Cut at 300 lines. The page has the rest.
docs/2025-03-26/learn/client-concepts New page · 146 lines, new page
# Understanding MCP clients ## Core Client Features ### Roots #### Overview #### Example: Travel Planning Workspace #### Design Philosophy #### User Interaction Model ### Sampling #### Overview #### Example: Flight Analysis Tool #### User Interaction Model
A whole new page. There's nothing to diff it against, so here is what it says.
# Understanding MCP clients
MCP clients are instantiated by host applications to communicate with particular MCP servers. The host application, like Claude.ai or an IDE, manages the overall user experience and coordinates multiple clients. Each client handles one direct communication with one server.
Understanding the distinction is important: the *host* is the application users interact with, while *clients* are the protocol-level components that enable server connections.
## Core Client Features
In addition to making use of context provided by servers, clients may provide several features to servers. These client features allow server authors to build richer interactions.
| Feature | Explanation | Example |
| ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| **Roots** | Roots allow clients to specify which directories servers should focus on, communicating intended scope through a coordination mechanism. | A server for booking travel may be given access to a specific directory, from which it can read a user's calendar. |
| **Sampling** | Sampling allows servers to request LLM completions through the client, enabling an agentic workflow. This approach puts the client in complete control of user permissions and security measures. | A server for booking travel may send a list of flights to an LLM and request that the LLM pick the best flight for the user. |
### Roots
Roots define filesystem boundaries for server operations, allowing clients to specify which directories servers should focus on.
#### Overview
Roots are a mechanism for clients to communicate filesystem access boundaries to servers. They consist of file URIs that indicate directories where servers can operate, helping servers understand the scope of available files and folders. While roots communicate intended boundaries, they do not enforce security restrictions. Actual security must be enforced at the operating system level, via file permissions and/or sandboxing.
**Root structure:**
```json theme={null}
{
"uri": "file:///Users/agent/travel-planning",
"name": "Travel Planning Workspace"
}
```
Roots are exclusively filesystem paths and always use the `file://` URI scheme. They help servers understand project boundaries, workspace organization, and accessible directories. The roots list can be updated dynamically as users work with different projects or folders, with servers receiving notifications through `roots/list_changed` when boundaries change.
#### Example: Travel Planning Workspace
A travel agent working with multiple client trips benefits from roots to organize filesystem access. Consider a workspace with different directories for various aspects of travel planning.
The client provides filesystem roots to the travel planning server:
* `file:///Users/agent/travel-planning` - Main workspace containing all travel files
* `file:///Users/agent/travel-templates` - Reusable itinerary templates and resources
* `file:///Users/agent/client-documents` - Client passports and travel documents
When the agent creates a Barcelona itinerary, well-behaved servers respect these boundaries—accessing templates, saving the new itinerary, and referencing client documents within the specified roots. Servers typically access files within roots by using relative paths from the root directories or by utilizing file search tools that respect the root boundaries.
If the agent opens an archive folder like `file:///Users/agent/archive/2023-trips`, the client updates the roots list via `roots/list_changed`.
For a complete implementation of a server that respects roots, see the [filesystem server](https://github.com/modelcontextprotocol/servers/tree/main/src/filesystem) in the official servers repository.
#### Design Philosophy
Roots serve as a coordination mechanism between clients and servers, not a security boundary. The specification requires that servers "SHOULD respect root boundaries," and not that they "MUST enforce" them, because servers run code the client cannot control.
Roots work best when servers are trusted or vetted, users understand their advisory nature, and the goal is preventing accidents rather than stopping malicious behavior. They excel at context scoping (telling servers where to focus), accident prevention (helping well-behaved servers stay in bounds), and workflow organization (such as managing project boundaries automatically).
#### User Interaction Model
Roots are typically managed automatically by host applications based on user actions, though some applications may expose manual root management:
**Automatic root detection**: When users open folders, clients automatically expose them as roots. Opening a travel workspace allows the client to expose that directory as a root, helping servers understand which itineraries and documents are in scope for the current work.
**Manual root configuration**: Advanced users can specify roots through configuration. For example, adding `/travel-templates` for reusable resources while excluding directories with financial records.
### Sampling
Sampling allows servers to request language model completions through the client, enabling agentic behaviors while maintaining security and user control.
#### Overview
Sampling enables servers to perform AI-dependent tasks without directly integrating with or paying for AI models. Instead, servers can request that the client—which already has AI model access—handle these tasks on their behalf. This approach puts the client in complete control of user permissions and security measures. Because sampling requests occur within the context of other operations—like a tool analyzing data—and are processed as separate model calls, they maintain clear boundaries between different contexts, allowing for more efficient use of the context window.
**Sampling flow:**
```mermaid theme={null}
sequenceDiagram
participant LLM
participant User
participant Client
participant Server
Note over Server,Client: Server initiates sampling
Server->>Client: sampling/createMessage
Note over Client,User: Human-in-the-loop review
Client->>User: Present request for approval
User-->>Client: Review and approve/modify
Note over Client,LLM: Model interaction
Client->>LLM: Forward approved request
LLM-->>Client: Return generation
Note over Client,User: Response review
Client->>User: Present response for approval
User-->>Client: Review and approve/modify
Note over Server,Client: Complete request
Client-->>Server: Return approved response
```
The flow ensures security through multiple human-in-the-loop checkpoints. Users review and can modify both the initial request and the generated response before it returns to the server.
**Request parameters example:**
```typescript theme={null}
{
messages: [
{
role: "user",
content: "Analyze these flight options and recommend the best choice:\n" +
"[47 flights with prices, times, airlines, and layovers]\n" +
"User preferences: morning departure, max 1 layover"
}
],
modelPreferences: {
hints: [{
name: "claude-sonnet-4-20250514" // Suggested model
}],
costPriority: 0.3, // Less concerned about API cost
speedPriority: 0.2, // Can wait for thorough analysis
intelligencePriority: 0.9 // Need complex trade-off evaluation
},
systemPrompt: "You are a travel expert helping users find the best flights based on their preferences",
maxTokens: 1500
}
```
#### Example: Flight Analysis Tool
Consider a travel booking server with a tool called `findBestFlight` that uses sampling to analyze available flights and recommend the optimal choice. When a user asks "Book me the best flight to Barcelona next month," the tool needs AI assistance to evaluate complex trade-offs.
The tool queries airline APIs and gathers 47 flight options. It then requests AI assistance to analyze these options: "Analyze these flight options and recommend the best choice: \[47 flights with prices, times, airlines, and layovers] User preferences: morning departure, max 1 layover."
The client initiates the sampling request, allowing the AI to evaluate trade-offs—like cheaper red-eye flights versus convenient morning departures. The tool uses this analysis to present the top three recommendations.
#### User Interaction Model
While not a requirement, sampling is designed to allow human-in-the-loop control. Users can maintain oversight through several mechanisms:
**Approval controls**: Sampling requests may require explicit user consent. Clients can show what the server wants to analyze and why. Users can approve, deny, or modify requests.
**Transparency features**: Clients can display the exact prompt, model selection, and token limits, allowing users to review AI responses before they return to the server.
**Configuration options**: Users can set model preferences, configure auto-approval for trusted operations, or require approval for everything. Clients may provide options to redact sensitive information.
**Security considerations**: Both clients and servers must handle sensitive data appropriately during sampling. Clients should implement rate limiting and validate all message content. The human-in-the-loop design ensures that server-initiated AI interactions cannot compromise security or access sensitive data without explicit user consent.
docs/2025-03-26/learn/server-concepts New page · 281 lines, new page
# Understanding MCP servers ## Core Server Features ### Tools #### How Tools Work #### Example: Travel Booking #### User Interaction Model ### Resources #### How Resources Work #### Example: Getting Travel Planning Context #### Parameter Completion #### User Interaction Model ### Prompts #### How Prompts Work #### Example: Streamlined Workflows #### User Interaction Model ## Bringing Servers Together ### Example: Multi-Server Travel Planning #### The Complete Flow
A whole new page. There's nothing to diff it against, so here is what it says.
# Understanding MCP servers
MCP servers are programs that expose specific capabilities to AI applications through standardized protocol interfaces.
Common examples include file system servers for document access, database servers for data queries, GitHub servers for code management, Slack servers for team communication, and calendar servers for scheduling.
## Core Server Features
Servers provide functionality through three building blocks:
| Feature | Explanation | Examples | Who controls it |
| ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------ | --------------- |
| **Tools** | Functions that your LLM can actively call, and decides when to use them based on user requests. Tools can write to databases, call external APIs, modify files, or trigger other logic. | Search flights<br />Send messages<br />Create calendar events | Model |
| **Resources** | Passive data sources that provide read-only access to information for context, such as file contents, database schemas, or API documentation. | Retrieve documents<br />Access knowledge bases<br />Read calendars | Application |
| **Prompts** | Pre-built instruction templates that tell the model to work with specific tools and resources. | Plan a vacation<br />Summarize my meetings<br />Draft an email | User |
We will use a hypothetical scenario to demonstrate the role of each of these features, and show how they can work together.
### Tools
Tools enable AI models to perform actions. Each tool defines a specific operation with typed inputs and outputs. The model requests tool execution based on context.
#### How Tools Work
Tools are schema-defined interfaces that LLMs can invoke. MCP uses JSON Schema for validation. Each tool performs a single operation with clearly defined inputs and outputs. Tools may require user consent prior to execution, helping to ensure users maintain control over actions taken by a model.
**Protocol operations:**
| Method | Purpose | Returns |
| ------------ | ------------------------ | -------------------------------------- |
| `tools/list` | Discover available tools | Array of tool definitions with schemas |
| `tools/call` | Execute a specific tool | Tool execution result |
**Example tool definition:**
```typescript theme={null}
{
name: "searchFlights",
description: "Search for available flights",
inputSchema: {
type: "object",
properties: {
origin: { type: "string", description: "Departure city" },
destination: { type: "string", description: "Arrival city" },
date: { type: "string", format: "date", description: "Travel date" }
},
required: ["origin", "destination", "date"]
}
}
```
#### Example: Travel Booking
Tools enable AI applications to perform actions on behalf of users. In a travel planning scenario, the AI application might use several tools to help book a vacation:
**Flight Search**
```
searchFlights(origin: "NYC", destination: "Barcelona", date: "2024-06-15")
```
Queries multiple airlines and returns structured flight options.
**Calendar Blocking**
```
createCalendarEvent(title: "Barcelona Trip", startDate: "2024-06-15", endDate: "2024-06-22")
```
Marks the travel dates in the user's calendar.
**Email notification**
```
sendEmail(to: "[email protected]", subject: "Out of Office", body: "...")
```
Sends an automated out-of-office message to colleagues.
#### User Interaction Model
Tools are model-controlled, meaning AI models can discover and invoke them automatically. However, MCP emphasizes human oversight through several mechanisms.
For trust and safety, applications can implement user control through various mechanisms, such as:
* Displaying available tools in the UI, enabling users to define whether a tool should be made available in specific interactions
* Approval dialogs for individual tool executions
* Permission settings for pre-approving certain safe operations
* Activity logs that show all tool executions with their results
### Resources
Resources provide structured access to information that the AI application can retrieve and provide to models as context.
#### How Resources Work
Resources expose data from files, APIs, databases, or any other source that an AI needs to understand context. Applications can access this information directly and decide how to use it - whether that's selecting relevant portions, searching with embeddings, or passing it all to the model.
Each resource has a unique URI (e.g., `file:///path/to/document.md`) and declares its MIME type for appropriate content handling.
Resources support two discovery patterns:
* **Direct Resources** - fixed URIs that point to specific data. Example: `calendar://events/2024` - returns calendar availability for 2024
* **Resource Templates** - dynamic URIs with parameters for flexible queries. Example:
* `travel://activities/{city}/{category}` - returns activities by city and category
* `travel://activities/barcelona/museums` - returns all museums in Barcelona
Resource Templates include metadata such as title, description, and expected MIME type, making them discoverable and self-documenting.
**Protocol operations:**
| Method | Purpose | Returns |
| -------------------------- | ------------------------------- | -------------------------------------- |
| `resources/list` | List available direct resources | Array of resource descriptors |
| `resources/templates/list` | Discover resource templates | Array of resource template definitions |
| `resources/read` | Retrieve resource contents | Resource data with metadata |
| `resources/subscribe` | Monitor resource changes | Subscription confirmation |
#### Example: Getting Travel Planning Context
Continuing with the travel planning example, resources provide the AI application with access to relevant information:
* **Calendar data** (`calendar://events/2024`) - Checks user availability
* **Travel documents** (`file:///Documents/Travel/passport.pdf`) - Accesses important documents
* **Previous itineraries** (`trips://history/barcelona-2023`) - References past trips and preferences
The AI application retrieves these resources and decides how to process them, whether selecting a subset of data using embeddings or keyword search, or passing raw data directly to the model.
In this case, it provides calendar data, weather information, and travel preferences to the model, enabling it to check availability, look up weather patterns, and reference past travel preferences.
**Resource Template Examples:**
```json theme={null}
{
"uriTemplate": "weather://forecast/{city}/{date}",
"name": "weather-forecast",
"title": "Weather Forecast",
"description": "Get weather forecast for any city and date",
"mimeType": "application/json"
}
{
"uriTemplate": "travel://flights/{origin}/{destination}",
"name": "flight-search",
"title": "Flight Search",
"description": "Search available flights between cities",
"mimeType": "application/json"
}
```
These templates enable flexible queries. For weather data, users can access forecasts for any city/date combination. For flights, they can search routes between any two airports. When a user has input "NYC" as the `origin` airport and begins to input "Bar" as the `destination` airport, the system can suggest "Barcelona (BCN)" or "Barbados (BGI)".
#### Parameter Completion
Dynamic resources support parameter completion. For example:
* Typing "Par" as input for `weather://forecast/{city}` might suggest "Paris" or "Park City"
* Typing "JFK" for `flights://search/{airport}` might suggest "JFK - John F. Kennedy International"
The system helps discover valid values without requiring exact format knowledge.
#### User Interaction Model
Resources are application-driven, giving them flexibility in how they retrieve, process, and present available context. Common interaction patterns include:
* Tree or list views for browsing resources in familiar folder-like structures
* Search and filter interfaces for finding specific resources
* Automatic context inclusion or smart suggestions based on heuristics or AI selection
* Manual or bulk selection interfaces for including single or multiple resources
Applications are free to implement resource discovery through any interface pattern that suits their needs. The protocol doesn't mandate specific UI patterns, allowing for resource pickers with preview capabilities, smart suggestions based on current conversation context, bulk selection for including multiple resources, or integration with existing file browsers and data explorers.
### Prompts
Prompts provide reusable templates. They allow MCP server authors to provide parameterized prompts for a domain, or showcase how to best use the MCP server.
#### How Prompts Work
Prompts are structured templates that define expected inputs and interaction patterns. They are user-controlled, requiring explicit invocation rather than automatic triggering. Prompts can be context-aware, referencing available resources and tools to create comprehensive workflows. Similar to resources, prompts support parameter completion to help users discover valid argument values.
**Protocol operations:**
| Method | Purpose | Returns |
| -------------- | -------------------------- | ------------------------------------- |
| `prompts/list` | Discover available prompts | Array of prompt descriptors |
| `prompts/get` | Retrieve prompt details | Full prompt definition with arguments |
#### Example: Streamlined Workflows
Prompts provide structured templates for common tasks. In the travel planning context:
**"Plan a vacation" prompt:**
```json theme={null}
{
"name": "plan-vacation",
"title": "Plan a vacation",
"description": "Guide through vacation planning process",
"arguments": [
{ "name": "destination", "type": "string", "required": true },
{ "name": "duration", "type": "number", "description": "days" },
{ "name": "budget", "type": "number", "required": false },
{ "name": "interests", "type": "array", "items": { "type": "string" } }
]
}
```
Rather than unstructured natural language input, the prompt system enables:
1. Selection of the "Plan a vacation" template
2. Structured input: Barcelona, 7 days, \$3000, \["beaches", "architecture", "food"]
3. Consistent workflow execution based on the template
#### User Interaction Model
Prompts are user-controlled, requiring explicit invocation. The protocol gives implementers freedom to design interfaces that feel natural within their application. Key principles include:
* Easy discovery of available prompts
* Clear descriptions of what each prompt does
* Natural argument input with validation
* Transparent display of the prompt's underlying template
Applications typically expose prompts through various UI patterns such as:
* Slash commands (typing "/" to see available prompts like /plan-vacation)
* Command palettes for searchable access
* Dedicated UI buttons for frequently used prompts
* Context menus that suggest relevant prompts
## Bringing Servers Together
The real power of MCP emerges when multiple servers work together, combining their specialized capabilities through a unified interface.
### Example: Multi-Server Travel Planning
Consider a personalized AI travel planner application, with three connected servers:
* **Travel Server** - Handles flights, hotels, and itineraries
* **Weather Server** - Provides climate data and forecasts
* **Calendar/Email Server** - Manages schedules and communications
#### The Complete Flow
1. **User invokes a prompt with parameters:**
```json theme={null}
{
"prompt": "plan-vacation",
"arguments": {
"destination": "Barcelona",
"departure_date": "2024-06-15",
"return_date": "2024-06-22",
"budget": 3000,
"travelers": 2
}
}
```
2. **User selects resources to include:**
* `calendar://my-calendar/June-2024` (from Calendar Server)
* `travel://preferences/europe` (from Travel Server)
* `travel://past-trips/Spain-2023` (from Travel Server)
3. **AI processes the request using tools:**
The AI first reads all selected resources to gather context - identifying available dates from the calendar, learning preferred airlines and hotel types from travel preferences, and discovering previously enjoyed locations from past trips.
Using this context, the AI then executes the prompt provided by the AI application. In our example, the AI application exposes the weather tools from the connected MCP weather server to the model. Because weather can affect travel plans, the AI chooses to call `checkWeather()` when interpreting the prompt.
As a result the AI executes a series of tools:
* `searchFlights()` - Queries airlines for NYC to Barcelona flights
* `checkWeather()` - Retrieves climate forecasts for travel dates
The AI then uses this information to create the booking and following steps, requesting approval from the user where necessary:
* `bookHotel()` - Finds hotels within the specified budget
* `createCalendarEvent()` - Adds the trip to the user's calendar
* `sendEmail()` - Sends confirmation with trip details
**The result:** Through multiple MCP servers, the user researched and booked a Barcelona trip tailored to their schedule. The "Plan a Vacation" prompt guided the AI to combine Resources (calendar availability and travel history) with Tools (searching flights, booking hotels, updating calendars) across different servers—gathering context and executing the booking. A task that could have taken hours was completed in minutes using MCP.
docs/2025-03-26/learn/versioning New page · 45 lines, new page
# Versioning ## Revisions ## Feature States ## Negotiation
A whole new page. There's nothing to diff it against, so here is what it says.
# Versioning The Model Context Protocol uses string-based version identifiers following the format `YYYY-MM-DD`, to indicate the last date backwards incompatible changes were made. <Info> The protocol version will *not* be incremented when the protocol is updated, as long as the changes maintain backwards compatibility. This allows for incremental improvements while preserving interoperability. </Info> ## Revisions Revisions may be marked as: * **Draft**: in-progress specifications, not yet ready for consumption. * **Current**: the current protocol version, which is ready for use and may continue to receive backwards compatible changes. * **Final**: past, complete specifications that will not be changed. The **current** protocol version is [**2025-11-25**](/specification/2025-11-25/). ## Feature States Individual features of the specification may additionally be marked as **Deprecated** under the [feature lifecycle and deprecation policy](/community/feature-lifecycle): the feature remains part of the specification, but is scheduled for removal. Deprecated features document a migration path (or state that none is required) and remain in the specification for at least twelve months, or at least ninety days under the policy's [expedited-removal exception](/community/feature-lifecycle#expedited-removal), before they become eligible for removal, after which they may be **Removed** in a future revision. ## Negotiation Version negotiation happens during [initialization](/specification/2025-03-26/basic/lifecycle#initialization). Clients and servers **MAY** support multiple protocol versions simultaneously, but they **MUST** agree on a single version to use for the session. The protocol provides appropriate error handling if version negotiation fails, allowing clients to gracefully terminate connections when they cannot find a version compatible with the server.
docs/2025-03-26/sdk New page · 47 lines, new page
# SDKs ## Available SDKs ## Getting Started ## Next Steps
A whole new page. There's nothing to diff it against, so here is what it says.
# SDKs
> Official SDKs for building with Model Context Protocol
Build MCP servers and clients using our official SDKs. SDKs are classified into tiers based on feature completeness, protocol support, and maintenance commitment. Learn more about [SDK tiers](/community/sdk-tiers).
## Available SDKs
| SDK | Repository | Tier |
| :----------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------- | ------------------------------------------------: |
| <Icon icon="square-js" size={24} /> [TypeScript](https://ts.sdk.modelcontextprotocol.io) | [modelcontextprotocol/typescript-sdk](https://github.com/modelcontextprotocol/typescript-sdk) | <Badge color="blue" shape="pill">Tier 1</Badge> |
| <Icon icon="python" size={24} /> [Python](https://py.sdk.modelcontextprotocol.io) | [modelcontextprotocol/python-sdk](https://github.com/modelcontextprotocol/python-sdk) | <Badge color="blue" shape="pill">Tier 1</Badge> |
| <Icon icon="square-c" size={24} /> [C#](https://csharp.sdk.modelcontextprotocol.io) | [modelcontextprotocol/csharp-sdk](https://github.com/modelcontextprotocol/csharp-sdk) | <Badge color="blue" shape="pill">Tier 1</Badge> |
| <Icon icon="golang" size={24} /> [Go](https://go.sdk.modelcontextprotocol.io) | [modelcontextprotocol/go-sdk](https://github.com/modelcontextprotocol/go-sdk) | <Badge color="blue" shape="pill">Tier 1</Badge> |
| <Icon icon="java" size={24} /> [Java](https://java.sdk.modelcontextprotocol.io) | [modelcontextprotocol/java-sdk](https://github.com/modelcontextprotocol/java-sdk) | <Badge color="purple" shape="pill">Tier 2</Badge> |
| <Icon icon="rust" size={24} /> [Rust](https://rust.sdk.modelcontextprotocol.io) | [modelcontextprotocol/rust-sdk](https://github.com/modelcontextprotocol/rust-sdk) | <Badge color="purple" shape="pill">Tier 2</Badge> |
| <Icon icon="swift" size={24} /> Swift | [modelcontextprotocol/swift-sdk](https://github.com/modelcontextprotocol/swift-sdk) | <Badge color="orange" shape="pill">Tier 3</Badge> |
| <Icon icon="gem" size={24} /> [Ruby](https://ruby.sdk.modelcontextprotocol.io) | [modelcontextprotocol/ruby-sdk](https://github.com/modelcontextprotocol/ruby-sdk) | <Badge color="orange" shape="pill">Tier 3</Badge> |
| <Icon icon="php" size={24} /> [PHP](https://php.sdk.modelcontextprotocol.io) | [modelcontextprotocol/php-sdk](https://github.com/modelcontextprotocol/php-sdk) | <Badge color="orange" shape="pill">Tier 3</Badge> |
| <Icon icon="square-k" size={24} /> [Kotlin](https://kotlin.sdk.modelcontextprotocol.io) | [modelcontextprotocol/kotlin-sdk](https://github.com/modelcontextprotocol/kotlin-sdk) | <Badge color="orange" shape="pill">Tier 3</Badge> |
See [SDK Tiering System](/community/sdk-tiers) for details on what each tier means.
## Getting Started
Each SDK provides the same functionality but follows the idioms and best practices of its language. All SDKs support:
* Creating MCP servers that expose tools, resources, and prompts
* Building MCP clients that can connect to any MCP server
* Local and remote transport protocols
* Protocol compliance with type safety
Visit the SDK page for your chosen language to find installation instructions, documentation, and examples.
## Next Steps
Ready to start building with MCP? Choose your path:
<CardGroup cols={2}>
<Card title="Build a Server" icon="server" href="/docs/2025-03-26/develop/build-server">
Learn how to create your first MCP server
</Card>
<Card title="Build a Client" icon="computer" href="/docs/2025-03-26/develop/build-client">
Create applications that connect to MCP servers
</Card>
</CardGroup>
docs/2025-03-26/tools/debugging New page · 347 lines, new page
# Debugging ## Debugging tools overview ## Implementing logging ### Server-side logging ## Common issues ### Working directory ### Environment variables ### Server initialization ### Connection problems ## Debugging in Claude Desktop ### Checking server status ### Viewing logs ### Using Chrome DevTools ## Debugging workflow ### Development cycle ### Testing changes ## Best practices ### Logging strategy ### Security considerations ## Getting help ## Next steps
A whole new page. There's nothing to diff it against, so here is what it says.
# Debugging
> A comprehensive guide to debugging Model Context Protocol (MCP) integrations
Effective debugging is essential when developing MCP servers or integrating
them with applications. This guide covers the debugging tools and approaches
available in the MCP ecosystem.
## Debugging tools overview
MCP provides several tools for debugging at different levels:
1. **[MCP Inspector](/docs/2025-03-26/tools/inspector)**: interactive, transport-agnostic
testing UI. Connect to stdio or Streamable HTTP servers, invoke
[tools](/specification/2025-03-26/server/tools),
[prompts](/specification/2025-03-26/server/prompts), and
[resources](/specification/2025-03-26/server/resources), and watch the
notification stream. This should be your first stop.
2. **Server logging**: structured logs to stderr (stdio transport) or via
[`notifications/message`](/specification/2025-03-26/server/utilities/logging#log-message-notifications)
(all transports).
3. **Client developer tools**: most MCP clients expose logs and connection
state. See [Debugging in Claude Desktop](#debugging-in-claude-desktop)
below for one example, or consult your client's documentation.
## Implementing logging
### Server-side logging
When building a server that uses the local
[stdio transport](/specification/2025-03-26/basic/transports#stdio), all messages
logged to stderr (standard error) will be captured by the host application
automatically.
<Warning>
Local MCP servers should not log messages to stdout (standard out), as this
will interfere with protocol operation.
</Warning>
For servers using the
[Streamable HTTP transport](/specification/2025-03-26/basic/transports#streamable-http),
stderr is not captured by the client. Use the log message notifications below,
your own server-side log aggregation, or standard HTTP tooling (curl, browser
DevTools Network panel) to inspect requests,
[`Mcp-Session-Id` headers](/specification/2025-03-26/basic/transports#session-management),
and SSE streams.
For all [transports](/specification/2025-03-26/basic/transports), you can also
provide logging to the client by sending a log message notification:
<CodeGroup>
```python Python theme={null}
@server.tool()
async def my_tool(ctx: Context) -> str:
await ctx.session.send_log_message(
level="info",
data="Server started successfully",
)
return "done"
```
```typescript TypeScript theme={null}
await server.sendLoggingMessage({
level: "info",
data: "Server started successfully",
});
```
</CodeGroup>
MCP defines eight
[RFC 5424 severity levels](/specification/2025-03-26/server/utilities/logging#log-levels)
(`debug` through `emergency`). Clients can adjust the minimum level at runtime
via the
[`logging/setLevel`](/specification/2025-03-26/server/utilities/logging#setting-log-level)
request.
Important events to log:
* Initialization steps
* Resource access
* Tool execution
* Error conditions
* Performance metrics
## Common issues
The examples below use Claude Desktop's
[`claude_desktop_config.json`](/docs/2025-03-26/develop/connect-local-servers); the same
principles apply to any stdio-based MCP client.
### Working directory
When an MCP client launches a stdio server:
* The working directory for servers launched via the client's config may be
undefined (like `/` on macOS) since the client could be started from
anywhere
* Always use absolute paths in your configuration and `.env` files to ensure
reliable operation
* For testing servers directly via command line, the working directory will be
where you run the command
For example in `claude_desktop_config.json`, use:
```json theme={null}
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"/Users/username/data"
]
}
}
}
```
Instead of relative paths like `./data`
### Environment variables
MCP servers launched over stdio inherit only a limited subset of environment
variables automatically (the exact set is platform-dependent).
To override the default variables or provide your own, you can specify an
`env` key in `claude_desktop_config.json`:
```json theme={null}
{
"mcpServers": {
"myserver": {
"command": "mcp-server-myapp",
"env": {
"MYAPP_API_KEY": "some_key"
}
}
}
}
```
### Server initialization
Common initialization problems:
1. **Path Issues**
* Incorrect server executable path
* Missing required files
* Permission problems
* Try using an absolute path for `command`
2. **Configuration Errors**
* Invalid JSON syntax
* Missing required fields
* Type mismatches
3. **Environment Problems**
* Missing environment variables
* Incorrect variable values
* Permission restrictions
### Connection problems
When servers fail to connect:
1. Check client logs
2. Verify server process is running
3. Test standalone with [Inspector](/docs/2025-03-26/tools/inspector)
4. Verify
[protocol compatibility](/specification/2025-03-26/basic/lifecycle#version-negotiation)
5. Check
[capability negotiation](/specification/2025-03-26/basic/lifecycle#capability-negotiation):
error [`-32602`](/specification/2025-03-26/basic/lifecycle#error-handling) is
the standard JSON-RPC "Invalid params" code and is returned in many
contexts. One common cause is a server sending
[sampling](/specification/2025-03-26/client/sampling) requests to a
client that hasn't declared that capability. Inspect the
[`initialize` exchange](/specification/2025-03-26/basic/lifecycle#initialization)
to verify both sides declared what you expect
## Debugging in Claude Desktop
Claude Desktop is one of many MCP clients. It is available on
macOS and Windows.
### Checking server status
Click the "Add files, connectors, and more" plus icon in the chat input, then
hover over the **Connectors** menu to see connected servers and available
tools.
<img src="https://mintcdn.com/mcp/zNouQwo2h8cbxlDS/images/available-mcp-tools.png?fit=max&auto=format&n=zNouQwo2h8cbxlDS&q=85&s=e2ace1ac88895a5fe30ebd8d01456bc3" alt="Available MCP tools" width="437" height="244" data-path="images/available-mcp-tools.png" />
### Viewing logs
Log files are written to:
* macOS: `~/Library/Logs/Claude`
* Windows: `%APPDATA%\Claude\logs`
<CodeGroup>
```bash macOS theme={null}
tail -n 20 -F ~/Library/Logs/Claude/mcp*.log
```
```powershell Windows theme={null}
type "$env:AppData\Claude\logs\mcp*.log"
```
</CodeGroup>
The logs capture:
* Server connection events
* Configuration issues
* Runtime errors
* Message exchanges
### Using Chrome DevTools
Access Chrome's developer tools inside Claude Desktop to investigate
client-side errors:
1. Create a `developer_settings.json` file with `allowDevTools` set to true:
<CodeGroup>
```bash macOS theme={null}
echo '{"allowDevTools": true}' > ~/Library/Application\ Support/Claude/developer_settings.json
```
```powershell Windows theme={null}
'{"allowDevTools": true}' | Set-Content "$env:AppData\Claude\developer_settings.json"
```
</CodeGroup>
2. Open DevTools: `Command-Option-I` (macOS) or `Ctrl+Alt+I` (Windows)
Note: You'll see two DevTools windows:
* Main content window
* App title bar window
Use the Console panel to inspect client-side errors.
Use the Network panel to inspect:
* Message payloads
* Connection timing
## Debugging workflow
### Development cycle
1. Initial Development
* Use [Inspector](/docs/2025-03-26/tools/inspector) for basic testing
* Implement core functionality
* Add logging points
2. Integration Testing
* Test in your target MCP client
* Monitor logs
* Check error handling
### Testing changes
To test changes efficiently:
* **Configuration changes**: Restart the MCP client
* **Server code changes**: Restart the client (for Claude Desktop, fully quit
and reopen; closing the window is not enough)
* **Quick iteration**: Use [Inspector](/docs/2025-03-26/tools/inspector) during
development
## Best practices
### Logging strategy
1. **Structured Logging**
* Use consistent formats
* Include context
* Add timestamps
* Track request IDs
2. **Error Handling**
* Log stack traces
* Include error context
* Track error patterns
* Monitor recovery
3. **Performance Tracking**
* Log operation timing
* Monitor resource usage
* Track message sizes
* Measure latency
### Security considerations
When debugging:
1. **Sensitive Data**
Cut at 300 lines. The page has the rest.
docs/2025-03-26/tools/inspector New page · 140 lines, new page
# MCP Inspector ## Getting started ### Installation and basic usage #### Inspecting servers from npm or PyPI #### Inspecting locally developed servers ## Feature overview ### Server connection pane ### Resources tab ### Prompts tab ### Tools tab ### Notifications pane ## Best practices ### Development workflow ## Next steps
A whole new page. There's nothing to diff it against, so here is what it says.
# MCP Inspector
> In-depth guide to using the MCP Inspector for testing and debugging Model Context Protocol servers
The [MCP Inspector](https://github.com/modelcontextprotocol/inspector) is an interactive developer tool for testing and debugging MCP servers. While the [Debugging Guide](/docs/2025-03-26/tools/debugging) covers the Inspector as part of the overall debugging toolkit, this document provides a detailed exploration of the Inspector's features and capabilities.
## Getting started
### Installation and basic usage
The Inspector runs directly through `npx` without requiring installation:
```bash theme={null}
npx @modelcontextprotocol/inspector <command>
```
```bash theme={null}
npx @modelcontextprotocol/inspector <command> <arg1> <arg2>
```
#### Inspecting servers from npm or PyPI
A common way to start server packages from [npm](https://npmjs.com) or [PyPI](https://pypi.org).
<Tabs>
<Tab title="npm package">
```bash theme={null}
npx -y @modelcontextprotocol/inspector npx <package-name> <args>
# For example
npx -y @modelcontextprotocol/inspector npx @modelcontextprotocol/server-filesystem /Users/username/Desktop
```
</Tab>
<Tab title="PyPI package">
```bash theme={null}
npx @modelcontextprotocol/inspector uvx <package-name> <args>
# For example
npx @modelcontextprotocol/inspector uvx mcp-server-git --repository ~/code/mcp/servers.git
```
</Tab>
</Tabs>
#### Inspecting locally developed servers
To inspect servers locally developed or downloaded as a repository, the most common
way is:
<Tabs>
<Tab title="TypeScript">
```bash theme={null}
npx @modelcontextprotocol/inspector node path/to/server/index.js args...
```
</Tab>
<Tab title="Python">
```bash theme={null}
npx @modelcontextprotocol/inspector \
uv \
--directory path/to/server \
run \
package-name \
args...
```
</Tab>
</Tabs>
Please carefully read any attached README for the most accurate instructions.
## Feature overview
<Frame caption="The MCP Inspector interface">
<img src="https://mintcdn.com/mcp/4ZXF1PrDkEaJvXpn/images/mcp-inspector.png?fit=max&auto=format&n=4ZXF1PrDkEaJvXpn&q=85&s=83b12e2a457c96ef4ad17c7357236290" width="2888" height="1761" data-path="images/mcp-inspector.png" />
</Frame>
The Inspector provides several features for interacting with your MCP server:
### Server connection pane
* Allows selecting the [transport](/specification/2025-03-26/basic/transports) for connecting to the server
* For local servers, supports customizing the command-line arguments and environment
### Resources tab
* Lists all available resources
* Shows resource metadata (MIME types, descriptions)
* Allows resource content inspection
* Supports subscription testing
### Prompts tab
* Displays available prompt templates
* Shows prompt arguments and descriptions
* Enables prompt testing with custom arguments
* Previews generated messages
### Tools tab
* Lists available tools
* Shows tool schemas and descriptions
* Enables tool testing with custom inputs
* Displays tool execution results
### Notifications pane
* Presents all logs recorded from the server
* Shows notifications received from the server
## Best practices
### Development workflow
1. Start Development
* Launch Inspector with your server
* Verify basic connectivity
* Check capability negotiation
2. Iterative testing
* Make server changes
* Rebuild the server
* Reconnect the Inspector
* Test affected features
* Monitor messages
3. Test edge cases
* Invalid inputs
* Missing prompt arguments
* Concurrent operations
* Verify error handling and error responses
## Next steps
<CardGroup cols={2}>
<Card title="Inspector Repository" icon="github" href="https://github.com/modelcontextprotocol/inspector">
Check out the MCP Inspector source code
</Card>
<Card title="Debugging Guide" icon="bug" href="/docs/2025-03-26/tools/debugging">
Learn about broader debugging strategies
</Card>
</CardGroup>
docs/2025-03-26/tutorials/security/authorization New page · 1057 lines, new page
# Understanding Authorization in MCP ## When Should You Use Authorization? ## The Authorization Flow: Step by Step ## Implementation Example ### Keycloak Setup ### MCP Server Setup ## Testing the MCP Server ## Common Pitfalls and How to Avoid Them ## Related Standards and Documentation
A whole new page. There's nothing to diff it against, so here is what it says.
# Understanding Authorization in MCP
> Learn how to implement secure authorization for MCP servers using OAuth 2.1 to protect sensitive resources and operations
Authorization in the Model Context Protocol (MCP) secures access to sensitive resources and operations exposed by MCP servers. If your MCP server handles user data or administrative actions, authorization ensures only permitted users can access its endpoints.
MCP uses standardized authorization flows to build trust between MCP clients and MCP servers. Its design doesn't focus on one specific authorization or identity system, but rather follows the conventions outlined for [OAuth 2.1](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-13). For detailed information, see the [Authorization specification](/specification/2025-03-26/basic/authorization).
## When Should You Use Authorization?
While authorization for MCP servers is **optional**, it is strongly recommended when:
* Your server accesses user-specific data (emails, documents, databases)
* You need to audit who performed which actions
* Your server grants access to its APIs that require user consent
* You're building for enterprise environments with strict access controls
* You want to implement rate limiting or usage tracking per user
<Tip>
**Authorization for Local MCP Servers**
For MCP servers using the [STDIO transport](/specification/2025-03-26/basic/transports#stdio), you can use environment-based credentials or credentials provided by third-party libraries embedded directly in the MCP server instead. Because a STDIO-built MCP server runs locally, it has access to a range of flexible options when it comes to acquiring user credentials that may or may not rely on in-browser authentication and authorization flows.
OAuth flows, in turn, are designed for HTTP-based transports where the MCP server is remotely-hosted and the client uses OAuth to establish that a user is authorized to access said remote server.
</Tip>
## The Authorization Flow: Step by Step
Let's walk through what happens when a client wants to connect to your protected MCP server:
<Steps>
<Step title="Initial Handshake">
When your MCP client first tries to connect, your server responds with a `401 Unauthorized` and tells the client where to find authorization information, captured in a [Protected Resource Metadata (PRM) document](https://datatracker.ietf.org/doc/html/rfc9728). The document is hosted by the MCP server, follows a predictable path pattern, and is provided to the client in the `resource_metadata` parameter within the `WWW-Authenticate` header.
```http theme={null}
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="mcp",
resource_metadata="https://your-server.com/.well-known/oauth-protected-resource"
```
This tells the client that authorization is required for the MCP server and where to get the necessary information to kickstart the authorization flow.
</Step>
<Step title="Protected Resource Metadata Discovery">
With the URI pointer to the PRM document, the client will fetch the metadata to learn about the authorization server, supported scopes, and other resource information. The data is typically encapsulated in a JSON blob, similar to the one below.
```json theme={null}
{
"resource": "https://your-server.com/mcp",
"authorization_servers": ["https://auth.your-server.com"],
"scopes_supported": ["mcp:tools", "mcp:resources"]
}
```
You can see a more comprehensive example in [RFC 9728 Section 3.2](https://datatracker.ietf.org/doc/html/rfc9728#name-protected-resource-metadata-r).
</Step>
<Step title="Authorization Server Discovery">
Next, the client discovers what the authorization server can do by fetching its metadata. If the PRM document lists more than one authorization server, the client can decide which one to use.
With an authorization server selected, the client will then construct a standard metadata URI and issue a request to the [OpenID Connect (OIDC) Discovery](https://openid.net/specs/openid-connect-discovery-1_0.html) or [OAuth 2.0 Auth Server Metadata](https://datatracker.ietf.org/doc/html/rfc8414) endpoints (depending on authorization server support)
and retrieve another set of metadata properties that will allow it to know the endpoints it needs to complete the authorization flow.
```json theme={null}
{
"issuer": "https://auth.your-server.com",
"authorization_endpoint": "https://auth.your-server.com/authorize",
"token_endpoint": "https://auth.your-server.com/token",
"registration_endpoint": "https://auth.your-server.com/register"
}
```
</Step>
<Step title="Client Registration">
With all the metadata out of the way, the client now needs to make sure that it's registered with the authorization server. This can be done in two ways.
First, the client can be **pre-registered** with a given authorization server, in which case it can have embedded client registration information that it uses to complete the authorization flow.
Alternatively, the client can use **Dynamic Client Registration** (DCR) to dynamically register itself with the authorization server. The latter scenario requires the authorization server to support DCR. If the authorization server does support DCR, the client will send a request to the `registration_endpoint` with its information:
```json theme={null}
{
"client_name": "My MCP Client",
"redirect_uris": ["http://localhost:3000/callback"],
"grant_types": ["authorization_code", "refresh_token"],
"response_types": ["code"]
}
```
If the registration succeeds, the authorization server will return a JSON blob with client registration information.
<Tip>
**No DCR or Pre-Registration**
In case an MCP client connects to an MCP server that doesn't use an authorization server that supports DCR and the client is not pre-registered with said authorization server, it's the responsibility of the client developer to provide an affordance for the end-user to enter client information manually.
</Tip>
</Step>
<Step title="User Authorization">
The client will now need to open a browser to the `/authorize` endpoint, where the user can log in and grant the required permissions. The authorization server will then redirect back to the client with an authorization code that the client exchanges for tokens:
```json theme={null}
{
"access_token": "eyJhbGciOiJSUzI1NiIs...",
"refresh_token": "def502...",
"token_type": "Bearer",
"expires_in": 3600
}
```
The access token is what the client will use to authenticate requests to the MCP server. This step follows standard [OAuth 2.1 authorization code with PKCE](https://oauth.net/2/grant-types/authorization-code/) conventions.
</Step>
<Step title="Making Authenticated Requests">
Finally, the client can make requests to your MCP server using the access token embedded in the `Authorization` header:
```http theme={null}
GET /mcp HTTP/1.1
Host: your-server.com
Authorization: Bearer eyJhbGciOiJSUzI1NiIs...
```
The MCP server will need to validate the token and process the request if the token is valid and has the required permissions.
</Step>
</Steps>
## Implementation Example
To get started with a practical implementation, we will use a [Keycloak](https://www.keycloak.org/) authorization server hosted in a Docker container. Keycloak is an open-source authorization server that can be easily deployed locally for testing and experimentation.
Make sure that you download and install [Docker Desktop](https://www.docker.com/products/docker-desktop/). We will need it to deploy Keycloak on our development machine.
### Keycloak Setup
From your terminal application, run the following command to start the Keycloak container:
```bash theme={null}
docker run -p 127.0.0.1:8080:8080 -e KC_BOOTSTRAP_ADMIN_USERNAME=admin -e KC_BOOTSTRAP_ADMIN_PASSWORD=admin quay.io/keycloak/keycloak start-dev
```
This command will pull the Keycloak container image locally and bootstrap the basic configuration. It will run on port `8080` and have an `admin` user with `admin` password.
<Warning>
**Not for Production**
The configuration above may be suitable for testing and experimentation; however, you should never use it in production. Refer to the [Configuring Keycloak for production](https://www.keycloak.org/server/configuration-production) guide for additional details on how to deploy the authorization server for scenarios that require reliability, security, and high availability.
</Warning>
You will be able to access the Keycloak authorization server from your browser at `http://localhost:8080`.
<Frame>
<img src="https://mintcdn.com/mcp/sAd4SGUO-cEUqgzn/images/tutorial-authorization/keycloak-browser.png?fit=max&auto=format&n=sAd4SGUO-cEUqgzn&q=85&s=cba689d986e113cbe937d732ac0558b6" alt="Keycloak admin dashboard authentication dialog." width="1834" height="1450" data-path="images/tutorial-authorization/keycloak-browser.png" />
</Frame>
When running with the default configuration, Keycloak will already support many of the capabilities that we need for MCP servers, including Dynamic Client Registration. You can check this by looking at the OIDC configuration, available at:
```http theme={null}
http://localhost:8080/realms/master/.well-known/openid-configuration
```
We will also need to set up Keycloak to support our scopes and allow our host (local machine) to dynamically register clients, as the default policies restrict anonymous dynamic client registration.
Go to **Client scopes** in the Keycloak dashboard and create a new `mcp:tools` scope. We will use this to access all of the tools on our MCP server.
<Frame>
<img src="https://mintcdn.com/mcp/sAd4SGUO-cEUqgzn/images/tutorial-authorization/keycloak-scopes.png?fit=max&auto=format&n=sAd4SGUO-cEUqgzn&q=85&s=3cd49dc2e070027609ae495751e0db58" alt="Configuring Keycloak scopes." width="1999" height="1710" data-path="images/tutorial-authorization/keycloak-scopes.png" />
</Frame>
After creating the scope, make sure that you assign its type to **Default** and have flipped the **Include in token scope** switch, as this will be needed for token validation.
Let's now also set up an **audience** for our Keycloak-issued tokens. An audience is important to configure because it embeds the intended destination directly into the issued access token. This helps your MCP server to verify that the token it got was actually meant for it rather than some other API. This is key to help avoid token passthrough scenarios.
To do this, open your `mcp:tools` client scope and click on **Mappers**, followed by **Configure a new mapper**. Select **Audience**.
<Frame>
<img src="https://mintcdn.com/mcp/sAd4SGUO-cEUqgzn/images/tutorial-authorization/scope-add-audience.gif?s=6ea9cf20c397f4c79c491c2e39019272" alt="Configuring an audience for a token in Keycloak." width="1080" height="921" data-path="images/tutorial-authorization/scope-add-audience.gif" />
</Frame>
For **Name**, use `audience-config`. Add a value for **Included Custom Audience**, set to `http://localhost:3000`. This will be the URI of our test server.
<Warning>
**Not for Production**
The audience configuration above is meant for testing. For production scenarios, additional set-up and configuration will be required to ensure that audiences are properly constrained for issued tokens. Specifically, the audience needs to be based on the resource parameter passed from the client, not a fixed value.
</Warning>
Now, navigate to **Clients**, then **Client registration**, and then **Trusted Hosts**. Disable the **Client URIs Must Match** setting and add the hosts from which you're testing. You can get your current host IP by running the `ifconfig` command on Linux or macOS, or `ipconfig` on Windows. You can see the IP address you need to add by looking at the keycloak logs for a line that looks like `Failed to verify remote host : 192.168.215.1`. Check that the IP address is associated with your host. This may be for a bridge network depending on your docker setup.
<Frame>
<img src="https://mintcdn.com/mcp/sAd4SGUO-cEUqgzn/images/tutorial-authorization/keycloak-client.gif?s=b5d40b36a5f1ea1e818821bb8ea77f6b" alt="Setting up client registration details in Keycloak." width="1199" height="1027" data-path="images/tutorial-authorization/keycloak-client.gif" />
</Frame>
<Warning>
**Getting the Host**
If you are running Keycloak from a container, you will also be able to see the host IP from the Terminal in the container logs.
</Warning>
Lastly, we need to register a new client that we can use with the **MCP server itself** to talk to Keycloak for things like [token introspection](https://oauth.net/2/token-introspection/). To do that:
1. Go to **Clients**.
2. Click **Create client**.
3. Give your client a unique **Client ID** and click **Next**.
4. Enable **Client authentication** and click **Next**.
5. Click **Save**.
Worth noting that token introspection is just *one of* the available approaches to validate tokens. This can also be done with the help of standalone libraries, specific to each language and platform.
When you open the client details, go to **Credentials** and take note of the **Client Secret**.
<Frame>
<img src="https://mintcdn.com/mcp/sAd4SGUO-cEUqgzn/images/tutorial-authorization/keycloak-client-auth.gif?s=7152c41a5746994fd399024bc4659e40" alt="Creating a new client in Keycloak." width="1200" height="1023" data-path="images/tutorial-authorization/keycloak-client-auth.gif" />
</Frame>
<Warning>
**Handling Secrets**
Never embed client credentials directly in your code. We recommend using environment variables or specialized solutions for secret storage.
</Warning>
With Keycloak configured, every time the authorization flow is triggered, your MCP server will receive a token like this:
```text theme={null}
eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI1TjcxMGw1WW5MWk13WGZ1VlJKWGtCS3ZZMzZzb3JnRG5scmlyZ2tlTHlzIn0.eyJleHAiOjE3NTU1NDA4MTcsImlhdCI6MTc1NTU0MDc1NywiYXV0aF90aW1lIjoxNzU1NTM4ODg4LCJqdGkiOiJvbnJ0YWM6YjM0MDgwZmYtODQwNC02ODY3LTgxYmUtMTIzMWI1MDU5M2E4IiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4MDgwL3JlYWxtcy9tYXN0ZXIiLCJhdWQiOiJodHRwOi8vbG9jYWxob3N0OjMwMDAiLCJzdWIiOiIzM2VkNmM2Yi1jNmUwLTQ5MjgtYTE2MS1mMmY2OWM3YTAzYjkiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiI3OTc1YTViNi04YjU5LTRhODUtOWNiYS04ZmFlYmRhYjg5NzQiLCJzaWQiOiI4ZjdlYzI3Ni0zNThmLTRjY2MtYjMxMy1kYjA4MjkwZjM3NmYiLCJzY29wZSI6Im1jcDp0b29scyJ9.P5xCRtXORly0R0EXjyqRCUx-z3J4uAOWNAvYtLPXroykZuVCCJ-K1haiQSwbURqfsVOMbL7jiV-sD6miuPzI1tmKOkN_Yct0Vp-azvj7U5rEj7U6tvPfMkg2Uj_jrIX0KOskyU2pVvGZ-5BgqaSvwTEdsGu_V3_E0xDuSBq2uj_wmhqiyTFm5lJ1WkM3Hnxxx1_AAnTj7iOKMFZ4VCwMmk8hhSC7clnDauORc0sutxiJuYUZzxNiNPkmNeQtMCGqWdP1igcbWbrfnNXhJ6NswBOuRbh97_QraET3hl-CNmyS6C72Xc0aOwR_uJ7xVSBTD02OaQ1JA6kjCATz30kGYg
```
Decoded, it will look like this:
```json theme={null}
{
"alg": "RS256",
"typ": "JWT",
"kid": "5N710l5YnLZMwXfuVRJXkBKvY36sorgDnlrirgkeLys"
}.{
"exp": 1755540817,
"iat": 1755540757,
"auth_time": 1755538888,
"jti": "onrtac:b34080ff-8404-6867-81be-1231b50593a8",
"iss": "http://localhost:8080/realms/master",
"aud": "http://localhost:3000",
"sub": "33ed6c6b-c6e0-4928-a161-f2f69c7a03b9",
"typ": "Bearer",
"azp": "7975a5b6-8b59-4a85-9cba-8faebdab8974",
"sid": "8f7ec276-358f-4ccc-b313-db08290f376f",
"scope": "mcp:tools"
}.[Signature]
```
<Warning>
**Embedded Audience**
Notice the `aud` claim embedded in the token - it's currently set to be the URI of the test MCP server and it's inferred from the scope that we've previously configured. This will be important in our implementation to validate.
</Warning>
### MCP Server Setup
We will now set up our MCP server to use the locally-running Keycloak authorization server. Depending on your programming language preference, you can use one of the supported [MCP SDKs](/docs/2025-03-26/sdk).
For our testing purposes, we will create an extremely simple MCP server that exposes two tools - one for addition and another for multiplication. The server will require authorization to access these.
<Tabs>
<Tab title="TypeScript">
You can see the complete TypeScript project in the [sample repository](https://github.com/localden/min-ts-mcp-auth).
Prior to running the code below, ensure that you have a `.env` file with the following content:
```env theme={null}
# Server host/port
HOST=localhost
PORT=3000
# Auth server location
AUTH_HOST=localhost
AUTH_PORT=8080
AUTH_REALM=master
# Keycloak OAuth client credentials
OAUTH_CLIENT_ID=<YOUR_SERVER_CLIENT_ID>
OAUTH_CLIENT_SECRET=<YOUR_SERVER_CLIENT_SECRET>
```
`OAUTH_CLIENT_ID` and `OAUTH_CLIENT_SECRET` are associated with the MCP server client we created earlier.
In addition to implementing the MCP authorization specification, the server below also does token introspection via Keycloak to make sure that the token it receives from the client is valid. It also implements basic logging to allow you to easily diagnose any issues.
```typescript theme={null}
import "dotenv/config";
import express from "express";
import { randomUUID } from "node:crypto";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
import { isInitializeRequest } from "@modelcontextprotocol/sdk/types.js";
import { z } from "zod";
import cors from "cors";
import {
mcpAuthMetadataRouter,
getOAuthProtectedResourceMetadataUrl,
} from "@modelcontextprotocol/sdk/server/auth/router.js";
import { requireBearerAuth } from "@modelcontextprotocol/sdk/server/auth/middleware/bearerAuth.js";
import { OAuthMetadata } from "@modelcontextprotocol/sdk/shared/auth.js";
Cut at 300 lines. The page has the rest.
docs/2025-03-26/tutorials/security/security_best_practices New page · 897 lines, new page
# Security Best Practices ## Introduction ### Purpose and Scope ## Attacks and Mitigations ### Confused Deputy Problem #### Terminology #### Vulnerable Conditions #### Architecture and Attack Flows ##### Normal OAuth proxy usage (preserves user consent) ##### Malicious OAuth proxy usage (skips user consent) #### Attack Description #### Mitigation ##### Consent Flow Implementation ##### Required Protections ### Token Passthrough #### Risks #### Mitigation ### Server-Side Request Forgery (SSRF) #### Attack Description #### Risks #### Mitigation #### Resources and Tools ### Session Hijacking #### Session Hijack Prompt Injection #### Session Hijack Impersonation #### Attack Description #### Mitigation ### Local MCP Server Compromise #### Attack Description #### Risks #### Mitigation ### OAuth Authorization URL Validation #### Attack Description #### Risks #### Mitigation ### stdio Transport Security in Proxy Scenarios #### Attack Description #### Risks #### Mitigation ### Scope Minimization #### Attack Description #### Risks #### Mitigation #### Common Mistakes
A whole new page. There's nothing to diff it against, so here is what it says.
# Security Best Practices
> Security considerations, attack vectors, and best practices for MCP implementations
## Introduction
### Purpose and Scope
This document provides security considerations for the Model Context
Protocol (MCP), complementing the
[MCP Authorization](/specification/2025-03-26/basic/authorization)
specification. This document identifies security risks, attack vectors,
and best practices specific to MCP implementations.
The primary audience for this document includes developers implementing
MCP authorization flows, MCP server operators, and security
professionals evaluating MCP-based systems. This document should be read
alongside the MCP Authorization specification and
[OAuth 2.0 security best practices](https://datatracker.ietf.org/doc/html/rfc9700).
## Attacks and Mitigations
This section gives a detailed description of attacks on MCP
implementations, along with potential countermeasures.
### Confused Deputy Problem
Attackers can exploit MCP proxy servers that connect to third-party
APIs, creating
"[confused deputy](https://en.wikipedia.org/wiki/Confused_deputy_problem)"
vulnerabilities. This attack allows malicious clients to obtain
authorization codes without proper user consent by exploiting the
combination of static client IDs, dynamic client registration, and
consent cookies.
#### Terminology
**MCP Proxy Server**
: An MCP server that connects MCP clients to third-party APIs, offering
MCP features while delegating operations and acting as a single OAuth
client to the third-party API server.
**Third-Party Authorization Server**
: Authorization server that protects the third-party API. It may lack
dynamic client registration support, requiring the MCP proxy to use a
static client ID for all requests.
**Third-Party API**
: The protected resource server that provides the actual API
functionality. Access to this API requires tokens issued by the
third-party authorization server.
**Static Client ID**
: A fixed OAuth 2.0 client identifier used by the MCP proxy server when
communicating with the third-party authorization server. This Client ID
refers to the MCP server acting as a client to the Third-Party API. It
is the same value for all MCP server to Third-Party API interactions
regardless of which MCP client initiated the request.
#### Vulnerable Conditions
This attack becomes possible when all of the following conditions are
present:
* MCP proxy server uses a **static client ID** with a third-party
authorization server
* MCP proxy server allows MCP clients to **dynamically register** (each
getting their own client\_id)
* The third-party authorization server sets a **consent cookie** after
the first authorization
* MCP proxy server does not implement proper per-client consent before
forwarding to third-party authorization
#### Architecture and Attack Flows
##### Normal OAuth proxy usage (preserves user consent)
```mermaid theme={null}
sequenceDiagram
participant UA as User-Agent (Browser)
participant MC as MCP Client
participant M as MCP Proxy Server
participant TAS as Third-Party Authorization Server
Note over UA,M: Initial Auth flow completed
Note over UA,TAS: Step 1: Legitimate user consent for Third Party Server
M->>UA: Redirect to third party authorization server
UA->>TAS: Authorization request (client_id: mcp-proxy)
TAS->>UA: Authorization consent screen
Note over UA: Review consent screen
UA->>TAS: Approve
TAS->>UA: Set consent cookie for client ID: mcp-proxy
TAS->>UA: 3P Authorization code + redirect to mcp-proxy-server.com
UA->>M: 3P Authorization code
Note over M,TAS: Exchange 3P code for 3P token
Note over M: Generate MCP authorization code
M->>UA: Redirect to MCP Client with MCP authorization code
Note over M,UA: Exchange code for token, etc.
```
##### Malicious OAuth proxy usage (skips user consent)
```mermaid theme={null}
sequenceDiagram
participant UA as User-Agent (Browser)
participant M as MCP Proxy Server
participant TAS as Third-Party Authorization Server
participant A as Attacker
Note over UA,A: Step 2: Attack (leveraging existing cookie, skipping consent)
A->>M: Dynamically register malicious client, redirect_uri: attacker.com
A->>UA: Sends malicious link
UA->>TAS: Authorization request (client_id: mcp-proxy) + consent cookie
rect rgba(255, 17, 0, 0.67)
TAS->>TAS: Cookie present, consent skipped
end
TAS->>UA: 3P Authorization code + redirect to mcp-proxy-server.com
UA->>M: 3P Authorization code
Note over M,TAS: Exchange 3P code for 3P token
Note over M: Generate MCP authorization code
M->>UA: Redirect to attacker.com with MCP Authorization code
UA->>A: MCP Authorization code delivered to attacker.com
Note over M,A: Attacker exchanges MCP code for MCP token
A->>M: Attacker impersonates user to MCP server
```
#### Attack Description
When an MCP proxy server uses a static client ID to authenticate with
a third-party authorization server, the following attack becomes
possible:
1. A user authenticates normally through the MCP proxy server to access
the third-party API
2. During this flow, the third-party authorization server sets a cookie
on the user agent indicating consent for the static client ID
3. An attacker later sends the user a malicious link containing a
crafted authorization request which contains a malicious redirect URI
along with a new dynamically registered client ID
4. When the user clicks the link, their browser still has the consent
cookie from the previous legitimate request
5. The third-party authorization server detects the cookie and skips the
consent screen
6. The MCP authorization code is redirected to the attacker's server
(specified in the malicious `redirect_uri` parameter during
[dynamic client registration](/specification/2025-03-26/basic/authorization#dynamic-client-registration))
7. The attacker exchanges the stolen authorization code for access
tokens for the MCP server without the user's explicit approval
8. The attacker now has access to the third-party API as the compromised
user
#### Mitigation
To prevent confused deputy attacks, MCP proxy servers **MUST** implement
per-client consent and proper security controls as detailed below.
##### Consent Flow Implementation
The following diagram shows how to properly implement per-client consent
that runs **before** the third-party authorization flow:
```mermaid theme={null}
sequenceDiagram
participant Client as MCP Client
participant Browser as User's Browser
participant MCP as MCP Server
participant ThirdParty as Third-Party AuthZ Server
Note over Client,ThirdParty: 1. Client Registration (Dynamic)
Client->>MCP: Register with redirect_uri
MCP-->>Client: client_id
Note over Client,ThirdParty: 2. Authorization Request
Client->>Browser: Open MCP server authorization URL
Browser->>MCP: GET /authorize?client_id=...&redirect_uri=...
alt Check MCP Server Consent
MCP->>MCP: Check consent for this client_id
Note over MCP: Not previously approved
end
MCP->>Browser: Show MCP server-owned consent page
Note over Browser: "Allow [Client Name] to access [Third-Party API]?"
Browser->>MCP: POST /consent (approve)
MCP->>MCP: Store consent decision for client_id
Note over Client,ThirdParty: 3. Forward to Third-Party
MCP->>Browser: Redirect to third-party /authorize
Note over MCP: Use static client_id for third-party
Browser->>ThirdParty: Authorization request (static client_id)
ThirdParty->>Browser: User authenticates & consents
ThirdParty->>Browser: Redirect with auth code
Browser->>MCP: Callback with third-party code
MCP->>ThirdParty: Exchange code for token (using static client_id)
MCP->>Browser: Redirect to client's registered redirect_uri
```
##### Required Protections
**Per-Client Consent Storage**
MCP proxy servers **MUST**:
* Maintain a registry of approved `client_id` values per user
* Check this registry **before** initiating the third-party
authorization flow
* Store consent decisions securely (server-side database, or server
specific cookies)
**Consent UI Requirements**
The MCP-level consent page **MUST**:
* Clearly identify the requesting MCP client by name
* Display the specific third-party API scopes being requested
* Show the registered `redirect_uri` where tokens will be sent
* Implement CSRF protection (e.g., state parameter, CSRF tokens)
* Prevent iframing via `frame-ancestors` CSP directive or
`X-Frame-Options: DENY` to prevent clickjacking
**Consent Cookie Security**
If using cookies to track consent decisions, they **MUST**:
* Use `__Host-` prefix for cookie names
* Set `Secure`, `HttpOnly`, and `SameSite=Lax` attributes
* Be cryptographically signed or use server-side sessions
* Bind to the specific `client_id` (not just "user has consented")
**Redirect URI Validation**
The MCP proxy server **MUST**:
* Validate that the `redirect_uri` in authorization requests exactly
matches the registered URI
* Reject requests if the `redirect_uri` has changed without
re-registration
* Use exact string matching (not pattern matching or wildcards)
**OAuth State Parameter Validation**
The OAuth `state` parameter is critical to prevent authorization code
interception and CSRF attacks. Proper state validation ensures that
consent approval at the authorization endpoint is enforced at the
callback endpoint.
MCP proxy servers implementing OAuth flows **MUST**:
* Generate a cryptographically secure random `state` value for each
authorization request
* Store the `state` value server-side (in a secure session store or
encrypted cookie) **only after** consent has been explicitly approved
* Set the `state` tracking cookie/session **immediately before**
redirecting to the third-party identity provider (not before consent
approval)
* Validate at the callback endpoint that the `state` query parameter
exactly matches the stored value in the callback request's cookies or
in the request's cookie-based session
* Reject any callback requests where the `state` parameter is missing
or does not match
* Ensure `state` values are single-use (delete after validation) and
have a short expiration time (e.g., 10 minutes)
The consent cookie or session containing the `state` value **MUST NOT**
be set until **after** the user has approved the consent screen at the
MCP server's authorization endpoint. Setting this cookie before consent
approval renders the consent screen ineffective, as an attacker could
bypass it by crafting a malicious authorization request.
### Token Passthrough
"Token passthrough" is an anti-pattern where an MCP server accepts
tokens from an MCP client without validating that the tokens were
properly issued *to the MCP server* and passes them through to the
downstream API.
#### Risks
Token passthrough is explicitly forbidden in the
[authorization specification](/specification/2025-03-26/basic/authorization)
as it introduces a number of security risks, that include:
* **Security Control Circumvention**
* The MCP Server or downstream APIs might implement important security
controls like rate limiting, request validation, or traffic
monitoring, that depend on the token audience or other credential
constraints. If clients can obtain and use tokens directly with the
downstream APIs without the MCP server validating them properly or
ensuring that the tokens are issued for the right service, they
bypass these controls.
* **Accountability and Audit Trail Issues**
* The MCP Server will be unable to identify or distinguish between MCP
Clients when clients are calling with an upstream-issued access token
Cut at 300 lines. The page has the rest.
docs/2025-06-18/develop/build-client New page · 2510 lines, new page
# Build an MCP client ## Next steps
A whole new page. There's nothing to diff it against, so here is what it says.
# Build an MCP client
> Get started building your own client that can integrate with all MCP servers.
In this tutorial, you'll learn how to build an LLM-powered chatbot client that connects to MCP servers.
Before you begin, it helps to have gone through our [Build an MCP Server](/docs/2025-06-18/develop/build-server) tutorial so you can understand how clients and servers communicate.
<Tabs>
<Tab title="Python">
[You can find the complete code for this tutorial here.](https://github.com/modelcontextprotocol/quickstart-resources/tree/main/mcp-client-python)
## System Requirements
Before starting, ensure your system meets these requirements:
* Mac or Windows computer
* Latest Python version installed
* Latest version of `uv` installed
## Setting Up Your Environment
First, create a new Python project with `uv`:
<CodeGroup>
```bash macOS/Linux theme={null}
# Create project directory
uv init mcp-client
cd mcp-client
# Create virtual environment
uv venv
# Activate virtual environment
source .venv/bin/activate
# Install required packages
uv add mcp anthropic python-dotenv
# Remove boilerplate files
rm main.py
# Create our main file
touch client.py
```
```powershell Windows theme={null}
# Create project directory
uv init mcp-client
cd mcp-client
# Create virtual environment
uv venv
# Activate virtual environment
.venv\Scripts\activate
# Install required packages
uv add mcp anthropic python-dotenv
# Remove boilerplate files
del main.py
# Create our main file
new-item client.py
```
</CodeGroup>
## Setting Up Your API Key
You'll need an Anthropic API key from the [Anthropic Console](https://console.anthropic.com/settings/keys).
Create a `.env` file to store it:
```bash theme={null}
echo "ANTHROPIC_API_KEY=your-api-key-goes-here" > .env
```
Add `.env` to your `.gitignore`:
```bash theme={null}
echo ".env" >> .gitignore
```
<Warning>
Make sure you keep your `ANTHROPIC_API_KEY` secure!
</Warning>
## Creating the Client
### Basic Client Structure
First, let's set up our imports and create the basic client class:
```python theme={null}
import asyncio
from typing import Optional
from contextlib import AsyncExitStack
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
from anthropic import Anthropic
from dotenv import load_dotenv
load_dotenv() # load environment variables from .env
class MCPClient:
def __init__(self):
# Initialize session and client objects
self.session: Optional[ClientSession] = None
self.exit_stack = AsyncExitStack()
self.anthropic = Anthropic()
# methods will go here
```
### Server Connection Management
Next, we'll implement the method to connect to an MCP server:
```python theme={null}
async def connect_to_server(self, server_script_path: str):
"""Connect to an MCP server
Args:
server_script_path: Path to the server script (.py or .js)
"""
is_python = server_script_path.endswith('.py')
is_js = server_script_path.endswith('.js')
if not (is_python or is_js):
raise ValueError("Server script must be a .py or .js file")
command = "python" if is_python else "node"
server_params = StdioServerParameters(
command=command,
args=[server_script_path],
env=None
)
stdio_transport = await self.exit_stack.enter_async_context(stdio_client(server_params))
self.stdio, self.write = stdio_transport
self.session = await self.exit_stack.enter_async_context(ClientSession(self.stdio, self.write))
await self.session.initialize()
# List available tools
response = await self.session.list_tools()
tools = response.tools
print("\nConnected to server with tools:", [tool.name for tool in tools])
```
### Query Processing Logic
Now let's add the core functionality for processing queries and handling tool calls:
```python theme={null}
async def process_query(self, query: str) -> str:
"""Process a query using Claude and available tools"""
messages = [
{
"role": "user",
"content": query
}
]
response = await self.session.list_tools()
available_tools = [{
"name": tool.name,
"description": tool.description,
"input_schema": tool.inputSchema
} for tool in response.tools]
# Initial Claude API call
response = self.anthropic.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1000,
messages=messages,
tools=available_tools
)
# Process response and handle tool calls
final_text = []
assistant_message_content = []
for content in response.content:
if content.type == 'text':
final_text.append(content.text)
assistant_message_content.append(content)
elif content.type == 'tool_use':
tool_name = content.name
tool_args = content.input
# Execute tool call
result = await self.session.call_tool(tool_name, tool_args)
final_text.append(f"[Calling tool {tool_name} with args {tool_args}]")
assistant_message_content.append(content)
messages.append({
"role": "assistant",
"content": assistant_message_content
})
messages.append({
"role": "user",
"content": [
{
"type": "tool_result",
"tool_use_id": content.id,
"content": result.content
}
]
})
# Get next response from Claude
response = self.anthropic.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1000,
messages=messages,
tools=available_tools
)
final_text.append(response.content[0].text)
return "\n".join(final_text)
```
### Interactive Chat Interface
Now we'll add the chat loop and cleanup functionality:
```python theme={null}
async def chat_loop(self):
"""Run an interactive chat loop"""
print("\nMCP Client Started!")
print("Type your queries or 'quit' to exit.")
while True:
try:
query = input("\nQuery: ").strip()
if query.lower() == 'quit':
break
response = await self.process_query(query)
print("\n" + response)
except Exception as e:
print(f"\nError: {str(e)}")
async def cleanup(self):
"""Clean up resources"""
await self.exit_stack.aclose()
```
### Main Entry Point
Finally, we'll add the main execution logic:
```python theme={null}
async def main():
if len(sys.argv) < 2:
print("Usage: python client.py <path_to_server_script>")
sys.exit(1)
client = MCPClient()
try:
await client.connect_to_server(sys.argv[1])
await client.chat_loop()
finally:
await client.cleanup()
if __name__ == "__main__":
import sys
asyncio.run(main())
```
You can find the complete `client.py` file [here](https://github.com/modelcontextprotocol/quickstart-resources/blob/main/mcp-client-python/client.py).
## Key Components Explained
### 1. Client Initialization
* The `MCPClient` class initializes with session management and API clients
* Uses `AsyncExitStack` for proper resource management
* Configures the Anthropic client for Claude interactions
### 2. Server Connection
* Supports both Python and Node.js servers
* Validates server script type
* Sets up proper communication channels
* Initializes the session and lists available tools
### 3. Query Processing
* Maintains conversation context
* Handles Claude's responses and tool calls
* Manages the message flow between Claude and tools
* Combines results into a coherent response
### 4. Interactive Interface
Cut at 300 lines. The page has the rest.
docs/2025-06-18/develop/build-server New page · 2997 lines, new page
# Build an MCP server ### What we'll be building ### Core MCP Concepts ### Test with commands ## What's happening under the hood ## Troubleshooting ## Next steps
A whole new page. There's nothing to diff it against, so here is what it says.
# Build an MCP server
> Get started building your own server to use in Claude for Desktop and other clients.
In this tutorial, we'll build a simple MCP weather server and connect it to a host, Claude for Desktop.
### What we'll be building
We'll build a server that exposes two tools: `get_alerts` and `get_forecast`. Then we'll connect the server to an MCP host (in this case, Claude for Desktop):
<Frame>
<img src="https://mintcdn.com/mcp/4ZXF1PrDkEaJvXpn/images/current-weather.png?fit=max&auto=format&n=4ZXF1PrDkEaJvXpn&q=85&s=dce7b2f8a06c20ba358e4bd2e75fa4c7" width="2780" height="1849" data-path="images/current-weather.png" />
</Frame>
<Note>
Servers can connect to any client. We've chosen Claude for Desktop here for simplicity, but we also have a guide on [building your own client](/docs/2025-06-18/develop/build-client).
</Note>
### Core MCP Concepts
MCP servers can provide three main types of capabilities:
1. **[Resources](/docs/2025-06-18/learn/server-concepts#resources)**: File-like data that can be read by clients (like API responses or file contents)
2. **[Tools](/docs/2025-06-18/learn/server-concepts#tools)**: Functions that can be called by the LLM (with user approval)
3. **[Prompts](/docs/2025-06-18/learn/server-concepts#prompts)**: Pre-written templates that help users accomplish specific tasks
This tutorial will primarily focus on tools.
<Tabs>
<Tab title="Python">
Let's get started with building our weather server! [You can find the complete code for what we'll be building here.](https://github.com/modelcontextprotocol/quickstart-resources/tree/main/weather-server-python)
### Prerequisite knowledge
This quickstart assumes you have familiarity with:
* Python
* LLMs like Claude
### Logging in MCP Servers
When implementing MCP servers, be careful about how you handle logging:
**For STDIO-based servers:** Never write to stdout. Writing to stdout will corrupt the JSON-RPC messages and break your server. The `print()` function writes to stdout by default, but can be used safely with `file=sys.stderr`.
**For HTTP-based servers:** Standard output logging is fine since it doesn't interfere with HTTP responses.
### Best Practices
* Use a logging library that writes to stderr or files.
### Quick Examples
```python theme={null}
import sys
import logging
# ❌ Bad (STDIO)
print("Processing request")
# ✅ Good (STDIO)
print("Processing request", file=sys.stderr)
# ✅ Good (STDIO)
logging.info("Processing request")
```
### System requirements
* Python 3.10 or higher installed.
* You must use the Python MCP SDK 1.2.0 or higher.
### Set up your environment
First, let's install `uv` and set up our Python project and environment:
<CodeGroup>
```bash macOS/Linux theme={null}
curl -LsSf https://astral.sh/uv/install.sh | sh
```
```powershell Windows theme={null}
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
```
</CodeGroup>
Make sure to restart your terminal afterwards to ensure that the `uv` command gets picked up.
Now, let's create and set up our project:
<CodeGroup>
```bash macOS/Linux theme={null}
# Create a new directory for our project
uv init weather
cd weather
# Create virtual environment and activate it
uv venv
source .venv/bin/activate
# Install dependencies
uv add "mcp[cli]" httpx
# Create our server file
touch weather.py
```
```powershell Windows theme={null}
# Create a new directory for our project
uv init weather
cd weather
# Create virtual environment and activate it
uv venv
.venv\Scripts\activate
# Install dependencies
uv add mcp[cli] httpx
# Create our server file
new-item weather.py
```
</CodeGroup>
Now let's dive into building your server.
## Building your server
### Importing packages and setting up the instance
Add these to the top of your `weather.py`:
```python theme={null}
from typing import Any
import httpx
from mcp.server.fastmcp import FastMCP
# Initialize FastMCP server
mcp = FastMCP("weather")
# Constants
NWS_API_BASE = "https://api.weather.gov"
USER_AGENT = "weather-app/1.0"
```
The FastMCP class uses Python type hints and docstrings to automatically generate tool definitions, making it easy to create and maintain MCP tools.
### Helper functions
Next, let's add our helper functions for querying and formatting the data from the National Weather Service API:
```python theme={null}
async def make_nws_request(url: str) -> dict[str, Any] | None:
"""Make a request to the NWS API with proper error handling."""
headers = {"User-Agent": USER_AGENT, "Accept": "application/geo+json"}
async with httpx.AsyncClient() as client:
try:
response = await client.get(url, headers=headers, timeout=30.0)
response.raise_for_status()
return response.json()
except Exception:
return None
def format_alert(feature: dict) -> str:
"""Format an alert feature into a readable string."""
props = feature["properties"]
return f"""
Event: {props.get("event", "Unknown")}
Area: {props.get("areaDesc", "Unknown")}
Severity: {props.get("severity", "Unknown")}
Description: {props.get("description", "No description available")}
Instructions: {props.get("instruction", "No specific instructions provided")}
"""
```
### Implementing tool execution
The tool execution handler is responsible for actually executing the logic of each tool. Let's add it:
```python theme={null}
@mcp.tool()
async def get_alerts(state: str) -> str:
"""Get weather alerts for a US state.
Args:
state: Two-letter US state code (e.g. CA, NY)
"""
url = f"{NWS_API_BASE}/alerts/active/area/{state}"
data = await make_nws_request(url)
if not data or "features" not in data:
return "Unable to fetch alerts or no alerts found."
if not data["features"]:
return "No active alerts for this state."
alerts = [format_alert(feature) for feature in data["features"]]
return "\n---\n".join(alerts)
@mcp.tool()
async def get_forecast(latitude: float, longitude: float) -> str:
"""Get weather forecast for a location.
Args:
latitude: Latitude of the location
longitude: Longitude of the location
"""
# First get the forecast grid endpoint
points_url = f"{NWS_API_BASE}/points/{latitude},{longitude}"
points_data = await make_nws_request(points_url)
if not points_data:
return "Unable to fetch forecast data for this location."
# Get the forecast URL from the points response
forecast_url = points_data["properties"]["forecast"]
forecast_data = await make_nws_request(forecast_url)
if not forecast_data:
return "Unable to fetch detailed forecast."
# Format the periods into a readable forecast
periods = forecast_data["properties"]["periods"]
forecasts = []
for period in periods[:5]: # Only show next 5 periods
forecast = f"""
{period["name"]}:
Temperature: {period["temperature"]}°{period["temperatureUnit"]}
Wind: {period["windSpeed"]} {period["windDirection"]}
Forecast: {period["detailedForecast"]}
"""
forecasts.append(forecast)
return "\n---\n".join(forecasts)
```
### Running the server
Finally, let's initialize and run the server:
```python theme={null}
def main():
# Initialize and run the server
mcp.run(transport="stdio")
if __name__ == "__main__":
main()
```
Your server is complete! Run `uv run weather.py` to start the MCP server, which will listen for messages from MCP hosts.
Let's now test your server from an existing MCP host, Claude for Desktop.
## Testing your server with Claude for Desktop
<Note>
Claude for Desktop is not yet available on Linux. Linux users can proceed to the [Building a client](/docs/2025-06-18/develop/build-client) tutorial to build an MCP client that connects to the server we just built.
</Note>
First, make sure you have Claude for Desktop installed. [You can install the latest version
here.](https://claude.ai/download) If you already have Claude for Desktop, **make sure it's updated to the latest version.**
We'll need to configure Claude for Desktop for whichever MCP servers you want to use. To do this, open your Claude for Desktop App configuration at `~/Library/Application Support/Claude/claude_desktop_config.json` in a text editor. Make sure to create the file if it doesn't exist.
For example, if you have [VS Code](https://code.visualstudio.com/) installed:
<CodeGroup>
```bash macOS/Linux theme={null}
code ~/Library/Application\ Support/Claude/claude_desktop_config.json
```
```powershell Windows theme={null}
code $env:AppData\Claude\claude_desktop_config.json
```
</CodeGroup>
You'll then add your servers in the `mcpServers` key. The MCP UI elements will only show up in Claude for Desktop if at least one server is properly configured.
In this case, we'll add our single weather server like so:
<CodeGroup>
```json macOS/Linux theme={null}
{
"mcpServers": {
"weather": {
"command": "uv",
"args": [
"--directory",
"/ABSOLUTE/PATH/TO/PARENT/FOLDER/weather",
"run",
"weather.py"
]
}
}
}
```
Cut at 300 lines. The page has the rest.
docs/2025-06-18/develop/build-with-agent-skills New page · 100 lines, new page
# Build with Agent Skills ## Available skills ## Start a build ## Deployment paths ## Next steps
A whole new page. There's nothing to diff it against, so here is what it says.
# Build with Agent Skills
> Use agent skills to guide AI coding assistants through MCP server design and implementation
[Agent skills](https://agentskills.io/home) are portable instruction sets that
give AI coding assistants domain knowledge for a task. For MCP development,
they encode the design decisions (deployment model, tool patterns, auth) so
your agent can interrogate your use case and scaffold a server that fits.
## Available skills
A reference set of MCP development skills is available as the
[`mcp-server-dev` plugin](https://github.com/anthropics/claude-plugins-official/tree/main/plugins/mcp-server-dev).
It provides three composing skills:
| Skill | Purpose |
| ------------------ | ----------------------------------------------------------------------------------------------------------------------- |
| `build-mcp-server` | Entry point. Interrogates the use case, picks a deployment model and tool-design pattern, routes to specialized skills. |
| `build-mcp-app` | Adds interactive UI widgets (forms, pickers, dashboards) rendered inline in chat. |
| `build-mcpb` | Packages a local stdio server with its runtime so users can install it without Node or Python. |
Each skill ships a `SKILL.md` file plus a `references/` folder of supporting
material (auth flows, tool-design patterns, widget templates, manifest schemas)
that the agent reads on demand. The files follow the open format and work with
any agent that implements the standard. For example, to install them in Claude
Code:
```bash theme={null}
/plugin marketplace add anthropics/claude-plugins-official
/plugin install mcp-server-dev
```
For other agents, check your skills or extensions catalog, or clone the
[skill directories](https://github.com/anthropics/claude-plugins-official/tree/main/plugins/mcp-server-dev/skills)
(`SKILL.md` plus `references/`) into your agent's skills location.
## Start a build
With the skills installed, ask your agent to help you build an MCP server. The
entry skill triggers on natural-language requests, or you can invoke it
directly using your agent's skill-invocation syntax.
The skill runs a short discovery phase before writing any code. Expect
questions about:
* **What it connects to** — a cloud API, a local process, the filesystem, hardware
* **Who will use it** — just you, your team, or anyone who installs it
* **Action surface size** — a handful of operations versus wrapping a large API
* **User interaction needs** — plain text results, structured input via
[elicitation](/specification/2025-06-18/client/elicitation), or rich UI widgets
* **Upstream auth** — API keys, OAuth 2.0, or none
If your opening message already covers these, the agent skips ahead to the
recommendation.
## Deployment paths
Based on discovery, the skill recommends one of four paths and scaffolds
accordingly:
**Remote [Streamable HTTP](/specification/2025-06-18/basic/transports#streamable-http)**
is the default for anything wrapping a cloud API. Zero install friction, one
deployment serves all users, and OAuth flows work properly because the server
can handle redirects and token storage. The reference skill includes scaffolds
for Cloudflare Workers and portable Express/FastMCP setups.
**[MCP apps](/extensions/apps/overview)** extend a server with interactive
widgets rendered in chat, such as searchable pickers, charts, and live
dashboards. The skill hands off to `build-mcp-app` when
[elicitation's](/specification/2025-06-18/client/elicitation) flat-form constraints
don't fit.
**[MCP Bundles (MCPB)](https://github.com/modelcontextprotocol/mcpb)** package a
local server together with its runtime as a single `.mcpb` archive, so users
can install it without setting up Node or Python. Use this path when the server
must touch the user's machine: reading local files, driving desktop apps, or
talking to localhost services. The skill hands off to `build-mcpb`.
**Local [stdio](/specification/2025-06-18/basic/transports#stdio)** remains available
for prototyping, with a noted upgrade path to MCPB when you're ready to
distribute.
## Next steps
Once your agent scaffolds the server, iterate on tool descriptions and error
handling, then test and ship:
<CardGroup cols={2}>
<Card title="MCP Inspector" icon="magnifying-glass" href="/docs/2025-06-18/tools/inspector">
Test your server's tools, resources, and prompts interactively
</Card>
<Card title="Connect to a client" icon="plug" href="/docs/2025-06-18/develop/connect-local-servers">
Wire your server into an MCP client via local or remote configuration
</Card>
<Card title="Publish to the Registry" icon="box" href="/registry/quickstart">
Make your server discoverable in the MCP Registry
</Card>
</CardGroup>
docs/2025-06-18/develop/clients/client-best-practices New page · 292 lines, new page
# Client Best Practices ## Progressive Tool Discovery ### When to Use Progressive Discovery ### Choosing a Discovery Strategy ### Using Progressive Discovery ### Dynamic Server Management ### Implementation Guidelines ### Interaction with Prompt Caching ## Programmatic Tool Calling / Code Mode ### How It Works ### Choosing a Sandbox ### Execution Architecture ### Security Considerations ### Error Handling ## Combining Both Patterns
A whole new page. There's nothing to diff it against, so here is what it says.
# Client Best Practices
> Patterns for scaling MCP host applications across many servers and tools.
As MCP host applications, such as agents, connect to more MCP servers and accumulate access to hundreds or thousands of tools, naive approaches to tool management break down. Loading every tool definition into the model's context window upfront wastes tokens, increases latency, and degrades model performance. Passing large intermediate results through the model between sequential tool calls compounds the problem.
Two patterns address these challenges: **progressive discovery**, which controls *when* tool definitions enter context, and **programmatic tool calling**, which controls *how* tools are invoked.
## Progressive Tool Discovery
Naive MCP host implementations pass the tool definitions of every connected server directly to the model at the start of each conversation. For a handful of tools, this is perfectly reasonable. But when a host has access to dozens of servers exposing hundreds of tools, those definitions alone can consume the majority of the context window before the model has even read the user's message.
<img src="https://mintcdn.com/mcp/JXfd5cBmEUh_qPUI/images/progressive-discovery.svg?fit=max&auto=format&n=JXfd5cBmEUh_qPUI&q=85&s=db39f47006107f04af43b5eeae2d6022" alt="Comparison of loading all tools upfront versus discovering tools on demand. The upfront approach consumes ~150,000 tokens on definitions alone, while progressive discovery uses ~2,000 tokens by loading only what the task requires." width="760" height="440" data-path="images/progressive-discovery.svg" />
Progressive discovery avoids this:
* The host fetches tool definitions via `tools/list` as normal, but defers injecting them into the model's context.
* The host provides a lightweight `search_tools` meta-tool to the model.
* The host loads full definitions into context only as needed.
### When to Use Progressive Discovery
Progressive discovery is best used when tool definitions take large parts of the context window. For a small
set of tools with tool definitions taking up a small part of the context window, loading all tools is fine.
Once the tool definitions take up a significant part of the available context window, clients should switch to progressive discovery. We recommend that clients implement thresholds to determine when to switch:
* Implement a threshold as a percentage of the context window. For example, 1%-5%.
* Load tool definitions. Once the threshold is reached, switch to progressive discovery.
### Choosing a Discovery Strategy
Once the model invokes the `search_tools` tool, we need to choose a search strategy:
* **Keyword-based**: Keyword matching (BM25, regex). Simple and effective, particularly for descriptive tool names and descriptions.
* **Embedding-based**: Vector-similarity retrieval over tool descriptions. Handles synonyms and semantic matching better.
* **Subagent-based**: A secondary model, often a small and fast model such as Claude Haiku or Gemini Flash, selects tools for the task. This usually works very well but can be more costly than embedding-based or keyword-based solutions.
* **Hybrid**: Combine approaches. For example, by scoring across keyword and embedding rankings, or choosing
different strategies depending on use-case or query.
Some model providers already offer built-in tool search. For example, [OpenAI](https://developers.openai.com/api/docs/guides/tools-tool-search) and [Anthropic](https://platform.claude.com/docs/en/agents-and-tools/tool-use/tool-search-tool) support this natively; check your provider's documentation for an equivalent. When available, you may prefer the platform's tool search over a custom implementation. Build your own when the provider doesn't offer one or when you need specialized retrieval logic (e.g., domain-specific ranking or access-control filtering).
The three-layer pattern below illustrates a custom search-based approach in detail, but the layered principle (catalog, inspect, execute) applies regardless of retrieval mechanism.
### Using Progressive Discovery
One common implementation for progressive discovery uses a search-based three-layer approach:
**Layer 1: Catalog.** The host exposes a small set of meta-tools for searching available capabilities. A `search_tools` tool accepts a natural-language query and returns matching tool names with brief descriptions.
```typescript theme={null}
// The model calls a lightweight search tool
search_tools({ query: "update salesforce record" })
// Returns concise matches: names and one-line descriptions only
→ [
{ name: "salesforce_updateRecord", description: "Update fields on a Salesforce object" },
{ name: "salesforce_upsertRecord", description: "Insert or update based on external ID" }
]
```
**Layer 2: Inspect.** Once the model identifies a candidate, it fetches the full definition (input schema, output schema, documentation) for that tool only.
```typescript theme={null}
// The model inspects only the tool it needs
get_tool_details({ name: "salesforce_updateRecord" });
```
This returns the complete schema for a single tool:
```json theme={null}
{
"name": "salesforce_updateRecord",
"description": "Updates a record in Salesforce",
"inputSchema": {
"type": "object",
"properties": {
"objectType": {
"type": "string",
"description": "Salesforce object type"
},
"recordId": { "type": "string", "description": "Record ID to update" },
"data": { "type": "object", "description": "Fields to update" }
},
"required": ["objectType", "recordId", "data"]
}
}
```
**Layer 3: Execute.** The model calls the tool with full knowledge of its interface, having loaded only the definitions it needed.
This pattern reduces token usage dramatically and can improve tool selection accuracy: the model focuses on a few relevant tools rather than scanning hundreds of irrelevant ones. Other discovery strategies (embeddings, subagents, etc.) follow the same layered principle but substitute different retrieval mechanisms in the catalog layer.
### Dynamic Server Management
Progressive discovery extends beyond individual tools to entire servers. Rather than connecting to every configured server at startup, a host can:
1. Maintain a registry of available servers and their high-level descriptions.
2. Connect to a server only when the model determines it needs that server's capabilities.
3. Disconnect servers that are no longer relevant to the current task, freeing context.
```mermaid theme={null}
sequenceDiagram
participant Model
participant Host
participant Registry
participant Server
Model->>Host: search_available_servers("CRM")
Host->>Registry: Query available servers
Registry-->>Host: Salesforce server (not connected)
Host-->>Model: Salesforce server available
Model->>Host: enable_server("salesforce")
Host->>Server: Initialize connection
Server-->>Host: Server capabilities + tools
Host-->>Model: Salesforce server connected
Note over Model: Task complete
Model->>Host: disable_server("salesforce")
Host->>Server: Close connection
Host-->>Model: Server disconnected, context freed
```
This works especially well for general-purpose agents, where the user's intent isn't known upfront. The agent starts with a minimal set of always-on servers and connects others as needed. Combined with [agent skills](/docs/2025-06-18/develop/build-with-agent-skills), a skill file can declare which MCP servers it needs, and the host connects them only when that skill is invoked.
### Implementation Guidelines
When implementing progressive discovery:
| Guideline | Rationale |
| -------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Offer multiple detail levels** | Let the model choose between name-only, name-and-description, or full-schema responses. |
| **Cache tool definitions** | Once fetched from a server, memoize the definition host-side so re-injecting it later doesn't need another `tools/list` round trip. This is separate from what's currently in the model's context. |
| **Refresh on `list_changed`** | Re-index the search catalog when a server sends `notifications/tools/list_changed`. |
| **Group tools by server** | Present tools organized by their source server so the model can reason about related capabilities. |
### Interaction with Prompt Caching
Most providers cache the prompt prefix, including the `tools` array. Adding or removing tool
definitions mid-conversation invalidates that cache, and the resulting miss can cost more tokens
than the definitions you removed. To preserve caching:
* Append newly discovered definitions after the cache breakpoint rather than re-sorting the
`tools` array, or route every call through a single stable `call_tool({name, args})` meta-tool
so the array never changes.
* Treat server disconnection as a conversation-boundary operation rather than a per-turn one.
* Consult your provider's caching documentation alongside the tool-search links above.
## Programmatic Tool Calling / Code Mode
With direct tool calling, every tool invocation is a round trip: the model generates a tool call, the client executes it, and the full result flows back into the model's context. When a task requires chaining multiple tools (read a document, transform it, write it somewhere else), each intermediate result passes through the model, consuming tokens and adding latency even when it has nothing to do with them.
Programmatic tool calling (sometimes called "code mode") provides a way for clients to **compose tool calls** effectively. Instead of calling tools directly, the model writes code that calls tools. The code executes in a sandboxed environment, and only the final result returns to the model.
Programmatic tool calling is powerful and allows for more efficient use of MCP tools and resources, but requires
clients to implement a sandbox environment.
<img src="https://mintcdn.com/mcp/JXfd5cBmEUh_qPUI/images/programmatic-tool-calling.svg?fit=max&auto=format&n=JXfd5cBmEUh_qPUI&q=85&s=a2be82d097bb7cd7c7fd415918b1571d" alt="Comparison of direct tool calling versus programmatic tool calling. Direct calling passes every intermediate result through the model (~100K+ tokens). Programmatic calling sends a ~200-token script to a sandbox, which executes the tool calls and returns a ~15-token summary." width="900" height="900" data-path="images/programmatic-tool-calling.svg" />
### How It Works
The host converts MCP tool schemas into a typed API available inside a sandbox. When the model needs tools, it writes a script and executes it.
**Step 1: Generate a programmatic API from MCP schemas.** The host reads each server's tool definitions and produces typed functions based on each tool's arguments and `outputSchema`:
```typescript theme={null}
// Auto-generated from the Logging MCP server's tool schema
interface LogEntry {
timestamp: string;
message: string;
level: string;
}
function logging_getLogs(input: {
level: "error" | "warn" | "info";
since: number;
}): Promise<{ entries: LogEntry[] }> {
return mcp.callTool<{ entries: LogEntry[] }>("logging_getLogs", input);
}
// Auto-generated from the Ticketing MCP server's tool schema
function ticketing_createIssue(input: {
title: string;
body?: string;
priority: "low" | "medium" | "high";
}): Promise<{ issueId: string }> {
return mcp.callTool<{ issueId: string }>("ticketing_createIssue", input);
}
```
MCP Servers can provide an optional [`outputSchema`](/specification/2025-06-18/server/tools#output-schema) for each tool. When an output schema is present, the host can produce precise return types (like `LogEntry` above).
When an output schema is absent, prefer the simple path:
* **Use a generic type and move on.** Accept `any` or `string` and handle the unstructured output downstream. The real fix is for server authors to provide `outputSchema`.
* **Extract a typed result using a fast model**, for single-shot calls outside loops. Expose a host-brokered `extract(value, ExpectedType)` helper through the same stub-interception path as MCP tool calls so the sandbox itself never opens a network connection. The helper routes to a small model (for example, Claude Haiku or Gemini Flash) to coerce the value into `ExpectedType`. This adds per-call latency and can hallucinate or drop fields, so validate the result against `ExpectedType` before use.
**Step 2: The model writes code against these APIs.** Rather than making separate tool calls with full results flowing through context between them, the model writes a single script. Consider a task like "find all error logs from the past hour and file a ticket for each unique error." With direct tool calling, thousands of log entries would flow through the model's context. With code, the model filters in the sandbox:
```typescript theme={null}
// Model-generated code, executes in sandbox
const logs = await logging_getLogs({
level: "error",
since: Date.now() - 3600000,
});
// Filter and deduplicate inside the sandbox, not in the model's context
const uniqueErrors = new Map<string, LogEntry>();
for (const log of logs.entries) {
if (!uniqueErrors.has(log.message)) {
uniqueErrors.set(log.message, log);
}
}
for (const [message, log] of uniqueErrors) {
await ticketing_createIssue({
title: `Error: ${message}`,
body: `First seen: ${log.timestamp}\nOccurrences: ${
logs.entries.filter((l) => l.message === message).length
}`,
priority: "high",
});
}
console.log(
`Filed ${uniqueErrors.size} tickets from ${logs.entries.length} error logs`,
);
```
**Step 3: The sandbox executes the code.** Function calls inside the sandbox are intercepted and routed back to the appropriate MCP server through the host broker. The log data and ticket creation flow directly between servers without ever entering the model's context. Only the `console.log` output, a single summary line, returns to the model.
### Choosing a Sandbox
The right sandbox depends on the language you want the model to write, your host application's language, and how much isolation you need. The table lists example runtimes rather than endorsements; evaluate maturity for your use case:
| Sandboxed language | Runtime / Library | Host language | Approach |
| ------------------ | ------------------------------------------------------------- | ----------------- | ----------------------------------------------------------------------------------------------- |
| **JavaScript** | [Deno](https://github.com/denoland/deno), `isolated-vm` | Rust / Node / CLI | V8-based runtimes with fine-grained permissions. Can disable all permissions for full lockdown. |
| **Python** | [Monty](https://github.com/pydantic/monty) *(experimental)* | Rust | Minimal Python interpreter built for AI use cases. No I/O by default. |
| **TypeScript** | [pctx](https://github.com/portofcontext/pctx) *(early-stage)* | Python / Rust | Incorporates code mode concepts as a library, with low-level Rust support. |
| **Any (via Wasm)** | [Wasmtime](https://github.com/bytecodealliance/wasmtime) | Rust / C / Go | Compile any language to Wasm and run it with capability-based security. |
Regardless of sandbox, the integration pattern is the same: the host injects function stubs, intercepts calls over an in-process or stdio channel (so network permissions can stay fully denied), and dispatches them as `tools/call` requests to MCP servers.
### Execution Architecture
The implementation has three components:
```mermaid theme={null}
flowchart LR
subgraph Host["MCP Host"]
A[LLM] -->|writes code| B[Sandbox]
B -->|function call| C[MCP Client]
C -->|return value| B
B -->|console output| A
end
C -->|tool call| D[MCP Server A]
C -->|tool call| E[MCP Server B]
D -->|result| C
E -->|result| C
```
**The sandbox** runs model-generated code in an isolated environment with no direct network access. Its only interface to the outside world is through the generated function stubs, which route calls back to the host.
**The host** acts as a broker. It receives function calls from the sandbox, maps them to the correct MCP server, executes the tool call, and returns the result to the sandbox. Authorization tokens and credentials are held by the host and never exposed to the generated code.
**The model** sees only what the sandbox returns, typically the output of `console.log` statements or a final return value. This gives the model (and the client developer) precise control over what enters the context window.
### Security Considerations
Programmatic tool calling introduces a code execution surface that requires careful sandboxing:
* **Per-call authorization**: The broker is still the MCP host for spec purposes. Apply the same human-in-the-loop confirmation policy to sandbox-originated calls that you apply to direct calls (see [Tools: Security](/specification/2025-06-18/server/tools#security-considerations)). Approving the script does not grant blanket approval for every tool call it makes at runtime; hosts may grant categorical approval (for example, "allow `ticketing_createIssue` for this script run") rather than prompting per iteration, but the broker must still evaluate each call against that grant.
* **Cross-server data flow**: Tool results from one server are untrusted input to another. The broker should apply the same input-review policy to brokered calls as to direct ones; output truncation alone does not prevent exfiltration.
* **Network isolation**: The sandbox should have no direct network access. All external communication flows through the host broker, which enforces authorization and access control.
* **No credential exposure**: API keys and tokens are held by the host. The generated code calls typed functions; the host adds authentication when forwarding to servers.
* **Resource limits**: Set timeouts and memory limits on sandbox execution to prevent runaway scripts.
* **Output filtering**: Validate and truncate sandbox console output before feeding it back to the model.
### Error Handling
MCP tool errors arrive as a successful response with
[`isError: true`](/specification/2025-06-18/server/tools#error-handling) rather than a transport
failure. Generated wrappers should convert this into a thrown exception so model-authored code
can use `try`/`catch`. If an uncaught error terminates the script, surface it as the script's
result so the model can self-correct; the model is responsible for reporting any partial side
effects already committed.
## Combining Both Patterns
Progressive discovery and programmatic tool calling work well together. The model uses discovery tools to identify which tools it needs, loads their schemas, and then writes a single script that calls multiple tools in one execution pass. This combination minimizes both the token cost of tool definitions *and* the token cost of tool results, keeping the model's context focused on reasoning rather than passing data through it.
docs/2025-06-18/develop/connect-local-servers New page · 283 lines, new page
# Connect to local MCP servers ## Prerequisites ### Claude Desktop ### Node.js ## Understanding MCP Servers ## Installing the Filesystem Server ## Using the Filesystem Server ### File Management Examples ### How Approval Works ## Troubleshooting ## Next Steps
A whole new page. There's nothing to diff it against, so here is what it says.
# Connect to local MCP servers
> Learn how to extend Claude Desktop with local MCP servers to enable file system access and other powerful integrations
Model Context Protocol (MCP) servers extend AI applications' capabilities by providing secure, controlled access to local resources and tools. Many clients support MCP, enabling diverse integration possibilities across different platforms and applications.
This guide demonstrates how to connect to local MCP servers using Claude Desktop as an example, one of the many clients that support MCP. While we focus on Claude Desktop's implementation, the concepts apply broadly to other MCP-compatible clients. By the end of this tutorial, Claude will be able to interact with files on your computer, create new documents, organize folders, and search through your file system—all with your explicit permission for each action.
<Frame>
<img src="https://mintcdn.com/mcp/4ZXF1PrDkEaJvXpn/images/quickstart-filesystem.png?fit=max&auto=format&n=4ZXF1PrDkEaJvXpn&q=85&s=629d7e754dc358d71a408d6ce970c1b1" alt="Claude Desktop with filesystem integration showing file management capabilities" width="1732" height="2060" data-path="images/quickstart-filesystem.png" />
</Frame>
## Prerequisites
Before starting this tutorial, ensure you have the following installed on your system:
### Claude Desktop
Download and install [Claude Desktop](https://claude.ai/download) for your operating system. Claude Desktop is available for macOS and Windows.
If you already have Claude Desktop installed, verify you're running the latest version by clicking the Claude menu and selecting "Check for Updates..."
### Node.js
The Filesystem Server and many other MCP servers require Node.js to run. Verify your Node.js installation by opening a terminal or command prompt and running:
```bash theme={null}
node --version
```
If Node.js is not installed, download it from [nodejs.org](https://nodejs.org/). We recommend the LTS (Long Term Support) version for stability.
## Understanding MCP Servers
MCP servers are programs that run on your computer and provide specific capabilities to Claude Desktop through a standardized protocol. Each server exposes tools that Claude can use to perform actions, with your approval. The Filesystem Server we'll install provides tools for:
* Reading file contents and directory structures
* Creating new files and directories
* Moving and renaming files
* Searching for files by name or content
All actions require your explicit approval before execution, ensuring you maintain full control over what Claude can access and modify.
## Installing the Filesystem Server
The process involves configuring Claude Desktop to automatically start the Filesystem Server whenever you launch the application. This configuration is done through a JSON file that tells Claude Desktop which servers to run and how to connect to them.
<Steps>
<Step title="Open Claude Desktop Settings">
Start by accessing the Claude Desktop settings. Click on the Claude menu in your system's menu bar (not the settings within the Claude window itself) and select "Settings..."
On macOS, this appears in the top menu bar:
<Frame style={{ textAlign: "center" }}>
<img src="https://mintcdn.com/mcp/4ZXF1PrDkEaJvXpn/images/quickstart-menu.png?fit=max&auto=format&n=4ZXF1PrDkEaJvXpn&q=85&s=0c8b57e0e17af3624b6762a3ea944c8e" width="400" alt="Claude Desktop menu showing Settings option" data-path="images/quickstart-menu.png" />
</Frame>
This opens the Claude Desktop configuration window, which is separate from your Claude account settings.
</Step>
<Step title="Access Developer Settings">
In the Settings window, navigate to the "Developer" tab in the left sidebar. This section contains options for configuring MCP servers and other developer features.
Click the "Edit Config" button to open the configuration file:
<Frame>
<img src="https://mintcdn.com/mcp/4ZXF1PrDkEaJvXpn/images/quickstart-developer.png?fit=max&auto=format&n=4ZXF1PrDkEaJvXpn&q=85&s=0fb595490a2f9e15c0301e771a57446c" alt="Developer settings showing Edit Config button" width="1688" height="534" data-path="images/quickstart-developer.png" />
</Frame>
This action creates a new configuration file if one doesn't exist, or opens your existing configuration. The file is located at:
* **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
* **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
</Step>
<Step title="Configure the Filesystem Server">
Replace the contents of the configuration file with the following JSON structure. This configuration tells Claude Desktop to start the Filesystem Server with access to specific directories:
<CodeGroup>
```json macOS theme={null}
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"/Users/username/Desktop",
"/Users/username/Downloads"
]
}
}
}
```
```json Windows theme={null}
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"C:\\Users\\username\\Desktop",
"C:\\Users\\username\\Downloads"
]
}
}
}
```
</CodeGroup>
Replace `username` with your actual computer username. The paths listed in the `args` array specify which directories the Filesystem Server can access. You can modify these paths or add additional directories as needed.
<Tip>
**Understanding the Configuration**
* `"filesystem"`: A friendly name for the server that appears in Claude Desktop
* `"command": "npx"`: Uses Node.js's npx tool to run the server
* `"-y"`: Automatically confirms the installation of the server package
* `"@modelcontextprotocol/server-filesystem"`: The package name of the Filesystem Server
* The remaining arguments: Directories the server is allowed to access
</Tip>
<Warning>
**Security Consideration**
Only grant access to directories you're comfortable with Claude reading and modifying. The server runs with your user account permissions, so it can perform any file operations you can perform manually.
</Warning>
</Step>
<Step title="Restart Claude Desktop">
After saving the configuration file, completely quit Claude Desktop and restart it. The application needs to restart to load the new configuration and start the MCP server.
Upon successful restart, click the "Add files, connectors and more" indicator <img src="https://mintcdn.com/mcp/cpXzQjUOzyH0mCNH/images/claude-add-files-connectors-and-more.png?fit=max&auto=format&n=cpXzQjUOzyH0mCNH&q=85&s=53acf21f6807dd5323b70b84b5d98d8a" style={{display: 'inline', margin: 0, height: '1.3em'}} width="33" height="33" data-path="images/claude-add-files-connectors-and-more.png" /> in the bottom-left corner of the conversation input box:
<Frame>
<img src="https://mintcdn.com/mcp/akpggzunDlIcY2im/images/quickstart-slider.png?fit=max&auto=format&n=akpggzunDlIcY2im&q=85&s=a1ebd4259cff2a7472171885f2edc035" alt="Claude Desktop interface showing MCP server indicator" width="1414" height="410" data-path="images/quickstart-slider.png" />
</Frame>
Click on this indicator, then scroll over "Connectors" and click "Manage connectors". Select "filesystem" from the connector list to view the the Filesystem Server's available tools:
<Frame style={{ textAlign: "center" }}>
<img src="https://mintcdn.com/mcp/cpXzQjUOzyH0mCNH/images/quickstart-tools.png?fit=max&auto=format&n=cpXzQjUOzyH0mCNH&q=85&s=212a63d76daba170d52db0d2f6f582be" width="400" alt="Available filesystem tools in Claude Desktop" data-path="images/quickstart-tools.png" />
</Frame>
If the Filesystem Server doesn't connect, refer to the [Troubleshooting](#troubleshooting) section for debugging steps.
</Step>
</Steps>
## Using the Filesystem Server
With the Filesystem Server connected, Claude can now interact with your file system. Try these example requests to explore the capabilities:
### File Management Examples
* **"Can you write a poem and save it to my desktop?"** - Claude will compose a poem and create a new text file on your desktop
* **"What work-related files are in my downloads folder?"** - Claude will scan your downloads and identify work-related documents
* **"Please organize all images on my desktop into a new folder called 'Images'"** - Claude will create a folder and move image files into it
### How Approval Works
Before executing any file system operation, Claude will request your approval. This ensures you maintain control over all actions:
<Frame style={{ textAlign: "center" }}>
<img src="https://mintcdn.com/mcp/4ZXF1PrDkEaJvXpn/images/quickstart-approve.png?fit=max&auto=format&n=4ZXF1PrDkEaJvXpn&q=85&s=98cc6e9dfe885fbd6e9bfae40601e494" width="500" alt="Claude requesting approval to perform a file operation" data-path="images/quickstart-approve.png" />
</Frame>
Review each request carefully before approving. You can always deny a request if you're not comfortable with the proposed action.
## Troubleshooting
If you encounter issues setting up or using the Filesystem Server, these solutions address common problems:
<AccordionGroup>
<Accordion title="Server not showing up in Claude / hammer icon missing">
1. Restart Claude Desktop completely
2. Check your `claude_desktop_config.json` file syntax
3. Make sure the file paths included in `claude_desktop_config.json` are valid and that they are absolute and not relative
4. Look at [logs](#getting-logs-from-claude-for-desktop) to see why the server is not connecting
5. In your command line, try manually running the server (replacing `username` as you did in `claude_desktop_config.json`) to see if you get any errors:
<CodeGroup>
```bash macOS/Linux theme={null}
npx -y @modelcontextprotocol/server-filesystem /Users/username/Desktop /Users/username/Downloads
```
```powershell Windows theme={null}
npx -y @modelcontextprotocol/server-filesystem C:\Users\username\Desktop C:\Users\username\Downloads
```
</CodeGroup>
</Accordion>
<Accordion title="Getting logs from Claude Desktop">
Claude.app logging related to MCP is written to log files in:
* macOS: `~/Library/Logs/Claude`
* Windows: `%APPDATA%\Claude\logs`
* `mcp.log` will contain general logging about MCP connections and connection failures.
* Files named `mcp-server-SERVERNAME.log` will contain error (stderr) logging from the named server.
You can run the following command to list recent logs and follow along with any new ones (on Windows, it will only show recent logs):
<CodeGroup>
```bash macOS/Linux theme={null}
tail -n 20 -f ~/Library/Logs/Claude/mcp*.log
```
```powershell Windows theme={null}
type "%APPDATA%\Claude\logs\mcp*.log"
```
</CodeGroup>
</Accordion>
<Accordion title="Tool calls failing silently">
If Claude attempts to use the tools but they fail:
1. Check Claude's logs for errors
2. Verify your server builds and runs without errors
3. Try restarting Claude Desktop
</Accordion>
<Accordion title="None of this is working. What do I do?">
Please refer to our [debugging guide](/docs/2025-06-18/tools/debugging) for better debugging tools and more detailed guidance.
</Accordion>
<Accordion title="ENOENT error and `${APPDATA}` in paths on Windows">
If your configured server fails to load, and you see within its logs an error referring to `${APPDATA}` within a path, you may need to add the expanded value of `%APPDATA%` to your `env` key in `claude_desktop_config.json`:
```json theme={null}
{
"brave-search": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-brave-search"],
"env": {
"APPDATA": "C:\\Users\\user\\AppData\\Roaming\\",
"BRAVE_API_KEY": "..."
}
}
}
```
With this change in place, launch Claude Desktop once again.
<Warning>
**npm should be installed globally**
The `npx` command may continue to fail if you have not installed npm globally. If npm is already installed globally, you will find `%APPDATA%\npm` exists on your system. If not, you can install npm globally by running the following command:
```bash theme={null}
npm install -g npm
```
</Warning>
</Accordion>
</AccordionGroup>
## Next Steps
Now that you've successfully connected Claude Desktop to a local MCP server, explore these options to expand your setup:
<CardGroup cols={2}>
<Card title="Explore other servers" icon="grid" href="https://github.com/modelcontextprotocol/servers">
Browse our collection of official and community-created MCP servers for
additional capabilities
</Card>
<Card title="Build your own server" icon="code" href="/docs/2025-06-18/develop/build-server">
Create custom MCP servers tailored to your specific workflows and
integrations
</Card>
<Card title="Connect to remote servers" icon="cloud" href="/docs/2025-06-18/develop/connect-remote-servers">
Learn how to connect Claude to remote MCP servers for cloud-based tools and
services
</Card>
<Card title="Understand the protocol" icon="book" href="/docs/2025-06-18/learn/architecture">
Dive deeper into how MCP works and its architecture
</Card>
</CardGroup>
docs/2025-06-18/develop/connect-remote-servers New page · 118 lines, new page
# Connect to remote MCP Servers ## Understanding Remote MCP Servers ## What are Custom Connectors? ## Connecting to a Remote MCP Server ## Best Practices for Using Remote MCP Servers ## Next Steps
A whole new page. There's nothing to diff it against, so here is what it says.
# Connect to remote MCP Servers
> Learn how to connect Claude to remote MCP servers and extend its capabilities with internet-hosted tools and data sources
Remote MCP servers extend AI applications' capabilities beyond your local environment, providing access to internet-hosted tools, services, and data sources. By connecting to remote MCP servers, you transform AI assistants from helpful tools into informed teammates capable of handling complex, multi-step projects with real-time access to external resources.
Many clients now support remote MCP servers, enabling a wide range of integration possibilities. This guide demonstrates how to connect to remote MCP servers using [Claude](https://claude.ai/) as an example, one of the many clients that support MCP. While we focus on Claude's implementation through Custom Connectors, the concepts apply broadly to other MCP-compatible clients.
## Understanding Remote MCP Servers
Remote MCP servers function similarly to local MCP servers but are hosted on the internet rather than your local machine. They expose tools, prompts, and resources that Claude can use to perform tasks on your behalf. These servers can integrate with various services such as project management tools, documentation systems, code repositories, and any other API-enabled service.
The key advantage of remote MCP servers is their accessibility. Unlike local servers that require installation and configuration on each device, remote servers are available from any MCP client with an internet connection. This makes them ideal for web-based AI applications, integrations that emphasize ease of use, and services that require server-side processing or authentication.
## What are Custom Connectors?
Custom Connectors serve as the bridge between Claude and remote MCP servers. They allow you to connect Claude directly to the tools and data sources that matter most to your workflows, enabling Claude to operate within your favorite software and draw insights from the complete context of your external tools.
With Custom Connectors, you can:
* [Connect Claude to existing remote MCP servers](https://support.anthropic.com/en/articles/11175166-getting-started-with-custom-connectors-using-remote-mcp) provided by third-party developers
* [Build your own remote MCP servers to connect with any tool](https://support.anthropic.com/en/articles/11503834-building-custom-connectors-via-remote-mcp-servers)
## Connecting to a Remote MCP Server
The process of connecting Claude to a remote MCP server involves adding a Custom Connector through the [Claude interface](https://claude.ai/). This establishes a secure connection between Claude and your chosen remote server.
<Steps>
<Step title="Navigate to Connector Settings">
Open Claude in your browser and navigate to the settings page. You can access this by clicking on your profile icon and selecting "Settings" from the dropdown menu. Once in settings, locate and click on the "Connectors" section in the sidebar.
This will display your currently configured connectors and provide options to add new ones.
</Step>
<Step title="Add a Custom Connector">
In the Connectors section, scroll to the bottom where you'll find the "Add custom connector" button. Click this button to begin the connection process.
<Frame>
<img src="https://mintcdn.com/mcp/4ZXF1PrDkEaJvXpn/images/quickstart-remote/1-add-connector.png?fit=max&auto=format&n=4ZXF1PrDkEaJvXpn&q=85&s=b5ae9b23164875bbaa3aff4c178cdc64" alt="Add custom connector button in Claude settings" width="1038" height="809" data-path="images/quickstart-remote/1-add-connector.png" />
</Frame>
A dialog will appear prompting you to enter the remote MCP server URL. This URL should be provided by the server developer or administrator. Enter the complete URL, ensuring it includes the proper protocol (https\://) and any necessary path components.
<Frame>
<img src="https://mintcdn.com/mcp/4ZXF1PrDkEaJvXpn/images/quickstart-remote/2-connect.png?fit=max&auto=format&n=4ZXF1PrDkEaJvXpn&q=85&s=0934f16d8e016cade8e560c8f89d011b" alt="Dialog for entering remote MCP server URL" width="1616" height="282" data-path="images/quickstart-remote/2-connect.png" />
</Frame>
After entering the URL, click "Add" to proceed with the connection.
</Step>
<Step title="Complete Authentication">
Most remote MCP servers require authentication to ensure secure access to their resources. The authentication process varies depending on the server implementation but commonly involves OAuth, API keys, or username/password combinations.
<Frame>
<img src="https://mintcdn.com/mcp/4ZXF1PrDkEaJvXpn/images/quickstart-remote/3-auth.png?fit=max&auto=format&n=4ZXF1PrDkEaJvXpn&q=85&s=89af6e1b85718637231388697cc7b015" alt="Authentication screen for remote MCP server" width="490" height="806" data-path="images/quickstart-remote/3-auth.png" />
</Frame>
Follow the authentication prompts provided by the server. This may redirect you to a third-party authentication provider or display a form within Claude. Once authentication is complete, Claude will establish a secure connection to the remote server.
</Step>
<Step title="Access Resources and Prompts">
After successful connection, the remote server's resources and prompts become available in your Claude conversations. You can access these by clicking the paperclip icon in the message input area, which opens the attachment menu.
<Frame>
<img src="https://mintcdn.com/mcp/cpXzQjUOzyH0mCNH/images/quickstart-remote/4-select-resources-menu.png?fit=max&auto=format&n=cpXzQjUOzyH0mCNH&q=85&s=e5fa85174f8acbadbd709bac66f42d5c" alt="Attachment menu showing available resources" width="735" height="378" data-path="images/quickstart-remote/4-select-resources-menu.png" />
</Frame>
The menu displays all available resources and prompts from your connected servers. Select the items you want to include in your conversation. These resources provide Claude with context and information from your external tools.
<Frame>
<img src="https://mintcdn.com/mcp/cpXzQjUOzyH0mCNH/images/quickstart-remote/5-select-prompts-resources.png?fit=max&auto=format&n=cpXzQjUOzyH0mCNH&q=85&s=68722669d9e18252756885c703e4f221" alt="Selecting specific resources and prompts from the menu" width="648" height="529" data-path="images/quickstart-remote/5-select-prompts-resources.png" />
</Frame>
</Step>
<Step title="Configure Tool Permissions">
Remote MCP servers often expose multiple tools with varying capabilities. You can control which tools Claude is allowed to use by configuring permissions in the connector settings. This ensures Claude only performs actions you've explicitly authorized.
<Frame>
<img src="https://mintcdn.com/mcp/cpXzQjUOzyH0mCNH/images/quickstart-remote/6-configure-tools.png?fit=max&auto=format&n=cpXzQjUOzyH0mCNH&q=85&s=5cfd8b2c5d06e7e3699eac24c68d090e" alt="Tool permission configuration interface" width="604" height="745" data-path="images/quickstart-remote/6-configure-tools.png" />
</Frame>
Navigate back to the Connectors settings and click on your connected server. Here you can enable or disable specific tools, set usage limits, and configure other security parameters according to your needs.
</Step>
</Steps>
## Best Practices for Using Remote MCP Servers
When working with remote MCP servers, consider these recommendations to ensure a secure and efficient experience:
**Security considerations**: Always verify the authenticity of remote MCP servers before connecting. Only connect to servers from trusted sources, and review the permissions requested during authentication. Be cautious about granting access to sensitive data or systems.
**Managing multiple connectors**: You can connect to multiple remote MCP servers simultaneously. Organize your connectors by purpose or project to maintain clarity. Regularly review and remove connectors you no longer use to keep your workspace organized and secure.
## Next Steps
Now that you've connected Claude to a remote MCP server, you can explore its capabilities in your conversations. Try using the connected tools to automate tasks, access external data, or integrate with your existing workflows.
<CardGroup cols={2}>
<Card title="Build your own remote server" icon="cloud" href="https://support.anthropic.com/en/articles/11503834-building-custom-connectors-via-remote-mcp-servers">
Create custom remote MCP servers to integrate with proprietary tools and
services
</Card>
<Card title="Explore available servers" icon="grid" href="https://github.com/modelcontextprotocol/servers">
Browse our collection of official and community-created MCP servers
</Card>
<Card title="Connect local servers" icon="computer" href="/docs/2025-06-18/develop/connect-local-servers">
Learn how to connect Claude Desktop to local MCP servers for direct system
access
</Card>
<Card title="Understand the architecture" icon="book" href="/docs/2025-06-18/learn/architecture">
Dive deeper into how MCP works and its architecture
</Card>
</CardGroup>
Remote MCP servers unlock powerful possibilities for extending Claude's capabilities. As you become familiar with these integrations, you'll discover new ways to streamline your workflows and accomplish complex tasks more efficiently.
docs/2025-06-18/getting-started/intro New page · 54 lines, new page
# What is the Model Context Protocol (MCP)? ## What can MCP enable? ## Why does MCP matter? ## Broad ecosystem support ## Start Building ## Learn more
A whole new page. There's nothing to diff it against, so here is what it says.
# What is the Model Context Protocol (MCP)?
MCP (Model Context Protocol) is an open-source standard for connecting AI applications to external systems.
Using MCP, AI applications like Claude or ChatGPT can connect to data sources (e.g. local files, databases), tools (e.g. search engines, calculators) and workflows (e.g. specialized prompts)—enabling them to access key information and perform tasks.
Think of MCP like a USB-C port for AI applications. Just as USB-C provides a standardized way to connect electronic devices, MCP provides a standardized way to connect AI applications to external systems.
<Frame>
<img src="https://mintcdn.com/mcp/bEUxYpZqie0DsluH/images/mcp-simple-diagram.png?fit=max&auto=format&n=bEUxYpZqie0DsluH&q=85&s=35268aa0ad50b8c385913810e7604550" width="3840" height="1500" data-path="images/mcp-simple-diagram.png" />
</Frame>
## What can MCP enable?
* Agents can access your Google Calendar and Notion, acting as a more personalized AI assistant.
* Claude Code can generate an entire web app using a Figma design.
* Enterprise chatbots can connect to multiple databases across an organization, empowering users to analyze data using chat.
* AI models can create 3D designs on Blender and print them out using a 3D printer.
## Why does MCP matter?
Depending on where you sit in the ecosystem, MCP can have a range of benefits.
* **Developers**: MCP reduces development time and complexity when building, or integrating with, an AI application or agent.
* **AI applications or agents**: MCP gives them access to an ecosystem of data sources, tools and apps, which enhances their capabilities and improves the end-user experience.
* **End-users**: MCP results in more capable AI applications or agents that can access user data and take actions on the user's behalf when necessary.
## Broad ecosystem support
MCP is an open protocol supported across a wide range of clients and servers. AI assistants like [Claude](https://claude.com/docs/connectors/building) and [ChatGPT](https://developers.openai.com/api/docs/mcp/), development tools like [Visual Studio Code](https://code.visualstudio.com/docs/copilot/chat/mcp-servers), [Cursor](https://cursor.com/docs/context/mcp), [MCPJam](https://docs.mcpjam.com/getting-started), and many others all support MCP — making it easy to build once and integrate everywhere.
## Start Building
<CardGroup cols={2}>
<Card title="Build servers" icon="server" href="/docs/2025-06-18/develop/build-server">
Create MCP servers to expose your data and tools
</Card>
<Card title="Build clients" icon="computer" href="/docs/2025-06-18/develop/build-client">
Develop applications that connect to MCP servers
</Card>
<Card title="Build MCP Apps" icon="puzzle-piece" href="/extensions/apps/overview">
Build interactive apps that run inside AI clients
</Card>
</CardGroup>
## Learn more
<CardGroup cols={2}>
<Card title="Understand concepts" icon="book" href="/docs/2025-06-18/learn/architecture">
Learn the core concepts and architecture of MCP
</Card>
</CardGroup>
docs/2025-06-18/learn/architecture New page · 460 lines, new page
# Architecture overview ## Scope ## Concepts of MCP ### Participants ### Layers #### Data layer #### Transport layer ### Data Layer Protocol #### Lifecycle management #### Primitives #### Notifications ## Example ### Data Layer
A whole new page. There's nothing to diff it against, so here is what it says.
# Architecture overview
This overview of the Model Context Protocol (MCP) discusses its [scope](#scope) and [core concepts](#concepts-of-mcp), and provides an [example](#example) demonstrating each core concept.
Because MCP SDKs abstract away many concerns, most developers will likely find the [data layer protocol](#data-layer-protocol) section to be the most useful. It discusses how MCP servers can provide context to an AI application.
For specific implementation details, please refer to the documentation for your [language-specific SDK](/docs/2025-06-18/sdk).
## Scope
The Model Context Protocol includes the following projects:
* [MCP Specification](https://modelcontextprotocol.io/specification/latest): A specification of MCP that outlines the implementation requirements for clients and servers.
* [MCP SDKs](/docs/2025-06-18/sdk): SDKs for different programming languages that implement MCP.
* **MCP Development Tools**: Tools for developing MCP servers and clients, including the [MCP Inspector](https://github.com/modelcontextprotocol/inspector)
* [MCP Reference Server Implementations](https://github.com/modelcontextprotocol/servers): Reference implementations of MCP servers.
<Note>
MCP focuses solely on the protocol for context exchange—it does not dictate
how AI applications use LLMs or manage the provided context.
</Note>
## Concepts of MCP
### Participants
MCP follows a client-server architecture where an MCP host — an AI application like [Claude Code](https://www.anthropic.com/claude-code) or [Claude Desktop](https://www.claude.ai/download) — establishes connections to one or more MCP servers. The MCP host accomplishes this by creating one MCP client for each MCP server. Each MCP client maintains a dedicated connection with its corresponding MCP server.
Local MCP servers that use the STDIO transport typically serve a single MCP client, whereas remote MCP servers that use the Streamable HTTP transport will typically serve many MCP clients.
The key participants in the MCP architecture are:
* **MCP Host**: The AI application that coordinates and manages one or multiple MCP clients
* **MCP Client**: A component that maintains a connection to an MCP server and obtains context from an MCP server for the MCP host to use
* **MCP Server**: A program that provides context to MCP clients
**For example**: Visual Studio Code acts as an MCP host. When Visual Studio Code establishes a connection to an MCP server, such as the [Sentry MCP server](https://docs.sentry.io/product/sentry-mcp/), the Visual Studio Code runtime instantiates an MCP client object that maintains the connection to the Sentry MCP server.
When Visual Studio Code subsequently connects to another MCP server, such as the [local filesystem server](https://github.com/modelcontextprotocol/servers/tree/main/src/filesystem), the Visual Studio Code runtime instantiates an additional MCP client object to maintain this connection.
```mermaid theme={null}
graph TB
subgraph "MCP Host (AI Application)"
Client1["MCP Client 1"]
Client2["MCP Client 2"]
Client3["MCP Client 3"]
Client4["MCP Client 4"]
end
ServerA["MCP Server A - Local<br/>(e.g. Filesystem)"]
ServerB["MCP Server B - Local<br/>(e.g. Database)"]
ServerC["MCP Server C - Remote<br/>(e.g. Sentry)"]
Client1 ---|"Dedicated<br/>connection"| ServerA
Client2 ---|"Dedicated<br/>connection"| ServerB
Client3 ---|"Dedicated<br/>connection"| ServerC
Client4 ---|"Dedicated<br/>connection"| ServerC
```
Note that **MCP server** refers to the program that serves context data, regardless of
where it runs. MCP servers can execute locally or remotely. For example, when
Claude Desktop launches the [filesystem
server](https://github.com/modelcontextprotocol/servers/tree/main/src/filesystem),
the server runs locally on the same machine because it uses the STDIO
transport. This is commonly referred to as a "local" MCP server. The official
[Sentry MCP server](https://docs.sentry.io/product/sentry-mcp/) runs on the
Sentry platform, and uses the Streamable HTTP transport. This is commonly
referred to as a "remote" MCP server.
### Layers
MCP consists of two layers:
* **Data layer**: Defines the JSON-RPC based protocol for client-server communication, including lifecycle management, and core primitives, such as tools, resources, prompts and notifications.
* **Transport layer**: Defines the communication mechanisms and channels that enable data exchange between clients and servers, including transport-specific connection establishment, message framing, and authorization.
Conceptually the data layer is the inner layer, while the transport layer is the outer layer.
#### Data layer
The data layer implements a [JSON-RPC 2.0](https://www.jsonrpc.org/) based exchange protocol that defines the message structure and semantics.
This layer includes:
* **Lifecycle management**: Handles connection initialization, capability negotiation, and connection termination between clients and servers
* **Server features**: Enables servers to provide core functionality including tools for AI actions, resources for context data, and prompts for interaction templates from and to the client
* **Client features**: Enables servers to ask the client to sample from the host LLM, elicit input from the user, and log messages to the client
* **Utility features**: Supports additional capabilities like notifications for real-time updates and progress tracking for long-running operations
#### Transport layer
The transport layer manages communication channels and authentication between clients and servers. It handles connection establishment, message framing, and secure communication between MCP participants.
MCP supports two transport mechanisms:
* **Stdio transport**: Uses standard input/output streams for direct process communication between local processes on the same machine, providing optimal performance with no network overhead.
* **Streamable HTTP transport**: Uses HTTP POST for client-to-server messages with optional Server-Sent Events for streaming capabilities. This transport enables remote server communication and supports standard HTTP authentication methods including bearer tokens, API keys, and custom headers. MCP recommends using OAuth to obtain authentication tokens.
The transport layer abstracts communication details from the protocol layer, enabling the same JSON-RPC 2.0 message format across all transport mechanisms.
### Data Layer Protocol
A core part of MCP is defining the schema and semantics between MCP clients and MCP servers. Developers will likely find the data layer — in particular, the set of [primitives](#primitives) — to be the most interesting part of MCP. It is the part of MCP that defines the ways developers can share context from MCP servers to MCP clients.
MCP uses [JSON-RPC 2.0](https://www.jsonrpc.org/) as its underlying RPC protocol. Client and servers send requests to each other and respond accordingly. Notifications can be used when no response is required.
#### Lifecycle management
MCP is a <Tooltip tip="A subset of MCP can be made stateless using the Streamable HTTP transport">stateful protocol</Tooltip> that requires lifecycle management. The purpose of lifecycle management is to negotiate the <Tooltip tip="Features and operations that a client or server supports, such as tools, resources, or prompts">capabilities</Tooltip> that both client and server support. Detailed information can be found in the [specification](/specification/2025-06-18/basic/lifecycle), and the [example](#example) showcases the initialization sequence.
#### Primitives
MCP primitives are the most important concept within MCP. They define what clients and servers can offer each other. These primitives specify the types of contextual information that can be shared with AI applications and the range of actions that can be performed.
MCP defines three core primitives that *servers* can expose:
* **Tools**: Executable functions that AI applications can invoke to perform actions (e.g., file operations, API calls, database queries)
* **Resources**: Data sources that provide contextual information to AI applications (e.g., file contents, database records, API responses)
* **Prompts**: Reusable templates that help structure interactions with language models (e.g., system prompts, few-shot examples)
Each primitive type has associated methods for discovery (`*/list`), retrieval (`*/get`), and in some cases, execution (`tools/call`).
MCP clients will use the `*/list` methods to discover available primitives. For example, a client can first list all available tools (`tools/list`) and then execute them. This design allows listings to be dynamic.
As a concrete example, consider an MCP server that provides context about a database. It can expose tools for querying the database, a resource that contains the schema of the database, and a prompt that includes few-shot examples for interacting with the tools.
For more details about server primitives see [server concepts](./server-concepts).
MCP also defines primitives that *clients* can expose. These primitives allow MCP server authors to build richer interactions.
* **Sampling**: Allows servers to request language model completions from the client's AI application. This is useful when server authors want access to a language model, but want to stay model-independent and not include a language model SDK in their MCP server. They can use the `sampling/createMessage` method to request a language model completion from the client's AI application.
* **Elicitation**: Allows servers to request additional information from users. This is useful when server authors want to get more information from the user, or ask for confirmation of an action. They can use the `elicitation/create` method to request additional information from the user.
* **Logging**: Enables servers to send log messages to clients for debugging and monitoring purposes.
For more details about client primitives see [client concepts](./client-concepts).
Besides server and client primitives, the protocol offers cross-cutting utility primitives that augment how requests are executed:
* **Tasks (Experimental)**: Durable execution wrappers that enable deferred result retrieval and status tracking for MCP requests (e.g., expensive computations, workflow automation, batch processing, multi-step operations)
#### Notifications
The protocol supports real-time notifications to enable dynamic updates between servers and clients. For example, when a server's available tools change—such as when new functionality becomes available or existing tools are modified—the server can send tool update notifications to inform connected clients about these changes. Notifications are sent as JSON-RPC 2.0 notification messages (without expecting a response) and enable MCP servers to provide real-time updates to connected clients.
## Example
### Data Layer
This section provides a step-by-step walkthrough of an MCP client-server interaction, focusing on the data layer protocol. We'll demonstrate the lifecycle sequence, tool operations, and notifications using JSON-RPC 2.0 messages.
<Steps>
<Step title="Initialization (Lifecycle Management)">
MCP begins with lifecycle management through a capability negotiation handshake. As described in the [lifecycle management](#lifecycle-management) section, the client sends an `initialize` request to establish the connection and negotiate supported features.
<CodeGroup>
```json Initialize Request theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2025-06-18",
"capabilities": {
"elicitation": {}
},
"clientInfo": {
"name": "example-client",
"version": "1.0.0"
}
}
}
```
```json Initialize Response theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"protocolVersion": "2025-06-18",
"capabilities": {
"tools": {
"listChanged": true
},
"resources": {}
},
"serverInfo": {
"name": "example-server",
"version": "1.0.0"
}
}
}
```
</CodeGroup>
#### Understanding the Initialization Exchange
The initialization process is a key part of MCP's lifecycle management and serves several critical purposes:
1. **Protocol Version Negotiation**: The `protocolVersion` field (e.g., "2025-06-18") ensures both client and server are using compatible protocol versions. This prevents communication errors that could occur when different versions attempt to interact. If a mutually compatible version is not negotiated, the connection should be terminated.
2. **Capability Discovery**: The `capabilities` object allows each party to declare what features they support, including which [primitives](#primitives) they can handle (tools, resources, prompts) and whether they support features like [notifications](#notifications). This enables efficient communication by avoiding unsupported operations.
3. **Identity Exchange**: The `clientInfo` and `serverInfo` objects provide identification and versioning information for debugging and compatibility purposes.
In this example, the capability negotiation demonstrates how MCP primitives are declared:
**Client Capabilities**:
* `"elicitation": {}` - The client declares it can work with user interaction requests (can receive `elicitation/create` method calls)
**Server Capabilities**:
* `"tools": {"listChanged": true}` - The server supports the tools primitive AND can send `tools/list_changed` notifications when its tool list changes
* `"resources": {}` - The server also supports the resources primitive (can handle `resources/list` and `resources/read` methods)
After successful initialization, the client sends a notification to indicate it's ready:
```json Notification theme={null}
{
"jsonrpc": "2.0",
"method": "notifications/initialized"
}
```
#### How This Works in AI Applications
During initialization, the AI application's MCP client manager establishes connections to configured servers and stores their capabilities for later use. The application uses this information to determine which servers can provide specific types of functionality (tools, resources, prompts) and whether they support real-time updates.
```python Pseudo-code for AI application initialization theme={null}
# Pseudo Code
async with stdio_client(server_config) as (read, write):
async with ClientSession(read, write) as session:
init_response = await session.initialize()
if init_response.capabilities.tools:
app.register_mcp_server(session, supports_tools=True)
app.set_server_ready(session)
```
</Step>
<Step title="Tool Discovery (Primitives)">
Now that the connection is established, the client can discover available tools by sending a `tools/list` request. This request is fundamental to MCP's tool discovery mechanism — it allows clients to understand what tools are available on the server before attempting to use them.
<CodeGroup>
```json Tools List Request theme={null}
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/list"
}
```
```json Tools List Response theme={null}
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"tools": [
{
"name": "calculator_arithmetic",
"title": "Calculator",
"description": "Perform mathematical calculations including basic arithmetic, trigonometric functions, and algebraic operations",
"inputSchema": {
"type": "object",
"properties": {
"expression": {
"type": "string",
"description": "Mathematical expression to evaluate (e.g., '2 + 3 * 4', 'sin(30)', 'sqrt(16)')"
}
},
"required": ["expression"]
}
},
{
"name": "weather_current",
"title": "Weather Information",
"description": "Get current weather information for any location worldwide",
"inputSchema": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "City name, address, or coordinates (latitude,longitude)"
},
"units": {
"type": "string",
"enum": ["metric", "imperial", "kelvin"],
"description": "Temperature units to use in response",
"default": "metric"
}
},
"required": ["location"]
}
}
]
}
}
```
</CodeGroup>
#### Understanding the Tool Discovery Request
The `tools/list` request is simple, containing no parameters.
Cut at 300 lines. The page has the rest.
docs/2025-06-18/learn/client-concepts New page · 232 lines, new page
# Understanding MCP clients ## Core Client Features ### Elicitation #### Overview #### Example: Holiday Booking Approval #### User Interaction Model ### Roots #### Overview #### Example: Travel Planning Workspace #### Design Philosophy #### User Interaction Model ### Sampling #### Overview #### Example: Flight Analysis Tool #### User Interaction Model
A whole new page. There's nothing to diff it against, so here is what it says.
# Understanding MCP clients
MCP clients are instantiated by host applications to communicate with particular MCP servers. The host application, like Claude.ai or an IDE, manages the overall user experience and coordinates multiple clients. Each client handles one direct communication with one server.
Understanding the distinction is important: the *host* is the application users interact with, while *clients* are the protocol-level components that enable server connections.
## Core Client Features
In addition to making use of context provided by servers, clients may provide several features to servers. These client features allow server authors to build richer interactions.
| Feature | Explanation | Example |
| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| **Elicitation** | Elicitation enables servers to request specific information from users during interactions, providing a structured way for servers to gather information on demand. | A server booking travel may ask for the user's preferences on airplane seats, room type or their contact number to finalise a booking. |
| **Roots** | Roots allow clients to specify which directories servers should focus on, communicating intended scope through a coordination mechanism. | A server for booking travel may be given access to a specific directory, from which it can read a user's calendar. |
| **Sampling** | Sampling allows servers to request LLM completions through the client, enabling an agentic workflow. This approach puts the client in complete control of user permissions and security measures. | A server for booking travel may send a list of flights to an LLM and request that the LLM pick the best flight for the user. |
### Elicitation
Elicitation enables servers to request specific information from users during interactions, creating more dynamic and responsive workflows.
#### Overview
Elicitation provides a structured way for servers to gather necessary information on demand. Instead of requiring all information up front or failing when data is missing, servers can pause their operations to request specific inputs from users. This creates more flexible interactions where servers adapt to user needs rather than following rigid patterns.
**Elicitation flow:**
```mermaid theme={null}
sequenceDiagram
participant User
participant Client
participant Server
Note over Server,Client: Server initiates elicitation
Server->>Client: elicitation/create
Note over Client,User: Human interaction
Client->>User: Present elicitation UI
User-->>Client: Provide requested information
Note over Server,Client: Complete request
Client-->>Server: Return user response
Note over Server: Continue processing with new information
```
The flow enables dynamic information gathering. Servers can request specific data when needed, users provide information through appropriate UI, and servers continue processing with the newly acquired context.
**Elicitation components example:**
```typescript theme={null}
{
method: "elicitation/create",
params: {
message: "Please confirm your Barcelona vacation booking details:",
requestedSchema: {
type: "object",
properties: {
confirmBooking: {
type: "boolean",
description: "Confirm the booking (Flights + Hotel = $3,000)"
},
seatPreference: {
type: "string",
enum: ["window", "aisle", "no preference"],
description: "Preferred seat type for flights"
},
roomType: {
type: "string",
enum: ["sea view", "city view", "garden view"],
description: "Preferred room type at hotel"
},
travelInsurance: {
type: "boolean",
default: false,
description: "Add travel insurance ($150)"
}
},
required: ["confirmBooking"]
}
}
}
```
#### Example: Holiday Booking Approval
A travel booking server demonstrates elicitation's power through the final booking confirmation process. When a user has selected their ideal vacation package to Barcelona, the server needs to gather final approval and any missing details before proceeding.
The server elicits booking confirmation with a structured request that includes the trip summary (Barcelona flights June 15-22, beachfront hotel, total \$3,000) and fields for any additional preferences—such as seat selection, room type, or travel insurance options.
As the booking progresses, the server elicits contact information needed to complete the reservation. It might ask for traveler details for flight bookings, special requests for the hotel, or emergency contact information.
#### User Interaction Model
Elicitation interactions are designed to be clear, contextual, and respectful of user autonomy:
**Request presentation**: Clients display elicitation requests with clear context about which server is asking, why the information is needed, and how it will be used. The request message explains the purpose while the schema provides structure and validation.
**Response options**: Users can provide the requested information through appropriate UI controls (text fields, dropdowns, checkboxes), decline to provide information with optional explanation, or cancel the entire operation. Clients validate responses against the provided schema before returning them to servers.
**Privacy considerations**: Elicitation never requests passwords or API keys. Clients warn about suspicious requests and let users review data before sending.
### Roots
Roots define filesystem boundaries for server operations, allowing clients to specify which directories servers should focus on.
#### Overview
Roots are a mechanism for clients to communicate filesystem access boundaries to servers. They consist of file URIs that indicate directories where servers can operate, helping servers understand the scope of available files and folders. While roots communicate intended boundaries, they do not enforce security restrictions. Actual security must be enforced at the operating system level, via file permissions and/or sandboxing.
**Root structure:**
```json theme={null}
{
"uri": "file:///Users/agent/travel-planning",
"name": "Travel Planning Workspace"
}
```
Roots are exclusively filesystem paths and always use the `file://` URI scheme. They help servers understand project boundaries, workspace organization, and accessible directories. The roots list can be updated dynamically as users work with different projects or folders, with servers receiving notifications through `roots/list_changed` when boundaries change.
#### Example: Travel Planning Workspace
A travel agent working with multiple client trips benefits from roots to organize filesystem access. Consider a workspace with different directories for various aspects of travel planning.
The client provides filesystem roots to the travel planning server:
* `file:///Users/agent/travel-planning` - Main workspace containing all travel files
* `file:///Users/agent/travel-templates` - Reusable itinerary templates and resources
* `file:///Users/agent/client-documents` - Client passports and travel documents
When the agent creates a Barcelona itinerary, well-behaved servers respect these boundaries—accessing templates, saving the new itinerary, and referencing client documents within the specified roots. Servers typically access files within roots by using relative paths from the root directories or by utilizing file search tools that respect the root boundaries.
If the agent opens an archive folder like `file:///Users/agent/archive/2023-trips`, the client updates the roots list via `roots/list_changed`.
For a complete implementation of a server that respects roots, see the [filesystem server](https://github.com/modelcontextprotocol/servers/tree/main/src/filesystem) in the official servers repository.
#### Design Philosophy
Roots serve as a coordination mechanism between clients and servers, not a security boundary. The specification requires that servers "SHOULD respect root boundaries," and not that they "MUST enforce" them, because servers run code the client cannot control.
Roots work best when servers are trusted or vetted, users understand their advisory nature, and the goal is preventing accidents rather than stopping malicious behavior. They excel at context scoping (telling servers where to focus), accident prevention (helping well-behaved servers stay in bounds), and workflow organization (such as managing project boundaries automatically).
#### User Interaction Model
Roots are typically managed automatically by host applications based on user actions, though some applications may expose manual root management:
**Automatic root detection**: When users open folders, clients automatically expose them as roots. Opening a travel workspace allows the client to expose that directory as a root, helping servers understand which itineraries and documents are in scope for the current work.
**Manual root configuration**: Advanced users can specify roots through configuration. For example, adding `/travel-templates` for reusable resources while excluding directories with financial records.
### Sampling
Sampling allows servers to request language model completions through the client, enabling agentic behaviors while maintaining security and user control.
#### Overview
Sampling enables servers to perform AI-dependent tasks without directly integrating with or paying for AI models. Instead, servers can request that the client—which already has AI model access—handle these tasks on their behalf. This approach puts the client in complete control of user permissions and security measures. Because sampling requests occur within the context of other operations—like a tool analyzing data—and are processed as separate model calls, they maintain clear boundaries between different contexts, allowing for more efficient use of the context window.
**Sampling flow:**
```mermaid theme={null}
sequenceDiagram
participant LLM
participant User
participant Client
participant Server
Note over Server,Client: Server initiates sampling
Server->>Client: sampling/createMessage
Note over Client,User: Human-in-the-loop review
Client->>User: Present request for approval
User-->>Client: Review and approve/modify
Note over Client,LLM: Model interaction
Client->>LLM: Forward approved request
LLM-->>Client: Return generation
Note over Client,User: Response review
Client->>User: Present response for approval
User-->>Client: Review and approve/modify
Note over Server,Client: Complete request
Client-->>Server: Return approved response
```
The flow ensures security through multiple human-in-the-loop checkpoints. Users review and can modify both the initial request and the generated response before it returns to the server.
**Request parameters example:**
```typescript theme={null}
{
messages: [
{
role: "user",
content: "Analyze these flight options and recommend the best choice:\n" +
"[47 flights with prices, times, airlines, and layovers]\n" +
"User preferences: morning departure, max 1 layover"
}
],
modelPreferences: {
hints: [{
name: "claude-sonnet-4-20250514" // Suggested model
}],
costPriority: 0.3, // Less concerned about API cost
speedPriority: 0.2, // Can wait for thorough analysis
intelligencePriority: 0.9 // Need complex trade-off evaluation
},
systemPrompt: "You are a travel expert helping users find the best flights based on their preferences",
maxTokens: 1500
}
```
#### Example: Flight Analysis Tool
Consider a travel booking server with a tool called `findBestFlight` that uses sampling to analyze available flights and recommend the optimal choice. When a user asks "Book me the best flight to Barcelona next month," the tool needs AI assistance to evaluate complex trade-offs.
The tool queries airline APIs and gathers 47 flight options. It then requests AI assistance to analyze these options: "Analyze these flight options and recommend the best choice: \[47 flights with prices, times, airlines, and layovers] User preferences: morning departure, max 1 layover."
The client initiates the sampling request, allowing the AI to evaluate trade-offs—like cheaper red-eye flights versus convenient morning departures. The tool uses this analysis to present the top three recommendations.
#### User Interaction Model
While not a requirement, sampling is designed to allow human-in-the-loop control. Users can maintain oversight through several mechanisms:
**Approval controls**: Sampling requests may require explicit user consent. Clients can show what the server wants to analyze and why. Users can approve, deny, or modify requests.
**Transparency features**: Clients can display the exact prompt, model selection, and token limits, allowing users to review AI responses before they return to the server.
**Configuration options**: Users can set model preferences, configure auto-approval for trusted operations, or require approval for everything. Clients may provide options to redact sensitive information.
**Security considerations**: Both clients and servers must handle sensitive data appropriately during sampling. Clients should implement rate limiting and validate all message content. The human-in-the-loop design ensures that server-initiated AI interactions cannot compromise security or access sensitive data without explicit user consent.
docs/2025-06-18/learn/server-concepts New page · 281 lines, new page
# Understanding MCP servers ## Core Server Features ### Tools #### How Tools Work #### Example: Travel Booking #### User Interaction Model ### Resources #### How Resources Work #### Example: Getting Travel Planning Context #### Parameter Completion #### User Interaction Model ### Prompts #### How Prompts Work #### Example: Streamlined Workflows #### User Interaction Model ## Bringing Servers Together ### Example: Multi-Server Travel Planning #### The Complete Flow
A whole new page. There's nothing to diff it against, so here is what it says.
# Understanding MCP servers
MCP servers are programs that expose specific capabilities to AI applications through standardized protocol interfaces.
Common examples include file system servers for document access, database servers for data queries, GitHub servers for code management, Slack servers for team communication, and calendar servers for scheduling.
## Core Server Features
Servers provide functionality through three building blocks:
| Feature | Explanation | Examples | Who controls it |
| ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------ | --------------- |
| **Tools** | Functions that your LLM can actively call, and decides when to use them based on user requests. Tools can write to databases, call external APIs, modify files, or trigger other logic. | Search flights<br />Send messages<br />Create calendar events | Model |
| **Resources** | Passive data sources that provide read-only access to information for context, such as file contents, database schemas, or API documentation. | Retrieve documents<br />Access knowledge bases<br />Read calendars | Application |
| **Prompts** | Pre-built instruction templates that tell the model to work with specific tools and resources. | Plan a vacation<br />Summarize my meetings<br />Draft an email | User |
We will use a hypothetical scenario to demonstrate the role of each of these features, and show how they can work together.
### Tools
Tools enable AI models to perform actions. Each tool defines a specific operation with typed inputs and outputs. The model requests tool execution based on context.
#### How Tools Work
Tools are schema-defined interfaces that LLMs can invoke. MCP uses JSON Schema for validation. Each tool performs a single operation with clearly defined inputs and outputs. Tools may require user consent prior to execution, helping to ensure users maintain control over actions taken by a model.
**Protocol operations:**
| Method | Purpose | Returns |
| ------------ | ------------------------ | -------------------------------------- |
| `tools/list` | Discover available tools | Array of tool definitions with schemas |
| `tools/call` | Execute a specific tool | Tool execution result |
**Example tool definition:**
```typescript theme={null}
{
name: "searchFlights",
description: "Search for available flights",
inputSchema: {
type: "object",
properties: {
origin: { type: "string", description: "Departure city" },
destination: { type: "string", description: "Arrival city" },
date: { type: "string", format: "date", description: "Travel date" }
},
required: ["origin", "destination", "date"]
}
}
```
#### Example: Travel Booking
Tools enable AI applications to perform actions on behalf of users. In a travel planning scenario, the AI application might use several tools to help book a vacation:
**Flight Search**
```
searchFlights(origin: "NYC", destination: "Barcelona", date: "2024-06-15")
```
Queries multiple airlines and returns structured flight options.
**Calendar Blocking**
```
createCalendarEvent(title: "Barcelona Trip", startDate: "2024-06-15", endDate: "2024-06-22")
```
Marks the travel dates in the user's calendar.
**Email notification**
```
sendEmail(to: "[email protected]", subject: "Out of Office", body: "...")
```
Sends an automated out-of-office message to colleagues.
#### User Interaction Model
Tools are model-controlled, meaning AI models can discover and invoke them automatically. However, MCP emphasizes human oversight through several mechanisms.
For trust and safety, applications can implement user control through various mechanisms, such as:
* Displaying available tools in the UI, enabling users to define whether a tool should be made available in specific interactions
* Approval dialogs for individual tool executions
* Permission settings for pre-approving certain safe operations
* Activity logs that show all tool executions with their results
### Resources
Resources provide structured access to information that the AI application can retrieve and provide to models as context.
#### How Resources Work
Resources expose data from files, APIs, databases, or any other source that an AI needs to understand context. Applications can access this information directly and decide how to use it - whether that's selecting relevant portions, searching with embeddings, or passing it all to the model.
Each resource has a unique URI (e.g., `file:///path/to/document.md`) and declares its MIME type for appropriate content handling.
Resources support two discovery patterns:
* **Direct Resources** - fixed URIs that point to specific data. Example: `calendar://events/2024` - returns calendar availability for 2024
* **Resource Templates** - dynamic URIs with parameters for flexible queries. Example:
* `travel://activities/{city}/{category}` - returns activities by city and category
* `travel://activities/barcelona/museums` - returns all museums in Barcelona
Resource Templates include metadata such as title, description, and expected MIME type, making them discoverable and self-documenting.
**Protocol operations:**
| Method | Purpose | Returns |
| -------------------------- | ------------------------------- | -------------------------------------- |
| `resources/list` | List available direct resources | Array of resource descriptors |
| `resources/templates/list` | Discover resource templates | Array of resource template definitions |
| `resources/read` | Retrieve resource contents | Resource data with metadata |
| `resources/subscribe` | Monitor resource changes | Subscription confirmation |
#### Example: Getting Travel Planning Context
Continuing with the travel planning example, resources provide the AI application with access to relevant information:
* **Calendar data** (`calendar://events/2024`) - Checks user availability
* **Travel documents** (`file:///Documents/Travel/passport.pdf`) - Accesses important documents
* **Previous itineraries** (`trips://history/barcelona-2023`) - References past trips and preferences
The AI application retrieves these resources and decides how to process them, whether selecting a subset of data using embeddings or keyword search, or passing raw data directly to the model.
In this case, it provides calendar data, weather information, and travel preferences to the model, enabling it to check availability, look up weather patterns, and reference past travel preferences.
**Resource Template Examples:**
```json theme={null}
{
"uriTemplate": "weather://forecast/{city}/{date}",
"name": "weather-forecast",
"title": "Weather Forecast",
"description": "Get weather forecast for any city and date",
"mimeType": "application/json"
}
{
"uriTemplate": "travel://flights/{origin}/{destination}",
"name": "flight-search",
"title": "Flight Search",
"description": "Search available flights between cities",
"mimeType": "application/json"
}
```
These templates enable flexible queries. For weather data, users can access forecasts for any city/date combination. For flights, they can search routes between any two airports. When a user has input "NYC" as the `origin` airport and begins to input "Bar" as the `destination` airport, the system can suggest "Barcelona (BCN)" or "Barbados (BGI)".
#### Parameter Completion
Dynamic resources support parameter completion. For example:
* Typing "Par" as input for `weather://forecast/{city}` might suggest "Paris" or "Park City"
* Typing "JFK" for `flights://search/{airport}` might suggest "JFK - John F. Kennedy International"
The system helps discover valid values without requiring exact format knowledge.
#### User Interaction Model
Resources are application-driven, giving them flexibility in how they retrieve, process, and present available context. Common interaction patterns include:
* Tree or list views for browsing resources in familiar folder-like structures
* Search and filter interfaces for finding specific resources
* Automatic context inclusion or smart suggestions based on heuristics or AI selection
* Manual or bulk selection interfaces for including single or multiple resources
Applications are free to implement resource discovery through any interface pattern that suits their needs. The protocol doesn't mandate specific UI patterns, allowing for resource pickers with preview capabilities, smart suggestions based on current conversation context, bulk selection for including multiple resources, or integration with existing file browsers and data explorers.
### Prompts
Prompts provide reusable templates. They allow MCP server authors to provide parameterized prompts for a domain, or showcase how to best use the MCP server.
#### How Prompts Work
Prompts are structured templates that define expected inputs and interaction patterns. They are user-controlled, requiring explicit invocation rather than automatic triggering. Prompts can be context-aware, referencing available resources and tools to create comprehensive workflows. Similar to resources, prompts support parameter completion to help users discover valid argument values.
**Protocol operations:**
| Method | Purpose | Returns |
| -------------- | -------------------------- | ------------------------------------- |
| `prompts/list` | Discover available prompts | Array of prompt descriptors |
| `prompts/get` | Retrieve prompt details | Full prompt definition with arguments |
#### Example: Streamlined Workflows
Prompts provide structured templates for common tasks. In the travel planning context:
**"Plan a vacation" prompt:**
```json theme={null}
{
"name": "plan-vacation",
"title": "Plan a vacation",
"description": "Guide through vacation planning process",
"arguments": [
{ "name": "destination", "type": "string", "required": true },
{ "name": "duration", "type": "number", "description": "days" },
{ "name": "budget", "type": "number", "required": false },
{ "name": "interests", "type": "array", "items": { "type": "string" } }
]
}
```
Rather than unstructured natural language input, the prompt system enables:
1. Selection of the "Plan a vacation" template
2. Structured input: Barcelona, 7 days, \$3000, \["beaches", "architecture", "food"]
3. Consistent workflow execution based on the template
#### User Interaction Model
Prompts are user-controlled, requiring explicit invocation. The protocol gives implementers freedom to design interfaces that feel natural within their application. Key principles include:
* Easy discovery of available prompts
* Clear descriptions of what each prompt does
* Natural argument input with validation
* Transparent display of the prompt's underlying template
Applications typically expose prompts through various UI patterns such as:
* Slash commands (typing "/" to see available prompts like /plan-vacation)
* Command palettes for searchable access
* Dedicated UI buttons for frequently used prompts
* Context menus that suggest relevant prompts
## Bringing Servers Together
The real power of MCP emerges when multiple servers work together, combining their specialized capabilities through a unified interface.
### Example: Multi-Server Travel Planning
Consider a personalized AI travel planner application, with three connected servers:
* **Travel Server** - Handles flights, hotels, and itineraries
* **Weather Server** - Provides climate data and forecasts
* **Calendar/Email Server** - Manages schedules and communications
#### The Complete Flow
1. **User invokes a prompt with parameters:**
```json theme={null}
{
"prompt": "plan-vacation",
"arguments": {
"destination": "Barcelona",
"departure_date": "2024-06-15",
"return_date": "2024-06-22",
"budget": 3000,
"travelers": 2
}
}
```
2. **User selects resources to include:**
* `calendar://my-calendar/June-2024` (from Calendar Server)
* `travel://preferences/europe` (from Travel Server)
* `travel://past-trips/Spain-2023` (from Travel Server)
3. **AI processes the request using tools:**
The AI first reads all selected resources to gather context - identifying available dates from the calendar, learning preferred airlines and hotel types from travel preferences, and discovering previously enjoyed locations from past trips.
Using this context, the AI then executes the prompt provided by the AI application. In our example, the AI application exposes the weather tools from the connected MCP weather server to the model. Because weather can affect travel plans, the AI chooses to call `checkWeather()` when interpreting the prompt.
As a result the AI executes a series of tools:
* `searchFlights()` - Queries airlines for NYC to Barcelona flights
* `checkWeather()` - Retrieves climate forecasts for travel dates
The AI then uses this information to create the booking and following steps, requesting approval from the user where necessary:
* `bookHotel()` - Finds hotels within the specified budget
* `createCalendarEvent()` - Adds the trip to the user's calendar
* `sendEmail()` - Sends confirmation with trip details
**The result:** Through multiple MCP servers, the user researched and booked a Barcelona trip tailored to their schedule. The "Plan a Vacation" prompt guided the AI to combine Resources (calendar availability and travel history) with Tools (searching flights, booking hotels, updating calendars) across different servers—gathering context and executing the booking. A task that could have taken hours was completed in minutes using MCP.
docs/2025-06-18/learn/versioning New page · 45 lines, new page
# Versioning ## Revisions ## Feature States ## Negotiation
A whole new page. There's nothing to diff it against, so here is what it says.
# Versioning The Model Context Protocol uses string-based version identifiers following the format `YYYY-MM-DD`, to indicate the last date backwards incompatible changes were made. <Info> The protocol version will *not* be incremented when the protocol is updated, as long as the changes maintain backwards compatibility. This allows for incremental improvements while preserving interoperability. </Info> ## Revisions Revisions may be marked as: * **Draft**: in-progress specifications, not yet ready for consumption. * **Current**: the current protocol version, which is ready for use and may continue to receive backwards compatible changes. * **Final**: past, complete specifications that will not be changed. The **current** protocol version is [**2025-11-25**](/specification/2025-11-25/). ## Feature States Individual features of the specification may additionally be marked as **Deprecated** under the [feature lifecycle and deprecation policy](/community/feature-lifecycle): the feature remains part of the specification, but is scheduled for removal. Deprecated features document a migration path (or state that none is required) and remain in the specification for at least twelve months, or at least ninety days under the policy's [expedited-removal exception](/community/feature-lifecycle#expedited-removal), before they become eligible for removal, after which they may be **Removed** in a future revision. ## Negotiation Version negotiation happens during [initialization](/specification/2025-06-18/basic/lifecycle#initialization). Clients and servers **MAY** support multiple protocol versions simultaneously, but they **MUST** agree on a single version to use for the session. The protocol provides appropriate error handling if version negotiation fails, allowing clients to gracefully terminate connections when they cannot find a version compatible with the server.
docs/2025-06-18/sdk New page · 47 lines, new page
# SDKs ## Available SDKs ## Getting Started ## Next Steps
A whole new page. There's nothing to diff it against, so here is what it says.
# SDKs
> Official SDKs for building with Model Context Protocol
Build MCP servers and clients using our official SDKs. SDKs are classified into tiers based on feature completeness, protocol support, and maintenance commitment. Learn more about [SDK tiers](/community/sdk-tiers).
## Available SDKs
| SDK | Repository | Tier |
| :----------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------- | ------------------------------------------------: |
| <Icon icon="square-js" size={24} /> [TypeScript](https://ts.sdk.modelcontextprotocol.io) | [modelcontextprotocol/typescript-sdk](https://github.com/modelcontextprotocol/typescript-sdk) | <Badge color="blue" shape="pill">Tier 1</Badge> |
| <Icon icon="python" size={24} /> [Python](https://py.sdk.modelcontextprotocol.io) | [modelcontextprotocol/python-sdk](https://github.com/modelcontextprotocol/python-sdk) | <Badge color="blue" shape="pill">Tier 1</Badge> |
| <Icon icon="square-c" size={24} /> [C#](https://csharp.sdk.modelcontextprotocol.io) | [modelcontextprotocol/csharp-sdk](https://github.com/modelcontextprotocol/csharp-sdk) | <Badge color="blue" shape="pill">Tier 1</Badge> |
| <Icon icon="golang" size={24} /> [Go](https://go.sdk.modelcontextprotocol.io) | [modelcontextprotocol/go-sdk](https://github.com/modelcontextprotocol/go-sdk) | <Badge color="blue" shape="pill">Tier 1</Badge> |
| <Icon icon="java" size={24} /> [Java](https://java.sdk.modelcontextprotocol.io) | [modelcontextprotocol/java-sdk](https://github.com/modelcontextprotocol/java-sdk) | <Badge color="purple" shape="pill">Tier 2</Badge> |
| <Icon icon="rust" size={24} /> [Rust](https://rust.sdk.modelcontextprotocol.io) | [modelcontextprotocol/rust-sdk](https://github.com/modelcontextprotocol/rust-sdk) | <Badge color="purple" shape="pill">Tier 2</Badge> |
| <Icon icon="swift" size={24} /> Swift | [modelcontextprotocol/swift-sdk](https://github.com/modelcontextprotocol/swift-sdk) | <Badge color="orange" shape="pill">Tier 3</Badge> |
| <Icon icon="gem" size={24} /> [Ruby](https://ruby.sdk.modelcontextprotocol.io) | [modelcontextprotocol/ruby-sdk](https://github.com/modelcontextprotocol/ruby-sdk) | <Badge color="orange" shape="pill">Tier 3</Badge> |
| <Icon icon="php" size={24} /> [PHP](https://php.sdk.modelcontextprotocol.io) | [modelcontextprotocol/php-sdk](https://github.com/modelcontextprotocol/php-sdk) | <Badge color="orange" shape="pill">Tier 3</Badge> |
| <Icon icon="square-k" size={24} /> [Kotlin](https://kotlin.sdk.modelcontextprotocol.io) | [modelcontextprotocol/kotlin-sdk](https://github.com/modelcontextprotocol/kotlin-sdk) | <Badge color="orange" shape="pill">Tier 3</Badge> |
See [SDK Tiering System](/community/sdk-tiers) for details on what each tier means.
## Getting Started
Each SDK provides the same functionality but follows the idioms and best practices of its language. All SDKs support:
* Creating MCP servers that expose tools, resources, and prompts
* Building MCP clients that can connect to any MCP server
* Local and remote transport protocols
* Protocol compliance with type safety
Visit the SDK page for your chosen language to find installation instructions, documentation, and examples.
## Next Steps
Ready to start building with MCP? Choose your path:
<CardGroup cols={2}>
<Card title="Build a Server" icon="server" href="/docs/2025-06-18/develop/build-server">
Learn how to create your first MCP server
</Card>
<Card title="Build a Client" icon="computer" href="/docs/2025-06-18/develop/build-client">
Create applications that connect to MCP servers
</Card>
</CardGroup>
docs/2025-06-18/tools/debugging New page · 348 lines, new page
# Debugging ## Debugging tools overview ## Implementing logging ### Server-side logging ## Common issues ### Working directory ### Environment variables ### Server initialization ### Connection problems ## Debugging in Claude Desktop ### Checking server status ### Viewing logs ### Using Chrome DevTools ## Debugging workflow ### Development cycle ### Testing changes ## Best practices ### Logging strategy ### Security considerations ## Getting help ## Next steps
A whole new page. There's nothing to diff it against, so here is what it says.
# Debugging
> A comprehensive guide to debugging Model Context Protocol (MCP) integrations
Effective debugging is essential when developing MCP servers or integrating
them with applications. This guide covers the debugging tools and approaches
available in the MCP ecosystem.
## Debugging tools overview
MCP provides several tools for debugging at different levels:
1. **[MCP Inspector](/docs/2025-06-18/tools/inspector)**: interactive, transport-agnostic
testing UI. Connect to stdio or Streamable HTTP servers, invoke
[tools](/specification/2025-06-18/server/tools),
[prompts](/specification/2025-06-18/server/prompts), and
[resources](/specification/2025-06-18/server/resources), and watch the
notification stream. This should be your first stop.
2. **Server logging**: structured logs to stderr (stdio transport) or via
[`notifications/message`](/specification/2025-06-18/server/utilities/logging#log-message-notifications)
(all transports).
3. **Client developer tools**: most MCP clients expose logs and connection
state. See [Debugging in Claude Desktop](#debugging-in-claude-desktop)
below for one example, or consult your client's documentation.
## Implementing logging
### Server-side logging
When building a server that uses the local
[stdio transport](/specification/2025-06-18/basic/transports#stdio), all messages
logged to stderr (standard error) will be captured by the host application
automatically.
<Warning>
Local MCP servers should not log messages to stdout (standard out), as this
will interfere with protocol operation.
</Warning>
For servers using the
[Streamable HTTP transport](/specification/2025-06-18/basic/transports#streamable-http),
stderr is not captured by the client. Use the log message notifications below,
your own server-side log aggregation, or standard HTTP tooling (curl, browser
DevTools Network panel) to inspect requests,
[`Mcp-Session-Id` headers](/specification/2025-06-18/basic/transports#session-management),
and SSE streams.
For all [transports](/specification/2025-06-18/basic/transports), you can also
provide logging to the client by sending a log message notification:
<CodeGroup>
```python Python theme={null}
@server.tool()
async def my_tool(ctx: Context) -> str:
await ctx.session.send_log_message(
level="info",
data="Server started successfully",
)
return "done"
```
```typescript TypeScript theme={null}
await server.sendLoggingMessage({
level: "info",
data: "Server started successfully",
});
```
</CodeGroup>
MCP defines eight
[RFC 5424 severity levels](/specification/2025-06-18/server/utilities/logging#log-levels)
(`debug` through `emergency`). Clients can adjust the minimum level at runtime
via the
[`logging/setLevel`](/specification/2025-06-18/server/utilities/logging#setting-log-level)
request.
Important events to log:
* Initialization steps
* Resource access
* Tool execution
* Error conditions
* Performance metrics
## Common issues
The examples below use Claude Desktop's
[`claude_desktop_config.json`](/docs/2025-06-18/develop/connect-local-servers); the same
principles apply to any stdio-based MCP client.
### Working directory
When an MCP client launches a stdio server:
* The working directory for servers launched via the client's config may be
undefined (like `/` on macOS) since the client could be started from
anywhere
* Always use absolute paths in your configuration and `.env` files to ensure
reliable operation
* For testing servers directly via command line, the working directory will be
where you run the command
For example in `claude_desktop_config.json`, use:
```json theme={null}
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"/Users/username/data"
]
}
}
}
```
Instead of relative paths like `./data`
### Environment variables
MCP servers launched over stdio inherit only a limited subset of environment
variables automatically (the exact set is platform-dependent).
To override the default variables or provide your own, you can specify an
`env` key in `claude_desktop_config.json`:
```json theme={null}
{
"mcpServers": {
"myserver": {
"command": "mcp-server-myapp",
"env": {
"MYAPP_API_KEY": "some_key"
}
}
}
}
```
### Server initialization
Common initialization problems:
1. **Path Issues**
* Incorrect server executable path
* Missing required files
* Permission problems
* Try using an absolute path for `command`
2. **Configuration Errors**
* Invalid JSON syntax
* Missing required fields
* Type mismatches
3. **Environment Problems**
* Missing environment variables
* Incorrect variable values
* Permission restrictions
### Connection problems
When servers fail to connect:
1. Check client logs
2. Verify server process is running
3. Test standalone with [Inspector](/docs/2025-06-18/tools/inspector)
4. Verify
[protocol compatibility](/specification/2025-06-18/basic/lifecycle#version-negotiation)
5. Check
[capability negotiation](/specification/2025-06-18/basic/lifecycle#capability-negotiation):
error [`-32602`](/specification/2025-06-18/basic/lifecycle#error-handling) is
the standard JSON-RPC "Invalid params" code and is returned in many
contexts. One common cause is a server sending
[sampling](/specification/2025-06-18/client/sampling) or
[elicitation](/specification/2025-06-18/client/elicitation) requests to a
client that hasn't declared that capability. Inspect the
[`initialize` exchange](/specification/2025-06-18/basic/lifecycle#initialization)
to verify both sides declared what you expect
## Debugging in Claude Desktop
Claude Desktop is one of many MCP clients. It is available on
macOS and Windows.
### Checking server status
Click the "Add files, connectors, and more" plus icon in the chat input, then
hover over the **Connectors** menu to see connected servers and available
tools.
<img src="https://mintcdn.com/mcp/zNouQwo2h8cbxlDS/images/available-mcp-tools.png?fit=max&auto=format&n=zNouQwo2h8cbxlDS&q=85&s=e2ace1ac88895a5fe30ebd8d01456bc3" alt="Available MCP tools" width="437" height="244" data-path="images/available-mcp-tools.png" />
### Viewing logs
Log files are written to:
* macOS: `~/Library/Logs/Claude`
* Windows: `%APPDATA%\Claude\logs`
<CodeGroup>
```bash macOS theme={null}
tail -n 20 -F ~/Library/Logs/Claude/mcp*.log
```
```powershell Windows theme={null}
type "$env:AppData\Claude\logs\mcp*.log"
```
</CodeGroup>
The logs capture:
* Server connection events
* Configuration issues
* Runtime errors
* Message exchanges
### Using Chrome DevTools
Access Chrome's developer tools inside Claude Desktop to investigate
client-side errors:
1. Create a `developer_settings.json` file with `allowDevTools` set to true:
<CodeGroup>
```bash macOS theme={null}
echo '{"allowDevTools": true}' > ~/Library/Application\ Support/Claude/developer_settings.json
```
```powershell Windows theme={null}
'{"allowDevTools": true}' | Set-Content "$env:AppData\Claude\developer_settings.json"
```
</CodeGroup>
2. Open DevTools: `Command-Option-I` (macOS) or `Ctrl+Alt+I` (Windows)
Note: You'll see two DevTools windows:
* Main content window
* App title bar window
Use the Console panel to inspect client-side errors.
Use the Network panel to inspect:
* Message payloads
* Connection timing
## Debugging workflow
### Development cycle
1. Initial Development
* Use [Inspector](/docs/2025-06-18/tools/inspector) for basic testing
* Implement core functionality
* Add logging points
2. Integration Testing
* Test in your target MCP client
* Monitor logs
* Check error handling
### Testing changes
To test changes efficiently:
* **Configuration changes**: Restart the MCP client
* **Server code changes**: Restart the client (for Claude Desktop, fully quit
and reopen; closing the window is not enough)
* **Quick iteration**: Use [Inspector](/docs/2025-06-18/tools/inspector) during
development
## Best practices
### Logging strategy
1. **Structured Logging**
* Use consistent formats
* Include context
* Add timestamps
* Track request IDs
2. **Error Handling**
* Log stack traces
* Include error context
* Track error patterns
* Monitor recovery
3. **Performance Tracking**
* Log operation timing
* Monitor resource usage
* Track message sizes
* Measure latency
### Security considerations
When debugging:
Cut at 300 lines. The page has the rest.
docs/2025-06-18/tools/inspector New page · 140 lines, new page
# MCP Inspector ## Getting started ### Installation and basic usage #### Inspecting servers from npm or PyPI #### Inspecting locally developed servers ## Feature overview ### Server connection pane ### Resources tab ### Prompts tab ### Tools tab ### Notifications pane ## Best practices ### Development workflow ## Next steps
A whole new page. There's nothing to diff it against, so here is what it says.
# MCP Inspector
> In-depth guide to using the MCP Inspector for testing and debugging Model Context Protocol servers
The [MCP Inspector](https://github.com/modelcontextprotocol/inspector) is an interactive developer tool for testing and debugging MCP servers. While the [Debugging Guide](/docs/2025-06-18/tools/debugging) covers the Inspector as part of the overall debugging toolkit, this document provides a detailed exploration of the Inspector's features and capabilities.
## Getting started
### Installation and basic usage
The Inspector runs directly through `npx` without requiring installation:
```bash theme={null}
npx @modelcontextprotocol/inspector <command>
```
```bash theme={null}
npx @modelcontextprotocol/inspector <command> <arg1> <arg2>
```
#### Inspecting servers from npm or PyPI
A common way to start server packages from [npm](https://npmjs.com) or [PyPI](https://pypi.org).
<Tabs>
<Tab title="npm package">
```bash theme={null}
npx -y @modelcontextprotocol/inspector npx <package-name> <args>
# For example
npx -y @modelcontextprotocol/inspector npx @modelcontextprotocol/server-filesystem /Users/username/Desktop
```
</Tab>
<Tab title="PyPI package">
```bash theme={null}
npx @modelcontextprotocol/inspector uvx <package-name> <args>
# For example
npx @modelcontextprotocol/inspector uvx mcp-server-git --repository ~/code/mcp/servers.git
```
</Tab>
</Tabs>
#### Inspecting locally developed servers
To inspect servers locally developed or downloaded as a repository, the most common
way is:
<Tabs>
<Tab title="TypeScript">
```bash theme={null}
npx @modelcontextprotocol/inspector node path/to/server/index.js args...
```
</Tab>
<Tab title="Python">
```bash theme={null}
npx @modelcontextprotocol/inspector \
uv \
--directory path/to/server \
run \
package-name \
args...
```
</Tab>
</Tabs>
Please carefully read any attached README for the most accurate instructions.
## Feature overview
<Frame caption="The MCP Inspector interface">
<img src="https://mintcdn.com/mcp/4ZXF1PrDkEaJvXpn/images/mcp-inspector.png?fit=max&auto=format&n=4ZXF1PrDkEaJvXpn&q=85&s=83b12e2a457c96ef4ad17c7357236290" width="2888" height="1761" data-path="images/mcp-inspector.png" />
</Frame>
The Inspector provides several features for interacting with your MCP server:
### Server connection pane
* Allows selecting the [transport](/specification/2025-06-18/basic/transports) for connecting to the server
* For local servers, supports customizing the command-line arguments and environment
### Resources tab
* Lists all available resources
* Shows resource metadata (MIME types, descriptions)
* Allows resource content inspection
* Supports subscription testing
### Prompts tab
* Displays available prompt templates
* Shows prompt arguments and descriptions
* Enables prompt testing with custom arguments
* Previews generated messages
### Tools tab
* Lists available tools
* Shows tool schemas and descriptions
* Enables tool testing with custom inputs
* Displays tool execution results
### Notifications pane
* Presents all logs recorded from the server
* Shows notifications received from the server
## Best practices
### Development workflow
1. Start Development
* Launch Inspector with your server
* Verify basic connectivity
* Check capability negotiation
2. Iterative testing
* Make server changes
* Rebuild the server
* Reconnect the Inspector
* Test affected features
* Monitor messages
3. Test edge cases
* Invalid inputs
* Missing prompt arguments
* Concurrent operations
* Verify error handling and error responses
## Next steps
<CardGroup cols={2}>
<Card title="Inspector Repository" icon="github" href="https://github.com/modelcontextprotocol/inspector">
Check out the MCP Inspector source code
</Card>
<Card title="Debugging Guide" icon="bug" href="/docs/2025-06-18/tools/debugging">
Learn about broader debugging strategies
</Card>
</CardGroup>
docs/2025-06-18/tutorials/security/authorization New page · 1057 lines, new page
# Understanding Authorization in MCP ## When Should You Use Authorization? ## The Authorization Flow: Step by Step ## Implementation Example ### Keycloak Setup ### MCP Server Setup ## Testing the MCP Server ## Common Pitfalls and How to Avoid Them ## Related Standards and Documentation
A whole new page. There's nothing to diff it against, so here is what it says.
# Understanding Authorization in MCP
> Learn how to implement secure authorization for MCP servers using OAuth 2.1 to protect sensitive resources and operations
Authorization in the Model Context Protocol (MCP) secures access to sensitive resources and operations exposed by MCP servers. If your MCP server handles user data or administrative actions, authorization ensures only permitted users can access its endpoints.
MCP uses standardized authorization flows to build trust between MCP clients and MCP servers. Its design doesn't focus on one specific authorization or identity system, but rather follows the conventions outlined for [OAuth 2.1](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-13). For detailed information, see the [Authorization specification](/specification/2025-06-18/basic/authorization).
## When Should You Use Authorization?
While authorization for MCP servers is **optional**, it is strongly recommended when:
* Your server accesses user-specific data (emails, documents, databases)
* You need to audit who performed which actions
* Your server grants access to its APIs that require user consent
* You're building for enterprise environments with strict access controls
* You want to implement rate limiting or usage tracking per user
<Tip>
**Authorization for Local MCP Servers**
For MCP servers using the [STDIO transport](/specification/2025-06-18/basic/transports#stdio), you can use environment-based credentials or credentials provided by third-party libraries embedded directly in the MCP server instead. Because a STDIO-built MCP server runs locally, it has access to a range of flexible options when it comes to acquiring user credentials that may or may not rely on in-browser authentication and authorization flows.
OAuth flows, in turn, are designed for HTTP-based transports where the MCP server is remotely-hosted and the client uses OAuth to establish that a user is authorized to access said remote server.
</Tip>
## The Authorization Flow: Step by Step
Let's walk through what happens when a client wants to connect to your protected MCP server:
<Steps>
<Step title="Initial Handshake">
When your MCP client first tries to connect, your server responds with a `401 Unauthorized` and tells the client where to find authorization information, captured in a [Protected Resource Metadata (PRM) document](https://datatracker.ietf.org/doc/html/rfc9728). The document is hosted by the MCP server, follows a predictable path pattern, and is provided to the client in the `resource_metadata` parameter within the `WWW-Authenticate` header.
```http theme={null}
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="mcp",
resource_metadata="https://your-server.com/.well-known/oauth-protected-resource"
```
This tells the client that authorization is required for the MCP server and where to get the necessary information to kickstart the authorization flow.
</Step>
<Step title="Protected Resource Metadata Discovery">
With the URI pointer to the PRM document, the client will fetch the metadata to learn about the authorization server, supported scopes, and other resource information. The data is typically encapsulated in a JSON blob, similar to the one below.
```json theme={null}
{
"resource": "https://your-server.com/mcp",
"authorization_servers": ["https://auth.your-server.com"],
"scopes_supported": ["mcp:tools", "mcp:resources"]
}
```
You can see a more comprehensive example in [RFC 9728 Section 3.2](https://datatracker.ietf.org/doc/html/rfc9728#name-protected-resource-metadata-r).
</Step>
<Step title="Authorization Server Discovery">
Next, the client discovers what the authorization server can do by fetching its metadata. If the PRM document lists more than one authorization server, the client can decide which one to use.
With an authorization server selected, the client will then construct a standard metadata URI and issue a request to the [OpenID Connect (OIDC) Discovery](https://openid.net/specs/openid-connect-discovery-1_0.html) or [OAuth 2.0 Auth Server Metadata](https://datatracker.ietf.org/doc/html/rfc8414) endpoints (depending on authorization server support)
and retrieve another set of metadata properties that will allow it to know the endpoints it needs to complete the authorization flow.
```json theme={null}
{
"issuer": "https://auth.your-server.com",
"authorization_endpoint": "https://auth.your-server.com/authorize",
"token_endpoint": "https://auth.your-server.com/token",
"registration_endpoint": "https://auth.your-server.com/register"
}
```
</Step>
<Step title="Client Registration">
With all the metadata out of the way, the client now needs to make sure that it's registered with the authorization server. This can be done in two ways.
First, the client can be **pre-registered** with a given authorization server, in which case it can have embedded client registration information that it uses to complete the authorization flow.
Alternatively, the client can use **Dynamic Client Registration** (DCR) to dynamically register itself with the authorization server. The latter scenario requires the authorization server to support DCR. If the authorization server does support DCR, the client will send a request to the `registration_endpoint` with its information:
```json theme={null}
{
"client_name": "My MCP Client",
"redirect_uris": ["http://localhost:3000/callback"],
"grant_types": ["authorization_code", "refresh_token"],
"response_types": ["code"]
}
```
If the registration succeeds, the authorization server will return a JSON blob with client registration information.
<Tip>
**No DCR or Pre-Registration**
In case an MCP client connects to an MCP server that doesn't use an authorization server that supports DCR and the client is not pre-registered with said authorization server, it's the responsibility of the client developer to provide an affordance for the end-user to enter client information manually.
</Tip>
</Step>
<Step title="User Authorization">
The client will now need to open a browser to the `/authorize` endpoint, where the user can log in and grant the required permissions. The authorization server will then redirect back to the client with an authorization code that the client exchanges for tokens:
```json theme={null}
{
"access_token": "eyJhbGciOiJSUzI1NiIs...",
"refresh_token": "def502...",
"token_type": "Bearer",
"expires_in": 3600
}
```
The access token is what the client will use to authenticate requests to the MCP server. This step follows standard [OAuth 2.1 authorization code with PKCE](https://oauth.net/2/grant-types/authorization-code/) conventions.
</Step>
<Step title="Making Authenticated Requests">
Finally, the client can make requests to your MCP server using the access token embedded in the `Authorization` header:
```http theme={null}
GET /mcp HTTP/1.1
Host: your-server.com
Authorization: Bearer eyJhbGciOiJSUzI1NiIs...
```
The MCP server will need to validate the token and process the request if the token is valid and has the required permissions.
</Step>
</Steps>
## Implementation Example
To get started with a practical implementation, we will use a [Keycloak](https://www.keycloak.org/) authorization server hosted in a Docker container. Keycloak is an open-source authorization server that can be easily deployed locally for testing and experimentation.
Make sure that you download and install [Docker Desktop](https://www.docker.com/products/docker-desktop/). We will need it to deploy Keycloak on our development machine.
### Keycloak Setup
From your terminal application, run the following command to start the Keycloak container:
```bash theme={null}
docker run -p 127.0.0.1:8080:8080 -e KC_BOOTSTRAP_ADMIN_USERNAME=admin -e KC_BOOTSTRAP_ADMIN_PASSWORD=admin quay.io/keycloak/keycloak start-dev
```
This command will pull the Keycloak container image locally and bootstrap the basic configuration. It will run on port `8080` and have an `admin` user with `admin` password.
<Warning>
**Not for Production**
The configuration above may be suitable for testing and experimentation; however, you should never use it in production. Refer to the [Configuring Keycloak for production](https://www.keycloak.org/server/configuration-production) guide for additional details on how to deploy the authorization server for scenarios that require reliability, security, and high availability.
</Warning>
You will be able to access the Keycloak authorization server from your browser at `http://localhost:8080`.
<Frame>
<img src="https://mintcdn.com/mcp/sAd4SGUO-cEUqgzn/images/tutorial-authorization/keycloak-browser.png?fit=max&auto=format&n=sAd4SGUO-cEUqgzn&q=85&s=cba689d986e113cbe937d732ac0558b6" alt="Keycloak admin dashboard authentication dialog." width="1834" height="1450" data-path="images/tutorial-authorization/keycloak-browser.png" />
</Frame>
When running with the default configuration, Keycloak will already support many of the capabilities that we need for MCP servers, including Dynamic Client Registration. You can check this by looking at the OIDC configuration, available at:
```http theme={null}
http://localhost:8080/realms/master/.well-known/openid-configuration
```
We will also need to set up Keycloak to support our scopes and allow our host (local machine) to dynamically register clients, as the default policies restrict anonymous dynamic client registration.
Go to **Client scopes** in the Keycloak dashboard and create a new `mcp:tools` scope. We will use this to access all of the tools on our MCP server.
<Frame>
<img src="https://mintcdn.com/mcp/sAd4SGUO-cEUqgzn/images/tutorial-authorization/keycloak-scopes.png?fit=max&auto=format&n=sAd4SGUO-cEUqgzn&q=85&s=3cd49dc2e070027609ae495751e0db58" alt="Configuring Keycloak scopes." width="1999" height="1710" data-path="images/tutorial-authorization/keycloak-scopes.png" />
</Frame>
After creating the scope, make sure that you assign its type to **Default** and have flipped the **Include in token scope** switch, as this will be needed for token validation.
Let's now also set up an **audience** for our Keycloak-issued tokens. An audience is important to configure because it embeds the intended destination directly into the issued access token. This helps your MCP server to verify that the token it got was actually meant for it rather than some other API. This is key to help avoid token passthrough scenarios.
To do this, open your `mcp:tools` client scope and click on **Mappers**, followed by **Configure a new mapper**. Select **Audience**.
<Frame>
<img src="https://mintcdn.com/mcp/sAd4SGUO-cEUqgzn/images/tutorial-authorization/scope-add-audience.gif?s=6ea9cf20c397f4c79c491c2e39019272" alt="Configuring an audience for a token in Keycloak." width="1080" height="921" data-path="images/tutorial-authorization/scope-add-audience.gif" />
</Frame>
For **Name**, use `audience-config`. Add a value for **Included Custom Audience**, set to `http://localhost:3000`. This will be the URI of our test server.
<Warning>
**Not for Production**
The audience configuration above is meant for testing. For production scenarios, additional set-up and configuration will be required to ensure that audiences are properly constrained for issued tokens. Specifically, the audience needs to be based on the resource parameter passed from the client, not a fixed value.
</Warning>
Now, navigate to **Clients**, then **Client registration**, and then **Trusted Hosts**. Disable the **Client URIs Must Match** setting and add the hosts from which you're testing. You can get your current host IP by running the `ifconfig` command on Linux or macOS, or `ipconfig` on Windows. You can see the IP address you need to add by looking at the keycloak logs for a line that looks like `Failed to verify remote host : 192.168.215.1`. Check that the IP address is associated with your host. This may be for a bridge network depending on your docker setup.
<Frame>
<img src="https://mintcdn.com/mcp/sAd4SGUO-cEUqgzn/images/tutorial-authorization/keycloak-client.gif?s=b5d40b36a5f1ea1e818821bb8ea77f6b" alt="Setting up client registration details in Keycloak." width="1199" height="1027" data-path="images/tutorial-authorization/keycloak-client.gif" />
</Frame>
<Warning>
**Getting the Host**
If you are running Keycloak from a container, you will also be able to see the host IP from the Terminal in the container logs.
</Warning>
Lastly, we need to register a new client that we can use with the **MCP server itself** to talk to Keycloak for things like [token introspection](https://oauth.net/2/token-introspection/). To do that:
1. Go to **Clients**.
2. Click **Create client**.
3. Give your client a unique **Client ID** and click **Next**.
4. Enable **Client authentication** and click **Next**.
5. Click **Save**.
Worth noting that token introspection is just *one of* the available approaches to validate tokens. This can also be done with the help of standalone libraries, specific to each language and platform.
When you open the client details, go to **Credentials** and take note of the **Client Secret**.
<Frame>
<img src="https://mintcdn.com/mcp/sAd4SGUO-cEUqgzn/images/tutorial-authorization/keycloak-client-auth.gif?s=7152c41a5746994fd399024bc4659e40" alt="Creating a new client in Keycloak." width="1200" height="1023" data-path="images/tutorial-authorization/keycloak-client-auth.gif" />
</Frame>
<Warning>
**Handling Secrets**
Never embed client credentials directly in your code. We recommend using environment variables or specialized solutions for secret storage.
</Warning>
With Keycloak configured, every time the authorization flow is triggered, your MCP server will receive a token like this:
```text theme={null}
eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI1TjcxMGw1WW5MWk13WGZ1VlJKWGtCS3ZZMzZzb3JnRG5scmlyZ2tlTHlzIn0.eyJleHAiOjE3NTU1NDA4MTcsImlhdCI6MTc1NTU0MDc1NywiYXV0aF90aW1lIjoxNzU1NTM4ODg4LCJqdGkiOiJvbnJ0YWM6YjM0MDgwZmYtODQwNC02ODY3LTgxYmUtMTIzMWI1MDU5M2E4IiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4MDgwL3JlYWxtcy9tYXN0ZXIiLCJhdWQiOiJodHRwOi8vbG9jYWxob3N0OjMwMDAiLCJzdWIiOiIzM2VkNmM2Yi1jNmUwLTQ5MjgtYTE2MS1mMmY2OWM3YTAzYjkiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiI3OTc1YTViNi04YjU5LTRhODUtOWNiYS04ZmFlYmRhYjg5NzQiLCJzaWQiOiI4ZjdlYzI3Ni0zNThmLTRjY2MtYjMxMy1kYjA4MjkwZjM3NmYiLCJzY29wZSI6Im1jcDp0b29scyJ9.P5xCRtXORly0R0EXjyqRCUx-z3J4uAOWNAvYtLPXroykZuVCCJ-K1haiQSwbURqfsVOMbL7jiV-sD6miuPzI1tmKOkN_Yct0Vp-azvj7U5rEj7U6tvPfMkg2Uj_jrIX0KOskyU2pVvGZ-5BgqaSvwTEdsGu_V3_E0xDuSBq2uj_wmhqiyTFm5lJ1WkM3Hnxxx1_AAnTj7iOKMFZ4VCwMmk8hhSC7clnDauORc0sutxiJuYUZzxNiNPkmNeQtMCGqWdP1igcbWbrfnNXhJ6NswBOuRbh97_QraET3hl-CNmyS6C72Xc0aOwR_uJ7xVSBTD02OaQ1JA6kjCATz30kGYg
```
Decoded, it will look like this:
```json theme={null}
{
"alg": "RS256",
"typ": "JWT",
"kid": "5N710l5YnLZMwXfuVRJXkBKvY36sorgDnlrirgkeLys"
}.{
"exp": 1755540817,
"iat": 1755540757,
"auth_time": 1755538888,
"jti": "onrtac:b34080ff-8404-6867-81be-1231b50593a8",
"iss": "http://localhost:8080/realms/master",
"aud": "http://localhost:3000",
"sub": "33ed6c6b-c6e0-4928-a161-f2f69c7a03b9",
"typ": "Bearer",
"azp": "7975a5b6-8b59-4a85-9cba-8faebdab8974",
"sid": "8f7ec276-358f-4ccc-b313-db08290f376f",
"scope": "mcp:tools"
}.[Signature]
```
<Warning>
**Embedded Audience**
Notice the `aud` claim embedded in the token - it's currently set to be the URI of the test MCP server and it's inferred from the scope that we've previously configured. This will be important in our implementation to validate.
</Warning>
### MCP Server Setup
We will now set up our MCP server to use the locally-running Keycloak authorization server. Depending on your programming language preference, you can use one of the supported [MCP SDKs](/docs/2025-06-18/sdk).
For our testing purposes, we will create an extremely simple MCP server that exposes two tools - one for addition and another for multiplication. The server will require authorization to access these.
<Tabs>
<Tab title="TypeScript">
You can see the complete TypeScript project in the [sample repository](https://github.com/localden/min-ts-mcp-auth).
Prior to running the code below, ensure that you have a `.env` file with the following content:
```env theme={null}
# Server host/port
HOST=localhost
PORT=3000
# Auth server location
AUTH_HOST=localhost
AUTH_PORT=8080
AUTH_REALM=master
# Keycloak OAuth client credentials
OAUTH_CLIENT_ID=<YOUR_SERVER_CLIENT_ID>
OAUTH_CLIENT_SECRET=<YOUR_SERVER_CLIENT_SECRET>
```
`OAUTH_CLIENT_ID` and `OAUTH_CLIENT_SECRET` are associated with the MCP server client we created earlier.
In addition to implementing the MCP authorization specification, the server below also does token introspection via Keycloak to make sure that the token it receives from the client is valid. It also implements basic logging to allow you to easily diagnose any issues.
```typescript theme={null}
import "dotenv/config";
import express from "express";
import { randomUUID } from "node:crypto";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
import { isInitializeRequest } from "@modelcontextprotocol/sdk/types.js";
import { z } from "zod";
import cors from "cors";
import {
mcpAuthMetadataRouter,
getOAuthProtectedResourceMetadataUrl,
} from "@modelcontextprotocol/sdk/server/auth/router.js";
import { requireBearerAuth } from "@modelcontextprotocol/sdk/server/auth/middleware/bearerAuth.js";
import { OAuthMetadata } from "@modelcontextprotocol/sdk/shared/auth.js";
Cut at 300 lines. The page has the rest.
docs/2025-06-18/tutorials/security/security_best_practices New page · 897 lines, new page
# Security Best Practices ## Introduction ### Purpose and Scope ## Attacks and Mitigations ### Confused Deputy Problem #### Terminology #### Vulnerable Conditions #### Architecture and Attack Flows ##### Normal OAuth proxy usage (preserves user consent) ##### Malicious OAuth proxy usage (skips user consent) #### Attack Description #### Mitigation ##### Consent Flow Implementation ##### Required Protections ### Token Passthrough #### Risks #### Mitigation ### Server-Side Request Forgery (SSRF) #### Attack Description #### Risks #### Mitigation #### Resources and Tools ### Session Hijacking #### Session Hijack Prompt Injection #### Session Hijack Impersonation #### Attack Description #### Mitigation ### Local MCP Server Compromise #### Attack Description #### Risks #### Mitigation ### OAuth Authorization URL Validation #### Attack Description #### Risks #### Mitigation ### stdio Transport Security in Proxy Scenarios #### Attack Description #### Risks #### Mitigation ### Scope Minimization #### Attack Description #### Risks #### Mitigation #### Common Mistakes
A whole new page. There's nothing to diff it against, so here is what it says.
# Security Best Practices
> Security considerations, attack vectors, and best practices for MCP implementations
## Introduction
### Purpose and Scope
This document provides security considerations for the Model Context
Protocol (MCP), complementing the
[MCP Authorization](/specification/2025-06-18/basic/authorization)
specification. This document identifies security risks, attack vectors,
and best practices specific to MCP implementations.
The primary audience for this document includes developers implementing
MCP authorization flows, MCP server operators, and security
professionals evaluating MCP-based systems. This document should be read
alongside the MCP Authorization specification and
[OAuth 2.0 security best practices](https://datatracker.ietf.org/doc/html/rfc9700).
## Attacks and Mitigations
This section gives a detailed description of attacks on MCP
implementations, along with potential countermeasures.
### Confused Deputy Problem
Attackers can exploit MCP proxy servers that connect to third-party
APIs, creating
"[confused deputy](https://en.wikipedia.org/wiki/Confused_deputy_problem)"
vulnerabilities. This attack allows malicious clients to obtain
authorization codes without proper user consent by exploiting the
combination of static client IDs, dynamic client registration, and
consent cookies.
#### Terminology
**MCP Proxy Server**
: An MCP server that connects MCP clients to third-party APIs, offering
MCP features while delegating operations and acting as a single OAuth
client to the third-party API server.
**Third-Party Authorization Server**
: Authorization server that protects the third-party API. It may lack
dynamic client registration support, requiring the MCP proxy to use a
static client ID for all requests.
**Third-Party API**
: The protected resource server that provides the actual API
functionality. Access to this API requires tokens issued by the
third-party authorization server.
**Static Client ID**
: A fixed OAuth 2.0 client identifier used by the MCP proxy server when
communicating with the third-party authorization server. This Client ID
refers to the MCP server acting as a client to the Third-Party API. It
is the same value for all MCP server to Third-Party API interactions
regardless of which MCP client initiated the request.
#### Vulnerable Conditions
This attack becomes possible when all of the following conditions are
present:
* MCP proxy server uses a **static client ID** with a third-party
authorization server
* MCP proxy server allows MCP clients to **dynamically register** (each
getting their own client\_id)
* The third-party authorization server sets a **consent cookie** after
the first authorization
* MCP proxy server does not implement proper per-client consent before
forwarding to third-party authorization
#### Architecture and Attack Flows
##### Normal OAuth proxy usage (preserves user consent)
```mermaid theme={null}
sequenceDiagram
participant UA as User-Agent (Browser)
participant MC as MCP Client
participant M as MCP Proxy Server
participant TAS as Third-Party Authorization Server
Note over UA,M: Initial Auth flow completed
Note over UA,TAS: Step 1: Legitimate user consent for Third Party Server
M->>UA: Redirect to third party authorization server
UA->>TAS: Authorization request (client_id: mcp-proxy)
TAS->>UA: Authorization consent screen
Note over UA: Review consent screen
UA->>TAS: Approve
TAS->>UA: Set consent cookie for client ID: mcp-proxy
TAS->>UA: 3P Authorization code + redirect to mcp-proxy-server.com
UA->>M: 3P Authorization code
Note over M,TAS: Exchange 3P code for 3P token
Note over M: Generate MCP authorization code
M->>UA: Redirect to MCP Client with MCP authorization code
Note over M,UA: Exchange code for token, etc.
```
##### Malicious OAuth proxy usage (skips user consent)
```mermaid theme={null}
sequenceDiagram
participant UA as User-Agent (Browser)
participant M as MCP Proxy Server
participant TAS as Third-Party Authorization Server
participant A as Attacker
Note over UA,A: Step 2: Attack (leveraging existing cookie, skipping consent)
A->>M: Dynamically register malicious client, redirect_uri: attacker.com
A->>UA: Sends malicious link
UA->>TAS: Authorization request (client_id: mcp-proxy) + consent cookie
rect rgba(255, 17, 0, 0.67)
TAS->>TAS: Cookie present, consent skipped
end
TAS->>UA: 3P Authorization code + redirect to mcp-proxy-server.com
UA->>M: 3P Authorization code
Note over M,TAS: Exchange 3P code for 3P token
Note over M: Generate MCP authorization code
M->>UA: Redirect to attacker.com with MCP Authorization code
UA->>A: MCP Authorization code delivered to attacker.com
Note over M,A: Attacker exchanges MCP code for MCP token
A->>M: Attacker impersonates user to MCP server
```
#### Attack Description
When an MCP proxy server uses a static client ID to authenticate with
a third-party authorization server, the following attack becomes
possible:
1. A user authenticates normally through the MCP proxy server to access
the third-party API
2. During this flow, the third-party authorization server sets a cookie
on the user agent indicating consent for the static client ID
3. An attacker later sends the user a malicious link containing a
crafted authorization request which contains a malicious redirect URI
along with a new dynamically registered client ID
4. When the user clicks the link, their browser still has the consent
cookie from the previous legitimate request
5. The third-party authorization server detects the cookie and skips the
consent screen
6. The MCP authorization code is redirected to the attacker's server
(specified in the malicious `redirect_uri` parameter during
[dynamic client registration](/specification/2025-06-18/basic/authorization#dynamic-client-registration))
7. The attacker exchanges the stolen authorization code for access
tokens for the MCP server without the user's explicit approval
8. The attacker now has access to the third-party API as the compromised
user
#### Mitigation
To prevent confused deputy attacks, MCP proxy servers **MUST** implement
per-client consent and proper security controls as detailed below.
##### Consent Flow Implementation
The following diagram shows how to properly implement per-client consent
that runs **before** the third-party authorization flow:
```mermaid theme={null}
sequenceDiagram
participant Client as MCP Client
participant Browser as User's Browser
participant MCP as MCP Server
participant ThirdParty as Third-Party AuthZ Server
Note over Client,ThirdParty: 1. Client Registration (Dynamic)
Client->>MCP: Register with redirect_uri
MCP-->>Client: client_id
Note over Client,ThirdParty: 2. Authorization Request
Client->>Browser: Open MCP server authorization URL
Browser->>MCP: GET /authorize?client_id=...&redirect_uri=...
alt Check MCP Server Consent
MCP->>MCP: Check consent for this client_id
Note over MCP: Not previously approved
end
MCP->>Browser: Show MCP server-owned consent page
Note over Browser: "Allow [Client Name] to access [Third-Party API]?"
Browser->>MCP: POST /consent (approve)
MCP->>MCP: Store consent decision for client_id
Note over Client,ThirdParty: 3. Forward to Third-Party
MCP->>Browser: Redirect to third-party /authorize
Note over MCP: Use static client_id for third-party
Browser->>ThirdParty: Authorization request (static client_id)
ThirdParty->>Browser: User authenticates & consents
ThirdParty->>Browser: Redirect with auth code
Browser->>MCP: Callback with third-party code
MCP->>ThirdParty: Exchange code for token (using static client_id)
MCP->>Browser: Redirect to client's registered redirect_uri
```
##### Required Protections
**Per-Client Consent Storage**
MCP proxy servers **MUST**:
* Maintain a registry of approved `client_id` values per user
* Check this registry **before** initiating the third-party
authorization flow
* Store consent decisions securely (server-side database, or server
specific cookies)
**Consent UI Requirements**
The MCP-level consent page **MUST**:
* Clearly identify the requesting MCP client by name
* Display the specific third-party API scopes being requested
* Show the registered `redirect_uri` where tokens will be sent
* Implement CSRF protection (e.g., state parameter, CSRF tokens)
* Prevent iframing via `frame-ancestors` CSP directive or
`X-Frame-Options: DENY` to prevent clickjacking
**Consent Cookie Security**
If using cookies to track consent decisions, they **MUST**:
* Use `__Host-` prefix for cookie names
* Set `Secure`, `HttpOnly`, and `SameSite=Lax` attributes
* Be cryptographically signed or use server-side sessions
* Bind to the specific `client_id` (not just "user has consented")
**Redirect URI Validation**
The MCP proxy server **MUST**:
* Validate that the `redirect_uri` in authorization requests exactly
matches the registered URI
* Reject requests if the `redirect_uri` has changed without
re-registration
* Use exact string matching (not pattern matching or wildcards)
**OAuth State Parameter Validation**
The OAuth `state` parameter is critical to prevent authorization code
interception and CSRF attacks. Proper state validation ensures that
consent approval at the authorization endpoint is enforced at the
callback endpoint.
MCP proxy servers implementing OAuth flows **MUST**:
* Generate a cryptographically secure random `state` value for each
authorization request
* Store the `state` value server-side (in a secure session store or
encrypted cookie) **only after** consent has been explicitly approved
* Set the `state` tracking cookie/session **immediately before**
redirecting to the third-party identity provider (not before consent
approval)
* Validate at the callback endpoint that the `state` query parameter
exactly matches the stored value in the callback request's cookies or
in the request's cookie-based session
* Reject any callback requests where the `state` parameter is missing
or does not match
* Ensure `state` values are single-use (delete after validation) and
have a short expiration time (e.g., 10 minutes)
The consent cookie or session containing the `state` value **MUST NOT**
be set until **after** the user has approved the consent screen at the
MCP server's authorization endpoint. Setting this cookie before consent
approval renders the consent screen ineffective, as an attacker could
bypass it by crafting a malicious authorization request.
### Token Passthrough
"Token passthrough" is an anti-pattern where an MCP server accepts
tokens from an MCP client without validating that the tokens were
properly issued *to the MCP server* and passes them through to the
downstream API.
#### Risks
Token passthrough is explicitly forbidden in the
[authorization specification](/specification/2025-06-18/basic/authorization)
as it introduces a number of security risks, that include:
* **Security Control Circumvention**
* The MCP Server or downstream APIs might implement important security
controls like rate limiting, request validation, or traffic
monitoring, that depend on the token audience or other credential
constraints. If clients can obtain and use tokens directly with the
downstream APIs without the MCP server validating them properly or
ensuring that the tokens are issued for the right service, they
bypass these controls.
* **Accountability and Audit Trail Issues**
* The MCP Server will be unable to identify or distinguish between MCP
Clients when clients are calling with an upstream-issued access token
Cut at 300 lines. The page has the rest.
docs/2025-11-25/develop/build-client New page · 2518 lines, new page
# Build an MCP client ## Next steps
A whole new page. There's nothing to diff it against, so here is what it says.
# Build an MCP client
> Get started building your own client that can integrate with all MCP servers.
In this tutorial, you'll learn how to build an LLM-powered chatbot client that connects to MCP servers.
Before you begin, it helps to have gone through our [Build an MCP Server](/docs/2025-11-25/develop/build-server) tutorial so you can understand how clients and servers communicate.
<Tabs>
<Tab title="Python">
[You can find the complete code for this tutorial here.](https://github.com/modelcontextprotocol/quickstart-resources/tree/main/mcp-client-python)
## System Requirements
Before starting, ensure your system meets these requirements:
* Mac or Windows computer
* Latest Python version installed
* Latest version of `uv` installed
## Setting Up Your Environment
First, create a new Python project with `uv`:
<CodeGroup>
```bash macOS/Linux theme={null}
# Create project directory
uv init mcp-client
cd mcp-client
# Create virtual environment
uv venv
# Activate virtual environment
source .venv/bin/activate
# Install required packages
uv add mcp anthropic python-dotenv
# Remove boilerplate files
rm main.py
# Create our main file
touch client.py
```
```powershell Windows theme={null}
# Create project directory
uv init mcp-client
cd mcp-client
# Create virtual environment
uv venv
# Activate virtual environment
.venv\Scripts\activate
# Install required packages
uv add mcp anthropic python-dotenv
# Remove boilerplate files
del main.py
# Create our main file
new-item client.py
```
</CodeGroup>
## Setting Up Your API Key
You'll need an Anthropic API key from the [Anthropic Console](https://console.anthropic.com/settings/keys).
Create a `.env` file to store it:
```bash theme={null}
echo "ANTHROPIC_API_KEY=your-api-key-goes-here" > .env
```
Add `.env` to your `.gitignore`:
```bash theme={null}
echo ".env" >> .gitignore
```
<Warning>
Make sure you keep your `ANTHROPIC_API_KEY` secure!
</Warning>
## Creating the Client
### Basic Client Structure
First, let's set up our imports and create the basic client class:
```python theme={null}
import asyncio
from typing import Optional
from contextlib import AsyncExitStack
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
from anthropic import Anthropic
from dotenv import load_dotenv
load_dotenv() # load environment variables from .env
class MCPClient:
def __init__(self):
# Initialize session and client objects
self.session: Optional[ClientSession] = None
self.exit_stack = AsyncExitStack()
self.anthropic = Anthropic()
# methods will go here
```
### Server Connection Management
Next, we'll implement the method to connect to an MCP server:
```python theme={null}
async def connect_to_server(self, server_script_path: str):
"""Connect to an MCP server
Args:
server_script_path: Path to the server script (.py or .js)
"""
is_python = server_script_path.endswith('.py')
is_js = server_script_path.endswith('.js')
if not (is_python or is_js):
raise ValueError("Server script must be a .py or .js file")
command = "python" if is_python else "node"
server_params = StdioServerParameters(
command=command,
args=[server_script_path],
env=None
)
stdio_transport = await self.exit_stack.enter_async_context(stdio_client(server_params))
self.stdio, self.write = stdio_transport
self.session = await self.exit_stack.enter_async_context(ClientSession(self.stdio, self.write))
await self.session.initialize()
# List available tools
response = await self.session.list_tools()
tools = response.tools
print("\nConnected to server with tools:", [tool.name for tool in tools])
```
### Query Processing Logic
Now let's add the core functionality for processing queries and handling tool calls:
```python theme={null}
async def process_query(self, query: str) -> str:
"""Process a query using Claude and available tools"""
messages = [
{
"role": "user",
"content": query
}
]
response = await self.session.list_tools()
available_tools = [{
"name": tool.name,
"description": tool.description,
"input_schema": tool.inputSchema
} for tool in response.tools]
# Initial Claude API call
response = self.anthropic.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1000,
messages=messages,
tools=available_tools
)
# Process response and handle tool calls
final_text = []
assistant_message_content = []
for content in response.content:
if content.type == 'text':
final_text.append(content.text)
assistant_message_content.append(content)
elif content.type == 'tool_use':
tool_name = content.name
tool_args = content.input
# Execute tool call
result = await self.session.call_tool(tool_name, tool_args)
final_text.append(f"[Calling tool {tool_name} with args {tool_args}]")
assistant_message_content.append(content)
messages.append({
"role": "assistant",
"content": assistant_message_content
})
messages.append({
"role": "user",
"content": [
{
"type": "tool_result",
"tool_use_id": content.id,
"content": result.content
}
]
})
# Get next response from Claude
response = self.anthropic.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1000,
messages=messages,
tools=available_tools
)
final_text.append(response.content[0].text)
return "\n".join(final_text)
```
### Interactive Chat Interface
Now we'll add the chat loop and cleanup functionality:
```python theme={null}
async def chat_loop(self):
"""Run an interactive chat loop"""
print("\nMCP Client Started!")
print("Type your queries or 'quit' to exit.")
while True:
try:
query = input("\nQuery: ").strip()
if query.lower() == 'quit':
break
response = await self.process_query(query)
print("\n" + response)
except Exception as e:
print(f"\nError: {str(e)}")
async def cleanup(self):
"""Clean up resources"""
await self.exit_stack.aclose()
```
### Main Entry Point
Finally, we'll add the main execution logic:
```python theme={null}
async def main():
if len(sys.argv) < 2:
print("Usage: python client.py <path_to_server_script>")
sys.exit(1)
client = MCPClient()
try:
await client.connect_to_server(sys.argv[1])
await client.chat_loop()
finally:
await client.cleanup()
if __name__ == "__main__":
import sys
asyncio.run(main())
```
You can find the complete `client.py` file [here](https://github.com/modelcontextprotocol/quickstart-resources/blob/main/mcp-client-python/client.py).
## Key Components Explained
### 1. Client Initialization
* The `MCPClient` class initializes with session management and API clients
* Uses `AsyncExitStack` for proper resource management
* Configures the Anthropic client for Claude interactions
### 2. Server Connection
* Supports both Python and Node.js servers
* Validates server script type
* Sets up proper communication channels
* Initializes the session and lists available tools
### 3. Query Processing
* Maintains conversation context
* Handles Claude's responses and tool calls
* Manages the message flow between Claude and tools
* Combines results into a coherent response
### 4. Interactive Interface
Cut at 300 lines. The page has the rest.
docs/2025-11-25/develop/build-server New page · 2997 lines, new page
# Build an MCP server ### What we'll be building ### Core MCP Concepts ### Test with commands ## What's happening under the hood ## Troubleshooting ## Next steps
A whole new page. There's nothing to diff it against, so here is what it says.
# Build an MCP server
> Get started building your own server to use in Claude for Desktop and other clients.
In this tutorial, we'll build a simple MCP weather server and connect it to a host, Claude for Desktop.
### What we'll be building
We'll build a server that exposes two tools: `get_alerts` and `get_forecast`. Then we'll connect the server to an MCP host (in this case, Claude for Desktop):
<Frame>
<img src="https://mintcdn.com/mcp/4ZXF1PrDkEaJvXpn/images/current-weather.png?fit=max&auto=format&n=4ZXF1PrDkEaJvXpn&q=85&s=dce7b2f8a06c20ba358e4bd2e75fa4c7" width="2780" height="1849" data-path="images/current-weather.png" />
</Frame>
<Note>
Servers can connect to any client. We've chosen Claude for Desktop here for simplicity, but we also have a guide on [building your own client](/docs/2025-11-25/develop/build-client).
</Note>
### Core MCP Concepts
MCP servers can provide three main types of capabilities:
1. **[Resources](/docs/2025-11-25/learn/server-concepts#resources)**: File-like data that can be read by clients (like API responses or file contents)
2. **[Tools](/docs/2025-11-25/learn/server-concepts#tools)**: Functions that can be called by the LLM (with user approval)
3. **[Prompts](/docs/2025-11-25/learn/server-concepts#prompts)**: Pre-written templates that help users accomplish specific tasks
This tutorial will primarily focus on tools.
<Tabs>
<Tab title="Python">
Let's get started with building our weather server! [You can find the complete code for what we'll be building here.](https://github.com/modelcontextprotocol/quickstart-resources/tree/main/weather-server-python)
### Prerequisite knowledge
This quickstart assumes you have familiarity with:
* Python
* LLMs like Claude
### Logging in MCP Servers
When implementing MCP servers, be careful about how you handle logging:
**For STDIO-based servers:** Never write to stdout. Writing to stdout will corrupt the JSON-RPC messages and break your server. The `print()` function writes to stdout by default, but can be used safely with `file=sys.stderr`.
**For HTTP-based servers:** Standard output logging is fine since it doesn't interfere with HTTP responses.
### Best Practices
* Use a logging library that writes to stderr or files.
### Quick Examples
```python theme={null}
import sys
import logging
# ❌ Bad (STDIO)
print("Processing request")
# ✅ Good (STDIO)
print("Processing request", file=sys.stderr)
# ✅ Good (STDIO)
logging.info("Processing request")
```
### System requirements
* Python 3.10 or higher installed.
* You must use the Python MCP SDK 1.2.0 or higher.
### Set up your environment
First, let's install `uv` and set up our Python project and environment:
<CodeGroup>
```bash macOS/Linux theme={null}
curl -LsSf https://astral.sh/uv/install.sh | sh
```
```powershell Windows theme={null}
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
```
</CodeGroup>
Make sure to restart your terminal afterwards to ensure that the `uv` command gets picked up.
Now, let's create and set up our project:
<CodeGroup>
```bash macOS/Linux theme={null}
# Create a new directory for our project
uv init weather
cd weather
# Create virtual environment and activate it
uv venv
source .venv/bin/activate
# Install dependencies
uv add "mcp[cli]" httpx
# Create our server file
touch weather.py
```
```powershell Windows theme={null}
# Create a new directory for our project
uv init weather
cd weather
# Create virtual environment and activate it
uv venv
.venv\Scripts\activate
# Install dependencies
uv add mcp[cli] httpx
# Create our server file
new-item weather.py
```
</CodeGroup>
Now let's dive into building your server.
## Building your server
### Importing packages and setting up the instance
Add these to the top of your `weather.py`:
```python theme={null}
from typing import Any
import httpx
from mcp.server.fastmcp import FastMCP
# Initialize FastMCP server
mcp = FastMCP("weather")
# Constants
NWS_API_BASE = "https://api.weather.gov"
USER_AGENT = "weather-app/1.0"
```
The FastMCP class uses Python type hints and docstrings to automatically generate tool definitions, making it easy to create and maintain MCP tools.
### Helper functions
Next, let's add our helper functions for querying and formatting the data from the National Weather Service API:
```python theme={null}
async def make_nws_request(url: str) -> dict[str, Any] | None:
"""Make a request to the NWS API with proper error handling."""
headers = {"User-Agent": USER_AGENT, "Accept": "application/geo+json"}
async with httpx.AsyncClient() as client:
try:
response = await client.get(url, headers=headers, timeout=30.0)
response.raise_for_status()
return response.json()
except Exception:
return None
def format_alert(feature: dict) -> str:
"""Format an alert feature into a readable string."""
props = feature["properties"]
return f"""
Event: {props.get("event", "Unknown")}
Area: {props.get("areaDesc", "Unknown")}
Severity: {props.get("severity", "Unknown")}
Description: {props.get("description", "No description available")}
Instructions: {props.get("instruction", "No specific instructions provided")}
"""
```
### Implementing tool execution
The tool execution handler is responsible for actually executing the logic of each tool. Let's add it:
```python theme={null}
@mcp.tool()
async def get_alerts(state: str) -> str:
"""Get weather alerts for a US state.
Args:
state: Two-letter US state code (e.g. CA, NY)
"""
url = f"{NWS_API_BASE}/alerts/active/area/{state}"
data = await make_nws_request(url)
if not data or "features" not in data:
return "Unable to fetch alerts or no alerts found."
if not data["features"]:
return "No active alerts for this state."
alerts = [format_alert(feature) for feature in data["features"]]
return "\n---\n".join(alerts)
@mcp.tool()
async def get_forecast(latitude: float, longitude: float) -> str:
"""Get weather forecast for a location.
Args:
latitude: Latitude of the location
longitude: Longitude of the location
"""
# First get the forecast grid endpoint
points_url = f"{NWS_API_BASE}/points/{latitude},{longitude}"
points_data = await make_nws_request(points_url)
if not points_data:
return "Unable to fetch forecast data for this location."
# Get the forecast URL from the points response
forecast_url = points_data["properties"]["forecast"]
forecast_data = await make_nws_request(forecast_url)
if not forecast_data:
return "Unable to fetch detailed forecast."
# Format the periods into a readable forecast
periods = forecast_data["properties"]["periods"]
forecasts = []
for period in periods[:5]: # Only show next 5 periods
forecast = f"""
{period["name"]}:
Temperature: {period["temperature"]}°{period["temperatureUnit"]}
Wind: {period["windSpeed"]} {period["windDirection"]}
Forecast: {period["detailedForecast"]}
"""
forecasts.append(forecast)
return "\n---\n".join(forecasts)
```
### Running the server
Finally, let's initialize and run the server:
```python theme={null}
def main():
# Initialize and run the server
mcp.run(transport="stdio")
if __name__ == "__main__":
main()
```
Your server is complete! Run `uv run weather.py` to start the MCP server, which will listen for messages from MCP hosts.
Let's now test your server from an existing MCP host, Claude for Desktop.
## Testing your server with Claude for Desktop
<Note>
Claude for Desktop is not yet available on Linux. Linux users can proceed to the [Building a client](/docs/2025-11-25/develop/build-client) tutorial to build an MCP client that connects to the server we just built.
</Note>
First, make sure you have Claude for Desktop installed. [You can install the latest version
here.](https://claude.ai/download) If you already have Claude for Desktop, **make sure it's updated to the latest version.**
We'll need to configure Claude for Desktop for whichever MCP servers you want to use. To do this, open your Claude for Desktop App configuration at `~/Library/Application Support/Claude/claude_desktop_config.json` in a text editor. Make sure to create the file if it doesn't exist.
For example, if you have [VS Code](https://code.visualstudio.com/) installed:
<CodeGroup>
```bash macOS/Linux theme={null}
code ~/Library/Application\ Support/Claude/claude_desktop_config.json
```
```powershell Windows theme={null}
code $env:AppData\Claude\claude_desktop_config.json
```
</CodeGroup>
You'll then add your servers in the `mcpServers` key. The MCP UI elements will only show up in Claude for Desktop if at least one server is properly configured.
In this case, we'll add our single weather server like so:
<CodeGroup>
```json macOS/Linux theme={null}
{
"mcpServers": {
"weather": {
"command": "uv",
"args": [
"--directory",
"/ABSOLUTE/PATH/TO/PARENT/FOLDER/weather",
"run",
"weather.py"
]
}
}
}
```
Cut at 300 lines. The page has the rest.
docs/2025-11-25/develop/build-with-agent-skills New page · 100 lines, new page
# Build with Agent Skills ## Available skills ## Start a build ## Deployment paths ## Next steps
A whole new page. There's nothing to diff it against, so here is what it says.
# Build with Agent Skills
> Use agent skills to guide AI coding assistants through MCP server design and implementation
[Agent skills](https://agentskills.io/home) are portable instruction sets that
give AI coding assistants domain knowledge for a task. For MCP development,
they encode the design decisions (deployment model, tool patterns, auth) so
your agent can interrogate your use case and scaffold a server that fits.
## Available skills
A reference set of MCP development skills is available as the
[`mcp-server-dev` plugin](https://github.com/anthropics/claude-plugins-official/tree/main/plugins/mcp-server-dev).
It provides three composing skills:
| Skill | Purpose |
| ------------------ | ----------------------------------------------------------------------------------------------------------------------- |
| `build-mcp-server` | Entry point. Interrogates the use case, picks a deployment model and tool-design pattern, routes to specialized skills. |
| `build-mcp-app` | Adds interactive UI widgets (forms, pickers, dashboards) rendered inline in chat. |
| `build-mcpb` | Packages a local stdio server with its runtime so users can install it without Node or Python. |
Each skill ships a `SKILL.md` file plus a `references/` folder of supporting
material (auth flows, tool-design patterns, widget templates, manifest schemas)
that the agent reads on demand. The files follow the open format and work with
any agent that implements the standard. For example, to install them in Claude
Code:
```bash theme={null}
/plugin marketplace add anthropics/claude-plugins-official
/plugin install mcp-server-dev
```
For other agents, check your skills or extensions catalog, or clone the
[skill directories](https://github.com/anthropics/claude-plugins-official/tree/main/plugins/mcp-server-dev/skills)
(`SKILL.md` plus `references/`) into your agent's skills location.
## Start a build
With the skills installed, ask your agent to help you build an MCP server. The
entry skill triggers on natural-language requests, or you can invoke it
directly using your agent's skill-invocation syntax.
The skill runs a short discovery phase before writing any code. Expect
questions about:
* **What it connects to** — a cloud API, a local process, the filesystem, hardware
* **Who will use it** — just you, your team, or anyone who installs it
* **Action surface size** — a handful of operations versus wrapping a large API
* **User interaction needs** — plain text results, structured input via
[elicitation](/specification/2025-11-25/client/elicitation), or rich UI widgets
* **Upstream auth** — API keys, OAuth 2.0, or none
If your opening message already covers these, the agent skips ahead to the
recommendation.
## Deployment paths
Based on discovery, the skill recommends one of four paths and scaffolds
accordingly:
**Remote [Streamable HTTP](/specification/2025-11-25/basic/transports#streamable-http)**
is the default for anything wrapping a cloud API. Zero install friction, one
deployment serves all users, and OAuth flows work properly because the server
can handle redirects and token storage. The reference skill includes scaffolds
for Cloudflare Workers and portable Express/FastMCP setups.
**[MCP apps](/extensions/apps/overview)** extend a server with interactive
widgets rendered in chat, such as searchable pickers, charts, and live
dashboards. The skill hands off to `build-mcp-app` when
[elicitation's](/specification/2025-11-25/client/elicitation) flat-form constraints
don't fit.
**[MCP Bundles (MCPB)](https://github.com/modelcontextprotocol/mcpb)** package a
local server together with its runtime as a single `.mcpb` archive, so users
can install it without setting up Node or Python. Use this path when the server
must touch the user's machine: reading local files, driving desktop apps, or
talking to localhost services. The skill hands off to `build-mcpb`.
**Local [stdio](/specification/2025-11-25/basic/transports#stdio)** remains available
for prototyping, with a noted upgrade path to MCPB when you're ready to
distribute.
## Next steps
Once your agent scaffolds the server, iterate on tool descriptions and error
handling, then test and ship:
<CardGroup cols={2}>
<Card title="MCP Inspector" icon="magnifying-glass" href="/docs/2025-11-25/tools/inspector">
Test your server's tools, resources, and prompts interactively
</Card>
<Card title="Connect to a client" icon="plug" href="/docs/2025-11-25/develop/connect-local-servers">
Wire your server into an MCP client via local or remote configuration
</Card>
<Card title="Publish to the Registry" icon="box" href="/registry/quickstart">
Make your server discoverable in the MCP Registry
</Card>
</CardGroup>
docs/2025-11-25/develop/clients/client-best-practices New page · 292 lines, new page
# Client Best Practices ## Progressive Tool Discovery ### When to Use Progressive Discovery ### Choosing a Discovery Strategy ### Using Progressive Discovery ### Dynamic Server Management ### Implementation Guidelines ### Interaction with Prompt Caching ## Programmatic Tool Calling / Code Mode ### How It Works ### Choosing a Sandbox ### Execution Architecture ### Security Considerations ### Error Handling ## Combining Both Patterns
A whole new page. There's nothing to diff it against, so here is what it says.
# Client Best Practices
> Patterns for scaling MCP host applications across many servers and tools.
As MCP host applications, such as agents, connect to more MCP servers and accumulate access to hundreds or thousands of tools, naive approaches to tool management break down. Loading every tool definition into the model's context window upfront wastes tokens, increases latency, and degrades model performance. Passing large intermediate results through the model between sequential tool calls compounds the problem.
Two patterns address these challenges: **progressive discovery**, which controls *when* tool definitions enter context, and **programmatic tool calling**, which controls *how* tools are invoked.
## Progressive Tool Discovery
Naive MCP host implementations pass the tool definitions of every connected server directly to the model at the start of each conversation. For a handful of tools, this is perfectly reasonable. But when a host has access to dozens of servers exposing hundreds of tools, those definitions alone can consume the majority of the context window before the model has even read the user's message.
<img src="https://mintcdn.com/mcp/JXfd5cBmEUh_qPUI/images/progressive-discovery.svg?fit=max&auto=format&n=JXfd5cBmEUh_qPUI&q=85&s=db39f47006107f04af43b5eeae2d6022" alt="Comparison of loading all tools upfront versus discovering tools on demand. The upfront approach consumes ~150,000 tokens on definitions alone, while progressive discovery uses ~2,000 tokens by loading only what the task requires." width="760" height="440" data-path="images/progressive-discovery.svg" />
Progressive discovery avoids this:
* The host fetches tool definitions via `tools/list` as normal, but defers injecting them into the model's context.
* The host provides a lightweight `search_tools` meta-tool to the model.
* The host loads full definitions into context only as needed.
### When to Use Progressive Discovery
Progressive discovery is best used when tool definitions take large parts of the context window. For a small
set of tools with tool definitions taking up a small part of the context window, loading all tools is fine.
Once the tool definitions take up a significant part of the available context window, clients should switch to progressive discovery. We recommend that clients implement thresholds to determine when to switch:
* Implement a threshold as a percentage of the context window. For example, 1%-5%.
* Load tool definitions. Once the threshold is reached, switch to progressive discovery.
### Choosing a Discovery Strategy
Once the model invokes the `search_tools` tool, we need to choose a search strategy:
* **Keyword-based**: Keyword matching (BM25, regex). Simple and effective, particularly for descriptive tool names and descriptions.
* **Embedding-based**: Vector-similarity retrieval over tool descriptions. Handles synonyms and semantic matching better.
* **Subagent-based**: A secondary model, often a small and fast model such as Claude Haiku or Gemini Flash, selects tools for the task. This usually works very well but can be more costly than embedding-based or keyword-based solutions.
* **Hybrid**: Combine approaches. For example, by scoring across keyword and embedding rankings, or choosing
different strategies depending on use-case or query.
Some model providers already offer built-in tool search. For example, [OpenAI](https://developers.openai.com/api/docs/guides/tools-tool-search) and [Anthropic](https://platform.claude.com/docs/en/agents-and-tools/tool-use/tool-search-tool) support this natively; check your provider's documentation for an equivalent. When available, you may prefer the platform's tool search over a custom implementation. Build your own when the provider doesn't offer one or when you need specialized retrieval logic (e.g., domain-specific ranking or access-control filtering).
The three-layer pattern below illustrates a custom search-based approach in detail, but the layered principle (catalog, inspect, execute) applies regardless of retrieval mechanism.
### Using Progressive Discovery
One common implementation for progressive discovery uses a search-based three-layer approach:
**Layer 1: Catalog.** The host exposes a small set of meta-tools for searching available capabilities. A `search_tools` tool accepts a natural-language query and returns matching tool names with brief descriptions.
```typescript theme={null}
// The model calls a lightweight search tool
search_tools({ query: "update salesforce record" })
// Returns concise matches: names and one-line descriptions only
→ [
{ name: "salesforce_updateRecord", description: "Update fields on a Salesforce object" },
{ name: "salesforce_upsertRecord", description: "Insert or update based on external ID" }
]
```
**Layer 2: Inspect.** Once the model identifies a candidate, it fetches the full definition (input schema, output schema, documentation) for that tool only.
```typescript theme={null}
// The model inspects only the tool it needs
get_tool_details({ name: "salesforce_updateRecord" });
```
This returns the complete schema for a single tool:
```json theme={null}
{
"name": "salesforce_updateRecord",
"description": "Updates a record in Salesforce",
"inputSchema": {
"type": "object",
"properties": {
"objectType": {
"type": "string",
"description": "Salesforce object type"
},
"recordId": { "type": "string", "description": "Record ID to update" },
"data": { "type": "object", "description": "Fields to update" }
},
"required": ["objectType", "recordId", "data"]
}
}
```
**Layer 3: Execute.** The model calls the tool with full knowledge of its interface, having loaded only the definitions it needed.
This pattern reduces token usage dramatically and can improve tool selection accuracy: the model focuses on a few relevant tools rather than scanning hundreds of irrelevant ones. Other discovery strategies (embeddings, subagents, etc.) follow the same layered principle but substitute different retrieval mechanisms in the catalog layer.
### Dynamic Server Management
Progressive discovery extends beyond individual tools to entire servers. Rather than connecting to every configured server at startup, a host can:
1. Maintain a registry of available servers and their high-level descriptions.
2. Connect to a server only when the model determines it needs that server's capabilities.
3. Disconnect servers that are no longer relevant to the current task, freeing context.
```mermaid theme={null}
sequenceDiagram
participant Model
participant Host
participant Registry
participant Server
Model->>Host: search_available_servers("CRM")
Host->>Registry: Query available servers
Registry-->>Host: Salesforce server (not connected)
Host-->>Model: Salesforce server available
Model->>Host: enable_server("salesforce")
Host->>Server: Initialize connection
Server-->>Host: Server capabilities + tools
Host-->>Model: Salesforce server connected
Note over Model: Task complete
Model->>Host: disable_server("salesforce")
Host->>Server: Close connection
Host-->>Model: Server disconnected, context freed
```
This works especially well for general-purpose agents, where the user's intent isn't known upfront. The agent starts with a minimal set of always-on servers and connects others as needed. Combined with [agent skills](/docs/2025-11-25/develop/build-with-agent-skills), a skill file can declare which MCP servers it needs, and the host connects them only when that skill is invoked.
### Implementation Guidelines
When implementing progressive discovery:
| Guideline | Rationale |
| -------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Offer multiple detail levels** | Let the model choose between name-only, name-and-description, or full-schema responses. |
| **Cache tool definitions** | Once fetched from a server, memoize the definition host-side so re-injecting it later doesn't need another `tools/list` round trip. This is separate from what's currently in the model's context. |
| **Refresh on `list_changed`** | Re-index the search catalog when a server sends `notifications/tools/list_changed`. |
| **Group tools by server** | Present tools organized by their source server so the model can reason about related capabilities. |
### Interaction with Prompt Caching
Most providers cache the prompt prefix, including the `tools` array. Adding or removing tool
definitions mid-conversation invalidates that cache, and the resulting miss can cost more tokens
than the definitions you removed. To preserve caching:
* Append newly discovered definitions after the cache breakpoint rather than re-sorting the
`tools` array, or route every call through a single stable `call_tool({name, args})` meta-tool
so the array never changes.
* Treat server disconnection as a conversation-boundary operation rather than a per-turn one.
* Consult your provider's caching documentation alongside the tool-search links above.
## Programmatic Tool Calling / Code Mode
With direct tool calling, every tool invocation is a round trip: the model generates a tool call, the client executes it, and the full result flows back into the model's context. When a task requires chaining multiple tools (read a document, transform it, write it somewhere else), each intermediate result passes through the model, consuming tokens and adding latency even when it has nothing to do with them.
Programmatic tool calling (sometimes called "code mode") provides a way for clients to **compose tool calls** effectively. Instead of calling tools directly, the model writes code that calls tools. The code executes in a sandboxed environment, and only the final result returns to the model.
Programmatic tool calling is powerful and allows for more efficient use of MCP tools and resources, but requires
clients to implement a sandbox environment.
<img src="https://mintcdn.com/mcp/JXfd5cBmEUh_qPUI/images/programmatic-tool-calling.svg?fit=max&auto=format&n=JXfd5cBmEUh_qPUI&q=85&s=a2be82d097bb7cd7c7fd415918b1571d" alt="Comparison of direct tool calling versus programmatic tool calling. Direct calling passes every intermediate result through the model (~100K+ tokens). Programmatic calling sends a ~200-token script to a sandbox, which executes the tool calls and returns a ~15-token summary." width="900" height="900" data-path="images/programmatic-tool-calling.svg" />
### How It Works
The host converts MCP tool schemas into a typed API available inside a sandbox. When the model needs tools, it writes a script and executes it.
**Step 1: Generate a programmatic API from MCP schemas.** The host reads each server's tool definitions and produces typed functions based on each tool's arguments and `outputSchema`:
```typescript theme={null}
// Auto-generated from the Logging MCP server's tool schema
interface LogEntry {
timestamp: string;
message: string;
level: string;
}
function logging_getLogs(input: {
level: "error" | "warn" | "info";
since: number;
}): Promise<{ entries: LogEntry[] }> {
return mcp.callTool<{ entries: LogEntry[] }>("logging_getLogs", input);
}
// Auto-generated from the Ticketing MCP server's tool schema
function ticketing_createIssue(input: {
title: string;
body?: string;
priority: "low" | "medium" | "high";
}): Promise<{ issueId: string }> {
return mcp.callTool<{ issueId: string }>("ticketing_createIssue", input);
}
```
MCP Servers can provide an optional [`outputSchema`](/specification/2025-11-25/server/tools#output-schema) for each tool. When an output schema is present, the host can produce precise return types (like `LogEntry` above).
When an output schema is absent, prefer the simple path:
* **Use a generic type and move on.** Accept `any` or `string` and handle the unstructured output downstream. The real fix is for server authors to provide `outputSchema`.
* **Extract a typed result using a fast model**, for single-shot calls outside loops. Expose a host-brokered `extract(value, ExpectedType)` helper through the same stub-interception path as MCP tool calls so the sandbox itself never opens a network connection. The helper routes to a small model (for example, Claude Haiku or Gemini Flash) to coerce the value into `ExpectedType`. This adds per-call latency and can hallucinate or drop fields, so validate the result against `ExpectedType` before use.
**Step 2: The model writes code against these APIs.** Rather than making separate tool calls with full results flowing through context between them, the model writes a single script. Consider a task like "find all error logs from the past hour and file a ticket for each unique error." With direct tool calling, thousands of log entries would flow through the model's context. With code, the model filters in the sandbox:
```typescript theme={null}
// Model-generated code, executes in sandbox
const logs = await logging_getLogs({
level: "error",
since: Date.now() - 3600000,
});
// Filter and deduplicate inside the sandbox, not in the model's context
const uniqueErrors = new Map<string, LogEntry>();
for (const log of logs.entries) {
if (!uniqueErrors.has(log.message)) {
uniqueErrors.set(log.message, log);
}
}
for (const [message, log] of uniqueErrors) {
await ticketing_createIssue({
title: `Error: ${message}`,
body: `First seen: ${log.timestamp}\nOccurrences: ${
logs.entries.filter((l) => l.message === message).length
}`,
priority: "high",
});
}
console.log(
`Filed ${uniqueErrors.size} tickets from ${logs.entries.length} error logs`,
);
```
**Step 3: The sandbox executes the code.** Function calls inside the sandbox are intercepted and routed back to the appropriate MCP server through the host broker. The log data and ticket creation flow directly between servers without ever entering the model's context. Only the `console.log` output, a single summary line, returns to the model.
### Choosing a Sandbox
The right sandbox depends on the language you want the model to write, your host application's language, and how much isolation you need. The table lists example runtimes rather than endorsements; evaluate maturity for your use case:
| Sandboxed language | Runtime / Library | Host language | Approach |
| ------------------ | ------------------------------------------------------------- | ----------------- | ----------------------------------------------------------------------------------------------- |
| **JavaScript** | [Deno](https://github.com/denoland/deno), `isolated-vm` | Rust / Node / CLI | V8-based runtimes with fine-grained permissions. Can disable all permissions for full lockdown. |
| **Python** | [Monty](https://github.com/pydantic/monty) *(experimental)* | Rust | Minimal Python interpreter built for AI use cases. No I/O by default. |
| **TypeScript** | [pctx](https://github.com/portofcontext/pctx) *(early-stage)* | Python / Rust | Incorporates code mode concepts as a library, with low-level Rust support. |
| **Any (via Wasm)** | [Wasmtime](https://github.com/bytecodealliance/wasmtime) | Rust / C / Go | Compile any language to Wasm and run it with capability-based security. |
Regardless of sandbox, the integration pattern is the same: the host injects function stubs, intercepts calls over an in-process or stdio channel (so network permissions can stay fully denied), and dispatches them as `tools/call` requests to MCP servers.
### Execution Architecture
The implementation has three components:
```mermaid theme={null}
flowchart LR
subgraph Host["MCP Host"]
A[LLM] -->|writes code| B[Sandbox]
B -->|function call| C[MCP Client]
C -->|return value| B
B -->|console output| A
end
C -->|tool call| D[MCP Server A]
C -->|tool call| E[MCP Server B]
D -->|result| C
E -->|result| C
```
**The sandbox** runs model-generated code in an isolated environment with no direct network access. Its only interface to the outside world is through the generated function stubs, which route calls back to the host.
**The host** acts as a broker. It receives function calls from the sandbox, maps them to the correct MCP server, executes the tool call, and returns the result to the sandbox. Authorization tokens and credentials are held by the host and never exposed to the generated code.
**The model** sees only what the sandbox returns, typically the output of `console.log` statements or a final return value. This gives the model (and the client developer) precise control over what enters the context window.
### Security Considerations
Programmatic tool calling introduces a code execution surface that requires careful sandboxing:
* **Per-call authorization**: The broker is still the MCP host for spec purposes. Apply the same human-in-the-loop confirmation policy to sandbox-originated calls that you apply to direct calls (see [Tools: Security](/specification/2025-11-25/server/tools#security-considerations)). Approving the script does not grant blanket approval for every tool call it makes at runtime; hosts may grant categorical approval (for example, "allow `ticketing_createIssue` for this script run") rather than prompting per iteration, but the broker must still evaluate each call against that grant.
* **Cross-server data flow**: Tool results from one server are untrusted input to another. The broker should apply the same input-review policy to brokered calls as to direct ones; output truncation alone does not prevent exfiltration.
* **Network isolation**: The sandbox should have no direct network access. All external communication flows through the host broker, which enforces authorization and access control.
* **No credential exposure**: API keys and tokens are held by the host. The generated code calls typed functions; the host adds authentication when forwarding to servers.
* **Resource limits**: Set timeouts and memory limits on sandbox execution to prevent runaway scripts.
* **Output filtering**: Validate and truncate sandbox console output before feeding it back to the model.
### Error Handling
MCP tool errors arrive as a successful response with
[`isError: true`](/specification/2025-11-25/server/tools#error-handling) rather than a transport
failure. Generated wrappers should convert this into a thrown exception so model-authored code
can use `try`/`catch`. If an uncaught error terminates the script, surface it as the script's
result so the model can self-correct; the model is responsible for reporting any partial side
effects already committed.
## Combining Both Patterns
Progressive discovery and programmatic tool calling work well together. The model uses discovery tools to identify which tools it needs, loads their schemas, and then writes a single script that calls multiple tools in one execution pass. This combination minimizes both the token cost of tool definitions *and* the token cost of tool results, keeping the model's context focused on reasoning rather than passing data through it.
docs/2025-11-25/develop/connect-local-servers New page · 283 lines, new page
# Connect to local MCP servers ## Prerequisites ### Claude Desktop ### Node.js ## Understanding MCP Servers ## Installing the Filesystem Server ## Using the Filesystem Server ### File Management Examples ### How Approval Works ## Troubleshooting ## Next Steps
A whole new page. There's nothing to diff it against, so here is what it says.
# Connect to local MCP servers
> Learn how to extend Claude Desktop with local MCP servers to enable file system access and other powerful integrations
Model Context Protocol (MCP) servers extend AI applications' capabilities by providing secure, controlled access to local resources and tools. Many clients support MCP, enabling diverse integration possibilities across different platforms and applications.
This guide demonstrates how to connect to local MCP servers using Claude Desktop as an example, one of the many clients that support MCP. While we focus on Claude Desktop's implementation, the concepts apply broadly to other MCP-compatible clients. By the end of this tutorial, Claude will be able to interact with files on your computer, create new documents, organize folders, and search through your file system—all with your explicit permission for each action.
<Frame>
<img src="https://mintcdn.com/mcp/4ZXF1PrDkEaJvXpn/images/quickstart-filesystem.png?fit=max&auto=format&n=4ZXF1PrDkEaJvXpn&q=85&s=629d7e754dc358d71a408d6ce970c1b1" alt="Claude Desktop with filesystem integration showing file management capabilities" width="1732" height="2060" data-path="images/quickstart-filesystem.png" />
</Frame>
## Prerequisites
Before starting this tutorial, ensure you have the following installed on your system:
### Claude Desktop
Download and install [Claude Desktop](https://claude.ai/download) for your operating system. Claude Desktop is available for macOS and Windows.
If you already have Claude Desktop installed, verify you're running the latest version by clicking the Claude menu and selecting "Check for Updates..."
### Node.js
The Filesystem Server and many other MCP servers require Node.js to run. Verify your Node.js installation by opening a terminal or command prompt and running:
```bash theme={null}
node --version
```
If Node.js is not installed, download it from [nodejs.org](https://nodejs.org/). We recommend the LTS (Long Term Support) version for stability.
## Understanding MCP Servers
MCP servers are programs that run on your computer and provide specific capabilities to Claude Desktop through a standardized protocol. Each server exposes tools that Claude can use to perform actions, with your approval. The Filesystem Server we'll install provides tools for:
* Reading file contents and directory structures
* Creating new files and directories
* Moving and renaming files
* Searching for files by name or content
All actions require your explicit approval before execution, ensuring you maintain full control over what Claude can access and modify.
## Installing the Filesystem Server
The process involves configuring Claude Desktop to automatically start the Filesystem Server whenever you launch the application. This configuration is done through a JSON file that tells Claude Desktop which servers to run and how to connect to them.
<Steps>
<Step title="Open Claude Desktop Settings">
Start by accessing the Claude Desktop settings. Click on the Claude menu in your system's menu bar (not the settings within the Claude window itself) and select "Settings..."
On macOS, this appears in the top menu bar:
<Frame style={{ textAlign: "center" }}>
<img src="https://mintcdn.com/mcp/4ZXF1PrDkEaJvXpn/images/quickstart-menu.png?fit=max&auto=format&n=4ZXF1PrDkEaJvXpn&q=85&s=0c8b57e0e17af3624b6762a3ea944c8e" width="400" alt="Claude Desktop menu showing Settings option" data-path="images/quickstart-menu.png" />
</Frame>
This opens the Claude Desktop configuration window, which is separate from your Claude account settings.
</Step>
<Step title="Access Developer Settings">
In the Settings window, navigate to the "Developer" tab in the left sidebar. This section contains options for configuring MCP servers and other developer features.
Click the "Edit Config" button to open the configuration file:
<Frame>
<img src="https://mintcdn.com/mcp/4ZXF1PrDkEaJvXpn/images/quickstart-developer.png?fit=max&auto=format&n=4ZXF1PrDkEaJvXpn&q=85&s=0fb595490a2f9e15c0301e771a57446c" alt="Developer settings showing Edit Config button" width="1688" height="534" data-path="images/quickstart-developer.png" />
</Frame>
This action creates a new configuration file if one doesn't exist, or opens your existing configuration. The file is located at:
* **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
* **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
</Step>
<Step title="Configure the Filesystem Server">
Replace the contents of the configuration file with the following JSON structure. This configuration tells Claude Desktop to start the Filesystem Server with access to specific directories:
<CodeGroup>
```json macOS theme={null}
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"/Users/username/Desktop",
"/Users/username/Downloads"
]
}
}
}
```
```json Windows theme={null}
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"C:\\Users\\username\\Desktop",
"C:\\Users\\username\\Downloads"
]
}
}
}
```
</CodeGroup>
Replace `username` with your actual computer username. The paths listed in the `args` array specify which directories the Filesystem Server can access. You can modify these paths or add additional directories as needed.
<Tip>
**Understanding the Configuration**
* `"filesystem"`: A friendly name for the server that appears in Claude Desktop
* `"command": "npx"`: Uses Node.js's npx tool to run the server
* `"-y"`: Automatically confirms the installation of the server package
* `"@modelcontextprotocol/server-filesystem"`: The package name of the Filesystem Server
* The remaining arguments: Directories the server is allowed to access
</Tip>
<Warning>
**Security Consideration**
Only grant access to directories you're comfortable with Claude reading and modifying. The server runs with your user account permissions, so it can perform any file operations you can perform manually.
</Warning>
</Step>
<Step title="Restart Claude Desktop">
After saving the configuration file, completely quit Claude Desktop and restart it. The application needs to restart to load the new configuration and start the MCP server.
Upon successful restart, click the "Add files, connectors and more" indicator <img src="https://mintcdn.com/mcp/cpXzQjUOzyH0mCNH/images/claude-add-files-connectors-and-more.png?fit=max&auto=format&n=cpXzQjUOzyH0mCNH&q=85&s=53acf21f6807dd5323b70b84b5d98d8a" style={{display: 'inline', margin: 0, height: '1.3em'}} width="33" height="33" data-path="images/claude-add-files-connectors-and-more.png" /> in the bottom-left corner of the conversation input box:
<Frame>
<img src="https://mintcdn.com/mcp/akpggzunDlIcY2im/images/quickstart-slider.png?fit=max&auto=format&n=akpggzunDlIcY2im&q=85&s=a1ebd4259cff2a7472171885f2edc035" alt="Claude Desktop interface showing MCP server indicator" width="1414" height="410" data-path="images/quickstart-slider.png" />
</Frame>
Click on this indicator, then scroll over "Connectors" and click "Manage connectors". Select "filesystem" from the connector list to view the the Filesystem Server's available tools:
<Frame style={{ textAlign: "center" }}>
<img src="https://mintcdn.com/mcp/cpXzQjUOzyH0mCNH/images/quickstart-tools.png?fit=max&auto=format&n=cpXzQjUOzyH0mCNH&q=85&s=212a63d76daba170d52db0d2f6f582be" width="400" alt="Available filesystem tools in Claude Desktop" data-path="images/quickstart-tools.png" />
</Frame>
If the Filesystem Server doesn't connect, refer to the [Troubleshooting](#troubleshooting) section for debugging steps.
</Step>
</Steps>
## Using the Filesystem Server
With the Filesystem Server connected, Claude can now interact with your file system. Try these example requests to explore the capabilities:
### File Management Examples
* **"Can you write a poem and save it to my desktop?"** - Claude will compose a poem and create a new text file on your desktop
* **"What work-related files are in my downloads folder?"** - Claude will scan your downloads and identify work-related documents
* **"Please organize all images on my desktop into a new folder called 'Images'"** - Claude will create a folder and move image files into it
### How Approval Works
Before executing any file system operation, Claude will request your approval. This ensures you maintain control over all actions:
<Frame style={{ textAlign: "center" }}>
<img src="https://mintcdn.com/mcp/4ZXF1PrDkEaJvXpn/images/quickstart-approve.png?fit=max&auto=format&n=4ZXF1PrDkEaJvXpn&q=85&s=98cc6e9dfe885fbd6e9bfae40601e494" width="500" alt="Claude requesting approval to perform a file operation" data-path="images/quickstart-approve.png" />
</Frame>
Review each request carefully before approving. You can always deny a request if you're not comfortable with the proposed action.
## Troubleshooting
If you encounter issues setting up or using the Filesystem Server, these solutions address common problems:
<AccordionGroup>
<Accordion title="Server not showing up in Claude / hammer icon missing">
1. Restart Claude Desktop completely
2. Check your `claude_desktop_config.json` file syntax
3. Make sure the file paths included in `claude_desktop_config.json` are valid and that they are absolute and not relative
4. Look at [logs](#getting-logs-from-claude-for-desktop) to see why the server is not connecting
5. In your command line, try manually running the server (replacing `username` as you did in `claude_desktop_config.json`) to see if you get any errors:
<CodeGroup>
```bash macOS/Linux theme={null}
npx -y @modelcontextprotocol/server-filesystem /Users/username/Desktop /Users/username/Downloads
```
```powershell Windows theme={null}
npx -y @modelcontextprotocol/server-filesystem C:\Users\username\Desktop C:\Users\username\Downloads
```
</CodeGroup>
</Accordion>
<Accordion title="Getting logs from Claude Desktop">
Claude.app logging related to MCP is written to log files in:
* macOS: `~/Library/Logs/Claude`
* Windows: `%APPDATA%\Claude\logs`
* `mcp.log` will contain general logging about MCP connections and connection failures.
* Files named `mcp-server-SERVERNAME.log` will contain error (stderr) logging from the named server.
You can run the following command to list recent logs and follow along with any new ones (on Windows, it will only show recent logs):
<CodeGroup>
```bash macOS/Linux theme={null}
tail -n 20 -f ~/Library/Logs/Claude/mcp*.log
```
```powershell Windows theme={null}
type "%APPDATA%\Claude\logs\mcp*.log"
```
</CodeGroup>
</Accordion>
<Accordion title="Tool calls failing silently">
If Claude attempts to use the tools but they fail:
1. Check Claude's logs for errors
2. Verify your server builds and runs without errors
3. Try restarting Claude Desktop
</Accordion>
<Accordion title="None of this is working. What do I do?">
Please refer to our [debugging guide](/docs/2025-11-25/tools/debugging) for better debugging tools and more detailed guidance.
</Accordion>
<Accordion title="ENOENT error and `${APPDATA}` in paths on Windows">
If your configured server fails to load, and you see within its logs an error referring to `${APPDATA}` within a path, you may need to add the expanded value of `%APPDATA%` to your `env` key in `claude_desktop_config.json`:
```json theme={null}
{
"brave-search": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-brave-search"],
"env": {
"APPDATA": "C:\\Users\\user\\AppData\\Roaming\\",
"BRAVE_API_KEY": "..."
}
}
}
```
With this change in place, launch Claude Desktop once again.
<Warning>
**npm should be installed globally**
The `npx` command may continue to fail if you have not installed npm globally. If npm is already installed globally, you will find `%APPDATA%\npm` exists on your system. If not, you can install npm globally by running the following command:
```bash theme={null}
npm install -g npm
```
</Warning>
</Accordion>
</AccordionGroup>
## Next Steps
Now that you've successfully connected Claude Desktop to a local MCP server, explore these options to expand your setup:
<CardGroup cols={2}>
<Card title="Explore other servers" icon="grid" href="https://github.com/modelcontextprotocol/servers">
Browse our collection of official and community-created MCP servers for
additional capabilities
</Card>
<Card title="Build your own server" icon="code" href="/docs/2025-11-25/develop/build-server">
Create custom MCP servers tailored to your specific workflows and
integrations
</Card>
<Card title="Connect to remote servers" icon="cloud" href="/docs/2025-11-25/develop/connect-remote-servers">
Learn how to connect Claude to remote MCP servers for cloud-based tools and
services
</Card>
<Card title="Understand the protocol" icon="book" href="/docs/2025-11-25/learn/architecture">
Dive deeper into how MCP works and its architecture
</Card>
</CardGroup>
docs/2025-11-25/develop/connect-remote-servers New page · 118 lines, new page
# Connect to remote MCP Servers ## Understanding Remote MCP Servers ## What are Custom Connectors? ## Connecting to a Remote MCP Server ## Best Practices for Using Remote MCP Servers ## Next Steps
A whole new page. There's nothing to diff it against, so here is what it says.
# Connect to remote MCP Servers
> Learn how to connect Claude to remote MCP servers and extend its capabilities with internet-hosted tools and data sources
Remote MCP servers extend AI applications' capabilities beyond your local environment, providing access to internet-hosted tools, services, and data sources. By connecting to remote MCP servers, you transform AI assistants from helpful tools into informed teammates capable of handling complex, multi-step projects with real-time access to external resources.
Many clients now support remote MCP servers, enabling a wide range of integration possibilities. This guide demonstrates how to connect to remote MCP servers using [Claude](https://claude.ai/) as an example, one of the many clients that support MCP. While we focus on Claude's implementation through Custom Connectors, the concepts apply broadly to other MCP-compatible clients.
## Understanding Remote MCP Servers
Remote MCP servers function similarly to local MCP servers but are hosted on the internet rather than your local machine. They expose tools, prompts, and resources that Claude can use to perform tasks on your behalf. These servers can integrate with various services such as project management tools, documentation systems, code repositories, and any other API-enabled service.
The key advantage of remote MCP servers is their accessibility. Unlike local servers that require installation and configuration on each device, remote servers are available from any MCP client with an internet connection. This makes them ideal for web-based AI applications, integrations that emphasize ease of use, and services that require server-side processing or authentication.
## What are Custom Connectors?
Custom Connectors serve as the bridge between Claude and remote MCP servers. They allow you to connect Claude directly to the tools and data sources that matter most to your workflows, enabling Claude to operate within your favorite software and draw insights from the complete context of your external tools.
With Custom Connectors, you can:
* [Connect Claude to existing remote MCP servers](https://support.anthropic.com/en/articles/11175166-getting-started-with-custom-connectors-using-remote-mcp) provided by third-party developers
* [Build your own remote MCP servers to connect with any tool](https://support.anthropic.com/en/articles/11503834-building-custom-connectors-via-remote-mcp-servers)
## Connecting to a Remote MCP Server
The process of connecting Claude to a remote MCP server involves adding a Custom Connector through the [Claude interface](https://claude.ai/). This establishes a secure connection between Claude and your chosen remote server.
<Steps>
<Step title="Navigate to Connector Settings">
Open Claude in your browser and navigate to the settings page. You can access this by clicking on your profile icon and selecting "Settings" from the dropdown menu. Once in settings, locate and click on the "Connectors" section in the sidebar.
This will display your currently configured connectors and provide options to add new ones.
</Step>
<Step title="Add a Custom Connector">
In the Connectors section, scroll to the bottom where you'll find the "Add custom connector" button. Click this button to begin the connection process.
<Frame>
<img src="https://mintcdn.com/mcp/4ZXF1PrDkEaJvXpn/images/quickstart-remote/1-add-connector.png?fit=max&auto=format&n=4ZXF1PrDkEaJvXpn&q=85&s=b5ae9b23164875bbaa3aff4c178cdc64" alt="Add custom connector button in Claude settings" width="1038" height="809" data-path="images/quickstart-remote/1-add-connector.png" />
</Frame>
A dialog will appear prompting you to enter the remote MCP server URL. This URL should be provided by the server developer or administrator. Enter the complete URL, ensuring it includes the proper protocol (https\://) and any necessary path components.
<Frame>
<img src="https://mintcdn.com/mcp/4ZXF1PrDkEaJvXpn/images/quickstart-remote/2-connect.png?fit=max&auto=format&n=4ZXF1PrDkEaJvXpn&q=85&s=0934f16d8e016cade8e560c8f89d011b" alt="Dialog for entering remote MCP server URL" width="1616" height="282" data-path="images/quickstart-remote/2-connect.png" />
</Frame>
After entering the URL, click "Add" to proceed with the connection.
</Step>
<Step title="Complete Authentication">
Most remote MCP servers require authentication to ensure secure access to their resources. The authentication process varies depending on the server implementation but commonly involves OAuth, API keys, or username/password combinations.
<Frame>
<img src="https://mintcdn.com/mcp/4ZXF1PrDkEaJvXpn/images/quickstart-remote/3-auth.png?fit=max&auto=format&n=4ZXF1PrDkEaJvXpn&q=85&s=89af6e1b85718637231388697cc7b015" alt="Authentication screen for remote MCP server" width="490" height="806" data-path="images/quickstart-remote/3-auth.png" />
</Frame>
Follow the authentication prompts provided by the server. This may redirect you to a third-party authentication provider or display a form within Claude. Once authentication is complete, Claude will establish a secure connection to the remote server.
</Step>
<Step title="Access Resources and Prompts">
After successful connection, the remote server's resources and prompts become available in your Claude conversations. You can access these by clicking the paperclip icon in the message input area, which opens the attachment menu.
<Frame>
<img src="https://mintcdn.com/mcp/cpXzQjUOzyH0mCNH/images/quickstart-remote/4-select-resources-menu.png?fit=max&auto=format&n=cpXzQjUOzyH0mCNH&q=85&s=e5fa85174f8acbadbd709bac66f42d5c" alt="Attachment menu showing available resources" width="735" height="378" data-path="images/quickstart-remote/4-select-resources-menu.png" />
</Frame>
The menu displays all available resources and prompts from your connected servers. Select the items you want to include in your conversation. These resources provide Claude with context and information from your external tools.
<Frame>
<img src="https://mintcdn.com/mcp/cpXzQjUOzyH0mCNH/images/quickstart-remote/5-select-prompts-resources.png?fit=max&auto=format&n=cpXzQjUOzyH0mCNH&q=85&s=68722669d9e18252756885c703e4f221" alt="Selecting specific resources and prompts from the menu" width="648" height="529" data-path="images/quickstart-remote/5-select-prompts-resources.png" />
</Frame>
</Step>
<Step title="Configure Tool Permissions">
Remote MCP servers often expose multiple tools with varying capabilities. You can control which tools Claude is allowed to use by configuring permissions in the connector settings. This ensures Claude only performs actions you've explicitly authorized.
<Frame>
<img src="https://mintcdn.com/mcp/cpXzQjUOzyH0mCNH/images/quickstart-remote/6-configure-tools.png?fit=max&auto=format&n=cpXzQjUOzyH0mCNH&q=85&s=5cfd8b2c5d06e7e3699eac24c68d090e" alt="Tool permission configuration interface" width="604" height="745" data-path="images/quickstart-remote/6-configure-tools.png" />
</Frame>
Navigate back to the Connectors settings and click on your connected server. Here you can enable or disable specific tools, set usage limits, and configure other security parameters according to your needs.
</Step>
</Steps>
## Best Practices for Using Remote MCP Servers
When working with remote MCP servers, consider these recommendations to ensure a secure and efficient experience:
**Security considerations**: Always verify the authenticity of remote MCP servers before connecting. Only connect to servers from trusted sources, and review the permissions requested during authentication. Be cautious about granting access to sensitive data or systems.
**Managing multiple connectors**: You can connect to multiple remote MCP servers simultaneously. Organize your connectors by purpose or project to maintain clarity. Regularly review and remove connectors you no longer use to keep your workspace organized and secure.
## Next Steps
Now that you've connected Claude to a remote MCP server, you can explore its capabilities in your conversations. Try using the connected tools to automate tasks, access external data, or integrate with your existing workflows.
<CardGroup cols={2}>
<Card title="Build your own remote server" icon="cloud" href="https://support.anthropic.com/en/articles/11503834-building-custom-connectors-via-remote-mcp-servers">
Create custom remote MCP servers to integrate with proprietary tools and
services
</Card>
<Card title="Explore available servers" icon="grid" href="https://github.com/modelcontextprotocol/servers">
Browse our collection of official and community-created MCP servers
</Card>
<Card title="Connect local servers" icon="computer" href="/docs/2025-11-25/develop/connect-local-servers">
Learn how to connect Claude Desktop to local MCP servers for direct system
access
</Card>
<Card title="Understand the architecture" icon="book" href="/docs/2025-11-25/learn/architecture">
Dive deeper into how MCP works and its architecture
</Card>
</CardGroup>
Remote MCP servers unlock powerful possibilities for extending Claude's capabilities. As you become familiar with these integrations, you'll discover new ways to streamline your workflows and accomplish complex tasks more efficiently.
docs/2025-11-25/getting-started/intro New page · 54 lines, new page
# What is the Model Context Protocol (MCP)? ## What can MCP enable? ## Why does MCP matter? ## Broad ecosystem support ## Start Building ## Learn more
A whole new page. There's nothing to diff it against, so here is what it says.
# What is the Model Context Protocol (MCP)?
MCP (Model Context Protocol) is an open-source standard for connecting AI applications to external systems.
Using MCP, AI applications like Claude or ChatGPT can connect to data sources (e.g. local files, databases), tools (e.g. search engines, calculators) and workflows (e.g. specialized prompts)—enabling them to access key information and perform tasks.
Think of MCP like a USB-C port for AI applications. Just as USB-C provides a standardized way to connect electronic devices, MCP provides a standardized way to connect AI applications to external systems.
<Frame>
<img src="https://mintcdn.com/mcp/bEUxYpZqie0DsluH/images/mcp-simple-diagram.png?fit=max&auto=format&n=bEUxYpZqie0DsluH&q=85&s=35268aa0ad50b8c385913810e7604550" width="3840" height="1500" data-path="images/mcp-simple-diagram.png" />
</Frame>
## What can MCP enable?
* Agents can access your Google Calendar and Notion, acting as a more personalized AI assistant.
* Claude Code can generate an entire web app using a Figma design.
* Enterprise chatbots can connect to multiple databases across an organization, empowering users to analyze data using chat.
* AI models can create 3D designs on Blender and print them out using a 3D printer.
## Why does MCP matter?
Depending on where you sit in the ecosystem, MCP can have a range of benefits.
* **Developers**: MCP reduces development time and complexity when building, or integrating with, an AI application or agent.
* **AI applications or agents**: MCP gives them access to an ecosystem of data sources, tools and apps, which enhances their capabilities and improves the end-user experience.
* **End-users**: MCP results in more capable AI applications or agents that can access user data and take actions on the user's behalf when necessary.
## Broad ecosystem support
MCP is an open protocol supported across a wide range of clients and servers. AI assistants like [Claude](https://claude.com/docs/connectors/building) and [ChatGPT](https://developers.openai.com/api/docs/mcp/), development tools like [Visual Studio Code](https://code.visualstudio.com/docs/copilot/chat/mcp-servers), [Cursor](https://cursor.com/docs/context/mcp), [MCPJam](https://docs.mcpjam.com/getting-started), and many others all support MCP — making it easy to build once and integrate everywhere.
## Start Building
<CardGroup cols={2}>
<Card title="Build servers" icon="server" href="/docs/2025-11-25/develop/build-server">
Create MCP servers to expose your data and tools
</Card>
<Card title="Build clients" icon="computer" href="/docs/2025-11-25/develop/build-client">
Develop applications that connect to MCP servers
</Card>
<Card title="Build MCP Apps" icon="puzzle-piece" href="/extensions/apps/overview">
Build interactive apps that run inside AI clients
</Card>
</CardGroup>
## Learn more
<CardGroup cols={2}>
<Card title="Understand concepts" icon="book" href="/docs/2025-11-25/learn/architecture">
Learn the core concepts and architecture of MCP
</Card>
</CardGroup>
docs/2025-11-25/learn/architecture New page · 460 lines, new page
# Architecture overview ## Scope ## Concepts of MCP ### Participants ### Layers #### Data layer #### Transport layer ### Data Layer Protocol #### Lifecycle management #### Primitives #### Notifications ## Example ### Data Layer
A whole new page. There's nothing to diff it against, so here is what it says.
# Architecture overview
This overview of the Model Context Protocol (MCP) discusses its [scope](#scope) and [core concepts](#concepts-of-mcp), and provides an [example](#example) demonstrating each core concept.
Because MCP SDKs abstract away many concerns, most developers will likely find the [data layer protocol](#data-layer-protocol) section to be the most useful. It discusses how MCP servers can provide context to an AI application.
For specific implementation details, please refer to the documentation for your [language-specific SDK](/docs/2025-11-25/sdk).
## Scope
The Model Context Protocol includes the following projects:
* [MCP Specification](https://modelcontextprotocol.io/specification/latest): A specification of MCP that outlines the implementation requirements for clients and servers.
* [MCP SDKs](/docs/2025-11-25/sdk): SDKs for different programming languages that implement MCP.
* **MCP Development Tools**: Tools for developing MCP servers and clients, including the [MCP Inspector](https://github.com/modelcontextprotocol/inspector)
* [MCP Reference Server Implementations](https://github.com/modelcontextprotocol/servers): Reference implementations of MCP servers.
<Note>
MCP focuses solely on the protocol for context exchange—it does not dictate
how AI applications use LLMs or manage the provided context.
</Note>
## Concepts of MCP
### Participants
MCP follows a client-server architecture where an MCP host — an AI application like [Claude Code](https://www.anthropic.com/claude-code) or [Claude Desktop](https://www.claude.ai/download) — establishes connections to one or more MCP servers. The MCP host accomplishes this by creating one MCP client for each MCP server. Each MCP client maintains a dedicated connection with its corresponding MCP server.
Local MCP servers that use the STDIO transport typically serve a single MCP client, whereas remote MCP servers that use the Streamable HTTP transport will typically serve many MCP clients.
The key participants in the MCP architecture are:
* **MCP Host**: The AI application that coordinates and manages one or multiple MCP clients
* **MCP Client**: A component that maintains a connection to an MCP server and obtains context from an MCP server for the MCP host to use
* **MCP Server**: A program that provides context to MCP clients
**For example**: Visual Studio Code acts as an MCP host. When Visual Studio Code establishes a connection to an MCP server, such as the [Sentry MCP server](https://docs.sentry.io/product/sentry-mcp/), the Visual Studio Code runtime instantiates an MCP client object that maintains the connection to the Sentry MCP server.
When Visual Studio Code subsequently connects to another MCP server, such as the [local filesystem server](https://github.com/modelcontextprotocol/servers/tree/main/src/filesystem), the Visual Studio Code runtime instantiates an additional MCP client object to maintain this connection.
```mermaid theme={null}
graph TB
subgraph "MCP Host (AI Application)"
Client1["MCP Client 1"]
Client2["MCP Client 2"]
Client3["MCP Client 3"]
Client4["MCP Client 4"]
end
ServerA["MCP Server A - Local<br/>(e.g. Filesystem)"]
ServerB["MCP Server B - Local<br/>(e.g. Database)"]
ServerC["MCP Server C - Remote<br/>(e.g. Sentry)"]
Client1 ---|"Dedicated<br/>connection"| ServerA
Client2 ---|"Dedicated<br/>connection"| ServerB
Client3 ---|"Dedicated<br/>connection"| ServerC
Client4 ---|"Dedicated<br/>connection"| ServerC
```
Note that **MCP server** refers to the program that serves context data, regardless of
where it runs. MCP servers can execute locally or remotely. For example, when
Claude Desktop launches the [filesystem
server](https://github.com/modelcontextprotocol/servers/tree/main/src/filesystem),
the server runs locally on the same machine because it uses the STDIO
transport. This is commonly referred to as a "local" MCP server. The official
[Sentry MCP server](https://docs.sentry.io/product/sentry-mcp/) runs on the
Sentry platform, and uses the Streamable HTTP transport. This is commonly
referred to as a "remote" MCP server.
### Layers
MCP consists of two layers:
* **Data layer**: Defines the JSON-RPC based protocol for client-server communication, including lifecycle management, and core primitives, such as tools, resources, prompts and notifications.
* **Transport layer**: Defines the communication mechanisms and channels that enable data exchange between clients and servers, including transport-specific connection establishment, message framing, and authorization.
Conceptually the data layer is the inner layer, while the transport layer is the outer layer.
#### Data layer
The data layer implements a [JSON-RPC 2.0](https://www.jsonrpc.org/) based exchange protocol that defines the message structure and semantics.
This layer includes:
* **Lifecycle management**: Handles connection initialization, capability negotiation, and connection termination between clients and servers
* **Server features**: Enables servers to provide core functionality including tools for AI actions, resources for context data, and prompts for interaction templates from and to the client
* **Client features**: Enables servers to ask the client to sample from the host LLM, elicit input from the user, and log messages to the client
* **Utility features**: Supports additional capabilities like notifications for real-time updates and progress tracking for long-running operations
#### Transport layer
The transport layer manages communication channels and authentication between clients and servers. It handles connection establishment, message framing, and secure communication between MCP participants.
MCP supports two transport mechanisms:
* **Stdio transport**: Uses standard input/output streams for direct process communication between local processes on the same machine, providing optimal performance with no network overhead.
* **Streamable HTTP transport**: Uses HTTP POST for client-to-server messages with optional Server-Sent Events for streaming capabilities. This transport enables remote server communication and supports standard HTTP authentication methods including bearer tokens, API keys, and custom headers. MCP recommends using OAuth to obtain authentication tokens.
The transport layer abstracts communication details from the protocol layer, enabling the same JSON-RPC 2.0 message format across all transport mechanisms.
### Data Layer Protocol
A core part of MCP is defining the schema and semantics between MCP clients and MCP servers. Developers will likely find the data layer — in particular, the set of [primitives](#primitives) — to be the most interesting part of MCP. It is the part of MCP that defines the ways developers can share context from MCP servers to MCP clients.
MCP uses [JSON-RPC 2.0](https://www.jsonrpc.org/) as its underlying RPC protocol. Client and servers send requests to each other and respond accordingly. Notifications can be used when no response is required.
#### Lifecycle management
MCP is a <Tooltip tip="A subset of MCP can be made stateless using the Streamable HTTP transport">stateful protocol</Tooltip> that requires lifecycle management. The purpose of lifecycle management is to negotiate the <Tooltip tip="Features and operations that a client or server supports, such as tools, resources, or prompts">capabilities</Tooltip> that both client and server support. Detailed information can be found in the [specification](/specification/2025-11-25/basic/lifecycle), and the [example](#example) showcases the initialization sequence.
#### Primitives
MCP primitives are the most important concept within MCP. They define what clients and servers can offer each other. These primitives specify the types of contextual information that can be shared with AI applications and the range of actions that can be performed.
MCP defines three core primitives that *servers* can expose:
* **Tools**: Executable functions that AI applications can invoke to perform actions (e.g., file operations, API calls, database queries)
* **Resources**: Data sources that provide contextual information to AI applications (e.g., file contents, database records, API responses)
* **Prompts**: Reusable templates that help structure interactions with language models (e.g., system prompts, few-shot examples)
Each primitive type has associated methods for discovery (`*/list`), retrieval (`*/get`), and in some cases, execution (`tools/call`).
MCP clients will use the `*/list` methods to discover available primitives. For example, a client can first list all available tools (`tools/list`) and then execute them. This design allows listings to be dynamic.
As a concrete example, consider an MCP server that provides context about a database. It can expose tools for querying the database, a resource that contains the schema of the database, and a prompt that includes few-shot examples for interacting with the tools.
For more details about server primitives see [server concepts](./server-concepts).
MCP also defines primitives that *clients* can expose. These primitives allow MCP server authors to build richer interactions.
* **Sampling**: Allows servers to request language model completions from the client's AI application. This is useful when server authors want access to a language model, but want to stay model-independent and not include a language model SDK in their MCP server. They can use the `sampling/createMessage` method to request a language model completion from the client's AI application.
* **Elicitation**: Allows servers to request additional information from users. This is useful when server authors want to get more information from the user, or ask for confirmation of an action. They can use the `elicitation/create` method to request additional information from the user.
* **Logging**: Enables servers to send log messages to clients for debugging and monitoring purposes.
For more details about client primitives see [client concepts](./client-concepts).
Besides server and client primitives, the protocol offers cross-cutting utility primitives that augment how requests are executed:
* **Tasks (Experimental)**: Durable execution wrappers that enable deferred result retrieval and status tracking for MCP requests (e.g., expensive computations, workflow automation, batch processing, multi-step operations)
#### Notifications
The protocol supports real-time notifications to enable dynamic updates between servers and clients. For example, when a server's available tools change—such as when new functionality becomes available or existing tools are modified—the server can send tool update notifications to inform connected clients about these changes. Notifications are sent as JSON-RPC 2.0 notification messages (without expecting a response) and enable MCP servers to provide real-time updates to connected clients.
## Example
### Data Layer
This section provides a step-by-step walkthrough of an MCP client-server interaction, focusing on the data layer protocol. We'll demonstrate the lifecycle sequence, tool operations, and notifications using JSON-RPC 2.0 messages.
<Steps>
<Step title="Initialization (Lifecycle Management)">
MCP begins with lifecycle management through a capability negotiation handshake. As described in the [lifecycle management](#lifecycle-management) section, the client sends an `initialize` request to establish the connection and negotiate supported features.
<CodeGroup>
```json Initialize Request theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2025-11-25",
"capabilities": {
"elicitation": {}
},
"clientInfo": {
"name": "example-client",
"version": "1.0.0"
}
}
}
```
```json Initialize Response theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"protocolVersion": "2025-11-25",
"capabilities": {
"tools": {
"listChanged": true
},
"resources": {}
},
"serverInfo": {
"name": "example-server",
"version": "1.0.0"
}
}
}
```
</CodeGroup>
#### Understanding the Initialization Exchange
The initialization process is a key part of MCP's lifecycle management and serves several critical purposes:
1. **Protocol Version Negotiation**: The `protocolVersion` field (e.g., "2025-11-25") ensures both client and server are using compatible protocol versions. This prevents communication errors that could occur when different versions attempt to interact. If a mutually compatible version is not negotiated, the connection should be terminated.
2. **Capability Discovery**: The `capabilities` object allows each party to declare what features they support, including which [primitives](#primitives) they can handle (tools, resources, prompts) and whether they support features like [notifications](#notifications). This enables efficient communication by avoiding unsupported operations.
3. **Identity Exchange**: The `clientInfo` and `serverInfo` objects provide identification and versioning information for debugging and compatibility purposes.
In this example, the capability negotiation demonstrates how MCP primitives are declared:
**Client Capabilities**:
* `"elicitation": {}` - The client declares it can work with user interaction requests (can receive `elicitation/create` method calls)
**Server Capabilities**:
* `"tools": {"listChanged": true}` - The server supports the tools primitive AND can send `tools/list_changed` notifications when its tool list changes
* `"resources": {}` - The server also supports the resources primitive (can handle `resources/list` and `resources/read` methods)
After successful initialization, the client sends a notification to indicate it's ready:
```json Notification theme={null}
{
"jsonrpc": "2.0",
"method": "notifications/initialized"
}
```
#### How This Works in AI Applications
During initialization, the AI application's MCP client manager establishes connections to configured servers and stores their capabilities for later use. The application uses this information to determine which servers can provide specific types of functionality (tools, resources, prompts) and whether they support real-time updates.
```python Pseudo-code for AI application initialization theme={null}
# Pseudo Code
async with stdio_client(server_config) as (read, write):
async with ClientSession(read, write) as session:
init_response = await session.initialize()
if init_response.capabilities.tools:
app.register_mcp_server(session, supports_tools=True)
app.set_server_ready(session)
```
</Step>
<Step title="Tool Discovery (Primitives)">
Now that the connection is established, the client can discover available tools by sending a `tools/list` request. This request is fundamental to MCP's tool discovery mechanism — it allows clients to understand what tools are available on the server before attempting to use them.
<CodeGroup>
```json Tools List Request theme={null}
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/list"
}
```
```json Tools List Response theme={null}
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"tools": [
{
"name": "calculator_arithmetic",
"title": "Calculator",
"description": "Perform mathematical calculations including basic arithmetic, trigonometric functions, and algebraic operations",
"inputSchema": {
"type": "object",
"properties": {
"expression": {
"type": "string",
"description": "Mathematical expression to evaluate (e.g., '2 + 3 * 4', 'sin(30)', 'sqrt(16)')"
}
},
"required": ["expression"]
}
},
{
"name": "weather_current",
"title": "Weather Information",
"description": "Get current weather information for any location worldwide",
"inputSchema": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "City name, address, or coordinates (latitude,longitude)"
},
"units": {
"type": "string",
"enum": ["metric", "imperial", "kelvin"],
"description": "Temperature units to use in response",
"default": "metric"
}
},
"required": ["location"]
}
}
]
}
}
```
</CodeGroup>
#### Understanding the Tool Discovery Request
The `tools/list` request is simple, containing no parameters.
Cut at 300 lines. The page has the rest.
docs/2025-11-25/learn/client-concepts New page · 232 lines, new page
# Understanding MCP clients ## Core Client Features ### Elicitation #### Overview #### Example: Holiday Booking Approval #### User Interaction Model ### Roots #### Overview #### Example: Travel Planning Workspace #### Design Philosophy #### User Interaction Model ### Sampling #### Overview #### Example: Flight Analysis Tool #### User Interaction Model
A whole new page. There's nothing to diff it against, so here is what it says.
# Understanding MCP clients
MCP clients are instantiated by host applications to communicate with particular MCP servers. The host application, like Claude.ai or an IDE, manages the overall user experience and coordinates multiple clients. Each client handles one direct communication with one server.
Understanding the distinction is important: the *host* is the application users interact with, while *clients* are the protocol-level components that enable server connections.
## Core Client Features
In addition to making use of context provided by servers, clients may provide several features to servers. These client features allow server authors to build richer interactions.
| Feature | Explanation | Example |
| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| **Elicitation** | Elicitation enables servers to request specific information from users during interactions, providing a structured way for servers to gather information on demand. | A server booking travel may ask for the user's preferences on airplane seats, room type or their contact number to finalise a booking. |
| **Roots** | Roots allow clients to specify which directories servers should focus on, communicating intended scope through a coordination mechanism. | A server for booking travel may be given access to a specific directory, from which it can read a user's calendar. |
| **Sampling** | Sampling allows servers to request LLM completions through the client, enabling an agentic workflow. This approach puts the client in complete control of user permissions and security measures. | A server for booking travel may send a list of flights to an LLM and request that the LLM pick the best flight for the user. |
### Elicitation
Elicitation enables servers to request specific information from users during interactions, creating more dynamic and responsive workflows.
#### Overview
Elicitation provides a structured way for servers to gather necessary information on demand. Instead of requiring all information up front or failing when data is missing, servers can pause their operations to request specific inputs from users. This creates more flexible interactions where servers adapt to user needs rather than following rigid patterns.
**Elicitation flow:**
```mermaid theme={null}
sequenceDiagram
participant User
participant Client
participant Server
Note over Server,Client: Server initiates elicitation
Server->>Client: elicitation/create
Note over Client,User: Human interaction
Client->>User: Present elicitation UI
User-->>Client: Provide requested information
Note over Server,Client: Complete request
Client-->>Server: Return user response
Note over Server: Continue processing with new information
```
The flow enables dynamic information gathering. Servers can request specific data when needed, users provide information through appropriate UI, and servers continue processing with the newly acquired context.
**Elicitation components example:**
```typescript theme={null}
{
method: "elicitation/create",
params: {
message: "Please confirm your Barcelona vacation booking details:",
requestedSchema: {
type: "object",
properties: {
confirmBooking: {
type: "boolean",
description: "Confirm the booking (Flights + Hotel = $3,000)"
},
seatPreference: {
type: "string",
enum: ["window", "aisle", "no preference"],
description: "Preferred seat type for flights"
},
roomType: {
type: "string",
enum: ["sea view", "city view", "garden view"],
description: "Preferred room type at hotel"
},
travelInsurance: {
type: "boolean",
default: false,
description: "Add travel insurance ($150)"
}
},
required: ["confirmBooking"]
}
}
}
```
#### Example: Holiday Booking Approval
A travel booking server demonstrates elicitation's power through the final booking confirmation process. When a user has selected their ideal vacation package to Barcelona, the server needs to gather final approval and any missing details before proceeding.
The server elicits booking confirmation with a structured request that includes the trip summary (Barcelona flights June 15-22, beachfront hotel, total \$3,000) and fields for any additional preferences—such as seat selection, room type, or travel insurance options.
As the booking progresses, the server elicits contact information needed to complete the reservation. It might ask for traveler details for flight bookings, special requests for the hotel, or emergency contact information.
#### User Interaction Model
Elicitation interactions are designed to be clear, contextual, and respectful of user autonomy:
**Request presentation**: Clients display elicitation requests with clear context about which server is asking, why the information is needed, and how it will be used. The request message explains the purpose while the schema provides structure and validation.
**Response options**: Users can provide the requested information through appropriate UI controls (text fields, dropdowns, checkboxes), decline to provide information with optional explanation, or cancel the entire operation. Clients validate responses against the provided schema before returning them to servers.
**Privacy considerations**: Elicitation never requests passwords or API keys. Clients warn about suspicious requests and let users review data before sending.
### Roots
Roots define filesystem boundaries for server operations, allowing clients to specify which directories servers should focus on.
#### Overview
Roots are a mechanism for clients to communicate filesystem access boundaries to servers. They consist of file URIs that indicate directories where servers can operate, helping servers understand the scope of available files and folders. While roots communicate intended boundaries, they do not enforce security restrictions. Actual security must be enforced at the operating system level, via file permissions and/or sandboxing.
**Root structure:**
```json theme={null}
{
"uri": "file:///Users/agent/travel-planning",
"name": "Travel Planning Workspace"
}
```
Roots are exclusively filesystem paths and always use the `file://` URI scheme. They help servers understand project boundaries, workspace organization, and accessible directories. The roots list can be updated dynamically as users work with different projects or folders, with servers receiving notifications through `roots/list_changed` when boundaries change.
#### Example: Travel Planning Workspace
A travel agent working with multiple client trips benefits from roots to organize filesystem access. Consider a workspace with different directories for various aspects of travel planning.
The client provides filesystem roots to the travel planning server:
* `file:///Users/agent/travel-planning` - Main workspace containing all travel files
* `file:///Users/agent/travel-templates` - Reusable itinerary templates and resources
* `file:///Users/agent/client-documents` - Client passports and travel documents
When the agent creates a Barcelona itinerary, well-behaved servers respect these boundaries—accessing templates, saving the new itinerary, and referencing client documents within the specified roots. Servers typically access files within roots by using relative paths from the root directories or by utilizing file search tools that respect the root boundaries.
If the agent opens an archive folder like `file:///Users/agent/archive/2023-trips`, the client updates the roots list via `roots/list_changed`.
For a complete implementation of a server that respects roots, see the [filesystem server](https://github.com/modelcontextprotocol/servers/tree/main/src/filesystem) in the official servers repository.
#### Design Philosophy
Roots serve as a coordination mechanism between clients and servers, not a security boundary. The specification requires that servers "SHOULD respect root boundaries," and not that they "MUST enforce" them, because servers run code the client cannot control.
Roots work best when servers are trusted or vetted, users understand their advisory nature, and the goal is preventing accidents rather than stopping malicious behavior. They excel at context scoping (telling servers where to focus), accident prevention (helping well-behaved servers stay in bounds), and workflow organization (such as managing project boundaries automatically).
#### User Interaction Model
Roots are typically managed automatically by host applications based on user actions, though some applications may expose manual root management:
**Automatic root detection**: When users open folders, clients automatically expose them as roots. Opening a travel workspace allows the client to expose that directory as a root, helping servers understand which itineraries and documents are in scope for the current work.
**Manual root configuration**: Advanced users can specify roots through configuration. For example, adding `/travel-templates` for reusable resources while excluding directories with financial records.
### Sampling
Sampling allows servers to request language model completions through the client, enabling agentic behaviors while maintaining security and user control.
#### Overview
Sampling enables servers to perform AI-dependent tasks without directly integrating with or paying for AI models. Instead, servers can request that the client—which already has AI model access—handle these tasks on their behalf. This approach puts the client in complete control of user permissions and security measures. Because sampling requests occur within the context of other operations—like a tool analyzing data—and are processed as separate model calls, they maintain clear boundaries between different contexts, allowing for more efficient use of the context window.
**Sampling flow:**
```mermaid theme={null}
sequenceDiagram
participant LLM
participant User
participant Client
participant Server
Note over Server,Client: Server initiates sampling
Server->>Client: sampling/createMessage
Note over Client,User: Human-in-the-loop review
Client->>User: Present request for approval
User-->>Client: Review and approve/modify
Note over Client,LLM: Model interaction
Client->>LLM: Forward approved request
LLM-->>Client: Return generation
Note over Client,User: Response review
Client->>User: Present response for approval
User-->>Client: Review and approve/modify
Note over Server,Client: Complete request
Client-->>Server: Return approved response
```
The flow ensures security through multiple human-in-the-loop checkpoints. Users review and can modify both the initial request and the generated response before it returns to the server.
**Request parameters example:**
```typescript theme={null}
{
messages: [
{
role: "user",
content: "Analyze these flight options and recommend the best choice:\n" +
"[47 flights with prices, times, airlines, and layovers]\n" +
"User preferences: morning departure, max 1 layover"
}
],
modelPreferences: {
hints: [{
name: "claude-sonnet-4-20250514" // Suggested model
}],
costPriority: 0.3, // Less concerned about API cost
speedPriority: 0.2, // Can wait for thorough analysis
intelligencePriority: 0.9 // Need complex trade-off evaluation
},
systemPrompt: "You are a travel expert helping users find the best flights based on their preferences",
maxTokens: 1500
}
```
#### Example: Flight Analysis Tool
Consider a travel booking server with a tool called `findBestFlight` that uses sampling to analyze available flights and recommend the optimal choice. When a user asks "Book me the best flight to Barcelona next month," the tool needs AI assistance to evaluate complex trade-offs.
The tool queries airline APIs and gathers 47 flight options. It then requests AI assistance to analyze these options: "Analyze these flight options and recommend the best choice: \[47 flights with prices, times, airlines, and layovers] User preferences: morning departure, max 1 layover."
The client initiates the sampling request, allowing the AI to evaluate trade-offs—like cheaper red-eye flights versus convenient morning departures. The tool uses this analysis to present the top three recommendations.
#### User Interaction Model
While not a requirement, sampling is designed to allow human-in-the-loop control. Users can maintain oversight through several mechanisms:
**Approval controls**: Sampling requests may require explicit user consent. Clients can show what the server wants to analyze and why. Users can approve, deny, or modify requests.
**Transparency features**: Clients can display the exact prompt, model selection, and token limits, allowing users to review AI responses before they return to the server.
**Configuration options**: Users can set model preferences, configure auto-approval for trusted operations, or require approval for everything. Clients may provide options to redact sensitive information.
**Security considerations**: Both clients and servers must handle sensitive data appropriately during sampling. Clients should implement rate limiting and validate all message content. The human-in-the-loop design ensures that server-initiated AI interactions cannot compromise security or access sensitive data without explicit user consent.
docs/2025-11-25/learn/server-concepts New page · 281 lines, new page
# Understanding MCP servers ## Core Server Features ### Tools #### How Tools Work #### Example: Travel Booking #### User Interaction Model ### Resources #### How Resources Work #### Example: Getting Travel Planning Context #### Parameter Completion #### User Interaction Model ### Prompts #### How Prompts Work #### Example: Streamlined Workflows #### User Interaction Model ## Bringing Servers Together ### Example: Multi-Server Travel Planning #### The Complete Flow
A whole new page. There's nothing to diff it against, so here is what it says.
# Understanding MCP servers
MCP servers are programs that expose specific capabilities to AI applications through standardized protocol interfaces.
Common examples include file system servers for document access, database servers for data queries, GitHub servers for code management, Slack servers for team communication, and calendar servers for scheduling.
## Core Server Features
Servers provide functionality through three building blocks:
| Feature | Explanation | Examples | Who controls it |
| ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------ | --------------- |
| **Tools** | Functions that your LLM can actively call, and decides when to use them based on user requests. Tools can write to databases, call external APIs, modify files, or trigger other logic. | Search flights<br />Send messages<br />Create calendar events | Model |
| **Resources** | Passive data sources that provide read-only access to information for context, such as file contents, database schemas, or API documentation. | Retrieve documents<br />Access knowledge bases<br />Read calendars | Application |
| **Prompts** | Pre-built instruction templates that tell the model to work with specific tools and resources. | Plan a vacation<br />Summarize my meetings<br />Draft an email | User |
We will use a hypothetical scenario to demonstrate the role of each of these features, and show how they can work together.
### Tools
Tools enable AI models to perform actions. Each tool defines a specific operation with typed inputs and outputs. The model requests tool execution based on context.
#### How Tools Work
Tools are schema-defined interfaces that LLMs can invoke. MCP uses JSON Schema for validation. Each tool performs a single operation with clearly defined inputs and outputs. Tools may require user consent prior to execution, helping to ensure users maintain control over actions taken by a model.
**Protocol operations:**
| Method | Purpose | Returns |
| ------------ | ------------------------ | -------------------------------------- |
| `tools/list` | Discover available tools | Array of tool definitions with schemas |
| `tools/call` | Execute a specific tool | Tool execution result |
**Example tool definition:**
```typescript theme={null}
{
name: "searchFlights",
description: "Search for available flights",
inputSchema: {
type: "object",
properties: {
origin: { type: "string", description: "Departure city" },
destination: { type: "string", description: "Arrival city" },
date: { type: "string", format: "date", description: "Travel date" }
},
required: ["origin", "destination", "date"]
}
}
```
#### Example: Travel Booking
Tools enable AI applications to perform actions on behalf of users. In a travel planning scenario, the AI application might use several tools to help book a vacation:
**Flight Search**
```
searchFlights(origin: "NYC", destination: "Barcelona", date: "2024-06-15")
```
Queries multiple airlines and returns structured flight options.
**Calendar Blocking**
```
createCalendarEvent(title: "Barcelona Trip", startDate: "2024-06-15", endDate: "2024-06-22")
```
Marks the travel dates in the user's calendar.
**Email notification**
```
sendEmail(to: "[email protected]", subject: "Out of Office", body: "...")
```
Sends an automated out-of-office message to colleagues.
#### User Interaction Model
Tools are model-controlled, meaning AI models can discover and invoke them automatically. However, MCP emphasizes human oversight through several mechanisms.
For trust and safety, applications can implement user control through various mechanisms, such as:
* Displaying available tools in the UI, enabling users to define whether a tool should be made available in specific interactions
* Approval dialogs for individual tool executions
* Permission settings for pre-approving certain safe operations
* Activity logs that show all tool executions with their results
### Resources
Resources provide structured access to information that the AI application can retrieve and provide to models as context.
#### How Resources Work
Resources expose data from files, APIs, databases, or any other source that an AI needs to understand context. Applications can access this information directly and decide how to use it - whether that's selecting relevant portions, searching with embeddings, or passing it all to the model.
Each resource has a unique URI (e.g., `file:///path/to/document.md`) and declares its MIME type for appropriate content handling.
Resources support two discovery patterns:
* **Direct Resources** - fixed URIs that point to specific data. Example: `calendar://events/2024` - returns calendar availability for 2024
* **Resource Templates** - dynamic URIs with parameters for flexible queries. Example:
* `travel://activities/{city}/{category}` - returns activities by city and category
* `travel://activities/barcelona/museums` - returns all museums in Barcelona
Resource Templates include metadata such as title, description, and expected MIME type, making them discoverable and self-documenting.
**Protocol operations:**
| Method | Purpose | Returns |
| -------------------------- | ------------------------------- | -------------------------------------- |
| `resources/list` | List available direct resources | Array of resource descriptors |
| `resources/templates/list` | Discover resource templates | Array of resource template definitions |
| `resources/read` | Retrieve resource contents | Resource data with metadata |
| `resources/subscribe` | Monitor resource changes | Subscription confirmation |
#### Example: Getting Travel Planning Context
Continuing with the travel planning example, resources provide the AI application with access to relevant information:
* **Calendar data** (`calendar://events/2024`) - Checks user availability
* **Travel documents** (`file:///Documents/Travel/passport.pdf`) - Accesses important documents
* **Previous itineraries** (`trips://history/barcelona-2023`) - References past trips and preferences
The AI application retrieves these resources and decides how to process them, whether selecting a subset of data using embeddings or keyword search, or passing raw data directly to the model.
In this case, it provides calendar data, weather information, and travel preferences to the model, enabling it to check availability, look up weather patterns, and reference past travel preferences.
**Resource Template Examples:**
```json theme={null}
{
"uriTemplate": "weather://forecast/{city}/{date}",
"name": "weather-forecast",
"title": "Weather Forecast",
"description": "Get weather forecast for any city and date",
"mimeType": "application/json"
}
{
"uriTemplate": "travel://flights/{origin}/{destination}",
"name": "flight-search",
"title": "Flight Search",
"description": "Search available flights between cities",
"mimeType": "application/json"
}
```
These templates enable flexible queries. For weather data, users can access forecasts for any city/date combination. For flights, they can search routes between any two airports. When a user has input "NYC" as the `origin` airport and begins to input "Bar" as the `destination` airport, the system can suggest "Barcelona (BCN)" or "Barbados (BGI)".
#### Parameter Completion
Dynamic resources support parameter completion. For example:
* Typing "Par" as input for `weather://forecast/{city}` might suggest "Paris" or "Park City"
* Typing "JFK" for `flights://search/{airport}` might suggest "JFK - John F. Kennedy International"
The system helps discover valid values without requiring exact format knowledge.
#### User Interaction Model
Resources are application-driven, giving them flexibility in how they retrieve, process, and present available context. Common interaction patterns include:
* Tree or list views for browsing resources in familiar folder-like structures
* Search and filter interfaces for finding specific resources
* Automatic context inclusion or smart suggestions based on heuristics or AI selection
* Manual or bulk selection interfaces for including single or multiple resources
Applications are free to implement resource discovery through any interface pattern that suits their needs. The protocol doesn't mandate specific UI patterns, allowing for resource pickers with preview capabilities, smart suggestions based on current conversation context, bulk selection for including multiple resources, or integration with existing file browsers and data explorers.
### Prompts
Prompts provide reusable templates. They allow MCP server authors to provide parameterized prompts for a domain, or showcase how to best use the MCP server.
#### How Prompts Work
Prompts are structured templates that define expected inputs and interaction patterns. They are user-controlled, requiring explicit invocation rather than automatic triggering. Prompts can be context-aware, referencing available resources and tools to create comprehensive workflows. Similar to resources, prompts support parameter completion to help users discover valid argument values.
**Protocol operations:**
| Method | Purpose | Returns |
| -------------- | -------------------------- | ------------------------------------- |
| `prompts/list` | Discover available prompts | Array of prompt descriptors |
| `prompts/get` | Retrieve prompt details | Full prompt definition with arguments |
#### Example: Streamlined Workflows
Prompts provide structured templates for common tasks. In the travel planning context:
**"Plan a vacation" prompt:**
```json theme={null}
{
"name": "plan-vacation",
"title": "Plan a vacation",
"description": "Guide through vacation planning process",
"arguments": [
{ "name": "destination", "type": "string", "required": true },
{ "name": "duration", "type": "number", "description": "days" },
{ "name": "budget", "type": "number", "required": false },
{ "name": "interests", "type": "array", "items": { "type": "string" } }
]
}
```
Rather than unstructured natural language input, the prompt system enables:
1. Selection of the "Plan a vacation" template
2. Structured input: Barcelona, 7 days, \$3000, \["beaches", "architecture", "food"]
3. Consistent workflow execution based on the template
#### User Interaction Model
Prompts are user-controlled, requiring explicit invocation. The protocol gives implementers freedom to design interfaces that feel natural within their application. Key principles include:
* Easy discovery of available prompts
* Clear descriptions of what each prompt does
* Natural argument input with validation
* Transparent display of the prompt's underlying template
Applications typically expose prompts through various UI patterns such as:
* Slash commands (typing "/" to see available prompts like /plan-vacation)
* Command palettes for searchable access
* Dedicated UI buttons for frequently used prompts
* Context menus that suggest relevant prompts
## Bringing Servers Together
The real power of MCP emerges when multiple servers work together, combining their specialized capabilities through a unified interface.
### Example: Multi-Server Travel Planning
Consider a personalized AI travel planner application, with three connected servers:
* **Travel Server** - Handles flights, hotels, and itineraries
* **Weather Server** - Provides climate data and forecasts
* **Calendar/Email Server** - Manages schedules and communications
#### The Complete Flow
1. **User invokes a prompt with parameters:**
```json theme={null}
{
"prompt": "plan-vacation",
"arguments": {
"destination": "Barcelona",
"departure_date": "2024-06-15",
"return_date": "2024-06-22",
"budget": 3000,
"travelers": 2
}
}
```
2. **User selects resources to include:**
* `calendar://my-calendar/June-2024` (from Calendar Server)
* `travel://preferences/europe` (from Travel Server)
* `travel://past-trips/Spain-2023` (from Travel Server)
3. **AI processes the request using tools:**
The AI first reads all selected resources to gather context - identifying available dates from the calendar, learning preferred airlines and hotel types from travel preferences, and discovering previously enjoyed locations from past trips.
Using this context, the AI then executes the prompt provided by the AI application. In our example, the AI application exposes the weather tools from the connected MCP weather server to the model. Because weather can affect travel plans, the AI chooses to call `checkWeather()` when interpreting the prompt.
As a result the AI executes a series of tools:
* `searchFlights()` - Queries airlines for NYC to Barcelona flights
* `checkWeather()` - Retrieves climate forecasts for travel dates
The AI then uses this information to create the booking and following steps, requesting approval from the user where necessary:
* `bookHotel()` - Finds hotels within the specified budget
* `createCalendarEvent()` - Adds the trip to the user's calendar
* `sendEmail()` - Sends confirmation with trip details
**The result:** Through multiple MCP servers, the user researched and booked a Barcelona trip tailored to their schedule. The "Plan a Vacation" prompt guided the AI to combine Resources (calendar availability and travel history) with Tools (searching flights, booking hotels, updating calendars) across different servers—gathering context and executing the booking. A task that could have taken hours was completed in minutes using MCP.
docs/2025-11-25/learn/versioning New page · 45 lines, new page
# Versioning ## Revisions ## Feature States ## Negotiation
A whole new page. There's nothing to diff it against, so here is what it says.
# Versioning The Model Context Protocol uses string-based version identifiers following the format `YYYY-MM-DD`, to indicate the last date backwards incompatible changes were made. <Info> The protocol version will *not* be incremented when the protocol is updated, as long as the changes maintain backwards compatibility. This allows for incremental improvements while preserving interoperability. </Info> ## Revisions Revisions may be marked as: * **Draft**: in-progress specifications, not yet ready for consumption. * **Current**: the current protocol version, which is ready for use and may continue to receive backwards compatible changes. * **Final**: past, complete specifications that will not be changed. The **current** protocol version is [**2025-11-25**](/specification/2025-11-25/). ## Feature States Individual features of the specification may additionally be marked as **Deprecated** under the [feature lifecycle and deprecation policy](/community/feature-lifecycle): the feature remains part of the specification, but is scheduled for removal. Deprecated features document a migration path (or state that none is required) and remain in the specification for at least twelve months, or at least ninety days under the policy's [expedited-removal exception](/community/feature-lifecycle#expedited-removal), before they become eligible for removal, after which they may be **Removed** in a future revision. ## Negotiation Version negotiation happens during [initialization](/specification/2025-11-25/basic/lifecycle#initialization). Clients and servers **MAY** support multiple protocol versions simultaneously, but they **MUST** agree on a single version to use for the session. The protocol provides appropriate error handling if version negotiation fails, allowing clients to gracefully terminate connections when they cannot find a version compatible with the server.
docs/2025-11-25/sdk New page · 47 lines, new page
# SDKs ## Available SDKs ## Getting Started ## Next Steps
A whole new page. There's nothing to diff it against, so here is what it says.
# SDKs
> Official SDKs for building with Model Context Protocol
Build MCP servers and clients using our official SDKs. SDKs are classified into tiers based on feature completeness, protocol support, and maintenance commitment. Learn more about [SDK tiers](/community/sdk-tiers).
## Available SDKs
| SDK | Repository | Tier |
| :----------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------- | ------------------------------------------------: |
| <Icon icon="square-js" size={24} /> [TypeScript](https://ts.sdk.modelcontextprotocol.io) | [modelcontextprotocol/typescript-sdk](https://github.com/modelcontextprotocol/typescript-sdk) | <Badge color="blue" shape="pill">Tier 1</Badge> |
| <Icon icon="python" size={24} /> [Python](https://py.sdk.modelcontextprotocol.io) | [modelcontextprotocol/python-sdk](https://github.com/modelcontextprotocol/python-sdk) | <Badge color="blue" shape="pill">Tier 1</Badge> |
| <Icon icon="square-c" size={24} /> [C#](https://csharp.sdk.modelcontextprotocol.io) | [modelcontextprotocol/csharp-sdk](https://github.com/modelcontextprotocol/csharp-sdk) | <Badge color="blue" shape="pill">Tier 1</Badge> |
| <Icon icon="golang" size={24} /> [Go](https://go.sdk.modelcontextprotocol.io) | [modelcontextprotocol/go-sdk](https://github.com/modelcontextprotocol/go-sdk) | <Badge color="blue" shape="pill">Tier 1</Badge> |
| <Icon icon="java" size={24} /> [Java](https://java.sdk.modelcontextprotocol.io) | [modelcontextprotocol/java-sdk](https://github.com/modelcontextprotocol/java-sdk) | <Badge color="purple" shape="pill">Tier 2</Badge> |
| <Icon icon="rust" size={24} /> [Rust](https://rust.sdk.modelcontextprotocol.io) | [modelcontextprotocol/rust-sdk](https://github.com/modelcontextprotocol/rust-sdk) | <Badge color="purple" shape="pill">Tier 2</Badge> |
| <Icon icon="swift" size={24} /> Swift | [modelcontextprotocol/swift-sdk](https://github.com/modelcontextprotocol/swift-sdk) | <Badge color="orange" shape="pill">Tier 3</Badge> |
| <Icon icon="gem" size={24} /> [Ruby](https://ruby.sdk.modelcontextprotocol.io) | [modelcontextprotocol/ruby-sdk](https://github.com/modelcontextprotocol/ruby-sdk) | <Badge color="orange" shape="pill">Tier 3</Badge> |
| <Icon icon="php" size={24} /> [PHP](https://php.sdk.modelcontextprotocol.io) | [modelcontextprotocol/php-sdk](https://github.com/modelcontextprotocol/php-sdk) | <Badge color="orange" shape="pill">Tier 3</Badge> |
| <Icon icon="square-k" size={24} /> [Kotlin](https://kotlin.sdk.modelcontextprotocol.io) | [modelcontextprotocol/kotlin-sdk](https://github.com/modelcontextprotocol/kotlin-sdk) | <Badge color="orange" shape="pill">Tier 3</Badge> |
See [SDK Tiering System](/community/sdk-tiers) for details on what each tier means.
## Getting Started
Each SDK provides the same functionality but follows the idioms and best practices of its language. All SDKs support:
* Creating MCP servers that expose tools, resources, and prompts
* Building MCP clients that can connect to any MCP server
* Local and remote transport protocols
* Protocol compliance with type safety
Visit the SDK page for your chosen language to find installation instructions, documentation, and examples.
## Next Steps
Ready to start building with MCP? Choose your path:
<CardGroup cols={2}>
<Card title="Build a Server" icon="server" href="/docs/2025-11-25/develop/build-server">
Learn how to create your first MCP server
</Card>
<Card title="Build a Client" icon="computer" href="/docs/2025-11-25/develop/build-client">
Create applications that connect to MCP servers
</Card>
</CardGroup>
docs/2025-11-25/tools/debugging New page · 348 lines, new page
# Debugging ## Debugging tools overview ## Implementing logging ### Server-side logging ## Common issues ### Working directory ### Environment variables ### Server initialization ### Connection problems ## Debugging in Claude Desktop ### Checking server status ### Viewing logs ### Using Chrome DevTools ## Debugging workflow ### Development cycle ### Testing changes ## Best practices ### Logging strategy ### Security considerations ## Getting help ## Next steps
A whole new page. There's nothing to diff it against, so here is what it says.
# Debugging
> A comprehensive guide to debugging Model Context Protocol (MCP) integrations
Effective debugging is essential when developing MCP servers or integrating
them with applications. This guide covers the debugging tools and approaches
available in the MCP ecosystem.
## Debugging tools overview
MCP provides several tools for debugging at different levels:
1. **[MCP Inspector](/docs/2025-11-25/tools/inspector)**: interactive, transport-agnostic
testing UI. Connect to stdio or Streamable HTTP servers, invoke
[tools](/specification/2025-11-25/server/tools),
[prompts](/specification/2025-11-25/server/prompts), and
[resources](/specification/2025-11-25/server/resources), and watch the
notification stream. This should be your first stop.
2. **Server logging**: structured logs to stderr (stdio transport) or via
[`notifications/message`](/specification/2025-11-25/server/utilities/logging#log-message-notifications)
(all transports).
3. **Client developer tools**: most MCP clients expose logs and connection
state. See [Debugging in Claude Desktop](#debugging-in-claude-desktop)
below for one example, or consult your client's documentation.
## Implementing logging
### Server-side logging
When building a server that uses the local
[stdio transport](/specification/2025-11-25/basic/transports#stdio), all messages
logged to stderr (standard error) will be captured by the host application
automatically.
<Warning>
Local MCP servers should not log messages to stdout (standard out), as this
will interfere with protocol operation.
</Warning>
For servers using the
[Streamable HTTP transport](/specification/2025-11-25/basic/transports#streamable-http),
stderr is not captured by the client. Use the log message notifications below,
your own server-side log aggregation, or standard HTTP tooling (curl, browser
DevTools Network panel) to inspect requests,
[`Mcp-Session-Id` headers](/specification/2025-11-25/basic/transports#session-management),
and SSE streams.
For all [transports](/specification/2025-11-25/basic/transports), you can also
provide logging to the client by sending a log message notification:
<CodeGroup>
```python Python theme={null}
@server.tool()
async def my_tool(ctx: Context) -> str:
await ctx.session.send_log_message(
level="info",
data="Server started successfully",
)
return "done"
```
```typescript TypeScript theme={null}
await server.sendLoggingMessage({
level: "info",
data: "Server started successfully",
});
```
</CodeGroup>
MCP defines eight
[RFC 5424 severity levels](/specification/2025-11-25/server/utilities/logging#log-levels)
(`debug` through `emergency`). Clients can adjust the minimum level at runtime
via the
[`logging/setLevel`](/specification/2025-11-25/server/utilities/logging#setting-log-level)
request.
Important events to log:
* Initialization steps
* Resource access
* Tool execution
* Error conditions
* Performance metrics
## Common issues
The examples below use Claude Desktop's
[`claude_desktop_config.json`](/docs/2025-11-25/develop/connect-local-servers); the same
principles apply to any stdio-based MCP client.
### Working directory
When an MCP client launches a stdio server:
* The working directory for servers launched via the client's config may be
undefined (like `/` on macOS) since the client could be started from
anywhere
* Always use absolute paths in your configuration and `.env` files to ensure
reliable operation
* For testing servers directly via command line, the working directory will be
where you run the command
For example in `claude_desktop_config.json`, use:
```json theme={null}
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"/Users/username/data"
]
}
}
}
```
Instead of relative paths like `./data`
### Environment variables
MCP servers launched over stdio inherit only a limited subset of environment
variables automatically (the exact set is platform-dependent).
To override the default variables or provide your own, you can specify an
`env` key in `claude_desktop_config.json`:
```json theme={null}
{
"mcpServers": {
"myserver": {
"command": "mcp-server-myapp",
"env": {
"MYAPP_API_KEY": "some_key"
}
}
}
}
```
### Server initialization
Common initialization problems:
1. **Path Issues**
* Incorrect server executable path
* Missing required files
* Permission problems
* Try using an absolute path for `command`
2. **Configuration Errors**
* Invalid JSON syntax
* Missing required fields
* Type mismatches
3. **Environment Problems**
* Missing environment variables
* Incorrect variable values
* Permission restrictions
### Connection problems
When servers fail to connect:
1. Check client logs
2. Verify server process is running
3. Test standalone with [Inspector](/docs/2025-11-25/tools/inspector)
4. Verify
[protocol compatibility](/specification/2025-11-25/basic/lifecycle#version-negotiation)
5. Check
[capability negotiation](/specification/2025-11-25/basic/lifecycle#capability-negotiation):
error [`-32602`](/specification/2025-11-25/basic/lifecycle#error-handling) is
the standard JSON-RPC "Invalid params" code and is returned in many
contexts. One common cause is a server sending
[sampling](/specification/2025-11-25/client/sampling) or
[elicitation](/specification/2025-11-25/client/elicitation) requests to a
client that hasn't declared that capability. Inspect the
[`initialize` exchange](/specification/2025-11-25/basic/lifecycle#initialization)
to verify both sides declared what you expect
## Debugging in Claude Desktop
Claude Desktop is one of many MCP clients. It is available on
macOS and Windows.
### Checking server status
Click the "Add files, connectors, and more" plus icon in the chat input, then
hover over the **Connectors** menu to see connected servers and available
tools.
<img src="https://mintcdn.com/mcp/zNouQwo2h8cbxlDS/images/available-mcp-tools.png?fit=max&auto=format&n=zNouQwo2h8cbxlDS&q=85&s=e2ace1ac88895a5fe30ebd8d01456bc3" alt="Available MCP tools" width="437" height="244" data-path="images/available-mcp-tools.png" />
### Viewing logs
Log files are written to:
* macOS: `~/Library/Logs/Claude`
* Windows: `%APPDATA%\Claude\logs`
<CodeGroup>
```bash macOS theme={null}
tail -n 20 -F ~/Library/Logs/Claude/mcp*.log
```
```powershell Windows theme={null}
type "$env:AppData\Claude\logs\mcp*.log"
```
</CodeGroup>
The logs capture:
* Server connection events
* Configuration issues
* Runtime errors
* Message exchanges
### Using Chrome DevTools
Access Chrome's developer tools inside Claude Desktop to investigate
client-side errors:
1. Create a `developer_settings.json` file with `allowDevTools` set to true:
<CodeGroup>
```bash macOS theme={null}
echo '{"allowDevTools": true}' > ~/Library/Application\ Support/Claude/developer_settings.json
```
```powershell Windows theme={null}
'{"allowDevTools": true}' | Set-Content "$env:AppData\Claude\developer_settings.json"
```
</CodeGroup>
2. Open DevTools: `Command-Option-I` (macOS) or `Ctrl+Alt+I` (Windows)
Note: You'll see two DevTools windows:
* Main content window
* App title bar window
Use the Console panel to inspect client-side errors.
Use the Network panel to inspect:
* Message payloads
* Connection timing
## Debugging workflow
### Development cycle
1. Initial Development
* Use [Inspector](/docs/2025-11-25/tools/inspector) for basic testing
* Implement core functionality
* Add logging points
2. Integration Testing
* Test in your target MCP client
* Monitor logs
* Check error handling
### Testing changes
To test changes efficiently:
* **Configuration changes**: Restart the MCP client
* **Server code changes**: Restart the client (for Claude Desktop, fully quit
and reopen; closing the window is not enough)
* **Quick iteration**: Use [Inspector](/docs/2025-11-25/tools/inspector) during
development
## Best practices
### Logging strategy
1. **Structured Logging**
* Use consistent formats
* Include context
* Add timestamps
* Track request IDs
2. **Error Handling**
* Log stack traces
* Include error context
* Track error patterns
* Monitor recovery
3. **Performance Tracking**
* Log operation timing
* Monitor resource usage
* Track message sizes
* Measure latency
### Security considerations
When debugging:
Cut at 300 lines. The page has the rest.
docs/2025-11-25/tools/inspector New page · 140 lines, new page
# MCP Inspector ## Getting started ### Installation and basic usage #### Inspecting servers from npm or PyPI #### Inspecting locally developed servers ## Feature overview ### Server connection pane ### Resources tab ### Prompts tab ### Tools tab ### Notifications pane ## Best practices ### Development workflow ## Next steps
A whole new page. There's nothing to diff it against, so here is what it says.
# MCP Inspector
> In-depth guide to using the MCP Inspector for testing and debugging Model Context Protocol servers
The [MCP Inspector](https://github.com/modelcontextprotocol/inspector) is an interactive developer tool for testing and debugging MCP servers. While the [Debugging Guide](/docs/2025-11-25/tools/debugging) covers the Inspector as part of the overall debugging toolkit, this document provides a detailed exploration of the Inspector's features and capabilities.
## Getting started
### Installation and basic usage
The Inspector runs directly through `npx` without requiring installation:
```bash theme={null}
npx @modelcontextprotocol/inspector <command>
```
```bash theme={null}
npx @modelcontextprotocol/inspector <command> <arg1> <arg2>
```
#### Inspecting servers from npm or PyPI
A common way to start server packages from [npm](https://npmjs.com) or [PyPI](https://pypi.org).
<Tabs>
<Tab title="npm package">
```bash theme={null}
npx -y @modelcontextprotocol/inspector npx <package-name> <args>
# For example
npx -y @modelcontextprotocol/inspector npx @modelcontextprotocol/server-filesystem /Users/username/Desktop
```
</Tab>
<Tab title="PyPI package">
```bash theme={null}
npx @modelcontextprotocol/inspector uvx <package-name> <args>
# For example
npx @modelcontextprotocol/inspector uvx mcp-server-git --repository ~/code/mcp/servers.git
```
</Tab>
</Tabs>
#### Inspecting locally developed servers
To inspect servers locally developed or downloaded as a repository, the most common
way is:
<Tabs>
<Tab title="TypeScript">
```bash theme={null}
npx @modelcontextprotocol/inspector node path/to/server/index.js args...
```
</Tab>
<Tab title="Python">
```bash theme={null}
npx @modelcontextprotocol/inspector \
uv \
--directory path/to/server \
run \
package-name \
args...
```
</Tab>
</Tabs>
Please carefully read any attached README for the most accurate instructions.
## Feature overview
<Frame caption="The MCP Inspector interface">
<img src="https://mintcdn.com/mcp/4ZXF1PrDkEaJvXpn/images/mcp-inspector.png?fit=max&auto=format&n=4ZXF1PrDkEaJvXpn&q=85&s=83b12e2a457c96ef4ad17c7357236290" width="2888" height="1761" data-path="images/mcp-inspector.png" />
</Frame>
The Inspector provides several features for interacting with your MCP server:
### Server connection pane
* Allows selecting the [transport](/specification/2025-11-25/basic/transports) for connecting to the server
* For local servers, supports customizing the command-line arguments and environment
### Resources tab
* Lists all available resources
* Shows resource metadata (MIME types, descriptions)
* Allows resource content inspection
* Supports subscription testing
### Prompts tab
* Displays available prompt templates
* Shows prompt arguments and descriptions
* Enables prompt testing with custom arguments
* Previews generated messages
### Tools tab
* Lists available tools
* Shows tool schemas and descriptions
* Enables tool testing with custom inputs
* Displays tool execution results
### Notifications pane
* Presents all logs recorded from the server
* Shows notifications received from the server
## Best practices
### Development workflow
1. Start Development
* Launch Inspector with your server
* Verify basic connectivity
* Check capability negotiation
2. Iterative testing
* Make server changes
* Rebuild the server
* Reconnect the Inspector
* Test affected features
* Monitor messages
3. Test edge cases
* Invalid inputs
* Missing prompt arguments
* Concurrent operations
* Verify error handling and error responses
## Next steps
<CardGroup cols={2}>
<Card title="Inspector Repository" icon="github" href="https://github.com/modelcontextprotocol/inspector">
Check out the MCP Inspector source code
</Card>
<Card title="Debugging Guide" icon="bug" href="/docs/2025-11-25/tools/debugging">
Learn about broader debugging strategies
</Card>
</CardGroup>
docs/2025-11-25/tutorials/security/authorization New page · 1057 lines, new page
# Understanding Authorization in MCP ## When Should You Use Authorization? ## The Authorization Flow: Step by Step ## Implementation Example ### Keycloak Setup ### MCP Server Setup ## Testing the MCP Server ## Common Pitfalls and How to Avoid Them ## Related Standards and Documentation
A whole new page. There's nothing to diff it against, so here is what it says.
# Understanding Authorization in MCP
> Learn how to implement secure authorization for MCP servers using OAuth 2.1 to protect sensitive resources and operations
Authorization in the Model Context Protocol (MCP) secures access to sensitive resources and operations exposed by MCP servers. If your MCP server handles user data or administrative actions, authorization ensures only permitted users can access its endpoints.
MCP uses standardized authorization flows to build trust between MCP clients and MCP servers. Its design doesn't focus on one specific authorization or identity system, but rather follows the conventions outlined for [OAuth 2.1](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-13). For detailed information, see the [Authorization specification](/specification/2025-11-25/basic/authorization).
## When Should You Use Authorization?
While authorization for MCP servers is **optional**, it is strongly recommended when:
* Your server accesses user-specific data (emails, documents, databases)
* You need to audit who performed which actions
* Your server grants access to its APIs that require user consent
* You're building for enterprise environments with strict access controls
* You want to implement rate limiting or usage tracking per user
<Tip>
**Authorization for Local MCP Servers**
For MCP servers using the [STDIO transport](/specification/2025-11-25/basic/transports#stdio), you can use environment-based credentials or credentials provided by third-party libraries embedded directly in the MCP server instead. Because a STDIO-built MCP server runs locally, it has access to a range of flexible options when it comes to acquiring user credentials that may or may not rely on in-browser authentication and authorization flows.
OAuth flows, in turn, are designed for HTTP-based transports where the MCP server is remotely-hosted and the client uses OAuth to establish that a user is authorized to access said remote server.
</Tip>
## The Authorization Flow: Step by Step
Let's walk through what happens when a client wants to connect to your protected MCP server:
<Steps>
<Step title="Initial Handshake">
When your MCP client first tries to connect, your server responds with a `401 Unauthorized` and tells the client where to find authorization information, captured in a [Protected Resource Metadata (PRM) document](https://datatracker.ietf.org/doc/html/rfc9728). The document is hosted by the MCP server, follows a predictable path pattern, and is provided to the client in the `resource_metadata` parameter within the `WWW-Authenticate` header.
```http theme={null}
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="mcp",
resource_metadata="https://your-server.com/.well-known/oauth-protected-resource"
```
This tells the client that authorization is required for the MCP server and where to get the necessary information to kickstart the authorization flow.
</Step>
<Step title="Protected Resource Metadata Discovery">
With the URI pointer to the PRM document, the client will fetch the metadata to learn about the authorization server, supported scopes, and other resource information. The data is typically encapsulated in a JSON blob, similar to the one below.
```json theme={null}
{
"resource": "https://your-server.com/mcp",
"authorization_servers": ["https://auth.your-server.com"],
"scopes_supported": ["mcp:tools", "mcp:resources"]
}
```
You can see a more comprehensive example in [RFC 9728 Section 3.2](https://datatracker.ietf.org/doc/html/rfc9728#name-protected-resource-metadata-r).
</Step>
<Step title="Authorization Server Discovery">
Next, the client discovers what the authorization server can do by fetching its metadata. If the PRM document lists more than one authorization server, the client can decide which one to use.
With an authorization server selected, the client will then construct a standard metadata URI and issue a request to the [OpenID Connect (OIDC) Discovery](https://openid.net/specs/openid-connect-discovery-1_0.html) or [OAuth 2.0 Auth Server Metadata](https://datatracker.ietf.org/doc/html/rfc8414) endpoints (depending on authorization server support)
and retrieve another set of metadata properties that will allow it to know the endpoints it needs to complete the authorization flow.
```json theme={null}
{
"issuer": "https://auth.your-server.com",
"authorization_endpoint": "https://auth.your-server.com/authorize",
"token_endpoint": "https://auth.your-server.com/token",
"registration_endpoint": "https://auth.your-server.com/register"
}
```
</Step>
<Step title="Client Registration">
With all the metadata out of the way, the client now needs to make sure that it's registered with the authorization server. This can be done in two ways.
First, the client can be **pre-registered** with a given authorization server, in which case it can have embedded client registration information that it uses to complete the authorization flow.
Alternatively, the client can use **Dynamic Client Registration** (DCR) to dynamically register itself with the authorization server. The latter scenario requires the authorization server to support DCR. If the authorization server does support DCR, the client will send a request to the `registration_endpoint` with its information:
```json theme={null}
{
"client_name": "My MCP Client",
"redirect_uris": ["http://localhost:3000/callback"],
"grant_types": ["authorization_code", "refresh_token"],
"response_types": ["code"]
}
```
If the registration succeeds, the authorization server will return a JSON blob with client registration information.
<Tip>
**No DCR or Pre-Registration**
In case an MCP client connects to an MCP server that doesn't use an authorization server that supports DCR and the client is not pre-registered with said authorization server, it's the responsibility of the client developer to provide an affordance for the end-user to enter client information manually.
</Tip>
</Step>
<Step title="User Authorization">
The client will now need to open a browser to the `/authorize` endpoint, where the user can log in and grant the required permissions. The authorization server will then redirect back to the client with an authorization code that the client exchanges for tokens:
```json theme={null}
{
"access_token": "eyJhbGciOiJSUzI1NiIs...",
"refresh_token": "def502...",
"token_type": "Bearer",
"expires_in": 3600
}
```
The access token is what the client will use to authenticate requests to the MCP server. This step follows standard [OAuth 2.1 authorization code with PKCE](https://oauth.net/2/grant-types/authorization-code/) conventions.
</Step>
<Step title="Making Authenticated Requests">
Finally, the client can make requests to your MCP server using the access token embedded in the `Authorization` header:
```http theme={null}
GET /mcp HTTP/1.1
Host: your-server.com
Authorization: Bearer eyJhbGciOiJSUzI1NiIs...
```
The MCP server will need to validate the token and process the request if the token is valid and has the required permissions.
</Step>
</Steps>
## Implementation Example
To get started with a practical implementation, we will use a [Keycloak](https://www.keycloak.org/) authorization server hosted in a Docker container. Keycloak is an open-source authorization server that can be easily deployed locally for testing and experimentation.
Make sure that you download and install [Docker Desktop](https://www.docker.com/products/docker-desktop/). We will need it to deploy Keycloak on our development machine.
### Keycloak Setup
From your terminal application, run the following command to start the Keycloak container:
```bash theme={null}
docker run -p 127.0.0.1:8080:8080 -e KC_BOOTSTRAP_ADMIN_USERNAME=admin -e KC_BOOTSTRAP_ADMIN_PASSWORD=admin quay.io/keycloak/keycloak start-dev
```
This command will pull the Keycloak container image locally and bootstrap the basic configuration. It will run on port `8080` and have an `admin` user with `admin` password.
<Warning>
**Not for Production**
The configuration above may be suitable for testing and experimentation; however, you should never use it in production. Refer to the [Configuring Keycloak for production](https://www.keycloak.org/server/configuration-production) guide for additional details on how to deploy the authorization server for scenarios that require reliability, security, and high availability.
</Warning>
You will be able to access the Keycloak authorization server from your browser at `http://localhost:8080`.
<Frame>
<img src="https://mintcdn.com/mcp/sAd4SGUO-cEUqgzn/images/tutorial-authorization/keycloak-browser.png?fit=max&auto=format&n=sAd4SGUO-cEUqgzn&q=85&s=cba689d986e113cbe937d732ac0558b6" alt="Keycloak admin dashboard authentication dialog." width="1834" height="1450" data-path="images/tutorial-authorization/keycloak-browser.png" />
</Frame>
When running with the default configuration, Keycloak will already support many of the capabilities that we need for MCP servers, including Dynamic Client Registration. You can check this by looking at the OIDC configuration, available at:
```http theme={null}
http://localhost:8080/realms/master/.well-known/openid-configuration
```
We will also need to set up Keycloak to support our scopes and allow our host (local machine) to dynamically register clients, as the default policies restrict anonymous dynamic client registration.
Go to **Client scopes** in the Keycloak dashboard and create a new `mcp:tools` scope. We will use this to access all of the tools on our MCP server.
<Frame>
<img src="https://mintcdn.com/mcp/sAd4SGUO-cEUqgzn/images/tutorial-authorization/keycloak-scopes.png?fit=max&auto=format&n=sAd4SGUO-cEUqgzn&q=85&s=3cd49dc2e070027609ae495751e0db58" alt="Configuring Keycloak scopes." width="1999" height="1710" data-path="images/tutorial-authorization/keycloak-scopes.png" />
</Frame>
After creating the scope, make sure that you assign its type to **Default** and have flipped the **Include in token scope** switch, as this will be needed for token validation.
Let's now also set up an **audience** for our Keycloak-issued tokens. An audience is important to configure because it embeds the intended destination directly into the issued access token. This helps your MCP server to verify that the token it got was actually meant for it rather than some other API. This is key to help avoid token passthrough scenarios.
To do this, open your `mcp:tools` client scope and click on **Mappers**, followed by **Configure a new mapper**. Select **Audience**.
<Frame>
<img src="https://mintcdn.com/mcp/sAd4SGUO-cEUqgzn/images/tutorial-authorization/scope-add-audience.gif?s=6ea9cf20c397f4c79c491c2e39019272" alt="Configuring an audience for a token in Keycloak." width="1080" height="921" data-path="images/tutorial-authorization/scope-add-audience.gif" />
</Frame>
For **Name**, use `audience-config`. Add a value for **Included Custom Audience**, set to `http://localhost:3000`. This will be the URI of our test server.
<Warning>
**Not for Production**
The audience configuration above is meant for testing. For production scenarios, additional set-up and configuration will be required to ensure that audiences are properly constrained for issued tokens. Specifically, the audience needs to be based on the resource parameter passed from the client, not a fixed value.
</Warning>
Now, navigate to **Clients**, then **Client registration**, and then **Trusted Hosts**. Disable the **Client URIs Must Match** setting and add the hosts from which you're testing. You can get your current host IP by running the `ifconfig` command on Linux or macOS, or `ipconfig` on Windows. You can see the IP address you need to add by looking at the keycloak logs for a line that looks like `Failed to verify remote host : 192.168.215.1`. Check that the IP address is associated with your host. This may be for a bridge network depending on your docker setup.
<Frame>
<img src="https://mintcdn.com/mcp/sAd4SGUO-cEUqgzn/images/tutorial-authorization/keycloak-client.gif?s=b5d40b36a5f1ea1e818821bb8ea77f6b" alt="Setting up client registration details in Keycloak." width="1199" height="1027" data-path="images/tutorial-authorization/keycloak-client.gif" />
</Frame>
<Warning>
**Getting the Host**
If you are running Keycloak from a container, you will also be able to see the host IP from the Terminal in the container logs.
</Warning>
Lastly, we need to register a new client that we can use with the **MCP server itself** to talk to Keycloak for things like [token introspection](https://oauth.net/2/token-introspection/). To do that:
1. Go to **Clients**.
2. Click **Create client**.
3. Give your client a unique **Client ID** and click **Next**.
4. Enable **Client authentication** and click **Next**.
5. Click **Save**.
Worth noting that token introspection is just *one of* the available approaches to validate tokens. This can also be done with the help of standalone libraries, specific to each language and platform.
When you open the client details, go to **Credentials** and take note of the **Client Secret**.
<Frame>
<img src="https://mintcdn.com/mcp/sAd4SGUO-cEUqgzn/images/tutorial-authorization/keycloak-client-auth.gif?s=7152c41a5746994fd399024bc4659e40" alt="Creating a new client in Keycloak." width="1200" height="1023" data-path="images/tutorial-authorization/keycloak-client-auth.gif" />
</Frame>
<Warning>
**Handling Secrets**
Never embed client credentials directly in your code. We recommend using environment variables or specialized solutions for secret storage.
</Warning>
With Keycloak configured, every time the authorization flow is triggered, your MCP server will receive a token like this:
```text theme={null}
eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI1TjcxMGw1WW5MWk13WGZ1VlJKWGtCS3ZZMzZzb3JnRG5scmlyZ2tlTHlzIn0.eyJleHAiOjE3NTU1NDA4MTcsImlhdCI6MTc1NTU0MDc1NywiYXV0aF90aW1lIjoxNzU1NTM4ODg4LCJqdGkiOiJvbnJ0YWM6YjM0MDgwZmYtODQwNC02ODY3LTgxYmUtMTIzMWI1MDU5M2E4IiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4MDgwL3JlYWxtcy9tYXN0ZXIiLCJhdWQiOiJodHRwOi8vbG9jYWxob3N0OjMwMDAiLCJzdWIiOiIzM2VkNmM2Yi1jNmUwLTQ5MjgtYTE2MS1mMmY2OWM3YTAzYjkiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiI3OTc1YTViNi04YjU5LTRhODUtOWNiYS04ZmFlYmRhYjg5NzQiLCJzaWQiOiI4ZjdlYzI3Ni0zNThmLTRjY2MtYjMxMy1kYjA4MjkwZjM3NmYiLCJzY29wZSI6Im1jcDp0b29scyJ9.P5xCRtXORly0R0EXjyqRCUx-z3J4uAOWNAvYtLPXroykZuVCCJ-K1haiQSwbURqfsVOMbL7jiV-sD6miuPzI1tmKOkN_Yct0Vp-azvj7U5rEj7U6tvPfMkg2Uj_jrIX0KOskyU2pVvGZ-5BgqaSvwTEdsGu_V3_E0xDuSBq2uj_wmhqiyTFm5lJ1WkM3Hnxxx1_AAnTj7iOKMFZ4VCwMmk8hhSC7clnDauORc0sutxiJuYUZzxNiNPkmNeQtMCGqWdP1igcbWbrfnNXhJ6NswBOuRbh97_QraET3hl-CNmyS6C72Xc0aOwR_uJ7xVSBTD02OaQ1JA6kjCATz30kGYg
```
Decoded, it will look like this:
```json theme={null}
{
"alg": "RS256",
"typ": "JWT",
"kid": "5N710l5YnLZMwXfuVRJXkBKvY36sorgDnlrirgkeLys"
}.{
"exp": 1755540817,
"iat": 1755540757,
"auth_time": 1755538888,
"jti": "onrtac:b34080ff-8404-6867-81be-1231b50593a8",
"iss": "http://localhost:8080/realms/master",
"aud": "http://localhost:3000",
"sub": "33ed6c6b-c6e0-4928-a161-f2f69c7a03b9",
"typ": "Bearer",
"azp": "7975a5b6-8b59-4a85-9cba-8faebdab8974",
"sid": "8f7ec276-358f-4ccc-b313-db08290f376f",
"scope": "mcp:tools"
}.[Signature]
```
<Warning>
**Embedded Audience**
Notice the `aud` claim embedded in the token - it's currently set to be the URI of the test MCP server and it's inferred from the scope that we've previously configured. This will be important in our implementation to validate.
</Warning>
### MCP Server Setup
We will now set up our MCP server to use the locally-running Keycloak authorization server. Depending on your programming language preference, you can use one of the supported [MCP SDKs](/docs/2025-11-25/sdk).
For our testing purposes, we will create an extremely simple MCP server that exposes two tools - one for addition and another for multiplication. The server will require authorization to access these.
<Tabs>
<Tab title="TypeScript">
You can see the complete TypeScript project in the [sample repository](https://github.com/localden/min-ts-mcp-auth).
Prior to running the code below, ensure that you have a `.env` file with the following content:
```env theme={null}
# Server host/port
HOST=localhost
PORT=3000
# Auth server location
AUTH_HOST=localhost
AUTH_PORT=8080
AUTH_REALM=master
# Keycloak OAuth client credentials
OAUTH_CLIENT_ID=<YOUR_SERVER_CLIENT_ID>
OAUTH_CLIENT_SECRET=<YOUR_SERVER_CLIENT_SECRET>
```
`OAUTH_CLIENT_ID` and `OAUTH_CLIENT_SECRET` are associated with the MCP server client we created earlier.
In addition to implementing the MCP authorization specification, the server below also does token introspection via Keycloak to make sure that the token it receives from the client is valid. It also implements basic logging to allow you to easily diagnose any issues.
```typescript theme={null}
import "dotenv/config";
import express from "express";
import { randomUUID } from "node:crypto";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
import { isInitializeRequest } from "@modelcontextprotocol/sdk/types.js";
import { z } from "zod";
import cors from "cors";
import {
mcpAuthMetadataRouter,
getOAuthProtectedResourceMetadataUrl,
} from "@modelcontextprotocol/sdk/server/auth/router.js";
import { requireBearerAuth } from "@modelcontextprotocol/sdk/server/auth/middleware/bearerAuth.js";
import { OAuthMetadata } from "@modelcontextprotocol/sdk/shared/auth.js";
Cut at 300 lines. The page has the rest.
docs/2025-11-25/tutorials/security/security_best_practices New page · 897 lines, new page
# Security Best Practices ## Introduction ### Purpose and Scope ## Attacks and Mitigations ### Confused Deputy Problem #### Terminology #### Vulnerable Conditions #### Architecture and Attack Flows ##### Normal OAuth proxy usage (preserves user consent) ##### Malicious OAuth proxy usage (skips user consent) #### Attack Description #### Mitigation ##### Consent Flow Implementation ##### Required Protections ### Token Passthrough #### Risks #### Mitigation ### Server-Side Request Forgery (SSRF) #### Attack Description #### Risks #### Mitigation #### Resources and Tools ### Session Hijacking #### Session Hijack Prompt Injection #### Session Hijack Impersonation #### Attack Description #### Mitigation ### Local MCP Server Compromise #### Attack Description #### Risks #### Mitigation ### OAuth Authorization URL Validation #### Attack Description #### Risks #### Mitigation ### stdio Transport Security in Proxy Scenarios #### Attack Description #### Risks #### Mitigation ### Scope Minimization #### Attack Description #### Risks #### Mitigation #### Common Mistakes
A whole new page. There's nothing to diff it against, so here is what it says.
# Security Best Practices
> Security considerations, attack vectors, and best practices for MCP implementations
## Introduction
### Purpose and Scope
This document provides security considerations for the Model Context
Protocol (MCP), complementing the
[MCP Authorization](/specification/2025-11-25/basic/authorization)
specification. This document identifies security risks, attack vectors,
and best practices specific to MCP implementations.
The primary audience for this document includes developers implementing
MCP authorization flows, MCP server operators, and security
professionals evaluating MCP-based systems. This document should be read
alongside the MCP Authorization specification and
[OAuth 2.0 security best practices](https://datatracker.ietf.org/doc/html/rfc9700).
## Attacks and Mitigations
This section gives a detailed description of attacks on MCP
implementations, along with potential countermeasures.
### Confused Deputy Problem
Attackers can exploit MCP proxy servers that connect to third-party
APIs, creating
"[confused deputy](https://en.wikipedia.org/wiki/Confused_deputy_problem)"
vulnerabilities. This attack allows malicious clients to obtain
authorization codes without proper user consent by exploiting the
combination of static client IDs, dynamic client registration, and
consent cookies.
#### Terminology
**MCP Proxy Server**
: An MCP server that connects MCP clients to third-party APIs, offering
MCP features while delegating operations and acting as a single OAuth
client to the third-party API server.
**Third-Party Authorization Server**
: Authorization server that protects the third-party API. It may lack
dynamic client registration support, requiring the MCP proxy to use a
static client ID for all requests.
**Third-Party API**
: The protected resource server that provides the actual API
functionality. Access to this API requires tokens issued by the
third-party authorization server.
**Static Client ID**
: A fixed OAuth 2.0 client identifier used by the MCP proxy server when
communicating with the third-party authorization server. This Client ID
refers to the MCP server acting as a client to the Third-Party API. It
is the same value for all MCP server to Third-Party API interactions
regardless of which MCP client initiated the request.
#### Vulnerable Conditions
This attack becomes possible when all of the following conditions are
present:
* MCP proxy server uses a **static client ID** with a third-party
authorization server
* MCP proxy server allows MCP clients to **dynamically register** (each
getting their own client\_id)
* The third-party authorization server sets a **consent cookie** after
the first authorization
* MCP proxy server does not implement proper per-client consent before
forwarding to third-party authorization
#### Architecture and Attack Flows
##### Normal OAuth proxy usage (preserves user consent)
```mermaid theme={null}
sequenceDiagram
participant UA as User-Agent (Browser)
participant MC as MCP Client
participant M as MCP Proxy Server
participant TAS as Third-Party Authorization Server
Note over UA,M: Initial Auth flow completed
Note over UA,TAS: Step 1: Legitimate user consent for Third Party Server
M->>UA: Redirect to third party authorization server
UA->>TAS: Authorization request (client_id: mcp-proxy)
TAS->>UA: Authorization consent screen
Note over UA: Review consent screen
UA->>TAS: Approve
TAS->>UA: Set consent cookie for client ID: mcp-proxy
TAS->>UA: 3P Authorization code + redirect to mcp-proxy-server.com
UA->>M: 3P Authorization code
Note over M,TAS: Exchange 3P code for 3P token
Note over M: Generate MCP authorization code
M->>UA: Redirect to MCP Client with MCP authorization code
Note over M,UA: Exchange code for token, etc.
```
##### Malicious OAuth proxy usage (skips user consent)
```mermaid theme={null}
sequenceDiagram
participant UA as User-Agent (Browser)
participant M as MCP Proxy Server
participant TAS as Third-Party Authorization Server
participant A as Attacker
Note over UA,A: Step 2: Attack (leveraging existing cookie, skipping consent)
A->>M: Dynamically register malicious client, redirect_uri: attacker.com
A->>UA: Sends malicious link
UA->>TAS: Authorization request (client_id: mcp-proxy) + consent cookie
rect rgba(255, 17, 0, 0.67)
TAS->>TAS: Cookie present, consent skipped
end
TAS->>UA: 3P Authorization code + redirect to mcp-proxy-server.com
UA->>M: 3P Authorization code
Note over M,TAS: Exchange 3P code for 3P token
Note over M: Generate MCP authorization code
M->>UA: Redirect to attacker.com with MCP Authorization code
UA->>A: MCP Authorization code delivered to attacker.com
Note over M,A: Attacker exchanges MCP code for MCP token
A->>M: Attacker impersonates user to MCP server
```
#### Attack Description
When an MCP proxy server uses a static client ID to authenticate with
a third-party authorization server, the following attack becomes
possible:
1. A user authenticates normally through the MCP proxy server to access
the third-party API
2. During this flow, the third-party authorization server sets a cookie
on the user agent indicating consent for the static client ID
3. An attacker later sends the user a malicious link containing a
crafted authorization request which contains a malicious redirect URI
along with a new dynamically registered client ID
4. When the user clicks the link, their browser still has the consent
cookie from the previous legitimate request
5. The third-party authorization server detects the cookie and skips the
consent screen
6. The MCP authorization code is redirected to the attacker's server
(specified in the malicious `redirect_uri` parameter during
[dynamic client registration](/specification/2025-11-25/basic/authorization#dynamic-client-registration))
7. The attacker exchanges the stolen authorization code for access
tokens for the MCP server without the user's explicit approval
8. The attacker now has access to the third-party API as the compromised
user
#### Mitigation
To prevent confused deputy attacks, MCP proxy servers **MUST** implement
per-client consent and proper security controls as detailed below.
##### Consent Flow Implementation
The following diagram shows how to properly implement per-client consent
that runs **before** the third-party authorization flow:
```mermaid theme={null}
sequenceDiagram
participant Client as MCP Client
participant Browser as User's Browser
participant MCP as MCP Server
participant ThirdParty as Third-Party AuthZ Server
Note over Client,ThirdParty: 1. Client Registration (Dynamic)
Client->>MCP: Register with redirect_uri
MCP-->>Client: client_id
Note over Client,ThirdParty: 2. Authorization Request
Client->>Browser: Open MCP server authorization URL
Browser->>MCP: GET /authorize?client_id=...&redirect_uri=...
alt Check MCP Server Consent
MCP->>MCP: Check consent for this client_id
Note over MCP: Not previously approved
end
MCP->>Browser: Show MCP server-owned consent page
Note over Browser: "Allow [Client Name] to access [Third-Party API]?"
Browser->>MCP: POST /consent (approve)
MCP->>MCP: Store consent decision for client_id
Note over Client,ThirdParty: 3. Forward to Third-Party
MCP->>Browser: Redirect to third-party /authorize
Note over MCP: Use static client_id for third-party
Browser->>ThirdParty: Authorization request (static client_id)
ThirdParty->>Browser: User authenticates & consents
ThirdParty->>Browser: Redirect with auth code
Browser->>MCP: Callback with third-party code
MCP->>ThirdParty: Exchange code for token (using static client_id)
MCP->>Browser: Redirect to client's registered redirect_uri
```
##### Required Protections
**Per-Client Consent Storage**
MCP proxy servers **MUST**:
* Maintain a registry of approved `client_id` values per user
* Check this registry **before** initiating the third-party
authorization flow
* Store consent decisions securely (server-side database, or server
specific cookies)
**Consent UI Requirements**
The MCP-level consent page **MUST**:
* Clearly identify the requesting MCP client by name
* Display the specific third-party API scopes being requested
* Show the registered `redirect_uri` where tokens will be sent
* Implement CSRF protection (e.g., state parameter, CSRF tokens)
* Prevent iframing via `frame-ancestors` CSP directive or
`X-Frame-Options: DENY` to prevent clickjacking
**Consent Cookie Security**
If using cookies to track consent decisions, they **MUST**:
* Use `__Host-` prefix for cookie names
* Set `Secure`, `HttpOnly`, and `SameSite=Lax` attributes
* Be cryptographically signed or use server-side sessions
* Bind to the specific `client_id` (not just "user has consented")
**Redirect URI Validation**
The MCP proxy server **MUST**:
* Validate that the `redirect_uri` in authorization requests exactly
matches the registered URI
* Reject requests if the `redirect_uri` has changed without
re-registration
* Use exact string matching (not pattern matching or wildcards)
**OAuth State Parameter Validation**
The OAuth `state` parameter is critical to prevent authorization code
interception and CSRF attacks. Proper state validation ensures that
consent approval at the authorization endpoint is enforced at the
callback endpoint.
MCP proxy servers implementing OAuth flows **MUST**:
* Generate a cryptographically secure random `state` value for each
authorization request
* Store the `state` value server-side (in a secure session store or
encrypted cookie) **only after** consent has been explicitly approved
* Set the `state` tracking cookie/session **immediately before**
redirecting to the third-party identity provider (not before consent
approval)
* Validate at the callback endpoint that the `state` query parameter
exactly matches the stored value in the callback request's cookies or
in the request's cookie-based session
* Reject any callback requests where the `state` parameter is missing
or does not match
* Ensure `state` values are single-use (delete after validation) and
have a short expiration time (e.g., 10 minutes)
The consent cookie or session containing the `state` value **MUST NOT**
be set until **after** the user has approved the consent screen at the
MCP server's authorization endpoint. Setting this cookie before consent
approval renders the consent screen ineffective, as an attacker could
bypass it by crafting a malicious authorization request.
### Token Passthrough
"Token passthrough" is an anti-pattern where an MCP server accepts
tokens from an MCP client without validating that the tokens were
properly issued *to the MCP server* and passes them through to the
downstream API.
#### Risks
Token passthrough is explicitly forbidden in the
[authorization specification](/specification/2025-11-25/basic/authorization)
as it introduces a number of security risks, that include:
* **Security Control Circumvention**
* The MCP Server or downstream APIs might implement important security
controls like rate limiting, request validation, or traffic
monitoring, that depend on the token audience or other credential
constraints. If clients can obtain and use tokens directly with the
downstream APIs without the MCP server validating them properly or
ensuring that the tokens are issued for the right service, they
bypass these controls.
* **Accountability and Audit Trail Issues**
* The MCP Server will be unable to identify or distinguish between MCP
Clients when clients are calling with an upstream-issued access token
Cut at 300 lines. The page has the rest.
docs/draft/develop/build-client New page · 2518 lines, new page
# Build an MCP client ## Next steps
A whole new page. There's nothing to diff it against, so here is what it says.
# Build an MCP client
> Get started building your own client that can integrate with all MCP servers.
In this tutorial, you'll learn how to build an LLM-powered chatbot client that connects to MCP servers.
Before you begin, it helps to have gone through our [Build an MCP Server](/docs/draft/develop/build-server) tutorial so you can understand how clients and servers communicate.
<Tabs>
<Tab title="Python">
[You can find the complete code for this tutorial here.](https://github.com/modelcontextprotocol/quickstart-resources/tree/main/mcp-client-python)
## System Requirements
Before starting, ensure your system meets these requirements:
* Mac or Windows computer
* Latest Python version installed
* Latest version of `uv` installed
* You must use the Python MCP SDK 2.0.0 or higher
## Setting Up Your Environment
First, create a new Python project with `uv`:
<CodeGroup>
```bash macOS/Linux theme={null}
# Create project directory
uv init mcp-client
cd mcp-client
# Create virtual environment
uv venv
# Activate virtual environment
source .venv/bin/activate
# Install required packages
uv add mcp anthropic python-dotenv
# Remove boilerplate files
rm main.py
# Create our main file
touch client.py
```
```powershell Windows theme={null}
# Create project directory
uv init mcp-client
cd mcp-client
# Create virtual environment
uv venv
# Activate virtual environment
.venv\Scripts\activate
# Install required packages
uv add mcp anthropic python-dotenv
# Remove boilerplate files
del main.py
# Create our main file
new-item client.py
```
</CodeGroup>
## Setting Up Your API Key
You'll need an Anthropic API key from the [Anthropic Console](https://console.anthropic.com/settings/keys).
Create a `.env` file to store it:
```bash theme={null}
echo "ANTHROPIC_API_KEY=your-api-key-goes-here" > .env
```
Add `.env` to your `.gitignore`:
```bash theme={null}
echo ".env" >> .gitignore
```
<Warning>
Make sure you keep your `ANTHROPIC_API_KEY` secure!
</Warning>
## Creating the Client
### Imports and Setup
First, let's set up our imports and the pieces the rest of the file shares:
```python theme={null}
import asyncio
import sys
from mcp import Client, StdioServerParameters
from mcp.client.stdio import stdio_client
from mcp_types import TextContent
from anthropic import Anthropic
from dotenv import load_dotenv
load_dotenv() # load environment variables from .env
MODEL = "claude-opus-5"
anthropic = Anthropic()
```
`Client` is the single object your program talks to the server through. Listing the tools, calling one, reading a resource: each of those is a method on it.
### Server Connection Management
Next, we'll work out which process to launch for a given server script:
```python theme={null}
def server_params(server_script_path: str) -> StdioServerParameters:
"""Describe the subprocess that runs an MCP server
Args:
server_script_path: Path to the server script (.py or .js)
"""
if server_script_path.endswith(".py"):
command = "python"
elif server_script_path.endswith(".js"):
command = "node"
else:
raise ValueError("Server script must be a .py or .js file")
return StdioServerParameters(command=command, args=[server_script_path])
```
`StdioServerParameters` is configuration, not a connection. `stdio_client()` turns it into a stdio transport, and `Client` opens that transport when you enter its `async with` block. We'll do both in `main()`.
### Query Processing Logic
Now let's add the core functionality for processing queries and handling tool calls:
```python theme={null}
async def process_query(client: Client, query: str) -> str:
"""Process a query using Claude and available tools"""
messages = [
{
"role": "user",
"content": query
}
]
tool_list = await client.list_tools()
available_tools = [{
"name": tool.name,
"description": tool.description,
"input_schema": tool.input_schema
} for tool in tool_list.tools]
# Initial Claude API call
response = anthropic.messages.create(
model=MODEL,
max_tokens=1000,
messages=messages,
tools=available_tools
)
# Process response and handle tool calls
final_text = []
tool_results = []
for content in response.content:
if content.type == 'text':
final_text.append(content.text)
elif content.type == 'tool_use':
tool_name = content.name
tool_args = content.input
# Execute tool call
result = await client.call_tool(tool_name, tool_args)
final_text.append(f"[Calling tool {tool_name} with args {tool_args}]")
tool_results.append({
"type": "tool_result",
"tool_use_id": content.id,
"content": "\n".join(
block.text
for block in result.content
if isinstance(block, TextContent)
),
"is_error": result.is_error
})
if tool_results:
messages.append({"role": "assistant", "content": response.content})
messages.append({"role": "user", "content": tool_results})
# Get next response from Claude
response = anthropic.messages.create(
model=MODEL,
max_tokens=1000,
messages=messages,
tools=available_tools
)
for content in response.content:
if content.type == 'text':
final_text.append(content.text)
return "\n".join(final_text)
```
`call_tool` returns a `CallToolResult`. Its `content` is a list of blocks, which is why we narrow to `TextContent` before reading `.text`. A tool that raises does not raise here: it answers with `is_error` set, and passing that flag on lets Claude read the message and try something else.
### Interactive Chat Interface
Now we'll add the chat loop:
```python theme={null}
async def chat_loop(client: Client) -> None:
"""Run an interactive chat loop"""
print("\nMCP Client Started!")
print("Type your queries or 'quit' to exit.")
while True:
try:
query = (await asyncio.to_thread(input, "\nQuery: ")).strip()
except EOFError:
break
if query.lower() == 'quit':
break
try:
response = await process_query(client, query)
print("\n" + response)
except Exception as e:
print(f"\nError: {e}")
```
`input()` blocks, so it runs on a worker thread. That keeps the event loop free to service the connection while you type.
### Main Entry Point
Finally, we'll add the main execution logic:
```python theme={null}
async def main() -> None:
if len(sys.argv) < 2:
print("Usage: python client.py <path_to_server_script>")
sys.exit(1)
async with Client(stdio_client(server_params(sys.argv[1]))) as client:
tool_list = await client.list_tools()
tool_names = [tool.name for tool in tool_list.tools]
print("\nConnected to server with tools:", tool_names)
await chat_loop(client)
if __name__ == "__main__":
asyncio.run(main())
```
That `async with` is the entire connection lifecycle. Entering it launches the server and agrees a protocol version with it; leaving it disconnects and shuts the subprocess down. There is nothing to close by hand.
You can find the complete `client.py` file [here](https://github.com/modelcontextprotocol/quickstart-resources/blob/main/mcp-client-python/client.py).
## Key Components Explained
### 1. Client Initialization
* A single `Client` carries the connection, and `async with` is its whole lifecycle
* There is no connect/close pair to call and nothing to clean up afterwards
* Configures the Anthropic client for Claude interactions
### 2. Server Connection
* Supports both Python and Node.js servers
* Validates server script type
* Launches the server as a subprocess and speaks stdio to it
* Lists the available tools once the connection is open
### 3. Query Processing
* Maintains conversation context
* Handles Claude's responses and tool calls
* Manages the message flow between Claude and tools
* Combines results into a coherent response
### 4. Interactive Interface
* Provides a simple command-line interface
* Handles user input and displays responses
* Includes basic error handling
* Allows graceful exit
### 5. Resource Management
* Leaving the `async with` block disconnects and shuts the server subprocess down
* A failing query is reported without ending the session
Cut at 300 lines. The page has the rest.
docs/draft/develop/build-server New page · 3003 lines, new page
# Build an MCP server ### What we'll be building ### Core MCP Concepts ### Test with commands ## What's happening under the hood ## Troubleshooting ## Next steps
A whole new page. There's nothing to diff it against, so here is what it says.
# Build an MCP server
> Get started building your own server to use in Claude for Desktop and other clients.
In this tutorial, we'll build a simple MCP weather server and connect it to a host, Claude for Desktop.
### What we'll be building
We'll build a server that exposes two tools: `get_alerts` and `get_forecast`. Then we'll connect the server to an MCP host (in this case, Claude for Desktop):
<Frame>
<img src="https://mintcdn.com/mcp/4ZXF1PrDkEaJvXpn/images/current-weather.png?fit=max&auto=format&n=4ZXF1PrDkEaJvXpn&q=85&s=dce7b2f8a06c20ba358e4bd2e75fa4c7" width="2780" height="1849" data-path="images/current-weather.png" />
</Frame>
<Note>
Servers can connect to any client. We've chosen Claude for Desktop here for simplicity, but we also have a guide on [building your own client](/docs/draft/develop/build-client).
</Note>
### Core MCP Concepts
MCP servers can provide three main types of capabilities:
1. **[Resources](/docs/draft/learn/server-concepts#resources)**: File-like data that can be read by clients (like API responses or file contents)
2. **[Tools](/docs/draft/learn/server-concepts#tools)**: Functions that can be called by the LLM (with user approval)
3. **[Prompts](/docs/draft/learn/server-concepts#prompts)**: Pre-written templates that help users accomplish specific tasks
This tutorial will primarily focus on tools.
<Tabs>
<Tab title="Python">
Let's get started with building our weather server! [You can find the complete code for what we'll be building here.](https://github.com/modelcontextprotocol/quickstart-resources/tree/main/weather-server-python)
### Prerequisite knowledge
This quickstart assumes you have familiarity with:
* Python
* LLMs like Claude
### Logging in MCP Servers
When implementing MCP servers, be careful about how you handle logging:
**For STDIO-based servers:** Never write to stdout. Writing to stdout will corrupt the JSON-RPC messages and break your server. The `print()` function writes to stdout by default, so keep it out of a STDIO server entirely.
**For HTTP-based servers:** Standard output logging is fine since it doesn't interfere with HTTP responses.
### Best Practices
* Use the standard library `logging` module, which writes to stderr.
* Create one logger per module with `logging.getLogger(__name__)` and call it from your tools.
### Quick Examples
```python theme={null}
import logging
logger = logging.getLogger(__name__)
# ❌ Bad (STDIO)
print("Processing request")
# ✅ Good (STDIO)
logger.info("Processing request") # writes to stderr
```
### System requirements
* Python 3.10 or higher installed.
* You must use the Python MCP SDK 2.0.0 or higher.
### Set up your environment
First, let's install `uv` and set up our Python project and environment:
<CodeGroup>
```bash macOS/Linux theme={null}
curl -LsSf https://astral.sh/uv/install.sh | sh
```
```powershell Windows theme={null}
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
```
</CodeGroup>
Make sure to restart your terminal afterwards to ensure that the `uv` command gets picked up.
Now, let's create and set up our project:
<CodeGroup>
```bash macOS/Linux theme={null}
# Create a new directory for our project
uv init weather
cd weather
# Create virtual environment and activate it
uv venv
source .venv/bin/activate
# Install dependencies
uv add "mcp[cli]"
# Create our server file
touch weather.py
```
```powershell Windows theme={null}
# Create a new directory for our project
uv init weather
cd weather
# Create virtual environment and activate it
uv venv
.venv\Scripts\activate
# Install dependencies
uv add mcp[cli]
# Create our server file
new-item weather.py
```
</CodeGroup>
Now let's dive into building your server.
## Building your server
### Importing packages and setting up the instance
Add these to the top of your `weather.py`:
```python theme={null}
from typing import Any
import httpx2
from mcp.server import MCPServer
# Initialize MCPServer
mcp = MCPServer("weather")
# Constants
NWS_API_BASE = "https://api.weather.gov"
USER_AGENT = "weather-app/1.0"
```
`httpx2` is the HTTP client the SDK itself depends on, so installing `mcp` already brought it in.
The MCPServer class uses Python type hints and docstrings to automatically generate tool definitions, making it easy to create and maintain MCP tools.
### Helper functions
Next, let's add our helper functions for querying and formatting the data from the National Weather Service API:
```python theme={null}
async def make_nws_request(url: str) -> dict[str, Any] | None:
"""Make a request to the NWS API with proper error handling."""
headers = {"User-Agent": USER_AGENT, "Accept": "application/geo+json"}
async with httpx2.AsyncClient() as client:
try:
response = await client.get(url, headers=headers, timeout=30.0)
response.raise_for_status()
return response.json()
except Exception:
return None
def format_alert(feature: dict) -> str:
"""Format an alert feature into a readable string."""
props = feature["properties"]
return f"""
Event: {props.get("event", "Unknown")}
Area: {props.get("areaDesc", "Unknown")}
Severity: {props.get("severity", "Unknown")}
Description: {props.get("description", "No description available")}
Instructions: {props.get("instruction", "No specific instructions provided")}
"""
```
### Implementing tool execution
The tool execution handler is responsible for actually executing the logic of each tool. Let's add it:
```python theme={null}
@mcp.tool()
async def get_alerts(state: str) -> str:
"""Get weather alerts for a US state.
Args:
state: Two-letter US state code (e.g. CA, NY)
"""
url = f"{NWS_API_BASE}/alerts/active/area/{state}"
data = await make_nws_request(url)
if not data or "features" not in data:
return "Unable to fetch alerts or no alerts found."
if not data["features"]:
return "No active alerts for this state."
alerts = [format_alert(feature) for feature in data["features"]]
return "\n---\n".join(alerts)
@mcp.tool()
async def get_forecast(latitude: float, longitude: float) -> str:
"""Get weather forecast for a location.
Args:
latitude: Latitude of the location
longitude: Longitude of the location
"""
# First get the forecast grid endpoint
points_url = f"{NWS_API_BASE}/points/{latitude},{longitude}"
points_data = await make_nws_request(points_url)
if not points_data:
return "Unable to fetch forecast data for this location."
# Get the forecast URL from the points response
forecast_url = points_data["properties"]["forecast"]
forecast_data = await make_nws_request(forecast_url)
if not forecast_data:
return "Unable to fetch detailed forecast."
# Format the periods into a readable forecast
periods = forecast_data["properties"]["periods"]
forecasts = []
for period in periods[:5]: # Only show next 5 periods
forecast = f"""
{period["name"]}:
Temperature: {period["temperature"]}°{period["temperatureUnit"]}
Wind: {period["windSpeed"]} {period["windDirection"]}
Forecast: {period["detailedForecast"]}
"""
forecasts.append(forecast)
return "\n---\n".join(forecasts)
```
### Running the server
Finally, let's initialize and run the server:
```python theme={null}
if __name__ == "__main__":
mcp.run(transport="stdio")
```
Your server is complete! Run `uv run weather.py` to start the MCP server, which will listen for messages from MCP hosts.
Let's now test your server from an existing MCP host, Claude for Desktop.
## Testing your server with Claude for Desktop
First, make sure you have Claude for Desktop installed. [You can install the latest version
here.](https://claude.ai/download) If you already have Claude for Desktop, **make sure it's updated to the latest version.**
We'll need to configure Claude for Desktop for whichever MCP servers you want to use. To do this, open your Claude for Desktop App configuration at `~/Library/Application Support/Claude/claude_desktop_config.json` in a text editor. Make sure to create the file if it doesn't exist.
For example, if you have [VS Code](https://code.visualstudio.com/) installed:
<CodeGroup>
```bash Linux theme={null}
code ~/.config/Claude/claude_desktop_config.json
```
```bash macOS theme={null}
code ~/Library/Application\ Support/Claude/claude_desktop_config.json
```
```powershell Windows theme={null}
code $env:AppData\Claude\claude_desktop_config.json
```
</CodeGroup>
You'll then add your servers in the `mcpServers` key. The MCP UI elements will only show up in Claude for Desktop if at least one server is properly configured.
In this case, we'll add our single weather server like so:
<CodeGroup>
```json macOS/Linux theme={null}
{
"mcpServers": {
"weather": {
"command": "uv",
"args": [
"--directory",
"/ABSOLUTE/PATH/TO/PARENT/FOLDER/weather",
"run",
"weather.py"
]
}
}
}
```
```json Windows theme={null}
{
"mcpServers": {
Cut at 300 lines. The page has the rest.
docs/draft/develop/build-with-agent-skills New page · 100 lines, new page
# Build with Agent Skills ## Available skills ## Start a build ## Deployment paths ## Next steps
A whole new page. There's nothing to diff it against, so here is what it says.
# Build with Agent Skills
> Use agent skills to guide AI coding assistants through MCP server design and implementation
[Agent skills](https://agentskills.io/home) are portable instruction sets that
give AI coding assistants domain knowledge for a task. For MCP development,
they encode the design decisions (deployment model, tool patterns, auth) so
your agent can interrogate your use case and scaffold a server that fits.
## Available skills
A reference set of MCP development skills is available as the
[`mcp-server-dev` plugin](https://github.com/anthropics/claude-plugins-official/tree/main/plugins/mcp-server-dev).
It provides three composing skills:
| Skill | Purpose |
| ------------------ | ----------------------------------------------------------------------------------------------------------------------- |
| `build-mcp-server` | Entry point. Interrogates the use case, picks a deployment model and tool-design pattern, routes to specialized skills. |
| `build-mcp-app` | Adds interactive UI widgets (forms, pickers, dashboards) rendered inline in chat. |
| `build-mcpb` | Packages a local stdio server with its runtime so users can install it without Node or Python. |
Each skill ships a `SKILL.md` file plus a `references/` folder of supporting
material (auth flows, tool-design patterns, widget templates, manifest schemas)
that the agent reads on demand. The files follow the open format and work with
any agent that implements the standard. For example, to install them in Claude
Code:
```bash theme={null}
/plugin marketplace add anthropics/claude-plugins-official
/plugin install mcp-server-dev
```
For other agents, check your skills or extensions catalog, or clone the
[skill directories](https://github.com/anthropics/claude-plugins-official/tree/main/plugins/mcp-server-dev/skills)
(`SKILL.md` plus `references/`) into your agent's skills location.
## Start a build
With the skills installed, ask your agent to help you build an MCP server. The
entry skill triggers on natural-language requests, or you can invoke it
directly using your agent's skill-invocation syntax.
The skill runs a short discovery phase before writing any code. Expect
questions about:
* **What it connects to** — a cloud API, a local process, the filesystem, hardware
* **Who will use it** — just you, your team, or anyone who installs it
* **Action surface size** — a handful of operations versus wrapping a large API
* **User interaction needs** — plain text results, structured input via
[elicitation](/specification/draft/client/elicitation), or rich UI widgets
* **Upstream auth** — API keys, OAuth 2.0, or none
If your opening message already covers these, the agent skips ahead to the
recommendation.
## Deployment paths
Based on discovery, the skill recommends one of four paths and scaffolds
accordingly:
**Remote [Streamable HTTP](/specification/draft/basic/transports/streamable-http)**
is the default for anything wrapping a cloud API. Zero install friction, one
deployment serves all users, and OAuth flows work properly because the server
can handle redirects and token storage. The reference skill includes scaffolds
for Cloudflare Workers and portable Express/FastMCP setups.
**[MCP apps](/extensions/apps/overview)** extend a server with interactive
widgets rendered in chat, such as searchable pickers, charts, and live
dashboards. The skill hands off to `build-mcp-app` when
[elicitation's](/specification/draft/client/elicitation) flat-form constraints
don't fit.
**[MCP Bundles (MCPB)](https://github.com/modelcontextprotocol/mcpb)** package a
local server together with its runtime as a single `.mcpb` archive, so users
can install it without setting up Node or Python. Use this path when the server
must touch the user's machine: reading local files, driving desktop apps, or
talking to localhost services. The skill hands off to `build-mcpb`.
**Local [stdio](/specification/draft/basic/transports/stdio)** remains available
for prototyping, with a noted upgrade path to MCPB when you're ready to
distribute.
## Next steps
Once your agent scaffolds the server, iterate on tool descriptions and error
handling, then test and ship:
<CardGroup cols={2}>
<Card title="MCP Inspector" icon="magnifying-glass" href="/docs/draft/tools/inspector">
Test your server's tools, resources, and prompts interactively
</Card>
<Card title="Connect to a client" icon="plug" href="/docs/draft/develop/connect-local-servers">
Wire your server into an MCP client via local or remote configuration
</Card>
<Card title="Publish to the Registry" icon="box" href="/registry/quickstart">
Make your server discoverable in the MCP Registry
</Card>
</CardGroup>
docs/draft/develop/clients/client-best-practices New page · 301 lines, new page
# Client Best Practices ## Progressive Tool Discovery ### When to Use Progressive Discovery ### Choosing a Discovery Strategy ### Using Progressive Discovery ### Dynamic Server Management ### Implementation Guidelines ### Caching ### Interaction with Prompt Caching ## Programmatic Tool Calling / Code Mode ### How It Works ### Choosing a Sandbox ### Execution Architecture ### Security Considerations ### Error Handling ## Combining Both Patterns
A whole new page. There's nothing to diff it against, so here is what it says.
# Client Best Practices
> Patterns for scaling MCP host applications across many servers and tools.
As MCP host applications, such as agents, connect to more MCP servers and accumulate access to hundreds or thousands of tools, naive approaches to tool management break down. Loading every tool definition into the model's context window upfront wastes tokens, increases latency, and degrades model performance. Passing large intermediate results through the model between sequential tool calls compounds the problem.
Two patterns address these challenges: **progressive discovery**, which controls *when* tool definitions enter context, and **programmatic tool calling**, which controls *how* tools are invoked.
## Progressive Tool Discovery
Naive MCP host implementations pass the tool definitions of every connected server directly to the model at the start of each conversation. For a handful of tools, this is perfectly reasonable. But when a host has access to dozens of servers exposing hundreds of tools, those definitions alone can consume the majority of the context window before the model has even read the user's message.
<img src="https://mintcdn.com/mcp/JXfd5cBmEUh_qPUI/images/progressive-discovery.svg?fit=max&auto=format&n=JXfd5cBmEUh_qPUI&q=85&s=db39f47006107f04af43b5eeae2d6022" alt="Comparison of loading all tools upfront versus discovering tools on demand. The upfront approach consumes ~150,000 tokens on definitions alone, while progressive discovery uses ~2,000 tokens by loading only what the task requires." width="760" height="440" data-path="images/progressive-discovery.svg" />
Progressive discovery avoids this:
* The host fetches tool definitions via `tools/list` as normal, but defers injecting them into the model's context.
* The host provides a lightweight `search_tools` meta-tool to the model.
* The host loads full definitions into context only as needed.
### When to Use Progressive Discovery
Progressive discovery is best used when tool definitions take large parts of the context window. For a small
set of tools with tool definitions taking up a small part of the context window, loading all tools is fine.
Once the tool definitions take up a significant part of the available context window, clients should switch to progressive discovery. We recommend that clients implement thresholds to determine when to switch:
* Implement a threshold as a percentage of the context window. For example, 1%-5%.
* Load tool definitions. Once the threshold is reached, switch to progressive discovery.
### Choosing a Discovery Strategy
Once the model invokes the `search_tools` tool, we need to choose a search strategy:
* **Keyword-based**: Keyword matching (BM25, regex). Simple and effective, particularly for descriptive tool names and descriptions.
* **Embedding-based**: Vector-similarity retrieval over tool descriptions. Handles synonyms and semantic matching better.
* **Subagent-based**: A secondary model, often a small and fast model such as Claude Haiku or Gemini Flash, selects tools for the task. This usually works very well but can be more costly than embedding-based or keyword-based solutions.
* **Hybrid**: Combine approaches. For example, by scoring across keyword and embedding rankings, or choosing
different strategies depending on use-case or query.
Some model providers already offer built-in tool search. For example, [OpenAI](https://developers.openai.com/api/docs/guides/tools-tool-search) and [Anthropic](https://platform.claude.com/docs/en/agents-and-tools/tool-use/tool-search-tool) support this natively; check your provider's documentation for an equivalent. When available, you may prefer the platform's tool search over a custom implementation. Build your own when the provider doesn't offer one or when you need specialized retrieval logic (e.g., domain-specific ranking or access-control filtering).
The three-layer pattern below illustrates a custom search-based approach in detail, but the layered principle (catalog, inspect, execute) applies regardless of retrieval mechanism.
### Using Progressive Discovery
One common implementation for progressive discovery uses a search-based three-layer approach:
**Layer 1: Catalog.** The host exposes a small set of meta-tools for searching available capabilities. A `search_tools` tool accepts a natural-language query and returns matching tool names with brief descriptions.
```typescript theme={null}
// The model calls a lightweight search tool
search_tools({ query: "update salesforce record" })
// Returns concise matches: names and one-line descriptions only
→ [
{ name: "salesforce_updateRecord", description: "Update fields on a Salesforce object" },
{ name: "salesforce_upsertRecord", description: "Insert or update based on external ID" }
]
```
**Layer 2: Inspect.** Once the model identifies a candidate, it fetches the full definition (input schema, output schema, documentation) for that tool only.
```typescript theme={null}
// The model inspects only the tool it needs
get_tool_details({ name: "salesforce_updateRecord" });
```
This returns the complete schema for a single tool:
```json theme={null}
{
"name": "salesforce_updateRecord",
"description": "Updates a record in Salesforce",
"inputSchema": {
"type": "object",
"properties": {
"objectType": {
"type": "string",
"description": "Salesforce object type"
},
"recordId": { "type": "string", "description": "Record ID to update" },
"data": { "type": "object", "description": "Fields to update" }
},
"required": ["objectType", "recordId", "data"]
}
}
```
**Layer 3: Execute.** The model calls the tool with full knowledge of its interface, having loaded only the definitions it needed.
This pattern reduces token usage dramatically and can improve tool selection accuracy: the model focuses on a few relevant tools rather than scanning hundreds of irrelevant ones. Other discovery strategies (embeddings, subagents, etc.) follow the same layered principle but substitute different retrieval mechanisms in the catalog layer.
### Dynamic Server Management
Progressive discovery extends beyond individual tools to entire servers. Rather than connecting to every configured server at startup, a host can:
1. Maintain a registry of available servers and their high-level descriptions.
2. Connect to a server only when the model determines it needs that server's capabilities.
3. Disconnect servers that are no longer relevant to the current task, freeing context.
```mermaid theme={null}
sequenceDiagram
participant Model
participant Host
participant Registry
participant Server
Model->>Host: search_available_servers("CRM")
Host->>Registry: Query available servers
Registry-->>Host: Salesforce server (not connected)
Host-->>Model: Salesforce server available
Model->>Host: enable_server("salesforce")
Host->>Server: server/discover
Server-->>Host: Supported versions + capabilities
Host->>Server: tools/list
Server-->>Host: Tool definitions
Host-->>Model: Salesforce server connected
Note over Model: Task complete
Model->>Host: disable_server("salesforce")
Host-->>Model: Server disconnected, context freed
```
This works especially well for general-purpose agents, where the user's intent isn't known upfront. The agent starts with a minimal set of always-on servers and connects others as needed. Combined with [agent skills](/docs/draft/develop/build-with-agent-skills), a skill file can declare which MCP servers it needs, and the host connects them only when that skill is invoked.
### Implementation Guidelines
When implementing progressive discovery:
| Guideline | Rationale |
| -------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Offer multiple detail levels** | Let the model choose between name-only, name-and-description, or full-schema responses. |
| **Cache tool definitions** | Once fetched from a server, memoize the definition host-side so re-injecting it later doesn't need another `tools/list` round trip. This is separate from what's currently in the model's context. |
| **Refresh on `list_changed`** | Re-index the search catalog when a server sends `notifications/tools/list_changed`. |
| **Group tools by server** | Present tools organized by their source server so the model can reason about related capabilities. |
### Caching
Each list result (such as `tools/list`), as well as each `server/discover` and
`resources/read` result, carries `ttlMs` and `cacheScope` hints. Follow them as defined in the
specification's [caching utility](/specification/draft/server/utilities/caching). In particular,
treat a cached list as stale once a `list_changed` notification arrives, even before its TTL
expires.
### Interaction with Prompt Caching
Most providers cache the prompt prefix, including the `tools` array. Adding or removing tool
definitions mid-conversation invalidates that cache, and the resulting miss can cost more tokens
than the definitions you removed. To preserve caching:
* Append newly discovered definitions after the cache breakpoint rather than re-sorting the
`tools` array, or route every call through a single stable `call_tool({name, args})` meta-tool
so the array never changes.
* Treat server disconnection as a conversation-boundary operation rather than a per-turn one.
* Consult your provider's caching documentation alongside the tool-search links above.
## Programmatic Tool Calling / Code Mode
With direct tool calling, every tool invocation is a round trip: the model generates a tool call, the client executes it, and the full result flows back into the model's context. When a task requires chaining multiple tools (read a document, transform it, write it somewhere else), each intermediate result passes through the model, consuming tokens and adding latency even when it has nothing to do with them.
Programmatic tool calling (sometimes called "code mode") provides a way for clients to **compose tool calls** effectively. Instead of calling tools directly, the model writes code that calls tools. The code executes in a sandboxed environment, and only the final result returns to the model.
Programmatic tool calling is powerful and allows for more efficient use of MCP tools and resources, but requires
clients to implement a sandbox environment.
<img src="https://mintcdn.com/mcp/JXfd5cBmEUh_qPUI/images/programmatic-tool-calling.svg?fit=max&auto=format&n=JXfd5cBmEUh_qPUI&q=85&s=a2be82d097bb7cd7c7fd415918b1571d" alt="Comparison of direct tool calling versus programmatic tool calling. Direct calling passes every intermediate result through the model (~100K+ tokens). Programmatic calling sends a ~200-token script to a sandbox, which executes the tool calls and returns a ~15-token summary." width="900" height="900" data-path="images/programmatic-tool-calling.svg" />
### How It Works
The host converts MCP tool schemas into a typed API available inside a sandbox. When the model needs tools, it writes a script and executes it.
**Step 1: Generate a programmatic API from MCP schemas.** The host reads each server's tool definitions and produces typed functions based on each tool's arguments and `outputSchema`:
```typescript theme={null}
// Auto-generated from the Logging MCP server's tool schema
interface LogEntry {
timestamp: string;
message: string;
level: string;
}
function logging_getLogs(input: {
level: "error" | "warn" | "info";
since: number;
}): Promise<{ entries: LogEntry[] }> {
return mcp.callTool<{ entries: LogEntry[] }>("logging_getLogs", input);
}
// Auto-generated from the Ticketing MCP server's tool schema
function ticketing_createIssue(input: {
title: string;
body?: string;
priority: "low" | "medium" | "high";
}): Promise<{ issueId: string }> {
return mcp.callTool<{ issueId: string }>("ticketing_createIssue", input);
}
```
MCP Servers can provide an optional [`outputSchema`](/specification/draft/server/tools#output-schema) for each tool. When an output schema is present, the host can produce precise return types (like `LogEntry` above).
When an output schema is absent, prefer the simple path:
* **Use a generic type and move on.** Accept `any` or `string` and handle the unstructured output downstream. The real fix is for server authors to provide `outputSchema`.
* **Extract a typed result using a fast model**, for single-shot calls outside loops. Expose a host-brokered `extract(value, ExpectedType)` helper through the same stub-interception path as MCP tool calls so the sandbox itself never opens a network connection. The helper routes to a small model (for example, Claude Haiku or Gemini Flash) to coerce the value into `ExpectedType`. This adds per-call latency and can hallucinate or drop fields, so validate the result against `ExpectedType` before use.
**Step 2: The model writes code against these APIs.** Rather than making separate tool calls with full results flowing through context between them, the model writes a single script. Consider a task like "find all error logs from the past hour and file a ticket for each unique error." With direct tool calling, thousands of log entries would flow through the model's context. With code, the model filters in the sandbox:
```typescript theme={null}
// Model-generated code, executes in sandbox
const logs = await logging_getLogs({
level: "error",
since: Date.now() - 3600000,
});
// Filter and deduplicate inside the sandbox, not in the model's context
const uniqueErrors = new Map<string, LogEntry>();
for (const log of logs.entries) {
if (!uniqueErrors.has(log.message)) {
uniqueErrors.set(log.message, log);
}
}
for (const [message, log] of uniqueErrors) {
await ticketing_createIssue({
title: `Error: ${message}`,
body: `First seen: ${log.timestamp}\nOccurrences: ${
logs.entries.filter((l) => l.message === message).length
}`,
priority: "high",
});
}
console.log(
`Filed ${uniqueErrors.size} tickets from ${logs.entries.length} error logs`,
);
```
**Step 3: The sandbox executes the code.** Function calls inside the sandbox are intercepted and routed back to the appropriate MCP server through the host broker. The log data and ticket creation flow directly between servers without ever entering the model's context. Only the `console.log` output, a single summary line, returns to the model.
### Choosing a Sandbox
The right sandbox depends on the language you want the model to write, your host application's language, and how much isolation you need. The table lists example runtimes rather than endorsements; evaluate maturity for your use case:
| Sandboxed language | Runtime / Library | Host language | Approach |
| ------------------ | ------------------------------------------------------------- | ----------------- | ----------------------------------------------------------------------------------------------- |
| **JavaScript** | [Deno](https://github.com/denoland/deno), `isolated-vm` | Rust / Node / CLI | V8-based runtimes with fine-grained permissions. Can disable all permissions for full lockdown. |
| **Python** | [Monty](https://github.com/pydantic/monty) *(experimental)* | Rust | Minimal Python interpreter built for AI use cases. No I/O by default. |
| **TypeScript** | [pctx](https://github.com/portofcontext/pctx) *(early-stage)* | Python / Rust | Incorporates code mode concepts as a library, with low-level Rust support. |
| **Any (via Wasm)** | [Wasmtime](https://github.com/bytecodealliance/wasmtime) | Rust / C / Go | Compile any language to Wasm and run it with capability-based security. |
Regardless of sandbox, the integration pattern is the same: the host injects function stubs, intercepts calls over an in-process or stdio channel (so network permissions can stay fully denied), and dispatches them as `tools/call` requests to MCP servers.
### Execution Architecture
The implementation has three components:
```mermaid theme={null}
flowchart LR
subgraph Host["MCP Host"]
A[LLM] -->|writes code| B[Sandbox]
B -->|function call| C[MCP Client]
C -->|return value| B
B -->|console output| A
end
C -->|tool call| D[MCP Server A]
C -->|tool call| E[MCP Server B]
D -->|result| C
E -->|result| C
```
**The sandbox** runs model-generated code in an isolated environment with no direct network access. Its only interface to the outside world is through the generated function stubs, which route calls back to the host.
**The host** acts as a broker. It receives function calls from the sandbox, maps them to the correct MCP server, executes the tool call, and returns the result to the sandbox. Authorization tokens and credentials are held by the host and never exposed to the generated code.
**The model** sees only what the sandbox returns, typically the output of `console.log` statements or a final return value. This gives the model (and the client developer) precise control over what enters the context window.
### Security Considerations
Programmatic tool calling introduces a code execution surface that requires careful sandboxing:
* **Per-call authorization**: The broker is still the MCP host for spec purposes. Apply the same human-in-the-loop confirmation policy to sandbox-originated calls that you apply to direct calls (see [Tools: Security](/specification/draft/server/tools#security-considerations)). Approving the script does not grant blanket approval for every tool call it makes at runtime; hosts may grant categorical approval (for example, "allow `ticketing_createIssue` for this script run") rather than prompting per iteration, but the broker must still evaluate each call against that grant.
* **Cross-server data flow**: Tool results from one server are untrusted input to another. The broker should apply the same input-review policy to brokered calls as to direct ones; output truncation alone does not prevent exfiltration.
* **Network isolation**: The sandbox should have no direct network access. All external communication flows through the host broker, which enforces authorization and access control.
* **No credential exposure**: API keys and tokens are held by the host. The generated code calls typed functions; the host adds authentication when forwarding to servers.
* **Resource limits**: Set timeouts and memory limits on sandbox execution to prevent runaway scripts.
* **Output filtering**: Validate and truncate sandbox console output before feeding it back to the model.
### Error Handling
MCP tool errors arrive as a successful response with
[`isError: true`](/specification/draft/server/tools#error-handling) rather than a transport
failure. Generated wrappers should convert this into a thrown exception so model-authored code
can use `try`/`catch`. If an uncaught error terminates the script, surface it as the script's
result so the model can self-correct; the model is responsible for reporting any partial side
effects already committed.
## Combining Both Patterns
Cut at 300 lines. The page has the rest.
docs/draft/develop/connect-local-servers New page · 283 lines, new page
# Connect to local MCP servers ## Prerequisites ### Claude Desktop ### Node.js ## Understanding MCP Servers ## Installing the Filesystem Server ## Using the Filesystem Server ### File Management Examples ### How Approval Works ## Troubleshooting ## Next Steps
A whole new page. There's nothing to diff it against, so here is what it says.
# Connect to local MCP servers
> Learn how to extend Claude Desktop with local MCP servers to enable file system access and other powerful integrations
Model Context Protocol (MCP) servers extend AI applications' capabilities by providing secure, controlled access to local resources and tools. Many clients support MCP, enabling diverse integration possibilities across different platforms and applications.
This guide demonstrates how to connect to local MCP servers using Claude Desktop as an example, one of the many clients that support MCP. While we focus on Claude Desktop's implementation, the concepts apply broadly to other MCP-compatible clients. By the end of this tutorial, Claude will be able to interact with files on your computer, create new documents, organize folders, and search through your file system—all with your explicit permission for each action.
<Frame>
<img src="https://mintcdn.com/mcp/4ZXF1PrDkEaJvXpn/images/quickstart-filesystem.png?fit=max&auto=format&n=4ZXF1PrDkEaJvXpn&q=85&s=629d7e754dc358d71a408d6ce970c1b1" alt="Claude Desktop with filesystem integration showing file management capabilities" width="1732" height="2060" data-path="images/quickstart-filesystem.png" />
</Frame>
## Prerequisites
Before starting this tutorial, ensure you have the following installed on your system:
### Claude Desktop
Download and install [Claude Desktop](https://claude.ai/download) for your operating system. Claude Desktop is available for macOS and Windows.
If you already have Claude Desktop installed, verify you're running the latest version by clicking the Claude menu and selecting "Check for Updates..."
### Node.js
The Filesystem Server and many other MCP servers require Node.js to run. Verify your Node.js installation by opening a terminal or command prompt and running:
```bash theme={null}
node --version
```
If Node.js is not installed, download it from [nodejs.org](https://nodejs.org/). We recommend the LTS (Long Term Support) version for stability.
## Understanding MCP Servers
MCP servers are programs that run on your computer and provide specific capabilities to Claude Desktop through a standardized protocol. Each server exposes tools that Claude can use to perform actions, with your approval. The Filesystem Server we'll install provides tools for:
* Reading file contents and directory structures
* Creating new files and directories
* Moving and renaming files
* Searching for files by name or content
All actions require your explicit approval before execution, ensuring you maintain full control over what Claude can access and modify.
## Installing the Filesystem Server
The process involves configuring Claude Desktop to automatically start the Filesystem Server whenever you launch the application. This configuration is done through a JSON file that tells Claude Desktop which servers to run and how to connect to them.
<Steps>
<Step title="Open Claude Desktop Settings">
Start by accessing the Claude Desktop settings. Click on the Claude menu in your system's menu bar (not the settings within the Claude window itself) and select "Settings..."
On macOS, this appears in the top menu bar:
<Frame style={{ textAlign: "center" }}>
<img src="https://mintcdn.com/mcp/4ZXF1PrDkEaJvXpn/images/quickstart-menu.png?fit=max&auto=format&n=4ZXF1PrDkEaJvXpn&q=85&s=0c8b57e0e17af3624b6762a3ea944c8e" width="400" alt="Claude Desktop menu showing Settings option" data-path="images/quickstart-menu.png" />
</Frame>
This opens the Claude Desktop configuration window, which is separate from your Claude account settings.
</Step>
<Step title="Access Developer Settings">
In the Settings window, navigate to the "Developer" tab in the left sidebar. This section contains options for configuring MCP servers and other developer features.
Click the "Edit Config" button to open the configuration file:
<Frame>
<img src="https://mintcdn.com/mcp/4ZXF1PrDkEaJvXpn/images/quickstart-developer.png?fit=max&auto=format&n=4ZXF1PrDkEaJvXpn&q=85&s=0fb595490a2f9e15c0301e771a57446c" alt="Developer settings showing Edit Config button" width="1688" height="534" data-path="images/quickstart-developer.png" />
</Frame>
This action creates a new configuration file if one doesn't exist, or opens your existing configuration. The file is located at:
* **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
* **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
</Step>
<Step title="Configure the Filesystem Server">
Replace the contents of the configuration file with the following JSON structure. This configuration tells Claude Desktop to start the Filesystem Server with access to specific directories:
<CodeGroup>
```json macOS theme={null}
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"/Users/username/Desktop",
"/Users/username/Downloads"
]
}
}
}
```
```json Windows theme={null}
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"C:\\Users\\username\\Desktop",
"C:\\Users\\username\\Downloads"
]
}
}
}
```
</CodeGroup>
Replace `username` with your actual computer username. The paths listed in the `args` array specify which directories the Filesystem Server can access. You can modify these paths or add additional directories as needed.
<Tip>
**Understanding the Configuration**
* `"filesystem"`: A friendly name for the server that appears in Claude Desktop
* `"command": "npx"`: Uses Node.js's npx tool to run the server
* `"-y"`: Automatically confirms the installation of the server package
* `"@modelcontextprotocol/server-filesystem"`: The package name of the Filesystem Server
* The remaining arguments: Directories the server is allowed to access
</Tip>
<Warning>
**Security Consideration**
Only grant access to directories you're comfortable with Claude reading and modifying. The server runs with your user account permissions, so it can perform any file operations you can perform manually.
</Warning>
</Step>
<Step title="Restart Claude Desktop">
After saving the configuration file, completely quit Claude Desktop and restart it. The application needs to restart to load the new configuration and start the MCP server.
Upon successful restart, click the "Add files, connectors, and more /" indicator <img src="https://mintcdn.com/mcp/cpXzQjUOzyH0mCNH/images/claude-add-files-connectors-and-more.png?fit=max&auto=format&n=cpXzQjUOzyH0mCNH&q=85&s=53acf21f6807dd5323b70b84b5d98d8a" style={{display: 'inline', margin: 0, height: '1.3em', width: 'auto'}} width="33" height="33" data-path="images/claude-add-files-connectors-and-more.png" /> in the bottom-left corner of the conversation input box:
<Frame>
<img src="https://mintcdn.com/mcp/akpggzunDlIcY2im/images/quickstart-slider.png?fit=max&auto=format&n=akpggzunDlIcY2im&q=85&s=a1ebd4259cff2a7472171885f2edc035" alt="Claude Desktop interface showing MCP server indicator" width="1414" height="410" data-path="images/quickstart-slider.png" />
</Frame>
Click on this indicator, then move the mouse over "Connectors" and click "Manage connectors". Select "filesystem" from the connector list to view the Filesystem Server's available tools:
<Frame style={{ textAlign: "center" }}>
<img src="https://mintcdn.com/mcp/cpXzQjUOzyH0mCNH/images/quickstart-tools.png?fit=max&auto=format&n=cpXzQjUOzyH0mCNH&q=85&s=212a63d76daba170d52db0d2f6f582be" width="400" alt="Available filesystem tools in Claude Desktop" data-path="images/quickstart-tools.png" />
</Frame>
If the Filesystem Server doesn't connect, refer to the [Troubleshooting](#troubleshooting) section for debugging steps.
</Step>
</Steps>
## Using the Filesystem Server
With the Filesystem Server connected, Claude can now interact with your file system. Try these example requests to explore the capabilities:
### File Management Examples
* **"Can you write a poem and save it to my desktop?"** - Claude will compose a poem and create a new text file on your desktop
* **"What work-related files are in my downloads folder?"** - Claude will scan your downloads and identify work-related documents
* **"Please organize all images on my desktop into a new folder called 'Images'"** - Claude will create a folder and move image files into it
### How Approval Works
Before executing any file system operation, Claude will request your approval. This ensures you maintain control over all actions:
<Frame style={{ textAlign: "center" }}>
<img src="https://mintcdn.com/mcp/4ZXF1PrDkEaJvXpn/images/quickstart-approve.png?fit=max&auto=format&n=4ZXF1PrDkEaJvXpn&q=85&s=98cc6e9dfe885fbd6e9bfae40601e494" width="500" alt="Claude requesting approval to perform a file operation" data-path="images/quickstart-approve.png" />
</Frame>
Review each request carefully before approving. You can always deny a request if you're not comfortable with the proposed action.
## Troubleshooting
If you encounter issues setting up or using the Filesystem Server, these solutions address common problems:
<AccordionGroup>
<Accordion title="Server not showing up in Claude / hammer icon missing">
1. Restart Claude Desktop completely
2. Check your `claude_desktop_config.json` file syntax
3. Make sure the file paths included in `claude_desktop_config.json` are valid and that they are absolute and not relative
4. Look at [logs](#getting-logs-from-claude-for-desktop) to see why the server is not connecting
5. In your command line, try manually running the server (replacing `username` as you did in `claude_desktop_config.json`) to see if you get any errors:
<CodeGroup>
```bash macOS/Linux theme={null}
npx -y @modelcontextprotocol/server-filesystem /Users/username/Desktop /Users/username/Downloads
```
```powershell Windows theme={null}
npx -y @modelcontextprotocol/server-filesystem C:\Users\username\Desktop C:\Users\username\Downloads
```
</CodeGroup>
</Accordion>
<Accordion title="Getting logs from Claude Desktop">
Claude.app logging related to MCP is written to log files in:
* macOS: `~/Library/Logs/Claude`
* Windows: `%APPDATA%\Claude\logs`
* `mcp.log` will contain general logging about MCP connections and connection failures.
* Files named `mcp-server-SERVERNAME.log` will contain the stderr output from the named server. Stdio servers may use stderr for all their logging, so these files are not limited to errors.
You can run the following command to list recent logs and follow along with any new ones (on Windows, it will only show recent logs):
<CodeGroup>
```bash macOS/Linux theme={null}
tail -n 20 -f ~/Library/Logs/Claude/mcp*.log
```
```powershell Windows theme={null}
type "%APPDATA%\Claude\logs\mcp*.log"
```
</CodeGroup>
</Accordion>
<Accordion title="Tool calls failing silently">
If Claude attempts to use the tools but they fail:
1. Check Claude's logs for errors
2. Verify your server builds and runs without errors
3. Try restarting Claude Desktop
</Accordion>
<Accordion title="None of this is working. What do I do?">
Please refer to our [debugging guide](/docs/draft/tools/debugging) for better debugging tools and more detailed guidance.
</Accordion>
<Accordion title="ENOENT error and `${APPDATA}` in paths on Windows">
If your configured server fails to load, and you see within its logs an error referring to `${APPDATA}` within a path, you may need to add the expanded value of `%APPDATA%` to your `env` key in `claude_desktop_config.json`:
```json theme={null}
{
"brave-search": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-brave-search"],
"env": {
"APPDATA": "C:\\Users\\user\\AppData\\Roaming\\",
"BRAVE_API_KEY": "..."
}
}
}
```
With this change in place, launch Claude Desktop once again.
<Warning>
**npm should be installed globally**
The `npx` command may continue to fail if you have not installed npm globally. If npm is already installed globally, you will find `%APPDATA%\npm` exists on your system. If not, you can install npm globally by running the following command:
```bash theme={null}
npm install -g npm
```
</Warning>
</Accordion>
</AccordionGroup>
## Next Steps
Now that you've successfully connected Claude Desktop to a local MCP server, explore these options to expand your setup:
<CardGroup cols={2}>
<Card title="Explore other servers" icon="grid" href="https://github.com/modelcontextprotocol/servers">
Browse our collection of official and community-created MCP servers for
additional capabilities
</Card>
<Card title="Build your own server" icon="code" href="/docs/draft/develop/build-server">
Create custom MCP servers tailored to your specific workflows and
integrations
</Card>
<Card title="Connect to remote servers" icon="cloud" href="/docs/draft/develop/connect-remote-servers">
Learn how to connect Claude to remote MCP servers for cloud-based tools and
services
</Card>
<Card title="Understand the protocol" icon="book" href="/docs/draft/learn/architecture">
Dive deeper into how MCP works and its architecture
</Card>
</CardGroup>
docs/draft/develop/connect-remote-servers New page · 125 lines, new page
# Connect to remote MCP Servers ## Understanding Remote MCP Servers ## What are Custom Connectors? ## Connecting to a Remote MCP Server ## Best Practices for Using Remote MCP Servers ## Next Steps
A whole new page. There's nothing to diff it against, so here is what it says.
# Connect to remote MCP Servers
> Learn how to connect Claude to remote MCP servers and extend its capabilities with internet-hosted tools and data sources
Remote MCP servers extend AI applications' capabilities beyond your local environment, providing access to internet-hosted tools, services, and data sources. By connecting to remote MCP servers, you transform AI assistants from helpful tools into informed teammates capable of handling complex, multi-step projects with real-time access to external resources.
Many clients now support remote MCP servers, enabling a wide range of integration possibilities. This guide demonstrates how to connect to remote MCP servers using [Claude](https://claude.ai/) as an example, one of the many clients that support MCP. While we focus on Claude's implementation through Custom Connectors, the concepts apply broadly to other MCP-compatible clients.
## Understanding Remote MCP Servers
Remote MCP servers function similarly to local MCP servers but are hosted on the internet rather than your local machine. They expose tools, prompts, and resources that Claude can use to perform tasks on your behalf. These servers can integrate with various services such as project management tools, documentation systems, code repositories, and any other API-enabled service.
The key advantage of remote MCP servers is their accessibility. Unlike local servers that require installation and configuration on each device, remote servers are available from any MCP client with an internet connection. This makes them ideal for web-based AI applications, integrations that emphasize ease of use, and services that require server-side processing or authentication.
## What are Custom Connectors?
Custom Connectors serve as the bridge between Claude and remote MCP servers. They allow you to connect Claude directly to the tools and data sources that matter most to your workflows, enabling Claude to operate within your favorite software and draw insights from the complete context of your external tools.
With Custom Connectors, you can:
* [Connect Claude to existing remote MCP servers](https://support.anthropic.com/en/articles/11175166-getting-started-with-custom-connectors-using-remote-mcp) provided by third-party developers
* [Build your own remote MCP servers to connect with any tool](https://support.anthropic.com/en/articles/11503834-building-custom-connectors-via-remote-mcp-servers)
## Connecting to a Remote MCP Server
The process of connecting Claude to a remote MCP server involves adding a Custom Connector through the [Claude interface](https://claude.ai/). This establishes a secure connection between Claude and your chosen remote server.
<Steps>
<Step title="Navigate to Connector Settings">
Open Claude Desktop or Claude in your browser, then navigate to the settings page:
* **Desktop**: Either use the keyboard shortcut `Ctrl+Comma` or click the top-left menu icon <img src="https://mintcdn.com/mcp/cpXzQjUOzyH0mCNH/images/claude-desktop-hamburger-menu-icon.png?fit=max&auto=format&n=cpXzQjUOzyH0mCNH&q=85&s=66e498f668362c79f829a07b5ce863c8" style={{display: 'inline', margin: 0, height: '1.3em', width: 'auto'}} width="33" height="33" data-path="images/claude-desktop-hamburger-menu-icon.png" />, hover over "File", and select "Settings"
* **Browser**: Either use the keyboard shortcut `⌘⇧,` (*macOS*) or click on your profile icon, and select "Settings" from the menu
Once you're in the settings page, click "Connectors" in the sidebar. This displays your currently configured connectors and provides options for adding new ones.
</Step>
<Step title="Add a Custom Connector">
In the Connectors section, click the "Add" button at the top-right of the window, then select "Add custom connector" from the dropdown. This begins the connection process. To follow along, copy/paste the URL below:
```text Example Remote Server theme={null}
https://example-server.modelcontextprotocol.io/mcp
```
<Frame>
<img src="https://mintcdn.com/mcp/4ZXF1PrDkEaJvXpn/images/quickstart-remote/1-add-connector.png?fit=max&auto=format&n=4ZXF1PrDkEaJvXpn&q=85&s=b5ae9b23164875bbaa3aff4c178cdc64" alt="Add custom connector button in Claude settings" width="1038" height="809" data-path="images/quickstart-remote/1-add-connector.png" />
</Frame>
A dialog will appear prompting you to enter the remote MCP server URL. This URL should be provided by the server developer or administrator. Enter the complete URL, ensuring it includes the proper protocol (https\://) and any necessary path components.
<Frame>
<img src="https://mintcdn.com/mcp/4ZXF1PrDkEaJvXpn/images/quickstart-remote/2-connect.png?fit=max&auto=format&n=4ZXF1PrDkEaJvXpn&q=85&s=0934f16d8e016cade8e560c8f89d011b" alt="Dialog for entering remote MCP server URL" width="1616" height="282" data-path="images/quickstart-remote/2-connect.png" />
</Frame>
After entering the URL, click "Add" to proceed with the connection.
</Step>
<Step title="Complete Authentication">
Most remote MCP servers require authentication to ensure secure access to their resources. The authentication process varies depending on the server implementation but commonly involves OAuth, API keys, or username/password combinations.
<Frame>
<img src="https://mintcdn.com/mcp/4ZXF1PrDkEaJvXpn/images/quickstart-remote/3-auth.png?fit=max&auto=format&n=4ZXF1PrDkEaJvXpn&q=85&s=89af6e1b85718637231388697cc7b015" alt="Authentication screen for remote MCP server" width="490" height="806" data-path="images/quickstart-remote/3-auth.png" />
</Frame>
Follow the authentication prompts provided by the server. This may redirect you to a third-party authentication provider or display a form within Claude. Once authentication is complete, Claude will establish a secure connection to the remote server.
</Step>
<Step title="Access Resources and Prompts">
After successful connection, the remote server’s resources and prompts become available in your Claude conversations. You can access these by clicking the "Add files, connectors, and more /" indicator <img src="https://mintcdn.com/mcp/cpXzQjUOzyH0mCNH/images/claude-add-files-connectors-and-more.png?fit=max&auto=format&n=cpXzQjUOzyH0mCNH&q=85&s=53acf21f6807dd5323b70b84b5d98d8a" style={{display: 'inline', margin: 0, height: '1.3em', width: 'auto'}} width="33" height="33" data-path="images/claude-add-files-connectors-and-more.png" /> in the bottom-left corner of the message input area. Then hover over "Connectors", move the cursor over "Add to Example Remote Server", where hovering displays the attachment menu.
<Frame>
<img src="https://mintcdn.com/mcp/cpXzQjUOzyH0mCNH/images/quickstart-remote/4-select-resources-menu.png?fit=max&auto=format&n=cpXzQjUOzyH0mCNH&q=85&s=e5fa85174f8acbadbd709bac66f42d5c" alt="Attachment menu showing available resources" width="735" height="378" data-path="images/quickstart-remote/4-select-resources-menu.png" />
</Frame>
The menu displays all available resources and prompts from your connected server. Select the items you want to include in your conversation. These resources provide Claude with context and information from your external tools.
<Frame>
<img src="https://mintcdn.com/mcp/cpXzQjUOzyH0mCNH/images/quickstart-remote/5-select-prompts-resources.png?fit=max&auto=format&n=cpXzQjUOzyH0mCNH&q=85&s=68722669d9e18252756885c703e4f221" alt="Selecting specific resources and prompts from the menu" width="648" height="529" data-path="images/quickstart-remote/5-select-prompts-resources.png" />
</Frame>
</Step>
<Step title="Configure Tool Permissions">
Remote MCP servers often expose multiple tools with varying capabilities. You can control which tools Claude is allowed to use by configuring permissions in the connector settings. This ensures Claude only performs actions you've explicitly authorized.
<Frame>
<img src="https://mintcdn.com/mcp/cpXzQjUOzyH0mCNH/images/quickstart-remote/6-configure-tools.png?fit=max&auto=format&n=cpXzQjUOzyH0mCNH&q=85&s=5cfd8b2c5d06e7e3699eac24c68d090e" alt="Tool permission configuration interface" width="604" height="745" data-path="images/quickstart-remote/6-configure-tools.png" />
</Frame>
Navigate back to the Connectors settings and click on your connected server. Here you can enable or disable specific tools, set usage limits, and configure other security parameters according to your needs.
</Step>
</Steps>
## Best Practices for Using Remote MCP Servers
When working with remote MCP servers, consider these recommendations to ensure a secure and efficient experience:
**Security considerations**: Always verify the authenticity of remote MCP servers before connecting. Only connect to servers from trusted sources, and review the permissions requested during authentication. Be cautious about granting access to sensitive data or systems.
**Managing multiple connectors**: You can connect to multiple remote MCP servers simultaneously. Organize your connectors by purpose or project to maintain clarity. Regularly review and remove connectors you no longer use to keep your workspace organized and secure.
## Next Steps
Now that you've connected Claude to a remote MCP server, you can explore its capabilities in your conversations. Try using the connected tools to automate tasks, access external data, or integrate with your existing workflows.
<CardGroup cols={2}>
<Card title="Build your own remote server" icon="cloud" href="https://support.anthropic.com/en/articles/11503834-building-custom-connectors-via-remote-mcp-servers">
Create custom remote MCP servers to integrate with proprietary tools and
services
</Card>
<Card title="Explore available servers" icon="grid" href="https://github.com/modelcontextprotocol/servers">
Browse our collection of official and community-created MCP servers
</Card>
<Card title="Connect local servers" icon="computer" href="/docs/draft/develop/connect-local-servers">
Learn how to connect Claude Desktop to local MCP servers for direct system
access
</Card>
<Card title="Understand the architecture" icon="book" href="/docs/draft/learn/architecture">
Dive deeper into how MCP works and its architecture
</Card>
</CardGroup>
Remote MCP servers unlock powerful possibilities for extending Claude's capabilities. As you become familiar with these integrations, you'll discover new ways to streamline your workflows and accomplish complex tasks more efficiently.
docs/draft/getting-started/intro New page · 54 lines, new page
# What is the Model Context Protocol (MCP)? ## What can MCP enable? ## Why does MCP matter? ## Broad ecosystem support ## Start Building ## Learn more
A whole new page. There's nothing to diff it against, so here is what it says.
# What is the Model Context Protocol (MCP)?
MCP (Model Context Protocol) is an open-source standard for connecting AI applications to external systems.
Using MCP, AI applications like Claude or ChatGPT can connect to data sources (e.g. local files, databases), tools (e.g. search engines, calculators) and workflows (e.g. specialized prompts)—enabling them to access key information and perform tasks.
Think of MCP like a USB-C port for AI applications. Just as USB-C provides a standardized way to connect electronic devices, MCP provides a standardized way to connect AI applications to external systems.
<Frame>
<img src="https://mintcdn.com/mcp/bEUxYpZqie0DsluH/images/mcp-simple-diagram.png?fit=max&auto=format&n=bEUxYpZqie0DsluH&q=85&s=35268aa0ad50b8c385913810e7604550" width="3840" height="1500" data-path="images/mcp-simple-diagram.png" />
</Frame>
## What can MCP enable?
* Agents can access your Google Calendar and Notion, acting as a more personalized AI assistant.
* Claude Code can generate an entire web app using a Figma design.
* Enterprise chatbots can connect to multiple databases across an organization, empowering users to analyze data using chat.
* AI models can create 3D designs on Blender and print them out using a 3D printer.
## Why does MCP matter?
Depending on where you sit in the ecosystem, MCP can have a range of benefits.
* **Developers**: MCP reduces development time and complexity when building, or integrating with, an AI application or agent.
* **AI applications or agents**: MCP gives them access to an ecosystem of data sources, tools and apps, which enhances their capabilities and improves the end-user experience.
* **End-users**: MCP results in more capable AI applications or agents that can access user data and take actions on the user's behalf when necessary.
## Broad ecosystem support
MCP is an open protocol supported across a wide range of clients and servers. AI assistants like [Claude](https://claude.com/docs/connectors/building) and [ChatGPT](https://developers.openai.com/api/docs/mcp/), development tools like [Visual Studio Code](https://code.visualstudio.com/docs/copilot/chat/mcp-servers), [Cursor](https://cursor.com/docs/context/mcp), [MCPJam](https://docs.mcpjam.com/getting-started), and many others all support MCP — making it easy to build once and integrate everywhere.
## Start Building
<CardGroup cols={2}>
<Card title="Build servers" icon="server" href="/docs/draft/develop/build-server">
Create MCP servers to expose your data and tools
</Card>
<Card title="Build clients" icon="computer" href="/docs/draft/develop/build-client">
Develop applications that connect to MCP servers
</Card>
<Card title="Build MCP Apps" icon="puzzle-piece" href="/extensions/apps/overview">
Build interactive apps that run inside AI clients
</Card>
</CardGroup>
## Learn more
<CardGroup cols={2}>
<Card title="Understand concepts" icon="book" href="/docs/draft/learn/architecture">
Learn the core concepts and architecture of MCP
</Card>
</CardGroup>
docs/draft/learn/architecture New page · 562 lines, new page
# Architecture overview ## Scope ## Concepts of MCP ### Participants ### Layers #### Data layer #### Transport layer ### Data Layer Protocol #### Statelessness and discovery #### Primitives #### Notifications ## Example ### Data Layer
A whole new page. There's nothing to diff it against, so here is what it says.
# Architecture overview
This overview of the Model Context Protocol (MCP) discusses its [scope](#scope) and [core concepts](#concepts-of-mcp), and provides an [example](#example) demonstrating each core concept.
Because MCP SDKs abstract away many concerns, most developers will likely find the [data layer protocol](#data-layer-protocol) section to be the most useful. It discusses how MCP servers can provide context to an AI application.
For specific implementation details, please refer to the documentation for your [language-specific SDK](/docs/draft/sdk).
## Scope
The Model Context Protocol includes the following projects:
* [MCP Specification](https://modelcontextprotocol.io/specification/latest): A specification of MCP that outlines the implementation requirements for clients and servers.
* [MCP SDKs](/docs/draft/sdk): SDKs for different programming languages that implement MCP.
* **MCP Development Tools**: Tools for developing MCP servers and clients, including the [MCP Inspector](https://github.com/modelcontextprotocol/inspector)
* [MCP Reference Server Implementations](https://github.com/modelcontextprotocol/servers): Reference implementations of MCP servers.
<Note>
MCP focuses solely on the protocol for context exchange—it does not dictate
how AI applications use LLMs or manage the provided context.
</Note>
## Concepts of MCP
### Participants
MCP follows a client-server architecture where an MCP host — an AI application like [Claude Code](https://www.anthropic.com/claude-code) or [Claude Desktop](https://www.claude.ai/download) — establishes connections to one or more MCP servers. The MCP host accomplishes this by creating one MCP client for each MCP server. Each MCP client maintains a dedicated connection with its corresponding MCP server.
Local MCP servers that use the STDIO transport typically serve a single MCP client, whereas remote MCP servers that use the Streamable HTTP transport will typically serve many MCP clients.
The key participants in the MCP architecture are:
* **MCP Host**: The AI application that coordinates and manages one or multiple MCP clients
* **MCP Client**: A component that maintains a connection to an MCP server and obtains context from an MCP server for the MCP host to use
* **MCP Server**: A program that provides context to MCP clients
**For example**: Visual Studio Code acts as an MCP host. When Visual Studio Code establishes a connection to an MCP server, such as the [Sentry MCP server](https://docs.sentry.io/product/sentry-mcp/), the Visual Studio Code runtime instantiates an MCP client object that maintains the connection to the Sentry MCP server.
When Visual Studio Code subsequently connects to another MCP server, such as the [local filesystem server](https://github.com/modelcontextprotocol/servers/tree/main/src/filesystem), the Visual Studio Code runtime instantiates an additional MCP client object to maintain this connection.
```mermaid theme={null}
graph TB
subgraph "MCP Host (AI Application)"
Client1["MCP Client 1"]
Client2["MCP Client 2"]
Client3["MCP Client 3"]
Client4["MCP Client 4"]
end
ServerA["MCP Server A - Local<br/>(e.g. Filesystem)"]
ServerB["MCP Server B - Local<br/>(e.g. Database)"]
ServerC["MCP Server C - Remote<br/>(e.g. Sentry)"]
Client1 ---|"Dedicated<br/>connection"| ServerA
Client2 ---|"Dedicated<br/>connection"| ServerB
Client3 ---|"Dedicated<br/>connection"| ServerC
Client4 ---|"Dedicated<br/>connection"| ServerC
```
Note that **MCP server** refers to the program that serves context data, regardless of
where it runs. MCP servers can execute locally or remotely. For example, when
Claude Desktop launches the [filesystem
server](https://github.com/modelcontextprotocol/servers/tree/main/src/filesystem),
the server runs locally on the same machine because it uses the STDIO
transport. This is commonly referred to as a "local" MCP server. The official
[Sentry MCP server](https://docs.sentry.io/product/sentry-mcp/) runs on the
Sentry platform, and uses the Streamable HTTP transport. This is commonly
referred to as a "remote" MCP server.
### Layers
MCP consists of two layers:
* **Data layer**: Defines the JSON-RPC based protocol for client-server communication, including capability and version discovery, and core primitives, such as tools, resources, prompts and notifications.
* **Transport layer**: Defines the communication mechanisms and channels that enable data exchange between clients and servers, including transport-specific connection establishment, message framing, and authorization.
Conceptually the data layer is the inner layer, while the transport layer is the outer layer.
#### Data layer
The data layer implements a [JSON-RPC 2.0](https://www.jsonrpc.org/) based exchange protocol that defines the message structure and semantics.
This layer includes:
* **Discovery**: Lets clients query a server's supported protocol versions, capabilities, and identity through the `server/discover` request
* **Server features**: Enables servers to provide core functionality including tools for AI actions, resources for context data, and prompts for interaction templates from and to the client
* **Client features**: Enables servers to elicit input from the user. Sampling is [deprecated](/specification/draft/deprecated) as of protocol version `2026-07-28`.
* **Utility features**: Supports additional capabilities like notifications for real-time updates and progress tracking for long-running operations
#### Transport layer
The transport layer manages communication channels and authentication between clients and servers. It handles connection establishment, message framing, and secure communication between MCP participants.
MCP supports two transport mechanisms:
* **Stdio transport**: Uses standard input/output streams for direct process communication between local processes on the same machine, providing optimal performance with no network overhead.
* **Streamable HTTP transport**: Uses HTTP POST for client-to-server messages with optional Server-Sent Events for streaming capabilities. This transport enables remote server communication and supports standard HTTP authentication methods including bearer tokens, API keys, and custom headers. MCP recommends using OAuth to obtain authentication tokens.
The transport layer abstracts communication details from the protocol layer, enabling the same JSON-RPC 2.0 message format across all transport mechanisms.
### Data Layer Protocol
A core part of MCP is defining the schema and semantics between MCP clients and MCP servers. Developers will likely find the data layer — in particular, the set of [primitives](#primitives) — to be the most interesting part of MCP. It is the part of MCP that defines the ways developers can share context from MCP servers to MCP clients.
MCP uses [JSON-RPC 2.0](https://www.jsonrpc.org/) as its underlying RPC protocol. Client and servers send requests to each other and respond accordingly. Notifications can be used when no response is required.
#### Statelessness and discovery
MCP is a <Tooltip tip="Every request contains all the information needed to process it, so servers infer nothing from previous requests">stateless protocol</Tooltip>. Every request carries the protocol version and the <Tooltip tip="Features and operations that a client or server supports, such as tools, resources, or prompts">capabilities</Tooltip> relevant to that request in its `_meta` field, so the server can process each request on its own. Clients should also identify themselves in the same field unless configured not to. Servers advertise their supported versions and capabilities through the mandatory [`server/discover`](/specification/draft/server/discover) request, which clients may send before any other request. Detailed information can be found in the [specification](/specification/draft/basic/index#statelessness), and the [example](#example) showcases the per-request metadata and the discovery sequence.
#### Primitives
MCP primitives are the most important concept within MCP. They define what clients and servers can offer each other. These primitives specify the types of contextual information that can be shared with AI applications and the range of actions that can be performed.
MCP defines three core primitives that *servers* can expose:
* **Tools**: Executable functions that AI applications can invoke to perform actions (e.g., file operations, API calls, database queries)
* **Resources**: Data sources that provide contextual information to AI applications (e.g., file contents, database records, API responses)
* **Prompts**: Reusable templates that help structure interactions with language models (e.g., system prompts, few-shot examples)
Each primitive type has associated methods for discovery (`*/list`), retrieval (`*/get`), and in some cases, execution (`tools/call`).
MCP clients will use the `*/list` methods to discover available primitives. For example, a client can first list all available tools (`tools/list`) and then execute them. This design allows listings to be dynamic.
As a concrete example, consider an MCP server that provides context about a database. It can expose tools for querying the database, a resource that contains the schema of the database, and a prompt that includes few-shot examples for interacting with the tools.
For more details about server primitives see [server concepts](./server-concepts).
MCP also defines primitives that *clients* can expose. These primitives allow MCP server authors to build richer interactions.
* **Elicitation**: Allows servers to request additional information from users. This is useful when server authors want to get more information from the user, or ask for confirmation of an action. Servers request user input with the `elicitation/create` method.
Elicitation requests are delivered through the [Multi Round-Trip Requests](/specification/draft/basic/patterns/mrtr) pattern, explained in the [elicitation overview](/docs/draft/learn/client-concepts#elicitation).
**Deprecated**: The following client primitives are deprecated as of protocol version `2026-07-28`.
* **Sampling**: Allows servers to request language model completions from the client's AI application. This is useful when server authors want access to a language model, but want to stay model-independent and not include a language model SDK in their MCP server. Servers request completions with the `sampling/createMessage` method, also delivered through the Multi Round-Trip Requests pattern. New implementations should integrate directly with LLM provider APIs.
* **Logging**: Enables servers to send log messages to clients for debugging and monitoring purposes. New implementations should log to `stderr` (stdio transport) or use OpenTelemetry.
For more details about client primitives see [client concepts](./client-concepts).
Besides server and client primitives, the protocol supports optional [extensions](/extensions/overview) that build on the core protocol. For example, the [Tasks extension](/extensions/tasks/overview) lets servers return a durable handle for long-running requests, so clients can poll for status and retrieve the result later.
#### Notifications
The protocol supports real-time notifications to enable dynamic updates between servers and clients. For example, when a server's available tools change (such as when new functionality becomes available or existing tools are modified), the server can send tool update notifications to inform connected clients about these changes. Notifications are sent as JSON-RPC 2.0 notification messages (without expecting a response). Change notifications are opt-in: the client opens a long-lived [`subscriptions/listen`](/specification/draft/basic/patterns/subscriptions) stream naming the notification types it wants to receive, and the server delivers matching notifications on that stream.
## Example
### Data Layer
This section provides a step-by-step walkthrough of an MCP client-server interaction, focusing on the data layer protocol. We'll demonstrate discovery, tool operations, and notifications using JSON-RPC 2.0 messages.
<Steps>
<Step title="Discovery">
As described in the [statelessness and discovery](#statelessness-and-discovery) section, every MCP request carries the protocol version and client capabilities in its `_meta` field, and clients should also include their identity there. A client that wants to learn what a server supports before issuing other requests sends a `server/discover` request, which every server must implement. The discovery response is typically cacheable, meaning it can be re-used so the discovery flow does not need to be performed for every request.
<CodeGroup>
```json Discover Request theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"method": "server/discover",
"params": {
"_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientInfo": {
"name": "example-client",
"version": "1.0.0"
},
"io.modelcontextprotocol/clientCapabilities": {
"elicitation": {}
}
}
}
}
```
```json Discover Response theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"resultType": "complete",
"supportedVersions": ["2026-07-28"],
"capabilities": {
"tools": {
"listChanged": true
},
"resources": {}
},
"_meta": {
"io.modelcontextprotocol/serverInfo": {
"name": "example-server",
"version": "1.0.0"
}
},
"ttlMs": 3600000,
"cacheScope": "public"
}
}
```
</CodeGroup>
#### Understanding the Discovery Exchange
The `_meta` fields and the discovery response together serve several purposes:
1. **Protocol Version Selection**: The `io.modelcontextprotocol/protocolVersion` field declares the version the client is speaking on this request, and `supportedVersions` in the response lists the versions the server accepts. If a server does not support the requested version, it rejects the request with an `UnsupportedProtocolVersionError` listing the versions it does support, and the client retries with a mutually supported version.
2. **Capability Discovery**: The client declares its capabilities in `io.modelcontextprotocol/clientCapabilities` on every request, and the server returns its own `capabilities` object from `server/discover`. This tells each party which [primitives](#primitives) the other can handle (tools, resources, prompts) and whether change [notifications](#notifications) are available, so unsupported operations are never attempted.
3. **Identity Exchange**: The `io.modelcontextprotocol/clientInfo` field in the request's `_meta` and the `io.modelcontextprotocol/serverInfo` field in the result's `_meta` provide identification and versioning information for debugging and compatibility purposes.
In this example, the exchange demonstrates how MCP capabilities are declared:
**Client Capabilities**:
* `"elicitation": {}` - The client declares it can gather additional input from the user when the server requests it
**Server Capabilities**:
* `"tools": {"listChanged": true}` - The server supports the tools primitive and can honor a `toolsListChanged` filter in [`subscriptions/listen`](/specification/draft/basic/patterns/subscriptions). Clients that request this filter receive `notifications/tools/list_changed` when the tool list changes.
* `"resources": {}` - The server also supports the resources primitive (can handle `resources/list` and `resources/read` methods)
Calling `server/discover` is optional. Because every request carries the same `_meta` fields, a client is free to send any request directly and handle a version error if one comes back. Discovery is a convenient way to fetch the server's identity, capabilities, and supported versions in a single request.
#### How This Works in AI Applications
The AI application's MCP client manager connects to configured servers and stores their discovered capabilities for later use. The application uses this information to determine which servers can provide specific types of functionality (tools, resources, prompts) and whether they support real-time updates. In the Python SDK, discovery happens while the client connects. The results are then available on the client object.
```python Pseudo-code for AI application discovery theme={null}
# Pseudo Code
async with Client(stdio_client(server_config)) as client:
if client.server_capabilities.tools:
app.register_mcp_server(client, supports_tools=True)
app.set_server_ready(client)
```
</Step>
<Step title="Tool Discovery (Primitives)">
The client can discover available tools by sending a `tools/list` request. This request is fundamental to MCP's tool discovery mechanism: it allows clients to understand what tools are available on the server before attempting to use them.
<CodeGroup>
```json Tools List Request theme={null}
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/list",
"params": {
"_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientInfo": {
"name": "example-client",
"version": "1.0.0"
},
"io.modelcontextprotocol/clientCapabilities": {
"elicitation": {}
}
}
}
}
```
```json Tools List Response theme={null}
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"resultType": "complete",
"tools": [
{
"name": "calculator_arithmetic",
"title": "Calculator",
"description": "Perform mathematical calculations including basic arithmetic, trigonometric functions, and algebraic operations",
"inputSchema": {
"type": "object",
"properties": {
"expression": {
"type": "string",
"description": "Mathematical expression to evaluate (e.g., '2 + 3 * 4', 'sin(30)', 'sqrt(16)')"
}
},
"required": ["expression"]
}
},
{
"name": "weather_current",
"title": "Weather Information",
"description": "Get current weather information for any location worldwide",
"inputSchema": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "City name, address, or coordinates (latitude,longitude)"
},
"units": {
"type": "string",
"enum": ["metric", "imperial", "kelvin"],
"description": "Temperature units to use in response",
"default": "metric"
}
Cut at 300 lines. The page has the rest.
docs/draft/learn/client-concepts New page · 266 lines, new page
# Understanding MCP clients ## Core Client Features ### Elicitation #### Overview #### Example: Holiday Booking Approval #### User Interaction Model ### Roots #### Overview #### Example: Travel Planning Workspace #### Design Philosophy #### User Interaction Model ### Sampling #### Overview #### Example: Flight Analysis Tool #### User Interaction Model
A whole new page. There's nothing to diff it against, so here is what it says.
# Understanding MCP clients
MCP clients are instantiated by host applications to communicate with particular MCP servers. The host application, like Claude.ai or an IDE, manages the overall user experience and coordinates multiple clients. Each client handles one direct communication with one server.
Understanding the distinction is important: the *host* is the application users interact with, while *clients* are the protocol-level components that enable server connections.
## Core Client Features
In addition to making use of context provided by servers, clients may provide several features to servers. These client features allow server authors to build richer interactions.
| Feature | Explanation | Example |
| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| **Elicitation** | Elicitation enables servers to request specific information from users during interactions, providing a structured way for servers to gather information on demand. | A server booking travel may ask for the user's preferences on airplane seats, room type or their contact number to finalize a booking. |
| **Roots** | Roots allow clients to specify which directories servers should focus on, communicating intended scope through a coordination mechanism. Roots are [deprecated](/specification/draft/deprecated) as of protocol version `2026-07-28`. | A server for booking travel may be given access to a specific directory, from which it can read a user's calendar. |
| **Sampling** | Sampling allows servers to request LLM completions through the client, enabling an agentic workflow. This approach puts the client in complete control of user permissions and security measures. Sampling is deprecated as of protocol version `2026-07-28`. | A server for booking travel may send a list of flights to an LLM and request that the LLM pick the best flight for the user. |
### Elicitation
Elicitation enables servers to request specific information from users during interactions, creating more dynamic and responsive workflows.
#### Overview
Elicitation provides a structured way for servers to gather necessary information on demand. Instead of requiring all information up front or failing when data is missing, servers can pause their operations to request specific inputs from users. This creates more flexible interactions where servers adapt to user needs rather than following rigid patterns.
Elicitation supports two modes:
* **Form mode**: The server asks the client to collect structured data from the user. The request includes a schema that the client uses to build an input form and validate the response.
* **URL mode**: The server provides a URL for the user to open. The interaction happens out of band and its data never passes through the client, which makes this mode suitable for sensitive flows such as credential entry or third-party OAuth authorization.
Elicitation follows the [Multi Round-Trip Requests](/specification/draft/basic/patterns/mrtr) (MRTR) pattern. When a server needs user input while processing a request such as `tools/call`, it responds with an `InputRequiredResult` whose `inputRequests` field carries one or more `elicitation/create` requests. The client gathers the input and retries the original request, attaching the collected `inputResponses` and echoing back any `requestState` the server included.
**Elicitation flow:**
```mermaid theme={null}
sequenceDiagram
participant User
participant Client
participant Server
Client->>Server: tools/call (id: 1)
Note over Server: Server needs more information
Server-->>Client: InputRequiredResult with elicitation/create request
Note over Client,User: Human interaction
Client->>User: Present elicitation UI
User-->>Client: Provide requested information
Note over Client,Server: Retry request with user input
Client->>Server: tools/call (id: 2, inputResponses)
Note over Server: Continue processing with new information
Server-->>Client: Final result
```
The flow enables dynamic information gathering. Servers can request specific data when needed, users provide information through appropriate UI, and servers complete the retried request with the newly acquired context.
**Elicitation request example (delivered inside `InputRequiredResult.inputRequests`):**
```typescript theme={null}
{
method: "elicitation/create",
params: {
mode: "form",
message: "Please confirm your Barcelona vacation booking details:",
requestedSchema: {
type: "object",
properties: {
confirmBooking: {
type: "boolean",
description: "Confirm the booking (Flights + Hotel = $3,000)"
},
seatPreference: {
type: "string",
enum: ["window", "aisle", "no preference"],
description: "Preferred seat type for flights"
},
roomType: {
type: "string",
enum: ["sea view", "city view", "garden view"],
description: "Preferred room type at hotel"
},
travelInsurance: {
type: "boolean",
default: false,
description: "Add travel insurance ($150)"
}
},
required: ["confirmBooking"]
}
}
}
```
#### Example: Holiday Booking Approval
A travel booking server demonstrates elicitation's power through the final booking confirmation process. When a user has selected their ideal vacation package to Barcelona, the server needs to gather final approval and any missing details before proceeding.
The server elicits booking confirmation with a structured request that includes the trip summary (Barcelona flights June 15-22, beachfront hotel, total \$3,000) and fields for any additional preferences—such as seat selection, room type, or travel insurance options.
As the booking progresses, the server elicits contact information needed to complete the reservation. It might ask for traveler details for flight bookings, special requests for the hotel, or emergency contact information.
#### User Interaction Model
Elicitation interactions are designed to be clear, contextual, and respectful of user autonomy:
**Request presentation**: Clients display elicitation requests with clear context about which server is asking, why the information is needed, and how it will be used. The request message explains the purpose while the schema provides structure and validation.
**Response options**: Users can provide the requested information through appropriate UI controls (text fields, dropdowns, checkboxes), decline to provide information with optional explanation, or cancel the entire operation. Clients validate responses against the provided schema before returning them to servers.
**URL handling**: For URL mode, clients show the full URL and gather explicit consent before opening it, and never fetch the URL automatically. The client only learns whether the user consented. The interaction itself stays between the user and the target site.
**Privacy considerations**: Servers must not use form mode to request sensitive information such as passwords, API keys, access tokens, or payment credentials. Those interactions belong in URL mode, which keeps the data out of band so it never passes through the client or the LLM context. Clients warn about suspicious requests and let users review form data before sending.
### Roots
<Warning>
Roots are [deprecated](/specification/draft/deprecated) as of protocol version
`2026-07-28` and scheduled for removal. New implementations should pass
directories or files via tool parameters, resource URIs, or server
configuration instead.
</Warning>
Roots define filesystem boundaries for server operations, allowing clients to specify which directories servers should focus on.
#### Overview
Roots are a mechanism for clients to communicate filesystem access boundaries to servers. They consist of file URIs that indicate directories where servers can operate, helping servers understand the scope of available files and folders. While roots communicate intended boundaries, they do not enforce security restrictions. Actual security must be enforced at the operating system level, via file permissions and/or sandboxing.
**Root structure:**
```json theme={null}
{
"uri": "file:///Users/agent/travel-planning",
"name": "Travel Planning Workspace"
}
```
Roots are exclusively filesystem paths and always use the `file://` URI scheme. They help servers understand project boundaries, workspace organization, and accessible directories. The roots list can change as users work with different projects or folders. Servers pick up the updated boundaries the next time they request the roots list.
#### Example: Travel Planning Workspace
A travel agent working with multiple client trips benefits from roots to organize filesystem access. Consider a workspace with different directories for various aspects of travel planning.
The client provides filesystem roots to the travel planning server:
* `file:///Users/agent/travel-planning` - Main workspace containing all travel files
* `file:///Users/agent/travel-templates` - Reusable itinerary templates and resources
* `file:///Users/agent/client-documents` - Client passports and travel documents
When the agent creates a Barcelona itinerary, well-behaved servers respect these boundaries—accessing templates, saving the new itinerary, and referencing client documents within the specified roots. Servers typically access files within roots by using relative paths from the root directories or by utilizing file search tools that respect the root boundaries.
If the agent opens an archive folder like `file:///Users/agent/archive/2023-trips`, the client adds it to the roots list, and the server sees the new boundary on its next `roots/list` request.
For a complete implementation of a server that respects roots, see the [filesystem server](https://github.com/modelcontextprotocol/servers/tree/main/src/filesystem) in the official servers repository.
#### Design Philosophy
Roots serve as a coordination mechanism between clients and servers, not a security boundary. The specification requires that servers "SHOULD respect root boundaries," and not that they "MUST enforce" them, because servers run code the client cannot control.
Roots work best when servers are trusted or vetted, users understand their advisory nature, and the goal is preventing accidents rather than stopping malicious behavior. They excel at context scoping (telling servers where to focus), accident prevention (helping well-behaved servers stay in bounds), and workflow organization (such as managing project boundaries automatically).
#### User Interaction Model
Roots are typically managed automatically by host applications based on user actions, though some applications may expose manual root management:
**Automatic root detection**: When users open folders, clients automatically expose them as roots. Opening a travel workspace allows the client to expose that directory as a root, helping servers understand which itineraries and documents are in scope for the current work.
**Manual root configuration**: Advanced users can specify roots through configuration. For example, adding `/travel-templates` for reusable resources while excluding directories with financial records.
### Sampling
<Warning>
Sampling is [deprecated](/specification/draft/deprecated) as of protocol
version `2026-07-28` and scheduled for removal. New implementations should
integrate directly with LLM provider APIs instead.
</Warning>
Sampling allows servers to request language model completions through the client, enabling agentic behaviors while maintaining security and user control.
#### Overview
Sampling enables servers to perform AI-dependent tasks without directly integrating with or paying for AI models. Instead, servers can request that the client—which already has AI model access—handle these tasks on their behalf. This approach puts the client in complete control of user permissions and security measures. Because sampling requests occur within the context of other operations—like a tool analyzing data—and are processed as separate model calls, they maintain clear boundaries between different contexts, allowing for more efficient use of the context window.
Sampling follows the same [Multi Round-Trip Requests](/specification/draft/basic/patterns/mrtr) flow described under [elicitation](#elicitation), with the `InputRequiredResult` carrying a `sampling/createMessage` request.
Servers can also request tool use during sampling by including a `tools` array and an optional `toolChoice` field in the request. The tool definitions are scoped to that sampling request and do not need to correspond to tools the server exposes. Clients declare support through the `sampling.tools` capability, and servers must not send tool-enabled sampling requests to clients that have not declared it. See [sampling](/specification/draft/client/sampling#tools-in-sampling) in the specification for details.
**Sampling flow:**
```mermaid theme={null}
sequenceDiagram
participant LLM
participant User
participant Client
participant Server
Client->>Server: tools/call (id: 1)
Note over Server: Server needs an LLM completion
Server-->>Client: InputRequiredResult with sampling/createMessage request
Note over Client,User: Human-in-the-loop review
Client->>User: Present request for approval
User-->>Client: Review and approve/modify
Note over Client,LLM: Model interaction
Client->>LLM: Forward approved request
LLM-->>Client: Return generation
Note over Client,User: Response review
Client->>User: Present response for approval
User-->>Client: Review and approve/modify
Note over Client,Server: Retry request with approved response
Client->>Server: tools/call (id: 2, inputResponses)
Server-->>Client: Final result
```
The flow ensures security through multiple human-in-the-loop checkpoints. Users review and can modify both the initial request and the generated response before the client retries the original request with it.
**Request parameters example:**
```typescript theme={null}
{
messages: [
{
role: "user",
content: {
type: "text",
text: "Analyze these flight options and recommend the best choice:\n" +
"[47 flights with prices, times, airlines, and layovers]\n" +
"User preferences: morning departure, max 1 layover"
}
}
],
modelPreferences: {
hints: [{
name: "claude-sonnet-4-20250514" // Suggested model
}],
costPriority: 0.3, // Less concerned about API cost
speedPriority: 0.2, // Can wait for thorough analysis
intelligencePriority: 0.9 // Need complex trade-off evaluation
},
systemPrompt: "You are a travel expert helping users find the best flights based on their preferences",
maxTokens: 1500
}
```
#### Example: Flight Analysis Tool
Consider a travel booking server with a tool called `findBestFlight` that uses sampling to analyze available flights and recommend the optimal choice. When a user asks "Book me the best flight to Barcelona next month," the tool needs AI assistance to evaluate complex trade-offs.
The tool queries airline APIs and gathers 47 flight options. It then requests AI assistance to analyze these options: "Analyze these flight options and recommend the best choice: \[47 flights with prices, times, airlines, and layovers] User preferences: morning departure, max 1 layover."
The client initiates the sampling request, allowing the AI to evaluate trade-offs—like cheaper red-eye flights versus convenient morning departures. The tool uses this analysis to present the top three recommendations.
#### User Interaction Model
While not a requirement, sampling is designed to allow human-in-the-loop control. Users can maintain oversight through several mechanisms:
**Approval controls**: Sampling requests may require explicit user consent. Clients can show what the server wants to analyze and why. Users can approve, deny, or modify requests.
**Transparency features**: Clients can display the exact prompt, model selection, and token limits, allowing users to review AI responses before they return to the server.
**Configuration options**: Users can set model preferences, configure auto-approval for trusted operations, or require approval for everything. Clients may provide options to redact sensitive information.
**Security considerations**: Both clients and servers must handle sensitive data appropriately during sampling. Clients should implement rate limiting and validate all message content. The human-in-the-loop design ensures that server-requested AI interactions cannot compromise security or access sensitive data without explicit user consent.
docs/draft/learn/server-concepts New page · 283 lines, new page
# Understanding MCP servers ## Core Server Features ### Tools #### How Tools Work #### Example: Travel Booking #### User Interaction Model ### Resources #### How Resources Work #### Example: Getting Travel Planning Context #### Parameter Completion #### User Interaction Model ### Prompts #### How Prompts Work #### Example: Streamlined Workflows #### User Interaction Model ## Bringing Servers Together ### Example: Multi-Server Travel Planning #### The Complete Flow
A whole new page. There's nothing to diff it against, so here is what it says.
# Understanding MCP servers
MCP servers are programs that expose specific capabilities to AI applications through standardized protocol interfaces.
Common examples include file system servers for document access, database servers for data queries, GitHub servers for code management, Slack servers for team communication, and calendar servers for scheduling.
## Core Server Features
Servers provide functionality through three building blocks:
| Feature | Explanation | Examples | Who controls it |
| ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------ | --------------- |
| **Tools** | Functions that your LLM can actively call, and decides when to use them based on user requests. Tools can write to databases, call external APIs, modify files, or trigger other logic. | Search flights<br />Send messages<br />Create calendar events | Model |
| **Resources** | Passive data sources that provide read-only access to information for context, such as file contents, database schemas, or API documentation. | Retrieve documents<br />Access knowledge bases<br />Read calendars | Application |
| **Prompts** | Pre-built instruction templates that tell the model to work with specific tools and resources. | Plan a vacation<br />Summarize my meetings<br />Draft an email | User |
We will use a hypothetical scenario to demonstrate the role of each of these features, and show how they can work together.
### Tools
Tools enable AI models to perform actions. Each tool defines a specific operation with typed inputs and outputs. The model requests tool execution based on context.
#### How Tools Work
Tools are schema-defined interfaces that LLMs can invoke. MCP uses JSON Schema for validation. Each tool performs a single operation with clearly defined inputs and outputs. Tools may require user consent prior to execution, helping to ensure users maintain control over actions taken by a model.
**Protocol operations:**
| Method | Purpose | Returns |
| ------------ | ------------------------ | -------------------------------------- |
| `tools/list` | Discover available tools | Array of tool definitions with schemas |
| `tools/call` | Execute a specific tool | Tool execution result |
**Example tool definition:**
```typescript theme={null}
{
name: "searchFlights",
description: "Search for available flights",
inputSchema: {
type: "object",
properties: {
origin: { type: "string", description: "Departure city" },
destination: { type: "string", description: "Arrival city" },
date: { type: "string", format: "date", description: "Travel date" }
},
required: ["origin", "destination", "date"]
}
}
```
#### Example: Travel Booking
Tools enable AI applications to perform actions on behalf of users. In a travel planning scenario, the AI application might use several tools to help book a vacation:
**Flight Search**
```
searchFlights(origin: "NYC", destination: "Barcelona", date: "2024-06-15")
```
Queries multiple airlines and returns structured flight options.
**Calendar Blocking**
```
createCalendarEvent(title: "Barcelona Trip", startDate: "2024-06-15", endDate: "2024-06-22")
```
Marks the travel dates in the user's calendar.
**Email notification**
```
sendEmail(to: "[email protected]", subject: "Out of Office", body: "...")
```
Sends an automated out-of-office message to colleagues.
#### User Interaction Model
Tools are model-controlled, meaning AI models can discover and invoke them automatically. However, MCP emphasizes human oversight through several mechanisms.
For trust and safety, applications can implement user control through various mechanisms, such as:
* Displaying available tools in the UI, enabling users to define whether a tool should be made available in specific interactions
* Approval dialogs for individual tool executions
* Permission settings for pre-approving certain safe operations
* Activity logs that show all tool executions with their results
### Resources
Resources provide structured access to information that the AI application can retrieve and provide to models as context.
#### How Resources Work
Resources expose data from files, APIs, databases, or any other source that an AI needs to understand context. Applications can access this information directly and decide how to use it - whether that's selecting relevant portions, searching with embeddings, or passing it all to the model.
Each resource has a unique URI (e.g., `file:///path/to/document.md`) and declares its MIME type for appropriate content handling.
Resources support two discovery patterns:
* **Direct Resources** - fixed URIs that point to specific data. Example: `calendar://events/2024` - returns calendar availability for 2024
* **Resource Templates** - dynamic URIs with parameters for flexible queries. Example:
* `travel://activities/{city}/{category}` - returns activities by city and category
* `travel://activities/barcelona/museums` - returns all museums in Barcelona
Resource Templates include metadata such as title, description, and expected MIME type, making them discoverable and self-documenting.
**Protocol operations:**
| Method | Purpose | Returns |
| -------------------------- | ------------------------------- | -------------------------------------- |
| `resources/list` | List available direct resources | Array of resource descriptors |
| `resources/templates/list` | Discover resource templates | Array of resource template definitions |
| `resources/read` | Retrieve resource contents | Resource data with metadata |
| `subscriptions/listen` | Monitor resource changes | Stream of update notifications |
To watch specific resources for changes, a client sends a [`subscriptions/listen`](/specification/draft/basic/patterns/subscriptions) request with the resource URIs listed in the `resourceSubscriptions` filter. The server delivers `notifications/resources/updated` on the resulting stream whenever a watched resource changes.
#### Example: Getting Travel Planning Context
Continuing with the travel planning example, resources provide the AI application with access to relevant information:
* **Calendar data** (`calendar://events/2024`) - Checks user availability
* **Travel documents** (`file:///Documents/Travel/passport.pdf`) - Accesses important documents
* **Previous itineraries** (`trips://history/barcelona-2023`) - References past trips and preferences
The AI application retrieves these resources and decides how to process them, whether selecting a subset of data using embeddings or keyword search, or passing raw data directly to the model.
In this case, it provides calendar data, weather information, and travel preferences to the model, enabling it to check availability, look up weather patterns, and reference past travel preferences.
**Resource Template Examples:**
```json theme={null}
{
"uriTemplate": "weather://forecast/{city}/{date}",
"name": "weather-forecast",
"title": "Weather Forecast",
"description": "Get weather forecast for any city and date",
"mimeType": "application/json"
}
{
"uriTemplate": "travel://flights/{origin}/{destination}",
"name": "flight-search",
"title": "Flight Search",
"description": "Search available flights between cities",
"mimeType": "application/json"
}
```
These templates enable flexible queries. For weather data, users can access forecasts for any city/date combination. For flights, they can search routes between any two airports. When a user has input "NYC" as the `origin` airport and begins to input "Bar" as the `destination` airport, the system can suggest "Barcelona (BCN)" or "Barbados (BGI)".
#### Parameter Completion
Dynamic resources support parameter completion. For example:
* Typing "Par" as input for `weather://forecast/{city}` might suggest "Paris" or "Park City"
* Typing "JFK" for `flights://search/{airport}` might suggest "JFK - John F. Kennedy International"
The system helps discover valid values without requiring exact format knowledge.
#### User Interaction Model
Resources are application-driven, giving them flexibility in how they retrieve, process, and present available context. Common interaction patterns include:
* Tree or list views for browsing resources in familiar folder-like structures
* Search and filter interfaces for finding specific resources
* Automatic context inclusion or smart suggestions based on heuristics or AI selection
* Manual or bulk selection interfaces for including single or multiple resources
Applications are free to implement resource discovery through any interface pattern that suits their needs. The protocol doesn't mandate specific UI patterns, allowing for resource pickers with preview capabilities, smart suggestions based on current conversation context, bulk selection for including multiple resources, or integration with existing file browsers and data explorers.
### Prompts
Prompts provide reusable templates. They allow MCP server authors to provide parameterized prompts for a domain, or showcase how to best use the MCP server.
#### How Prompts Work
Prompts are structured templates that define expected inputs and interaction patterns. They are user-controlled, requiring explicit invocation rather than automatic triggering. Prompts can be context-aware, referencing available resources and tools to create comprehensive workflows. Similar to resources, prompts support parameter completion to help users discover valid argument values.
**Protocol operations:**
| Method | Purpose | Returns |
| -------------- | -------------------------- | ------------------------------------- |
| `prompts/list` | Discover available prompts | Array of prompt descriptors |
| `prompts/get` | Retrieve prompt details | Full prompt definition with arguments |
#### Example: Streamlined Workflows
Prompts provide structured templates for common tasks. In the travel planning context:
**"Plan a vacation" prompt:**
```json theme={null}
{
"name": "plan-vacation",
"title": "Plan a vacation",
"description": "Guide through vacation planning process",
"arguments": [
{ "name": "destination", "type": "string", "required": true },
{ "name": "duration", "type": "number", "description": "days" },
{ "name": "budget", "type": "number", "required": false },
{ "name": "interests", "type": "array", "items": { "type": "string" } }
]
}
```
Rather than unstructured natural language input, the prompt system enables:
1. Selection of the "Plan a vacation" template
2. Structured input: Barcelona, 7 days, \$3000, \["beaches", "architecture", "food"]
3. Consistent workflow execution based on the template
#### User Interaction Model
Prompts are user-controlled, requiring explicit invocation. The protocol gives implementers freedom to design interfaces that feel natural within their application. Key principles include:
* Easy discovery of available prompts
* Clear descriptions of what each prompt does
* Natural argument input with validation
* Transparent display of the prompt's underlying template
Applications typically expose prompts through various UI patterns such as:
* Slash commands (typing "/" to see available prompts like /plan-vacation)
* Command palettes for searchable access
* Dedicated UI buttons for frequently used prompts
* Context menus that suggest relevant prompts
## Bringing Servers Together
The real power of MCP emerges when multiple servers work together, combining their specialized capabilities through a unified interface.
### Example: Multi-Server Travel Planning
Consider a personalized AI travel planner application, with three connected servers:
* **Travel Server** - Handles flights, hotels, and itineraries
* **Weather Server** - Provides climate data and forecasts
* **Calendar/Email Server** - Manages schedules and communications
#### The Complete Flow
1. **User invokes a prompt with parameters:**
```json theme={null}
{
"prompt": "plan-vacation",
"arguments": {
"destination": "Barcelona",
"departure_date": "2024-06-15",
"return_date": "2024-06-22",
"budget": 3000,
"travelers": 2
}
}
```
2. **User selects resources to include:**
* `calendar://my-calendar/June-2024` (from Calendar Server)
* `travel://preferences/europe` (from Travel Server)
* `travel://past-trips/Spain-2023` (from Travel Server)
3. **AI processes the request using tools:**
The AI first reads all selected resources to gather context - identifying available dates from the calendar, learning preferred airlines and hotel types from travel preferences, and discovering previously enjoyed locations from past trips.
Using this context, the AI then executes the prompt provided by the AI application. In our example, the AI application exposes the weather tools from the connected MCP weather server to the model. Because weather can affect travel plans, the AI chooses to call `checkWeather()` when interpreting the prompt.
As a result the AI executes a series of tools:
* `searchFlights()` - Queries airlines for NYC to Barcelona flights
* `checkWeather()` - Retrieves climate forecasts for travel dates
The AI then uses this information to create the booking and following steps, requesting approval from the user where necessary:
* `bookHotel()` - Finds hotels within the specified budget
* `createCalendarEvent()` - Adds the trip to the user's calendar
* `sendEmail()` - Sends confirmation with trip details
**The result:** Through multiple MCP servers, the user researched and booked a Barcelona trip tailored to their schedule. The "Plan a Vacation" prompt guided the AI to combine Resources (calendar availability and travel history) with Tools (searching flights, booking hotels, updating calendars) across different servers—gathering context and executing the booking. A task that could have taken hours was completed in minutes using MCP.
docs/draft/learn/versioning New page · 62 lines, new page
# Versioning ## Revisions ## Feature States ## Negotiation
A whole new page. There's nothing to diff it against, so here is what it says.
# Versioning The Model Context Protocol uses string-based version identifiers following the format `YYYY-MM-DD`, to indicate the last date backwards incompatible changes were made. <Info> The protocol version will *not* be incremented when the protocol is updated, as long as the changes maintain backwards compatibility. This allows for incremental improvements while preserving interoperability. </Info> ## Revisions Revisions may be marked as: * **Draft**: in-progress specifications, not yet ready for consumption. * **Current**: the current protocol version, which is ready for use and may continue to receive backwards compatible changes. * **Final**: past, complete specifications that will not be changed. The **current** protocol version is [**2026-07-28**](/specification/2026-07-28/). ## Feature States Individual features of the specification may additionally be marked as **Deprecated** under the [feature lifecycle and deprecation policy](/community/feature-lifecycle): the feature remains part of the specification, but is scheduled for removal. Deprecated features document a migration path (or state that none is required) and remain in the specification for at least twelve months, or at least ninety days under the policy's [expedited-removal exception](/community/feature-lifecycle#expedited-removal), before they become eligible for removal, after which they may be **Removed** in a future revision. Features that are currently Deprecated are listed in the [deprecated features registry](/specification/draft/deprecated). ## Negotiation Every request declares the protocol version it is using via the `io.modelcontextprotocol/protocolVersion` key in its [`_meta`](/specification/draft/basic/index#meta) field, and the server accepts or rejects each request independently. On Streamable HTTP, the same value is also carried in the [`MCP-Protocol-Version` header](/specification/draft/basic/transports/streamable-http#protocol-version-header). Clients and servers **MAY** support multiple protocol versions simultaneously. If the server does not support the requested version, it responds with an [`UnsupportedProtocolVersionError`](/specification/draft/basic/versioning#protocol-version-negotiation) listing the versions it does support. The client can then retry the request with a mutually supported version, or surface an error to the user if none exists. Clients that want to select a version up front can call [`server/discover`](/specification/draft/server/discover), a mandatory RPC that returns the server's supported protocol versions, capabilities, and identity in a single request. Calling it is optional: a client is free to send any request directly and handle a version error if one comes back. For interoperability with servers and clients that implement the handshake-based protocol revisions (`2025-11-25` and earlier), see [Backward Compatibility](/specification/draft/basic/versioning#backward-compatibility-with-initialization-based-versions).
docs/draft/sdk New page · 47 lines, new page
# SDKs ## Available SDKs ## Getting Started ## Next Steps
A whole new page. There's nothing to diff it against, so here is what it says.
# SDKs
> Official SDKs for building with Model Context Protocol
Build MCP servers and clients using our official SDKs. SDKs are classified into tiers based on feature completeness, protocol support, and maintenance commitment. Learn more about [SDK tiers](/community/sdk-tiers).
## Available SDKs
| SDK | Repository | Tier |
| :----------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------- | ------------------------------------------------: |
| <Icon icon="square-js" size={24} /> [TypeScript](https://ts.sdk.modelcontextprotocol.io) | [modelcontextprotocol/typescript-sdk](https://github.com/modelcontextprotocol/typescript-sdk) | <Badge color="blue" shape="pill">Tier 1</Badge> |
| <Icon icon="python" size={24} /> [Python](https://py.sdk.modelcontextprotocol.io) | [modelcontextprotocol/python-sdk](https://github.com/modelcontextprotocol/python-sdk) | <Badge color="blue" shape="pill">Tier 1</Badge> |
| <Icon icon="square-c" size={24} /> [C#](https://csharp.sdk.modelcontextprotocol.io) | [modelcontextprotocol/csharp-sdk](https://github.com/modelcontextprotocol/csharp-sdk) | <Badge color="blue" shape="pill">Tier 1</Badge> |
| <Icon icon="golang" size={24} /> [Go](https://go.sdk.modelcontextprotocol.io) | [modelcontextprotocol/go-sdk](https://github.com/modelcontextprotocol/go-sdk) | <Badge color="blue" shape="pill">Tier 1</Badge> |
| <Icon icon="rust" size={24} /> [Rust](https://rust.sdk.modelcontextprotocol.io) | [modelcontextprotocol/rust-sdk](https://github.com/modelcontextprotocol/rust-sdk) | <Badge color="blue" shape="pill">Tier 1</Badge> |
| <Icon icon="java" size={24} /> [Java](https://java.sdk.modelcontextprotocol.io) | [modelcontextprotocol/java-sdk](https://github.com/modelcontextprotocol/java-sdk) | <Badge color="purple" shape="pill">Tier 2</Badge> |
| <Icon icon="gem" size={24} /> [Ruby](https://ruby.sdk.modelcontextprotocol.io) | [modelcontextprotocol/ruby-sdk](https://github.com/modelcontextprotocol/ruby-sdk) | <Badge color="purple" shape="pill">Tier 2</Badge> |
| <Icon icon="swift" size={24} /> Swift | [modelcontextprotocol/swift-sdk](https://github.com/modelcontextprotocol/swift-sdk) | <Badge color="orange" shape="pill">Tier 3</Badge> |
| <Icon icon="php" size={24} /> [PHP](https://php.sdk.modelcontextprotocol.io) | [modelcontextprotocol/php-sdk](https://github.com/modelcontextprotocol/php-sdk) | <Badge color="orange" shape="pill">Tier 3</Badge> |
| <Icon icon="square-k" size={24} /> [Kotlin](https://kotlin.sdk.modelcontextprotocol.io) | [modelcontextprotocol/kotlin-sdk](https://github.com/modelcontextprotocol/kotlin-sdk) | <Badge color="orange" shape="pill">Tier 3</Badge> |
See [SDK Tiering System](/community/sdk-tiers) for details on what each tier means.
## Getting Started
Each SDK provides the same functionality but follows the idioms and best practices of its language. All SDKs support:
* Creating MCP servers that expose tools, resources, and prompts
* Building MCP clients that can connect to any MCP server
* Local and remote transport protocols
* Protocol compliance with type safety
Visit the SDK page for your chosen language to find installation instructions, documentation, and examples.
## Next Steps
Ready to start building with MCP? Choose your path:
<CardGroup cols={2}>
<Card title="Build a Server" icon="server" href="/docs/draft/develop/build-server">
Learn how to create your first MCP server
</Card>
<Card title="Build a Client" icon="computer" href="/docs/draft/develop/build-client">
Create applications that connect to MCP servers
</Card>
</CardGroup>
docs/draft/tools/debugging New page · 368 lines, new page
# Debugging ## Debugging tools overview ## Implementing logging ### Server-side logging ## Common issues ### Working directory ### Environment variables ### Server startup ### Connection problems ## Debugging in Claude Desktop ### Checking server status ### Viewing logs ### Using Chrome DevTools ## Debugging workflow ### Development cycle ### Testing changes ## Best practices ### Logging strategy ### Security considerations ## Getting help ## Next steps
A whole new page. There's nothing to diff it against, so here is what it says.
# Debugging
> A comprehensive guide to debugging Model Context Protocol (MCP) integrations
Effective debugging is essential when developing MCP servers or integrating
them with applications. This guide covers the debugging tools and approaches
available in the MCP ecosystem.
## Debugging tools overview
MCP provides several tools for debugging at different levels:
1. **[MCP Inspector](/docs/draft/tools/inspector)**: interactive, transport-agnostic
testing UI. Connect to stdio or Streamable HTTP servers, invoke
[tools](/specification/latest/server/tools),
[prompts](/specification/latest/server/prompts), and
[resources](/specification/latest/server/resources), and watch the
notification stream. This should be your first stop.
2. **Server logging**: structured logs to stderr (stdio transport) or via
[OpenTelemetry](https://opentelemetry.io/) (all transports).
[Logging](/specification/draft/server/utilities/logging) over the protocol
(`notifications/message`) is deprecated as of protocol version `2026-07-28`.
3. **Client developer tools**: most MCP clients expose logs and connection
state. See [Debugging in Claude Desktop](#debugging-in-claude-desktop)
below for one example, or consult your client's documentation.
## Implementing logging
### Server-side logging
When building a server that uses the local
[stdio transport](/specification/draft/basic/transports/stdio), all messages
logged to stderr (standard error) will be captured by the host application
automatically.
<Warning>
Local MCP servers should not log messages to stdout (standard out), as this
will interfere with protocol operation.
</Warning>
For servers using the
[Streamable HTTP transport](/specification/draft/basic/transports/streamable-http),
stderr is not captured by the client. Use your own server-side log aggregation
or [OpenTelemetry](https://opentelemetry.io/) for logs, and standard HTTP
tooling (curl, browser DevTools Network panel) to inspect requests and SSE
streams.
<Warning>
The `notifications/message` mechanism below is deprecated as of protocol
version `2026-07-28`. It remains available during the deprecation window.
</Warning>
For all [transports](/specification/latest/basic/transports), record what the
server is doing as it runs:
<CodeGroup>
```python Python theme={null}
import logging
from mcp.server import MCPServer
logger = logging.getLogger(__name__)
mcp = MCPServer("reports")
@mcp.tool()
async def fetch_report(report_id: str) -> str:
"""Fetch a report by id."""
logger.info("Fetching report %s", report_id)
return f"Report {report_id} is ready."
```
```typescript TypeScript theme={null}
await server.sendLoggingMessage({
level: "info",
data: "Server started successfully",
});
```
</CodeGroup>
MCP defines eight
[RFC 5424 severity levels](/specification/latest/server/utilities/logging#log-levels)
(`debug` through `emergency`). Clients opt in to log messages per request by
setting the
[`io.modelcontextprotocol/logLevel`](/specification/draft/server/utilities/logging#per-request-log-level)
field in the request's `_meta`. Servers must not send `notifications/message`
for requests that omit this field.
Important events to log:
* Startup steps
* Resource access
* Tool execution
* Error conditions
* Performance metrics
## Common issues
The examples below use Claude Desktop's
[`claude_desktop_config.json`](/docs/draft/develop/connect-local-servers); the same
principles apply to any stdio-based MCP client.
### Working directory
When an MCP client launches a stdio server:
* The working directory for servers launched via the client's config may be
undefined (like `/` on macOS) since the client could be started from
anywhere
* Always use absolute paths in your configuration and `.env` files to ensure
reliable operation
* For testing servers directly via command line, the working directory will be
where you run the command
For example in `claude_desktop_config.json`, use:
```json theme={null}
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"/Users/username/data"
]
}
}
}
```
Instead of relative paths like `./data`
### Environment variables
MCP servers launched over stdio inherit only a limited subset of environment
variables automatically (the exact set is platform-dependent).
To override the default variables or provide your own, you can specify an
`env` key in `claude_desktop_config.json`:
```json theme={null}
{
"mcpServers": {
"myserver": {
"command": "mcp-server-myapp",
"env": {
"MYAPP_API_KEY": "some_key"
}
}
}
}
```
### Server startup
Common startup problems:
1. **Path Issues**
* Incorrect server executable path
* Missing required files
* Permission problems
* Try using an absolute path for `command`
2. **Configuration Errors**
* Invalid JSON syntax
* Missing required fields
* Type mismatches
3. **Environment Problems**
* Missing environment variables
* Incorrect variable values
* Permission restrictions
### Connection problems
When servers fail to connect:
1. Check client logs
2. Verify server process is running
3. Test standalone with [Inspector](/docs/draft/tools/inspector)
4. Verify
[protocol compatibility](/docs/draft/learn/versioning#negotiation): call
[`server/discover`](/specification/draft/server/discover) to see which
protocol versions the server supports. An
`UnsupportedProtocolVersionError` (`-32022`) lists the server's supported
versions in its `data` field
5. Check the
[per-request `_meta` fields](/specification/draft/basic/index#meta):
every request must carry `io.modelcontextprotocol/protocolVersion` and
`io.modelcontextprotocol/clientCapabilities`, and clients should also
include `io.modelcontextprotocol/clientInfo`. A request missing either
required field is rejected with error `-32602` (Invalid params), the same
code returned for many other malformed inputs. If the server needs a
capability the request's `clientCapabilities` did not declare, such as
[elicitation](/specification/draft/client/elicitation), it returns a
`MissingRequiredClientCapabilityError` (`-32021`) naming the missing
capabilities. Inspect the request's `_meta` and the
[`server/discover`](/specification/draft/server/discover) response to
verify both sides declared what you expect
## Debugging in Claude Desktop
Claude Desktop is one of many MCP clients. It is available on
macOS and Windows.
### Checking server status
Click the "Add files, connectors, and more" plus icon in the chat input, then
hover over the **Connectors** menu to see connected servers and available
tools.
<img src="https://mintcdn.com/mcp/zNouQwo2h8cbxlDS/images/available-mcp-tools.png?fit=max&auto=format&n=zNouQwo2h8cbxlDS&q=85&s=e2ace1ac88895a5fe30ebd8d01456bc3" alt="Available MCP tools" width="437" height="244" data-path="images/available-mcp-tools.png" />
### Viewing logs
Log files are written to:
* macOS: `~/Library/Logs/Claude`
* Windows: `%APPDATA%\Claude\logs`
<CodeGroup>
```bash macOS theme={null}
tail -n 20 -F ~/Library/Logs/Claude/mcp*.log
```
```powershell Windows theme={null}
type "$env:AppData\Claude\logs\mcp*.log"
```
</CodeGroup>
The logs capture:
* Server connection events
* Configuration issues
* Runtime errors
* Message exchanges
### Using Chrome DevTools
Access Chrome's developer tools inside Claude Desktop to investigate
client-side errors:
1. Create a `developer_settings.json` file with `allowDevTools` set to true:
<CodeGroup>
```bash macOS theme={null}
echo '{"allowDevTools": true}' > ~/Library/Application\ Support/Claude/developer_settings.json
```
```powershell Windows theme={null}
'{"allowDevTools": true}' | Set-Content "$env:AppData\Claude\developer_settings.json"
```
</CodeGroup>
2. Open DevTools: `Command-Option-I` (macOS) or `Ctrl+Alt+I` (Windows)
Note: You'll see two DevTools windows:
* Main content window
* App title bar window
Use the Console panel to inspect client-side errors.
Use the Network panel to inspect:
* Message payloads
* Connection timing
## Debugging workflow
### Development cycle
1. Initial Development
* Use [Inspector](/docs/draft/tools/inspector) for basic testing
* Implement core functionality
* Add logging points
2. Integration Testing
* Test in your target MCP client
* Monitor logs
* Check error handling
### Testing changes
To test changes efficiently:
* **Configuration changes**: Restart the MCP client
* **Server code changes**: Restart the client (for Claude Desktop, fully quit
and reopen; closing the window is not enough)
* **Quick iteration**: Use [Inspector](/docs/draft/tools/inspector) during
development
## Best practices
### Logging strategy
1. **Structured Logging**
* Use consistent formats
Cut at 300 lines. The page has the rest.
docs/draft/tools/inspector New page · 144 lines, new page
# MCP Inspector ## Quickstart ### Inspecting published servers ## Launcher flags vs. client flags ## Where to go next
A whole new page. There's nothing to diff it against, so here is what it says.
# MCP Inspector
> Interactive developer tooling for testing and debugging MCP servers, in the browser, on the command line, and in the terminal
The [MCP Inspector](https://github.com/modelcontextprotocol/inspector) is the reference developer tool for testing and debugging [MCP servers](/docs/draft/learn/server-concepts). It ships as a single package, `@modelcontextprotocol/inspector`, providing **three clients behind one binary**:
| Client | Invocation | What it's for |
| ------- | ------------------------------------------- | --------------------------------------------------------------------------------- |
| **Web** | `npx @modelcontextprotocol/inspector` | A full graphical inspector in the browser. The default, and the richest surface. |
| **CLI** | `npx @modelcontextprotocol/inspector --cli` | A scriptable, machine-readable client for CI, shell pipelines, and coding agents. |
| **TUI** | `npx @modelcontextprotocol/inspector --tui` | An interactive terminal UI, for when a browser isn't available or wanted. |
All three are built on the same shared core, so a connection behaves identically across them: the same transports, the same configuration files, the same OAuth state on disk, and the same [protocol-era](/docs/draft/tools/inspector/protocol-eras) negotiation (legacy vs. modern 2026-07-28).
<Frame caption="The MCP Inspector web client, connected to a server, with the monitoring sidebar pinned so protocol traffic stays visible while you work.">
<img src="https://mintcdn.com/mcp/gk28X8wi_tbRYzej/images/inspector/web-monitor-sidebar.png?fit=max&auto=format&n=gk28X8wi_tbRYzej&q=85&s=eef6e546b9831b3d169e26bba8c54ce3" width="3840" height="2160" data-path="images/inspector/web-monitor-sidebar.png" />
</Frame>
## Quickstart
The Inspector requires **Node 22.19.0 or newer** and runs directly through `npx`. No installation is required:
<Tabs>
<Tab title="Web">
```bash theme={null}
# Launch the web UI and connect to a local stdio server
npx @modelcontextprotocol/inspector node path/to/server/index.js
# Or launch with no target and add servers from the UI
npx @modelcontextprotocol/inspector
```
The command prints a URL containing a one-time session token; open it in your browser. See [Web client](/docs/draft/tools/inspector/web).
</Tab>
<Tab title="CLI">
```bash theme={null}
# List a server's tools and exit
npx @modelcontextprotocol/inspector --cli node path/to/server/index.js --method tools/list
# Call a tool and pipe the result into jq
npx @modelcontextprotocol/inspector --cli https://api.example.com/mcp --transport http \
--method tools/call --tool-name get_weather --tool-arg city=Boston --format json | jq .result
```
See [CLI client](/docs/draft/tools/inspector/cli).
</Tab>
<Tab title="TUI">
```bash theme={null}
npx @modelcontextprotocol/inspector --tui node path/to/server/index.js
```
See [TUI client](/docs/draft/tools/inspector/tui).
</Tab>
</Tabs>
### Inspecting published servers
Pass the command that launches the server as the Inspector's arguments, or point it at a remote server with `--server-url`:
<Tabs>
<Tab title="npm package">
```bash theme={null}
npx -y @modelcontextprotocol/inspector npx @modelcontextprotocol/server-filesystem ~/Desktop
```
</Tab>
<Tab title="PyPI package">
```bash theme={null}
npx @modelcontextprotocol/inspector uvx mcp-server-git --repository ~/code/mcp/servers.git
```
</Tab>
<Tab title="Remote HTTP server">
```bash theme={null}
npx @modelcontextprotocol/inspector --server-url https://api.example.com/mcp --transport http
```
</Tab>
</Tabs>
Always read a server's own README first, since every server requires different commands and arguments.
## Launcher flags vs. client flags
`mcp-inspector`, the binary that `npx @modelcontextprotocol/inspector` runs, is a thin launcher. It owns only two things:
1. **The mode flag:** `--web` (default), `--cli`, or `--tui`. At most one; passing two errors with `Specify at most one of --web, --cli, or --tui.`
2. **`-h` / `--help`.**
Everything else (`--catalog`, `--config`, `--server-url`, `--transport`, `--method`, the OAuth flags) is defined by the *client*, not the launcher, and the clients do not all define the same set. The [Configuration and flags](/docs/draft/tools/inspector/configuration) page is organized that way, by owner.
<Note>
Mode flags are recognized only at the front of the command line: the first token that isn't `--web` / `--cli` / `--tui` ends launcher parsing, and everything after it is forwarded to the client unchanged. That's what lets a literal `--cli` appear later as one of your server's own arguments:
```bash theme={null}
mcp-inspector --cli node server.js --cli # mode is CLI; the trailing --cli goes to server.js
```
</Note>
<Note>
`--help` behaves differently with and without a mode flag. Bare `mcp-inspector --help` prints the launcher's help and exits. With a mode flag it is
forwarded, so `mcp-inspector --cli --help` prints the CLI's full flag
reference instead.
</Note>
## Where to go next
<CardGroup cols={2}>
<Card title="Web client" icon="browser" href="/docs/draft/tools/inspector/web">
A tab-by-tab walkthrough of the graphical inspector.
</Card>
<Card title="CLI client" icon="terminal" href="/docs/draft/tools/inspector/cli">
Method reference, output formats, exit codes, and CI recipes.
</Card>
<Card title="TUI client" icon="table-columns" href="/docs/draft/tools/inspector/tui">
Terminal navigation and keyboard reference.
</Card>
<Card title="Configuration and flags" icon="sliders" href="/docs/draft/tools/inspector/configuration">
Catalog vs. config files, the full per-client flag reference, and
environment variables.
</Card>
<Card title="Authorization" icon="lock" href="/docs/draft/tools/inspector/authorization">
The OAuth flow end to end, mid-session re-authorization, and loopback
callbacks.
</Card>
<Card title="Protocol eras" icon="code-branch" href="/docs/draft/tools/inspector/protocol-eras">
Legacy vs. modern (2026-07-28) operation, and how every tab changes between
protocol eras.
</Card>
<Card title="Recipes" icon="book" href="/docs/draft/tools/inspector/recipes">
Importing client configs, reviewing MCP Apps, Docker, and network hosting.
</Card>
<Card title="Debugging guide" icon="bug" href="/docs/draft/tools/debugging">
Broader debugging strategies beyond the Inspector.
</Card>
</CardGroup>
docs/draft/tools/inspector/authorization New page · 159 lines, new page
# Authorization ## The flow, end to end ## Callback URLs ## Where credentials live ## Mid-session re-authorization ## Non-interactive and CI runs ## Handing off from the web client to the CLI ## Inspecting auth state
A whole new page. There's nothing to diff it against, so here is what it says.
# Authorization
> How the MCP Inspector performs OAuth, re-authorizes mid-session, and shares tokens between its clients
Remote MCP servers usually require authorization. The Inspector implements the full [authorization](/specification/latest/basic/authorization) flow in all three clients, sharing the resulting tokens on disk so a login done once is usable everywhere.
## The flow, end to end
<Steps>
<Step title="Connect, and get refused">
The Inspector connects to the server URL. The server answers `401`. When the
response carries a `WWW-Authenticate` header, it points at the
protected-resource metadata URL (`resource_metadata`) and, optionally, the
scopes the request requires.
</Step>
<Step title="Discover the authorization server">
The Inspector fetches the server's [protected-resource and
authorization-server
metadata](/specification/latest/basic/authorization/authorization-server-discovery)
to learn the endpoints and the supported grants.
</Step>
<Step title="Register or identify the client">
The Inspector identifies itself to the authorization server through
whichever mechanism is configured: [dynamic client
registration](/specification/latest/basic/authorization/client-registration#dynamic-client-registration),
a pre-registered static client (`--client-id` / `--client-secret`), a
[Client ID Metadata
Document](/specification/latest/basic/authorization/client-registration#client-id-metadata-documents)
(`--client-metadata-url`), or an [enterprise-managed
IdP](/extensions/auth/enterprise-managed-authorization).
</Step>
<Step title="Authorize in the browser">
The Inspector opens the authorization URL. You sign in and consent.
</Step>
<Step title="Receive the callback">
The authorization server redirects to the Inspector's callback URL, carrying
the authorization code.
</Step>
<Step title="Exchange and retry">
The code is exchanged for tokens, the tokens are persisted, and the original
connect (or, for a [mid-session challenge](#mid-session-re-authorization),
the request that was refused) is retried automatically.
</Step>
</Steps>
<Frame caption="Connection Info after a completed OAuth flow: the authorization status, the dynamically registered client, and the granted scopes.">
<img src="https://mintcdn.com/mcp/gk28X8wi_tbRYzej/images/inspector/auth-connection-info.png?fit=max&auto=format&n=gk28X8wi_tbRYzej&q=85&s=01a8d11058c2d33e0069b8dec98591b5" width="3840" height="2160" data-path="images/inspector/auth-connection-info.png" />
</Frame>
## Callback URLs
The web app listens for the OAuth callback on its own URL, while the CLI and TUI deliberately share a second one:
| Surface | Default callback | Why |
| ------- | -------------------------------------- | ---------------------------------------------------------------------------------- |
| **Web** | `http://localhost:6274/oauth/callback` | The main app server already has an HTTP listener. |
| **CLI** | `http://127.0.0.1:6276/oauth/callback` | A dedicated loopback listener, so it doesn't collide with a running web Inspector. |
| **TUI** | `http://127.0.0.1:6276/oauth/callback` | The same listener as the CLI. |
**Register `http://127.0.0.1:6276/oauth/callback`** on any IdP that requires pre-registered redirect URIs before using the CLI or TUI. A predictable default is the point: you register once and reuse it.
Override with `--callback-url` or `MCP_OAUTH_CALLBACK_URL`.
<Warning>
The callback URL **must bind a loopback host**: `localhost`, `127.0.0.0/8`, or
`[::1]`. The listener receives the authorization code over plaintext `http`,
so a non-loopback host is rejected with an error and there is no flag to
override that. If your browser runs on a different machine, forward the
callback port to it; `--print-handoff` (below) prints a ready-made
`portForwardCmd`.
</Warning>
<Note>
Redirect URIs must match your registration **exactly**. `http://localhost:6276/...` and `http://127.0.0.1:6276/...` are different URIs to an authorization server, even though they reach the same listener.
Only one process can hold the default port at a time; a second concurrent flow fails with `EADDRINUSE`. Use a different fixed port per instance, or `http://127.0.0.1:0/oauth/callback` for an OS-assigned ephemeral port when your authorization server supports dynamic redirect-URI registration.
</Note>
## Where credentials live
| File | Contents |
| --------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| `~/.mcp-inspector/storage/oauth.json` | Tokens and client information, keyed by canonicalized server URL. Written owner-only. |
| `~/.mcp-inspector/storage/client.json` | Install-level client settings (client metadata URL, enterprise IdP). The same file the web client's **Client Settings** dialog writes. |
| The server's `oauth` block in the [catalog file](/docs/draft/tools/inspector/configuration#catalog-file-format) | Per-server client id/secret, scopes, the enterprise-managed flag, and the [step-up](#mid-session-re-authorization) policy. |
The path to `oauth.json` is resolved in order: `MCP_INSPECTOR_OAUTH_STATE_PATH`, then `<MCP_STORAGE_DIR>/oauth.json` (see [Environment variables](/docs/draft/tools/inspector/configuration#environment-variables)), then the default above. All three clients resolve it the same way. Command-line `--client-id` / `--client-secret` / `--client-metadata-url` override `client.json`.
## Mid-session re-authorization
A server can refuse a *single* request mid-session with a `401` or a `403 insufficient_scope`, and the Inspector handles both without dropping the connection:
* **Re-authorization**: the token expired or was revoked. The Inspector parses the `WWW-Authenticate` challenge and re-runs the flow, then retries the failed request.
* **Step-up**: the request needs scopes the current token doesn't carry. The Inspector re-authorizes for the union of the held and required scopes, so the new token covers everything the old one did plus the newly required scopes.
In the **web** client this surfaces as a re-authorization banner. In the **CLI** it prompts on stderr:
```
Proceed with step-up authorization? [y/N]
```
Answer **y** to continue. Piped input works (`echo y | ...`), as long as it's newline-terminated or stdin closes. **N**, or EOF with no answer, declines. A non-TTY stdin that sends nothing within 5 seconds fails with `auth_required`, which is distinct from an explicit decline. Enterprise-managed step-up re-mints silently, with no prompt.
## Non-interactive and CI runs
Interactive OAuth requires a TTY on **stdin or stderr**, or [`MCP_AUTO_OPEN_ENABLED=true`](/docs/draft/tools/inspector/configuration#environment-variables). Redirecting stderr into a pipe, as in `2>&1 | tee`, still works because stdin stays a TTY. When neither is true, which is the normal CI shape, the CLI fails fast with `auth_required` rather than waiting up to fifteen minutes for a callback nobody will complete.
For CI, be explicit:
```bash theme={null}
mcp-inspector --cli "$URL" --transport http --stored-auth-only --method tools/list
```
`--stored-auth-only` never starts interactive OAuth or step-up, never opens a browser, uses the shared store if a token is there, and fails immediately otherwise.
## Handing off from the web client to the CLI
The common case: a human completed OAuth in the web Inspector on this machine, and now a script wants to use that token.
| Flag | Behavior |
| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--use-stored-auth` | Read the stored auth for `--server-url` and inject `Authorization: Bearer`. When a refresh token is stored, run the refresh grant first and inject the **fresh** token, persisting the rotation. Exits `3` (listing the stored server URLs) when nothing matches. |
| `--wait-for-auth <sec>` | Poll the state file until a token for `--server-url` appears, then inject it. Times out at `<sec>` with exit `3`. Use after handing a login off to a human. |
| `--list-stored-auth` | Print `{ oauthStatePath, storedServerUrls }` and exit without connecting. |
| `--print-handoff` | Print a JSON block (`deepLink`, `portForwardCmd`, `oauthStatePath`, `apiToken`) for `--server-url` and exit; this is everything a remote script needs to drive the browser side. |
| `--relogin` | Delete the stored OAuth for this server URL before connecting. HTTP/SSE only. |
A typical remote-VM sequence:
```bash theme={null}
# On the VM: print what the human needs in order to complete OAuth in their browser
mcp-inspector --cli --server-url https://api.example/mcp --print-handoff
# Then block until the token lands, and run the call with it
mcp-inspector --cli --transport http --server-url https://api.example/mcp \
--wait-for-auth 120 --method tools/list
```
The `deepLink` in the handoff block navigates a browser straight to a *connected* Inspector; see [Deep links](/docs/draft/tools/inspector/web#deep-links).
<Note>
Because the stored entry records no expiry, a stored refresh token is
exercised on **every** `--use-stored-auth` run. With rotating (single-use)
refresh tokens that opens two narrow failure windows: two concurrent
invocations against the same state file can race for the token, and a crash
between a successful refresh and the write-back leaves the rotated token
unsaved. Both are unlikely; re-authorize in the web client to recover.
</Note>
## Inspecting auth state
* **Web**: the Connection Info panel shows discovery results, the registered client, granted scopes, and token state, and offers **Clear OAuth state** for the active server.
* **TUI**: the **Auth** tab (`a`) shows the same fields and clears state the same way.
* **CLI**: `--list-stored-auth` shows what's on disk, and `--relogin` discards it and starts over.
docs/draft/tools/inspector/cli New page · 196 lines, new page
# CLI client ## Choosing a server ## Methods ### Passing arguments ## Output ## Probing MCP Apps ## Exit codes and error envelopes ## Authorization in scripts ## Recipes ### Verify a server in CI ### Branch on the failure class ### Smoke-test every tool that has a UI ### Inspect a catalog without connecting ## Proxies
A whole new page. There's nothing to diff it against, so here is what it says.
# CLI client
> Scripting the MCP Inspector: methods, output formats, exit codes, and CI recipes
Each CLI run connects to a server, invokes the single request you name with `--method`, prints the result, and exits. That makes it a good fit for CI pipelines, shell one-liners, and coding agents that need to verify a server change immediately.
```bash theme={null}
npx @modelcontextprotocol/inspector --cli node build/index.js --method tools/list
```
The examples below use the installed `mcp-inspector` binary. Without a global install, prefix each command with `npx @modelcontextprotocol/inspector` instead, as above.
## Choosing a server
The CLI accepts a positional command (stdio), a `--server-url` (HTTP/SSE), or a named server out of a catalog or config file:
```bash theme={null}
# stdio: everything positional is the command to spawn
mcp-inspector --cli node build/index.js --method tools/list
# HTTP
mcp-inspector --cli https://api.example.com/mcp --transport http --method tools/list
# From a file
mcp-inspector --cli --config ./mcp.json --server myserver --method tools/list
```
When the server comes from a file, its per-server settings (headers, timeouts, OAuth, [protocol era](/docs/draft/tools/inspector/protocol-eras), and roots) apply to the connection, resolved exactly as the TUI and web client resolve them. A `--header` flag overrides the file's headers for that run while leaving its timeouts and OAuth in place.
Later examples abbreviate whichever of these forms you use, along with its `--transport` or `--config`/`--server` flags, as `<server>`.
<Note>
**The config file is the only durable way to give a run its
[roots](/specification/draft/client/roots):** there is no roots flag, and
`--method roots/set` applies only to that one short-lived connection. Roots
configured for a server are advertised at connect, so a server that calls
`roots/list` (as `@modelcontextprotocol/server-filesystem` does, to learn its
allowed directories) gets them.
</Note>
See [Configuration and flags](/docs/draft/tools/inspector/configuration) for `--catalog` vs. `--config`, the `--` separator, and the shared server-selection flags.
## Methods
| `--method` | Required companions | Notes |
| ------------------------------ | ----------------------------------------------------- | -------------------------------------------------------------------------------- |
| `initialize` | None | Connect-only probe: `{serverInfo, protocolVersion, capabilities, instructions}`. |
| `tools/list` | None | |
| `tools/call` | `--tool-name`, plus `--tool-arg` / `--tool-args-json` | |
| `resources/list` | None | |
| `resources/read` | `--uri` | |
| `resources/templates/list` | None | |
| `prompts/list` | None | |
| `prompts/get` | `--prompt-name`, `--prompt-args` | |
| `logging/setLevel` | `--log-level` | Legacy era only; modern servers opt in per request instead. |
| `servers/list`, `servers/show` | None | Read the catalog **without connecting** to anything. |
Stream- or session-only methods (`logging/tail`, for example) are rejected, since a process that exits can't hold a stream open.
### Passing arguments
`--tool-arg` takes `key=value` and **coerces** values by JSON-parsing them, so `count=1` becomes a number and `"012"` becomes `12`:
```bash theme={null}
mcp-inspector --cli <server> --method tools/call --tool-name mytool \
--tool-arg key=value --tool-arg count=1 --tool-arg 'options={"format":"json"}'
```
`--tool-args-json` takes the whole argument object at once and passes it **verbatim**, with no coercion, so `"012"` stays the string `012`. The two are mutually exclusive:
```bash theme={null}
mcp-inspector --cli <server> --method tools/call --tool-name mytool \
--tool-args-json '{"zip":"10001"}'
```
## Output
`--format text` (the default) pretty-prints for humans. `--format json` emits a single JSON object on stdout with no banners, so the whole output pipes cleanly:
```bash theme={null}
mcp-inspector --cli <server> --method tools/list --format json | jq '.result.tools[].name'
```
## Probing MCP Apps
`--app-info` reports whether a tool ships an [MCP App](/extensions/apps/overview) UI (its `ui://` resource, CSP, and permissions) **without calling the tool**, so a pipeline can decide whether it needs a browser before invoking anything:
```bash theme={null}
# One tool -> one JSON line
mcp-inspector --cli <server> --method tools/call --tool-name my_tool --app-info
# {"hasApp":true,"toolName":"my_tool","resourceUri":"ui://...","csp":{...},"permissions":{...}}
# Every tool -> NDJSON, one line each, over a single connection
mcp-inspector --cli <server> --method tools/list --app-info | jq -c 'select(.hasApp)'
```
Exit codes distinguish the outcomes: a tool with an app exits `0`, one with no app exits `2`, and a missing tool exits `5`, so a typo isn't mistaken for "no app". A probe failure (unreadable UI resource, malformed `resourceUri`) is reported in a `resourceError` field rather than aborting, so one bad tool never kills a whole listing.
<Note>
`tools/list --app-info` always emits NDJSON (one line per tool) regardless of
`--format`; `--format json` reshapes only the single-tool output of
`tools/call --app-info`.
</Note>
## Exit codes and error envelopes
Every non-zero exit maps to a stable failure class, so a caller can branch on *why* without scraping prose:
| Code | Meaning |
| ---- | ---------------------------------------------------------------------------- |
| `0` | Success. |
| `1` | Usage or unexpected error (the catch-all). |
| `2` | No MCP App found on the tool (`--app-info` probe). |
| `3` | Server requires authentication (401/403, `WWW-Authenticate`, OAuth). |
| `4` | Server unreachable (DNS, connection refused, timeout, `fetch failed`). |
| `5` | Tool error: `tools/call` returned `isError: true`, or the tool wasn't found. |
On any non-zero exit the CLI also writes a **single JSON line to stderr**:
```json theme={null}
{
"error": {
"code": "auth_required",
"message": "Unauthorized",
"status": 401,
"url": "https://api.example/mcp"
}
}
```
Because it's one line, a caller can parse it with `2>&1 | tail -1 | jq .error`.
A `tools/call` that returns `isError: true` still prints its payload, but exits `5`, so an `&&` chain doesn't proceed on a failed call.
## Authorization in scripts
By default the CLI runs the same loopback OAuth flow as the TUI: it opens a browser and waits on a localhost callback that a CI job can't complete. Two flags make non-interactive runs predictable:
* `--stored-auth-only`: never start interactive OAuth or step-up, and never auto-open a browser. Use tokens from the shared store if present, otherwise fail immediately with `auth_required`. This is the flag CI wants.
* `--use-stored-auth`: reuse a token that the web Inspector already obtained on this machine, refreshing it first when a refresh token is stored.
Without either, and with no TTY on stdin or stderr, the CLI fails fast with `auth_required` rather than hanging for fifteen minutes on a callback nobody will complete.
See [Authorization](/docs/draft/tools/inspector/authorization) for the full flow, the web-to-CLI handoff, and `--print-handoff`.
## Recipes
### Verify a server in CI
```bash theme={null}
set -euo pipefail
# Fail the build if the server can't be reached or doesn't expose the tool
mcp-inspector --cli --config ./ci-servers.json --server my-server \
--stored-auth-only --method tools/list --format json \
| jq -e '.result.tools | map(.name) | index("get_weather")' > /dev/null
```
### Branch on the failure class
```bash theme={null}
if out=$(mcp-inspector --cli "$URL" --transport http --method tools/list 2>err.json); then
echo "$out"
else
case $? in
3) echo "needs auth: run the web inspector once to sign in" ;;
4) echo "server unreachable" ;;
*) jq .error < err.json ;;
esac
fi
```
### Smoke-test every tool that has a UI
```bash theme={null}
mcp-inspector --cli "$URL" --transport http --method tools/list --app-info \
| jq -r 'select(.hasApp) | .toolName'
```
### Inspect a catalog without connecting
```bash theme={null}
mcp-inspector --cli --catalog ~/.mcp-inspector/mcp.json --method servers/list
mcp-inspector --cli --catalog ~/.mcp-inspector/mcp.json --method servers/show --server my-server
```
<Warning>
`servers/show` redacts secret-bearing fields (`env` values, sensitive headers,
OAuth client secrets), but it does **not** scrub credentials embedded in a
server `url` (userinfo or query tokens) or in stdio `args`. Treat raw URL and
`detail` fields as sensitive before pasting them into an issue.
</Warning>
## Proxies
Connections to remote HTTP/SSE servers honor the conventional proxy variables: `HTTPS_PROXY` / `HTTP_PROXY` (and their lowercase forms) select the proxy and `NO_PROXY` exempts hosts. No Inspector-specific flag is needed, and the proxy agent is loaded lazily, so runs without a proxy pay nothing. The same applies to the web client's backend.
docs/draft/tools/inspector/configuration New page · 193 lines, new page
# Configuration and flags ## The launcher owns exactly two things ## Choosing servers ### `--catalog` vs. `--config` ### Ad-hoc targets ### Shared server-selection flags ### The `--` separator ## Web-only flags ## CLI and TUI: OAuth client flags ## CLI-only flags ## Environment variables ### Read by the launcher ### CLI and TUI ### Web backend environment variables ## Catalog file format
A whole new page. There's nothing to diff it against, so here is what it says.
# Configuration and flags
> Catalog vs. config files, which client owns which flag, and every environment variable
The `mcp-inspector` binary is a launcher: it reads two flags of its own and forwards every other argument to one of three clients (web, CLI, or TUI). Each client defines its own flags, so a flag that works in one can be unknown to another (`--method`, for example, is CLI-only). This page groups flags and environment variables by the client that owns them.
## The launcher owns exactly two things
| Flag | Behavior |
| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `--web` / `--cli` / `--tui` | Selects the client, `--web` by default. Passing more than one fails with `Specify at most one of --web, --cli, or --tui.` Launcher flags must come first: parsing stops at the first argument the launcher does not own, and everything from that point on is forwarded to the client unchanged. |
| `-h` / `--help` | With no mode flag, prints the launcher's own help and exits. With a mode flag it is forwarded, so `mcp-inspector --cli --help` prints the CLI's help. |
Everything below belongs to a client.
## Choosing servers
### `--catalog` vs. `--config`
All three clients resolve `--catalog` and `--config` through the same shared code, so each flag behaves the same in the web app, the CLI, and the TUI. Where the two differ from each other is the table below.
| | `--catalog <path>` | `--config <path>` |
| --------------------------- | ---------------------------------------------------------------------------- | ------------------------------------------------------- |
| **Writable?** | Yes, the Inspector's own server list. | No. Served as-is, never written, seeded, or migrated. |
| **Missing file?** | Created and seeded (see below). | **Errors.** |
| **Default** | `~/.mcp-inspector/mcp.json`, or the `MCP_CATALOG_PATH` environment variable. | None; you must pass it. |
| **Editable in the web UI?** | Yes. | No. |
| **Use it for** | Your own working set of servers. | A read-only session against someone else's config file. |
The two are **mutually exclusive**, and neither combines with an ad-hoc target. Passing both is rejected identically by all three clients.
<Note>
**What a freshly seeded catalog contains depends on the client.** The web backend seeds two sample servers, so a first launch has something to connect to immediately:
```json theme={null}
{
"mcpServers": {
"filesystem-server-default": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"]
},
"everything-server-default": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-everything"]
}
}
}
```
The CLI and TUI seed an empty `{ "mcpServers": {} }` instead: they are non-interactive or list-driven, so sample entries would be noise rather than a starting point.
Either way, seeding happens only when the file does not exist yet, and a read-only `--config` is never seeded at all.
</Note>
<Note>
`--config` is what you want when pointing the Inspector at a config file you
didn't write: a coworker's, a client application's, or one checked into a
repo. It guarantees the Inspector will not touch the file.
</Note>
### Ad-hoc targets
Instead of a file you can name one server directly, either as a positional command (stdio) or a URL:
```bash theme={null}
mcp-inspector node build/index.js # stdio, positional
mcp-inspector --server-url https://api.example.com/mcp --transport http
```
### Shared server-selection flags
Defined **separately by each of web, CLI, and TUI**, so they're available in all three, with the divergences noted:
| Flag | Meaning | Divergence |
| ------------------------ | ----------------------------------------------------- | ----------------------------------------------------------------------------------------------- |
| `--catalog <path>` | Writable catalog file. | None |
| `--config <path>` | Read-only session file. | None |
| `--server <name>` | Pick one named server out of the file. | **Web and CLI only.** The TUI loads every server in the file and lets you choose interactively. |
| `--transport <type>` | `stdio`, `sse`, or `http`. | Ad-hoc targets only. |
| `--server-url <url>` | Server URL for SSE/HTTP. | Ad-hoc targets only. |
| `--cwd <path>` | Working directory for a stdio server process. | None |
| `-e <KEY=VALUE>` | Environment variables for a stdio server. Repeatable. | None |
| `--header "Name: Value"` | HTTP headers for an HTTP/SSE server. Repeatable. | Requires an ad-hoc HTTP/SSE server on the web client. |
| `[target...]` | Positional command/URL for one ad-hoc server. | None |
### The `--` separator
The **web and CLI** clients split their arguments at a bare `--` and pass everything after it to the target command as its own arguments. This is how you pass a flag that the Inspector would otherwise eat:
```bash theme={null}
mcp-inspector node build/index.js -- --config /etc/myserver.conf --verbose
```
Without the separator, `--config` would be read as the Inspector's own read-only-session flag.
## Web-only flags
| Flag | Meaning |
| ------- | ----------------------------------------------------------------------------------------------------- |
| `--dev` | Run the Vite dev server instead of the pre-built bundle. Useful when working on the Inspector itself. |
## CLI and TUI: OAuth client flags
These five are defined by the **CLI and TUI** only. The web client obtains the same settings through its Client Settings dialog.
| Flag | Environment variable | Meaning |
| ----------------------------- | ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--client-config <path>` | `MCP_CLIENT_CONFIG_PATH` | Install-level client config. Default `~/.mcp-inspector/storage/client.json`. |
| `--client-id <id>` | None | OAuth client ID for a static client. Overrides `client.json`. |
| `--client-secret <secret>` | None | OAuth client secret for confidential clients. Overrides `client.json`. |
| `--client-metadata-url <url>` | None | CIMD metadata URL. Overrides `client.json`. |
| `--callback-url <url>` | `MCP_OAUTH_CALLBACK_URL` | The redirect URI sent to the authorization server. Default `http://127.0.0.1:6276/oauth/callback`. Must be a loopback host (`127.0.0.1` or `localhost`): the local callback listener receives the authorization code over plaintext `http`, so any other host is rejected and there is no flag to override this. |
## CLI-only flags
The whole scripting surface belongs to the CLI. See [CLI client](/docs/draft/tools/inspector/cli) for usage.
| Group | Flags |
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **What to invoke** | `--method`, `--tool-name`, `--tool-arg`, `--tool-args-json`, `--uri`, `--prompt-name`, `--prompt-args`, `--log-level`, `--metadata`, `--tool-metadata` |
| **How to run it** | `--connect-timeout`, `--format`, `--app-info` |
| **Auth** | `--use-stored-auth`, `--stored-auth-only`, `--relogin`, `--wait-for-auth`, `--list-stored-auth`, `--print-handoff` |
## Environment variables
Environment variables split the same way as flags: two are read by the launcher itself, and the rest belong to the CLI and TUI or to the web backend.
### Read by the launcher
| Variable | Effect |
| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `MCP_DEBUG` | Append the error stack to a top-level failure. Only when set to a meaningful value: `0`, `false`, and empty read as off. |
| `DEBUG` | Same, with the same meaningful-value rule, so a stray `DEBUG=0` doesn't turn stack traces on and `DEBUG` still works as the npm `debug` package's namespace filter. |
### CLI and TUI
| Variable | Effect |
| -------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `MCP_CATALOG_PATH` | Fallback for `--catalog`. Honored only when no ad-hoc target is given, so a shell that exports it can still run one-off ad-hoc invocations. |
| `MCP_CLIENT_CONFIG_PATH` | Fallback for `--client-config`. |
| `MCP_OAUTH_CALLBACK_URL` | Fallback for `--callback-url`. |
| `MCP_STORAGE_DIR` | Directory for the OAuth state file (`<dir>/oauth.json`). |
| `MCP_INSPECTOR_OAUTH_STATE_PATH` | Per-file override of the OAuth state path. Takes precedence over `MCP_STORAGE_DIR`. |
| `MCP_AUTO_OPEN_ENABLED` | Controls browser auto-open and whether interactive OAuth may run without a TTY. `true` forces auto-open and allows OAuth prompts without a TTY, `false` never opens, and unset opens only on a TTY. |
### Web backend environment variables
| Variable | Effect |
| ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
| `MCP_INSPECTOR_API_TOKEN` | Pin the [session token](/docs/draft/tools/inspector/web#the-session-token) instead of generating a random one per launch. |
| `DANGEROUSLY_OMIT_AUTH` | Disable the `/api/*` token check entirely. |
| `HOST` | Bind host. Defaults to `localhost`. |
| `CLIENT_PORT` | Web UI port. Defaults to `6274`. |
| `DANGEROUSLY_BIND_ALL_INTERFACES` | Required opt-in to bind a wildcard host (`0.0.0.0`, `::`, or any equivalent spelling). |
| `ALLOWED_ORIGINS` | Comma-separated origin allow-list. **Replaces** the default list rather than merging. |
| `MCP_SANDBOX_PORT` | Pin the MCP Apps sandbox port, which is dynamic by default. |
| `HTTPS_PROXY` / `HTTP_PROXY` / `NO_PROXY` | Standard proxy routing for outbound MCP connections. |
<Warning>
Never combine `DANGEROUSLY_OMIT_AUTH` and `DANGEROUSLY_BIND_ALL_INTERFACES`.
The web backend spawns processes and holds OAuth tokens, so anyone who can
reach it can drive it.
</Warning>
## Catalog file format
A catalog or config file is the familiar MCP client config shape (a `mcpServers` object) with per-server Inspector settings alongside:
```json theme={null}
{
"mcpServers": {
"my-stdio-server": {
"command": "node",
"args": ["build/index.js"],
"env": { "API_KEY": "..." }
},
"my-modern-server": {
"type": "http",
"url": "https://api.example.com/mcp",
"protocolEra": "modern",
"modernLogLevel": "info",
"headers": { "X-Tenant": "acme" },
"roots": [{ "uri": "file:///Users/me/project", "name": "project" }]
}
}
}
```
Fields that equal their default are omitted when the Inspector writes the file back, keeping diffs minimal. `protocolEra` (see [Protocol eras](/docs/draft/tools/inspector/protocol-eras)) defaults to `legacy` and `modernLogLevel` to `debug`.
You do not have to hand-write these; the web client can [import an existing client config](/docs/draft/tools/inspector/recipes#importing-an-existing-client-config) from Claude Desktop, Cursor, Cline, or VS Code, or a registry `server.json`.
docs/draft/tools/inspector/protocol-eras New page · 232 lines, new page
# Protocol eras ## The `Protocol Era` setting ## Reproducing each era locally ## Logging ## Resource subscriptions ## Tasks ## Multi-round tool results (MRTR) ## Tools: mirrored headers and excluded tools ### `-32602` error panels ## Network and Protocol: headers and the error taxonomy ## Sessions
A whole new page. There's nothing to diff it against, so here is what it says.
# Protocol eras
> How the Inspector negotiates legacy vs. modern MCP, and how every feature is handled between protocol eras
The 2026-07-28 revision of MCP made substantial changes to the protocol. The Inspector therefore treats **protocol era** (legacy or modern, meaning before or as of that revision) as a first-class, per-server setting, orthogonal to the transport: the same HTTP URL can be inspected as a legacy server or as a modern one. Several tabs render meaningfully different UI and traffic depending on which era is in effect.
## The `Protocol Era` setting
Each server carries a `protocolEra` of `legacy`, `auto`, or `modern`. In the web client it lives in **Server Settings**; in a catalog or config file it is the `protocolEra` field; in the CLI and TUI it comes from that same file.
| Era | What the Inspector does at connect |
| -------- | --------------------------------------------------------------------------------------- |
| `legacy` | **The default.** Plain `initialize`, no probing at all. |
| `auto` | Probe `server/discover` first, and fall back to `initialize` on any non-modern outcome. |
| `modern` | Pin exactly `2026-07-28`. No fallback, so a non-modern server fails loudly. |
<Note>
**Why `legacy` is the default, and not `auto`.** A debugging tool must not
auto-probe. A `server/discover` probe stalls against silent legacy stdio
servers, and it pollutes the recorded transcript you came here to read. Opting
into `auto` or `modern` is a deliberate act, so what you see in the Protocol
tab is what your server would have seen from a client behaving the way you
configured.
</Note>
Era selection works the same way in all three clients.
Once connected, the negotiated era is reported in the connection header and in **Connection Info**. On a modern connection, `server/discover` also supplies `capabilities` (including `extensions`), `instructions`, and the list of `supportedVersions`. The server's name and version arrive in the result `_meta` under `io.modelcontextprotocol/serverInfo`.
<Frame caption="Server Settings: the Protocol Era selector, with all three choices.">
<img src="https://mintcdn.com/mcp/gk28X8wi_tbRYzej/images/inspector/settings-protocol-era.png?fit=max&auto=format&n=gk28X8wi_tbRYzej&q=85&s=34566c45f97c8af0e2c0d9ee0493b572" width="3840" height="2160" data-path="images/inspector/settings-protocol-era.png" />
</Frame>
## Reproducing each era locally
Every section below ends with a **Reproduce with ...** pointer to a JSON config for one of the **composable test servers** shipped in the Inspector repository. Clone the repo, build the test servers, then point the Inspector at the config the section names.
```bash theme={null}
git clone https://github.com/modelcontextprotocol/inspector
cd inspector && npm install && npm run build
cd clients/web && npm run test-servers:build
```
***
## Logging
<Tabs>
<Tab title="Legacy">
Logging is **session-scoped**. The client sends `logging/setLevel` once, and the server emits `notifications/message` at or above that level for the rest of the session.
The **Logs** tab shows a **Set Active Level** selector plus a **Set** button. Choose a level, click Set, and subsequent server logs stream into the panel.
Reproduce with `test-servers/configs/logging-legacy-http.json`.
</Tab>
<Tab title="Modern">
`logging/setLevel` is **gone**. Instead the client opts in **per request**, by stamping `_meta["io.modelcontextprotocol/logLevel"]` on each outgoing request. A server MUST NOT emit `notifications/message` for a request that did not opt in.
The **Logs** tab therefore shows a **Log Level per Request** control instead. Pick a level and every subsequent request carries the stamp, visible in the Network tab's request body. Logs emitted while handling a request ride that request's SSE response stream.
Set the control to **Off** and the `logLevel` key is omitted entirely, so the same tool call produces no logs at all. That silence is correct behavior, not a bug.
The per-server default is `debug` (opted in at the most verbose level, since the Inspector is a debugging tool); set `modernLogLevel: "off"` on a server to opt back out by default.
Reproduce with `test-servers/configs/logging-modern-http.json`.
</Tab>
</Tabs>
<Frame caption="Legacy: the Logs tab offers a session-scoped Set Active Level control, and a log arrives after calling send_notification.">
<img src="https://mintcdn.com/mcp/gk28X8wi_tbRYzej/images/inspector/logs-legacy.png?fit=max&auto=format&n=gk28X8wi_tbRYzej&q=85&s=ec5fddd86d1fe7ecc1ef83549798f33e" width="3840" height="2160" data-path="images/inspector/logs-legacy.png" />
</Frame>
<Frame caption="Modern: the same tab instead offers Log Level per Request. The level is stamped on every outgoing request, and the log rides that request's stream.">
<img src="https://mintcdn.com/mcp/gk28X8wi_tbRYzej/images/inspector/logs-modern.png?fit=max&auto=format&n=gk28X8wi_tbRYzej&q=85&s=85a1d7118a1e693930aefab8ca6b21a3" width="3840" height="2160" data-path="images/inspector/logs-modern.png" />
</Frame>
***
## Resource subscriptions
<Tabs>
<Tab title="Legacy">
Clicking **Subscribe** on a resource sends `resources/subscribe`. The Subscriptions section lists the URI with no stream chrome. When the resource changes, the server emits `notifications/resources/updated` and the subscribed tile's last-updated time is stamped.
Reproduce with `test-servers/configs/subscriptions-legacy-http.json`, which also serves an `update_resource` tool so you can drive the notification round-trip yourself.
</Tab>
<Tab title="Modern">
The same **Subscribe** button instead sends **`subscriptions/listen`**, with a filter carrying `resourceSubscriptions` plus the `resourcesListChanged` opt-in. The subscription is confirmed when the server sends `notifications/subscriptions/acknowledged`.
Because the subscription is now a long-lived stream rather than a session flag, the Subscriptions section grows a **stream-status badge** in its header that moves from `Connecting...` to `Listening`. If the stream drops, the Inspector reconnects by re-sending `subscriptions/listen`.
Reproduce with `test-servers/configs/subscriptions-modern-http.json`.
</Tab>
</Tabs>
<Frame caption="A modern subscription: the Subscriptions section carries a LISTENING stream-status badge that a legacy subscription has no need for.">
<img src="https://mintcdn.com/mcp/gk28X8wi_tbRYzej/images/inspector/resources-subscriptions-modern.png?fit=max&auto=format&n=gk28X8wi_tbRYzej&q=85&s=5ca4c64c6783eb210fe54248f03de144" width="3840" height="2160" data-path="images/inspector/resources-subscriptions-modern.png" />
</Frame>
***
## Tasks
Tasks change the most between protocol eras, including *how the Inspector UI tab is gated*.
<Tabs>
<Tab title="Legacy">
The **Tasks** tab appears when the server advertises `capabilities.tasks`. Run a tool with **Run as task** enabled and the tab lists it, populated by `tasks/list` and polled with `tasks/get`. The completed payload is fetched with a **blocking `tasks/result`**, and **Cancel** sends `tasks/cancel`.
Reproduce with `test-servers/configs/tasks-legacy-http.json`.
</Tab>
<Tab title="Modern">
Tasks are an **extension** (`io.modelcontextprotocol/tasks`, [SEP-2663](/seps/2663-tasks-extension)), so the tab is gated on the *negotiated extension* rather than on `capabilities.tasks`.
Run a tool as a task and `tools/call` returns a `CreateTaskResult` (`resultType: "task"`, visible in the Protocol and Network tabs). The Inspector polls **`tasks/get`** only; there is no `tasks/list`, so **Refresh** re-polls the handles the client already knows about. A completed task **inlines its result**, with no blocking `tasks/result` call.
A task that needs more information moves to `input_required` and surfaces an embedded [elicitation](/specification/draft/client/elicitation) in the pending-request modal (the dialog the web client opens whenever a request is waiting on you). Answering it sends **`tasks/update`** carrying the `inputResponses`, and the next poll completes.
Reproduce with `test-servers/configs/tasks-modern-http.json` (tools `modern_task` and `modern_input_task`).
</Tab>
</Tabs>
<Frame caption="Legacy: the Tasks tab is populated from tasks/list, and the payload is fetched with a blocking tasks/result.">
<img src="https://mintcdn.com/mcp/gk28X8wi_tbRYzej/images/inspector/tasks-legacy.png?fit=max&auto=format&n=gk28X8wi_tbRYzej&q=85&s=777729bfc1b58b359808c8120d9597d3" width="3840" height="2160" data-path="images/inspector/tasks-legacy.png" />
</Frame>
<Frame caption="Modern: the client polls tasks/get on handles it already holds, and the completed task inlines its result; note resultType: complete in the full task object.">
<img src="https://mintcdn.com/mcp/gk28X8wi_tbRYzej/images/inspector/tasks-modern.png?fit=max&auto=format&n=gk28X8wi_tbRYzej&q=85&s=8e90d128528463fd672537c79db2e1fe" width="3840" height="2160" data-path="images/inspector/tasks-modern.png" />
</Frame>
***
## Multi-round tool results (MRTR)
On the modern era a tool can return `input_required` instead of a final result, embedding an [elicitation](/specification/draft/client/elicitation), a [sampling](/specification/draft/client/sampling) request, or a [`roots/list`](/specification/draft/client/roots) request. The client answers that embedded request and retries the `tools/call` under a fresh JSON-RPC id until the call reaches `complete`.
The Inspector drives MRTR **manually**, so each round pauses at the **pending-request modal**, tagged `input_required`, for you to answer. The Protocol view groups the whole exchange as one MRTR conversation rather than as unrelated calls.
`test-servers/configs/mrtr-showcase-http.json` bundles every shape in one modern server:
| Tool | What it exercises |
| --------------- | ----------------------------------------------------------------------------- |
| `mrtr_confirm` | A single elicitation round. |
| `mrtr_two_step` | Two elicitation rounds, threaded through `requestState`. |
| `mrtr_sample` | An embedded sampling request, routed to the Sampling panel. |
| `mrtr_roots` | An embedded `roots/list`, answered silently from configured roots (no modal). |
| `mrtr_edge` | An `inputRequests`-only round, then a `requestState`-only round. |
| `mrtr_loop` | Never completes, so the client stops at its `MRTR_MAX_ROUNDS` limit. |
<Note>
The legacy `collect_elicitation` pattern (a server calling
`server.elicitInput`) **errors** on a 2026-07-28 connection, because
server-to-client requests aren't allowed there. MRTR is its modern
replacement.
</Note>
<Frame caption="An MRTR round paused at the pending-request modal, tagged input_required. Answering it retries the original request.">
<img src="https://mintcdn.com/mcp/gk28X8wi_tbRYzej/images/inspector/mrtr-pending-request.png?fit=max&auto=format&n=gk28X8wi_tbRYzej&q=85&s=99f8acb7f845a12aed42bcea4d310fee" width="3840" height="2160" data-path="images/inspector/mrtr-pending-request.png" />
</Frame>
***
## Tools: mirrored headers and excluded tools
[SEP-2243](/seps/2243-http-standardization) lets a tool annotate an argument with `x-mcp-header`, asking a Streamable HTTP client to mirror that argument's value into an `Mcp-Param-*` request header.
The Inspector surfaces both halves of that contract in the **Tools** tab:
* A tool with a **valid** annotation shows a **"Mirrored request headers (SEP-2243)"** section in its detail panel, for example `city -> Mcp-Param-City`.
* A tool with an **invalid** annotation (say, a header name of `"Bad Header"`, where the space makes it an invalid RFC 9110 token) appears struck through in the sidebar under an **"Excluded (SEP-2243)"** divider, with the reason on hover. A conforming client MUST drop such a tool from `tools/list`; the Inspector shows you *why* it was dropped instead of silently hiding it.
Reproduce with `test-servers/configs/xmcpheader-modern-http.json`.
<Warning>
**`Mcp-Param-*` mirroring is skipped by the SDK in the browser.** Calling a
mirrored tool from the *web* client omits the header, so a strict server
answers `-32020` (`HeaderMismatch`, see the [error
taxonomy](#network-and-protocol-headers-and-the-error-taxonomy) below). The
same tool called from the **CLI** or **TUI**, which both run on Node, mirrors
correctly. The header is dropped by an environment check inside the SDK,
outside the Inspector's control.
</Warning>
<Frame caption="get_weather shows its mirrored city -> Mcp-Param-City header, while invalid_header_tool is struck through under the Excluded (SEP-2243) divider.">
<img src="https://mintcdn.com/mcp/gk28X8wi_tbRYzej/images/inspector/tools-sep2243.png?fit=max&auto=format&n=gk28X8wi_tbRYzej&q=85&s=98b020f6612b3a76b78b1a8d6159c2c0" width="3840" height="2160" data-path="images/inspector/tools-sep2243.png" />
</Frame>
### `-32602` error panels
Under the modern era a `tools/call` that rejects with `-32602` renders as a distinct **error panel**:
* **Unknown Tool**: when the message names a tool the server does not list. Reproduce by calling any name absent from the server's `tools/list`.
* **Invalid Parameters**: any other `-32602`. Reproduce with the `trigger_invalid_params` tool in the config above.
Both eras reject with `-32602`; only the Inspector's presentation changes. On a legacy connection you get one generic JSON-RPC failure and have to read the message to tell which case you hit.
***
## Network and Protocol: headers and the error taxonomy
The modern era standardizes a set of `Mcp-*` HTTP headers and introduces a richer JSON-RPC error taxonomy ([SEP-2243](/seps/2243-http-standardization) / [SEP-2575](/seps/2575-stateless-mcp)). The two monitoring tabs divide the work:
* The **Network** tab is the HTTP view: mirrored `Mcp-*` headers are highlighted and sentinel values decoded.
* The **Protocol** tab is the JSON-RPC view: each spec error renders distinctly rather than as a generic failure.
`test-servers/configs/modern-network-http.json` serves four tools that produce a real HTTP status plus a JSON-RPC error body, one per class:
| Tool | HTTP | JSON-RPC code | Meaning |
| ----------------------------- | ----- | ------------- | ------------------------------------------------------------ |
| `trigger_header_mismatch` | `400` | `-32020` | A required mirrored header was missing or wrong. |
| `trigger_missing_capability` | `400` | `-32021` | The request omitted a client capability the server requires. |
| `trigger_unsupported_version` | `400` | `-32022` | Unsupported version; supported versions in `data.supported`. |
| `trigger_method_not_found` | `404` | `-32601` | Method not found. |
<Frame caption="The Network tab shows the HTTP layer; here, the 400 Bad Request the strict server answered with.">
<img src="https://mintcdn.com/mcp/gk28X8wi_tbRYzej/images/inspector/network-modern-headers.png?fit=max&auto=format&n=gk28X8wi_tbRYzej&q=85&s=7df4c01f5ab68aa7632ac3b5a5866b42" width="3840" height="2160" data-path="images/inspector/network-modern-headers.png" />
</Frame>
<Frame caption="The Protocol tab renders the same failure as a typed spec error: -32022 UnsupportedProtocolVersion, with the versions the server does support.">
<img src="https://mintcdn.com/mcp/gk28X8wi_tbRYzej/images/inspector/protocol-modern-error.png?fit=max&auto=format&n=gk28X8wi_tbRYzej&q=85&s=d578ea8262ff327e4d61d3697937900b" width="3840" height="2160" data-path="images/inspector/protocol-modern-error.png" />
</Frame>
***
## Sessions
A legacy Streamable HTTP connection may carry a server-assigned session id (`Mcp-Session-Id`), which the client tears down with an HTTP `DELETE`. A modern connection is **sessionless and per-request**: with no session id the client SDK sends no `DELETE` to the server, so disconnect is purely local.
This has a practical consequence for your own test servers. A stateless modern handler constructed per request cannot hold state between calls, which is why `test-servers/configs/subscriptions-modern-http.json`, unlike its legacy counterpart, omits an `update_resource` tool: the mutation would run against a throwaway server instance and be invisible to the next read.
docs/draft/tools/inspector/recipes New page · 207 lines, new page
# Recipes ## Connecting stdio vs. HTTP servers ### stdio ### HTTP and SSE ## Importing an existing client config ## Reviewing an MCP App ## Docker ## Hosting on a network ## Development workflow
A whole new page. There's nothing to diff it against, so here is what it says.
# Recipes
> Practical guides for transports, importing configs, reviewing MCP Apps, Docker, and network hosting
## Connecting stdio vs. HTTP servers
### stdio
A stdio server is a process the Inspector spawns. Everything positional is the command line:
```bash theme={null}
mcp-inspector node build/index.js -- --verbose --config /etc/myserver.conf
```
Put `--` before any arguments meant for your server. Without the separator, `--verbose` would be
parsed by the Inspector and never reach the server.
Give the process environment variables with `-e` and a working directory with `--cwd`:
```bash theme={null}
mcp-inspector -e API_KEY=abc123 -e REGION=us-east-1 --cwd ~/projects/my-server \
node build/index.js
```
The server's `stderr` lands in the **Console** tab (web) or the Console tab (`o`, TUI), which is where most stdio servers put their diagnostics, so check there first when a connection fails for no visible reason.
### HTTP and SSE
```bash theme={null}
mcp-inspector --server-url https://api.example.com/mcp --transport http \
--header "X-Tenant: acme"
```
`--transport` accepts `http` (Streamable HTTP) and `sse`. If the server is protected, see [Authorization](/docs/draft/tools/inspector/authorization): no setup is needed in advance, because when the server answers `401` the Inspector runs the OAuth flow described there and retries the connection.
For an HTTP server, also decide its [protocol era](/docs/draft/tools/inspector/protocol-eras). The default is `legacy`; set `modern` or `auto` in Server Settings (or `protocolEra` in the catalog file) to exercise the 2026-07-28 behavior.
## Importing an existing client config
On the Servers screen, **Add Servers** can import MCP servers you have already configured
elsewhere instead of retyping them. It parses Claude Desktop, Cursor, Cline, and VS Code client
configs directly, and it also reads a server's own [MCP Registry](/registry/about) `server.json`.
Import merges into the active [catalog](/docs/draft/tools/inspector/configuration#choosing-servers)
(the Inspector's writable server list), so existing entries aren't clobbered. If you'd rather
not touch your catalog at all, launch against the foreign file read-only instead:
```bash theme={null}
mcp-inspector --config ~/Library/Application\ Support/Claude/claude_desktop_config.json
```
`--config` guarantees the file is served as-is and never written, seeded, or migrated.
<Frame caption="Add Servers offers import from an existing client config or from a registry server.json.">
<img src="https://mintcdn.com/mcp/gk28X8wi_tbRYzej/images/inspector/import-config.png?fit=max&auto=format&n=gk28X8wi_tbRYzej&q=85&s=c9f5229c2d827f4bcab37938879f21f2" width="3840" height="2160" data-path="images/inspector/import-config.png" />
</Frame>
## Reviewing an MCP App
[MCP Apps](/extensions/apps/overview) are tools that carry a UI widget. For an automated reviewer (CI or an agent), use the CLI for every check that returns JSON, and open a browser only to inspect the rendered widget.
<Steps>
<Step title="Probe the security posture without calling the tool">
```bash theme={null}
mcp-inspector --cli --transport http --server-url https://example.com/mcp \
--method tools/call --tool-name <tool> --app-info
```
One JSON line on stdout; exit `0` if the tool has an app, `2` if not, so an `&&` chain short-circuits:
```json theme={null}
{
"hasApp": true,
"toolName": "get_pros",
"resourceUri": "ui://pros/view.html",
"csp": { "connectDomains": ["https://api.example.com"] },
"permissions": { "clipboard": false },
"prefersBorder": true,
"resourceMimeType": "text/html"
}
```
`csp` and `permissions` (and `domain`, when the resource declares one) live on the UI **resource** rather than the tool, so `--app-info` reads that resource. The tool is never called.
</Step>
<Step title="Get the full result payload, still with no browser">
```bash theme={null}
mcp-inspector --cli --transport http --server-url https://example.com/mcp \
--method tools/call --tool-name <tool> --tool-args-json '{"zip":"10001"}' --format json
```
</Step>
<Step title="Launch the web Inspector once, loopback-only">
```bash theme={null}
TOKEN="$(openssl rand -hex 24)"
HOST=127.0.0.1 CLIENT_PORT=6274 MCP_SANDBOX_PORT=6275 \
MCP_AUTO_OPEN_ENABLED=false MCP_INSPECTOR_API_TOKEN="$TOKEN" \
mcp-inspector --web &
```
Pinning `MCP_SANDBOX_PORT` matters here: the app's UI is served from a separate sandbox port that is dynamic by default, and your automation needs a fixed address to reach it.
</Step>
<Step title="Navigate one deep link to a rendered widget">
```
http://127.0.0.1:6274/?serverUrl=<encoded url>&transport=http&autoConnect=<TOKEN>&openApp=<tool>&appArgs=<base64url(JSON)>&autoOpen=<TOKEN>
```
`appArgs` is the tool's arguments as base64url-encoded JSON, and every deep-link parameter is described under [Deep links](/docs/draft/tools/inspector/web#deep-links). `autoConnect` and `autoOpen` must both equal the session token, since `autoOpen` fires a tool call straight from the URL and needs the same gate as `autoConnect`.
</Step>
<Step title="Wait on a deterministic signal instead of sleeping">
The Apps screen exposes a stable automation contract. Poll these attributes instead of sleeping:
| Selector | Attribute | Values |
| ----------------------------------- | ----------------- | ------------------------------------------------------------------------------------------------------- |
| `[data-testid="apps-form"]` | `data-app-status` | `ready` (on failure, `data-app-error` carries the reason) |
| `[data-testid="connection-status"]` | `data-status` | `connecting`, then `connected` or `error` (`data-error-message` has the detail) |
| `[data-testid="connection-status"]` | `data-deeplink` | `parsed`, `rejected`, or `none` (`none` means no deep link was given, `rejected` means one was refused) |
</Step>
</Steps>
## Docker
A container image is published to GitHub Container Registry for `linux/amd64` and `linux/arm64`:
```bash theme={null}
docker run --rm -p 6274:6274 ghcr.io/modelcontextprotocol/inspector
```
Read the [session token](/docs/draft/tools/inspector/web#the-session-token) from the container logs, or pin it with `-e MCP_INSPECTOR_API_TOKEN=<value>`.
The image defaults to `--web`, bound to `0.0.0.0:6274` with browser auto-open off, and runs as a non-root user. It sets `DANGEROUSLY_BIND_ALL_INTERFACES=true` because a container must bind the wildcard address to be reachable through `-p`.
Its `HEALTHCHECK` probes the web UI, so add `--no-healthcheck` when running `--cli` or `--tui` (neither has a web server). `<target>` below is an [ad-hoc target](/docs/draft/tools/inspector/configuration#ad-hoc-targets): a positional stdio command, or `--server-url <url> --transport http`.
```bash theme={null}
docker run --rm --no-healthcheck ghcr.io/modelcontextprotocol/inspector --cli <target> --method tools/list
```
<Warning>
**If you remap the published port, set `ALLOWED_ORIGINS`.** With `-p
8080:6274` the browser's origin becomes `http://localhost:8080`, which no
longer matches the in-container port, and connects will `403`. Either run `-e
CLIENT_PORT=8080 -p 8080:8080`, or set `-e
ALLOWED_ORIGINS=http://localhost:8080,http://127.0.0.1:8080`.
</Warning>
## Hosting on a network
The Inspector binds `localhost` by default and its backend spawns processes, so treat exposing it to a network as a deliberate decision.
The Inspector refuses to bind the **wildcard** all-interfaces addresses (`0.0.0.0`, `::`, and every equivalent spelling) unless you set `DANGEROUSLY_BIND_ALL_INTERFACES=true`. Binding a **specific** address is allowed with no opt-in, because that's one deliberate exposure rather than every interface at once, which is the shape DNS-rebinding attacks target.
| Goal | What to do |
| -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Reach it from another machine on the LAN** | `HOST=192.168.1.50`. The default origin allow-list follows the bind host, so `http://192.168.1.50:6274` is accepted with no further config. |
| **Behind TLS or a reverse proxy** | The browser's `Origin` becomes the public origin, which won't match the bind host. Set `ALLOWED_ORIGINS=https://inspector.example.com`. |
| **Wildcard bind (containers)** | Set `DANGEROUSLY_BIND_ALL_INTERFACES=true`. Loopback access still works out of the box; reaching it at a non-loopback address needs `ALLOWED_ORIGINS`. |
<Warning>
`ALLOWED_ORIGINS` **replaces** the default list rather than merging with it. List every origin you'll browse from, including the loopback forms you want to keep:
```
ALLOWED_ORIGINS=http://localhost:6274,http://127.0.0.1:6274,http://192.168.1.50:6274
```
Each entry must include the scheme; a scheme-less value is dropped with a warning. A blank value does **not** disable the check; it falls back to the default. There is no knob to turn origin validation off.
</Warning>
Two further caveats when going off loopback:
* **MCP Apps need their sandbox port reachable too.** It's a separate, dynamic-by-default port; pin it with `MCP_SANDBOX_PORT` and expose or forward it. The Docker image publishes only `6274`.
* **MCP Apps can't render over TLS or at a bare IPv6 literal.** The sandbox URL is always plain `http`, so an `https://` page blocks the iframe as mixed content; and a bracketed IPv6 literal isn't a valid CSP host-source, so browse at a name or an IPv4 address.
Whatever the shape: keep authentication on. Do not set `DANGEROUSLY_OMIT_AUTH` on anything reachable by anyone but you.
## Development workflow
A loop that works well in practice:
<Steps>
<Step title="Start with the CLI">
`--method initialize` confirms the server starts, handshakes, and reports
the capabilities you expect, in one second, with a machine-readable answer.
Most "it doesn't work" turns out to be here.
</Step>
<Step title="Move to the web client for exploration">
Schema-driven forms, rendered results, and the Protocol tab beside them make
it fast to find the case where a tool misbehaves.
</Step>
<Step title="Test the edges">
Invalid inputs, missing required prompt arguments, concurrent calls, and,
for HTTP servers, both protocol eras. Verify the *errors* are as intentional
as the successes.
</Step>
<Step title="Lock it in with the CLI">
Turn what you found into a CI assertion: pipe the CLI's `--format json`
output to `jq -e` with `--stored-auth-only`, so a missing token fails fast
instead of starting interactive OAuth. See [Verify a server in
CI](/docs/draft/tools/inspector/cli#verify-a-server-in-ci) for the full
command.
</Step>
</Steps>
docs/draft/tools/inspector/tui New page · 78 lines, new page
# TUI client ## Choosing servers ## Tabs ## Navigation ## Authorizing an HTTP server ## Requirements
A whole new page. There's nothing to diff it against, so here is what it says.
# TUI client
> The terminal MCP Inspector: navigation, tabs, and keyboard reference
The TUI is the Inspector's terminal interface, with the same interactive exploration of tools, resources, and prompts as the web client. Use it on a remote host over SSH, in a locked-down environment, or when you prefer to stay in the terminal.
```bash theme={null}
npx @modelcontextprotocol/inspector --tui node build/index.js # with an ad-hoc stdio server
```
<Frame caption="The TUI connected to a server, on the Tools tab, showing a tool's input schema.">
<img src="https://mintcdn.com/mcp/gk28X8wi_tbRYzej/images/inspector/tui-tools.png?fit=max&auto=format&n=gk28X8wi_tbRYzej&q=85&s=5d11d64f4b98df8c26e7ac048f38576f" width="2986" height="1832" data-path="images/inspector/tui-tools.png" />
</Frame>
## Choosing servers
Unlike the CLI, the TUI has no `--server <name>` flag for picking one entry: it reads its servers from a catalog or config file, loads every server in it, and lets you pick from an on-screen list:
```bash theme={null}
mcp-inspector --tui --catalog mcp.json # writable catalog, seeded empty if missing (unlike the web client)
mcp-inspector --tui --config mcp.json # read-only session, errors if absent
```
With neither `--catalog` nor `--config`, and no [ad-hoc target](/docs/draft/tools/inspector/configuration#ad-hoc-targets), it uses the default writable catalog `~/.mcp-inspector/mcp.json`. See [Configuration and flags](/docs/draft/tools/inspector/configuration).
## Tabs
| Tab | Key | What it shows |
| ------------- | --- | ------------------------------------------------------------------------------------------- |
| **Info** | `i` | Server info, capabilities, and negotiated protocol details. |
| **Auth** | `a` | OAuth state for the selected server, plus a **Clear OAuth state** action. |
| **Resources** | `r` | Browse and read resources. |
| **Prompts** | `m` | List prompts and render them with arguments. |
| **Tools** | `t` | View tools and execute them with form-like inputs. |
| **Protocol** | `p` | JSON-RPC request/response/notification history. |
| **Network** | `n` | HTTP traffic for SSE and [Streamable HTTP](/specification/latest/basic/transports) servers. |
| **Console** | `o` | `stderr` from a connected stdio server process. |
The accelerators avoid collisions rather than always taking the first letter: **P**rotocol takes `p` so Pro**m**pts takes `m`, and **C**onsole takes `o` because `c` is the global Connect action.
## Navigation
| Key | Action |
| -------------------------------- | --------------------------------------------------- |
| `Left` / `Right` arrows or `Tab` | Switch tabs |
| `Up` / `Down` arrows | Move through the current list |
| `Enter` | Select an item, execute a tool, or fetch a resource |
| `c` | Connect to the selected server |
| `d` | Disconnect |
| `Esc` or `Ctrl+C` | Exit |
## Authorizing an HTTP server
1. Select an HTTP or SSE server and press **`c`** to connect.
2. If the server requires authorization, the TUI starts OAuth automatically and opens the authorization URL in a browser.
3. When the browser redirect lands on the TUI's loopback listener, the connection finishes on its own, with no second **`c`**.
4. Use the **Auth** tab to inspect the resulting OAuth state, or to clear it.
The TUI's callback listener defaults to `http://127.0.0.1:6276/oauth/callback`. The port is fixed on purpose: a pre-registered (static) OAuth client, a [Client ID Metadata Document (CIMD)](/specification/latest/basic/authorization/client-registration#client-id-metadata-documents), or an enterprise-managed IdP all need a redirect URI known in advance. Register that URI once and it works across sessions. On a remote host where your browser is on another machine, forward the callback port so the redirect reaches this listener; see [Callback URLs](/docs/draft/tools/inspector/authorization#callback-urls).
The trade-off is that only one TUI OAuth flow can hold the port at a time; a second concurrent flow fails with `EADDRINUSE`. To override it, pass `--callback-url` or set `MCP_OAUTH_CALLBACK_URL`: use a different fixed port per instance, or `http://127.0.0.1:0/oauth/callback` for an OS-assigned ephemeral port when your authorization server registers redirect URIs dynamically.
<Warning>
Redirect URIs must match **exactly** what you registered. `localhost` and
`127.0.0.1` are different URIs as far as an authorization server is concerned.
</Warning>
Per-server OAuth fields in the catalog (static client id/secret, scopes, the enterprise-managed flag) are applied automatically. Install-wide settings (CIMD, enterprise IdP) come from `~/.mcp-inspector/storage/client.json`, the same file the web client's **Client Settings** dialog writes. Point at a different one with `--client-config` or `MCP_CLIENT_CONFIG_PATH`.
See [Authorization](/docs/draft/tools/inspector/authorization) for the full picture.
<Frame caption="The Auth tab. It shows the same OAuth fields as the web client's Connection Info, or reports that the server needs no authorization.">
<img src="https://mintcdn.com/mcp/gk28X8wi_tbRYzej/images/inspector/tui-auth.png?fit=max&auto=format&n=gk28X8wi_tbRYzej&q=85&s=2e5ef574e80e81c4b49fa2ef0eac0528" width="2986" height="1832" data-path="images/inspector/tui-auth.png" />
</Frame>
## Requirements
The TUI needs a real TTY with raw-mode support. It will not run usefully in a headless CI job; use the [CLI](/docs/draft/tools/inspector/cli) there.
docs/draft/tools/inspector/web New page · 168 lines, new page
# Web client ## The session token ## Dev mode ## The tab bar ### The monitoring sidebar ## Servers ### Server Settings ## Tools ## Resources ## Prompts ## Apps ## Protocol, Network, and Console ## Deep links ## Host binding and origins
A whole new page. There's nothing to diff it against, so here is what it says.
# Web client
> A tab-by-tab walkthrough of the graphical MCP Inspector
The web client is the Inspector's richest surface: a single-page app backed by a small Node server that owns the actual MCP connections. It is the default mode, so `npx @modelcontextprotocol/inspector` with no mode flag lands here.
```bash theme={null}
npx @modelcontextprotocol/inspector # empty, add servers in the UI
npx @modelcontextprotocol/inspector node build/index.js # with an ad-hoc stdio server
npx @modelcontextprotocol/inspector --catalog ./mcp.json # with a catalog file
```
## The session token
The Node server behind the web client guards every `/api/*` route with a per-launch token, because it can spawn processes on your machine. The launcher prints a URL containing that token: **open that URL**, and don't type `localhost:6274` from memory.
The browser recovers the token from three places, in priority order:
1. `window.__INSPECTOR_API_TOKEN__`, injected into `index.html` on every page load. This is what makes a bare-URL reload or a bookmark keep working.
2. A `?MCP_INSPECTOR_API_TOKEN=...` query string, the form used in that printed URL.
3. `sessionStorage`, as a backstop.
Set the `MCP_INSPECTOR_API_TOKEN` environment variable to pin a known token (useful for scripted launches), or set `DANGEROUSLY_OMIT_AUTH=true` to disable the check entirely, but only on a machine where nothing else can reach the port. Both are described under [Web backend environment variables](/docs/draft/tools/inspector/configuration#web-backend-environment-variables).
## Dev mode
`--dev` is a **web-only** flag. It runs the Vite dev server instead of serving the pre-built bundle, which matters if you're working on the Inspector itself:
```bash theme={null}
mcp-inspector --web --dev
```
Production `--web` serves a built bundle. In the published package that bundle always ships; in a fresh source checkout it doesn't, so the runner builds it on demand the first time you launch.
## The tab bar
| Tab | Shown when | What it does |
| ------------- | --------------------------------------------------------------------- | ------------------------------------------------------------------------------ |
| **Servers** | Always | The server list: add, edit, import, connect, and open per-server settings. |
| **Apps** | The server exposes MCP App tools | Renders a tool's UI in a sandboxed frame. |
| **Tools** | `tools` capability | Browse schemas, fill arguments, call, inspect results. |
| **Prompts** | `prompts` capability | List prompts, supply arguments, preview generated messages. |
| **Resources** | `resources` capability | Browse, read, and subscribe to resources. |
| **Tasks** | `capabilities.tasks` (legacy era) or the tasks extension (modern era) | Track long-running tool calls. |
| **Logs** | `logging` capability | Server `notifications/message` output, plus the era-appropriate level control. |
| **Protocol** | Always | The JSON-RPC transcript: requests, responses, notifications. |
| **Network** | HTTP / SSE servers | The raw HTTP view: status, headers, bodies. |
| **Console** | stdio servers | The server process's `stderr`. |
**Network** and **Console** never appear together. Legacy and modern eras are described in [Protocol eras](/docs/draft/tools/inspector/protocol-eras).
<Frame caption="The tab bar on a connected server. Which tabs appear depends on the capabilities the server reported.">
<img src="https://mintcdn.com/mcp/gk28X8wi_tbRYzej/images/inspector/web-tab-bar.png?fit=max&auto=format&n=gk28X8wi_tbRYzej&q=85&s=04bb61c4a45ff12e8337c701e195c386" width="3840" height="2400" data-path="images/inspector/web-tab-bar.png" />
</Frame>
### The monitoring sidebar
**Tasks**, **Logs**, **Protocol**, **Network**, and **Console** form a *monitor group*. Pin the group and they leave the tab bar and move into a resizable right-hand column, so you can watch traffic while working in Tools or Resources. The column width and the selected monitor tab persist across reloads.
<Frame caption="The monitoring sidebar pinned beside the Tools screen. The Protocol stream stays visible while you work.">
<img src="https://mintcdn.com/mcp/gk28X8wi_tbRYzej/images/inspector/web-monitor-sidebar.png?fit=max&auto=format&n=gk28X8wi_tbRYzej&q=85&s=eef6e546b9831b3d169e26bba8c54ce3" width="3840" height="2160" data-path="images/inspector/web-monitor-sidebar.png" />
</Frame>
## Servers
The Servers screen is the entry point. A server row carries its transport, its connection state, and a control that opens its per-server settings.
Where that list comes from, and whether it's editable, depends on how you launched:
| Launch | Server list | Editable? |
| -------------------------------------------- | ----------------------------------------------------------------------- | --------- |
| `mcp-inspector --web` | The default catalog `~/.mcp-inspector/mcp.json`, seeded on first launch | Yes |
| `--catalog <path>` | That file, seeded with the sample servers if missing | Yes |
| `--config <path>` | That file, read-only (never written or seeded) | No |
| `--server-url <url>` or a positional command | One ad-hoc server, held in memory | No |
On a first launch the web client seeds the catalog with two sample servers: a filesystem server scoped to `/tmp` and the canonical "everything" reference server. See [Configuration and flags](/docs/draft/tools/inspector/configuration) for the full rules, including why the CLI and TUI seed an empty catalog instead.
### Server Settings
* **Protocol Era**: `legacy` / `auto` / `modern`. See [Protocol eras](/docs/draft/tools/inspector/protocol-eras).
* **Log level per request**: the level a modern-era connection stamps on each outgoing request by default, or `off` to opt out (see [Logging](/docs/draft/tools/inspector/protocol-eras#logging)).
* **Advertised Extensions**: which extensions the Inspector declares in `capabilities.extensions`. A debugging knob: a server may legitimately change what it registers based on what you advertise. Uncheck the Tasks extension and reconnect against the `test-servers/configs/advertised-extensions-http.json` fixture (setup in [Reproducing each era locally](/docs/draft/tools/inspector/protocol-eras#reproducing-each-era-locally)) to watch a tool disappear.
* **Roots**: the roots advertised via the `roots` client capability. `@modelcontextprotocol/server-filesystem`, for instance, calls `roots/list` to learn its allowed directories.
* **Headers**, **timeouts**, and **OAuth** fields.
* **Fetch lists one page at a time**: when off, list results are auto-aggregated across pages on connect; when on, each list loads page 1 only with a **Load next page** control and an *N pages loaded* status. Reproduce with `test-servers/configs/pagination-http.json`, which paginates 12 tools, resources, and prompts into three pages each.
<Frame caption="Server Settings with Advertised Extensions expanded. Unchecking one changes what the Inspector declares at connect.">
<img src="https://mintcdn.com/mcp/gk28X8wi_tbRYzej/images/inspector/web-server-settings.png?fit=max&auto=format&n=gk28X8wi_tbRYzej&q=85&s=d42be09ee8de7e45e58a8ff1a444ba52" width="3840" height="2160" data-path="images/inspector/web-server-settings.png" />
</Frame>
## Tools
Select a tool to see its description, its input schema rendered as a form, and its annotations. Fill the form and call it; the result renders below with structured content, embedded resources, and images handled natively.
On modern-era servers this screen also shows mirrored `Mcp-Param-*` headers, excluded tools, and distinct `-32602` error panels, all covered in [Protocol eras](/docs/draft/tools/inspector/protocol-eras#tools-mirrored-headers-and-excluded-tools).
<Frame caption="A tool call and its rendered result. The argument form collapses into the result panel once the call returns.">
<img src="https://mintcdn.com/mcp/gk28X8wi_tbRYzej/images/inspector/web-tools.png?fit=max&auto=format&n=gk28X8wi_tbRYzej&q=85&s=7ef469a969f398ac0ec70cf019c133da" width="3840" height="2160" data-path="images/inspector/web-tools.png" />
</Frame>
## Resources
Lists resources and resource templates with their MIME types and descriptions, reads content on selection, and offers **Subscribe** on servers that support subscriptions. The subscription mechanics differ by era; see [Resource subscriptions](/docs/draft/tools/inspector/protocol-eras#resource-subscriptions).
<Frame caption="A resource read, with an active subscription listed below the resource list.">
<img src="https://mintcdn.com/mcp/gk28X8wi_tbRYzej/images/inspector/web-resources.png?fit=max&auto=format&n=gk28X8wi_tbRYzej&q=85&s=1a94ea452e1ef8aaf2c9f486ed810b28" width="3840" height="2160" data-path="images/inspector/web-resources.png" />
</Frame>
## Prompts
Lists prompt templates with their arguments, and renders the generated messages for the arguments you supply, which is the fastest way to confirm a prompt produces what you intended.
<Frame caption="A prompt rendered with the arguments supplied.">
<img src="https://mintcdn.com/mcp/gk28X8wi_tbRYzej/images/inspector/web-prompts.png?fit=max&auto=format&n=gk28X8wi_tbRYzej&q=85&s=81b16312b1adff5601622a72444b0f92" width="3840" height="2160" data-path="images/inspector/web-prompts.png" />
</Frame>
## Apps
[MCP Apps](/extensions/apps/overview) are tools that carry UI. The Apps tab renders one in a sandboxed iframe served from a **separate port**, exercises the `ui/*` bridge, and shows the view's `ui/message` submissions and its `notifications/message` logs in side panels.
* The sandbox port is dynamic by default; pin it with `MCP_SANDBOX_PORT` if you need to expose or forward it.
* The sandbox is gated by a `frame-ancestors` CSP, and a bracketed IPv6 literal is not a valid CSP host-source, so browse the Inspector at `localhost`, `127.0.0.1`, a hostname, or a LAN IPv4, **not** at a bare `http://[::1]:...`.
* The sandbox URL is always plain `http`, so an `https://` Inspector page blocks the frame as mixed content. MCP Apps need a plain-`http` origin today.
See [Recipes](/docs/draft/tools/inspector/recipes#reviewing-an-mcp-app) for the CLI-first automated review flow.
<Frame caption="An MCP App rendered in its sandboxed frame, with the app's own logs below it.">
<img src="https://mintcdn.com/mcp/gk28X8wi_tbRYzej/images/inspector/web-apps.png?fit=max&auto=format&n=gk28X8wi_tbRYzej&q=85&s=bd311848514f7d251640012986abfc4d" width="3840" height="2160" data-path="images/inspector/web-apps.png" />
</Frame>
## Protocol, Network, and Console
The three tabs show the same traffic at different levels of detail:
* **Protocol**: the JSON-RPC transcript. Requests paired with responses, notifications inline, [MRTR](/docs/draft/tools/inspector/protocol-eras#multi-round-tool-results-mrtr) rounds grouped as one conversation, and spec errors rendered by class.
* **Network**: the HTTP layer, for SSE and Streamable HTTP servers. Status codes, request and response headers, and bodies. On modern connections the standardized `Mcp-*` headers are highlighted and sentinel values decoded.
* **Console**: the connected stdio server process's `stderr`, which is where most stdio servers put their own diagnostics.
Secrets are masked in these views, and entries can be cleared or exported.
<Frame caption="The Protocol tab with an entry expanded, showing the full JSON-RPC exchange.">
<img src="https://mintcdn.com/mcp/gk28X8wi_tbRYzej/images/inspector/web-protocol.png?fit=max&auto=format&n=gk28X8wi_tbRYzej&q=85&s=f31338c83a389c5588f11c0d5b2b97ed" width="3840" height="2160" data-path="images/inspector/web-protocol.png" />
</Frame>
## Deep links
A driver (a script, a CI harness, or the CLI's [`--print-handoff`](/docs/draft/tools/inspector/authorization#handing-off-from-the-web-client-to-the-cli)) can reach a *connected* Inspector with a single navigation:
```
http://127.0.0.1:6274/?serverUrl=<url>&transport=http|sse&autoConnect=<token>
```
| Parameter | Meaning |
| ------------- | -------------------------------------------------------------------------------------------------------------- |
| `serverUrl` | The MCP server URL. Restricted to `http:` / `https:`; a crafted `javascript:` or `file:` value is rejected. |
| `transport` | `http` (default) or `sse`. |
| `autoConnect` | **Required CSRF gate.** Must equal the per-launch session token, which only whatever started the server knows. |
Three further parameters land you on a *rendered app*: `openApp=<toolName>` names the tool, `appArgs=<base64url(JSON)>` supplies its arguments (merged over the tool's schema defaults), and `autoOpen=<token>` fires the tool call automatically. Because `autoOpen` fires a call, it carries the same mandatory token gate as `autoConnect`.
## Host binding and origins
By default the Inspector binds `localhost` and accepts requests only from the loopback origins for its port. Treat both defaults as security boundaries, since the backend spawns processes on your machine.
Binding all interfaces (`HOST=0.0.0.0`) is **refused** unless you set `DANGEROUSLY_BIND_ALL_INTERFACES=true`. Binding a *specific* non-loopback address is allowed with no opt-in, since that's a single deliberate exposure rather than every interface at once.
See the [Hosting on a network](/docs/draft/tools/inspector/recipes#hosting-on-a-network) recipe for the full matrix, and [Configuration](/docs/draft/tools/inspector/configuration#web-backend-environment-variables) for the variables.
docs/draft/tutorials/security/authorization New page · 1098 lines, new page
# Understanding Authorization in MCP ## When Should You Use Authorization? ## The Authorization Flow: Step by Step ## Implementation Example ### Keycloak Setup ### MCP Server Setup ## Testing the MCP Server ## Common Pitfalls and How to Avoid Them ## Related Standards and Documentation
A whole new page. There's nothing to diff it against, so here is what it says.
# Understanding Authorization in MCP
> Learn how to implement secure authorization for MCP servers using OAuth 2.1 to protect sensitive resources and operations
Authorization in the Model Context Protocol (MCP) secures access to sensitive resources and operations exposed by MCP servers. If your MCP server handles user data or administrative actions, authorization ensures only permitted users can access its endpoints.
MCP uses standardized authorization flows to build trust between MCP clients and MCP servers. Its design doesn't focus on one specific authorization or identity system, but rather follows the conventions outlined for [OAuth 2.1](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-13). For detailed information, see the [Authorization specification](/specification/latest/basic/authorization).
## When Should You Use Authorization?
While authorization for MCP servers is **optional**, it is strongly recommended when:
* Your server accesses user-specific data (emails, documents, databases)
* You need to audit who performed which actions
* Your server grants access to its APIs that require user consent
* You're building for enterprise environments with strict access controls
* You want to implement rate limiting or usage tracking per user
<Tip>
**Authorization for Local MCP Servers**
For MCP servers using the [STDIO transport](/specification/latest/basic/transports#stdio), you can use environment-based credentials or credentials provided by third-party libraries embedded directly in the MCP server instead. Because a STDIO-built MCP server runs locally, it has access to a range of flexible options when it comes to acquiring user credentials that may or may not rely on in-browser authentication and authorization flows.
OAuth flows, in turn, are designed for HTTP-based transports where the MCP server is remotely-hosted and the client uses OAuth to establish that a user is authorized to access said remote server.
</Tip>
## The Authorization Flow: Step by Step
Let's walk through what happens when a client wants to connect to your protected MCP server:
<Steps>
<Step title="Initial Handshake">
When your MCP client first tries to connect, your server responds with a `401 Unauthorized` and tells the client where to find authorization information, captured in a [Protected Resource Metadata (PRM) document](https://datatracker.ietf.org/doc/html/rfc9728). The document is hosted by the MCP server, follows a predictable path pattern, and is provided to the client in the `resource_metadata` parameter within the `WWW-Authenticate` header.
```http theme={null}
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="mcp",
resource_metadata="https://your-server.com/.well-known/oauth-protected-resource"
```
This tells the client that authorization is required for the MCP server and where to get the necessary information to kickstart the authorization flow.
</Step>
<Step title="Protected Resource Metadata Discovery">
With the URI pointer to the PRM document, the client will fetch the metadata to learn about the authorization server, supported scopes, and other resource information. The data is typically encapsulated in a JSON blob, similar to the one below.
```json theme={null}
{
"resource": "https://your-server.com/mcp",
"authorization_servers": ["https://auth.your-server.com"],
"scopes_supported": ["mcp:tools", "mcp:resources"]
}
```
You can see a more comprehensive example in [RFC 9728 Section 3.2](https://datatracker.ietf.org/doc/html/rfc9728#name-protected-resource-metadata-r).
</Step>
<Step title="Authorization Server Discovery">
Next, the client discovers what the authorization server can do by fetching its metadata. If the PRM document lists more than one authorization server, the client can decide which one to use.
With an authorization server selected, the client will then construct a standard metadata URI and issue a request to the [OpenID Connect (OIDC) Discovery](https://openid.net/specs/openid-connect-discovery-1_0.html) or [OAuth 2.0 Auth Server Metadata](https://datatracker.ietf.org/doc/html/rfc8414) endpoints (depending on authorization server support)
and retrieve another set of metadata properties that will allow it to know the endpoints it needs to complete the authorization flow.
```json theme={null}
{
"issuer": "https://auth.your-server.com",
"authorization_endpoint": "https://auth.your-server.com/authorize",
"token_endpoint": "https://auth.your-server.com/token",
"registration_endpoint": "https://auth.your-server.com/register"
}
```
</Step>
<Step title="Client Registration">
With all the metadata out of the way, the client now needs to make sure that it's registered with the authorization server. This can be done in two ways.
First, the client can be **pre-registered** with a given authorization server, in which case it can have embedded client registration information that it uses to complete the authorization flow.
Alternatively, the client can use **Dynamic Client Registration** (DCR) to dynamically register itself with the authorization server. The latter scenario requires the authorization server to support DCR. If the authorization server does support DCR, the client will send a request to the `registration_endpoint` with its information:
```json theme={null}
{
"client_name": "My MCP Client",
"redirect_uris": ["http://localhost:3000/callback"],
"grant_types": ["authorization_code", "refresh_token"],
"response_types": ["code"]
}
```
If the registration succeeds, the authorization server will return a JSON blob with client registration information.
<Tip>
**No DCR or Pre-Registration**
In case an MCP client connects to an MCP server that doesn't use an authorization server that supports DCR and the client is not pre-registered with said authorization server, it's the responsibility of the client developer to provide an affordance for the end-user to enter client information manually.
</Tip>
</Step>
<Step title="User Authorization">
The client will now need to open a browser to the `/authorize` endpoint, where the user can log in and grant the required permissions. The authorization server will then redirect back to the client with an authorization code that the client exchanges for tokens:
```json theme={null}
{
"access_token": "eyJhbGciOiJSUzI1NiIs...",
"refresh_token": "def502...",
"token_type": "Bearer",
"expires_in": 3600
}
```
The access token is what the client will use to authenticate requests to the MCP server. This step follows standard [OAuth 2.1 authorization code with PKCE](https://oauth.net/2/grant-types/authorization-code/) conventions.
</Step>
<Step title="Making Authenticated Requests">
Finally, the client can make requests to your MCP server using the access token embedded in the `Authorization` header:
```http theme={null}
GET /mcp HTTP/1.1
Host: your-server.com
Authorization: Bearer eyJhbGciOiJSUzI1NiIs...
```
The MCP server will need to validate the token and process the request if the token is valid and has the required permissions.
</Step>
</Steps>
## Implementation Example
To get started with a practical implementation, we will use a [Keycloak](https://www.keycloak.org/) authorization server hosted in a Docker container. Keycloak is an open-source authorization server that can be easily deployed locally for testing and experimentation.
Make sure that you download and install [Docker Desktop](https://www.docker.com/products/docker-desktop/). We will need it to deploy Keycloak on our development machine.
### Keycloak Setup
From your terminal application, run the following command to start the Keycloak container:
```bash theme={null}
docker run -p 127.0.0.1:8080:8080 -e KC_BOOTSTRAP_ADMIN_USERNAME=admin -e KC_BOOTSTRAP_ADMIN_PASSWORD=admin quay.io/keycloak/keycloak start-dev
```
This command will pull the Keycloak container image locally and bootstrap the basic configuration. It will run on port `8080` and have an `admin` user with `admin` password.
<Warning>
**Not for Production**
The configuration above may be suitable for testing and experimentation; however, you should never use it in production. Refer to the [Configuring Keycloak for production](https://www.keycloak.org/server/configuration-production) guide for additional details on how to deploy the authorization server for scenarios that require reliability, security, and high availability.
</Warning>
You will be able to access the Keycloak authorization server from your browser at `http://localhost:8080`.
<Frame>
<img src="https://mintcdn.com/mcp/sAd4SGUO-cEUqgzn/images/tutorial-authorization/keycloak-browser.png?fit=max&auto=format&n=sAd4SGUO-cEUqgzn&q=85&s=cba689d986e113cbe937d732ac0558b6" alt="Keycloak admin dashboard authentication dialog." width="1834" height="1450" data-path="images/tutorial-authorization/keycloak-browser.png" />
</Frame>
When running with the default configuration, Keycloak will already support many of the capabilities that we need for MCP servers, including Dynamic Client Registration. You can check this by looking at the OIDC configuration, available at:
```http theme={null}
http://localhost:8080/realms/master/.well-known/openid-configuration
```
We will also need to set up Keycloak to support our scopes and allow our host (local machine) to dynamically register clients, as the default policies restrict anonymous dynamic client registration.
Go to **Client scopes** in the Keycloak dashboard and create a new `mcp:tools` scope. We will use this to access all of the tools on our MCP server.
<Frame>
<img src="https://mintcdn.com/mcp/sAd4SGUO-cEUqgzn/images/tutorial-authorization/keycloak-scopes.png?fit=max&auto=format&n=sAd4SGUO-cEUqgzn&q=85&s=3cd49dc2e070027609ae495751e0db58" alt="Configuring Keycloak scopes." width="1999" height="1710" data-path="images/tutorial-authorization/keycloak-scopes.png" />
</Frame>
After creating the scope, make sure that you assign its type to **Default** and have flipped the **Include in token scope** switch, as this will be needed for token validation.
Let's now also set up an **audience** for our Keycloak-issued tokens. An audience is important to configure because it embeds the intended destination directly into the issued access token. This helps your MCP server to verify that the token it got was actually meant for it rather than some other API. This is key to help avoid token passthrough scenarios.
To do this, open your `mcp:tools` client scope and click on **Mappers**, followed by **Configure a new mapper**. Select **Audience**.
<Frame>
<img src="https://mintcdn.com/mcp/sAd4SGUO-cEUqgzn/images/tutorial-authorization/scope-add-audience.gif?s=6ea9cf20c397f4c79c491c2e39019272" alt="Configuring an audience for a token in Keycloak." width="1080" height="921" data-path="images/tutorial-authorization/scope-add-audience.gif" />
</Frame>
For **Name**, use `audience-config`. Add a value for **Included Custom Audience**, set to `http://localhost:3000`. This will be the URI of our test server.
<Warning>
**Not for Production**
The audience configuration above is meant for testing. For production scenarios, additional set-up and configuration will be required to ensure that audiences are properly constrained for issued tokens. Specifically, the audience needs to be based on the resource parameter passed from the client, not a fixed value.
</Warning>
Now, navigate to **Clients**, then **Client registration**, and then **Trusted Hosts**. Disable the **Client URIs Must Match** setting and add the hosts from which you're testing. You can get your current host IP by running the `ifconfig` command on Linux or macOS, or `ipconfig` on Windows. You can see the IP address you need to add by looking at the keycloak logs for a line that looks like `Failed to verify remote host : 192.168.215.1`. Check that the IP address is associated with your host. This may be for a bridge network depending on your docker setup.
<Frame>
<img src="https://mintcdn.com/mcp/sAd4SGUO-cEUqgzn/images/tutorial-authorization/keycloak-client.gif?s=b5d40b36a5f1ea1e818821bb8ea77f6b" alt="Setting up client registration details in Keycloak." width="1199" height="1027" data-path="images/tutorial-authorization/keycloak-client.gif" />
</Frame>
<Warning>
**Getting the Host**
If you are running Keycloak from a container, you will also be able to see the host IP from the Terminal in the container logs.
</Warning>
Lastly, we need to register a new client that we can use with the **MCP server itself** to talk to Keycloak for things like [token introspection](https://oauth.net/2/token-introspection/). To do that:
1. Go to **Clients**.
2. Click **Create client**.
3. Give your client a unique **Client ID** and click **Next**.
4. Enable **Client authentication** and click **Next**.
5. Click **Save**.
Worth noting that token introspection is just *one of* the available approaches to validate tokens. This can also be done with the help of standalone libraries, specific to each language and platform.
When you open the client details, go to **Credentials** and take note of the **Client Secret**.
<Frame>
<img src="https://mintcdn.com/mcp/sAd4SGUO-cEUqgzn/images/tutorial-authorization/keycloak-client-auth.gif?s=7152c41a5746994fd399024bc4659e40" alt="Creating a new client in Keycloak." width="1200" height="1023" data-path="images/tutorial-authorization/keycloak-client-auth.gif" />
</Frame>
<Warning>
**Handling Secrets**
Never embed client credentials directly in your code. We recommend using environment variables or specialized solutions for secret storage.
</Warning>
With Keycloak configured, every time the authorization flow is triggered, your MCP server will receive a token like this:
```text theme={null}
eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI1TjcxMGw1WW5MWk13WGZ1VlJKWGtCS3ZZMzZzb3JnRG5scmlyZ2tlTHlzIn0.eyJleHAiOjE3NTU1NDA4MTcsImlhdCI6MTc1NTU0MDc1NywiYXV0aF90aW1lIjoxNzU1NTM4ODg4LCJqdGkiOiJvbnJ0YWM6YjM0MDgwZmYtODQwNC02ODY3LTgxYmUtMTIzMWI1MDU5M2E4IiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4MDgwL3JlYWxtcy9tYXN0ZXIiLCJhdWQiOiJodHRwOi8vbG9jYWxob3N0OjMwMDAiLCJzdWIiOiIzM2VkNmM2Yi1jNmUwLTQ5MjgtYTE2MS1mMmY2OWM3YTAzYjkiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiI3OTc1YTViNi04YjU5LTRhODUtOWNiYS04ZmFlYmRhYjg5NzQiLCJzaWQiOiI4ZjdlYzI3Ni0zNThmLTRjY2MtYjMxMy1kYjA4MjkwZjM3NmYiLCJzY29wZSI6Im1jcDp0b29scyJ9.P5xCRtXORly0R0EXjyqRCUx-z3J4uAOWNAvYtLPXroykZuVCCJ-K1haiQSwbURqfsVOMbL7jiV-sD6miuPzI1tmKOkN_Yct0Vp-azvj7U5rEj7U6tvPfMkg2Uj_jrIX0KOskyU2pVvGZ-5BgqaSvwTEdsGu_V3_E0xDuSBq2uj_wmhqiyTFm5lJ1WkM3Hnxxx1_AAnTj7iOKMFZ4VCwMmk8hhSC7clnDauORc0sutxiJuYUZzxNiNPkmNeQtMCGqWdP1igcbWbrfnNXhJ6NswBOuRbh97_QraET3hl-CNmyS6C72Xc0aOwR_uJ7xVSBTD02OaQ1JA6kjCATz30kGYg
```
Decoded, it will look like this:
```json theme={null}
{
"alg": "RS256",
"typ": "JWT",
"kid": "5N710l5YnLZMwXfuVRJXkBKvY36sorgDnlrirgkeLys"
}.{
"exp": 1755540817,
"iat": 1755540757,
"auth_time": 1755538888,
"jti": "onrtac:b34080ff-8404-6867-81be-1231b50593a8",
"iss": "http://localhost:8080/realms/master",
"aud": "http://localhost:3000",
"sub": "33ed6c6b-c6e0-4928-a161-f2f69c7a03b9",
"typ": "Bearer",
"azp": "7975a5b6-8b59-4a85-9cba-8faebdab8974",
"sid": "8f7ec276-358f-4ccc-b313-db08290f376f",
"scope": "mcp:tools"
}.[Signature]
```
<Warning>
**Embedded Audience**
Notice the `aud` claim embedded in the token - it's currently set to be the URI of the test MCP server and it's inferred from the scope that we've previously configured. This will be important in our implementation to validate.
</Warning>
### MCP Server Setup
We will now set up our MCP server to use the locally-running Keycloak authorization server. Depending on your programming language preference, you can use one of the supported [MCP SDKs](/docs/draft/sdk).
For our testing purposes, we will create an extremely simple MCP server that exposes two tools - one for addition and another for multiplication. The server will require authorization to access these.
<Tabs>
<Tab title="TypeScript">
You can see the complete TypeScript project in the [sample repository](https://github.com/localden/min-ts-mcp-auth).
Prior to running the code below, ensure that you have a `.env` file with the following content:
```env theme={null}
# Server host/port
HOST=localhost
PORT=3000
# Auth server location
AUTH_HOST=localhost
AUTH_PORT=8080
AUTH_REALM=master
# Keycloak OAuth client credentials
OAUTH_CLIENT_ID=<YOUR_SERVER_CLIENT_ID>
OAUTH_CLIENT_SECRET=<YOUR_SERVER_CLIENT_SECRET>
```
`OAUTH_CLIENT_ID` and `OAUTH_CLIENT_SECRET` are associated with the MCP server client we created earlier.
In addition to implementing the MCP authorization specification, the server below also does token introspection via Keycloak to make sure that the token it receives from the client is valid. It also implements basic logging to allow you to easily diagnose any issues.
```typescript theme={null}
import "dotenv/config";
import express from "express";
import { randomUUID } from "node:crypto";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
import { isInitializeRequest } from "@modelcontextprotocol/sdk/types.js";
import { z } from "zod";
import cors from "cors";
import {
mcpAuthMetadataRouter,
getOAuthProtectedResourceMetadataUrl,
} from "@modelcontextprotocol/sdk/server/auth/router.js";
import { requireBearerAuth } from "@modelcontextprotocol/sdk/server/auth/middleware/bearerAuth.js";
import { OAuthMetadata } from "@modelcontextprotocol/sdk/shared/auth.js";
Cut at 300 lines. The page has the rest.
docs/draft/tutorials/security/security_best_practices New page · 983 lines, new page
# Security Best Practices ## Introduction ### Purpose and Scope ## Attacks and Mitigations ### Confused Deputy Problem #### Terminology #### Vulnerable Conditions #### Architecture and Attack Flows ##### Normal OAuth proxy usage (preserves user consent) ##### Malicious OAuth proxy usage (skips user consent) #### Attack Description #### Mitigation ##### Consent Flow Implementation ##### Required Protections ### Token Passthrough #### Risks #### Mitigation ### Server-Side Request Forgery (SSRF) #### Attack Description #### Risks #### Mitigation #### SSRF Against Authorization Servers #### Resources and Tools ### State Handle Hijacking #### Attack Description #### Mitigation ### Local MCP Server Compromise #### Attack Description #### Risks #### Mitigation ### OAuth Authorization URL Validation #### Attack Description #### Risks #### Mitigation ### stdio Transport Security in Proxy Scenarios #### Attack Description #### Risks #### Mitigation ### Mix-Up Attacks #### Attack Description #### Mitigation ### Localhost Redirect URI Impersonation #### Attack Description #### Mitigation ### CIMD Trust Policies ### Scope Minimization #### Attack Description #### Risks #### Mitigation #### Common Mistakes
A whole new page. There's nothing to diff it against, so here is what it says.
# Security Best Practices
> Security considerations, attack vectors, and best practices for MCP implementations
## Introduction
### Purpose and Scope
This document provides security considerations for the Model Context
Protocol (MCP), complementing the
[MCP Authorization](/specification/latest/basic/authorization)
specification. This document identifies security risks, attack vectors,
and best practices specific to MCP implementations.
The primary audience for this document includes developers implementing
MCP authorization flows, MCP server operators, and security
professionals evaluating MCP-based systems. This document should be read
alongside the MCP Authorization specification and
[OAuth 2.0 security best practices](https://datatracker.ietf.org/doc/html/rfc9700).
## Attacks and Mitigations
This section gives a detailed description of attacks on MCP
implementations, along with potential countermeasures.
### Confused Deputy Problem
Attackers can exploit MCP proxy servers that connect to third-party
APIs, creating
"[confused deputy](https://en.wikipedia.org/wiki/Confused_deputy_problem)"
vulnerabilities. This attack allows malicious clients to obtain
authorization codes without proper user consent by exploiting the
combination of static client IDs, dynamic client registration, and
consent cookies.
#### Terminology
**MCP Proxy Server**
: An MCP server that connects MCP clients to third-party APIs, offering
MCP features while delegating operations and acting as a single OAuth
client to the third-party API server.
**Third-Party Authorization Server**
: Authorization server that protects the third-party API. It may lack
dynamic client registration support, requiring the MCP proxy to use a
static client ID for all requests.
**Third-Party API**
: The protected resource server that provides the actual API
functionality. Access to this API requires tokens issued by the
third-party authorization server.
**Static Client ID**
: A fixed OAuth 2.0 client identifier used by the MCP proxy server when
communicating with the third-party authorization server. This Client ID
refers to the MCP server acting as a client to the Third-Party API. It
is the same value for all MCP server to Third-Party API interactions
regardless of which MCP client initiated the request.
#### Vulnerable Conditions
This attack becomes possible when all of the following conditions are
present:
* MCP proxy server uses a **static client ID** with a third-party
authorization server
* MCP proxy server allows MCP clients to **dynamically register** (each
getting their own client\_id)
* The third-party authorization server sets a **consent cookie** after
the first authorization
* MCP proxy server does not implement proper per-client consent before
forwarding to third-party authorization
#### Architecture and Attack Flows
##### Normal OAuth proxy usage (preserves user consent)
```mermaid theme={null}
sequenceDiagram
participant UA as User-Agent (Browser)
participant MC as MCP Client
participant M as MCP Proxy Server
participant TAS as Third-Party Authorization Server
Note over UA,M: Initial Auth flow completed
Note over UA,TAS: Step 1: Legitimate user consent for Third Party Server
M->>UA: Redirect to third party authorization server
UA->>TAS: Authorization request (client_id: mcp-proxy)
TAS->>UA: Authorization consent screen
Note over UA: Review consent screen
UA->>TAS: Approve
TAS->>UA: Set consent cookie for client ID: mcp-proxy
TAS->>UA: 3P Authorization code + redirect to mcp-proxy-server.com
UA->>M: 3P Authorization code
Note over M,TAS: Exchange 3P code for 3P token
Note over M: Generate MCP authorization code
M->>UA: Redirect to MCP Client with MCP authorization code
Note over M,UA: Exchange code for token, etc.
```
##### Malicious OAuth proxy usage (skips user consent)
```mermaid theme={null}
sequenceDiagram
participant UA as User-Agent (Browser)
participant M as MCP Proxy Server
participant TAS as Third-Party Authorization Server
participant A as Attacker
Note over UA,A: Step 2: Attack (leveraging existing cookie, skipping consent)
A->>M: Dynamically register malicious client, redirect_uri: attacker.com
A->>UA: Sends malicious link
UA->>TAS: Authorization request (client_id: mcp-proxy) + consent cookie
rect rgba(255, 17, 0, 0.67)
TAS->>TAS: Cookie present, consent skipped
end
TAS->>UA: 3P Authorization code + redirect to mcp-proxy-server.com
UA->>M: 3P Authorization code
Note over M,TAS: Exchange 3P code for 3P token
Note over M: Generate MCP authorization code
M->>UA: Redirect to attacker.com with MCP Authorization code
UA->>A: MCP Authorization code delivered to attacker.com
Note over M,A: Attacker exchanges MCP code for MCP token
A->>M: Attacker impersonates user to MCP server
```
#### Attack Description
When an MCP proxy server uses a static client ID to authenticate with
a third-party authorization server, the following attack becomes
possible:
1. A user authenticates normally through the MCP proxy server to access
the third-party API
2. During this flow, the third-party authorization server sets a cookie
on the user agent indicating consent for the static client ID
3. An attacker later sends the user a malicious link containing a
crafted authorization request which contains a malicious redirect URI
along with a new dynamically registered client ID
4. When the user clicks the link, their browser still has the consent
cookie from the previous legitimate request
5. The third-party authorization server detects the cookie and skips the
consent screen
6. The MCP authorization code is redirected to the attacker's server
(specified in the malicious `redirect_uri` parameter during
[dynamic client registration](/specification/latest/basic/authorization#dynamic-client-registration))
7. The attacker exchanges the stolen authorization code for access
tokens for the MCP server without the user's explicit approval
8. The attacker now has access to the third-party API as the compromised
user
#### Mitigation
To prevent confused deputy attacks, MCP proxy servers **MUST** implement
per-client consent and proper security controls as detailed below.
##### Consent Flow Implementation
The following diagram shows how to properly implement per-client consent
that runs **before** the third-party authorization flow:
```mermaid theme={null}
sequenceDiagram
participant Client as MCP Client
participant Browser as User's Browser
participant MCP as MCP Server
participant ThirdParty as Third-Party AuthZ Server
Note over Client,ThirdParty: 1. Client Registration (Dynamic)
Client->>MCP: Register with redirect_uri
MCP-->>Client: client_id
Note over Client,ThirdParty: 2. Authorization Request
Client->>Browser: Open MCP server authorization URL
Browser->>MCP: GET /authorize?client_id=...&redirect_uri=...
alt Check MCP Server Consent
MCP->>MCP: Check consent for this client_id
Note over MCP: Not previously approved
end
MCP->>Browser: Show MCP server-owned consent page
Note over Browser: "Allow [Client Name] to access [Third-Party API]?"
Browser->>MCP: POST /consent (approve)
MCP->>MCP: Store consent decision for client_id
Note over Client,ThirdParty: 3. Forward to Third-Party
MCP->>Browser: Redirect to third-party /authorize
Note over MCP: Use static client_id for third-party
Browser->>ThirdParty: Authorization request (static client_id)
ThirdParty->>Browser: User authenticates & consents
ThirdParty->>Browser: Redirect with auth code
Browser->>MCP: Callback with third-party code
MCP->>ThirdParty: Exchange code for token (using static client_id)
MCP->>Browser: Redirect to client's registered redirect_uri
```
##### Required Protections
**Per-Client Consent Storage**
MCP proxy servers **MUST**:
* Maintain a registry of approved `client_id` values per user
* Check this registry **before** initiating the third-party
authorization flow
* Store consent decisions securely (server-side database, or server
specific cookies)
**Consent UI Requirements**
The MCP-level consent page **MUST**:
* Clearly identify the requesting MCP client by name
* Display the specific third-party API scopes being requested
* Show the registered `redirect_uri` where tokens will be sent
* Implement CSRF protection (e.g., state parameter, CSRF tokens)
* Prevent iframing via `frame-ancestors` CSP directive or
`X-Frame-Options: DENY` to prevent clickjacking
**Consent Cookie Security**
If using cookies to track consent decisions, they **MUST**:
* Use `__Host-` prefix for cookie names
* Set `Secure`, `HttpOnly`, and `SameSite=Lax` attributes
* Be cryptographically signed or use server-side sessions
* Bind to the specific `client_id` (not just "user has consented")
**Redirect URI Validation**
The MCP proxy server **MUST**:
* Validate that the `redirect_uri` in authorization requests exactly
matches the registered URI
* Reject requests if the `redirect_uri` has changed without
re-registration
* Use exact string matching (not pattern matching or wildcards)
**OAuth State Parameter Validation**
The OAuth `state` parameter is critical to prevent authorization code
interception and CSRF attacks. Proper state validation ensures that
consent approval at the authorization endpoint is enforced at the
callback endpoint.
MCP proxy servers implementing OAuth flows **MUST**:
* Generate a cryptographically secure random `state` value for each
authorization request
* Store the `state` value server-side (in a secure session store or
encrypted cookie) **only after** consent has been explicitly approved
* Set the `state` tracking cookie/session **immediately before**
redirecting to the third-party identity provider (not before consent
approval)
* Validate at the callback endpoint that the `state` query parameter
exactly matches the stored value in the callback request's cookies or
in the request's cookie-based session
* Reject any callback requests where the `state` parameter is missing
or does not match
* Ensure `state` values are single-use (delete after validation) and
have a short expiration time (e.g., 10 minutes)
The consent cookie or session containing the `state` value **MUST NOT**
be set until **after** the user has approved the consent screen at the
MCP server's authorization endpoint. Setting this cookie before consent
approval renders the consent screen ineffective, as an attacker could
bypass it by crafting a malicious authorization request.
### Token Passthrough
"Token passthrough" is an anti-pattern where an MCP server accepts
tokens from an MCP client without validating that the tokens were
properly issued *to the MCP server* and passes them through to the
downstream API.
An attacker can gain unauthorized access or otherwise compromise an
MCP server if the server accepts tokens issued for other resources.
This vulnerability has two critical dimensions:
1. **Audience validation failures.** When an MCP server doesn't verify
that tokens were specifically intended for it (for example, via the
audience claim, as mentioned in
[RFC9068](https://www.rfc-editor.org/rfc/rfc9068.html)), it may
accept tokens originally issued for other services. This breaks a
fundamental OAuth security boundary, allowing attackers to reuse
legitimate tokens across different services than intended.
2. **Token passthrough.** If the MCP server not only accepts tokens
with incorrect audiences but also forwards these unmodified tokens
to downstream services, it can potentially cause the
["confused deputy" problem](#confused-deputy-problem), where the
downstream API may incorrectly trust the token as if it came from
the MCP server or assume the token was validated by the upstream
Cut at 300 lines. The page has the rest.
specification/2024-11-05/architecture/index New page · 182 lines, new page
# Architecture ## Core Components ### Host ### Clients ### Servers ## Design Principles ## Message Types ## Capability Negotiation
A whole new page. There's nothing to diff it against, so here is what it says.
# Architecture
The Model Context Protocol (MCP) follows a client-host-server architecture where each
host can run multiple client instances. This architecture enables users to integrate AI
capabilities across applications while maintaining clear security boundaries and
isolating concerns. Built on JSON-RPC, MCP provides a stateful session protocol focused
on context exchange and sampling coordination between clients and servers.
## Core Components
```mermaid theme={null}
graph LR
subgraph "Application Host Process"
H[Host]
C1[Client 1]
C2[Client 2]
C3[Client 3]
H --> C1
H --> C2
H --> C3
end
subgraph "Local machine"
S1[Server 1<br>Files & Git]
S2[Server 2<br>Database]
R1[("Local<br>Resource A")]
R2[("Local<br>Resource B")]
C1 --> S1
C2 --> S2
S1 <--> R1
S2 <--> R2
end
subgraph "Internet"
S3[Server 3<br>External APIs]
R3[("Remote<br>Resource C")]
C3 --> S3
S3 <--> R3
end
```
### Host
The host process acts as the container and coordinator:
* Creates and manages multiple client instances
* Controls client connection permissions and lifecycle
* Enforces security policies and consent requirements
* Handles user authorization decisions
* Coordinates AI/LLM integration and sampling
* Manages context aggregation across clients
### Clients
Each client is created by the host and maintains an isolated server connection:
* Establishes one stateful session per server
* Handles protocol negotiation and capability exchange
* Routes protocol messages bidirectionally
* Manages subscriptions and notifications
* Maintains security boundaries between servers
A host application creates and manages multiple clients, with each client having a 1:1
relationship with a particular server.
### Servers
Servers provide specialized context and capabilities:
* Expose resources, tools and prompts via MCP primitives
* Operate independently with focused responsibilities
* Request sampling through client interfaces
* Must respect security constraints
* Can be local processes or remote services
## Design Principles
MCP is built on several key design principles that inform its architecture and
implementation:
1. **Servers should be extremely easy to build**
* Host applications handle complex orchestration responsibilities
* Servers focus on specific, well-defined capabilities
* Simple interfaces minimize implementation overhead
* Clear separation enables maintainable code
2. **Servers should be highly composable**
* Each server provides focused functionality in isolation
* Multiple servers can be combined seamlessly
* Shared protocol enables interoperability
* Modular design supports extensibility
3. **Servers should not be able to read the whole conversation, nor "see into" other
servers**
* Servers receive only necessary contextual information
* Full conversation history stays with the host
* Each server connection maintains isolation
* Cross-server interactions are controlled by the host
* Host process enforces security boundaries
4. **Features can be added to servers and clients progressively**
* Core protocol provides minimal required functionality
* Additional capabilities can be negotiated as needed
* Servers and clients evolve independently
* Protocol designed for future extensibility
* Backwards compatibility is maintained
## Message Types
MCP defines three core message types based on
[JSON-RPC 2.0](https://www.jsonrpc.org/specification):
* **Requests**: Bidirectional messages with method and parameters expecting a response
* **Responses**: Successful results or errors matching specific request IDs
* **Notifications**: One-way messages requiring no response
Each message type follows the JSON-RPC 2.0 specification for structure and delivery
semantics.
## Capability Negotiation
The Model Context Protocol uses a capability-based negotiation system where clients and
servers explicitly declare their supported features during initialization. Capabilities
determine which protocol features and primitives are available during a session.
* Servers declare capabilities like resource subscriptions, tool support, and prompt
templates
* Clients declare capabilities like sampling support and notification handling
* Both parties must respect declared capabilities throughout the session
* Additional capabilities can be negotiated through extensions to the protocol
```mermaid theme={null}
sequenceDiagram
participant Host
participant Client
participant Server
Host->>+Client: Initialize client
Client->>+Server: Initialize session with capabilities
Server-->>Client: Respond with supported capabilities
Note over Host,Server: Active Session with Negotiated Features
loop Client Requests
Host->>Client: User- or model-initiated action
Client->>Server: Request (tools/resources)
Server-->>Client: Response
Client-->>Host: Update UI or respond to model
end
loop Server Requests
Server->>Client: Request (sampling)
Client->>Host: Forward to AI
Host-->>Client: AI response
Client-->>Server: Response
end
loop Notifications
Server--)Client: Resource updates
Client--)Server: Status changes
end
Host->>Client: Terminate
Client->>-Server: End session
deactivate Server
```
Each capability unlocks specific protocol features for use during the session. For
example:
* Implemented [server features](/specification/2024-11-05/server) must be
advertised in the server's capabilities
* Emitting resource subscription notifications requires the server to declare
subscription support
* Tool invocation requires the server to declare tool capabilities
* [Sampling](/specification/2024-11-05/client/sampling) requires the client to
declare support in its capabilities
This capability negotiation ensures clients and servers have a clear understanding of
supported functionality while maintaining protocol extensibility.
specification/2024-11-05/basic/index New page · 71 lines, new page
# Overview ## Protocol Layers ## Auth ## Schema
A whole new page. There's nothing to diff it against, so here is what it says.
# Overview
All messages between MCP clients and servers **MUST** follow the
[JSON-RPC 2.0](https://www.jsonrpc.org/specification) specification. The protocol defines
three fundamental types of messages:
| Type | Description | Requirements |
| --------------- | -------------------------------------- | -------------------------------------- |
| `Requests` | Messages sent to initiate an operation | Must include unique ID and method name |
| `Responses` | Messages sent in reply to requests | Must include same ID as request |
| `Notifications` | One-way messages with no reply | Must not include an ID |
**Responses** are further sub-categorized as either **successful results** or **errors**.
Results can follow any JSON object structure, while errors must include an error code and
message at minimum.
## Protocol Layers
The Model Context Protocol consists of several key components that work together:
* **Base Protocol**: Core JSON-RPC message types
* **Lifecycle Management**: Connection initialization, capability negotiation, and
session control
* **Server Features**: Resources, prompts, and tools exposed by servers
* **Client Features**: Sampling and root directory lists provided by clients
* **Utilities**: Cross-cutting concerns like logging and argument completion
All implementations **MUST** support the base protocol and lifecycle management
components. Other components **MAY** be implemented based on the specific needs of the
application.
These protocol layers establish clear separation of concerns while enabling rich
interactions between clients and servers. The modular design allows implementations to
support exactly the features they need.
See the following pages for more details on the different components:
<CardGroup cols={3}>
<Card title="Lifecycle" icon="arrows-rotate" href="/specification/2024-11-05/basic/lifecycle" />
<Card title="Resources" icon="file-lines" href="/specification/2024-11-05/server/resources" />
<Card title="Prompts" icon="message" href="/specification/2024-11-05/server/prompts" />
<Card title="Tools" icon="wrench" href="/specification/2024-11-05/server/tools" />
<Card title="Logging" icon="rectangle-list" href="/specification/2024-11-05/server/utilities/logging" />
<Card title="Sampling" icon="code" href="/specification/2024-11-05/client/sampling" />
</CardGroup>
## Auth
Authentication and authorization are not currently part of the core MCP specification,
but we are considering ways to introduce them in future. Join us in
[GitHub Discussions](https://github.com/modelcontextprotocol/specification/discussions)
to help shape the future of the protocol!
Clients and servers **MAY** negotiate their own custom authentication and authorization
strategies.
## Schema
The full specification of the protocol is defined as a
[TypeScript schema](http://github.com/modelcontextprotocol/specification/tree/main/schema/2024-11-05/schema.ts).
This is the source of truth for all protocol messages and structures.
There is also a
[JSON Schema](http://github.com/modelcontextprotocol/specification/tree/main/schema/2024-11-05/schema.json),
which is automatically generated from the TypeScript source of truth, for use with
various automated tooling.
specification/2024-11-05/basic/lifecycle New page · 214 lines, new page
# Lifecycle ## Lifecycle Phases ### Initialization #### Version Negotiation #### Capability Negotiation ### Operation ### Shutdown #### stdio #### HTTP ## Error Handling
A whole new page. There's nothing to diff it against, so here is what it says.
# Lifecycle
The Model Context Protocol (MCP) defines a rigorous lifecycle for client-server
connections that ensures proper capability negotiation and state management.
1. **Initialization**: Capability negotiation and protocol version agreement
2. **Operation**: Normal protocol communication
3. **Shutdown**: Graceful termination of the connection
```mermaid theme={null}
sequenceDiagram
participant Client
participant Server
Note over Client,Server: Initialization Phase
activate Client
Client->>+Server: initialize request
Server-->>Client: initialize response
Client--)Server: initialized notification
Note over Client,Server: Operation Phase
rect rgb(200, 220, 250)
note over Client,Server: Normal protocol operations
end
Note over Client,Server: Shutdown
Client--)-Server: Disconnect
deactivate Server
Note over Client,Server: Connection closed
```
## Lifecycle Phases
### Initialization
The initialization phase **MUST** be the first interaction between client and server.
During this phase, the client and server:
* Establish protocol version compatibility
* Exchange and negotiate capabilities
* Share implementation details
The client **MUST** initiate this phase by sending an `initialize` request containing:
* Protocol version supported
* Client capabilities
* Client implementation information
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2024-11-05",
"capabilities": {
"roots": {
"listChanged": true
},
"sampling": {}
},
"clientInfo": {
"name": "ExampleClient",
"version": "1.0.0"
}
}
}
```
The server **MUST** respond with its own capabilities and information:
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"protocolVersion": "2024-11-05",
"capabilities": {
"logging": {},
"prompts": {
"listChanged": true
},
"resources": {
"subscribe": true,
"listChanged": true
},
"tools": {
"listChanged": true
}
},
"serverInfo": {
"name": "ExampleServer",
"version": "1.0.0"
}
}
}
```
After successful initialization, the client **MUST** send an `initialized` notification
to indicate it is ready to begin normal operations:
```json theme={null}
{
"jsonrpc": "2.0",
"method": "notifications/initialized"
}
```
* The client **SHOULD NOT** send requests other than
[pings](/specification/2024-11-05/basic/utilities/ping) before the server
has responded to the `initialize` request.
* The server **SHOULD NOT** send requests other than
[pings](/specification/2024-11-05/basic/utilities/ping) and
[logging](/specification/2024-11-05/server/utilities/logging) before
receiving the `initialized` notification.
#### Version Negotiation
In the `initialize` request, the client **MUST** send a protocol version it supports.
This **SHOULD** be the *latest* version supported by the client.
If the server supports the requested protocol version, it **MUST** respond with the same
version. Otherwise, the server **MUST** respond with another protocol version it
supports. This **SHOULD** be the *latest* version supported by the server.
If the client does not support the version in the server's response, it **SHOULD**
disconnect.
#### Capability Negotiation
Client and server capabilities establish which optional protocol features will be
available during the session.
Key capabilities include:
| Category | Capability | Description |
| -------- | -------------- | ----------------------------------------------------------------------------------- |
| Client | `roots` | Ability to provide filesystem [roots](/specification/2024-11-05/client/roots) |
| Client | `sampling` | Support for LLM [sampling](/specification/2024-11-05/client/sampling) requests |
| Client | `experimental` | Describes support for non-standard experimental features |
| Server | `prompts` | Offers [prompt templates](/specification/2024-11-05/server/prompts) |
| Server | `resources` | Provides readable [resources](/specification/2024-11-05/server/resources) |
| Server | `tools` | Exposes callable [tools](/specification/2024-11-05/server/tools) |
| Server | `logging` | Emits structured [log messages](/specification/2024-11-05/server/utilities/logging) |
| Server | `experimental` | Describes support for non-standard experimental features |
Capability objects can describe sub-capabilities like:
* `listChanged`: Support for list change notifications (for prompts, resources, and
tools)
* `subscribe`: Support for subscribing to individual items' changes (resources only)
### Operation
During the operation phase, the client and server exchange messages according to the
negotiated capabilities.
Both parties **SHOULD**:
* Respect the negotiated protocol version
* Only use capabilities that were successfully negotiated
### Shutdown
During the shutdown phase, one side (usually the client) cleanly terminates the protocol
connection. No specific shutdown messages are defined—instead, the underlying transport
mechanism should be used to signal connection termination:
#### stdio
For the stdio [transport](/specification/2024-11-05/basic/transports), the
client **SHOULD** initiate shutdown by:
1. First, closing the input stream to the child process (the server)
2. Waiting for the server to exit, or sending `SIGTERM` if the server does not exit
within a reasonable time
3. Sending `SIGKILL` if the server does not exit within a reasonable time after `SIGTERM`
The server **MAY** initiate shutdown by closing its output stream to the client and
exiting.
#### HTTP
For HTTP [transports](/specification/2024-11-05/basic/transports), shutdown
is indicated by closing the associated HTTP connection(s).
## Error Handling
Implementations **SHOULD** be prepared to handle these error cases:
* Protocol version mismatch
* Failure to negotiate required capabilities
* Initialize request timeout
* Shutdown timeout
Implementations **SHOULD** implement appropriate timeouts for all requests, to prevent
hung connections and resource exhaustion.
Example initialization error:
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32602,
"message": "Unsupported protocol version",
"data": {
"supported": ["2024-11-05"],
"requested": "1.0.0"
}
}
}
```
specification/2024-11-05/basic/messages New page · 65 lines, new page
# Messages ## Requests ## Responses ## Notifications
A whole new page. There's nothing to diff it against, so here is what it says.
# Messages
All messages in MCP **MUST** follow the
[JSON-RPC 2.0](https://www.jsonrpc.org/specification) specification. The protocol defines
three types of messages:
## Requests
Requests are sent from the client to the server or vice versa.
```typescript theme={null}
{
jsonrpc: "2.0";
id: string | number;
method: string;
params?: {
[key: string]: unknown;
};
}
```
* Requests **MUST** include a string or integer ID.
* Unlike base JSON-RPC, the ID **MUST NOT** be `null`.
* The request ID **MUST NOT** have been previously used by the requestor within the same
session.
## Responses
Responses are sent in reply to requests.
```typescript theme={null}
{
jsonrpc: "2.0";
id: string | number;
result?: {
[key: string]: unknown;
}
error?: {
code: number;
message: string;
data?: unknown;
}
}
```
* Responses **MUST** include the same ID as the request they correspond to.
* Either a `result` or an `error` **MUST** be set. A response **MUST NOT** set both.
* Error codes **MUST** be integers.
## Notifications
Notifications are sent from the client to the server or vice versa. They do not expect a
response.
```typescript theme={null}
{
jsonrpc: "2.0";
method: string;
params?: {
[key: string]: unknown;
};
}
```
* Notifications **MUST NOT** include an ID.
specification/2024-11-05/basic/transports New page · 93 lines, new page
# Transports ## stdio ## HTTP with SSE #### Security Warning ## Custom Transports
A whole new page. There's nothing to diff it against, so here is what it says.
# Transports
MCP currently defines two standard transport mechanisms for client-server communication:
1. [stdio](#stdio), communication over standard in and standard out
2. [HTTP with Server-Sent Events](#http-with-sse) (SSE)
Clients **SHOULD** support stdio whenever possible.
It is also possible for clients and servers to implement
[custom transports](#custom-transports) in a pluggable fashion.
## stdio
In the **stdio** transport:
* The client launches the MCP server as a subprocess.
* The server receives JSON-RPC messages on its standard input (`stdin`) and writes
responses to its standard output (`stdout`).
* Messages are delimited by newlines, and **MUST NOT** contain embedded newlines.
* The server **MAY** write UTF-8 strings to its standard error (`stderr`) for logging
purposes. Clients **MAY** capture, forward, or ignore this logging.
* The server **MUST NOT** write anything to its `stdout` that is not a valid MCP message.
* The client **MUST NOT** write anything to the server's `stdin` that is not a valid MCP
message.
```mermaid theme={null}
sequenceDiagram
participant Client
participant Server Process
Client->>+Server Process: Launch subprocess
loop Message Exchange
Client->>Server Process: Write to stdin
Server Process->>Client: Write to stdout
Server Process--)Client: Optional logs on stderr
end
Client->>Server Process: Close stdin, terminate subprocess
deactivate Server Process
```
## HTTP with SSE
In the **SSE** transport, the server operates as an independent process that can handle
multiple client connections.
#### Security Warning
When implementing HTTP with SSE transport:
1. Servers **MUST** validate the `Origin` header on all incoming connections to prevent DNS rebinding attacks
2. When running locally, servers **SHOULD** bind only to localhost (127.0.0.1) rather than all network interfaces (0.0.0.0)
3. Servers **SHOULD** implement proper authentication for all connections
Without these protections, attackers could use DNS rebinding to interact with local MCP servers from remote websites.
The server **MUST** provide two endpoints:
1. An SSE endpoint, for clients to establish a connection and receive messages from the
server
2. A regular HTTP POST endpoint for clients to send messages to the server
When a client connects, the server **MUST** send an `endpoint` event containing a URI for
the client to use for sending messages. All subsequent client messages **MUST** be sent
as HTTP POST requests to this endpoint.
Server messages are sent as SSE `message` events, with the message content encoded as
JSON in the event data.
```mermaid theme={null}
sequenceDiagram
participant Client
participant Server
Client->>Server: Open SSE connection
Server->>Client: endpoint event
loop Message Exchange
Client->>Server: HTTP POST messages
Server->>Client: SSE message events
end
Client->>Server: Close SSE connection
```
## Custom Transports
Clients and servers **MAY** implement additional custom transport mechanisms to suit
their specific needs. The protocol is transport-agnostic and can be implemented over any
communication channel that supports bidirectional message exchange.
Implementers who choose to support custom transports **MUST** ensure they preserve the
JSON-RPC message format and lifecycle requirements defined by MCP. Custom transports
**SHOULD** document their specific connection establishment and message exchange patterns
to aid interoperability.
specification/2024-11-05/basic/utilities/cancellation New page · 79 lines, new page
# Cancellation ## Cancellation Flow ## Behavior Requirements ## Timing Considerations ## Implementation Notes ## Error Handling
A whole new page. There's nothing to diff it against, so here is what it says.
# Cancellation
The Model Context Protocol (MCP) supports optional cancellation of in-progress requests
through notification messages. Either side can send a cancellation notification to
indicate that a previously-issued request should be terminated.
## Cancellation Flow
When a party wants to cancel an in-progress request, it sends a `notifications/cancelled`
notification containing:
* The ID of the request to cancel
* An optional reason string that can be logged or displayed
```json theme={null}
{
"jsonrpc": "2.0",
"method": "notifications/cancelled",
"params": {
"requestId": "123",
"reason": "User requested cancellation"
}
}
```
## Behavior Requirements
1. Cancellation notifications **MUST** only reference requests that:
* Were previously issued in the same direction
* Are believed to still be in-progress
2. The `initialize` request **MUST NOT** be cancelled by clients
3. Receivers of cancellation notifications **SHOULD**:
* Stop processing the cancelled request
* Free associated resources
* Not send a response for the cancelled request
4. Receivers **MAY** ignore cancellation notifications if:
* The referenced request is unknown
* Processing has already completed
* The request cannot be cancelled
5. The sender of the cancellation notification **SHOULD** ignore any response to the
request that arrives afterward
## Timing Considerations
Due to network latency, cancellation notifications may arrive after request processing
has completed, and potentially after a response has already been sent.
Both parties **MUST** handle these race conditions gracefully:
```mermaid theme={null}
sequenceDiagram
participant Client
participant Server
Client->>Server: Request (ID: 123)
Note over Server: Processing starts
Client--)Server: notifications/cancelled (ID: 123)
alt
Note over Server: Processing may have<br/>completed before<br/>cancellation arrives
else If not completed
Note over Server: Stop processing
end
```
## Implementation Notes
* Both parties **SHOULD** log cancellation reasons for debugging
* Application UIs **SHOULD** indicate when cancellation is requested
## Error Handling
Invalid cancellation notifications **SHOULD** be ignored:
* Unknown request IDs
* Already completed requests
* Malformed notifications
This maintains the "fire and forget" nature of notifications while allowing for race
conditions in asynchronous communication.
specification/2024-11-05/basic/utilities/ping New page · 62 lines, new page
# Ping ## Overview ## Message Format ## Behavior Requirements ## Usage Patterns ## Implementation Considerations ## Error Handling
A whole new page. There's nothing to diff it against, so here is what it says.
# Ping
The Model Context Protocol includes an optional ping mechanism that allows either party
to verify that their counterpart is still responsive and the connection is alive.
## Overview
The ping functionality is implemented through a simple request/response pattern. Either
the client or server can initiate a ping by sending a `ping` request.
## Message Format
A ping request is a standard JSON-RPC request with no parameters:
```json theme={null}
{
"jsonrpc": "2.0",
"id": "123",
"method": "ping"
}
```
## Behavior Requirements
1. The receiver **MUST** respond promptly with an empty response:
```json theme={null}
{
"jsonrpc": "2.0",
"id": "123",
"result": {}
}
```
2. If no response is received within a reasonable timeout period, the sender **MAY**:
* Consider the connection stale
* Terminate the connection
* Attempt reconnection procedures
## Usage Patterns
```mermaid theme={null}
sequenceDiagram
participant Sender
participant Receiver
Sender->>Receiver: ping request
Receiver->>Sender: empty response
```
## Implementation Considerations
* Implementations **SHOULD** periodically issue pings to detect connection health
* The frequency of pings **SHOULD** be configurable
* Timeouts **SHOULD** be appropriate for the network environment
* Excessive pinging **SHOULD** be avoided to reduce network overhead
## Error Handling
* Timeouts **SHOULD** be treated as connection failures
* Multiple failed pings **MAY** trigger connection reset
* Implementations **SHOULD** log ping failures for diagnostics
specification/2024-11-05/basic/utilities/progress New page · 85 lines, new page
# Progress ## Progress Flow ## Behavior Requirements ## Implementation Notes
A whole new page. There's nothing to diff it against, so here is what it says.
# Progress
The Model Context Protocol (MCP) supports optional progress tracking for long-running
operations through notification messages. Either side can send progress notifications to
provide updates about operation status.
## Progress Flow
When a party wants to *receive* progress updates for a request, it includes a
`progressToken` in the request metadata.
* Progress tokens **MUST** be a string or integer value
* Progress tokens can be chosen by the sender using any means, but **MUST** be unique
across all active requests.
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"method": "some_method",
"params": {
"_meta": {
"progressToken": "abc123"
}
}
}
```
The receiver **MAY** then send progress notifications containing:
* The original progress token
* The current progress value so far
* An optional "total" value
```json theme={null}
{
"jsonrpc": "2.0",
"method": "notifications/progress",
"params": {
"progressToken": "abc123",
"progress": 50,
"total": 100
}
}
```
* The `progress` value **MUST** increase with each notification, even if the total is
unknown.
* The `progress` and the `total` values **MAY** be floating point.
## Behavior Requirements
1. Progress notifications **MUST** only reference tokens that:
* Were provided in an active request
* Are associated with an in-progress operation
2. Receivers of progress requests **MAY**:
* Choose not to send any progress notifications
* Send notifications at whatever frequency they deem appropriate
* Omit the total value if unknown
```mermaid theme={null}
sequenceDiagram
participant Sender
participant Receiver
Note over Sender,Receiver: Request with progress token
Sender->>Receiver: Method request with progressToken
Note over Sender,Receiver: Progress updates
loop Progress Updates
Receiver-->>Sender: Progress notification (0.2/1.0)
Receiver-->>Sender: Progress notification (0.6/1.0)
Receiver-->>Sender: Progress notification (1.0/1.0)
end
Note over Sender,Receiver: Operation complete
Receiver->>Sender: Method response
```
## Implementation Notes
* Senders and receivers **SHOULD** track active progress tokens
* Both parties **SHOULD** implement rate limiting to prevent flooding
* Progress notifications **MUST** stop after completion
specification/2024-11-05/client/roots New page · 184 lines, new page
# Roots ## User Interaction Model ## Capabilities ## Protocol Messages ### Listing Roots ### Root List Changes ## Message Flow ## Data Types ### Root #### Project Directory #### Multiple Repositories ## Error Handling ## Security Considerations ## Implementation Guidelines
A whole new page. There's nothing to diff it against, so here is what it says.
# Roots
The Model Context Protocol (MCP) provides a standardized way for clients to expose
filesystem "roots" to servers. Roots define the boundaries of where servers can operate
within the filesystem, allowing them to understand which directories and files they have
access to. Servers can request the list of roots from supporting clients and receive
notifications when that list changes.
## User Interaction Model
Roots in MCP are typically exposed through workspace or project configuration interfaces.
For example, implementations could offer a workspace/project picker that allows users to
select directories and files the server should have access to. This can be combined with
automatic workspace detection from version control systems or project files.
However, implementations are free to expose roots through any interface pattern that
suits their needs—the protocol itself does not mandate any specific user
interaction model.
## Capabilities
Clients that support roots **MUST** declare the `roots` capability during
[initialization](/specification/2024-11-05/basic/lifecycle#initialization):
```json theme={null}
{
"capabilities": {
"roots": {
"listChanged": true
}
}
}
```
`listChanged` indicates whether the client will emit notifications when the list of roots
changes.
## Protocol Messages
### Listing Roots
To retrieve roots, servers send a `roots/list` request:
**Request:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"method": "roots/list"
}
```
**Response:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"roots": [
{
"uri": "file:///home/user/projects/myproject",
"name": "My Project"
}
]
}
}
```
### Root List Changes
When roots change, clients that support `listChanged` **MUST** send a notification:
```json theme={null}
{
"jsonrpc": "2.0",
"method": "notifications/roots/list_changed"
}
```
## Message Flow
```mermaid theme={null}
sequenceDiagram
participant Server
participant Client
Note over Server,Client: Discovery
Server->>Client: roots/list
Client-->>Server: Available roots
Note over Server,Client: Changes
Client--)Server: notifications/roots/list_changed
Server->>Client: roots/list
Client-->>Server: Updated roots
```
## Data Types
### Root
A root definition includes:
* `uri`: Unique identifier for the root. This **MUST** be a `file://` URI in the current
specification.
* `name`: Optional human-readable name for display purposes.
Example roots for different use cases:
#### Project Directory
```json theme={null}
{
"uri": "file:///home/user/projects/myproject",
"name": "My Project"
}
```
#### Multiple Repositories
```json theme={null}
[
{
"uri": "file:///home/user/repos/frontend",
"name": "Frontend Repository"
},
{
"uri": "file:///home/user/repos/backend",
"name": "Backend Repository"
}
]
```
## Error Handling
Clients **SHOULD** return standard JSON-RPC errors for common failure cases:
* Client does not support roots: `-32601` (Method not found)
* Internal errors: `-32603`
Example error:
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32601,
"message": "Roots not supported",
"data": {
"reason": "Client does not have roots capability"
}
}
}
```
## Security Considerations
1. Clients **MUST**:
* Only expose roots with appropriate permissions
* Validate all root URIs to prevent path traversal
* Implement proper access controls
* Monitor root accessibility
2. Servers **SHOULD**:
* Handle cases where roots become unavailable
* Respect root boundaries during operations
* Validate all paths against provided roots
## Implementation Guidelines
1. Clients **SHOULD**:
* Prompt users for consent before exposing roots to servers
* Provide clear user interfaces for root management
* Validate root accessibility before exposing
* Monitor for root changes
2. Servers **SHOULD**:
* Check for roots capability before usage
* Handle root list changes gracefully
* Respect root boundaries in operations
* Cache root information appropriately
specification/2024-11-05/client/sampling New page · 222 lines, new page
# Sampling ## User Interaction Model ## Capabilities ## Protocol Messages ### Creating Messages ## Message Flow ## Data Types ### Messages #### Text Content #### Image Content ### Model Preferences #### Capability Priorities #### Model Hints ## Error Handling ## Security Considerations
A whole new page. There's nothing to diff it against, so here is what it says.
# Sampling
The Model Context Protocol (MCP) provides a standardized way for servers to request LLM
sampling ("completions" or "generations") from language models via clients. This flow
allows clients to maintain control over model access, selection, and permissions while
enabling servers to leverage AI capabilities—with no server API keys necessary.
Servers can request text or image-based interactions and optionally include context from
MCP servers in their prompts.
## User Interaction Model
Sampling in MCP allows servers to implement agentic behaviors, by enabling LLM calls to
occur *nested* inside other MCP server features.
Implementations are free to expose sampling through any interface pattern that suits
their needs—the protocol itself does not mandate any specific user interaction
model.
<Warning>
For trust & safety and security, there **SHOULD** always
be a human in the loop with the ability to deny sampling requests.
Applications **SHOULD**:
* Provide UI that makes it easy and intuitive to review sampling requests
* Allow users to view and edit prompts before sending
* Present generated responses for review before delivery
</Warning>
## Capabilities
Clients that support sampling **MUST** declare the `sampling` capability during
[initialization](/specification/2024-11-05/basic/lifecycle#initialization):
```json theme={null}
{
"capabilities": {
"sampling": {}
}
}
```
## Protocol Messages
### Creating Messages
To request a language model generation, servers send a `sampling/createMessage` request:
**Request:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"method": "sampling/createMessage",
"params": {
"messages": [
{
"role": "user",
"content": {
"type": "text",
"text": "What is the capital of France?"
}
}
],
"modelPreferences": {
"hints": [
{
"name": "claude-3-sonnet"
}
],
"intelligencePriority": 0.8,
"speedPriority": 0.5
},
"systemPrompt": "You are a helpful assistant.",
"maxTokens": 100
}
}
```
**Response:**
```json theme={null}
{
"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"
}
}
```
## Message Flow
```mermaid theme={null}
sequenceDiagram
participant Server
participant Client
participant User
participant LLM
Note over Server,Client: Server initiates sampling
Server->>Client: sampling/createMessage
Note over Client,User: Human-in-the-loop review
Client->>User: Present request for approval
User-->>Client: Review and approve/modify
Note over Client,LLM: Model interaction
Client->>LLM: Forward approved request
LLM-->>Client: Return generation
Note over Client,User: Response review
Client->>User: Present response for approval
User-->>Client: Review and approve/modify
Note over Server,Client: Complete request
Client-->>Server: Return approved response
```
## Data Types
### Messages
Sampling messages can contain:
#### Text Content
```json theme={null}
{
"type": "text",
"text": "The message content"
}
```
#### Image Content
```json theme={null}
{
"type": "image",
"data": "base64-encoded-image-data",
"mimeType": "image/jpeg"
}
```
### Model Preferences
Model selection in MCP requires careful abstraction since servers and clients may use
different AI providers with distinct model offerings. A server cannot simply request a
specific model by name since the client may not have access to that exact model or may
prefer to use a different provider's equivalent model.
To solve this, MCP implements a preference system that combines abstract capability
priorities with optional model hints:
#### Capability Priorities
Servers express their needs through three normalized priority values (0-1):
* `costPriority`: How important is minimizing costs? Higher values prefer cheaper models.
* `speedPriority`: How important is low latency? Higher values prefer faster models.
* `intelligencePriority`: How important are advanced capabilities? Higher values prefer
more capable models.
#### Model Hints
While priorities help select models based on characteristics, `hints` allow servers to
suggest specific models or model families:
* Hints are treated as substrings that can match model names flexibly
* Multiple hints are evaluated in order of preference
* Clients **MAY** map hints to equivalent models from different providers
* Hints are advisory—clients make final model selection
For example:
```json theme={null}
{
"hints": [
{ "name": "claude-3-sonnet" }, // Prefer Sonnet-class models
{ "name": "claude" } // Fall back to any Claude model
],
"costPriority": 0.3, // Cost is less important
"speedPriority": 0.8, // Speed is very important
"intelligencePriority": 0.5 // Moderate capability needs
}
```
The client processes these preferences to select an appropriate model from its available
options. For instance, if the client doesn't have access to Claude models but has Gemini,
it might map the sonnet hint to `gemini-1.5-pro` based on similar capabilities.
## Error Handling
Clients **SHOULD** return errors for common failure cases:
Example error:
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -1,
"message": "User rejected sampling request"
}
}
```
## Security Considerations
1. Clients **SHOULD** implement user approval controls
2. Both parties **SHOULD** validate message content
3. Clients **SHOULD** respect model preference hints
4. Clients **SHOULD** implement rate limiting
5. Both parties **MUST** handle sensitive data appropriately
specification/2024-11-05/index New page · 129 lines, new page
# Specification ## Overview ## Key Details ### Base Protocol ### Features ### Additional Utilities ## Security and Trust & Safety ### Key Principles ### Implementation Guidelines ## Learn More
A whole new page. There's nothing to diff it against, so here is what it says.
# Specification
[Model Context Protocol](https://modelcontextprotocol.io) (MCP) is an open protocol that
enables seamless integration between LLM applications and external data sources and
tools. Whether you're building an AI-powered IDE, enhancing a chat interface, or creating
custom AI workflows, MCP provides a standardized way to connect LLMs with the context
they need.
This specification defines the authoritative protocol requirements, based on the
TypeScript schema in
[schema.ts](https://github.com/modelcontextprotocol/specification/blob/main/schema/2024-11-05/schema.ts).
For implementation guides and examples, visit
[modelcontextprotocol.io](https://modelcontextprotocol.io).
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD
NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be
interpreted as described in [BCP 14](https://datatracker.ietf.org/doc/html/bcp14)
\[[RFC2119](https://datatracker.ietf.org/doc/html/rfc2119)]
\[[RFC8174](https://datatracker.ietf.org/doc/html/rfc8174)] when, and only when, they
appear in all capitals, as shown here.
## Overview
MCP provides a standardized way for applications to:
* Share contextual information with language models
* Expose tools and capabilities to AI systems
* Build composable integrations and workflows
The protocol uses [JSON-RPC](https://www.jsonrpc.org/) 2.0 messages to establish
communication between:
* **Hosts**: LLM applications that initiate connections
* **Clients**: Connectors within the host application
* **Servers**: Services that provide context and capabilities
MCP takes some inspiration from the
[Language Server Protocol](https://microsoft.github.io/language-server-protocol/), which
standardizes how to add support for programming languages across a whole ecosystem of
development tools. In a similar way, MCP standardizes how to integrate additional context
and tools into the ecosystem of AI applications.
## Key Details
### Base Protocol
* [JSON-RPC](https://www.jsonrpc.org/) message format
* Stateful connections
* Server and client capability negotiation
### Features
Servers offer any of the following features to clients:
* **Resources**: Context and data, for the user or the AI model to use
* **Prompts**: Templated messages and workflows for users
* **Tools**: Functions for the AI model to execute
Clients may offer the following feature to servers:
* **Sampling**: Server-initiated agentic behaviors and recursive LLM interactions
### Additional Utilities
* Configuration
* Progress tracking
* Cancellation
* Error reporting
* Logging
## Security and Trust & Safety
The Model Context Protocol enables powerful capabilities through arbitrary data access
and code execution paths. With this power comes important security and trust
considerations that all implementors must carefully address.
### Key Principles
1. **User Consent and Control**
* Users must explicitly consent to and understand all data access and operations
* Users must retain control over what data is shared and what actions are taken
* Implementors should provide clear UIs for reviewing and authorizing activities
2. **Data Privacy**
* Hosts must obtain explicit user consent before exposing user data to servers
* Hosts must not transmit resource data elsewhere without user consent
* User data should be protected with appropriate access controls
3. **Tool Safety**
* Tools represent arbitrary code execution and must be treated with appropriate
caution
* Hosts must obtain explicit user consent before invoking any tool
* Users should understand what each tool does before authorizing its use
4. **LLM Sampling Controls**
* Users must explicitly approve any LLM sampling requests
* Users should control:
* Whether sampling occurs at all
* The actual prompt that will be sent
* What results the server can see
* The protocol intentionally limits server visibility into prompts
### Implementation Guidelines
While MCP itself cannot enforce these security principles at the protocol level,
implementors **SHOULD**:
1. Build robust consent and authorization flows into their applications
2. Provide clear documentation of security implications
3. Implement appropriate access controls and data protections
4. Follow security best practices in their integrations
5. Consider privacy implications in their feature designs
## Learn More
Explore the detailed specification for each protocol component:
<CardGroup cols={5}>
<Card title="Architecture" icon="sitemap" href="/specification/2024-11-05/architecture" />
<Card title="Base Protocol" icon="code" href="/specification/2024-11-05/basic" />
<Card title="Server Features" icon="server" href="/specification/2024-11-05/server" />
<Card title="Client Features" icon="user" href="/specification/2024-11-05/client" />
<Card title="Contributing" icon="pencil" href="/community/contributing" />
</CardGroup>
specification/2024-11-05/server/index New page · 29 lines, new page
# Overview
A whole new page. There's nothing to diff it against, so here is what it says.
# Overview
Servers provide the fundamental building blocks for adding context to language models via
MCP. These primitives enable rich interactions between clients, servers, and language
models:
* **Prompts**: Pre-defined templates or instructions that guide language model
interactions
* **Resources**: Structured data or content that provides additional context to the model
* **Tools**: Executable functions that allow models to perform actions or retrieve
information
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 |
Explore these key primitives in more detail below:
<CardGroup cols={3}>
<Card title="Prompts" icon="message" href="/specification/2024-11-05/server/prompts" />
<Card title="Resources" icon="file-lines" href="/specification/2024-11-05/server/resources" />
<Card title="Tools" icon="wrench" href="/specification/2024-11-05/server/tools" />
</CardGroup>
specification/2024-11-05/server/prompts New page · 252 lines, new page
# Prompts ## User Interaction Model ## Capabilities ## Protocol Messages ### Listing Prompts ### Getting a Prompt ### List Changed Notification ## Message Flow ## Data Types ### Prompt ### PromptMessage #### Text Content #### Image Content #### Embedded Resources ## Error Handling ## Implementation Considerations ## Security
A whole new page. There's nothing to diff it against, so here is what it says.
# Prompts
The Model Context Protocol (MCP) provides a standardized way for servers to expose prompt
templates to clients. Prompts allow servers to provide structured messages and
instructions for interacting with language models. Clients can discover available
prompts, retrieve their contents, and provide arguments to customize them.
## User Interaction Model
Prompts are designed to be **user-controlled**, meaning they are exposed from servers to
clients with the intention of the user being able to explicitly select them for use.
Typically, prompts would be triggered through user-initiated commands in the user
interface, which allows users to naturally discover and invoke available prompts.
For example, as slash commands:
<img src="https://mintcdn.com/mcp/4ZXF1PrDkEaJvXpn/specification/2024-11-05/server/slash-command.png?fit=max&auto=format&n=4ZXF1PrDkEaJvXpn&q=85&s=ae78d658be66d75446ffd37a36e944c9" alt="Example of prompt exposed as slash command" width="293" height="106" data-path="specification/2024-11-05/server/slash-command.png" />
However, implementors are free to expose prompts through any interface pattern that suits
their needs—the protocol itself does not mandate any specific user interaction
model.
## Capabilities
Servers that support prompts **MUST** declare the `prompts` capability during
[initialization](/specification/2024-11-05/basic/lifecycle#initialization):
```json theme={null}
{
"capabilities": {
"prompts": {
"listChanged": true
}
}
}
```
`listChanged` indicates whether the server will emit notifications when the list of
available prompts changes.
## Protocol Messages
### Listing Prompts
To retrieve available prompts, clients send a `prompts/list` request. This operation
supports
[pagination](/specification/2024-11-05/server/utilities/pagination).
**Request:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"method": "prompts/list",
"params": {
"cursor": "optional-cursor-value"
}
}
```
**Response:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"prompts": [
{
"name": "code_review",
"description": "Asks the LLM to analyze code quality and suggest improvements",
"arguments": [
{
"name": "code",
"description": "The code to review",
"required": true
}
]
}
],
"nextCursor": "next-page-cursor"
}
}
```
### Getting a Prompt
To retrieve a specific prompt, clients send a `prompts/get` request. Arguments may be
auto-completed through [the completion API](/specification/2024-11-05/server/utilities/completion).
**Request:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 2,
"method": "prompts/get",
"params": {
"name": "code_review",
"arguments": {
"code": "def hello():\n print('world')"
}
}
}
```
**Response:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"description": "Code review prompt",
"messages": [
{
"role": "user",
"content": {
"type": "text",
"text": "Please review this Python code:\ndef hello():\n print('world')"
}
}
]
}
}
```
### List Changed Notification
When the list of available prompts changes, servers that declared the `listChanged`
capability **SHOULD** send a notification:
```json theme={null}
{
"jsonrpc": "2.0",
"method": "notifications/prompts/list_changed"
}
```
## Message Flow
```mermaid theme={null}
sequenceDiagram
participant Client
participant Server
Note over Client,Server: Discovery
Client->>Server: prompts/list
Server-->>Client: List of prompts
Note over Client,Server: Usage
Client->>Server: prompts/get
Server-->>Client: Prompt content
opt listChanged
Note over Client,Server: Changes
Server--)Client: prompts/list_changed
Client->>Server: prompts/list
Server-->>Client: Updated prompts
end
```
## Data Types
### Prompt
A prompt definition includes:
* `name`: Unique identifier for the prompt
* `description`: Optional human-readable description
* `arguments`: Optional list of arguments for customization
### PromptMessage
Messages in a prompt can contain:
* `role`: Either "user" or "assistant" to indicate the speaker
* `content`: One of the following content types:
#### Text Content
Text content represents plain text messages:
```json theme={null}
{
"type": "text",
"text": "The text content of the message"
}
```
This is the most common content type used for natural language interactions.
#### Image Content
Image content allows including visual information in messages:
```json theme={null}
{
"type": "image",
"data": "base64-encoded-image-data",
"mimeType": "image/png"
}
```
The image data **MUST** be base64-encoded and include a valid MIME type. This enables
multi-modal interactions where visual context is important.
#### Embedded Resources
Embedded resources allow referencing server-side resources directly in messages:
```json theme={null}
{
"type": "resource",
"resource": {
"uri": "resource://example",
"mimeType": "text/plain",
"text": "Resource content"
}
}
```
Resources can contain either text or binary (blob) data and **MUST** include:
* A valid resource URI
* The appropriate MIME type
* Either text content or base64-encoded blob data
Embedded resources enable prompts to seamlessly incorporate server-managed content like
documentation, code samples, or other reference materials directly into the conversation
flow.
## Error Handling
Servers **SHOULD** return standard JSON-RPC errors for common failure cases:
* Invalid prompt name: `-32602` (Invalid params)
* Missing required arguments: `-32602` (Invalid params)
* Internal errors: `-32603` (Internal error)
## Implementation Considerations
1. Servers **SHOULD** validate prompt arguments before processing
2. Clients **SHOULD** handle pagination for large prompt lists
3. Both parties **SHOULD** respect capability negotiation
## Security
Implementations **MUST** carefully validate all prompt inputs and outputs to prevent
injection attacks or unauthorized access to resources.
specification/2024-11-05/server/resources New page · 357 lines, new page
# Resources ## User Interaction Model ## Capabilities ## Protocol Messages ### Listing Resources ### Reading Resources ### Resource Templates ### List Changed Notification ### Subscriptions ## Message Flow ## Data Types ### Resource ### Resource Contents #### Text Content #### Binary Content ## Common URI Schemes ### https\:// ### file:// ### git:// ## Error Handling ## Security Considerations
A whole new page. There's nothing to diff it against, so here is what it says.
# Resources
The Model Context Protocol (MCP) provides a standardized way for servers to expose
resources to clients. Resources allow servers to share data that provides context to
language models, such as files, database schemas, or application-specific information.
Each resource is uniquely identified by a
[URI](https://datatracker.ietf.org/doc/html/rfc3986).
## User Interaction Model
Resources in MCP are designed to be **application-driven**, with host applications
determining how to incorporate context based on their needs.
For example, applications could:
* Expose resources through UI elements for explicit selection, in a tree or list view
* Allow the user to search through and filter available resources
* Implement automatic context inclusion, based on heuristics or the AI model's selection
<img src="https://mintcdn.com/mcp/4ZXF1PrDkEaJvXpn/specification/2024-11-05/server/resource-picker.png?fit=max&auto=format&n=4ZXF1PrDkEaJvXpn&q=85&s=c393fd9aa41eca521cb2f830d839612f" alt="Example of resource context picker" width="174" height="181" data-path="specification/2024-11-05/server/resource-picker.png" />
However, implementations are free to expose resources through any interface pattern that
suits their needs—the protocol itself does not mandate any specific user
interaction model.
## Capabilities
Servers that support resources **MUST** declare the `resources` capability:
```json theme={null}
{
"capabilities": {
"resources": {
"subscribe": true,
"listChanged": true
}
}
}
```
The capability supports two optional features:
* `subscribe`: whether the client can subscribe to be notified of changes to individual
resources.
* `listChanged`: whether the server will emit notifications when the list of available
resources changes.
Both `subscribe` and `listChanged` are optional—servers can support neither,
either, or both:
```json theme={null}
{
"capabilities": {
"resources": {} // Neither feature supported
}
}
```
```json theme={null}
{
"capabilities": {
"resources": {
"subscribe": true // Only subscriptions supported
}
}
}
```
```json theme={null}
{
"capabilities": {
"resources": {
"listChanged": true // Only list change notifications supported
}
}
}
```
## Protocol Messages
### Listing Resources
To discover available resources, clients send a `resources/list` request. This operation
supports
[pagination](/specification/2024-11-05/server/utilities/pagination).
**Request:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"method": "resources/list",
"params": {
"cursor": "optional-cursor-value"
}
}
```
**Response:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"resources": [
{
"uri": "file:///project/src/main.rs",
"name": "main.rs",
"description": "Primary application entry point",
"mimeType": "text/x-rust"
}
],
"nextCursor": "next-page-cursor"
}
}
```
### Reading Resources
To retrieve resource contents, clients send a `resources/read` request:
**Request:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 2,
"method": "resources/read",
"params": {
"uri": "file:///project/src/main.rs"
}
}
```
**Response:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"contents": [
{
"uri": "file:///project/src/main.rs",
"mimeType": "text/x-rust",
"text": "fn main() {\n println!(\"Hello world!\");\n}"
}
]
}
}
```
### Resource Templates
Resource templates allow servers to expose parameterized resources using
[URI templates](https://datatracker.ietf.org/doc/html/rfc6570). Arguments may be
auto-completed through [the completion API](/specification/2024-11-05/server/utilities/completion).
This operation supports
[pagination](/specification/2024-11-05/server/utilities/pagination).
**Request:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 3,
"method": "resources/templates/list",
"params": {
"cursor": "optional-cursor-value"
}
}
```
**Response:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 3,
"result": {
"resourceTemplates": [
{
"uriTemplate": "file:///{path}",
"name": "Project Files",
"description": "Access files in the project directory",
"mimeType": "application/octet-stream"
}
],
"nextCursor": "next-page-cursor"
}
}
```
### List Changed Notification
When the list of available resources changes, servers that declared the `listChanged`
capability **SHOULD** send a notification:
```json theme={null}
{
"jsonrpc": "2.0",
"method": "notifications/resources/list_changed"
}
```
### Subscriptions
The protocol supports optional subscriptions to resource changes. Clients can subscribe
to specific resources and receive notifications when they change:
**Subscribe Request:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 4,
"method": "resources/subscribe",
"params": {
"uri": "file:///project/src/main.rs"
}
}
```
**Update Notification:**
```json theme={null}
{
"jsonrpc": "2.0",
"method": "notifications/resources/updated",
"params": {
"uri": "file:///project/src/main.rs"
}
}
```
## Message Flow
```mermaid theme={null}
sequenceDiagram
participant Client
participant Server
Note over Client,Server: Resource Discovery
Client->>Server: resources/list
Server-->>Client: List of resources
Note over Client,Server: Resource Access
Client->>Server: resources/read
Server-->>Client: Resource contents
Note over Client,Server: Subscriptions
Client->>Server: resources/subscribe
Server-->>Client: Subscription confirmed
Note over Client,Server: Updates
Server--)Client: notifications/resources/updated
Client->>Server: resources/read
Server-->>Client: Updated contents
```
## Data Types
### Resource
A resource definition includes:
* `uri`: Unique identifier for the resource
* `name`: Human-readable name
* `description`: Optional description
* `mimeType`: Optional MIME type
### Resource Contents
Resources can contain either text or binary data:
#### Text Content
```json theme={null}
{
"uri": "file:///example.txt",
"mimeType": "text/plain",
"text": "Resource content"
}
```
#### Binary Content
```json theme={null}
{
"uri": "file:///example.png",
"mimeType": "image/png",
"blob": "base64-encoded-data"
}
```
## Common URI Schemes
The protocol defines several standard URI schemes. This list not
Cut at 300 lines. The page has the rest.
specification/2024-11-05/server/tools New page · 280 lines, new page
# Tools ## User Interaction Model ## Capabilities ## Protocol Messages ### Listing Tools ### Calling Tools ### List Changed Notification ## Message Flow ## Data Types ### Tool ### Tool Result #### Text Content #### Image Content #### Embedded Resources ## Error Handling ## Security Considerations
A whole new page. There's nothing to diff it against, so here is what it says.
# Tools
The Model Context Protocol (MCP) allows servers to expose tools that can be invoked by
language models. Tools enable models to interact with external systems, such as querying
databases, calling APIs, or performing computations. Each tool is uniquely identified by
a name and includes metadata describing its schema.
## User Interaction Model
Tools in MCP are designed to be **model-controlled**, meaning that the language model can
discover and invoke tools automatically based on its contextual understanding and the
user's prompts.
However, implementations are free to expose tools through any interface pattern that
suits their needs—the protocol itself does not mandate any specific user
interaction model.
<Warning>
For trust & safety and security, there **SHOULD** always
be a human in the loop with the ability to deny tool invocations.
Applications **SHOULD**:
* Provide UI that makes clear which tools are being exposed to the AI model
* Insert clear visual indicators when tools are invoked
* Present confirmation prompts to the user for operations, to ensure a human is in the
loop
</Warning>
## Capabilities
Servers that support tools **MUST** declare the `tools` capability:
```json theme={null}
{
"capabilities": {
"tools": {
"listChanged": true
}
}
}
```
`listChanged` indicates whether the server will emit notifications when the list of
available tools changes.
## Protocol Messages
### Listing Tools
To discover available tools, clients send a `tools/list` request. This operation supports
[pagination](/specification/2024-11-05/server/utilities/pagination).
**Request:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list",
"params": {
"cursor": "optional-cursor-value"
}
}
```
**Response:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"tools": [
{
"name": "get_weather",
"description": "Get current weather information for a location",
"inputSchema": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "City name or zip code"
}
},
"required": ["location"]
}
}
],
"nextCursor": "next-page-cursor"
}
}
```
### Calling Tools
To invoke a tool, clients send a `tools/call` request:
**Request:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "get_weather",
"arguments": {
"location": "New York"
}
}
}
```
**Response:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"content": [
{
"type": "text",
"text": "Current weather in New York:\nTemperature: 72°F\nConditions: Partly cloudy"
}
],
"isError": false
}
}
```
### List Changed Notification
When the list of available tools changes, servers that declared the `listChanged`
capability **SHOULD** send a notification:
```json theme={null}
{
"jsonrpc": "2.0",
"method": "notifications/tools/list_changed"
}
```
## Message Flow
```mermaid theme={null}
sequenceDiagram
participant LLM
participant Client
participant Server
Note over Client,Server: Discovery
Client->>Server: tools/list
Server-->>Client: List of tools
Note over Client,LLM: Tool Selection
LLM->>Client: Select tool to use
Note over Client,Server: Invocation
Client->>Server: tools/call
Server-->>Client: Tool result
Client->>LLM: Process result
Note over Client,Server: Updates
Server--)Client: tools/list_changed
Client->>Server: tools/list
Server-->>Client: Updated tools
```
## Data Types
### Tool
A tool definition includes:
* `name`: Unique identifier for the tool
* `description`: Human-readable description of functionality
* `inputSchema`: JSON Schema defining expected parameters
### Tool Result
Tool results can contain multiple content items of different types:
#### Text Content
```json theme={null}
{
"type": "text",
"text": "Tool result text"
}
```
#### Image Content
```json theme={null}
{
"type": "image",
"data": "base64-encoded-data",
"mimeType": "image/png"
}
```
#### Embedded Resources
[Resources](/specification/2024-11-05/server/resources) **MAY** be
embedded, to provide additional context or data, behind a URI that can be subscribed to
or fetched again by the client later:
```json theme={null}
{
"type": "resource",
"resource": {
"uri": "resource://example",
"mimeType": "text/plain",
"text": "Resource content"
}
}
```
## Error Handling
Tools use two error reporting mechanisms:
1. **Protocol Errors**: Standard JSON-RPC errors for issues like:
* Unknown tools
* Invalid arguments
* Server errors
2. **Tool Execution Errors**: Reported in tool results with `isError: true`:
* API failures
* Invalid input data
* Business logic errors
Example protocol error:
```json theme={null}
{
"jsonrpc": "2.0",
"id": 3,
"error": {
"code": -32602,
"message": "Unknown tool: invalid_tool_name"
}
}
```
Example tool execution error:
```json theme={null}
{
"jsonrpc": "2.0",
"id": 4,
"result": {
"content": [
{
"type": "text",
"text": "Failed to fetch weather data: API rate limit exceeded"
}
],
"isError": true
}
}
```
## Security Considerations
1. Servers **MUST**:
* Validate all tool inputs
* Implement proper access controls
* Rate limit tool invocations
* Sanitize tool outputs
2. Clients **SHOULD**:
* Prompt for user confirmation on sensitive operations
* Show tool inputs to the user before calling the server, to avoid malicious or
accidental data exfiltration
* Validate tool results before passing to LLM
* Implement timeouts for tool calls
* Log tool usage for audit purposes
specification/2024-11-05/server/utilities/completion New page · 132 lines, new page
# Completion ## User Interaction Model ## Protocol Messages ### Requesting Completions ### Reference Types ### Completion Results ## Message Flow ## Data Types ### CompleteRequest ### CompleteResult ## Implementation Considerations ## Security
A whole new page. There's nothing to diff it against, so here is what it says.
# Completion
The Model Context Protocol (MCP) provides a standardized way for servers to offer
argument autocompletion suggestions for prompts and resource URIs. This enables rich,
IDE-like experiences where users receive contextual suggestions while entering argument
values.
## User Interaction Model
Completion in MCP is designed to support interactive user experiences similar to IDE code
completion.
For example, applications may show completion suggestions in a dropdown or popup menu as
users type, with the ability to filter and select from available options.
However, implementations are free to expose completion through any interface pattern that
suits their needs—the protocol itself does not mandate any specific user
interaction model.
## Protocol Messages
### Requesting Completions
To get completion suggestions, clients send a `completion/complete` request specifying
what is being completed through a reference type:
**Request:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"method": "completion/complete",
"params": {
"ref": {
"type": "ref/prompt",
"name": "code_review"
},
"argument": {
"name": "language",
"value": "py"
}
}
}
```
**Response:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"completion": {
"values": ["python", "pytorch", "pyside"],
"total": 10,
"hasMore": true
}
}
}
```
### Reference Types
The protocol supports two types of completion references:
| Type | Description | Example |
| -------------- | --------------------------- | --------------------------------------------------- |
| `ref/prompt` | References a prompt by name | `{"type": "ref/prompt", "name": "code_review"}` |
| `ref/resource` | References a resource URI | `{"type": "ref/resource", "uri": "file:///{path}"}` |
### Completion Results
Servers return an array of completion values ranked by relevance, with:
* Maximum 100 items per response
* Optional total number of available matches
* Boolean indicating if additional results exist
## Message Flow
```mermaid theme={null}
sequenceDiagram
participant Client
participant Server
Note over Client: User types argument
Client->>Server: completion/complete
Server-->>Client: Completion suggestions
Note over Client: User continues typing
Client->>Server: completion/complete
Server-->>Client: Refined suggestions
```
## Data Types
### CompleteRequest
* `ref`: A `PromptReference` or `ResourceReference`
* `argument`: Object containing:
* `name`: Argument name
* `value`: Current value
### CompleteResult
* `completion`: Object containing:
* `values`: Array of suggestions (max 100)
* `total`: Optional total matches
* `hasMore`: Additional results flag
## Implementation Considerations
1. Servers **SHOULD**:
* Return suggestions sorted by relevance
* Implement fuzzy matching where appropriate
* Rate limit completion requests
* Validate all inputs
2. Clients **SHOULD**:
* Debounce rapid completion requests
* Cache completion results where appropriate
* Handle missing or partial results gracefully
## Security
Implementations **MUST**:
* Validate all completion inputs
* Implement appropriate rate limiting
* Control access to sensitive suggestions
* Prevent completion-based information disclosure
specification/2024-11-05/server/utilities/logging New page · 136 lines, new page
# Logging ## User Interaction Model ## Capabilities ## Log Levels ## Protocol Messages ### Setting Log Level ### Log Message Notifications ## Message Flow ## Error Handling ## Implementation Considerations ## Security
A whole new page. There's nothing to diff it against, so here is what it says.
# Logging
The Model Context Protocol (MCP) provides a standardized way for servers to send
structured log messages to clients. Clients can control logging verbosity by setting
minimum log levels, with servers sending notifications containing severity levels,
optional logger names, and arbitrary JSON-serializable data.
## User Interaction Model
Implementations are free to expose logging through any interface pattern that suits their
needs—the protocol itself does not mandate any specific user interaction model.
## Capabilities
Servers that emit log message notifications **MUST** declare the `logging` capability:
```json theme={null}
{
"capabilities": {
"logging": {}
}
}
```
## Log Levels
The protocol follows the standard syslog severity levels specified in
[RFC 5424](https://datatracker.ietf.org/doc/html/rfc5424#section-6.2.1):
| Level | Description | Example Use Case |
| --------- | -------------------------------- | -------------------------- |
| debug | Detailed debugging information | Function entry/exit points |
| info | General informational messages | Operation progress updates |
| notice | Normal but significant events | Configuration changes |
| warning | Warning conditions | Deprecated feature usage |
| error | Error conditions | Operation failures |
| critical | Critical conditions | System component failures |
| alert | Action must be taken immediately | Data corruption detected |
| emergency | System is unusable | Complete system failure |
## Protocol Messages
### Setting Log Level
To configure the minimum log level, clients **MAY** send a `logging/setLevel` request:
**Request:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"method": "logging/setLevel",
"params": {
"level": "info"
}
}
```
### Log Message Notifications
Servers send log messages using `notifications/message` notifications:
```json theme={null}
{
"jsonrpc": "2.0",
"method": "notifications/message",
"params": {
"level": "error",
"logger": "database",
"data": {
"error": "Connection failed",
"details": {
"host": "localhost",
"port": 5432
}
}
}
}
```
## Message Flow
```mermaid theme={null}
sequenceDiagram
participant Client
participant Server
Note over Client,Server: Configure Logging
Client->>Server: logging/setLevel (info)
Server-->>Client: Empty Result
Note over Client,Server: Server Activity
Server--)Client: notifications/message (info)
Server--)Client: notifications/message (warning)
Server--)Client: notifications/message (error)
Note over Client,Server: Level Change
Client->>Server: logging/setLevel (error)
Server-->>Client: Empty Result
Note over Server: Only sends error level<br/>and above
```
## Error Handling
Servers **SHOULD** return standard JSON-RPC errors for common failure cases:
* Invalid log level: `-32602` (Invalid params)
* Configuration errors: `-32603` (Internal error)
## Implementation Considerations
1. Servers **SHOULD**:
* Rate limit log messages
* Include relevant context in data field
* Use consistent logger names
* Remove sensitive information
2. Clients **MAY**:
* Present log messages in the UI
* Implement log filtering/search
* Display severity visually
* Persist log messages
## Security
1. Log messages **MUST NOT** contain:
* Credentials or secrets
* Personal identifying information
* Internal system details that could aid attacks
2. Implementations **SHOULD**:
* Rate limit messages
* Validate all data fields
* Control log access
* Monitor for sensitive content
specification/2024-11-05/server/utilities/pagination New page · 92 lines, new page
# Pagination ## Pagination Model ## Response Format ## Request Format ## Pagination Flow ## Operations Supporting Pagination ## Implementation Guidelines ## Error Handling
A whole new page. There's nothing to diff it against, so here is what it says.
# Pagination
The Model Context Protocol (MCP) supports paginating list operations that may return
large result sets. Pagination allows servers to yield results in smaller chunks rather
than all at once.
Pagination is especially important when connecting to external services over the
internet, but also useful for local integrations to avoid performance issues with large
data sets.
## Pagination Model
Pagination in MCP uses an opaque cursor-based approach, instead of numbered pages.
* The **cursor** is an opaque string token, representing a position in the result set
* **Page size** is determined by the server, and clients **MUST NOT** assume a fixed page
size
## Response Format
Pagination starts when the server sends a **response** that includes:
* The current page of results
* An optional `nextCursor` field if more results exist
```json theme={null}
{
"jsonrpc": "2.0",
"id": "123",
"result": {
"resources": [...],
"nextCursor": "eyJwYWdlIjogM30="
}
}
```
## Request Format
After receiving a cursor, the client can *continue* paginating by issuing a request
including that cursor:
```json theme={null}
{
"jsonrpc": "2.0",
"method": "resources/list",
"params": {
"cursor": "eyJwYWdlIjogMn0="
}
}
```
## Pagination Flow
```mermaid theme={null}
sequenceDiagram
participant Client
participant Server
Client->>Server: List Request (no cursor)
loop Pagination Loop
Server-->>Client: Page of results + nextCursor
Client->>Server: List Request (with cursor)
end
```
## Operations Supporting Pagination
The following MCP operations support pagination:
* `resources/list` - List available resources
* `resources/templates/list` - List resource templates
* `prompts/list` - List available prompts
* `tools/list` - List available tools
## Implementation Guidelines
1. Servers **SHOULD**:
* Provide stable cursors
* Handle invalid cursors gracefully
2. Clients **SHOULD**:
* Treat a missing `nextCursor` as the end of results
* Support both paginated and non-paginated flows
3. Clients **MUST** treat cursors as opaque tokens:
* Don't make assumptions about cursor format
* Don't attempt to parse or modify cursors
* Don't persist cursors across sessions
## Error Handling
Invalid cursors **SHOULD** result in an error with code -32602 (Invalid params).
specification/2025-03-26/architecture/index New page · 170 lines, new page
# Architecture ## Core Components ### Host ### Clients ### Servers ## Design Principles ## Capability Negotiation
A whole new page. There's nothing to diff it against, so here is what it says.
# Architecture
The Model Context Protocol (MCP) follows a client-host-server architecture where each
host can run multiple client instances. This architecture enables users to integrate AI
capabilities across applications while maintaining clear security boundaries and
isolating concerns. Built on JSON-RPC, MCP provides a stateful session protocol focused
on context exchange and sampling coordination between clients and servers.
## Core Components
```mermaid theme={null}
graph LR
subgraph "Application Host Process"
H[Host]
C1[Client 1]
C2[Client 2]
C3[Client 3]
H --> C1
H --> C2
H --> C3
end
subgraph "Local machine"
S1[Server 1<br>Files & Git]
S2[Server 2<br>Database]
R1[("Local<br>Resource A")]
R2[("Local<br>Resource B")]
C1 --> S1
C2 --> S2
S1 <--> R1
S2 <--> R2
end
subgraph "Internet"
S3[Server 3<br>External APIs]
R3[("Remote<br>Resource C")]
C3 --> S3
S3 <--> R3
end
```
### Host
The host process acts as the container and coordinator:
* Creates and manages multiple client instances
* Controls client connection permissions and lifecycle
* Enforces security policies and consent requirements
* Handles user authorization decisions
* Coordinates AI/LLM integration and sampling
* Manages context aggregation across clients
### Clients
Each client is created by the host and maintains an isolated server connection:
* Establishes one stateful session per server
* Handles protocol negotiation and capability exchange
* Routes protocol messages bidirectionally
* Manages subscriptions and notifications
* Maintains security boundaries between servers
A host application creates and manages multiple clients, with each client having a 1:1
relationship with a particular server.
### Servers
Servers provide specialized context and capabilities:
* Expose resources, tools and prompts via MCP primitives
* Operate independently with focused responsibilities
* Request sampling through client interfaces
* Must respect security constraints
* Can be local processes or remote services
## Design Principles
MCP is built on several key design principles that inform its architecture and
implementation:
1. **Servers should be extremely easy to build**
* Host applications handle complex orchestration responsibilities
* Servers focus on specific, well-defined capabilities
* Simple interfaces minimize implementation overhead
* Clear separation enables maintainable code
2. **Servers should be highly composable**
* Each server provides focused functionality in isolation
* Multiple servers can be combined seamlessly
* Shared protocol enables interoperability
* Modular design supports extensibility
3. **Servers should not be able to read the whole conversation, nor "see into" other
servers**
* Servers receive only necessary contextual information
* Full conversation history stays with the host
* Each server connection maintains isolation
* Cross-server interactions are controlled by the host
* Host process enforces security boundaries
4. **Features can be added to servers and clients progressively**
* Core protocol provides minimal required functionality
* Additional capabilities can be negotiated as needed
* Servers and clients evolve independently
* Protocol designed for future extensibility
* Backwards compatibility is maintained
## Capability Negotiation
The Model Context Protocol uses a capability-based negotiation system where clients and
servers explicitly declare their supported features during initialization. Capabilities
determine which protocol features and primitives are available during a session.
* Servers declare capabilities like resource subscriptions, tool support, and prompt
templates
* Clients declare capabilities like sampling support and notification handling
* Both parties must respect declared capabilities throughout the session
* Additional capabilities can be negotiated through extensions to the protocol
```mermaid theme={null}
sequenceDiagram
participant Host
participant Client
participant Server
Host->>+Client: Initialize client
Client->>+Server: Initialize session with capabilities
Server-->>Client: Respond with supported capabilities
Note over Host,Server: Active Session with Negotiated Features
loop Client Requests
Host->>Client: User- or model-initiated action
Client->>Server: Request (tools/resources)
Server-->>Client: Response
Client-->>Host: Update UI or respond to model
end
loop Server Requests
Server->>Client: Request (sampling)
Client->>Host: Forward to AI
Host-->>Client: AI response
Client-->>Server: Response
end
loop Notifications
Server--)Client: Resource updates
Client--)Server: Status changes
end
Host->>Client: Terminate
Client->>-Server: End session
deactivate Server
```
Each capability unlocks specific protocol features for use during the session. For
example:
* Implemented [server features](/specification/2025-03-26/server) must be advertised in the
server's capabilities
* Emitting resource subscription notifications requires the server to declare
subscription support
* Tool invocation requires the server to declare tool capabilities
* [Sampling](/specification/2025-03-26/client/sampling) requires the client to declare support in its
capabilities
This capability negotiation ensures clients and servers have a clear understanding of
supported functionality while maintaining protocol extensibility.
specification/2025-03-26/basic/authorization New page · 404 lines, new page
# Authorization ## Introduction ### Purpose and Scope ### Protocol Requirements ### Standards Compliance ## Authorization Flow ### Overview ### OAuth Grant Types ### Example: authorization code grant ### Server Metadata Discovery #### Server Metadata Discovery Headers #### Authorization Base URL #### Fallbacks for Servers without Metadata Discovery ### Dynamic Client Registration ### Authorization Flow Steps #### Decision Flow Overview ### Access Token Usage #### Token Requirements #### Token Handling ### Security Considerations ### Error Handling ### Implementation Requirements ### Third-Party Authorization Flow #### Overview #### Flow Description #### Session Binding Requirements #### Security Considerations ## Best Practices #### Local clients as Public OAuth 2.1 Clients #### Authorization Metadata Discovery #### Dynamic Client Registration
A whole new page. There's nothing to diff it against, so here is what it says.
# Authorization
## Introduction
### Purpose and Scope
The Model Context Protocol provides authorization capabilities at the transport level,
enabling MCP clients to make requests to restricted MCP servers on behalf of resource
owners. This specification defines the authorization flow for HTTP-based transports.
### Protocol Requirements
Authorization is **OPTIONAL** for MCP implementations. When supported:
* Implementations using an HTTP-based transport **SHOULD** conform to this specification.
* Implementations using an STDIO transport **SHOULD NOT** follow this specification, and
instead retrieve credentials from the environment.
* Implementations using alternative transports **MUST** follow established security best
practices for their protocol.
### Standards Compliance
This authorization mechanism is based on established specifications listed below, but
implements a selected subset of their features to ensure security and interoperability
while maintaining simplicity:
* [OAuth 2.1 IETF DRAFT](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-12)
* OAuth 2.0 Authorization Server Metadata
([RFC8414](https://datatracker.ietf.org/doc/html/rfc8414))
* OAuth 2.0 Dynamic Client Registration Protocol
([RFC7591](https://datatracker.ietf.org/doc/html/rfc7591))
## Authorization Flow
### Overview
1. MCP auth implementations **MUST** implement OAuth 2.1 with appropriate security
measures for both confidential and public clients.
2. MCP auth implementations **SHOULD** support the OAuth 2.0 Dynamic Client Registration
Protocol ([RFC7591](https://datatracker.ietf.org/doc/html/rfc7591)).
3. MCP servers **SHOULD** and MCP clients **MUST** implement OAuth 2.0 Authorization
Server Metadata ([RFC8414](https://datatracker.ietf.org/doc/html/rfc8414)). Servers
that do not support Authorization Server Metadata **MUST** follow the default URI
schema.
### OAuth Grant Types
OAuth specifies different flows or grant types, which are different ways of obtaining an
access token. Each of these targets different use cases and scenarios.
MCP servers **SHOULD** support the OAuth grant types that best align with the intended
audience. For instance:
1. Authorization Code: useful when the client is acting on behalf of a (human) end user.
* For instance, an agent calls an MCP tool implemented by a SaaS system.
2. Client Credentials: the client is another application (not a human)
* For instance, an agent calls a secure MCP tool to check inventory at a specific
store. No need to impersonate the end user.
### Example: authorization code grant
This demonstrates the OAuth 2.1 flow for the authorization code grant type, used for user
auth.
**NOTE**: The following example assumes the MCP server is also functioning as the
authorization server. However, the authorization server may be deployed as its own
distinct service.
A human user completes the OAuth flow through a web browser, obtaining an access token
that identifies them personally and allows the client to act on their behalf.
When authorization is required and not yet proven by the client, servers **MUST** respond
with *HTTP 401 Unauthorized*.
Clients initiate the
[OAuth 2.1 IETF DRAFT](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-12#name-authorization-code-grant)
authorization flow after receiving the *HTTP 401 Unauthorized*.
The following demonstrates the basic OAuth 2.1 for public clients using PKCE.
```mermaid theme={null}
sequenceDiagram
participant B as User-Agent (Browser)
participant C as Client
participant M as MCP Server
C->>M: MCP Request
M->>C: HTTP 401 Unauthorized
Note over C: Generate code_verifier and code_challenge
C->>B: Open browser with authorization URL + code_challenge
B->>M: GET /authorize
Note over M: User logs in and authorizes
M->>B: Redirect to callback URL with auth code
B->>C: Callback with authorization code
C->>M: Token Request with code + code_verifier
M->>C: Access Token (+ Refresh Token)
C->>M: MCP Request with Access Token
Note over C,M: Begin standard MCP message exchange
```
### Server Metadata Discovery
For server capability discovery:
* MCP clients *MUST* follow the OAuth 2.0 Authorization Server Metadata protocol defined
in [RFC8414](https://datatracker.ietf.org/doc/html/rfc8414).
* MCP server *SHOULD* follow the OAuth 2.0 Authorization Server Metadata protocol.
* MCP servers that do not support the OAuth 2.0 Authorization Server Metadata protocol,
*MUST* support fallback URLs.
The discovery flow is illustrated below:
```mermaid theme={null}
sequenceDiagram
participant C as Client
participant S as Server
C->>S: GET /.well-known/oauth-authorization-server
alt Discovery Success
S->>C: 200 OK + Metadata Document
Note over C: Use endpoints from metadata
else Discovery Failed
S->>C: 404 Not Found
Note over C: Fall back to default endpoints
end
Note over C: Continue with authorization flow
```
#### Server Metadata Discovery Headers
MCP clients *SHOULD* include the header `MCP-Protocol-Version: <protocol-version>` during
Server Metadata Discovery to allow the MCP server to respond based on the MCP protocol
version.
For example: `MCP-Protocol-Version: 2024-11-05`
#### Authorization Base URL
The authorization base URL **MUST** be determined from the MCP server URL by discarding
any existing `path` component. For example:
If the MCP server URL is `https://api.example.com/v1/mcp`, then:
* The authorization base URL is `https://api.example.com`
* The metadata endpoint **MUST** be at
`https://api.example.com/.well-known/oauth-authorization-server`
This ensures authorization endpoints are consistently located at the root level of the
domain hosting the MCP server, regardless of any path components in the MCP server URL.
#### Fallbacks for Servers without Metadata Discovery
For servers that do not implement OAuth 2.0 Authorization Server Metadata, clients
**MUST** use the following default endpoint paths relative to the [authorization base
URL](#authorization-base-url):
| Endpoint | Default Path | Description |
| ---------------------- | ------------ | ------------------------------------ |
| Authorization Endpoint | /authorize | Used for authorization requests |
| Token Endpoint | /token | Used for token exchange & refresh |
| Registration Endpoint | /register | Used for dynamic client registration |
For example, with an MCP server hosted at `https://api.example.com/v1/mcp`, the default
endpoints would be:
* `https://api.example.com/authorize`
* `https://api.example.com/token`
* `https://api.example.com/register`
Clients **MUST** first attempt to discover endpoints via the metadata document before
falling back to default paths. When using default paths, all other protocol requirements
remain unchanged.
### Dynamic Client Registration
MCP clients and servers **SHOULD** support the
[OAuth 2.0 Dynamic Client Registration Protocol](https://datatracker.ietf.org/doc/html/rfc7591)
to allow MCP clients to obtain OAuth client IDs without user interaction. This provides a
standardized way for clients to automatically register with new servers, which is crucial
for MCP because:
* Clients cannot know all possible servers in advance
* Manual registration would create friction for users
* It enables seamless connection to new servers
* Servers can implement their own registration policies
Any MCP servers that *do not* support Dynamic Client Registration need to provide
alternative ways to obtain a client ID (and, if applicable, client secret). For one of
these servers, MCP clients will have to either:
1. Hardcode a client ID (and, if applicable, client secret) specifically for that MCP
server, or
2. Present a UI to users that allows them to enter these details, after registering an
OAuth client themselves (e.g., through a configuration interface hosted by the
server).
### Authorization Flow Steps
The complete Authorization flow proceeds as follows:
```mermaid theme={null}
sequenceDiagram
participant B as User-Agent (Browser)
participant C as Client
participant M as MCP Server
C->>M: GET /.well-known/oauth-authorization-server
alt Server Supports Discovery
M->>C: Authorization Server Metadata
else No Discovery
M->>C: 404 (Use default endpoints)
end
alt Dynamic Client Registration
C->>M: POST /register
M->>C: Client Credentials
end
Note over C: Generate PKCE Parameters
C->>B: Open browser with authorization URL + code_challenge
B->>M: Authorization Request
Note over M: User /authorizes
M->>B: Redirect to callback with authorization code
B->>C: Authorization code callback
C->>M: Token Request + code_verifier
M->>C: Access Token (+ Refresh Token)
C->>M: API Requests with Access Token
```
#### Decision Flow Overview
```mermaid theme={null}
flowchart TD
A[Start Auth Flow] --> B{Check Metadata Discovery}
B -->|Available| C[Use Metadata Endpoints]
B -->|Not Available| D[Use Default Endpoints]
C --> G{Check Registration Endpoint}
D --> G
G -->|Available| H[Perform Dynamic Registration]
G -->|Not Available| I[Alternative Registration Required]
H --> J[Start OAuth Flow]
I --> J
J --> K[Generate PKCE Parameters]
K --> L[Request Authorization]
L --> M[User Authorization]
M --> N[Exchange Code for Tokens]
N --> O[Use Access Token]
```
### Access Token Usage
#### Token Requirements
Access token handling **MUST** conform to
[OAuth 2.1 Section 5](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-12#section-5)
requirements for resource requests. Specifically:
1. MCP client **MUST** use the Authorization request header field
[Section 5.1.1](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-12#section-5.1.1):
```
Authorization: Bearer <access-token>
```
Note that authorization **MUST** be included in every HTTP request from client to server,
even if they are part of the same logical session.
2. Access tokens **MUST NOT** be included in the URI query string
Example request:
```http theme={null}
GET /v1/contexts HTTP/1.1
Host: mcp.example.com
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
```
#### Token Handling
Resource servers **MUST** validate access tokens as described in
[Section 5.2](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-12#section-5.2).
If validation fails, servers **MUST** respond according to
[Section 5.3](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-12#section-5.3)
error handling requirements. Invalid or expired tokens **MUST** receive a HTTP 401
response.
### Security Considerations
The following security requirements **MUST** be implemented:
1. Clients **MUST** securely store tokens following OAuth 2.0 best practices
2. Servers **SHOULD** enforce token expiration and rotation
3. All authorization endpoints **MUST** be served over HTTPS
4. Servers **MUST** validate redirect URIs to prevent open redirect vulnerabilities
Cut at 300 lines. The page has the rest.
specification/2025-03-26/basic/index New page · 121 lines, new page
# Overview ## Messages ### Requests ### Responses ### Notifications ### Batching ## Auth ## Schema
A whole new page. There's nothing to diff it against, so here is what it says.
# Overview
The Model Context Protocol consists of several key components that work together:
* **Base Protocol**: Core JSON-RPC message types
* **Lifecycle Management**: Connection initialization, capability negotiation, and
session control
* **Server Features**: Resources, prompts, and tools exposed by servers
* **Client Features**: Sampling and root directory lists provided by clients
* **Utilities**: Cross-cutting concerns like logging and argument completion
All implementations **MUST** support the base protocol and lifecycle management
components. Other components **MAY** be implemented based on the specific needs of the
application.
These protocol layers establish clear separation of concerns while enabling rich
interactions between clients and servers. The modular design allows implementations to
support exactly the features they need.
## Messages
All messages between MCP clients and servers **MUST** follow the
[JSON-RPC 2.0](https://www.jsonrpc.org/specification) specification. The protocol defines
these types of messages:
### Requests
Requests are sent from the client to the server or vice versa, to initiate an operation.
```typescript theme={null}
{
jsonrpc: "2.0";
id: string | number;
method: string;
params?: {
[key: string]: unknown;
};
}
```
* Requests **MUST** include a string or integer ID.
* Unlike base JSON-RPC, the ID **MUST NOT** be `null`.
* The request ID **MUST NOT** have been previously used by the requestor within the same
session.
### Responses
Responses are sent in reply to requests, containing the result or error of the operation.
```typescript theme={null}
{
jsonrpc: "2.0";
id: string | number;
result?: {
[key: string]: unknown;
}
error?: {
code: number;
message: string;
data?: unknown;
}
}
```
* Responses **MUST** include the same ID as the request they correspond to.
* **Responses** are further sub-categorized as either **successful results** or
**errors**. Either a `result` or an `error` **MUST** be set. A response **MUST NOT**
set both.
* Results **MAY** follow any JSON object structure, while errors **MUST** include an
error code and message at minimum.
* Error codes **MUST** be integers.
### Notifications
Notifications are sent from the client to the server or vice versa, as a one-way message.
The receiver **MUST NOT** send a response.
```typescript theme={null}
{
jsonrpc: "2.0";
method: string;
params?: {
[key: string]: unknown;
};
}
```
* Notifications **MUST NOT** include an ID.
### Batching
JSON-RPC also defines a means to
[batch multiple requests and notifications](https://www.jsonrpc.org/specification#batch),
by sending them in an array. MCP implementations **MAY** support sending JSON-RPC
batches, but **MUST** support receiving JSON-RPC batches.
## Auth
MCP provides an [Authorization](/specification/2025-03-26/basic/authorization) framework for use with HTTP.
Implementations using an HTTP-based transport **SHOULD** conform to this specification,
whereas implementations using STDIO transport **SHOULD NOT** follow this specification,
and instead retrieve credentials from the environment.
Additionally, clients and servers **MAY** negotiate their own custom authentication and
authorization strategies.
For further discussions and contributions to the evolution of MCP’s auth mechanisms, join
us in
[GitHub Discussions](https://github.com/modelcontextprotocol/specification/discussions)
to help shape the future of the protocol!
## Schema
The full specification of the protocol is defined as a
[TypeScript schema](https://github.com/modelcontextprotocol/specification/blob/main/schema/2025-03-26/schema.ts).
This is the source of truth for all protocol messages and structures.
There is also a
[JSON Schema](https://github.com/modelcontextprotocol/specification/blob/main/schema/2025-03-26/schema.json),
which is automatically generated from the TypeScript source of truth, for use with
various automated tooling.
specification/2025-03-26/basic/lifecycle New page · 235 lines, new page
# Lifecycle ## Lifecycle Phases ### Initialization #### Version Negotiation #### Capability Negotiation ### Operation ### Shutdown #### stdio #### HTTP ## Timeouts ## Error Handling
A whole new page. There's nothing to diff it against, so here is what it says.
# Lifecycle
The Model Context Protocol (MCP) defines a rigorous lifecycle for client-server
connections that ensures proper capability negotiation and state management.
1. **Initialization**: Capability negotiation and protocol version agreement
2. **Operation**: Normal protocol communication
3. **Shutdown**: Graceful termination of the connection
```mermaid theme={null}
sequenceDiagram
participant Client
participant Server
Note over Client,Server: Initialization Phase
activate Client
Client->>+Server: initialize request
Server-->>Client: initialize response
Client--)Server: initialized notification
Note over Client,Server: Operation Phase
rect rgb(200, 220, 250)
note over Client,Server: Normal protocol operations
end
Note over Client,Server: Shutdown
Client--)-Server: Disconnect
deactivate Server
Note over Client,Server: Connection closed
```
## Lifecycle Phases
### Initialization
The initialization phase **MUST** be the first interaction between client and server.
During this phase, the client and server:
* Establish protocol version compatibility
* Exchange and negotiate capabilities
* Share implementation details
The client **MUST** initiate this phase by sending an `initialize` request containing:
* Protocol version supported
* Client capabilities
* Client implementation information
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2025-03-26",
"capabilities": {
"roots": {
"listChanged": true
},
"sampling": {}
},
"clientInfo": {
"name": "ExampleClient",
"version": "1.0.0"
}
}
}
```
The initialize request **MUST NOT** be part of a JSON-RPC
[batch](https://www.jsonrpc.org/specification#batch), as other requests and notifications
are not possible until initialization has completed. This also permits backwards
compatibility with prior protocol versions that do not explicitly support JSON-RPC
batches.
The server **MUST** respond with its own capabilities and information:
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"protocolVersion": "2025-03-26",
"capabilities": {
"logging": {},
"prompts": {
"listChanged": true
},
"resources": {
"subscribe": true,
"listChanged": true
},
"tools": {
"listChanged": true
}
},
"serverInfo": {
"name": "ExampleServer",
"version": "1.0.0"
},
"instructions": "Optional instructions for the client"
}
}
```
After successful initialization, the client **MUST** send an `initialized` notification
to indicate it is ready to begin normal operations:
```json theme={null}
{
"jsonrpc": "2.0",
"method": "notifications/initialized"
}
```
* The client **SHOULD NOT** send requests other than
[pings](/specification/2025-03-26/basic/utilities/ping) before the server has responded to the
`initialize` request.
* The server **SHOULD NOT** send requests other than
[pings](/specification/2025-03-26/basic/utilities/ping) and
[logging](/specification/2025-03-26/server/utilities/logging) before receiving the `initialized`
notification.
#### Version Negotiation
In the `initialize` request, the client **MUST** send a protocol version it supports.
This **SHOULD** be the *latest* version supported by the client.
If the server supports the requested protocol version, it **MUST** respond with the same
version. Otherwise, the server **MUST** respond with another protocol version it
supports. This **SHOULD** be the *latest* version supported by the server.
If the client does not support the version in the server's response, it **SHOULD**
disconnect.
#### Capability Negotiation
Client and server capabilities establish which optional protocol features will be
available during the session.
Key capabilities include:
| Category | Capability | Description |
| -------- | -------------- | ----------------------------------------------------------------------------------------- |
| Client | `roots` | Ability to provide filesystem [roots](/specification/2025-03-26/client/roots) |
| Client | `sampling` | Support for LLM [sampling](/specification/2025-03-26/client/sampling) requests |
| Client | `experimental` | Describes support for non-standard experimental features |
| Server | `prompts` | Offers [prompt templates](/specification/2025-03-26/server/prompts) |
| Server | `resources` | Provides readable [resources](/specification/2025-03-26/server/resources) |
| Server | `tools` | Exposes callable [tools](/specification/2025-03-26/server/tools) |
| Server | `logging` | Emits structured [log messages](/specification/2025-03-26/server/utilities/logging) |
| Server | `completions` | Supports argument [autocompletion](/specification/2025-03-26/server/utilities/completion) |
| Server | `experimental` | Describes support for non-standard experimental features |
Capability objects can describe sub-capabilities like:
* `listChanged`: Support for list change notifications (for prompts, resources, and
tools)
* `subscribe`: Support for subscribing to individual items' changes (resources only)
### Operation
During the operation phase, the client and server exchange messages according to the
negotiated capabilities.
Both parties **SHOULD**:
* Respect the negotiated protocol version
* Only use capabilities that were successfully negotiated
### Shutdown
During the shutdown phase, one side (usually the client) cleanly terminates the protocol
connection. No specific shutdown messages are defined—instead, the underlying transport
mechanism should be used to signal connection termination:
#### stdio
For the stdio [transport](/specification/2025-03-26/basic/transports), the client **SHOULD** initiate
shutdown by:
1. First, closing the input stream to the child process (the server)
2. Waiting for the server to exit, or sending `SIGTERM` if the server does not exit
within a reasonable time
3. Sending `SIGKILL` if the server does not exit within a reasonable time after `SIGTERM`
The server **MAY** initiate shutdown by closing its output stream to the client and
exiting.
#### HTTP
For HTTP [transports](/specification/2025-03-26/basic/transports), shutdown is indicated by closing the
associated HTTP connection(s).
## Timeouts
Implementations **SHOULD** establish timeouts for all sent requests, to prevent hung
connections and resource exhaustion. When the request has not received a success or error
response within the timeout period, the sender **SHOULD** issue a [cancellation
notification](/specification/2025-03-26/basic/utilities/cancellation) for that request and stop waiting for
a response.
SDKs and other middleware **SHOULD** allow these timeouts to be configured on a
per-request basis.
Implementations **MAY** choose to reset the timeout clock when receiving a [progress
notification](/specification/2025-03-26/basic/utilities/progress) corresponding to the request, as this
implies that work is actually happening. However, implementations **SHOULD** always
enforce a maximum timeout, regardless of progress notifications, to limit the impact of a
misbehaving client or server.
## Error Handling
Implementations **SHOULD** be prepared to handle these error cases:
* Protocol version mismatch
* Failure to negotiate required capabilities
* Request [timeouts](#timeouts)
Example initialization error:
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32602,
"message": "Unsupported protocol version",
"data": {
"supported": ["2024-11-05"],
"requested": "1.0.0"
}
}
}
```
specification/2025-03-26/basic/transports New page · 284 lines, new page
# Transports ## stdio ## Streamable HTTP #### Security Warning ### Sending Messages to the Server ### Listening for Messages from the Server ### Multiple Connections ### Resumability and Redelivery ### Session Management ### Sequence Diagram ### Backwards Compatibility ## Custom Transports
A whole new page. There's nothing to diff it against, so here is what it says.
# Transports
MCP uses JSON-RPC to encode messages. JSON-RPC messages **MUST** be UTF-8 encoded.
The protocol currently defines two standard transport mechanisms for client-server
communication:
1. [stdio](#stdio), communication over standard in and standard out
2. [Streamable HTTP](#streamable-http)
Clients **SHOULD** support stdio whenever possible.
It is also possible for clients and servers to implement
[custom transports](#custom-transports) in a pluggable fashion.
## stdio
In the **stdio** transport:
* The client launches the MCP server as a subprocess.
* The server reads JSON-RPC messages from its standard input (`stdin`) and sends messages
to its standard output (`stdout`).
* Messages may be JSON-RPC requests, notifications, responses—or a JSON-RPC
[batch](https://www.jsonrpc.org/specification#batch) containing one or more requests
and/or notifications.
* Messages are delimited by newlines, and **MUST NOT** contain embedded newlines.
* The server **MAY** write UTF-8 strings to its standard error (`stderr`) for logging
purposes. Clients **MAY** capture, forward, or ignore this logging.
* The server **MUST NOT** write anything to its `stdout` that is not a valid MCP message.
* The client **MUST NOT** write anything to the server's `stdin` that is not a valid MCP
message.
```mermaid theme={null}
sequenceDiagram
participant Client
participant Server Process
Client->>+Server Process: Launch subprocess
loop Message Exchange
Client->>Server Process: Write to stdin
Server Process->>Client: Write to stdout
Server Process--)Client: Optional logs on stderr
end
Client->>Server Process: Close stdin, terminate subprocess
deactivate Server Process
```
## Streamable HTTP
<Info>
This replaces the [HTTP+SSE
transport](/specification/2024-11-05/basic/transports#http-with-sse) from
protocol version 2024-11-05. See the [backwards compatibility](#backwards-compatibility)
guide below.
</Info>
In the **Streamable HTTP** transport, the server operates as an independent process that
can handle multiple client connections. This transport uses HTTP POST and GET requests.
Server can optionally make use of
[Server-Sent Events](https://en.wikipedia.org/wiki/Server-sent_events) (SSE) to stream
multiple server messages. This permits basic MCP servers, as well as more feature-rich
servers supporting streaming and server-to-client notifications and requests.
The server **MUST** provide a single HTTP endpoint path (hereafter referred to as the
**MCP endpoint**) that supports both POST and GET methods. For example, this could be a
URL like `https://example.com/mcp`.
#### Security Warning
When implementing Streamable HTTP transport:
1. Servers **MUST** validate the `Origin` header on all incoming connections to prevent DNS rebinding attacks
2. When running locally, servers **SHOULD** bind only to localhost (127.0.0.1) rather than all network interfaces (0.0.0.0)
3. Servers **SHOULD** implement proper authentication for all connections
Without these protections, attackers could use DNS rebinding to interact with local MCP servers from remote websites.
### Sending Messages to the Server
Every JSON-RPC message sent from the client **MUST** be a new HTTP POST request to the
MCP endpoint.
1. The client **MUST** use HTTP POST to send JSON-RPC messages to the MCP endpoint.
2. The client **MUST** include an `Accept` header, listing both `application/json` and
`text/event-stream` as supported content types.
3. The body of the POST request **MUST** be one of the following:
* A single JSON-RPC *request*, *notification*, or *response*
* An array [batching](https://www.jsonrpc.org/specification#batch) one or more
*requests and/or notifications*
* An array [batching](https://www.jsonrpc.org/specification#batch) one or more
*responses*
4. If the input consists solely of (any number of) JSON-RPC *responses* or
*notifications*:
* If the server accepts the input, the server **MUST** return HTTP status code 202
Accepted with no body.
* If the server cannot accept the input, it **MUST** return an HTTP error status code
(e.g., 400 Bad Request). The HTTP response body **MAY** comprise a JSON-RPC *error
response* that has no `id`.
5. If the input contains any number of JSON-RPC *requests*, the server **MUST** either
return `Content-Type: text/event-stream`, to initiate an SSE stream, or
`Content-Type: application/json`, to return one JSON object. The client **MUST**
support both these cases.
6. If the server initiates an SSE stream:
* The SSE stream **SHOULD** eventually include one JSON-RPC *response* per each
JSON-RPC *request* sent in the POST body. These *responses* **MAY** be
[batched](https://www.jsonrpc.org/specification#batch).
* The server **MAY** send JSON-RPC *requests* and *notifications* before sending a
JSON-RPC *response*. These messages **SHOULD** relate to the originating client
*request*. These *requests* and *notifications* **MAY** be
[batched](https://www.jsonrpc.org/specification#batch).
* The server **SHOULD NOT** close the SSE stream before sending a JSON-RPC *response*
per each received JSON-RPC *request*, unless the [session](#session-management)
expires.
* After all JSON-RPC *responses* have been sent, the server **SHOULD** close the SSE
stream.
* Disconnection **MAY** occur at any time (e.g., due to network conditions).
Therefore:
* Disconnection **SHOULD NOT** be interpreted as the client cancelling its request.
* To cancel, the client **SHOULD** explicitly send an MCP `CancelledNotification`.
* To avoid message loss due to disconnection, the server **MAY** make the stream
[resumable](#resumability-and-redelivery).
### Listening for Messages from the Server
1. The client **MAY** issue an HTTP GET to the MCP endpoint. This can be used to open an
SSE stream, allowing the server to communicate to the client, without the client first
sending data via HTTP POST.
2. The client **MUST** include an `Accept` header, listing `text/event-stream` as a
supported content type.
3. The server **MUST** either return `Content-Type: text/event-stream` in response to
this HTTP GET, or else return HTTP 405 Method Not Allowed, indicating that the server
does not offer an SSE stream at this endpoint.
4. If the server initiates an SSE stream:
* The server **MAY** send JSON-RPC *requests* and *notifications* on the stream. These
*requests* and *notifications* **MAY** be
[batched](https://www.jsonrpc.org/specification#batch).
* These messages **SHOULD** be unrelated to any concurrently-running JSON-RPC
*request* from the client.
* The server **MUST NOT** send a JSON-RPC *response* on the stream **unless**
[resuming](#resumability-and-redelivery) a stream associated with a previous client
request.
* The server **MAY** close the SSE stream at any time.
* The client **MAY** close the SSE stream at any time.
### Multiple Connections
1. The client **MAY** remain connected to multiple SSE streams simultaneously.
2. The server **MUST** send each of its JSON-RPC messages on only one of the connected
streams; that is, it **MUST NOT** broadcast the same message across multiple streams.
* The risk of message loss **MAY** be mitigated by making the stream
[resumable](#resumability-and-redelivery).
### Resumability and Redelivery
To support resuming broken connections, and redelivering messages that might otherwise be
lost:
1. Servers **MAY** attach an `id` field to their SSE events, as described in the
[SSE standard](https://html.spec.whatwg.org/multipage/server-sent-events.html#event-stream-interpretation).
* If present, the ID **MUST** be globally unique across all streams within that
[session](#session-management)—or all streams with that specific client, if session
management is not in use.
2. If the client wishes to resume after a broken connection, it **SHOULD** issue an HTTP
GET to the MCP endpoint, and include the
[`Last-Event-ID`](https://html.spec.whatwg.org/multipage/server-sent-events.html#the-last-event-id-header)
header to indicate the last event ID it received.
* The server **MAY** use this header to replay messages that would have been sent
after the last event ID, *on the stream that was disconnected*, and to resume the
stream from that point.
* The server **MUST NOT** replay messages that would have been delivered on a
different stream.
In other words, these event IDs should be assigned by servers on a *per-stream* basis, to
act as a cursor within that particular stream.
### Session Management
An MCP "session" consists of logically related interactions between a client and a
server, beginning with the [initialization phase](/specification/2025-03-26/basic/lifecycle). To support
servers which want to establish stateful sessions:
1. A server using the Streamable HTTP transport **MAY** assign a session ID at
initialization time, by including it in an `Mcp-Session-Id` header on the HTTP
response containing the `InitializeResult`.
* The session ID **SHOULD** be globally unique and cryptographically secure (e.g., a
securely generated UUID, a JWT, or a cryptographic hash).
* The session ID **MUST** only contain visible ASCII characters (ranging from 0x21 to
0x7E).
2. If an `Mcp-Session-Id` is returned by the server during initialization, clients using
the Streamable HTTP transport **MUST** include it in the `Mcp-Session-Id` header on
all of their subsequent HTTP requests.
* Servers that require a session ID **SHOULD** respond to requests without an
`Mcp-Session-Id` header (other than initialization) with HTTP 400 Bad Request.
3. The server **MAY** terminate the session at any time, after which it **MUST** respond
to requests containing that session ID with HTTP 404 Not Found.
4. When a client receives HTTP 404 in response to a request containing an
`Mcp-Session-Id`, it **MUST** start a new session by sending a new `InitializeRequest`
without a session ID attached.
5. Clients that no longer need a particular session (e.g., because the user is leaving
the client application) **SHOULD** send an HTTP DELETE to the MCP endpoint with the
`Mcp-Session-Id` header, to explicitly terminate the session.
* The server **MAY** respond to this request with HTTP 405 Method Not Allowed,
indicating that the server does not allow clients to terminate sessions.
### Sequence Diagram
```mermaid theme={null}
sequenceDiagram
participant Client
participant Server
note over Client, Server: initialization
Client->>+Server: POST InitializeRequest
Server->>-Client: InitializeResponse<br>Mcp-Session-Id: 1868a90c...
Client->>+Server: POST InitializedNotification<br>Mcp-Session-Id: 1868a90c...
Server->>-Client: 202 Accepted
note over Client, Server: client requests
Client->>+Server: POST ... request ...<br>Mcp-Session-Id: 1868a90c...
alt single HTTP response
Server->>Client: ... response ...
else server opens SSE stream
loop while connection remains open
Server-)Client: ... SSE messages from server ...
end
Server-)Client: SSE event: ... response ...
end
deactivate Server
note over Client, Server: client notifications/responses
Client->>+Server: POST ... notification/response ...<br>Mcp-Session-Id: 1868a90c...
Server->>-Client: 202 Accepted
note over Client, Server: server requests
Client->>+Server: GET<br>Mcp-Session-Id: 1868a90c...
loop while connection remains open
Server-)Client: ... SSE messages from server ...
end
deactivate Server
```
### Backwards Compatibility
Clients and servers can maintain backwards compatibility with the deprecated [HTTP+SSE
transport](/specification/2024-11-05/basic/transports#http-with-sse) (from
protocol version 2024-11-05) as follows:
**Servers** wanting to support older clients should:
* Continue to host both the SSE and POST endpoints of the old transport, alongside the
new "MCP endpoint" defined for the Streamable HTTP transport.
* It is also possible to combine the old POST endpoint and the new MCP endpoint, but
this may introduce unneeded complexity.
**Clients** wanting to support older servers should:
1. Accept an MCP server URL from the user, which may point to either a server using the
old transport or the new transport.
2. Attempt to POST an `InitializeRequest` to the server URL, with an `Accept` header as
defined above:
* If it succeeds, the client can assume this is a server supporting the new Streamable
HTTP transport.
* If it fails with an HTTP 4xx status code (e.g., 405 Method Not Allowed or 404 Not
Found):
* Issue a GET request to the server URL, expecting that this will open an SSE stream
and return an `endpoint` event as the first event.
* When the `endpoint` event arrives, the client can assume this is a server running
the old HTTP+SSE transport, and should use that transport for all subsequent
communication.
## Custom Transports
Clients and servers **MAY** implement additional custom transport mechanisms to suit
their specific needs. The protocol is transport-agnostic and can be implemented over any
communication channel that supports bidirectional message exchange.
Implementers who choose to support custom transports **MUST** ensure they preserve the
JSON-RPC message format and lifecycle requirements defined by MCP. Custom transports
**SHOULD** document their specific connection establishment and message exchange patterns
to aid interoperability.
specification/2025-03-26/basic/utilities/cancellation New page · 79 lines, new page
# Cancellation ## Cancellation Flow ## Behavior Requirements ## Timing Considerations ## Implementation Notes ## Error Handling
A whole new page. There's nothing to diff it against, so here is what it says.
# Cancellation
The Model Context Protocol (MCP) supports optional cancellation of in-progress requests
through notification messages. Either side can send a cancellation notification to
indicate that a previously-issued request should be terminated.
## Cancellation Flow
When a party wants to cancel an in-progress request, it sends a `notifications/cancelled`
notification containing:
* The ID of the request to cancel
* An optional reason string that can be logged or displayed
```json theme={null}
{
"jsonrpc": "2.0",
"method": "notifications/cancelled",
"params": {
"requestId": "123",
"reason": "User requested cancellation"
}
}
```
## Behavior Requirements
1. Cancellation notifications **MUST** only reference requests that:
* Were previously issued in the same direction
* Are believed to still be in-progress
2. The `initialize` request **MUST NOT** be cancelled by clients
3. Receivers of cancellation notifications **SHOULD**:
* Stop processing the cancelled request
* Free associated resources
* Not send a response for the cancelled request
4. Receivers **MAY** ignore cancellation notifications if:
* The referenced request is unknown
* Processing has already completed
* The request cannot be cancelled
5. The sender of the cancellation notification **SHOULD** ignore any response to the
request that arrives afterward
## Timing Considerations
Due to network latency, cancellation notifications may arrive after request processing
has completed, and potentially after a response has already been sent.
Both parties **MUST** handle these race conditions gracefully:
```mermaid theme={null}
sequenceDiagram
participant Client
participant Server
Client->>Server: Request (ID: 123)
Note over Server: Processing starts
Client--)Server: notifications/cancelled (ID: 123)
alt
Note over Server: Processing may have<br/>completed before<br/>cancellation arrives
else If not completed
Note over Server: Stop processing
end
```
## Implementation Notes
* Both parties **SHOULD** log cancellation reasons for debugging
* Application UIs **SHOULD** indicate when cancellation is requested
## Error Handling
Invalid cancellation notifications **SHOULD** be ignored:
* Unknown request IDs
* Already completed requests
* Malformed notifications
This maintains the "fire and forget" nature of notifications while allowing for race
conditions in asynchronous communication.
specification/2025-03-26/basic/utilities/ping New page · 62 lines, new page
# Ping ## Overview ## Message Format ## Behavior Requirements ## Usage Patterns ## Implementation Considerations ## Error Handling
A whole new page. There's nothing to diff it against, so here is what it says.
# Ping
The Model Context Protocol includes an optional ping mechanism that allows either party
to verify that their counterpart is still responsive and the connection is alive.
## Overview
The ping functionality is implemented through a simple request/response pattern. Either
the client or server can initiate a ping by sending a `ping` request.
## Message Format
A ping request is a standard JSON-RPC request with no parameters:
```json theme={null}
{
"jsonrpc": "2.0",
"id": "123",
"method": "ping"
}
```
## Behavior Requirements
1. The receiver **MUST** respond promptly with an empty response:
```json theme={null}
{
"jsonrpc": "2.0",
"id": "123",
"result": {}
}
```
2. If no response is received within a reasonable timeout period, the sender **MAY**:
* Consider the connection stale
* Terminate the connection
* Attempt reconnection procedures
## Usage Patterns
```mermaid theme={null}
sequenceDiagram
participant Sender
participant Receiver
Sender->>Receiver: ping request
Receiver->>Sender: empty response
```
## Implementation Considerations
* Implementations **SHOULD** periodically issue pings to detect connection health
* The frequency of pings **SHOULD** be configurable
* Timeouts **SHOULD** be appropriate for the network environment
* Excessive pinging **SHOULD** be avoided to reduce network overhead
## Error Handling
* Timeouts **SHOULD** be treated as connection failures
* Multiple failed pings **MAY** trigger connection reset
* Implementations **SHOULD** log ping failures for diagnostics
specification/2025-03-26/basic/utilities/progress New page · 88 lines, new page
# Progress ## Progress Flow ## Behavior Requirements ## Implementation Notes
A whole new page. There's nothing to diff it against, so here is what it says.
# Progress
The Model Context Protocol (MCP) supports optional progress tracking for long-running
operations through notification messages. Either side can send progress notifications to
provide updates about operation status.
## Progress Flow
When a party wants to *receive* progress updates for a request, it includes a
`progressToken` in the request metadata.
* Progress tokens **MUST** be a string or integer value
* Progress tokens can be chosen by the sender using any means, but **MUST** be unique
across all active requests.
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"method": "some_method",
"params": {
"_meta": {
"progressToken": "abc123"
}
}
}
```
The receiver **MAY** then send progress notifications containing:
* The original progress token
* The current progress value so far
* An optional "total" value
* An optional "message" value
```json theme={null}
{
"jsonrpc": "2.0",
"method": "notifications/progress",
"params": {
"progressToken": "abc123",
"progress": 50,
"total": 100,
"message": "Reticulating splines..."
}
}
```
* The `progress` value **MUST** increase with each notification, even if the total is
unknown.
* The `progress` and the `total` values **MAY** be floating point.
* The `message` field **SHOULD** provide relevant human readable progress information.
## Behavior Requirements
1. Progress notifications **MUST** only reference tokens that:
* Were provided in an active request
* Are associated with an in-progress operation
2. Receivers of progress requests **MAY**:
* Choose not to send any progress notifications
* Send notifications at whatever frequency they deem appropriate
* Omit the total value if unknown
```mermaid theme={null}
sequenceDiagram
participant Sender
participant Receiver
Note over Sender,Receiver: Request with progress token
Sender->>Receiver: Method request with progressToken
Note over Sender,Receiver: Progress updates
loop Progress Updates
Receiver-->>Sender: Progress notification (0.2/1.0)
Receiver-->>Sender: Progress notification (0.6/1.0)
Receiver-->>Sender: Progress notification (1.0/1.0)
end
Note over Sender,Receiver: Operation complete
Receiver->>Sender: Method response
```
## Implementation Notes
* Senders and receivers **SHOULD** track active progress tokens
* Both parties **SHOULD** implement rate limiting to prevent flooding
* Progress notifications **MUST** stop after completion
specification/2025-03-26/changelog New page · 34 lines, new page
# Key Changes ## Major changes ## Other schema changes ## Full changelog
A whole new page. There's nothing to diff it against, so here is what it says.
# Key Changes This document lists changes made to the Model Context Protocol (MCP) specification since the previous revision, [2024-11-05](/specification/2024-11-05). ## Major changes 1. Added a comprehensive **[authorization framework](/specification/2025-03-26/basic/authorization)** based on OAuth 2.1 (PR [#133](https://github.com/modelcontextprotocol/specification/pull/133)) 2. Replaced the previous HTTP+SSE transport with a more flexible **[Streamable HTTP transport](/specification/2025-03-26/basic/transports#streamable-http)** (PR [#206](https://github.com/modelcontextprotocol/specification/pull/206)) 3. Added support for JSON-RPC **[batching](https://www.jsonrpc.org/specification#batch)** (PR [#228](https://github.com/modelcontextprotocol/specification/pull/228)) 4. Added comprehensive **tool annotations** for better describing tool behavior, like whether it is read-only or destructive (PR [#185](https://github.com/modelcontextprotocol/specification/pull/185)) ## Other schema changes * Added `message` field to `ProgressNotification` to provide descriptive status updates * Added support for audio data, joining the existing text and image content types * Added `completions` capability to explicitly indicate support for argument autocompletion suggestions See [the updated schema](http://github.com/modelcontextprotocol/specification/tree/main/schema/2025-03-26/schema.ts) for more details. ## Full changelog For a complete list of all changes that have been made since the last protocol revision, [see GitHub](https://github.com/modelcontextprotocol/specification/compare/2024-11-05...2025-03-26).
specification/2025-03-26/client/roots New page · 184 lines, new page
# Roots ## User Interaction Model ## Capabilities ## Protocol Messages ### Listing Roots ### Root List Changes ## Message Flow ## Data Types ### Root #### Project Directory #### Multiple Repositories ## Error Handling ## Security Considerations ## Implementation Guidelines
A whole new page. There's nothing to diff it against, so here is what it says.
# Roots
The Model Context Protocol (MCP) provides a standardized way for clients to expose
filesystem "roots" to servers. Roots define the boundaries of where servers can operate
within the filesystem, allowing them to understand which directories and files they have
access to. Servers can request the list of roots from supporting clients and receive
notifications when that list changes.
## User Interaction Model
Roots in MCP are typically exposed through workspace or project configuration interfaces.
For example, implementations could offer a workspace/project picker that allows users to
select directories and files the server should have access to. This can be combined with
automatic workspace detection from version control systems or project files.
However, implementations are free to expose roots through any interface pattern that
suits their needs—the protocol itself does not mandate any specific user
interaction model.
## Capabilities
Clients that support roots **MUST** declare the `roots` capability during
[initialization](/specification/2025-03-26/basic/lifecycle#initialization):
```json theme={null}
{
"capabilities": {
"roots": {
"listChanged": true
}
}
}
```
`listChanged` indicates whether the client will emit notifications when the list of roots
changes.
## Protocol Messages
### Listing Roots
To retrieve roots, servers send a `roots/list` request:
**Request:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"method": "roots/list"
}
```
**Response:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"roots": [
{
"uri": "file:///home/user/projects/myproject",
"name": "My Project"
}
]
}
}
```
### Root List Changes
When roots change, clients that support `listChanged` **MUST** send a notification:
```json theme={null}
{
"jsonrpc": "2.0",
"method": "notifications/roots/list_changed"
}
```
## Message Flow
```mermaid theme={null}
sequenceDiagram
participant Server
participant Client
Note over Server,Client: Discovery
Server->>Client: roots/list
Client-->>Server: Available roots
Note over Server,Client: Changes
Client--)Server: notifications/roots/list_changed
Server->>Client: roots/list
Client-->>Server: Updated roots
```
## Data Types
### Root
A root definition includes:
* `uri`: Unique identifier for the root. This **MUST** be a `file://` URI in the current
specification.
* `name`: Optional human-readable name for display purposes.
Example roots for different use cases:
#### Project Directory
```json theme={null}
{
"uri": "file:///home/user/projects/myproject",
"name": "My Project"
}
```
#### Multiple Repositories
```json theme={null}
[
{
"uri": "file:///home/user/repos/frontend",
"name": "Frontend Repository"
},
{
"uri": "file:///home/user/repos/backend",
"name": "Backend Repository"
}
]
```
## Error Handling
Clients **SHOULD** return standard JSON-RPC errors for common failure cases:
* Client does not support roots: `-32601` (Method not found)
* Internal errors: `-32603`
Example error:
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32601,
"message": "Roots not supported",
"data": {
"reason": "Client does not have roots capability"
}
}
}
```
## Security Considerations
1. Clients **MUST**:
* Only expose roots with appropriate permissions
* Validate all root URIs to prevent path traversal
* Implement proper access controls
* Monitor root accessibility
2. Servers **SHOULD**:
* Handle cases where roots become unavailable
* Respect root boundaries during operations
* Validate all paths against provided roots
## Implementation Guidelines
1. Clients **SHOULD**:
* Prompt users for consent before exposing roots to servers
* Provide clear user interfaces for root management
* Validate root accessibility before exposing
* Monitor for root changes
2. Servers **SHOULD**:
* Check for roots capability before usage
* Handle root list changes gracefully
* Respect root boundaries in operations
* Cache root information appropriately
specification/2025-03-26/client/sampling New page · 232 lines, new page
# Sampling ## User Interaction Model ## Capabilities ## Protocol Messages ### Creating Messages ## Message Flow ## Data Types ### Messages #### Text Content #### Image Content #### Audio Content ### Model Preferences #### Capability Priorities #### Model Hints ## Error Handling ## Security Considerations
A whole new page. There's nothing to diff it against, so here is what it says.
# Sampling
The Model Context Protocol (MCP) provides a standardized way for servers to request LLM
sampling ("completions" or "generations") from language models via clients. This flow
allows clients to maintain control over model access, selection, and permissions while
enabling servers to leverage AI capabilities—with no server API keys necessary.
Servers can request text, audio, or image-based interactions and optionally include
context from MCP servers in their prompts.
## User Interaction Model
Sampling in MCP allows servers to implement agentic behaviors, by enabling LLM calls to
occur *nested* inside other MCP server features.
Implementations are free to expose sampling through any interface pattern that suits
their needs—the protocol itself does not mandate any specific user interaction
model.
<Warning>
For trust & safety and security, there **SHOULD** always
be a human in the loop with the ability to deny sampling requests.
Applications **SHOULD**:
* Provide UI that makes it easy and intuitive to review sampling requests
* Allow users to view and edit prompts before sending
* Present generated responses for review before delivery
</Warning>
## Capabilities
Clients that support sampling **MUST** declare the `sampling` capability during
[initialization](/specification/2025-03-26/basic/lifecycle#initialization):
```json theme={null}
{
"capabilities": {
"sampling": {}
}
}
```
## Protocol Messages
### Creating Messages
To request a language model generation, servers send a `sampling/createMessage` request:
**Request:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"method": "sampling/createMessage",
"params": {
"messages": [
{
"role": "user",
"content": {
"type": "text",
"text": "What is the capital of France?"
}
}
],
"modelPreferences": {
"hints": [
{
"name": "claude-3-sonnet"
}
],
"intelligencePriority": 0.8,
"speedPriority": 0.5
},
"systemPrompt": "You are a helpful assistant.",
"maxTokens": 100
}
}
```
**Response:**
```json theme={null}
{
"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"
}
}
```
## Message Flow
```mermaid theme={null}
sequenceDiagram
participant Server
participant Client
participant User
participant LLM
Note over Server,Client: Server initiates sampling
Server->>Client: sampling/createMessage
Note over Client,User: Human-in-the-loop review
Client->>User: Present request for approval
User-->>Client: Review and approve/modify
Note over Client,LLM: Model interaction
Client->>LLM: Forward approved request
LLM-->>Client: Return generation
Note over Client,User: Response review
Client->>User: Present response for approval
User-->>Client: Review and approve/modify
Note over Server,Client: Complete request
Client-->>Server: Return approved response
```
## Data Types
### Messages
Sampling messages can contain:
#### Text Content
```json theme={null}
{
"type": "text",
"text": "The message content"
}
```
#### Image Content
```json theme={null}
{
"type": "image",
"data": "base64-encoded-image-data",
"mimeType": "image/jpeg"
}
```
#### Audio Content
```json theme={null}
{
"type": "audio",
"data": "base64-encoded-audio-data",
"mimeType": "audio/wav"
}
```
### Model Preferences
Model selection in MCP requires careful abstraction since servers and clients may use
different AI providers with distinct model offerings. A server cannot simply request a
specific model by name since the client may not have access to that exact model or may
prefer to use a different provider's equivalent model.
To solve this, MCP implements a preference system that combines abstract capability
priorities with optional model hints:
#### Capability Priorities
Servers express their needs through three normalized priority values (0-1):
* `costPriority`: How important is minimizing costs? Higher values prefer cheaper models.
* `speedPriority`: How important is low latency? Higher values prefer faster models.
* `intelligencePriority`: How important are advanced capabilities? Higher values prefer
more capable models.
#### Model Hints
While priorities help select models based on characteristics, `hints` allow servers to
suggest specific models or model families:
* Hints are treated as substrings that can match model names flexibly
* Multiple hints are evaluated in order of preference
* Clients **MAY** map hints to equivalent models from different providers
* Hints are advisory—clients make final model selection
For example:
```json theme={null}
{
"hints": [
{ "name": "claude-3-sonnet" }, // Prefer Sonnet-class models
{ "name": "claude" } // Fall back to any Claude model
],
"costPriority": 0.3, // Cost is less important
"speedPriority": 0.8, // Speed is very important
"intelligencePriority": 0.5 // Moderate capability needs
}
```
The client processes these preferences to select an appropriate model from its available
options. For instance, if the client doesn't have access to Claude models but has Gemini,
it might map the sonnet hint to `gemini-1.5-pro` based on similar capabilities.
## Error Handling
Clients **SHOULD** return errors for common failure cases:
Example error:
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -1,
"message": "User rejected sampling request"
}
}
```
## Security Considerations
1. Clients **SHOULD** implement user approval controls
2. Both parties **SHOULD** validate message content
3. Clients **SHOULD** respect model preference hints
4. Clients **SHOULD** implement rate limiting
5. Both parties **MUST** handle sensitive data appropriately
specification/2025-03-26/index New page · 131 lines, new page
# Specification ## Overview ## Key Details ### Base Protocol ### Features ### Additional Utilities ## Security and Trust & Safety ### Key Principles ### Implementation Guidelines ## Learn More
A whole new page. There's nothing to diff it against, so here is what it says.
# Specification
[Model Context Protocol](https://modelcontextprotocol.io) (MCP) is an open protocol that
enables seamless integration between LLM applications and external data sources and
tools. Whether you're building an AI-powered IDE, enhancing a chat interface, or creating
custom AI workflows, MCP provides a standardized way to connect LLMs with the context
they need.
This specification defines the authoritative protocol requirements, based on the
TypeScript schema in
[schema.ts](https://github.com/modelcontextprotocol/specification/blob/main/schema/2025-03-26/schema.ts).
For implementation guides and examples, visit
[modelcontextprotocol.io](https://modelcontextprotocol.io).
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD
NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be
interpreted as described in [BCP 14](https://datatracker.ietf.org/doc/html/bcp14)
\[[RFC2119](https://datatracker.ietf.org/doc/html/rfc2119)]
\[[RFC8174](https://datatracker.ietf.org/doc/html/rfc8174)] when, and only when, they
appear in all capitals, as shown here.
## Overview
MCP provides a standardized way for applications to:
* Share contextual information with language models
* Expose tools and capabilities to AI systems
* Build composable integrations and workflows
The protocol uses [JSON-RPC](https://www.jsonrpc.org/) 2.0 messages to establish
communication between:
* **Hosts**: LLM applications that initiate connections
* **Clients**: Connectors within the host application
* **Servers**: Services that provide context and capabilities
MCP takes some inspiration from the
[Language Server Protocol](https://microsoft.github.io/language-server-protocol/), which
standardizes how to add support for programming languages across a whole ecosystem of
development tools. In a similar way, MCP standardizes how to integrate additional context
and tools into the ecosystem of AI applications.
## Key Details
### Base Protocol
* [JSON-RPC](https://www.jsonrpc.org/) message format
* Stateful connections
* Server and client capability negotiation
### Features
Servers offer any of the following features to clients:
* **Resources**: Context and data, for the user or the AI model to use
* **Prompts**: Templated messages and workflows for users
* **Tools**: Functions for the AI model to execute
Clients may offer the following feature to servers:
* **Sampling**: Server-initiated agentic behaviors and recursive LLM interactions
### Additional Utilities
* Configuration
* Progress tracking
* Cancellation
* Error reporting
* Logging
## Security and Trust & Safety
The Model Context Protocol enables powerful capabilities through arbitrary data access
and code execution paths. With this power comes important security and trust
considerations that all implementors must carefully address.
### Key Principles
1. **User Consent and Control**
* Users must explicitly consent to and understand all data access and operations
* Users must retain control over what data is shared and what actions are taken
* Implementors should provide clear UIs for reviewing and authorizing activities
2. **Data Privacy**
* Hosts must obtain explicit user consent before exposing user data to servers
* Hosts must not transmit resource data elsewhere without user consent
* User data should be protected with appropriate access controls
3. **Tool Safety**
* Tools represent arbitrary code execution and must be treated with appropriate
caution.
* In particular, descriptions of tool behavior such as annotations should be
considered untrusted, unless obtained from a trusted server.
* Hosts must obtain explicit user consent before invoking any tool
* Users should understand what each tool does before authorizing its use
4. **LLM Sampling Controls**
* Users must explicitly approve any LLM sampling requests
* Users should control:
* Whether sampling occurs at all
* The actual prompt that will be sent
* What results the server can see
* The protocol intentionally limits server visibility into prompts
### Implementation Guidelines
While MCP itself cannot enforce these security principles at the protocol level,
implementors **SHOULD**:
1. Build robust consent and authorization flows into their applications
2. Provide clear documentation of security implications
3. Implement appropriate access controls and data protections
4. Follow security best practices in their integrations
5. Consider privacy implications in their feature designs
## Learn More
Explore the detailed specification for each protocol component:
<CardGroup cols={5}>
<Card title="Architecture" icon="sitemap" href="/specification/2025-03-26/architecture" />
<Card title="Base Protocol" icon="code" href="/specification/2025-03-26/basic" />
<Card title="Server Features" icon="server" href="/specification/2025-03-26/server" />
<Card title="Client Features" icon="user" href="/specification/2025-03-26/client" />
<Card title="Contributing" icon="pencil" href="/community/contributing" />
</CardGroup>
specification/2025-03-26/server/index New page · 29 lines, new page
# Overview
A whole new page. There's nothing to diff it against, so here is what it says.
# Overview
Servers provide the fundamental building blocks for adding context to language models via
MCP. These primitives enable rich interactions between clients, servers, and language
models:
* **Prompts**: Pre-defined templates or instructions that guide language model
interactions
* **Resources**: Structured data or content that provides additional context to the model
* **Tools**: Executable functions that allow models to perform actions or retrieve
information
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 |
Explore these key primitives in more detail below:
<CardGroup cols={3}>
<Card title="Prompts" icon="message" href="/specification/2025-03-26/server/prompts" />
<Card title="Resources" icon="file-lines" href="/specification/2025-03-26/server/resources" />
<Card title="Tools" icon="wrench" href="/specification/2025-03-26/server/tools" />
</CardGroup>
specification/2025-03-26/server/prompts New page · 266 lines, new page
# Prompts ## User Interaction Model ## Capabilities ## Protocol Messages ### Listing Prompts ### Getting a Prompt ### List Changed Notification ## Message Flow ## Data Types ### Prompt ### PromptMessage #### Text Content #### Image Content #### Audio Content #### Embedded Resources ## Error Handling ## Implementation Considerations ## Security
A whole new page. There's nothing to diff it against, so here is what it says.
# Prompts
The Model Context Protocol (MCP) provides a standardized way for servers to expose prompt
templates to clients. Prompts allow servers to provide structured messages and
instructions for interacting with language models. Clients can discover available
prompts, retrieve their contents, and provide arguments to customize them.
## User Interaction Model
Prompts are designed to be **user-controlled**, meaning they are exposed from servers to
clients with the intention of the user being able to explicitly select them for use.
Typically, prompts would be triggered through user-initiated commands in the user
interface, which allows users to naturally discover and invoke available prompts.
For example, as slash commands:
<img src="https://mintcdn.com/mcp/4ZXF1PrDkEaJvXpn/specification/2025-03-26/server/slash-command.png?fit=max&auto=format&n=4ZXF1PrDkEaJvXpn&q=85&s=8390583e2400c914dd404e37e014613e" alt="Example of prompt exposed as slash command" width="293" height="106" data-path="specification/2025-03-26/server/slash-command.png" />
However, implementors are free to expose prompts through any interface pattern that suits
their needs—the protocol itself does not mandate any specific user interaction
model.
## Capabilities
Servers that support prompts **MUST** declare the `prompts` capability during
[initialization](/specification/2025-03-26/basic/lifecycle#initialization):
```json theme={null}
{
"capabilities": {
"prompts": {
"listChanged": true
}
}
}
```
`listChanged` indicates whether the server will emit notifications when the list of
available prompts changes.
## Protocol Messages
### Listing Prompts
To retrieve available prompts, clients send a `prompts/list` request. This operation
supports [pagination](/specification/2025-03-26/server/utilities/pagination).
**Request:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"method": "prompts/list",
"params": {
"cursor": "optional-cursor-value"
}
}
```
**Response:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"prompts": [
{
"name": "code_review",
"description": "Asks the LLM to analyze code quality and suggest improvements",
"arguments": [
{
"name": "code",
"description": "The code to review",
"required": true
}
]
}
],
"nextCursor": "next-page-cursor"
}
}
```
### Getting a Prompt
To retrieve a specific prompt, clients send a `prompts/get` request. Arguments may be
auto-completed through [the completion API](/specification/2025-03-26/server/utilities/completion).
**Request:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 2,
"method": "prompts/get",
"params": {
"name": "code_review",
"arguments": {
"code": "def hello():\n print('world')"
}
}
}
```
**Response:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"description": "Code review prompt",
"messages": [
{
"role": "user",
"content": {
"type": "text",
"text": "Please review this Python code:\ndef hello():\n print('world')"
}
}
]
}
}
```
### List Changed Notification
When the list of available prompts changes, servers that declared the `listChanged`
capability **SHOULD** send a notification:
```json theme={null}
{
"jsonrpc": "2.0",
"method": "notifications/prompts/list_changed"
}
```
## Message Flow
```mermaid theme={null}
sequenceDiagram
participant Client
participant Server
Note over Client,Server: Discovery
Client->>Server: prompts/list
Server-->>Client: List of prompts
Note over Client,Server: Usage
Client->>Server: prompts/get
Server-->>Client: Prompt content
opt listChanged
Note over Client,Server: Changes
Server--)Client: prompts/list_changed
Client->>Server: prompts/list
Server-->>Client: Updated prompts
end
```
## Data Types
### Prompt
A prompt definition includes:
* `name`: Unique identifier for the prompt
* `description`: Optional human-readable description
* `arguments`: Optional list of arguments for customization
### PromptMessage
Messages in a prompt can contain:
* `role`: Either "user" or "assistant" to indicate the speaker
* `content`: One of the following content types:
#### Text Content
Text content represents plain text messages:
```json theme={null}
{
"type": "text",
"text": "The text content of the message"
}
```
This is the most common content type used for natural language interactions.
#### Image Content
Image content allows including visual information in messages:
```json theme={null}
{
"type": "image",
"data": "base64-encoded-image-data",
"mimeType": "image/png"
}
```
The image data **MUST** be base64-encoded and include a valid MIME type. This enables
multi-modal interactions where visual context is important.
#### Audio Content
Audio content allows including audio information in messages:
```json theme={null}
{
"type": "audio",
"data": "base64-encoded-audio-data",
"mimeType": "audio/wav"
}
```
The audio data MUST be base64-encoded and include a valid MIME type. This enables
multi-modal interactions where audio context is important.
#### Embedded Resources
Embedded resources allow referencing server-side resources directly in messages:
```json theme={null}
{
"type": "resource",
"resource": {
"uri": "resource://example",
"mimeType": "text/plain",
"text": "Resource content"
}
}
```
Resources can contain either text or binary (blob) data and **MUST** include:
* A valid resource URI
* The appropriate MIME type
* Either text content or base64-encoded blob data
Embedded resources enable prompts to seamlessly incorporate server-managed content like
documentation, code samples, or other reference materials directly into the conversation
flow.
## Error Handling
Servers **SHOULD** return standard JSON-RPC errors for common failure cases:
* Invalid prompt name: `-32602` (Invalid params)
* Missing required arguments: `-32602` (Invalid params)
* Internal errors: `-32603` (Internal error)
## Implementation Considerations
1. Servers **SHOULD** validate prompt arguments before processing
2. Clients **SHOULD** handle pagination for large prompt lists
3. Both parties **SHOULD** respect capability negotiation
## Security
Implementations **MUST** carefully validate all prompt inputs and outputs to prevent
injection attacks or unauthorized access to resources.
specification/2025-03-26/server/resources New page · 360 lines, new page
# Resources ## User Interaction Model ## Capabilities ## Protocol Messages ### Listing Resources ### Reading Resources ### Resource Templates ### List Changed Notification ### Subscriptions ## Message Flow ## Data Types ### Resource ### Resource Contents #### Text Content #### Binary Content ## Common URI Schemes ### https\:// ### file:// ### git:// ## Error Handling ## Security Considerations
A whole new page. There's nothing to diff it against, so here is what it says.
# Resources
The Model Context Protocol (MCP) provides a standardized way for servers to expose
resources to clients. Resources allow servers to share data that provides context to
language models, such as files, database schemas, or application-specific information.
Each resource is uniquely identified by a
[URI](https://datatracker.ietf.org/doc/html/rfc3986).
## User Interaction Model
Resources in MCP are designed to be **application-driven**, with host applications
determining how to incorporate context based on their needs.
For example, applications could:
* Expose resources through UI elements for explicit selection, in a tree or list view
* Allow the user to search through and filter available resources
* Implement automatic context inclusion, based on heuristics or the AI model's selection
<img src="https://mintcdn.com/mcp/4ZXF1PrDkEaJvXpn/specification/2025-03-26/server/resource-picker.png?fit=max&auto=format&n=4ZXF1PrDkEaJvXpn&q=85&s=7f6d9a491a97e714b5d5fc74cb0c7132" alt="Example of resource context picker" width="174" height="181" data-path="specification/2025-03-26/server/resource-picker.png" />
However, implementations are free to expose resources through any interface pattern that
suits their needs—the protocol itself does not mandate any specific user
interaction model.
## Capabilities
Servers that support resources **MUST** declare the `resources` capability:
```json theme={null}
{
"capabilities": {
"resources": {
"subscribe": true,
"listChanged": true
}
}
}
```
The capability supports two optional features:
* `subscribe`: whether the client can subscribe to be notified of changes to individual
resources.
* `listChanged`: whether the server will emit notifications when the list of available
resources changes.
Both `subscribe` and `listChanged` are optional—servers can support neither,
either, or both:
```json theme={null}
{
"capabilities": {
"resources": {} // Neither feature supported
}
}
```
```json theme={null}
{
"capabilities": {
"resources": {
"subscribe": true // Only subscriptions supported
}
}
}
```
```json theme={null}
{
"capabilities": {
"resources": {
"listChanged": true // Only list change notifications supported
}
}
}
```
## Protocol Messages
### Listing Resources
To discover available resources, clients send a `resources/list` request. This operation
supports [pagination](/specification/2025-03-26/server/utilities/pagination).
**Request:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"method": "resources/list",
"params": {
"cursor": "optional-cursor-value"
}
}
```
**Response:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"resources": [
{
"uri": "file:///project/src/main.rs",
"name": "main.rs",
"description": "Primary application entry point",
"mimeType": "text/x-rust"
}
],
"nextCursor": "next-page-cursor"
}
}
```
### Reading Resources
To retrieve resource contents, clients send a `resources/read` request:
**Request:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 2,
"method": "resources/read",
"params": {
"uri": "file:///project/src/main.rs"
}
}
```
**Response:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"contents": [
{
"uri": "file:///project/src/main.rs",
"mimeType": "text/x-rust",
"text": "fn main() {\n println!(\"Hello world!\");\n}"
}
]
}
}
```
### Resource Templates
Resource templates allow servers to expose parameterized resources using
[URI templates](https://datatracker.ietf.org/doc/html/rfc6570). Arguments may be
auto-completed through [the completion API](/specification/2025-03-26/server/utilities/completion).
This operation supports [pagination](/specification/2025-03-26/server/utilities/pagination).
**Request:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 3,
"method": "resources/templates/list",
"params": {
"cursor": "optional-cursor-value"
}
}
```
**Response:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 3,
"result": {
"resourceTemplates": [
{
"uriTemplate": "file:///{path}",
"name": "Project Files",
"description": "Access files in the project directory",
"mimeType": "application/octet-stream"
}
],
"nextCursor": "next-page-cursor"
}
}
```
### List Changed Notification
When the list of available resources changes, servers that declared the `listChanged`
capability **SHOULD** send a notification:
```json theme={null}
{
"jsonrpc": "2.0",
"method": "notifications/resources/list_changed"
}
```
### Subscriptions
The protocol supports optional subscriptions to resource changes. Clients can subscribe
to specific resources and receive notifications when they change:
**Subscribe Request:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 4,
"method": "resources/subscribe",
"params": {
"uri": "file:///project/src/main.rs"
}
}
```
**Update Notification:**
```json theme={null}
{
"jsonrpc": "2.0",
"method": "notifications/resources/updated",
"params": {
"uri": "file:///project/src/main.rs"
}
}
```
## Message Flow
```mermaid theme={null}
sequenceDiagram
participant Client
participant Server
Note over Client,Server: Resource Discovery
Client->>Server: resources/list
Server-->>Client: List of resources
Note over Client,Server: Resource Template Discovery
Client->>Server: resources/templates/list
Server-->>Client: List of resource templates
Note over Client,Server: Resource Access
Client->>Server: resources/read
Server-->>Client: Resource contents
Note over Client,Server: Subscriptions
Client->>Server: resources/subscribe
Server-->>Client: Subscription confirmed
Note over Client,Server: Updates
Server--)Client: notifications/resources/updated
Client->>Server: resources/read
Server-->>Client: Updated contents
```
## Data Types
### Resource
A resource definition includes:
* `uri`: Unique identifier for the resource
* `name`: Human-readable name
* `description`: Optional description
* `mimeType`: Optional MIME type
* `size`: Optional size in bytes
### Resource Contents
Resources can contain either text or binary data:
#### Text Content
```json theme={null}
{
"uri": "file:///example.txt",
"mimeType": "text/plain",
"text": "Resource content"
}
```
#### Binary Content
```json theme={null}
{
"uri": "file:///example.png",
"mimeType": "image/png",
"blob": "base64-encoded-data"
}
```
Cut at 300 lines. The page has the rest.
specification/2025-03-26/server/tools New page · 295 lines, new page
# Tools ## User Interaction Model ## Capabilities ## Protocol Messages ### Listing Tools ### Calling Tools ### List Changed Notification ## Message Flow ## Data Types ### Tool ### Tool Result #### Text Content #### Image Content #### Audio Content #### Embedded Resources ## Error Handling ## Security Considerations
A whole new page. There's nothing to diff it against, so here is what it says.
# Tools
The Model Context Protocol (MCP) allows servers to expose tools that can be invoked by
language models. Tools enable models to interact with external systems, such as querying
databases, calling APIs, or performing computations. Each tool is uniquely identified by
a name and includes metadata describing its schema.
## User Interaction Model
Tools in MCP are designed to be **model-controlled**, meaning that the language model can
discover and invoke tools automatically based on its contextual understanding and the
user's prompts.
However, implementations are free to expose tools through any interface pattern that
suits their needs—the protocol itself does not mandate any specific user
interaction model.
<Warning>
For trust & safety and security, there **SHOULD** always
be a human in the loop with the ability to deny tool invocations.
Applications **SHOULD**:
* Provide UI that makes clear which tools are being exposed to the AI model
* Insert clear visual indicators when tools are invoked
* Present confirmation prompts to the user for operations, to ensure a human is in the
loop
</Warning>
## Capabilities
Servers that support tools **MUST** declare the `tools` capability:
```json theme={null}
{
"capabilities": {
"tools": {
"listChanged": true
}
}
}
```
`listChanged` indicates whether the server will emit notifications when the list of
available tools changes.
## Protocol Messages
### Listing Tools
To discover available tools, clients send a `tools/list` request. This operation supports
[pagination](/specification/2025-03-26/server/utilities/pagination).
**Request:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list",
"params": {
"cursor": "optional-cursor-value"
}
}
```
**Response:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"tools": [
{
"name": "get_weather",
"description": "Get current weather information for a location",
"inputSchema": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "City name or zip code"
}
},
"required": ["location"]
}
}
],
"nextCursor": "next-page-cursor"
}
}
```
### Calling Tools
To invoke a tool, clients send a `tools/call` request:
**Request:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "get_weather",
"arguments": {
"location": "New York"
}
}
}
```
**Response:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"content": [
{
"type": "text",
"text": "Current weather in New York:\nTemperature: 72°F\nConditions: Partly cloudy"
}
],
"isError": false
}
}
```
### List Changed Notification
When the list of available tools changes, servers that declared the `listChanged`
capability **SHOULD** send a notification:
```json theme={null}
{
"jsonrpc": "2.0",
"method": "notifications/tools/list_changed"
}
```
## Message Flow
```mermaid theme={null}
sequenceDiagram
participant LLM
participant Client
participant Server
Note over Client,Server: Discovery
Client->>Server: tools/list
Server-->>Client: List of tools
Note over Client,LLM: Tool Selection
LLM->>Client: Select tool to use
Note over Client,Server: Invocation
Client->>Server: tools/call
Server-->>Client: Tool result
Client->>LLM: Process result
Note over Client,Server: Updates
Server--)Client: tools/list_changed
Client->>Server: tools/list
Server-->>Client: Updated tools
```
## Data Types
### Tool
A tool definition includes:
* `name`: Unique identifier for the tool
* `description`: Human-readable description of functionality
* `inputSchema`: JSON Schema defining expected parameters
* `annotations`: optional properties describing tool behavior
<Warning>
For trust & safety and security, clients **MUST** consider
tool annotations to be untrusted unless they come from trusted servers.
</Warning>
### Tool Result
Tool results can contain multiple content items of different types:
#### Text Content
```json theme={null}
{
"type": "text",
"text": "Tool result text"
}
```
#### Image Content
```json theme={null}
{
"type": "image",
"data": "base64-encoded-data",
"mimeType": "image/png"
}
```
#### Audio Content
```json theme={null}
{
"type": "audio",
"data": "base64-encoded-audio-data",
"mimeType": "audio/wav"
}
```
#### Embedded Resources
[Resources](/specification/2025-03-26/server/resources) **MAY** be embedded, to provide additional context
or data, behind a URI that can be subscribed to or fetched again by the client later:
```json theme={null}
{
"type": "resource",
"resource": {
"uri": "resource://example",
"mimeType": "text/plain",
"text": "Resource content"
}
}
```
## Error Handling
Tools use two error reporting mechanisms:
1. **Protocol Errors**: Standard JSON-RPC errors for issues like:
* Unknown tools
* Invalid arguments
* Server errors
2. **Tool Execution Errors**: Reported in tool results with `isError: true`:
* API failures
* Invalid input data
* Business logic errors
Example protocol error:
```json theme={null}
{
"jsonrpc": "2.0",
"id": 3,
"error": {
"code": -32602,
"message": "Unknown tool: invalid_tool_name"
}
}
```
Example tool execution error:
```json theme={null}
{
"jsonrpc": "2.0",
"id": 4,
"result": {
"content": [
{
"type": "text",
"text": "Failed to fetch weather data: API rate limit exceeded"
}
],
"isError": true
}
}
```
## Security Considerations
1. Servers **MUST**:
* Validate all tool inputs
* Implement proper access controls
* Rate limit tool invocations
* Sanitize tool outputs
2. Clients **SHOULD**:
* Prompt for user confirmation on sensitive operations
* Show tool inputs to the user before calling the server, to avoid malicious or
accidental data exfiltration
* Validate tool results before passing to LLM
* Implement timeouts for tool calls
* Log tool usage for audit purposes
specification/2025-03-26/server/utilities/completion New page · 153 lines, new page
# Completion ## User Interaction Model ## Capabilities ## Protocol Messages ### Requesting Completions ### Reference Types ### Completion Results ## Message Flow ## Data Types ### CompleteRequest ### CompleteResult ## Error Handling ## Implementation Considerations ## Security
A whole new page. There's nothing to diff it against, so here is what it says.
# Completion
The Model Context Protocol (MCP) provides a standardized way for servers to offer
argument autocompletion suggestions for prompts and resource URIs. This enables rich,
IDE-like experiences where users receive contextual suggestions while entering argument
values.
## User Interaction Model
Completion in MCP is designed to support interactive user experiences similar to IDE code
completion.
For example, applications may show completion suggestions in a dropdown or popup menu as
users type, with the ability to filter and select from available options.
However, implementations are free to expose completion through any interface pattern that
suits their needs—the protocol itself does not mandate any specific user
interaction model.
## Capabilities
Servers that support completions **MUST** declare the `completions` capability:
```json theme={null}
{
"capabilities": {
"completions": {}
}
}
```
## Protocol Messages
### Requesting Completions
To get completion suggestions, clients send a `completion/complete` request specifying
what is being completed through a reference type:
**Request:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"method": "completion/complete",
"params": {
"ref": {
"type": "ref/prompt",
"name": "code_review"
},
"argument": {
"name": "language",
"value": "py"
}
}
}
```
**Response:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"completion": {
"values": ["python", "pytorch", "pyside"],
"total": 10,
"hasMore": true
}
}
}
```
### Reference Types
The protocol supports two types of completion references:
| Type | Description | Example |
| -------------- | --------------------------- | --------------------------------------------------- |
| `ref/prompt` | References a prompt by name | `{"type": "ref/prompt", "name": "code_review"}` |
| `ref/resource` | References a resource URI | `{"type": "ref/resource", "uri": "file:///{path}"}` |
### Completion Results
Servers return an array of completion values ranked by relevance, with:
* Maximum 100 items per response
* Optional total number of available matches
* Boolean indicating if additional results exist
## Message Flow
```mermaid theme={null}
sequenceDiagram
participant Client
participant Server
Note over Client: User types argument
Client->>Server: completion/complete
Server-->>Client: Completion suggestions
Note over Client: User continues typing
Client->>Server: completion/complete
Server-->>Client: Refined suggestions
```
## Data Types
### CompleteRequest
* `ref`: A `PromptReference` or `ResourceReference`
* `argument`: Object containing:
* `name`: Argument name
* `value`: Current value
### CompleteResult
* `completion`: Object containing:
* `values`: Array of suggestions (max 100)
* `total`: Optional total matches
* `hasMore`: Additional results flag
## Error Handling
Servers **SHOULD** return standard JSON-RPC errors for common failure cases:
* Method not found: `-32601` (Capability not supported)
* Invalid prompt name: `-32602` (Invalid params)
* Missing required arguments: `-32602` (Invalid params)
* Internal errors: `-32603` (Internal error)
## Implementation Considerations
1. Servers **SHOULD**:
* Return suggestions sorted by relevance
* Implement fuzzy matching where appropriate
* Rate limit completion requests
* Validate all inputs
2. Clients **SHOULD**:
* Debounce rapid completion requests
* Cache completion results where appropriate
* Handle missing or partial results gracefully
## Security
Implementations **MUST**:
* Validate all completion inputs
* Implement appropriate rate limiting
* Control access to sensitive suggestions
* Prevent completion-based information disclosure
specification/2025-03-26/server/utilities/logging New page · 136 lines, new page
# Logging ## User Interaction Model ## Capabilities ## Log Levels ## Protocol Messages ### Setting Log Level ### Log Message Notifications ## Message Flow ## Error Handling ## Implementation Considerations ## Security
A whole new page. There's nothing to diff it against, so here is what it says.
# Logging
The Model Context Protocol (MCP) provides a standardized way for servers to send
structured log messages to clients. Clients can control logging verbosity by setting
minimum log levels, with servers sending notifications containing severity levels,
optional logger names, and arbitrary JSON-serializable data.
## User Interaction Model
Implementations are free to expose logging through any interface pattern that suits their
needs—the protocol itself does not mandate any specific user interaction model.
## Capabilities
Servers that emit log message notifications **MUST** declare the `logging` capability:
```json theme={null}
{
"capabilities": {
"logging": {}
}
}
```
## Log Levels
The protocol follows the standard syslog severity levels specified in
[RFC 5424](https://datatracker.ietf.org/doc/html/rfc5424#section-6.2.1):
| Level | Description | Example Use Case |
| --------- | -------------------------------- | -------------------------- |
| debug | Detailed debugging information | Function entry/exit points |
| info | General informational messages | Operation progress updates |
| notice | Normal but significant events | Configuration changes |
| warning | Warning conditions | Deprecated feature usage |
| error | Error conditions | Operation failures |
| critical | Critical conditions | System component failures |
| alert | Action must be taken immediately | Data corruption detected |
| emergency | System is unusable | Complete system failure |
## Protocol Messages
### Setting Log Level
To configure the minimum log level, clients **MAY** send a `logging/setLevel` request:
**Request:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"method": "logging/setLevel",
"params": {
"level": "info"
}
}
```
### Log Message Notifications
Servers send log messages using `notifications/message` notifications:
```json theme={null}
{
"jsonrpc": "2.0",
"method": "notifications/message",
"params": {
"level": "error",
"logger": "database",
"data": {
"error": "Connection failed",
"details": {
"host": "localhost",
"port": 5432
}
}
}
}
```
## Message Flow
```mermaid theme={null}
sequenceDiagram
participant Client
participant Server
Note over Client,Server: Configure Logging
Client->>Server: logging/setLevel (info)
Server-->>Client: Empty Result
Note over Client,Server: Server Activity
Server--)Client: notifications/message (info)
Server--)Client: notifications/message (warning)
Server--)Client: notifications/message (error)
Note over Client,Server: Level Change
Client->>Server: logging/setLevel (error)
Server-->>Client: Empty Result
Note over Server: Only sends error level<br/>and above
```
## Error Handling
Servers **SHOULD** return standard JSON-RPC errors for common failure cases:
* Invalid log level: `-32602` (Invalid params)
* Configuration errors: `-32603` (Internal error)
## Implementation Considerations
1. Servers **SHOULD**:
* Rate limit log messages
* Include relevant context in data field
* Use consistent logger names
* Remove sensitive information
2. Clients **MAY**:
* Present log messages in the UI
* Implement log filtering/search
* Display severity visually
* Persist log messages
## Security
1. Log messages **MUST NOT** contain:
* Credentials or secrets
* Personal identifying information
* Internal system details that could aid attacks
2. Implementations **SHOULD**:
* Rate limit messages
* Validate all data fields
* Control log access
* Monitor for sensitive content
specification/2025-03-26/server/utilities/pagination New page · 92 lines, new page
# Pagination ## Pagination Model ## Response Format ## Request Format ## Pagination Flow ## Operations Supporting Pagination ## Implementation Guidelines ## Error Handling
A whole new page. There's nothing to diff it against, so here is what it says.
# Pagination
The Model Context Protocol (MCP) supports paginating list operations that may return
large result sets. Pagination allows servers to yield results in smaller chunks rather
than all at once.
Pagination is especially important when connecting to external services over the
internet, but also useful for local integrations to avoid performance issues with large
data sets.
## Pagination Model
Pagination in MCP uses an opaque cursor-based approach, instead of numbered pages.
* The **cursor** is an opaque string token, representing a position in the result set
* **Page size** is determined by the server, and clients **MUST NOT** assume a fixed page
size
## Response Format
Pagination starts when the server sends a **response** that includes:
* The current page of results
* An optional `nextCursor` field if more results exist
```json theme={null}
{
"jsonrpc": "2.0",
"id": "123",
"result": {
"resources": [...],
"nextCursor": "eyJwYWdlIjogM30="
}
}
```
## Request Format
After receiving a cursor, the client can *continue* paginating by issuing a request
including that cursor:
```json theme={null}
{
"jsonrpc": "2.0",
"method": "resources/list",
"params": {
"cursor": "eyJwYWdlIjogMn0="
}
}
```
## Pagination Flow
```mermaid theme={null}
sequenceDiagram
participant Client
participant Server
Client->>Server: List Request (no cursor)
loop Pagination Loop
Server-->>Client: Page of results + nextCursor
Client->>Server: List Request (with cursor)
end
```
## Operations Supporting Pagination
The following MCP operations support pagination:
* `resources/list` - List available resources
* `resources/templates/list` - List resource templates
* `prompts/list` - List available prompts
* `tools/list` - List available tools
## Implementation Guidelines
1. Servers **SHOULD**:
* Provide stable cursors
* Handle invalid cursors gracefully
2. Clients **SHOULD**:
* Treat a missing `nextCursor` as the end of results
* Support both paginated and non-paginated flows
3. Clients **MUST** treat cursors as opaque tokens:
* Don't make assumptions about cursor format
* Don't attempt to parse or modify cursors
* Don't persist cursors across sessions
## Error Handling
Invalid cursors **SHOULD** result in an error with code -32602 (Invalid params).
specification/2025-06-18/architecture/index New page · 172 lines, new page
# Architecture ## Core Components ### Host ### Clients ### Servers ## Design Principles ## Capability Negotiation
A whole new page. There's nothing to diff it against, so here is what it says.
# Architecture
<div id="enable-section-numbers" />
The Model Context Protocol (MCP) follows a client-host-server architecture where each
host can run multiple client instances. This architecture enables users to integrate AI
capabilities across applications while maintaining clear security boundaries and
isolating concerns. Built on JSON-RPC, MCP provides a stateful session protocol focused
on context exchange and sampling coordination between clients and servers.
## Core Components
```mermaid theme={null}
graph LR
subgraph "Application Host Process"
H[Host]
C1[Client 1]
C2[Client 2]
C3[Client 3]
H --> C1
H --> C2
H --> C3
end
subgraph "Local machine"
S1[Server 1<br>Files & Git]
S2[Server 2<br>Database]
R1[("Local<br>Resource A")]
R2[("Local<br>Resource B")]
C1 --> S1
C2 --> S2
S1 <--> R1
S2 <--> R2
end
subgraph "Internet"
S3[Server 3<br>External APIs]
R3[("Remote<br>Resource C")]
C3 --> S3
S3 <--> R3
end
```
### Host
The host process acts as the container and coordinator:
* Creates and manages multiple client instances
* Controls client connection permissions and lifecycle
* Enforces security policies and consent requirements
* Handles user authorization decisions
* Coordinates AI/LLM integration and sampling
* Manages context aggregation across clients
### Clients
Each client is created by the host and maintains an isolated server connection:
* Establishes one stateful session per server
* Handles protocol negotiation and capability exchange
* Routes protocol messages bidirectionally
* Manages subscriptions and notifications
* Maintains security boundaries between servers
A host application creates and manages multiple clients, with each client having a 1:1
relationship with a particular server.
### Servers
Servers provide specialized context and capabilities:
* Expose resources, tools and prompts via MCP primitives
* Operate independently with focused responsibilities
* Request sampling through client interfaces
* Must respect security constraints
* Can be local processes or remote services
## Design Principles
MCP is built on several key design principles that inform its architecture and
implementation:
1. **Servers should be extremely easy to build**
* Host applications handle complex orchestration responsibilities
* Servers focus on specific, well-defined capabilities
* Simple interfaces minimize implementation overhead
* Clear separation enables maintainable code
2. **Servers should be highly composable**
* Each server provides focused functionality in isolation
* Multiple servers can be combined seamlessly
* Shared protocol enables interoperability
* Modular design supports extensibility
3. **Servers should not be able to read the whole conversation, nor "see into" other
servers**
* Servers receive only necessary contextual information
* Full conversation history stays with the host
* Each server connection maintains isolation
* Cross-server interactions are controlled by the host
* Host process enforces security boundaries
4. **Features can be added to servers and clients progressively**
* Core protocol provides minimal required functionality
* Additional capabilities can be negotiated as needed
* Servers and clients evolve independently
* Protocol designed for future extensibility
* Backwards compatibility is maintained
## Capability Negotiation
The Model Context Protocol uses a capability-based negotiation system where clients and
servers explicitly declare their supported features during initialization. Capabilities
determine which protocol features and primitives are available during a session.
* Servers declare capabilities like resource subscriptions, tool support, and prompt
templates
* Clients declare capabilities like sampling support and notification handling
* Both parties must respect declared capabilities throughout the session
* Additional capabilities can be negotiated through extensions to the protocol
```mermaid theme={null}
sequenceDiagram
participant Host
participant Client
participant Server
Host->>+Client: Initialize client
Client->>+Server: Initialize session with capabilities
Server-->>Client: Respond with supported capabilities
Note over Host,Server: Active Session with Negotiated Features
loop Client Requests
Host->>Client: User- or model-initiated action
Client->>Server: Request (tools/resources)
Server-->>Client: Response
Client-->>Host: Update UI or respond to model
end
loop Server Requests
Server->>Client: Request (sampling)
Client->>Host: Forward to AI
Host-->>Client: AI response
Client-->>Server: Response
end
loop Notifications
Server--)Client: Resource updates
Client--)Server: Status changes
end
Host->>Client: Terminate
Client->>-Server: End session
deactivate Server
```
Each capability unlocks specific protocol features for use during the session. For
example:
* Implemented [server features](/specification/2025-06-18/server) must be advertised in the
server's capabilities
* Emitting resource subscription notifications requires the server to declare
subscription support
* Tool invocation requires the server to declare tool capabilities
* [Sampling](/specification/2025-06-18/client/sampling) requires the client to declare support in its
capabilities
This capability negotiation ensures clients and servers have a clear understanding of
supported functionality while maintaining protocol extensibility.
specification/2025-06-18/basic/authorization New page · 371 lines, new page
# Authorization ## Introduction ### Purpose and Scope ### Protocol Requirements ### Standards Compliance ## Authorization Flow ### Roles ### Overview ### Authorization Server Discovery #### Authorization Server Location #### Server Metadata Discovery #### Sequence Diagram ### Dynamic Client Registration ### Authorization Flow Steps #### Resource Parameter Implementation ##### Canonical Server URI ### Access Token Usage #### Token Requirements #### Token Handling ### Error Handling ## Security Considerations ### Token Audience Binding and Validation ### Token Theft ### Communication Security ### Authorization Code Protection ### Open Redirection ### Confused Deputy Problem ### Access Token Privilege Restriction
A whole new page. There's nothing to diff it against, so here is what it says.
# Authorization
<div id="enable-section-numbers" />
## Introduction
### Purpose and Scope
The Model Context Protocol provides authorization capabilities at the transport level,
enabling MCP clients to make requests to restricted MCP servers on behalf of resource
owners. This specification defines the authorization flow for HTTP-based transports.
### Protocol Requirements
Authorization is **OPTIONAL** for MCP implementations. When supported:
* Implementations using an HTTP-based transport **SHOULD** conform to this specification.
* Implementations using an STDIO transport **SHOULD NOT** follow this specification, and
instead retrieve credentials from the environment.
* Implementations using alternative transports **MUST** follow established security best
practices for their protocol.
### Standards Compliance
This authorization mechanism is based on established specifications listed below, but
implements a selected subset of their features to ensure security and interoperability
while maintaining simplicity:
* OAuth 2.1 IETF DRAFT ([draft-ietf-oauth-v2-1-13](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-13))
* OAuth 2.0 Authorization Server Metadata
([RFC8414](https://datatracker.ietf.org/doc/html/rfc8414))
* OAuth 2.0 Dynamic Client Registration Protocol
([RFC7591](https://datatracker.ietf.org/doc/html/rfc7591))
* OAuth 2.0 Protected Resource Metadata ([RFC9728](https://datatracker.ietf.org/doc/html/rfc9728))
## Authorization Flow
### Roles
A protected *MCP server* acts as an [OAuth 2.1 resource server](https://www.ietf.org/archive/id/draft-ietf-oauth-v2-1-13.html#name-roles),
capable of accepting and responding to protected resource requests using access tokens.
An *MCP client* acts as an [OAuth 2.1 client](https://www.ietf.org/archive/id/draft-ietf-oauth-v2-1-13.html#name-roles),
making protected resource requests on behalf of a resource owner.
The *authorization server* is responsible for interacting with the user (if necessary) and issuing access tokens for use at the MCP server.
The implementation details of the authorization server are beyond the scope of this specification. It may be hosted with the
resource server or a separate entity. The [Authorization Server Discovery section](#authorization-server-discovery)
specifies how an MCP server indicates the location of its corresponding authorization server to a client.
### Overview
1. Authorization servers **MUST** implement OAuth 2.1 with appropriate security
measures for both confidential and public clients.
2. Authorization servers and MCP clients **SHOULD** support the OAuth 2.0 Dynamic Client Registration
Protocol ([RFC7591](https://datatracker.ietf.org/doc/html/rfc7591)).
3. MCP servers **MUST** implement OAuth 2.0 Protected Resource Metadata ([RFC9728](https://datatracker.ietf.org/doc/html/rfc9728)).
MCP clients **MUST** use OAuth 2.0 Protected Resource Metadata for authorization server discovery.
4. Authorization servers **MUST** provide OAuth 2.0 Authorization
Server Metadata ([RFC8414](https://datatracker.ietf.org/doc/html/rfc8414)).
MCP clients **MUST** use the OAuth 2.0 Authorization Server Metadata.
### Authorization Server Discovery
This section describes the mechanisms by which MCP servers advertise their associated
authorization servers to MCP clients, as well as the discovery process through which MCP
clients can determine authorization server endpoints and supported capabilities.
#### Authorization Server Location
MCP servers **MUST** implement the OAuth 2.0 Protected Resource Metadata ([RFC9728](https://datatracker.ietf.org/doc/html/rfc9728))
specification to indicate the locations of authorization servers. The Protected Resource Metadata document returned by the MCP server **MUST** include
the `authorization_servers` field containing at least one authorization server.
The specific use of `authorization_servers` is beyond the scope of this specification; implementers should consult
OAuth 2.0 Protected Resource Metadata ([RFC9728](https://datatracker.ietf.org/doc/html/rfc9728)) for
guidance on implementation details.
Implementors should note that Protected Resource Metadata documents can define multiple authorization servers. The responsibility for selecting which authorization server to use lies with the MCP client, following the guidelines specified in
[RFC9728 Section 7.6 "Authorization Servers"](https://datatracker.ietf.org/doc/html/rfc9728#name-authorization-servers).
MCP servers **MUST** use the HTTP header `WWW-Authenticate` when returning a *401 Unauthorized* to indicate the location of the resource server metadata URL
as described in [RFC9728 Section 5.1 "WWW-Authenticate Response"](https://datatracker.ietf.org/doc/html/rfc9728#name-www-authenticate-response).
MCP clients **MUST** be able to parse `WWW-Authenticate` headers and respond appropriately to `HTTP 401 Unauthorized` responses from the MCP server.
#### Server Metadata Discovery
MCP clients **MUST** follow the OAuth 2.0 Authorization Server Metadata [RFC8414](https://datatracker.ietf.org/doc/html/rfc8414)
specification to obtain the information required to interact with the authorization server.
#### Sequence Diagram
The following diagram outlines an example flow:
```mermaid theme={null}
sequenceDiagram
participant C as Client
participant M as MCP Server (Resource Server)
participant A as Authorization Server
C->>M: MCP request without token
M-->>C: HTTP 401 Unauthorized with WWW-Authenticate header
Note over C: Extract resource_metadata<br />from WWW-Authenticate
C->>M: GET /.well-known/oauth-protected-resource
M-->>C: Resource metadata with authorization server URL
Note over C: Validate RS metadata,<br />build AS metadata URL
C->>A: GET /.well-known/oauth-authorization-server
A-->>C: Authorization server metadata
Note over C,A: OAuth 2.1 authorization flow happens here
C->>A: Token request
A-->>C: Access token
C->>M: MCP request with access token
M-->>C: MCP response
Note over C,M: MCP communication continues with valid token
```
### Dynamic Client Registration
MCP clients and authorization servers **SHOULD** support the
OAuth 2.0 Dynamic Client Registration Protocol [RFC7591](https://datatracker.ietf.org/doc/html/rfc7591)
to allow MCP clients to obtain OAuth client IDs without user interaction. This provides a
standardized way for clients to automatically register with new authorization servers, which is crucial
for MCP because:
* Clients may not know all possible MCP servers and their authorization servers in advance.
* Manual registration would create friction for users.
* It enables seamless connection to new MCP servers and their authorization servers.
* Authorization servers can implement their own registration policies.
Any authorization servers that *do not* support Dynamic Client Registration need to provide
alternative ways to obtain a client ID (and, if applicable, client credentials). For one of
these authorization servers, MCP clients will have to either:
1. Hardcode a client ID (and, if applicable, client credentials) specifically for the MCP client to use when
interacting with that authorization server, or
2. Present a UI to users that allows them to enter these details, after registering an
OAuth client themselves (e.g., through a configuration interface hosted by the
server).
### Authorization Flow Steps
The complete Authorization flow proceeds as follows:
```mermaid theme={null}
sequenceDiagram
participant B as User-Agent (Browser)
participant C as Client
participant M as MCP Server (Resource Server)
participant A as Authorization Server
C->>M: MCP request without token
M->>C: HTTP 401 Unauthorized with WWW-Authenticate header
Note over C: Extract resource_metadata URL from WWW-Authenticate
C->>M: Request Protected Resource Metadata
M->>C: Return metadata
Note over C: Parse metadata and extract authorization server(s)<br/>Client determines AS to use
C->>A: GET /.well-known/oauth-authorization-server
A->>C: Authorization server metadata response
alt Dynamic client registration
C->>A: POST /register
A->>C: Client Credentials
end
Note over C: Generate PKCE parameters<br/>Include resource parameter
C->>B: Open browser with authorization URL + code_challenge + resource
B->>A: Authorization request with resource parameter
Note over A: User authorizes
A->>B: Redirect to callback with authorization code
B->>C: Authorization code callback
C->>A: Token request + code_verifier + resource
A->>C: Access token (+ refresh token)
C->>M: MCP request with access token
M-->>C: MCP response
Note over C,M: MCP communication continues with valid token
```
#### Resource Parameter Implementation
MCP clients **MUST** implement Resource Indicators for OAuth 2.0 as defined in [RFC 8707](https://www.rfc-editor.org/rfc/rfc8707.html)
to explicitly specify the target resource for which the token is being requested. The `resource` parameter:
1. **MUST** be included in both authorization requests and token requests.
2. **MUST** identify the MCP server that the client intends to use the token with.
3. **MUST** use the canonical URI of the MCP server as defined in [RFC 8707 Section 2](https://www.rfc-editor.org/rfc/rfc8707.html#name-access-token-request).
##### Canonical Server URI
For the purposes of this specification, the canonical URI of an MCP server is defined as the resource identifier as specified in
[RFC 8707 Section 2](https://www.rfc-editor.org/rfc/rfc8707.html#section-2) and aligns with the `resource` parameter in
[RFC 9728](https://datatracker.ietf.org/doc/html/rfc9728).
MCP clients **SHOULD** provide the most specific URI that they can for the MCP server they intend to access, following the guidance in [RFC 8707](https://www.rfc-editor.org/rfc/rfc8707). While the canonical form uses lowercase scheme and host components, implementations **SHOULD** accept uppercase scheme and host components for robustness and interoperability.
Examples of valid canonical URIs:
* `https://mcp.example.com/mcp`
* `https://mcp.example.com`
* `https://mcp.example.com:8443`
* `https://mcp.example.com/server/mcp` (when path component is necessary to identify individual MCP server)
Examples of invalid canonical URIs:
* `mcp.example.com` (missing scheme)
* `https://mcp.example.com#fragment` (contains fragment)
> **Note:** While both `https://mcp.example.com/` (with trailing slash) and `https://mcp.example.com` (without trailing slash) are technically valid absolute URIs according to [RFC 3986](https://www.rfc-editor.org/rfc/rfc3986), implementations **SHOULD** consistently use the form without the trailing slash for better interoperability unless the trailing slash is semantically significant for the specific resource.
For example, if accessing an MCP server at `https://mcp.example.com`, the authorization request would include:
```
&resource=https%3A%2F%2Fmcp.example.com
```
MCP clients **MUST** send this parameter regardless of whether authorization servers support it.
### Access Token Usage
#### Token Requirements
Access token handling when making requests to MCP servers **MUST** conform to the requirements defined in
[OAuth 2.1 Section 5 "Resource Requests"](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-13#section-5).
Specifically:
1. MCP client **MUST** use the Authorization request header field defined in
[OAuth 2.1 Section 5.1.1](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-13#section-5.1.1):
```
Authorization: Bearer <access-token>
```
Note that authorization **MUST** be included in every HTTP request from client to server,
even if they are part of the same logical session.
2. Access tokens **MUST NOT** be included in the URI query string
Example request:
```http theme={null}
GET /mcp HTTP/1.1
Host: mcp.example.com
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
```
#### Token Handling
MCP servers, acting in their role as an OAuth 2.1 resource server, **MUST** validate access tokens as described in
[OAuth 2.1 Section 5.2](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-13#section-5.2).
MCP servers **MUST** validate that access tokens were issued specifically for them as the intended audience,
according to [RFC 8707 Section 2](https://www.rfc-editor.org/rfc/rfc8707.html#section-2).
If validation fails, servers **MUST** respond according to
[OAuth 2.1 Section 5.3](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-13#section-5.3)
error handling requirements. Invalid or expired tokens **MUST** receive a HTTP 401
response.
MCP clients **MUST NOT** send tokens to the MCP server other than ones issued by the MCP server's authorization server.
Authorization servers **MUST** only accept tokens that are valid for use with their
own resources.
MCP servers **MUST NOT** accept or transit any other tokens.
### Error Handling
Servers **MUST** return appropriate HTTP status codes for authorization errors:
| Status Code | Description | Usage |
| ----------- | ------------ | ------------------------------------------ |
| 401 | Unauthorized | Authorization required or token invalid |
| 403 | Forbidden | Invalid scopes or insufficient permissions |
| 400 | Bad Request | Malformed authorization request |
## Security Considerations
Implementations **MUST** follow OAuth 2.1 security best practices as laid out in [OAuth 2.1 Section 7. "Security Considerations"](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-13#name-security-considerations).
### Token Audience Binding and Validation
[RFC 8707](https://www.rfc-editor.org/rfc/rfc8707.html) Resource Indicators provide critical security benefits by binding tokens to their intended
audiences **when the Authorization Server supports the capability**. To enable current and future adoption:
* MCP clients **MUST** include the `resource` parameter in authorization and token requests as specified in the [Resource Parameter Implementation](#resource-parameter-implementation) section
* MCP servers **MUST** validate that tokens presented to them were specifically issued for their use
The [Security Best Practices document](/specification/2025-06-18/basic/security_best_practices#token-passthrough)
outlines why token audience validation is crucial and why token passthrough is explicitly forbidden.
### Token Theft
Cut at 300 lines. The page has the rest.
specification/2025-06-18/basic/index New page · 145 lines, new page
# Overview ## Messages ### Requests ### Responses ### Notifications ## Auth ## Schema ### General fields #### `_meta`
A whole new page. There's nothing to diff it against, so here is what it says.
# Overview
<div id="enable-section-numbers" />
The Model Context Protocol consists of several key components that work together:
* **Base Protocol**: Core JSON-RPC message types
* **Lifecycle Management**: Connection initialization, capability negotiation, and
session control
* **Authorization**: Authentication and authorization framework for HTTP-based transports
* **Server Features**: Resources, prompts, and tools exposed by servers
* **Client Features**: Sampling and root directory lists provided by clients
* **Utilities**: Cross-cutting concerns like logging and argument completion
All implementations **MUST** support the base protocol and lifecycle management
components. Other components **MAY** be implemented based on the specific needs of the
application.
These protocol layers establish clear separation of concerns while enabling rich
interactions between clients and servers. The modular design allows implementations to
support exactly the features they need.
## Messages
All messages between MCP clients and servers **MUST** follow the
[JSON-RPC 2.0](https://www.jsonrpc.org/specification) specification. The protocol defines
these types of messages:
### Requests
Requests are sent from the client to the server or vice versa, to initiate an operation.
```typescript theme={null}
{
jsonrpc: "2.0";
id: string | number;
method: string;
params?: {
[key: string]: unknown;
};
}
```
* Requests **MUST** include a string or integer ID.
* Unlike base JSON-RPC, the ID **MUST NOT** be `null`.
* The request ID **MUST NOT** have been previously used by the requestor within the same
session.
### Responses
Responses are sent in reply to requests, containing the result or error of the operation.
```typescript theme={null}
{
jsonrpc: "2.0";
id: string | number;
result?: {
[key: string]: unknown;
}
error?: {
code: number;
message: string;
data?: unknown;
}
}
```
* Responses **MUST** include the same ID as the request they correspond to.
* **Responses** are further sub-categorized as either **successful results** or
**errors**. Either a `result` or an `error` **MUST** be set. A response **MUST NOT**
set both.
* Results **MAY** follow any JSON object structure, while errors **MUST** include an
error code and message at minimum.
* Error codes **MUST** be integers.
### Notifications
Notifications are sent from the client to the server or vice versa, as a one-way message.
The receiver **MUST NOT** send a response.
```typescript theme={null}
{
jsonrpc: "2.0";
method: string;
params?: {
[key: string]: unknown;
};
}
```
* Notifications **MUST NOT** include an ID.
## Auth
MCP provides an [Authorization](/specification/2025-06-18/basic/authorization) framework for use with HTTP.
Implementations using an HTTP-based transport **SHOULD** conform to this specification,
whereas implementations using STDIO transport **SHOULD NOT** follow this specification,
and instead retrieve credentials from the environment.
Additionally, clients and servers **MAY** negotiate their own custom authentication and
authorization strategies.
For further discussions and contributions to the evolution of MCP’s auth mechanisms, join
us in
[GitHub Discussions](https://github.com/modelcontextprotocol/specification/discussions)
to help shape the future of the protocol!
## Schema
The full specification of the protocol is defined as a
[TypeScript schema](https://github.com/modelcontextprotocol/specification/blob/main/schema/2025-06-18/schema.ts).
This is the source of truth for all protocol messages and structures.
There is also a
[JSON Schema](https://github.com/modelcontextprotocol/specification/blob/main/schema/2025-06-18/schema.json),
which is automatically generated from the TypeScript source of truth, for use with
various automated tooling.
### General fields
#### `_meta`
The `_meta` property/parameter is reserved by MCP to allow clients and servers
to attach additional metadata to their interactions.
Certain key names are reserved by MCP for protocol-level metadata, as specified below;
implementations MUST NOT make assumptions about values at these keys.
Additionally, definitions in the [schema](https://github.com/modelcontextprotocol/specification/blob/main/schema/2025-06-18/schema.ts)
may reserve particular names for purpose-specific metadata, as declared in those definitions.
**Key name format:** valid `_meta` key names have two segments: an optional **prefix**, and a **name**.
**Prefix:**
* If specified, MUST be a series of labels separated by dots (`.`), followed by a slash (`/`).
* Labels MUST start with a letter and end with a letter or digit; interior characters can be letters, digits, or hyphens (`-`).
* Any prefix beginning with zero or more valid labels, followed by `modelcontextprotocol` or `mcp`, followed by any valid label,
is **reserved** for MCP use.
* For example: `modelcontextprotocol.io/`, `mcp.dev/`, `api.modelcontextprotocol.org/`, and `tools.mcp.com/` are all reserved.
**Name:**
* Unless empty, MUST begin and end with an alphanumeric character (`[a-z0-9A-Z]`).
* MAY contain hyphens (`-`), underscores (`_`), dots (`.`), and alphanumerics in between.
specification/2025-06-18/basic/lifecycle New page · 241 lines, new page
# Lifecycle ## Lifecycle Phases ### Initialization #### Version Negotiation #### Capability Negotiation ### Operation ### Shutdown #### stdio #### HTTP ## Timeouts ## Error Handling
A whole new page. There's nothing to diff it against, so here is what it says.
# Lifecycle
<div id="enable-section-numbers" />
The Model Context Protocol (MCP) defines a rigorous lifecycle for client-server
connections that ensures proper capability negotiation and state management.
1. **Initialization**: Capability negotiation and protocol version agreement
2. **Operation**: Normal protocol communication
3. **Shutdown**: Graceful termination of the connection
```mermaid theme={null}
sequenceDiagram
participant Client
participant Server
Note over Client,Server: Initialization Phase
activate Client
Client->>+Server: initialize request
Server-->>Client: initialize response
Client--)Server: initialized notification
Note over Client,Server: Operation Phase
rect rgb(200, 220, 250)
note over Client,Server: Normal protocol operations
end
Note over Client,Server: Shutdown
Client--)-Server: Disconnect
deactivate Server
Note over Client,Server: Connection closed
```
## Lifecycle Phases
### Initialization
The initialization phase **MUST** be the first interaction between client and server.
During this phase, the client and server:
* Establish protocol version compatibility
* Exchange and negotiate capabilities
* Share implementation details
The client **MUST** initiate this phase by sending an `initialize` request containing:
* Protocol version supported
* Client capabilities
* Client implementation information
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2025-06-18",
"capabilities": {
"roots": {
"listChanged": true
},
"sampling": {},
"elicitation": {}
},
"clientInfo": {
"name": "ExampleClient",
"title": "Example Client Display Name",
"version": "1.0.0"
}
}
}
```
The server **MUST** respond with its own capabilities and information:
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"protocolVersion": "2025-06-18",
"capabilities": {
"logging": {},
"prompts": {
"listChanged": true
},
"resources": {
"subscribe": true,
"listChanged": true
},
"tools": {
"listChanged": true
}
},
"serverInfo": {
"name": "ExampleServer",
"title": "Example Server Display Name",
"version": "1.0.0"
},
"instructions": "Optional instructions for the client"
}
}
```
After successful initialization, the client **MUST** send an `initialized` notification
to indicate it is ready to begin normal operations:
```json theme={null}
{
"jsonrpc": "2.0",
"method": "notifications/initialized"
}
```
* The client **SHOULD NOT** send requests other than
[pings](/specification/2025-06-18/basic/utilities/ping) before the server has responded to the
`initialize` request.
* The server **SHOULD NOT** send requests other than
[pings](/specification/2025-06-18/basic/utilities/ping) and
[logging](/specification/2025-06-18/server/utilities/logging) before receiving the `initialized`
notification.
#### Version Negotiation
In the `initialize` request, the client **MUST** send a protocol version it supports.
This **SHOULD** be the *latest* version supported by the client.
If the server supports the requested protocol version, it **MUST** respond with the same
version. Otherwise, the server **MUST** respond with another protocol version it
supports. This **SHOULD** be the *latest* version supported by the server.
If the client does not support the version in the server's response, it **SHOULD**
disconnect.
<Note>
If using HTTP, the client **MUST** include the `MCP-Protocol-Version: <protocol-version>` HTTP header on all subsequent requests to the MCP
server.
For details, see [the Protocol Version Header section in Transports](/specification/2025-06-18/basic/transports#protocol-version-header).
</Note>
#### Capability Negotiation
Client and server capabilities establish which optional protocol features will be
available during the session.
Key capabilities include:
| Category | Capability | Description |
| -------- | -------------- | ----------------------------------------------------------------------------------------- |
| Client | `roots` | Ability to provide filesystem [roots](/specification/2025-06-18/client/roots) |
| Client | `sampling` | Support for LLM [sampling](/specification/2025-06-18/client/sampling) requests |
| Client | `elicitation` | Support for server [elicitation](/specification/2025-06-18/client/elicitation) requests |
| Client | `experimental` | Describes support for non-standard experimental features |
| Server | `prompts` | Offers [prompt templates](/specification/2025-06-18/server/prompts) |
| Server | `resources` | Provides readable [resources](/specification/2025-06-18/server/resources) |
| Server | `tools` | Exposes callable [tools](/specification/2025-06-18/server/tools) |
| Server | `logging` | Emits structured [log messages](/specification/2025-06-18/server/utilities/logging) |
| Server | `completions` | Supports argument [autocompletion](/specification/2025-06-18/server/utilities/completion) |
| Server | `experimental` | Describes support for non-standard experimental features |
Capability objects can describe sub-capabilities like:
* `listChanged`: Support for list change notifications (for prompts, resources, and
tools)
* `subscribe`: Support for subscribing to individual items' changes (resources only)
### Operation
During the operation phase, the client and server exchange messages according to the
negotiated capabilities.
Both parties **MUST**:
* Respect the negotiated protocol version
* Only use capabilities that were successfully negotiated
### Shutdown
During the shutdown phase, one side (usually the client) cleanly terminates the protocol
connection. No specific shutdown messages are defined—instead, the underlying transport
mechanism should be used to signal connection termination:
#### stdio
For the stdio [transport](/specification/2025-06-18/basic/transports), the client **SHOULD** initiate
shutdown by:
1. First, closing the input stream to the child process (the server)
2. Waiting for the server to exit, or sending `SIGTERM` if the server does not exit
within a reasonable time
3. Sending `SIGKILL` if the server does not exit within a reasonable time after `SIGTERM`
The server **MAY** initiate shutdown by closing its output stream to the client and
exiting.
#### HTTP
For HTTP [transports](/specification/2025-06-18/basic/transports), shutdown is indicated by closing the
associated HTTP connection(s).
## Timeouts
Implementations **SHOULD** establish timeouts for all sent requests, to prevent hung
connections and resource exhaustion. When the request has not received a success or error
response within the timeout period, the sender **SHOULD** issue a [cancellation
notification](/specification/2025-06-18/basic/utilities/cancellation) for that request and stop waiting for
a response.
SDKs and other middleware **SHOULD** allow these timeouts to be configured on a
per-request basis.
Implementations **MAY** choose to reset the timeout clock when receiving a [progress
notification](/specification/2025-06-18/basic/utilities/progress) corresponding to the request, as this
implies that work is actually happening. However, implementations **SHOULD** always
enforce a maximum timeout, regardless of progress notifications, to limit the impact of a
misbehaving client or server.
## Error Handling
Implementations **SHOULD** be prepared to handle these error cases:
* Protocol version mismatch
* Failure to negotiate required capabilities
* Request [timeouts](#timeouts)
Example initialization error:
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32602,
"message": "Unsupported protocol version",
"data": {
"supported": ["2024-11-05"],
"requested": "1.0.0"
}
}
}
```
specification/2025-06-18/basic/transports New page · 292 lines, new page
# Transports ## stdio ## Streamable HTTP #### Security Warning ### Sending Messages to the Server ### Listening for Messages from the Server ### Multiple Connections ### Resumability and Redelivery ### Session Management ### Sequence Diagram ### Protocol Version Header ### Backwards Compatibility ## Custom Transports
A whole new page. There's nothing to diff it against, so here is what it says.
# Transports
<div id="enable-section-numbers" />
MCP uses JSON-RPC to encode messages. JSON-RPC messages **MUST** be UTF-8 encoded.
The protocol currently defines two standard transport mechanisms for client-server
communication:
1. [stdio](#stdio), communication over standard in and standard out
2. [Streamable HTTP](#streamable-http)
Clients **SHOULD** support stdio whenever possible.
It is also possible for clients and servers to implement
[custom transports](#custom-transports) in a pluggable fashion.
## stdio
In the **stdio** transport:
* The client launches the MCP server as a subprocess.
* The server reads JSON-RPC messages from its standard input (`stdin`) and sends messages
to its standard output (`stdout`).
* Messages are individual JSON-RPC requests, notifications, or responses.
* Messages are delimited by newlines, and **MUST NOT** contain embedded newlines.
* The server **MAY** write UTF-8 strings to its standard error (`stderr`) for logging
purposes. Clients **MAY** capture, forward, or ignore this logging.
* The server **MUST NOT** write anything to its `stdout` that is not a valid MCP message.
* The client **MUST NOT** write anything to the server's `stdin` that is not a valid MCP
message.
```mermaid theme={null}
sequenceDiagram
participant Client
participant Server Process
Client->>+Server Process: Launch subprocess
loop Message Exchange
Client->>Server Process: Write to stdin
Server Process->>Client: Write to stdout
Server Process--)Client: Optional logs on stderr
end
Client->>Server Process: Close stdin, terminate subprocess
deactivate Server Process
```
## Streamable HTTP
<Info>
This replaces the [HTTP+SSE
transport](/specification/2024-11-05/basic/transports#http-with-sse) from
protocol version 2024-11-05. See the [backwards compatibility](#backwards-compatibility)
guide below.
</Info>
In the **Streamable HTTP** transport, the server operates as an independent process that
can handle multiple client connections. This transport uses HTTP POST and GET requests.
Server can optionally make use of
[Server-Sent Events](https://en.wikipedia.org/wiki/Server-sent_events) (SSE) to stream
multiple server messages. This permits basic MCP servers, as well as more feature-rich
servers supporting streaming and server-to-client notifications and requests.
The server **MUST** provide a single HTTP endpoint path (hereafter referred to as the
**MCP endpoint**) that supports both POST and GET methods. For example, this could be a
URL like `https://example.com/mcp`.
#### Security Warning
When implementing Streamable HTTP transport:
1. Servers **MUST** validate the `Origin` header on all incoming connections to prevent DNS rebinding attacks
2. When running locally, servers **SHOULD** bind only to localhost (127.0.0.1) rather than all network interfaces (0.0.0.0)
3. Servers **SHOULD** implement proper authentication for all connections
Without these protections, attackers could use DNS rebinding to interact with local MCP servers from remote websites.
### Sending Messages to the Server
Every JSON-RPC message sent from the client **MUST** be a new HTTP POST request to the
MCP endpoint.
1. The client **MUST** use HTTP POST to send JSON-RPC messages to the MCP endpoint.
2. The client **MUST** include an `Accept` header, listing both `application/json` and
`text/event-stream` as supported content types.
3. The body of the POST request **MUST** be a single JSON-RPC *request*, *notification*, or *response*.
4. If the input is a JSON-RPC *response* or *notification*:
* If the server accepts the input, the server **MUST** return HTTP status code 202
Accepted with no body.
* If the server cannot accept the input, it **MUST** return an HTTP error status code
(e.g., 400 Bad Request). The HTTP response body **MAY** comprise a JSON-RPC *error
response* that has no `id`.
5. If the input is a JSON-RPC *request*, the server **MUST** either
return `Content-Type: text/event-stream`, to initiate an SSE stream, or
`Content-Type: application/json`, to return one JSON object. The client **MUST**
support both these cases.
6. If the server initiates an SSE stream:
* The SSE stream **SHOULD** eventually include JSON-RPC *response* for the
JSON-RPC *request* sent in the POST body.
* The server **MAY** send JSON-RPC *requests* and *notifications* before sending the
JSON-RPC *response*. These messages **SHOULD** relate to the originating client
*request*.
* The server **SHOULD NOT** close the SSE stream before sending the JSON-RPC *response*
for the received JSON-RPC *request*, unless the [session](#session-management)
expires.
* After the JSON-RPC *response* has been sent, the server **SHOULD** close the SSE
stream.
* Disconnection **MAY** occur at any time (e.g., due to network conditions).
Therefore:
* Disconnection **SHOULD NOT** be interpreted as the client cancelling its request.
* To cancel, the client **SHOULD** explicitly send an MCP `CancelledNotification`.
* To avoid message loss due to disconnection, the server **MAY** make the stream
[resumable](#resumability-and-redelivery).
### Listening for Messages from the Server
1. The client **MAY** issue an HTTP GET to the MCP endpoint. This can be used to open an
SSE stream, allowing the server to communicate to the client, without the client first
sending data via HTTP POST.
2. The client **MUST** include an `Accept` header, listing `text/event-stream` as a
supported content type.
3. The server **MUST** either return `Content-Type: text/event-stream` in response to
this HTTP GET, or else return HTTP 405 Method Not Allowed, indicating that the server
does not offer an SSE stream at this endpoint.
4. If the server initiates an SSE stream:
* The server **MAY** send JSON-RPC *requests* and *notifications* on the stream.
* These messages **SHOULD** be unrelated to any concurrently-running JSON-RPC
*request* from the client.
* The server **MUST NOT** send a JSON-RPC *response* on the stream **unless**
[resuming](#resumability-and-redelivery) a stream associated with a previous client
request.
* The server **MAY** close the SSE stream at any time.
* The client **MAY** close the SSE stream at any time.
### Multiple Connections
1. The client **MAY** remain connected to multiple SSE streams simultaneously.
2. The server **MUST** send each of its JSON-RPC messages on only one of the connected
streams; that is, it **MUST NOT** broadcast the same message across multiple streams.
* The risk of message loss **MAY** be mitigated by making the stream
[resumable](#resumability-and-redelivery).
### Resumability and Redelivery
To support resuming broken connections, and redelivering messages that might otherwise be
lost:
1. Servers **MAY** attach an `id` field to their SSE events, as described in the
[SSE standard](https://html.spec.whatwg.org/multipage/server-sent-events.html#event-stream-interpretation).
* If present, the ID **MUST** be globally unique across all streams within that
[session](#session-management)—or all streams with that specific client, if session
management is not in use.
2. If the client wishes to resume after a broken connection, it **SHOULD** issue an HTTP
GET to the MCP endpoint, and include the
[`Last-Event-ID`](https://html.spec.whatwg.org/multipage/server-sent-events.html#the-last-event-id-header)
header to indicate the last event ID it received.
* The server **MAY** use this header to replay messages that would have been sent
after the last event ID, *on the stream that was disconnected*, and to resume the
stream from that point.
* The server **MUST NOT** replay messages that would have been delivered on a
different stream.
In other words, these event IDs should be assigned by servers on a *per-stream* basis, to
act as a cursor within that particular stream.
### Session Management
An MCP "session" consists of logically related interactions between a client and a
server, beginning with the [initialization phase](/specification/2025-06-18/basic/lifecycle). To support
servers which want to establish stateful sessions:
1. A server using the Streamable HTTP transport **MAY** assign a session ID at
initialization time, by including it in an `Mcp-Session-Id` header on the HTTP
response containing the `InitializeResult`.
* The session ID **SHOULD** be globally unique and cryptographically secure (e.g., a
securely generated UUID, a JWT, or a cryptographic hash).
* The session ID **MUST** only contain visible ASCII characters (ranging from 0x21 to
0x7E).
2. If an `Mcp-Session-Id` is returned by the server during initialization, clients using
the Streamable HTTP transport **MUST** include it in the `Mcp-Session-Id` header on
all of their subsequent HTTP requests.
* Servers that require a session ID **SHOULD** respond to requests without an
`Mcp-Session-Id` header (other than initialization) with HTTP 400 Bad Request.
3. The server **MAY** terminate the session at any time, after which it **MUST** respond
to requests containing that session ID with HTTP 404 Not Found.
4. When a client receives HTTP 404 in response to a request containing an
`Mcp-Session-Id`, it **MUST** start a new session by sending a new `InitializeRequest`
without a session ID attached.
5. Clients that no longer need a particular session (e.g., because the user is leaving
the client application) **SHOULD** send an HTTP DELETE to the MCP endpoint with the
`Mcp-Session-Id` header, to explicitly terminate the session.
* The server **MAY** respond to this request with HTTP 405 Method Not Allowed,
indicating that the server does not allow clients to terminate sessions.
### Sequence Diagram
```mermaid theme={null}
sequenceDiagram
participant Client
participant Server
note over Client, Server: initialization
Client->>+Server: POST InitializeRequest
Server->>-Client: InitializeResponse<br>Mcp-Session-Id: 1868a90c...
Client->>+Server: POST InitializedNotification<br>Mcp-Session-Id: 1868a90c...
Server->>-Client: 202 Accepted
note over Client, Server: client requests
Client->>+Server: POST ... request ...<br>Mcp-Session-Id: 1868a90c...
alt single HTTP response
Server->>Client: ... response ...
else server opens SSE stream
loop while connection remains open
Server-)Client: ... SSE messages from server ...
end
Server-)Client: SSE event: ... response ...
end
deactivate Server
note over Client, Server: client notifications/responses
Client->>+Server: POST ... notification/response ...<br>Mcp-Session-Id: 1868a90c...
Server->>-Client: 202 Accepted
note over Client, Server: server requests
Client->>+Server: GET<br>Mcp-Session-Id: 1868a90c...
loop while connection remains open
Server-)Client: ... SSE messages from server ...
end
deactivate Server
```
### Protocol Version Header
If using HTTP, the client **MUST** include the `MCP-Protocol-Version: <protocol-version>` HTTP header on all subsequent requests to the MCP
server, allowing the MCP server to respond based on the MCP protocol version.
For example: `MCP-Protocol-Version: 2025-06-18`
The protocol version sent by the client **SHOULD** be the one [negotiated during
initialization](/specification/2025-06-18/basic/lifecycle#version-negotiation).
For backwards compatibility, if the server does *not* receive an `MCP-Protocol-Version`
header, and has no other way to identify the version - for example, by relying on the
protocol version negotiated during initialization - the server **SHOULD** assume protocol
version `2025-03-26`.
If the server receives a request with an invalid or unsupported
`MCP-Protocol-Version`, it **MUST** respond with `400 Bad Request`.
### Backwards Compatibility
Clients and servers can maintain backwards compatibility with the deprecated [HTTP+SSE
transport](/specification/2024-11-05/basic/transports#http-with-sse) (from
protocol version 2024-11-05) as follows:
**Servers** wanting to support older clients should:
* Continue to host both the SSE and POST endpoints of the old transport, alongside the
new "MCP endpoint" defined for the Streamable HTTP transport.
* It is also possible to combine the old POST endpoint and the new MCP endpoint, but
this may introduce unneeded complexity.
**Clients** wanting to support older servers should:
1. Accept an MCP server URL from the user, which may point to either a server using the
old transport or the new transport.
2. Attempt to POST an `InitializeRequest` to the server URL, with an `Accept` header as
defined above:
* If it succeeds, the client can assume this is a server supporting the new Streamable
HTTP transport.
* If it fails with an HTTP 4xx status code (e.g., 405 Method Not Allowed or 404 Not
Found):
* Issue a GET request to the server URL, expecting that this will open an SSE stream
and return an `endpoint` event as the first event.
* When the `endpoint` event arrives, the client can assume this is a server running
the old HTTP+SSE transport, and should use that transport for all subsequent
communication.
## Custom Transports
Clients and servers **MAY** implement additional custom transport mechanisms to suit
their specific needs. The protocol is transport-agnostic and can be implemented over any
communication channel that supports bidirectional message exchange.
Implementers who choose to support custom transports **MUST** ensure they preserve the
JSON-RPC message format and lifecycle requirements defined by MCP. Custom transports
**SHOULD** document their specific connection establishment and message exchange patterns
to aid interoperability.
specification/2025-06-18/basic/utilities/cancellation New page · 81 lines, new page
# Cancellation ## Cancellation Flow ## Behavior Requirements ## Timing Considerations ## Implementation Notes ## Error Handling
A whole new page. There's nothing to diff it against, so here is what it says.
# Cancellation
<div id="enable-section-numbers" />
The Model Context Protocol (MCP) supports optional cancellation of in-progress requests
through notification messages. Either side can send a cancellation notification to
indicate that a previously-issued request should be terminated.
## Cancellation Flow
When a party wants to cancel an in-progress request, it sends a `notifications/cancelled`
notification containing:
* The ID of the request to cancel
* An optional reason string that can be logged or displayed
```json theme={null}
{
"jsonrpc": "2.0",
"method": "notifications/cancelled",
"params": {
"requestId": "123",
"reason": "User requested cancellation"
}
}
```
## Behavior Requirements
1. Cancellation notifications **MUST** only reference requests that:
* Were previously issued in the same direction
* Are believed to still be in-progress
2. The `initialize` request **MUST NOT** be cancelled by clients
3. Receivers of cancellation notifications **SHOULD**:
* Stop processing the cancelled request
* Free associated resources
* Not send a response for the cancelled request
4. Receivers **MAY** ignore cancellation notifications if:
* The referenced request is unknown
* Processing has already completed
* The request cannot be cancelled
5. The sender of the cancellation notification **SHOULD** ignore any response to the
request that arrives afterward
## Timing Considerations
Due to network latency, cancellation notifications may arrive after request processing
has completed, and potentially after a response has already been sent.
Both parties **MUST** handle these race conditions gracefully:
```mermaid theme={null}
sequenceDiagram
participant Client
participant Server
Client->>Server: Request (ID: 123)
Note over Server: Processing starts
Client--)Server: notifications/cancelled (ID: 123)
alt
Note over Server: Processing may have<br/>completed before<br/>cancellation arrives
else If not completed
Note over Server: Stop processing
end
```
## Implementation Notes
* Both parties **SHOULD** log cancellation reasons for debugging
* Application UIs **SHOULD** indicate when cancellation is requested
## Error Handling
Invalid cancellation notifications **SHOULD** be ignored:
* Unknown request IDs
* Already completed requests
* Malformed notifications
This maintains the "fire and forget" nature of notifications while allowing for race
conditions in asynchronous communication.
specification/2025-06-18/basic/utilities/ping New page · 64 lines, new page
# Ping ## Overview ## Message Format ## Behavior Requirements ## Usage Patterns ## Implementation Considerations ## Error Handling
A whole new page. There's nothing to diff it against, so here is what it says.
# Ping
<div id="enable-section-numbers" />
The Model Context Protocol includes an optional ping mechanism that allows either party
to verify that their counterpart is still responsive and the connection is alive.
## Overview
The ping functionality is implemented through a simple request/response pattern. Either
the client or server can initiate a ping by sending a `ping` request.
## Message Format
A ping request is a standard JSON-RPC request with no parameters:
```json theme={null}
{
"jsonrpc": "2.0",
"id": "123",
"method": "ping"
}
```
## Behavior Requirements
1. The receiver **MUST** respond promptly with an empty response:
```json theme={null}
{
"jsonrpc": "2.0",
"id": "123",
"result": {}
}
```
2. If no response is received within a reasonable timeout period, the sender **MAY**:
* Consider the connection stale
* Terminate the connection
* Attempt reconnection procedures
## Usage Patterns
```mermaid theme={null}
sequenceDiagram
participant Sender
participant Receiver
Sender->>Receiver: ping request
Receiver->>Sender: empty response
```
## Implementation Considerations
* Implementations **SHOULD** periodically issue pings to detect connection health
* The frequency of pings **SHOULD** be configurable
* Timeouts **SHOULD** be appropriate for the network environment
* Excessive pinging **SHOULD** be avoided to reduce network overhead
## Error Handling
* Timeouts **SHOULD** be treated as connection failures
* Multiple failed pings **MAY** trigger connection reset
* Implementations **SHOULD** log ping failures for diagnostics
specification/2025-06-18/basic/utilities/progress New page · 88 lines, new page
# Progress ## Progress Flow ## Behavior Requirements ## Implementation Notes
A whole new page. There's nothing to diff it against, so here is what it says.
# Progress
<div id="enable-section-numbers" />
The Model Context Protocol (MCP) supports optional progress tracking for long-running
operations through notification messages. Either side can send progress notifications to
provide updates about operation status.
## Progress Flow
When a party wants to *receive* progress updates for a request, it includes a
`progressToken` in the request metadata.
* Progress tokens **MUST** be a string or integer value
* Progress tokens can be chosen by the sender using any means, but **MUST** be unique
across all active requests.
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"method": "some_method",
"params": {
"_meta": {
"progressToken": "abc123"
}
}
}
```
The receiver **MAY** then send progress notifications containing:
* The original progress token
* The current progress value so far
* An optional "total" value
* An optional "message" value
```json theme={null}
{
"jsonrpc": "2.0",
"method": "notifications/progress",
"params": {
"progressToken": "abc123",
"progress": 50,
"total": 100,
"message": "Reticulating splines..."
}
}
```
* The `progress` value **MUST** increase with each notification, even if the total is
unknown.
* The `progress` and the `total` values **MAY** be floating point.
* The `message` field **SHOULD** provide relevant human readable progress information.
## Behavior Requirements
1. Progress notifications **MUST** only reference tokens that:
* Were provided in an active request
* Are associated with an in-progress operation
2. Receivers of progress requests **MAY**:
* Choose not to send any progress notifications
* Send notifications at whatever frequency they deem appropriate
* Omit the total value if unknown
```mermaid theme={null}
sequenceDiagram
participant Sender
participant Receiver
Note over Sender,Receiver: Request with progress token
Sender->>Receiver: Method request with progressToken
Note over Sender,Receiver: Progress updates
Receiver-->>Sender: Progress notification (0.2/1.0)
Receiver-->>Sender: Progress notification (0.6/1.0)
Receiver-->>Sender: Progress notification (1.0/1.0)
Note over Sender,Receiver: Operation complete
Receiver->>Sender: Method response
```
## Implementation Notes
* Senders and receivers **SHOULD** track active progress tokens
* Both parties **SHOULD** implement rate limiting to prevent flooding
* Progress notifications **MUST** stop after completion
specification/2025-06-18/changelog New page · 43 lines, new page
# Key Changes ## Major changes ## Other schema changes ## Full changelog
A whole new page. There's nothing to diff it against, so here is what it says.
# Key Changes <div id="enable-section-numbers" /> This document lists changes made to the Model Context Protocol (MCP) specification since the previous revision, [2025-03-26](/specification/2025-03-26). ## Major changes 1. Remove support for JSON-RPC **[batching](https://www.jsonrpc.org/specification#batch)** (PR [#416](https://github.com/modelcontextprotocol/specification/pull/416)) 2. Add support for [structured tool output](/specification/2025-06-18/server/tools#structured-content) (PR [#371](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/371)) 3. Classify MCP servers as [OAuth Resource Servers](/specification/2025-06-18/basic/authorization#authorization-server-discovery), adding protected resource metadata to discover the corresponding Authorization server. (PR [#338](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/338)) 4. Require MCP clients to implement Resource Indicators as described in [RFC 8707](https://www.rfc-editor.org/rfc/rfc8707.html) to prevent malicious servers from obtaining access tokens. (PR [#734](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/734)) 5. Clarify [security considerations](/specification/2025-06-18/basic/authorization#security-considerations) and best practices in the authorization spec and in a new [security best practices page](/specification/2025-06-18/basic/security_best_practices). 6. Add support for **[elicitation](/specification/2025-06-18/client/elicitation)**, enabling servers to request additional information from users during interactions. (PR [#382](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/382)) 7. Add support for **[resource links](/specification/2025-06-18/server/tools#resource-links)** in tool call results. (PR [#603](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/603)) 8. Require [negotiated protocol version to be specified](/specification/2025-06-18/basic/transports#protocol-version-header) via `MCP-Protocol-Version` header in subsequent requests when using HTTP (PR [#548](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/548)). 9. Change **SHOULD** to **MUST** in [Lifecycle Operation](/specification/2025-06-18/basic/lifecycle#operation) ## Other schema changes 1. Add `_meta` field to additional interface types (PR [#710](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/710)), and specify [proper usage](/specification/2025-06-18/basic#meta). 2. Add `context` field to `CompletionRequest`, providing for completion requests to include previously-resolved variables (PR [#598](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/598)). 3. Add `title` field for human-friendly display names, so that `name` can be used as a programmatic identifier (PR [#663](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/663)) ## Full changelog For a complete list of all changes that have been made since the last protocol revision, [see GitHub](https://github.com/modelcontextprotocol/specification/compare/2025-03-26...2025-06-18).
specification/2025-06-18/client/elicitation New page · 321 lines, new page
# Elicitation ## User Interaction Model ## Capabilities ## Protocol Messages ### Creating Elicitation Requests #### Simple Text Request #### Structured Data Request ## Message Flow ## Request Schema ### Supported Schema Types ## Response Actions ## Security Considerations
A whole new page. There's nothing to diff it against, so here is what it says.
# Elicitation
<div id="enable-section-numbers" />
<Note>
Elicitation is newly introduced in this version of the MCP specification and its design may evolve in future protocol versions.
</Note>
The Model Context Protocol (MCP) provides a standardized way for servers to request additional
information from users through the client during interactions. This flow allows clients to
maintain control over user interactions and data sharing while enabling servers to gather
necessary information dynamically.
Servers request structured data from users with JSON schemas to validate responses.
## User Interaction Model
Elicitation in MCP allows servers to implement interactive workflows by enabling user input
requests to occur *nested* inside other MCP server features.
Implementations are free to expose elicitation through any interface pattern that suits
their needs—the protocol itself does not mandate any specific user interaction
model.
<Warning>
For trust & safety and security:
* Servers **MUST NOT** use elicitation to request sensitive information.
Applications **SHOULD**:
* Provide UI that makes it clear which server is requesting information
* Allow users to review and modify their responses before sending
* Respect user privacy and provide clear decline and cancel options
</Warning>
## Capabilities
Clients that support elicitation **MUST** declare the `elicitation` capability during
[initialization](/specification/2025-06-18/basic/lifecycle#initialization):
```json theme={null}
{
"capabilities": {
"elicitation": {}
}
}
```
## Protocol Messages
### Creating Elicitation Requests
To request information from a user, servers send an `elicitation/create` request:
#### Simple Text Request
**Request:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"method": "elicitation/create",
"params": {
"message": "Please provide your GitHub username",
"requestedSchema": {
"type": "object",
"properties": {
"name": {
"type": "string"
}
},
"required": ["name"]
}
}
}
```
**Response:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"action": "accept",
"content": {
"name": "octocat"
}
}
}
```
#### Structured Data Request
**Request:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 2,
"method": "elicitation/create",
"params": {
"message": "Please provide your contact information",
"requestedSchema": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Your full name"
},
"email": {
"type": "string",
"format": "email",
"description": "Your email address"
},
"age": {
"type": "number",
"minimum": 18,
"description": "Your age"
}
},
"required": ["name", "email"]
}
}
}
```
**Response:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"action": "accept",
"content": {
"name": "Monalisa Octocat",
"email": "[email protected]",
"age": 30
}
}
}
```
**Reject Response Example:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"action": "decline"
}
}
```
**Cancel Response Example:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"action": "cancel"
}
}
```
## Message Flow
```mermaid theme={null}
sequenceDiagram
participant User
participant Client
participant Server
Note over Server,Client: Server initiates elicitation
Server->>Client: elicitation/create
Note over Client,User: Human interaction
Client->>User: Present elicitation UI
User-->>Client: Provide requested information
Note over Server,Client: Complete request
Client-->>Server: Return user response
Note over Server: Continue processing with new information
```
## Request Schema
The `requestedSchema` field allows servers to define the structure of the expected response using a restricted subset of JSON Schema. To simplify implementation for clients, elicitation schemas are limited to flat objects with primitive properties only:
```json theme={null}
"requestedSchema": {
"type": "object",
"properties": {
"propertyName": {
"type": "string",
"title": "Display Name",
"description": "Description of the property"
},
"anotherProperty": {
"type": "number",
"minimum": 0,
"maximum": 100
}
},
"required": ["propertyName"]
}
```
### Supported Schema Types
The schema is restricted to these primitive types:
1. **String Schema**
```json theme={null}
{
"type": "string",
"title": "Display Name",
"description": "Description text",
"minLength": 3,
"maxLength": 50,
"format": "email" // Supported: "email", "uri", "date", "date-time"
}
```
Supported formats: `email`, `uri`, `date`, `date-time`
2. **Number Schema**
```json theme={null}
{
"type": "number", // or "integer"
"title": "Display Name",
"description": "Description text",
"minimum": 0,
"maximum": 100
}
```
3. **Boolean Schema**
```json theme={null}
{
"type": "boolean",
"title": "Display Name",
"description": "Description text",
"default": false
}
```
4. **Enum Schema**
```json theme={null}
{
"type": "string",
"title": "Display Name",
"description": "Description text",
"enum": ["option1", "option2", "option3"],
"enumNames": ["Option 1", "Option 2", "Option 3"]
}
```
Clients can use this schema to:
1. Generate appropriate input forms
2. Validate user input before sending
3. Provide better guidance to users
Note that complex nested structures, arrays of objects, and other advanced JSON Schema features are intentionally not supported to simplify client implementation.
## Response Actions
Elicitation responses use a three-action model to clearly distinguish between different user actions:
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"action": "accept", // or "decline" or "cancel"
"content": {
"propertyName": "value",
"anotherProperty": 42
}
}
}
```
The three response actions are:
1. **Accept** (`action: "accept"`): User explicitly approved and submitted with data
* The `content` field contains the submitted data matching the requested schema
* Example: User clicked "Submit", "OK", "Confirm", etc.
2. **Decline** (`action: "decline"`): User explicitly declined the request
* The `content` field is typically omitted
Cut at 300 lines. The page has the rest.
specification/2025-06-18/client/roots New page · 186 lines, new page
# Roots ## User Interaction Model ## Capabilities ## Protocol Messages ### Listing Roots ### Root List Changes ## Message Flow ## Data Types ### Root #### Project Directory #### Multiple Repositories ## Error Handling ## Security Considerations ## Implementation Guidelines
A whole new page. There's nothing to diff it against, so here is what it says.
# Roots
<div id="enable-section-numbers" />
The Model Context Protocol (MCP) provides a standardized way for clients to expose
filesystem "roots" to servers. Roots define the boundaries of where servers can operate
within the filesystem, allowing them to understand which directories and files they have
access to. Servers can request the list of roots from supporting clients and receive
notifications when that list changes.
## User Interaction Model
Roots in MCP are typically exposed through workspace or project configuration interfaces.
For example, implementations could offer a workspace/project picker that allows users to
select directories and files the server should have access to. This can be combined with
automatic workspace detection from version control systems or project files.
However, implementations are free to expose roots through any interface pattern that
suits their needs—the protocol itself does not mandate any specific user
interaction model.
## Capabilities
Clients that support roots **MUST** declare the `roots` capability during
[initialization](/specification/2025-06-18/basic/lifecycle#initialization):
```json theme={null}
{
"capabilities": {
"roots": {
"listChanged": true
}
}
}
```
`listChanged` indicates whether the client will emit notifications when the list of roots
changes.
## Protocol Messages
### Listing Roots
To retrieve roots, servers send a `roots/list` request:
**Request:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"method": "roots/list"
}
```
**Response:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"roots": [
{
"uri": "file:///home/user/projects/myproject",
"name": "My Project"
}
]
}
}
```
### Root List Changes
When roots change, clients that support `listChanged` **MUST** send a notification:
```json theme={null}
{
"jsonrpc": "2.0",
"method": "notifications/roots/list_changed"
}
```
## Message Flow
```mermaid theme={null}
sequenceDiagram
participant Server
participant Client
Note over Server,Client: Discovery
Server->>Client: roots/list
Client-->>Server: Available roots
Note over Server,Client: Changes
Client--)Server: notifications/roots/list_changed
Server->>Client: roots/list
Client-->>Server: Updated roots
```
## Data Types
### Root
A root definition includes:
* `uri`: Unique identifier for the root. This **MUST** be a `file://` URI in the current
specification.
* `name`: Optional human-readable name for display purposes.
Example roots for different use cases:
#### Project Directory
```json theme={null}
{
"uri": "file:///home/user/projects/myproject",
"name": "My Project"
}
```
#### Multiple Repositories
```json theme={null}
[
{
"uri": "file:///home/user/repos/frontend",
"name": "Frontend Repository"
},
{
"uri": "file:///home/user/repos/backend",
"name": "Backend Repository"
}
]
```
## Error Handling
Clients **SHOULD** return standard JSON-RPC errors for common failure cases:
* Client does not support roots: `-32601` (Method not found)
* Internal errors: `-32603`
Example error:
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32601,
"message": "Roots not supported",
"data": {
"reason": "Client does not have roots capability"
}
}
}
```
## Security Considerations
1. Clients **MUST**:
* Only expose roots with appropriate permissions
* Validate all root URIs to prevent path traversal
* Implement proper access controls
* Monitor root accessibility
2. Servers **SHOULD**:
* Handle cases where roots become unavailable
* Respect root boundaries during operations
* Validate all paths against provided roots
## Implementation Guidelines
1. Clients **SHOULD**:
* Prompt users for consent before exposing roots to servers
* Provide clear user interfaces for root management
* Validate root accessibility before exposing
* Monitor for root changes
2. Servers **SHOULD**:
* Check for roots capability before usage
* Handle root list changes gracefully
* Respect root boundaries in operations
* Cache root information appropriately
specification/2025-06-18/client/sampling New page · 234 lines, new page
# Sampling ## User Interaction Model ## Capabilities ## Protocol Messages ### Creating Messages ## Message Flow ## Data Types ### Messages #### Text Content #### Image Content #### Audio Content ### Model Preferences #### Capability Priorities #### Model Hints ## Error Handling ## Security Considerations
A whole new page. There's nothing to diff it against, so here is what it says.
# Sampling
<div id="enable-section-numbers" />
The Model Context Protocol (MCP) provides a standardized way for servers to request LLM
sampling ("completions" or "generations") from language models via clients. This flow
allows clients to maintain control over model access, selection, and permissions while
enabling servers to leverage AI capabilities—with no server API keys necessary.
Servers can request text, audio, or image-based interactions and optionally include
context from MCP servers in their prompts.
## User Interaction Model
Sampling in MCP allows servers to implement agentic behaviors, by enabling LLM calls to
occur *nested* inside other MCP server features.
Implementations are free to expose sampling through any interface pattern that suits
their needs—the protocol itself does not mandate any specific user interaction
model.
<Warning>
For trust & safety and security, there **SHOULD** always
be a human in the loop with the ability to deny sampling requests.
Applications **SHOULD**:
* Provide UI that makes it easy and intuitive to review sampling requests
* Allow users to view and edit prompts before sending
* Present generated responses for review before delivery
</Warning>
## Capabilities
Clients that support sampling **MUST** declare the `sampling` capability during
[initialization](/specification/2025-06-18/basic/lifecycle#initialization):
```json theme={null}
{
"capabilities": {
"sampling": {}
}
}
```
## Protocol Messages
### Creating Messages
To request a language model generation, servers send a `sampling/createMessage` request:
**Request:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"method": "sampling/createMessage",
"params": {
"messages": [
{
"role": "user",
"content": {
"type": "text",
"text": "What is the capital of France?"
}
}
],
"modelPreferences": {
"hints": [
{
"name": "claude-3-sonnet"
}
],
"intelligencePriority": 0.8,
"speedPriority": 0.5
},
"systemPrompt": "You are a helpful assistant.",
"maxTokens": 100
}
}
```
**Response:**
```json theme={null}
{
"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"
}
}
```
## Message Flow
```mermaid theme={null}
sequenceDiagram
participant Server
participant Client
participant User
participant LLM
Note over Server,Client: Server initiates sampling
Server->>Client: sampling/createMessage
Note over Client,User: Human-in-the-loop review
Client->>User: Present request for approval
User-->>Client: Review and approve/modify
Note over Client,LLM: Model interaction
Client->>LLM: Forward approved request
LLM-->>Client: Return generation
Note over Client,User: Response review
Client->>User: Present response for approval
User-->>Client: Review and approve/modify
Note over Server,Client: Complete request
Client-->>Server: Return approved response
```
## Data Types
### Messages
Sampling messages can contain:
#### Text Content
```json theme={null}
{
"type": "text",
"text": "The message content"
}
```
#### Image Content
```json theme={null}
{
"type": "image",
"data": "base64-encoded-image-data",
"mimeType": "image/jpeg"
}
```
#### Audio Content
```json theme={null}
{
"type": "audio",
"data": "base64-encoded-audio-data",
"mimeType": "audio/wav"
}
```
### Model Preferences
Model selection in MCP requires careful abstraction since servers and clients may use
different AI providers with distinct model offerings. A server cannot simply request a
specific model by name since the client may not have access to that exact model or may
prefer to use a different provider's equivalent model.
To solve this, MCP implements a preference system that combines abstract capability
priorities with optional model hints:
#### Capability Priorities
Servers express their needs through three normalized priority values (0-1):
* `costPriority`: How important is minimizing costs? Higher values prefer cheaper models.
* `speedPriority`: How important is low latency? Higher values prefer faster models.
* `intelligencePriority`: How important are advanced capabilities? Higher values prefer
more capable models.
#### Model Hints
While priorities help select models based on characteristics, `hints` allow servers to
suggest specific models or model families:
* Hints are treated as substrings that can match model names flexibly
* Multiple hints are evaluated in order of preference
* Clients **MAY** map hints to equivalent models from different providers
* Hints are advisory—clients make final model selection
For example:
```json theme={null}
{
"hints": [
{ "name": "claude-3-sonnet" }, // Prefer Sonnet-class models
{ "name": "claude" } // Fall back to any Claude model
],
"costPriority": 0.3, // Cost is less important
"speedPriority": 0.8, // Speed is very important
"intelligencePriority": 0.5 // Moderate capability needs
}
```
The client processes these preferences to select an appropriate model from its available
options. For instance, if the client doesn't have access to Claude models but has Gemini,
it might map the sonnet hint to `gemini-1.5-pro` based on similar capabilities.
## Error Handling
Clients **SHOULD** return errors for common failure cases:
Example error:
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -1,
"message": "User rejected sampling request"
}
}
```
## Security Considerations
1. Clients **SHOULD** implement user approval controls
2. Both parties **SHOULD** validate message content
3. Clients **SHOULD** respect model preference hints
4. Clients **SHOULD** implement rate limiting
5. Both parties **MUST** handle sensitive data appropriately
specification/2025-06-18/index New page · 135 lines, new page
# Specification ## Overview ## Key Details ### Base Protocol ### Features ### Additional Utilities ## Security and Trust & Safety ### Key Principles ### Implementation Guidelines ## Learn More
A whole new page. There's nothing to diff it against, so here is what it says.
# Specification
<div id="enable-section-numbers" />
[Model Context Protocol](https://modelcontextprotocol.io) (MCP) is an open protocol that
enables seamless integration between LLM applications and external data sources and
tools. Whether you're building an AI-powered IDE, enhancing a chat interface, or creating
custom AI workflows, MCP provides a standardized way to connect LLMs with the context
they need.
This specification defines the authoritative protocol requirements, based on the
TypeScript schema in
[schema.ts](https://github.com/modelcontextprotocol/specification/blob/main/schema/2025-06-18/schema.ts).
For implementation guides and examples, visit
[modelcontextprotocol.io](https://modelcontextprotocol.io).
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD
NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be
interpreted as described in [BCP 14](https://datatracker.ietf.org/doc/html/bcp14)
\[[RFC2119](https://datatracker.ietf.org/doc/html/rfc2119)]
\[[RFC8174](https://datatracker.ietf.org/doc/html/rfc8174)] when, and only when, they
appear in all capitals, as shown here.
## Overview
MCP provides a standardized way for applications to:
* Share contextual information with language models
* Expose tools and capabilities to AI systems
* Build composable integrations and workflows
The protocol uses [JSON-RPC](https://www.jsonrpc.org/) 2.0 messages to establish
communication between:
* **Hosts**: LLM applications that initiate connections
* **Clients**: Connectors within the host application
* **Servers**: Services that provide context and capabilities
MCP takes some inspiration from the
[Language Server Protocol](https://microsoft.github.io/language-server-protocol/), which
standardizes how to add support for programming languages across a whole ecosystem of
development tools. In a similar way, MCP standardizes how to integrate additional context
and tools into the ecosystem of AI applications.
## Key Details
### Base Protocol
* [JSON-RPC](https://www.jsonrpc.org/) message format
* Stateful connections
* Server and client capability negotiation
### Features
Servers offer any of the following features to clients:
* **Resources**: Context and data, for the user or the AI model to use
* **Prompts**: Templated messages and workflows for users
* **Tools**: Functions for the AI model to execute
Clients may offer the following features to servers:
* **Sampling**: Server-initiated agentic behaviors and recursive LLM interactions
* **Roots**: Server-initiated inquiries into uri or filesystem boundaries to operate in
* **Elicitation**: Server-initiated requests for additional information from users
### Additional Utilities
* Configuration
* Progress tracking
* Cancellation
* Error reporting
* Logging
## Security and Trust & Safety
The Model Context Protocol enables powerful capabilities through arbitrary data access
and code execution paths. With this power comes important security and trust
considerations that all implementors must carefully address.
### Key Principles
1. **User Consent and Control**
* Users must explicitly consent to and understand all data access and operations
* Users must retain control over what data is shared and what actions are taken
* Implementors should provide clear UIs for reviewing and authorizing activities
2. **Data Privacy**
* Hosts must obtain explicit user consent before exposing user data to servers
* Hosts must not transmit resource data elsewhere without user consent
* User data should be protected with appropriate access controls
3. **Tool Safety**
* Tools represent arbitrary code execution and must be treated with appropriate
caution.
* In particular, descriptions of tool behavior such as annotations should be
considered untrusted, unless obtained from a trusted server.
* Hosts must obtain explicit user consent before invoking any tool
* Users should understand what each tool does before authorizing its use
4. **LLM Sampling Controls**
* Users must explicitly approve any LLM sampling requests
* Users should control:
* Whether sampling occurs at all
* The actual prompt that will be sent
* What results the server can see
* The protocol intentionally limits server visibility into prompts
### Implementation Guidelines
While MCP itself cannot enforce these security principles at the protocol level,
implementors **SHOULD**:
1. Build robust consent and authorization flows into their applications
2. Provide clear documentation of security implications
3. Implement appropriate access controls and data protections
4. Follow security best practices in their integrations
5. Consider privacy implications in their feature designs
## Learn More
Explore the detailed specification for each protocol component:
<CardGroup cols={5}>
<Card title="Architecture" icon="sitemap" href="/specification/2025-06-18/architecture" />
<Card title="Base Protocol" icon="code" href="/specification/2025-06-18/basic" />
<Card title="Server Features" icon="server" href="/specification/2025-06-18/server" />
<Card title="Client Features" icon="user" href="/specification/2025-06-18/client" />
<Card title="Contributing" icon="pencil" href="/community/contributing" />
</CardGroup>
specification/2025-06-18/schema New page · 614 lines, new page
# Schema Reference ## JSON-RPC ## Common Types ## Content ## `completion/complete` ## `elicitation/create` ## `initialize` ## `logging/setLevel` ## `notifications/cancelled` ## `notifications/initialized` ## `notifications/message` ## `notifications/progress` ## `notifications/prompts/list_changed` ## `notifications/resources/list_changed` ## `notifications/resources/updated` ## `notifications/roots/list_changed` ## `notifications/tools/list_changed` ## `ping` ## `prompts/get` ## `prompts/list` ## `resources/list` ## `resources/read` ## `resources/subscribe` ## `resources/templates/list` ## `resources/unsubscribe` ## `roots/list` ## `sampling/createMessage` ## `tools/call` ## `tools/list`
This page is larger than the 256 KiB this site keeps, so one side of the diff below stops where the stored text does.
A whole new page. There's nothing to diff it against, so here is what it says.
# Schema Reference
<div id="schema-reference" />
## JSON-RPC
<div class="type">
### `JSONRPCError`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">JSONRPCError</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#jsonrpcerror-jsonrpc">jsonrpc</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">"2.0"</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#jsonrpcerror-id">id</a><span class="tsd-signature-symbol">:</span> <a href="#requestid" class="tsd-signature-type tsd-kind-type-alias">RequestId</a><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#jsonrpcerror-error">error</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-symbol">\{</span> <span class="tsd-kind-property">code</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">;</span> <span class="tsd-kind-property">message</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span> <span class="tsd-kind-property">data</span><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">unknown</span> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>A response to a request that indicates an error occurred.</p> </div> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="jsonrpcerror-jsonrpc" data-typedoc-h="3"><span>jsonrpc: "2.0"</span><a href="#jsonrpcerror-jsonrpc" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="jsonrpcerror-id" data-typedoc-h="3"><span>id: RequestId</span><a href="#jsonrpcerror-id" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="jsonrpcerror-error" data-typedoc-h="3"><span>error: \{ code: number; message: string; data?: unknown }</span><a href="#jsonrpcerror-error" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-type-declaration"> <div data-typedoc-h="4">Type Declaration</div> <ul class="tsd-parameters"> <li class="tsd-parameter"> <div data-typedoc-h="5"><span class="tsd-kind-property">code</span><span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">number</span></div> <div class="tsd-comment tsd-typography"><p>The error type that occurred.</p> </div></li> <li class="tsd-parameter"> <div data-typedoc-h="5"><span class="tsd-kind-property">message</span><span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">string</span></div> <div class="tsd-comment tsd-typography"><p>A short description of the error. The message SHOULD be limited to a concise single sentence.</p> </div></li> <li class="tsd-parameter"> <div data-typedoc-h="5"><code class="tsd-tag">Optional</code><span class="tsd-kind-property">data</span><span class="tsd-signature-symbol">?: </span><span class="tsd-signature-type">unknown</span></div> <div class="tsd-comment tsd-typography"><p>Additional information about the error. The value of this member is defined by the sender (e.g. detailed error information, nested errors etc.).</p> </div></li></ul></div></section>
</div>
<div class="type">
### `JSONRPCMessage`
<div class="tsd-signature"><span class="tsd-kind-type-alias">JSONRPCMessage</span><span class="tsd-signature-symbol">:</span><br /> <span class="tsd-signature-symbol">|</span> <a href="#jsonrpcrequest" class="tsd-signature-type tsd-kind-interface">JSONRPCRequest</a><br /> <span class="tsd-signature-symbol">|</span> <a href="#jsonrpcnotification" class="tsd-signature-type tsd-kind-interface">JSONRPCNotification</a><br /> <span class="tsd-signature-symbol">|</span> <a href="#jsonrpcresponse" class="tsd-signature-type tsd-kind-interface">JSONRPCResponse</a><br /> <span class="tsd-signature-symbol">|</span> <a href="#jsonrpcerror" class="tsd-signature-type tsd-kind-interface">JSONRPCError</a></div> <div class="tsd-comment tsd-typography"><p>Refers to any valid JSON-RPC object that can be decoded off the wire, or encoded to be sent.</p> </div>
</div>
<div class="type">
### `JSONRPCNotification`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">JSONRPCNotification</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#jsonrpcnotification-method">method</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#jsonrpcnotification-params">params</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-symbol">\{</span> <span class="tsd-kind-property">\_meta</span><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-symbol">\{</span> <span class="tsd-signature-symbol">\[</span><span class="tsd-kind-index-signature">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <span class="tsd-signature-type">unknown</span> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span> <span class="tsd-signature-symbol">\[</span><span class="tsd-kind-index-signature">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <span class="tsd-signature-type">unknown</span> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#jsonrpcnotification-jsonrpc">jsonrpc</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">"2.0"</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>A notification which does not expect a response.</p> </div> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="jsonrpcnotification-method" data-typedoc-h="3"><span>method: string</span><a href="#jsonrpcnotification-method" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <aside class="tsd-sources"> <p>Inherited from Notification.method</p></aside></section> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="jsonrpcnotification-params" data-typedoc-h="3"><span>params?: \{ \_meta?: \{ \[key: string]: unknown }; \[key: string]: unknown }</span><a href="#jsonrpcnotification-params" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-type-declaration"> <div data-typedoc-h="4">Type Declaration</div> <ul class="tsd-parameters"> <li class="tsd-parameter-index-signature"> <div data-typedoc-h="5"><span class="tsd-signature-symbol">\[</span><span class="tsd-kind-parameter">key</span>: <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <span class="tsd-signature-type">unknown</span></div></li> <li class="tsd-parameter"> <div data-typedoc-h="5"><code class="tsd-tag">Optional</code><span class="tsd-kind-property">\_meta</span><span class="tsd-signature-symbol">?: </span><span class="tsd-signature-symbol">\{</span> <span class="tsd-signature-symbol">\[</span><span class="tsd-kind-index-signature">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <span class="tsd-signature-type">unknown</span> <span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>See <a href="/specification/2025-06-18/basic/index#meta">General fields: <code>\_meta</code></a> for notes on <code>\_meta</code> usage.</p> </div></li></ul></div><aside class="tsd-sources"> <p>Inherited from Notification.params</p></aside></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="jsonrpcnotification-jsonrpc" data-typedoc-h="3"><span>jsonrpc: "2.0"</span><a href="#jsonrpcnotification-jsonrpc" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section>
</div>
<div class="type">
### `JSONRPCRequest`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">JSONRPCRequest</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#jsonrpcrequest-method">method</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#jsonrpcrequest-params">params</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-symbol">\{</span><br /> <span class="tsd-kind-property">\_meta</span><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-symbol">\{</span> <span class="tsd-kind-property">progressToken</span><span class="tsd-signature-symbol">?:</span> <a href="#progresstoken" class="tsd-signature-type tsd-kind-type-alias">ProgressToken</a><span class="tsd-signature-symbol">;</span> <span class="tsd-signature-symbol">\[</span><span class="tsd-kind-index-signature">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <span class="tsd-signature-type">unknown</span> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span><br /> <span class="tsd-signature-symbol">\[</span><span class="tsd-kind-index-signature">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <span class="tsd-signature-type">unknown</span><span class="tsd-signature-symbol">;</span><br /> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#jsonrpcrequest-jsonrpc">jsonrpc</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">"2.0"</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#jsonrpcrequest-id">id</a><span class="tsd-signature-symbol">:</span> <a href="#requestid" class="tsd-signature-type tsd-kind-type-alias">RequestId</a><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>A request that expects a response.</p> </div> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="jsonrpcrequest-method" data-typedoc-h="3"><span>method: string</span><a href="#jsonrpcrequest-method" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <aside class="tsd-sources"> <p>Inherited from Request.method</p></aside></section> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="jsonrpcrequest-params" data-typedoc-h="3"><span>params?: \{ \_meta?: \{ progressToken?: ProgressToken; \[key: string]: unknown }; \[key: string]: unknown; }</span><a href="#jsonrpcrequest-params" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-type-declaration"> <div data-typedoc-h="4">Type Declaration</div> <ul class="tsd-parameters"> <li class="tsd-parameter-index-signature"> <div data-typedoc-h="5"><span class="tsd-signature-symbol">\[</span><span class="tsd-kind-parameter">key</span>: <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <span class="tsd-signature-type">unknown</span></div></li> <li class="tsd-parameter"> <div data-typedoc-h="5"><code class="tsd-tag">Optional</code><span class="tsd-kind-property">\_meta</span><span class="tsd-signature-symbol">?: </span><span class="tsd-signature-symbol">\{</span> <span class="tsd-kind-property">progressToken</span><span class="tsd-signature-symbol">?:</span> <a href="#progresstoken" class="tsd-signature-type tsd-kind-type-alias">ProgressToken</a><span class="tsd-signature-symbol">;</span> <span class="tsd-signature-symbol">\[</span><span class="tsd-kind-index-signature">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <span class="tsd-signature-type">unknown</span> <span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>See <a href="/specification/2025-06-18/basic/index#meta">General fields: <code>\_meta</code></a> for notes on <code>\_meta</code> usage.</p> </div> <ul class="tsd-parameters"> <li class="tsd-parameter"> <div data-typedoc-h="5"><code class="tsd-tag">Optional</code><span class="tsd-kind-property">progressToken</span><span class="tsd-signature-symbol">?: </span><a href="#progresstoken" class="tsd-signature-type tsd-kind-type-alias">ProgressToken</a></div> <div class="tsd-comment tsd-typography"><p>If specified, the caller is requesting out-of-band progress notifications for this request (as represented by notifications/progress). The value of this parameter is an opaque token that will be attached to any subsequent notifications. The receiver is not obligated to provide these notifications.</p> </div></li></ul></li></ul></div><aside class="tsd-sources"> <p>Inherited from Request.params</p></aside></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="jsonrpcrequest-jsonrpc" data-typedoc-h="3"><span>jsonrpc: "2.0"</span><a href="#jsonrpcrequest-jsonrpc" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="jsonrpcrequest-id" data-typedoc-h="3"><span>id: RequestId</span><a href="#jsonrpcrequest-id" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section>
</div>
<div class="type">
### `JSONRPCResponse`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">JSONRPCResponse</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#jsonrpcresponse-jsonrpc">jsonrpc</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">"2.0"</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#jsonrpcresponse-id">id</a><span class="tsd-signature-symbol">:</span> <a href="#requestid" class="tsd-signature-type tsd-kind-type-alias">RequestId</a><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#jsonrpcresponse-result">result</a><span class="tsd-signature-symbol">:</span> <a href="#result" class="tsd-signature-type tsd-kind-interface">Result</a><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>A successful (non-error) response to a request.</p> </div> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="jsonrpcresponse-jsonrpc" data-typedoc-h="3"><span>jsonrpc: "2.0"</span><a href="#jsonrpcresponse-jsonrpc" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="jsonrpcresponse-id" data-typedoc-h="3"><span>id: RequestId</span><a href="#jsonrpcresponse-id" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="jsonrpcresponse-result" data-typedoc-h="3"><span>result: Result</span><a href="#jsonrpcresponse-result" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section>
</div>
## Common Types
<div class="type">
### `Annotations`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">Annotations</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#annotations-audience">audience</a><span class="tsd-signature-symbol">?:</span> <a href="#role" class="tsd-signature-type tsd-kind-type-alias">Role</a><span class="tsd-signature-symbol">\[]</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#annotations-priority">priority</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#annotations-lastmodified">lastModified</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>Optional annotations for the client. The client can use annotations to inform how objects are used or displayed</p> </div> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="annotations-audience" data-typedoc-h="3"><span>audience?: Role\[]</span><a href="#annotations-audience" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>Describes who the intended customer of this object or data is.</p> <p>It can include multiple entries to indicate content useful for multiple audiences (e.g., <code>\["user", "assistant"]</code>).</p> </div></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="annotations-priority" data-typedoc-h="3"><span>priority?: number</span><a href="#annotations-priority" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>Describes how important this data is for operating the server.</p> <p>A value of 1 means "most important," and indicates that the data is
effectively required, while 0 means "least important," and indicates that
the data is entirely optional.</p> </div></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="annotations-lastmodified" data-typedoc-h="3"><span>lastModified?: string</span><a href="#annotations-lastmodified" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>The moment the resource was last modified, as an ISO 8601 formatted string.</p> <p>Should be an ISO 8601 formatted string (e.g., "2025-01-12T15:00:58Z").</p> <p>Examples: last activity timestamp in an open file, timestamp when the resource
was attached, etc.</p> </div></section>
</div>
<div class="type">
### `Cursor`
<div class="tsd-signature"><span class="tsd-kind-type-alias">Cursor</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span></div> <div class="tsd-comment tsd-typography"><p>An opaque token used to represent a cursor for pagination.</p> </div>
</div>
<div class="type">
### `EmptyResult`
<div class="tsd-signature"><span class="tsd-kind-type-alias">EmptyResult</span><span class="tsd-signature-symbol">:</span> <a href="#result" class="tsd-signature-type tsd-kind-interface">Result</a></div> <div class="tsd-comment tsd-typography"><p>A response that indicates success but carries no data.</p> </div>
</div>
<div class="type">
### `LoggingLevel`
<div class="tsd-signature"><span class="tsd-kind-type-alias">LoggingLevel</span><span class="tsd-signature-symbol">:</span><br /> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"debug"</span><br /> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"info"</span><br /> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"notice"</span><br /> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"warning"</span><br /> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"error"</span><br /> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"critical"</span><br /> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"alert"</span><br /> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"emergency"</span></div> <div class="tsd-comment tsd-typography"><p>The severity of a log message.</p> <p>These map to syslog message severities, as specified in RFC-5424: <a href="https://datatracker.ietf.org/doc/html/rfc5424#section-6.2.1">[https://datatracker.ietf.org/doc/html/rfc5424#section-6.2.1](https://datatracker.ietf.org/doc/html/rfc5424#section-6.2.1)</a></p> </div>
</div>
<div class="type">
### `ProgressToken`
<div class="tsd-signature"><span class="tsd-kind-type-alias">ProgressToken</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">number</span></div> <div class="tsd-comment tsd-typography"><p>A progress token, used to associate progress notifications with the original request.</p> </div>
</div>
<div class="type">
### `RequestId`
<div class="tsd-signature"><span class="tsd-kind-type-alias">RequestId</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">number</span></div> <div class="tsd-comment tsd-typography"><p>A uniquely identifying ID for a request in JSON-RPC.</p> </div>
</div>
<div class="type">
### `Result`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">Result</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#result-_meta">\_meta</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-symbol">\{</span> <span class="tsd-signature-symbol">\[</span><span class="tsd-kind-index-signature">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <span class="tsd-signature-type">unknown</span> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span><br /> <span class="tsd-signature-symbol">\[</span><span class="tsd-kind-index-signature">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <span class="tsd-signature-type">unknown</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="result-_meta" data-typedoc-h="3"><span>\_meta?: \{ \[key: string]: unknown }</span><a href="#result-_meta" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>See <a href="/specification/2025-06-18/basic/index#meta">General fields: <code>\_meta</code></a> for notes on <code>\_meta</code> usage.</p> </div></section>
</div>
<div class="type">
### `Role`
<div class="tsd-signature"><span class="tsd-kind-type-alias">Role</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">"user"</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"assistant"</span></div> <div class="tsd-comment tsd-typography"><p>The sender or recipient of messages and data in a conversation.</p> </div>
</div>
## Content
<div class="type">
### `AudioContent`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">AudioContent</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#audiocontent-type">type</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">"audio"</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#audiocontent-data">data</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#audiocontent-mimetype">mimeType</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#audiocontent-annotations">annotations</a><span class="tsd-signature-symbol">?:</span> <a href="#annotations" class="tsd-signature-type tsd-kind-interface">Annotations</a><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#audiocontent-_meta">\_meta</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-symbol">\{</span> <span class="tsd-signature-symbol">\[</span><span class="tsd-kind-index-signature">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <span class="tsd-signature-type">unknown</span> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>Audio provided to or from an LLM.</p> </div> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="audiocontent-type" data-typedoc-h="3"><span>type: "audio"</span><a href="#audiocontent-type" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="audiocontent-data" data-typedoc-h="3"><span>data: string</span><a href="#audiocontent-data" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>The base64-encoded audio data.</p> </div></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="audiocontent-mimetype" data-typedoc-h="3"><span>mimeType: string</span><a href="#audiocontent-mimetype" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>The MIME type of the audio. Different providers may support different audio types.</p> </div></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="audiocontent-annotations" data-typedoc-h="3"><span>annotations?: Annotations</span><a href="#audiocontent-annotations" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>Optional annotations for the client.</p> </div></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="audiocontent-_meta" data-typedoc-h="3"><span>\_meta?: \{ \[key: string]: unknown }</span><a href="#audiocontent-_meta" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>See <a href="/specification/2025-06-18/basic/index#meta">General fields: <code>\_meta</code></a> for notes on <code>\_meta</code> usage.</p> </div></section>
</div>
<div class="type">
### `BlobResourceContents`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">BlobResourceContents</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#blobresourcecontents-uri">uri</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#blobresourcecontents-mimetype">mimeType</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#blobresourcecontents-_meta">\_meta</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-symbol">\{</span> <span class="tsd-signature-symbol">\[</span><span class="tsd-kind-index-signature">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <span class="tsd-signature-type">unknown</span> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#blobresourcecontents-blob">blob</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="blobresourcecontents-uri" data-typedoc-h="3"><span>uri: string</span><a href="#blobresourcecontents-uri" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>The URI of this resource.</p> </div><aside class="tsd-sources"> <p>Inherited from ResourceContents.uri</p></aside></section> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="blobresourcecontents-mimetype" data-typedoc-h="3"><span>mimeType?: string</span><a href="#blobresourcecontents-mimetype" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>The MIME type of this resource, if known.</p> </div><aside class="tsd-sources"> <p>Inherited from ResourceContents.mimeType</p></aside></section> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="blobresourcecontents-_meta" data-typedoc-h="3"><span>\_meta?: \{ \[key: string]: unknown }</span><a href="#blobresourcecontents-_meta" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>See <a href="/specification/2025-06-18/basic/index#meta">General fields: <code>\_meta</code></a> for notes on <code>\_meta</code> usage.</p> </div><aside class="tsd-sources"> <p>Inherited from ResourceContents.\_meta</p></aside></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="blobresourcecontents-blob" data-typedoc-h="3"><span>blob: string</span><a href="#blobresourcecontents-blob" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>A base64-encoded string representing the binary data of the item.</p> </div></section>
</div>
<div class="type">
### `ContentBlock`
<div class="tsd-signature"><span class="tsd-kind-type-alias">ContentBlock</span><span class="tsd-signature-symbol">:</span><br /> <span class="tsd-signature-symbol">|</span> <a href="#textcontent" class="tsd-signature-type tsd-kind-interface">TextContent</a><br /> <span class="tsd-signature-symbol">|</span> <a href="#imagecontent" class="tsd-signature-type tsd-kind-interface">ImageContent</a><br /> <span class="tsd-signature-symbol">|</span> <a href="#audiocontent" class="tsd-signature-type tsd-kind-interface">AudioContent</a><br /> <span class="tsd-signature-symbol">|</span> <a href="#resourcelink" class="tsd-signature-type tsd-kind-interface">ResourceLink</a><br /> <span class="tsd-signature-symbol">|</span> <a href="#embeddedresource" class="tsd-signature-type tsd-kind-interface">EmbeddedResource</a></div>
</div>
<div class="type">
### `EmbeddedResource`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">EmbeddedResource</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#embeddedresource-type">type</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">"resource"</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#embeddedresource-resource">resource</a><span class="tsd-signature-symbol">:</span> <a href="#textresourcecontents" class="tsd-signature-type tsd-kind-interface">TextResourceContents</a> <span class="tsd-signature-symbol">|</span> <a href="#blobresourcecontents" class="tsd-signature-type tsd-kind-interface">BlobResourceContents</a><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#embeddedresource-annotations">annotations</a><span class="tsd-signature-symbol">?:</span> <a href="#annotations" class="tsd-signature-type tsd-kind-interface">Annotations</a><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#embeddedresource-_meta">\_meta</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-symbol">\{</span> <span class="tsd-signature-symbol">\[</span><span class="tsd-kind-index-signature">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <span class="tsd-signature-type">unknown</span> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>The contents of a resource, embedded into a prompt or tool call result.</p> <p>It is up to the client how best to render embedded resources for the benefit
of the LLM and/or the user.</p> </div> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="embeddedresource-type" data-typedoc-h="3"><span>type: "resource"</span><a href="#embeddedresource-type" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="embeddedresource-resource" data-typedoc-h="3"><span>resource: TextResourceContents | BlobResourceContents</span><a href="#embeddedresource-resource" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="embeddedresource-annotations" data-typedoc-h="3"><span>annotations?: Annotations</span><a href="#embeddedresource-annotations" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>Optional annotations for the client.</p> </div></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="embeddedresource-_meta" data-typedoc-h="3"><span>\_meta?: \{ \[key: string]: unknown }</span><a href="#embeddedresource-_meta" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>See <a href="/specification/2025-06-18/basic/index#meta">General fields: <code>\_meta</code></a> for notes on <code>\_meta</code> usage.</p> </div></section>
</div>
<div class="type">
### `ImageContent`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">ImageContent</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#imagecontent-type">type</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">"image"</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#imagecontent-data">data</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#imagecontent-mimetype">mimeType</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#imagecontent-annotations">annotations</a><span class="tsd-signature-symbol">?:</span> <a href="#annotations" class="tsd-signature-type tsd-kind-interface">Annotations</a><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#imagecontent-_meta">\_meta</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-symbol">\{</span> <span class="tsd-signature-symbol">\[</span><span class="tsd-kind-index-signature">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <span class="tsd-signature-type">unknown</span> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>An image provided to or from an LLM.</p> </div> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="imagecontent-type" data-typedoc-h="3"><span>type: "image"</span><a href="#imagecontent-type" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="imagecontent-data" data-typedoc-h="3"><span>data: string</span><a href="#imagecontent-data" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>The base64-encoded image data.</p> </div></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="imagecontent-mimetype" data-typedoc-h="3"><span>mimeType: string</span><a href="#imagecontent-mimetype" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>The MIME type of the image. Different providers may support different image types.</p> </div></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="imagecontent-annotations" data-typedoc-h="3"><span>annotations?: Annotations</span><a href="#imagecontent-annotations" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>Optional annotations for the client.</p> </div></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="imagecontent-_meta" data-typedoc-h="3"><span>\_meta?: \{ \[key: string]: unknown }</span><a href="#imagecontent-_meta" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>See <a href="/specification/2025-06-18/basic/index#meta">General fields: <code>\_meta</code></a> for notes on <code>\_meta</code> usage.</p> </div></section>
</div>
<div class="type">
### `ResourceLink`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">ResourceLink</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#resourcelink-name">name</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#resourcelink-title">title</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#resourcelink-uri">uri</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#resourcelink-description">description</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#resourcelink-mimetype">mimeType</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#resourcelink-annotations">annotations</a><span class="tsd-signature-symbol">?:</span> <a href="#annotations" class="tsd-signature-type tsd-kind-interface">Annotations</a><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#resourcelink-size">size</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#resourcelink-_meta">\_meta</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-symbol">\{</span> <span class="tsd-signature-symbol">\[</span><span class="tsd-kind-index-signature">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <span class="tsd-signature-type">unknown</span> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#resourcelink-type">type</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">"resource\_link"</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>A resource that the server is capable of reading, included in a prompt or tool call result.</p> <p>Note: resource links returned by tools are not guaranteed to appear in the results of <code>resources/list</code> requests.</p> </div> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="resourcelink-name" data-typedoc-h="3"><span>name: string</span><a href="#resourcelink-name" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>Intended for programmatic or logical use, but used as a display name in past specs or fallback (if title isn't present).</p> </div><aside class="tsd-sources"> <p>Inherited from <a href="#resource">Resource</a>.<a href="#resource-name">name</a></p></aside></section> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="resourcelink-title" data-typedoc-h="3"><span>title?: string</span><a href="#resourcelink-title" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>Intended for UI and end-user contexts — optimized to be human-readable and easily understood,
even by those unfamiliar with domain-specific terminology.</p> <p>If not provided, the name should be used for display (except for Tool,
where <code>annotations.title</code> should be given precedence over using <code>name</code>,
if present).</p> </div><aside class="tsd-sources"> <p>Inherited from <a href="#resource">Resource</a>.<a href="#resource-title">title</a></p></aside></section> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="resourcelink-uri" data-typedoc-h="3"><span>uri: string</span><a href="#resourcelink-uri" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>The URI of this resource.</p> </div><aside class="tsd-sources"> <p>Inherited from <a href="#resource">Resource</a>.<a href="#resource-uri">uri</a></p></aside></section> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="resourcelink-description" data-typedoc-h="3"><span>description?: string</span><a href="#resourcelink-description" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>A description of what this resource represents.</p> <p>This can be used by clients to improve the LLM's understanding of available resources. It can be thought of like a "hint" to the model.</p> </div><aside class="tsd-sources"> <p>Inherited from <a href="#resource">Resource</a>.<a href="#resource-description">description</a></p></aside></section> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="resourcelink-mimetype" data-typedoc-h="3"><span>mimeType?: string</span><a href="#resourcelink-mimetype" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>The MIME type of this resource, if known.</p> </div><aside class="tsd-sources"> <p>Inherited from <a href="#resource">Resource</a>.<a href="#resource-mimetype">mimeType</a></p></aside></section> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="resourcelink-annotations" data-typedoc-h="3"><span>annotations?: Annotations</span><a href="#resourcelink-annotations" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>Optional annotations for the client.</p> </div><aside class="tsd-sources"> <p>Inherited from <a href="#resource">Resource</a>.<a href="#resource-annotations">annotations</a></p></aside></section> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="resourcelink-size" data-typedoc-h="3"><span>size?: number</span><a href="#resourcelink-size" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>The size of the raw resource content, in bytes (i.e., before base64 encoding or any tokenization), if known.</p> <p>This can be used by Hosts to display file sizes and estimate context window usage.</p> </div><aside class="tsd-sources"> <p>Inherited from <a href="#resource">Resource</a>.<a href="#resource-size">size</a></p></aside></section> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="resourcelink-_meta" data-typedoc-h="3"><span>\_meta?: \{ \[key: string]: unknown }</span><a href="#resourcelink-_meta" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>See <a href="/specification/2025-06-18/basic/index#meta">General fields: <code>\_meta</code></a> for notes on <code>\_meta</code> usage.</p> </div><aside class="tsd-sources"> <p>Inherited from <a href="#resource">Resource</a>.<a href="#resource-_meta">\_meta</a></p></aside></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="resourcelink-type" data-typedoc-h="3"><span>type: "resource\_link"</span><a href="#resourcelink-type" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section>
</div>
<div class="type">
### `TextContent`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">TextContent</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#textcontent-type">type</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">"text"</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#textcontent-text">text</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#textcontent-annotations">annotations</a><span class="tsd-signature-symbol">?:</span> <a href="#annotations" class="tsd-signature-type tsd-kind-interface">Annotations</a><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#textcontent-_meta">\_meta</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-symbol">\{</span> <span class="tsd-signature-symbol">\[</span><span class="tsd-kind-index-signature">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <span class="tsd-signature-type">unknown</span> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>Text provided to or from an LLM.</p> </div> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="textcontent-type" data-typedoc-h="3"><span>type: "text"</span><a href="#textcontent-type" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="textcontent-text" data-typedoc-h="3"><span>text: string</span><a href="#textcontent-text" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>The text content of the message.</p> </div></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="textcontent-annotations" data-typedoc-h="3"><span>annotations?: Annotations</span><a href="#textcontent-annotations" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>Optional annotations for the client.</p> </div></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="textcontent-_meta" data-typedoc-h="3"><span>\_meta?: \{ \[key: string]: unknown }</span><a href="#textcontent-_meta" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>See <a href="/specification/2025-06-18/basic/index#meta">General fields: <code>\_meta</code></a> for notes on <code>\_meta</code> usage.</p> </div></section>
</div>
<div class="type">
### `TextResourceContents`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">TextResourceContents</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#textresourcecontents-uri">uri</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#textresourcecontents-mimetype">mimeType</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#textresourcecontents-_meta">\_meta</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-symbol">\{</span> <span class="tsd-signature-symbol">\[</span><span class="tsd-kind-index-signature">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <span class="tsd-signature-type">unknown</span> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#textresourcecontents-text">text</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="textresourcecontents-uri" data-typedoc-h="3"><span>uri: string</span><a href="#textresourcecontents-uri" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>The URI of this resource.</p> </div><aside class="tsd-sources"> <p>Inherited from ResourceContents.uri</p></aside></section> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="textresourcecontents-mimetype" data-typedoc-h="3"><span>mimeType?: string</span><a href="#textresourcecontents-mimetype" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>The MIME type of this resource, if known.</p> </div><aside class="tsd-sources"> <p>Inherited from ResourceContents.mimeType</p></aside></section> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="textresourcecontents-_meta" data-typedoc-h="3"><span>\_meta?: \{ \[key: string]: unknown }</span><a href="#textresourcecontents-_meta" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>See <a href="/specification/2025-06-18/basic/index#meta">General fields: <code>\_meta</code></a> for notes on <code>\_meta</code> usage.</p> </div><aside class="tsd-sources"> <p>Inherited from ResourceContents.\_meta</p></aside></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="textresourcecontents-text" data-typedoc-h="3"><span>text: string</span><a href="#textresourcecontents-text" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>The text of the item. This must only be set if the item can actually be represented as text (not binary data).</p> </div></section>
</div>
## `completion/complete`
<div class="type">
### `CompleteRequest`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">CompleteRequest</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#completerequest-method">method</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">"completion/complete"</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#completerequest-params">params</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-symbol">\{</span><br /> <span class="tsd-kind-property">ref</span><span class="tsd-signature-symbol">:</span> <a href="#promptreference" class="tsd-signature-type tsd-kind-interface">PromptReference</a> <span class="tsd-signature-symbol">|</span> <a href="#resourcetemplatereference" class="tsd-signature-type tsd-kind-interface">ResourceTemplateReference</a><span class="tsd-signature-symbol">;</span><br /> <span class="tsd-kind-property">argument</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-symbol">\{</span> <span class="tsd-kind-property">name</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span> <span class="tsd-kind-property">value</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span><br /> <span class="tsd-kind-property">context</span><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-symbol">\{</span> <span class="tsd-kind-property">arguments</span><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-symbol">\{</span> <span class="tsd-signature-symbol">\[</span><span class="tsd-kind-index-signature">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <span class="tsd-signature-type">string</span> <span class="tsd-signature-symbol">}</span> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span><br /> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>A request from the client to the server, to ask for completion options.</p> </div> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="completerequest-method" data-typedoc-h="3"><span>method: "completion/complete"</span><a href="#completerequest-method" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <aside class="tsd-sources"> <p>Overrides Request.method</p></aside></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="completerequest-params" data-typedoc-h="3"><span>params: \{ ref: PromptReference | ResourceTemplateReference; argument: \{ name: string; value: string }; context?: \{ arguments?: \{ \[key: string]: string } }; }</span><a href="#completerequest-params" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-type-declaration"> <div data-typedoc-h="4">Type Declaration</div> <ul class="tsd-parameters"> <li class="tsd-parameter"> <div data-typedoc-h="5"><span class="tsd-kind-property">ref</span><span class="tsd-signature-symbol">: </span><a href="#promptreference" class="tsd-signature-type tsd-kind-interface">PromptReference</a> <span class="tsd-signature-symbol">|</span> <a href="#resourcetemplatereference" class="tsd-signature-type tsd-kind-interface">ResourceTemplateReference</a></div></li> <li class="tsd-parameter"> <div data-typedoc-h="5"><span class="tsd-kind-property">argument</span><span class="tsd-signature-symbol">: </span><span class="tsd-signature-symbol">\{</span> <span class="tsd-kind-property">name</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span> <span class="tsd-kind-property">value</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span> <span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>The argument's information</p> </div> <ul class="tsd-parameters"> <li class="tsd-parameter"> <div data-typedoc-h="5"><span class="tsd-kind-property">name</span><span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">string</span></div> <div class="tsd-comment tsd-typography"><p>The name of the argument</p> </div></li> <li class="tsd-parameter"> <div data-typedoc-h="5"><span class="tsd-kind-property">value</span><span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">string</span></div> <div class="tsd-comment tsd-typography"><p>The value of the argument to use for completion matching.</p> </div></li></ul></li> <li class="tsd-parameter"> <div data-typedoc-h="5"><code class="tsd-tag">Optional</code><span class="tsd-kind-property">context</span><span class="tsd-signature-symbol">?: </span><span class="tsd-signature-symbol">\{</span> <span class="tsd-kind-property">arguments</span><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-symbol">\{</span> <span class="tsd-signature-symbol">\[</span><span class="tsd-kind-index-signature">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <span class="tsd-signature-type">string</span> <span class="tsd-signature-symbol">}</span> <span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>Additional, optional context for completions</p> </div> <ul class="tsd-parameters"> <li class="tsd-parameter"> <div data-typedoc-h="5"><code class="tsd-tag">Optional</code><span class="tsd-kind-property">arguments</span><span class="tsd-signature-symbol">?: </span><span class="tsd-signature-symbol">\{</span> <span class="tsd-signature-symbol">\[</span><span class="tsd-kind-index-signature">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <span class="tsd-signature-type">string</span> <span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>Previously-resolved variables in a URI template or prompt.</p> </div></li></ul></li></ul></div><aside class="tsd-sources"> <p>Overrides Request.params</p></aside></section>
</div>
<div class="type">
### `CompleteResult`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">CompleteResult</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#completeresult-_meta">\_meta</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-symbol">\{</span> <span class="tsd-signature-symbol">\[</span><span class="tsd-kind-index-signature">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <span class="tsd-signature-type">unknown</span> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#completeresult-completion">completion</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-symbol">\{</span> <span class="tsd-kind-property">values</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">\[]</span><span class="tsd-signature-symbol">;</span> <span class="tsd-kind-property">total</span><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">;</span> <span class="tsd-kind-property">hasMore</span><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">boolean</span> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span><br /> <span class="tsd-signature-symbol">\[</span><span class="tsd-kind-index-signature">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <span class="tsd-signature-type">unknown</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>The server's response to a completion/complete request</p> </div> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="completeresult-_meta" data-typedoc-h="3"><span>\_meta?: \{ \[key: string]: unknown }</span><a href="#completeresult-_meta" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>See <a href="/specification/2025-06-18/basic/index#meta">General fields: <code>\_meta</code></a> for notes on <code>\_meta</code> usage.</p> </div><aside class="tsd-sources"> <p>Inherited from <a href="#result">Result</a>.<a href="#result-_meta">\_meta</a></p></aside></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="completeresult-completion" data-typedoc-h="3"><span>completion: \{ values: string\[]; total?: number; hasMore?: boolean }</span><a href="#completeresult-completion" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-type-declaration"> <div data-typedoc-h="4">Type Declaration</div> <ul class="tsd-parameters"> <li class="tsd-parameter"> <div data-typedoc-h="5"><span class="tsd-kind-property">values</span><span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">\[]</span></div> <div class="tsd-comment tsd-typography"><p>An array of completion values. Must not exceed 100 items.</p> </div></li> <li class="tsd-parameter"> <div data-typedoc-h="5"><code class="tsd-tag">Optional</code><span class="tsd-kind-property">total</span><span class="tsd-signature-symbol">?: </span><span class="tsd-signature-type">number</span></div> <div class="tsd-comment tsd-typography"><p>The total number of completion options available. This can exceed the number of values actually sent in the response.</p> </div></li> <li class="tsd-parameter"> <div data-typedoc-h="5"><code class="tsd-tag">Optional</code><span class="tsd-kind-property">hasMore</span><span class="tsd-signature-symbol">?: </span><span class="tsd-signature-type">boolean</span></div> <div class="tsd-comment tsd-typography"><p>Indicates whether there are additional completion options beyond those provided in the current response, even if the exact total is unknown.</p> </div></li></ul></div></section>
</div>
<div class="type">
### `PromptReference`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">PromptReference</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#promptreference-name">name</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#promptreference-title">title</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#promptreference-type">type</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">"ref/prompt"</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>Identifies a prompt.</p> </div> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="promptreference-name" data-typedoc-h="3"><span>name: string</span><a href="#promptreference-name" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>Intended for programmatic or logical use, but used as a display name in past specs or fallback (if title isn't present).</p> </div><aside class="tsd-sources"> <p>Inherited from BaseMetadata.name</p></aside></section> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="promptreference-title" data-typedoc-h="3"><span>title?: string</span><a href="#promptreference-title" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>Intended for UI and end-user contexts — optimized to be human-readable and easily understood,
even by those unfamiliar with domain-specific terminology.</p> <p>If not provided, the name should be used for display (except for Tool,
where <code>annotations.title</code> should be given precedence over using <code>name</code>,
if present).</p> </div><aside class="tsd-sources"> <p>Inherited from BaseMetadata.title</p></aside></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="promptreference-type" data-typedoc-h="3"><span>type: "ref/prompt"</span><a href="#promptreference-type" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section>
</div>
<div class="type">
### `ResourceTemplateReference`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">ResourceTemplateReference</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#resourcetemplatereference-type">type</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">"ref/resource"</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#resourcetemplatereference-uri">uri</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>A reference to a resource or resource template definition.</p> </div> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="resourcetemplatereference-type" data-typedoc-h="3"><span>type: "ref/resource"</span><a href="#resourcetemplatereference-type" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="resourcetemplatereference-uri" data-typedoc-h="3"><span>uri: string</span><a href="#resourcetemplatereference-uri" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>The URI or URI template of the resource.</p> </div></section>
</div>
## `elicitation/create`
<div class="type">
### `ElicitRequest`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">ElicitRequest</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#elicitrequest-method">method</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">"elicitation/create"</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#elicitrequest-params">params</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-symbol">\{</span><br /> <span class="tsd-kind-property">message</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <span class="tsd-kind-property">requestedSchema</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-symbol">\{</span><br /> <span class="tsd-kind-property">type</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">"object"</span><span class="tsd-signature-symbol">;</span><br /> <span class="tsd-kind-property">properties</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-symbol">\{</span> <span class="tsd-signature-symbol">\[</span><span class="tsd-kind-index-signature">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <a href="#primitiveschemadefinition" class="tsd-signature-type tsd-kind-type-alias">PrimitiveSchemaDefinition</a> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span><br /> <span class="tsd-kind-property">required</span><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">\[]</span><span class="tsd-signature-symbol">;</span><br /> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span><br /> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>A request from the server to elicit additional information from the user via the client.</p> </div> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="elicitrequest-method" data-typedoc-h="3"><span>method: "elicitation/create"</span><a href="#elicitrequest-method" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <aside class="tsd-sources"> <p>Overrides Request.method</p></aside></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="elicitrequest-params" data-typedoc-h="3"><span>params: \{ message: string; requestedSchema: \{ type: "object"; properties: \{ \[key: string]: PrimitiveSchemaDefinition }; required?: string\[]; }; }</span><a href="#elicitrequest-params" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-type-declaration"> <div data-typedoc-h="4">Type Declaration</div> <ul class="tsd-parameters"> <li class="tsd-parameter"> <div data-typedoc-h="5"><span class="tsd-kind-property">message</span><span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">string</span></div> <div class="tsd-comment tsd-typography"><p>The message to present to the user.</p> </div></li> <li class="tsd-parameter"> <div data-typedoc-h="5"><span class="tsd-kind-property">requestedSchema</span><span class="tsd-signature-symbol">: </span><span class="tsd-signature-symbol">\{</span><br /> <span class="tsd-kind-property">type</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">"object"</span><span class="tsd-signature-symbol">;</span><br /> <span class="tsd-kind-property">properties</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-symbol">\{</span> <span class="tsd-signature-symbol">\[</span><span class="tsd-kind-index-signature">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <a href="#primitiveschemadefinition" class="tsd-signature-type tsd-kind-type-alias">PrimitiveSchemaDefinition</a> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span><br /> <span class="tsd-kind-property">required</span><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">\[]</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>A restricted subset of JSON Schema.
Only top-level properties are allowed, without nesting.</p> </div></li></ul></div><aside class="tsd-sources"> <p>Overrides Request.params</p></aside></section>
</div>
<div class="type">
### `ElicitResult`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">ElicitResult</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#elicitresult-_meta">\_meta</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-symbol">\{</span> <span class="tsd-signature-symbol">\[</span><span class="tsd-kind-index-signature">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <span class="tsd-signature-type">unknown</span> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#elicitresult-action">action</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">"accept"</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"decline"</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"cancel"</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#elicitresult-content">content</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-symbol">\{</span> <span class="tsd-signature-symbol">\[</span><span class="tsd-kind-index-signature">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <span class="tsd-signature-type">string</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">number</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">boolean</span> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span><br /> <span class="tsd-signature-symbol">\[</span><span class="tsd-kind-index-signature">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <span class="tsd-signature-type">unknown</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>The client's response to an elicitation request.</p> </div> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="elicitresult-_meta" data-typedoc-h="3"><span>\_meta?: \{ \[key: string]: unknown }</span><a href="#elicitresult-_meta" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>See <a href="/specification/2025-06-18/basic/index#meta">General fields: <code>\_meta</code></a> for notes on <code>\_meta</code> usage.</p> </div><aside class="tsd-sources"> <p>Inherited from <a href="#result">Result</a>.<a href="#result-_meta">\_meta</a></p></aside></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="elicitresult-action" data-typedoc-h="3"><span>action: "accept" | "decline" | "cancel"</span><a href="#elicitresult-action" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>The user action in response to the elicitation.</p> <ul> <li>"accept": User submitted the form/confirmed the action</li> <li>"decline": User explicitly declined the action</li> <li>"cancel": User dismissed without making an explicit choice</li> </ul> </div></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="elicitresult-content" data-typedoc-h="3"><span>content?: \{ \[key: string]: string | number | boolean }</span><a href="#elicitresult-content" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>The submitted form data, only present when action is "accept".
Contains values matching the requested schema.</p> </div></section>
</div>
<div class="type">
### `BooleanSchema`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">BooleanSchema</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#booleanschema-type">type</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">"boolean"</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#booleanschema-title">title</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#booleanschema-description">description</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#booleanschema-default">default</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">boolean</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="booleanschema-type" data-typedoc-h="3"><span>type: "boolean"</span><a href="#booleanschema-type" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="booleanschema-title" data-typedoc-h="3"><span>title?: string</span><a href="#booleanschema-title" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="booleanschema-description" data-typedoc-h="3"><span>description?: string</span><a href="#booleanschema-description" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="booleanschema-default" data-typedoc-h="3"><span>default?: boolean</span><a href="#booleanschema-default" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section>
</div>
<div class="type">
### `EnumSchema`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">EnumSchema</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#enumschema-type">type</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">"string"</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#enumschema-title">title</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#enumschema-description">description</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#enumschema-enum">enum</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">\[]</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#enumschema-enumnames">enumNames</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">\[]</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="enumschema-type" data-typedoc-h="3"><span>type: "string"</span><a href="#enumschema-type" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="enumschema-title" data-typedoc-h="3"><span>title?: string</span><a href="#enumschema-title" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="enumschema-description" data-typedoc-h="3"><span>description?: string</span><a href="#enumschema-description" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="enumschema-enum" data-typedoc-h="3"><span>enum: string\[]</span><a href="#enumschema-enum" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="enumschema-enumnames" data-typedoc-h="3"><span>enumNames?: string\[]</span><a href="#enumschema-enumnames" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section>
</div>
<div class="type">
### `NumberSchema`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">NumberSchema</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#numberschema-type">type</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">"number"</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"integer"</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#numberschema-title">title</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#numberschema-description">description</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#numberschema-minimum">minimum</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#numberschema-maximum">maximum</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="numberschema-type" data-typedoc-h="3"><span>type: "number" | "integer"</span><a href="#numberschema-type" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="numberschema-title" data-typedoc-h="3"><span>title?: string</span><a href="#numberschema-title" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="numberschema-description" data-typedoc-h="3"><span>description?: string</span><a href="#numberschema-description" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="numberschema-minimum" data-typedoc-h="3"><span>minimum?: number</span><a href="#numberschema-minimum" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="numberschema-maximum" data-typedoc-h="3"><span>maximum?: number</span><a href="#numberschema-maximum" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section>
</div>
<div class="type">
### `PrimitiveSchemaDefinition`
<div class="tsd-signature"><span class="tsd-kind-type-alias">PrimitiveSchemaDefinition</span><span class="tsd-signature-symbol">:</span><br /> <span class="tsd-signature-symbol">|</span> <a href="#stringschema" class="tsd-signature-type tsd-kind-interface">StringSchema</a><br /> <span class="tsd-signature-symbol">|</span> <a href="#numberschema" class="tsd-signature-type tsd-kind-interface">NumberSchema</a><br /> <span class="tsd-signature-symbol">|</span> <a href="#booleanschema" class="tsd-signature-type tsd-kind-interface">BooleanSchema</a><br /> <span class="tsd-signature-symbol">|</span> <a href="#enumschema" class="tsd-signature-type tsd-kind-interface">EnumSchema</a></div> <div class="tsd-comment tsd-typography"><p>Restricted schema definitions that only allow primitive types
without nested objects or arrays.</p> </div>
</div>
<div class="type">
### `StringSchema`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">StringSchema</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#stringschema-type">type</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">"string"</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#stringschema-title">title</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#stringschema-description">description</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#stringschema-minlength">minLength</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#stringschema-maxlength">maxLength</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#stringschema-format">format</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">"uri"</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"email"</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"date"</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"date-time"</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="stringschema-type" data-typedoc-h="3"><span>type: "string"</span><a href="#stringschema-type" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="stringschema-title" data-typedoc-h="3"><span>title?: string</span><a href="#stringschema-title" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="stringschema-description" data-typedoc-h="3"><span>description?: string</span><a href="#stringschema-description" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="stringschema-minlength" data-typedoc-h="3"><span>minLength?: number</span><a href="#stringschema-minlength" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="stringschema-maxlength" data-typedoc-h="3"><span>maxLength?: number</span><a href="#stringschema-maxlength" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="stringschema-format" data-typedoc-h="3"><span>format?: "uri" | "email" | "date" | "date-time"</span><a href="#stringschema-format" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section>
</div>
## `initialize`
<div class="type">
### `InitializeRequest`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">InitializeRequest</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#initializerequest-method">method</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">"initialize"</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#initializerequest-params">params</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-symbol">\{</span><br /> <span class="tsd-kind-property">protocolVersion</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <span class="tsd-kind-property">capabilities</span><span class="tsd-signature-symbol">:</span> <a href="#clientcapabilities" class="tsd-signature-type tsd-kind-interface">ClientCapabilities</a><span class="tsd-signature-symbol">;</span><br /> <span class="tsd-kind-property">clientInfo</span><span class="tsd-signature-symbol">:</span> <a href="#implementation" class="tsd-signature-type tsd-kind-interface">Implementation</a><span class="tsd-signature-symbol">;</span><br /> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>This request is sent from the client to the server when it first connects, asking it to begin initialization.</p> </div> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="initializerequest-method" data-typedoc-h="3"><span>method: "initialize"</span><a href="#initializerequest-method" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <aside class="tsd-sources"> <p>Overrides Request.method</p></aside></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="initializerequest-params" data-typedoc-h="3"><span>params: \{ protocolVersion: string; capabilities: ClientCapabilities; clientInfo: Implementation; }</span><a href="#initializerequest-params" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-type-declaration"> <div data-typedoc-h="4">Type Declaration</div> <ul class="tsd-parameters"> <li class="tsd-parameter"> <div data-typedoc-h="5"><span class="tsd-kind-property">protocolVersion</span><span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">string</span></div> <div class="tsd-comment tsd-typography"><p>The latest version of the Model Context Protocol that the client supports. The client MAY decide to support older versions as well.</p> </div></li> <li class="tsd-parameter"> <div data-typedoc-h="5"><span class="tsd-kind-property">capabilities</span><span class="tsd-signature-symbol">: </span><a href="#clientcapabilities" class="tsd-signature-type tsd-kind-interface">ClientCapabilities</a></div></li> <li class="tsd-parameter"> <div data-typedoc-h="5"><span class="tsd-kind-property">clientInfo</span><span class="tsd-signature-symbol">: </span><a href="#implementation" class="tsd-signature-type tsd-kind-interface">Implementation</a></div></li></ul></div><aside class="tsd-sources"> <p>Overrides Request.params</p></aside></section>
</div>
<div class="type">
### `InitializeResult`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">InitializeResult</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#initializeresult-_meta">\_meta</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-symbol">\{</span> <span class="tsd-signature-symbol">\[</span><span class="tsd-kind-index-signature">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <span class="tsd-signature-type">unknown</span> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#initializeresult-protocolversion">protocolVersion</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#initializeresult-capabilities">capabilities</a><span class="tsd-signature-symbol">:</span> <a href="#servercapabilities" class="tsd-signature-type tsd-kind-interface">ServerCapabilities</a><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#initializeresult-serverinfo">serverInfo</a><span class="tsd-signature-symbol">:</span> <a href="#implementation" class="tsd-signature-type tsd-kind-interface">Implementation</a><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#initializeresult-instructions">instructions</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <span class="tsd-signature-symbol">\[</span><span class="tsd-kind-index-signature">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <span class="tsd-signature-type">unknown</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>After receiving an initialize request from the client, the server sends this response.</p> </div> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="initializeresult-_meta" data-typedoc-h="3"><span>\_meta?: \{ \[key: string]: unknown }</span><a href="#initializeresult-_meta" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>See <a href="/specification/2025-06-18/basic/index#meta">General fields: <code>\_meta</code></a> for notes on <code>\_meta</code> usage.</p> </div><aside class="tsd-sources"> <p>Inherited from <a href="#result">Result</a>.<a href="#result-_meta">\_meta</a></p></aside></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="initializeresult-protocolversion" data-typedoc-h="3"><span>protocolVersion: string</span><a href="#initializeresult-protocolversion" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>The version of the Model Context Protocol that the server wants to use. This may not match the version that the client requested. If the client cannot support this version, it MUST disconnect.</p> </div></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="initializeresult-capabilities" data-typedoc-h="3"><span>capabilities: ServerCapabilities</span><a href="#initializeresult-capabilities" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="initializeresult-serverinfo" data-typedoc-h="3"><span>serverInfo: Implementation</span><a href="#initializeresult-serverinfo" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="initializeresult-instructions" data-typedoc-h="3"><span>instructions?: string</span><a href="#initializeresult-instructions" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>Instructions describing how to use the server and its features.</p> <p>This can be used by clients to improve the LLM's understanding of available tools, resources, etc. It can be thought of like a "hint" to the model. For example, this information MAY be added to the system prompt.</p> </div></section>
</div>
<div class="type">
### `ClientCapabilities`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">ClientCapabilities</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#clientcapabilities-experimental">experimental</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-symbol">\{</span> <span class="tsd-signature-symbol">\[</span><span class="tsd-kind-index-signature">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <span class="tsd-signature-type">object</span> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#clientcapabilities-roots">roots</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-symbol">\{</span> <span class="tsd-kind-property">listChanged</span><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">boolean</span> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#clientcapabilities-sampling">sampling</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">object</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#clientcapabilities-elicitation">elicitation</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">object</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>Capabilities a client may support. Known capabilities are defined here, in this schema, but this is not a closed set: any client can define its own, additional capabilities.</p> </div> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="clientcapabilities-experimental" data-typedoc-h="3"><span>experimental?: \{ \[key: string]: object }</span><a href="#clientcapabilities-experimental" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>Experimental, non-standard capabilities that the client supports.</p> </div></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="clientcapabilities-roots" data-typedoc-h="3"><span>roots?: \{ listChanged?: boolean }</span><a href="#clientcapabilities-roots" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>Present if the client supports listing roots.</p> </div> <div class="tsd-type-declaration"> <div data-typedoc-h="4">Type Declaration</div> <ul class="tsd-parameters"> <li class="tsd-parameter"> <div data-typedoc-h="5"><code class="tsd-tag">Optional</code><span class="tsd-kind-property">listChanged</span><span class="tsd-signature-symbol">?: </span><span class="tsd-signature-type">boolean</span></div> <div class="tsd-comment tsd-typography"><p>Whether the client supports notifications for changes to the roots list.</p> </div></li></ul></div></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="clientcapabilities-sampling" data-typedoc-h="3"><span>sampling?: object</span><a href="#clientcapabilities-sampling" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>Present if the client supports sampling from an LLM.</p> </div></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="clientcapabilities-elicitation" data-typedoc-h="3"><span>elicitation?: object</span><a href="#clientcapabilities-elicitation" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>Present if the client supports elicitation from the server.</p> </div></section>
</div>
<div class="type">
### `Implementation`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">Implementation</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#implementation-name">name</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#implementation-title">title</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#implementation-version">version</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>Describes the name and version of an MCP implementation, with an optional title for UI representation.</p> </div> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="implementation-name" data-typedoc-h="3"><span>name: string</span><a href="#implementation-name" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>Intended for programmatic or logical use, but used as a display name in past specs or fallback (if title isn't present).</p> </div><aside class="tsd-sources"> <p>Inherited from BaseMetadata.name</p></aside></section> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="implementation-title" data-typedoc-h="3"><span>title?: string</span><a href="#implementation-title" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>Intended for UI and end-user contexts — optimized to be human-readable and easily understood,
even by those unfamiliar with domain-specific terminology.</p> <p>If not provided, the name should be used for display (except for Tool,
where <code>annotations.title</code> should be given precedence over using <code>name</code>,
if present).</p> </div><aside class="tsd-sources"> <p>Inherited from BaseMetadata.title</p></aside></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="implementation-version" data-typedoc-h="3"><span>version: string</span><a href="#implementation-version" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section>
</div>
<div class="type">
### `ServerCapabilities`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">ServerCapabilities</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#servercapabilities-experimental">experimental</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-symbol">\{</span> <span class="tsd-signature-symbol">\[</span><span class="tsd-kind-index-signature">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <span class="tsd-signature-type">object</span> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#servercapabilities-logging">logging</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">object</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#servercapabilities-completions">completions</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">object</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#servercapabilities-prompts">prompts</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-symbol">\{</span> <span class="tsd-kind-property">listChanged</span><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">boolean</span> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#servercapabilities-resources">resources</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-symbol">\{</span> <span class="tsd-kind-property">subscribe</span><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">boolean</span><span class="tsd-signature-symbol">;</span> <span class="tsd-kind-property">listChanged</span><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">boolean</span> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#servercapabilities-tools">tools</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-symbol">\{</span> <span class="tsd-kind-property">listChanged</span><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">boolean</span> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>Capabilities that a server may support. Known capabilities are defined here, in this schema, but this is not a closed set: any server can define its own, additional capabilities.</p> </div> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="servercapabilities-experimental" data-typedoc-h="3"><span>experimental?: \{ \[key: string]: object }</span><a href="#servercapabilities-experimental" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>Experimental, non-standard capabilities that the server supports.</p> </div></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="servercapabilities-logging" data-typedoc-h="3"><span>logging?: object</span><a href="#servercapabilities-logging" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>Present if the server supports sending log messages to the client.</p> </div></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="servercapabilities-completions" data-typedoc-h="3"><span>completions?: object</span><a href="#servercapabilities-completions" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>Present if the server supports argument autocompletion suggestions.</p> </div></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="servercapabilities-prompts" data-typedoc-h="3"><span>prompts?: \{ listChanged?: boolean }</span><a href="#servercapabilities-prompts" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>Present if the server offers any prompt templates.</p> </div> <div class="tsd-type-declaration"> <div data-typedoc-h="4">Type Declaration</div> <ul class="tsd-parameters"> <li class="tsd-parameter"> <div data-typedoc-h="5"><code class="tsd-tag">Optional</code><span class="tsd-kind-property">listChanged</span><span class="tsd-signature-symbol">?: </span><span class="tsd-signature-type">boolean</span></div> <div class="tsd-comment tsd-typography"><p>Whether this server supports notifications for changes to the prompt list.</p> </div></li></ul></div></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="servercapabilities-resources" data-typedoc-h="3"><span>resources?: \{ subscribe?: boolean; listChanged?: boolean }</span><a href="#servercapabilities-resources" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>Present if the server offers any resources to read.</p> </div> <div class="tsd-type-declaration"> <div data-typedoc-h="4">Type Declaration</div> <ul class="tsd-parameters"> <li class="tsd-parameter"> <div data-typedoc-h="5"><code class="tsd-tag">Optional</code><span class="tsd-kind-property">subscribe</span><span class="tsd-signature-symbol">?: </span><span class="tsd-signature-type">boolean</span></div> <div class="tsd-comment tsd-typography"><p>Whether this server supports subscribing to resource updates.</p> </div></li> <li class="tsd-parameter"> <div data-typedoc-h="5"><code class="tsd-tag">Optional</code><span class="tsd-kind-property">listChanged</span><span class="tsd-signature-symbol">?: </span><span class="tsd-signature-type">boolean</span></div> <div class="tsd-comment tsd-typography"><p>Whether this server supports notifications for changes to the resource list.</p> </div></li></ul></div></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="servercapabilities-tools" data-typedoc-h="3"><span>tools?: \{ listChanged?: boolean }</span><a href="#servercapabilities-tools" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>Present if the server offers any tools to call.</p> </div> <div class="tsd-type-declaration"> <div data-typedoc-h="4">Type Declaration</div> <ul class="tsd-parameters"> <li class="tsd-parameter"> <div data-typedoc-h="5"><code class="tsd-tag">Optional</code><span class="tsd-kind-property">listChanged</span><span class="tsd-signature-symbol">?: </span><span class="tsd-signature-type">boolean</span></div> <div class="tsd-comment tsd-typography"><p>Whether this server supports notifications for changes to the tool list.</p> </div></li></ul></div></section>
</div>
## `logging/setLevel`
<div class="type">
### `SetLevelRequest`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">SetLevelRequest</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#setlevelrequest-method">method</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">"logging/setLevel"</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#setlevelrequest-params">params</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-symbol">\{</span> <span class="tsd-kind-property">level</span><span class="tsd-signature-symbol">:</span> <a href="#logginglevel" class="tsd-signature-type tsd-kind-type-alias">LoggingLevel</a> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>A request from the client to the server, to enable or adjust logging.</p> </div> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="setlevelrequest-method" data-typedoc-h="3"><span>method: "logging/setLevel"</span><a href="#setlevelrequest-method" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <aside class="tsd-sources"> <p>Overrides Request.method</p></aside></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="setlevelrequest-params" data-typedoc-h="3"><span>params: \{ level: LoggingLevel }</span><a href="#setlevelrequest-params" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-type-declaration"> <div data-typedoc-h="4">Type Declaration</div> <ul class="tsd-parameters"> <li class="tsd-parameter"> <div data-typedoc-h="5"><span class="tsd-kind-property">level</span><span class="tsd-signature-symbol">: </span><a href="#logginglevel" class="tsd-signature-type tsd-kind-type-alias">LoggingLevel</a></div> <div class="tsd-comment tsd-typography"><p>The level of logging that the client wants to receive from the server. The server should send all logs at this level and higher (i.e., more severe) to the client as notifications/message.</p> </div></li></ul></div><aside class="tsd-sources"> <p>Overrides Request.params</p></aside></section>
</div>
## `notifications/cancelled`
<div class="type">
### `CancelledNotification`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">CancelledNotification</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#cancellednotification-method">method</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">"notifications/cancelled"</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#cancellednotification-params">params</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-symbol">\{</span> <span class="tsd-kind-property">requestId</span><span class="tsd-signature-symbol">:</span> <a href="#requestid" class="tsd-signature-type tsd-kind-type-alias">RequestId</a><span class="tsd-signature-symbol">;</span> <span class="tsd-kind-property">reason</span><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">string</span> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>This notification can be sent by either side to indicate that it is cancelling a previously-issued request.</p> <p>The request SHOULD still be in-flight, but due to communication latency, it is always possible that this notification MAY arrive after the request has already finished.</p> <p>This notification indicates that the result will be unused, so any associated processing SHOULD cease.</p> <p>A client MUST NOT attempt to cancel its <code>initialize</code> request.</p> </div> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="cancellednotification-method" data-typedoc-h="3"><span>method: "notifications/cancelled"</span><a href="#cancellednotification-method" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <aside class="tsd-sources"> <p>Overrides Notification.method</p></aside></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="cancellednotification-params" data-typedoc-h="3"><span>params: \{ requestId: RequestId; reason?: string }</span><a href="#cancellednotification-params" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-type-declaration"> <div data-typedoc-h="4">Type Declaration</div> <ul class="tsd-parameters"> <li class="tsd-parameter"> <div data-typedoc-h="5"><span class="tsd-kind-property">requestId</span><span class="tsd-signature-symbol">: </span><a href="#requestid" class="tsd-signature-type tsd-kind-type-alias">RequestId</a></div> <div class="tsd-comment tsd-typography"><p>The ID of the request to cancel.</p> <p>This MUST correspond to the ID of a request previously issued in the same direction.</p> </div></li> <li class="tsd-parameter"> <div data-typedoc-h="5"><code class="tsd-tag">Optional</code><span class="tsd-kind-property">reason</span><span class="tsd-signature-symbol">?: </span><span class="tsd-signature-type">string</span></div> <div class="tsd-comment tsd-typography"><p>An optional string describing the reason for the cancellation. This MAY be logged or presented to the user.</p> </div></li></ul></div><aside class="tsd-sources"> <p>Overrides Notification.params</p></aside></section>
</div>
## `notifications/initialized`
<div class="type">
### `InitializedNotification`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">InitializedNotification</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#initializednotification-params">params</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-symbol">\{</span> <span class="tsd-kind-property">\_meta</span><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-symbol">\{</span> <span class="tsd-signature-symbol">\[</span><span class="tsd-kind-index-signature">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <span class="tsd-signature-type">unknown</span> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span> <span class="tsd-signature-symbol">\[</span><span class="tsd-kind-index-signature">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <span class="tsd-signature-type">unknown</span> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#initializednotification-method">method</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">"notifications/initialized"</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>This notification is sent from the client to the server after initialization has finished.</p> </div> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="initializednotification-params" data-typedoc-h="3"><span>params?: \{ \_meta?: \{ \[key: string]: unknown }; \[key: string]: unknown }</span><a href="#initializednotification-params" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-type-declaration"> <div data-typedoc-h="4">Type Declaration</div> <ul class="tsd-parameters"> <li class="tsd-parameter-index-signature"> <div data-typedoc-h="5"><span class="tsd-signature-symbol">\[</span><span class="tsd-kind-parameter">key</span>: <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <span class="tsd-signature-type">unknown</span></div></li> <li class="tsd-parameter"> <div data-typedoc-h="5"><code class="tsd-tag">Optional</code><span class="tsd-kind-property">\_meta</span><span class="tsd-signature-symbol">?: </span><span class="tsd-signature-symbol">\{</span> <span class="tsd-signature-symbol">\[</span><span class="tsd-kind-index-signature">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <span class="tsd-signature-type">unknown</span> <span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>See <a href="/specification/2025-06-18/basic/index#meta">General fields: <code>\_meta</code></a> for notes on <code>\_meta</code> usage.</p> </div></li></ul></div><aside class="tsd-sources"> <p>Inherited from Notification.params</p></aside></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="initializednotification-method" data-typedoc-h="3"><span>method: "notifications/initialized"</span><a href="#initializednotification-method" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <aside class="tsd-sources"> <p>Overrides Notification.method</p></aside></section>
</div>
## `notifications/message`
<div class="type">
### `LoggingMessageNotification`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">LoggingMessageNotification</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#loggingmessagenotification-method">method</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">"notifications/message"</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#loggingmessagenotification-params">params</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-symbol">\{</span> <span class="tsd-kind-property">level</span><span class="tsd-signature-symbol">:</span> <a href="#logginglevel" class="tsd-signature-type tsd-kind-type-alias">LoggingLevel</a><span class="tsd-signature-symbol">;</span> <span class="tsd-kind-property">logger</span><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span> <span class="tsd-kind-property">data</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">unknown</span> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>Notification of a log message passed from server to client. If no logging/setLevel request has been sent from the client, the server MAY decide which messages to send automatically.</p> </div> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="loggingmessagenotification-method" data-typedoc-h="3"><span>method: "notifications/message"</span><a href="#loggingmessagenotification-method" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <aside class="tsd-sources"> <p>Overrides Notification.method</p></aside></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="loggingmessagenotification-params" data-typedoc-h="3"><span>params: \{ level: LoggingLevel; logger?: string; data: unknown }</span><a href="#loggingmessagenotification-params" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-type-declaration"> <div data-typedoc-h="4">Type Declaration</div> <ul class="tsd-parameters"> <li class="tsd-parameter"> <div data-typedoc-h="5"><span class="tsd-kind-property">level</span><span class="tsd-signature-symbol">: </span><a href="#logginglevel" class="tsd-signature-type tsd-kind-type-alias">LoggingLevel</a></div> <div class="tsd-comment tsd-typography"><p>The severity of this log message.</p> </div></li> <li class="tsd-parameter"> <div data-typedoc-h="5"><code class="tsd-tag">Optional</code><span class="tsd-kind-property">logger</span><span class="tsd-signature-symbol">?: </span><span class="tsd-signature-type">string</span></div> <div class="tsd-comment tsd-typography"><p>An optional name of the logger issuing this message.</p> </div></li> <li class="tsd-parameter"> <div data-typedoc-h="5"><span class="tsd-kind-property">data</span><span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">unknown</span></div> <div class="tsd-comment tsd-typography"><p>The data to be logged, such as a string message or an object. Any JSON serializable type is allowed here.</p> </div></li></ul></div><aside class="tsd-sources"> <p>Overrides Notification.params</p></aside></section>
</div>
## `notifications/progress`
<div class="type">
### `ProgressNotification`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">ProgressNotification</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#progressnotification-method">method</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">"notifications/progress"</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#progressnotification-params">params</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-symbol">\{</span><br /> <span class="tsd-kind-property">progressToken</span><span class="tsd-signature-symbol">:</span> <a href="#progresstoken" class="tsd-signature-type tsd-kind-type-alias">ProgressToken</a><span class="tsd-signature-symbol">;</span><br /> <span class="tsd-kind-property">progress</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">;</span><br /> <span class="tsd-kind-property">total</span><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">;</span><br /> <span class="tsd-kind-property">message</span><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>An out-of-band notification used to inform the receiver of a progress update for a long-running request.</p> </div> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="progressnotification-method" data-typedoc-h="3"><span>method: "notifications/progress"</span><a href="#progressnotification-method" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <aside class="tsd-sources"> <p>Overrides Notification.method</p></aside></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="progressnotification-params" data-typedoc-h="3"><span>params: \{ progressToken: ProgressToken; progress: number; total?: number; message?: string; }</span><a href="#progressnotification-params" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-type-declaration"> <div data-typedoc-h="4">Type Declaration</div> <ul class="tsd-parameters"> <li class="tsd-parameter"> <div data-typedoc-h="5"><span class="tsd-kind-property">progressToken</span><span class="tsd-signature-symbol">: </span><a href="#progresstoken" class="tsd-signature-type tsd-kind-type-alias">ProgressToken</a></div> <div class="tsd-comment tsd-typography"><p>The progress token which was given in the initial request, used to associate this notification with the request that is proceeding.</p> </div></li> <li class="tsd-parameter"> <div data-typedoc-h="5"><span class="tsd-kind-property">progress</span><span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">number</span></div> <div class="tsd-comment tsd-typography"><p>The progress thus far. This should increase every time progress is made, even if the total is unknown.</p> </div></li> <li class="tsd-parameter"> <div data-typedoc-h="5"><code class="tsd-tag">Optional</code><span class="tsd-kind-property">total</span><span class="tsd-signature-symbol">?: </span><span class="tsd-signature-type">number</span></div> <div class="tsd-comment tsd-typography"><p>Total number of items to process (or total progress required), if known.</p> </div></li> <li class="tsd-parameter"> <div data-typedoc-h="5"><code class="tsd-tag">Optional</code><span class="tsd-kind-property">message</span><span class="tsd-signature-symbol">?: </span><span class="tsd-signature-type">string</span></div> <div class="tsd-comment tsd-typography"><p>An optional message describing the current progress.</p> </div></li></ul></div><aside class="tsd-sources"> <p>Overrides Notification.params</p></aside></section>
</div>
## `notifications/prompts/list_changed`
<div class="type">
### `PromptListChangedNotification`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">PromptListChangedNotification</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#promptlistchangednotification-params">params</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-symbol">\{</span> <span class="tsd-kind-property">\_meta</span><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-symbol">\{</span> <span class="tsd-signature-symbol">\[</span><span class="tsd-kind-index-signature">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <span class="tsd-signature-type">unknown</span> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span> <span class="tsd-signature-symbol">\[</span><span class="tsd-kind-index-signature">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <span class="tsd-signature-type">unknown</span> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#promptlistchangednotification-method">method</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">"notifications/prompts/list\_changed"</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>An optional notification from the server to the client, informing it that the list of prompts it offers has changed. This may be issued by servers without any previous subscription from the client.</p> </div> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="promptlistchangednotification-params" data-typedoc-h="3"><span>params?: \{ \_meta?: \{ \[key: string]: unknown }; \[key: string]: unknown }</span><a href="#promptlistchangednotification-params" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-type-declaration"> <div data-typedoc-h="4">Type Declaration</div> <ul class="tsd-parameters"> <li class="tsd-parameter-index-signature"> <div data-typedoc-h="5"><span class="tsd-signature-symbol">\[</span><span class="tsd-kind-parameter">key</span>: <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <span class="tsd-signature-type">unknown</span></div></li> <li class="tsd-parameter"> <div data-typedoc-h="5"><code class="tsd-tag">Optional</code><span class="tsd-kind-property">\_meta</span><span class="tsd-signature-symbol">?: </span><span class="tsd-signature-symbol">\{</span> <span class="tsd-signature-symbol">\[</span><span class="tsd-kind-index-signature">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <span class="tsd-signature-type">unknown</span> <span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>See <a href="/specification/2025-06-18/basic/index#meta">General fields: <code>\_meta</code></a> for notes on <code>\_meta</code> usage.</p> </div></li></ul></div><aside class="tsd-sources"> <p>Inherited from Notification.params</p></aside></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="promptlistchangednotification-method" data-typedoc-h="3"><span>method: "notifications/prompts/list\_changed"</span><a href="#promptlistchangednotification-method" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <aside class="tsd-sources"> <p>Overrides Notification.method</p></aside></section>
Cut at 300 lines. The page has the rest.
specification/2025-06-18/server/index New page · 29 lines, new page
# Overview
A whole new page. There's nothing to diff it against, so here is what it says.
# Overview
Servers provide the fundamental building blocks for adding context to language models via
MCP. These primitives enable rich interactions between clients, servers, and language
models:
* **Prompts**: Pre-defined templates or instructions that guide language model
interactions
* **Resources**: Structured data or content that provides additional context to the model
* **Tools**: Executable functions that allow models to perform actions or retrieve
information
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 |
Explore these key primitives in more detail below:
<CardGroup cols={3}>
<Card title="Prompts" icon="message" href="/specification/2025-06-18/server/prompts" />
<Card title="Resources" icon="file-lines" href="/specification/2025-06-18/server/resources" />
<Card title="Tools" icon="wrench" href="/specification/2025-06-18/server/tools" />
</CardGroup>
specification/2025-06-18/server/prompts New page · 276 lines, new page
# Prompts ## User Interaction Model ## Capabilities ## Protocol Messages ### Listing Prompts ### Getting a Prompt ### List Changed Notification ## Message Flow ## Data Types ### Prompt ### PromptMessage #### Text Content #### Image Content #### Audio Content #### Embedded Resources ## Error Handling ## Implementation Considerations ## Security
A whole new page. There's nothing to diff it against, so here is what it says.
# Prompts
<div id="enable-section-numbers" />
The Model Context Protocol (MCP) provides a standardized way for servers to expose prompt
templates to clients. Prompts allow servers to provide structured messages and
instructions for interacting with language models. Clients can discover available
prompts, retrieve their contents, and provide arguments to customize them.
## User Interaction Model
Prompts are designed to be **user-controlled**, meaning they are exposed from servers to
clients with the intention of the user being able to explicitly select them for use.
Typically, prompts would be triggered through user-initiated commands in the user
interface, which allows users to naturally discover and invoke available prompts.
For example, as slash commands:
<img src="https://mintcdn.com/mcp/4ZXF1PrDkEaJvXpn/specification/2025-06-18/server/slash-command.png?fit=max&auto=format&n=4ZXF1PrDkEaJvXpn&q=85&s=7f003e36d881dd6f3e5b8cbdd85e5ca5" alt="Example of prompt exposed as slash command" width="293" height="106" data-path="specification/2025-06-18/server/slash-command.png" />
However, implementors are free to expose prompts through any interface pattern that suits
their needs—the protocol itself does not mandate any specific user interaction
model.
## Capabilities
Servers that support prompts **MUST** declare the `prompts` capability during
[initialization](/specification/2025-06-18/basic/lifecycle#initialization):
```json theme={null}
{
"capabilities": {
"prompts": {
"listChanged": true
}
}
}
```
`listChanged` indicates whether the server will emit notifications when the list of
available prompts changes.
## Protocol Messages
### Listing Prompts
To retrieve available prompts, clients send a `prompts/list` request. This operation
supports [pagination](/specification/2025-06-18/server/utilities/pagination).
**Request:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"method": "prompts/list",
"params": {
"cursor": "optional-cursor-value"
}
}
```
**Response:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"prompts": [
{
"name": "code_review",
"title": "Request Code Review",
"description": "Asks the LLM to analyze code quality and suggest improvements",
"arguments": [
{
"name": "code",
"description": "The code to review",
"required": true
}
]
}
],
"nextCursor": "next-page-cursor"
}
}
```
### Getting a Prompt
To retrieve a specific prompt, clients send a `prompts/get` request. Arguments may be
auto-completed through [the completion API](/specification/2025-06-18/server/utilities/completion).
**Request:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 2,
"method": "prompts/get",
"params": {
"name": "code_review",
"arguments": {
"code": "def hello():\n print('world')"
}
}
}
```
**Response:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"description": "Code review prompt",
"messages": [
{
"role": "user",
"content": {
"type": "text",
"text": "Please review this Python code:\ndef hello():\n print('world')"
}
}
]
}
}
```
### List Changed Notification
When the list of available prompts changes, servers that declared the `listChanged`
capability **SHOULD** send a notification:
```json theme={null}
{
"jsonrpc": "2.0",
"method": "notifications/prompts/list_changed"
}
```
## Message Flow
```mermaid theme={null}
sequenceDiagram
participant Client
participant Server
Note over Client,Server: Discovery
Client->>Server: prompts/list
Server-->>Client: List of prompts
Note over Client,Server: Usage
Client->>Server: prompts/get
Server-->>Client: Prompt content
opt listChanged
Note over Client,Server: Changes
Server--)Client: prompts/list_changed
Client->>Server: prompts/list
Server-->>Client: Updated prompts
end
```
## Data Types
### Prompt
A prompt definition includes:
* `name`: Unique identifier for the prompt
* `title`: Optional human-readable name of the prompt for display purposes.
* `description`: Optional human-readable description
* `arguments`: Optional list of arguments for customization
### PromptMessage
Messages in a prompt can contain:
* `role`: Either "user" or "assistant" to indicate the speaker
* `content`: One of the following content types:
<Note>
All content types in prompt messages support optional
[annotations](/specification/2025-06-18/server/resources#annotations) for
metadata about audience, priority, and modification times.
</Note>
#### Text Content
Text content represents plain text messages:
```json theme={null}
{
"type": "text",
"text": "The text content of the message"
}
```
This is the most common content type used for natural language interactions.
#### Image Content
Image content allows including visual information in messages:
```json theme={null}
{
"type": "image",
"data": "base64-encoded-image-data",
"mimeType": "image/png"
}
```
The image data **MUST** be base64-encoded and include a valid MIME type. This enables
multi-modal interactions where visual context is important.
#### Audio Content
Audio content allows including audio information in messages:
```json theme={null}
{
"type": "audio",
"data": "base64-encoded-audio-data",
"mimeType": "audio/wav"
}
```
The audio data MUST be base64-encoded and include a valid MIME type. This enables
multi-modal interactions where audio context is important.
#### Embedded Resources
Embedded resources allow referencing server-side resources directly in messages:
```json theme={null}
{
"type": "resource",
"resource": {
"uri": "resource://example",
"mimeType": "text/plain",
"text": "Resource content"
}
}
```
Resources can contain either text or binary (blob) data and **MUST** include:
* A valid resource URI
* The appropriate MIME type
* Either text content or base64-encoded blob data
Embedded resources enable prompts to seamlessly incorporate server-managed content like
documentation, code samples, or other reference materials directly into the conversation
flow.
## Error Handling
Servers **SHOULD** return standard JSON-RPC errors for common failure cases:
* Invalid prompt name: `-32602` (Invalid params)
* Missing required arguments: `-32602` (Invalid params)
* Internal errors: `-32603` (Internal error)
## Implementation Considerations
1. Servers **SHOULD** validate prompt arguments before processing
2. Clients **SHOULD** handle pagination for large prompt lists
3. Both parties **SHOULD** respect capability negotiation
## Security
Implementations **MUST** carefully validate all prompt inputs and outputs to prevent
injection attacks or unauthorized access to resources.
specification/2025-06-18/server/resources New page · 400 lines, new page
# Resources ## User Interaction Model ## Capabilities ## Protocol Messages ### Listing Resources ### Reading Resources ### Resource Templates ### List Changed Notification ### Subscriptions ## Message Flow ## Data Types ### Resource ### Resource Contents #### Text Content #### Binary Content ### Annotations ## Common URI Schemes ### https\:// ### file:// ### git:// ### Custom URI Schemes ## Error Handling ## Security Considerations
A whole new page. There's nothing to diff it against, so here is what it says.
# Resources
<div id="enable-section-numbers" />
The Model Context Protocol (MCP) provides a standardized way for servers to expose
resources to clients. Resources allow servers to share data that provides context to
language models, such as files, database schemas, or application-specific information.
Each resource is uniquely identified by a
[URI](https://datatracker.ietf.org/doc/html/rfc3986).
## User Interaction Model
Resources in MCP are designed to be **application-driven**, with host applications
determining how to incorporate context based on their needs.
For example, applications could:
* Expose resources through UI elements for explicit selection, in a tree or list view
* Allow the user to search through and filter available resources
* Implement automatic context inclusion, based on heuristics or the AI model's selection
<img src="https://mintcdn.com/mcp/4ZXF1PrDkEaJvXpn/specification/2025-06-18/server/resource-picker.png?fit=max&auto=format&n=4ZXF1PrDkEaJvXpn&q=85&s=133fa885ef6e9c2e20049da5c33f4386" alt="Example of resource context picker" width="174" height="181" data-path="specification/2025-06-18/server/resource-picker.png" />
However, implementations are free to expose resources through any interface pattern that
suits their needs—the protocol itself does not mandate any specific user
interaction model.
## Capabilities
Servers that support resources **MUST** declare the `resources` capability:
```json theme={null}
{
"capabilities": {
"resources": {
"subscribe": true,
"listChanged": true
}
}
}
```
The capability supports two optional features:
* `subscribe`: whether the client can subscribe to be notified of changes to individual
resources.
* `listChanged`: whether the server will emit notifications when the list of available
resources changes.
Both `subscribe` and `listChanged` are optional—servers can support neither,
either, or both:
```json theme={null}
{
"capabilities": {
"resources": {} // Neither feature supported
}
}
```
```json theme={null}
{
"capabilities": {
"resources": {
"subscribe": true // Only subscriptions supported
}
}
}
```
```json theme={null}
{
"capabilities": {
"resources": {
"listChanged": true // Only list change notifications supported
}
}
}
```
## Protocol Messages
### Listing Resources
To discover available resources, clients send a `resources/list` request. This operation
supports [pagination](/specification/2025-06-18/server/utilities/pagination).
**Request:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"method": "resources/list",
"params": {
"cursor": "optional-cursor-value"
}
}
```
**Response:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"resources": [
{
"uri": "file:///project/src/main.rs",
"name": "main.rs",
"title": "Rust Software Application Main File",
"description": "Primary application entry point",
"mimeType": "text/x-rust"
}
],
"nextCursor": "next-page-cursor"
}
}
```
### Reading Resources
To retrieve resource contents, clients send a `resources/read` request:
**Request:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 2,
"method": "resources/read",
"params": {
"uri": "file:///project/src/main.rs"
}
}
```
**Response:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"contents": [
{
"uri": "file:///project/src/main.rs",
"mimeType": "text/x-rust",
"text": "fn main() {\n println!(\"Hello world!\");\n}"
}
]
}
}
```
### Resource Templates
Resource templates allow servers to expose parameterized resources using
[URI templates](https://datatracker.ietf.org/doc/html/rfc6570). Arguments may be
auto-completed through [the completion API](/specification/2025-06-18/server/utilities/completion).
This operation supports [pagination](/specification/2025-06-18/server/utilities/pagination).
**Request:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 3,
"method": "resources/templates/list",
"params": {
"cursor": "optional-cursor-value"
}
}
```
**Response:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 3,
"result": {
"resourceTemplates": [
{
"uriTemplate": "file:///{path}",
"name": "Project Files",
"title": "📁 Project Files",
"description": "Access files in the project directory",
"mimeType": "application/octet-stream"
}
],
"nextCursor": "next-page-cursor"
}
}
```
### List Changed Notification
When the list of available resources changes, servers that declared the `listChanged`
capability **SHOULD** send a notification:
```json theme={null}
{
"jsonrpc": "2.0",
"method": "notifications/resources/list_changed"
}
```
### Subscriptions
The protocol supports optional subscriptions to resource changes. Clients can subscribe
to specific resources and receive notifications when they change:
**Subscribe Request:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 4,
"method": "resources/subscribe",
"params": {
"uri": "file:///project/src/main.rs"
}
}
```
**Update Notification:**
```json theme={null}
{
"jsonrpc": "2.0",
"method": "notifications/resources/updated",
"params": {
"uri": "file:///project/src/main.rs"
}
}
```
## Message Flow
```mermaid theme={null}
sequenceDiagram
participant Client
participant Server
Note over Client,Server: Resource Discovery
Client->>Server: resources/list
Server-->>Client: List of resources
Note over Client,Server: Resource Template Discovery
Client->>Server: resources/templates/list
Server-->>Client: List of resource templates
Note over Client,Server: Resource Access
Client->>Server: resources/read
Server-->>Client: Resource contents
Note over Client,Server: Subscriptions
Client->>Server: resources/subscribe
Server-->>Client: Subscription confirmed
Note over Client,Server: Updates
Server--)Client: notifications/resources/updated
Client->>Server: resources/read
Server-->>Client: Updated contents
```
## Data Types
### Resource
A resource definition includes:
* `uri`: Unique identifier for the resource
* `name`: The name of the resource.
* `title`: Optional human-readable name of the resource for display purposes.
* `description`: Optional description
* `mimeType`: Optional MIME type
* `size`: Optional size in bytes
### Resource Contents
Resources can contain either text or binary data:
#### Text Content
```json theme={null}
{
"uri": "file:///example.txt",
"mimeType": "text/plain",
"text": "Resource content"
}
```
#### Binary Content
```json theme={null}
{
"uri": "file:///example.png",
Cut at 300 lines. The page has the rest.
specification/2025-06-18/server/tools New page · 436 lines, new page
# Tools ## User Interaction Model ## Capabilities ## Protocol Messages ### Listing Tools ### Calling Tools ### List Changed Notification ## Message Flow ## Data Types ### Tool ### Tool Result #### Text Content #### Image Content #### Audio Content #### Resource Links #### Embedded Resources #### Structured Content #### Output Schema ## Error Handling ## Security Considerations
A whole new page. There's nothing to diff it against, so here is what it says.
# Tools
<div id="enable-section-numbers" />
The Model Context Protocol (MCP) allows servers to expose tools that can be invoked by
language models. Tools enable models to interact with external systems, such as querying
databases, calling APIs, or performing computations. Each tool is uniquely identified by
a name and includes metadata describing its schema.
## User Interaction Model
Tools in MCP are designed to be **model-controlled**, meaning that the language model can
discover and invoke tools automatically based on its contextual understanding and the
user's prompts.
However, implementations are free to expose tools through any interface pattern that
suits their needs—the protocol itself does not mandate any specific user
interaction model.
<Warning>
For trust & safety and security, there **SHOULD** always
be a human in the loop with the ability to deny tool invocations.
Applications **SHOULD**:
* Provide UI that makes clear which tools are being exposed to the AI model
* Insert clear visual indicators when tools are invoked
* Present confirmation prompts to the user for operations, to ensure a human is in the
loop
</Warning>
## Capabilities
Servers that support tools **MUST** declare the `tools` capability:
```json theme={null}
{
"capabilities": {
"tools": {
"listChanged": true
}
}
}
```
`listChanged` indicates whether the server will emit notifications when the list of
available tools changes.
## Protocol Messages
### Listing Tools
To discover available tools, clients send a `tools/list` request. This operation supports
[pagination](/specification/2025-06-18/server/utilities/pagination).
**Request:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list",
"params": {
"cursor": "optional-cursor-value"
}
}
```
**Response:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"tools": [
{
"name": "get_weather",
"title": "Weather Information Provider",
"description": "Get current weather information for a location",
"inputSchema": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "City name or zip code"
}
},
"required": ["location"]
}
}
],
"nextCursor": "next-page-cursor"
}
}
```
### Calling Tools
To invoke a tool, clients send a `tools/call` request:
**Request:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "get_weather",
"arguments": {
"location": "New York"
}
}
}
```
**Response:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"content": [
{
"type": "text",
"text": "Current weather in New York:\nTemperature: 72°F\nConditions: Partly cloudy"
}
],
"isError": false
}
}
```
### List Changed Notification
When the list of available tools changes, servers that declared the `listChanged`
capability **SHOULD** send a notification:
```json theme={null}
{
"jsonrpc": "2.0",
"method": "notifications/tools/list_changed"
}
```
## Message Flow
```mermaid theme={null}
sequenceDiagram
participant LLM
participant Client
participant Server
Note over Client,Server: Discovery
Client->>Server: tools/list
Server-->>Client: List of tools
Note over Client,LLM: Tool Selection
LLM->>Client: Select tool to use
Note over Client,Server: Invocation
Client->>Server: tools/call
Server-->>Client: Tool result
Client->>LLM: Process result
Note over Client,Server: Updates
Server--)Client: tools/list_changed
Client->>Server: tools/list
Server-->>Client: Updated tools
```
## Data Types
### Tool
A tool definition includes:
* `name`: Unique identifier for the tool
* `title`: Optional human-readable name of the tool for display purposes.
* `description`: Human-readable description of functionality
* `inputSchema`: JSON Schema defining expected parameters
* `outputSchema`: Optional JSON Schema defining expected output structure
* `annotations`: optional properties describing tool behavior
<Warning>
For trust & safety and security, clients **MUST** consider
tool annotations to be untrusted unless they come from trusted servers.
</Warning>
### Tool Result
Tool results may contain [**structured**](#structured-content) or **unstructured** content.
**Unstructured** content is returned in the `content` field of a result, and can contain multiple content items of different types:
<Note>
All content types (text, image, audio, resource links, and embedded resources)
support optional
[annotations](/specification/2025-06-18/server/resources#annotations) that
provide metadata about audience, priority, and modification times. This is the
same annotation format used by resources and prompts.
</Note>
#### Text Content
```json theme={null}
{
"type": "text",
"text": "Tool result text"
}
```
#### Image Content
```json theme={null}
{
"type": "image",
"data": "base64-encoded-data",
"mimeType": "image/png"
"annotations": {
"audience": ["user"],
"priority": 0.9
}
}
```
This example demonstrates the use of an optional Annotation.
#### Audio Content
```json theme={null}
{
"type": "audio",
"data": "base64-encoded-audio-data",
"mimeType": "audio/wav"
}
```
#### Resource Links
A tool **MAY** return links to [Resources](/specification/2025-06-18/server/resources), to provide additional context
or data. In this case, the tool will return a URI that can be subscribed to or fetched by the client:
```json theme={null}
{
"type": "resource_link",
"uri": "file:///project/src/main.rs",
"name": "main.rs",
"description": "Primary application entry point",
"mimeType": "text/x-rust",
"annotations": {
"audience": ["assistant"],
"priority": 0.9
}
}
```
Resource links support the same [Resource annotations](/specification/2025-06-18/server/resources#annotations) as regular resources to help clients understand how to use them.
<Info>
Resource links returned by tools are not guaranteed to appear in the results
of a `resources/list` request.
</Info>
#### Embedded Resources
[Resources](/specification/2025-06-18/server/resources) **MAY** be embedded to provide additional context
or data using a suitable [URI scheme](./resources#common-uri-schemes). Servers that use embedded resources **SHOULD** implement the `resources` capability:
```json theme={null}
{
"type": "resource",
"resource": {
"uri": "file:///project/src/main.rs",
"mimeType": "text/x-rust",
"text": "fn main() {\n println!(\"Hello world!\");\n}",
"annotations": {
"audience": ["user", "assistant"],
"priority": 0.7,
"lastModified": "2025-05-03T14:30:00Z"
}
}
}
```
Embedded resources support the same [Resource annotations](/specification/2025-06-18/server/resources#annotations) as regular resources to help clients understand how to use them.
#### Structured Content
**Structured** content is returned as a JSON object in the `structuredContent` field of a result.
For backwards compatibility, a tool that returns structured content SHOULD also return the serialized JSON in a TextContent block.
<Note>
`structuredContent` is server-produced result data and is unrelated to LLM
"structured outputs" (schema-constrained model generation).
</Note>
Cut at 300 lines. The page has the rest.
specification/2025-06-18/server/utilities/completion New page · 200 lines, new page
# Completion ## User Interaction Model ## Capabilities ## Protocol Messages ### Requesting Completions ### Reference Types ### Completion Results ## Message Flow ## Data Types ### CompleteRequest ### CompleteResult ## Error Handling ## Implementation Considerations ## Security
A whole new page. There's nothing to diff it against, so here is what it says.
# Completion
<div id="enable-section-numbers" />
The Model Context Protocol (MCP) provides a standardized way for servers to offer
argument autocompletion suggestions for prompts and resource URIs. This enables rich,
IDE-like experiences where users receive contextual suggestions while entering argument
values.
## User Interaction Model
Completion in MCP is designed to support interactive user experiences similar to IDE code
completion.
For example, applications may show completion suggestions in a dropdown or popup menu as
users type, with the ability to filter and select from available options.
However, implementations are free to expose completion through any interface pattern that
suits their needs—the protocol itself does not mandate any specific user
interaction model.
## Capabilities
Servers that support completions **MUST** declare the `completions` capability:
```json theme={null}
{
"capabilities": {
"completions": {}
}
}
```
## Protocol Messages
### Requesting Completions
To get completion suggestions, clients send a `completion/complete` request specifying
what is being completed through a reference type:
**Request:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"method": "completion/complete",
"params": {
"ref": {
"type": "ref/prompt",
"name": "code_review"
},
"argument": {
"name": "language",
"value": "py"
}
}
}
```
**Response:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"completion": {
"values": ["python", "pytorch", "pyside"],
"total": 10,
"hasMore": true
}
}
}
```
For prompts or URI templates with multiple arguments, clients should include previous completions in the `context.arguments` object to provide context for subsequent requests.
**Request:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"method": "completion/complete",
"params": {
"ref": {
"type": "ref/prompt",
"name": "code_review"
},
"argument": {
"name": "framework",
"value": "fla"
},
"context": {
"arguments": {
"language": "python"
}
}
}
}
```
**Response:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"completion": {
"values": ["flask"],
"total": 1,
"hasMore": false
}
}
}
```
### Reference Types
The protocol supports two types of completion references:
| Type | Description | Example |
| -------------- | --------------------------- | --------------------------------------------------- |
| `ref/prompt` | References a prompt by name | `{"type": "ref/prompt", "name": "code_review"}` |
| `ref/resource` | References a resource URI | `{"type": "ref/resource", "uri": "file:///{path}"}` |
### Completion Results
Servers return an array of completion values ranked by relevance, with:
* Maximum 100 items per response
* Optional total number of available matches
* Boolean indicating if additional results exist
## Message Flow
```mermaid theme={null}
sequenceDiagram
participant Client
participant Server
Note over Client: User types argument
Client->>Server: completion/complete
Server-->>Client: Completion suggestions
Note over Client: User continues typing
Client->>Server: completion/complete
Server-->>Client: Refined suggestions
```
## Data Types
### CompleteRequest
* `ref`: A `PromptReference` or `ResourceReference`
* `argument`: Object containing:
* `name`: Argument name
* `value`: Current value
* `context`: Object containing:
* `arguments`: A mapping of already-resolved argument names to their values.
### CompleteResult
* `completion`: Object containing:
* `values`: Array of suggestions (max 100)
* `total`: Optional total matches
* `hasMore`: Additional results flag
## Error Handling
Servers **SHOULD** return standard JSON-RPC errors for common failure cases:
* Method not found: `-32601` (Capability not supported)
* Invalid prompt name: `-32602` (Invalid params)
* Missing required arguments: `-32602` (Invalid params)
* Internal errors: `-32603` (Internal error)
## Implementation Considerations
1. Servers **SHOULD**:
* Return suggestions sorted by relevance
* Implement fuzzy matching where appropriate
* Rate limit completion requests
* Validate all inputs
2. Clients **SHOULD**:
* Debounce rapid completion requests
* Cache completion results where appropriate
* Handle missing or partial results gracefully
## Security
Implementations **MUST**:
* Validate all completion inputs
* Implement appropriate rate limiting
* Control access to sensitive suggestions
* Prevent completion-based information disclosure
specification/2025-06-18/server/utilities/logging New page · 138 lines, new page
# Logging ## User Interaction Model ## Capabilities ## Log Levels ## Protocol Messages ### Setting Log Level ### Log Message Notifications ## Message Flow ## Error Handling ## Implementation Considerations ## Security
A whole new page. There's nothing to diff it against, so here is what it says.
# Logging
<div id="enable-section-numbers" />
The Model Context Protocol (MCP) provides a standardized way for servers to send
structured log messages to clients. Clients can control logging verbosity by setting
minimum log levels, with servers sending notifications containing severity levels,
optional logger names, and arbitrary JSON-serializable data.
## User Interaction Model
Implementations are free to expose logging through any interface pattern that suits their
needs—the protocol itself does not mandate any specific user interaction model.
## Capabilities
Servers that emit log message notifications **MUST** declare the `logging` capability:
```json theme={null}
{
"capabilities": {
"logging": {}
}
}
```
## Log Levels
The protocol follows the standard syslog severity levels specified in
[RFC 5424](https://datatracker.ietf.org/doc/html/rfc5424#section-6.2.1):
| Level | Description | Example Use Case |
| --------- | -------------------------------- | -------------------------- |
| debug | Detailed debugging information | Function entry/exit points |
| info | General informational messages | Operation progress updates |
| notice | Normal but significant events | Configuration changes |
| warning | Warning conditions | Deprecated feature usage |
| error | Error conditions | Operation failures |
| critical | Critical conditions | System component failures |
| alert | Action must be taken immediately | Data corruption detected |
| emergency | System is unusable | Complete system failure |
## Protocol Messages
### Setting Log Level
To configure the minimum log level, clients **MAY** send a `logging/setLevel` request:
**Request:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"method": "logging/setLevel",
"params": {
"level": "info"
}
}
```
### Log Message Notifications
Servers send log messages using `notifications/message` notifications:
```json theme={null}
{
"jsonrpc": "2.0",
"method": "notifications/message",
"params": {
"level": "error",
"logger": "database",
"data": {
"error": "Connection failed",
"details": {
"host": "localhost",
"port": 5432
}
}
}
}
```
## Message Flow
```mermaid theme={null}
sequenceDiagram
participant Client
participant Server
Note over Client,Server: Configure Logging
Client->>Server: logging/setLevel (info)
Server-->>Client: Empty Result
Note over Client,Server: Server Activity
Server--)Client: notifications/message (info)
Server--)Client: notifications/message (warning)
Server--)Client: notifications/message (error)
Note over Client,Server: Level Change
Client->>Server: logging/setLevel (error)
Server-->>Client: Empty Result
Note over Server: Only sends error level<br/>and above
```
## Error Handling
Servers **SHOULD** return standard JSON-RPC errors for common failure cases:
* Invalid log level: `-32602` (Invalid params)
* Configuration errors: `-32603` (Internal error)
## Implementation Considerations
1. Servers **SHOULD**:
* Rate limit log messages
* Include relevant context in data field
* Use consistent logger names
* Remove sensitive information
2. Clients **MAY**:
* Present log messages in the UI
* Implement log filtering/search
* Display severity visually
* Persist log messages
## Security
1. Log messages **MUST NOT** contain:
* Credentials or secrets
* Personal identifying information
* Internal system details that could aid attacks
2. Implementations **SHOULD**:
* Rate limit messages
* Validate all data fields
* Control log access
* Monitor for sensitive content
specification/2025-06-18/server/utilities/pagination New page · 95 lines, new page
# Pagination ## Pagination Model ## Response Format ## Request Format ## Pagination Flow ## Operations Supporting Pagination ## Implementation Guidelines ## Error Handling
A whole new page. There's nothing to diff it against, so here is what it says.
# Pagination
<div id="enable-section-numbers" />
The Model Context Protocol (MCP) supports paginating list operations that may return
large result sets. Pagination allows servers to yield results in smaller chunks rather
than all at once.
Pagination is especially important when connecting to external services over the
internet, but also useful for local integrations to avoid performance issues with large
data sets.
## Pagination Model
Pagination in MCP uses an opaque cursor-based approach, instead of numbered pages.
* The **cursor** is an opaque string token, representing a position in the result set
* **Page size** is determined by the server, and clients **MUST NOT** assume a fixed page
size
## Response Format
Pagination starts when the server sends a **response** that includes:
* The current page of results
* An optional `nextCursor` field if more results exist
```json theme={null}
{
"jsonrpc": "2.0",
"id": "123",
"result": {
"resources": [...],
"nextCursor": "eyJwYWdlIjogM30="
}
}
```
## Request Format
After receiving a cursor, the client can *continue* paginating by issuing a request
including that cursor:
```json theme={null}
{
"jsonrpc": "2.0",
"id": "124",
"method": "resources/list",
"params": {
"cursor": "eyJwYWdlIjogMn0="
}
}
```
## Pagination Flow
```mermaid theme={null}
sequenceDiagram
participant Client
participant Server
Client->>Server: List Request (no cursor)
loop Pagination Loop
Server-->>Client: Page of results + nextCursor
Client->>Server: List Request (with cursor)
end
```
## Operations Supporting Pagination
The following MCP operations support pagination:
* `resources/list` - List available resources
* `resources/templates/list` - List resource templates
* `prompts/list` - List available prompts
* `tools/list` - List available tools
## Implementation Guidelines
1. Servers **SHOULD**:
* Provide stable cursors
* Handle invalid cursors gracefully
2. Clients **SHOULD**:
* Treat a missing `nextCursor` as the end of results
* Support both paginated and non-paginated flows
3. Clients **MUST** treat cursors as opaque tokens:
* Don't make assumptions about cursor format
* Don't attempt to parse or modify cursors
* Don't persist cursors across sessions
## Error Handling
Invalid cursors **SHOULD** result in an error with code -32602 (Invalid params).
specification/2025-11-25/architecture/index New page · 172 lines, new page
# Architecture ## Core Components ### Host ### Clients ### Servers ## Design Principles ## Capability Negotiation
A whole new page. There's nothing to diff it against, so here is what it says.
# Architecture
<div id="enable-section-numbers" />
The Model Context Protocol (MCP) follows a client-host-server architecture where each
host can run multiple client instances. This architecture enables users to integrate AI
capabilities across applications while maintaining clear security boundaries and
isolating concerns. Built on JSON-RPC, MCP provides a stateful session protocol focused
on context exchange and sampling coordination between clients and servers.
## Core Components
```mermaid theme={null}
graph LR
subgraph "Application Host Process"
H[Host]
C1[Client 1]
C2[Client 2]
C3[Client 3]
H --> C1
H --> C2
H --> C3
end
subgraph "Local machine"
S1[Server 1<br>Files & Git]
S2[Server 2<br>Database]
R1[("Local<br>Resource A")]
R2[("Local<br>Resource B")]
C1 --> S1
C2 --> S2
S1 <--> R1
S2 <--> R2
end
subgraph "Internet"
S3[Server 3<br>External APIs]
R3[("Remote<br>Resource C")]
C3 --> S3
S3 <--> R3
end
```
### Host
The host process acts as the container and coordinator:
* Creates and manages multiple client instances
* Controls client connection permissions and lifecycle
* Enforces security policies and consent requirements
* Handles user authorization decisions
* Coordinates AI/LLM integration and sampling
* Manages context aggregation across clients
### Clients
Each client is created by the host and maintains an isolated server connection:
* Establishes one stateful session per server
* Handles protocol negotiation and capability exchange
* Routes protocol messages bidirectionally
* Manages subscriptions and notifications
* Maintains security boundaries between servers
A host application creates and manages multiple clients, with each client having a 1:1
relationship with a particular server.
### Servers
Servers provide specialized context and capabilities:
* Expose resources, tools and prompts via MCP primitives
* Operate independently with focused responsibilities
* Request sampling through client interfaces
* Must respect security constraints
* Can be local processes or remote services
## Design Principles
MCP is built on several key design principles that inform its architecture and
implementation:
1. **Servers should be extremely easy to build**
* Host applications handle complex orchestration responsibilities
* Servers focus on specific, well-defined capabilities
* Simple interfaces minimize implementation overhead
* Clear separation enables maintainable code
2. **Servers should be highly composable**
* Each server provides focused functionality in isolation
* Multiple servers can be combined seamlessly
* Shared protocol enables interoperability
* Modular design supports extensibility
3. **Servers should not be able to read the whole conversation, nor "see into" other
servers**
* Servers receive only necessary contextual information
* Full conversation history stays with the host
* Each server connection maintains isolation
* Cross-server interactions are controlled by the host
* Host process enforces security boundaries
4. **Features can be added to servers and clients progressively**
* Core protocol provides minimal required functionality
* Additional capabilities can be negotiated as needed
* Servers and clients evolve independently
* Protocol designed for future extensibility
* Backwards compatibility is maintained
## Capability Negotiation
The Model Context Protocol uses a capability-based negotiation system where clients and
servers explicitly declare their supported features during initialization. Capabilities
determine which protocol features and primitives are available during a session.
* Servers declare capabilities like resource subscriptions, tool support, and prompt
templates
* Clients declare capabilities like sampling support and notification handling
* Both parties must respect declared capabilities throughout the session
* Additional capabilities can be negotiated through extensions to the protocol
```mermaid theme={null}
sequenceDiagram
participant Host
participant Client
participant Server
Host->>+Client: Initialize client
Client->>+Server: Initialize session with capabilities
Server-->>Client: Respond with supported capabilities
Note over Host,Server: Active Session with Negotiated Features
loop Client Requests
Host->>Client: User- or model-initiated action
Client->>Server: Request (tools/resources)
Server-->>Client: Response
Client-->>Host: Update UI or respond to model
end
loop Server Requests
Server->>Client: Request (sampling)
Client->>Host: Forward to AI
Host-->>Client: AI response
Client-->>Server: Response
end
loop Notifications
Server--)Client: Resource updates
Client--)Server: Status changes
end
Host->>Client: Terminate
Client->>-Server: End session
deactivate Server
```
Each capability unlocks specific protocol features for use during the session. For
example:
* Implemented [server features](/specification/2025-11-25/server) must be advertised in the
server's capabilities
* Emitting resource subscription notifications requires the server to declare
subscription support
* Tool invocation requires the server to declare tool capabilities
* [Sampling](/specification/2025-11-25/client/sampling) requires the client to declare support in its
capabilities
This capability negotiation ensures clients and servers have a clear understanding of
supported functionality while maintaining protocol extensibility.
specification/2025-11-25/basic/authorization New page · 707 lines, new page
# Authorization ## Introduction ### Purpose and Scope ### Protocol Requirements ### Standards Compliance ## Roles ## Overview ## Authorization Server Discovery ### Authorization Server Location ### Protected Resource Metadata Discovery Requirements ### Authorization Server Metadata Discovery ### Authorization Server Discovery Sequence Diagram ## Client Registration Approaches ### Client ID Metadata Documents #### Implementation Requirements #### Example Metadata Document #### Client ID Metadata Documents Flow #### Discovery ### Preregistration ### Dynamic Client Registration ## Scope Selection Strategy ## Authorization Flow Steps ## Resource Parameter Implementation ### Canonical Server URI ## Access Token Usage ### Token Requirements ### Token Handling ## Error Handling ### Scope Challenge Handling #### Runtime Insufficient Scope Errors #### Step-Up Authorization Flow ## Security Considerations ### Token Audience Binding and Validation ### Token Theft ### Communication Security ### Authorization Code Protection ### Open Redirection ### Client ID Metadata Document Security #### Authorization Server Abuse Protection #### Localhost Redirect URI Risks #### Trust Policies ### Confused Deputy Problem ### Access Token Privilege Restriction ## MCP Authorization Extensions
A whole new page. There's nothing to diff it against, so here is what it says.
# Authorization
<div id="enable-section-numbers" />
## Introduction
### Purpose and Scope
The Model Context Protocol provides authorization capabilities at the transport level,
enabling MCP clients to make requests to restricted MCP servers on behalf of resource
owners. This specification defines the authorization flow for HTTP-based transports.
### Protocol Requirements
Authorization is **OPTIONAL** for MCP implementations. When supported:
* Implementations using an HTTP-based transport **SHOULD** conform to this specification.
* Implementations using an STDIO transport **SHOULD NOT** follow this specification, and
instead retrieve credentials from the environment.
* Implementations using alternative transports **MUST** follow established security best
practices for their protocol.
### Standards Compliance
This authorization mechanism is based on established specifications listed below, but
implements a selected subset of their features to ensure security and interoperability
while maintaining simplicity:
* OAuth 2.1 IETF DRAFT ([draft-ietf-oauth-v2-1-13](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-13))
* OAuth 2.0 Authorization Server Metadata
([RFC8414](https://datatracker.ietf.org/doc/html/rfc8414))
* OAuth 2.0 Dynamic Client Registration Protocol
([RFC7591](https://datatracker.ietf.org/doc/html/rfc7591))
* OAuth 2.0 Protected Resource Metadata ([RFC9728](https://datatracker.ietf.org/doc/html/rfc9728))
* OAuth Client ID Metadata Documents ([draft-ietf-oauth-client-id-metadata-document-00](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-client-id-metadata-document-00))
## Roles
A protected *MCP server* acts as an [OAuth 2.1 resource server](https://www.ietf.org/archive/id/draft-ietf-oauth-v2-1-13.html#name-roles),
capable of accepting and responding to protected resource requests using access tokens.
An *MCP client* acts as an [OAuth 2.1 client](https://www.ietf.org/archive/id/draft-ietf-oauth-v2-1-13.html#name-roles),
making protected resource requests on behalf of a resource owner.
The *authorization server* is responsible for interacting with the user (if necessary) and issuing access tokens for use at the MCP server.
The implementation details of the authorization server are beyond the scope of this specification. It may be hosted with the
resource server or a separate entity. The [Authorization Server Discovery section](#authorization-server-discovery)
specifies how an MCP server indicates the location of its corresponding authorization server to a client.
## Overview
1. Authorization servers **MUST** implement OAuth 2.1 with appropriate security
measures for both confidential and public clients.
2. Authorization servers and MCP clients **SHOULD** support OAuth Client ID Metadata Documents
([draft-ietf-oauth-client-id-metadata-document-00](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-client-id-metadata-document-00)).
3. Authorization servers and MCP clients **MAY** support the OAuth 2.0 Dynamic Client Registration
Protocol ([RFC7591](https://datatracker.ietf.org/doc/html/rfc7591)).
4. MCP servers **MUST** implement OAuth 2.0 Protected Resource Metadata ([RFC9728](https://datatracker.ietf.org/doc/html/rfc9728)).
MCP clients **MUST** use OAuth 2.0 Protected Resource Metadata for authorization server discovery.
5. MCP authorization servers **MUST** provide at least one of the following discovery mechanisms:
* OAuth 2.0 Authorization Server Metadata ([RFC8414](https://datatracker.ietf.org/doc/html/rfc8414))
* [OpenID Connect Discovery 1.0](https://openid.net/specs/openid-connect-discovery-1_0.html)
MCP clients **MUST** support both discovery mechanisms to obtain the information required to interact with the authorization server.
## Authorization Server Discovery
This section describes the mechanisms by which MCP servers advertise their associated
authorization servers to MCP clients, as well as the discovery process through which MCP
clients can determine authorization server endpoints and supported capabilities.
### Authorization Server Location
MCP servers **MUST** implement the OAuth 2.0 Protected Resource Metadata ([RFC9728](https://datatracker.ietf.org/doc/html/rfc9728))
specification to indicate the locations of authorization servers. The Protected Resource Metadata document returned by the MCP server **MUST** include
the `authorization_servers` field containing at least one authorization server.
The specific use of `authorization_servers` is beyond the scope of this specification; implementers should consult
OAuth 2.0 Protected Resource Metadata ([RFC9728](https://datatracker.ietf.org/doc/html/rfc9728)) for
guidance on implementation details.
Implementors should note that Protected Resource Metadata documents can define multiple authorization servers. The responsibility for selecting which authorization server to use lies with the MCP client, following the guidelines specified in
[RFC9728 Section 7.6 "Authorization Servers"](https://datatracker.ietf.org/doc/html/rfc9728#name-authorization-servers).
### Protected Resource Metadata Discovery Requirements
MCP servers **MUST** implement one of the following discovery mechanisms to provide authorization server location information to MCP clients:
1. **WWW-Authenticate Header**: Include the resource metadata URL in the `WWW-Authenticate` HTTP header under `resource_metadata` when returning `401 Unauthorized` responses, as described in [RFC9728 Section 5.1](https://datatracker.ietf.org/doc/html/rfc9728#name-www-authenticate-response).
2. **Well-Known URI**: Serve metadata at a well-known URI as specified in [RFC9728](https://datatracker.ietf.org/doc/html/rfc9728). This can be either:
* At the path of the server's MCP endpoint: `https://example.com/public/mcp` could host metadata at `https://example.com/.well-known/oauth-protected-resource/public/mcp`
* At the root: `https://example.com/.well-known/oauth-protected-resource`
MCP clients **MUST** support both discovery mechanisms and use the resource metadata URL from the parsed `WWW-Authenticate` headers when present; otherwise, they **MUST** fall back to constructing and requesting the well-known URIs in the order listed above.
MCP servers **SHOULD** include a `scope` parameter in the `WWW-Authenticate` header as defined in
[RFC 6750 Section 3](https://datatracker.ietf.org/doc/html/rfc6750#section-3)
to indicate the scopes required for accessing the resource. This provides clients with immediate
guidance on the appropriate scopes to request during authorization,
following the principle of least privilege and preventing clients from requesting excessive permissions.
The scopes included in the `WWW-Authenticate` challenge **MAY** match `scopes_supported`, be a subset
or superset of it, or an alternative collection that is neither a strict subset nor
superset. Clients **MUST NOT** assume any particular set relationship between the challenged
scope set and `scopes_supported`. Clients **MUST** treat the scopes provided in the
challenge as authoritative for satisfying the current request. Servers **SHOULD** strive for
consistency in how they construct scope sets but they are not required to surface every dynamically
issued scope through `scopes_supported`.
Example 401 response with scope guidance:
```http theme={null}
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer resource_metadata="https://mcp.example.com/.well-known/oauth-protected-resource",
scope="files:read"
```
MCP clients **MUST** be able to parse `WWW-Authenticate` headers and respond appropriately to `HTTP 401 Unauthorized` responses from the MCP server.
If the `scope` parameter is absent, clients **SHOULD** apply the fallback behavior defined in the [Scope Selection Strategy](#scope-selection-strategy) section.
### Authorization Server Metadata Discovery
To handle different issuer URL formats and ensure interoperability with both OAuth 2.0 Authorization Server Metadata and OpenID Connect Discovery 1.0 specifications, MCP clients **MUST** attempt multiple well-known endpoints when discovering authorization server metadata.
The discovery approach is based on [RFC8414 Section 3.1 "Authorization Server Metadata Request"](https://datatracker.ietf.org/doc/html/rfc8414#section-3.1) for OAuth 2.0 Authorization Server Metadata discovery and [RFC8414 Section 5 "Compatibility Notes"](https://datatracker.ietf.org/doc/html/rfc8414#section-5) for OpenID Connect Discovery 1.0 interoperability.
For issuer URLs with path components (e.g., `https://auth.example.com/tenant1`), clients **MUST** try endpoints in the following priority order:
1. OAuth 2.0 Authorization Server Metadata with path insertion: `https://auth.example.com/.well-known/oauth-authorization-server/tenant1`
2. OpenID Connect Discovery 1.0 with path insertion: `https://auth.example.com/.well-known/openid-configuration/tenant1`
3. OpenID Connect Discovery 1.0 path appending: `https://auth.example.com/tenant1/.well-known/openid-configuration`
For issuer URLs without path components (e.g., `https://auth.example.com`), clients **MUST** try:
1. OAuth 2.0 Authorization Server Metadata: `https://auth.example.com/.well-known/oauth-authorization-server`
2. OpenID Connect Discovery 1.0: `https://auth.example.com/.well-known/openid-configuration`
### Authorization Server Discovery Sequence Diagram
The following diagram outlines an example flow:
```mermaid theme={null}
sequenceDiagram
participant C as Client
participant M as MCP Server (Resource Server)
participant A as Authorization Server
Note over C: Attempt unauthenticated MCP request
C->>M: MCP request without token
M-->>C: HTTP 401 Unauthorized (may include WWW-Authenticate header)
alt Header includes resource_metadata
Note over C: Extract resource_metadata URL from header
C->>M: GET resource_metadata URI
M-->>C: Resource metadata with authorization server URL
else No resource_metadata in header
Note over C: Fallback to well-known URI probing
Note over M: _Not applicable if the MCP server is at the root_
C->>M: GET /.well-known/oauth-protected-resource/mcp
alt Sub-path metadata found
M-->>C: Resource metadata with authorization server URL
else Sub-path not found
C->>M: GET /.well-known/oauth-protected-resource
alt Root metadata found
M-->>C: Resource metadata with authorization server URL
else Root metadata not found
Note over C: Abort or use pre-configured values
end
end
end
Note over C: Validate RS metadata,<br />build AS metadata URL
C->>A: GET Authorization server metadata endpoint
Note over C,A: Try OAuth 2.0 and OpenID Connect<br/>discovery endpoints in priority order
A-->>C: Authorization server metadata
Note over C,A: OAuth 2.1 authorization flow happens here
C->>A: Token request
A-->>C: Access token
C->>M: MCP request with access token
M-->>C: MCP response
Note over C,M: MCP communication continues with valid token
```
## Client Registration Approaches
MCP supports three client registration mechanisms. Choose based on your scenario:
* **Client ID Metadata Documents**: When client and server have no prior relationship (most common)
* **Pre-registration**: When client and server have an existing relationship
* **Dynamic Client Registration**: For backwards compatibility or specific requirements
Clients supporting all options **SHOULD** follow the following priority order:
1. Use pre-registered client information for the server if the client has it available
2. Use Client ID Metadata Documents if the Authorization Server indicates if the server supports it (via `client_id_metadata_document_supported` in OAuth Authorization Server Metadata)
3. Use Dynamic Client Registration as a fallback if the Authorization Server supports it (via `registration_endpoint` in OAuth Authorization Server Metadata)
4. Prompt the user to enter the client information if no other option is available
### Client ID Metadata Documents
MCP clients and authorization servers **SHOULD** support OAuth Client ID Metadata Documents as specified in
[OAuth Client ID Metadata Document](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-client-id-metadata-document-00).
This approach enables clients to use HTTPS URLs as client identifiers, where the URL points to a JSON document
containing client metadata. This addresses the common MCP scenario where servers and clients have
no pre-existing relationship.
#### Implementation Requirements
MCP implementations supporting Client ID Metadata Documents **MUST** follow the requirements specified in
[OAuth Client ID Metadata Document](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-client-id-metadata-document-00).
Key requirements include:
**For MCP Clients:**
* Clients **MUST** host their metadata document at an HTTPS URL following RFC requirements
* The `client_id` URL **MUST** use the "https" scheme and contain a path component, e.g. `https://example.com/client.json`
* The metadata document **MUST** include at least the following properties: `client_id`, `client_name`, `redirect_uris`
* Clients **MUST** ensure the `client_id` value in the metadata matches the document URL exactly
* Clients **MAY** use `private_key_jwt` for client authentication (e.g., for requests to the token endpoint) with appropriate JWKS configuration as described in [Section 6.2 of Client ID Metadata Document](https://www.ietf.org/archive/id/draft-ietf-oauth-client-id-metadata-document-00.html#section-6.2)
**For Authorization Servers:**
* **SHOULD** fetch metadata documents when encountering URL-formatted client\_ids
* **MUST** validate that the fetched document's `client_id` matches the URL exactly
* **SHOULD** cache metadata respecting HTTP cache headers
* **MUST** validate redirect URIs presented in an authorization request against those in the metadata document
* **MUST** validate the document structure is valid JSON and contains required fields
* **SHOULD** follow the security considerations in [Section 6 of Client ID Metadata Document](https://www.ietf.org/archive/id/draft-ietf-oauth-client-id-metadata-document-00.html#section-6)
#### Example Metadata Document
```json theme={null}
{
"client_id": "https://app.example.com/oauth/client-metadata.json",
"client_name": "Example MCP Client",
"client_uri": "https://app.example.com",
"logo_uri": "https://app.example.com/logo.png",
"redirect_uris": [
"http://127.0.0.1:3000/callback",
"http://localhost:3000/callback"
],
"grant_types": ["authorization_code"],
"response_types": ["code"],
"token_endpoint_auth_method": "none"
}
```
#### Client ID Metadata Documents Flow
The following diagram illustrates the complete flow when using Client ID Metadata Documents:
```mermaid theme={null}
sequenceDiagram
participant User
participant Client as MCP Client
participant Server as Authorization Server
participant Metadata as Metadata Endpoint<br/>(Client's HTTPS URL)
participant Resource as MCP Server
Note over Client,Metadata: Client hosts metadata at<br/>https://app.example.com/oauth/metadata.json
User->>Client: Initiates connection to MCP Server
Client->>Server: Authorization Request<br/>client_id=https://app.example.com/oauth/metadata.json<br/>redirect_uri=http://localhost:3000/callback
Server->>User: Authentication prompt
User->>Server: Provides credentials
Note over Server: Authenticates user
Note over Server: Detects URL-formatted client_id
Server->>Metadata: GET https://app.example.com/oauth/metadata.json
Metadata-->>Server: JSON Metadata Document<br/>{client_id, client_name, redirect_uris, ...}
Note over Server: Validates:<br/>1. client_id matches URL<br/>2. redirect_uri in allowed list<br/>3. Document structure valid<br/>4. (Optional) Domain allowed via trust policy
alt Validation Success
Server->>User: Display consent page with client_name
User->>Server: Approves access
Server->>Client: Authorization code via redirect_uri
Client->>Server: Exchange code for token<br/>client_id=https://app.example.com/oauth/metadata.json
Server-->>Client: Access token
Client->>Resource: MCP requests with access token
Resource-->>Client: MCP responses
else Validation Failure
Server->>User: Error response<br/>error=invalid_client or invalid_request
end
Note over Server: Cache metadata for future requests<br/>(respecting HTTP cache headers)
```
Cut at 300 lines. The page has the rest.
specification/2025-11-25/basic/index New page · 265 lines, new page
# Overview ## Messages ### Requests ### Responses #### Result Responses #### Error Responses ### Notifications ## Auth ## Schema ## JSON Schema Usage ### Schema Dialect ### Example Usage #### Default dialect (2020-12): #### Explicit dialect (draft-07): ### Implementation Requirements ### Schema Validation ## General fields ### `_meta` ### `icons`
A whole new page. There's nothing to diff it against, so here is what it says.
# Overview
<div id="enable-section-numbers" />
The Model Context Protocol consists of several key components that work together:
* **Base Protocol**: Core JSON-RPC message types
* **Lifecycle Management**: Connection initialization, capability negotiation, and
session control
* **Authorization**: Authentication and authorization framework for HTTP-based transports
* **Server Features**: Resources, prompts, and tools exposed by servers
* **Client Features**: Sampling and root directory lists provided by clients
* **Utilities**: Cross-cutting concerns like logging and argument completion
All implementations **MUST** support the base protocol and lifecycle management
components. Other components **MAY** be implemented based on the specific needs of the
application.
These protocol layers establish clear separation of concerns while enabling rich
interactions between clients and servers. The modular design allows implementations to
support exactly the features they need.
## Messages
All messages between MCP clients and servers **MUST** follow the
[JSON-RPC 2.0](https://www.jsonrpc.org/specification) specification. The protocol defines
these types of messages:
### Requests
[Requests](/specification/2025-11-25/schema#jsonrpcrequest) are sent from the client to the server or vice versa, to initiate an operation.
```typescript theme={null}
{
jsonrpc: "2.0";
id: string | number;
method: string;
params?: {
[key: string]: unknown;
};
}
```
* Requests **MUST** include a string or integer ID.
* Unlike base JSON-RPC, the ID **MUST NOT** be `null`.
* The request ID **MUST NOT** have been previously used by the requestor within the same
session.
### Responses
Responses are sent in reply to requests, containing either the result or error of the operation.
#### Result Responses
[Result responses](/specification/2025-11-25/schema#jsonrpcresultresponse) are sent when the operation completes successfully.
```typescript theme={null}
{
jsonrpc: "2.0";
id: string | number;
result: {
[key: string]: unknown;
}
}
```
* Result responses **MUST** include the same ID as the request they correspond to.
* Result responses **MUST** include a `result` field.
* The `result` **MAY** follow any JSON object structure.
#### Error Responses
[Error responses](/specification/2025-11-25/schema#jsonrpcerrorresponse) are sent when the operation fails or encounters an error.
```typescript theme={null}
{
jsonrpc: "2.0";
id?: string | number;
error: {
code: number;
message: string;
data?: unknown;
}
}
```
* Error responses **MUST** include the same ID as the request they correspond to (except in error cases where the ID could not be read due a malformed request).
* Error responses **MUST** include an `error` field with a `code` and `message`.
* Error codes **MUST** be integers.
### Notifications
[Notifications](/specification/2025-11-25/schema#jsonrpcnotification) are sent from the client to the server or vice versa, as a one-way message.
The receiver **MUST NOT** send a response.
```typescript theme={null}
{
jsonrpc: "2.0";
method: string;
params?: {
[key: string]: unknown;
};
}
```
* Notifications **MUST NOT** include an ID.
## Auth
MCP provides an [Authorization](/specification/2025-11-25/basic/authorization) framework for use with HTTP.
Implementations using an HTTP-based transport **SHOULD** conform to this specification,
whereas implementations using STDIO transport **SHOULD NOT** follow this specification,
and instead retrieve credentials from the environment.
Additionally, clients and servers **MAY** negotiate their own custom authentication and
authorization strategies.
For further discussions and contributions to the evolution of MCP's auth mechanisms, join
us in
[GitHub Discussions](https://github.com/modelcontextprotocol/specification/discussions)
to help shape the future of the protocol!
## Schema
The full specification of the protocol is defined as a
[TypeScript schema](https://github.com/modelcontextprotocol/specification/blob/main/schema/2025-11-25/schema.ts).
This is the source of truth for all protocol messages and structures.
There is also a
[JSON Schema](https://github.com/modelcontextprotocol/specification/blob/main/schema/2025-11-25/schema.json),
which is automatically generated from the TypeScript source of truth, for use with
various automated tooling.
## JSON Schema Usage
The Model Context Protocol uses JSON Schema for validation throughout the protocol. This section clarifies how JSON Schema should be used within MCP messages.
### Schema Dialect
MCP supports JSON Schema with the following rules:
1. **Default dialect**: When a schema does not include a `$schema` field, it defaults to [JSON Schema 2020-12](https://json-schema.org/draft/2020-12/schema)
2. **Explicit dialect**: Schemas MAY include a `$schema` field to specify a different dialect
3. **Supported dialects**: Implementations MUST support at least 2020-12 and SHOULD document which additional dialects they support
4. **Recommendation**: Implementors are RECOMMENDED to use JSON Schema 2020-12.
### Example Usage
#### Default dialect (2020-12):
```json theme={null}
{
"type": "object",
"properties": {
"name": { "type": "string" },
"age": { "type": "integer", "minimum": 0 }
},
"required": ["name"]
}
```
#### Explicit dialect (draft-07):
```json theme={null}
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"name": { "type": "string" },
"age": { "type": "integer", "minimum": 0 }
},
"required": ["name"]
}
```
### Implementation Requirements
* Clients and servers **MUST** support JSON Schema 2020-12 for schemas without an explicit `$schema` field
* Clients and servers **MUST** validate schemas according to their declared or default dialect. They **MUST** handle unsupported dialects gracefully by returning an appropriate error indicating the dialect is not supported.
* Clients and servers **SHOULD** document which schema dialects they support
### Schema Validation
* Schemas **MUST** be valid according to their declared or default dialect
## General fields
### `_meta`
The `_meta` property/parameter is reserved by MCP to allow clients and servers
to attach additional metadata to their interactions.
Certain key names are reserved by MCP for protocol-level metadata, as specified below;
implementations MUST NOT make assumptions about values at these keys.
Additionally, definitions in the [schema](https://github.com/modelcontextprotocol/specification/blob/main/schema/2025-11-25/schema.ts)
may reserve particular names for purpose-specific metadata, as declared in those definitions.
**Key name format:** valid `_meta` key names have two segments: an optional **prefix**, and a **name**.
**Prefix:**
* If specified, MUST be a series of labels separated by dots (`.`), followed by a slash (`/`).
* Labels MUST start with a letter and end with a letter or digit; interior characters can be letters, digits, or hyphens (`-`).
* Implementations SHOULD use reverse DNS notation (e.g., `com.example/` rather than `example.com/`).
* Any prefix where the second label is `modelcontextprotocol` or `mcp` is **reserved** for MCP use.
* For example: `io.modelcontextprotocol/`, `dev.mcp/`, `org.modelcontextprotocol.api/`, and `com.mcp.tools/` are all reserved.
* However, `com.example.mcp/` is NOT reserved, as the second label is `example`.
**Name:**
* Unless empty, MUST begin and end with an alphanumeric character (`[a-z0-9A-Z]`).
* MAY contain hyphens (`-`), underscores (`_`), dots (`.`), and alphanumerics in between.
### `icons`
The `icons` property provides a standardized way for servers to expose visual identifiers for their resources, tools, prompts, and implementations. Icons enhance user interfaces by providing visual context and improving the discoverability of available functionality.
Icons are represented as an array of `Icon` objects, where each icon includes:
* `src`: A URI pointing to the icon resource (required). This can be:
* An HTTP/HTTPS URL pointing to an image file
* A data URI with base64-encoded image data
* `mimeType`: Optional MIME type if the server's type is missing or generic
* `sizes`: Optional array of size specifications (e.g., `["48x48"]`, `["any"]` for scalable formats like SVG, or `["48x48", "96x96"]` for multiple sizes)
* `theme`: Optional theme preference (`light` or `dark`) for the icon background
**Required MIME type support:**
Clients that support rendering icons **MUST** support at least the following MIME types:
* `image/png` - PNG images (safe, universal compatibility)
* `image/jpeg` (and `image/jpg`) - JPEG images (safe, universal compatibility)
Clients that support rendering icons **SHOULD** also support:
* `image/svg+xml` - SVG images (scalable but requires security precautions as noted below)
* `image/webp` - WebP images (modern, efficient format)
**Security considerations:**
Consumers of icon metadata **MUST** take appropriate security precautions when handling icons to prevent compromise:
* Treat icon metadata and icon bytes as untrusted inputs and defend against network, privacy, and parsing risks.
* Ensure that the icon URI is either a HTTPS or `data:` URI. Clients **MUST** reject icon URIs that use unsafe schemes and redirects, such as `javascript:`, `file:`, `ftp:`, `ws:`, or local app URI schemes.
* Disallow scheme changes and redirects to hosts on different origins.
* Be resilient against resource exhaustion attacks stemming from oversized images, large dimensions, or excessive frames (e.g., in GIFs).
* Consumers **MAY** set limits for image and content size.
* Fetch icons without credentials. Do not send cookies, `Authorization` headers, or client credentials.
* Verify that icon URIs are from the same origin as the server. This minimizes the risk of exposing data or tracking information to third-parties.
* Exercise caution when fetching and rendering icons as the payload **MAY** contain executable content (e.g., SVG with [embedded JavaScript](https://www.w3.org/TR/SVG11/script.html) or [extended capabilities](https://www.w3.org/TR/SVG11/extend.html)).
* Consumers **MAY** choose to disallow specific file types or otherwise sanitize icon files before rendering.
* Validate MIME types and file contents before rendering. Treat the MIME type information as advisory. Detect content type via magic bytes; reject on mismatch or unknown types.
* Maintain a strict allowlist of image types.
**Usage:**
Icons can be attached to:
* `Implementation`: Visual identifier for the MCP server/client implementation
* `Tool`: Visual representation of the tool's functionality
* `Prompt`: Icon to display alongside prompt templates
* `Resource`: Visual indicator for different resource types
Multiple icons can be provided to support different display contexts and resolutions. Clients should select the most appropriate icon based on their UI requirements.
specification/2025-11-25/basic/lifecycle New page · 283 lines, new page
# Lifecycle ## Lifecycle Phases ### Initialization #### Version Negotiation #### Capability Negotiation ### Operation ### Shutdown #### stdio #### HTTP ## Timeouts ## Error Handling
A whole new page. There's nothing to diff it against, so here is what it says.
# Lifecycle
<div id="enable-section-numbers" />
The Model Context Protocol (MCP) defines a rigorous lifecycle for client-server
connections that ensures proper capability negotiation and state management.
1. **Initialization**: Capability negotiation and protocol version agreement
2. **Operation**: Normal protocol communication
3. **Shutdown**: Graceful termination of the connection
```mermaid theme={null}
sequenceDiagram
participant Client
participant Server
Note over Client,Server: Initialization Phase
activate Client
Client->>+Server: initialize request
Server-->>Client: initialize response
Client--)Server: initialized notification
Note over Client,Server: Operation Phase
rect rgb(200, 220, 250)
note over Client,Server: Normal protocol operations
end
Note over Client,Server: Shutdown
Client--)-Server: Disconnect
deactivate Server
Note over Client,Server: Connection closed
```
## Lifecycle Phases
### Initialization
The initialization phase **MUST** be the first interaction between client and server.
During this phase, the client and server:
* Establish protocol version compatibility
* Exchange and negotiate capabilities
* Share implementation details
The client **MUST** initiate this phase by sending an `initialize` request containing:
* Protocol version supported
* Client capabilities
* Client implementation information
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2025-11-25",
"capabilities": {
"roots": {
"listChanged": true
},
"sampling": {},
"elicitation": {
"form": {},
"url": {}
},
"tasks": {
"requests": {
"elicitation": {
"create": {}
},
"sampling": {
"createMessage": {}
}
}
}
},
"clientInfo": {
"name": "ExampleClient",
"title": "Example Client Display Name",
"version": "1.0.0",
"description": "An example MCP client application",
"icons": [
{
"src": "https://example.com/icon.png",
"mimeType": "image/png",
"sizes": ["48x48"]
}
],
"websiteUrl": "https://example.com"
}
}
}
```
The server **MUST** respond with its own capabilities and information:
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"protocolVersion": "2025-11-25",
"capabilities": {
"logging": {},
"prompts": {
"listChanged": true
},
"resources": {
"subscribe": true,
"listChanged": true
},
"tools": {
"listChanged": true
},
"tasks": {
"list": {},
"cancel": {},
"requests": {
"tools": {
"call": {}
}
}
}
},
"serverInfo": {
"name": "ExampleServer",
"title": "Example Server Display Name",
"version": "1.0.0",
"description": "An example MCP server providing tools and resources",
"icons": [
{
"src": "https://example.com/server-icon.svg",
"mimeType": "image/svg+xml",
"sizes": ["any"]
}
],
"websiteUrl": "https://example.com/server"
},
"instructions": "Optional instructions for the client"
}
}
```
After successful initialization, the client **MUST** send an `initialized` notification
to indicate it is ready to begin normal operations:
```json theme={null}
{
"jsonrpc": "2.0",
"method": "notifications/initialized"
}
```
* The client **SHOULD NOT** send requests other than
[pings](/specification/2025-11-25/basic/utilities/ping) before the server has responded to the
`initialize` request.
* The server **SHOULD NOT** send requests other than
[pings](/specification/2025-11-25/basic/utilities/ping) and
[logging](/specification/2025-11-25/server/utilities/logging) before receiving the `initialized`
notification.
#### Version Negotiation
In the `initialize` request, the client **MUST** send a protocol version it supports.
This **SHOULD** be the *latest* version supported by the client.
If the server supports the requested protocol version, it **MUST** respond with the same
version. Otherwise, the server **MUST** respond with another protocol version it
supports. This **SHOULD** be the *latest* version supported by the server.
If the client does not support the version in the server's response, it **SHOULD**
disconnect.
<Note>
If using HTTP, the client **MUST** include the `MCP-Protocol-Version: <protocol-version>` HTTP header on all subsequent requests to the MCP
server.
For details, see [the Protocol Version Header section in Transports](/specification/2025-11-25/basic/transports#protocol-version-header).
</Note>
#### Capability Negotiation
Client and server capabilities establish which optional protocol features will be
available during the session.
Key capabilities include:
| Category | Capability | Description |
| -------- | -------------- | --------------------------------------------------------------------------------------------- |
| Client | `roots` | Ability to provide filesystem [roots](/specification/2025-11-25/client/roots) |
| Client | `sampling` | Support for LLM [sampling](/specification/2025-11-25/client/sampling) requests |
| Client | `elicitation` | Support for server [elicitation](/specification/2025-11-25/client/elicitation) requests |
| Client | `tasks` | Support for [task-augmented](/specification/2025-11-25/basic/utilities/tasks) client requests |
| Client | `experimental` | Describes support for non-standard experimental features |
| Server | `prompts` | Offers [prompt templates](/specification/2025-11-25/server/prompts) |
| Server | `resources` | Provides readable [resources](/specification/2025-11-25/server/resources) |
| Server | `tools` | Exposes callable [tools](/specification/2025-11-25/server/tools) |
| Server | `logging` | Emits structured [log messages](/specification/2025-11-25/server/utilities/logging) |
| Server | `completions` | Supports argument [autocompletion](/specification/2025-11-25/server/utilities/completion) |
| Server | `tasks` | Support for [task-augmented](/specification/2025-11-25/basic/utilities/tasks) server requests |
| Server | `experimental` | Describes support for non-standard experimental features |
Capability objects can describe sub-capabilities like:
* `listChanged`: Support for list change notifications (for prompts, resources, and
tools)
* `subscribe`: Support for subscribing to individual items' changes (resources only)
### Operation
During the operation phase, the client and server exchange messages according to the
negotiated capabilities.
Both parties **MUST**:
* Respect the negotiated protocol version
* Only use capabilities that were successfully negotiated
### Shutdown
During the shutdown phase, one side (usually the client) cleanly terminates the protocol
connection. No specific shutdown messages are defined—instead, the underlying transport
mechanism should be used to signal connection termination:
#### stdio
For the stdio [transport](/specification/2025-11-25/basic/transports), the client **SHOULD** initiate
shutdown by:
1. First, closing the input stream to the child process (the server)
2. Waiting for the server to exit, or sending `SIGTERM` if the server does not exit
within a reasonable time
3. Sending `SIGKILL` if the server does not exit within a reasonable time after `SIGTERM`
The server **MAY** initiate shutdown by closing its output stream to the client and
exiting.
#### HTTP
For HTTP [transports](/specification/2025-11-25/basic/transports), shutdown is indicated by closing the
associated HTTP connection(s).
## Timeouts
Implementations **SHOULD** establish timeouts for all sent requests, to prevent hung
connections and resource exhaustion. When the request has not received a success or error
response within the timeout period, the sender **SHOULD** issue a [cancellation
notification](/specification/2025-11-25/basic/utilities/cancellation) for that request and stop waiting for
a response.
SDKs and other middleware **SHOULD** allow these timeouts to be configured on a
per-request basis.
Implementations **MAY** choose to reset the timeout clock when receiving a [progress
notification](/specification/2025-11-25/basic/utilities/progress) corresponding to the request, as this
implies that work is actually happening. However, implementations **SHOULD** always
enforce a maximum timeout, regardless of progress notifications, to limit the impact of a
misbehaving client or server.
## Error Handling
Implementations **SHOULD** be prepared to handle these error cases:
* Protocol version mismatch
* Failure to negotiate required capabilities
* Request [timeouts](#timeouts)
Example initialization error:
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32602,
"message": "Unsupported protocol version",
"data": {
"supported": ["2024-11-05"],
"requested": "1.0.0"
}
}
}
```
specification/2025-11-25/basic/transports New page · 315 lines, new page
# Transports ## stdio ## Streamable HTTP #### Security Warning ### Sending Messages to the Server ### Listening for Messages from the Server ### Multiple Connections ### Resumability and Redelivery ### Session Management ### Sequence Diagram ### Protocol Version Header ### Backwards Compatibility ## Custom Transports
A whole new page. There's nothing to diff it against, so here is what it says.
# Transports
<div id="enable-section-numbers" />
MCP uses JSON-RPC to encode messages. JSON-RPC messages **MUST** be UTF-8 encoded.
The protocol currently defines two standard transport mechanisms for client-server
communication:
1. [stdio](#stdio), communication over standard in and standard out
2. [Streamable HTTP](#streamable-http)
Clients **SHOULD** support stdio whenever possible.
It is also possible for clients and servers to implement
[custom transports](#custom-transports) in a pluggable fashion.
## stdio
In the **stdio** transport:
* The client launches the MCP server as a subprocess.
* The server reads JSON-RPC messages from its standard input (`stdin`) and sends messages
to its standard output (`stdout`).
* Messages are individual JSON-RPC requests, notifications, or responses.
* Messages are delimited by newlines, and **MUST NOT** contain embedded newlines.
* The server **MAY** write UTF-8 strings to its standard error (`stderr`) for any
logging purposes including informational, debug, and error messages.
* The client **MAY** capture, forward, or ignore the server's `stderr` output
and **SHOULD NOT** assume `stderr` output indicates error conditions.
* The server **MUST NOT** write anything to its `stdout` that is not a valid MCP message.
* The client **MUST NOT** write anything to the server's `stdin` that is not a valid MCP
message.
```mermaid theme={null}
sequenceDiagram
participant Client
participant Server Process
Client->>+Server Process: Launch subprocess
loop Message Exchange
Client->>Server Process: Write to stdin
Server Process->>Client: Write to stdout
Server Process--)Client: Optional logs on stderr
end
Client->>Server Process: Close stdin, terminate subprocess
deactivate Server Process
```
## Streamable HTTP
<Info>
This replaces the [HTTP+SSE
transport](/specification/2024-11-05/basic/transports#http-with-sse) from
protocol version 2024-11-05. See the [backwards compatibility](#backwards-compatibility)
guide below.
</Info>
In the **Streamable HTTP** transport, the server operates as an independent process that
can handle multiple client connections. This transport uses HTTP POST and GET requests.
Server can optionally make use of
[Server-Sent Events](https://en.wikipedia.org/wiki/Server-sent_events) (SSE) to stream
multiple server messages. This permits basic MCP servers, as well as more feature-rich
servers supporting streaming and server-to-client notifications and requests.
The server **MUST** provide a single HTTP endpoint path (hereafter referred to as the
**MCP endpoint**) that supports both POST and GET methods. For example, this could be a
URL like `https://example.com/mcp`.
#### Security Warning
When implementing Streamable HTTP transport:
1. Servers **MUST** validate the `Origin` header on all incoming connections to prevent DNS rebinding attacks
* If the `Origin` header is present and invalid, servers **MUST** respond with HTTP 403 Forbidden. The HTTP response
body **MAY** comprise a JSON-RPC *error response* that has no `id`
2. When running locally, servers **SHOULD** bind only to localhost (127.0.0.1) rather than all network interfaces (0.0.0.0)
3. Servers **SHOULD** implement proper authentication for all connections
Without these protections, attackers could use DNS rebinding to interact with local MCP servers from remote websites.
### Sending Messages to the Server
Every JSON-RPC message sent from the client **MUST** be a new HTTP POST request to the
MCP endpoint.
1. The client **MUST** use HTTP POST to send JSON-RPC messages to the MCP endpoint.
2. The client **MUST** include an `Accept` header, listing both `application/json` and
`text/event-stream` as supported content types.
3. The body of the POST request **MUST** be a single JSON-RPC *request*, *notification*, or *response*.
4. If the input is a JSON-RPC *response* or *notification*:
* If the server accepts the input, the server **MUST** return HTTP status code 202
Accepted with no body.
* If the server cannot accept the input, it **MUST** return an HTTP error status code
(e.g., 400 Bad Request). The HTTP response body **MAY** comprise a JSON-RPC *error
response* that has no `id`.
5. If the input is a JSON-RPC *request*, the server **MUST** either
return `Content-Type: text/event-stream`, to initiate an SSE stream, or
`Content-Type: application/json`, to return one JSON object. The client **MUST**
support both these cases.
6. If the server initiates an SSE stream:
* The server **SHOULD** immediately send an SSE event consisting of an event
ID and an empty `data` field in order to prime the client to reconnect
(using that event ID as `Last-Event-ID`).
* After the server has sent an SSE event with an event ID to the client, the
server **MAY** close the *connection* (without terminating the *SSE stream*)
at any time in order to avoid holding a long-lived connection. The client
**SHOULD** then "poll" the SSE stream by attempting to reconnect.
* If the server does close the *connection* prior to terminating the *SSE stream*,
it **SHOULD** send an SSE event with a standard [`retry`](https://html.spec.whatwg.org/multipage/server-sent-events.html#:~:text=field%20name%20is%20%22retry%22) field before
closing the connection. The client **MUST** respect the `retry` field,
waiting the given number of milliseconds before attempting to reconnect.
* The SSE stream **SHOULD** eventually include a JSON-RPC *response* for the
JSON-RPC *request* sent in the POST body.
* The server **MAY** send JSON-RPC *requests* and *notifications* before sending the
JSON-RPC *response*. These messages **SHOULD** relate to the originating client
*request*.
* The server **MAY** terminate the SSE stream if the [session](#session-management)
expires.
* After the JSON-RPC *response* has been sent, the server **SHOULD** terminate the
SSE stream.
* Disconnection **MAY** occur at any time (e.g., due to network conditions).
Therefore:
* Disconnection **SHOULD NOT** be interpreted as the client cancelling its request.
* To cancel, the client **SHOULD** explicitly send an MCP `CancelledNotification`.
* To avoid message loss due to disconnection, the server **MAY** make the stream
[resumable](#resumability-and-redelivery).
### Listening for Messages from the Server
1. The client **MAY** issue an HTTP GET to the MCP endpoint. This can be used to open an
SSE stream, allowing the server to communicate to the client, without the client first
sending data via HTTP POST.
2. The client **MUST** include an `Accept` header, listing `text/event-stream` as a
supported content type.
3. The server **MUST** either return `Content-Type: text/event-stream` in response to
this HTTP GET, or else return HTTP 405 Method Not Allowed, indicating that the server
does not offer an SSE stream at this endpoint.
4. If the server initiates an SSE stream:
* The server **MAY** send JSON-RPC *requests* and *notifications* on the stream.
* These messages **SHOULD** be unrelated to any concurrently-running JSON-RPC
*request* from the client.
* The server **MUST NOT** send a JSON-RPC *response* on the stream **unless**
[resuming](#resumability-and-redelivery) a stream associated with a previous client
request.
* The server **MAY** close the SSE stream at any time.
* If the server closes the *connection* without terminating the *stream*, it
**SHOULD** follow the same polling behavior as described for POST requests:
sending a `retry` field and allowing the client to reconnect.
* The client **MAY** close the SSE stream at any time.
### Multiple Connections
1. The client **MAY** remain connected to multiple SSE streams simultaneously.
2. The server **MUST** send each of its JSON-RPC messages on only one of the connected
streams; that is, it **MUST NOT** broadcast the same message across multiple streams.
* The risk of message loss **MAY** be mitigated by making the stream
[resumable](#resumability-and-redelivery).
### Resumability and Redelivery
To support resuming broken connections, and redelivering messages that might otherwise be
lost:
1. Servers **MAY** attach an `id` field to their SSE events, as described in the
[SSE standard](https://html.spec.whatwg.org/multipage/server-sent-events.html#event-stream-interpretation).
* If present, the ID **MUST** be globally unique across all streams within that
[session](#session-management)—or all streams with that specific client, if session
management is not in use.
* Event IDs **SHOULD** encode sufficient information to identify the originating
stream, enabling the server to correlate a `Last-Event-ID` to the correct stream.
2. If the client wishes to resume after a disconnection (whether due to network failure
or server-initiated closure), it **SHOULD** issue an HTTP GET to the MCP endpoint,
and include the
[`Last-Event-ID`](https://html.spec.whatwg.org/multipage/server-sent-events.html#the-last-event-id-header)
header to indicate the last event ID it received.
* The server **MAY** use this header to replay messages that would have been sent
after the last event ID, *on the stream that was disconnected*, and to resume the
stream from that point.
* The server **MUST NOT** replay messages that would have been delivered on a
different stream.
* This mechanism applies regardless of how the original stream was initiated (via
POST or GET). Resumption is always via HTTP GET with `Last-Event-ID`.
In other words, these event IDs should be assigned by servers on a *per-stream* basis, to
act as a cursor within that particular stream.
### Session Management
An MCP "session" consists of logically related interactions between a client and a
server, beginning with the [initialization phase](/specification/2025-11-25/basic/lifecycle). To support
servers which want to establish stateful sessions:
1. A server using the Streamable HTTP transport **MAY** assign a session ID at
initialization time, by including it in an `MCP-Session-Id` header on the HTTP
response containing the `InitializeResult`.
* The session ID **SHOULD** be globally unique and cryptographically secure (e.g., a
securely generated UUID, a JWT, or a cryptographic hash).
* The session ID **MUST** only contain visible ASCII characters (ranging from 0x21 to
0x7E).
* The client **MUST** handle the session ID in a secure manner, see [Session Hijacking mitigations](/specification/2025-11-25/basic/security_best_practices#session-hijacking) for more details.
2. If an `MCP-Session-Id` is returned by the server during initialization, clients using
the Streamable HTTP transport **MUST** include it in the `MCP-Session-Id` header on
all of their subsequent HTTP requests.
* Servers that require a session ID **SHOULD** respond to requests without an
`MCP-Session-Id` header (other than initialization) with HTTP 400 Bad Request.
3. The server **MAY** terminate the session at any time, after which it **MUST** respond
to requests containing that session ID with HTTP 404 Not Found.
4. When a client receives HTTP 404 in response to a request containing an
`MCP-Session-Id`, it **MUST** start a new session by sending a new `InitializeRequest`
without a session ID attached.
5. Clients that no longer need a particular session (e.g., because the user is leaving
the client application) **SHOULD** send an HTTP DELETE to the MCP endpoint with the
`MCP-Session-Id` header, to explicitly terminate the session.
* The server **MAY** respond to this request with HTTP 405 Method Not Allowed,
indicating that the server does not allow clients to terminate sessions.
### Sequence Diagram
```mermaid theme={null}
sequenceDiagram
participant Client
participant Server
note over Client, Server: initialization
Client->>+Server: POST InitializeRequest
Server->>-Client: InitializeResponse<br>MCP-Session-Id: 1868a90c...
Client->>+Server: POST InitializedNotification<br>MCP-Session-Id: 1868a90c...
Server->>-Client: 202 Accepted
note over Client, Server: client requests
Client->>+Server: POST ... request ...<br>MCP-Session-Id: 1868a90c...
alt single HTTP response
Server->>Client: ... response ...
else server opens SSE stream
loop while connection remains open
Server-)Client: ... SSE messages from server ...
end
Server-)Client: SSE event: ... response ...
end
deactivate Server
note over Client, Server: client notifications/responses
Client->>+Server: POST ... notification/response ...<br>MCP-Session-Id: 1868a90c...
Server->>-Client: 202 Accepted
note over Client, Server: server requests
Client->>+Server: GET<br>MCP-Session-Id: 1868a90c...
loop while connection remains open
Server-)Client: ... SSE messages from server ...
end
deactivate Server
```
### Protocol Version Header
If using HTTP, the client **MUST** include the `MCP-Protocol-Version: <protocol-version>` HTTP header on all subsequent requests to the MCP
server, allowing the MCP server to respond based on the MCP protocol version.
For example: `MCP-Protocol-Version: 2025-11-25`
The protocol version sent by the client **SHOULD** be the one [negotiated during
initialization](/specification/2025-11-25/basic/lifecycle#version-negotiation).
For backwards compatibility, if the server does *not* receive an `MCP-Protocol-Version`
header, and has no other way to identify the version - for example, by relying on the
protocol version negotiated during initialization - the server **SHOULD** assume protocol
version `2025-03-26`.
If the server receives a request with an invalid or unsupported
`MCP-Protocol-Version`, it **MUST** respond with `400 Bad Request`.
### Backwards Compatibility
Clients and servers can maintain backwards compatibility with the deprecated [HTTP+SSE
transport](/specification/2024-11-05/basic/transports#http-with-sse) (from
protocol version 2024-11-05) as follows:
**Servers** wanting to support older clients should:
* Continue to host both the SSE and POST endpoints of the old transport, alongside the
new "MCP endpoint" defined for the Streamable HTTP transport.
* It is also possible to combine the old POST endpoint and the new MCP endpoint, but
this may introduce unneeded complexity.
**Clients** wanting to support older servers should:
1. Accept an MCP server URL from the user, which may point to either a server using the
old transport or the new transport.
2. Attempt to POST an `InitializeRequest` to the server URL, with an `Accept` header as
defined above:
* If it succeeds, the client can assume this is a server supporting the new Streamable
HTTP transport.
* If it fails with the following HTTP status codes "400 Bad Request", "404 Not
Found" or "405 Method Not Allowed":
* Issue a GET request to the server URL, expecting that this will open an SSE stream
Cut at 300 lines. The page has the rest.
specification/2025-11-25/basic/utilities/cancellation New page · 82 lines, new page
# Cancellation ## Cancellation Flow ## Behavior Requirements ## Timing Considerations ## Implementation Notes ## Error Handling
A whole new page. There's nothing to diff it against, so here is what it says.
# Cancellation
<div id="enable-section-numbers" />
The Model Context Protocol (MCP) supports optional cancellation of in-progress requests
through notification messages. Either side can send a cancellation notification to
indicate that a previously-issued request should be terminated.
## Cancellation Flow
When a party wants to cancel an in-progress request, it sends a `notifications/cancelled`
notification containing:
* The ID of the request to cancel
* An optional reason string that can be logged or displayed
```json theme={null}
{
"jsonrpc": "2.0",
"method": "notifications/cancelled",
"params": {
"requestId": "123",
"reason": "User requested cancellation"
}
}
```
## Behavior Requirements
1. Cancellation notifications **MUST** only reference requests that:
* Were previously issued in the same direction
* Are believed to still be in-progress
2. The `initialize` request **MUST NOT** be cancelled by clients
3. For [task-augmented requests](./tasks), the `tasks/cancel` request **MUST** be used instead of the `notifications/cancelled` notification. Tasks have their own dedicated cancellation mechanism that returns the final task state.
4. Receivers of cancellation notifications **SHOULD**:
* Stop processing the cancelled request
* Free associated resources
* Not send a response for the cancelled request
5. Receivers **MAY** ignore cancellation notifications if:
* The referenced request is unknown
* Processing has already completed
* The request cannot be cancelled
6. The sender of the cancellation notification **SHOULD** ignore any response to the
request that arrives afterward
## Timing Considerations
Due to network latency, cancellation notifications may arrive after request processing
has completed, and potentially after a response has already been sent.
Both parties **MUST** handle these race conditions gracefully:
```mermaid theme={null}
sequenceDiagram
participant Client
participant Server
Client->>Server: Request (ID: 123)
Note over Server: Processing starts
Client--)Server: notifications/cancelled (ID: 123)
alt
Note over Server: Processing may have<br/>completed before<br/>cancellation arrives
else If not completed
Note over Server: Stop processing
end
```
## Implementation Notes
* Both parties **SHOULD** log cancellation reasons for debugging
* Application UIs **SHOULD** indicate when cancellation is requested
## Error Handling
Invalid cancellation notifications **SHOULD** be ignored:
* Unknown request IDs
* Already completed requests
* Malformed notifications
This maintains the "fire and forget" nature of notifications while allowing for race
conditions in asynchronous communication.
specification/2025-11-25/basic/utilities/ping New page · 64 lines, new page
# Ping ## Overview ## Message Format ## Behavior Requirements ## Usage Patterns ## Implementation Considerations ## Error Handling
A whole new page. There's nothing to diff it against, so here is what it says.
# Ping
<div id="enable-section-numbers" />
The Model Context Protocol includes an optional ping mechanism that allows either party
to verify that their counterpart is still responsive and the connection is alive.
## Overview
The ping functionality is implemented through a simple request/response pattern. Either
the client or server can initiate a ping by sending a `ping` request.
## Message Format
A ping request is a standard JSON-RPC request with no parameters:
```json theme={null}
{
"jsonrpc": "2.0",
"id": "123",
"method": "ping"
}
```
## Behavior Requirements
1. The receiver **MUST** respond promptly with an empty response:
```json theme={null}
{
"jsonrpc": "2.0",
"id": "123",
"result": {}
}
```
2. If no response is received within a reasonable timeout period, the sender **MAY**:
* Consider the connection stale
* Terminate the connection
* Attempt reconnection procedures
## Usage Patterns
```mermaid theme={null}
sequenceDiagram
participant Sender
participant Receiver
Sender->>Receiver: ping request
Receiver->>Sender: empty response
```
## Implementation Considerations
* Implementations **SHOULD** periodically issue pings to detect connection health
* The frequency of pings **SHOULD** be configurable
* Timeouts **SHOULD** be appropriate for the network environment
* Excessive pinging **SHOULD** be avoided to reduce network overhead
## Error Handling
* Timeouts **SHOULD** be treated as connection failures
* Multiple failed pings **MAY** trigger connection reset
* Implementations **SHOULD** log ping failures for diagnostics
specification/2025-11-25/basic/utilities/progress New page · 92 lines, new page
# Progress ## Progress Flow ## Behavior Requirements ## Implementation Notes
A whole new page. There's nothing to diff it against, so here is what it says.
# Progress
<div id="enable-section-numbers" />
The Model Context Protocol (MCP) supports optional progress tracking for long-running
operations through notification messages. Either side can send progress notifications to
provide updates about operation status.
## Progress Flow
When a party wants to *receive* progress updates for a request, it includes a
`progressToken` in the request metadata.
* Progress tokens **MUST** be a string or integer value
* Progress tokens can be chosen by the sender using any means, but **MUST** be unique
across all active requests.
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"method": "some_method",
"params": {
"_meta": {
"progressToken": "abc123"
}
}
}
```
The receiver **MAY** then send progress notifications containing:
* The original progress token
* The current progress value so far
* An optional "total" value
* An optional "message" value
```json theme={null}
{
"jsonrpc": "2.0",
"method": "notifications/progress",
"params": {
"progressToken": "abc123",
"progress": 50,
"total": 100,
"message": "Reticulating splines..."
}
}
```
* The `progress` value **MUST** increase with each notification, even if the total is
unknown.
* The `progress` and the `total` values **MAY** be floating point.
* The `message` field **SHOULD** provide relevant human readable progress information.
## Behavior Requirements
1. Progress notifications **MUST** only reference tokens that:
* Were provided in an active request
* Are associated with an in-progress operation
2. Receivers of progress requests **MAY**:
* Choose not to send any progress notifications
* Send notifications at whatever frequency they deem appropriate
* Omit the total value if unknown
3. For [task-augmented requests](./tasks), the `progressToken` provided in the original request **MUST** continue to be used for progress notifications throughout the task's lifetime, even after the `CreateTaskResult` has been returned. The progress token remains valid and associated with the task until the task reaches a terminal status.
* Progress notifications for tasks **MUST** use the same `progressToken` that was provided in the initial task-augmented request
* Progress notifications for tasks **MUST** stop after the task reaches a terminal status (`completed`, `failed`, or `cancelled`)
```mermaid theme={null}
sequenceDiagram
participant Sender
participant Receiver
Note over Sender,Receiver: Request with progress token
Sender->>Receiver: Method request with progressToken
Note over Sender,Receiver: Progress updates
Receiver-->>Sender: Progress notification (0.2/1.0)
Receiver-->>Sender: Progress notification (0.6/1.0)
Receiver-->>Sender: Progress notification (1.0/1.0)
Note over Sender,Receiver: Operation complete
Receiver->>Sender: Method response
```
## Implementation Notes
* Senders and receivers **SHOULD** track active progress tokens
* Both parties **SHOULD** implement rate limiting to prevent flooding
* Progress notifications **MUST** stop after completion
specification/2025-11-25/basic/utilities/tasks New page · 886 lines, new page
# Tasks ## Definitions ## User Interaction Model ## Capabilities ### Server Capabilities ### Client Capabilities ### Capability Negotiation ### Tool-Level Negotiation ## Protocol Messages ### Creating Tasks ### Getting Tasks ### Retrieving Task Results ### Task Status Notification ### Listing Tasks ### Cancelling Tasks ## Behavior Requirements ### Task Support and Handling ### Task ID Requirements ### Task Status Lifecycle ### Input Required Status ### TTL and Resource Management ### Result Retrieval ### Associating Task-Related Messages ### Task Notifications ### Task Progress Notifications ### Task Listing ### Task Cancellation ## Message Flow ### Basic Task Lifecycle ### Task-Augmented Tool Call With Elicitation ### Task-Augmented Sampling Request ### Task Cancellation Flow ## Data Types ### Task ### Task Status ### Task Parameters ### Related Task Metadata ## Error Handling ### Protocol Errors ### Task Execution Errors ## Security Considerations ### Task Isolation and Access Control ### Resource Management ### Audit and Logging
A whole new page. There's nothing to diff it against, so here is what it says.
# Tasks
<div id="enable-section-numbers" />
<Note>
Tasks were introduced in version 2025-11-25 of the MCP specification and are currently considered **experimental**.
The design and behavior of tasks may evolve in future protocol versions.
</Note>
The Model Context Protocol (MCP) allows requestors — which can be either clients or servers, depending on the direction of communication — to augment their requests with **tasks**. Tasks are durable state machines that carry information about the underlying execution state of the request they wrap, and are intended for requestor polling and deferred result retrieval. Each task is uniquely identifiable by a receiver-generated **task ID**.
Tasks are useful for representing expensive computations and batch processing requests, and integrate seamlessly with external job APIs.
## Definitions
Tasks represent parties as either "requestors" or "receivers," defined as follows:
* **Requestor:** The sender of a task-augmented request. This can be the client or the server — either can create tasks.
* **Receiver:** The receiver of a task-augmented request, and the entity executing the task. This can be the client or the server — either can receive and execute tasks.
## User Interaction Model
Tasks are designed to be **requestor-driven** - requestors are responsible for augmenting requests with tasks and for polling for the results of those tasks; meanwhile, receivers tightly control which requests (if any) support task-based execution and manages the lifecycles of those tasks.
This requestor-driven approach ensures deterministic response handling and enables sophisticated patterns such as dispatching concurrent requests, which only the requestor has sufficient context to orchestrate.
Implementations are free to expose tasks through any interface pattern that suits their needs — the protocol itself does not mandate any specific user interaction model.
## Capabilities
Servers and clients that support task-augmented requests **MUST** declare a `tasks` capability during initialization. The `tasks` capability is structured by request category, with boolean properties indicating which specific request types support task augmentation.
### Server Capabilities
Servers declare if they support tasks, and if so, which server-side requests can be augmented with tasks.
| Capability | Description |
| --------------------------- | ---------------------------------------------------- |
| `tasks.list` | Server supports the `tasks/list` operation |
| `tasks.cancel` | Server supports the `tasks/cancel` operation |
| `tasks.requests.tools.call` | Server supports task-augmented `tools/call` requests |
```json theme={null}
{
"capabilities": {
"tasks": {
"list": {},
"cancel": {},
"requests": {
"tools": {
"call": {}
}
}
}
}
}
```
### Client Capabilities
Clients declare if they support tasks, and if so, which client-side requests can be augmented with tasks.
| Capability | Description |
| --------------------------------------- | ---------------------------------------------------------------- |
| `tasks.list` | Client supports the `tasks/list` operation |
| `tasks.cancel` | Client supports the `tasks/cancel` operation |
| `tasks.requests.sampling.createMessage` | Client supports task-augmented `sampling/createMessage` requests |
| `tasks.requests.elicitation.create` | Client supports task-augmented `elicitation/create` requests |
```json theme={null}
{
"capabilities": {
"tasks": {
"list": {},
"cancel": {},
"requests": {
"sampling": {
"createMessage": {}
},
"elicitation": {
"create": {}
}
}
}
}
}
```
### Capability Negotiation
During the initialization phase, both parties exchange their `tasks` capabilities to establish which operations support task-based execution. Requestors **SHOULD** only augment requests with a task if the corresponding capability has been declared by the receiver.
For example, if a server's capabilities include `tasks.requests.tools.call: {}`, then clients may augment `tools/call` requests with a task. If a client's capabilities include `tasks.requests.sampling.createMessage: {}`, then servers may augment `sampling/createMessage` requests with a task.
If `capabilities.tasks` is not defined, the peer **SHOULD NOT** attempt to create tasks during requests.
The set of capabilities in `capabilities.tasks.requests` is exhaustive. If a request type is not present, it does not support task-augmentation.
`capabilities.tasks.list` controls if the `tasks/list` operation is supported by the party.
`capabilities.tasks.cancel` controls if the `tasks/cancel` operation is supported by the party.
### Tool-Level Negotiation
Tool calls are given special consideration for the purpose of task augmentation. In the result of `tools/list`, tools declare support for tasks via `execution.taskSupport`, which if present can have a value of `"required"`, `"optional"`, or `"forbidden"`.
This is to be interpreted as a fine-grained layer in addition to capabilities, following these rules:
1. If a server's capabilities do not include `tasks.requests.tools.call`, then clients **MUST NOT** attempt to use task augmentation on that server's tools, regardless of the `execution.taskSupport` value.
2. If a server's capabilities include `tasks.requests.tools.call`, then clients consider the value of `execution.taskSupport`, and handle it accordingly:
1. If `execution.taskSupport` is not present or `"forbidden"`, clients **MUST NOT** attempt to invoke the tool as a task. Servers **SHOULD** return a `-32601` (Method not found) error if a client attempts to do so. This is the default behavior.
2. If `execution.taskSupport` is `"optional"`, clients **MAY** invoke the tool as a task or as a normal request.
3. If `execution.taskSupport` is `"required"`, clients **MUST** invoke the tool as a task. Servers **MUST** return a `-32601` (Method not found) error if a client does not attempt to do so.
## Protocol Messages
### Creating Tasks
Task-augmented requests follow a two-phase response pattern that differs from normal requests:
* **Normal requests**: The server processes the request and returns the actual operation result directly.
* **Task-augmented requests**: The server accepts the request and immediately returns a `CreateTaskResult` containing task data. The actual operation result becomes available later through `tasks/result` after the task completes.
To create a task, requestors send a request with the `task` field included in the request params. Requestors **MAY** include a `ttl` value indicating the desired task lifetime duration (in milliseconds) since its creation.
**Request:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "get_weather",
"arguments": {
"city": "New York"
},
"task": {
"ttl": 60000
}
}
}
```
**Response:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"task": {
"taskId": "786512e2-9e0d-44bd-8f29-789f320fe840",
"status": "working",
"statusMessage": "The operation is now in progress.",
"createdAt": "2025-11-25T10:30:00Z",
"lastUpdatedAt": "2025-11-25T10:40:00Z",
"ttl": 60000,
"pollInterval": 5000
}
}
}
```
When a receiver accepts a task-augmented request, it returns a [`CreateTaskResult`](/specification/2025-11-25/schema#createtaskresult) containing task data. The response does not include the actual operation result. The actual result (e.g., tool result for `tools/call`) becomes available only through `tasks/result` after the task completes.
<Note>
When a task is created in response to a `tools/call` request, host applications may wish to return control to the model while the task is executing. This allows the model to continue processing other requests or perform additional work while waiting for the task to complete.
To support this pattern, servers can provide an optional `io.modelcontextprotocol/model-immediate-response` key in the `_meta` field of the `CreateTaskResult`. The value of this key should be a string intended to be passed as an immediate tool result to the model.
If a server does not provide this field, the host application can fall back to its own predefined message.
This guidance is non-binding and is provisional logic intended to account for the specific use case. This behavior may be formalized or modified as part of `CreateTaskResult` in future protocol versions.
</Note>
### Getting Tasks
<Note>
In the Streamable HTTP (SSE) transport, clients **MAY** disconnect from an SSE stream opened by the server in response to a `tasks/get` request at any time.
While this note is not prescriptive regarding the specific usage of SSE streams, all implementations **MUST** continue to comply with the existing [Streamable HTTP transport specification](../transports#sending-messages-to-the-server).
</Note>
Requestors poll for task completion by sending [`tasks/get`](/specification/2025-11-25/schema#tasks%2Fget) requests.
Requestors **SHOULD** respect the `pollInterval` provided in responses when determining polling frequency.
Requestors **SHOULD** continue polling until the task reaches a terminal status (`completed`, `failed`, or `cancelled`), or until encountering the [`input_required`](#input-required-status) status. Note that invoking `tasks/result` does not imply that the requestor needs to stop polling - requestors **SHOULD** continue polling the task status via `tasks/get` if they are not actively waiting for `tasks/result` to complete.
**Request:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 3,
"method": "tasks/get",
"params": {
"taskId": "786512e2-9e0d-44bd-8f29-789f320fe840"
}
}
```
**Response:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 3,
"result": {
"taskId": "786512e2-9e0d-44bd-8f29-789f320fe840",
"status": "working",
"statusMessage": "The operation is now in progress.",
"createdAt": "2025-11-25T10:30:00Z",
"lastUpdatedAt": "2025-11-25T10:40:00Z",
"ttl": 30000,
"pollInterval": 5000
}
}
```
### Retrieving Task Results
<Note>
In the Streamable HTTP (SSE) transport, clients **MAY** disconnect from an SSE stream opened by the server in response to a `tasks/result` request at any time.
While this note is not prescriptive regarding the specific usage of SSE streams, all implementations **MUST** continue to comply with the existing [Streamable HTTP transport specification](../transports#sending-messages-to-the-server).
</Note>
After a task completes the operation result is retrieved via [`tasks/result`](/specification/2025-11-25/schema#tasks%2Fresult). This is distinct from the initial `CreateTaskResult` response, which contains only task data. The result structure matches the original request type (e.g., `CallToolResult` for `tools/call`).
To retrieve the result of a completed task, requestors can send a `tasks/result` request:
While `tasks/result` blocks until the task reaches a terminal status, requestors can continue polling via `tasks/get` in parallel if they are not actively blocked waiting for the result, such as if their previous `tasks/result` request failed or was cancelled. This allows requestors to monitor status changes or display progress updates while the task executes, even after invoking `tasks/result`.
**Request:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 4,
"method": "tasks/result",
"params": {
"taskId": "786512e2-9e0d-44bd-8f29-789f320fe840"
}
}
```
**Response:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 4,
"result": {
"content": [
{
"type": "text",
"text": "Current weather in New York:\nTemperature: 72°F\nConditions: Partly cloudy"
}
],
"isError": false,
"_meta": {
"io.modelcontextprotocol/related-task": {
"taskId": "786512e2-9e0d-44bd-8f29-789f320fe840"
}
}
}
}
```
### Task Status Notification
When a task status changes, receivers **MAY** send a [`notifications/tasks/status`](/specification/2025-11-25/schema#notifications%2Ftasks%2Fstatus) notification to inform the requestor of the change. This notification includes the full task state.
**Notification:**
```json theme={null}
{
"jsonrpc": "2.0",
"method": "notifications/tasks/status",
"params": {
"taskId": "786512e2-9e0d-44bd-8f29-789f320fe840",
"status": "completed",
"createdAt": "2025-11-25T10:30:00Z",
"lastUpdatedAt": "2025-11-25T10:50:00Z",
"ttl": 60000,
"pollInterval": 5000
}
}
```
The notification includes the full [`Task`](/specification/2025-11-25/schema#task) object, including the updated `status` and `statusMessage` (if present). This allows requestors to access the complete task state without making an additional `tasks/get` request.
Requestors **MUST NOT** rely on receiving this notifications, as it is optional. Receivers are not required to send status notifications and may choose to only send them for certain status transitions. Requestors **SHOULD** continue to poll via `tasks/get` to ensure they receive status updates.
### Listing Tasks
To retrieve a list of tasks, requestors can send a [`tasks/list`](/specification/2025-11-25/schema#tasks%2Flist) request. This operation supports pagination.
**Request:**
Cut at 300 lines. The page has the rest.
specification/2025-11-25/changelog New page · 47 lines, new page
# Key Changes ## Major changes ## Minor changes ## Other schema changes ## Governance and process updates ## Full changelog
A whole new page. There's nothing to diff it against, so here is what it says.
# Key Changes <div id="enable-section-numbers" /> This document lists changes made to the Model Context Protocol (MCP) specification since the previous revision, [2025-06-18](/specification/2025-06-18). ## Major changes 1. Enhance authorization server discovery with support for [OpenID Connect Discovery 1.0](https://openid.net/specs/openid-connect-discovery-1_0.html). (PR [#797](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/797)) 2. Allow servers to expose icons as additional metadata for tools, resources, resource templates, and prompts ([SEP-973](https://github.com/modelcontextprotocol/modelcontextprotocol/issues/973)). 3. Enhance authorization flows with incremental scope consent via `WWW-Authenticate` ([SEP-835](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/835)) 4. Provide guidance on tool names ([SEP-986](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/1603)) 5. Update `ElicitResult` and `EnumSchema` to use a more standards-based approach and support titled, untitled, single-select, and multi-select enums ([SEP-1330](https://github.com/modelcontextprotocol/modelcontextprotocol/issues/1330)). 6. Added support for [URL mode elicitation](/specification/2025-11-25/client/elicitation#url-elicitation-requests) ([SEP-1036](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/887)) 7. Add tool calling support to sampling via `tools` and `toolChoice` parameters ([SEP-1577](https://github.com/modelcontextprotocol/modelcontextprotocol/issues/1577)) 8. Add support for OAuth Client ID Metadata Documents as a recommended client registration mechanism ([SEP-991](https://github.com/modelcontextprotocol/modelcontextprotocol/issues/991), PR [#1296](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/1296)) 9. Add experimental support for [tasks](/specification/2025-11-25/basic/utilities/tasks) to enable tracking durable requests with polling and deferred result retrieval ([SEP-1686](https://github.com/modelcontextprotocol/modelcontextprotocol/issues/1686)). ## Minor changes 1. Clarify that servers using stdio transport may use stderr for all types of logging, not just error messages (PR [#670](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/670)). 2. Add optional `description` field to `Implementation` interface to align with MCP registry server.json format and provide human-readable context during initialization. 3. Clarify that servers must respond with HTTP 403 Forbidden for invalid Origin headers in Streamable HTTP transport. (PR [#1439](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/1439)) 4. Updated the [Security Best Practices guidance](https://modelcontextprotocol.io/specification/draft/basic/security_best_practices). 5. Clarify that input validation errors should be returned as Tool Execution Errors rather than Protocol Errors to enable model self-correction ([SEP-1303](https://github.com/modelcontextprotocol/modelcontextprotocol/issues/1303)). 6. Support polling SSE streams by allowing servers to disconnect at will ([SEP-1699](https://github.com/modelcontextprotocol/modelcontextprotocol/issues/1699)). 7. Clarify SEP-1699: GET streams support polling, resumption always via GET regardless of stream origin, event IDs should encode stream identity, disconnection includes server-initiated closure (Issue [#1847](https://github.com/modelcontextprotocol/modelcontextprotocol/issues/1847)). 8. Align OAuth 2.0 Protected Resource Metadata discovery with RFC 9728, making `WWW-Authenticate` header optional with fallback to `.well-known` endpoint ([SEP-985](https://github.com/modelcontextprotocol/modelcontextprotocol/issues/985)). 9. Add support for default values in all primitive types (string, number, enum) for elicitation schemas ([SEP-1034](https://github.com/modelcontextprotocol/modelcontextprotocol/issues/1034)). 10. Establish JSON Schema 2020-12 as the default dialect for MCP schema definitions ([SEP-1613](https://github.com/modelcontextprotocol/modelcontextprotocol/issues/1613)). ## Other schema changes 1. Decouple request payloads from RPC method definitions into standalone parameter schemas. ([SEP-1319](https://github.com/modelcontextprotocol/specification/issues/1319), PR [#1284](https://github.com/modelcontextprotocol/specification/pull/1284)) ## Governance and process updates 1. Formalize Model Context Protocol governance structure ([SEP-932](https://github.com/modelcontextprotocol/modelcontextprotocol/issues/932)). 2. Establish shared communication practices and guidelines for the MCP community ([SEP-994](https://github.com/modelcontextprotocol/modelcontextprotocol/issues/994)). 3. Formalize Working Groups and Interest Groups in MCP governance ([SEP-1302](https://github.com/modelcontextprotocol/modelcontextprotocol/issues/1302)). 4. Establish SDK tiering system with clear requirements for feature support and maintenance commitments ([SEP-1730](https://github.com/modelcontextprotocol/modelcontextprotocol/issues/1730)). ## Full changelog For a complete list of all changes that have been made since the last protocol revision, [see GitHub](https://github.com/modelcontextprotocol/specification/compare/2025-06-18...2025-11-25).
specification/2025-11-25/client/elicitation New page · 775 lines, new page
# Elicitation ## User Interaction Model ## Capabilities ## Protocol Messages ### Elicitation Requests ### Form Mode Elicitation Requests #### Requested Schema #### Example: Simple Text Request #### Example: Structured Data Request ### URL Mode Elicitation Requests #### Example: Request Sensitive Data ### Completion Notifications for URL Mode Elicitation #### Example ### URL Elicitation Required Error ## Message Flow ### Form Mode Flow ### URL Mode Flow ### URL Mode With Elicitation Required Error Flow ## Response Actions ## Implementation Considerations ### Statefulness ### URL Mode Elicitation for Sensitive Data ### URL Mode Elicitation for OAuth Flows #### Understanding the Distinction #### Implementation Pattern ## Error Handling ## Security Considerations ### Safe URL Handling ### Identifying the User ### Form Mode Security #### Phishing
A whole new page. There's nothing to diff it against, so here is what it says.
# Elicitation
<div id="enable-section-numbers" />
The Model Context Protocol (MCP) provides a standardized way for servers to request additional
information from users through the client during interactions. This flow allows clients to
maintain control over user interactions and data sharing while enabling servers to gather
necessary information dynamically.
Elicitation supports two modes:
* **Form mode**: Servers can request structured data from users with optional JSON schemas to validate responses
* **URL mode**: Servers can direct users to external URLs for sensitive interactions that must *not* pass through the MCP client
## User Interaction Model
Elicitation in MCP allows servers to implement interactive workflows by enabling user input
requests to occur *nested* inside other MCP server features.
Implementations are free to expose elicitation through any interface pattern that suits
their needs—the protocol itself does not mandate any specific user interaction
model.
<Warning>
For trust & safety and security:
* Servers **MUST NOT** use form mode elicitation to request sensitive information such as
passwords, API keys, access tokens, or payment credentials
* Servers **MUST** use [URL mode](#url-mode-elicitation-requests) for interactions involving
such sensitive information
"Sensitive information" in this context refers to secrets and credentials that grant access or
authorize transactions. General contact or profile information (such as a name, email address,
or username) is not categorically prohibited; whether to request such data via form mode is at
the discretion of the server and subject to the user's ability to review and decline.
MCP clients **MUST**:
* Provide UI that makes it clear which server is requesting information
* Respect user privacy and provide clear decline and cancel options
* For form mode, allow users to review and modify their responses before sending
* For URL mode, clearly display the target domain/host and gather user consent before navigation to the target URL
</Warning>
## Capabilities
Clients that support elicitation **MUST** declare the `elicitation` capability during
[initialization](../basic/lifecycle#initialization):
```json theme={null}
{
"capabilities": {
"elicitation": {
"form": {},
"url": {}
}
}
}
```
For backwards compatibility, an empty capabilities object is equivalent to declaring support for `form` mode only:
```jsonc theme={null}
{
"capabilities": {
"elicitation": {}, // Equivalent to { "form": {} }
},
}
```
Clients declaring the `elicitation` capability **MUST** support at least one mode (`form` or `url`).
Servers **MUST NOT** send elicitation requests with modes that are not supported by the client.
## Protocol Messages
### Elicitation Requests
To request information from a user, servers send an `elicitation/create` request.
All elicitation requests **MUST** include the following parameters:
| Name | Type | Options | Description |
| --------- | ------ | ------------- | -------------------------------------------------------------------------------------- |
| `mode` | string | `form`, `url` | The mode of the elicitation. Optional for form mode (defaults to `"form"` if omitted). |
| `message` | string | | A human-readable message explaining why the interaction is needed. |
The `mode` parameter specifies the type of elicitation:
* `"form"`: In-band structured data collection with optional schema validation. Data is exposed to the client.
* `"url"`: Out-of-band interaction via URL navigation. Data (other than the URL itself) is **not** exposed to the client.
For backwards compatibility, servers **MAY** omit the `mode` field for form mode elicitation requests. Clients **MUST** treat requests without a `mode` field as form mode.
### Form Mode Elicitation Requests
Form mode elicitation allows servers to collect structured data directly through the MCP client.
Form mode elicitation requests **MUST** either specify `mode: "form"` or omit the `mode` field, and include these additional parameters:
| Name | Type | Description |
| ----------------- | ------ | -------------------------------------------------------------- |
| `requestedSchema` | object | A JSON Schema defining the structure of the expected response. |
#### Requested Schema
The `requestedSchema` parameter allows servers to define the structure of the expected
response using a restricted subset of JSON Schema.
To simplify client user experience, form mode elicitation schemas are limited to flat objects
with primitive properties only.
The schema is restricted to these primitive types:
1. **String Schema**
```json theme={null}
{
"type": "string",
"title": "Display Name",
"description": "Description text",
"minLength": 3,
"maxLength": 50,
"pattern": "^[A-Za-z]+$",
"format": "email",
"default": "[email protected]"
}
```
Supported formats: `email`, `uri`, `date`, `date-time`
2. **Number Schema**
```json theme={null}
{
"type": "number", // or "integer"
"title": "Display Name",
"description": "Description text",
"minimum": 0,
"maximum": 100,
"default": 50
}
```
3. **Boolean Schema**
```json theme={null}
{
"type": "boolean",
"title": "Display Name",
"description": "Description text",
"default": false
}
```
4. **Enum Schema**
Single-select enum (without titles):
```json theme={null}
{
"type": "string",
"title": "Color Selection",
"description": "Choose your favorite color",
"enum": ["Red", "Green", "Blue"],
"default": "Red"
}
```
Single-select enum (with titles):
```json theme={null}
{
"type": "string",
"title": "Color Selection",
"description": "Choose your favorite color",
"oneOf": [
{ "const": "#FF0000", "title": "Red" },
{ "const": "#00FF00", "title": "Green" },
{ "const": "#0000FF", "title": "Blue" }
],
"default": "#FF0000"
}
```
Multi-select enum (without titles):
```json theme={null}
{
"type": "array",
"title": "Color Selection",
"description": "Choose your favorite colors",
"minItems": 1,
"maxItems": 2,
"items": {
"type": "string",
"enum": ["Red", "Green", "Blue"]
},
"default": ["Red", "Green"]
}
```
Multi-select enum (with titles):
```json theme={null}
{
"type": "array",
"title": "Color Selection",
"description": "Choose your favorite colors",
"minItems": 1,
"maxItems": 2,
"items": {
"anyOf": [
{ "const": "#FF0000", "title": "Red" },
{ "const": "#00FF00", "title": "Green" },
{ "const": "#0000FF", "title": "Blue" }
]
},
"default": ["#FF0000", "#00FF00"]
}
```
Clients can use this schema to:
1. Generate appropriate input forms
2. Validate user input before sending
3. Provide better guidance to users
All primitive types support optional default values to provide sensible starting points. Clients that support defaults SHOULD pre-populate form fields with these values.
Note that complex nested structures, arrays of objects (beyond enums), and other advanced JSON Schema features are intentionally not supported to simplify client user experience.
#### Example: Simple Text Request
**Request:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"method": "elicitation/create",
"params": {
"mode": "form",
"message": "Please provide your GitHub username",
"requestedSchema": {
"type": "object",
"properties": {
"name": {
"type": "string"
}
},
"required": ["name"]
}
}
}
```
**Response:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"action": "accept",
"content": {
"name": "octocat"
}
}
}
```
#### Example: Structured Data Request
**Request:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 2,
"method": "elicitation/create",
"params": {
"mode": "form",
"message": "Please provide your contact information",
"requestedSchema": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Your full name"
},
"email": {
"type": "string",
"format": "email",
"description": "Your email address"
},
"age": {
"type": "number",
"minimum": 18,
"description": "Your age"
Cut at 300 lines. The page has the rest.
specification/2025-11-25/client/roots New page · 186 lines, new page
# Roots ## User Interaction Model ## Capabilities ## Protocol Messages ### Listing Roots ### Root List Changes ## Message Flow ## Data Types ### Root #### Project Directory #### Multiple Repositories ## Error Handling ## Security Considerations ## Implementation Guidelines
A whole new page. There's nothing to diff it against, so here is what it says.
# Roots
<div id="enable-section-numbers" />
The Model Context Protocol (MCP) provides a standardized way for clients to expose
filesystem "roots" to servers. Roots define the boundaries of where servers can operate
within the filesystem, allowing them to understand which directories and files they have
access to. Servers can request the list of roots from supporting clients and receive
notifications when that list changes.
## User Interaction Model
Roots in MCP are typically exposed through workspace or project configuration interfaces.
For example, implementations could offer a workspace/project picker that allows users to
select directories and files the server should have access to. This can be combined with
automatic workspace detection from version control systems or project files.
However, implementations are free to expose roots through any interface pattern that
suits their needs—the protocol itself does not mandate any specific user
interaction model.
## Capabilities
Clients that support roots **MUST** declare the `roots` capability during
[initialization](/specification/2025-11-25/basic/lifecycle#initialization):
```json theme={null}
{
"capabilities": {
"roots": {
"listChanged": true
}
}
}
```
`listChanged` indicates whether the client will emit notifications when the list of roots
changes.
## Protocol Messages
### Listing Roots
To retrieve roots, servers send a `roots/list` request:
**Request:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"method": "roots/list"
}
```
**Response:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"roots": [
{
"uri": "file:///home/user/projects/myproject",
"name": "My Project"
}
]
}
}
```
### Root List Changes
When roots change, clients that support `listChanged` **MUST** send a notification:
```json theme={null}
{
"jsonrpc": "2.0",
"method": "notifications/roots/list_changed"
}
```
## Message Flow
```mermaid theme={null}
sequenceDiagram
participant Server
participant Client
Note over Server,Client: Discovery
Server->>Client: roots/list
Client-->>Server: Available roots
Note over Server,Client: Changes
Client--)Server: notifications/roots/list_changed
Server->>Client: roots/list
Client-->>Server: Updated roots
```
## Data Types
### Root
A root definition includes:
* `uri`: Unique identifier for the root. This **MUST** be a `file://` URI in the current
specification.
* `name`: Optional human-readable name for display purposes.
Example roots for different use cases:
#### Project Directory
```json theme={null}
{
"uri": "file:///home/user/projects/myproject",
"name": "My Project"
}
```
#### Multiple Repositories
```json theme={null}
[
{
"uri": "file:///home/user/repos/frontend",
"name": "Frontend Repository"
},
{
"uri": "file:///home/user/repos/backend",
"name": "Backend Repository"
}
]
```
## Error Handling
Clients **SHOULD** return standard JSON-RPC errors for common failure cases:
* Client does not support roots: `-32601` (Method not found)
* Internal errors: `-32603`
Example error:
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32601,
"message": "Roots not supported",
"data": {
"reason": "Client does not have roots capability"
}
}
}
```
## Security Considerations
1. Clients **MUST**:
* Only expose roots with appropriate permissions
* Validate all root URIs to prevent path traversal
* Implement proper access controls
* Monitor root accessibility
2. Servers **SHOULD**:
* Handle cases where roots become unavailable
* Respect root boundaries during operations
* Validate all paths against provided roots
## Implementation Guidelines
1. Clients **SHOULD**:
* Prompt users for consent before exposing roots to servers
* Provide clear user interfaces for root management
* Validate root accessibility before exposing
* Monitor for root changes
2. Servers **SHOULD**:
* Check for roots capability before usage
* Handle root list changes gracefully
* Respect root boundaries in operations
* Cache root information appropriately
specification/2025-11-25/client/sampling New page · 631 lines, new page
# Sampling ## User Interaction Model ## Tools in Sampling ## Capabilities ## Protocol Messages ### Creating Messages ### Sampling with Tools ### Multi-turn Tool Loop ## Message Content Constraints ### Tool Result Messages ### Tool Use and Result Balance ## Cross-API Compatibility ### Message Roles ### Tool Choice Modes ### Parallel Tool Use ## Message Flow ## Data Types ### Messages #### Text Content #### Image Content #### Audio Content ### Model Preferences #### Capability Priorities #### Model Hints ## Error Handling ## Security Considerations
A whole new page. There's nothing to diff it against, so here is what it says.
# Sampling
<div id="enable-section-numbers" />
The Model Context Protocol (MCP) provides a standardized way for servers to request LLM
sampling ("completions" or "generations") from language models via clients. This flow
allows clients to maintain control over model access, selection, and permissions while
enabling servers to leverage AI capabilities—with no server API keys necessary.
Servers can request text, audio, or image-based interactions and optionally include
context from MCP servers in their prompts.
## User Interaction Model
Sampling in MCP allows servers to implement agentic behaviors, by enabling LLM calls to
occur *nested* inside other MCP server features.
Implementations are free to expose sampling through any interface pattern that suits
their needs—the protocol itself does not mandate any specific user interaction
model.
<Warning>
For trust & safety and security, there **SHOULD** always
be a human in the loop with the ability to deny sampling requests.
Applications **SHOULD**:
* Provide UI that makes it easy and intuitive to review sampling requests
* Allow users to view and edit prompts before sending
* Present generated responses for review before delivery
</Warning>
## Tools in Sampling
Servers can request that the client's LLM use tools during sampling by providing a `tools` array and optional `toolChoice` configuration in their sampling requests. This enables servers to implement agentic behaviors where the LLM can call tools, receive results, and continue the conversation - all within a single sampling request flow.
Clients **MUST** declare support for tool use via the `sampling.tools` capability to receive tool-enabled sampling requests. Servers **MUST NOT** send tool-enabled sampling requests to Clients that have not declared support for tool use via the `sampling.tools` capability.
## Capabilities
Clients that support sampling **MUST** declare the `sampling` capability during
[initialization](/specification/2025-11-25/basic/lifecycle#initialization):
**Basic sampling:**
```json theme={null}
{
"capabilities": {
"sampling": {}
}
}
```
**With tool use support:**
```json theme={null}
{
"capabilities": {
"sampling": {
"tools": {}
}
}
}
```
**With context inclusion support (soft-deprecated):**
```json theme={null}
{
"capabilities": {
"sampling": {
"context": {}
}
}
}
```
<Note>
The `includeContext` parameter values `"thisServer"` and `"allServers"` are
soft-deprecated. Servers **SHOULD** avoid using these values (e.g. can just
omit `includeContext` since it defaults to `"none"`), and **SHOULD NOT** use
them unless the client declares `sampling.context` capability. These values
may be removed in future spec releases.
</Note>
## Protocol Messages
### Creating Messages
To request a language model generation, servers send a `sampling/createMessage` request:
**Request:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"method": "sampling/createMessage",
"params": {
"messages": [
{
"role": "user",
"content": {
"type": "text",
"text": "What is the capital of France?"
}
}
],
"modelPreferences": {
"hints": [
{
"name": "claude-3-sonnet"
}
],
"intelligencePriority": 0.8,
"speedPriority": 0.5
},
"systemPrompt": "You are a helpful assistant.",
"maxTokens": 100
}
}
```
**Response:**
```json theme={null}
{
"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"
}
}
```
### Sampling with Tools
The following diagram illustrates the complete flow of sampling with tools, including the multi-turn tool loop:
```mermaid theme={null}
sequenceDiagram
participant Server
participant Client
participant User
participant LLM
Note over Server,Client: Initial request with tools
Server->>Client: sampling/createMessage<br/>(messages + tools)
Note over Client,User: Human-in-the-loop review
Client->>User: Present request for approval
User-->>Client: Approve/modify
Client->>LLM: Forward request with tools
LLM-->>Client: Response with tool_use<br/>(stopReason: "toolUse")
Client->>User: Present tool calls for review
User-->>Client: Approve tool calls
Client-->>Server: Return tool_use response
Note over Server: Execute tool(s)
Server->>Server: Run get_weather("Paris")<br/>Run get_weather("London")
Note over Server,Client: Continue with tool results
Server->>Client: sampling/createMessage<br/>(history + tool_results + tools)
Client->>User: Present continuation
User-->>Client: Approve
Client->>LLM: Forward with tool results
LLM-->>Client: Final text response<br/>(stopReason: "endTurn")
Client->>User: Present response
User-->>Client: Approve
Client-->>Server: Return final response
Note over Server: Server processes result<br/>(may continue conversation...)
```
To request LLM generation with tool use capabilities, servers include `tools` and optionally `toolChoice` in the request:
**Request (Server -> Client):**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"method": "sampling/createMessage",
"params": {
"messages": [
{
"role": "user",
"content": {
"type": "text",
"text": "What's the weather like in Paris and London?"
}
}
],
"tools": [
{
"name": "get_weather",
"description": "Get current weather for a city",
"inputSchema": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "City name"
}
},
"required": ["city"]
}
}
],
"toolChoice": {
"mode": "auto"
},
"maxTokens": 1000
}
}
```
**Response (Client -> Server):**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "call_abc123",
"name": "get_weather",
"input": {
"city": "Paris"
}
},
{
"type": "tool_use",
"id": "call_def456",
"name": "get_weather",
"input": {
"city": "London"
}
}
],
"model": "claude-3-sonnet-20240307",
"stopReason": "toolUse"
}
}
```
### Multi-turn Tool Loop
After receiving tool use requests from the LLM, the server typically:
1. Executes the requested tool uses.
2. Sends a new sampling request with the tool results appended
3. Receives the LLM's response (which might contain new tool uses)
4. Repeats as many times as needed (server might cap the maximum number of iterations, and e.g. pass `toolChoice: {mode: "none"}` on the last iteration to force a final result)
**Follow-up request (Server -> Client) with tool results:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 2,
"method": "sampling/createMessage",
"params": {
"messages": [
{
"role": "user",
"content": {
"type": "text",
"text": "What's the weather like in Paris and London?"
}
},
{
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "call_abc123",
"name": "get_weather",
"input": { "city": "Paris" }
},
{
"type": "tool_use",
"id": "call_def456",
"name": "get_weather",
"input": { "city": "London" }
}
]
Cut at 300 lines. The page has the rest.
specification/2025-11-25/index New page · 135 lines, new page
# Specification ## Overview ## Key Details ### Base Protocol ### Features ### Additional Utilities ## Security and Trust & Safety ### Key Principles ### Implementation Guidelines ## Learn More
A whole new page. There's nothing to diff it against, so here is what it says.
# Specification
<div id="enable-section-numbers" />
[Model Context Protocol](https://modelcontextprotocol.io) (MCP) is an open protocol that
enables seamless integration between LLM applications and external data sources and
tools. Whether you're building an AI-powered IDE, enhancing a chat interface, or creating
custom AI workflows, MCP provides a standardized way to connect LLMs with the context
they need.
This specification defines the authoritative protocol requirements, based on the
TypeScript schema in
[schema.ts](https://github.com/modelcontextprotocol/specification/blob/main/schema/2025-11-25/schema.ts).
For implementation guides and examples, visit
[modelcontextprotocol.io](https://modelcontextprotocol.io).
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD
NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be
interpreted as described in [BCP 14](https://datatracker.ietf.org/doc/html/bcp14)
\[[RFC2119](https://datatracker.ietf.org/doc/html/rfc2119)]
\[[RFC8174](https://datatracker.ietf.org/doc/html/rfc8174)] when, and only when, they
appear in all capitals, as shown here.
## Overview
MCP provides a standardized way for applications to:
* Share contextual information with language models
* Expose tools and capabilities to AI systems
* Build composable integrations and workflows
The protocol uses [JSON-RPC](https://www.jsonrpc.org/) 2.0 messages to establish
communication between:
* **Hosts**: LLM applications that initiate connections
* **Clients**: Connectors within the host application
* **Servers**: Services that provide context and capabilities
MCP takes some inspiration from the
[Language Server Protocol](https://microsoft.github.io/language-server-protocol/), which
standardizes how to add support for programming languages across a whole ecosystem of
development tools. In a similar way, MCP standardizes how to integrate additional context
and tools into the ecosystem of AI applications.
## Key Details
### Base Protocol
* [JSON-RPC](https://www.jsonrpc.org/) message format
* Stateful connections
* Server and client capability negotiation
### Features
Servers offer any of the following features to clients:
* **Resources**: Context and data, for the user or the AI model to use
* **Prompts**: Templated messages and workflows for users
* **Tools**: Functions for the AI model to execute
Clients may offer the following features to servers:
* **Sampling**: Server-initiated agentic behaviors and recursive LLM interactions
* **Roots**: Server-initiated inquiries into URI or filesystem boundaries to operate in
* **Elicitation**: Server-initiated requests for additional information from users
### Additional Utilities
* Configuration
* Progress tracking
* Cancellation
* Error reporting
* Logging
## Security and Trust & Safety
The Model Context Protocol enables powerful capabilities through arbitrary data access
and code execution paths. With this power comes important security and trust
considerations that all implementors must carefully address.
### Key Principles
1. **User Consent and Control**
* Users must explicitly consent to and understand all data access and operations
* Users must retain control over what data is shared and what actions are taken
* Implementors should provide clear UIs for reviewing and authorizing activities
2. **Data Privacy**
* Hosts must obtain explicit user consent before exposing user data to servers
* Hosts must not transmit resource data elsewhere without user consent
* User data should be protected with appropriate access controls
3. **Tool Safety**
* Tools represent arbitrary code execution and must be treated with appropriate
caution.
* In particular, descriptions of tool behavior such as annotations should be
considered untrusted, unless obtained from a trusted server.
* Hosts must obtain explicit user consent before invoking any tool
* Users should understand what each tool does before authorizing its use
4. **LLM Sampling Controls**
* Users must explicitly approve any LLM sampling requests
* Users should control:
* Whether sampling occurs at all
* The actual prompt that will be sent
* What results the server can see
* The protocol intentionally limits server visibility into prompts
### Implementation Guidelines
While MCP itself cannot enforce these security principles at the protocol level,
implementors **SHOULD**:
1. Build robust consent and authorization flows into their applications
2. Provide clear documentation of security implications
3. Implement appropriate access controls and data protections
4. Follow security best practices in their integrations
5. Consider privacy implications in their feature designs
## Learn More
Explore the detailed specification for each protocol component:
<CardGroup cols={5}>
<Card title="Architecture" icon="sitemap" href="/specification/2025-11-25/architecture" />
<Card title="Base Protocol" icon="code" href="/specification/2025-11-25/basic" />
<Card title="Server Features" icon="server" href="/specification/2025-11-25/server" />
<Card title="Client Features" icon="user" href="/specification/2025-11-25/client" />
<Card title="Contributing" icon="pencil" href="/community/contributing" />
</CardGroup>
specification/2025-11-25/schema New page · 953 lines, new page
# Schema Reference ## JSON-RPC ## Common Types ## Content ## `completion/complete` ## `elicitation/create` ## `initialize` ## `logging/setLevel` ## `notifications/cancelled` ## `notifications/initialized` ## `notifications/tasks/status` ## `notifications/message` ## `notifications/progress` ## `notifications/prompts/list_changed` ## `notifications/resources/list_changed` ## `notifications/resources/updated` ## `notifications/roots/list_changed` ## `notifications/tools/list_changed` ## `notifications/elicitation/complete` ## `ping` ## `tasks` ## `tasks/get` ## `tasks/result` ## `tasks/list` ## `tasks/cancel` ## `prompts/get` ## `prompts/list` ## `resources/list` ## `resources/read` ## `resources/subscribe` ## `resources/templates/list` ## `resources/unsubscribe` ## `roots/list` ## `sampling/createMessage` ## `tools/call` ## `tools/list`
This page is larger than the 256 KiB this site keeps, so one side of the diff below stops where the stored text does.
A whole new page. There's nothing to diff it against, so here is what it says.
# Schema Reference
<div id="schema-reference" />
## JSON-RPC
<div class="type">
### `JSONRPCErrorResponse`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">JSONRPCErrorResponse</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#jsonrpcerrorresponse-jsonrpc">jsonrpc</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">"2.0"</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#jsonrpcerrorresponse-id">id</a><span class="tsd-signature-symbol">?:</span> <a href="#requestid" class="tsd-signature-type tsd-kind-type-alias">RequestId</a><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#jsonrpcerrorresponse-error">error</a><span class="tsd-signature-symbol">:</span> <a href="#error" class="tsd-signature-type tsd-kind-interface">Error</a><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>A response to a request that indicates an error occurred.</p> </div> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="jsonrpcerrorresponse-jsonrpc" data-typedoc-h="3"><span>jsonrpc: "2.0"</span><a href="#jsonrpcerrorresponse-jsonrpc" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="jsonrpcerrorresponse-id" data-typedoc-h="3"><span>id?: RequestId</span><a href="#jsonrpcerrorresponse-id" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="jsonrpcerrorresponse-error" data-typedoc-h="3"><span>error: Error</span><a href="#jsonrpcerrorresponse-error" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section>
</div>
<div class="type">
### `JSONRPCMessage`
<div class="tsd-signature"><span class="tsd-kind-type-alias">JSONRPCMessage</span><span class="tsd-signature-symbol">:</span> <a href="#jsonrpcrequest" class="tsd-signature-type tsd-kind-interface">JSONRPCRequest</a> <span class="tsd-signature-symbol">|</span> <a href="#jsonrpcnotification" class="tsd-signature-type tsd-kind-interface">JSONRPCNotification</a> <span class="tsd-signature-symbol">|</span> <a href="#jsonrpcresponse" class="tsd-signature-type tsd-kind-type-alias">JSONRPCResponse</a></div> <div class="tsd-comment tsd-typography"><p>Refers to any valid JSON-RPC object that can be decoded off the wire, or encoded to be sent.</p> </div>
</div>
<div class="type">
### `JSONRPCNotification`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">JSONRPCNotification</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#jsonrpcnotification-method">method</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#jsonrpcnotification-params">params</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-symbol">\{</span> <span class="tsd-signature-symbol">\[</span><span class="tsd-kind-index-signature">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <span class="tsd-signature-type">any</span> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#jsonrpcnotification-jsonrpc">jsonrpc</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">"2.0"</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>A notification which does not expect a response.</p> </div> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="jsonrpcnotification-method" data-typedoc-h="3"><span>method: string</span><a href="#jsonrpcnotification-method" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <aside class="tsd-sources"> <p>Inherited from Notification.method</p></aside></section> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="jsonrpcnotification-params" data-typedoc-h="3"><span>params?: \{ \[key: string]: any }</span><a href="#jsonrpcnotification-params" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <aside class="tsd-sources"> <p>Inherited from Notification.params</p></aside></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="jsonrpcnotification-jsonrpc" data-typedoc-h="3"><span>jsonrpc: "2.0"</span><a href="#jsonrpcnotification-jsonrpc" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section>
</div>
<div class="type">
### `JSONRPCRequest`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">JSONRPCRequest</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#jsonrpcrequest-method">method</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#jsonrpcrequest-params">params</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-symbol">\{</span> <span class="tsd-signature-symbol">\[</span><span class="tsd-kind-index-signature">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <span class="tsd-signature-type">any</span> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#jsonrpcrequest-jsonrpc">jsonrpc</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">"2.0"</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#jsonrpcrequest-id">id</a><span class="tsd-signature-symbol">:</span> <a href="#requestid" class="tsd-signature-type tsd-kind-type-alias">RequestId</a><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>A request that expects a response.</p> </div> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="jsonrpcrequest-method" data-typedoc-h="3"><span>method: string</span><a href="#jsonrpcrequest-method" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <aside class="tsd-sources"> <p>Inherited from Request.method</p></aside></section> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="jsonrpcrequest-params" data-typedoc-h="3"><span>params?: \{ \[key: string]: any }</span><a href="#jsonrpcrequest-params" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <aside class="tsd-sources"> <p>Inherited from Request.params</p></aside></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="jsonrpcrequest-jsonrpc" data-typedoc-h="3"><span>jsonrpc: "2.0"</span><a href="#jsonrpcrequest-jsonrpc" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="jsonrpcrequest-id" data-typedoc-h="3"><span>id: RequestId</span><a href="#jsonrpcrequest-id" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section>
</div>
<div class="type">
### `JSONRPCResponse`
<div class="tsd-signature"><span class="tsd-kind-type-alias">JSONRPCResponse</span><span class="tsd-signature-symbol">:</span> <a href="#jsonrpcresultresponse" class="tsd-signature-type tsd-kind-interface">JSONRPCResultResponse</a> <span class="tsd-signature-symbol">|</span> <a href="#jsonrpcerrorresponse" class="tsd-signature-type tsd-kind-interface">JSONRPCErrorResponse</a></div> <div class="tsd-comment tsd-typography"><p>A response to a request, containing either the result or error.</p> </div>
</div>
<div class="type">
### `JSONRPCResultResponse`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">JSONRPCResultResponse</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#jsonrpcresultresponse-jsonrpc">jsonrpc</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">"2.0"</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#jsonrpcresultresponse-id">id</a><span class="tsd-signature-symbol">:</span> <a href="#requestid" class="tsd-signature-type tsd-kind-type-alias">RequestId</a><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#jsonrpcresultresponse-result">result</a><span class="tsd-signature-symbol">:</span> <a href="#result" class="tsd-signature-type tsd-kind-interface">Result</a><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>A successful (non-error) response to a request.</p> </div> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="jsonrpcresultresponse-jsonrpc" data-typedoc-h="3"><span>jsonrpc: "2.0"</span><a href="#jsonrpcresultresponse-jsonrpc" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="jsonrpcresultresponse-id" data-typedoc-h="3"><span>id: RequestId</span><a href="#jsonrpcresultresponse-id" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="jsonrpcresultresponse-result" data-typedoc-h="3"><span>result: Result</span><a href="#jsonrpcresultresponse-result" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section>
</div>
## Common Types
<div class="type">
### `Annotations`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">Annotations</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#annotations-audience">audience</a><span class="tsd-signature-symbol">?:</span> <a href="#role" class="tsd-signature-type tsd-kind-type-alias">Role</a><span class="tsd-signature-symbol">\[]</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#annotations-priority">priority</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#annotations-lastmodified">lastModified</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>Optional annotations for the client. The client can use annotations to inform how objects are used or displayed</p> </div> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="annotations-audience" data-typedoc-h="3"><span>audience?: Role\[]</span><a href="#annotations-audience" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>Describes who the intended audience of this object or data is.</p> <p>It can include multiple entries to indicate content useful for multiple audiences (e.g., <code>\["user", "assistant"]</code>).</p> </div></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="annotations-priority" data-typedoc-h="3"><span>priority?: number</span><a href="#annotations-priority" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>Describes how important this data is for operating the server.</p> <p>A value of 1 means "most important," and indicates that the data is
effectively required, while 0 means "least important," and indicates that
the data is entirely optional.</p> </div></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="annotations-lastmodified" data-typedoc-h="3"><span>lastModified?: string</span><a href="#annotations-lastmodified" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>The moment the resource was last modified, as an ISO 8601 formatted string.</p> <p>Should be an ISO 8601 formatted string (e.g., "2025-01-12T15:00:58Z").</p> <p>Examples: last activity timestamp in an open file, timestamp when the resource
was attached, etc.</p> </div></section>
</div>
<div class="type">
### `Cursor`
<div class="tsd-signature"><span class="tsd-kind-type-alias">Cursor</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span></div> <div class="tsd-comment tsd-typography"><p>An opaque token used to represent a cursor for pagination.</p> </div>
</div>
<div class="type">
### `EmptyResult`
<div class="tsd-signature"><span class="tsd-kind-type-alias">EmptyResult</span><span class="tsd-signature-symbol">:</span> <a href="#result" class="tsd-signature-type tsd-kind-interface">Result</a></div> <div class="tsd-comment tsd-typography"><p>A response that indicates success but carries no data.</p> </div>
</div>
<div class="type">
### `Error`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">Error</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#error-code">code</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#error-message">message</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#error-data">data</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">unknown</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="error-code" data-typedoc-h="3"><span>code: number</span><a href="#error-code" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>The error type that occurred.</p> </div></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="error-message" data-typedoc-h="3"><span>message: string</span><a href="#error-message" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>A short description of the error. The message SHOULD be limited to a concise single sentence.</p> </div></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="error-data" data-typedoc-h="3"><span>data?: unknown</span><a href="#error-data" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>Additional information about the error. The value of this member is defined by the sender (e.g. detailed error information, nested errors etc.).</p> </div></section>
</div>
<div class="type">
### `Icon`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">Icon</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#icon-src">src</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#icon-mimetype">mimeType</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#icon-sizes">sizes</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">\[]</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#icon-theme">theme</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">"light"</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"dark"</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>An optionally-sized icon that can be displayed in a user interface.</p> </div> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="icon-src" data-typedoc-h="3"><span>src: string</span><a href="#icon-src" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>A standard URI pointing to an icon resource. May be an HTTP/HTTPS URL or a <code>data:</code> URI with Base64-encoded image data.</p> <p>Consumers SHOULD takes steps to ensure URLs serving icons are from the
same domain as the client/server or a trusted domain.</p> <p>Consumers SHOULD take appropriate precautions when consuming SVGs as they can contain
executable JavaScript.</p> </div></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="icon-mimetype" data-typedoc-h="3"><span>mimeType?: string</span><a href="#icon-mimetype" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>Optional MIME type override if the source MIME type is missing or generic.
For example: <code>"image/png"</code>, <code>"image/jpeg"</code>, or <code>"image/svg+xml"</code>.</p> </div></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="icon-sizes" data-typedoc-h="3"><span>sizes?: string\[]</span><a href="#icon-sizes" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>Optional array of strings that specify sizes at which the icon can be used.
Each string should be in WxH format (e.g., <code>"48x48"</code>, <code>"96x96"</code>) or <code>"any"</code> for scalable formats like SVG.</p> <p>If not provided, the client should assume that the icon can be used at any size.</p> </div></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="icon-theme" data-typedoc-h="3"><span>theme?: "light" | "dark"</span><a href="#icon-theme" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>Optional specifier for the theme this icon is designed for. <code>light</code> indicates
the icon is designed to be used with a light background, and <code>dark</code> indicates
the icon is designed to be used with a dark background.</p> <p>If not provided, the client should assume the icon can be used with any theme.</p> </div></section>
</div>
<div class="type">
### `LoggingLevel`
<div class="tsd-signature"><span class="tsd-kind-type-alias">LoggingLevel</span><span class="tsd-signature-symbol">:</span><br /> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"debug"</span><br /> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"info"</span><br /> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"notice"</span><br /> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"warning"</span><br /> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"error"</span><br /> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"critical"</span><br /> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"alert"</span><br /> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"emergency"</span></div> <div class="tsd-comment tsd-typography"><p>The severity of a log message.</p> <p>These map to syslog message severities, as specified in RFC-5424: <a href="https://datatracker.ietf.org/doc/html/rfc5424#section-6.2.1">[https://datatracker.ietf.org/doc/html/rfc5424#section-6.2.1](https://datatracker.ietf.org/doc/html/rfc5424#section-6.2.1)</a></p> </div>
</div>
<div class="type">
### `ProgressToken`
<div class="tsd-signature"><span class="tsd-kind-type-alias">ProgressToken</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">number</span></div> <div class="tsd-comment tsd-typography"><p>A progress token, used to associate progress notifications with the original request.</p> </div>
</div>
<div class="type">
### `RequestId`
<div class="tsd-signature"><span class="tsd-kind-type-alias">RequestId</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">number</span></div> <div class="tsd-comment tsd-typography"><p>A uniquely identifying ID for a request in JSON-RPC.</p> </div>
</div>
<div class="type">
### `Result`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">Result</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#result-_meta">\_meta</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-symbol">\{</span> <span class="tsd-signature-symbol">\[</span><span class="tsd-kind-index-signature">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <span class="tsd-signature-type">unknown</span> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span><br /> <span class="tsd-signature-symbol">\[</span><span class="tsd-kind-index-signature">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <span class="tsd-signature-type">unknown</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="result-_meta" data-typedoc-h="3"><span>\_meta?: \{ \[key: string]: unknown }</span><a href="#result-_meta" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>See <a href="/specification/2025-11-25/basic/index#meta">General fields: <code>\_meta</code></a> for notes on <code>\_meta</code> usage.</p> </div></section>
</div>
<div class="type">
### `Role`
<div class="tsd-signature"><span class="tsd-kind-type-alias">Role</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">"user"</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"assistant"</span></div> <div class="tsd-comment tsd-typography"><p>The sender or recipient of messages and data in a conversation.</p> </div>
</div>
## Content
<div class="type">
### `AudioContent`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">AudioContent</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#audiocontent-type">type</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">"audio"</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#audiocontent-data">data</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#audiocontent-mimetype">mimeType</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#audiocontent-annotations">annotations</a><span class="tsd-signature-symbol">?:</span> <a href="#annotations" class="tsd-signature-type tsd-kind-interface">Annotations</a><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#audiocontent-_meta">\_meta</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-symbol">\{</span> <span class="tsd-signature-symbol">\[</span><span class="tsd-kind-index-signature">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <span class="tsd-signature-type">unknown</span> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>Audio provided to or from an LLM.</p> </div> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="audiocontent-type" data-typedoc-h="3"><span>type: "audio"</span><a href="#audiocontent-type" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="audiocontent-data" data-typedoc-h="3"><span>data: string</span><a href="#audiocontent-data" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>The base64-encoded audio data.</p> </div></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="audiocontent-mimetype" data-typedoc-h="3"><span>mimeType: string</span><a href="#audiocontent-mimetype" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>The MIME type of the audio. Different providers may support different audio types.</p> </div></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="audiocontent-annotations" data-typedoc-h="3"><span>annotations?: Annotations</span><a href="#audiocontent-annotations" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>Optional annotations for the client.</p> </div></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="audiocontent-_meta" data-typedoc-h="3"><span>\_meta?: \{ \[key: string]: unknown }</span><a href="#audiocontent-_meta" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>See <a href="/specification/2025-11-25/basic/index#meta">General fields: <code>\_meta</code></a> for notes on <code>\_meta</code> usage.</p> </div></section>
</div>
<div class="type">
### `BlobResourceContents`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">BlobResourceContents</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#blobresourcecontents-uri">uri</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#blobresourcecontents-mimetype">mimeType</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#blobresourcecontents-_meta">\_meta</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-symbol">\{</span> <span class="tsd-signature-symbol">\[</span><span class="tsd-kind-index-signature">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <span class="tsd-signature-type">unknown</span> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#blobresourcecontents-blob">blob</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="blobresourcecontents-uri" data-typedoc-h="3"><span>uri: string</span><a href="#blobresourcecontents-uri" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>The URI of this resource.</p> </div><aside class="tsd-sources"> <p>Inherited from ResourceContents.uri</p></aside></section> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="blobresourcecontents-mimetype" data-typedoc-h="3"><span>mimeType?: string</span><a href="#blobresourcecontents-mimetype" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>The MIME type of this resource, if known.</p> </div><aside class="tsd-sources"> <p>Inherited from ResourceContents.mimeType</p></aside></section> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="blobresourcecontents-_meta" data-typedoc-h="3"><span>\_meta?: \{ \[key: string]: unknown }</span><a href="#blobresourcecontents-_meta" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>See <a href="/specification/2025-11-25/basic/index#meta">General fields: <code>\_meta</code></a> for notes on <code>\_meta</code> usage.</p> </div><aside class="tsd-sources"> <p>Inherited from ResourceContents.\_meta</p></aside></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="blobresourcecontents-blob" data-typedoc-h="3"><span>blob: string</span><a href="#blobresourcecontents-blob" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>A base64-encoded string representing the binary data of the item.</p> </div></section>
</div>
<div class="type">
### `ContentBlock`
<div class="tsd-signature"><span class="tsd-kind-type-alias">ContentBlock</span><span class="tsd-signature-symbol">:</span><br /> <span class="tsd-signature-symbol">|</span> <a href="#textcontent" class="tsd-signature-type tsd-kind-interface">TextContent</a><br /> <span class="tsd-signature-symbol">|</span> <a href="#imagecontent" class="tsd-signature-type tsd-kind-interface">ImageContent</a><br /> <span class="tsd-signature-symbol">|</span> <a href="#audiocontent" class="tsd-signature-type tsd-kind-interface">AudioContent</a><br /> <span class="tsd-signature-symbol">|</span> <a href="#resourcelink" class="tsd-signature-type tsd-kind-interface">ResourceLink</a><br /> <span class="tsd-signature-symbol">|</span> <a href="#embeddedresource" class="tsd-signature-type tsd-kind-interface">EmbeddedResource</a></div>
</div>
<div class="type">
### `EmbeddedResource`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">EmbeddedResource</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#embeddedresource-type">type</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">"resource"</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#embeddedresource-resource">resource</a><span class="tsd-signature-symbol">:</span> <a href="#textresourcecontents" class="tsd-signature-type tsd-kind-interface">TextResourceContents</a> <span class="tsd-signature-symbol">|</span> <a href="#blobresourcecontents" class="tsd-signature-type tsd-kind-interface">BlobResourceContents</a><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#embeddedresource-annotations">annotations</a><span class="tsd-signature-symbol">?:</span> <a href="#annotations" class="tsd-signature-type tsd-kind-interface">Annotations</a><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#embeddedresource-_meta">\_meta</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-symbol">\{</span> <span class="tsd-signature-symbol">\[</span><span class="tsd-kind-index-signature">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <span class="tsd-signature-type">unknown</span> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>The contents of a resource, embedded into a prompt or tool call result.</p> <p>It is up to the client how best to render embedded resources for the benefit
of the LLM and/or the user.</p> </div> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="embeddedresource-type" data-typedoc-h="3"><span>type: "resource"</span><a href="#embeddedresource-type" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="embeddedresource-resource" data-typedoc-h="3"><span>resource: TextResourceContents | BlobResourceContents</span><a href="#embeddedresource-resource" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="embeddedresource-annotations" data-typedoc-h="3"><span>annotations?: Annotations</span><a href="#embeddedresource-annotations" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>Optional annotations for the client.</p> </div></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="embeddedresource-_meta" data-typedoc-h="3"><span>\_meta?: \{ \[key: string]: unknown }</span><a href="#embeddedresource-_meta" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>See <a href="/specification/2025-11-25/basic/index#meta">General fields: <code>\_meta</code></a> for notes on <code>\_meta</code> usage.</p> </div></section>
</div>
<div class="type">
### `ImageContent`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">ImageContent</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#imagecontent-type">type</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">"image"</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#imagecontent-data">data</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#imagecontent-mimetype">mimeType</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#imagecontent-annotations">annotations</a><span class="tsd-signature-symbol">?:</span> <a href="#annotations" class="tsd-signature-type tsd-kind-interface">Annotations</a><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#imagecontent-_meta">\_meta</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-symbol">\{</span> <span class="tsd-signature-symbol">\[</span><span class="tsd-kind-index-signature">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <span class="tsd-signature-type">unknown</span> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>An image provided to or from an LLM.</p> </div> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="imagecontent-type" data-typedoc-h="3"><span>type: "image"</span><a href="#imagecontent-type" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="imagecontent-data" data-typedoc-h="3"><span>data: string</span><a href="#imagecontent-data" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>The base64-encoded image data.</p> </div></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="imagecontent-mimetype" data-typedoc-h="3"><span>mimeType: string</span><a href="#imagecontent-mimetype" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>The MIME type of the image. Different providers may support different image types.</p> </div></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="imagecontent-annotations" data-typedoc-h="3"><span>annotations?: Annotations</span><a href="#imagecontent-annotations" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>Optional annotations for the client.</p> </div></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="imagecontent-_meta" data-typedoc-h="3"><span>\_meta?: \{ \[key: string]: unknown }</span><a href="#imagecontent-_meta" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>See <a href="/specification/2025-11-25/basic/index#meta">General fields: <code>\_meta</code></a> for notes on <code>\_meta</code> usage.</p> </div></section>
</div>
<div class="type">
### `ResourceLink`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">ResourceLink</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#resourcelink-icons">icons</a><span class="tsd-signature-symbol">?:</span> <a href="#icon" class="tsd-signature-type tsd-kind-interface">Icon</a><span class="tsd-signature-symbol">\[]</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#resourcelink-name">name</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#resourcelink-title">title</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#resourcelink-uri">uri</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#resourcelink-description">description</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#resourcelink-mimetype">mimeType</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#resourcelink-annotations">annotations</a><span class="tsd-signature-symbol">?:</span> <a href="#annotations" class="tsd-signature-type tsd-kind-interface">Annotations</a><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#resourcelink-size">size</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#resourcelink-_meta">\_meta</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-symbol">\{</span> <span class="tsd-signature-symbol">\[</span><span class="tsd-kind-index-signature">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <span class="tsd-signature-type">unknown</span> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#resourcelink-type">type</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">"resource\_link"</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>A resource that the server is capable of reading, included in a prompt or tool call result.</p> <p>Note: resource links returned by tools are not guaranteed to appear in the results of <code>resources/list</code> requests.</p> </div> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="resourcelink-icons" data-typedoc-h="3"><span>icons?: Icon\[]</span><a href="#resourcelink-icons" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>Optional set of sized icons that the client can display in a user interface.</p> <p>Clients that support rendering icons MUST support at least the following MIME types:</p> <ul> <li><code>image/png</code> - PNG images (safe, universal compatibility)</li> <li><code>image/jpeg</code> (and <code>image/jpg</code>) - JPEG images (safe, universal compatibility)</li> </ul> <p>Clients that support rendering icons SHOULD also support:</p> <ul> <li><code>image/svg+xml</code> - SVG images (scalable but requires security precautions)</li> <li><code>image/webp</code> - WebP images (modern, efficient format)</li> </ul> </div><aside class="tsd-sources"> <p>Inherited from <a href="#resource">Resource</a>.<a href="#resource-icons">icons</a></p></aside></section> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="resourcelink-name" data-typedoc-h="3"><span>name: string</span><a href="#resourcelink-name" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>Intended for programmatic or logical use, but used as a display name in past specs or fallback (if title isn't present).</p> </div><aside class="tsd-sources"> <p>Inherited from <a href="#resource">Resource</a>.<a href="#resource-name">name</a></p></aside></section> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="resourcelink-title" data-typedoc-h="3"><span>title?: string</span><a href="#resourcelink-title" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>Intended for UI and end-user contexts — optimized to be human-readable and easily understood,
even by those unfamiliar with domain-specific terminology.</p> <p>If not provided, the name should be used for display (except for Tool,
where <code>annotations.title</code> should be given precedence over using <code>name</code>,
if present).</p> </div><aside class="tsd-sources"> <p>Inherited from <a href="#resource">Resource</a>.<a href="#resource-title">title</a></p></aside></section> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="resourcelink-uri" data-typedoc-h="3"><span>uri: string</span><a href="#resourcelink-uri" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>The URI of this resource.</p> </div><aside class="tsd-sources"> <p>Inherited from <a href="#resource">Resource</a>.<a href="#resource-uri">uri</a></p></aside></section> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="resourcelink-description" data-typedoc-h="3"><span>description?: string</span><a href="#resourcelink-description" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>A description of what this resource represents.</p> <p>This can be used by clients to improve the LLM's understanding of available resources. It can be thought of like a "hint" to the model.</p> </div><aside class="tsd-sources"> <p>Inherited from <a href="#resource">Resource</a>.<a href="#resource-description">description</a></p></aside></section> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="resourcelink-mimetype" data-typedoc-h="3"><span>mimeType?: string</span><a href="#resourcelink-mimetype" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>The MIME type of this resource, if known.</p> </div><aside class="tsd-sources"> <p>Inherited from <a href="#resource">Resource</a>.<a href="#resource-mimetype">mimeType</a></p></aside></section> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="resourcelink-annotations" data-typedoc-h="3"><span>annotations?: Annotations</span><a href="#resourcelink-annotations" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>Optional annotations for the client.</p> </div><aside class="tsd-sources"> <p>Inherited from <a href="#resource">Resource</a>.<a href="#resource-annotations">annotations</a></p></aside></section> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="resourcelink-size" data-typedoc-h="3"><span>size?: number</span><a href="#resourcelink-size" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>The size of the raw resource content, in bytes (i.e., before base64 encoding or any tokenization), if known.</p> <p>This can be used by Hosts to display file sizes and estimate context window usage.</p> </div><aside class="tsd-sources"> <p>Inherited from <a href="#resource">Resource</a>.<a href="#resource-size">size</a></p></aside></section> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="resourcelink-_meta" data-typedoc-h="3"><span>\_meta?: \{ \[key: string]: unknown }</span><a href="#resourcelink-_meta" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>See <a href="/specification/2025-11-25/basic/index#meta">General fields: <code>\_meta</code></a> for notes on <code>\_meta</code> usage.</p> </div><aside class="tsd-sources"> <p>Inherited from <a href="#resource">Resource</a>.<a href="#resource-_meta">\_meta</a></p></aside></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="resourcelink-type" data-typedoc-h="3"><span>type: "resource\_link"</span><a href="#resourcelink-type" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section>
</div>
<div class="type">
### `TextContent`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">TextContent</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#textcontent-type">type</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">"text"</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#textcontent-text">text</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#textcontent-annotations">annotations</a><span class="tsd-signature-symbol">?:</span> <a href="#annotations" class="tsd-signature-type tsd-kind-interface">Annotations</a><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#textcontent-_meta">\_meta</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-symbol">\{</span> <span class="tsd-signature-symbol">\[</span><span class="tsd-kind-index-signature">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <span class="tsd-signature-type">unknown</span> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>Text provided to or from an LLM.</p> </div> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="textcontent-type" data-typedoc-h="3"><span>type: "text"</span><a href="#textcontent-type" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="textcontent-text" data-typedoc-h="3"><span>text: string</span><a href="#textcontent-text" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>The text content of the message.</p> </div></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="textcontent-annotations" data-typedoc-h="3"><span>annotations?: Annotations</span><a href="#textcontent-annotations" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>Optional annotations for the client.</p> </div></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="textcontent-_meta" data-typedoc-h="3"><span>\_meta?: \{ \[key: string]: unknown }</span><a href="#textcontent-_meta" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>See <a href="/specification/2025-11-25/basic/index#meta">General fields: <code>\_meta</code></a> for notes on <code>\_meta</code> usage.</p> </div></section>
</div>
<div class="type">
### `TextResourceContents`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">TextResourceContents</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#textresourcecontents-uri">uri</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#textresourcecontents-mimetype">mimeType</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#textresourcecontents-_meta">\_meta</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-symbol">\{</span> <span class="tsd-signature-symbol">\[</span><span class="tsd-kind-index-signature">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <span class="tsd-signature-type">unknown</span> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#textresourcecontents-text">text</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="textresourcecontents-uri" data-typedoc-h="3"><span>uri: string</span><a href="#textresourcecontents-uri" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>The URI of this resource.</p> </div><aside class="tsd-sources"> <p>Inherited from ResourceContents.uri</p></aside></section> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="textresourcecontents-mimetype" data-typedoc-h="3"><span>mimeType?: string</span><a href="#textresourcecontents-mimetype" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>The MIME type of this resource, if known.</p> </div><aside class="tsd-sources"> <p>Inherited from ResourceContents.mimeType</p></aside></section> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="textresourcecontents-_meta" data-typedoc-h="3"><span>\_meta?: \{ \[key: string]: unknown }</span><a href="#textresourcecontents-_meta" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>See <a href="/specification/2025-11-25/basic/index#meta">General fields: <code>\_meta</code></a> for notes on <code>\_meta</code> usage.</p> </div><aside class="tsd-sources"> <p>Inherited from ResourceContents.\_meta</p></aside></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="textresourcecontents-text" data-typedoc-h="3"><span>text: string</span><a href="#textresourcecontents-text" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>The text of the item. This must only be set if the item can actually be represented as text (not binary data).</p> </div></section>
</div>
## `completion/complete`
<div class="type">
### `CompleteRequest`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">CompleteRequest</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#completerequest-jsonrpc">jsonrpc</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">"2.0"</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#completerequest-id">id</a><span class="tsd-signature-symbol">:</span> <a href="#requestid" class="tsd-signature-type tsd-kind-type-alias">RequestId</a><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#completerequest-method">method</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">"completion/complete"</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#completerequest-params">params</a><span class="tsd-signature-symbol">:</span> <a href="#completerequestparams" class="tsd-signature-type tsd-kind-interface">CompleteRequestParams</a><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>A request from the client to the server, to ask for completion options.</p> </div> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="completerequest-jsonrpc" data-typedoc-h="3"><span>jsonrpc: "2.0"</span><a href="#completerequest-jsonrpc" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <aside class="tsd-sources"> <p>Inherited from <a href="#jsonrpcrequest">JSONRPCRequest</a>.<a href="#jsonrpcrequest-jsonrpc">jsonrpc</a></p></aside></section> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="completerequest-id" data-typedoc-h="3"><span>id: RequestId</span><a href="#completerequest-id" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <aside class="tsd-sources"> <p>Inherited from <a href="#jsonrpcrequest">JSONRPCRequest</a>.<a href="#jsonrpcrequest-id">id</a></p></aside></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="completerequest-method" data-typedoc-h="3"><span>method: "completion/complete"</span><a href="#completerequest-method" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <aside class="tsd-sources"> <p>Overrides <a href="#jsonrpcrequest">JSONRPCRequest</a>.<a href="#jsonrpcrequest-method">method</a></p></aside></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="completerequest-params" data-typedoc-h="3"><span>params: CompleteRequestParams</span><a href="#completerequest-params" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <aside class="tsd-sources"> <p>Overrides <a href="#jsonrpcrequest">JSONRPCRequest</a>.<a href="#jsonrpcrequest-params">params</a></p></aside></section>
</div>
<div class="type">
### `CompleteRequestParams`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">CompleteRequestParams</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#completerequestparams-_meta">\_meta</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-symbol">\{</span> <span class="tsd-kind-property">progressToken</span><span class="tsd-signature-symbol">?:</span> <a href="#progresstoken" class="tsd-signature-type tsd-kind-type-alias">ProgressToken</a><span class="tsd-signature-symbol">;</span> <span class="tsd-signature-symbol">\[</span><span class="tsd-kind-index-signature">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <span class="tsd-signature-type">unknown</span> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#completerequestparams-ref">ref</a><span class="tsd-signature-symbol">:</span> <a href="#promptreference" class="tsd-signature-type tsd-kind-interface">PromptReference</a> <span class="tsd-signature-symbol">|</span> <a href="#resourcetemplatereference" class="tsd-signature-type tsd-kind-interface">ResourceTemplateReference</a><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#completerequestparams-argument">argument</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-symbol">\{</span> <span class="tsd-kind-property">name</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span> <span class="tsd-kind-property">value</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#completerequestparams-context">context</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-symbol">\{</span> <span class="tsd-kind-property">arguments</span><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-symbol">\{</span> <span class="tsd-signature-symbol">\[</span><span class="tsd-kind-index-signature">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <span class="tsd-signature-type">string</span> <span class="tsd-signature-symbol">}</span> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>Parameters for a <code>completion/complete</code> request.</p> </div> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="completerequestparams-_meta" data-typedoc-h="3"><span>\_meta?: \{ progressToken?: ProgressToken; \[key: string]: unknown }</span><a href="#completerequestparams-_meta" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>See <a href="/specification/2025-11-25/basic/index#meta">General fields: <code>\_meta</code></a> for notes on <code>\_meta</code> usage.</p> </div> <div class="tsd-type-declaration"> <div data-typedoc-h="4">Type Declaration</div> <ul class="tsd-parameters"> <li class="tsd-parameter-index-signature"> <div data-typedoc-h="5"><span class="tsd-signature-symbol">\[</span><span class="tsd-kind-parameter">key</span>: <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <span class="tsd-signature-type">unknown</span></div></li> <li class="tsd-parameter"> <div data-typedoc-h="5"><code class="tsd-tag">Optional</code><span class="tsd-kind-property">progressToken</span><span class="tsd-signature-symbol">?: </span><a href="#progresstoken" class="tsd-signature-type tsd-kind-type-alias">ProgressToken</a></div> <div class="tsd-comment tsd-typography"><p>If specified, the caller is requesting out-of-band progress notifications for this request (as represented by notifications/progress). The value of this parameter is an opaque token that will be attached to any subsequent notifications. The receiver is not obligated to provide these notifications.</p> </div></li></ul></div><aside class="tsd-sources"> <p>Inherited from RequestParams.\_meta</p></aside></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="completerequestparams-ref" data-typedoc-h="3"><span>ref: PromptReference | ResourceTemplateReference</span><a href="#completerequestparams-ref" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="completerequestparams-argument" data-typedoc-h="3"><span>argument: \{ name: string; value: string }</span><a href="#completerequestparams-argument" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>The argument's information</p> </div> <div class="tsd-type-declaration"> <div data-typedoc-h="4">Type Declaration</div> <ul class="tsd-parameters"> <li class="tsd-parameter"> <div data-typedoc-h="5"><span class="tsd-kind-property">name</span><span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">string</span></div> <div class="tsd-comment tsd-typography"><p>The name of the argument</p> </div></li> <li class="tsd-parameter"> <div data-typedoc-h="5"><span class="tsd-kind-property">value</span><span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">string</span></div> <div class="tsd-comment tsd-typography"><p>The value of the argument to use for completion matching.</p> </div></li></ul></div></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="completerequestparams-context" data-typedoc-h="3"><span>context?: \{ arguments?: \{ \[key: string]: string } }</span><a href="#completerequestparams-context" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>Additional, optional context for completions</p> </div> <div class="tsd-type-declaration"> <div data-typedoc-h="4">Type Declaration</div> <ul class="tsd-parameters"> <li class="tsd-parameter"> <div data-typedoc-h="5"><code class="tsd-tag">Optional</code><span class="tsd-kind-property">arguments</span><span class="tsd-signature-symbol">?: </span><span class="tsd-signature-symbol">\{</span> <span class="tsd-signature-symbol">\[</span><span class="tsd-kind-index-signature">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <span class="tsd-signature-type">string</span> <span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>Previously-resolved variables in a URI template or prompt.</p> </div></li></ul></div></section>
</div>
<div class="type">
### `CompleteResult`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">CompleteResult</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#completeresult-_meta">\_meta</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-symbol">\{</span> <span class="tsd-signature-symbol">\[</span><span class="tsd-kind-index-signature">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <span class="tsd-signature-type">unknown</span> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#completeresult-completion">completion</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-symbol">\{</span> <span class="tsd-kind-property">values</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">\[]</span><span class="tsd-signature-symbol">;</span> <span class="tsd-kind-property">total</span><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">;</span> <span class="tsd-kind-property">hasMore</span><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">boolean</span> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span><br /> <span class="tsd-signature-symbol">\[</span><span class="tsd-kind-index-signature">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <span class="tsd-signature-type">unknown</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>The server's response to a completion/complete request</p> </div> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="completeresult-_meta" data-typedoc-h="3"><span>\_meta?: \{ \[key: string]: unknown }</span><a href="#completeresult-_meta" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>See <a href="/specification/2025-11-25/basic/index#meta">General fields: <code>\_meta</code></a> for notes on <code>\_meta</code> usage.</p> </div><aside class="tsd-sources"> <p>Inherited from <a href="#result">Result</a>.<a href="#result-_meta">\_meta</a></p></aside></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="completeresult-completion" data-typedoc-h="3"><span>completion: \{ values: string\[]; total?: number; hasMore?: boolean }</span><a href="#completeresult-completion" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-type-declaration"> <div data-typedoc-h="4">Type Declaration</div> <ul class="tsd-parameters"> <li class="tsd-parameter"> <div data-typedoc-h="5"><span class="tsd-kind-property">values</span><span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">\[]</span></div> <div class="tsd-comment tsd-typography"><p>An array of completion values. Must not exceed 100 items.</p> </div></li> <li class="tsd-parameter"> <div data-typedoc-h="5"><code class="tsd-tag">Optional</code><span class="tsd-kind-property">total</span><span class="tsd-signature-symbol">?: </span><span class="tsd-signature-type">number</span></div> <div class="tsd-comment tsd-typography"><p>The total number of completion options available. This can exceed the number of values actually sent in the response.</p> </div></li> <li class="tsd-parameter"> <div data-typedoc-h="5"><code class="tsd-tag">Optional</code><span class="tsd-kind-property">hasMore</span><span class="tsd-signature-symbol">?: </span><span class="tsd-signature-type">boolean</span></div> <div class="tsd-comment tsd-typography"><p>Indicates whether there are additional completion options beyond those provided in the current response, even if the exact total is unknown.</p> </div></li></ul></div></section>
</div>
<div class="type">
### `PromptReference`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">PromptReference</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#promptreference-name">name</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#promptreference-title">title</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#promptreference-type">type</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">"ref/prompt"</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>Identifies a prompt.</p> </div> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="promptreference-name" data-typedoc-h="3"><span>name: string</span><a href="#promptreference-name" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>Intended for programmatic or logical use, but used as a display name in past specs or fallback (if title isn't present).</p> </div><aside class="tsd-sources"> <p>Inherited from BaseMetadata.name</p></aside></section> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="promptreference-title" data-typedoc-h="3"><span>title?: string</span><a href="#promptreference-title" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>Intended for UI and end-user contexts — optimized to be human-readable and easily understood,
even by those unfamiliar with domain-specific terminology.</p> <p>If not provided, the name should be used for display (except for Tool,
where <code>annotations.title</code> should be given precedence over using <code>name</code>,
if present).</p> </div><aside class="tsd-sources"> <p>Inherited from BaseMetadata.title</p></aside></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="promptreference-type" data-typedoc-h="3"><span>type: "ref/prompt"</span><a href="#promptreference-type" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section>
</div>
<div class="type">
### `ResourceTemplateReference`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">ResourceTemplateReference</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#resourcetemplatereference-type">type</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">"ref/resource"</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#resourcetemplatereference-uri">uri</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>A reference to a resource or resource template definition.</p> </div> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="resourcetemplatereference-type" data-typedoc-h="3"><span>type: "ref/resource"</span><a href="#resourcetemplatereference-type" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="resourcetemplatereference-uri" data-typedoc-h="3"><span>uri: string</span><a href="#resourcetemplatereference-uri" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>The URI or URI template of the resource.</p> </div></section>
</div>
## `elicitation/create`
<div class="type">
### `ElicitRequest`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">ElicitRequest</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#elicitrequest-jsonrpc">jsonrpc</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">"2.0"</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#elicitrequest-id">id</a><span class="tsd-signature-symbol">:</span> <a href="#requestid" class="tsd-signature-type tsd-kind-type-alias">RequestId</a><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#elicitrequest-method">method</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">"elicitation/create"</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#elicitrequest-params">params</a><span class="tsd-signature-symbol">:</span> <a href="#elicitrequestparams" class="tsd-signature-type tsd-kind-type-alias">ElicitRequestParams</a><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>A request from the server to elicit additional information from the user via the client.</p> </div> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="elicitrequest-jsonrpc" data-typedoc-h="3"><span>jsonrpc: "2.0"</span><a href="#elicitrequest-jsonrpc" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <aside class="tsd-sources"> <p>Inherited from <a href="#jsonrpcrequest">JSONRPCRequest</a>.<a href="#jsonrpcrequest-jsonrpc">jsonrpc</a></p></aside></section> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="elicitrequest-id" data-typedoc-h="3"><span>id: RequestId</span><a href="#elicitrequest-id" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <aside class="tsd-sources"> <p>Inherited from <a href="#jsonrpcrequest">JSONRPCRequest</a>.<a href="#jsonrpcrequest-id">id</a></p></aside></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="elicitrequest-method" data-typedoc-h="3"><span>method: "elicitation/create"</span><a href="#elicitrequest-method" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <aside class="tsd-sources"> <p>Overrides <a href="#jsonrpcrequest">JSONRPCRequest</a>.<a href="#jsonrpcrequest-method">method</a></p></aside></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="elicitrequest-params" data-typedoc-h="3"><span>params: ElicitRequestParams</span><a href="#elicitrequest-params" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <aside class="tsd-sources"> <p>Overrides <a href="#jsonrpcrequest">JSONRPCRequest</a>.<a href="#jsonrpcrequest-params">params</a></p></aside></section>
</div>
<div class="type">
### `ElicitRequestParams`
<div class="tsd-signature"><span class="tsd-kind-type-alias">ElicitRequestParams</span><span class="tsd-signature-symbol">:</span> <a href="#elicitrequestformparams" class="tsd-signature-type tsd-kind-interface">ElicitRequestFormParams</a> <span class="tsd-signature-symbol">|</span> <a href="#elicitrequesturlparams" class="tsd-signature-type tsd-kind-interface">ElicitRequestURLParams</a></div> <div class="tsd-comment tsd-typography"><p>The parameters for a request to elicit additional information from the user via the client.</p> </div>
</div>
<div class="type">
### `ElicitResult`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">ElicitResult</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#elicitresult-_meta">\_meta</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-symbol">\{</span> <span class="tsd-signature-symbol">\[</span><span class="tsd-kind-index-signature">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <span class="tsd-signature-type">unknown</span> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#elicitresult-action">action</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">"accept"</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"decline"</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"cancel"</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#elicitresult-content">content</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-symbol">\{</span> <span class="tsd-signature-symbol">\[</span><span class="tsd-kind-index-signature">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <span class="tsd-signature-type">string</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">number</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">boolean</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">\[]</span> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span><br /> <span class="tsd-signature-symbol">\[</span><span class="tsd-kind-index-signature">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <span class="tsd-signature-type">unknown</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>The client's response to an elicitation request.</p> </div> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="elicitresult-_meta" data-typedoc-h="3"><span>\_meta?: \{ \[key: string]: unknown }</span><a href="#elicitresult-_meta" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>See <a href="/specification/2025-11-25/basic/index#meta">General fields: <code>\_meta</code></a> for notes on <code>\_meta</code> usage.</p> </div><aside class="tsd-sources"> <p>Inherited from <a href="#result">Result</a>.<a href="#result-_meta">\_meta</a></p></aside></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="elicitresult-action" data-typedoc-h="3"><span>action: "accept" | "decline" | "cancel"</span><a href="#elicitresult-action" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>The user action in response to the elicitation.</p> <ul> <li>"accept": User submitted the form/confirmed the action</li> <li>"decline": User explicitly decline the action</li> <li>"cancel": User dismissed without making an explicit choice</li> </ul> </div></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="elicitresult-content" data-typedoc-h="3"><span>content?: \{ \[key: string]: string | number | boolean | string\[] }</span><a href="#elicitresult-content" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>The submitted form data, only present when action is "accept" and mode was "form".
Contains values matching the requested schema.
Omitted for out-of-band mode responses.</p> </div></section>
</div>
<div class="type">
### `BooleanSchema`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">BooleanSchema</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#booleanschema-type">type</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">"boolean"</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#booleanschema-title">title</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#booleanschema-description">description</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#booleanschema-default">default</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">boolean</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="booleanschema-type" data-typedoc-h="3"><span>type: "boolean"</span><a href="#booleanschema-type" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="booleanschema-title" data-typedoc-h="3"><span>title?: string</span><a href="#booleanschema-title" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="booleanschema-description" data-typedoc-h="3"><span>description?: string</span><a href="#booleanschema-description" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="booleanschema-default" data-typedoc-h="3"><span>default?: boolean</span><a href="#booleanschema-default" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section>
</div>
<div class="type">
### `ElicitRequestFormParams`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">ElicitRequestFormParams</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#elicitrequestformparams-task">task</a><span class="tsd-signature-symbol">?:</span> <a href="#taskmetadata" class="tsd-signature-type tsd-kind-interface">TaskMetadata</a><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#elicitrequestformparams-_meta">\_meta</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-symbol">\{</span> <span class="tsd-kind-property">progressToken</span><span class="tsd-signature-symbol">?:</span> <a href="#progresstoken" class="tsd-signature-type tsd-kind-type-alias">ProgressToken</a><span class="tsd-signature-symbol">;</span> <span class="tsd-signature-symbol">\[</span><span class="tsd-kind-index-signature">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <span class="tsd-signature-type">unknown</span> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#elicitrequestformparams-mode">mode</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">"form"</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#elicitrequestformparams-message">message</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#elicitrequestformparams-requestedschema">requestedSchema</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-symbol">\{</span><br /> <span class="tsd-kind-property">\$schema</span><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <span class="tsd-kind-property">type</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">"object"</span><span class="tsd-signature-symbol">;</span><br /> <span class="tsd-kind-property">properties</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-symbol">\{</span> <span class="tsd-signature-symbol">\[</span><span class="tsd-kind-index-signature">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <a href="#primitiveschemadefinition" class="tsd-signature-type tsd-kind-type-alias">PrimitiveSchemaDefinition</a> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span><br /> <span class="tsd-kind-property">required</span><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">\[]</span><span class="tsd-signature-symbol">;</span><br /> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>The parameters for a request to elicit non-sensitive information from the user via a form in the client.</p> </div> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="elicitrequestformparams-task" data-typedoc-h="3"><span>task?: TaskMetadata</span><a href="#elicitrequestformparams-task" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>If specified, the caller is requesting task-augmented execution for this request.
The request will return a CreateTaskResult immediately, and the actual result can be
retrieved later via tasks/result.</p> <p>Task augmentation is subject to capability negotiation - receivers MUST declare support
for task augmentation of specific request types in their capabilities.</p> </div><aside class="tsd-sources"> <p>Inherited from TaskAugmentedRequestParams.task</p></aside></section> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="elicitrequestformparams-_meta" data-typedoc-h="3"><span>\_meta?: \{ progressToken?: ProgressToken; \[key: string]: unknown }</span><a href="#elicitrequestformparams-_meta" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>See <a href="/specification/2025-11-25/basic/index#meta">General fields: <code>\_meta</code></a> for notes on <code>\_meta</code> usage.</p> </div> <div class="tsd-type-declaration"> <div data-typedoc-h="4">Type Declaration</div> <ul class="tsd-parameters"> <li class="tsd-parameter-index-signature"> <div data-typedoc-h="5"><span class="tsd-signature-symbol">\[</span><span class="tsd-kind-parameter">key</span>: <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <span class="tsd-signature-type">unknown</span></div></li> <li class="tsd-parameter"> <div data-typedoc-h="5"><code class="tsd-tag">Optional</code><span class="tsd-kind-property">progressToken</span><span class="tsd-signature-symbol">?: </span><a href="#progresstoken" class="tsd-signature-type tsd-kind-type-alias">ProgressToken</a></div> <div class="tsd-comment tsd-typography"><p>If specified, the caller is requesting out-of-band progress notifications for this request (as represented by notifications/progress). The value of this parameter is an opaque token that will be attached to any subsequent notifications. The receiver is not obligated to provide these notifications.</p> </div></li></ul></div><aside class="tsd-sources"> <p>Inherited from TaskAugmentedRequestParams.\_meta</p></aside></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="elicitrequestformparams-mode" data-typedoc-h="3"><span>mode?: "form"</span><a href="#elicitrequestformparams-mode" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>The elicitation mode.</p> </div></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="elicitrequestformparams-message" data-typedoc-h="3"><span>message: string</span><a href="#elicitrequestformparams-message" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>The message to present to the user describing what information is being requested.</p> </div></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="elicitrequestformparams-requestedschema" data-typedoc-h="3"><span>requestedSchema: \{ \$schema?: string; type: "object"; properties: \{ \[key: string]: PrimitiveSchemaDefinition }; required?: string\[]; }</span><a href="#elicitrequestformparams-requestedschema" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>A restricted subset of JSON Schema.
Only top-level properties are allowed, without nesting.</p> </div></section>
</div>
<div class="type">
### `ElicitRequestURLParams`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">ElicitRequestURLParams</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#elicitrequesturlparams-task">task</a><span class="tsd-signature-symbol">?:</span> <a href="#taskmetadata" class="tsd-signature-type tsd-kind-interface">TaskMetadata</a><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#elicitrequesturlparams-_meta">\_meta</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-symbol">\{</span> <span class="tsd-kind-property">progressToken</span><span class="tsd-signature-symbol">?:</span> <a href="#progresstoken" class="tsd-signature-type tsd-kind-type-alias">ProgressToken</a><span class="tsd-signature-symbol">;</span> <span class="tsd-signature-symbol">\[</span><span class="tsd-kind-index-signature">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <span class="tsd-signature-type">unknown</span> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#elicitrequesturlparams-mode">mode</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">"url"</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#elicitrequesturlparams-message">message</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#elicitrequesturlparams-elicitationid">elicitationId</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#elicitrequesturlparams-url">url</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>The parameters for a request to elicit information from the user via a URL in the client.</p> </div> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="elicitrequesturlparams-task" data-typedoc-h="3"><span>task?: TaskMetadata</span><a href="#elicitrequesturlparams-task" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>If specified, the caller is requesting task-augmented execution for this request.
The request will return a CreateTaskResult immediately, and the actual result can be
retrieved later via tasks/result.</p> <p>Task augmentation is subject to capability negotiation - receivers MUST declare support
for task augmentation of specific request types in their capabilities.</p> </div><aside class="tsd-sources"> <p>Inherited from TaskAugmentedRequestParams.task</p></aside></section> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="elicitrequesturlparams-_meta" data-typedoc-h="3"><span>\_meta?: \{ progressToken?: ProgressToken; \[key: string]: unknown }</span><a href="#elicitrequesturlparams-_meta" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>See <a href="/specification/2025-11-25/basic/index#meta">General fields: <code>\_meta</code></a> for notes on <code>\_meta</code> usage.</p> </div> <div class="tsd-type-declaration"> <div data-typedoc-h="4">Type Declaration</div> <ul class="tsd-parameters"> <li class="tsd-parameter-index-signature"> <div data-typedoc-h="5"><span class="tsd-signature-symbol">\[</span><span class="tsd-kind-parameter">key</span>: <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <span class="tsd-signature-type">unknown</span></div></li> <li class="tsd-parameter"> <div data-typedoc-h="5"><code class="tsd-tag">Optional</code><span class="tsd-kind-property">progressToken</span><span class="tsd-signature-symbol">?: </span><a href="#progresstoken" class="tsd-signature-type tsd-kind-type-alias">ProgressToken</a></div> <div class="tsd-comment tsd-typography"><p>If specified, the caller is requesting out-of-band progress notifications for this request (as represented by notifications/progress). The value of this parameter is an opaque token that will be attached to any subsequent notifications. The receiver is not obligated to provide these notifications.</p> </div></li></ul></div><aside class="tsd-sources"> <p>Inherited from TaskAugmentedRequestParams.\_meta</p></aside></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="elicitrequesturlparams-mode" data-typedoc-h="3"><span>mode: "url"</span><a href="#elicitrequesturlparams-mode" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>The elicitation mode.</p> </div></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="elicitrequesturlparams-message" data-typedoc-h="3"><span>message: string</span><a href="#elicitrequesturlparams-message" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>The message to present to the user explaining why the interaction is needed.</p> </div></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="elicitrequesturlparams-elicitationid" data-typedoc-h="3"><span>elicitationId: string</span><a href="#elicitrequesturlparams-elicitationid" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>The ID of the elicitation, which must be unique within the context of the server.
The client MUST treat this ID as an opaque value.</p> </div></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="elicitrequesturlparams-url" data-typedoc-h="3"><span>url: string</span><a href="#elicitrequesturlparams-url" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>The URL that the user should navigate to.</p> </div></section>
</div>
<div class="type">
### `EnumSchema`
<div class="tsd-signature"><span class="tsd-kind-type-alias">EnumSchema</span><span class="tsd-signature-symbol">:</span><br /> <span class="tsd-signature-symbol">|</span> <a href="#singleselectenumschema" class="tsd-signature-type tsd-kind-type-alias">SingleSelectEnumSchema</a><br /> <span class="tsd-signature-symbol">|</span> <a href="#multiselectenumschema" class="tsd-signature-type tsd-kind-type-alias">MultiSelectEnumSchema</a><br /> <span class="tsd-signature-symbol">|</span> <a href="#legacytitledenumschema" class="tsd-signature-type tsd-kind-interface">LegacyTitledEnumSchema</a></div>
</div>
<div class="type">
### `LegacyTitledEnumSchema`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">LegacyTitledEnumSchema</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#legacytitledenumschema-type">type</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">"string"</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#legacytitledenumschema-title">title</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#legacytitledenumschema-description">description</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#legacytitledenumschema-enum">enum</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">\[]</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#legacytitledenumschema-enumnames">enumNames</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">\[]</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#legacytitledenumschema-default">default</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>Use TitledSingleSelectEnumSchema instead.
This interface will be removed in a future version.</p> </div> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="legacytitledenumschema-type" data-typedoc-h="3"><span>type: "string"</span><a href="#legacytitledenumschema-type" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="legacytitledenumschema-title" data-typedoc-h="3"><span>title?: string</span><a href="#legacytitledenumschema-title" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="legacytitledenumschema-description" data-typedoc-h="3"><span>description?: string</span><a href="#legacytitledenumschema-description" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="legacytitledenumschema-enum" data-typedoc-h="3"><span>enum: string\[]</span><a href="#legacytitledenumschema-enum" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="legacytitledenumschema-enumnames" data-typedoc-h="3"><span>enumNames?: string\[]</span><a href="#legacytitledenumschema-enumnames" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>(Legacy) Display names for enum values.
Non-standard according to JSON schema 2020-12.</p> </div></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="legacytitledenumschema-default" data-typedoc-h="3"><span>default?: string</span><a href="#legacytitledenumschema-default" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section>
</div>
<div class="type">
### `MultiSelectEnumSchema`
<div class="tsd-signature"><span class="tsd-kind-type-alias">MultiSelectEnumSchema</span><span class="tsd-signature-symbol">:</span><br /> <span class="tsd-signature-symbol">|</span> <a href="#untitledmultiselectenumschema" class="tsd-signature-type tsd-kind-interface">UntitledMultiSelectEnumSchema</a><br /> <span class="tsd-signature-symbol">|</span> <a href="#titledmultiselectenumschema" class="tsd-signature-type tsd-kind-interface">TitledMultiSelectEnumSchema</a></div>
</div>
<div class="type">
### `NumberSchema`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">NumberSchema</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#numberschema-type">type</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">"number"</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"integer"</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#numberschema-title">title</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#numberschema-description">description</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#numberschema-minimum">minimum</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#numberschema-maximum">maximum</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#numberschema-default">default</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="numberschema-type" data-typedoc-h="3"><span>type: "number" | "integer"</span><a href="#numberschema-type" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="numberschema-title" data-typedoc-h="3"><span>title?: string</span><a href="#numberschema-title" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="numberschema-description" data-typedoc-h="3"><span>description?: string</span><a href="#numberschema-description" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="numberschema-minimum" data-typedoc-h="3"><span>minimum?: number</span><a href="#numberschema-minimum" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="numberschema-maximum" data-typedoc-h="3"><span>maximum?: number</span><a href="#numberschema-maximum" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="numberschema-default" data-typedoc-h="3"><span>default?: number</span><a href="#numberschema-default" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section>
</div>
<div class="type">
### `PrimitiveSchemaDefinition`
<div class="tsd-signature"><span class="tsd-kind-type-alias">PrimitiveSchemaDefinition</span><span class="tsd-signature-symbol">:</span><br /> <span class="tsd-signature-symbol">|</span> <a href="#stringschema" class="tsd-signature-type tsd-kind-interface">StringSchema</a><br /> <span class="tsd-signature-symbol">|</span> <a href="#numberschema" class="tsd-signature-type tsd-kind-interface">NumberSchema</a><br /> <span class="tsd-signature-symbol">|</span> <a href="#booleanschema" class="tsd-signature-type tsd-kind-interface">BooleanSchema</a><br /> <span class="tsd-signature-symbol">|</span> <a href="#enumschema" class="tsd-signature-type tsd-kind-type-alias">EnumSchema</a></div> <div class="tsd-comment tsd-typography"><p>Restricted schema definitions that only allow primitive types
without nested objects or arrays.</p> </div>
</div>
<div class="type">
### `SingleSelectEnumSchema`
<div class="tsd-signature"><span class="tsd-kind-type-alias">SingleSelectEnumSchema</span><span class="tsd-signature-symbol">:</span><br /> <span class="tsd-signature-symbol">|</span> <a href="#untitledsingleselectenumschema" class="tsd-signature-type tsd-kind-interface">UntitledSingleSelectEnumSchema</a><br /> <span class="tsd-signature-symbol">|</span> <a href="#titledsingleselectenumschema" class="tsd-signature-type tsd-kind-interface">TitledSingleSelectEnumSchema</a></div>
</div>
<div class="type">
### `StringSchema`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">StringSchema</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#stringschema-type">type</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">"string"</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#stringschema-title">title</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#stringschema-description">description</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#stringschema-minlength">minLength</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#stringschema-maxlength">maxLength</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#stringschema-format">format</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">"uri"</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"email"</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"date"</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"date-time"</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#stringschema-default">default</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="stringschema-type" data-typedoc-h="3"><span>type: "string"</span><a href="#stringschema-type" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="stringschema-title" data-typedoc-h="3"><span>title?: string</span><a href="#stringschema-title" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="stringschema-description" data-typedoc-h="3"><span>description?: string</span><a href="#stringschema-description" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="stringschema-minlength" data-typedoc-h="3"><span>minLength?: number</span><a href="#stringschema-minlength" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="stringschema-maxlength" data-typedoc-h="3"><span>maxLength?: number</span><a href="#stringschema-maxlength" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="stringschema-format" data-typedoc-h="3"><span>format?: "uri" | "email" | "date" | "date-time"</span><a href="#stringschema-format" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="stringschema-default" data-typedoc-h="3"><span>default?: string</span><a href="#stringschema-default" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section>
</div>
<div class="type">
### `TitledMultiSelectEnumSchema`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">TitledMultiSelectEnumSchema</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#titledmultiselectenumschema-type">type</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">"array"</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#titledmultiselectenumschema-title">title</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#titledmultiselectenumschema-description">description</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#titledmultiselectenumschema-minitems">minItems</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#titledmultiselectenumschema-maxitems">maxItems</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#titledmultiselectenumschema-items">items</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-symbol">\{</span> <span class="tsd-kind-property">anyOf</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-symbol">\{</span> <span class="tsd-kind-property">const</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span> <span class="tsd-kind-property">title</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">\[]</span> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#titledmultiselectenumschema-default">default</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">\[]</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>Schema for multiple-selection enumeration with display titles for each option.</p> </div> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="titledmultiselectenumschema-type" data-typedoc-h="3"><span>type: "array"</span><a href="#titledmultiselectenumschema-type" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="titledmultiselectenumschema-title" data-typedoc-h="3"><span>title?: string</span><a href="#titledmultiselectenumschema-title" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>Optional title for the enum field.</p> </div></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="titledmultiselectenumschema-description" data-typedoc-h="3"><span>description?: string</span><a href="#titledmultiselectenumschema-description" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>Optional description for the enum field.</p> </div></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="titledmultiselectenumschema-minitems" data-typedoc-h="3"><span>minItems?: number</span><a href="#titledmultiselectenumschema-minitems" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>Minimum number of items to select.</p> </div></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="titledmultiselectenumschema-maxitems" data-typedoc-h="3"><span>maxItems?: number</span><a href="#titledmultiselectenumschema-maxitems" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>Maximum number of items to select.</p> </div></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="titledmultiselectenumschema-items" data-typedoc-h="3"><span>items: \{ anyOf: \{ const: string; title: string }\[] }</span><a href="#titledmultiselectenumschema-items" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>Schema for array items with enum options and display labels.</p> </div> <div class="tsd-type-declaration"> <div data-typedoc-h="4">Type Declaration</div> <ul class="tsd-parameters"> <li class="tsd-parameter"> <div data-typedoc-h="5"><span class="tsd-kind-property">anyOf</span><span class="tsd-signature-symbol">: </span><span class="tsd-signature-symbol">\{</span> <span class="tsd-kind-property">const</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span> <span class="tsd-kind-property">title</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">\[]</span></div> <div class="tsd-comment tsd-typography"><p>Array of enum options with values and display labels.</p> </div></li></ul></div></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="titledmultiselectenumschema-default" data-typedoc-h="3"><span>default?: string\[]</span><a href="#titledmultiselectenumschema-default" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>Optional default value.</p> </div></section>
</div>
Cut at 300 lines. The page has the rest.
specification/2025-11-25/server/index New page · 29 lines, new page
# Overview
A whole new page. There's nothing to diff it against, so here is what it says.
# Overview
Servers provide the fundamental building blocks for adding context to language models via
MCP. These primitives enable rich interactions between clients, servers, and language
models:
* **Prompts**: Pre-defined templates or instructions that guide language model
interactions
* **Resources**: Structured data or content that provides additional context to the model
* **Tools**: Executable functions that allow models to perform actions or retrieve
information
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 |
Explore these key primitives in more detail below:
<CardGroup cols={3}>
<Card title="Prompts" icon="message" href="/specification/2025-11-25/server/prompts" />
<Card title="Resources" icon="file-lines" href="/specification/2025-11-25/server/resources" />
<Card title="Tools" icon="wrench" href="/specification/2025-11-25/server/tools" />
</CardGroup>
specification/2025-11-25/server/prompts New page · 284 lines, new page
# Prompts ## User Interaction Model ## Capabilities ## Protocol Messages ### Listing Prompts ### Getting a Prompt ### List Changed Notification ## Message Flow ## Data Types ### Prompt ### PromptMessage #### Text Content #### Image Content #### Audio Content #### Embedded Resources ## Error Handling ## Implementation Considerations ## Security
A whole new page. There's nothing to diff it against, so here is what it says.
# Prompts
<div id="enable-section-numbers" />
The Model Context Protocol (MCP) provides a standardized way for servers to expose prompt
templates to clients. Prompts allow servers to provide structured messages and
instructions for interacting with language models. Clients can discover available
prompts, retrieve their contents, and provide arguments to customize them.
## User Interaction Model
Prompts are designed to be **user-controlled**, meaning they are exposed from servers to
clients with the intention of the user being able to explicitly select them for use.
Typically, prompts would be triggered through user-initiated commands in the user
interface, which allows users to naturally discover and invoke available prompts.
For example, as slash commands:
<img src="https://mintcdn.com/mcp/uzELntid9uQ-QMAr/specification/2025-11-25/server/slash-command.png?fit=max&auto=format&n=uzELntid9uQ-QMAr&q=85&s=965e4fa2273b376721d6f26c396c69c5" alt="Example of prompt exposed as slash command" width="293" height="106" data-path="specification/2025-11-25/server/slash-command.png" />
However, implementors are free to expose prompts through any interface pattern that suits
their needs—the protocol itself does not mandate any specific user interaction
model.
## Capabilities
Servers that support prompts **MUST** declare the `prompts` capability during
[initialization](/specification/2025-11-25/basic/lifecycle#initialization):
```json theme={null}
{
"capabilities": {
"prompts": {
"listChanged": true
}
}
}
```
`listChanged` indicates whether the server will emit notifications when the list of
available prompts changes.
## Protocol Messages
### Listing Prompts
To retrieve available prompts, clients send a `prompts/list` request. This operation
supports [pagination](/specification/2025-11-25/server/utilities/pagination).
**Request:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"method": "prompts/list",
"params": {
"cursor": "optional-cursor-value"
}
}
```
**Response:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"prompts": [
{
"name": "code_review",
"title": "Request Code Review",
"description": "Asks the LLM to analyze code quality and suggest improvements",
"arguments": [
{
"name": "code",
"description": "The code to review",
"required": true
}
],
"icons": [
{
"src": "https://example.com/review-icon.svg",
"mimeType": "image/svg+xml",
"sizes": ["any"]
}
]
}
],
"nextCursor": "next-page-cursor"
}
}
```
### Getting a Prompt
To retrieve a specific prompt, clients send a `prompts/get` request. Arguments may be
auto-completed through [the completion API](/specification/2025-11-25/server/utilities/completion).
**Request:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 2,
"method": "prompts/get",
"params": {
"name": "code_review",
"arguments": {
"code": "def hello():\n print('world')"
}
}
}
```
**Response:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"description": "Code review prompt",
"messages": [
{
"role": "user",
"content": {
"type": "text",
"text": "Please review this Python code:\ndef hello():\n print('world')"
}
}
]
}
}
```
### List Changed Notification
When the list of available prompts changes, servers that declared the `listChanged`
capability **SHOULD** send a notification:
```json theme={null}
{
"jsonrpc": "2.0",
"method": "notifications/prompts/list_changed"
}
```
## Message Flow
```mermaid theme={null}
sequenceDiagram
participant Client
participant Server
Note over Client,Server: Discovery
Client->>Server: prompts/list
Server-->>Client: List of prompts
Note over Client,Server: Usage
Client->>Server: prompts/get
Server-->>Client: Prompt content
opt listChanged
Note over Client,Server: Changes
Server--)Client: prompts/list_changed
Client->>Server: prompts/list
Server-->>Client: Updated prompts
end
```
## Data Types
### Prompt
A prompt definition includes:
* `name`: Unique identifier for the prompt
* `title`: Optional human-readable name of the prompt for display purposes.
* `description`: Optional human-readable description
* `icons`: Optional array of icons for display in user interfaces
* `arguments`: Optional list of arguments for customization
### PromptMessage
Messages in a prompt can contain:
* `role`: Either "user" or "assistant" to indicate the speaker
* `content`: One of the following content types:
<Note>
All content types in prompt messages support optional
[annotations](./resources#annotations) for metadata about audience, priority,
and modification times.
</Note>
#### Text Content
Text content represents plain text messages:
```json theme={null}
{
"type": "text",
"text": "The text content of the message"
}
```
This is the most common content type used for natural language interactions.
#### Image Content
Image content allows including visual information in messages:
```json theme={null}
{
"type": "image",
"data": "base64-encoded-image-data",
"mimeType": "image/png"
}
```
The image data **MUST** be base64-encoded and include a valid MIME type. This enables
multi-modal interactions where visual context is important.
#### Audio Content
Audio content allows including audio information in messages:
```json theme={null}
{
"type": "audio",
"data": "base64-encoded-audio-data",
"mimeType": "audio/wav"
}
```
The audio data MUST be base64-encoded and include a valid MIME type. This enables
multi-modal interactions where audio context is important.
#### Embedded Resources
Embedded resources allow referencing server-side resources directly in messages:
```json theme={null}
{
"type": "resource",
"resource": {
"uri": "resource://example",
"mimeType": "text/plain",
"text": "Resource content"
}
}
```
Resources can contain either text or binary (blob) data and **MUST** include:
* A valid resource URI
* The appropriate MIME type
* Either text content or base64-encoded blob data
Embedded resources enable prompts to seamlessly incorporate server-managed content like
documentation, code samples, or other reference materials directly into the conversation
flow.
## Error Handling
Servers **SHOULD** return standard JSON-RPC errors for common failure cases:
* Invalid prompt name: `-32602` (Invalid params)
* Missing required arguments: `-32602` (Invalid params)
* Internal errors: `-32603` (Internal error)
## Implementation Considerations
1. Servers **SHOULD** validate prompt arguments before processing
2. Clients **SHOULD** handle pagination for large prompt lists
3. Both parties **SHOULD** respect capability negotiation
## Security
Implementations **MUST** carefully validate all prompt inputs and outputs to prevent
injection attacks or unauthorized access to resources.
specification/2025-11-25/server/resources New page · 410 lines, new page
# Resources ## User Interaction Model ## Capabilities ## Protocol Messages ### Listing Resources ### Reading Resources ### Resource Templates ### List Changed Notification ### Subscriptions ## Message Flow ## Data Types ### Resource ### Resource Contents #### Text Content #### Binary Content ### Annotations ## Common URI Schemes ### https\:// ### file:// ### git:// ### Custom URI Schemes ## Error Handling ## Security Considerations
A whole new page. There's nothing to diff it against, so here is what it says.
# Resources
<div id="enable-section-numbers" />
The Model Context Protocol (MCP) provides a standardized way for servers to expose
resources to clients. Resources allow servers to share data that provides context to
language models, such as files, database schemas, or application-specific information.
Each resource is uniquely identified by a
[URI](https://datatracker.ietf.org/doc/html/rfc3986).
## User Interaction Model
Resources in MCP are designed to be **application-driven**, with host applications
determining how to incorporate context based on their needs.
For example, applications could:
* Expose resources through UI elements for explicit selection, in a tree or list view
* Allow the user to search through and filter available resources
* Implement automatic context inclusion, based on heuristics or the AI model's selection
<img src="https://mintcdn.com/mcp/uzELntid9uQ-QMAr/specification/2025-11-25/server/resource-picker.png?fit=max&auto=format&n=uzELntid9uQ-QMAr&q=85&s=bc7bc3db17d447a69809689e5888a3ab" alt="Example of resource context picker" width="174" height="181" data-path="specification/2025-11-25/server/resource-picker.png" />
However, implementations are free to expose resources through any interface pattern that
suits their needs—the protocol itself does not mandate any specific user
interaction model.
## Capabilities
Servers that support resources **MUST** declare the `resources` capability:
```json theme={null}
{
"capabilities": {
"resources": {
"subscribe": true,
"listChanged": true
}
}
}
```
The capability supports two optional features:
* `subscribe`: whether the client can subscribe to be notified of changes to individual
resources.
* `listChanged`: whether the server will emit notifications when the list of available
resources changes.
Both `subscribe` and `listChanged` are optional—servers can support neither,
either, or both:
```json theme={null}
{
"capabilities": {
"resources": {} // Neither feature supported
}
}
```
```json theme={null}
{
"capabilities": {
"resources": {
"subscribe": true // Only subscriptions supported
}
}
}
```
```json theme={null}
{
"capabilities": {
"resources": {
"listChanged": true // Only list change notifications supported
}
}
}
```
## Protocol Messages
### Listing Resources
To discover available resources, clients send a `resources/list` request. This operation
supports [pagination](/specification/2025-11-25/server/utilities/pagination).
**Request:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"method": "resources/list",
"params": {
"cursor": "optional-cursor-value"
}
}
```
**Response:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"resources": [
{
"uri": "file:///project/src/main.rs",
"name": "main.rs",
"title": "Rust Software Application Main File",
"description": "Primary application entry point",
"mimeType": "text/x-rust",
"icons": [
{
"src": "https://example.com/rust-file-icon.png",
"mimeType": "image/png",
"sizes": ["48x48"]
}
]
}
],
"nextCursor": "next-page-cursor"
}
}
```
### Reading Resources
To retrieve resource contents, clients send a `resources/read` request:
**Request:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 2,
"method": "resources/read",
"params": {
"uri": "file:///project/src/main.rs"
}
}
```
**Response:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"contents": [
{
"uri": "file:///project/src/main.rs",
"mimeType": "text/x-rust",
"text": "fn main() {\n println!(\"Hello world!\");\n}"
}
]
}
}
```
### Resource Templates
Resource templates allow servers to expose parameterized resources using
[URI templates](https://datatracker.ietf.org/doc/html/rfc6570). Arguments may be
auto-completed through [the completion API](/specification/2025-11-25/server/utilities/completion).
**Request:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 3,
"method": "resources/templates/list"
}
```
**Response:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 3,
"result": {
"resourceTemplates": [
{
"uriTemplate": "file:///{path}",
"name": "Project Files",
"title": "📁 Project Files",
"description": "Access files in the project directory",
"mimeType": "application/octet-stream",
"icons": [
{
"src": "https://example.com/folder-icon.png",
"mimeType": "image/png",
"sizes": ["48x48"]
}
]
}
]
}
}
```
### List Changed Notification
When the list of available resources changes, servers that declared the `listChanged`
capability **SHOULD** send a notification:
```json theme={null}
{
"jsonrpc": "2.0",
"method": "notifications/resources/list_changed"
}
```
### Subscriptions
The protocol supports optional subscriptions to resource changes. Clients can subscribe
to specific resources and receive notifications when they change:
**Subscribe Request:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 4,
"method": "resources/subscribe",
"params": {
"uri": "file:///project/src/main.rs"
}
}
```
**Update Notification:**
```json theme={null}
{
"jsonrpc": "2.0",
"method": "notifications/resources/updated",
"params": {
"uri": "file:///project/src/main.rs"
}
}
```
## Message Flow
```mermaid theme={null}
sequenceDiagram
participant Client
participant Server
Note over Client,Server: Resource Discovery
Client->>Server: resources/list
Server-->>Client: List of resources
Note over Client,Server: Resource Template Discovery
Client->>Server: resources/templates/list
Server-->>Client: List of resource templates
Note over Client,Server: Resource Access
Client->>Server: resources/read
Server-->>Client: Resource contents
Note over Client,Server: Subscriptions
Client->>Server: resources/subscribe
Server-->>Client: Subscription confirmed
Note over Client,Server: Updates
Server--)Client: notifications/resources/updated
Client->>Server: resources/read
Server-->>Client: Updated contents
```
## Data Types
### Resource
A resource definition includes:
* `uri`: Unique identifier for the resource
* `name`: The name of the resource.
* `title`: Optional human-readable name of the resource for display purposes.
* `description`: Optional description
* `icons`: Optional array of icons for display in user interfaces
* `mimeType`: Optional MIME type
* `size`: Optional size in bytes
### Resource Contents
Resources can contain either text or binary data:
#### Text Content
```json theme={null}
{
"uri": "file:///example.txt",
Cut at 300 lines. The page has the rest.
specification/2025-11-25/server/tools New page · 518 lines, new page
# Tools ## User Interaction Model ## Capabilities ## Protocol Messages ### Listing Tools ### Calling Tools ### List Changed Notification ## Message Flow ## Data Types ### Tool #### Tool Names ### Tool Result #### Text Content #### Image Content #### Audio Content #### Resource Links #### Embedded Resources #### Structured Content #### Output Schema ### Schema Examples #### Tool with default 2020-12 schema: #### Tool with explicit draft-07 schema: #### Tool with no parameters: ## Error Handling ## Security Considerations
A whole new page. There's nothing to diff it against, so here is what it says.
# Tools
<div id="enable-section-numbers" />
The Model Context Protocol (MCP) allows servers to expose tools that can be invoked by
language models. Tools enable models to interact with external systems, such as querying
databases, calling APIs, or performing computations. Each tool is uniquely identified by
a name and includes metadata describing its schema.
## User Interaction Model
Tools in MCP are designed to be **model-controlled**, meaning that the language model can
discover and invoke tools automatically based on its contextual understanding and the
user's prompts.
However, implementations are free to expose tools through any interface pattern that
suits their needs—the protocol itself does not mandate any specific user
interaction model.
<Warning>
For trust & safety and security, there **SHOULD** always
be a human in the loop with the ability to deny tool invocations.
Applications **SHOULD**:
* Provide UI that makes clear which tools are being exposed to the AI model
* Insert clear visual indicators when tools are invoked
* Present confirmation prompts to the user for operations, to ensure a human is in the
loop
</Warning>
## Capabilities
Servers that support tools **MUST** declare the `tools` capability:
```json theme={null}
{
"capabilities": {
"tools": {
"listChanged": true
}
}
}
```
`listChanged` indicates whether the server will emit notifications when the list of
available tools changes.
## Protocol Messages
### Listing Tools
To discover available tools, clients send a `tools/list` request. This operation supports
[pagination](/specification/2025-11-25/server/utilities/pagination).
**Request:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list",
"params": {
"cursor": "optional-cursor-value"
}
}
```
**Response:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"tools": [
{
"name": "get_weather",
"title": "Weather Information Provider",
"description": "Get current weather information for a location",
"inputSchema": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "City name or zip code"
}
},
"required": ["location"]
},
"icons": [
{
"src": "https://example.com/weather-icon.png",
"mimeType": "image/png",
"sizes": ["48x48"]
}
],
"execution": {
"taskSupport": "optional"
}
}
],
"nextCursor": "next-page-cursor"
}
}
```
### Calling Tools
To invoke a tool, clients send a `tools/call` request:
**Request:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "get_weather",
"arguments": {
"location": "New York"
}
}
}
```
**Response:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"content": [
{
"type": "text",
"text": "Current weather in New York:\nTemperature: 72°F\nConditions: Partly cloudy"
}
],
"isError": false
}
}
```
### List Changed Notification
When the list of available tools changes, servers that declared the `listChanged`
capability **SHOULD** send a notification:
```json theme={null}
{
"jsonrpc": "2.0",
"method": "notifications/tools/list_changed"
}
```
## Message Flow
```mermaid theme={null}
sequenceDiagram
participant LLM
participant Client
participant Server
Note over Client,Server: Discovery
Client->>Server: tools/list
Server-->>Client: List of tools
Note over Client,LLM: Tool Selection
LLM->>Client: Select tool to use
Note over Client,Server: Invocation
Client->>Server: tools/call
Server-->>Client: Tool result
Client->>LLM: Process result
Note over Client,Server: Updates
Server--)Client: tools/list_changed
Client->>Server: tools/list
Server-->>Client: Updated tools
```
## Data Types
### Tool
A tool definition includes:
* `name`: Unique identifier for the tool
* `title`: Optional human-readable name of the tool for display purposes.
* `description`: Human-readable description of functionality
* `icons`: Optional array of icons for display in user interfaces
* `inputSchema`: JSON Schema defining expected parameters
* Follows the [JSON Schema usage guidelines](/specification/2025-11-25/basic#json-schema-usage)
* Defaults to 2020-12 if no `$schema` field is present
* **MUST** be a valid JSON Schema object (not `null`)
* For tools with no parameters, use one of these valid approaches:
* `{ "type": "object", "additionalProperties": false }` - **Recommended**: explicitly accepts only empty objects
* `{ "type": "object" }` - accepts any object (including with properties)
* `outputSchema`: Optional JSON Schema defining expected output structure
* Follows the [JSON Schema usage guidelines](/specification/2025-11-25/basic#json-schema-usage)
* Defaults to 2020-12 if no `$schema` field is present
* `annotations`: Optional properties describing tool behavior
* `execution`: Optional object describing execution-related properties
* `taskSupport`: Indicates whether this tool supports [task-augmented execution](/specification/2025-11-25/basic/utilities/tasks#tool-level-negotiation). Values: `"forbidden"` (default), `"optional"`, or `"required"`
<Warning>
For trust & safety and security, clients **MUST** consider tool annotations to
be untrusted unless they come from trusted servers.
</Warning>
#### Tool Names
* Tool names **SHOULD** be between 1 and 128 characters in length (inclusive).
* Tool names **SHOULD** be considered case-sensitive.
* The following **SHOULD** be the only allowed characters: uppercase and lowercase ASCII letters (A-Z, a-z), digits
(0-9), underscore (\_), hyphen (-), and dot (.)
* Tool names **SHOULD NOT** contain spaces, commas, or other special characters.
* Tool names **SHOULD** be unique within a server.
* Example valid tool names:
* getUser
* DATA\_EXPORT\_v2
* admin.tools.list
### Tool Result
Tool results may contain [**structured**](#structured-content) or **unstructured** content.
**Unstructured** content is returned in the `content` field of a result, and can contain multiple content items of different types:
<Note>
All content types (text, image, audio, resource links, and embedded resources)
support optional
[annotations](/specification/2025-11-25/server/resources#annotations) that
provide metadata about audience, priority, and modification times. This is the
same annotation format used by resources and prompts.
</Note>
#### Text Content
```json theme={null}
{
"type": "text",
"text": "Tool result text"
}
```
#### Image Content
```json theme={null}
{
"type": "image",
"data": "base64-encoded-data",
"mimeType": "image/png",
"annotations": {
"audience": ["user"],
"priority": 0.9
}
}
```
#### Audio Content
```json theme={null}
{
"type": "audio",
"data": "base64-encoded-audio-data",
"mimeType": "audio/wav"
}
```
#### Resource Links
A tool **MAY** return links to [Resources](/specification/2025-11-25/server/resources), to provide additional context
or data. In this case, the tool will return a URI that can be subscribed to or fetched by the client:
```json theme={null}
{
"type": "resource_link",
"uri": "file:///project/src/main.rs",
"name": "main.rs",
"description": "Primary application entry point",
"mimeType": "text/x-rust"
}
```
Resource links support the same [Resource annotations](/specification/2025-11-25/server/resources#annotations) as regular resources to help clients understand how to use them.
<Info>
Resource links returned by tools are not guaranteed to appear in the results
of a `resources/list` request.
</Info>
#### Embedded Resources
[Resources](/specification/2025-11-25/server/resources) **MAY** be embedded to provide additional context
or data using a suitable [URI scheme](./resources#common-uri-schemes). Servers that use embedded resources **SHOULD** implement the `resources` capability:
```json theme={null}
Cut at 300 lines. The page has the rest.
specification/2025-11-25/server/utilities/completion New page · 200 lines, new page
# Completion ## User Interaction Model ## Capabilities ## Protocol Messages ### Requesting Completions ### Reference Types ### Completion Results ## Message Flow ## Data Types ### CompleteRequest ### CompleteResult ## Error Handling ## Implementation Considerations ## Security
A whole new page. There's nothing to diff it against, so here is what it says.
# Completion
<div id="enable-section-numbers" />
The Model Context Protocol (MCP) provides a standardized way for servers to offer
autocompletion suggestions for the arguments of prompts and resource templates. When
users are filling in argument values for a specific prompt (identified by name) or
resource template (identified by URI), servers can provide contextual suggestions.
## User Interaction Model
Completion in MCP is designed to support interactive user experiences similar to IDE code
completion.
For example, applications may show completion suggestions in a dropdown or popup menu as
users type, with the ability to filter and select from available options.
However, implementations are free to expose completion through any interface pattern that
suits their needs—the protocol itself does not mandate any specific user
interaction model.
## Capabilities
Servers that support completions **MUST** declare the `completions` capability:
```json theme={null}
{
"capabilities": {
"completions": {}
}
}
```
## Protocol Messages
### Requesting Completions
To get completion suggestions, clients send a `completion/complete` request specifying
what is being completed through a reference type:
**Request:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"method": "completion/complete",
"params": {
"ref": {
"type": "ref/prompt",
"name": "code_review"
},
"argument": {
"name": "language",
"value": "py"
}
}
}
```
**Response:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"completion": {
"values": ["python", "pytorch", "pyside"],
"total": 10,
"hasMore": true
}
}
}
```
For prompts or URI templates with multiple arguments, clients should include previous completions in the `context.arguments` object to provide context for subsequent requests.
**Request:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"method": "completion/complete",
"params": {
"ref": {
"type": "ref/prompt",
"name": "code_review"
},
"argument": {
"name": "framework",
"value": "fla"
},
"context": {
"arguments": {
"language": "python"
}
}
}
}
```
**Response:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"completion": {
"values": ["flask"],
"total": 1,
"hasMore": false
}
}
}
```
### Reference Types
The protocol supports two types of completion references:
| Type | Description | Example |
| -------------- | --------------------------- | --------------------------------------------------- |
| `ref/prompt` | References a prompt by name | `{"type": "ref/prompt", "name": "code_review"}` |
| `ref/resource` | References a resource URI | `{"type": "ref/resource", "uri": "file:///{path}"}` |
### Completion Results
Servers return an array of completion values ranked by relevance, with:
* Maximum 100 items per response
* Optional total number of available matches
* Boolean indicating if additional results exist
## Message Flow
```mermaid theme={null}
sequenceDiagram
participant Client
participant Server
Note over Client: User types argument
Client->>Server: completion/complete
Server-->>Client: Completion suggestions
Note over Client: User continues typing
Client->>Server: completion/complete
Server-->>Client: Refined suggestions
```
## Data Types
### CompleteRequest
* `ref`: A `PromptReference` or `ResourceReference`
* `argument`: Object containing:
* `name`: Argument name
* `value`: Current value
* `context`: Object containing:
* `arguments`: A mapping of already-resolved argument names to their values.
### CompleteResult
* `completion`: Object containing:
* `values`: Array of suggestions (max 100)
* `total`: Optional total matches
* `hasMore`: Additional results flag
## Error Handling
Servers **SHOULD** return standard JSON-RPC errors for common failure cases:
* Method not found: `-32601` (Capability not supported)
* Invalid prompt name: `-32602` (Invalid params)
* Missing required arguments: `-32602` (Invalid params)
* Internal errors: `-32603` (Internal error)
## Implementation Considerations
1. Servers **SHOULD**:
* Return suggestions sorted by relevance
* Implement fuzzy matching where appropriate
* Rate limit completion requests
* Validate all inputs
2. Clients **SHOULD**:
* Debounce rapid completion requests
* Cache completion results where appropriate
* Handle missing or partial results gracefully
## Security
Implementations **MUST**:
* Validate all completion inputs
* Implement appropriate rate limiting
* Control access to sensitive suggestions
* Prevent completion-based information disclosure
specification/2025-11-25/server/utilities/logging New page · 138 lines, new page
# Logging ## User Interaction Model ## Capabilities ## Log Levels ## Protocol Messages ### Setting Log Level ### Log Message Notifications ## Message Flow ## Error Handling ## Implementation Considerations ## Security
A whole new page. There's nothing to diff it against, so here is what it says.
# Logging
<div id="enable-section-numbers" />
The Model Context Protocol (MCP) provides a standardized way for servers to send
structured log messages to clients. Clients can control logging verbosity by setting
minimum log levels, with servers sending notifications containing severity levels,
optional logger names, and arbitrary JSON-serializable data.
## User Interaction Model
Implementations are free to expose logging through any interface pattern that suits their
needs—the protocol itself does not mandate any specific user interaction model.
## Capabilities
Servers that emit log message notifications **MUST** declare the `logging` capability:
```json theme={null}
{
"capabilities": {
"logging": {}
}
}
```
## Log Levels
The protocol follows the standard syslog severity levels specified in
[RFC 5424](https://datatracker.ietf.org/doc/html/rfc5424#section-6.2.1):
| Level | Description | Example Use Case |
| --------- | -------------------------------- | -------------------------- |
| debug | Detailed debugging information | Function entry/exit points |
| info | General informational messages | Operation progress updates |
| notice | Normal but significant events | Configuration changes |
| warning | Warning conditions | Deprecated feature usage |
| error | Error conditions | Operation failures |
| critical | Critical conditions | System component failures |
| alert | Action must be taken immediately | Data corruption detected |
| emergency | System is unusable | Complete system failure |
## Protocol Messages
### Setting Log Level
To configure the minimum log level, clients **MAY** send a `logging/setLevel` request:
**Request:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"method": "logging/setLevel",
"params": {
"level": "info"
}
}
```
### Log Message Notifications
Servers send log messages using `notifications/message` notifications:
```json theme={null}
{
"jsonrpc": "2.0",
"method": "notifications/message",
"params": {
"level": "error",
"logger": "database",
"data": {
"error": "Connection failed",
"details": {
"host": "localhost",
"port": 5432
}
}
}
}
```
## Message Flow
```mermaid theme={null}
sequenceDiagram
participant Client
participant Server
Note over Client,Server: Configure Logging
Client->>Server: logging/setLevel (info)
Server-->>Client: Empty Result
Note over Client,Server: Server Activity
Server--)Client: notifications/message (info)
Server--)Client: notifications/message (warning)
Server--)Client: notifications/message (error)
Note over Client,Server: Level Change
Client->>Server: logging/setLevel (error)
Server-->>Client: Empty Result
Note over Server: Only sends error level<br/>and above
```
## Error Handling
Servers **SHOULD** return standard JSON-RPC errors for common failure cases:
* Invalid log level: `-32602` (Invalid params)
* Configuration errors: `-32603` (Internal error)
## Implementation Considerations
1. Servers **SHOULD**:
* Rate limit log messages
* Include relevant context in data field
* Use consistent logger names
* Remove sensitive information
2. Clients **MAY**:
* Present log messages in the UI
* Implement log filtering/search
* Display severity visually
* Persist log messages
## Security
1. Log messages **MUST NOT** contain:
* Credentials or secrets
* Personal identifying information
* Internal system details that could aid attacks
2. Implementations **SHOULD**:
* Rate limit messages
* Validate all data fields
* Control log access
* Monitor for sensitive content
specification/2025-11-25/server/utilities/pagination New page · 95 lines, new page
# Pagination ## Pagination Model ## Response Format ## Request Format ## Pagination Flow ## Operations Supporting Pagination ## Implementation Guidelines ## Error Handling
A whole new page. There's nothing to diff it against, so here is what it says.
# Pagination
<div id="enable-section-numbers" />
The Model Context Protocol (MCP) supports paginating list operations that may return
large result sets. Pagination allows servers to yield results in smaller chunks rather
than all at once.
Pagination is especially important when connecting to external services over the
internet, but also useful for local integrations to avoid performance issues with large
data sets.
## Pagination Model
Pagination in MCP uses an opaque cursor-based approach, instead of numbered pages.
* The **cursor** is an opaque string token, representing a position in the result set
* **Page size** is determined by the server, and clients **MUST NOT** assume a fixed page
size
## Response Format
Pagination starts when the server sends a **response** that includes:
* The current page of results
* An optional `nextCursor` field if more results exist
```json theme={null}
{
"jsonrpc": "2.0",
"id": "123",
"result": {
"resources": [...],
"nextCursor": "eyJwYWdlIjogM30="
}
}
```
## Request Format
After receiving a cursor, the client can *continue* paginating by issuing a request
including that cursor:
```json theme={null}
{
"jsonrpc": "2.0",
"id": "124",
"method": "resources/list",
"params": {
"cursor": "eyJwYWdlIjogMn0="
}
}
```
## Pagination Flow
```mermaid theme={null}
sequenceDiagram
participant Client
participant Server
Client->>Server: List Request (no cursor)
loop Pagination Loop
Server-->>Client: Page of results + nextCursor
Client->>Server: List Request (with cursor)
end
```
## Operations Supporting Pagination
The following MCP operations support pagination:
* `resources/list` - List available resources
* `resources/templates/list` - List resource templates
* `prompts/list` - List available prompts
* `tools/list` - List available tools
## Implementation Guidelines
1. Servers **SHOULD**:
* Provide stable cursors
* Handle invalid cursors gracefully
2. Clients **SHOULD**:
* Treat a missing `nextCursor` as the end of results
* Support both paginated and non-paginated flows
3. Clients **MUST** treat cursors as opaque tokens:
* Don't make assumptions about cursor format
* Don't attempt to parse or modify cursors
* Don't persist cursors across sessions
## Error Handling
Invalid cursors **SHOULD** result in an error with code -32602 (Invalid params).
specification/draft/architecture/index New page · 172 lines, new page
# Architecture ## Core Components ### Host ### Clients ### Servers ## Design Principles ## Capability Negotiation
A whole new page. There's nothing to diff it against, so here is what it says.
# Architecture
<div id="enable-section-numbers" />
The Model Context Protocol (MCP) follows a client-host-server architecture where each
host can run multiple client instances. MCP is a stateless protocol: every request is
self-contained and carries its own protocol version and capabilities.
This architecture enables users to integrate AI capabilities across applications while
maintaining clear security boundaries and isolating concerns. Built on JSON-RPC, MCP
provides a protocol focused on context exchange and sampling coordination between
clients and servers.
## Core Components
```mermaid theme={null}
graph LR
subgraph "Application Host Process"
H[Host]
C1[Client 1]
C2[Client 2]
C3[Client 3]
H --> C1
H --> C2
H --> C3
end
subgraph "Local machine"
S1[Server 1<br>Files & Git]
S2[Server 2<br>Database]
R1[("Local<br>Resource A")]
R2[("Local<br>Resource B")]
C1 --> S1
C2 --> S2
S1 <--> R1
S2 <--> R2
end
subgraph "Internet"
S3[Server 3<br>External APIs]
R3[("Remote<br>Resource C")]
C3 --> S3
S3 <--> R3
end
```
### Host
The host process acts as the container and coordinator:
* Creates and manages multiple client instances
* Controls client connection permissions and lifecycle
* Enforces security policies and consent requirements
* Handles user authorization decisions
* Coordinates AI/LLM integration and sampling
* Manages context aggregation across clients
### Clients
Each client is created by the host and communicates with exactly one server:
* Communicates with exactly one server
* Attaches protocol version and capabilities to every request
* Routes protocol messages bidirectionally
* Manages subscriptions and notifications
* Maintains security boundaries between servers
A host application creates and manages multiple clients, with each client having a 1:1
relationship with a particular server.
### Servers
Servers provide specialized context and capabilities:
* Expose resources, tools and prompts via MCP primitives
* Operate independently with focused responsibilities
* Request client input (sampling, elicitation, roots) via `InputRequiredResult` within a reply
* Must respect security constraints
* Can be local processes or remote services
## Design Principles
MCP is built on several key design principles that inform its architecture and
implementation:
1. **Servers should be extremely easy to build**
* Host applications handle complex orchestration responsibilities
* Servers focus on specific, well-defined capabilities
* Simple interfaces minimize implementation overhead
* Clear separation enables maintainable code
2. **Servers should be highly composable**
* Each server provides focused functionality in isolation
* Multiple servers can be combined seamlessly
* Shared protocol enables interoperability
* Modular design supports extensibility
3. **Servers should not be able to read the whole conversation, nor "see into" other
servers**
* Servers receive only necessary contextual information
* Full conversation history stays with the host
* Each server maintains isolation
* Cross-server interactions are controlled by the host
* Host process enforces security boundaries
4. **Features can be added to servers and clients progressively**
* Core protocol provides minimal required functionality
* Additional capabilities can be negotiated as needed
* Servers and clients evolve independently
* Protocol designed for future extensibility
* Backwards compatibility is maintained
## Capability Negotiation
The Model Context Protocol uses a capability-based negotiation system where clients and
servers declare their supported features on each request. Clients include their
capabilities in `_meta.io.modelcontextprotocol/clientCapabilities` on every request.
Servers advertise their capabilities in response to
[`server/discover`](/specification/draft/server/discover), which clients may call before
any other request for up-front capability discovery.
* Servers declare capabilities like tool support, resource subscriptions, and prompt
templates
* Clients declare capabilities like sampling support and elicitation handling
* Both parties must respect declared capabilities throughout the interaction
* Additional capabilities can be negotiated through extensions to the protocol
```mermaid theme={null}
sequenceDiagram
participant Host
participant Client
participant Server
opt Discovery
Client->>Server: server/discover
Server-->>Client: supported versions + capabilities
end
loop Client Requests
Host->>Client: User- or model-initiated action
Client->>Server: Request (with _meta: version, clientCapabilities)
alt Server requires client input
Server-->>Client: InputRequiredResult (e.g. sampling/createMessage)
Client->>Host: Forward to AI
Host-->>Client: AI response
Client->>Server: Original request (with input)
end
Server-->>Client: Response
Client-->>Host: Update UI or respond to model
end
opt Subscriptions
Client->>Server: subscriptions/listen (toolsListChanged, resourceSubscriptions, …)
Server--)Client: notifications/subscriptions/acknowledged
loop Stream
Server--)Client: notifications/* (tagged with subscriptionId)
end
end
```
Each capability unlocks specific protocol features on a per-request basis. For example:
* Implemented [server features](/specification/draft/server) must be advertised in the
server's capabilities
* Receiving resource update notifications requires opening a
[`subscriptions/listen`](/specification/draft/basic/patterns/subscriptions) stream
with the desired resource URIs
* [Tool](/specification/draft/server/tools) invocation requires the server to declare tool capabilities
This capability negotiation ensures clients and servers have a clear understanding of
supported functionality while maintaining protocol extensibility.
specification/draft/basic/authorization/authorization-server-discovery New page · 142 lines, new page
# Authorization Server Discovery ## Authorization Server Location ## Protected Resource Metadata Discovery Requirements ## Authorization Server Metadata Discovery ## Sequence Diagram
A whole new page. There's nothing to diff it against, so here is what it says.
# Authorization Server Discovery
<div id="enable-section-numbers" />
This document describes the mechanisms by which MCP servers advertise their associated
authorization servers to MCP clients, as well as the discovery process through which MCP
clients can determine authorization server endpoints and supported capabilities.
## Authorization Server Location
MCP servers **MUST** implement the OAuth 2.0 Protected Resource Metadata ([RFC9728](https://datatracker.ietf.org/doc/html/rfc9728))
specification to indicate the locations of authorization servers. The Protected Resource Metadata document returned by the MCP server **MUST** include
the `authorization_servers` field containing at least one authorization server.
The specific use of `authorization_servers` is beyond the scope of this specification; implementers should consult
OAuth 2.0 Protected Resource Metadata ([RFC9728](https://datatracker.ietf.org/doc/html/rfc9728)) for
guidance on implementation details.
Implementors should note that Protected Resource Metadata documents
can define multiple authorization servers. The responsibility for
selecting which authorization server to use lies with the MCP client,
following the guidelines specified in
[RFC9728 Section 7.6 "Authorization Servers"](https://datatracker.ietf.org/doc/html/rfc9728#name-authorization-servers).
When multiple authorization servers are listed in `authorization_servers`, each is an
independent OAuth 2.0 authorization server. Consistent with
[RFC 6749 Section 2.2](https://datatracker.ietf.org/doc/html/rfc6749#section-2.2), client
identifiers are unique to the authorization server that issued them. Clients **MUST** maintain
separate registration state (client credentials, tokens) per authorization server and
**MUST NOT** assume that credentials valid for one authorization server will be accepted by
another. See
[Authorization Server Binding](/specification/draft/basic/authorization/client-registration#authorization-server-binding)
for the requirements on associating client credentials with the authorization server that issued them.
## Protected Resource Metadata Discovery Requirements
MCP servers **MUST** implement one of the following discovery mechanisms to provide authorization server location information to MCP clients:
1. **WWW-Authenticate Header**: Include the resource metadata URL in the `WWW-Authenticate` HTTP header under `resource_metadata` when returning `401 Unauthorized` responses, as described in [RFC9728 Section 5.1](https://datatracker.ietf.org/doc/html/rfc9728#name-www-authenticate-response).
2. **Well-Known URI**: Serve metadata at a well-known URI as specified in [RFC9728](https://datatracker.ietf.org/doc/html/rfc9728). This can be either:
* At the path of the server's MCP endpoint: `https://example.com/public/mcp` could host metadata at `https://example.com/.well-known/oauth-protected-resource/public/mcp`
* At the root: `https://example.com/.well-known/oauth-protected-resource`
MCP clients **MUST** support both discovery mechanisms and use the resource metadata URL from the parsed `WWW-Authenticate` headers when present; otherwise, they **MUST** fall back to constructing and requesting the well-known URIs in the order listed above.
MCP clients **MUST** be able to parse `WWW-Authenticate` headers and respond appropriately to `HTTP 401 Unauthorized` responses from the MCP server.
Servers can also include a `scope` parameter in the `WWW-Authenticate` challenge to indicate the
scopes required for accessing the resource; the scope semantics and the associated client behavior
are defined in the [Scope Selection Strategy](/specification/draft/basic/authorization#scope-selection-strategy) section.
## Authorization Server Metadata Discovery
MCP uses the default `oauth-authorization-server` well-known URI
suffix defined in
[RFC 8414 Section 3.1](https://datatracker.ietf.org/doc/html/rfc8414#section-3.1)
for authorization server metadata discovery. MCP does not define
an application-specific well-known URI suffix.
To handle different issuer URL formats and ensure
interoperability with both OAuth 2.0 Authorization Server
Metadata and OpenID Connect Discovery 1.0 specifications, MCP
clients **MUST** attempt multiple well-known endpoints when
discovering authorization server metadata.
The discovery approach is based on
[RFC 8414 Section 3.1 "Authorization Server Metadata Request"](https://datatracker.ietf.org/doc/html/rfc8414#section-3.1)
for OAuth 2.0 Authorization Server Metadata discovery and
[RFC 8414 Section 5 "Compatibility Notes"](https://datatracker.ietf.org/doc/html/rfc8414#section-5)
for OpenID Connect Discovery 1.0 interoperability.
For issuer URLs with path components
(e.g., `https://auth.example.com/tenant1`), clients **MUST**
try endpoints in the following priority order:
1. OAuth 2.0 Authorization Server Metadata with path insertion:
`https://auth.example.com/.well-known/oauth-authorization-server/tenant1`
2. OpenID Connect Discovery 1.0 with path insertion:
`https://auth.example.com/.well-known/openid-configuration/tenant1`
3. OpenID Connect Discovery 1.0 path appending:
`https://auth.example.com/tenant1/.well-known/openid-configuration`
For issuer URLs without path components
(e.g., `https://auth.example.com`), clients **MUST** try:
1. OAuth 2.0 Authorization Server Metadata:
`https://auth.example.com/.well-known/oauth-authorization-server`
2. OpenID Connect Discovery 1.0:
`https://auth.example.com/.well-known/openid-configuration`
After retrieving a metadata document, MCP clients **MUST** validate it as required by [RFC8414 Section 3.3](https://datatracker.ietf.org/doc/html/rfc8414#section-3.3) or [OpenID Connect Discovery Section 4.3](https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationValidation): the `issuer` value in the document **MUST** be identical to the issuer identifier used to construct the well-known URL. If they differ, the client **MUST NOT** use the metadata. For example, a document fetched from `https://attacker.example/.well-known/oauth-authorization-server` that contains `"issuer": "https://honest.example"` **MUST** be rejected.
## Sequence Diagram
The following diagram outlines an example flow:
```mermaid theme={null}
sequenceDiagram
participant C as Client
participant M as MCP Server (Resource Server)
participant A as Authorization Server
Note over C: Attempt unauthenticated MCP request
C->>M: MCP request without token
M-->>C: HTTP 401 Unauthorized (may include WWW-Authenticate header)
alt Header includes resource_metadata
Note over C: Extract resource_metadata URL from header
C->>M: GET resource_metadata URI
M-->>C: Resource metadata with authorization server URL
else No resource_metadata in header
Note over C: Fallback to well-known URI probing
Note over M: _Not applicable if the MCP server is at the root_
C->>M: GET /.well-known/oauth-protected-resource/mcp
alt Sub-path metadata found
M-->>C: Resource metadata with authorization server URL
else Sub-path not found
C->>M: GET /.well-known/oauth-protected-resource
alt Root metadata found
M-->>C: Resource metadata with authorization server URL
else Root metadata not found
Note over C: Abort or use pre-configured values
end
end
end
Note over C: Validate RS metadata,<br />build AS metadata URL
C->>A: GET Authorization server metadata endpoint
Note over C,A: Try OAuth 2.0 and OpenID Connect<br/>discovery endpoints in priority order
A-->>C: Authorization server metadata
Note over C,A: OAuth 2.1 authorization flow happens here
C->>A: Token request
A-->>C: Access token
C->>M: MCP request with access token
M-->>C: MCP response
Note over C,M: MCP communication continues with valid token
```
specification/draft/basic/authorization/client-registration New page · 200 lines, new page
# Client Registration ## Client ID Metadata Documents ### Implementation Requirements ### Example Metadata Document ### Client ID Metadata Documents Flow ### Advertising CIMD Support ## Pre-registration ## Dynamic Client Registration ### Application Type and Redirect URI Constraints ## Authorization Server Binding
A whole new page. There's nothing to diff it against, so here is what it says.
# Client Registration
<div id="enable-section-numbers" />
MCP supports three client registration mechanisms. Choose based on your scenario:
* **[Client ID Metadata Documents](#client-id-metadata-documents)**: When client and server have no prior relationship (most common)
* **[Pre-registration](#pre-registration)**: When client and server have an existing relationship
* **[Dynamic Client Registration](#dynamic-client-registration)**: For backwards compatibility or specific requirements
Clients supporting all options **SHOULD** use the following priority order:
1. Use pre-registered client information for the server if the client has it available
2. Use Client ID Metadata Documents if the Authorization Server indicates that it supports them (via `client_id_metadata_document_supported` in OAuth Authorization Server Metadata)
3. Use Dynamic Client Registration as a fallback if the Authorization Server supports it (via `registration_endpoint` in OAuth Authorization Server Metadata)
4. Prompt the user to enter the client information if no other option is available
## Client ID Metadata Documents
MCP clients and authorization servers **SHOULD** support OAuth Client ID Metadata Documents as specified in
[OAuth Client ID Metadata Document](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-client-id-metadata-document-00)
for client registration.
This approach enables clients to use HTTPS URLs as client identifiers, where the URL points to a JSON document
containing client metadata. This addresses the common MCP scenario where servers and clients have
no pre-existing relationship.
### Implementation Requirements
MCP implementations supporting Client ID Metadata Documents **MUST** follow the requirements specified in
[OAuth Client ID Metadata Document](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-client-id-metadata-document-00).
Key requirements include:
**For MCP Clients:**
* Clients **MUST** host their metadata document at an HTTPS URL following RFC requirements
* The `client_id` URL **MUST** use the "https" scheme and contain a path component, e.g. `https://example.com/client.json`
* The metadata document **MUST** include at least the following properties: `client_id`, `client_name`, `redirect_uris`
* Clients **MUST** ensure the `client_id` value in the metadata matches the document URL exactly
* Clients **MAY** use `private_key_jwt` for client authentication (e.g., for requests to the token endpoint) with appropriate JWKS configuration as described in [Section 6.2 of Client ID Metadata Document](https://www.ietf.org/archive/id/draft-ietf-oauth-client-id-metadata-document-00.html#section-6.2)
**For Authorization Servers:**
* **SHOULD** fetch metadata documents when encountering URL-formatted client\_ids
* **MUST** validate that the fetched document's `client_id` matches the URL exactly
* **SHOULD** cache metadata respecting HTTP cache headers
* **MUST** validate redirect URIs presented in an authorization request against those in the metadata document
* **MUST** validate the document structure is valid JSON and contains required fields
* **SHOULD** follow the security considerations in [Section 6 of Client ID Metadata Document](https://www.ietf.org/archive/id/draft-ietf-oauth-client-id-metadata-document-00.html#section-6) and in [Client ID Metadata Document Security](/specification/draft/basic/authorization/security-considerations#client-id-metadata-document-security)
### Example Metadata Document
```json theme={null}
{
"client_id": "https://app.example.com/oauth/client-metadata.json",
"client_name": "Example MCP Client",
"client_uri": "https://app.example.com",
"logo_uri": "https://app.example.com/logo.png",
"redirect_uris": [
"http://127.0.0.1:3000/callback",
"http://localhost:3000/callback"
],
"grant_types": ["authorization_code"],
"response_types": ["code"],
"token_endpoint_auth_method": "none"
}
```
### Client ID Metadata Documents Flow
The following diagram illustrates the complete flow when using Client ID Metadata Documents:
```mermaid theme={null}
sequenceDiagram
participant User
participant Client as MCP Client
participant Server as Authorization Server
participant Metadata as Metadata Endpoint<br/>(Client's HTTPS URL)
participant Resource as MCP Server
Note over Client,Metadata: Client hosts metadata at<br/>https://app.example.com/oauth/metadata.json
User->>Client: Initiates connection to MCP Server
Client->>Server: Authorization Request<br/>client_id=https://app.example.com/oauth/metadata.json<br/>redirect_uri=http://localhost:3000/callback
Server->>User: Authentication prompt
User->>Server: Provides credentials
Note over Server: Authenticates user
Note over Server: Detects URL-formatted client_id
Server->>Metadata: GET https://app.example.com/oauth/metadata.json
Metadata-->>Server: JSON Metadata Document<br/>{client_id, client_name, redirect_uris, ...}
Note over Server: Validates:<br/>1. client_id matches URL<br/>2. redirect_uri in allowed list<br/>3. Document structure valid<br/>4. (Optional) Domain allowed via trust policy
alt Validation Success
Server->>User: Display consent page with client_name
User->>Server: Approves access
Server->>Client: Authorization code via redirect_uri
Client->>Server: Exchange code for token<br/>client_id=https://app.example.com/oauth/metadata.json
Server-->>Client: Access token
Client->>Resource: MCP requests with access token
Resource-->>Client: MCP responses
else Validation Failure
Server->>User: Error response<br/>error=invalid_client or invalid_request
end
Note over Server: Cache metadata for future requests<br/>(respecting HTTP cache headers)
```
### Advertising CIMD Support
Authorization servers advertise that they support clients using Client ID Metadata Documents by including the following property in their OAuth Authorization Server metadata:
```json theme={null}
{
"client_id_metadata_document_supported": true
}
```
MCP clients **SHOULD** check for this capability and **MAY** fall back to
[Dynamic Client Registration](#dynamic-client-registration)
or [pre-registration](#pre-registration) if unavailable.
## Pre-registration
MCP clients **SHOULD** support an option for static client credentials such as those supplied by a pre-registration flow. This could be:
1. Hardcode a client ID (and, if applicable, client credentials) specifically for the MCP client to use when
interacting with that authorization server, or
2. Present a UI to users that allows them to enter these details, after registering an
OAuth client themselves (e.g., through a configuration interface hosted by the
server).
## Dynamic Client Registration
<Warning>
Dynamic Client Registration is deprecated. New implementations should use
[Client ID Metadata Documents](#client-id-metadata-documents) instead. This
option remains available for backwards compatibility with authorization
servers that do not support Client ID Metadata Documents.
</Warning>
MCP clients and authorization servers **MAY** support the
OAuth 2.0 Dynamic Client Registration Protocol [RFC7591](https://datatracker.ietf.org/doc/html/rfc7591)
to allow MCP clients to obtain OAuth client IDs without user interaction.
This option is included for backwards compatibility with earlier versions of the MCP authorization spec.
### Application Type and Redirect URI Constraints
When authorization servers support OpenID Connect (OIDC) and
Dynamic Client Registration, they may enforce additional
constraints on redirect URIs based on the `application_type`
parameter as defined in
[OpenID Connect Dynamic Client Registration 1.0](https://openid.net/specs/openid-connect-registration-1_0.html).
MCP clients **MUST** specify an appropriate `application_type`
during Dynamic Client Registration. Omitting it defaults to
`"web"` under OIDC, which can conflict with native-style redirect
URIs; non-OIDC servers safely ignore the parameter.
* **Native applications** (desktop applications, mobile apps,
CLI tools, and locally-hosted web applications accessed via
`localhost`) **SHOULD** use `application_type: "native"`
* **Web applications** (remote browser-based applications
served from a non-local host) **SHOULD** use
`application_type: "web"`
MCP clients **MUST** be prepared to handle registration
failures due to redirect URI constraints when authorization
servers implement OIDC. When a registration request is rejected,
clients **SHOULD** surface a meaningful error to the user or
developer. Clients **MAY** retry registration with an adjusted
`application_type` or with redirect URIs that conform to the
authorization server's requirements for the given application
type.
## Authorization Server Binding
Clients that use pre-registered credentials, or persist client credentials obtained via Dynamic Client
Registration, **MUST** associate those
credentials with the specific authorization server that issued them,
keyed by the authorization server's `issuer` identifier. When the
authorization server changes (detected via updated
[protected resource metadata](/specification/draft/basic/authorization/authorization-server-discovery#authorization-server-location)),
clients **MUST NOT** reuse client credentials
from a different authorization server and **MUST** re-register
with the new authorization server.
Pre-registered credentials are inherently specific to a particular
authorization server. If the authorization server indicated by
protected resource metadata no longer matches the one the
credentials were registered with, clients **SHOULD** surface an
error rather than silently attempting to use mismatched credentials.
Client IDs based on Client ID Metadata Documents are portable
across authorization servers, since they are self-hosted HTTPS URLs
resolved by the authorization server on demand. No re-registration
is needed when the authorization server changes.
specification/draft/basic/authorization/index New page · 422 lines, new page
# Authorization ## Introduction ### Purpose and Scope ### Protocol Requirements ### Standards Compliance ## Roles ## Overview ## Authorization Server Discovery ## Client Registration ## Scope Selection Strategy ## Authorization Flow Steps ### Authorization Response Validation ## Resource Parameter Implementation ### Canonical Server URI ## Access Token Usage ### Token Requirements ### Token Handling ## Refresh Tokens ## Error Handling ### Scope Challenge Handling #### Runtime Insufficient Scope Errors #### Step-Up Authorization Flow ## Security Considerations ## MCP Authorization Extensions
A whole new page. There's nothing to diff it against, so here is what it says.
# Authorization
<div id="enable-section-numbers" />
## Introduction
### Purpose and Scope
The Model Context Protocol provides authorization capabilities at the transport level,
enabling MCP clients to make requests to restricted MCP servers on behalf of resource
owners. This specification defines the authorization flow for HTTP-based transports.
### Protocol Requirements
Authorization is **OPTIONAL** for MCP implementations. When supported:
* Implementations using an HTTP-based transport **SHOULD** conform to this specification.
* Implementations using an STDIO transport **SHOULD NOT** follow this specification, and
instead retrieve credentials from the environment.
* Implementations using alternative transports **MUST** follow established security best
practices for their protocol.
### Standards Compliance
This authorization mechanism is based on established specifications listed below, but
implements a selected subset of their features to ensure security and interoperability
while maintaining simplicity:
* OAuth 2.1 IETF DRAFT ([draft-ietf-oauth-v2-1-13](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-13))
* OAuth 2.0 Bearer Token Usage
([RFC6750](https://datatracker.ietf.org/doc/html/rfc6750))
* OAuth 2.0 Authorization Server Metadata
([RFC8414](https://datatracker.ietf.org/doc/html/rfc8414))
* OAuth 2.0 Dynamic Client Registration Protocol
([RFC7591](https://datatracker.ietf.org/doc/html/rfc7591))
* Resource Indicators for OAuth 2.0
([RFC8707](https://www.rfc-editor.org/rfc/rfc8707.html))
* OAuth 2.0 Protected Resource Metadata ([RFC9728](https://datatracker.ietf.org/doc/html/rfc9728))
* OAuth 2.0 Authorization Server Issuer Identification ([RFC9207](https://datatracker.ietf.org/doc/html/rfc9207))
* OAuth Client ID Metadata Documents ([draft-ietf-oauth-client-id-metadata-document-00](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-client-id-metadata-document-00))
* [OpenID Connect Discovery 1.0](https://openid.net/specs/openid-connect-discovery-1_0.html)
* OpenID Connect Dynamic Client Registration 1.0 ([OpenID Connect Registration](https://openid.net/specs/openid-connect-registration-1_0.html))
## Roles
A protected *MCP server* acts as an [OAuth 2.1 resource server](https://www.ietf.org/archive/id/draft-ietf-oauth-v2-1-13.html#name-roles),
capable of accepting and responding to protected resource requests using access tokens.
An *MCP client* acts as an [OAuth 2.1 client](https://www.ietf.org/archive/id/draft-ietf-oauth-v2-1-13.html#name-roles),
making protected resource requests on behalf of a resource owner.
The *authorization server* is responsible for interacting with the user (if necessary) and issuing access tokens for use at the MCP server.
The implementation details of the authorization server are beyond the scope of this specification. It may be hosted with the
resource server or a separate entity. [Authorization Server Discovery](/specification/draft/basic/authorization/authorization-server-discovery)
specifies how an MCP server indicates the location of its corresponding authorization server to a client.
## Overview
1. Authorization servers **MUST** implement OAuth 2.1 with appropriate security
measures for both confidential and public clients.
2. Authorization servers and MCP clients **SHOULD** support [OAuth Client ID Metadata Documents](/specification/draft/basic/authorization/client-registration#client-id-metadata-documents)
([draft-ietf-oauth-client-id-metadata-document-00](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-client-id-metadata-document-00)).
3. Authorization servers and MCP clients **MAY** support the OAuth 2.0 Dynamic Client Registration
Protocol ([RFC7591](https://datatracker.ietf.org/doc/html/rfc7591)). Note that
[Dynamic Client Registration](/specification/draft/basic/authorization/client-registration#dynamic-client-registration)
is deprecated and retained for backwards compatibility with authorization servers that do not support Client ID Metadata Documents.
4. MCP servers **MUST** implement OAuth 2.0 Protected Resource Metadata ([RFC9728](https://datatracker.ietf.org/doc/html/rfc9728)).
MCP clients **MUST** use OAuth 2.0 Protected Resource Metadata for [authorization server discovery](/specification/draft/basic/authorization/authorization-server-discovery).
5. MCP authorization servers **MUST** provide at least one of the following discovery mechanisms:
* OAuth 2.0 Authorization Server Metadata ([RFC8414](https://datatracker.ietf.org/doc/html/rfc8414))
* [OpenID Connect Discovery 1.0](https://openid.net/specs/openid-connect-discovery-1_0.html)
MCP clients **MUST** support both [discovery mechanisms](/specification/draft/basic/authorization/authorization-server-discovery#authorization-server-metadata-discovery) to obtain the information required to interact with the authorization server.
## Authorization Server Discovery
MCP servers advertise their associated authorization servers through OAuth 2.0 Protected
Resource Metadata, and MCP clients determine authorization server endpoints and supported
capabilities through authorization server metadata discovery. Implementations **MUST**
follow the normative discovery requirements defined in
[Authorization Server Discovery](/specification/draft/basic/authorization/authorization-server-discovery).
## Client Registration
Before initiating the authorization flow, MCP clients **MUST** obtain a client ID through
one of three registration mechanisms: Client ID Metadata Documents, pre-registration, or
Dynamic Client Registration, following the requirements and selection priority defined in
[Client Registration](/specification/draft/basic/authorization/client-registration).
## Scope Selection Strategy
MCP servers **SHOULD** include a `scope` parameter in the `WWW-Authenticate` header as defined in
[RFC 6750 Section 3](https://datatracker.ietf.org/doc/html/rfc6750#section-3)
to indicate the scopes required for accessing the resource. This provides clients with immediate
guidance on the appropriate scopes to request during authorization,
following the principle of least privilege and preventing clients from requesting excessive permissions.
The scopes included in the `WWW-Authenticate` challenge **MAY** match `scopes_supported`, be a subset
or superset of it, or an alternative collection that is neither a strict subset nor
superset. Clients **MUST NOT** assume any particular set relationship between the challenged
scope set and `scopes_supported`. Clients **MUST** treat the scopes provided in the
challenge as authoritative for the current operation. These scopes are required to
satisfy the current request. When re-authorizing, clients **SHOULD** include these scopes
alongside any previously granted scopes to avoid losing permissions needed for other operations
(see [Step-Up Authorization Flow](#step-up-authorization-flow)). Servers **SHOULD** strive for
consistency in how they construct scope sets but they are not required to surface every dynamically
issued scope through `scopes_supported`.
Example 401 response with scope guidance:
```http theme={null}
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer resource_metadata="https://mcp.example.com/.well-known/oauth-protected-resource",
scope="files:read"
```
When implementing authorization flows, MCP clients **SHOULD** follow the principle of least privilege by requesting
only the scopes necessary for their intended operations. During the initial authorization handshake, MCP clients
**SHOULD** follow this priority order for scope selection:
1. **Use `scope` parameter** from the initial `WWW-Authenticate` header in the 401 response, if provided
2. **If `scope` is not available**, use all scopes defined in `scopes_supported` from the Protected Resource Metadata document, omitting the `scope` parameter if `scopes_supported` is undefined.
The `scopes_supported` field is intended to represent the minimal set of scopes necessary
for basic functionality (see [Scope Minimization](/docs/draft/tutorials/security/security_best_practices#scope-minimization)),
with additional scopes requested incrementally through the step-up authorization flow steps
described in the [Scope Challenge Handling](#scope-challenge-handling) section.
## Authorization Flow Steps
The registration step shown in the flow uses one of the mechanisms defined in
[Client Registration](/specification/draft/basic/authorization/client-registration).
The complete Authorization flow proceeds as follows:
```mermaid theme={null}
sequenceDiagram
participant B as User-Agent (Browser)
participant C as Client
participant M as MCP Server (Resource Server)
participant A as Authorization Server
C->>M: MCP request without token
M->>C: HTTP 401 Unauthorized with WWW-Authenticate header
Note over C: Extract resource_metadata URL from WWW-Authenticate
C->>M: Request Protected Resource Metadata
M->>C: Return metadata
Note over C: Parse metadata and extract authorization server(s)<br/>Client determines AS to use
C->>A: GET Authorization server metadata endpoint
Note over C,A: Try OAuth 2.0 and OpenID Connect<br/>discovery endpoints in priority order
A-->>C: Authorization server metadata
alt Client ID Metadata Documents
Note over C: Client uses HTTPS URL as client_id
Note over A: Server detects URL-formatted client_id
A->>C: Fetch metadata from client_id URL
C-->>A: JSON metadata document
Note over A: Validate metadata and redirect_uris
else Dynamic client registration
C->>A: POST /register
A->>C: Client Credentials
else Pre-registered client
Note over C: Use existing client_id
end
Note over C: Generate PKCE parameters<br/>Include resource parameter<br/>Apply scope selection strategy<br/>Record expected issuer
C->>B: Open browser with authorization URL + code_challenge + resource
B->>A: Authorization request with resource parameter
Note over A: User authorizes
A->>B: Redirect to callback with authorization code + iss
B->>C: Authorization code callback
Note over C: Validate iss against recorded issuer (RFC 9207)
C->>A: Token request + code_verifier + resource
A->>C: Access token (+ refresh token)
C->>M: MCP request with access token
M-->>C: MCP response
Note over C,M: MCP communication continues with valid token
```
### Authorization Response Validation
Before redirecting the user-agent, the client **MUST** record the `issuer` value from the selected authorization server's validated metadata document (see [Authorization Server Metadata Discovery](/specification/draft/basic/authorization/authorization-server-discovery#authorization-server-metadata-discovery)) and associate it with the same per-request record used to store the PKCE code verifier (and the `state` value, if used). The validation in this section depends on that recorded value being authentic; it provides no protection if the expected issuer was obtained from an unvalidated source.
MCP authorization servers **SHOULD** include the `iss` parameter in authorization responses, including error responses, as defined in [RFC9207 Section 2](https://datatracker.ietf.org/doc/html/rfc9207#section-2). Authorization servers that include the `iss` parameter **MUST** advertise this by setting `authorization_response_iss_parameter_supported` to `true` in their metadata ([RFC9207 Section 2.3](https://datatracker.ietf.org/doc/html/rfc9207#section-2.3)).
On receiving the authorization response, MCP clients **MUST** apply the validation in [RFC9207 Section 2.4](https://datatracker.ietf.org/doc/html/rfc9207#section-2.4) before transmitting the authorization code to any token endpoint:
| `authorization_response_iss_parameter_supported` | `iss` in response | Client action |
| ------------------------------------------------ | ----------------- | ------------------------------------------------------------------------------------------ |
| `true` | present | Compare to the recorded issuer using simple string comparison ([RFC3986 Section 6.2.1][1]) |
| `true` | absent | Reject the response |
| `false` or absent | present | Compare to the recorded issuer using simple string comparison ([RFC3986 Section 6.2.1][1]) |
| `false` or absent | absent | Proceed |
[1]: https://datatracker.ietf.org/doc/html/rfc3986#section-6.2.1
The third row applies the local-policy provision in [RFC9207 Section 2.4](https://datatracker.ietf.org/doc/html/rfc9207#section-2.4): this specification compares a present `iss` against the recorded issuer regardless of metadata advertisement, to accommodate authorization servers that emit `iss` before updating their metadata.
A future revision of this specification is expected to upgrade authorization server inclusion of `iss` from **SHOULD** to **MUST**. Implementers are encouraged to emit and validate `iss` now to ease that transition; client rejection behavior on `iss` absence will continue to be keyed on `authorization_response_iss_parameter_supported` until that revision defines the upgrade path.
After decoding the `iss` value from the `application/x-www-form-urlencoded` response per [RFC 9207 Section 2.4](https://datatracker.ietf.org/doc/html/rfc9207#section-2.4), clients **MUST NOT** apply scheme or host case folding, default-port elision, trailing-slash, or percent-encoding normalization ([RFC 3986 Sections 6.2.2-6.2.3](https://datatracker.ietf.org/doc/html/rfc3986#section-6.2.2)) before comparison.
This validation applies equally to error responses - on mismatch the client **MUST NOT** act on or display `error`, `error_description`, or `error_uri`.
## Resource Parameter Implementation
MCP clients **MUST** implement Resource Indicators for OAuth 2.0 as defined in [RFC 8707](https://www.rfc-editor.org/rfc/rfc8707.html)
to explicitly specify the target resource for which the token is being requested. The `resource` parameter:
1. **MUST** be included in both authorization requests and token requests.
2. **MUST** identify the MCP server that the client intends to use the token with.
3. **MUST** use the canonical URI of the MCP server as defined in [RFC 8707 Section 2](https://www.rfc-editor.org/rfc/rfc8707.html#name-access-token-request).
### Canonical Server URI
For the purposes of this specification, the canonical URI of an MCP server is defined as the resource identifier as specified in
[RFC 8707 Section 2](https://www.rfc-editor.org/rfc/rfc8707.html#section-2) and aligns with the `resource` parameter in
[RFC 9728](https://datatracker.ietf.org/doc/html/rfc9728).
MCP clients **SHOULD** provide the most specific URI that they can for the MCP server they intend to access, following the guidance in [RFC 8707](https://www.rfc-editor.org/rfc/rfc8707). While the canonical form uses lowercase scheme and host components, implementations **SHOULD** accept uppercase scheme and host components for robustness and interoperability.
Examples of valid canonical URIs:
* `https://mcp.example.com/mcp`
* `https://mcp.example.com`
* `https://mcp.example.com:8443`
* `https://mcp.example.com/server/mcp` (when path component is necessary to identify individual MCP server)
Examples of invalid canonical URIs:
* `mcp.example.com` (missing scheme)
* `https://mcp.example.com#fragment` (contains fragment)
> **Note:** While both `https://mcp.example.com/` (with trailing slash) and `https://mcp.example.com` (without trailing slash) are technically valid absolute URIs according to [RFC 3986](https://www.rfc-editor.org/rfc/rfc3986), implementations **SHOULD** consistently use the form without the trailing slash for better interoperability unless the trailing slash is semantically significant for the specific resource.
For example, if accessing an MCP server at `https://mcp.example.com`, the authorization request would include:
```
&resource=https%3A%2F%2Fmcp.example.com
```
MCP clients **MUST** send this parameter regardless of whether authorization servers support it.
## Access Token Usage
### Token Requirements
Access token handling when making requests to MCP servers **MUST** conform to the requirements defined in
[OAuth 2.1 Section 5 "Resource Requests"](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-13#section-5).
Specifically:
1. MCP client **MUST** use the Authorization request header field defined in
[OAuth 2.1 Section 5.1.1](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-13#section-5.1.1):
```
Authorization: Bearer <access-token>
```
Note that authorization **MUST** be included in every HTTP request from client to server.
2. Access tokens **MUST NOT** be included in the URI query string
Example request:
```http theme={null}
GET /mcp HTTP/1.1
Host: mcp.example.com
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
```
### Token Handling
MCP servers, acting in their role as an OAuth 2.1 resource server, **MUST** validate access tokens as described in
[OAuth 2.1 Section 5.2](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-13#section-5.2).
MCP servers **MUST** validate that access tokens were issued specifically for them as the intended audience,
according to [RFC 8707 Section 2](https://www.rfc-editor.org/rfc/rfc8707.html#section-2).
If validation fails, servers **MUST** respond according to
[OAuth 2.1 Section 5.3](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-13#section-5.3)
error handling requirements. Invalid or expired tokens **MUST** receive a HTTP 401
response.
MCP clients **MUST NOT** send tokens to the MCP server other than ones issued by the MCP server's authorization server.
MCP servers **MUST** only accept tokens that are valid for use with their
own resources.
MCP servers **MUST NOT** accept or transit any other tokens.
## Refresh Tokens
This section provides guidance for MCP Clients and MCP Servers when handling or issuing
refresh tokens for both OAuth and OpenID Connect.
Cut at 300 lines. The page has the rest.
specification/draft/basic/authorization/security-considerations New page · 128 lines, new page
# Authorization Security Considerations ## Token Audience Binding and Validation ## Token Theft ## Communication Security ## Authorization Code Protection ## Mix-Up Attacks ## Open Redirection ## Client ID Metadata Document Security ### Authorization Server Abuse Protection ### Localhost Redirect URI Risks ### Trust Policies ## Confused Deputy Problem ## Access Token Privilege Restriction
A whole new page. There's nothing to diff it against, so here is what it says.
# Authorization Security Considerations <div id="enable-section-numbers" /> This document outlines security requirements that implementers **MUST** consider when building MCP clients and servers. Additionally, implementors **MUST** follow OAuth 2.1 security best practices as outlined in [OAuth 2.1 Section 7. "Security Considerations"](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-13#name-security-considerations). ## Token Audience Binding and Validation [RFC 8707](https://www.rfc-editor.org/rfc/rfc8707.html) Resource Indicators provide critical security benefits by binding tokens to their intended audiences **when the Authorization Server supports the capability**. To enable current and future adoption: * MCP clients **MUST** include the `resource` parameter in authorization and token requests as specified in the [Resource Parameter Implementation](/specification/draft/basic/authorization#resource-parameter-implementation) section * MCP servers **MUST** validate that tokens presented to them were specifically issued for their use The [Security Best Practices document](/docs/draft/tutorials/security/security_best_practices#token-passthrough) outlines why token audience validation is crucial and why token passthrough is explicitly forbidden. ## Token Theft Attackers who obtain tokens stored by the client, or tokens cached or logged on the server can access protected resources with requests that appear legitimate to resource servers. Clients and servers **MUST** implement secure token storage and follow OAuth best practices, as outlined in [OAuth 2.1, Section 7.1](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-13#section-7.1). Authorization servers **SHOULD** issue short-lived access tokens to reduce the impact of leaked tokens. For public clients, authorization servers **MUST** rotate refresh tokens as described in [OAuth 2.1 Section 4.3.1 "Token Endpoint Extension"](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-13#section-4.3.1). ## Communication Security Implementations **MUST** follow [OAuth 2.1 Section 1.5 "Communication Security"](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-13#section-1.5). Specifically: 1. All authorization server endpoints **MUST** be served over HTTPS. 2. All redirect URIs **MUST** be either `localhost` or use HTTPS. ## Authorization Code Protection An attacker who has gained access to an authorization code contained in an authorization response can try to redeem the authorization code for an access token or otherwise make use of the authorization code. (Further described in [OAuth 2.1 Section 7.5](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-13#section-7.5)) To mitigate this, MCP clients **MUST** implement PKCE according to [OAuth 2.1 Section 7.5.2](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-13#section-7.5.2) and **MUST** verify PKCE support before proceeding with authorization. PKCE helps prevent authorization code interception and injection attacks by requiring clients to create a secret verifier-challenge pair, ensuring that only the original requestor can exchange an authorization code for tokens. MCP clients **MUST** use the `S256` code challenge method when technically capable, as required by [OAuth 2.1 Section 4.1.1](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-13#section-4.1.1). Since OAuth 2.1 and PKCE specifications do not define a mechanism for clients to discover PKCE support, MCP clients **MUST** rely on authorization server metadata to verify this capability: * **OAuth 2.0 Authorization Server Metadata**: If `code_challenge_methods_supported` is absent, the authorization server does not support PKCE and MCP clients **MUST** refuse to proceed. * **OpenID Connect Discovery 1.0**: While the [OpenID Provider Metadata](https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata) does not define `code_challenge_methods_supported`, this field is commonly included by OpenID providers. MCP clients **MUST** verify the presence of `code_challenge_methods_supported` in the provider metadata response. If the field is absent, MCP clients **MUST** refuse to proceed. Authorization servers providing OpenID Connect Discovery 1.0 **MUST** include `code_challenge_methods_supported` in their metadata to ensure MCP compatibility. ## Mix-Up Attacks An attacker that controls one of the authorization servers an MCP client interacts with may attempt to have the client send it an authorization code or token issued by a different, honest authorization server (a mix-up attack, described in [RFC9207 Section 1](https://datatracker.ietf.org/doc/html/rfc9207#section-1)). [Authorization Response Validation](/specification/draft/basic/authorization#authorization-response-validation) specifies the required mitigation. ## Open Redirection An attacker may craft malicious redirect URIs to direct users to phishing sites. MCP clients **MUST** have redirect URIs registered with the authorization server. Authorization servers **MUST** validate exact redirect URIs against pre-registered values to prevent redirection attacks. MCP clients **SHOULD** use and verify state parameters in the authorization code flow and discard any results that do not include or have a mismatch with the original state. Authorization servers **MUST** take precautions to prevent redirecting user agents to untrusted URI's, following suggestions laid out in [OAuth 2.1 Section 7.12.2](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-13#section-7.12.2) Authorization servers **SHOULD** only automatically redirect the user agent if it trusts the redirection URI. If the URI is not trusted, the authorization server MAY inform the user and rely on the user to make the correct decision. ## Client ID Metadata Document Security When implementing [Client ID Metadata Documents](/specification/draft/basic/authorization/client-registration#client-id-metadata-documents), authorization servers **MUST** consider the security implications detailed in [OAuth Client ID Metadata Document, Section 6](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-client-id-metadata-document-00#name-security-considerations). Key considerations include: ### Authorization Server Abuse Protection Authorization servers fetching metadata documents **SHOULD** consider [Server-Side Request Forgery (SSRF)](https://developer.mozilla.org/docs/Web/Security/Attacks/SSRF) risks, as described in [OAuth Client ID Metadata Document: Server Side Request Forgery (SSRF) Attacks](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-client-id-metadata-document-00#name-server-side-request-forgery). ### Localhost Redirect URI Risks Client ID Metadata Documents cannot prevent `localhost` URL impersonation by themselves. Authorization servers: * **SHOULD** display additional warnings for `localhost`-only redirect URIs * **MAY** require additional attestation mechanisms for enhanced security * **MUST** clearly display the redirect URI hostname during authorization ### Trust Policies Authorization servers **MAY** implement domain-based trust policies for accepting Client ID Metadata Documents, as described in [Section 6.4](https://www.ietf.org/archive/id/draft-ietf-oauth-client-id-metadata-document-00.html#section-6.4) and [Section 6.8](https://www.ietf.org/archive/id/draft-ietf-oauth-client-id-metadata-document-00.html#section-6.8) of the Client ID Metadata Document specification. ## Confused Deputy Problem Attackers can exploit MCP servers acting as intermediaries to third-party APIs, leading to [confused deputy vulnerabilities](/docs/draft/tutorials/security/security_best_practices#confused-deputy-problem). By using stolen authorization codes, they can obtain access tokens without user consent. MCP proxy servers using static client IDs **MUST** obtain user consent for each [dynamically registered client](/specification/draft/basic/authorization/client-registration#dynamic-client-registration) before forwarding to third-party authorization servers (which may require additional consent). ## Access Token Privilege Restriction An attacker can gain unauthorized access or otherwise compromise an MCP server if the server accepts tokens issued for other resources. MCP servers **MUST** validate access tokens before processing the request, ensuring the access token is issued specifically for the MCP server, and take all necessary steps to ensure no data is returned to unauthorized parties. A MCP server **MUST** follow the guidelines in [OAuth 2.1 - Section 5.2](https://www.ietf.org/archive/id/draft-ietf-oauth-v2-1-13.html#section-5.2) to validate inbound tokens. MCP servers **MUST** only accept tokens specifically intended for themselves and **MUST** reject tokens that do not include them in the audience claim or otherwise verify that they are the intended recipient of the token. See the [Security Best Practices Token Passthrough section](/docs/draft/tutorials/security/security_best_practices#token-passthrough) for details. If the MCP server makes requests to upstream APIs, it may act as an OAuth client to them. The access token used at the upstream API is a separate token, issued by the upstream authorization server. The MCP server **MUST NOT** pass through the token it received from the MCP client. MCP clients **MUST** implement and use the `resource` parameter as defined in [RFC 8707 - Resource Indicators for OAuth 2.0](https://www.rfc-editor.org/rfc/rfc8707.html) to explicitly specify the target resource for which the token is being requested. This requirement aligns with the recommendation in [RFC 9728 Section 7.4](https://datatracker.ietf.org/doc/html/rfc9728#section-7.4). This ensures that access tokens are bound to their intended resources and cannot be misused across different services.
specification/draft/basic/index New page · 497 lines, new page
# Overview ## Messages ### Requests ### Responses #### Result Responses ##### ResultType #### Error Responses #### Error Codes ### Notifications ### Message Patterns ## Statelessness ## Auth ## Schema ## JSON Schema Usage ### Schema Dialect ### Example Usage #### Default dialect (2020-12): #### Explicit dialect (draft-07): ### Implementation Requirements ### Schema Validation ### `$ref` Resolution ### Composition-Keyword Resource Use ## General fields ### `_meta` ### `icons`
A whole new page. There's nothing to diff it against, so here is what it says.
# Overview
<div id="enable-section-numbers" />
The Model Context Protocol consists of several key components that work together:
* **Base Protocol**: Core JSON-RPC message types
* **Versioning and Compatibility**: Protocol version negotiation, extension negotiation, and interoperability with earlier protocol revisions
* **Message Patterns**: Messaging patterns supported by the core protocol including request and response, multi round-trip requests (MRTR), and subscribe and notify
* **Authorization**: Authentication and authorization framework for HTTP-based transports
* **Server Features**: Resources, prompts, and tools exposed by servers
* **Client Features**: Elicitation, sampling and root directory lists provided by clients
* **Utilities**: Cross-cutting concerns like logging and argument completion
All implementations **MUST** support the base protocol, versioning,
and the message patterns. Other components **MAY** be implemented based on the specific needs of the
application.
These protocol layers establish clear separation of concerns while enabling rich
interactions between clients and servers. The modular design allows implementations to
support exactly the features they need.
## Messages
All messages between MCP clients and servers **MUST** follow the
[JSON-RPC 2.0](https://www.jsonrpc.org/specification) specification. The protocol defines
these types of messages:
### Requests
[Requests](/specification/draft/schema#jsonrpcrequest) are sent from the client to the server, to initiate an operation.
```typescript theme={null}
{
jsonrpc: "2.0";
id: string | number;
method: string;
params?: {
[key: string]: unknown;
};
}
```
* Requests **MUST** include a string or integer ID.
* Unlike base JSON-RPC, the ID **MUST NOT** be `null`.
* The request ID **MUST NOT** match the ID of any other request the sender has issued and
not yet received a response for.
### Responses
Responses are sent in reply to requests, containing either the result or error of the operation.
#### Result Responses
[Result responses](/specification/draft/schema#jsonrpcresultresponse) are sent when the operation completes successfully.
```typescript theme={null}
{
jsonrpc: "2.0";
id: string | number;
result: {
resultType: string;
[key: string]: unknown;
};
}
```
* Result responses **MUST** include the same ID as the request they correspond to.
* Result responses **MUST** include a `result` field.
* The `result` **MAY** follow any JSON object structure.
* The `result` **MUST** include a `resultType` field to indicate the type of the result.
##### ResultType
The `resultType` field in a result indicates the type of the result being returned. MCP supports polymorphic result types,
allowing servers to return different structures based on the outcome of the request. The `resultType` field is a string that clients
can use to determine how to parse and handle the `result` object.
* A `resultType` of `"complete"` indicates the request completed successfully and the result contains the final content.
* A `resultType` of `"input_required"` indicates the request is incomplete and more information is needed to process the request. The result contains an [`InputRequiredResult`](/specification/draft/basic/patterns/mrtr#inputrequiredresult) object with additional information needed.
* Extensions **MAY** add additional `ResultType` values. The set of supported `ResultType` values **MUST** be created from the set defined in the core protocol and include any additional values of supported extensions that are advertised via capabilities.
* A `resultType` of any value unrecognized by the client **MUST** be considered invalid.
* For backward compatibility with servers implementing earlier protocol versions, which do not include `resultType`, clients **MUST** treat an absent `resultType` as `"complete"`.
#### Error Responses
[Error responses](/specification/draft/schema#jsonrpcerrorresponse) are sent when the operation fails or encounters an error.
```typescript theme={null}
{
jsonrpc: "2.0";
id?: string | number;
error: {
code: number;
message: string;
data?: unknown;
}
}
```
* Error responses **MUST** include the same ID as the request they correspond to (except in error cases where the ID could not be read due a malformed request).
* Error responses **MUST** include an `error` field with a `code` and `message`.
* Error codes **MUST** be integers.
* Error responses **MAY** include a `data` member with additional information of any type, such
as nested errors.
#### Error Codes
MCP uses the standard JSON-RPC 2.0 error codes (`-32700`, `-32600` to `-32603`)
for general protocol failures.
JSON-RPC 2.0 reserves the range `-32000` to `-32099` for implementation-defined
server errors. MCP partitions this range as follows:
* **`-32000` to `-32019` — legacy.** Codes in this sub-range were allocated by
implementations before this policy was introduced. New codes **MUST NOT** be
allocated in this sub-range, and new implementations **SHOULD NOT** use codes
from this sub-range at all. Apart from `-32002` (see below), receivers
**MUST NOT** assume any specific meaning for these codes.
* **`-32020` to `-32099` — reserved for the MCP specification.** Error codes
in this sub-range are defined exclusively by the MCP specification and
recorded in the [schema](/specification/draft/schema). Implementations
**MUST NOT** emit any code from this sub-range that is not defined by this
specification and **MUST** use defined codes only with their specified
meanings.
MCP defines the following error codes:
| Code | Name |
| -------- | ----------------------------------------------------------------------------------------------------- |
| `-32020` | [`HeaderMismatch`](/specification/draft/schema#headermismatcherror) |
| `-32021` | [`MissingRequiredClientCapability`](/specification/draft/schema#missingrequiredclientcapabilityerror) |
| `-32022` | [`UnsupportedProtocolVersion`](/specification/draft/schema#unsupportedprotocolversionerror) |
Codes defined by earlier protocol versions remain reserved and will not be
reused. Implementations of this protocol version **MUST NOT** emit these codes:
* `-32002` — resource not found (2025-11-25 and earlier; replaced by `-32602`).
Clients [**SHOULD** still
accept `-32002`](/specification/draft/server/resources#error-handling) from
servers implementing earlier versions.
* `-32042` — URL elicitation required (2025-11-25 only).
Errors that are purely local to an implementation (for example, a request
timeout raised inside an SDK) are not currently assigned codes by this
specification. Implementations surfacing local errors in JSON-RPC-shaped
structures should ensure they cannot be mistaken for errors received from the
peer. Future versions of the specification may define standard codes for
common local error conditions in the reserved sub-range.
New error codes for purposes not defined by this specification **SHOULD** be
allocated outside the JSON-RPC reserved range (`-32768` to `-32000`); the
remainder of the integer space is available for application-defined errors.
### Notifications
[Notifications](/specification/draft/schema#jsonrpcnotification) are sent from the client to the server or vice versa, as a one-way message.
The receiver **MUST NOT** send a response.
```typescript theme={null}
{
jsonrpc: "2.0";
method: string;
params?: {
[key: string]: unknown;
};
}
```
* Notifications **MUST NOT** include an ID.
### Message Patterns
The Model Context Protocol (MCP) supports several [Message Patterns](/specification/draft/basic/patterns) that define how clients and servers interact:
1. **[Request and Response](/specification/draft/basic/patterns#request-and-response)**: A client sends a request to the server, and the server responds with a result or error.
2. **[Multi Round-Trip Requests (MRTR)](/specification/draft/basic/patterns#multi-round-trip-requests)**: A server requires additional client input (sampling, elicitation, or roots) to complete a request.
3. **[Subscribe and Notify](/specification/draft/basic/patterns#subscribe-and-notify)**: A client subscribes to a stream of notifications from the server, which are sent as they occur.
## Statelessness
The Model Context Protocol (MCP) is a **stateless protocol**: all the
information needed to process a request is contained in the request itself.
A server processes each request independently; no state should be inferred
from previous requests, even those on the same connection or stream.
Specifically:
* Servers **MUST NOT** rely on prior requests over the same connection to
establish context (e.g., capabilities, protocol version, client identity).
Every request supplies this metadata in its [`_meta`](#_meta) field.
* Servers **SHOULD** be prepared to handle requests associated with multiple
tasks, threads, or conversations.
* Servers **SHOULD NOT** require that a client reuse the same connection or process to
perform related operations.
* Clients **SHOULD NOT** use an individual task, thread, or conversation as the
lifetime boundary for the stdio process.
* State that needs to span multiple requests (e.g., long-running tasks,
application-level handles) **MUST** be referenced by an explicit identifier
the client passes on each request.
<Note>
This implies that an open connection, such as a STDIO process, is not a
conversation or session: clients may interleave unrelated requests on the same
transport, and a server must not treat connection or process identity as a
proxy for conversation or session continuity.
</Note>
Long-lived requests like
[`subscriptions/listen`](/specification/draft/basic/patterns/subscriptions)
remain request/response; the response is just an open stream of notifications.
Their state is scoped to the request itself, not to the connection underneath.
<Info>
For a walkthrough of how the per-request model maps to SDK code, see the
[Architecture guide](/docs/draft/learn/architecture#example).
</Info>
## Auth
MCP provides an [Authorization](/specification/draft/basic/authorization) framework for use with HTTP.
Implementations using an HTTP-based transport **SHOULD** conform to this specification,
whereas implementations using STDIO transport **SHOULD NOT** follow this specification,
and instead retrieve credentials from the environment.
Additionally, clients and servers **MAY** negotiate their own custom authentication and
authorization strategies.
For further discussions and contributions to the evolution of MCP's auth mechanisms, join
us in
[GitHub Discussions](https://github.com/modelcontextprotocol/specification/discussions)
to help shape the future of the protocol!
## Schema
The full specification of the protocol is defined as a
[TypeScript schema](https://github.com/modelcontextprotocol/specification/blob/main/schema/draft/schema.ts).
This is the source of truth for all protocol messages and structures.
There is also a
[JSON Schema](https://github.com/modelcontextprotocol/specification/blob/main/schema/draft/schema.json),
which is automatically generated from the TypeScript source of truth, for use with
various automated tooling.
## JSON Schema Usage
The Model Context Protocol uses JSON Schema for validation throughout the protocol. This section clarifies how JSON Schema should be used within MCP messages.
### Schema Dialect
MCP supports JSON Schema with the following rules:
1. **Default dialect**: When a schema does not include a `$schema` field, it defaults to [JSON Schema 2020-12](https://json-schema.org/draft/2020-12/schema)
2. **Explicit dialect**: Schemas MAY include a `$schema` field to specify a different dialect
3. **Supported dialects**: Implementations MUST support at least 2020-12 and SHOULD document which additional dialects they support
4. **Recommendation**: Implementors are RECOMMENDED to use JSON Schema 2020-12.
### Example Usage
#### Default dialect (2020-12):
```json theme={null}
{
"type": "object",
"properties": {
"name": { "type": "string" },
"age": { "type": "integer", "minimum": 0 }
},
"required": ["name"]
}
```
#### Explicit dialect (draft-07):
```json theme={null}
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"name": { "type": "string" },
"age": { "type": "integer", "minimum": 0 }
},
"required": ["name"]
}
```
### Implementation Requirements
* Clients and servers **MUST** support JSON Schema 2020-12 for schemas without an explicit `$schema` field
* Clients and servers **MUST** validate schemas according to their declared or default dialect. They **MUST** handle unsupported dialects gracefully by returning an appropriate error indicating the dialect is not supported.
* Clients and servers **SHOULD** document which schema dialects they support
### Schema Validation
* Schemas **MUST** be valid according to their declared or default dialect
### `$ref` Resolution
JSON Schema 2020-12 permits `$ref` to point at an absolute URI. Implementations **MUST NOT**
automatically dereference `$ref` values that resolve to a network URI.
Cut at 300 lines. The page has the rest.
specification/draft/basic/patterns/cancellation New page · 120 lines, new page
# Cancellation ## Cancellation Flow ## Transport-Specific Cancellation ## Timeouts ## Behavior Requirements ## Timing Considerations ## Implementation Notes ## Error Handling
A whole new page. There's nothing to diff it against, so here is what it says.
# Cancellation
<div id="enable-section-numbers" />
The Model Context Protocol (MCP) supports optional cancellation of in-progress requests
through notification messages. A client **SHOULD** send a cancellation notification
to indicate that a request it previously issued should be terminated.
A server **MUST** send `notifications/cancelled`
referencing a `subscriptions/listen` request ID when it tears down that subscription
stream (see [Subscriptions][subscriptions]). Servers **MUST NOT** send
`notifications/cancelled` for any other purpose.
## Cancellation Flow
When a client wants to cancel an in-progress request, it sends a `notifications/cancelled`
notification containing:
* The ID of the request to cancel
* An optional reason string that can be logged or displayed
```json theme={null}
{
"jsonrpc": "2.0",
"method": "notifications/cancelled",
"params": {
"requestId": "123",
"reason": "User requested cancellation"
}
}
```
## Transport-Specific Cancellation
How a client signals cancellation depends on the transport:
* **Streamable HTTP**: Closing the SSE response stream is the cancellation signal.
The server **MUST** treat a client disconnect as cancellation of that request. No
`notifications/cancelled` message is required or expected.
* **stdio**: There is no per-request stream to close. The client **MUST** send a
`notifications/cancelled` notification referencing the request ID.
## Timeouts
Implementations **SHOULD** establish timeouts for all sent requests, to prevent hung
connections and resource exhaustion. When the request has not received a success or error
response within the timeout period, the sender **SHOULD** cancel the request and stop
waiting for a response. As described in
[Transport-Specific Cancellation](#transport-specific-cancellation), this means:
* **Streamable HTTP**: closing the response stream for the request, which constitutes
cancellation.
* **stdio**: sending a `notifications/cancelled` notification referencing the request ID.
SDKs and other middleware **SHOULD** allow these timeouts to be configured on a
per-request basis.
Implementations **MAY** choose to reset the timeout clock when receiving a
[progress notification](/specification/draft/basic/patterns/progress) corresponding to
the request, as this implies that work is actually happening. However, implementations
**SHOULD** always enforce a maximum timeout, regardless of progress notifications, to
limit the impact of a misbehaving client or server.
## Behavior Requirements
1. Cancellation notifications **MUST** only reference requests that:
* Were previously issued by the client
* Are believed to still be in-progress
2. Server-sent cancellation notifications **MUST** reference a
`subscriptions/listen` request, to terminate that subscription stream
3. Servers receiving cancellation notifications **SHOULD**:
* Stop processing the cancelled request
* Free associated resources
* Not send a response for the cancelled request
4. Servers **MAY** ignore cancellation notifications if:
* The referenced request is unknown
* Processing has already completed
* The request cannot be cancelled
5. The client **SHOULD** ignore any response to the cancelled request that arrives
afterward
## Timing Considerations
Due to network latency, cancellation notifications may arrive after request processing
has completed, and potentially after a response has already been sent.
Both parties **MUST** handle these race conditions gracefully:
```mermaid theme={null}
sequenceDiagram
participant Client
participant Server
Client->>Server: Request (ID: 123)
Note over Server: Processing starts
Client--)Server: notifications/cancelled (ID: 123)
alt
Note over Server: Processing may have<br/>completed before<br/>cancellation arrives
else If not completed
Note over Server: Stop processing
end
```
## Implementation Notes
* Both parties **SHOULD** log cancellation reasons for debugging
* Application UIs **SHOULD** indicate when cancellation is requested
## Error Handling
Invalid cancellation notifications **SHOULD** be ignored:
* Unknown request IDs
* Already completed requests
* Malformed notifications
This maintains the "fire and forget" nature of notifications while allowing for race
conditions in asynchronous communication.
[subscriptions]: /specification/draft/basic/patterns/subscriptions
specification/draft/basic/patterns/index New page · 83 lines, new page
# Overview ## Request and Response ## Multi Round-Trip Requests ## Subscribe and Notify ## Adding Patterns
A whole new page. There's nothing to diff it against, so here is what it says.
# Overview
<div id="enable-section-numbers" />
This page defines the message patterns of the core protocol: the ways a
client and server compose JSON-RPC
[requests, responses, and notifications](/specification/draft/basic/index#messages)
into interactions. Every
[transport](/specification/draft/basic/transports) carries all of these
patterns; transports differ only in how messages are framed and delivered.
Every interaction begins with the client:
* The **client** sends JSON-RPC *requests* and *notifications*.
* The **server** answers each request with a JSON-RPC *response* (a result
or error), optionally preceded by *notifications* scoped to that request.
Servers **MUST NOT** initiate JSON-RPC requests, and clients do not send
JSON-RPC responses.
## Request and Response
The client sends a request; the server answers it with a result or an error.
While the request is in flight, the server **MAY** send notifications scoped
to it, such as
[`notifications/progress`](/specification/draft/basic/patterns/progress)
and [`notifications/message`](/specification/draft/server/utilities/logging).
```mermaid theme={null}
sequenceDiagram
participant Client
participant Server
Client->>Server: request
Server-->>Client: notifications/progress (optional)
Server-->>Client: response
```
## Multi Round-Trip Requests
When a server needs client input (sampling, elicitation, or roots) to
complete a request, it answers with an
[`InputRequiredResult`](/specification/draft/basic/patterns/mrtr#inputrequiredresult)
and the client retries the request with the matching `inputResponses`. See
[Multi Round-Trip Requests](/specification/draft/basic/patterns/mrtr).
```mermaid theme={null}
sequenceDiagram
participant Client
participant Server
Client->>Server: request (id: 1)
Server-->>Client: InputRequiredResult (inputRequests)
Client->>Server: request (id: 2, original params + inputResponses)
Server-->>Client: response
```
## Subscribe and Notify
To receive change notifications (list changes, resource updates), the client
sends a
[`subscriptions/listen`](/specification/draft/basic/patterns/subscriptions)
request; the reply is a long-lived stream of the requested notification
types. Stream state is scoped to the request: if the underlying channel is
lost, the client re-issues the request.
```mermaid theme={null}
sequenceDiagram
participant Client
participant Server
Client->>Server: subscriptions/listen
Server-->>Client: notifications/subscriptions/acknowledged
note over Client,Server: Stream stays open
Server-->>Client: notifications/* (tagged with subscriptionId)
```
## Adding Patterns
All core protocol features are built from these patterns. A protocol
revision that adds a pattern defines it on this page. Transports carry new
patterns without changes, because patterns are expressed entirely in terms
of requests, responses, and notifications.
specification/draft/basic/patterns/mrtr New page · 275 lines, new page
# Multi Round-Trip Requests ## Multi Round-Trip Requests ### Core Types #### InputRequests #### InputResponses #### InputRequiredResult ### Supported Requests ### Basic Workflow #### Server Requirements (Basic Workflow) #### Client Requirements (Basic Workflow) ### Error Handling ### Security Considerations
A whole new page. There's nothing to diff it against, so here is what it says.
# Multi Round-Trip Requests
<div id="enable-section-numbers" />
<Note>
Multi Round-Trip Requests (MRTR) was introduced in this version of the MCP
specification. This replaces the previous approach of sending server-initiated
requests. Servers **MUST** send server-to-client requests (such as
`roots/list`, `sampling/createMessage`, or `elicitation/create`) using the
MRTR pattern. The previous pattern of server-initiated requests is no longer
supported. This is a breaking change.
</Note>
<Note>
For brevity, the request examples on this page omit the `_meta` request
metadata (`io.modelcontextprotocol/protocolVersion`,
`io.modelcontextprotocol/clientInfo`, and
`io.modelcontextprotocol/clientCapabilities`). Every request **MUST** include
the required `_meta` fields; see
[`_meta`](/specification/draft/basic/index#meta).
</Note>
## Multi Round-Trip Requests
The Model Context Protocol (MCP) defines several ways for servers to request additional information
from users during the processing of client requests (such as
`roots/list`, `sampling/createMessage`, or `elicitation/create`). The **multi round-trip requests** pattern
provides a standardized way to handle these server-requests without requiring a shared storage layer across
server instances or requiring stateful load balancing.
The high level flow functions as follows:
1. Client sends an initial request to the server with the parameters needed to perform the operation.
2. Server determines that additional information is required to fulfill the request and responds requesting more information.
3. Client gathers the requested information from the user or other sources, then retries the original request including the additional requested information.
4. Server determines it has sufficient information to complete the operation, and responds with the final result.
```mermaid theme={null}
sequenceDiagram
participant C as Client
participant S as Server
C->>S: client request (id: 1, request params)
note over S: Server needs more info <br/> to process request.
S-->>C: Request for additional input.
note over C: Client gathers input and <br/> retries initial request.
C->>S: client request (id: 2, request params, requested input)
note over S: Server has enough information <br/> to complete the request.
S-->>C: Result (id: 2, result)
```
### Core Types
This flow is implemented in MCP using the following Types.
#### InputRequests
An [`InputRequests`](/specification/draft/schema#inputrequests) object is a map of server-client requests.
Keys are server-assigned string identifiers;
values are request objects (e.g., [`ElicitRequest`](/specification/draft/schema#elicitrequest), [`CreateMessageRequest`](/specification/draft/schema#createmessagerequest), or [`ListRootsRequest`](/specification/draft/schema#listrootsrequest)).
```json theme={null}
{
"github_login": {
"method": "elicitation/create",
"params": {
"mode": "form",
"message": "Please provide your GitHub username",
"requestedSchema": {
"type": "object",
"properties": {
"name": { "type": "string" }
},
"required": ["name"]
}
}
},
"capital_of_france": {
"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
}
}
}
```
#### InputResponses
An [`InputResponses`](/specification/draft/schema#inputresponses) object is a map of client responses to the server requests.
Keys correspond to the keys in the `InputRequests` map; values are the client's result for each request (e.g., [`ElicitResult`](/specification/draft/schema#elicitresult), [`CreateMessageResult`](/specification/draft/schema#createmessageresult), or [`ListRootsResult`](/specification/draft/schema#listrootsresult)).
```json theme={null}
{
"github_login": {
"action": "accept",
"content": {
"name": "octocat"
}
},
"capital_of_france": {
"role": "assistant",
"content": {
"type": "text",
"text": "The capital of France is Paris."
},
"model": "claude-3-sonnet-20240307",
"stopReason": "endTurn"
}
}
```
#### InputRequiredResult
An [`InputRequiredResult`](/specification/draft/schema#inputrequiredresult) is a type of [`Result`](/specification/draft/basic#responses),
indicating that additional input is needed before the request can be completed.
* `inputRequests` *(optional)*: An [`InputRequests`](/specification/draft/schema#inputrequests) map of server-initiated requests that the client must fulfill.
* `requestState` *(optional)*: An opaque string meaningful only to the server. Clients **MUST NOT** inspect, parse, modify, or make any assumptions about its contents.
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"resultType": "input_required",
"inputRequests": {
// Elicitation request.
"github_login": {
"method": "elicitation/create",
"params": {
"mode": "form",
"message": "Please provide your GitHub username",
"requestedSchema": {
"type": "object",
"properties": {
"name": { "type": "string" }
},
"required": ["name"]
}
}
},
// Sampling request.
"capital_of_france": {
"method": "sampling/createMessage",
"params": {
"messages": [
{
"role": "user",
"content": {
"type": "text",
"text": "What is the capital of France?"
}
}
],
"modelPreferences": {
"hints": [{ "name": "claude-3-sonnet" }],
"intelligencePriority": 0.8,
"speedPriority": 0.5
},
"systemPrompt": "You are a helpful assistant.",
"maxTokens": 100
}
}
},
"requestState": "AEAD-protected blob"
}
}
```
### Supported Requests
Servers **MAY** send `InputRequiredResult` responses on the following client requests:
| Client Request | Supports InputRequiredResult |
| --------------------------------------------------------------------------- | ---------------------------- |
| [`prompts/get`](/specification/draft/server/prompts#getting-a-prompt) | Yes |
| [`resources/read`](/specification/draft/server/resources#reading-resources) | Yes |
| [`tools/call`](/specification/draft/server/tools#calling-tools) | Yes |
Servers **MUST NOT** send `InputRequiredResult` responses on any other client requests.
### Basic Workflow
The basic workflow describes how a server can request additional input from the client as part of a client-server request.
In this example we use `tools/call` as the client request, but the same pattern applies to any of the supported requests listed above.
Notably, it allows servers to request additional information without maintaining any server-side state.
The server encodes any needed context into the `requestState` field, which the client echoes back on retry.
```mermaid theme={null}
sequenceDiagram
participant U as User
participant C as Client
participant S as Server
C->>S: tools/call (id: 1)
note over S: Server needs more info via Elicitation
S-->>C: InputRequiredResult (id: 1, ElicitRequest, requestState)
note over C,S: Initial Request Terminated
C->>U: Prompts user for input
U-->>C: Provides responses
note over C: Client retries tool call <br/> with inputResponses and requestState
C->>S: tools/call (id: 2, ElicitResult, requestState)
note over S: Server reconstitutes state<br/>Completes execution
S-->>C: Result (id: 2, ToolCallResult)
```
Note that the requests in each step are completely independent: the server processing the retry does not need any information beyond
what is directly present in the retry request.
#### Server Requirements (Basic Workflow)
1. Servers **MAY** respond to any [supported client request](#supported-requests) with an `InputRequiredResult`.
2. The `InputRequiredResult` **MAY** include an `inputRequests` field.
* `inputRequests` keys are server assigned identifiers and **MUST** be unique within the scope of the request.
* `inputRequests` values are request objects that **MUST** be one of [`ElicitRequest`](/specification/draft/schema#elicitrequest), [`CreateMessageRequest`](/specification/draft/schema#createmessagerequest), or [`ListRootsRequest`](/specification/draft/schema#listrootsrequest)
3. The `InputRequiredResult` **MAY** include a `requestState` field. If specified, this field is an opaque string meaningful only to the server. Servers are free to encode the state in any format (e.g. base64-encoded JSON, encrypted JWT, serialized binary).
4. If a client request contains a `requestState` field, servers **MUST** treat `requestState` as an attacker-controlled input. If `requestState` influences authorization, resource access, or business logic, servers **MUST** protect its integrity (e.g. HMAC or AEAD)
and **MUST** reject state that fails verification. Integrity protection **MAY** be omitted only when tampering can cause nothing worse than request failure.
5. To prevent replay, servers **SHOULD** include the following inside the integrity-protected `requestState` payload and verify each on receipt:
* the authenticated principal, rejecting state presented by a different principal.
* a short expiry (TTL), rejecting state presented after it lapses;
* an identifier for the originating request, e.g. the method name and a digest of its salient parameters, rejecting state presented on a request that does not match.
<Warning>
Note that these measures bound the replay window and prevent cross-user
and cross-request reuse, but do not by themselves guarantee single-use.
Servers for which a given `requestState` must be consumed at most once
(e.g., one-time redemptions) **MUST** enforce that invariant server-side.
</Warning>
6. Servers **MUST** include at least one of `inputRequests` or `requestState` in every `InputRequiredResult` response.
7. Servers **MUST NOT** send an `inputRequests` that the client has not declared support for in its capabilities. For example, if a client does not declare support for `elicitation`, the server **MUST NOT** include any `elicitation/create` requests in the `inputRequests` field.
8. Servers **MUST NOT** assume that clients will fulfill the `inputRequests` or retry the original request. Servers **MAY** choose to return an `InputRequiredResult` on multiple attempts at the same request if they want to repeatedly prompt the user for information until they have what they need to complete the request.
#### Client Requirements (Basic Workflow)
1. If a client receives an `InputRequiredResult` that contains the `inputRequests` field, the client **MUST** construct the requested
inputs before retrying the original request. If the `InputRequiredResult` does *not* contain the `inputRequests` field,
the client **MAY** retry the original request immediately.
2. If an `InputRequiredResult` contains the `requestState` field, the client **MUST** echo back the exact value of that field when retrying the original request.
Clients **MUST NOT** inspect, parse, modify, or make any assumptions about the `requestState` contents. If the `InputRequiredResult` does not contain a `requestState` field, the client **MUST NOT** include one in the retry.
3. The JSON-RPC `id` **MUST** be different between the initial request and the retry, as they are independent requests.
4. Both the `inputRequests` and `requestState` fields affect only the client's retry of the original request. They **MUST NOT** be used for any other request that the client may be sending in parallel.
### Error Handling
Servers **SHOULD** validate that the data provided by the client is a valid `InputResponses` object and that the information inside can be correctly parsed.
Protocol errors (malformed JSON, invalid schema, internal server errors) **SHOULD** return a JSON-RPC error response with an appropriate error code and message.
If additional, unexpected parameters are provided in the `InputResponses` object, the server **SHOULD** ignore any information it does not recognize or need.
If the client fails to send all the information requested in a previous `InputRequests`, and the missing information is necessary for the server to process the request,
the server **SHOULD** respond with a new `InputRequiredResult` requesting the missing information again, rather than returning an error.
### Security Considerations
Because `requestState` passes through the client, malicious or compromised clients could attempt to modify it to alter server behavior,
bypass authorization checks, or corrupt server logic. Servers **MUST** validate request state as described in the [server requirements](#server-requirements-basic-workflow) above.
specification/draft/basic/patterns/progress New page · 88 lines, new page
# Progress ## Progress Flow ## Behavior Requirements ## Implementation Notes
A whole new page. There's nothing to diff it against, so here is what it says.
# Progress
<div id="enable-section-numbers" />
The Model Context Protocol (MCP) supports optional progress tracking for long-running
operations through notification messages. The server **MAY** send progress notifications
to report the status of requests the client has issued.
## Progress Flow
When a client wants to *receive* progress updates for a request, it includes a
`progressToken` in the request metadata.
* Progress tokens **MUST** be a string or integer value
* Progress tokens can be chosen by the client using any means, but **MUST** be unique
across all active requests.
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"method": "some_method",
"params": {
"_meta": {
"progressToken": "abc123"
}
}
}
```
The server **MAY** then send progress notifications containing:
* The original progress token
* The current progress value so far
* An optional "total" value
* An optional "message" value
```json theme={null}
{
"jsonrpc": "2.0",
"method": "notifications/progress",
"params": {
"progressToken": "abc123",
"progress": 50,
"total": 100,
"message": "Reticulating splines..."
}
}
```
* The `progress` value **MUST** increase with each notification, even if the total is
unknown.
* The `progress` and the `total` values **MAY** be floating point.
* The `message` field **SHOULD** provide relevant human readable progress information.
## Behavior Requirements
1. Progress notifications **MUST** only reference tokens that:
* Were provided in an active request
* Are associated with an in-progress operation
2. Servers receiving a request with a progress token **MAY**:
* Choose not to send any progress notifications
* Send notifications at whatever frequency they deem appropriate
* Omit the total value if unknown
```mermaid theme={null}
sequenceDiagram
participant Client
participant Server
Note over Client,Server: Request with progress token
Client->>Server: Method request with progressToken
Note over Client,Server: Progress updates
Server-->>Client: Progress notification (0.2/1.0)
Server-->>Client: Progress notification (0.6/1.0)
Server-->>Client: Progress notification (1.0/1.0)
Note over Client,Server: Operation complete
Server->>Client: Method response
```
## Implementation Notes
* Clients and servers **SHOULD** track active progress tokens
* Both parties **SHOULD** implement rate limiting to prevent flooding
* Progress notifications **MUST** stop after completion
specification/draft/basic/patterns/subscriptions New page · 164 lines, new page
# Subscriptions ## Opening a Stream ### Notification Filter ## Acknowledgment ## Receiving Notifications ## Multiple Concurrent Subscriptions ## Cancellation ### Graceful Closure
A whole new page. There's nothing to diff it against, so here is what it says.
# Subscriptions
<div id="enable-section-numbers" />
`subscriptions/listen` opens a long-lived notification stream from the server to the
client. Unlike one-off requests, the stream stays open and delivers notifications until
the client cancels it. It replaces the former `resources/subscribe` RPC and the HTTP GET
endpoint.
## Opening a Stream
The client sends a `subscriptions/listen` request with a `notifications` filter
specifying which event types it wants to receive. The server **MUST NOT** send
notification types the client has not explicitly requested.
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"method": "subscriptions/listen",
"params": {
"_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientInfo": {
"name": "ExampleClient",
"version": "1.0.0"
},
"io.modelcontextprotocol/clientCapabilities": {}
},
"notifications": {
"toolsListChanged": true,
"resourceSubscriptions": ["file:///project/config.json"]
}
}
}
```
### Notification Filter
| Field | Type | Description |
| ----------------------- | ---------- | ----------------------------------------------------------------- |
| `toolsListChanged` | `boolean` | Receive `notifications/tools/list_changed` when tools change |
| `promptsListChanged` | `boolean` | Receive `notifications/prompts/list_changed` when prompts change |
| `resourcesListChanged` | `boolean` | Receive `notifications/resources/list_changed` when list changes |
| `resourceSubscriptions` | `string[]` | Receive `notifications/resources/updated` for these resource URIs |
All fields are optional. Omitting a field is equivalent to not subscribing to that
notification type.
## Acknowledgment
The server **MUST** send `notifications/subscriptions/acknowledged` as the first message
carrying the subscription's ID in `_meta` under `io.modelcontextprotocol/subscriptionId`,
and **MUST NOT** send any notification on the
subscription before it. On stdio, where every subscription shares one channel, this
ordering is defined per subscription ID and not per channel: messages belonging to other
subscriptions **MAY** be interleaved before it.
The `notifications` field in the acknowledgment reflects the subset the server agreed to
honor. Notification types the server does not support are omitted.
```json theme={null}
{
"jsonrpc": "2.0",
"method": "notifications/subscriptions/acknowledged",
"params": {
"_meta": {
"io.modelcontextprotocol/subscriptionId": 1
},
"notifications": {
"toolsListChanged": true,
"resourceSubscriptions": ["file:///project/config.json"]
}
}
}
```
The client **SHOULD** check the acknowledged filter against what it requested and handle
any unsupported types gracefully.
## Receiving Notifications
All notifications delivered on the stream carry
`io.modelcontextprotocol/subscriptionId` in `_meta`, identifying the
`subscriptions/listen` request that opened the stream. The value is the JSON-RPC ID of
the `subscriptions/listen` request. In the examples above, the request used `"id": 1`,
so the acknowledgment and all subsequent notifications carry the subscription ID `1`.
On stdio, where all messages
share a single channel, clients **MUST** use this field to correlate notifications
with their originating subscription.
```json theme={null}
{
"jsonrpc": "2.0",
"method": "notifications/resources/updated",
"params": {
"_meta": {
"io.modelcontextprotocol/subscriptionId": 1
},
"uri": "file:///project/config.json"
}
}
```
## Multiple Concurrent Subscriptions
A client **MAY** have multiple active subscriptions concurrently — for example,
one listening for tools-list changes and another for resource updates. Each
subscription is identified by the JSON-RPC request ID of its
`subscriptions/listen` request, and every notification on the stream carries
that ID in
`io.modelcontextprotocol/subscriptionId` so clients can demultiplex them.
## Cancellation
A subscription ends when:
* The **client** cancels it — close the SSE stream (HTTP) or send
`notifications/cancelled` referencing the `subscriptions/listen` request ID (stdio).
* The **server** tears it down (e.g., during shutdown) — it **SHOULD** send a
successful `subscriptions/listen` response to signal a graceful end (see
[Graceful Closure](#graceful-closure)), then close the stream.
* The underlying transport closes (HTTP timeout, TCP disconnect, stdio process
exit).
### Graceful Closure
When the server ends a subscription on its own initiative (for example, during
shutdown), it **SHOULD** respond to the original `subscriptions/listen` request
with a completion result before closing the stream. The result carries no
method-specific data beyond the standard result fields and subscription
metadata. This is the JSON-RPC response to the long-lived request, correlated by
its `id`, and signals that the subscription ended gracefully — as opposed to an
abrupt transport drop, which carries no response.
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"resultType": "complete",
"_meta": {
"io.modelcontextprotocol/subscriptionId": 1
}
}
}
```
Like every other message on the stream, the response carries
`io.modelcontextprotocol/subscriptionId` in `_meta`, identifying which
subscription it closes. The value matches the JSON-RPC `id` of the originating
`subscriptions/listen` request.
A client that receives this response knows the subscription closed cleanly; a
transport that closes without it indicates an unexpected disconnect, which the
client **MAY** treat as a trigger to reconnect.
On **stdio**, if the connection is terminated and then re-established, the
client **MUST** re-send `subscriptions/listen` to re-establish its
subscriptions — the server holds no subscription state across reconnections.
See [Cancellation][cancellation] for the full rules.
[cancellation]: /specification/draft/basic/patterns/cancellation
specification/draft/basic/transports/index New page · 87 lines, new page
# Overview ## Messages ## Request Metadata ## Cancellation ## Custom Transports ## Backward Compatibility
A whole new page. There's nothing to diff it against, so here is what it says.
# Overview <div id="enable-section-numbers" /> This page defines what a transport must provide to carry MCP messages, the standard transport bindings, and the requirements for defining new ones. Protocol semantics are identical on every transport. A transport is a **binding**: it defines how messages are framed and delivered, how request metadata is carried, and how cancellation and termination are signaled. It does not define what the messages mean: the [message patterns](/specification/draft/basic/patterns) are part of the core protocol and are the same on every binding. The binding pages specify the standard transports: 1. [stdio](/specification/draft/basic/transports/stdio): newline-delimited messages over the standard streams of a client-launched subprocess. 2. [Streamable HTTP](/specification/draft/basic/transports/streamable-http): each message is an HTTP POST to a single MCP endpoint; replies arrive as a JSON object or a request-scoped SSE stream. It is also possible for clients and servers to implement [custom transports](#custom-transports). ## Messages MCP uses JSON-RPC to encode messages. JSON-RPC messages **MUST** be UTF-8 encoded. A binding **MUST** deliver client-sent *requests* and *notifications* to the server, and server-sent *responses* and *notifications* to the client. No other message direction exists: per the [message patterns](/specification/draft/basic/patterns), servers do not initiate JSON-RPC requests and clients do not send JSON-RPC responses. ## Request Metadata All protocol metadata travels in the message body: every request carries its protocol version and client capabilities in [`_meta.io.modelcontextprotocol/*`](/specification/draft/basic/index#meta) fields. A binding **MAY** additionally mirror selected body fields into envelope metadata. The Streamable HTTP transport mirrors them into [HTTP headers](/specification/draft/basic/transports/streamable-http#request-metadata) so that intermediaries can route and inspect requests without parsing the body. The body remains the source of truth; bindings that mirror metadata define how mismatches are rejected. ## Cancellation Each binding defines how a client abandons an in-flight request: on stdio the client sends a `notifications/cancelled` notification; on Streamable HTTP it closes the request's response stream. The protocol-level rules are the same everywhere; see [Cancellation](/specification/draft/basic/patterns/cancellation). ## Custom Transports Clients and servers **MAY** implement additional custom transport mechanisms to suit their specific needs. The protocol is transport-agnostic and can be implemented over any communication channel that supports bidirectional message exchange. Implementers who choose to support custom transports **MUST** preserve the JSON-RPC message format, the [message patterns](/specification/draft/basic/patterns), and the per-request metadata model. Custom transports **SHOULD** document their connection establishment, message framing, and cancellation patterns to aid interoperability. Custom transports that run over a reliable bidirectional byte stream (e.g., Unix domain sockets or TCP) **SHOULD** reuse the [stdio framing](/specification/draft/basic/transports/stdio) rather than defining a new one: the stdio binding is just newline-delimited JSON-RPC over a byte stream, and only its process-lifecycle rules are specific to standard streams. ## Backward Compatibility Earlier protocol revisions established a connection-scoped session with an `initialize` handshake and allowed servers to initiate JSON-RPC requests. Clients and servers that interoperate with those revisions detect the counterpart's era and fall back as described in [Versioning: Backward Compatibility](/specification/draft/basic/versioning#backward-compatibility-with-initialization-based-versions), which includes a compatibility matrix for implementors. Each binding page describes its transport-specific detection mechanics.
specification/draft/basic/transports/stdio New page · 159 lines, new page
# stdio ## Sending Messages ## Receiving Messages ## Request Metadata ## Cancellation ## Shutdown ## Unexpected Termination ## Backward Compatibility
A whole new page. There's nothing to diff it against, so here is what it says.
# stdio <div id="enable-section-numbers" /> In the **stdio** transport, the client launches the MCP server as a subprocess. The two ends communicate over the subprocess's standard streams: * The server reads JSON-RPC messages from `stdin` and writes JSON-RPC messages to `stdout`. * Each message is a single JSON-RPC request, notification, or response. * Messages are delimited by newlines, and **MUST NOT** contain embedded newlines. * The server **MAY** write UTF-8 strings to `stderr` for any logging purposes including informational, debug, and error messages. * The client **MAY** capture, forward, or ignore the server's `stderr` output and **SHOULD NOT** assume `stderr` output indicates error conditions. * The server **MUST NOT** write anything to its `stdout` that is not a valid MCP message. * The client **MUST NOT** write anything to the server's `stdin` that is not a valid MCP message. Standard streams are the canonical channel, but nothing in this binding depends on them except the process lifecycle. The wire format (one newline-delimited JSON-RPC message per line over a reliable bidirectional byte stream) works unchanged over Unix domain sockets, TCP connections, or any similar channel. [Custom transports](/specification/draft/basic/transports#custom-transports) built on such streams **SHOULD** reuse this framing and the message rules on this page; only the subprocess-specific aspects (launch, `stderr`, shutdown by closing the stream, process restart) need channel-specific equivalents. ## Sending Messages The client sends messages by writing JSON-RPC *requests* and *notifications* to the server's `stdin`, one message per line. The client **MUST NOT** write JSON-RPC *responses*. ## Receiving Messages The client reads server messages from `stdout`, one message per line. All messages share this single channel; there are no per-request streams. The server writes three kinds of messages: 1. *Responses* to client requests, correlated by JSON-RPC `id`. 2. *Notifications* that relate to an in-flight request, such as `notifications/progress` and `notifications/message`. 3. *Notifications* delivered for an active [`subscriptions/listen`][subscriptions-listen] request. Clients **MUST** correlate these using the `io.modelcontextprotocol/subscriptionId` field in `_meta`; see [`SubscriptionsListenRequest`][subscriptions-listen-request]. The server **MUST NOT** write JSON-RPC *requests* to `stdout`. Server-to-client interactions are carried in [`InputRequiredResult`][mrtr-input-required] replies; see [Multi Round-Trip Requests][mrtr]. [mrtr]: /specification/draft/basic/patterns/mrtr [mrtr-input-required]: /specification/draft/basic/patterns/mrtr#inputrequiredresult [subscriptions-listen]: /specification/draft/basic/patterns/subscriptions [subscriptions-listen-request]: /specification/draft/schema#subscriptionslistenrequest ## Request Metadata All request metadata for the stdio transport is carried inline in the JSON-RPC message body. The protocol version, per-request capabilities, and optional client identity live in [`_meta.io.modelcontextprotocol/*`][meta-fields]; the method name and arguments live where JSON-RPC puts them. There is no header layer. [meta-fields]: /specification/draft/basic/index#meta ## Cancellation To cancel an in-flight request, the client **MUST** send a `notifications/cancelled` notification referencing the request's ID. Because stdio is a single shared bidirectional channel, there is no per-request stream to close. Servers **SHOULD** stop work on a cancelled request as soon as practical and **MUST NOT** send any further messages for it. See [Cancellation][cancellation] for the full rules. [cancellation]: /specification/draft/basic/patterns/cancellation ## Shutdown The client **SHOULD** initiate shutdown by: 1. Closing the input stream to the child process (the server). 2. Waiting for the server to exit. 3. If the server does not exit within a reasonable time, forcibly terminating the process using the mechanism appropriate for the operating system. On POSIX systems, forced termination typically escalates from [`SIGTERM`][sigterm] to `SIGKILL`. On Windows, where POSIX signals are not available, clients can use [`TerminateProcess`][terminateprocess] or [Job Objects][job-objects]. Servers **SHOULD** exit promptly when their standard input is closed or reads return end-of-file. This is the primary graceful-shutdown signal and the only portable one, so honoring it reduces the need for forced termination. The server **MAY** initiate shutdown by closing its output stream to the client and exiting. ## Unexpected Termination If the server process exits unexpectedly, the client **SHOULD** restart it. Because the protocol is stateless, any in-flight requests are simply lost and the client can retry them against the fresh process. Active [`subscriptions/listen`][subscriptions-listen] streams must also be re-established after restart. [sigterm]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/signal.h.html [terminateprocess]: https://learn.microsoft.com/windows/win32/api/processthreadsapi/nf-processthreadsapi-terminateprocess [job-objects]: https://learn.microsoft.com/windows/win32/procthread/job-objects ## Backward Compatibility A client that supports both modern (per-request-metadata) MCP versions and a legacy version that requires an `initialize` handshake **SHOULD** probe with [`server/discover`][server-discover] before sending any other request, setting its preferred modern version in `_meta`. The probe has three possible outcomes: * The server returns a `DiscoverResult`: the server is modern. Select a mutually supported version from `supportedVersions` and continue. * The server returns a recognized modern JSON-RPC error such as [`UnsupportedProtocolVersionError`][unsupported-version]: the server is modern but does not support the requested version. Use one of the versions in its advertised `supported` list. Do **not** fall back to `initialize`. * The server returns any other error, or does not respond within a reasonable timeout: the server is legacy. Fall back to the `initialize` handshake. The fallback **MUST NOT** be keyed to one specific error code: legacy servers respond to unknown pre-`initialize` requests with implementation-defined errors (commonly `-32601` or `-32602`) or not at all. A client that only supports modern versions does not need to probe, but probing is still **RECOMMENDED**: some legacy servers do not validate that a request arrives after `initialize` and would process an era-ambiguous method (such as `tools/call`) under legacy semantics. Probing yields a deterministic failure instead. See [Versioning: Backward Compatibility][lifecycle-compat] for the era model and a compatibility matrix for implementors. [server-discover]: /specification/draft/schema#discoverrequest [unsupported-version]: /specification/draft/schema#unsupportedprotocolversionerror [lifecycle-compat]: /specification/draft/basic/versioning#backward-compatibility-with-initialization-based-versions
specification/draft/basic/transports/streamable-http New page · 731 lines, new page
# Streamable HTTP ## Security & Endpoint ## Sending Messages ## Receiving Messages ## Message Flow ## Cancellation ## Request Metadata ### Protocol Version Header ### Standard Request Headers ### Custom Headers from Tool Parameters #### Schema Extension #### Value Encoding #### Client Behavior #### Server Behavior for Custom Headers ### Case Sensitivity ### Server Validation ## Backward Compatibility ### Earlier Streamable HTTP Revisions ### HTTP+SSE Transport (2024-11-05)
A whole new page. There's nothing to diff it against, so here is what it says.
# Streamable HTTP
<div id="enable-section-numbers" />
<Info>
Streamable HTTP was introduced in protocol version 2025-03-26 as a replacement
for the [HTTP+SSE transport][http-sse] from protocol version 2024-11-05.
</Info>
<Info>
Revision 2026-07-28 changed the behavior of Streamable HTTP. Clients must
ensure they handle backwards compatibility correctly. Changes included:
* Removal of the GET stream endpoint.
* Removal of protocol-level sessions.
See the [changelog](/specification/draft/changelog) and
[Backward Compatibility](#backward-compatibility) below.
</Info>
In the **Streamable HTTP** transport, the server operates as an independent
process that can handle multiple client connections. At a glance:
* The server exposes a single HTTP endpoint (the **MCP endpoint**) that
accepts POST.
* The client sends every JSON-RPC request or notification as its own HTTP
POST.
* The server answers each request with either a single JSON object or a
[Server-Sent Events][sse] (SSE) stream scoped to that request, carrying
request-related notifications followed by the final response.
* Server-to-client interactions (sampling, elicitation, roots) are embedded
in results as input requests per
[Multi Round-Trip Requests (MRTR)][mrtr] ([SEP-2322][sep-2322]).
* Long-lived change notifications (such as list changes and resource updates)
are delivered on the response stream of a
[`subscriptions/listen`][subscriptions-listen] request.
See [Message Flow](#message-flow) for sequence diagrams of these
interactions.
The server **MUST** provide a single HTTP endpoint path (hereafter referred to
as the **MCP endpoint**) that supports POST. For example, this could be a URL
like `https://example.com/mcp`.
[http-sse]: /specification/2024-11-05/basic/transports#http-with-sse
[sse]: https://en.wikipedia.org/wiki/Server-sent_events
## Security & Endpoint
When implementing Streamable HTTP transport:
1. Servers **MUST** validate the `Origin` header on all incoming connections
to prevent DNS rebinding attacks.
* If the `Origin` header is present and invalid, servers **MUST** respond
with HTTP 403 Forbidden. The HTTP response body **MAY** comprise a
JSON-RPC *error response* that has no `id`.
2. When running locally, servers **SHOULD** bind only to localhost
(127.0.0.1) rather than all network interfaces (0.0.0.0).
3. Servers **SHOULD** implement proper authentication for all connections.
Without these protections, attackers could use DNS rebinding to interact with
local MCP servers from remote websites.
## Sending Messages
Every JSON-RPC message sent from the client **MUST** be a new HTTP POST
request to the MCP endpoint.
1. The client **MUST** use HTTP POST to send JSON-RPC messages.
2. The client **MUST** include an `Accept` header listing both
`application/json` and `text/event-stream` as supported content types.
3. The client **MUST** include the [request metadata headers](#request-metadata)
on each POST request.
4. The body of the HTTP POST **MUST** be a single JSON-RPC *request* or
*notification*. The client **MUST NOT** send JSON-RPC *responses*.
5. If the body is a JSON-RPC *notification*:
* If the server accepts it, the server **MUST** return HTTP status code
`202 Accepted` with no body.
* If the server cannot accept it, it **MUST** return an HTTP error status
code (e.g., `400 Bad Request`). The HTTP response body **MAY** comprise
a JSON-RPC *error response* that has no `id`.
6. If the body is a JSON-RPC *request*, the server **MUST** return either
`Content-Type: application/json` (a single JSON object) or
`Content-Type: text/event-stream` (an SSE response stream). The client
**MUST** support both.
<Note>
This revision of the core protocol defines no client-to-server
*notifications* over Streamable HTTP. The only client-sent notification in
the core protocol, `notifications/cancelled`, is used only on the
[stdio](/specification/draft/basic/transports/stdio) transport; on
Streamable HTTP, closing the SSE response stream is itself the cancellation
signal and no `notifications/cancelled` message is expected (see
[Cancellation][cancellation]). The notification rules above describe the
transport mechanics for a notification POST; header requirements for
notification POSTs are not defined by this revision.
</Note>
## Receiving Messages
When the server returns an SSE response stream
(`Content-Type: text/event-stream`):
* The server **MAY** send JSON-RPC *notifications* — for example,
[`notifications/progress`][notifications-progress]
or [`notifications/message`][notifications-message] —
before the final response. These notifications **MUST** relate to the
originating client request.
* The server **MUST NOT** send independent JSON-RPC *requests* on this stream.
Server-to-client interactions (sampling, elicitation, list-roots) are
embedded as input requests inside an
[`InputRequiredResult`][input-required-result] per
[MRTR][mrtr] ([SEP-2322][sep-2322]), not delivered as separate requests on
this or any other stream. This is a change from Streamable HTTP in protocol
versions `2025-03-26` through `2025-11-25`, where servers could send such
requests on SSE streams.
* The final JSON-RPC *response* **SHOULD** terminate the stream.
Long-lived notification streams are obtained by sending a
[`subscriptions/listen`][subscriptions-listen]
request. The server's response is itself an SSE stream that stays open and
delivers the change notifications the client opted in to (such as
`notifications/tools/list_changed` or `notifications/resources/updated`).
Request-scoped notifications like `notifications/progress` and
`notifications/message` are **not** delivered on the listen stream — they
flow only on the response stream of the request they relate to.
When initiating an SSE stream, servers **SHOULD** include the
`X-Accel-Buffering: no` header in the HTTP response. This instructs reverse
proxies (such as nginx) to disable response buffering, ensuring that SSE
events are delivered to clients immediately rather than being held in a
buffer. Without this header, proxies may accumulate messages before sending
them to the client, introducing unwanted latency and potentially breaking the
real-time nature of SSE communication.
<Note>
For long-lived streams — in particular the
[`subscriptions/listen`][subscriptions-listen] response stream — servers are
encouraged to periodically emit an SSE comment line (a line beginning with a
colon, e.g. `:\r\n`) as a keep-alive. This keeps the connection from being
closed by intermediaries or client idle timeouts during quiet periods when no
notifications are flowing. Per the [SSE specification][sse], any line beginning
with a colon is a comment that carries no event data; clients must ignore such
lines and must not treat them as malformed input.
</Note>
Resumable SSE streams via `Last-Event-ID` are not supported.
[notifications-progress]: /specification/draft/basic/patterns/progress
[notifications-message]: /specification/draft/server/utilities/logging
[input-required-result]: /specification/draft/schema#inputrequiredresult
[mrtr]: /specification/draft/basic/patterns/mrtr
[sep-2322]: /seps/2322-MRTR
[subscriptions-listen]: /specification/draft/basic/patterns/subscriptions
## Message Flow
The following diagrams illustrate the message flows on a single MCP endpoint.
**Requests and responses.** Each request is its own POST; the server chooses
per request whether to respond with a single JSON object or an SSE stream:
```mermaid theme={null}
sequenceDiagram
participant Client
participant Server
note over Client,Server: Simple response
Client->>Server: POST tools/call (JSON-RPC request)
Server-->>Client: 200 OK, application/json<br/>JSON-RPC response
note over Client,Server: Streaming response
Client->>Server: POST tools/call (JSON-RPC request)
note over Server: Opens SSE stream<br/>scoped to this request
Server-->>Client: SSE: notifications/progress
Server-->>Client: SSE: notifications/progress
Server-->>Client: SSE: JSON-RPC response
note over Client,Server: Stream closes
note over Client,Server: Notification
Client->>Server: POST (JSON-RPC notification)
Server-->>Client: 202 Accepted
```
**Server-to-client interactions (MRTR).** When the server needs input from
the client — sampling, elicitation, or roots — it does not send its own
JSON-RPC request. It returns an
[`InputRequiredResult`][input-required-result] containing `inputRequests`,
and the client retries the original request with the matching
`inputResponses` (see [Multi Round-Trip Requests][mrtr]):
```mermaid theme={null}
sequenceDiagram
participant Client
participant Server
Client->>Server: POST tools/call (id: 1)
note over Server: Needs user input or<br/>an LLM completion
Server-->>Client: InputRequiredResult<br/>(inputRequests: elicitation/create)
note over Client: Gathers the requested input
Client->>Server: POST tools/call (id: 2)<br/>(original params + inputResponses)
Server-->>Client: Final result
```
**Change notifications.** Clients that want server-initiated change
notifications open a long-lived stream with
[`subscriptions/listen`][subscriptions-listen]; the response stream stays
open and carries only the notification types the client opted in to:
```mermaid theme={null}
sequenceDiagram
participant Client
participant Server
Client->>Server: POST subscriptions/listen<br/>(notification filter)
Server-->>Client: SSE: notifications/subscriptions/acknowledged
note over Client,Server: Stream stays open
Server-->>Client: SSE: notifications/tools/list_changed
Server-->>Client: SSE: notifications/resources/updated
note over Client,Server: Until the client or server closes the stream
```
## Cancellation
Closing the SSE response stream **MUST** be treated by the server as
cancellation of that request. Because each request has its own response
stream, the transport-level disconnect is unambiguous. The server **SHOULD**
stop work on the cancelled request as soon as practical and **MUST NOT** send
any further messages for it. See
[Cancellation][cancellation] for the full rules.
[cancellation]: /specification/draft/basic/patterns/cancellation
## Request Metadata
The Streamable HTTP transport mirrors selected JSON-RPC body fields into HTTP
headers so that intermediaries (load balancers, gateways, observability
tooling) can route and inspect requests without parsing the body.
### Protocol Version Header
Every POST request to the MCP endpoint **MUST** include an
`MCP-Protocol-Version` header.
For example: `MCP-Protocol-Version: 2026-07-28`
The header value **MUST** match the
`io.modelcontextprotocol/protocolVersion` field carried in the request body's
`_meta`. If the values do not match, the server **MUST** reject the request
with `400 Bad Request` and a `HeaderMismatch` JSON-RPC error
(see [Server Validation](#server-validation)).
If the server does not implement the requested protocol version (whether the
version is unknown to the server, or is a known version the server has chosen
not to support), it **MUST** respond with `400 Bad Request` and an
[`UnsupportedProtocolVersionError`][unsupported-version]
listing its supported versions. See
[Versioning: Protocol Version Negotiation][lifecycle-version]
for the negotiation flow.
If the server does not implement the requested RPC method, it **MUST** respond
with `404 Not Found` and a JSON-RPC error with code `-32601`
(`Method not found`). The JSON-RPC error body distinguishes this case from a
`404` returned by a legacy [HTTP+SSE][http-sse] server that does not host the
modern MCP endpoint (see [Backward Compatibility](#backward-compatibility)).
A server that supports clients implementing protocol versions earlier than
`2025-06-18` (which did not define the `MCP-Protocol-Version` header) **MAY**
treat a request that omits the header as protocol version `2025-03-26`. A
server that does not support such clients **MUST** reject a request without
the header per [Server Validation](#server-validation).
[unsupported-version]: /specification/draft/schema#unsupportedprotocolversionerror
[lifecycle-version]: /specification/draft/basic/versioning#protocol-version-negotiation
### Standard Request Headers
| Header Name | Source Field | Required For |
| ------------ | ----------------------------- | ------------------------------------------------------ |
| `Mcp-Method` | `method` | All requests |
| `Mcp-Name` | `params.name` or `params.uri` | `tools/call`, `resources/read`, `prompts/get` requests |
These headers are **REQUIRED** for compliance.
If the `Mcp-Name` source value cannot be safely represented as a plain ASCII
header value, clients **MUST** encode it using the Base64 sentinel format
described in [Value Encoding](#value-encoding).
**`tools/call` request:**
```http theme={null}
POST /mcp HTTP/1.1
Content-Type: application/json
Cut at 300 lines. The page has the rest.
specification/draft/basic/versioning New page · 181 lines, new page
# Versioning and Compatibility ## Terminology ## Protocol Version Negotiation ## Extension Negotiation ## Backward Compatibility with Initialization-Based Versions ### Compatibility Matrix
A whole new page. There's nothing to diff it against, so here is what it says.
# Versioning and Compatibility
<div id="enable-section-numbers" />
This page defines how a client and server agree on what they are speaking:
the protocol version, declared on every request; optional extensions,
negotiated through capabilities; and interoperability with earlier,
handshake-based protocol revisions.
There is no negotiation handshake. Every request carries its protocol
version, and the server accepts or rejects each request independently:
```mermaid theme={null}
sequenceDiagram
participant Client
participant Server
Client->>Server: request (with `_meta`)
alt server supports requested version
Server-->>Client: result
else version unsupported
Server-->>Client: UnsupportedProtocolVersionError
Note over Client,Server: Client retries with a mutually supported version
end
```
## Terminology
This page uses the following terms for interoperability across protocol
revisions:
* **Modern**: protocol versions that convey version, identity, and
capabilities as per-request metadata (revision `2026-07-28` and later).
* **Legacy**: protocol versions that establish a session with an
`initialize` handshake (`2025-11-25` and earlier).
* **Dual-era**: an implementation that supports both modern and legacy
versions.
## Protocol Version Negotiation
Every request declares the protocol version it is using in its
[`_meta`](/specification/draft/basic/index#meta) field. On HTTP, this is
also carried in the
[`MCP-Protocol-Version` header](/specification/draft/basic/transports/streamable-http#protocol-version-header).
If the server does not implement the requested version (whether the version
is unknown to the server, or is a known version the server has chosen not to
support), it **MUST** respond with an
[`UnsupportedProtocolVersionError`](/specification/draft/schema#unsupportedprotocolversionerror)
listing the versions it does support:
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32022,
"message": "Unsupported protocol version",
"data": {
"supported": ["2026-07-28", "2025-11-25"],
"requested": "1900-01-01"
}
}
}
```
The client **SHOULD** select a mutually supported version from the `supported`
list and retry the request, or surface an error to the user if no compatible
version exists.
Servers **MUST** implement
[`server/discover`](/specification/draft/server/discover). Clients
**MAY** call it before sending any other requests to learn the server's
supported versions up front, but are not required to: a client is free to
invoke any RPC inline and handle `UnsupportedProtocolVersionError` if its
preferred version is not supported.
## Extension Negotiation
Clients and servers can negotiate support for optional
[extensions](/docs/extensions/overview) beyond the core protocol. Extensions
are advertised in the `extensions` field of capabilities, which is a map of
extension identifiers to per-extension settings objects. Extension identifiers
**MUST** follow the [`_meta` key naming rules](/specification/draft/basic/index#meta),
with a mandatory prefix.
The following is an example of a client that advertises the
[MCP Apps extension](/extensions/apps/overview) identified as `io.modelcontextprotocol/ui`:
```json theme={null}
{
"capabilities": {
"roots": {},
"extensions": {
"io.modelcontextprotocol/ui": {
"mimeTypes": ["text/html;profile=mcp-app"]
}
}
}
}
```
An example of [Tasks extension](/extensions/tasks/overview) identified as `io.modelcontextprotocol/tasks`:
```json theme={null}
{
"capabilities": {
"tools": {},
"extensions": {
"io.modelcontextprotocol/tasks": {}
}
}
}
```
Each extension specifies the schema of its settings object; an empty object
indicates support with no additional settings.
If one party supports an extension but the other does not, the supporting
party **MUST** either revert to core protocol behavior or reject the request
with an appropriate error. Extensions **SHOULD** document their expected
fallback behavior.
## Backward Compatibility with Initialization-Based Versions
A server that wishes to support both [legacy](#terminology) clients (which
expect an `initialize` handshake) and [modern](#terminology) clients (which
use per-request metadata) **MAY** implement both behaviors.
A client that needs to interoperate with both kinds of servers detects the
server's era with transport-specific mechanics, specified in the binding
pages:
* [stdio](/specification/draft/basic/transports/stdio#backward-compatibility):
probe with `server/discover` and fall back on any error that is not a
recognized modern error.
* [Streamable HTTP](/specification/draft/basic/transports/streamable-http#backward-compatibility):
attempt a modern request and inspect the body of a `400 Bad Request`
before falling back.
In both cases, a recognized modern JSON-RPC error (such as
[`UnsupportedProtocolVersionError`](/specification/draft/schema#unsupportedprotocolversionerror))
identifies a modern server: the client retries with a supported version
rather than falling back. Anything else identifies a legacy server.
The era determination is a property of the server, not of an individual
request. Clients **SHOULD** cache the result for the lifetime of the server
process (stdio) or origin (HTTP), and **MAY** persist it across restarts of
the same server configuration, re-probing if the cached assumption later
fails.
A server that supports only [modern](#terminology) versions **SHOULD** name
the protocol versions it supports in any error it returns to an `initialize`
request, on any transport: legacy clients have no fall-forward mechanism, and
this message may be the only diagnostic they can surface to users.
### Compatibility Matrix
The following matrix summarizes the expected outcome of every combination of
client and server era:
| Client | Server | Outcome |
| -------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Modern | Modern | Works. `server/discover` is optional; version mismatches surface as `UnsupportedProtocolVersionError` and the client retries with a mutually supported version. |
| Modern | Legacy | Fails. The server may reject the request with an implementation-defined error, stay silent, or even process an era-ambiguous method under legacy semantics. On stdio, clients **SHOULD** send `server/discover` first to fail deterministically; the client then surfaces an actionable error to the user. |
| Dual-era | Modern | Works. The stdio probe returns a `DiscoverResult` (or `UnsupportedProtocolVersionError`); on HTTP, the first modern request succeeds or returns a modern error. The client stays modern. |
| Dual-era | Legacy | Works. stdio: the probe returns a non-modern error or times out, and the client falls back to `initialize`. HTTP: the modern request returns a `4xx` without a recognized modern error body, and the client falls back to `initialize` (and possibly further to the deprecated HTTP+SSE transport). |
| Legacy | Modern | Fails. stdio: the server rejects `initialize` with a JSON-RPC error; the exact code is implementation-defined (`initialize` is an unknown method and the request also lacks the required `_meta` fields). HTTP: the request is missing the required headers and is rejected per [server validation](/specification/draft/basic/transports/streamable-http#server-validation) with `400 Bad Request` (a client on the deprecated HTTP+SSE transport fails at its opening `GET` instead). Legacy clients have no fall-forward mechanism. |
| Legacy | Dual-era | Works. The server answers `initialize` and serves the client according to the negotiated legacy revision. |
| Legacy | Legacy | Works according to the legacy revision; out of scope for this document. |
A dual-era **server** selects its behavior from how the client opens:
* A request carrying modern per-request `_meta` is served statelessly
according to this revision.
* An `initialize` request selects legacy semantics, scoped to the stdio
process (stdio) or the session (HTTP), as specified by the negotiated
legacy protocol version.
A dual-era server **MAY** serve both eras concurrently on the same endpoint
or process.
specification/draft/changelog New page · 3 lines, new page
# Changelog
A whole new page. There's nothing to diff it against, so here is what it says.
# Changelog Changes since the most recent release will accumulate here.
specification/draft/client/elicitation New page · 665 lines, new page
# Elicitation ## User Interaction Model ## Capabilities ## Protocol Messages ### Elicitation Requests ### Form Mode Elicitation Requests #### Requested Schema #### Example: Simple Text Request #### Example: Structured Data Request ### URL Mode Elicitation Requests #### Example: Request Sensitive Data ## Message Flow ### Form Mode Flow ### URL Mode Flow ## Response Actions ## Implementation Considerations ### Statefulness ### URL Mode Elicitation for Sensitive Data ### URL Mode Elicitation for OAuth Flows #### Understanding the Distinction #### Implementation Pattern ## Error Handling ## Security Considerations ### Safe URL Handling ### Identifying the User ### Form Mode Security #### Phishing
A whole new page. There's nothing to diff it against, so here is what it says.
# Elicitation
<div id="enable-section-numbers" />
The Model Context Protocol (MCP) provides a standardized way for servers to request additional
information from users through the client during interactions. This flow allows clients to
maintain control over user interactions and data sharing while enabling servers to gather
necessary information dynamically.
Elicitation supports two modes:
* **Form mode**: Servers can request structured data from users with optional JSON schemas to validate responses
* **URL mode**: Servers can direct users to external URLs for sensitive interactions that must *not* pass through the MCP client
## User Interaction Model
Elicitation in MCP allows servers to implement interactive workflows by enabling user input
requests to occur *nested* inside other MCP server features.
Implementations are free to expose elicitation through any interface pattern that suits
their needs—the protocol itself does not mandate any specific user interaction
model.
<Warning>
For trust & safety and security:
* Servers **MUST NOT** use form mode elicitation to request sensitive information such as
passwords, API keys, access tokens, or payment credentials
* Servers **MUST** use [URL mode](#url-mode-elicitation-requests) for interactions involving
such sensitive information
"Sensitive information" in this context refers to secrets and credentials that grant access or
authorize transactions. General contact or profile information (such as a name, email address,
or username) is not categorically prohibited; whether to request such data via form mode is at
the discretion of the server and subject to the user's ability to review and decline.
MCP clients **MUST**:
* Provide UI that makes it clear which server is requesting information
* Respect user privacy and provide clear decline and cancel options
* For form mode, allow users to review and modify their responses before sending
* For URL mode, clearly display the target domain/host and gather user consent before navigation to the target URL
</Warning>
## Capabilities
Clients that support elicitation **MUST** declare the `elicitation` capability in
`_meta.io.modelcontextprotocol/clientCapabilities` on each request:
```json theme={null}
{
"_meta": {
"io.modelcontextprotocol/clientCapabilities": {
"elicitation": {
"form": {},
"url": {}
}
}
}
}
```
For backwards compatibility, an empty capabilities object is equivalent to declaring support for `form` mode only:
```jsonc theme={null}
{
"_meta": {
"io.modelcontextprotocol/clientCapabilities": {
"elicitation": {}, // Equivalent to { "form": {} }
},
},
}
```
Clients declaring the `elicitation` capability **MUST** support at least one mode (`form` or `url`).
Servers **MUST NOT** send elicitation requests with modes that are not supported by the client.
## Protocol Messages
### Elicitation Requests
Servers **MAY** request information from a user during the processing of a client request, by sending an [`InputRequiredResult`](/specification/draft/basic/patterns/mrtr#inputrequiredresult)
containing an `elicitation/create` request.
All elicitation requests **MUST** include the following parameters:
| Name | Type | Options | Description |
| --------- | ------ | ------------- | -------------------------------------------------------------------------------------- |
| `mode` | string | `form`, `url` | The mode of the elicitation. Optional for form mode (defaults to `"form"` if omitted). |
| `message` | string | | A human-readable message explaining why the interaction is needed. |
The `mode` parameter specifies the type of elicitation:
* `"form"`: In-band structured data collection with optional schema validation. Data is exposed to the client.
* `"url"`: Out-of-band interaction via URL navigation. Data (other than the URL itself) is **not** exposed to the client.
For backwards compatibility, servers **MAY** omit the `mode` field for form mode elicitation requests. Clients **MUST** treat requests without a `mode` field as form mode.
### Form Mode Elicitation Requests
Form mode elicitation allows servers to collect structured data directly through the MCP client.
Form mode elicitation requests **MUST** either specify `mode: "form"` or omit the `mode` field, and include these additional parameters:
| Name | Type | Description |
| ----------------- | ------ | -------------------------------------------------------------- |
| `requestedSchema` | object | A JSON Schema defining the structure of the expected response. |
#### Requested Schema
The `requestedSchema` parameter allows servers to define the structure of the expected
response using a restricted subset of JSON Schema.
To simplify client user experience, form mode elicitation schemas are limited to flat objects
with primitive properties only.
The schema is restricted to these primitive types:
1. **String Schema**
```json theme={null}
{
"type": "string",
"title": "Display Name",
"description": "Description text",
"minLength": 3,
"maxLength": 50,
"format": "email",
"default": "[email protected]"
}
```
Supported formats: `email`, `uri`, `date`, `date-time`
2. **Number Schema**
```json theme={null}
{
"type": "number", // or "integer"
"title": "Display Name",
"description": "Description text",
"minimum": 0,
"maximum": 100,
"default": 50
}
```
3. **Boolean Schema**
```json theme={null}
{
"type": "boolean",
"title": "Display Name",
"description": "Description text",
"default": false
}
```
4. **Enum Schema**
Single-select enum (without titles):
```json theme={null}
{
"type": "string",
"title": "Color Selection",
"description": "Choose your favorite color",
"enum": ["Red", "Green", "Blue"],
"default": "Red"
}
```
Single-select enum (with titles):
```json theme={null}
{
"type": "string",
"title": "Color Selection",
"description": "Choose your favorite color",
"oneOf": [
{ "const": "#FF0000", "title": "Red" },
{ "const": "#00FF00", "title": "Green" },
{ "const": "#0000FF", "title": "Blue" }
],
"default": "#FF0000"
}
```
Multi-select enum (without titles):
```json theme={null}
{
"type": "array",
"title": "Color Selection",
"description": "Choose your favorite colors",
"minItems": 1,
"maxItems": 2,
"items": {
"type": "string",
"enum": ["Red", "Green", "Blue"]
},
"default": ["Red", "Green"]
}
```
Multi-select enum (with titles):
```json theme={null}
{
"type": "array",
"title": "Color Selection",
"description": "Choose your favorite colors",
"minItems": 1,
"maxItems": 2,
"items": {
"anyOf": [
{ "const": "#FF0000", "title": "Red" },
{ "const": "#00FF00", "title": "Green" },
{ "const": "#0000FF", "title": "Blue" }
]
},
"default": ["#FF0000", "#00FF00"]
}
```
Clients can use this schema to:
1. Generate appropriate input forms
2. Validate user input before sending
3. Provide better guidance to users
All primitive types support optional default values to provide sensible starting points. Clients that support defaults SHOULD pre-populate form fields with these values.
Note that complex nested structures, arrays of objects (beyond enums), and other advanced JSON Schema features are intentionally not supported to simplify client user experience.
#### Example: Simple Text Request
**Input request (delivered inside [`InputRequiredResult.inputRequests`](/specification/draft/basic/patterns/mrtr#inputrequests)):**
```json theme={null}
{
"method": "elicitation/create",
"params": {
"mode": "form",
"message": "Please provide your GitHub username",
"requestedSchema": {
"type": "object",
"properties": {
"name": {
"type": "string"
}
},
"required": ["name"]
}
}
}
```
**Client result (returned inside `inputResponses` on the retried request):**
```json theme={null}
{
"action": "accept",
"content": {
"name": "octocat"
}
}
```
#### Example: Structured Data Request
**Input request (delivered inside `InputRequiredResult.inputRequests`):**
```json theme={null}
{
"method": "elicitation/create",
"params": {
"mode": "form",
"message": "Please provide your contact information",
"requestedSchema": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Your full name"
},
"email": {
"type": "string",
"format": "email",
"description": "Your email address"
},
"age": {
"type": "number",
"minimum": 18,
"description": "Your age"
}
},
"required": ["name", "email"]
}
Cut at 300 lines. The page has the rest.
specification/draft/client/roots New page · 157 lines, new page
# Roots ## User Interaction Model ## Capabilities ## Protocol Messages ### Listing Roots ## Message Flow ## Data Types ### Root #### Project Directory #### Multiple Repositories ## Error Handling ## Security Considerations ## Implementation Guidelines
A whole new page. There's nothing to diff it against, so here is what it says.
# Roots
<div id="enable-section-numbers" />
<Warning>
**Deprecated**: The Roots feature is deprecated as of protocol version
`2026-07-28`
([SEP-2577](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2577)).
Under the [feature lifecycle policy](/community/feature-lifecycle), it remains
in the specification for at least twelve months after this revision's release
before it becomes eligible for removal. New implementations **SHOULD NOT**
adopt it; existing implementations **SHOULD** migrate to passing directories
or files via tool parameters, resource URIs, or server configuration. See the
[deprecated features registry](/specification/draft/deprecated).
</Warning>
The Model Context Protocol (MCP) provides a standardized way for clients to expose
filesystem "roots" to servers. Roots inform servers about the directories and files the
client considers relevant, so that servers can focus their operations accordingly. They
are informational guidance rather than an access-control mechanism. The protocol does
not enforce that servers stay within roots. Servers can request the list of roots from
supporting clients.
## User Interaction Model
Roots in MCP are typically exposed through workspace or project configuration interfaces.
For example, implementations could offer a workspace/project picker that allows users to
select directories and files the server should have access to. This can be combined with
automatic workspace detection from version control systems or project files.
However, implementations are free to expose roots through any interface pattern that
suits their needs—the protocol itself does not mandate any specific user
interaction model.
## Capabilities
Clients that support roots **MUST** declare the `roots` capability in
`_meta.io.modelcontextprotocol/clientCapabilities` on each request:
```json theme={null}
{
"_meta": {
"io.modelcontextprotocol/clientCapabilities": {
"roots": {}
}
}
}
```
## Protocol Messages
### Listing Roots
To retrieve roots during the processing of a client request, servers send an `InputRequiredResult`
containing a `roots/list` request:
**Input request (delivered inside [`InputRequiredResult.inputRequests`](/specification/draft/basic/patterns/mrtr#inputrequests)):**
```json theme={null}
{
"method": "roots/list"
}
```
**Client result (returned inside `inputResponses` on the retried request):**
```json theme={null}
{
"roots": [
{
"uri": "file:///home/user/projects/myproject",
"name": "My Project"
}
]
}
```
## Message Flow
```mermaid theme={null}
sequenceDiagram
participant Server
participant Client
Note over Server,Client: Initial Request
Client->>Server: tools/call(id: 1)
Server-->>Client: InputRequiredResult(roots/list)
Client->>Server: tools/call(id: 2, inputResponses{key: roots} + requestState)
```
## Data Types
### Root
A root definition includes:
* `uri`: Unique identifier for the root. This **MUST** be a `file://` URI in the current
specification.
* `name`: Optional human-readable name for display purposes.
Example roots for different use cases:
#### Project Directory
```json theme={null}
{
"uri": "file:///home/user/projects/myproject",
"name": "My Project"
}
```
#### Multiple Repositories
```json theme={null}
[
{
"uri": "file:///home/user/repos/frontend",
"name": "Frontend Repository"
},
{
"uri": "file:///home/user/repos/backend",
"name": "Backend Repository"
}
]
```
## Error Handling
If an error occurs, the client does not need to replay the initial call with an error message
as the server is not waiting for a response with the `InputRequiredResult` pattern.
## Security Considerations
1. Clients **MUST**:
* Only expose roots with appropriate permissions
* Validate all root URIs to prevent path traversal
* Implement proper access controls
* Monitor root accessibility
2. Servers **SHOULD**:
* Handle cases where roots become unavailable
* Respect root boundaries during operations
* Validate all paths against provided roots
## Implementation Guidelines
1. Clients **SHOULD**:
* Prompt users for consent before exposing roots to servers
* Provide clear user interfaces for root management
* Validate root accessibility before exposing
* Monitor for root changes
2. Servers **SHOULD**:
* Check for roots capability before usage
* Respect root boundaries in operations
* Cache root information appropriately
specification/draft/client/sampling New page · 677 lines, new page
# Sampling ## User Interaction Model ## Tools in Sampling ## Capabilities ## Protocol Messages ### Creating Messages ### Sampling with Tools ### Multi-turn Tool Loop ## Message Content Constraints ### Tool Result Messages ### Tool Use and Result Balance ## Cross-API Compatibility ### Message Roles ### Tool Choice Modes ### Parallel Tool Use ## Message Flow ## Data Types ### Messages #### Text Content #### Image Content #### Audio Content ### Model Preferences #### Capability Priorities #### Model Hints ### System Prompt ### Context Inclusion ### Sampling Parameters ### Result Fields ## Error Handling ## Security Considerations
A whole new page. There's nothing to diff it against, so here is what it says.
# Sampling
<div id="enable-section-numbers" />
<Warning>
**Deprecated**: The Sampling feature is deprecated as of protocol version
`2026-07-28`
([SEP-2577](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2577)).
Under the [feature lifecycle policy](/community/feature-lifecycle), it remains
in the specification for at least twelve months after this revision's release
before it becomes eligible for removal. New implementations **SHOULD NOT**
adopt it; existing implementations **SHOULD** migrate to integrating directly
with LLM provider APIs. See the [deprecated features
registry](/specification/draft/deprecated).
</Warning>
The Model Context Protocol (MCP) provides a standardized way for servers to request LLM
sampling ("completions" or "generations") from language models via clients. This flow
allows clients to maintain control over model access, selection, and permissions while
enabling servers to leverage AI capabilities—with no server API keys necessary.
Servers can request text, audio, or image-based interactions and optionally include
context from MCP servers in their prompts.
## User Interaction Model
Sampling in MCP allows servers to implement agentic behaviors, by enabling LLM calls to
occur *nested* inside other MCP server features.
Implementations are free to expose sampling through any interface pattern that suits
their needs—the protocol itself does not mandate any specific user interaction
model.
<Warning>
For trust & safety and security, there **SHOULD** always
be a human in the loop with the ability to deny sampling requests.
Applications **SHOULD**:
* Provide UI that makes it easy and intuitive to review sampling requests
* Allow users to view and edit prompts before sending
* Present generated responses for review before delivery
</Warning>
## Tools in Sampling
Servers can request that the client's LLM use tools during sampling by providing a `tools` array and optional `toolChoice` configuration in their sampling requests. The tool definitions in the `tools` array are scoped to the sampling request — they don't need to correspond to registered tools. This enables servers to implement agentic behaviors where the LLM can call specially designated tools, receive results, and continue the conversation - all within a single sampling request flow.
Clients **MUST** declare support for tool use via the `sampling.tools` capability to receive tool-enabled sampling requests. Servers **MUST NOT** send tool-enabled sampling requests to Clients that have not declared support for tool use via the `sampling.tools` capability.
## Capabilities
Clients that support sampling **MUST** declare the `sampling` capability in
`_meta.io.modelcontextprotocol/clientCapabilities` on each request:
**Basic sampling:**
```json theme={null}
{
"_meta": {
"io.modelcontextprotocol/clientCapabilities": {
"sampling": {}
}
}
}
```
**With tool use support:**
```json theme={null}
{
"_meta": {
"io.modelcontextprotocol/clientCapabilities": {
"sampling": {
"tools": {}
}
}
}
}
```
**With context inclusion support (deprecated):**
```json theme={null}
{
"_meta": {
"io.modelcontextprotocol/clientCapabilities": {
"sampling": {
"context": {}
}
}
}
}
```
<Note>
The `includeContext` parameter values `"thisServer"` and `"allServers"` are
deprecated under the [feature lifecycle
policy](/community/feature-lifecycle#deprecating-a-feature)
([SEP-2596](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2596));
they will be removed no later than the Sampling feature itself. Servers
**SHOULD** avoid using these values (e.g. can just omit `includeContext` since
it defaults to `"none"`), and **SHOULD NOT** use them unless the client
declares `sampling.context` capability. See the [deprecated features
registry](/specification/draft/deprecated).
</Note>
## Protocol Messages
### Creating Messages
To request a language model generation during the processing of a client request, servers send an `InputRequiredResult` containing a `sampling/createMessage` request:
**Input request (delivered inside [`InputRequiredResult.inputRequests`](/specification/draft/basic/patterns/mrtr#inputrequests)):**
```json theme={null}
{
"method": "sampling/createMessage",
"params": {
"messages": [
{
"role": "user",
"content": {
"type": "text",
"text": "What is the capital of France?"
}
}
],
"modelPreferences": {
"hints": [
{
"name": "claude-3-sonnet"
}
],
"costPriority": 0.3,
"intelligencePriority": 0.8,
"speedPriority": 0.5
},
"temperature": 0.1,
"systemPrompt": "You are a helpful assistant.",
"includeContext": "thisServer",
"maxTokens": 100
}
}
```
**Client result (returned inside `inputResponses` on the retried request):**
```json theme={null}
{
"role": "assistant",
"content": {
"type": "text",
"text": "The capital of France is Paris."
},
"model": "claude-3-sonnet-20240307",
"stopReason": "endTurn"
}
```
### Sampling with Tools
The following diagram illustrates the complete flow of sampling with tools, including the multi-turn tool loop:
```mermaid theme={null}
sequenceDiagram
participant Server
participant Client
participant User
participant LLM
Client->>Server: tools/call(id:1)
note right of Server: Server needs more info
Server->>Client: InputRequiredResult(<br/>sampling/createMessage<br/>(messages + tools))
Note over Client,User: Human-in-the-loop review
Client->>User: Present request for approval
User-->>Client: Approve/modify
Client->>LLM: Forward request with tools
LLM-->>Client: Response with tool_use<br/>(stopReason: "toolUse")
Client->>User: Present tool calls for review
User-->>Client: Approve tool calls
Client-->>Server: tools/call(id:2, Return tool_use response)
Note over Server: Execute tool(s)
Server->>Server: Run get_weather("Paris")<br/>Run get_weather("London")
Note over Server,Client: Continue with tool results
Server->>Client: InputRequiredResult(<br/>sampling/createMessage<br/>(history + tool_results + tools))
Client->>User: Present continuation
User-->>Client: Approve
Client->>LLM: Forward with tool results
LLM-->>Client: Final text response<br/>(stopReason: "endTurn")
Client->>User: Present response
User-->>Client: Approve
Client-->>Server: tools/call(id:3, Return final response)
Note over Server: Server processes result<br/>(may continue conversation...)
```
To request LLM generation with tool use capabilities, servers include `tools` and optionally `toolChoice` in the request:
**Input request (Server -> Client, delivered inside `InputRequiredResult.inputRequests`):**
```json theme={null}
{
"method": "sampling/createMessage",
"params": {
"messages": [
{
"role": "user",
"content": {
"type": "text",
"text": "What's the weather like in Paris and London?"
}
}
],
"tools": [
{
"name": "get_weather",
"description": "Get current weather for a city",
"inputSchema": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "City name"
}
},
"required": ["city"]
}
}
],
"toolChoice": {
"mode": "auto"
},
"maxTokens": 1000
}
}
```
**Client result (Client -> Server, returned inside `inputResponses` on the retried request):**
```json theme={null}
{
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "call_abc123",
"name": "get_weather",
"input": {
"city": "Paris"
}
},
{
"type": "tool_use",
"id": "call_def456",
"name": "get_weather",
"input": {
"city": "London"
}
}
],
"model": "claude-3-sonnet-20240307",
"stopReason": "toolUse"
}
```
### Multi-turn Tool Loop
After receiving tool use requests from the LLM, the server typically:
1. Executes the requested tool uses.
2. Sends a new sampling request with the tool results appended
3. Receives the LLM's response (which might contain new tool uses)
4. Repeats as many times as needed (server might cap the maximum number of iterations, and e.g. pass `toolChoice: {mode: "none"}` on the last iteration to force a final result)
**Follow-up input request (Server -> Client, delivered inside `InputRequiredResult.inputRequests`) with tool results:**
```json theme={null}
{
"method": "sampling/createMessage",
"params": {
"messages": [
{
"role": "user",
"content": {
"type": "text",
"text": "What's the weather like in Paris and London?"
}
},
{
"role": "assistant",
"content": [
{
Cut at 300 lines. The page has the rest.
specification/draft/deprecated New page · 39 lines, new page
# Deprecated Features ## Deprecated ## Removed
A whole new page. There's nothing to diff it against, so here is what it says.
# Deprecated Features <div id="enable-section-numbers" /> This page is the registry of specification features that are currently in the **Deprecated** state under the [feature lifecycle and deprecation policy](/community/feature-lifecycle) ([SEP-2596](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2596)). A Deprecated feature remains part of the specification but is scheduled for removal: new implementations **SHOULD NOT** adopt it, and existing implementations **SHOULD** migrate before the feature's earliest removal. The earliest removal marks when a feature becomes *eligible* for removal; the actual removal is a Core Maintainer decision taken during release preparation and may happen later. This registry is a derived view kept consistent with the per-feature deprecation notices and changelog entries, which are the normative records. ## Deprecated | Feature | Deprecation SEP | Deprecated in | Migration path | Earliest removal | | ----------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | | [Roots](/specification/draft/client/roots) | [SEP-2577](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2577) | `2026-07-28` | Pass directories or files via tool parameters, resource URIs, or server configuration | First revision released on or after 2027-07-28 | | [Sampling](/specification/draft/client/sampling) | [SEP-2577](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2577) | `2026-07-28` | Integrate directly with LLM provider APIs | First revision released on or after 2027-07-28 | | [Logging](/specification/draft/server/utilities/logging) | [SEP-2577](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2577) | `2026-07-28` | Log to `stderr` for stdio transports; use [OpenTelemetry](https://opentelemetry.io/) for observability | First revision released on or after 2027-07-28 | | [Dynamic Client Registration](/specification/draft/basic/authorization/client-registration#dynamic-client-registration) | [PR #2858](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2858) | `2026-07-28` | [Client ID Metadata Documents](/specification/draft/basic/authorization/client-registration#client-id-metadata-documents) | First revision released on or after 2027-07-28 | | `includeContext: "thisServer"` / `"allServers"` ([Sampling](/specification/draft/client/sampling#capabilities)) | [SEP-2596](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2596) | `2025-11-25` | Omit the field or use `"none"` | Follows Sampling ([SEP-2577](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2577)) | | [HTTP+SSE transport](/specification/2024-11-05/basic/transports#http-with-sse) | [SEP-2596](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2596) | `2025-03-26` | [Streamable HTTP](/specification/draft/basic/transports/streamable-http) | Three months after SEP-2596 reaches Final | The HTTP+SSE transport and the `includeContext` values were already described as deprecated before the lifecycle policy existed; SEP-2596 reclassifies them as Deprecated under its [transition provisions](/community/feature-lifecycle). ## Removed No features have been removed under this policy yet. When a Deprecated feature is removed, its row moves to this section with a link to the changelog entry recording the removal.
specification/draft/index New page · 138 lines, new page
# Specification ## Overview ## Key Details ### Base Protocol ### Features ### Additional Utilities ### Extensions ## Security and Trust & Safety ### Key Principles ### Implementation Guidelines ## Learn More
A whole new page. There's nothing to diff it against, so here is what it says.
# Specification
<div id="enable-section-numbers" />
[Model Context Protocol](https://modelcontextprotocol.io) (MCP) is an open protocol that
enables seamless integration between LLM applications and external data sources and
tools. Whether you're building an AI-powered IDE, enhancing a chat interface, or creating
custom AI workflows, MCP provides a standardized way to connect LLMs with the context
they need.
This specification defines the authoritative protocol requirements, based on the
TypeScript schema in
[schema.ts](https://github.com/modelcontextprotocol/specification/blob/main/schema/draft/schema.ts).
For implementation guides and examples, visit
[modelcontextprotocol.io](https://modelcontextprotocol.io).
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD
NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be
interpreted as described in [BCP 14](https://datatracker.ietf.org/doc/html/bcp14)
\[[RFC2119](https://datatracker.ietf.org/doc/html/rfc2119)]
\[[RFC8174](https://datatracker.ietf.org/doc/html/rfc8174)] when, and only when, they
appear in all capitals, as shown here.
## Overview
MCP provides a standardized way for applications to:
* Share contextual information with language models
* Expose tools and capabilities to AI systems
* Build composable integrations and workflows
The protocol uses [JSON-RPC](https://www.jsonrpc.org/) 2.0 messages to establish
communication between:
* **Hosts**: LLM applications that initiate connections
* **Clients**: Connectors within the host application
* **Servers**: Services that provide context and capabilities
MCP takes some inspiration from the
[Language Server Protocol](https://microsoft.github.io/language-server-protocol/), which
standardizes how to add support for programming languages across a whole ecosystem of
development tools. In a similar way, MCP standardizes how to integrate additional context
and tools into the ecosystem of AI applications.
## Key Details
### Base Protocol
* [JSON-RPC](https://www.jsonrpc.org/) message format
* Stateless, self-contained requests
* Per-request capability negotiation
### Features
Servers offer any of the following features to clients:
* **Resources**: Context and data, for the user or the AI model to use
* **Prompts**: Templated messages and workflows for users
* **Tools**: Functions for the AI model to execute
Clients may offer the following features to servers:
* **Elicitation**: Server-initiated requests for additional information from users
### Additional Utilities
* Configuration
* Progress tracking
* Cancellation
* Error reporting
### Extensions
Beyond the core protocol, MCP defines optional [extensions](/extensions/overview)
that add modular, specialized, or experimental functionality. Extensions
are always opt-in and require explicit support from both client and server, negotiated
during initialization. Notable extensions include:
* **[Tasks](/extensions/tasks/overview)**: Asynchronous execution of long-running
operations, with polling, mid-flight input, and durable handles
* **[Skills over MCP](/community/working-groups/skills-over-mcp)**: Rich, structured
instructions for agent workflows, discovered and consumed through MCP
* **[MCP Apps](/extensions/apps/overview)**: Interactive UI elements (charts, forms,
video players) rendered inline within conversations
## Security and Trust & Safety
The Model Context Protocol enables powerful capabilities through arbitrary data access
and code execution paths. With this power comes important security and trust
considerations that all implementors must carefully address.
### Key Principles
1. **User Consent and Control**
* Users must explicitly consent to and understand all data access and operations
* Users must retain control over what data is shared and what actions are taken
* Implementors should provide clear UIs for reviewing and authorizing activities
2. **Data Privacy**
* Hosts must obtain explicit user consent before exposing user data to servers
* Hosts must not transmit resource data elsewhere without user consent
* User data should be protected with appropriate access controls
3. **Tool Safety**
* Tools represent arbitrary code execution and must be treated with appropriate
caution.
* In particular, descriptions of tool behavior such as annotations should be
considered untrusted, unless obtained from a trusted server.
* Hosts must obtain explicit user consent before invoking any tool
* Users should understand what each tool does before authorizing its use
### Implementation Guidelines
While MCP itself cannot enforce these security principles at the protocol level,
implementors **SHOULD**:
1. Build robust consent and authorization flows into their applications
2. Provide clear documentation of security implications
3. Implement appropriate access controls and data protections
4. Follow security best practices in their integrations
5. Consider privacy implications in their feature designs
## Learn More
Explore the detailed specification for each protocol component:
<CardGroup cols={5}>
<Card title="Architecture" icon="sitemap" href="/specification/draft/architecture" />
<Card title="Base Protocol" icon="code" href="/specification/draft/basic" />
<Card title="Server Features" icon="server" href="/specification/draft/server" />
<Card title="Client Features" icon="user" href="/specification/draft/client" />
<Card title="Contributing" icon="pencil" href="/community/contributing" />
</CardGroup>
specification/draft/schema New page · 1227 lines, new page
# Schema Reference ## JSON-RPC ## Common Types ## Errors ## Content ## `completion/complete` ## `elicitation/create` ## `notifications/cancelled` ## `notifications/message` ## `notifications/progress` ## `notifications/prompts/list_changed` ## `notifications/resources/list_changed` ## `notifications/resources/updated` ## `notifications/subscriptions/acknowledged` ## `notifications/tools/list_changed` ## Multi Round-Trip ## `prompts/get` ## `prompts/list` ## `resources/list` ## `resources/read` ## `resources/templates/list` ## `roots/list` ## `sampling/createMessage` ## `server/discover` ## `subscriptions/listen` ## `tools/call` ## `tools/list`
This page is larger than the 256 KiB this site keeps, so one side of the diff below stops where the stored text does.
A whole new page. There's nothing to diff it against, so here is what it says.
# Schema Reference
<div id="schema-reference" />
## JSON-RPC
<div class="type">
### `JSONRPCErrorResponse`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">JSONRPCErrorResponse</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#jsonrpcerrorresponse-jsonrpc">jsonrpc</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">"2.0"</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#jsonrpcerrorresponse-id">id</a><span class="tsd-signature-symbol">?:</span> <a href="#requestid" class="tsd-signature-type tsd-kind-type-alias">RequestId</a><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#jsonrpcerrorresponse-error">error</a><span class="tsd-signature-symbol">:</span> <a href="#error" class="tsd-signature-type tsd-kind-interface">Error</a><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>A response to a request that indicates an error occurred.</p> </div> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="jsonrpcerrorresponse-jsonrpc" data-typedoc-h="3"><span>jsonrpc: "2.0"</span><a href="#jsonrpcerrorresponse-jsonrpc" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="jsonrpcerrorresponse-id" data-typedoc-h="3"><span>id?: RequestId</span><a href="#jsonrpcerrorresponse-id" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="jsonrpcerrorresponse-error" data-typedoc-h="3"><span>error: Error</span><a href="#jsonrpcerrorresponse-error" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section>
</div>
<div class="type">
### `JSONRPCMessage`
<div class="tsd-signature"><span class="tsd-kind-type-alias">JSONRPCMessage</span><span class="tsd-signature-symbol">:</span> <a href="#jsonrpcrequest" class="tsd-signature-type tsd-kind-interface">JSONRPCRequest</a> <span class="tsd-signature-symbol">|</span> <a href="#jsonrpcnotification" class="tsd-signature-type tsd-kind-interface">JSONRPCNotification</a> <span class="tsd-signature-symbol">|</span> <a href="#jsonrpcresponse" class="tsd-signature-type tsd-kind-type-alias">JSONRPCResponse</a></div> <div class="tsd-comment tsd-typography"><p>Refers to any valid JSON-RPC object that can be decoded off the wire, or encoded to be sent.</p> </div>
</div>
<div class="type">
### `JSONRPCNotification`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">JSONRPCNotification</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#jsonrpcnotification-method">method</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#jsonrpcnotification-params">params</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-symbol">\{</span> <span class="tsd-signature-symbol">\[</span><span class="tsd-kind-index-signature">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <span class="tsd-signature-type">any</span> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#jsonrpcnotification-jsonrpc">jsonrpc</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">"2.0"</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>A notification which does not expect a response.</p> </div> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="jsonrpcnotification-method" data-typedoc-h="3"><span>method: string</span><a href="#jsonrpcnotification-method" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <aside class="tsd-sources"> <p>Inherited from Notification.method</p></aside></section> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="jsonrpcnotification-params" data-typedoc-h="3"><span>params?: \{ \[key: string]: any }</span><a href="#jsonrpcnotification-params" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <aside class="tsd-sources"> <p>Inherited from Notification.params</p></aside></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="jsonrpcnotification-jsonrpc" data-typedoc-h="3"><span>jsonrpc: "2.0"</span><a href="#jsonrpcnotification-jsonrpc" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section>
</div>
<div class="type">
### `JSONRPCRequest`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">JSONRPCRequest</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#jsonrpcrequest-method">method</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#jsonrpcrequest-params">params</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-symbol">\{</span> <span class="tsd-signature-symbol">\[</span><span class="tsd-kind-index-signature">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <span class="tsd-signature-type">any</span> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#jsonrpcrequest-jsonrpc">jsonrpc</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">"2.0"</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#jsonrpcrequest-id">id</a><span class="tsd-signature-symbol">:</span> <a href="#requestid" class="tsd-signature-type tsd-kind-type-alias">RequestId</a><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>A request that expects a response.</p> </div> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="jsonrpcrequest-method" data-typedoc-h="3"><span>method: string</span><a href="#jsonrpcrequest-method" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <aside class="tsd-sources"> <p>Inherited from Request.method</p></aside></section> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="jsonrpcrequest-params" data-typedoc-h="3"><span>params?: \{ \[key: string]: any }</span><a href="#jsonrpcrequest-params" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <aside class="tsd-sources"> <p>Inherited from Request.params</p></aside></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="jsonrpcrequest-jsonrpc" data-typedoc-h="3"><span>jsonrpc: "2.0"</span><a href="#jsonrpcrequest-jsonrpc" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="jsonrpcrequest-id" data-typedoc-h="3"><span>id: RequestId</span><a href="#jsonrpcrequest-id" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section>
</div>
<div class="type">
### `JSONRPCResponse`
<div class="tsd-signature"><span class="tsd-kind-type-alias">JSONRPCResponse</span><span class="tsd-signature-symbol">:</span> <a href="#jsonrpcresultresponse" class="tsd-signature-type tsd-kind-interface">JSONRPCResultResponse</a> <span class="tsd-signature-symbol">|</span> <a href="#jsonrpcerrorresponse" class="tsd-signature-type tsd-kind-interface">JSONRPCErrorResponse</a></div> <div class="tsd-comment tsd-typography"><p>A response to a request, containing either the result or error.</p> </div>
</div>
<div class="type">
### `JSONRPCResultResponse`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">JSONRPCResultResponse</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#jsonrpcresultresponse-jsonrpc">jsonrpc</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">"2.0"</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#jsonrpcresultresponse-id">id</a><span class="tsd-signature-symbol">:</span> <a href="#requestid" class="tsd-signature-type tsd-kind-type-alias">RequestId</a><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#jsonrpcresultresponse-result">result</a><span class="tsd-signature-symbol">:</span> <a href="#result" class="tsd-signature-type tsd-kind-interface">Result</a><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>A successful (non-error) response to a request.</p> </div> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="jsonrpcresultresponse-jsonrpc" data-typedoc-h="3"><span>jsonrpc: "2.0"</span><a href="#jsonrpcresultresponse-jsonrpc" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="jsonrpcresultresponse-id" data-typedoc-h="3"><span>id: RequestId</span><a href="#jsonrpcresultresponse-id" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="jsonrpcresultresponse-result" data-typedoc-h="3"><span>result: Result</span><a href="#jsonrpcresultresponse-result" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section>
</div>
## Common Types
<div class="type">
### `Annotations`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">Annotations</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#annotations-audience">audience</a><span class="tsd-signature-symbol">?:</span> <a href="#role" class="tsd-signature-type tsd-kind-type-alias">Role</a><span class="tsd-signature-symbol">\[]</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#annotations-priority">priority</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#annotations-lastmodified">lastModified</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>Optional annotations for the client. The client can use annotations to inform how objects are used or displayed</p> </div> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="annotations-audience" data-typedoc-h="3"><span>audience?: Role\[]</span><a href="#annotations-audience" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>Describes who the intended audience of this object or data is.</p> <p>It can include multiple entries to indicate content useful for multiple audiences (e.g., <code>\["user", "assistant"]</code>).</p> </div></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="annotations-priority" data-typedoc-h="3"><span>priority?: number</span><a href="#annotations-priority" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>Describes how important this data is for operating the server.</p> <p>A value of 1 means "most important," and indicates that the data is
effectively required, while 0 means "least important," and indicates that
the data is entirely optional.</p> </div></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="annotations-lastmodified" data-typedoc-h="3"><span>lastModified?: string</span><a href="#annotations-lastmodified" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>The moment the resource was last modified, as an ISO 8601 formatted string.</p> <p>Should be an ISO 8601 formatted string (e.g., "2025-01-12T15:00:58Z").</p> <p>Examples: last activity timestamp in an open file, timestamp when the resource
was attached, etc.</p> </div></section>
</div>
<div class="type">
### `Cursor`
<div class="tsd-signature"><span class="tsd-kind-type-alias">Cursor</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span></div> <div class="tsd-comment tsd-typography"><p>An opaque token used to represent a cursor for pagination.</p> </div>
</div>
<div class="type">
### `EmptyResult`
<div class="tsd-signature"><span class="tsd-kind-type-alias">EmptyResult</span><span class="tsd-signature-symbol">:</span> <a href="#result" class="tsd-signature-type tsd-kind-interface">Result</a></div> <div class="tsd-comment tsd-typography"><p>A result that indicates success but carries no data.</p> </div>
</div>
<div class="type">
### `Icon`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">Icon</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#icon-src">src</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#icon-mimetype">mimeType</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#icon-sizes">sizes</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">\[]</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#icon-theme">theme</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">"light"</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"dark"</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>An optionally-sized icon that can be displayed in a user interface.</p> </div> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="icon-src" data-typedoc-h="3"><span>src: string</span><a href="#icon-src" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>A standard URI pointing to an icon resource. May be an HTTP/HTTPS URL or a <code>data:</code> URI with Base64-encoded image data.</p> <p>Consumers SHOULD take steps to ensure URLs serving icons are from the
same domain as the client/server or a trusted domain.</p> <p>Consumers SHOULD take appropriate precautions when consuming SVGs as they can contain
executable JavaScript.</p> </div></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="icon-mimetype" data-typedoc-h="3"><span>mimeType?: string</span><a href="#icon-mimetype" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>Optional MIME type override if the source MIME type is missing or generic.
For example: <code>"image/png"</code>, <code>"image/jpeg"</code>, or <code>"image/svg+xml"</code>.</p> </div></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="icon-sizes" data-typedoc-h="3"><span>sizes?: string\[]</span><a href="#icon-sizes" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>Optional array of strings that specify sizes at which the icon can be used.
Each string should be in WxH format (e.g., <code>"48x48"</code>, <code>"96x96"</code>) or <code>"any"</code> for scalable formats like SVG.</p> <p>If not provided, the client should assume that the icon can be used at any size.</p> </div></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="icon-theme" data-typedoc-h="3"><span>theme?: "light" | "dark"</span><a href="#icon-theme" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>Optional specifier for the theme this icon is designed for. <code>"light"</code> indicates
the icon is designed to be used with a light background, and <code>"dark"</code> indicates
the icon is designed to be used with a dark background.</p> <p>If not provided, the client should assume the icon can be used with any theme.</p> </div></section>
</div>
<div class="type">
### `InputResponseRequestParams`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">InputResponseRequestParams</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#inputresponserequestparams-_meta">\_meta</a><span class="tsd-signature-symbol">:</span> <a href="#requestmetaobject" class="tsd-signature-type tsd-kind-interface">RequestMetaObject</a><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#inputresponserequestparams-inputresponses">inputResponses</a><span class="tsd-signature-symbol">?:</span> <a href="#inputresponses" class="tsd-signature-type tsd-kind-interface">InputResponses</a><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#inputresponserequestparams-requeststate">requestState</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>Common params for any request.</p> </div> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="inputresponserequestparams-_meta" data-typedoc-h="3"><span>\_meta: RequestMetaObject</span><a href="#inputresponserequestparams-_meta" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <aside class="tsd-sources"> <p>Inherited from <a href="#requestparams">RequestParams</a>.<a href="#requestparams-_meta">\_meta</a></p></aside></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="inputresponserequestparams-inputresponses" data-typedoc-h="3"><span>inputResponses?: InputResponses</span><a href="#inputresponserequestparams-inputresponses" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="inputresponserequestparams-requeststate" data-typedoc-h="3"><span>requestState?: string</span><a href="#inputresponserequestparams-requeststate" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section>
</div>
<div class="type">
### `JSONArray`
<div class="tsd-signature"><span class="tsd-kind-type-alias">JSONArray</span><span class="tsd-signature-symbol">:</span> <a href="#jsonvalue" class="tsd-signature-type tsd-kind-type-alias">JSONValue</a><span class="tsd-signature-symbol">\[]</span></div>
</div>
<div class="type">
### `JSONObject`
<div class="tsd-signature"><span class="tsd-kind-type-alias">JSONObject</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-symbol">\{</span> <span class="tsd-signature-symbol">\[</span><span class="tsd-kind-index-signature">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <a href="#jsonvalue" class="tsd-signature-type tsd-kind-type-alias">JSONValue</a> <span class="tsd-signature-symbol">}</span></div> <div class="tsd-type-declaration"> <div data-typedoc-h="4">Type Declaration</div> <ul class="tsd-parameters"> <li class="tsd-parameter-index-signature"> <div data-typedoc-h="5"><span class="tsd-signature-symbol">\[</span><span class="tsd-kind-parameter">key</span>: <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <a href="#jsonvalue" class="tsd-signature-type tsd-kind-type-alias">JSONValue</a></div></li></ul></div>
</div>
<div class="type">
### `JSONValue`
<div class="tsd-signature"><span class="tsd-kind-type-alias">JSONValue</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">number</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">boolean</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">null</span> <span class="tsd-signature-symbol">|</span> <a href="#jsonobject" class="tsd-signature-type tsd-kind-type-alias">JSONObject</a> <span class="tsd-signature-symbol">|</span> <a href="#jsonarray" class="tsd-signature-type tsd-kind-type-alias">JSONArray</a></div>
</div>
<div class="type">
### `LoggingLevel`
<div class="tsd-signature"><span class="tsd-kind-type-alias">LoggingLevel</span><span class="tsd-signature-symbol">:</span><br /> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"debug"</span><br /> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"info"</span><br /> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"notice"</span><br /> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"warning"</span><br /> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"error"</span><br /> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"critical"</span><br /> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"alert"</span><br /> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"emergency"</span></div> <div class="tsd-comment tsd-typography"><p>The severity of a log message.</p> <p>These map to syslog message severities, as specified in RFC-5424: <a href="https://datatracker.ietf.org/doc/html/rfc5424#section-6.2.1">[https://datatracker.ietf.org/doc/html/rfc5424#section-6.2.1](https://datatracker.ietf.org/doc/html/rfc5424#section-6.2.1)</a></p> </div> <div class="tsd-comment tsd-typography"> <div class="tsd-tag-deprecated"> <div class="tsd-anchor-link" data-typedoc-h="4">Deprecated</div><p>Deprecated as of protocol version 2026-07-28 (SEP-2577).
Remains in the specification for at least twelve months; see the
deprecated features registry.</p> </div></div>
</div>
<div class="type">
### `MetaObject`
<div class="tsd-signature"><span class="tsd-kind-type-alias">MetaObject</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">Record</span><span class="tsd-signature-symbol">\<</span><span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">,</span> <span class="tsd-signature-type">unknown</span><span class="tsd-signature-symbol">></span></div> <div class="tsd-comment tsd-typography"><p>Represents the contents of a <code>\_meta</code> field, which clients and servers use to attach additional metadata to their interactions.</p> <p>Certain key names are reserved by MCP for protocol-level metadata; implementations MUST NOT make assumptions about values at these keys. Additionally, specific schema definitions may reserve particular names for purpose-specific metadata, as declared in those definitions.</p> <p>Valid keys have two segments:</p> <p><strong>Prefix:</strong></p> <ul> <li>Optional — if specified, MUST be a series of <em>labels</em> separated by dots (<code>.</code>), followed by a slash (<code>/</code>).</li> <li>Labels MUST start with a letter and end with a letter or digit. Interior characters may be letters, digits, or hyphens (<code>-</code>).</li> <li>Implementations SHOULD use reverse DNS notation (e.g., <code>com.example/</code> rather than <code>example.com/</code>).</li> <li>Any prefix where the second label is <code>modelcontextprotocol</code> or <code>mcp</code> is <strong>reserved</strong> for MCP use. For example: <code>io.modelcontextprotocol/</code>, <code>dev.mcp/</code>, <code>org.modelcontextprotocol.api/</code>, and <code>com.mcp.tools/</code> are all reserved. However, <code>com.example.mcp/</code> is NOT reserved, as the second label is <code>example</code>.</li> </ul> <p><strong>Name:</strong></p> <ul> <li>Unless empty, MUST start and end with an alphanumeric character (<code>\[a-z0-9A-Z]</code>).</li> <li>Interior characters may be alphanumeric, hyphens (<code>-</code>), underscores (<code>\_</code>), or dots (<code>.</code>).</li> </ul> </div> <div class="tsd-comment tsd-typography"> <div class="tsd-tag-see"> <div class="tsd-anchor-link" data-typedoc-h="4">See</div><p><a href="/specification/draft/basic/index#meta">General fields: <code>\_meta</code></a> for more details.</p> </div></div>
</div>
<div class="type">
### `NotificationMetaObject`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">NotificationMetaObject</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#notificationmetaobject-iomodelcontextprotocolsubscriptionid">"io.modelcontextprotocol/subscriptionId"</a><span class="tsd-signature-symbol">?:</span> <a href="#requestid" class="tsd-signature-type tsd-kind-type-alias">RequestId</a><span class="tsd-signature-symbol">;</span><br /> <span class="tsd-signature-symbol">\[</span><span class="tsd-kind-index-signature">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <span class="tsd-signature-type">unknown</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>Extends <a href="#metaobject" class="tsd-kind-type-alias">MetaObject</a> with additional notification-specific fields. All key naming rules from <code>MetaObject</code> apply.</p> </div> <div class="tsd-comment tsd-typography"> <div class="tsd-tag-see"> <div class="tsd-anchor-link" data-typedoc-h="4">See</div><ul> <li><a href="#metaobject" class="tsd-kind-type-alias">MetaObject</a> for key naming rules and reserved prefixes.</li> <li><a href="/specification/draft/basic/index#meta">General fields: <code>\_meta</code></a> for more details.</li> </ul> </div></div> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="notificationmetaobject-iomodelcontextprotocolsubscriptionid" data-typedoc-h="3"><span>"io.modelcontextprotocol/subscriptionId"?: RequestId</span><a href="#notificationmetaobject-iomodelcontextprotocolsubscriptionid" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>Identifies the subscription stream a notification was delivered on. The
server MUST include this key on every notification delivered via a <a href="#subscriptionslistenrequest" class="tsd-kind-interface">subscriptions/listen</a> stream, so the
client can correlate the notification with the originating subscription.
The key is absent on notifications not delivered via a subscription
stream (e.g. progress notifications for an in-flight request), which is
why it is optional here.</p> <p>The value is the JSON-RPC ID of the <code>subscriptions/listen</code> request that
opened the stream.</p> </div></section>
</div>
<div class="type">
### `NotificationParams`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">NotificationParams</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#notificationparams-_meta">\_meta</a><span class="tsd-signature-symbol">?:</span> <a href="#notificationmetaobject" class="tsd-signature-type tsd-kind-interface">NotificationMetaObject</a><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>Common params for any notification.</p> </div> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="notificationparams-_meta" data-typedoc-h="3"><span>\_meta?: NotificationMetaObject</span><a href="#notificationparams-_meta" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section>
</div>
<div class="type">
### `PaginatedRequestParams`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">PaginatedRequestParams</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#paginatedrequestparams-_meta">\_meta</a><span class="tsd-signature-symbol">:</span> <a href="#requestmetaobject" class="tsd-signature-type tsd-kind-interface">RequestMetaObject</a><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#paginatedrequestparams-cursor">cursor</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>Common params for paginated requests.</p> </div> <div class="tsd-comment tsd-typography"> <details class="tsd-tag-example"> <summary class="tsd-anchor-link">Example: List request with cursor<a href="#paginatedrequestparams-example-list-request-with-cursor" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></summary><pre id="paginatedrequestparams-example-list-request-with-cursor"><code class="json"><span class="hl-0">\{</span><br /><span class="hl-0"> </span><span class="hl-1">"\_meta"</span><span class="hl-0">: \{</span><br /><span class="hl-0"> </span><span class="hl-1">"io.modelcontextprotocol/protocolVersion"</span><span class="hl-0">: </span><span class="hl-2">"2026-07-28"</span><span class="hl-0">,</span><br /><span class="hl-0"> </span><span class="hl-1">"io.modelcontextprotocol/clientInfo"</span><span class="hl-0">: \{</span><br /><span class="hl-0"> </span><span class="hl-1">"name"</span><span class="hl-0">: </span><span class="hl-2">"ExampleClient"</span><span class="hl-0">,</span><br /><span class="hl-0"> </span><span class="hl-1">"version"</span><span class="hl-0">: </span><span class="hl-2">"1.0.0"</span><br /><span class="hl-0"> },</span><br /><span class="hl-0"> </span><span class="hl-1">"io.modelcontextprotocol/clientCapabilities"</span><span class="hl-0">: \{}</span><br /><span class="hl-0"> },</span><br /><span class="hl-0"> </span><span class="hl-1">"cursor"</span><span class="hl-0">: </span><span class="hl-2">"eyJwYWdlIjogMn0="</span><br /><span class="hl-0">}</span> </code><button type="button">Copy</button></pre> </details></div> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="paginatedrequestparams-_meta" data-typedoc-h="3"><span>\_meta: RequestMetaObject</span><a href="#paginatedrequestparams-_meta" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <aside class="tsd-sources"> <p>Inherited from <a href="#requestparams">RequestParams</a>.<a href="#requestparams-_meta">\_meta</a></p></aside></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="paginatedrequestparams-cursor" data-typedoc-h="3"><span>cursor?: string</span><a href="#paginatedrequestparams-cursor" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>An opaque token representing the current pagination position.
If provided, the server should return results starting after this cursor.</p> </div></section>
</div>
<div class="type">
### `ProgressToken`
<div class="tsd-signature"><span class="tsd-kind-type-alias">ProgressToken</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">number</span></div> <div class="tsd-comment tsd-typography"><p>A progress token, used to associate progress notifications with the original request.</p> </div>
</div>
<div class="type">
### `RequestId`
<div class="tsd-signature"><span class="tsd-kind-type-alias">RequestId</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">number</span></div> <div class="tsd-comment tsd-typography"><p>A uniquely identifying ID for a request in JSON-RPC.</p> </div>
</div>
<div class="type">
### `RequestMetaObject`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">RequestMetaObject</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#requestmetaobject-progresstoken">progressToken</a><span class="tsd-signature-symbol">?:</span> <a href="#progresstoken" class="tsd-signature-type tsd-kind-type-alias">ProgressToken</a><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#requestmetaobject-iomodelcontextprotocolprotocolversion">"io.modelcontextprotocol/protocolVersion"</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#requestmetaobject-iomodelcontextprotocolclientinfo">"io.modelcontextprotocol/clientInfo"</a><span class="tsd-signature-symbol">?:</span> <a href="#implementation" class="tsd-signature-type tsd-kind-interface">Implementation</a><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#requestmetaobject-iomodelcontextprotocolclientcapabilities">"io.modelcontextprotocol/clientCapabilities"</a><span class="tsd-signature-symbol">:</span> <a href="#clientcapabilities" class="tsd-signature-type tsd-kind-interface">ClientCapabilities</a><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#requestmetaobject-iomodelcontextprotocolloglevel">"io.modelcontextprotocol/logLevel"</a><span class="tsd-signature-symbol">?:</span> <a href="#logginglevel" class="tsd-signature-type tsd-kind-type-alias">LoggingLevel</a><span class="tsd-signature-symbol">;</span><br /> <span class="tsd-signature-symbol">\[</span><span class="tsd-kind-index-signature">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <span class="tsd-signature-type">unknown</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>Extends <a href="#metaobject" class="tsd-kind-type-alias">MetaObject</a> with additional request-specific fields. All key naming rules from <code>MetaObject</code> apply.</p> </div> <div class="tsd-comment tsd-typography"> <div class="tsd-tag-see"> <div class="tsd-anchor-link" data-typedoc-h="4">See</div><ul> <li><a href="#metaobject" class="tsd-kind-type-alias">MetaObject</a> for key naming rules and reserved prefixes.</li> <li><a href="/specification/draft/basic/index#meta">General fields: <code>\_meta</code></a> for more details.</li> </ul> </div></div> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="requestmetaobject-progresstoken" data-typedoc-h="3"><span>progressToken?: ProgressToken</span><a href="#requestmetaobject-progresstoken" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>If specified, the caller is requesting out-of-band progress notifications for this request (as represented by <a href="#progressnotification" class="tsd-kind-interface">notifications/progress</a>). The value of this parameter is an opaque token that will be attached to any subsequent notifications. The receiver is not obligated to provide these notifications.</p> </div></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="requestmetaobject-iomodelcontextprotocolprotocolversion" data-typedoc-h="3"><span>"io.modelcontextprotocol/protocolVersion": string</span><a href="#requestmetaobject-iomodelcontextprotocolprotocolversion" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>The MCP Protocol Version being used for this request. Required.</p> <p>For the HTTP transport, this value MUST match the <code>MCP-Protocol-Version</code>
header; otherwise the server MUST return a <code>400 Bad Request</code>. If the
server does not support the requested version, it MUST return an <a href="#unsupportedprotocolversionerror" class="tsd-kind-interface">UnsupportedProtocolVersionError</a>.</p> </div></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="requestmetaobject-iomodelcontextprotocolclientinfo" data-typedoc-h="3"><span>"io.modelcontextprotocol/clientInfo"?: Implementation</span><a href="#requestmetaobject-iomodelcontextprotocolclientinfo" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>Identifies the client software making the request. Clients SHOULD
include this field on every request unless specifically configured not
to do so.</p> <p>The <a href="#implementation" class="tsd-kind-interface">Implementation</a> schema requires <code>name</code> and <code>version</code>; other
fields are optional.</p> <p>The value is self-reported by the client and is not verified by the
protocol. It is intended for display, logging, and debugging. Servers
SHOULD NOT use it to change their behavior, and SHOULD NOT rely on it for
security decisions.</p> </div></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="requestmetaobject-iomodelcontextprotocolclientcapabilities" data-typedoc-h="3"><span>"io.modelcontextprotocol/clientCapabilities": ClientCapabilities</span><a href="#requestmetaobject-iomodelcontextprotocolclientcapabilities" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>The client's capabilities for this specific request. Required.</p> <p>Capabilities are declared per-request rather than once at initialization;
an empty object means the client supports no optional capabilities.
Servers MUST NOT infer capabilities from prior requests.</p> </div></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="requestmetaobject-iomodelcontextprotocolloglevel" data-typedoc-h="3"><span class="deprecated">"io.modelcontextprotocol/logLevel"?: LoggingLevel</span><a href="#requestmetaobject-iomodelcontextprotocolloglevel" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>The desired log level for this request. Optional.</p> <p>If absent, the server MUST NOT send any <a href="#loggingmessagenotification" class="tsd-kind-interface">notifications/message</a>
notifications for this request. The client opts in to log messages by
explicitly setting a level. Replaces the former <code>logging/setLevel</code> RPC.</p> </div> <div class="tsd-comment tsd-typography"> <div class="tsd-tag-deprecated"> <div class="tsd-anchor-link" data-typedoc-h="4">Deprecated</div><p>Deprecated as of protocol version 2026-07-28 (SEP-2577).
Remains in the specification for at least twelve months; see the
deprecated features registry.</p> </div></div></section>
</div>
<div class="type">
### `RequestParams`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">RequestParams</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#requestparams-_meta">\_meta</a><span class="tsd-signature-symbol">:</span> <a href="#requestmetaobject" class="tsd-signature-type tsd-kind-interface">RequestMetaObject</a><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>Common params for any request.</p> </div> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="requestparams-_meta" data-typedoc-h="3"><span>\_meta: RequestMetaObject</span><a href="#requestparams-_meta" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section>
</div>
<div class="type">
### `Result`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">Result</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#result-_meta">\_meta</a><span class="tsd-signature-symbol">?:</span> <a href="#resultmetaobject" class="tsd-signature-type tsd-kind-interface">ResultMetaObject</a><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#result-resulttype">resultType</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <span class="tsd-signature-symbol">\[</span><span class="tsd-kind-index-signature">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <span class="tsd-signature-type">unknown</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>Common result fields.</p> </div> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="result-_meta" data-typedoc-h="3"><span>\_meta?: ResultMetaObject</span><a href="#result-_meta" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="result-resulttype" data-typedoc-h="3"><span>resultType: string</span><a href="#result-resulttype" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>Indicates the type of the result, which allows the client to determine
how to parse the result object.</p> <p>Servers implementing this protocol version MUST include this field.
For backward compatibility, when a client receives a result from a
server implementing an earlier protocol version (which does not include <code>resultType</code>), the client MUST treat the absent field as <code>"complete"</code>.</p> </div></section>
</div>
<div class="type">
### `ResultMetaObject`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">ResultMetaObject</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#resultmetaobject-iomodelcontextprotocolserverinfo">"io.modelcontextprotocol/serverInfo"</a><span class="tsd-signature-symbol">?:</span> <a href="#implementation" class="tsd-signature-type tsd-kind-interface">Implementation</a><span class="tsd-signature-symbol">;</span><br /> <span class="tsd-signature-symbol">\[</span><span class="tsd-kind-index-signature">key</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]:</span> <span class="tsd-signature-type">unknown</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>Extends <a href="#metaobject" class="tsd-kind-type-alias">MetaObject</a> with additional result-specific fields. All key naming rules from <code>MetaObject</code> apply.</p> </div> <div class="tsd-comment tsd-typography"> <div class="tsd-tag-see"> <div class="tsd-anchor-link" data-typedoc-h="4">See</div><ul> <li><a href="#metaobject" class="tsd-kind-type-alias">MetaObject</a> for key naming rules and reserved prefixes.</li> <li><a href="/specification/draft/basic/index#meta">General fields: <code>\_meta</code></a> for more details.</li> </ul> </div></div> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="resultmetaobject-iomodelcontextprotocolserverinfo" data-typedoc-h="3"><span>"io.modelcontextprotocol/serverInfo"?: Implementation</span><a href="#resultmetaobject-iomodelcontextprotocolserverinfo" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>Identifies the server software producing the response. Servers SHOULD
include this field on every response unless specifically configured not
to do so.</p> <p>The <a href="#implementation" class="tsd-kind-interface">Implementation</a> schema requires <code>name</code> and <code>version</code>; other
fields are optional.</p> <p>The value is self-reported by the server and is not verified by the
protocol. It is intended for display, logging, and debugging. Clients
SHOULD NOT use it to change their behavior, and SHOULD NOT rely on it for
security decisions.</p> </div></section>
</div>
<div class="type">
### `ResultType`
<div class="tsd-signature"><span class="tsd-kind-type-alias">ResultType</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">"complete"</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"input\_required"</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">string</span></div> <div class="tsd-comment tsd-typography"><p>Indicates the type of a <a href="#result" class="tsd-kind-interface">Result</a> object, allowing the client to
determine how to parse the response.</p> <p>complete - the request completed successfully and the result contains the final content.
input\_required - the request requires additional input and the result contains an <a href="#inputrequiredresult" class="tsd-kind-interface">InputRequiredResult</a> object with instructions for the client to provide additional input before retrying the original request.</p> </div>
</div>
<div class="type">
### `Role`
<div class="tsd-signature"><span class="tsd-kind-type-alias">Role</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">"user"</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">"assistant"</span></div> <div class="tsd-comment tsd-typography"><p>The sender or recipient of messages and data in a conversation.</p> </div>
</div>
## Errors
<div class="type">
### `Error`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">Error</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#error-code">code</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#error-message">message</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#error-data">data</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">unknown</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="error-code" data-typedoc-h="3"><span>code: number</span><a href="#error-code" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>The error type that occurred.</p> </div></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="error-message" data-typedoc-h="3"><span>message: string</span><a href="#error-message" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>A short description of the error. The message SHOULD be limited to a concise single sentence.</p> </div></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="error-data" data-typedoc-h="3"><span>data?: unknown</span><a href="#error-data" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>Additional information about the error. The value of this member is defined by the sender (e.g. detailed error information, nested errors etc.).</p> </div></section>
</div>
<div class="type">
### `HEADER_MISMATCH`
<div class="tsd-signature"><span class="tsd-kind-variable">HEADER\_MISMATCH</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">-32020</span></div> <div class="tsd-comment tsd-typography"><p>Error code returned when the HTTP headers of a request do not match the
corresponding values in the request body, or required headers are
missing or malformed.</p> </div>
</div>
<div class="type">
### `HeaderMismatchError`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">HeaderMismatchError</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#headermismatcherror-jsonrpc">jsonrpc</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">"2.0"</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#headermismatcherror-id">id</a><span class="tsd-signature-symbol">?:</span> <a href="#requestid" class="tsd-signature-type tsd-kind-type-alias">RequestId</a><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#headermismatcherror-error">error</a><span class="tsd-signature-symbol">:</span> <a href="#error" class="tsd-signature-type tsd-kind-interface">Error</a> <span class="tsd-signature-symbol">&</span> <span class="tsd-signature-symbol">\{</span> <span class="tsd-kind-property">code</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">-32020</span> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>Returned when a server rejects a request because the values in the HTTP
headers do not match the corresponding values in the request body, or
because required headers are missing or malformed. For HTTP, the response
status code MUST be <code>400 Bad Request</code>.</p> </div> <div class="tsd-comment tsd-typography"> <details class="tsd-tag-example"> <summary class="tsd-anchor-link">Example: Header mismatch<a href="#headermismatcherror-example-header-mismatch" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></summary><pre id="headermismatcherror-example-header-mismatch"><code class="json"><span class="hl-0">\{</span><br /><span class="hl-0"> </span><span class="hl-1">"jsonrpc"</span><span class="hl-0">: </span><span class="hl-2">"2.0"</span><span class="hl-0">,</span><br /><span class="hl-0"> </span><span class="hl-1">"id"</span><span class="hl-0">: </span><span class="hl-3">1</span><span class="hl-0">,</span><br /><span class="hl-0"> </span><span class="hl-1">"error"</span><span class="hl-0">: \{</span><br /><span class="hl-0"> </span><span class="hl-1">"code"</span><span class="hl-0">: </span><span class="hl-3">-32020</span><span class="hl-0">,</span><br /><span class="hl-0"> </span><span class="hl-1">"message"</span><span class="hl-0">: </span><span class="hl-2">"Header mismatch: Mcp-Name header value 'foo' does not match body value 'bar'"</span><br /><span class="hl-0"> }</span><br /><span class="hl-0">}</span> </code><button type="button">Copy</button></pre> </details></div> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="headermismatcherror-jsonrpc" data-typedoc-h="3"><span>jsonrpc: "2.0"</span><a href="#headermismatcherror-jsonrpc" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <aside class="tsd-sources"> <p>Inherited from <a href="#jsonrpcerrorresponse">JSONRPCErrorResponse</a>.<a href="#jsonrpcerrorresponse-jsonrpc">jsonrpc</a></p></aside></section> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="headermismatcherror-id" data-typedoc-h="3"><span>id?: RequestId</span><a href="#headermismatcherror-id" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <aside class="tsd-sources"> <p>Inherited from <a href="#jsonrpcerrorresponse">JSONRPCErrorResponse</a>.<a href="#jsonrpcerrorresponse-id">id</a></p></aside></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="headermismatcherror-error" data-typedoc-h="3"><span>error: Error & \{ code: -32020 }</span><a href="#headermismatcherror-error" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section>
</div>
<div class="type">
### `InternalError`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">InternalError</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#internalerror-message">message</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#internalerror-data">data</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">unknown</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#internalerror-code">code</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">-32603</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>A JSON-RPC error indicating that an internal error occurred on the receiver. This error is returned when the receiver encounters an unexpected condition that prevents it from fulfilling the request.</p> </div> <div class="tsd-comment tsd-typography"> <div class="tsd-tag-see"> <div class="tsd-anchor-link" data-typedoc-h="4">See</div><p><a href="https://www.jsonrpc.org/specification#error_object">JSON-RPC 2.0 Error Object</a></p> </div> <details class="tsd-tag-example"> <summary class="tsd-anchor-link">Example: Unexpected error<a href="#internalerror-example-unexpected-error" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></summary><pre id="internalerror-example-unexpected-error"><code class="json"><span class="hl-0">\{</span><br /><span class="hl-0"> </span><span class="hl-1">"code"</span><span class="hl-0">: </span><span class="hl-3">-32603</span><span class="hl-0">,</span><br /><span class="hl-0"> </span><span class="hl-1">"message"</span><span class="hl-0">: </span><span class="hl-2">"Internal error"</span><br /><span class="hl-0">}</span> </code><button type="button">Copy</button></pre> </details></div> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="internalerror-message" data-typedoc-h="3"><span>message: string</span><a href="#internalerror-message" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>A short description of the error. The message SHOULD be limited to a concise single sentence.</p> </div><aside class="tsd-sources"> <p>Inherited from <a href="#error">Error</a>.<a href="#error-message">message</a></p></aside></section> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="internalerror-data" data-typedoc-h="3"><span>data?: unknown</span><a href="#internalerror-data" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>Additional information about the error. The value of this member is defined by the sender (e.g. detailed error information, nested errors etc.).</p> </div><aside class="tsd-sources"> <p>Inherited from <a href="#error">Error</a>.<a href="#error-data">data</a></p></aside></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="internalerror-code" data-typedoc-h="3"><span>code: -32603</span><a href="#internalerror-code" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>The error type that occurred.</p> </div><aside class="tsd-sources"> <p>Overrides <a href="#error">Error</a>.<a href="#error-code">code</a></p></aside></section>
</div>
<div class="type">
### `InvalidParamsError`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">InvalidParamsError</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#invalidparamserror-message">message</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#invalidparamserror-data">data</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">unknown</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#invalidparamserror-code">code</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">-32602</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>A JSON-RPC error indicating that the method parameters are invalid or malformed.</p> <p>In MCP, this error is returned in various contexts when request parameters fail validation:</p> <ul> <li><strong>Tools</strong>: Unknown tool name or invalid tool arguments</li> <li><strong>Prompts</strong>: Unknown prompt name or missing required arguments</li> <li><strong>Pagination</strong>: Invalid or expired cursor values</li> <li><strong>Logging</strong>: Invalid log level</li> <li><strong>Elicitation</strong>: Server requests an elicitation mode not declared in client capabilities</li> <li><strong>Sampling</strong>: Missing tool result or tool results mixed with other content</li> </ul> </div> <div class="tsd-comment tsd-typography"> <div class="tsd-tag-see"> <div class="tsd-anchor-link" data-typedoc-h="4">See</div><p><a href="https://www.jsonrpc.org/specification#error_object">JSON-RPC 2.0 Error Object</a></p> </div> <details class="tsd-tag-example"> <summary class="tsd-anchor-link">Example: Unknown tool<a href="#invalidparamserror-example-unknown-tool" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></summary><pre id="invalidparamserror-example-unknown-tool"><code class="json"><span class="hl-0">\{</span><br /><span class="hl-0"> </span><span class="hl-1">"code"</span><span class="hl-0">: </span><span class="hl-3">-32602</span><span class="hl-0">,</span><br /><span class="hl-0"> </span><span class="hl-1">"message"</span><span class="hl-0">: </span><span class="hl-2">"Unknown tool: invalid\_tool\_name"</span><br /><span class="hl-0">}</span> </code><button type="button">Copy</button></pre> </details> <details class="tsd-tag-example"> <summary class="tsd-anchor-link">Example: Invalid tool arguments<a href="#invalidparamserror-example-invalid-tool-arguments" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></summary><pre id="invalidparamserror-example-invalid-tool-arguments"><code class="json"><span class="hl-0">\{</span><br /><span class="hl-0"> </span><span class="hl-1">"code"</span><span class="hl-0">: </span><span class="hl-3">-32602</span><span class="hl-0">,</span><br /><span class="hl-0"> </span><span class="hl-1">"message"</span><span class="hl-0">: </span><span class="hl-2">"Invalid arguments for tool calculate: Missing required property 'expression'"</span><br /><span class="hl-0">}</span> </code><button type="button">Copy</button></pre> </details> <details class="tsd-tag-example"> <summary class="tsd-anchor-link">Example: Unknown prompt<a href="#invalidparamserror-example-unknown-prompt" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></summary><pre id="invalidparamserror-example-unknown-prompt"><code class="json"><span class="hl-0">\{</span><br /><span class="hl-0"> </span><span class="hl-1">"code"</span><span class="hl-0">: </span><span class="hl-3">-32602</span><span class="hl-0">,</span><br /><span class="hl-0"> </span><span class="hl-1">"message"</span><span class="hl-0">: </span><span class="hl-2">"Unknown prompt: invalid\_prompt\_name"</span><br /><span class="hl-0">}</span> </code><button type="button">Copy</button></pre> </details> <details class="tsd-tag-example"> <summary class="tsd-anchor-link">Example: Invalid cursor<a href="#invalidparamserror-example-invalid-cursor" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></summary><pre id="invalidparamserror-example-invalid-cursor"><code class="json"><span class="hl-0">\{</span><br /><span class="hl-0"> </span><span class="hl-1">"code"</span><span class="hl-0">: </span><span class="hl-3">-32602</span><span class="hl-0">,</span><br /><span class="hl-0"> </span><span class="hl-1">"message"</span><span class="hl-0">: </span><span class="hl-2">"Invalid cursor"</span><br /><span class="hl-0">}</span> </code><button type="button">Copy</button></pre> </details></div> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="invalidparamserror-message" data-typedoc-h="3"><span>message: string</span><a href="#invalidparamserror-message" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>A short description of the error. The message SHOULD be limited to a concise single sentence.</p> </div><aside class="tsd-sources"> <p>Inherited from <a href="#error">Error</a>.<a href="#error-message">message</a></p></aside></section> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="invalidparamserror-data" data-typedoc-h="3"><span>data?: unknown</span><a href="#invalidparamserror-data" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>Additional information about the error. The value of this member is defined by the sender (e.g. detailed error information, nested errors etc.).</p> </div><aside class="tsd-sources"> <p>Inherited from <a href="#error">Error</a>.<a href="#error-data">data</a></p></aside></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="invalidparamserror-code" data-typedoc-h="3"><span>code: -32602</span><a href="#invalidparamserror-code" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>The error type that occurred.</p> </div><aside class="tsd-sources"> <p>Overrides <a href="#error">Error</a>.<a href="#error-code">code</a></p></aside></section>
</div>
<div class="type">
### `InvalidRequestError`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">InvalidRequestError</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#invalidrequesterror-message">message</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#invalidrequesterror-data">data</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">unknown</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#invalidrequesterror-code">code</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">-32600</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>A JSON-RPC error indicating that the request is not a valid request object. This error is returned when the message structure does not conform to the JSON-RPC 2.0 specification requirements for a request (e.g., missing required fields like <code>jsonrpc</code> or <code>method</code>, or using invalid types for these fields).</p> </div> <div class="tsd-comment tsd-typography"> <div class="tsd-tag-see"> <div class="tsd-anchor-link" data-typedoc-h="4">See</div><p><a href="https://www.jsonrpc.org/specification#error_object">JSON-RPC 2.0 Error Object</a></p> </div></div> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="invalidrequesterror-message" data-typedoc-h="3"><span>message: string</span><a href="#invalidrequesterror-message" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>A short description of the error. The message SHOULD be limited to a concise single sentence.</p> </div><aside class="tsd-sources"> <p>Inherited from <a href="#error">Error</a>.<a href="#error-message">message</a></p></aside></section> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="invalidrequesterror-data" data-typedoc-h="3"><span>data?: unknown</span><a href="#invalidrequesterror-data" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>Additional information about the error. The value of this member is defined by the sender (e.g. detailed error information, nested errors etc.).</p> </div><aside class="tsd-sources"> <p>Inherited from <a href="#error">Error</a>.<a href="#error-data">data</a></p></aside></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="invalidrequesterror-code" data-typedoc-h="3"><span>code: -32600</span><a href="#invalidrequesterror-code" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>The error type that occurred.</p> </div><aside class="tsd-sources"> <p>Overrides <a href="#error">Error</a>.<a href="#error-code">code</a></p></aside></section>
</div>
<div class="type">
### `MethodNotFoundError`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">MethodNotFoundError</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#methodnotfounderror-message">message</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#methodnotfounderror-data">data</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">unknown</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#methodnotfounderror-code">code</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">-32601</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>A JSON-RPC error indicating that the requested method does not exist or is not available.</p> <p>In MCP, a server returns this error when a client invokes a method the server does not implement — either a genuinely unknown method, or one gated behind a server capability the server did not advertise (e.g., calling <code>prompts/list</code> when the <code>prompts</code> capability was not advertised).</p> <p>A request that requires a client capability the client did not declare is signalled instead by <a href="#missingrequiredclientcapabilityerror" class="tsd-kind-interface">MissingRequiredClientCapabilityError</a> (<code>-32021</code>).</p> </div> <div class="tsd-comment tsd-typography"> <div class="tsd-tag-see"> <div class="tsd-anchor-link" data-typedoc-h="4">See</div><p><a href="https://www.jsonrpc.org/specification#error_object">JSON-RPC 2.0 Error Object</a></p> </div> <details class="tsd-tag-example"> <summary class="tsd-anchor-link">Example: Prompts not supported<a href="#methodnotfounderror-example-prompts-not-supported" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></summary><pre id="methodnotfounderror-example-prompts-not-supported"><code class="json"><span class="hl-0">\{</span><br /><span class="hl-0"> </span><span class="hl-1">"code"</span><span class="hl-0">: </span><span class="hl-3">-32601</span><span class="hl-0">,</span><br /><span class="hl-0"> </span><span class="hl-1">"message"</span><span class="hl-0">: </span><span class="hl-2">"Prompts not supported"</span><span class="hl-0">,</span><br /><span class="hl-0"> </span><span class="hl-1">"data"</span><span class="hl-0">: \{</span><br /><span class="hl-0"> </span><span class="hl-1">"reason"</span><span class="hl-0">: </span><span class="hl-2">"Server does not support the prompts capability"</span><br /><span class="hl-0"> }</span><br /><span class="hl-0">}</span> </code><button type="button">Copy</button></pre> </details></div> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="methodnotfounderror-message" data-typedoc-h="3"><span>message: string</span><a href="#methodnotfounderror-message" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>A short description of the error. The message SHOULD be limited to a concise single sentence.</p> </div><aside class="tsd-sources"> <p>Inherited from <a href="#error">Error</a>.<a href="#error-message">message</a></p></aside></section> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="methodnotfounderror-data" data-typedoc-h="3"><span>data?: unknown</span><a href="#methodnotfounderror-data" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>Additional information about the error. The value of this member is defined by the sender (e.g. detailed error information, nested errors etc.).</p> </div><aside class="tsd-sources"> <p>Inherited from <a href="#error">Error</a>.<a href="#error-data">data</a></p></aside></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="methodnotfounderror-code" data-typedoc-h="3"><span>code: -32601</span><a href="#methodnotfounderror-code" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>The error type that occurred.</p> </div><aside class="tsd-sources"> <p>Overrides <a href="#error">Error</a>.<a href="#error-code">code</a></p></aside></section>
</div>
<div class="type">
### `MISSING_REQUIRED_CLIENT_CAPABILITY`
<div class="tsd-signature"><span class="tsd-kind-variable">MISSING\_REQUIRED\_CLIENT\_CAPABILITY</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">-32021</span></div> <div class="tsd-comment tsd-typography"><p>Error code returned when a server requires a client capability that was
not declared in the request's <code>clientCapabilities</code>.</p> </div>
</div>
<div class="type">
### `MissingRequiredClientCapabilityError`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">MissingRequiredClientCapabilityError</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#missingrequiredclientcapabilityerror-jsonrpc">jsonrpc</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">"2.0"</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#missingrequiredclientcapabilityerror-id">id</a><span class="tsd-signature-symbol">?:</span> <a href="#requestid" class="tsd-signature-type tsd-kind-type-alias">RequestId</a><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#missingrequiredclientcapabilityerror-error">error</a><span class="tsd-signature-symbol">:</span> <a href="#error" class="tsd-signature-type tsd-kind-interface">Error</a> <span class="tsd-signature-symbol">&</span> <span class="tsd-signature-symbol">\{</span><br /> <span class="tsd-kind-property">code</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">-32021</span><span class="tsd-signature-symbol">;</span><br /> <span class="tsd-kind-property">data</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-symbol">\{</span> <span class="tsd-kind-property">requiredCapabilities</span><span class="tsd-signature-symbol">:</span> <a href="#clientcapabilities" class="tsd-signature-type tsd-kind-interface">ClientCapabilities</a> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span><br /> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>Returned when processing a request requires a capability the client did not
declare in <code>clientCapabilities</code>. For HTTP, the response status code MUST be <code>400 Bad Request</code>.</p> </div> <div class="tsd-comment tsd-typography"> <details class="tsd-tag-example"> <summary class="tsd-anchor-link">Example: Missing elicitation capability<a href="#missingrequiredclientcapabilityerror-example-missing-elicitation-capability" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></summary><pre id="missingrequiredclientcapabilityerror-example-missing-elicitation-capability"><code class="json"><span class="hl-0">\{</span><br /><span class="hl-0"> </span><span class="hl-1">"jsonrpc"</span><span class="hl-0">: </span><span class="hl-2">"2.0"</span><span class="hl-0">,</span><br /><span class="hl-0"> </span><span class="hl-1">"id"</span><span class="hl-0">: </span><span class="hl-3">1</span><span class="hl-0">,</span><br /><span class="hl-0"> </span><span class="hl-1">"error"</span><span class="hl-0">: \{</span><br /><span class="hl-0"> </span><span class="hl-1">"code"</span><span class="hl-0">: </span><span class="hl-3">-32021</span><span class="hl-0">,</span><br /><span class="hl-0"> </span><span class="hl-1">"message"</span><span class="hl-0">: </span><span class="hl-2">"Server requires the elicitation capability for this request"</span><span class="hl-0">,</span><br /><span class="hl-0"> </span><span class="hl-1">"data"</span><span class="hl-0">: \{</span><br /><span class="hl-0"> </span><span class="hl-1">"requiredCapabilities"</span><span class="hl-0">: \{</span><br /><span class="hl-0"> </span><span class="hl-1">"elicitation"</span><span class="hl-0">: \{}</span><br /><span class="hl-0"> }</span><br /><span class="hl-0"> }</span><br /><span class="hl-0"> }</span><br /><span class="hl-0">}</span> </code><button type="button">Copy</button></pre> </details></div> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="missingrequiredclientcapabilityerror-jsonrpc" data-typedoc-h="3"><span>jsonrpc: "2.0"</span><a href="#missingrequiredclientcapabilityerror-jsonrpc" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <aside class="tsd-sources"> <p>Inherited from <a href="#jsonrpcerrorresponse">JSONRPCErrorResponse</a>.<a href="#jsonrpcerrorresponse-jsonrpc">jsonrpc</a></p></aside></section> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="missingrequiredclientcapabilityerror-id" data-typedoc-h="3"><span>id?: RequestId</span><a href="#missingrequiredclientcapabilityerror-id" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <aside class="tsd-sources"> <p>Inherited from <a href="#jsonrpcerrorresponse">JSONRPCErrorResponse</a>.<a href="#jsonrpcerrorresponse-id">id</a></p></aside></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="missingrequiredclientcapabilityerror-error" data-typedoc-h="3"><span>error: Error & \{ code: -32021; data: \{ requiredCapabilities: ClientCapabilities }; }</span><a href="#missingrequiredclientcapabilityerror-error" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section>
</div>
<div class="type">
### `ParseError`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">ParseError</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#parseerror-message">message</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#parseerror-data">data</a><span class="tsd-signature-symbol">?:</span> <span class="tsd-signature-type">unknown</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#parseerror-code">code</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">-32700</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>A JSON-RPC error indicating that invalid JSON was received by the server. This error is returned when the server cannot parse the JSON text of a message.</p> </div> <div class="tsd-comment tsd-typography"> <div class="tsd-tag-see"> <div class="tsd-anchor-link" data-typedoc-h="4">See</div><p><a href="https://www.jsonrpc.org/specification#error_object">JSON-RPC 2.0 Error Object</a></p> </div> <details class="tsd-tag-example"> <summary class="tsd-anchor-link">Example: Invalid JSON<a href="#parseerror-example-invalid-json" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></summary><pre id="parseerror-example-invalid-json"><code class="json"><span class="hl-0">\{</span><br /><span class="hl-0"> </span><span class="hl-1">"code"</span><span class="hl-0">: </span><span class="hl-3">-32700</span><span class="hl-0">,</span><br /><span class="hl-0"> </span><span class="hl-1">"message"</span><span class="hl-0">: </span><span class="hl-2">"Parse error: Invalid JSON"</span><br /><span class="hl-0">}</span> </code><button type="button">Copy</button></pre> </details></div> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="parseerror-message" data-typedoc-h="3"><span>message: string</span><a href="#parseerror-message" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>A short description of the error. The message SHOULD be limited to a concise single sentence.</p> </div><aside class="tsd-sources"> <p>Inherited from <a href="#error">Error</a>.<a href="#error-message">message</a></p></aside></section> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="parseerror-data" data-typedoc-h="3"><span>data?: unknown</span><a href="#parseerror-data" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>Additional information about the error. The value of this member is defined by the sender (e.g. detailed error information, nested errors etc.).</p> </div><aside class="tsd-sources"> <p>Inherited from <a href="#error">Error</a>.<a href="#error-data">data</a></p></aside></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="parseerror-code" data-typedoc-h="3"><span>code: -32700</span><a href="#parseerror-code" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <div class="tsd-comment tsd-typography"><p>The error type that occurred.</p> </div><aside class="tsd-sources"> <p>Overrides <a href="#error">Error</a>.<a href="#error-code">code</a></p></aside></section>
</div>
<div class="type">
### `UNSUPPORTED_PROTOCOL_VERSION`
<div class="tsd-signature"><span class="tsd-kind-variable">UNSUPPORTED\_PROTOCOL\_VERSION</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">-32022</span></div> <div class="tsd-comment tsd-typography"><p>Error code returned when the request's protocol version is not supported
by the server.</p> </div>
</div>
<div class="type">
### `UnsupportedProtocolVersionError`
<div class="tsd-signature"><span class="tsd-signature-keyword">interface</span> <span class="tsd-kind-interface">UnsupportedProtocolVersionError</span> <span class="tsd-signature-symbol">\{</span><br /> <a class="tsd-kind-property" href="#unsupportedprotocolversionerror-jsonrpc">jsonrpc</a><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">"2.0"</span><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#unsupportedprotocolversionerror-id">id</a><span class="tsd-signature-symbol">?:</span> <a href="#requestid" class="tsd-signature-type tsd-kind-type-alias">RequestId</a><span class="tsd-signature-symbol">;</span><br /> <a class="tsd-kind-property" href="#unsupportedprotocolversionerror-error">error</a><span class="tsd-signature-symbol">:</span> <a href="#error" class="tsd-signature-type tsd-kind-interface">Error</a> <span class="tsd-signature-symbol">&</span> <span class="tsd-signature-symbol">\{</span><br /> <span class="tsd-kind-property">code</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">-32022</span><span class="tsd-signature-symbol">;</span><br /> <span class="tsd-kind-property">data</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-symbol">\{</span> <span class="tsd-kind-property">supported</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">\[]</span><span class="tsd-signature-symbol">;</span> <span class="tsd-kind-property">requested</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span><br /> <span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol">;</span><br /><span class="tsd-signature-symbol">}</span></div> <div class="tsd-comment tsd-typography"><p>Returned when the request's protocol version is unknown to the server or
unsupported (e.g., a known experimental or draft version the server has
chosen not to implement). For HTTP, the response status code MUST be <code>400 Bad Request</code>.</p> </div> <div class="tsd-comment tsd-typography"> <details class="tsd-tag-example"> <summary class="tsd-anchor-link">Example: Unsupported protocol version<a href="#unsupportedprotocolversionerror-example-unsupported-protocol-version" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></summary><pre id="unsupportedprotocolversionerror-example-unsupported-protocol-version"><code class="json"><span class="hl-0">\{</span><br /><span class="hl-0"> </span><span class="hl-1">"jsonrpc"</span><span class="hl-0">: </span><span class="hl-2">"2.0"</span><span class="hl-0">,</span><br /><span class="hl-0"> </span><span class="hl-1">"id"</span><span class="hl-0">: </span><span class="hl-3">1</span><span class="hl-0">,</span><br /><span class="hl-0"> </span><span class="hl-1">"error"</span><span class="hl-0">: \{</span><br /><span class="hl-0"> </span><span class="hl-1">"code"</span><span class="hl-0">: </span><span class="hl-3">-32022</span><span class="hl-0">,</span><br /><span class="hl-0"> </span><span class="hl-1">"message"</span><span class="hl-0">: </span><span class="hl-2">"Unsupported protocol version"</span><span class="hl-0">,</span><br /><span class="hl-0"> </span><span class="hl-1">"data"</span><span class="hl-0">: \{</span><br /><span class="hl-0"> </span><span class="hl-1">"supported"</span><span class="hl-0">: \[</span><br /><span class="hl-0"> </span><span class="hl-2">"2026-07-28"</span><span class="hl-0">,</span><br /><span class="hl-0"> </span><span class="hl-2">"2025-11-25"</span><br /><span class="hl-0"> ],</span><br /><span class="hl-0"> </span><span class="hl-1">"requested"</span><span class="hl-0">: </span><span class="hl-2">"1900-01-01"</span><br /><span class="hl-0"> }</span><br /><span class="hl-0"> }</span><br /><span class="hl-0">}</span> </code><button type="button">Copy</button></pre> </details></div> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="unsupportedprotocolversionerror-jsonrpc" data-typedoc-h="3"><span>jsonrpc: "2.0"</span><a href="#unsupportedprotocolversionerror-jsonrpc" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <aside class="tsd-sources"> <p>Inherited from <a href="#jsonrpcerrorresponse">JSONRPCErrorResponse</a>.<a href="#jsonrpcerrorresponse-jsonrpc">jsonrpc</a></p></aside></section> <section class="tsd-panel tsd-member tsd-is-inherited"> <div class="tsd-anchor-link" id="unsupportedprotocolversionerror-id" data-typedoc-h="3"><span>id?: RequestId</span><a href="#unsupportedprotocolversionerror-id" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> <aside class="tsd-sources"> <p>Inherited from <a href="#jsonrpcerrorresponse">JSONRPCErrorResponse</a>.<a href="#jsonrpcerrorresponse-id">id</a></p></aside></section> <section class="tsd-panel tsd-member"> <div class="tsd-anchor-link" id="unsupportedprotocolversionerror-error" data-typedoc-h="3"><span>error: Error & \{ code: -32022; data: \{ supported: string\[]; requested: string }; }</span><a href="#unsupportedprotocolversionerror-error" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor" /></svg></a></div> </section>
</div>
## Content
<div class="type">
Cut at 300 lines. The page has the rest.
specification/draft/server/discover New page · 106 lines, new page
# Discovery ## Request ## Response ## When to Call ## Data Types ### DiscoverResult
A whole new page. There's nothing to diff it against, so here is what it says.
# Discovery
<div id="enable-section-numbers" />
`server/discover` lets a client query a server's supported protocol versions,
capabilities, and identity before sending any other requests. Servers **MUST**
implement it.
## Request
The request carries no body parameters beyond the standard `_meta`:
```json theme={null}
{
"jsonrpc": "2.0",
"id": "discover-1",
"method": "server/discover",
"params": {
"_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientInfo": {
"name": "ExampleClient",
"version": "1.0.0"
},
"io.modelcontextprotocol/clientCapabilities": {}
}
}
}
```
## Response
The server replies with its supported protocol versions, capabilities, and
identity. This operation supports [caching](/specification/draft/server/utilities/caching).
```json theme={null}
{
"jsonrpc": "2.0",
"id": "discover-1",
"result": {
"resultType": "complete",
"supportedVersions": ["2026-07-28"],
"capabilities": {
"tools": {},
"resources": {}
},
"_meta": {
"io.modelcontextprotocol/serverInfo": {
"name": "ExampleServer",
"version": "1.0.0"
}
},
"instructions": "This server provides weather and resource utilities.",
"ttlMs": 3600000,
"cacheScope": "public"
}
}
```
## When to Call
Calling `server/discover` is optional for clients — a client may invoke any
RPC inline and handle
[`UnsupportedProtocolVersionError`](/specification/draft/schema#unsupportedprotocolversionerror)
if the server does not support the requested version. However, `server/discover`
is useful in two scenarios:
* **Presenting server information.** While a client doesn't need to call
`server/discover` to use the server, it's a convenient way to retrieve the
server's identity, capabilities, and supported versions in a single request.
For example, a client can present the capabilities a server supports from a
single `server/discover` response instead of probing with separate
`tools/list`, `prompts/list`, and `resources/list` requests.
* **stdio backward-compatibility probe.** On stdio, there is no per-request
HTTP status code to drive fallback. A client that supports both modern
(per-request `_meta`) and legacy (`initialize` handshake) servers **SHOULD**
send `server/discover` first; see
[stdio: Backward Compatibility](/specification/draft/basic/transports/stdio#backward-compatibility)
for the fallback rules.
See [Protocol Version Negotiation](/specification/draft/basic/versioning#protocol-version-negotiation)
for the full version-selection flow. For HTTP-specific status codes returned for
unknown methods, see the [Protocol Version Header](/specification/draft/basic/transports/streamable-http#protocol-version-header)
section in Transports.
## Data Types
### DiscoverResult
A discovery result includes:
* `supportedVersions`: Protocol versions the server supports. The client should
choose one of these for subsequent requests.
* `capabilities`: Capabilities the server supports (tools, resources, prompts,
etc.)
* `_meta['io.modelcontextprotocol/serverInfo']`: Name and version of the server
software. Servers **SHOULD** include this field.
* `instructions`: Optional natural-language guidance for LLMs on how to use
this server effectively
<Note>
`serverInfo` is self-reported by the server and is not verified by the
protocol. It is intended for display, logging, and debugging. Clients **SHOULD
NOT** use it to change their behavior, and **SHOULD NOT** rely on it for
security decisions.
</Note>
community/interest-groups/security Changed · +1 / -1 lines
* **[Server Card WG](/community/working-groups/server-card) / [Registry WG](/community/working-groups/registry)**: server identity, provenance, and discovery metadata intersect with admission and supply-chain concerns -* **Transports WG**: stdio process isolation and unauthenticated method surface +* **[Transports WG](/community/working-groups/transports)**: stdio process isolation and unauthenticated method surface * **SDK Maintainers**: coordinated handling of SDK security advisories and cross-SDK security defaults
specification/draft/server/index New page · 29 lines, new page
# Overview
A whole new page. There's nothing to diff it against, so here is what it says.
# Overview
Servers provide the fundamental building blocks for adding context to language models via
MCP. These primitives enable rich interactions between clients, servers, and language
models:
* **Prompts**: Pre-defined templates or instructions that guide language model
interactions
* **Resources**: Structured data or content that provides additional context to the model
* **Tools**: Executable functions that allow models to perform actions or retrieve
information
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 |
Explore these key primitives in more detail below:
<CardGroup cols={3}>
<Card title="Prompts" icon="message" href="/specification/draft/server/prompts" />
<Card title="Resources" icon="file-lines" href="/specification/draft/server/resources" />
<Card title="Tools" icon="wrench" href="/specification/draft/server/tools" />
</CardGroup>
specification/draft/server/prompts New page · 334 lines, new page
# Prompts ## User Interaction Model ## Capabilities ## Protocol Messages ### Listing Prompts ### Getting a Prompt ### List Changed Notification ## Message Flow ## Data Types ### Prompt ### PromptMessage #### Text Content #### Image Content #### Audio Content #### Resource Links #### Embedded Resources ## Error Handling ## Implementation Considerations ## Security
A whole new page. There's nothing to diff it against, so here is what it says.
# Prompts
<div id="enable-section-numbers" />
The Model Context Protocol (MCP) provides a standardized way for servers to expose prompt
templates to clients. Prompts allow servers to provide structured messages and
instructions for interacting with language models. Clients can discover available
prompts, retrieve their contents, and provide arguments to customize them.
<Note>
For brevity, the request examples on this page omit the `_meta` request
metadata (`io.modelcontextprotocol/protocolVersion`,
`io.modelcontextprotocol/clientInfo`, and
`io.modelcontextprotocol/clientCapabilities`). Every request **MUST** include
the required `_meta` fields; see
[`_meta`](/specification/draft/basic/index#meta).
</Note>
## User Interaction Model
Prompts are designed to be **user-controlled**, meaning they are exposed from servers to
clients with the intention of the user being able to explicitly select them for use.
This refers to who decides when the prompt is used, not who authors its content. Prompt
content is defined by the server.
Typically, prompts would be triggered through user-initiated commands in the user
interface, which allows users to naturally discover and invoke available prompts.
For example, as slash commands:
<img src="https://mintcdn.com/mcp/4ZXF1PrDkEaJvXpn/specification/draft/server/slash-command.png?fit=max&auto=format&n=4ZXF1PrDkEaJvXpn&q=85&s=02e1902c84120c10cfa83d0234a0040d" alt="Example of prompt exposed as slash command" width="293" height="106" data-path="specification/draft/server/slash-command.png" />
However, implementors are free to expose prompts through any interface pattern that suits
their needs—the protocol itself does not mandate any specific user interaction
model.
## Capabilities
Servers that support prompts **MUST** declare the `prompts` capability in their
[`DiscoverResult`](/specification/draft/schema#discoverresult):
```json theme={null}
{
"capabilities": {
"prompts": {
"listChanged": true
}
}
}
```
`listChanged` indicates whether the server will emit notifications when the list of
available prompts changes.
Servers that declare the `prompts` capability **MUST** respond to `prompts/list` requests
with the set of prompts currently available to the requesting client. This set **MAY** be
empty and **MAY** change over time (see
[List Changed Notification](#list-changed-notification)), but **MUST NOT** vary
per-connection or as a side effect of other requests on the connection. The set
**MAY** vary by the authorization presented on the request — for example, returning
only the prompts the caller's granted scopes permit — since credentials are
per-request input, not connection state.
## Protocol Messages
### Listing Prompts
To retrieve available prompts, clients send a `prompts/list` request. This operation
supports [pagination](/specification/draft/server/utilities/pagination) and [caching](/specification/draft/server/utilities/caching).
**Request:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"method": "prompts/list",
"params": {
"cursor": "optional-cursor-value"
}
}
```
**Response:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"resultType": "complete",
"prompts": [
{
"name": "code_review",
"title": "Request Code Review",
"description": "Asks the LLM to analyze code quality and suggest improvements",
"arguments": [
{
"name": "code",
"description": "The code to review",
"required": true
}
],
"icons": [
{
"src": "https://example.com/review-icon.svg",
"mimeType": "image/svg+xml",
"sizes": ["any"]
}
]
}
],
"nextCursor": "next-page-cursor",
"ttlMs": 600000,
"cacheScope": "public"
}
}
```
### Getting a Prompt
To retrieve a specific prompt, clients send a `prompts/get` request. Arguments may be
auto-completed through [the completion API](/specification/draft/server/utilities/completion).
**Request:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 2,
"method": "prompts/get",
"params": {
"name": "code_review",
"arguments": {
"code": "def hello():\n print('world')"
}
}
}
```
**Response:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"resultType": "complete",
"description": "Code review prompt",
"messages": [
{
"role": "user",
"content": {
"type": "text",
"text": "Please review this Python code:\ndef hello():\n print('world')"
}
}
]
}
}
```
Servers **MAY** also respond to `prompts/get` with an [`InputRequiredResult`](/specification/draft/basic/patterns/mrtr#inputrequiredresult) to indicate that additional input is needed before the prompt can be resolved. This follows the [multi round-trip requests](/specification/draft/basic/patterns/mrtr#multi-round-trip-requests) mechanism. When retrying the request, clients include `inputResponses` and, if provided by the server, `requestState` in the request parameters.
### List Changed Notification
When the list of available prompts changes, servers that declared the `listChanged`
capability **SHOULD** send a notification to clients that have opened a
[`subscriptions/listen`](/specification/draft/basic/patterns/subscriptions) stream with
`promptsListChanged: true`:
```json theme={null}
{
"jsonrpc": "2.0",
"method": "notifications/prompts/list_changed"
}
```
## Message Flow
```mermaid theme={null}
sequenceDiagram
participant Client
participant Server
Note over Client,Server: Discovery
Client->>Server: prompts/list
Server-->>Client: List of prompts
Note over Client,Server: Usage
Client->>Server: prompts/get
Server-->>Client: Prompt content
opt listChanged
Client->>Server: subscriptions/listen (promptsListChanged: true)
Server--)Client: notifications/subscriptions/acknowledged
Note over Client,Server: Changes
Server--)Client: notifications/prompts/list_changed
Client->>Server: prompts/list
Server-->>Client: Updated prompts
end
```
## Data Types
### Prompt
A prompt definition includes:
* `name`: Unique identifier for the prompt
* `title`: Optional human-readable name of the prompt for display purposes.
* `description`: Optional human-readable description
* `icons`: Optional array of icons for display in user interfaces
* `arguments`: Optional list of arguments for customization
### PromptMessage
Messages in a prompt can contain:
* `role`: Either "user" or "assistant" to indicate the speaker
* `content`: One of the following content types:
<Note>
All content types in prompt messages support optional
[annotations](/specification/draft/server/resources#annotations) for metadata
about audience, priority, and modification times.
</Note>
#### Text Content
Text content represents plain text messages:
```json theme={null}
{
"type": "text",
"text": "The text content of the message"
}
```
This is the most common content type used for natural language interactions.
#### Image Content
Image content allows including visual information in messages:
```json theme={null}
{
"type": "image",
"data": "base64-encoded-image-data",
"mimeType": "image/png"
}
```
The image data **MUST** be base64-encoded and include a valid MIME type. This enables
multi-modal interactions where visual context is important.
#### Audio Content
Audio content allows including audio information in messages:
```json theme={null}
{
"type": "audio",
"data": "base64-encoded-audio-data",
"mimeType": "audio/wav"
}
```
The audio data MUST be base64-encoded and include a valid MIME type. This enables
multi-modal interactions where audio context is important.
#### Resource Links
Prompt messages **MAY** include links to
[Resources](/specification/draft/server/resources), to provide additional context or
data without embedding the resource contents directly. In this case, the prompt message
returns a URI that can be fetched by the client:
```json theme={null}
{
"type": "resource_link",
"uri": "file:///project/src/main.rs",
"name": "main.rs",
"description": "Primary application entry point",
"mimeType": "text/x-rust"
}
```
Resource links support the same [Resource annotations](/specification/draft/server/resources#annotations)
as regular resources to help clients understand how to use them.
#### Embedded Resources
Embedded resources allow referencing server-side resources directly in messages:
```json theme={null}
{
"type": "resource",
"resource": {
"uri": "resource://example",
Cut at 300 lines. The page has the rest.
specification/draft/server/resources New page · 434 lines, new page
# Resources ## User Interaction Model ## Capabilities ## Protocol Messages ### Listing Resources ### Reading Resources ### Resource Templates ### List Changed Notification ### Subscriptions ## Message Flow ## Data Types ### Resource ### Resource Contents #### Text Content #### Binary Content ### Annotations ## Common URI Schemes ### https\:// ### file:// ### git:// ### Custom URI Schemes ## Error Handling ## Security Considerations
A whole new page. There's nothing to diff it against, so here is what it says.
# Resources
<div id="enable-section-numbers" />
The Model Context Protocol (MCP) provides a standardized way for servers to expose
resources to clients. Resources allow servers to share data that provides context to
language models, such as files, database schemas, or application-specific information.
Each resource is uniquely identified by a
[URI](https://datatracker.ietf.org/doc/html/rfc3986).
<Note>
For brevity, the request examples on this page omit the `_meta` request
metadata (`io.modelcontextprotocol/protocolVersion`,
`io.modelcontextprotocol/clientInfo`, and
`io.modelcontextprotocol/clientCapabilities`). Every request **MUST** include
the required `_meta` fields; see
[`_meta`](/specification/draft/basic/index#meta).
</Note>
## User Interaction Model
Resources in MCP are designed to be **application-driven**, with host applications
determining how to incorporate context based on their needs.
For example, applications could:
* Expose resources through UI elements for explicit selection, in a tree or list view
* Allow the user to search through and filter available resources
* Implement automatic context inclusion, based on heuristics or the AI model's selection
<img src="https://mintcdn.com/mcp/4ZXF1PrDkEaJvXpn/specification/draft/server/resource-picker.png?fit=max&auto=format&n=4ZXF1PrDkEaJvXpn&q=85&s=2026c8851a10ac020117731076a486b9" alt="Example of resource context picker" width="174" height="181" data-path="specification/draft/server/resource-picker.png" />
However, implementations are free to expose resources through any interface pattern that
suits their needs—the protocol itself does not mandate any specific user
interaction model.
## Capabilities
Servers that support resources **MUST** declare the `resources` capability:
```json theme={null}
{
"capabilities": {
"resources": {
"listChanged": true,
"subscribe": true
}
}
}
```
The capability supports two optional features:
* `listChanged`: whether the server will emit notifications when the list of available
resources changes.
* `subscribe` : whether the server supports resource-specific update notifications
for resources requested through subscriptions/listen using the resourceSubscriptions
filter.
Servers may advertise either feature independently, together or neither.
Serves that support neither `listChanged` or `subscribe` may omit it:
```json theme={null}
{
"capabilities": {
"resources": {}
}
}
```
Servers that declare the `resources` capability **MUST** respond to `resources/list`
requests with the set of resources currently available to the requesting client. This set
**MAY** be empty and **MAY** change over time (see
[List Changed Notification](#list-changed-notification)), but **MUST NOT** vary
per-connection or as a side effect of other requests on the connection. The set
**MAY** vary by the authorization presented on the request — for example, returning
only the resources the caller's granted scopes permit — since credentials are
per-request input, not connection state.
## Protocol Messages
### Listing Resources
To discover available resources, clients send a `resources/list` request. This operation
supports [pagination](/specification/draft/server/utilities/pagination) and [caching](/specification/draft/server/utilities/caching).
**Request:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"method": "resources/list",
"params": {
"cursor": "optional-cursor-value"
}
}
```
**Response:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"resultType": "complete",
"resources": [
{
"uri": "file:///project/src/main.rs",
"name": "main.rs",
"title": "Rust Software Application Main File",
"description": "Primary application entry point",
"mimeType": "text/x-rust",
"icons": [
{
"src": "https://example.com/rust-file-icon.png",
"mimeType": "image/png",
"sizes": ["48x48"]
}
]
}
],
"nextCursor": "next-page-cursor",
"ttlMs": 300000,
"cacheScope": "public"
}
}
```
### Reading Resources
To retrieve resource contents, clients send a `resources/read` request. This operation
supports [caching](/specification/draft/server/utilities/caching).
**Request:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 2,
"method": "resources/read",
"params": {
"uri": "file:///project/src/main.rs"
}
}
```
**Response:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"resultType": "complete",
"contents": [
{
"uri": "file:///project/src/main.rs",
"mimeType": "text/x-rust",
"text": "fn main() {\n println!(\"Hello world!\");\n}"
}
],
"ttlMs": 60000,
"cacheScope": "private"
}
}
```
Servers **MAY** return multiple resource contents in response to a single
`resources/read` request. For example, a server could return the contents of
several files when a directory resource is read.
Servers **MAY** also respond to `resources/read` with an [`InputRequiredResult`](/specification/draft/basic/patterns/mrtr#inputrequiredresult) to indicate that additional input is needed before the resource can be read. This follows the [multi round-trip requests](/specification/draft/basic/patterns/mrtr#multi-round-trip-requests) mechanism. When retrying the request, clients include `inputResponses` and, if provided by the server, `requestState` in the request parameters.
Alternatively, if the scheme of `uri` is `https://`, clients may fetch the resource directly from the web. See the [Common URI Schemes section](#https%3A%2F%2F) for more information.
### Resource Templates
Resource templates allow servers to expose parameterized resources using
[URI templates](https://datatracker.ietf.org/doc/html/rfc6570). Arguments may be
auto-completed through [the completion API](/specification/draft/server/utilities/completion).
This operation supports [pagination](/specification/draft/server/utilities/pagination) and [caching](/specification/draft/server/utilities/caching).
**Request:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 3,
"method": "resources/templates/list",
"params": {
"cursor": "optional-cursor-value"
}
}
```
**Response:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 3,
"result": {
"resultType": "complete",
"resourceTemplates": [
{
"uriTemplate": "file:///{path}",
"name": "Project Files",
"title": "📁 Project Files",
"description": "Access files in the project directory",
"mimeType": "application/octet-stream",
"icons": [
{
"src": "https://example.com/folder-icon.png",
"mimeType": "image/png",
"sizes": ["48x48"]
}
]
}
],
"nextCursor": "next-page-cursor",
"ttlMs": 300000,
"cacheScope": "public"
}
}
```
### List Changed Notification
When the list of available resources changes, servers that declared the `listChanged`
capability **SHOULD** send a notification:
```json theme={null}
{
"jsonrpc": "2.0",
"method": "notifications/resources/list_changed"
}
```
### Subscriptions
Clients subscribe to change notifications for specific resources by sending a
[`subscriptions/listen`][subscriptions-listen] request with the resource URIs listed in
`notifications.resourceSubscriptions`. The server delivers
`notifications/resources/updated` on the resulting stream whenever a watched resource
changes.
```json theme={null}
{
"jsonrpc": "2.0",
"method": "notifications/resources/updated",
"params": {
"_meta": { "io.modelcontextprotocol/subscriptionId": 4 },
"uri": "file:///project/src/main.rs"
}
}
```
See [Subscriptions][subscriptions] for the full protocol mechanics (acknowledgment,
`subscriptionId` correlation, and cancellation).
[subscriptions-listen]: /specification/draft/schema#subscriptionslistenrequest
[subscriptions]: /specification/draft/basic/patterns/subscriptions
## Message Flow
```mermaid theme={null}
sequenceDiagram
participant Client
participant Server
Note over Client,Server: Resource Discovery
Client->>Server: resources/list
Server-->>Client: List of resources
Note over Client,Server: Resource Template Discovery
Client->>Server: resources/templates/list
Server-->>Client: List of resource templates
Note over Client,Server: Resource Access
Client->>Server: resources/read
Server-->>Client: Resource contents
Note over Client,Server: Subscribe to changes
Client->>Server: subscriptions/listen (resourceSubscriptions)
Server--)Client: notifications/subscriptions/acknowledged
Note over Client,Server: Resource updated
Server--)Client: notifications/resources/updated
Client->>Server: resources/read
Server-->>Client: Updated contents
```
## Data Types
### Resource
Cut at 300 lines. The page has the rest.
specification/draft/server/tools New page · 793 lines, new page
# Tools ## User Interaction Model ## Capabilities ## Protocol Messages ### Listing Tools ### Calling Tools ### Input Required Tool Results ### List Changed Notification ## Message Flow ## Data Types ### Tool #### Tool Names #### x-mcp-header ### Tool Result #### Text Content #### Image Content #### Audio Content #### Resource Links #### Embedded Resources #### Structured Content #### Output Schema ### Schema Examples #### Tool with default 2020-12 schema: #### Tool with explicit draft-07 schema: #### Tool with no parameters: ## Stateful Tools ## Error Handling ## Security Considerations
A whole new page. There's nothing to diff it against, so here is what it says.
# Tools
<div id="enable-section-numbers" />
The Model Context Protocol (MCP) allows servers to expose tools that can be invoked by
language models. Tools enable models to interact with external systems, such as querying
databases, calling APIs, or performing computations. Each tool is uniquely identified by
a name and includes metadata describing its schema.
<Note>
For brevity, the request examples on this page omit the `_meta` request
metadata (`io.modelcontextprotocol/protocolVersion`,
`io.modelcontextprotocol/clientInfo`, and
`io.modelcontextprotocol/clientCapabilities`). Every request **MUST** include
the required `_meta` fields; see
[`_meta`](/specification/draft/basic/index#meta).
</Note>
## User Interaction Model
Tools in MCP are designed to be **model-controlled**, meaning that the language model can
discover and invoke tools automatically based on its contextual understanding and the
user's prompts.
However, implementations are free to expose tools through any interface pattern that
suits their needs—the protocol itself does not mandate any specific user
interaction model.
<Warning>
For trust & safety and security, there **SHOULD** always
be a human in the loop with the ability to deny tool invocations.
Applications **SHOULD**:
* Provide UI that makes clear which tools are being exposed to the AI model
* Insert clear visual indicators when tools are invoked
* Present confirmation prompts to the user for operations, to ensure a human is in the
loop
</Warning>
## Capabilities
Servers that support tools **MUST** declare the `tools` capability:
```json theme={null}
{
"capabilities": {
"tools": {
"listChanged": true
}
}
}
```
`listChanged` indicates whether the server will emit notifications when the list of
available tools changes.
Servers that declare the `tools` capability **MUST** respond to `tools/list` requests
with the set of tools currently available to the requesting client. This set **MAY** be
empty and **MAY** change over time (see
[List Changed Notification](#list-changed-notification)), but **MUST NOT** vary
per-connection or as a side effect of other requests on the connection. The set
**MAY** vary by the authorization presented on the request — for example, returning
only the tools the caller's granted scopes permit — since credentials are
per-request input, not connection state.
Servers **SHOULD** return tools in a deterministic order (i.e., the same ordering across
requests when the underlying set of tools has not changed). Deterministic ordering enables
clients to reliably cache the tool list and improves LLM prompt cache hit rates when tools
are included in model context.
## Protocol Messages
### Listing Tools
To discover available tools, clients send a `tools/list` request. This operation supports
[pagination](/specification/draft/server/utilities/pagination) and [caching](/specification/draft/server/utilities/caching).
**Request:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list",
"params": {
"cursor": "optional-cursor-value"
}
}
```
**Response:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"resultType": "complete",
"tools": [
{
"name": "get_weather",
"title": "Weather Information Provider",
"description": "Get current weather information for a location",
"inputSchema": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "City name or zip code"
}
},
"required": ["location"]
},
"icons": [
{
"src": "https://example.com/weather-icon.png",
"mimeType": "image/png",
"sizes": ["48x48"]
}
]
}
],
"nextCursor": "next-page-cursor",
"ttlMs": 300000,
"cacheScope": "public"
}
}
```
### Calling Tools
To invoke a tool, clients send a `tools/call` request:
**Request:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "get_weather",
"arguments": {
"location": "New York"
}
}
}
```
**Response:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"resultType": "complete",
"content": [
{
"type": "text",
"text": "Current weather in New York:\nTemperature: 72°F\nConditions: Partly cloudy"
}
],
"isError": false
}
}
```
### Input Required Tool Results
Servers **MAY** respond to `tools/call` with an [`InputRequiredResult`](/specification/draft/basic/patterns/mrtr#inputrequiredresult) to indicate that additional input is needed before the tool call can be completed. This follows the [multi round-trip requests](/specification/draft/basic/patterns/mrtr#multi-round-trip-requests) mechanism.
When retrying the request with input responses, clients include `inputResponses` and, if provided by the server, `requestState` in the request parameters:
**Input Required Response:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"resultType": "input_required",
"inputRequests": {
"github_login": {
"method": "elicitation/create",
"params": {
"mode": "form",
"message": "Please provide your GitHub username",
"requestedSchema": {
"type": "object",
"properties": {
"name": { "type": "string" }
},
"required": ["name"]
}
}
}
},
"requestState": "eyJsb2NhdGlvbiI6Ik5ldyBZb3JrIn0..."
}
}
```
**Retry with Input Responses:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "get_weather",
"arguments": {
"location": "New York"
},
"inputResponses": {
"github_login": {
"action": "accept",
"content": {
"name": "octocat"
}
}
},
"requestState": "eyJsb2NhdGlvbiI6Ik5ldyBZb3JrIn0..."
}
}
```
Note that the JSON-RPC `id` **MUST** be different between the initial request and the retry.
### List Changed Notification
When the list of available tools changes, servers that declared the `listChanged`
capability **SHOULD** send a notification to clients that have opened a
[`subscriptions/listen`](/specification/draft/basic/patterns/subscriptions) stream with
`toolsListChanged: true`:
```json theme={null}
{
"jsonrpc": "2.0",
"method": "notifications/tools/list_changed"
}
```
## Message Flow
```mermaid theme={null}
sequenceDiagram
participant LLM
participant Client
participant Server
Note over Client,Server: Discovery
Client->>Server: tools/list
Server-->>Client: List of tools
Note over Client,LLM: Tool Selection
LLM->>Client: Select tool to use
Note over Client,Server: Invocation
Client->>Server: tools/call
Server-->>Client: Tool result
Client->>LLM: Process result
opt listChanged
Client->>Server: subscriptions/listen (toolsListChanged: true)
Server--)Client: notifications/subscriptions/acknowledged
Note over Client,Server: Updates
Server--)Client: notifications/tools/list_changed
Client->>Server: tools/list
Server-->>Client: Updated tools
end
```
## Data Types
### Tool
A tool definition includes:
* `name`: Unique identifier for the tool
* `title`: Optional human-readable name of the tool for display purposes.
* `description`: Human-readable description of functionality
* `icons`: Optional array of icons for display in user interfaces
* `inputSchema`: JSON Schema defining expected parameters
* Follows the [JSON Schema usage guidelines](/specification/draft/basic#json-schema-usage)
* Defaults to 2020-12 if no `$schema` field is present
* **MUST** be a valid JSON Schema object (not `null`)
* For tools with no parameters, use one of these valid approaches:
* `{ "type": "object", "additionalProperties": false }` - **Recommended**: explicitly accepts only empty objects
* `{ "type": "object" }` - accepts any object (including with properties)
* Properties **MAY** include an [`x-mcp-header`](#x-mcp-header) annotation to expose
parameter values as HTTP headers
* `outputSchema`: Optional JSON Schema defining expected output structure
* Follows the [JSON Schema usage guidelines](/specification/draft/basic#json-schema-usage)
* Defaults to 2020-12 if no `$schema` field is present
* `annotations`: Optional properties describing tool behavior
<Warning>
Cut at 300 lines. The page has the rest.
specification/draft/server/utilities/caching New page · 177 lines, new page
# Caching ## Cacheable Results ## Cache Key ## Cacheable Model ### Time-to-Live (TTL) Field #### Freshness Calculation ### Cache Scope Field #### Choosing a Cache Scope ## Interaction with Notifications ## Interaction with Pagination ## Security Considerations
A whole new page. There's nothing to diff it against, so here is what it says.
# Caching
<div id="enable-section-numbers" />
The Model Context Protocol (MCP) supports caching for some results. This allows clients to cache responses and reduce unnecessary re-fetching.
Caching is complementary to [change notifications](#interaction-with-notifications)—both
mechanisms can coexist.
## Cacheable Results
Servers MUST include caching hints on results with `resultType: "complete"` returned by
the following operations:
* `server/discover`
* `tools/list`
* `prompts/list`
* `resources/list`
* `resources/templates/list`
* `resources/read`
Interim results with `resultType: "input_required"` (see
[multi round-trip requests](/specification/draft/basic/patterns/mrtr)) are not cacheable
and carry no caching hints.
## Cache Key
A cached response is identified by the request method together with the request
parameters that affect the result (for example, the `uri` for `resources/read`, or the
`cursor` for paginated list requests). Clients **MUST NOT** serve a cached response for
a request whose method or parameters differ from the request that produced it.
Results produced by retrying a request through the
[multi round-trip requests](/specification/draft/basic/patterns/mrtr) mechanism—that
is, requests carrying `inputResponses` or `requestState`—**MUST NOT** be cached,
as they depend on inputs that are not part of the cache key.
## Cacheable Model
Cacheable Results in MCP use two fields to provide caching hints to clients:
* The <b>Time-to-live (TTL) Field</b>,`ttlMs`, is an integer value in milliseconds specifying how long the client MAY consider the result fresh.
* The <b>Cache Scope Field</b>,`cacheScope`, indicates the intended scope of the cached response, either `"public"` or `"private"`.
### Time-to-Live (TTL) Field
The `ttlMs` field is a hint from the server indicating how long, in
milliseconds, the client MAY consider the result fresh. Semantics are
analogous to HTTP `Cache-Control: max-age`.
* If `ttlMs` is `0`, the response **SHOULD** be considered immediately stale. The client
MAY re-fetch every time the result is needed.
* If `ttlMs` is positive, the client **SHOULD** consider the result fresh for that many
milliseconds after receiving the response.
* If `ttlMs` is absent, clients **SHOULD** assume a default of `0` (immediately stale)
and rely on their own caching heuristics or notifications. This should only occur in older server versions.
* If `ttlMs` is negative, clients **SHOULD** ignore it and treat it as `0`.
Servers **MUST** provide a `ttlMs` value that is `>= 0`.
<Note>
TTL is a **freshness hint**, not a guarantee. Servers MAY change the
underlying data before the TTL expires. The TTL tells the client how long it
can reasonably avoid re-fetching, not how long the data is guaranteed to
remain unchanged.
</Note>
#### Freshness Calculation
A client records the local time at which the response was received (`t_received`). The
response is considered **fresh** while:
```
now < t_received + ttlMs
```
Once the TTL expires, the response is **stale** and the client **SHOULD** re-fetch on
next access.
Clients **SHOULD NOT** treat TTL as a polling interval that triggers automatic background
refetches. The TTL is a freshness hint: the client checks freshness when it needs the
data, and re-fetches only if stale. Implementations that do choose to poll **MUST**
apply jitter and backoff.
Clients **MAY** re-fetch before the TTL expires if they have reason to believe the data
has changed (e.g., receiving an unexpected error on a tool call indicating the method was
not found or the parameters were invalid).
Clients **MAY** serve stale responses if errors occur during re-fetching (e.g., network
issues, server downtime).
### Cache Scope Field
The `cacheScope` field controls who may cache a response, analogous to HTTP
`Cache-Control: public` vs `Cache-Control: private`.
| Value | Meaning |
| ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `"public"` | The response does not contain user-specific data. Any client, shared gateway, or caching proxy **MAY** store and serve the cached response to any user. |
| `"private"` | The response contains private data that is not meant to be shared between callers. Cached responses **MAY** be reused for the same authorization context. Caches **MUST NOT** be shared across authorization contexts (e.g. a different access token requires a different cache). |
#### Choosing a Cache Scope
* **`"public"`** is appropriate for lists of tools, prompts, and resource templates when
they are identical for all users.
* **`"private"`** is appropriate for `resources/read` results that depend on the
authenticated user, or for filtered list results that vary per user.
## Interaction with Notifications
TTL and server-push notifications are complementary:
* A server **MAY** provide `ttlMs` without advertising `listChanged: true` in its
capabilities. In this case, the client relies entirely on TTL-based freshness.
* A server **MAY** advertise `listChanged: true` **and** provide `ttlMs`. In this case,
the client can use the TTL to avoid unnecessary refetches between notifications, and
the notification acts as an immediate invalidation signal.
When a relevant notification is received while a cached response is still fresh, the
notification **invalidates** the cached response and it should be considered immediately stale.
```mermaid theme={null}
sequenceDiagram
participant Client
participant Server
Client->>Server: tools/list
Server-->>Client: { tools: [...], ttlMs: 300000 }
Note over Client: Cache response, fresh for 5 min
Note over Client: 2 minutes later...
Client->>Client: Need tools list → cache still fresh, use cached
Note over Client: 3 minutes later (TTL expired)...
Client->>Client: Need tools list → cache stale
Client->>Server: tools/list
Server-->>Client: { tools: [...], ttlMs: 300000 }
Note over Server: Tools change before TTL expires
Server-->>Client: notifications/tools/list_changed
Note over Client: Invalidate cache immediately
Client->>Server: tools/list
Server-->>Client: { tools: [...], ttlMs: 300000 }
```
## Interaction with Pagination
When a list result is [paginated](/specification/draft/server/utilities/pagination), each
page is an independently cacheable response—consistent with how HTTP
`Cache-Control` treats paginated resources.
* Each page response carries its own `ttlMs` value. The freshness clock for each page
starts at the time that page was received.
* Servers **MAY** return different `ttlMs` values on different pages (e.g., a longer TTL
for early pages of a stable list, a shorter TTL for the final page).
* When a cached page expires, the client **SHOULD** re-fetch that page using its cursor.
* There is no cross-page consistency guarantee. If the underlying data changes between
page fetches, clients may observe duplicates or gaps.
* Clients that require a consistent snapshot of the full list **SHOULD** re-fetch from
the beginning (without a cursor).
* If a cursor becomes invalid (e.g., the server returns an error for a previously valid
cursor), the client **SHOULD** discard all cached pages and re-fetch from the
beginning.
Servers **MUST** apply the same `cacheScope` to all response pages for a given list
request. For example, if the first page of a `tools/list` response has
`cacheScope: "private"`, all subsequent pages for that request **MUST** also be
`"private"`.
## Security Considerations
A `cacheScope` of `"public"` indicates that the response does not contain user-specific data and can be safely shared. Servers MUST be aware that responses with a `"public"` `cacheScope` may be shared between callers even if the Result is coming from an authenticated endpoint. For example, the Result from an authenticated `tools/list` call with a `"public"` `cacheScope` may be cached by a client and may be shared outside of the initial requests authorization context. (i.e. different access tokens can leverage the same cache).
Server implementors:
* should ensure that the `cacheScope` correctly reflects the intended visibility of the primitive.
* MUST apply appropriate per-primitive access controls, and MUST NOT rely on
`cacheScope` alone to prevent unauthorized access to primitives.
specification/draft/server/utilities/completion New page · 212 lines, new page
# Completion ## User Interaction Model ## Capabilities ## Protocol Messages ### Requesting Completions ### Reference Types ### Completion Results ## Message Flow ## Data Types ### CompleteRequest ### CompleteResult ## Error Handling ## Implementation Considerations ## Security
A whole new page. There's nothing to diff it against, so here is what it says.
# Completion
<div id="enable-section-numbers" />
The Model Context Protocol (MCP) provides a standardized way for servers to offer
autocompletion suggestions for the arguments of prompts and resource templates. When
users are filling in argument values for a specific prompt (identified by name) or
resource template (identified by URI), servers can provide contextual suggestions.
<Note>
For brevity, the request examples on this page omit the `_meta` request
metadata (`io.modelcontextprotocol/protocolVersion`,
`io.modelcontextprotocol/clientInfo`, and
`io.modelcontextprotocol/clientCapabilities`). Every request **MUST** include
the required `_meta` fields; see
[`_meta`](/specification/draft/basic/index#meta).
</Note>
## User Interaction Model
Completion in MCP is designed to support interactive user experiences similar to IDE code
completion.
For example, applications may show completion suggestions in a dropdown or popup menu as
users type, with the ability to filter and select from available options.
However, implementations are free to expose completion through any interface pattern that
suits their needs—the protocol itself does not mandate any specific user
interaction model.
## Capabilities
Servers that support completions **MUST** declare the `completions` capability:
```json theme={null}
{
"capabilities": {
"completions": {}
}
}
```
## Protocol Messages
### Requesting Completions
To get completion suggestions, clients send a `completion/complete` request specifying
what is being completed through a reference type:
**Request:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"method": "completion/complete",
"params": {
"ref": {
"type": "ref/prompt",
"name": "code_review"
},
"argument": {
"name": "language",
"value": "py"
}
}
}
```
**Response:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"resultType": "complete",
"completion": {
"values": ["python", "pytorch", "pyside"],
"total": 10,
"hasMore": true
}
}
}
```
For prompts or URI templates with multiple arguments, clients should include previous completions in the `context.arguments` object to provide context for subsequent requests.
**Request:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"method": "completion/complete",
"params": {
"ref": {
"type": "ref/prompt",
"name": "code_review"
},
"argument": {
"name": "framework",
"value": "fla"
},
"context": {
"arguments": {
"language": "python"
}
}
}
}
```
**Response:**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"resultType": "complete",
"completion": {
"values": ["flask"],
"total": 1,
"hasMore": false
}
}
}
```
### Reference Types
The protocol supports two types of completion references:
| Type | Description | Example |
| -------------- | ----------------------------------------- | --------------------------------------------------- |
| `ref/prompt` | References a prompt by name | `{"type": "ref/prompt", "name": "code_review"}` |
| `ref/resource` | References a resource URI or URI template | `{"type": "ref/resource", "uri": "file:///{path}"}` |
### Completion Results
Servers return an array of completion values ranked by relevance, with:
* Maximum 100 items per response
* Optional total number of available matches
* Boolean indicating if additional results exist
## Message Flow
```mermaid theme={null}
sequenceDiagram
participant Client
participant Server
Note over Client: User types argument
Client->>Server: completion/complete
Server-->>Client: Completion suggestions
Note over Client: User continues typing
Client->>Server: completion/complete
Server-->>Client: Refined suggestions
```
## Data Types
### CompleteRequest
* `ref`: A `PromptReference` or `ResourceTemplateReference`. For
`ResourceTemplateReference`, `uri` is a URI or URI template.
* `argument`: Object containing:
* `name`: Argument name
* `value`: Current value
* `context`: Object containing:
* `arguments`: A mapping of already-resolved argument names to their values.
### CompleteResult
* `completion`: Object containing:
* `values`: Array of suggestions (max 100)
* `total`: Optional total matches
* `hasMore`: Additional results flag
## Error Handling
Servers **SHOULD** return standard JSON-RPC errors for common failure cases:
* Method not found: `-32601` (Capability not supported)
* Invalid prompt name: `-32602` (Invalid params)
* Missing required arguments: `-32602` (Invalid params)
* Internal errors: `-32603` (Internal error)
## Implementation Considerations
1. Servers **SHOULD**:
* Return suggestions sorted by relevance
* Implement fuzzy matching where appropriate
* Rate limit completion requests
* Validate all inputs
2. Clients **SHOULD**:
* Debounce rapid completion requests
* Cache completion results where appropriate
* Handle missing or partial results gracefully
## Security
Implementations **MUST**:
* Validate all completion inputs
* Implement appropriate rate limiting
* Control access to sensitive suggestions
* Prevent completion-based information disclosure
specification/draft/server/utilities/logging New page · 130 lines, new page
# Logging ## User Interaction Model ## Capabilities ## Log Levels ## Requesting Log Messages ### Per-request log level ## Protocol Messages ### Log Message Notifications ## Error Handling ## Implementation Considerations ## Security
A whole new page. There's nothing to diff it against, so here is what it says.
# Logging
<div id="enable-section-numbers" />
<Warning>
**Deprecated**: The Logging feature is deprecated as of protocol version
`2026-07-28`
([SEP-2577](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2577)).
Under the [feature lifecycle policy](/community/feature-lifecycle), it remains
in the specification for at least twelve months after this revision's release
before it becomes eligible for removal. New implementations **SHOULD NOT**
adopt it; existing implementations **SHOULD** migrate to logging to `stderr`
for stdio transports, or to [OpenTelemetry](https://opentelemetry.io/) for
structured observability. See the [deprecated features
registry](/specification/draft/deprecated).
</Warning>
The Model Context Protocol (MCP) provides a standardized way for servers to send
structured log messages to clients. Clients control logging verbosity per-request via
`_meta`, with servers sending notifications containing severity levels, optional logger
names, and arbitrary JSON-serializable data.
## User Interaction Model
Implementations are free to expose logging through any interface pattern that suits their
needs—the protocol itself does not mandate any specific user interaction model.
## Capabilities
Servers that emit log message notifications **MUST** declare the `logging` capability:
```json theme={null}
{
"capabilities": {
"logging": {}
}
}
```
## Log Levels
The protocol follows the standard syslog severity levels specified in
[RFC 5424](https://datatracker.ietf.org/doc/html/rfc5424#section-6.2.1):
| Level | Description | Example Use Case |
| --------- | -------------------------------- | -------------------------- |
| debug | Detailed debugging information | Function entry/exit points |
| info | General informational messages | Operation progress updates |
| notice | Normal but significant events | Configuration changes |
| warning | Warning conditions | Deprecated feature usage |
| error | Error conditions | Operation failures |
| critical | Critical conditions | System component failures |
| alert | Action must be taken immediately | Data corruption detected |
| emergency | System is unusable | Complete system failure |
## Requesting Log Messages
### Per-request log level
To receive log messages for a specific request, include
`io.modelcontextprotocol/logLevel` in the request's `_meta`. The server **MUST NOT**
emit `notifications/message` for a request that does not include this field.
When the field is present, the server **MAY** send `notifications/message`
notifications at or above the requested level on the response stream of that
request, before the final response. `notifications/message` is request-scoped:
the server **MUST NOT** deliver it on a
[`subscriptions/listen`](/specification/draft/basic/patterns/subscriptions)
stream or on any stream other than the one carrying the response to the request
that set the log level.
## Protocol Messages
### Log Message Notifications
Servers send log messages using `notifications/message` notifications:
```json theme={null}
{
"jsonrpc": "2.0",
"method": "notifications/message",
"params": {
"level": "error",
"logger": "database",
"data": {
"error": "Connection failed",
"details": {
"host": "localhost",
"port": 5432
}
}
}
}
```
## Error Handling
If the `io.modelcontextprotocol/logLevel` value carried in a request's `_meta`
is not a recognized [log level](#log-levels), the server **SHOULD** reject that
request with a standard JSON-RPC error:
* Invalid log level: `-32602` (Invalid params)
* Internal errors: `-32603` (Internal error)
## Implementation Considerations
1. Servers **SHOULD**:
* Rate limit log messages
* Include relevant context in data field
* Use consistent logger names
* Remove sensitive information
2. Clients **MAY**:
* Present log messages in the UI
* Implement log filtering/search
* Display severity visually
* Persist log messages
## Security
1. Log messages **MUST NOT** contain:
* Credentials or secrets
* Personal identifying information
* Internal system details that could aid attacks
2. Implementations **SHOULD**:
* Rate limit messages
* Validate all data fields
* Control log access
* Monitor for sensitive content
specification/draft/server/utilities/pagination New page · 109 lines, new page
# Pagination ## Pagination Model ## Response Format ## Request Format ## Pagination Flow ## Operations Supporting Pagination ## Implementation Guidelines ## Error Handling
A whole new page. There's nothing to diff it against, so here is what it says.
# Pagination
<div id="enable-section-numbers" />
The Model Context Protocol (MCP) supports paginating list operations that may return
large result sets. Pagination allows servers to yield results in smaller chunks rather
than all at once.
Pagination is especially important when connecting to external services over the
internet, but also useful for local integrations to avoid performance issues with large
data sets.
<Note>
For brevity, the request examples on this page omit the `_meta` request
metadata (`io.modelcontextprotocol/protocolVersion`,
`io.modelcontextprotocol/clientInfo`, and
`io.modelcontextprotocol/clientCapabilities`). Every request **MUST** include
the required `_meta` fields; see
[`_meta`](/specification/draft/basic/index#meta).
</Note>
## Pagination Model
Pagination in MCP uses an opaque cursor-based approach, instead of numbered pages.
* The **cursor** is an opaque string token, representing a position in the result set
* **Page size** is determined by the server, and clients **MUST NOT** assume a fixed page
size
## Response Format
Pagination starts when the server sends a **response** that includes:
* The current page of results
* An optional `nextCursor` field if more results exist
```json theme={null}
{
"jsonrpc": "2.0",
"id": "123",
"result": {
"resultType": "complete",
"resources": [...],
"nextCursor": "eyJwYWdlIjogM30=",
"ttlMs": 300000,
"cacheScope": "public"
}
}
```
## Request Format
After receiving a cursor, the client can *continue* paginating by issuing a request
including that cursor:
```json theme={null}
{
"jsonrpc": "2.0",
"id": "124",
"method": "resources/list",
"params": {
"cursor": "eyJwYWdlIjogMn0="
}
}
```
## Pagination Flow
```mermaid theme={null}
sequenceDiagram
participant Client
participant Server
Client->>Server: List Request (no cursor)
loop Pagination Loop
Server-->>Client: Page of results + nextCursor
Client->>Server: List Request (with cursor)
end
```
## Operations Supporting Pagination
The following MCP operations support pagination:
* `resources/list` - List available resources
* `resources/templates/list` - List resource templates
* `prompts/list` - List available prompts
* `tools/list` - List available tools
## Implementation Guidelines
1. Servers **SHOULD**:
* Provide stable cursors
* Handle invalid cursors gracefully
2. Clients **SHOULD**:
* Treat a missing `nextCursor` as the end of results
* Support both paginated and non-paginated flows
3. Clients **MUST** treat cursors as opaque tokens:
* Don't make assumptions about cursor format
* Don't attempt to parse or modify cursors
* Don't make any determination based on cursor value other than whether a
non-null value was provided (e.g. an empty string is a valid cursor and
thus **MUST NOT** be treated as the end of results)
## Error Handling
Invalid cursors **SHOULD** result in an error with code -32602 (Invalid params).
community/interest-groups/auth Changed · +1 / -1 lines
### Related Groups * **[Security IG](/community/interest-groups/security)**: token-audience confusion, issuer validation, and account-linking risks sit at the boundary between the two groups -* **Transports WG**: authorization is currently specified at the HTTP transport level; changes to transports affect where credentials are carried +* **[Transports WG](/community/working-groups/transports)**: authorization is currently specified at the HTTP transport level; changes to transports affect where credentials are carried * **Agents WG**: delegated/on-behalf-of access and consent for multi-agent chains overlap heavily with agentic use cases * **[Server Card WG](/community/working-groups/server-card) / [Registry](/community/working-groups/registry)**: client and server identity, discovery metadata, and trust establishment intersect with how authorization servers and resource servers are located and verified * **SDK Maintainers**: SDKs ship the auth client implementations; IG findings should inform cross-SDK auth ergonomics and defaults