Spaces:
Running
Running
Jeremiah Lowin commited on
Add docs for context state management (#1227)
Browse files- docs/servers/context.mdx +46 -0
- docs/servers/middleware.mdx +4 -0
docs/servers/context.mdx
CHANGED
|
@@ -17,6 +17,7 @@ The `Context` object provides a clean interface to access MCP features within yo
|
|
| 17 |
- **Resource Access**: Read data from resources registered with the server
|
| 18 |
- **LLM Sampling**: Request the client's LLM to generate text based on provided messages
|
| 19 |
- **User Elicitation**: Request structured input from users during tool execution
|
|
|
|
| 20 |
- **Request Information**: Access metadata about the current request
|
| 21 |
- **Server Access**: When needed, access the underlying FastMCP server instance
|
| 22 |
|
|
@@ -185,6 +186,51 @@ content = content_list[0].content
|
|
| 185 |
**Method signature:**
|
| 186 |
- **`ctx.read_resource(uri: str | AnyUrl) -> list[ReadResourceContents]`**: Returns a list of resource content parts
|
| 187 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 188 |
|
| 189 |
### Change Notifications
|
| 190 |
|
|
|
|
| 17 |
- **Resource Access**: Read data from resources registered with the server
|
| 18 |
- **LLM Sampling**: Request the client's LLM to generate text based on provided messages
|
| 19 |
- **User Elicitation**: Request structured input from users during tool execution
|
| 20 |
+
- **State Management**: Store and share data across middleware and tool calls within a request
|
| 21 |
- **Request Information**: Access metadata about the current request
|
| 22 |
- **Server Access**: When needed, access the underlying FastMCP server instance
|
| 23 |
|
|
|
|
| 186 |
**Method signature:**
|
| 187 |
- **`ctx.read_resource(uri: str | AnyUrl) -> list[ReadResourceContents]`**: Returns a list of resource content parts
|
| 188 |
|
| 189 |
+
### State Management
|
| 190 |
+
|
| 191 |
+
<VersionBadge version="2.11.0" />
|
| 192 |
+
|
| 193 |
+
Store and share data across middleware and tool calls within a request. Context objects maintain a state dictionary that's especially useful for passing information from [middleware](/servers/middleware) to your tools.
|
| 194 |
+
|
| 195 |
+
To store a value in the context state, use `ctx.set_state(key, value)`. To retrieve a value, use `ctx.get_state(key)`.
|
| 196 |
+
|
| 197 |
+
This simplified example shows how to use MCP middleware to store user info in the context state, and how to access that state in a tool:
|
| 198 |
+
|
| 199 |
+
```python {7-8, 16-17}
|
| 200 |
+
from fastmcp.server.middleware import Middleware, MiddlewareContext
|
| 201 |
+
|
| 202 |
+
class UserAuthMiddleware(Middleware):
|
| 203 |
+
async def on_call_tool(self, context: MiddlewareContext, call_next):
|
| 204 |
+
|
| 205 |
+
# Middleware stores user info in context state
|
| 206 |
+
context.fastmcp_context.set_state("user_id", "user_123")
|
| 207 |
+
context.fastmcp_context.set_state("permissions", ["read", "write"])
|
| 208 |
+
|
| 209 |
+
return await call_next()
|
| 210 |
+
|
| 211 |
+
@mcp.tool
|
| 212 |
+
async def secure_operation(data: str, ctx: Context) -> str:
|
| 213 |
+
"""Tool can access state set by middleware."""
|
| 214 |
+
|
| 215 |
+
user_id = ctx.get_state("user_id") # "user_123"
|
| 216 |
+
permissions = ctx.get_state("permissions") # ["read", "write"]
|
| 217 |
+
|
| 218 |
+
if "write" not in permissions:
|
| 219 |
+
return "Access denied"
|
| 220 |
+
|
| 221 |
+
return f"Processing {data} for user {user_id}"
|
| 222 |
+
```
|
| 223 |
+
|
| 224 |
+
**Method signatures:**
|
| 225 |
+
- **`ctx.set_state_value(key: str, value: Any) -> None`**: Store a value in the context state
|
| 226 |
+
- **`ctx.get_state_value(key: str) -> Any`**: Retrieve a value from the context state (returns None if not found)
|
| 227 |
+
|
| 228 |
+
**State Inheritance:**
|
| 229 |
+
When a new context is created (nested contexts), it inherits a copy of its parent's state. This ensures that:
|
| 230 |
+
- State set on a child context never affects the parent context
|
| 231 |
+
- State set on a parent context after the child context is initialized is not propagated to the child context
|
| 232 |
+
|
| 233 |
+
This makes state management predictable and prevents unexpected side effects between nested operations.
|
| 234 |
|
| 235 |
### Change Notifications
|
| 236 |
|
docs/servers/middleware.mdx
CHANGED
|
@@ -244,6 +244,10 @@ You have complete control over the request flow:
|
|
| 244 |
- **Stop the chain**: Don't call `call_next` (rarely needed)
|
| 245 |
- **Handle errors**: Wrap `call_next` in try/catch blocks
|
| 246 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 247 |
## Creating Middleware
|
| 248 |
|
| 249 |
FastMCP middleware is implemented by subclassing the `Middleware` base class and overriding the hooks you need. You only need to implement the hooks that are relevant to your use case.
|
|
|
|
| 244 |
- **Stop the chain**: Don't call `call_next` (rarely needed)
|
| 245 |
- **Handle errors**: Wrap `call_next` in try/catch blocks
|
| 246 |
|
| 247 |
+
#### State Management
|
| 248 |
+
|
| 249 |
+
In addition to modifying the request and response, you can also store state data that your tools can (optionally) access later. To do so, use the FastMCP Context to either `set_state` or `get_state` as appropriate. For more information, see the [Context State Management](/servers/context#state-management) docs.
|
| 250 |
+
|
| 251 |
## Creating Middleware
|
| 252 |
|
| 253 |
FastMCP middleware is implemented by subclassing the `Middleware` base class and overriding the hooks you need. You only need to implement the hooks that are relevant to your use case.
|