mirror of
https://github.com/PrefectHQ/fastmcp.git
synced 2026-08-09 15:19:10 +02:00
Update docs for context
This commit is contained in:
parent
ef432ade0f
commit
eefaadee34
4 changed files with 146 additions and 90 deletions
|
|
@ -1,16 +1,16 @@
|
|||
---
|
||||
title: MCP Context
|
||||
sidebarTitle: Context
|
||||
description: Access MCP capabilities like logging, progress, and resources within your tools.
|
||||
description: Access MCP capabilities like logging, progress, and resources within your MCP objects.
|
||||
icon: rectangle-code
|
||||
---
|
||||
import { VersionBadge } from '/snippets/version-badge.mdx'
|
||||
|
||||
When defining FastMCP [tools](/servers/tools), your functions might need to interact with the underlying MCP session or access server capabilities. FastMCP provides the `Context` object for this purpose.
|
||||
When defining FastMCP [tools](/servers/tools), [resources](/servers/resources), resource templates, or [prompts](/servers/prompts), your functions might need to interact with the underlying MCP session or access server capabilities. FastMCP provides the `Context` object for this purpose.
|
||||
|
||||
## What Is Context?
|
||||
|
||||
The `Context` object provides a clean interface to access MCP features within your tool functions, including:
|
||||
The `Context` object provides a clean interface to access MCP features within your functions, including:
|
||||
|
||||
- **Logging**: Send debug, info, warning, and error messages back to the client
|
||||
- **Progress Reporting**: Update the client on the progress of long-running operations
|
||||
|
|
@ -21,7 +21,7 @@ The `Context` object provides a clean interface to access MCP features within yo
|
|||
|
||||
## Accessing the Context
|
||||
|
||||
To use the context object within your tool function, simply add a parameter to your function signature and type-hint it as `Context`. FastMCP will automatically inject the context instance when your tool is called.
|
||||
To use the context object within any of your functions, simply add a parameter to your function signature and type-hint it as `Context`. FastMCP will automatically inject the context instance when your function is called.
|
||||
|
||||
```python
|
||||
from fastmcp import FastMCP, Context
|
||||
|
|
@ -65,15 +65,15 @@ async def process_file(file_uri: str, ctx: Context) -> str:
|
|||
|
||||
- The parameter name (e.g., `ctx`, `context`) doesn't matter, only the type hint `Context` is important.
|
||||
- The context parameter can be placed anywhere in your function's signature.
|
||||
- The context is optional - tools that don't need it can omit the parameter.
|
||||
- Context is only available within tool functions during a request; attempting to use context methods outside a request will raise errors.
|
||||
- Context methods are async, so your tool function usually needs to be async as well.
|
||||
- The context is optional - functions that don't need it can omit the parameter.
|
||||
- Context is only available during a request; attempting to use context methods outside a request will raise errors.
|
||||
- Context methods are async, so your function usually needs to be async as well.
|
||||
|
||||
## Context Capabilities
|
||||
|
||||
### Logging
|
||||
|
||||
Send log messages back to the MCP client. This is useful for debugging and providing visibility into tool execution during a request.
|
||||
Send log messages back to the MCP client. This is useful for debugging and providing visibility into function execution during a request.
|
||||
|
||||
```python
|
||||
@mcp.tool()
|
||||
|
|
@ -97,14 +97,14 @@ async def analyze_data(data: list[float], ctx: Context) -> dict:
|
|||
**Available Logging Methods:**
|
||||
|
||||
- **`ctx.debug(message: str)`**: Low-level details useful for debugging
|
||||
- **`ctx.info(message: str)`**: General information about tool execution
|
||||
- **`ctx.info(message: str)`**: General information about execution
|
||||
- **`ctx.warning(message: str)`**: Potential issues that didn't prevent execution
|
||||
- **`ctx.error(message: str)`**: Errors that occurred during execution
|
||||
- **`ctx.log(level: Literal["debug", "info", "warning", "error"], message: str, logger_name: str | None = None)`**: Generic log method supporting custom logger names
|
||||
|
||||
### Progress Reporting
|
||||
|
||||
For long-running tools, notify the client about the progress of the operation. This allows clients to display progress indicators and provide a better user experience.
|
||||
For long-running operations, notify the client about the progress. This allows clients to display progress indicators and provide a better user experience.
|
||||
|
||||
```python
|
||||
@mcp.tool()
|
||||
|
|
@ -137,7 +137,7 @@ Progress reporting requires the client to have sent a `progressToken` in the ini
|
|||
|
||||
### Resource Access
|
||||
|
||||
Read data from resources registered with your FastMCP server. This allows tools to access files, configuration, or dynamically generated content.
|
||||
Read data from resources registered with your FastMCP server. This allows functions to access files, configuration, or dynamically generated content.
|
||||
|
||||
```python
|
||||
@mcp.tool()
|
||||
|
|
@ -177,7 +177,7 @@ The returned content is typically accessed via `content_list[0].content` and can
|
|||
|
||||
<VersionBadge version="2.0.0" />
|
||||
|
||||
Request the client's LLM to generate text based on provided messages. This is useful when your tool needs to leverage the LLM's capabilities to process data or generate responses.
|
||||
Request the client's LLM to generate text based on provided messages. This is useful when your function needs to leverage the LLM's capabilities to process data or generate responses.
|
||||
|
||||
```python
|
||||
@mcp.tool()
|
||||
|
|
@ -279,6 +279,60 @@ async def advanced_tool(ctx: Context) -> str:
|
|||
Direct use of `session` or `request_context` requires understanding the low-level MCP Python SDK and may be less stable than using the methods provided directly on the `Context` object.
|
||||
</Warning>
|
||||
|
||||
## Using Context in Other Components
|
||||
## Using Context in Different Components
|
||||
|
||||
Currently, Context is primarily designed for use within tool functions. Support for Context in other components like resources and prompts is planned for future releases.
|
||||
All FastMCP components (tools, resources, templates, and prompts) can use the Context object following the same pattern - simply add a parameter with the `Context` type annotation.
|
||||
|
||||
### Context in Resources and Templates
|
||||
|
||||
Resources and resource templates can access context to customize their behavior:
|
||||
|
||||
```python
|
||||
@mcp.resource("resource://user-data")
|
||||
async def get_user_data(ctx: Context) -> dict:
|
||||
"""Fetch personalized user data based on the request context."""
|
||||
user_id = ctx.client_id or "anonymous"
|
||||
await ctx.info(f"Fetching data for user {user_id}")
|
||||
|
||||
# Example of using context for dynamic resource generation
|
||||
return {
|
||||
"user_id": user_id,
|
||||
"last_access": datetime.now().isoformat(),
|
||||
"request_id": ctx.request_id
|
||||
}
|
||||
|
||||
@mcp.resource("resource://users/{user_id}/profile")
|
||||
async def get_user_profile(user_id: str, ctx: Context) -> dict:
|
||||
"""Fetch user profile from database with context-aware logging."""
|
||||
await ctx.info(f"Fetching profile for user {user_id}")
|
||||
|
||||
# Example of using context in a template resource
|
||||
# In a real implementation, you might query a database
|
||||
return {
|
||||
"id": user_id,
|
||||
"name": f"User {user_id}",
|
||||
"request_id": ctx.request_id
|
||||
}
|
||||
```
|
||||
|
||||
### Context in Prompts
|
||||
|
||||
Prompts can use context to generate more dynamic templates:
|
||||
|
||||
```python
|
||||
@mcp.prompt()
|
||||
async def data_analysis_request(dataset: str, ctx: Context) -> str:
|
||||
"""Generate a request to analyze data with contextual information."""
|
||||
await ctx.info(f"Generating data analysis prompt for {dataset}")
|
||||
|
||||
# Could use context to read configuration or personalize the prompt
|
||||
return f"""Please analyze the following dataset: {dataset}
|
||||
|
||||
Request initiated at: {datetime.now().isoformat()}
|
||||
Request ID: {ctx.request_id}
|
||||
"""
|
||||
```
|
||||
|
||||
<VersionBadge version="2.3.0" />
|
||||
|
||||
All FastMCP objects now support context injection using the same consistent pattern, making it easy to add session-aware capabilities to all aspects of your MCP server.
|
||||
|
|
@ -171,33 +171,24 @@ async def data_based_prompt(data_id: str) -> str:
|
|||
|
||||
Use `async def` when your prompt function performs I/O operations like network requests, database queries, file I/O, or external service calls.
|
||||
|
||||
### The MCP Session
|
||||
### Accessing MCP Context
|
||||
|
||||
Prompts can access the MCP features via the `Context` object, just like tools.
|
||||
<VersionBadge version="2.2.5" />
|
||||
|
||||
```python
|
||||
from fastmcp import Context
|
||||
Prompts can access additional MCP information and features through the `Context` object. To access it, add a parameter to your prompt function with a type annotation of `Context`:
|
||||
|
||||
```python {6}
|
||||
from fastmcp import FastMCP, Context
|
||||
|
||||
mcp = FastMCP(name="PromptServer")
|
||||
|
||||
@mcp.prompt()
|
||||
async def generate_report_request(report_type: str, ctx: Context) -> str:
|
||||
"""Generates a request for a report based on available data."""
|
||||
# Log the request
|
||||
await ctx.info(f"Generating prompt for report type: {report_type}")
|
||||
|
||||
# Could potentially use ctx.read_resource to fetch data
|
||||
# Or ctx.sample to get additional input from the LLM
|
||||
|
||||
return f"Please create a {report_type} report based on the available data."
|
||||
"""Generates a request for a report."""
|
||||
return f"Please create a {report_type} report. Request ID: {ctx.request_id}"
|
||||
```
|
||||
|
||||
Using the `ctx` parameter (based on its `Context` type hint), you can access:
|
||||
|
||||
- **Logging:** `ctx.debug()`, `ctx.info()`, etc.
|
||||
- **Resource Access:** `ctx.read_resource(uri)`
|
||||
- **LLM Sampling:** `ctx.sample(...)`
|
||||
- **Request Info:** `ctx.request_id`, `ctx.client_id`
|
||||
|
||||
Refer to the [Context documentation](/servers/context) for more details on these capabilities.
|
||||
For full documentation on the Context object and all its capabilities, see the [Context documentation](/servers/context).
|
||||
|
||||
## Server Behavior
|
||||
|
||||
|
|
|
|||
|
|
@ -95,6 +95,36 @@ def get_application_status() -> dict:
|
|||
- **`mime_type`**: Specifies the content type (FastMCP often infers a default like `text/plain` or `application/json`, but explicit is better for non-text types).
|
||||
- **`tags`**: A set of strings for categorization, potentially used by clients for filtering.
|
||||
|
||||
### Accessing MCP Context
|
||||
|
||||
<VersionBadge version="2.2.5" />
|
||||
|
||||
Resources and resource templates can access additional MCP information and features through the `Context` object. To access it, add a parameter to your resource function with a type annotation of `Context`:
|
||||
|
||||
```python {6, 14}
|
||||
from fastmcp import FastMCP, Context
|
||||
|
||||
mcp = FastMCP(name="DataServer")
|
||||
|
||||
@mcp.resource("resource://system-status")
|
||||
async def get_system_status(ctx: Context) -> dict:
|
||||
"""Provides system status information."""
|
||||
return {
|
||||
"status": "operational",
|
||||
"request_id": ctx.request_id
|
||||
}
|
||||
|
||||
@mcp.resource("resource://{name}/details")
|
||||
async def get_details(name: str, ctx: Context) -> dict:
|
||||
"""Get details for a specific name."""
|
||||
return {
|
||||
"name": name,
|
||||
"accessed_at": ctx.request_id
|
||||
}
|
||||
```
|
||||
|
||||
For full documentation on the Context object and all its capabilities, see the [Context documentation](/servers/context).
|
||||
|
||||
|
||||
### Asynchronous Resources
|
||||
|
||||
|
|
@ -205,6 +235,8 @@ Note that this parameter is only available when using `add_resource()` directly
|
|||
|
||||
Resource Templates allow clients to request resources whose content depends on parameters embedded in the URI. Define a template using the **same `@mcp.resource` decorator**, but include `{parameter_name}` placeholders in the URI string and add corresponding arguments to your function signature.
|
||||
|
||||
Resource templates share most configuration options with regular resources (name, description, mime_type, tags), but add the ability to define URI parameters that map to function parameters.
|
||||
|
||||
Resource templates generate a new resource for each unique set of parameters, which means that resources can be dynamically created on-demand. For example, if the resource template `"user://profile/{name}"` is registered, MCP clients could request `"user://profile/ford"` or `"user://profile/marvin"` to retrieve either of those two user profiles as resources, without having to register each resource individually.
|
||||
|
||||
Here is a complete example that shows how to define two resource templates:
|
||||
|
|
@ -379,28 +411,6 @@ In this stacked decorator pattern:
|
|||
|
||||
Templates provide a powerful way to expose parameterized data access points following REST-like principles.
|
||||
|
||||
### Custom Template Keys
|
||||
|
||||
<VersionBadge version="2.2.0" />
|
||||
|
||||
Similar to resources, you can provide custom keys when directly adding templates:
|
||||
|
||||
```python
|
||||
from fastmcp.resources import ResourceTemplate
|
||||
|
||||
# Create a template with a function
|
||||
template = ResourceTemplate.from_function(
|
||||
my_function,
|
||||
uri_template="data://{id}/details",
|
||||
name="Data Details"
|
||||
)
|
||||
|
||||
# Register with a custom key
|
||||
mcp._resource_manager.add_template(template, key="custom://{id}/view")
|
||||
```
|
||||
|
||||
This allows accessing the same template implementation through different URI patterns.
|
||||
|
||||
## Server Behavior
|
||||
|
||||
### Duplicate Resources
|
||||
|
|
|
|||
|
|
@ -263,7 +263,8 @@ FastMCP automatically catches exceptions raised within your tool function:
|
|||
|
||||
Using informative exceptions helps the LLM understand failures and react appropriately.
|
||||
|
||||
### Accessing MCP Context
|
||||
## MCP Context
|
||||
|
||||
|
||||
Tools can access MCP features like logging, reading resources, or reporting progress through the `Context` object. To use it, add a parameter to your tool function with the type hint `Context`.
|
||||
|
||||
|
|
@ -304,39 +305,6 @@ The Context object provides access to:
|
|||
|
||||
For full documentation on the Context object and all its capabilities, see the [Context documentation](/servers/context).
|
||||
|
||||
## Server Behavior
|
||||
|
||||
### Duplicate Tools
|
||||
|
||||
<VersionBadge version="2.1.0" />
|
||||
|
||||
You can control how the FastMCP server behaves if you try to register multiple tools with the same name. This is configured using the `on_duplicate_tools` argument when creating the `FastMCP` instance.
|
||||
|
||||
```python
|
||||
from fastmcp import FastMCP
|
||||
|
||||
mcp = FastMCP(
|
||||
name="StrictServer",
|
||||
# Configure behavior for duplicate tool names
|
||||
on_duplicate_tools="error"
|
||||
)
|
||||
|
||||
@mcp.tool()
|
||||
def my_tool(): return "Version 1"
|
||||
|
||||
# This will now raise a ValueError because 'my_tool' already exists
|
||||
# and on_duplicate_tools is set to "error".
|
||||
# @mcp.tool()
|
||||
# def my_tool(): return "Version 2"
|
||||
```
|
||||
|
||||
The duplicate behavior options are:
|
||||
|
||||
- `"warn"` (default): Logs a warning and the new tool replaces the old one.
|
||||
- `"error"`: Raises a `ValueError`, preventing the duplicate registration.
|
||||
- `"replace"`: Silently replaces the existing tool with the new one.
|
||||
- `"ignore"`: Keeps the original tool and ignores the new registration attempt.
|
||||
|
||||
## Parameter Types
|
||||
|
||||
FastMCP supports a wide variety of parameter types to give you flexibility when designing your tools.
|
||||
|
|
@ -663,3 +631,36 @@ Common validation options include:
|
|||
| `description` | Any | Human-readable description (appears in schema) |
|
||||
|
||||
When a client sends invalid data, FastMCP will return a validation error explaining why the parameter failed validation.
|
||||
|
||||
## Server Behavior
|
||||
|
||||
### Duplicate Tools
|
||||
|
||||
<VersionBadge version="2.1.0" />
|
||||
|
||||
You can control how the FastMCP server behaves if you try to register multiple tools with the same name. This is configured using the `on_duplicate_tools` argument when creating the `FastMCP` instance.
|
||||
|
||||
```python
|
||||
from fastmcp import FastMCP
|
||||
|
||||
mcp = FastMCP(
|
||||
name="StrictServer",
|
||||
# Configure behavior for duplicate tool names
|
||||
on_duplicate_tools="error"
|
||||
)
|
||||
|
||||
@mcp.tool()
|
||||
def my_tool(): return "Version 1"
|
||||
|
||||
# This will now raise a ValueError because 'my_tool' already exists
|
||||
# and on_duplicate_tools is set to "error".
|
||||
# @mcp.tool()
|
||||
# def my_tool(): return "Version 2"
|
||||
```
|
||||
|
||||
The duplicate behavior options are:
|
||||
|
||||
- `"warn"` (default): Logs a warning and the new tool replaces the old one.
|
||||
- `"error"`: Raises a `ValueError`, preventing the duplicate registration.
|
||||
- `"replace"`: Silently replaces the existing tool with the new one.
|
||||
- `"ignore"`: Keeps the original tool and ignores the new registration attempt.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue