agent-mcp-gateway 0.1.0__py3-none-any.whl

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.

Potentially problematic release.


This version of agent-mcp-gateway might be problematic. Click here for more details.

@@ -0,0 +1,1229 @@
1
+ Metadata-Version: 2.4
2
+ Name: agent-mcp-gateway
3
+ Version: 0.1.0
4
+ Summary: An MCP gateway that aggregates your existing MCP servers and lets you define which servers and individual tools each agent or subagent can access. Solves Claude Code's MCP context window waste where all tool definitions load upfront instead of being discovered when actually needed.
5
+ Project-URL: Homepage, https://github.com/roddutra/agent-mcp-gateway
6
+ Project-URL: Documentation, https://github.com/roddutra/agent-mcp-gateway#readme
7
+ Project-URL: Repository, https://github.com/roddutra/agent-mcp-gateway
8
+ Project-URL: Issues, https://github.com/roddutra/agent-mcp-gateway/issues
9
+ Author: Rodrigo Franken Dutra
10
+ License: MIT
11
+ License-File: LICENSE
12
+ Keywords: agent,fastmcp,gateway,mcp,model-context-protocol,proxy
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
19
+ Requires-Python: >=3.12
20
+ Requires-Dist: fastmcp<3.0,>=2.13.0.1
21
+ Requires-Dist: watchdog<7.0,>=6.0.0
22
+ Description-Content-Type: text/markdown
23
+
24
+ # Agent MCP Gateway
25
+
26
+ A [Model Context Protocol (MCP)](https://modelcontextprotocol.io) gateway that aggregates multiple MCP servers and provides policy-based access control for agents and subagents. Solves Claude Code's MCP context window waste by enabling on-demand tool discovery instead of loading all tool definitions upfront.
27
+
28
+ ## Status
29
+
30
+ - ✅ **M0: Foundation** - Configuration, policy engine, audit logging, `list_servers` tool
31
+ - ✅ **M1: Core** - Proxy infrastructure, `get_server_tools`, `execute_tool`, middleware, metrics, hot reload, OAuth support
32
+ - 🚧 **M2: Production** - HTTP transport, health checks (planned)
33
+ - 🚧 **M3: DX** - Single-agent mode, config validation CLI, Docker (planned)
34
+
35
+ **Current Version:** M1-Core Complete (with OAuth)
36
+
37
+ ## Table of Contents
38
+
39
+ - [Overview](#overview)
40
+ - [Quick Start](#quick-start)
41
+ - [Configuration](#configuration)
42
+ - [Usage](#usage)
43
+ - [Gateway Tools](#gateway-tools)
44
+ - [Security Considerations](#security-considerations)
45
+ - [Troubleshooting](#troubleshooting)
46
+ - [Testing](#testing)
47
+ - [Development](#development)
48
+ - [Architecture](#architecture)
49
+ - [Future Features](#future-features)
50
+ - [Documentation](#documentation)
51
+ - [Contributing](#contributing)
52
+ - [License](#license)
53
+ - [Support](#support)
54
+ - [Acknowledgments](#acknowledgments)
55
+
56
+ ## Overview
57
+
58
+ ### The Problem
59
+
60
+ When multiple MCP servers are configured in development environments (Claude Code, Cursor, VS Code), all tool definitions from all servers load into every agent's and subagent's context window at startup:
61
+
62
+ - 5,000-50,000+ tokens consumed upfront
63
+ - 80-95% of loaded tools never used by individual agents
64
+ - Context needed for actual work gets wasted on unused tool definitions
65
+
66
+ ### The Solution
67
+
68
+ The Agent MCP Gateway acts as a single MCP server that proxies to multiple downstream MCP servers based on configurable per-agent rules:
69
+
70
+ - **3 gateway tools** load at startup (~400 tokens)
71
+ - Agents discover and request specific tools on-demand
72
+ - **90%+ context reduction**
73
+ - Policy-based access control per agent/subagent
74
+
75
+ ### How It Works
76
+
77
+ ![Agent MCP Gateway Architecture](docs/diagram-snippet.png)
78
+
79
+ The gateway sits between agents and downstream MCP servers, exposing only 3 lightweight tools. When an agent needs specific functionality, it discovers available servers and tools through the gateway, which filters visibility based on policy rules - agents only see servers and tools they have access to. This reduces each agent's context window to only relevant tools, while the gateway handles proxying authorized requests to downstream servers.
80
+
81
+ **[View detailed diagram with examples →](docs/diagram-full.png)** (includes downstream servers, tools, and gateway rules examples)
82
+
83
+ ### Key Features
84
+
85
+ - ✅ **On-Demand Tool Discovery** - Load tool definitions only when needed
86
+ - ✅ **Per-Agent Access Control** - Configure which servers/tools each agent can access
87
+ - ✅ **Easy Agent Integration** - Simple template to add gateway support to any agent ([see guide](#configuring-agents-to-use-the-gateway))
88
+ - ✅ **Deny-Before-Allow Policies** - Explicit deny rules take precedence
89
+ - ✅ **Wildcard Support** - Pattern matching for tool names (`get_*`, `*_user`)
90
+ - ✅ **Session Isolation** - Concurrent requests don't interfere
91
+ - ✅ **Transparent Proxying** - Downstream servers unaware of gateway
92
+ - ✅ **Audit Logging** - All operations logged for monitoring
93
+ - ✅ **Performance Metrics** - Track latency and error rates per agent/operation
94
+ - ✅ **Hot Configuration Reload** - Update rules/servers without restart
95
+ - ✅ **Thread-Safe Operations** - Safe concurrent access during reloads
96
+ - ✅ **Diagnostic Tools** - Health monitoring via `get_gateway_status` (debug mode only)
97
+
98
+ ## Quick Start
99
+
100
+ ### Prerequisites
101
+
102
+ - Python 3.12+
103
+ - [uv](https://docs.astral.sh/uv/) (Python package manager)
104
+
105
+ ### 1. Install Dependencies
106
+
107
+ ```bash
108
+ # Clone the repository
109
+ git clone <repository-url>
110
+ cd agent-mcp-gateway
111
+
112
+ # Install dependencies with uv
113
+ uv sync
114
+ ```
115
+
116
+ This installs:
117
+ - `fastmcp >= 2.13.0.1` - MCP server framework
118
+ - `pytest`, `pytest-cov`, `pytest-asyncio` - Testing tools (dev)
119
+
120
+ ### 2. Set Up Configuration Files
121
+
122
+ ```bash
123
+ cp config/.mcp.json.example .mcp.json
124
+ cp config/.mcp-gateway-rules.json.example .mcp-gateway-rules.json
125
+
126
+ # Edit configs with your servers and rules...
127
+ # Note: .mcp.json is the standard MCP config format used by Claude Code
128
+ ```
129
+
130
+ ### 3. Add Gateway to Your MCP Client
131
+
132
+ **Claude Code CLI:**
133
+ ```bash
134
+ claude mcp add agent-mcp-gateway \
135
+ uv run --directory /path/to/agent-mcp-gateway python main.py
136
+ ```
137
+
138
+ **Manual MCP Client Configuration** (Claude Desktop, etc.):
139
+ ```json
140
+ {
141
+ "mcpServers": {
142
+ "agent-mcp-gateway": {
143
+ "command": "uv",
144
+ "args": ["run", "--directory", "/path/to/agent-mcp-gateway", "python", "main.py"],
145
+ "env": {
146
+ "GATEWAY_DEFAULT_AGENT": "developer"
147
+ }
148
+ }
149
+ }
150
+ }
151
+ ```
152
+
153
+ Replace `/path/to/agent-mcp-gateway` with the actual path to your gateway installation.
154
+
155
+ **Note:** The `--directory` flag tells `uv run` to change to the project directory before running, ensuring it finds `pyproject.toml` and the gateway configuration files.
156
+
157
+ **Verify Gateway Connection:**
158
+
159
+ After adding the gateway to your MCP client, verify it's working:
160
+
161
+ ```bash
162
+ # Using MCP Inspector (for testing)
163
+ npx @modelcontextprotocol/inspector uv run python main.py
164
+ # Then call list_servers with agent_id parameter
165
+
166
+ # Or ask your agent to list available servers
167
+ # Expected response: List of servers from your .mcp.json
168
+ ```
169
+
170
+ Expected startup output:
171
+ ```
172
+ Loading MCP server configuration from: .mcp.json
173
+ Loading gateway rules from: .mcp-gateway-rules.json
174
+ Gateway initialized successfully
175
+ - X MCP server(s) configured
176
+ - Y agent(s) configured
177
+ - 3 gateway tools available
178
+ ```
179
+
180
+ ### 4. Development Usage (Optional)
181
+
182
+ For local development and testing:
183
+
184
+ ```bash
185
+ # Run gateway directly
186
+ uv run python main.py
187
+
188
+ # Test with MCP Inspector
189
+ npx @modelcontextprotocol/inspector uv run python main.py
190
+ ```
191
+
192
+ ### 5. Configure Your Agents
193
+
194
+ The gateway's tool descriptions are self-documenting, but for proper access control you should configure how your agents identify themselves.
195
+
196
+ #### Choose Your Approach
197
+
198
+ **Approach 1: Single-Agent Mode (Simplest)**
199
+
200
+ If all your agents should have the same permissions, configure a default agent using either method:
201
+
202
+ **Option A: Environment Variable**
203
+ ```bash
204
+ # Set in your MCP client configuration
205
+ export GATEWAY_DEFAULT_AGENT=developer
206
+ ```
207
+ **Note:** The agent specified (e.g., "developer") must exist in your `.mcp-gateway-rules.json` file with appropriate permissions.
208
+
209
+ **Option B: "default" Agent in Rules**
210
+ ```json
211
+ {
212
+ "agents": {
213
+ "default": {
214
+ "allow": {
215
+ "servers": ["*"]
216
+ }
217
+ }
218
+ },
219
+ "defaults": {
220
+ "deny_on_missing_agent": false
221
+ }
222
+ }
223
+ ```
224
+ **Note:** Allowing all servers (`"servers": ["*"]`) without specifying tool restrictions grants access to all tools on all servers.
225
+
226
+ With either approach, agents can omit `agent_id` in tool calls - the gateway uses your configured default agent automatically.
227
+
228
+ **Approach 2: Multi-Agent Mode (Recommended for Access Control)**
229
+
230
+ For different agents with different permissions, configure each agent to pass its identity.
231
+
232
+ **Add this to your agent's system prompt** (e.g., `CLAUDE.md`, `.claude/agents/agent-name.md`):
233
+
234
+ ```markdown
235
+ ## MCP Gateway Access
236
+
237
+ **Available Tools (via agent-mcp-gateway):**
238
+
239
+ You have access to MCP servers through the agent-mcp-gateway. The specific servers and tools available to you are determined by the gateway's access control rules.
240
+
241
+ **Tool Discovery Process:**
242
+
243
+ When you need to use tools from downstream MCP servers:
244
+ 1. Use `agent_id: "YOUR_AGENT_NAME"` in ALL gateway tool calls for proper access control
245
+ 2. Call `list_servers` to discover which servers you have access to
246
+ 3. Call `get_server_tools` with the specific server name to discover available tools
247
+ 4. Use `execute_tool` to invoke tools with appropriate parameters
248
+ 5. If you cannot access a tool you need, immediately notify the user
249
+
250
+ **Important:** Always include `agent_id: "YOUR_AGENT_NAME"` in your gateway tool calls. This ensures proper access control and audit logging.
251
+ ```
252
+
253
+ Replace `YOUR_AGENT_NAME` with your agent's identifier (e.g., "researcher", "backend", "admin").
254
+
255
+ **Examples:** See [`.claude/agents/researcher.md`](.claude/agents/researcher.md) and [`.claude/agents/mcp-developer.md`](.claude/agents/mcp-developer.md) for complete configuration examples.
256
+
257
+ ## Configuration
258
+
259
+ The gateway requires two configuration files:
260
+
261
+ ### 1. MCP Servers Configuration
262
+
263
+ **File:** `.mcp.json` (or `config/.mcp.json`)
264
+
265
+ Defines the downstream MCP servers the gateway will proxy to. Uses the standard `.mcp.json` format compatible with Claude Code and other coding agents:
266
+
267
+ ```json
268
+ {
269
+ "mcpServers": {
270
+ "brave-search": {
271
+ "description": "Web search via Brave Search API",
272
+ "command": "npx",
273
+ "args": ["-y", "@modelcontextprotocol/server-brave-search"],
274
+ "env": {
275
+ "BRAVE_API_KEY": "${BRAVE_API_KEY}"
276
+ }
277
+ },
278
+ "postgres": {
279
+ "description": "PostgreSQL database access and query execution",
280
+ "command": "uvx",
281
+ "args": ["mcp-server-postgres"],
282
+ "env": {
283
+ "DATABASE_URL": "${DATABASE_URL}"
284
+ }
285
+ },
286
+ "remote-server": {
287
+ "description": "Custom remote API integration",
288
+ "url": "https://example.com/mcp",
289
+ "transport": "http",
290
+ "headers": {
291
+ "Authorization": "Bearer ${API_TOKEN}"
292
+ }
293
+ }
294
+ }
295
+ }
296
+ ```
297
+
298
+ **Server Descriptions (Recommended):**
299
+ Adding a `description` field to each server helps AI agents understand what each server provides and when to use it. Descriptions are always returned by `list_servers`, enabling agents to make informed decisions about which servers to query for tools. While optional, descriptions significantly improve agent tool discovery and decision-making.
300
+
301
+ **Supported Transports:**
302
+ - `stdio` - Local servers via npx/uvx (specified with `command` + `args`)
303
+ - `http` - Remote HTTP servers (specified with `url`)
304
+
305
+ **Environment Variables:**
306
+ - Use `${VAR_NAME}` syntax for environment variable substitution
307
+ - Set variables before running: `export BRAVE_API_KEY=your-key`
308
+
309
+ **Important - GUI Applications (Claude Desktop, etc.):**
310
+ If you use `${VAR_NAME}` syntax in `.mcp.json`, note that macOS GUI applications run in isolated environments without access to your shell's environment variables. For Claude Desktop and similar apps, add API keys to the gateway's `env` object in your MCP client configuration:
311
+
312
+ ```json
313
+ {
314
+ "mcpServers": {
315
+ "agent-mcp-gateway": {
316
+ "command": "uv",
317
+ "args": ["run", "--directory", "/path/to/agent-mcp-gateway", "python", "main.py"],
318
+ "env": {
319
+ "BRAVE_API_KEY": "your-actual-key-here",
320
+ "DATABASE_URL": "postgresql://...",
321
+ "GATEWAY_DEFAULT_AGENT": "claude-desktop"
322
+ }
323
+ }
324
+ }
325
+ }
326
+ ```
327
+
328
+ (If you hardcode values directly in `.mcp.json` without `${VAR_NAME}` syntax, this is not necessary.)
329
+
330
+ ### 2. Gateway Rules Configuration
331
+
332
+ **File:** `.mcp-gateway-rules.json` (or `config/.mcp-gateway-rules.json`)
333
+
334
+ Defines per-agent access policies using deny-before-allow precedence:
335
+
336
+ ```json
337
+ {
338
+ "agents": {
339
+ "researcher": {
340
+ "allow": {
341
+ "servers": ["brave-search"],
342
+ "tools": {
343
+ "brave-search": ["*"]
344
+ }
345
+ }
346
+ },
347
+ "backend": {
348
+ "allow": {
349
+ "servers": ["postgres"],
350
+ "tools": {
351
+ "postgres": ["query", "list_*"]
352
+ }
353
+ },
354
+ "deny": {
355
+ "tools": {
356
+ "postgres": ["drop_*", "truncate_*"]
357
+ }
358
+ }
359
+ },
360
+ "admin": {
361
+ "allow": {
362
+ "servers": ["*"],
363
+ "tools": {
364
+ "*": ["*"]
365
+ }
366
+ }
367
+ },
368
+ "default": {
369
+ "deny": {
370
+ "servers": ["*"]
371
+ }
372
+ }
373
+ },
374
+ "defaults": {
375
+ "deny_on_missing_agent": false
376
+ }
377
+ }
378
+ ```
379
+
380
+ **Note on "default" Agent:** The special agent named "default" is used as a fallback when `agent_id` is not provided and `deny_on_missing_agent` is `false`. In this example, the default agent denies all servers, following the principle of least privilege. You can also use `GATEWAY_DEFAULT_AGENT` environment variable to specify a different default agent.
381
+
382
+ **Policy Precedence Order:**
383
+ 1. Explicit deny rules (highest priority)
384
+ 2. Explicit allow rules
385
+ 3. Wildcard deny rules
386
+ 4. Wildcard allow rules
387
+ 5. Default policy (lowest priority)
388
+
389
+ **Configuration Flexibility:**
390
+ - Rules can reference servers not currently in `.mcp.json`
391
+ - Undefined server references treated as warnings (not errors)
392
+ - Allows keeping rules for temporarily removed servers
393
+ - Hot reload applies changes immediately without restart
394
+
395
+ **Wildcard Patterns:**
396
+ - `*` - Matches everything
397
+ - `get_*` - Matches tools starting with "get_"
398
+ - `*_user` - Matches tools ending with "_user"
399
+
400
+ **Agent Naming:**
401
+ - Use hierarchical names: `team.role` (e.g., `backend.database`, `frontend.ui`)
402
+ - Alphanumeric characters, hyphens, underscores, and dots allowed
403
+ - **Configure your agents** to pass their identity: See [Configuring Agents to Use the Gateway](#configuring-agents-to-use-the-gateway)
404
+
405
+ ### Configuration Validation
406
+
407
+ The gateway validates configurations at startup and during hot reload:
408
+
409
+ ```bash
410
+ uv run python main.py
411
+ # ✓ Configuration loaded from .mcp.json
412
+ # ⚠ Warning: Agent 'researcher' references undefined server 'unknown-server'
413
+ # ℹ These rules will be ignored until the server is added
414
+ ```
415
+
416
+ **Validation Behavior:**
417
+ - Structural errors (invalid JSON, missing required fields) → Fail startup/reload
418
+ - Undefined server references → Log warnings, continue with valid rules
419
+ - Policy conflicts → Deny-before-allow precedence resolves automatically
420
+
421
+ ### 3. OAuth Support for Downstream Servers
422
+
423
+ OAuth-protected downstream servers (Notion, GitHub) are automatically supported via auto-detection when servers return HTTP 401. The gateway uses FastMCP's OAuth support to handle authentication flows transparently - browser opens once for initial authentication, then tokens are cached for future use. See [OAuth User Guide](docs/oauth-user-guide.md) for detailed setup and troubleshooting.
424
+
425
+ ### 4. Environment Variables Reference
426
+
427
+ | Variable | Description | Default | Example |
428
+ |----------|-------------|---------|---------|
429
+ | `GATEWAY_MCP_CONFIG` | Path to MCP servers configuration file | `.mcp.json`, fallback: `./config/.mcp.json` | `export GATEWAY_MCP_CONFIG=./custom.json` |
430
+ | `GATEWAY_RULES` | Path to gateway rules configuration file | `.mcp-gateway-rules.json`, fallback: `./config/.mcp-gateway-rules.json` | `export GATEWAY_RULES=~/.claude/rules.json` |
431
+ | `GATEWAY_DEFAULT_AGENT` | Default agent identity when `agent_id` not provided (optional) | None | `export GATEWAY_DEFAULT_AGENT=developer` |
432
+ | `GATEWAY_DEBUG` | Enable debug mode to expose `get_gateway_status` tool | `false` | `export GATEWAY_DEBUG=true` |
433
+ | `GATEWAY_AUDIT_LOG` | Path to audit log file | `./logs/audit.jsonl` | `export GATEWAY_AUDIT_LOG=./audit.jsonl` |
434
+ | `GATEWAY_TRANSPORT` | Transport protocol (stdio or http) | `stdio` | `export GATEWAY_TRANSPORT=stdio` |
435
+ | `GATEWAY_INIT_STRATEGY` | Initialization strategy (eager or lazy) | `eager` | `export GATEWAY_INIT_STRATEGY=eager` |
436
+
437
+ **Note on GUI Applications:** macOS GUI applications (Claude Desktop, etc.) run in isolated environments without access to shell environment variables. If using `${VAR_NAME}` syntax in `.mcp.json`, add required API keys to the gateway's `env` object in your MCP client configuration.
438
+
439
+ ## Usage
440
+
441
+ ### Starting the Gateway
442
+
443
+ **In MCP Clients (Recommended):**
444
+
445
+ Add to your MCP client configuration (e.g., Claude Desktop config):
446
+ ```json
447
+ {
448
+ "mcpServers": {
449
+ "agent-mcp-gateway": {
450
+ "command": "uv",
451
+ "args": ["run", "--directory", "/path/to/agent-mcp-gateway", "python", "main.py"],
452
+ "env": {
453
+ "GATEWAY_MCP_CONFIG": ".mcp.json",
454
+ "GATEWAY_RULES": ".mcp-gateway-rules.json"
455
+ }
456
+ }
457
+ }
458
+ }
459
+ ```
460
+
461
+ Or use Claude Code CLI:
462
+ ```bash
463
+ claude mcp add agent-mcp-gateway \
464
+ uv run --directory /path/to/agent-mcp-gateway python main.py
465
+ ```
466
+
467
+ **For Development/Testing:**
468
+
469
+ ```bash
470
+ # Use default config paths
471
+ uv run python main.py
472
+
473
+ # Or specify custom paths via environment (see Configuration section for all variables)
474
+ export GATEWAY_MCP_CONFIG=./custom-mcp-config.json
475
+ export GATEWAY_RULES=./custom-gateway-rules.json
476
+ uv run python main.py
477
+ ```
478
+
479
+ ### Startup Output
480
+
481
+ ```
482
+ Loading MCP server configuration from: .mcp.json
483
+ Loading gateway rules from: .mcp-gateway-rules.json
484
+ Audit log will be written to: ./logs/audit.jsonl
485
+
486
+ Initializing proxy connections to downstream servers...
487
+ - 2 proxy client(s) initialized
488
+ * brave-search: ready
489
+ * postgres: ready
490
+ - Metrics collector initialized
491
+ - Access control middleware registered
492
+
493
+ Agent MCP Gateway initialized successfully
494
+ - 2 MCP server(s) configured
495
+ - 3 agent(s) configured
496
+ - Default policy: deny unknown agents
497
+ - 3 gateway tools available: list_servers, get_server_tools, execute_tool
498
+ (4 tools if GATEWAY_DEBUG=true: includes get_gateway_status)
499
+
500
+ Gateway is ready. Running with stdio transport...
501
+ ```
502
+
503
+ ## Gateway Tools
504
+
505
+ The gateway exposes exactly 3 tools to agents. All tools accept an optional `agent_id` parameter for access control. When `agent_id` is not provided, the gateway uses a fallback chain to determine agent identity (see [Agent Identity Modes](#agent-identity-modes)).
506
+
507
+ **For Agent Developers:** To configure your agents to properly use these gateway tools with access control, see [Configuring Agents to Use the Gateway](#configuring-agents-to-use-the-gateway).
508
+
509
+ ### 1. `list_servers`
510
+
511
+ Lists MCP servers available to the calling agent based on policy rules.
512
+
513
+ **Parameters:**
514
+ - `agent_id` (string, optional) - Identifier of the agent making the request (see [Agent Identity Modes](#agent-identity-modes))
515
+ - `include_metadata` (boolean, optional) - Include technical details like transport, command, and url (default: false)
516
+
517
+ **Returns:**
518
+ ```json
519
+ [
520
+ {
521
+ "name": "brave-search",
522
+ "description": "Web search via Brave Search API"
523
+ },
524
+ {
525
+ "name": "postgres",
526
+ "description": "PostgreSQL database access and query execution"
527
+ }
528
+ ]
529
+ ```
530
+
531
+ **With `include_metadata=true`:**
532
+ ```json
533
+ [
534
+ {
535
+ "name": "brave-search",
536
+ "description": "Web search via Brave Search API",
537
+ "transport": "stdio",
538
+ "command": "npx"
539
+ },
540
+ {
541
+ "name": "postgres",
542
+ "description": "PostgreSQL database access and query execution",
543
+ "transport": "stdio",
544
+ "command": "uvx"
545
+ }
546
+ ]
547
+ ```
548
+
549
+ **Note:** Server descriptions are always included (when configured in `.mcp.json`) to help agents understand what each server provides. The `include_metadata` flag only controls whether technical details (transport, command, url) are included.
550
+
551
+ **Example:**
552
+ ```python
553
+ # Basic usage - returns names and descriptions
554
+ result = await client.call_tool("list_servers", {
555
+ "agent_id": "researcher"
556
+ })
557
+
558
+ # With technical metadata
559
+ result = await client.call_tool("list_servers", {
560
+ "agent_id": "researcher",
561
+ "include_metadata": True
562
+ })
563
+ ```
564
+
565
+ ### 2. `get_server_tools`
566
+
567
+ Retrieves tool definitions from a specific MCP server, filtered by agent permissions.
568
+
569
+ **Parameters:**
570
+ - `agent_id` (string, optional) - Identifier of the agent (see [Agent Identity Modes](#agent-identity-modes))
571
+ - `server` (string, required) - Name of the downstream MCP server
572
+ - `names` (string, optional) - Comma-separated list of tool names (e.g., `"tool1,tool2,tool3"`) or single tool name
573
+ - `pattern` (string, optional) - Wildcard pattern for tool names (e.g., `"get_*"`)
574
+ - `max_schema_tokens` (integer, optional) - Token budget limit for schemas
575
+
576
+ **Returns:**
577
+ ```json
578
+ {
579
+ "tools": [
580
+ {
581
+ "name": "brave_web_search",
582
+ "description": "Search the web using Brave Search",
583
+ "inputSchema": {
584
+ "type": "object",
585
+ "properties": {
586
+ "query": {"type": "string"}
587
+ },
588
+ "required": ["query"]
589
+ }
590
+ }
591
+ ],
592
+ "server": "brave-search",
593
+ "total_available": 5,
594
+ "returned": 1,
595
+ "tokens_used": 150
596
+ }
597
+ ```
598
+
599
+ **Example:**
600
+ ```python
601
+ # Get all allowed tools
602
+ tools = await client.call_tool("get_server_tools", {
603
+ "agent_id": "researcher",
604
+ "server": "brave-search"
605
+ })
606
+
607
+ # Get specific tools by name (comma-separated)
608
+ tools = await client.call_tool("get_server_tools", {
609
+ "agent_id": "researcher",
610
+ "server": "brave-search",
611
+ "names": "brave_web_search,brave_local_search"
612
+ })
613
+
614
+ # Get specific tools by pattern
615
+ tools = await client.call_tool("get_server_tools", {
616
+ "agent_id": "backend",
617
+ "server": "postgres",
618
+ "pattern": "get_*"
619
+ })
620
+
621
+ # Limit token usage
622
+ tools = await client.call_tool("get_server_tools", {
623
+ "agent_id": "researcher",
624
+ "server": "brave-search",
625
+ "max_schema_tokens": 1000
626
+ })
627
+ ```
628
+
629
+ ### 3. `execute_tool`
630
+
631
+ Executes a tool on a downstream MCP server with transparent result forwarding.
632
+
633
+ **Parameters:**
634
+ - `agent_id` (string, optional) - Identifier of the agent (see [Agent Identity Modes](#agent-identity-modes))
635
+ - `server` (string, required) - Name of the downstream MCP server
636
+ - `tool` (string, required) - Name of the tool to execute
637
+ - `args` (object, required) - Arguments to pass to the tool
638
+ - `timeout_ms` (integer, optional) - Timeout in milliseconds
639
+
640
+ **Returns:**
641
+ ```json
642
+ {
643
+ "content": [
644
+ {
645
+ "type": "text",
646
+ "text": "Search results: ..."
647
+ }
648
+ ],
649
+ "isError": false
650
+ }
651
+ ```
652
+
653
+ **Example:**
654
+ ```python
655
+ # Execute a tool
656
+ result = await client.call_tool("execute_tool", {
657
+ "agent_id": "researcher",
658
+ "server": "brave-search",
659
+ "tool": "brave_web_search",
660
+ "args": {
661
+ "query": "FastMCP documentation"
662
+ }
663
+ })
664
+
665
+ # With timeout
666
+ result = await client.call_tool("execute_tool", {
667
+ "agent_id": "backend",
668
+ "server": "postgres",
669
+ "tool": "query",
670
+ "args": {
671
+ "sql": "SELECT * FROM users LIMIT 10"
672
+ },
673
+ "timeout_ms": 5000
674
+ })
675
+ ```
676
+
677
+ ### 4. `get_gateway_status` (Debug Mode Only)
678
+
679
+ Returns comprehensive gateway health and diagnostics information.
680
+
681
+ **Important:** This tool is only available when debug mode is enabled (via `GATEWAY_DEBUG=true` environment variable or `--debug` CLI flag). See [Security Considerations](#security-considerations) for details.
682
+
683
+ **Parameters:**
684
+ - `agent_id` (string, optional) - Identifier of the agent (see [Agent Identity Modes](#agent-identity-modes))
685
+
686
+ **Returns:**
687
+ ```json
688
+ {
689
+ "reload_status": {
690
+ "mcp_config": {
691
+ "last_attempt": "2025-10-30T10:30:00Z",
692
+ "last_success": "2025-10-30T10:30:00Z",
693
+ "last_error": null,
694
+ "attempt_count": 1,
695
+ "success_count": 1
696
+ },
697
+ "gateway_rules": {
698
+ "last_attempt": "2025-10-30T10:35:00Z",
699
+ "last_success": "2025-10-30T10:35:00Z",
700
+ "last_error": null,
701
+ "attempt_count": 2,
702
+ "success_count": 2,
703
+ "last_warnings": []
704
+ }
705
+ },
706
+ "policy_state": {
707
+ "total_agents": 3,
708
+ "agent_ids": ["researcher", "backend", "admin"],
709
+ "defaults": {"deny_on_missing_agent": true}
710
+ },
711
+ "available_servers": ["brave-search", "postgres"],
712
+ "config_paths": {
713
+ "mcp_config": "/path/to/.mcp.json",
714
+ "gateway_rules": "/path/to/.mcp-gateway-rules.json"
715
+ },
716
+ "message": "Gateway is operational. Check reload_status for hot reload health."
717
+ }
718
+ ```
719
+
720
+ **Example:**
721
+ ```python
722
+ # Check gateway health and reload status (requires GATEWAY_DEBUG=true)
723
+ status = await client.call_tool("get_gateway_status", {
724
+ "agent_id": "admin"
725
+ })
726
+
727
+ # Verify last reload was successful
728
+ if status["reload_status"]["gateway_rules"]["last_error"]:
729
+ print("Warning: Last rule reload failed!")
730
+ ```
731
+
732
+ ### Error Handling
733
+
734
+ All tools return structured errors with clear messages:
735
+
736
+ ```json
737
+ {
738
+ "error": {
739
+ "code": "DENIED_BY_POLICY",
740
+ "message": "Agent 'frontend' denied access to tool 'drop_table'",
741
+ "rule": "agents.frontend.deny.tools.postgres[0]"
742
+ }
743
+ }
744
+ ```
745
+
746
+ **Error Codes:**
747
+ - `DENIED_BY_POLICY` - Agent lacks permission
748
+ - `SERVER_UNAVAILABLE` - Downstream server unreachable
749
+ - `TOOL_NOT_FOUND` - Requested tool doesn't exist
750
+ - `TIMEOUT` - Operation exceeded time limit
751
+ - `INVALID_AGENT_ID` - Missing or unknown agent identifier
752
+ - `FALLBACK_AGENT_NOT_IN_RULES` - Configured fallback agent not found in gateway rules
753
+ - `NO_FALLBACK_CONFIGURED` - No agent_id provided and no fallback agent configured
754
+
755
+ ### Complete Workflow Example
756
+
757
+ Here's a minimal working example showing the typical gateway workflow:
758
+
759
+ ```python
760
+ from fastmcp import Client
761
+
762
+ async def gateway_workflow():
763
+ async with Client('agent-mcp-gateway') as client:
764
+ # 1. Discover available servers
765
+ servers = await client.call_tool('list_servers', {
766
+ 'agent_id': 'researcher'
767
+ })
768
+ # Response: [{"name": "brave-search", "description": "Web search..."}]
769
+
770
+ # 2. Get tools from specific server
771
+ tools = await client.call_tool('get_server_tools', {
772
+ 'agent_id': 'researcher',
773
+ 'server': 'brave-search'
774
+ })
775
+ # Response: {"tools": [...], "server": "brave-search", ...}
776
+
777
+ # 3. Execute a tool
778
+ result = await client.call_tool('execute_tool', {
779
+ 'agent_id': 'researcher',
780
+ 'server': 'brave-search',
781
+ 'tool': 'brave_web_search',
782
+ 'args': {'query': 'MCP protocol documentation'}
783
+ })
784
+ # Response: {"content": [...search results...], "isError": false}
785
+ ```
786
+
787
+ This workflow demonstrates on-demand tool discovery - load definitions only when needed, not upfront.
788
+
789
+ ### Agent Identity Modes
790
+
791
+ The gateway supports two deployment modes for handling agent identity:
792
+
793
+ #### Single-Agent Mode
794
+
795
+ Use when all agents should have the same permissions (development, personal use, single-agent deployments):
796
+
797
+ ```bash
798
+ # Set default agent via environment variable
799
+ export GATEWAY_DEFAULT_AGENT=developer
800
+ ```
801
+
802
+ Or define a "default" agent in rules:
803
+ ```json
804
+ {
805
+ "agents": {
806
+ "default": {
807
+ "allow": {"servers": ["brave-search", "postgres"]}
808
+ }
809
+ },
810
+ "defaults": {
811
+ "deny_on_missing_agent": false
812
+ }
813
+ }
814
+ ```
815
+
816
+ Agents can omit `agent_id` in tool calls - the gateway automatically uses the configured default.
817
+
818
+ #### Multi-Agent Mode
819
+
820
+ Use when different agents need different permissions (production, multi-agent systems):
821
+
822
+ ```json
823
+ {
824
+ "agents": {
825
+ "researcher": {"allow": {"servers": ["brave-search"]}},
826
+ "backend": {"allow": {"servers": ["postgres"]}}
827
+ },
828
+ "defaults": {
829
+ "deny_on_missing_agent": true // Require explicit agent_id
830
+ }
831
+ }
832
+ ```
833
+
834
+ Configure each agent to pass their identity (see [Configuring Agents to Use the Gateway](#configuring-agents-to-use-the-gateway)).
835
+
836
+ <details>
837
+ <summary><strong>Technical Details: Agent Identity Resolution</strong></summary>
838
+
839
+ When `agent_id` is not provided, the gateway uses this fallback chain:
840
+
841
+ 1. `GATEWAY_DEFAULT_AGENT` environment variable (highest priority)
842
+ 2. Agent named "default" in `.mcp-gateway-rules.json`
843
+ 3. Error if neither configured
844
+
845
+ The `deny_on_missing_agent` setting controls this behavior:
846
+ - `true`: Require explicit `agent_id` (bypass fallback chain)
847
+ - `false`: Use fallback chain when `agent_id` omitted
848
+
849
+ **Security Note:** The fallback mechanism follows the principle of least privilege - it never grants implicit "allow all" access, only the explicitly configured agent's permissions.
850
+
851
+ </details>
852
+
853
+ ## Security Considerations
854
+
855
+ **Rules File Location:** Store `.mcp-gateway-rules.json` in-project for context optimization only. For production access control, store outside project directory (e.g., `~/.claude/mcp-gateway-rules.json`) to prevent agents from reading/modifying permissions.
856
+
857
+ **Debug Mode:** The `get_gateway_status` tool exposes gateway internals and is only available when `GATEWAY_DEBUG=true`. Disable in production environments.
858
+
859
+ **For comprehensive security guidance:** See [Security Guide](docs/security-guide.md) for detailed information on rules file security, debug mode considerations, agent impersonation risks, and production best practices.
860
+
861
+ ## Troubleshooting
862
+
863
+ ### Gateway Won't Start
864
+
865
+ **Symptom:** Error on startup or gateway fails to initialize
866
+
867
+ **Solutions:**
868
+ - **Check configuration files exist:** Verify `.mcp.json` and `.mcp-gateway-rules.json` are in the expected location
869
+ - **Validate JSON syntax:** Use `python -m json.tool < .mcp.json` to check for syntax errors
870
+ - **Check Python version:** Ensure Python 3.12+ is installed (`python --version`)
871
+ - **Verify dependencies:** Run `uv sync` to ensure all packages are installed
872
+
873
+ ### Can't Connect to Downstream Server
874
+
875
+ **Symptom:** `SERVER_UNAVAILABLE` error when calling tools
876
+
877
+ **Solutions:**
878
+ - **Verify server configuration:** Check server is properly defined in `.mcp.json`
879
+ - **Test stdio servers:** Ensure command is available (`npx --version`, `uvx --version`)
880
+ - **Check environment variables:** Verify API keys and credentials are set
881
+ - **Test HTTP servers:** Try accessing server URL directly in browser
882
+ - **Review startup logs:** Look for server initialization errors in gateway output
883
+
884
+ ### Permission Denied Errors
885
+
886
+ **Symptom:** `DENIED_BY_POLICY` when agent tries to use a tool
887
+
888
+ **Solutions:**
889
+ - **Verify agent_id:** Ensure agent is passing correct identity (check audit logs)
890
+ - **Check agent rules:** Confirm agent exists in `.mcp-gateway-rules.json`
891
+ - **Review policy precedence:** Remember deny rules take precedence over allow rules
892
+ - **Test with wildcard:** Try `"tools": {"server-name": ["*"]}` to grant broad access temporarily
893
+ - **Enable debug mode:** Use `GATEWAY_DEBUG=true` and call `get_gateway_status` to inspect policy state
894
+
895
+ ### OAuth Authentication Issues
896
+
897
+ **Symptom:** Browser doesn't open or OAuth flow fails
898
+
899
+ See detailed troubleshooting in [OAuth User Guide](docs/oauth-user-guide.md).
900
+
901
+ Quick fixes:
902
+ - **Clear token cache:** `rm -rf ~/.fastmcp/oauth-mcp-client-cache/`
903
+ - **Test browser:** `python -m webbrowser https://example.com`
904
+ - **Check server URL:** Verify correct OAuth server URL in `.mcp.json`
905
+
906
+ ### Hot Reload Not Working
907
+
908
+ **Symptom:** Changes to config files don't take effect
909
+
910
+ **Solutions:**
911
+ - **Check file watch:** Ensure config files are in expected locations
912
+ - **Review logs:** Look for reload errors in gateway output
913
+ - **Manual reload:** Send SIGHUP signal or restart gateway
914
+ - **Debug mode:** Use `get_gateway_status` to check last reload timestamps
915
+
916
+ **For additional help:** See [Security Guide](docs/security-guide.md), [OAuth User Guide](docs/oauth-user-guide.md), or open a GitHub issue.
917
+
918
+ ## Testing
919
+
920
+ ### Running Tests
921
+
922
+ ```bash
923
+ # Run all tests
924
+ uv run pytest
925
+
926
+ # Run with coverage
927
+ uv run pytest --cov=src --cov-report=term
928
+
929
+ # Run specific test file
930
+ uv run pytest tests/test_gateway.py -v
931
+
932
+ # Run integration tests only
933
+ uv run pytest tests/test_integration_m1.py -v
934
+ ```
935
+
936
+ ### Testing with MCP Inspector
937
+
938
+ The [MCP Inspector](https://github.com/modelcontextprotocol/inspector) is an interactive developer tool for testing and debugging MCP servers.
939
+
940
+ #### Install and Run
941
+
942
+ ```bash
943
+ # Run Inspector with the gateway (no installation needed)
944
+ npx @modelcontextprotocol/inspector uv run python main.py
945
+ ```
946
+
947
+ This opens a web interface where you can:
948
+ 1. Connect to the gateway via stdio transport
949
+ 2. View all three gateway tools
950
+ 3. Test each tool with custom parameters
951
+ 4. Inspect request/response messages
952
+ 5. Monitor logs and notifications
953
+
954
+ #### Testing Gateway Tools in Inspector
955
+
956
+ **1. Test `list_servers`:**
957
+ ```json
958
+ {
959
+ "agent_id": "researcher"
960
+ }
961
+ ```
962
+
963
+ Expected: List of servers the "researcher" agent can access.
964
+
965
+ **2. Test `get_server_tools`:**
966
+ ```json
967
+ {
968
+ "agent_id": "researcher",
969
+ "server": "brave-search"
970
+ }
971
+ ```
972
+
973
+ Expected: Tool definitions from brave-search server.
974
+
975
+ **3. Test `execute_tool`:**
976
+ ```json
977
+ {
978
+ "agent_id": "researcher",
979
+ "server": "brave-search",
980
+ "tool": "brave_web_search",
981
+ "args": {
982
+ "query": "test query"
983
+ }
984
+ }
985
+ ```
986
+
987
+ Expected: Search results from Brave (if server configured and running).
988
+
989
+ #### Inspector Features
990
+
991
+ - **Tools Tab**: View all gateway tools with schemas
992
+ - **Test Execution**: Call tools with custom inputs
993
+ - **Message Pane**: See raw JSON-RPC messages
994
+ - **Logs**: Monitor server logs and notifications
995
+ - **Connection**: Verify gateway startup and initialization
996
+
997
+ #### Troubleshooting with Inspector
998
+
999
+ If tools fail:
1000
+ 1. Check the **Logs pane** for error messages
1001
+ 2. Verify your `agent_id` exists in `.mcp-gateway-rules.json`
1002
+ 3. Confirm downstream servers are configured in `.mcp.json`
1003
+ 4. Check that required environment variables are set
1004
+ 5. Review the **Message pane** for policy denial reasons
1005
+
1006
+ ### Manual Testing (without Inspector)
1007
+
1008
+ ```bash
1009
+ # Run the existing integration test
1010
+ uv run python test_integration.py
1011
+
1012
+ # Or use FastMCP Client directly
1013
+ uv run python -c "
1014
+ import asyncio
1015
+ from fastmcp import Client
1016
+
1017
+ async def test():
1018
+ async with Client('main.py') as client:
1019
+ result = await client.call_tool('list_servers', {'agent_id': 'researcher'})
1020
+ print(result)
1021
+
1022
+ asyncio.run(test())
1023
+ "
1024
+ ```
1025
+
1026
+ ## Development
1027
+
1028
+ ### Project Structure
1029
+
1030
+ ```
1031
+ agent-mcp-gateway/
1032
+ ├── src/ # Core gateway implementation
1033
+ ├── tests/ # Test suite
1034
+ ├── config/ # Configuration examples
1035
+ ├── docs/ # Documentation and specifications
1036
+ ├── main.py # Entry point
1037
+ └── pyproject.toml # Python dependencies
1038
+ ```
1039
+
1040
+ ### Adding a New Feature
1041
+
1042
+ 1. **Update specs**: Document in relevant milestone file
1043
+ 2. **Write tests first**: Create test file in `tests/`
1044
+ 3. **Implement feature**: Add code in `src/`
1045
+ 4. **Run tests**: `uv run pytest`
1046
+ 5. **Check coverage**: `uv run pytest --cov=src`
1047
+ 6. **Update docs**: Document in README and relevant files
1048
+ 7. **Commit**: Follow commit message format
1049
+
1050
+ ### Running in Development
1051
+
1052
+ ```bash
1053
+ # Run with verbose logging
1054
+ uv run python main.py
1055
+
1056
+ # Run tests in watch mode
1057
+ uv run pytest-watch
1058
+
1059
+ # Generate coverage report
1060
+ uv run pytest --cov=src --cov-report=html
1061
+ open htmlcov/index.html
1062
+ ```
1063
+
1064
+ ### Code Style
1065
+
1066
+ - Follow existing patterns in M0/M1 code
1067
+ - Use type hints throughout
1068
+ - Write docstrings for all public functions
1069
+ - Keep functions focused and testable
1070
+ - Add tests for all new functionality
1071
+
1072
+ ## Architecture
1073
+
1074
+ ### Component Diagram
1075
+
1076
+ ```
1077
+ ┌─────────────────────────────────────────────────────────┐
1078
+ │ Agent / Client │
1079
+ └─────────────────────┬───────────────────────────────────┘
1080
+
1081
+
1082
+ ┌─────────────────────────────────────────────────────────┐
1083
+ │ Agent MCP Gateway │
1084
+ │ ┌───────────────────────────────────────────────────┐ │
1085
+ │ │ Gateway Tools (3 tools, ~400 tokens) │ │
1086
+ │ │ • list_servers │ │
1087
+ │ │ • get_server_tools │ │
1088
+ │ │ • execute_tool │ │
1089
+ │ └───────────────────────────────────────────────────┘ │
1090
+ │ │ │
1091
+ │ ┌─────────────────────────────────────────────────┐ │
1092
+ │ │ AgentAccessControl Middleware │ │
1093
+ │ │ • Extract agent_id │ │
1094
+ │ │ • Validate permissions │ │
1095
+ │ └─────────────────────────────────────────────────┘ │
1096
+ │ │ │
1097
+ │ ┌─────────────────────────────────────────────────┐ │
1098
+ │ │ PolicyEngine │ │
1099
+ │ │ • Deny-before-allow precedence │ │
1100
+ │ │ • Wildcard matching │ │
1101
+ │ └─────────────────────────────────────────────────┘ │
1102
+ │ │ │
1103
+ │ ┌─────────────────────────────────────────────────┐ │
1104
+ │ │ ProxyManager │ │
1105
+ │ │ • Session isolation │ │
1106
+ │ │ • Connection pooling │ │
1107
+ │ └─────────────────────────────────────────────────┘ │
1108
+ │ │ │
1109
+ │ ┌─────────────────────────────────────────────────┐ │
1110
+ │ │ AuditLogger & MetricsCollector │ │
1111
+ │ └─────────────────────────────────────────────────┘ │
1112
+ └──────────────────────┬───────────────────────────────────┘
1113
+
1114
+ ┌─────────────┼─────────────┐
1115
+ ▼ ▼ ▼
1116
+ ┌─────────┐ ┌─────────┐ ┌─────────┐
1117
+ │ Server │ │ Server │ │ Server │
1118
+ │ A │ │ B │ │ C │
1119
+ │ (stdio) │ │ (stdio) │ │ (HTTP) │
1120
+ └─────────┘ └─────────┘ └─────────┘
1121
+ ```
1122
+
1123
+ ### Request Flow
1124
+
1125
+ 1. **Agent sends request** to gateway tool with `agent_id`
1126
+ 2. **Middleware intercepts**: Extracts and validates `agent_id`
1127
+ 3. **Tool validates**: Checks PolicyEngine for server/tool access
1128
+ 4. **Proxy forwards**: ProxyManager routes to downstream server
1129
+ 5. **Session isolated**: Each request gets fresh connection
1130
+ 6. **Result returns**: Transparently forwarded to agent
1131
+ 7. **Audit logged**: Operation recorded with metrics
1132
+
1133
+ ### Performance Characteristics
1134
+
1135
+ - **Context reduction**: 90%+ (400 tokens vs 5,000-50,000+)
1136
+ - **Added latency**: <100ms (P95)
1137
+ - **Gateway overhead**: <30ms per operation
1138
+ - **Session isolation**: Automatic per-request
1139
+ - **Concurrent requests**: Fully supported
1140
+
1141
+ ## Future Features
1142
+
1143
+ ### M2: Production (Planned)
1144
+
1145
+ 🚧 **Status:** Not yet implemented
1146
+
1147
+ **Features:**
1148
+ - [ ] HTTP transport for gateway server
1149
+ - [ ] Health check endpoints
1150
+ - [ ] Enhanced error handling
1151
+ - [ ] Metrics export API
1152
+ - [ ] Connection pooling optimization
1153
+ - [ ] Rate limiting
1154
+
1155
+ **When available:**
1156
+ ```bash
1157
+ # Run with HTTP transport
1158
+ export GATEWAY_TRANSPORT=http
1159
+ export GATEWAY_PORT=8080
1160
+ uv run python main.py
1161
+
1162
+ # Health check endpoint
1163
+ curl http://localhost:8080/health
1164
+
1165
+ # Metrics endpoint
1166
+ curl http://localhost:8080/metrics
1167
+ ```
1168
+
1169
+ ### M3: Developer Experience (Planned)
1170
+
1171
+ 🚧 **Status:** Not yet implemented
1172
+
1173
+ **Features:**
1174
+ - [ ] Single-agent mode (bypass agent_id requirement)
1175
+ - [ ] Config validation CLI tool
1176
+ - [ ] Docker container with examples
1177
+ - [ ] Interactive setup wizard
1178
+ - [ ] VS Code extension
1179
+
1180
+ **When available:**
1181
+ ```bash
1182
+ # Single-agent mode (no agent_id required)
1183
+ export GATEWAY_DEFAULT_AGENT=developer
1184
+ uv run python main.py
1185
+
1186
+ # Validate configs
1187
+ uv run python -m src.cli validate
1188
+
1189
+ # Run with Docker
1190
+ docker run -v ./config:/config agent-mcp-gateway
1191
+ ```
1192
+
1193
+ ## Documentation
1194
+
1195
+ - [Product Requirements Document](docs/specs/PRD.md)
1196
+ - [M0: Foundation Spec](docs/specs/m0-foundation.md)
1197
+ - [M0: Success Report](docs/milestones/m0-success-report.md)
1198
+ - [M1: Core Spec](docs/specs/m1-core.md)
1199
+ - [M1: Success Report](docs/milestones/m1-success-report.md)
1200
+ - [FastMCP Implementation Guide](docs/fastmcp-implementation-guide.md)
1201
+ - [Claude Code Subagent Limitations](docs/claude-code-subagent-mcp-limitations.md)
1202
+
1203
+ ## Contributing
1204
+
1205
+ Contributions welcome! Please:
1206
+
1207
+ 1. Read the [PRD](docs/specs/PRD.md) and relevant milestone specs
1208
+ 2. Follow the existing code style and patterns
1209
+ 3. Write tests for all new functionality
1210
+ 4. Ensure all tests pass: `uv run pytest`
1211
+ 5. Update documentation as needed
1212
+ 6. Submit a pull request with clear description
1213
+
1214
+ ## License
1215
+
1216
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
1217
+
1218
+ ## Support
1219
+
1220
+ For issues and questions:
1221
+ - GitHub Issues: [Create an issue](link-to-issues)
1222
+ - Documentation: [docs/specs/](docs/specs/)
1223
+ - MCP Specification: https://modelcontextprotocol.io
1224
+
1225
+ ## Acknowledgments
1226
+
1227
+ Built with:
1228
+ - [FastMCP](https://gofastmcp.com/) - MCP server framework
1229
+ - [Model Context Protocol](https://modelcontextprotocol.io/) - Protocol specification