fastapi-fastmcp 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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 manavmehta2403
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,412 @@
1
+ Metadata-Version: 2.4
2
+ Name: fastapi-fastmcp
3
+ Version: 0.1.0
4
+ Summary: The unified bridge between FastAPI and FastMCP / Model Context Protocol.
5
+ Author: Manav Mehta
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/manavmehta2403/fastapi-mcp
8
+ Project-URL: Repository, https://github.com/manavmehta2403/fastapi-mcp
9
+ Project-URL: Issues, https://github.com/manavmehta2403/fastapi-mcp/issues
10
+ Keywords: fastapi,mcp,fastmcp,model-context-protocol,ai,agents,llm,claude,cursor
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Topic :: Internet :: WWW/HTTP :: HTTP Servers
20
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
21
+ Requires-Python: >=3.10
22
+ Description-Content-Type: text/markdown
23
+ License-File: LICENSE
24
+ Requires-Dist: fastapi>=0.100.0
25
+ Requires-Dist: mcp>=1.0.0
26
+ Requires-Dist: httpx>=0.25.0
27
+ Requires-Dist: pydantic>=2.0.0
28
+ Requires-Dist: starlette>=0.27.0
29
+ Requires-Dist: uvicorn>=0.22.0
30
+ Provides-Extra: test
31
+ Requires-Dist: pytest>=8.0.0; extra == "test"
32
+ Requires-Dist: pytest-asyncio>=0.23.0; extra == "test"
33
+ Requires-Dist: pytest-cov>=4.0.0; extra == "test"
34
+ Requires-Dist: pylint>=3.0.0; extra == "test"
35
+ Dynamic: license-file
36
+
37
+ # FastAPI-MCP โšก๐Ÿค–
38
+
39
+ <p align="center">
40
+ <b>The unified bridge between FastAPI and FastMCP / Model Context Protocol.</b><br>
41
+ <i>Serve REST APIs and MCP AI Tools simultaneously from a single server with zero resource overhead.</i>
42
+ </p>
43
+
44
+ <p align="center">
45
+ <a href="#-key-highlights"><img src="https://img.shields.io/badge/FastAPI-009688?style=flat&logo=fastapi&logoColor=white" alt="FastAPI"></a>
46
+ <a href="#-key-highlights"><img src="https://img.shields.io/badge/MCP-Protocol-blueviolet?style=flat" alt="MCP"></a>
47
+ <a href="#-key-highlights"><img src="https://img.shields.io/badge/Python-3.10+-3776AB?style=flat&logo=python&logoColor=white" alt="Python"></a>
48
+ <a href="#license"><img src="https://img.shields.io/badge/License-MIT-green.svg" alt="License"></a>
49
+ </p>
50
+
51
+ ---
52
+
53
+ ## ๐ŸŒŸ Key Highlights
54
+
55
+ * ๐Ÿค **True Protocol Coexistence**: Serve your REST API (OpenAPI/Swagger docs), MCP Server-Sent Events (SSE), and Streamable HTTP endpoints from a **single Uvicorn process and single port**.
56
+ * ๐Ÿ› ๏ธ **Dual `@app.api_tool` Decorator**: Define an endpoint once โ€” it instantly becomes both an HTTP REST endpoint for web clients and an MCP tool for AI agents (Claude, Cursor, Antigravity).
57
+ * ๐Ÿ”„ **2-Line Existing App Conversion**: Point to any existing FastAPI application and automatically expose its endpoints as MCP tools with zero changes to your existing code.
58
+ * ๐Ÿ“– **Built-in MCP Swagger Explorer (`/mcp/docs`)**: An interactive visual playground for testing MCP tools right alongside FastAPI's `/docs`. Inspect parameters and execute tools live with "Try it out" in your browser.
59
+ * โšก **Zero-Network In-Memory Dispatch**: In-memory ASGI transport executes tool calls directly without TCP socket loopbacks, preserving FastAPI `Depends()` injections, auth, and Pydantic validation.
60
+
61
+ ---
62
+
63
+ ## ๐Ÿ’ก Why a Single Server Architecture? (Resource & Performance Benefits)
64
+
65
+ Running separate microservices or independent processes for REST and MCP introduces unnecessary infrastructure complexity and resource waste:
66
+
67
+ ### 1. Zero Process Multiplication & Low Memory Footprint
68
+ A typical Python web server process uses 60โ€“150 MB of RAM at boot. Running a separate server process for MCP doubles baseline memory consumption and CPU thread contention. With `fastapi-mcp`, everything runs in a **single shared event loop**, conserving memory on budget VMs and cloud containers.
69
+
70
+ ### 2. Zero-Network In-Memory Execution
71
+ When an AI agent triggers an MCP tool that maps to a FastAPI route, `fastapi-mcp` dispatches the request through an **in-memory ASGI pipeline (`httpx.ASGITransport`)**:
72
+ - No TCP socket handshakes
73
+ - No loopback network latency
74
+ - Sub-millisecond execution speeds
75
+
76
+ ### 3. Shared Database Pools & Dependencies
77
+ Instead of maintaining two independent database connection pools (one for your REST API and one for your MCP server), your MCP tools directly reuse the existing FastAPI `Depends(get_db)` connection pool and caching layers.
78
+
79
+ ### 4. Single Source of Truth for Schemas
80
+ You define your Pydantic v2 data models once. Both your OpenAPI specification (`/docs`) and your MCP tool definitions (`/mcp/docs`) are generated from the exact same model definitions without drift.
81
+
82
+ ---
83
+
84
+ ## ๐Ÿ—๏ธ Architecture Overview
85
+
86
+ ```
87
+ +-----------------------+
88
+ | AI Agent / Client |
89
+ | (Claude Desktop, Cursor|
90
+ +-----------+-----------+
91
+ |
92
+ +------------------------+-----------------------+
93
+ | (HTTP / SSE) | (stdio)
94
+ v v
95
+ +--------------------+---------------------+ +-----------------+---------------------+
96
+ | FastAPI ASGI Server (Uvicorn) | | fastapi-mcp CLI (stdio) |
97
+ | - Swagger UI: /docs | | (Direct pipe for desktop LLM agents) |
98
+ | - REST Endpoints: /items, /users | +-----------------+---------------------+
99
+ | - MCP Streamable: /mcp | |
100
+ | - MCP SSE Stream: /sse | |
101
+ | - MCP Swagger Explorer: /mcp/docs | |
102
+ +--------------------+---------------------+ |
103
+ | |
104
+ +------------------------+-----------------------+
105
+ |
106
+ v
107
+ +---------------+---------------+
108
+ | FastAPIMCP Unified Hub |
109
+ +---------------+---------------+
110
+ |
111
+ +-------------------------+-------------------------+
112
+ | |
113
+ v v
114
+ +-------------------+--------------------+ +-----------------+-------------------+
115
+ | Route Scanner & Dynamic Tools | | Native MCP Tools |
116
+ | - Inspects Path, Query, Body, Headers | | - @app.tool() |
117
+ | - Filters out Depends(db), Request | | - @app.resource() |
118
+ | - Preserves Pydantic Schema & Docstrings| | - @app.prompt() |
119
+ +-------------------+--------------------+ +-----------------+-------------------+
120
+ | |
121
+ v v
122
+ +-------------------+---------------------------------------------------+-------------------+
123
+ | In-Memory ASGITransport Dispatcher |
124
+ | Resolves Depends() -> Validates Schema -> Invokes Route -> Returns Structured Result |
125
+ +-------------------------------------------------------------------------------------------+
126
+ ```
127
+
128
+ ---
129
+
130
+ ## ๐Ÿ“ฆ Installation
131
+
132
+ ```bash
133
+ pip install fastapi-fastmcp
134
+ ```
135
+
136
+ *(Works with the latest releases of `fastapi`, `mcp`, `pydantic`, `httpx`, and `uvicorn`)*
137
+
138
+ ---
139
+
140
+ ## ๐Ÿš€ Quickstart Guides
141
+
142
+ ### Pattern 1: Convert an Existing FastAPI App (2 Lines)
143
+
144
+ Take any existing FastAPI application with routes, database sessions, and dependencies, and expose it to AI agents:
145
+
146
+ ```python
147
+ from fastapi import FastAPI, Depends, Query, Path
148
+ from pydantic import BaseModel, Field
149
+ from fastapi_mcp import FastAPIMCP
150
+
151
+ app = FastAPI(title="Store API")
152
+
153
+ class Item(BaseModel):
154
+ name: str = Field(..., description="Product title")
155
+ price: float = Field(..., description="Product price")
156
+
157
+ def get_db():
158
+ return {"status": "connected"}
159
+
160
+ @app.get("/items/{item_id}", summary="Get item details")
161
+ async def get_item(
162
+ item_id: int = Path(..., description="Unique product ID"),
163
+ verbose: bool = Query(False, description="Include detailed specs"),
164
+ db: dict = Depends(get_db) # Auto-resolved in-memory, hidden from LLM schema!
165
+ ):
166
+ """Retrieve item details by ID."""
167
+ return {"id": item_id, "verbose": verbose, "db": db["status"]}
168
+
169
+ @app.post("/items", summary="Create item")
170
+ async def create_item(item: Item, db: dict = Depends(get_db)):
171
+ """Create a new item in the catalog."""
172
+ return {"status": "created", "item": item.model_dump()}
173
+
174
+ # -------------------------------------------------------------
175
+ # ๐ŸŒŸ CONVERT & MOUNT IN 2 LINES:
176
+ # -------------------------------------------------------------
177
+ mcp = FastAPIMCP.bind(app, name="StoreMCP")
178
+ mcp.mount_to(app, path="/mcp", sse_path="/sse")
179
+ ```
180
+
181
+ ---
182
+
183
+ ### Pattern 2: Hybrid Dual API (`@app.api_tool`)
184
+
185
+ Build new services where functions are simultaneously REST endpoints and MCP tools:
186
+
187
+ ```python
188
+ from fastapi_mcp import FastAPIMCP
189
+ from pydantic import BaseModel, Field
190
+
191
+ # FastAPIMCP is a drop-in replacement for FastAPI
192
+ app = FastAPIMCP(title="Hybrid Service", mcp_name="UnifiedServer")
193
+
194
+ class CalculateRequest(BaseModel):
195
+ x: float = Field(..., description="First operand")
196
+ y: float = Field(..., description="Second operand")
197
+ op: str = Field("add", description="Operation: 'add', 'sub', 'mul', 'div'")
198
+
199
+ # 1. ๐Ÿ› ๏ธ DUAL ENDPOINT: Accessible via REST POST /math/calc AND as MCP Tool 'calculate'
200
+ @app.api_tool("/math/calc", methods=["POST"], tool_name="calculate")
201
+ async def calculate(data: CalculateRequest) -> dict:
202
+ """Perform mathematical calculations."""
203
+ if data.op == "add":
204
+ res = data.x + data.y
205
+ elif data.op == "mul":
206
+ res = data.x * data.y
207
+ else:
208
+ res = data.x - data.y
209
+ return {"result": res, "op": data.op}
210
+
211
+ # 2. ๐Ÿงฉ PURE MCP TOOL: Agent-only tool (hidden from public REST routes)
212
+ @app.tool(name="internal_rag_search")
213
+ async def internal_search(query: str) -> list[str]:
214
+ """Search internal documentation."""
215
+ return [f"Article match for '{query}'"]
216
+
217
+ # 3. ๐ŸŒ PURE REST ROUTE: Standard FastAPI route
218
+ @app.get("/health")
219
+ async def health():
220
+ return {"status": "ok"}
221
+
222
+ # Mount MCP endpoints onto the server
223
+ app.mount_mcp(path="/mcp", sse_path="/sse")
224
+ ```
225
+
226
+ ---
227
+
228
+ ## ๐ŸŒ Deployment Options
229
+
230
+ ### Option A: Single Port Deployment (Default & Recommended)
231
+ Serve both your REST API and MCP transports from the same port:
232
+
233
+ ```bash
234
+ uvicorn main:app --host 0.0.0.0 --port 8000
235
+ ```
236
+
237
+ Available endpoints on port 8000:
238
+ * **FastAPI Swagger UI**: `http://localhost:8000/docs`
239
+ * **MCP Swagger Explorer**: `http://localhost:8000/mcp/docs`
240
+ * **MCP Streamable HTTP**: `http://localhost:8000/mcp`
241
+ * **MCP Server-Sent Events (SSE)**: `http://localhost:8000/sse`
242
+
243
+ ---
244
+
245
+ ### Option B: Split Port Deployment (Network Segmentation)
246
+ If your infrastructure requires keeping internal AI traffic on an isolated private port while serving public REST traffic externally:
247
+
248
+ ```python
249
+ import uvicorn
250
+ import threading
251
+
252
+ # Serve REST on public port 8000, and MCP on internal port 9000
253
+ def run_rest():
254
+ uvicorn.run(app, host="0.0.0.0", port=8000)
255
+
256
+ def run_mcp():
257
+ # Run standalone MCP SSE or streamable app on isolated port
258
+ mcp_app = mcp.mcp_server.streamable_http_app()
259
+ uvicorn.run(mcp_app, host="127.0.0.1", port=9000)
260
+
261
+ if __name__ == "__main__":
262
+ threading.Thread(target=run_mcp, daemon=True).start()
263
+ run_rest()
264
+ ```
265
+
266
+ ---
267
+
268
+ ## ๐Ÿ“– Interactive MCP Swagger Explorer (`/mcp/docs`)
269
+
270
+ FastAPI-MCP includes a visual explorer for your MCP tools, served right at `/mcp/docs`.
271
+
272
+ Features:
273
+ - **Interactive Tool Catalog**: Inspect all tools, schemas, and parameter requirements.
274
+ - **Live "Try It Out"**: Input fields for numbers, strings, booleans, and JSON objects.
275
+ - **Instant Live Execution**: Trigger tool calls directly in the browser and see structured responses in real time.
276
+
277
+ ---
278
+
279
+ ## ๐Ÿ’ป Claude Desktop & Cursor Integration
280
+
281
+ Run your FastAPI application directly over `stdio` without needing an active HTTP server:
282
+
283
+ Add this to your `claude_desktop_config.json`:
284
+
285
+ ```json
286
+ {
287
+ "mcpServers": {
288
+ "my-fastapi-app": {
289
+ "command": "python",
290
+ "args": ["-m", "fastapi_mcp.cli", "run", "main:app", "--transport", "stdio"]
291
+ }
292
+ }
293
+ }
294
+ ```
295
+
296
+ ---
297
+
298
+ ## ๐Ÿ›ก๏ธ Enterprise Hardening: Solving Production Bottlenecks
299
+
300
+ In large enterprise microservices with dozens or hundreds of routes, simply dumping every endpoint as an individual MCP tool creates serious production hurdles. `fastapi-mcp` ships with built-in primitives to solve them:
301
+
302
+ ### 1. Librarian Discovery Pattern (Preventing Context Window Bloat)
303
+ Exposing 80+ tools dumps 15,000โ€“25,000 tokens into the LLM system prompt on every single turn, degrading reasoning and exploding API bills.
304
+
305
+ Activate **Librarian Mode** to condense all catalog tools into **3 lightweight meta-tools**:
306
+ ```python
307
+ mcp = FastAPIMCP.bind(app, librarian=True)
308
+ ```
309
+ The LLM now only sees:
310
+ * `list_api_categories()`: Browse high-level domains (e.g. `billing`, `inventory`, `users`) with tool summaries.
311
+ * `search_api_tools(query, category)`: Fetch detailed schemas for matching tools on demand.
312
+ * `execute_api_tool(tool_name, arguments)`: Dynamically invoke the requested underlying endpoint.
313
+
314
+ ### 2. Dry-Run Simulation Mode (`enable_dry_run=True`)
315
+ Allow AI agents to validate parameters and simulate state mutations (`POST`, `PUT`, `DELETE`, `PATCH`) safely:
316
+ ```python
317
+ mcp = FastAPIMCP.bind(app, enable_dry_run=True)
318
+ ```
319
+ * Injects a `dry_run: bool = False` argument into mutation tools.
320
+ * Dispatches in-memory with `X-Dry-Run: true` header and `?dry_run=true` query parameter.
321
+ * Wraps responses with `{"dry_run": True, "simulated": True, "result": ...}` so agents can test changes before committing them.
322
+
323
+ ### 3. Dynamic Session Context Provider (Multi-Tenant Stdio & SSE Auth)
324
+ Desktop agents connecting via `stdio` (like Claude Desktop or Cursor) do not send standard HTTP `Authorization: Bearer <token>` headers. Without caller context, endpoints with `Depends(get_current_user)` fail with 401 Unauthorized.
325
+
326
+ Inject authentication claims dynamically per session:
327
+ ```python
328
+ def resolve_tenant_context(tool_args: dict) -> dict:
329
+ # Resolve active tenant / user from session or environment
330
+ return {"Authorization": "Bearer session-token-xyz", "X-Tenant-ID": "acme-corp"}
331
+
332
+ mcp = FastAPIMCP.bind(
333
+ app,
334
+ session_context_provider=resolve_tenant_context,
335
+ )
336
+
337
+ # Or update dynamically during runtime
338
+ mcp.set_session_context_provider(lambda kwargs: {"Authorization": "Bearer rotated-token"})
339
+ ```
340
+
341
+ ---
342
+
343
+ ## ๐Ÿ› ๏ธ CLI Utilities
344
+
345
+ ### 1. Inspect Tools and Schemas
346
+ Inspect which tools and schemas are generated from your FastAPI application:
347
+ ```bash
348
+ fastapi-mcp inspect main:app
349
+ ```
350
+
351
+ Output:
352
+ ```text
353
+ === FastAPI-MCP Server: UnifiedServer ===
354
+ Found 2 tools:
355
+
356
+ * Tool: calculate
357
+ Description: [POST /math/calc] Perform mathematical calculations.
358
+ Arguments (1):
359
+ - data: CalculateRequest (required) - Calculation input data
360
+
361
+ * Tool: internal_rag_search
362
+ Description: Search internal documentation.
363
+ Arguments (1):
364
+ - query: string (required)
365
+ ```
366
+
367
+ Export schema as JSON:
368
+ ```bash
369
+ fastapi-mcp inspect main:app --json
370
+ ```
371
+
372
+ ### 2. Run Directly from CLI
373
+ ```bash
374
+ fastapi-mcp run main:app --transport stdio
375
+ fastapi-mcp run main:app --transport sse
376
+ ```
377
+
378
+ ---
379
+
380
+ ## โš™๏ธ Route Filtering & Custom Headers
381
+
382
+ ```python
383
+ mcp = FastAPIMCP.bind(
384
+ app,
385
+ # Exclude internal routes
386
+ exclude_paths=["/admin/*", "/metrics"],
387
+ # Only expose routes with specific OpenAPI tags
388
+ include_tags={"mcp", "public"},
389
+ # Filter methods
390
+ include_methods={"GET", "POST"},
391
+ # Static auth headers for protected routes
392
+ default_headers={"Authorization": "Bearer internal-service-token"},
393
+ # Or dynamic headers callback
394
+ headers_factory=lambda: {"X-Request-Source": "mcp-agent"}
395
+ )
396
+ ```
397
+
398
+ ---
399
+
400
+ ## ๐Ÿงช Running Tests
401
+
402
+ The test suite covers route auto-scanning, in-memory ASGI dispatch, dual-mode decorators, single-port co-hosting, and the MCP Swagger UI:
403
+
404
+ ```bash
405
+ pytest tests/ -v
406
+ ```
407
+
408
+ ---
409
+
410
+ ## ๐Ÿ“„ License
411
+
412
+ MIT License. See [LICENSE](LICENSE) for details.