Add title to tools, resources, prompts (#972)

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Felix Weinberger 2025-06-17 10:53:14 -04:00 • committed by GitHub
commit a2f8766a8a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -212,13 +212,13 @@ from mcp.server.fastmcp import FastMCP
mcp = FastMCP("My App")
@mcp.resource("config://app")
@mcp.resource("config://app", title="Application Configuration")
def get_config() -> str:
"""Static configuration data"""
return "App configuration here"
@mcp.resource("users://{user_id}/profile")
@mcp.resource("users://{user_id}/profile", title="User Profile")
def get_user_profile(user_id: str) -> str:
"""Dynamic user data"""
return f"Profile data for user {user_id}"
@ -235,13 +235,13 @@ from mcp.server.fastmcp import FastMCP
mcp = FastMCP("My App")
@mcp.tool()
@mcp.tool(title="BMI Calculator")
def calculate_bmi(weight_kg: float, height_m: float) -> float:
"""Calculate BMI given weight in kg and height in meters"""
return weight_kg / (height_m**2)
@mcp.tool()
@mcp.tool(title="Weather Fetcher")
async def fetch_weather(city: str) -> str:
"""Fetch current weather for a city"""
async with httpx.AsyncClient() as client:
@ -260,12 +260,12 @@ from mcp.server.fastmcp.prompts import base
mcp = FastMCP("My App")
@mcp.prompt()
@mcp.prompt(title="Code Review")
def review_code(code: str) -> str:
return f"Please review this code:\n\n{code}"
@mcp.prompt()
@mcp.prompt(title="Debug Assistant")
def debug_error(error: str) -> list[base.Message]:
return [
base.UserMessage("I'm seeing this error:"),
@ -918,6 +918,42 @@ async def main():
tool_result = await session.call_tool("echo", {"message": "hello"})
```
### Client Display Utilities
When building MCP clients, the SDK provides utilities to help display human-readable names for tools, resources, and prompts:
```python
from mcp.shared.metadata_utils import get_display_name
from mcp.client.session import ClientSession
async def display_tools(session: ClientSession):
"""Display available tools with human-readable names"""
tools_response = await session.list_tools()
for tool in tools_response.tools:
# get_display_name() returns the title if available, otherwise the name
display_name = get_display_name(tool)
print(f"Tool: {display_name}")
if tool.description:
print(f" {tool.description}")
async def display_resources(session: ClientSession):
"""Display available resources with human-readable names"""
resources_response = await session.list_resources()
for resource in resources_response.resources:
display_name = get_display_name(resource)
print(f"Resource: {display_name} ({resource.uri})")
```
The `get_display_name()` function implements the proper precedence rules for displaying names:
- For tools: `title` > `annotations.title` > `name`
- For other objects: `title` > `name`
This ensures your client UI shows the most user-friendly names that servers provide.
### OAuth Authentication for Clients
The SDK includes [authorization support](https://modelcontextprotocol.io/specification/2025-03-26/basic/authorization) for connecting to protected MCP servers: