Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
4987647
feat: add mcp_server() helper with built-in server info and credentia…
devin-ai-integration[bot] Jan 17, 2026
ec397f3
style: fix ruff format in test file
devin-ai-integration[bot] Jan 17, 2026
2c0e1ef
refactor: rename header to http_header_key, make fields optional, add…
devin-ai-integration[bot] Jan 17, 2026
127afca
refactor: rename domain to mcp_modules per PR feedback
devin-ai-integration[bot] Jan 17, 2026
b818b74
refactor: move package_name to top-level parameter and implement MCP …
devin-ai-integration[bot] Jan 17, 2026
6c88381
refactor: rename _mcp_server_config to x_mcp_server_config
devin-ai-integration[bot] Jan 17, 2026
afcea17
feat: add normalize_fn parameter to MCPServerConfigArg
devin-ai-integration[bot] Jan 17, 2026
68796f4
docs: add security note about sensitive values in normalize_fn except…
devin-ai-integration[bot] Jan 17, 2026
e87a61d
feat: update resolve_config to accept Context or FastMCP app
devin-ai-integration[bot] Jan 19, 2026
4f38302
docs: add usage examples and cross-links to module docstring
devin-ai-integration[bot] Jan 19, 2026
7330b0b
Merge branch 'devin/1768688145-mcp-server-helper' of https://git-mana…
devin-ai-integration[bot] Jan 19, 2026
aa21599
docs: use dedented code blocks in module docstring
devin-ai-integration[bot] Jan 19, 2026
5f64368
docs: use markdown headers and bulleted lists in module docstring
devin-ai-integration[bot] Jan 19, 2026
cd9df92
docs: remove redundant See Also section from module docstring
devin-ai-integration[bot] Jan 19, 2026
3d8c4db
tidy
aaronsteers Jan 19, 2026
e488a96
refactor: rename resolve_config to get_mcp_config
devin-ai-integration[bot] Jan 19, 2026
9630166
refactor: make get_registered_* and clear_registrations private
devin-ai-integration[bot] Jan 19, 2026
cb9c1a3
tidy docs
aaronsteers Jan 19, 2026
a7ac8c4
fix table format
aaronsteers Jan 19, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 44 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@ Unofficial extension library for FastMCP 2.0 with patterns, practices, and utili

## Features

- MCP Server Factory: `mcp_server()` helper that creates FastMCP instances with built-in server info resources, MCP asset discovery (optional), and credential resolution.
- MCP Annotation Constants: Standard annotation hints (`readOnlyHint`, `destructiveHint`, `idempotentHint`, `openWorldHint`) following the FastMCP 2.2.7+ specification
- Deferred Registration Decorators: `@mcp_tool`, `@mcp_prompt`, `@mcp_resource` decorators for organizing tools by domain with automatic domain detection
- Registration Utilities: Functions to register tools, prompts, and resources with a FastMCP app, filtered by domain
- Tool Testing Utilities: Helpers for testing MCP tools directly with JSON arguments (stdio and HTTP transports)
- Tool List Measurement: Utilities for measuring tool list size to track context truncation issues
- Prompt Helpers: Generic `get_prompt_text` helper for agents that cannot access prompt assets directly
- Deferred Registration Decorators: `@mcp_tool`, `@mcp_prompt`, `@mcp_resource` decorators for organizing tools by domain with automatic domain detection.
- Registration Utilities: Functions to register tools, prompts, and resources with a FastMCP app, filtered by domain.
- Tool Testing Utilities: Helpers for testing MCP tools directly with JSON arguments (stdio and HTTP transports).
- Tool List Measurement: Utilities for measuring tool list size to track context truncation issues.
- Prompt Helpers: Generic `get_prompt_text` helper for agents that cannot access prompt assets directly.

## Installation

Expand All @@ -25,6 +26,37 @@ uv add fastmcp-extensions

## Quick Start

### Using the MCP Server Factory

The `mcp_server` function creates a FastMCP instance with built-in server info resources and optional credential resolution:

```python
from fastmcp_extensions import mcp_server, MCPServerConfigArg

app = mcp_server(
name="my-mcp-server",
package_name="my-package",
advertised_properties={
"docs_url": "https://github.com/org/repo",
"release_history_url": "https://github.com/org/repo/releases",
},
server_config_args=[
MCPServerConfigArg(
name="api_key",
http_header_key="X-API-Key",
env_var="MY_API_KEY",
required=True,
sensitive=True,
),
],
)

# Server info resource is automatically registered at {name}://server/info
# Get credentials from HTTP headers or environment variables
from fastmcp_extensions import get_mcp_config
api_key = get_mcp_config(app, "api_key")
```

