diff --git a/docs/servers/context.mdx b/docs/servers/context.mdx index cb4fe52ad..c33f1812c 100644 --- a/docs/servers/context.mdx +++ b/docs/servers/context.mdx @@ -14,7 +14,8 @@ The `Context` object provides a clean interface to access MCP features within yo - **Logging**: Send debug, info, warning, and error messages back to the client - **Progress Reporting**: Update the client on the progress of long-running operations -- **Resource Access**: Read data from resources registered with the server +- **Resource Access**: List and read data from resources registered with the server +- **Prompt Access**: List and retrieve prompts registered with the server - **LLM Sampling**: Request the client's LLM to generate text based on provided messages - **User Elicitation**: Request structured input from users during tool execution - **State Management**: Store and share data between middleware and the handler within a single request @@ -177,16 +178,40 @@ See [Progress Reporting](/servers/progress) for detailed patterns and examples. ### Resource Access -Read data from resources registered with your FastMCP server, allowing access to files, configuration, or dynamic content. +List and read data from resources registered with your FastMCP server, allowing access to files, configuration, or dynamic content. ```python +# List available resources +resources = await ctx.list_resources() + +# Read a specific resource content_list = await ctx.read_resource("resource://config") content = content_list[0].content ``` -**Method signature:** +**Method signatures:** +- **`ctx.list_resources() -> list[MCPResource]`**: Returns list of all available resources - **`ctx.read_resource(uri: str | AnyUrl) -> list[ReadResourceContents]`**: Returns a list of resource content parts +### Prompt Access + + + +List and retrieve prompts registered with your FastMCP server, allowing tools and middleware to discover and use available prompts programmatically. + +```python +# List available prompts +prompts = await ctx.list_prompts() + +# Get a specific prompt with arguments +result = await ctx.get_prompt("analyze_data", {"dataset": "users"}) +messages = result.messages +``` + +**Method signatures:** +- **`ctx.list_prompts() -> list[MCPPrompt]`**: Returns list of all available prompts +- **`ctx.get_prompt(name: str, arguments: dict[str, Any] | None = None) -> GetPromptResult`**: Get a specific prompt with optional arguments + ### State Management diff --git a/src/fastmcp/server/context.py b/src/fastmcp/server/context.py index a0fcfc1c2..1c565db55 100644 --- a/src/fastmcp/server/context.py +++ b/src/fastmcp/server/context.py @@ -22,6 +22,7 @@ AudioContent, ClientCapabilities, CreateMessageResult, + GetPromptResult, ImageContent, IncludeContext, ModelHint, @@ -32,6 +33,8 @@ TextContent, ) from mcp.types import CreateMessageRequestParams as SamplingParams +from mcp.types import Prompt as MCPPrompt +from mcp.types import Resource as MCPResource from pydantic.networks import AnyUrl from starlette.requests import Request from typing_extensions import TypeVar @@ -215,6 +218,42 @@ async def report_progress( related_request_id=self.request_id, ) + async def list_resources(self) -> list[MCPResource]: + """List all available resources from the server. + + Returns: + List of Resource objects available on the server + """ + if self.fastmcp is None: + raise ValueError("Context is not available outside of a request") + return await self.fastmcp._list_resources_mcp() + + async def list_prompts(self) -> list[MCPPrompt]: + """List all available prompts from the server. + + Returns: + List of Prompt objects available on the server + """ + if self.fastmcp is None: + raise ValueError("Context is not available outside of a request") + return await self.fastmcp._list_prompts_mcp() + + async def get_prompt( + self, name: str, arguments: dict[str, Any] | None = None + ) -> GetPromptResult: + """Get a prompt by name with optional arguments. + + Args: + name: The name of the prompt to get + arguments: Optional arguments to pass to the prompt + + Returns: + The prompt result + """ + if self.fastmcp is None: + raise ValueError("Context is not available outside of a request") + return await self.fastmcp._get_prompt_mcp(name, arguments) + async def read_resource(self, uri: str | AnyUrl) -> list[ReadResourceContents]: """Read a resource by URI. diff --git a/src/fastmcp/server/middleware/tool_injection.py b/src/fastmcp/server/middleware/tool_injection.py index 8df5d18a4..7914c5eca 100644 --- a/src/fastmcp/server/middleware/tool_injection.py +++ b/src/fastmcp/server/middleware/tool_injection.py @@ -10,8 +10,6 @@ from pydantic import AnyUrl from typing_extensions import override -from fastmcp.client.client import Client -from fastmcp.client.transports import FastMCPTransport from fastmcp.server.context import Context from fastmcp.server.middleware.middleware import CallNext, Middleware, MiddlewareContext from fastmcp.tools.tool import Tool, ToolResult @@ -55,9 +53,7 @@ async def on_call_tool( async def list_prompts(context: Context) -> list[Prompt]: """List prompts available on the server.""" - - async with Client[FastMCPTransport](context.fastmcp) as client: - return await client.list_prompts() + return await context.list_prompts() list_prompts_tool = Tool.from_function( @@ -73,9 +69,7 @@ async def get_prompt( ] = None, ) -> mcp.types.GetPromptResult: """Render a prompt available on the server.""" - - async with Client[FastMCPTransport](context.fastmcp) as client: - return await client.get_prompt(name=name, arguments=arguments) + return await context.get_prompt(name=name, arguments=arguments) get_prompt_tool = Tool.from_function( @@ -93,9 +87,7 @@ def __init__(self) -> None: async def list_resources(context: Context) -> list[mcp.types.Resource]: """List resources available on the server.""" - - async with Client[FastMCPTransport](context.fastmcp) as client: - return await client.list_resources() + return await context.list_resources() list_resources_tool = Tool.from_function(