# Chapter 6: Talking Back - FastMCP Context (`Context`)
In [Chapter 5: Reusable Chat Starters - FastMCP Prompts (`Prompt`, `PromptManager`)](05_fastmcp_prompts___prompt____promptmanager__.md), we learned how to create reusable message templates for interacting with AI models. We've seen how to build servers with data resources ([Chapter 3](03_fastmcp_resources___resource____resourcemanager__.md)) and action tools ([Chapter 4](04_fastmcp_tools___tool____toolmanager__.md)).
But imagine you have a tool that takes a while to run, like processing a large file or making a complex calculation. How does your tool communicate back to the user *while* it's running? How can it say "I'm 50% done!" or log important steps? Or what if a tool needs to read some data from one of the server's resources to do its job?
This is where the **`Context`** object comes in. It's like giving your tool function a temporary **backstage pass** for the specific request it's handling. This pass grants it access to special features like sending logs, reporting progress, or accessing other parts of the server environment related to that request.
## What is `Context`?
The `Context` object is a special helper object provided by the `FastMCP` framework. If you define a tool function (or a resource function) that includes a parameter specifically typed as `Context`, `FastMCP` will automatically create and pass this object to your function when it's called.
Think of it this way:
* Each client request (like `callTool` or `readResource`) is like a separate event.
* For that specific event, `FastMCP` can provide a `Context` object.
* This `Context` object holds information about *that specific request* (like its unique ID).
* It also provides methods (functions) to interact with the ongoing session, such as:
* Sending log messages back to the client (`ctx.info`, `ctx.debug`, etc.).
* Reading data from other resources defined on the server (`ctx.read_resource`).
It's your function's way of communicating out or accessing shared server capabilities during its execution for a particular request.
## Getting Access: Asking for the `Context`
How do you tell `FastMCP` that your function needs this backstage pass? You simply add a parameter to your function definition and use a **type hint** to mark it as `Context`.
Let's create a tool that simulates a long-running task and uses `Context` to report progress and log messages.
**File: `long_task_server.py`**
```python
importanyio# For simulating delay with sleep
frommcp.server.fastmcpimportFastMCP
# 1. Import the Context type
frommcp.server.fastmcp.serverimportContext
# Create the server instance
server=FastMCP(name="LongTaskServer")
# Define our tool function
# 2. Add a parameter (e.g., 'ctx') and type hint it as 'Context'
@server.tool(name="long_task",description="Simulates a task that takes time.")
* Crucially, we add a parameter named `ctx`. You can name it anything (like `context`, `req_ctx`), but `ctx` is common.
* We add the type hint `: Context` after the parameter name. This is the signal to `FastMCP` to inject the context object here.
3.**Using `ctx`**: Inside the function, we can now use the methods provided by the `ctx` object:
*`await ctx.info(...)`: Sends an informational log message back to the client connected to this session.
*`await ctx.debug(...)`: Sends a debug-level log message. There are also `warning` and `error` methods.
*`await ctx.report_progress(step, total_steps)`: Sends a progress update to the client. The client application might display this in a progress bar.
When a client calls the `long_task` tool, `FastMCP` will:
1. See the `ctx: Context` parameter.
2. Create a `Context` object specific to this request.
3. Call your `run_long_task` function, passing the duration and the newly created `ctx` object.
4. Your function runs, and calls like `ctx.info` or `ctx.report_progress` send messages back to the client *during* the execution of the tool.
## Using `Context` to Access Resources
The `Context` object isn't just for sending information *out*; it can also be used to access other parts of the server, like reading resources defined using `@server.resource`.
Let's modify our example. Imagine our long task needs some configuration data stored in a resource.
**File: `long_task_server_with_resource.py`**
```python
importanyio
frommcp.server.fastmcpimportFastMCP
frommcp.server.fastmcp.serverimportContext
# Create the server instance
server=FastMCP(name="LongTaskServer")
# Define a simple resource that holds some config data
@server.resource(uri="config://task_settings",description="Settings for the long task.")
defget_task_settings()->str:
"""Returns task settings as a simple string."""
# In a real app, this might load from a file or database
print("Resource 'config://task_settings' was read!")
return"Default speed: Normal"# Simple example setting
# Define our tool function
@server.tool(name="long_task",description="Simulates a task using config resource.")
awaitctx.warning(f"Could not read task settings: {e}")
total_steps=5
foriinrange(total_steps):
step=i+1
awaitctx.debug(f"Working on step {step}/{total_steps}...")
awaitanyio.sleep(duration_seconds/total_steps)
awaitctx.report_progress(step,total_steps)
awaitctx.info("Long task completed!")
returnf"Finished simulated task of {duration_seconds} seconds using settings."
# Standard run block
if__name__=="__main__":
print(f"Starting {server.name}...")
server.run()
print(f"{server.name} finished.")
```
**Explanation:**
1.**`@server.resource(...)`**: We added a simple resource named `config://task_settings` that just returns a string.
2.**`resource_contents = await ctx.read_resource("config://task_settings")`**: Inside our `run_long_task` tool, we now use `ctx.read_resource()` to fetch the content of our configuration resource. This allows the tool to dynamically access data managed by the server without having direct access to the resource's implementation function (`get_task_settings`).
3.**Processing Content**: The `read_resource` method returns an iterable of `ReadResourceContents` objects (often just one). We extracted the string content to use it.
Now, our tool can both communicate outwards (logs, progress) and interact inwards (read resources) using the same `Context` object, all within the scope of the single request it's handling.
## How `Context` Works Under the Hood
It feels like magic that just adding `: Context` gives your function these powers, but it's a well-defined process within `FastMCP`.
1.**Request Arrives:** A client sends a request, for example, `callTool` for our `long_task`.
2.**Low-Level Handling:** The underlying `MCPServer` receives the request and creates a `RequestContext` object. This low-level context holds the raw request details, a reference to the current `ServerSession`, and the request ID.
3.**`FastMCP` Takes Over:** The request is routed to the appropriate `FastMCP` handler method (e.g., `FastMCP.call_tool`).
4.**Context Creation:** Before calling the actual tool function, `FastMCP` calls its internal `get_context()` method. This method creates the high-level `Context` object we use. It wraps the low-level `RequestContext` and also adds a reference to the `FastMCP` server instance itself.
5.**Function Inspection:** The `ToolManager` (when asked to run the tool) inspects the signature of your target function (`run_long_task`). It sees the `ctx: Context` parameter.
6.**Injection:** The `ToolManager` (specifically the `Tool.run` method which uses `FuncMetadata.call_fn_with_arg_validation`) knows it needs to provide a `Context` object. It takes the `Context` created in step 4 and passes it as the argument for the `ctx` parameter when calling your `run_long_task` function.
7.**Execution:** Your function runs. When you call `ctx.info("...")`, the `Context` object uses its reference to the underlying `RequestContext` and `ServerSession` to send the appropriate log message back to the client via the session. Similarly, `ctx.report_progress` uses the session, and `ctx.read_resource` uses the reference to the `FastMCP` instance to call its `read_resource` method.
**Simplified Sequence Diagram (`callTool` with `Context`):**
```mermaid
sequenceDiagram
participant Client
participant FastMCPServer as FastMCP (server.py)
participant ToolMgr as ToolManager (_tool_manager)
participant ToolRunner as Tool.run / FuncMetadata
participant YourToolFunc as run_long_task(ctx: Context)
***Context Creation (`server/fastmcp/server.py`)**: The `FastMCP.get_context` method is responsible for creating the `Context` object when needed, typically just before calling a tool or resource handler. It grabs the low-level context and wraps it.
* **Context Injection (`server/fastmcp/tools/base.py`)**: The `Tool.from_function` method inspects the function signature to see if a `Context` parameter exists and stores its name (`context_kwarg`). Later, `Tool.run` uses this information (via `FuncMetadata`) to pass the context object when calling your function.
# Add the context object to the arguments passed to the function
kwargs_for_fn[self.context_kwarg] = context
# Call the original function (self.fn)
result = await self.fn(**kwargs_for_fn) # Or sync call
return result
```
* **Context Implementation (`server/fastmcp/server.py`)**: The `Context` class itself implements methods like `info`, `report_progress`, `read_resource` by calling methods on the stored `_request_context.session` or `_fastmcp` instance.
* `FastMCP` automatically creates and injects the `Context` object when your function is called for a specific request.
The `Context` object is key to building more interactive and communicative tools and resources that can provide feedback to the user and interact with their environment during execution.
So far, we've focused on the high-level abstractions `FastMCP` provides (`Tool`, `Resource`, `Prompt`, `Context`). In the next chapter, we'll take a step back and look at the fundamental data structures defined by the MCP specification itself: [Chapter 7: MCP Protocol Types](07_mcp_protocol_types.md). Understanding these types helps clarify the data being exchanged between clients and servers under the hood.
---
Generated by [AI Codebase Knowledge Builder](https://github.com/The-Pocket/Tutorial-Codebase-Knowledge)