fastapi-mcp-router 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- fastapi_mcp_router-0.1.0/.codannaignore +70 -0
- fastapi_mcp_router-0.1.0/.github/workflows/release.yml +61 -0
- fastapi_mcp_router-0.1.0/.gitignore +49 -0
- fastapi_mcp_router-0.1.0/CHANGELOG.md +35 -0
- fastapi_mcp_router-0.1.0/CLAUDE.md +81 -0
- fastapi_mcp_router-0.1.0/LICENSE +21 -0
- fastapi_mcp_router-0.1.0/PKG-INFO +104 -0
- fastapi_mcp_router-0.1.0/README.md +67 -0
- fastapi_mcp_router-0.1.0/docs/guide.md +685 -0
- fastapi_mcp_router-0.1.0/docs/quickstart.md +136 -0
- fastapi_mcp_router-0.1.0/docs/reference.md +814 -0
- fastapi_mcp_router-0.1.0/examples/README.md +102 -0
- fastapi_mcp_router-0.1.0/examples/__init__.py +0 -0
- fastapi_mcp_router-0.1.0/examples/server.py +97 -0
- fastapi_mcp_router-0.1.0/fastapi_mcp_router/__init__.py +44 -0
- fastapi_mcp_router-0.1.0/fastapi_mcp_router/exceptions.py +146 -0
- fastapi_mcp_router-0.1.0/fastapi_mcp_router/prompts.py +337 -0
- fastapi_mcp_router-0.1.0/fastapi_mcp_router/protocol.py +135 -0
- fastapi_mcp_router-0.1.0/fastapi_mcp_router/registry.py +871 -0
- fastapi_mcp_router-0.1.0/fastapi_mcp_router/resources.py +782 -0
- fastapi_mcp_router-0.1.0/fastapi_mcp_router/router.py +2191 -0
- fastapi_mcp_router-0.1.0/fastapi_mcp_router/session.py +956 -0
- fastapi_mcp_router-0.1.0/fastapi_mcp_router/telemetry.py +60 -0
- fastapi_mcp_router-0.1.0/fastapi_mcp_router/types.py +389 -0
- fastapi_mcp_router-0.1.0/pyproject.toml +108 -0
- fastapi_mcp_router-0.1.0/tests/__init__.py +1 -0
- fastapi_mcp_router-0.1.0/tests/conftest.py +168 -0
- fastapi_mcp_router-0.1.0/tests/test_annotations.py +189 -0
- fastapi_mcp_router-0.1.0/tests/test_background_tasks_injection.py +310 -0
- fastapi_mcp_router-0.1.0/tests/test_backwards_compat.py +333 -0
- fastapi_mcp_router-0.1.0/tests/test_completions.py +289 -0
- fastapi_mcp_router-0.1.0/tests/test_elicitation.py +538 -0
- fastapi_mcp_router-0.1.0/tests/test_exceptions.py +483 -0
- fastapi_mcp_router-0.1.0/tests/test_handle_tools_list.py +174 -0
- fastapi_mcp_router-0.1.0/tests/test_logging_protocol.py +261 -0
- fastapi_mcp_router-0.1.0/tests/test_mcp_router_class.py +308 -0
- fastapi_mcp_router-0.1.0/tests/test_output_schemas.py +254 -0
- fastapi_mcp_router-0.1.0/tests/test_prm.py +188 -0
- fastapi_mcp_router-0.1.0/tests/test_progress.py +582 -0
- fastapi_mcp_router-0.1.0/tests/test_prompts.py +559 -0
- fastapi_mcp_router-0.1.0/tests/test_protocol.py +423 -0
- fastapi_mcp_router-0.1.0/tests/test_redis_session.py +466 -0
- fastapi_mcp_router-0.1.0/tests/test_registry.py +1106 -0
- fastapi_mcp_router-0.1.0/tests/test_registry_generator.py +210 -0
- fastapi_mcp_router-0.1.0/tests/test_request_injection.py +409 -0
- fastapi_mcp_router-0.1.0/tests/test_resources.py +554 -0
- fastapi_mcp_router-0.1.0/tests/test_roots.py +224 -0
- fastapi_mcp_router-0.1.0/tests/test_router_integration.py +1345 -0
- fastapi_mcp_router-0.1.0/tests/test_sampling.py +490 -0
- fastapi_mcp_router-0.1.0/tests/test_security.py +445 -0
- fastapi_mcp_router-0.1.0/tests/test_session.py +478 -0
- fastapi_mcp_router-0.1.0/tests/test_session_management.py +795 -0
- fastapi_mcp_router-0.1.0/tests/test_session_store.py +353 -0
- fastapi_mcp_router-0.1.0/tests/test_sse_events.py +734 -0
- fastapi_mcp_router-0.1.0/tests/test_sse_streaming.py +660 -0
- fastapi_mcp_router-0.1.0/tests/test_streamable_http.py +875 -0
- fastapi_mcp_router-0.1.0/tests/test_streaming_tools.py +458 -0
- fastapi_mcp_router-0.1.0/tests/test_subscriptions.py +390 -0
- fastapi_mcp_router-0.1.0/tests/test_telemetry.py +588 -0
- fastapi_mcp_router-0.1.0/tests/test_types.py +225 -0
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# Codanna ignore patterns (gitignore syntax)
|
|
2
|
+
# https://git-scm.com/docs/gitignore
|
|
3
|
+
#
|
|
4
|
+
# This file tells codanna which files to exclude from indexing.
|
|
5
|
+
# Each line specifies a pattern. Patterns follow the same rules as .gitignore.
|
|
6
|
+
|
|
7
|
+
# Build artifacts
|
|
8
|
+
target/
|
|
9
|
+
build/
|
|
10
|
+
dist/
|
|
11
|
+
*.o
|
|
12
|
+
*.so
|
|
13
|
+
*.dylib
|
|
14
|
+
*.exe
|
|
15
|
+
*.dll
|
|
16
|
+
|
|
17
|
+
# Test files (uncomment to exclude tests from indexing)
|
|
18
|
+
# tests/
|
|
19
|
+
# *_test.rs
|
|
20
|
+
# *.test.js
|
|
21
|
+
# *.spec.ts
|
|
22
|
+
# test_*.py
|
|
23
|
+
|
|
24
|
+
# Temporary files
|
|
25
|
+
*.tmp
|
|
26
|
+
*.temp
|
|
27
|
+
*.bak
|
|
28
|
+
*.swp
|
|
29
|
+
*.swo
|
|
30
|
+
*~
|
|
31
|
+
.DS_Store
|
|
32
|
+
|
|
33
|
+
# Codanna's own directory
|
|
34
|
+
.codanna/
|
|
35
|
+
|
|
36
|
+
# Dependency directories
|
|
37
|
+
node_modules/
|
|
38
|
+
vendor/
|
|
39
|
+
.venv/
|
|
40
|
+
venv/
|
|
41
|
+
__pycache__/
|
|
42
|
+
*.egg-info/
|
|
43
|
+
.cargo/
|
|
44
|
+
|
|
45
|
+
# IDE and editor directories
|
|
46
|
+
.idea/
|
|
47
|
+
.vscode/
|
|
48
|
+
*.iml
|
|
49
|
+
.project
|
|
50
|
+
.classpath
|
|
51
|
+
.settings/
|
|
52
|
+
|
|
53
|
+
# Documentation (uncomment if you don't want to index docs)
|
|
54
|
+
# docs/
|
|
55
|
+
# *.md
|
|
56
|
+
|
|
57
|
+
# Generated files
|
|
58
|
+
*.generated.*
|
|
59
|
+
*.auto.*
|
|
60
|
+
*_pb2.py
|
|
61
|
+
*.pb.go
|
|
62
|
+
|
|
63
|
+
# Version control
|
|
64
|
+
.git/
|
|
65
|
+
.svn/
|
|
66
|
+
.hg/
|
|
67
|
+
|
|
68
|
+
# Example of including specific files from ignored directories:
|
|
69
|
+
# !target/doc/
|
|
70
|
+
# !vendor/specific-file.rs
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
|
|
6
|
+
jobs:
|
|
7
|
+
release:
|
|
8
|
+
runs-on: ubuntu-latest
|
|
9
|
+
permissions:
|
|
10
|
+
contents: write
|
|
11
|
+
id-token: write
|
|
12
|
+
|
|
13
|
+
steps:
|
|
14
|
+
- uses: actions/checkout@v4
|
|
15
|
+
|
|
16
|
+
- uses: astral-sh/setup-uv@v5
|
|
17
|
+
|
|
18
|
+
- uses: actions/setup-python@v5
|
|
19
|
+
with:
|
|
20
|
+
python-version: '3.13'
|
|
21
|
+
|
|
22
|
+
- name: Install dependencies
|
|
23
|
+
run: uv sync --extra dev
|
|
24
|
+
|
|
25
|
+
- name: Run tests
|
|
26
|
+
run: uv run pytest
|
|
27
|
+
|
|
28
|
+
- name: Build package
|
|
29
|
+
run: uv run python -m build
|
|
30
|
+
|
|
31
|
+
- name: Publish to PyPI
|
|
32
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
33
|
+
|
|
34
|
+
- name: Create git tag
|
|
35
|
+
run: |
|
|
36
|
+
git config --global user.name "github-actions[bot]"
|
|
37
|
+
git config --global user.email "github-actions[bot]@users.noreply.github.com"
|
|
38
|
+
|
|
39
|
+
VERSION=$(python -c "import tomllib; print(tomllib.load(open('pyproject.toml','rb'))['project']['version'])")
|
|
40
|
+
|
|
41
|
+
if git tag -l "v${VERSION}" | grep -q "v${VERSION}"; then
|
|
42
|
+
echo "Tag v${VERSION} already exists, skipping"
|
|
43
|
+
else
|
|
44
|
+
git tag -a "v${VERSION}" -m "Release v${VERSION}"
|
|
45
|
+
git push --tags
|
|
46
|
+
fi
|
|
47
|
+
|
|
48
|
+
echo "RELEASE_VERSION=${VERSION}" >> "$GITHUB_ENV"
|
|
49
|
+
|
|
50
|
+
- name: Create GitHub Release
|
|
51
|
+
env:
|
|
52
|
+
GH_TOKEN: ${{ github.token }}
|
|
53
|
+
run: |
|
|
54
|
+
if gh release view "v${RELEASE_VERSION}" &>/dev/null; then
|
|
55
|
+
echo "Release v${RELEASE_VERSION} already exists, skipping"
|
|
56
|
+
else
|
|
57
|
+
gh release create "v${RELEASE_VERSION}" \
|
|
58
|
+
--title "v${RELEASE_VERSION}" \
|
|
59
|
+
--generate-notes \
|
|
60
|
+
dist/*
|
|
61
|
+
fi
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.so
|
|
6
|
+
*.egg-info/
|
|
7
|
+
*.egg
|
|
8
|
+
dist/
|
|
9
|
+
build/
|
|
10
|
+
|
|
11
|
+
# Virtual environments
|
|
12
|
+
.venv/
|
|
13
|
+
venv/
|
|
14
|
+
|
|
15
|
+
# Testing & coverage
|
|
16
|
+
.coverage
|
|
17
|
+
coverage/
|
|
18
|
+
reports/
|
|
19
|
+
.pytest_cache/
|
|
20
|
+
htmlcov/
|
|
21
|
+
|
|
22
|
+
# Linting
|
|
23
|
+
.ruff_cache/
|
|
24
|
+
|
|
25
|
+
# IDE
|
|
26
|
+
.idea/
|
|
27
|
+
.vscode/
|
|
28
|
+
*.swp
|
|
29
|
+
*.swo
|
|
30
|
+
|
|
31
|
+
# OS
|
|
32
|
+
.DS_Store
|
|
33
|
+
Thumbs.db
|
|
34
|
+
|
|
35
|
+
# Claude Code
|
|
36
|
+
.claude/
|
|
37
|
+
|
|
38
|
+
# Conduct workflow artifacts
|
|
39
|
+
conduct/
|
|
40
|
+
|
|
41
|
+
# Code intelligence
|
|
42
|
+
.codanna/
|
|
43
|
+
.fastembed_*
|
|
44
|
+
|
|
45
|
+
# Generated docs
|
|
46
|
+
ARCHITECTURE.md
|
|
47
|
+
|
|
48
|
+
# uv lock (library — consumers pin their own deps)
|
|
49
|
+
uv.lock
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [0.1.0] - 2026-03-01
|
|
9
|
+
|
|
10
|
+
Initial release.
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- `MCPRouter` — `APIRouter` subclass with `@mcp.tool()`, `@mcp.resource()`, `@mcp.prompt()` decorators
|
|
15
|
+
- `create_mcp_router()` factory for external registry composition
|
|
16
|
+
- Full MCP 2025-06-18 protocol coverage (17 methods)
|
|
17
|
+
- Streamable HTTP transport (JSON and SSE responses via `Accept` header)
|
|
18
|
+
- Legacy SSE compatibility via `legacy_sse=True`
|
|
19
|
+
- `MCPToolRegistry` with auto-generated JSON schemas from function signatures
|
|
20
|
+
- FastAPI `Depends()`, `Request`, and `BackgroundTasks` injection in tool handlers
|
|
21
|
+
- `ToolFilter` callback for per-connection tool filtering
|
|
22
|
+
- `ResourceRegistry` with decorator and provider patterns
|
|
23
|
+
- `FileResourceProvider` with path traversal protection and 10 MB size limit
|
|
24
|
+
- `PromptRegistry` with auto-generated argument metadata
|
|
25
|
+
- Streaming tools via `AsyncGenerator` return type
|
|
26
|
+
- `ProgressCallback` injection for long-running tools
|
|
27
|
+
- `SessionStore` ABC with `InMemorySessionStore` and `RedisSessionStore`
|
|
28
|
+
- `SamplingManager` and `RootsManager` for server-to-client requests
|
|
29
|
+
- Resource subscriptions with per-session URI change tracking
|
|
30
|
+
- `auth_validator` callback for API key and Bearer token authentication
|
|
31
|
+
- `create_prm_router()` for OAuth 2.1 Protected Resource Metadata (RFC 9728)
|
|
32
|
+
- `MCPError` (protocol-level) and `ToolError` (LLM-visible) error separation
|
|
33
|
+
- Optional OpenTelemetry spans and counters via `fastapi-mcp-router[otel]`
|
|
34
|
+
- Stateless mode for AWS Lambda deployment via Mangum
|
|
35
|
+
- Documentation: quick start, narrative guide, API reference
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
+
|
|
5
|
+
## Project
|
|
6
|
+
|
|
7
|
+
fastapi-mcp-router is a lightweight FastAPI integration for the Model Context Protocol (MCP). It exposes MCP tools, resources, and prompts through FastAPI endpoints using decorator-based registration and JSON-RPC 2.0 transport. Supports stateless HTTP (Lambda-compatible) and Streamable HTTP with SSE streaming.
|
|
8
|
+
|
|
9
|
+
## Commands
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
# Run all tests (includes coverage, enforces 80% minimum)
|
|
13
|
+
uv run pytest
|
|
14
|
+
|
|
15
|
+
# Run a single test
|
|
16
|
+
uv run pytest tests/test_registry.py::test_register_tool_default_name -v
|
|
17
|
+
|
|
18
|
+
# Run tests by marker
|
|
19
|
+
uv run pytest -m unit
|
|
20
|
+
uv run pytest -m integration
|
|
21
|
+
|
|
22
|
+
# Run tests without coverage (faster iteration)
|
|
23
|
+
uv run pytest --no-cov
|
|
24
|
+
|
|
25
|
+
# Build package
|
|
26
|
+
uv run python -m build
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
No separate lint or format commands are configured. No Makefile exists. The venv is managed by `uv` — use `uv run` to execute commands.
|
|
30
|
+
|
|
31
|
+
## Architecture
|
|
32
|
+
|
|
33
|
+
The package has 10 modules across 5,909 LOC with this dependency flow:
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
router.py → registry.py → exceptions.py
|
|
37
|
+
↓ ↓
|
|
38
|
+
protocol.py types.py
|
|
39
|
+
↓
|
|
40
|
+
telemetry.py (leaf, zero internal imports)
|
|
41
|
+
↓
|
|
42
|
+
session.py, resources.py, prompts.py
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**router.py** — `create_mcp_router()` factory and `MCPRouter` class. Handles 17 MCP methods. Streamable HTTP POST returns `JSONResponse` or `StreamingResponse` based on `Accept` header. `legacy_sse=True` registers GET endpoint for backward compatibility. OTel instrumentation via `telemetry.py`.
|
|
46
|
+
|
|
47
|
+
**registry.py** — `MCPToolRegistry` stores tool definitions registered via `@registry.tool()` decorator. Auto-generates JSON schemas from function signatures using Pydantic `TypeAdapter`. Filters out FastAPI `Depends()`, `Request`, and `BackgroundTasks` parameters from schemas.
|
|
48
|
+
|
|
49
|
+
**telemetry.py** — Leaf module with zero internal imports. Wraps optional `opentelemetry-api` behind try/except ImportError. Exports `get_tracer()` and `get_meter()`.
|
|
50
|
+
|
|
51
|
+
**protocol.py** — Pure functions for formatting JSON-RPC 2.0 responses and errors.
|
|
52
|
+
|
|
53
|
+
**types.py** — Pydantic models: `TextContent`, `ToolResponse`, `ServerInfo`, `ServerIcon`, `McpSessionData`.
|
|
54
|
+
|
|
55
|
+
**exceptions.py** — `MCPError` (protocol-level, JSON-RPC error codes -32700 to -32603) vs `ToolError` (business logic, returns `isError: true` so LLM can recover).
|
|
56
|
+
|
|
57
|
+
**session.py** — `SessionStore` ABC, `InMemorySessionStore`, `RedisSessionStore`, `SamplingManager`, `RootsManager`.
|
|
58
|
+
|
|
59
|
+
**resources.py** — `ResourceRegistry`, `ResourceProvider` ABC, `FileResourceProvider`.
|
|
60
|
+
|
|
61
|
+
**prompts.py** — `PromptRegistry` with auto-generated argument metadata.
|
|
62
|
+
|
|
63
|
+
## Key Patterns
|
|
64
|
+
|
|
65
|
+
- Streamable HTTP: POST with `Accept: text/event-stream` returns `StreamingResponse`; without returns `JSONResponse`.
|
|
66
|
+
- `legacy_sse=True` registers SSE GET endpoint alongside Streamable HTTP POST. Default is `False`.
|
|
67
|
+
- All JSON-RPC responses use HTTP 200. Errors are at the protocol level, not HTTP status codes.
|
|
68
|
+
- Tool handlers can be sync or async. Registry detects and handles both.
|
|
69
|
+
- `ToolFilter` callback enables per-connection tool filtering (e.g., OAuth vs API key scopes).
|
|
70
|
+
- Auth validation uses `auth_validator` callback passed to `create_mcp_router()`.
|
|
71
|
+
- Protocol versions supported: `2025-06-18` (primary), `2025-03-26` (fallback).
|
|
72
|
+
- Public API is defined in `__init__.py` via `__all__` (17 exports).
|
|
73
|
+
- OTel tracing is optional: `enable_telemetry=True` (default) emits spans when `opentelemetry-api` is installed. Install via `pip install fastapi-mcp-router[otel]`.
|
|
74
|
+
|
|
75
|
+
## Testing
|
|
76
|
+
|
|
77
|
+
- 544 tests across 33 files using pytest + pytest-asyncio.
|
|
78
|
+
- Integration tests use `httpx.AsyncClient` with FastAPI `TestClient`.
|
|
79
|
+
- Tests use `@pytest.mark.unit` and `@pytest.mark.integration` markers.
|
|
80
|
+
- Async test functions use explicit `@pytest.mark.asyncio` decorator (`asyncio_mode = "auto"` is NOT configured).
|
|
81
|
+
- Key test files: `test_streamable_http.py` (Streamable HTTP transport), `test_telemetry.py` (OTel), `test_sse_streaming.py` (legacy SSE).
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Andre Bremer
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: fastapi-mcp-router
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Lightweight FastAPI integration for Model Context Protocol (MCP)
|
|
5
|
+
Project-URL: Homepage, https://github.com/rcrsr/fastapi-mcp-router
|
|
6
|
+
Project-URL: Repository, https://github.com/rcrsr/fastapi-mcp-router
|
|
7
|
+
Project-URL: Issues, https://github.com/rcrsr/fastapi-mcp-router/issues
|
|
8
|
+
License-Expression: MIT
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Keywords: ai,fastapi,llm,mcp,model-context-protocol
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Framework :: FastAPI
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
21
|
+
Classifier: Typing :: Typed
|
|
22
|
+
Requires-Python: >=3.10
|
|
23
|
+
Requires-Dist: fastapi>=0.134.0
|
|
24
|
+
Requires-Dist: pydantic>=2.12.5
|
|
25
|
+
Provides-Extra: dev
|
|
26
|
+
Requires-Dist: build>=1.4.0; extra == 'dev'
|
|
27
|
+
Requires-Dist: httpx>=0.28.1; extra == 'dev'
|
|
28
|
+
Requires-Dist: pytest-asyncio>=1.3.0; extra == 'dev'
|
|
29
|
+
Requires-Dist: pytest-cov>=7.0.0; extra == 'dev'
|
|
30
|
+
Requires-Dist: pytest>=9.0.2; extra == 'dev'
|
|
31
|
+
Requires-Dist: ruff>=0.15.4; extra == 'dev'
|
|
32
|
+
Requires-Dist: twine>=6.2.0; extra == 'dev'
|
|
33
|
+
Requires-Dist: ty>=0.0.19; extra == 'dev'
|
|
34
|
+
Provides-Extra: otel
|
|
35
|
+
Requires-Dist: opentelemetry-api>=1.0; extra == 'otel'
|
|
36
|
+
Description-Content-Type: text/markdown
|
|
37
|
+
|
|
38
|
+
# fastapi-mcp-router
|
|
39
|
+
|
|
40
|
+
Add MCP to your existing FastAPI app. Register tools, resources, and prompts with decorators. Use `Depends()`, `Request`, and `BackgroundTasks` the same way you already do.
|
|
41
|
+
|
|
42
|
+
## Why fastapi-mcp-router
|
|
43
|
+
|
|
44
|
+
- **It's just an `APIRouter`.** Mount it like any other router. No separate framework, no new server process.
|
|
45
|
+
- **Your DI still works.** `Depends()`, `Request`, `BackgroundTasks` — same patterns, same middleware.
|
|
46
|
+
- **2 dependencies.** FastAPI and Pydantic. Nothing else.
|
|
47
|
+
- **No lock-in.** Tools are regular async functions. Call them from tests, CLI scripts, or other endpoints without MCP.
|
|
48
|
+
- **Lambda-ready.** Stateless mode + Mangum. No adapter layer.
|
|
49
|
+
|
|
50
|
+
**Use FastMCP instead** if you need STDIO transport, OpenAPI spec imports, or managed hosting.
|
|
51
|
+
|
|
52
|
+
## Install
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
pip install fastapi-mcp-router
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Quick Start
|
|
59
|
+
|
|
60
|
+
```python
|
|
61
|
+
from fastapi import FastAPI
|
|
62
|
+
from fastapi_mcp_router import MCPRouter
|
|
63
|
+
|
|
64
|
+
app = FastAPI()
|
|
65
|
+
mcp = MCPRouter()
|
|
66
|
+
|
|
67
|
+
@mcp.tool()
|
|
68
|
+
async def write_message(payload: str) -> dict:
|
|
69
|
+
"""Write coordination message."""
|
|
70
|
+
return {"success": True, "message_id": "msg-123"}
|
|
71
|
+
|
|
72
|
+
@mcp.resource("project://{project_id}/config")
|
|
73
|
+
async def project_config(project_id: str) -> dict:
|
|
74
|
+
return {"project_id": project_id, "env": "production"}
|
|
75
|
+
|
|
76
|
+
@mcp.prompt()
|
|
77
|
+
async def review_code(file_path: str, language: str = "python") -> list[dict]:
|
|
78
|
+
return [{"role": "user", "content": f"Review {file_path} ({language})"}]
|
|
79
|
+
|
|
80
|
+
app.include_router(mcp, prefix="/mcp")
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
That's it. Your FastAPI app now speaks MCP over Streamable HTTP.
|
|
84
|
+
|
|
85
|
+
## What You Get
|
|
86
|
+
|
|
87
|
+
- **Full MCP 2025-06-18 spec** — tools, resources, prompts, sampling, logging, completions, elicitation
|
|
88
|
+
- **Streamable HTTP** — JSON or SSE response based on `Accept` header
|
|
89
|
+
- **Streaming tools** — return `AsyncGenerator` for incremental results
|
|
90
|
+
- **Session management** — in-memory and Redis stores for stateful connections
|
|
91
|
+
- **Progress reporting** — inject `ProgressCallback` into tool signatures
|
|
92
|
+
- **Auth** — `auth_validator` callback + OAuth 2.1 PRM (RFC 9728)
|
|
93
|
+
- **OpenTelemetry** — opt-in spans and counters via `pip install fastapi-mcp-router[otel]`
|
|
94
|
+
- **Lambda-ready** — stateless mode works with Mangum, no adapter overhead
|
|
95
|
+
|
|
96
|
+
## Documentation
|
|
97
|
+
|
|
98
|
+
- [Quick Start](docs/quickstart.md) — installation, first tool, stateful mode, auth, Lambda
|
|
99
|
+
- [Guide](docs/guide.md) — resources, prompts, streaming, sessions, telemetry
|
|
100
|
+
- [API Reference](docs/reference.md) — all exports, types, and configuration options
|
|
101
|
+
|
|
102
|
+
## License
|
|
103
|
+
|
|
104
|
+
MIT
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# fastapi-mcp-router
|
|
2
|
+
|
|
3
|
+
Add MCP to your existing FastAPI app. Register tools, resources, and prompts with decorators. Use `Depends()`, `Request`, and `BackgroundTasks` the same way you already do.
|
|
4
|
+
|
|
5
|
+
## Why fastapi-mcp-router
|
|
6
|
+
|
|
7
|
+
- **It's just an `APIRouter`.** Mount it like any other router. No separate framework, no new server process.
|
|
8
|
+
- **Your DI still works.** `Depends()`, `Request`, `BackgroundTasks` — same patterns, same middleware.
|
|
9
|
+
- **2 dependencies.** FastAPI and Pydantic. Nothing else.
|
|
10
|
+
- **No lock-in.** Tools are regular async functions. Call them from tests, CLI scripts, or other endpoints without MCP.
|
|
11
|
+
- **Lambda-ready.** Stateless mode + Mangum. No adapter layer.
|
|
12
|
+
|
|
13
|
+
**Use FastMCP instead** if you need STDIO transport, OpenAPI spec imports, or managed hosting.
|
|
14
|
+
|
|
15
|
+
## Install
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
pip install fastapi-mcp-router
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Quick Start
|
|
22
|
+
|
|
23
|
+
```python
|
|
24
|
+
from fastapi import FastAPI
|
|
25
|
+
from fastapi_mcp_router import MCPRouter
|
|
26
|
+
|
|
27
|
+
app = FastAPI()
|
|
28
|
+
mcp = MCPRouter()
|
|
29
|
+
|
|
30
|
+
@mcp.tool()
|
|
31
|
+
async def write_message(payload: str) -> dict:
|
|
32
|
+
"""Write coordination message."""
|
|
33
|
+
return {"success": True, "message_id": "msg-123"}
|
|
34
|
+
|
|
35
|
+
@mcp.resource("project://{project_id}/config")
|
|
36
|
+
async def project_config(project_id: str) -> dict:
|
|
37
|
+
return {"project_id": project_id, "env": "production"}
|
|
38
|
+
|
|
39
|
+
@mcp.prompt()
|
|
40
|
+
async def review_code(file_path: str, language: str = "python") -> list[dict]:
|
|
41
|
+
return [{"role": "user", "content": f"Review {file_path} ({language})"}]
|
|
42
|
+
|
|
43
|
+
app.include_router(mcp, prefix="/mcp")
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
That's it. Your FastAPI app now speaks MCP over Streamable HTTP.
|
|
47
|
+
|
|
48
|
+
## What You Get
|
|
49
|
+
|
|
50
|
+
- **Full MCP 2025-06-18 spec** — tools, resources, prompts, sampling, logging, completions, elicitation
|
|
51
|
+
- **Streamable HTTP** — JSON or SSE response based on `Accept` header
|
|
52
|
+
- **Streaming tools** — return `AsyncGenerator` for incremental results
|
|
53
|
+
- **Session management** — in-memory and Redis stores for stateful connections
|
|
54
|
+
- **Progress reporting** — inject `ProgressCallback` into tool signatures
|
|
55
|
+
- **Auth** — `auth_validator` callback + OAuth 2.1 PRM (RFC 9728)
|
|
56
|
+
- **OpenTelemetry** — opt-in spans and counters via `pip install fastapi-mcp-router[otel]`
|
|
57
|
+
- **Lambda-ready** — stateless mode works with Mangum, no adapter overhead
|
|
58
|
+
|
|
59
|
+
## Documentation
|
|
60
|
+
|
|
61
|
+
- [Quick Start](docs/quickstart.md) — installation, first tool, stateful mode, auth, Lambda
|
|
62
|
+
- [Guide](docs/guide.md) — resources, prompts, streaming, sessions, telemetry
|
|
63
|
+
- [API Reference](docs/reference.md) — all exports, types, and configuration options
|
|
64
|
+
|
|
65
|
+
## License
|
|
66
|
+
|
|
67
|
+
MIT
|