Skip to content

Commit 3add4e6

Browse files
authored
misc docstring work (#8)
1 parent ced06b7 commit 3add4e6

File tree

7 files changed

+443
-98
lines changed

7 files changed

+443
-98
lines changed

CLAUDE.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,4 +134,5 @@ This document contains critical information about working with this codebase. Fo
134134
- Cleanup blocks (log at debug level)
135135

136136
- Always use sentence case for all headings and heading-like text in any Markdown-formatted content, including docstrings.
137-
- Example snippets in docsstrings MUST only appear within the Examples section of the docstring. You MAY include multiple examples in the Examples section.
137+
- Example snippets in docsstrings MUST only appear within the Examples section of the docstring. You MAY include multiple examples in the Examples section.
138+
- Surround all lists, both ordered and unordered, with blank lines. Applies to Markdown in Markdown files as well as docstrings in Python files.

src/mcp/server/fastmcp/exceptions.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ class ResourceError(FastMCPError):
2323
"""Raised when resource operations fail.
2424
2525
This exception is raised for resource-related errors such as:
26+
2627
- Resource not found for a given URI
2728
- Resource content cannot be read or generated
2829
- Resource template parameter validation failures
@@ -34,6 +35,7 @@ class ToolError(FastMCPError):
3435
"""Raised when tool operations fail.
3536
3637
This exception is raised for tool-related errors such as:
38+
3739
- Tool not found for a given name
3840
- Tool execution failures or unhandled exceptions
3941
- Tool registration conflicts or validation errors

src/mcp/server/fastmcp/prompts/base.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ def from_function(
7474
"""Create a Prompt from a function.
7575
7676
The function can return:
77+
7778
- A string (converted to a message)
7879
- A Message object
7980
- A dict (converted to a message)

src/mcp/server/fastmcp/prompts/manager.py

Lines changed: 171 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,70 @@
1-
"""Prompt management functionality."""
1+
"""Prompt management functionality for FastMCP servers.
2+
3+
This module provides the PromptManager class, which serves as the central registry
4+
for managing prompts in FastMCP servers. Prompts are reusable templates that generate
5+
structured messages for AI model interactions, enabling consistent and parameterized
6+
communication patterns.
7+
8+
The PromptManager handles the complete lifecycle of prompts:
9+
10+
- Registration and storage of prompt templates
11+
- Retrieval by name for use in MCP protocol handlers
12+
- Rendering with arguments to produce message sequences
13+
- Duplicate detection and management
14+
15+
Key concepts:
16+
17+
- Prompts are created from functions using Prompt.from_function()
18+
- Each prompt has a unique name used for registration and retrieval
19+
- Prompts can accept typed arguments for dynamic content generation
20+
- Rendered prompts return Message objects ready for AI model consumption
21+
22+
Examples:
23+
Basic prompt management workflow:
24+
25+
```python
26+
from mcp.server.fastmcp.prompts import PromptManager, Prompt
27+
28+
# Initialize the manager
29+
manager = PromptManager()
30+
31+
# Create a prompt from a function
32+
def analysis_prompt(topic: str, context: str) -> list[str]:
33+
return [
34+
f"Please analyze the following topic: {topic}",
35+
f"Additional context: {context}",
36+
"Provide a detailed analysis with key insights."
37+
]
38+
39+
# Register the prompt
40+
prompt = Prompt.from_function(analysis_prompt)
41+
manager.add_prompt(prompt)
42+
43+
# Render the prompt with arguments
44+
messages = await manager.render_prompt(
45+
"analysis_prompt",
46+
{"topic": "AI Safety", "context": "Enterprise deployment"}
47+
)
48+
```
49+
50+
Integration with FastMCP servers:
51+
52+
```python
53+
from mcp.server.fastmcp import FastMCP
54+
55+
mcp = FastMCP("My Server")
56+
57+
@mcp.prompt()
58+
def code_review(language: str, code: str) -> str:
59+
return f"Review this {language} code for best practices:\\n\\n{code}"
60+
61+
# The prompt is automatically registered with the server's PromptManager
62+
```
63+
64+
Note:
65+
This module is primarily used internally by FastMCP servers, but can be used
66+
directly for advanced prompt management scenarios or custom MCP implementations.
67+
"""
268

369
from typing import Any
470

@@ -9,25 +75,91 @@
975

1076

1177
class PromptManager:
12-
"""Manages FastMCP prompts."""
78+
"""Manages prompt registration, storage, and rendering for FastMCP servers.
79+
80+
The PromptManager is the central registry for all prompts in a FastMCP server. It handles
81+
prompt registration, retrieval by name, listing all available prompts, and rendering
82+
prompts with provided arguments. Prompts are templates that can generate structured
83+
messages for AI model interactions.
84+
85+
This class is typically used internally by FastMCP servers but can be used directly
86+
for advanced prompt management scenarios.
87+
88+
Args:
89+
warn_on_duplicate_prompts: Whether to log warnings when attempting to register
90+
a prompt with a name that already exists. Defaults to True.
91+
92+
Attributes:
93+
warn_on_duplicate_prompts: Whether duplicate prompt warnings are enabled.
94+
95+
Examples:
96+
Basic usage:
97+
98+
```python
99+
from mcp.server.fastmcp.prompts import PromptManager, Prompt
100+
101+
# Create a manager
102+
manager = PromptManager()
103+
104+
# Create and add a prompt
105+
def greeting_prompt(name: str) -> str:
106+
return f"Hello, {name}! How can I help you today?"
107+
108+
prompt = Prompt.from_function(greeting_prompt)
109+
manager.add_prompt(prompt)
110+
111+
# Render the prompt
112+
messages = await manager.render_prompt("greeting_prompt", {"name": "Alice"})
113+
```
114+
115+
Disabling duplicate warnings:
116+
117+
```python
118+
# Useful in testing scenarios or when you need to replace prompts
119+
manager = PromptManager(warn_on_duplicate_prompts=False)
120+
```
121+
"""
13122

14123
def __init__(self, warn_on_duplicate_prompts: bool = True):
15124
self._prompts: dict[str, Prompt] = {}
16125
self.warn_on_duplicate_prompts = warn_on_duplicate_prompts
17126

18127
def get_prompt(self, name: str) -> Prompt | None:
19-
"""Get prompt by name."""
128+
"""Retrieve a registered prompt by its name.
129+
130+
Args:
131+
name: The name of the prompt to retrieve.
132+
133+
Returns:
134+
The Prompt object if found, None if no prompt exists with the given name.
135+
"""
20136
return self._prompts.get(name)
21137

22138
def list_prompts(self) -> list[Prompt]:
23-
"""List all registered prompts."""
139+
"""Get a list of all registered prompts.
140+
141+
Returns:
142+
A list containing all Prompt objects currently registered with this manager.
143+
Returns an empty list if no prompts are registered.
144+
"""
24145
return list(self._prompts.values())
25146

26147
def add_prompt(
27148
self,
28149
prompt: Prompt,
29150
) -> Prompt:
30-
"""Add a prompt to the manager."""
151+
"""Register a prompt with the manager.
152+
153+
If a prompt with the same name already exists, the existing prompt is returned
154+
without modification. A warning is logged if warn_on_duplicate_prompts is True.
155+
156+
Args:
157+
prompt: The Prompt object to register.
158+
159+
Returns:
160+
The registered Prompt object. If a prompt with the same name already exists,
161+
returns the existing prompt instead of the new one.
162+
"""
31163

32164
# Check for duplicates
33165
existing = self._prompts.get(prompt.name)
@@ -40,7 +172,40 @@ def add_prompt(
40172
return prompt
41173

42174
async def render_prompt(self, name: str, arguments: dict[str, Any] | None = None) -> list[Message]:
43-
"""Render a prompt by name with arguments."""
175+
"""Render a prompt into a list of messages ready for AI model consumption.
176+
177+
This method looks up the prompt by name, validates that all required arguments
178+
are provided, executes the prompt function with the given arguments, and converts
179+
the result into a standardized list of Message objects.
180+
181+
Args:
182+
name: The name of the prompt to render.
183+
arguments: Optional dictionary of arguments to pass to the prompt function.
184+
Must include all required arguments defined by the prompt.
185+
186+
Returns:
187+
A list of Message objects containing the rendered prompt content.
188+
Each Message has a role ("user" or "assistant") and content.
189+
190+
Raises:
191+
ValueError: If the prompt name is not found or if required arguments are missing.
192+
193+
Examples:
194+
Simple prompt without arguments:
195+
196+
```python
197+
messages = await manager.render_prompt("welcome")
198+
```
199+
200+
Prompt with arguments:
201+
202+
```python
203+
messages = await manager.render_prompt(
204+
"greeting",
205+
{"name": "Alice", "language": "en"}
206+
)
207+
```
208+
"""
44209
prompt = self.get_prompt(name)
45210
if not prompt:
46211
raise ValueError(f"Unknown prompt: {name}")

0 commit comments

Comments
 (0)