Spaces:
Running
Running
Jeremiah Lowin commited on
Commit ·
3cbdde4
1
Parent(s): 4af3969
Improve documentation
Browse files- docs/servers/context.mdx +37 -86
docs/servers/context.mdx
CHANGED
|
@@ -23,6 +23,17 @@ The `Context` object provides a clean interface to access MCP features within yo
|
|
| 23 |
|
| 24 |
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.
|
| 25 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 26 |
```python
|
| 27 |
from fastmcp import FastMCP, Context
|
| 28 |
|
|
@@ -31,43 +42,40 @@ mcp = FastMCP(name="ContextDemo")
|
|
| 31 |
@mcp.tool()
|
| 32 |
async def process_file(file_uri: str, ctx: Context) -> str:
|
| 33 |
"""Processes a file, using context for logging and resource access."""
|
| 34 |
-
|
| 35 |
-
|
|
|
|
| 36 |
|
| 37 |
-
|
| 38 |
-
# Use context to read a resource
|
| 39 |
-
contents_list = await ctx.read_resource(file_uri)
|
| 40 |
-
if not contents_list:
|
| 41 |
-
await ctx.warning(f"Resource {file_uri} is empty.")
|
| 42 |
-
return "Resource empty"
|
| 43 |
|
| 44 |
-
|
| 45 |
-
await ctx.debug(f"Read {len(data)} bytes from {file_uri}")
|
| 46 |
|
| 47 |
-
|
| 48 |
-
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 52 |
|
| 53 |
-
|
| 54 |
-
await ctx.info(f"Processing complete for {file_uri}")
|
| 55 |
|
| 56 |
-
|
| 57 |
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
|
| 61 |
-
|
|
|
|
|
|
|
| 62 |
```
|
| 63 |
|
| 64 |
-
**Key Points:**
|
| 65 |
-
|
| 66 |
-
- The parameter name (e.g., `ctx`, `context`) doesn't matter, only the type hint `Context` is important.
|
| 67 |
-
- The context parameter can be placed anywhere in your function's signature.
|
| 68 |
-
- The context is optional - functions that don't need it can omit the parameter.
|
| 69 |
-
- Context is only available during a request; attempting to use context methods outside a request will raise errors.
|
| 70 |
-
- Context methods are async, so your function usually needs to be async as well.
|
| 71 |
|
| 72 |
## Context Capabilities
|
| 73 |
|
|
@@ -305,60 +313,3 @@ async def handle_web_request(ctx: Context) -> dict:
|
|
| 305 |
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.
|
| 306 |
</Warning>
|
| 307 |
|
| 308 |
-
## Using Context in Different Components
|
| 309 |
-
|
| 310 |
-
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.
|
| 311 |
-
|
| 312 |
-
### Context in Resources and Templates
|
| 313 |
-
|
| 314 |
-
Resources and resource templates can access context to customize their behavior:
|
| 315 |
-
|
| 316 |
-
```python
|
| 317 |
-
@mcp.resource("resource://user-data")
|
| 318 |
-
async def get_user_data(ctx: Context) -> dict:
|
| 319 |
-
"""Fetch personalized user data based on the request context."""
|
| 320 |
-
user_id = ctx.client_id or "anonymous"
|
| 321 |
-
await ctx.info(f"Fetching data for user {user_id}")
|
| 322 |
-
|
| 323 |
-
# Example of using context for dynamic resource generation
|
| 324 |
-
return {
|
| 325 |
-
"user_id": user_id,
|
| 326 |
-
"last_access": datetime.now().isoformat(),
|
| 327 |
-
"request_id": ctx.request_id
|
| 328 |
-
}
|
| 329 |
-
|
| 330 |
-
@mcp.resource("resource://users/{user_id}/profile")
|
| 331 |
-
async def get_user_profile(user_id: str, ctx: Context) -> dict:
|
| 332 |
-
"""Fetch user profile from database with context-aware logging."""
|
| 333 |
-
await ctx.info(f"Fetching profile for user {user_id}")
|
| 334 |
-
|
| 335 |
-
# Example of using context in a template resource
|
| 336 |
-
# In a real implementation, you might query a database
|
| 337 |
-
return {
|
| 338 |
-
"id": user_id,
|
| 339 |
-
"name": f"User {user_id}",
|
| 340 |
-
"request_id": ctx.request_id
|
| 341 |
-
}
|
| 342 |
-
```
|
| 343 |
-
|
| 344 |
-
### Context in Prompts
|
| 345 |
-
|
| 346 |
-
Prompts can use context to generate more dynamic templates:
|
| 347 |
-
|
| 348 |
-
```python
|
| 349 |
-
@mcp.prompt()
|
| 350 |
-
async def data_analysis_request(dataset: str, ctx: Context) -> str:
|
| 351 |
-
"""Generate a request to analyze data with contextual information."""
|
| 352 |
-
await ctx.info(f"Generating data analysis prompt for {dataset}")
|
| 353 |
-
|
| 354 |
-
# Could use context to read configuration or personalize the prompt
|
| 355 |
-
return f"""Please analyze the following dataset: {dataset}
|
| 356 |
-
|
| 357 |
-
Request initiated at: {datetime.now().isoformat()}
|
| 358 |
-
Request ID: {ctx.request_id}
|
| 359 |
-
"""
|
| 360 |
-
```
|
| 361 |
-
|
| 362 |
-
<VersionBadge version="2.3.0" />
|
| 363 |
-
|
| 364 |
-
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.
|
|
|
|
| 23 |
|
| 24 |
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.
|
| 25 |
|
| 26 |
+
**Key Points:**
|
| 27 |
+
|
| 28 |
+
- The parameter name (e.g., `ctx`, `context`) doesn't matter, only the type hint `Context` is important.
|
| 29 |
+
- The context parameter can be placed anywhere in your function's signature; it will not be exposed to MCP clients as a valid parameter.
|
| 30 |
+
- The context is optional - functions that don't need it can omit the parameter entirely.
|
| 31 |
+
- Context methods are async, so your function usually needs to be async as well.
|
| 32 |
+
- The type hint can be a union (`Context | None`) or use `Annotated[]` and it will still work properly.
|
| 33 |
+
- Context is only available during a request; attempting to use context methods outside a request will raise errors. If you need to debug or call your context methods outside of a request, you can type your variable as `Context | None=None` to avoid missing argument errors.
|
| 34 |
+
|
| 35 |
+
### Tools
|
| 36 |
+
|
| 37 |
```python
|
| 38 |
from fastmcp import FastMCP, Context
|
| 39 |
|
|
|
|
| 42 |
@mcp.tool()
|
| 43 |
async def process_file(file_uri: str, ctx: Context) -> str:
|
| 44 |
"""Processes a file, using context for logging and resource access."""
|
| 45 |
+
# Context is available as the ctx parameter
|
| 46 |
+
return "Processed file"
|
| 47 |
+
```
|
| 48 |
|
| 49 |
+
### Resources and Templates
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 50 |
|
| 51 |
+
<VersionBadge version="2.2.5" />
|
|
|
|
| 52 |
|
| 53 |
+
```python
|
| 54 |
+
@mcp.resource("resource://user-data")
|
| 55 |
+
async def get_user_data(ctx: Context) -> dict:
|
| 56 |
+
"""Fetch personalized user data based on the request context."""
|
| 57 |
+
# Context is available as the ctx parameter
|
| 58 |
+
return {"user_id": "example"}
|
| 59 |
+
|
| 60 |
+
@mcp.resource("resource://users/{user_id}/profile")
|
| 61 |
+
async def get_user_profile(user_id: str, ctx: Context) -> dict:
|
| 62 |
+
"""Fetch user profile with context-aware logging."""
|
| 63 |
+
# Context is available as the ctx parameter
|
| 64 |
+
return {"id": user_id}
|
| 65 |
+
```
|
| 66 |
|
| 67 |
+
### Prompts
|
|
|
|
| 68 |
|
| 69 |
+
<VersionBadge version="2.2.5" />
|
| 70 |
|
| 71 |
+
```python
|
| 72 |
+
@mcp.prompt()
|
| 73 |
+
async def data_analysis_request(dataset: str, ctx: Context) -> str:
|
| 74 |
+
"""Generate a request to analyze data with contextual information."""
|
| 75 |
+
# Context is available as the ctx parameter
|
| 76 |
+
return f"Please analyze the following dataset: {dataset}"
|
| 77 |
```
|
| 78 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 79 |
|
| 80 |
## Context Capabilities
|
| 81 |
|
|
|
|
| 313 |
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.
|
| 314 |
</Warning>
|
| 315 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|