### Using Annotation Constants

```python
Expand Down Expand Up @@ -132,10 +164,16 @@ cmd = "python bin/measure_mcp_tool_list.py"

## API Reference

### Server Factory

- `mcp_server` - Create a FastMCP instance with built-in server info resource and auto-registration of decorated tools and assets.
- `MCPServerConfigArg` - Configuration for credential resolution and other server settings.
- `get_mcp_config` - Get a credential from HTTP headers or environment variables.

### Annotations

| Constant | Description | FastMCP Default |
|----------|-------------|-----------------|
| -------- | ----------- | --------------- |
| `READ_ONLY_HINT` | Tool only reads data | `False` |
| `DESTRUCTIVE_HINT` | Tool modifies/deletes data | `True` |
| `IDEMPOTENT_HINT` | Repeated calls have same effect | `False` |
Expand Down
18 changes: 10 additions & 8 deletions src/fastmcp_extensions/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,6 @@
READ_ONLY_HINT,
)
from fastmcp_extensions.decorators import (
clear_registrations,
get_registered_prompts,
get_registered_resources,
get_registered_tools,
mcp_prompt,
mcp_resource,
mcp_tool,
Expand All @@ -33,20 +29,26 @@
register_mcp_resources,
register_mcp_tools,
)
from fastmcp_extensions.server import (
MCPServerConfig,
MCPServerConfigArg,
get_mcp_config,
mcp_server,
)

__all__ = [
"DESTRUCTIVE_HINT",
"IDEMPOTENT_HINT",
"OPEN_WORLD_HINT",
"READ_ONLY_HINT",
"MCPServerConfig",
"MCPServerConfigArg",
"PromptDef",
"ResourceDef",
"clear_registrations",
"get_registered_prompts",
"get_registered_resources",
"get_registered_tools",
"get_mcp_config",
"mcp_prompt",
"mcp_resource",
"mcp_server",
"mcp_tool",
"register_mcp_prompts",
"register_mcp_resources",
Expand Down
29 changes: 1 addition & 28 deletions src/fastmcp_extensions/decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,34 +186,7 @@ def decorator(func: Callable[..., Any]) -> Callable[..., Any]:
return decorator


def get_registered_tools() -> list[tuple[Callable[..., Any], dict[str, Any]]]:
"""Get all registered tools.

Returns:
List of (function, annotations) tuples for all registered tools.
"""
return _REGISTERED_TOOLS.copy()


def get_registered_prompts() -> list[tuple[Callable[..., Any], dict[str, Any]]]:
"""Get all registered prompts.

Returns:
List of (function, annotations) tuples for all registered prompts.
"""
return _REGISTERED_PROMPTS.copy()


def get_registered_resources() -> list[tuple[Callable[..., Any], dict[str, Any]]]:
"""Get all registered resources.

Returns:
List of (function, annotations) tuples for all registered resources.
"""
return _REGISTERED_RESOURCES.copy()


def clear_registrations() -> None:
def _clear_registrations() -> None:
"""Clear all registered tools, prompts, and resources.

This is primarily useful for testing.
Expand Down
27 changes: 0 additions & 27 deletions src/fastmcp_extensions/registration.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,30 +191,3 @@ def _register_fn(
resource_list=_REGISTERED_RESOURCES,
register_fn=_register_fn,
)


def get_registered_tools() -> list[tuple[Callable[..., Any], dict[str, Any]]]:
"""Get all registered tools.

Returns:
List of (function, annotations) tuples for all registered tools.
"""
return _REGISTERED_TOOLS.copy()


def get_registered_prompts() -> list[tuple[Callable[..., Any], dict[str, Any]]]:
"""Get all registered prompts.

Returns:
List of (function, annotations) tuples for all registered prompts.
"""
return _REGISTERED_PROMPTS.copy()


def get_registered_resources() -> list[tuple[Callable[..., Any], dict[str, Any]]]:
"""Get all registered resources.

Returns:
List of (function, annotations) tuples for all registered resources.
"""
return _REGISTERED_RESOURCES.copy()
Loading
Loading