Skip to main content
Glama
mcp-test-mcp-tech-stack.md17.1 kB
# Technology Stack: mcp-test-mcp **Date:** 2025-10-09 **Status:** Draft **Version:** 1.0 **Based on Sketch:** `sketches/mcp-test-mcp-sketch.md` --- ## Decision Summary | Component | Technology | Version | Rationale | |-----------|-----------|---------|-----------| | Language | Python | 3.11+ | CLAUDE.md standard, FastMCP requirement | | MCP Framework | FastMCP | 2.x (latest) | Purpose-built for MCP, both server & client | | Server Transport | stdio | - | Local only - Claude Code launches via stdio | | Client Transport | streamable-http + stdio | - | Test deployed (http) or local (stdio) servers | | Data Validation | Pydantic | 2.x | Built into FastMCP, type-safe schemas | | Testing | pytest | Latest | CLAUDE.md standard | | Package Distribution | PyPI / pip | - | Standard Python package | | Deployment | Local only | - | Not a deployed service | --- ## Detailed Technology Decisions ### Language: Python 3.11+ **Decision:** Python 3.11 or higher **Options Considered:** - Python 3.11+ (chosen) - Python 3.9+ (minimum for some frameworks) **Rationale:** - FastMCP requires Python 3.11+ for modern async features - CLAUDE.md specifies Python for backend development - Type hints and async/await are first-class features - Strong ecosystem for MCP development **Consistency Check:** - ✓ Matches CLAUDE.md preference for Python - ✓ No existing codebase to reconcile (greenfield) **Trade-offs Accepted:** - Requires Python 3.11+ runtime (not 3.9 or 3.10) - Modern Python features may not work on legacy systems **Key Dependencies:** ``` python >= 3.11 ``` **Integration Notes:** All components written in Python, single runtime environment --- ### MCP Framework: FastMCP v2 **Decision:** FastMCP version 2.x (latest stable) **Options Considered:** - FastMCP v2 (chosen) - Purpose-built Python MCP framework - Official MCP Python SDK - Lower-level, more boilerplate - Custom implementation - Reinventing the wheel **Rationale:** - **Dual role**: FastMCP provides BOTH server and client implementations - Server: Expose testing tools to AI assistants - Client: Connect to and test target MCP servers - **Single framework**: Consistent patterns for both sides of the architecture - **Transport flexibility**: Automatic transport detection (stdio, HTTP) - **Type safety**: Built on Pydantic for schema validation - **Active development**: Current version 2.x with ongoing updates - **Documentation**: Comprehensive docs available locally **Consistency Check:** - ✓ Python-native (matches CLAUDE.md) - ✓ No existing framework to reconcile (greenfield) - ✓ Designed specifically for MCP use cases **Trade-offs Accepted:** - Framework lock-in (but MCP protocol is standard) - Less control than using official SDK directly - Framework is newer (2024), smaller ecosystem than FastAPI **Key Dependencies:** ``` fastmcp >= 2.0.0 pydantic >= 2.0 # Included with FastMCP ``` **Integration Notes:** - Server component uses `FastMCP` class to expose tools - Client component uses `fastmcp.Client` to connect to targets - Single import namespace for both server and client --- ### Server Transport: stdio only **Decision:** stdio only (mcp-test-mcp runs locally) **Options Considered:** - stdio only (chosen) - Local execution by Claude Code - streamable-http - Not needed, server runs locally - Both - Unnecessary complexity for this use case **Rationale:** - **stdio is the correct pattern**: AI assistants (Claude Code/Desktop) launch MCP servers as local subprocesses - **Simple setup**: No network configuration needed - **Standard for desktop MCP tools**: How Claude Code runs local MCP servers - **Architecture clarity**: ``` Claude Code (stdio) → mcp-test-mcp Server ↓ Internal Client (http/stdio) ↓ Target MCP Server (being tested) ``` - **No deployment needed**: The server is a local development tool, not a service **Consistency Check:** - ✓ Matches desktop MCP server pattern (Claude Code/Desktop usage) - ✓ stdio is standard for local MCP servers - ✓ Simpler than supporting multiple transports for the server side **Trade-offs Accepted:** - Server cannot be shared across team (but that's not the use case) - Each developer runs their own local instance (this is desired) **Implementation:** ```python if __name__ == "__main__": # stdio by default - Claude Code will launch this mcp.run() ``` **Integration Notes:** - Runs as subprocess when Claude Code starts - No HTTP endpoints on the server itself - All HTTP communication happens in the internal client layer --- ### Client Transport: streamable-http + stdio **Decision:** Support both streamable-http and stdio for connecting to target servers **Options Considered:** - streamable-http only - Would exclude local server testing - stdio only - Would exclude deployed server testing - Both streamable-http and stdio (chosen) - Full flexibility **Rationale:** - **Primary use case**: Testing deployed MCP servers on OpenShift/cloud (streamable-http) - **Secondary use case**: Testing local MCP servers during development (stdio) - **FastMCP Client auto-detection**: Automatically selects transport based on connection string - URL starting with `http://` or `https://` → streamable-http transport - File path (e.g., `my_server.py`) → stdio transport - **No additional complexity**: FastMCP handles both transparently - **Complete testing capability**: Can test servers in any deployment mode **Consistency Check:** - ✓ Matches requirements (both deployed and local testing) - ✓ Uses recommended transport (streamable-http, not legacy SSE) - ✓ CLAUDE.md: streamable-http preferred for production **Trade-offs Accepted:** - Must handle both connection patterns in tool implementations - Different error modes for network vs subprocess connections **Implementation:** ```python from fastmcp import Client # Connect to deployed server (auto-detects HTTP transport) async with Client("https://my-server.apps.openshift.com/mcp") as client: tools = await client.list_tools() # Connect to local server (auto-detects stdio transport) async with Client("./my_local_server.py") as client: tools = await client.list_tools() ``` **Integration Notes:** - FastMCP Client auto-detects transport from connection string - No explicit transport configuration needed - Both patterns handled identically in tool code --- ### Data Validation: Pydantic v2 **Decision:** Pydantic 2.x (comes with FastMCP) **Options Considered:** - Pydantic v2 (chosen) - Industry standard, FastMCP dependency - dataclasses - Less validation - attrs - Less common in async Python **Rationale:** - **Included with FastMCP**: No additional dependency - **Type safety**: Automatic validation from type hints - **Schema generation**: JSON schemas for MCP tools - **Industry standard**: Widely used in Python async frameworks - **Performance**: v2 has Rust-based core for speed **Consistency Check:** - ✓ Part of FastMCP (no additional choice needed) - ✓ Python type hints align with CLAUDE.md best practices **Trade-offs Accepted:** - Pydantic adds runtime overhead (minimal with v2) - Learning curve for complex validations **Key Dependencies:** ``` pydantic >= 2.0 # Dependency of FastMCP ``` **Integration Notes:** - Used for connection state models - Automatic validation in FastMCP tool definitions - Type hints drive schema generation --- ### Testing: pytest **Decision:** pytest with 80%+ coverage target **Options Considered:** - pytest (chosen) - CLAUDE.md standard - unittest - Standard library but more verbose - nose - Deprecated **Rationale:** - **CLAUDE.md standard**: Explicitly specified - **80%+ coverage target**: Per CLAUDE.md requirements - **Async support**: pytest-asyncio for async tests - **Fixtures**: Clean test setup/teardown - **Rich ecosystem**: Many plugins available **Consistency Check:** - ✓ Matches CLAUDE.md testing standard - ✓ Industry standard for Python projects **Trade-offs Accepted:** - Additional dependency (but standard) - Async tests require pytest-asyncio plugin **Key Dependencies:** ``` pytest >= 7.0 pytest-asyncio >= 0.21 # For async test support pytest-cov >= 4.0 # For coverage reporting ``` **Integration Notes:** - Test structure mirrors src/ directory - Async tests for MCP client/server operations - Coverage reports in HTML format for review --- ## CLAUDE.md Compliance **Standards Applied:** - ✓ **Python Framework**: FastMCP (MCP-specific) - ✓ **Python Environment**: venv for local development - ✓ **Testing**: pytest with 80%+ coverage target - ✓ **No mocking**: Let broken things stay broken - ✓ **File organization**: Separate files, <512 lines where possible - ✓ **Transport**: stdio for server (standard), streamable-http for client (preferred over SSE) **Standards Not Applicable (Local Tool, Not Deployed):** - ⊘ **Container Runtime**: Not needed (no container deployment) - ⊘ **Base Images**: Not needed (no container deployment) - ⊘ **Deployment Platform**: Not needed (runs locally) - ⊘ **Kustomize/CI/CD**: Not needed (Python package distribution) **Rationale:** mcp-test-mcp is a local development tool that runs on the developer's machine as a subprocess of Claude Code/Desktop. It is not a deployed service, so container/deployment standards don't apply. **Exceptions Requested:** - None - All applicable CLAUDE.md standards applied --- ## Existing Codebase Integration **Current State:** Greenfield project - no existing code **Our Approach:** - ✓ Starting fresh with CLAUDE.md standards from day one - ✓ No legacy code to reconcile - ✓ Clean slate for best practices --- ## Component Architecture Mapping ### 1. FastMCP Server Layer **Technologies:** - FastMCP 2.x server - Python 3.11+ - Pydantic for tool schemas - stdio transport only **Responsibilities:** - Expose 9 testing tools to AI assistants - Handle connection state management - Validate inputs with Pydantic - Return verbose responses **Integration:** ```python from fastmcp import FastMCP mcp = FastMCP(name="mcp-test-mcp") @mcp.tool() async def connect_to_server(url: str) -> dict: # Implementation pass if __name__ == "__main__": mcp.run() # stdio by default - Claude Code launches this ``` --- ### 2. Connection Manager **Technologies:** - Pure Python (standard library) - In-memory state (no database) - Pydantic models for state **Responsibilities:** - Manage single active connection - Track connection metadata - Handle timeouts and errors - Maintain statistics **State Model:** ```python from pydantic import BaseModel from datetime import datetime from typing import Optional class ConnectionState(BaseModel): server_url: str transport: str connected_at: datetime server_info: dict statistics: dict ``` **Integration:** - Global state within mcp-test-mcp process - Accessed by all tool implementations - Reset on disconnect or restart --- ### 3. FastMCP Client Layer **Technologies:** - FastMCP Client (fastmcp.Client) - streamable-http + stdio transports - Async/await patterns **Responsibilities:** - Connect to target MCP servers (deployed or local) - Execute MCP protocol operations - Return raw responses for verbosity - Handle transport-level errors **Integration:** ```python from fastmcp import Client # In connection manager async def connect(url_or_path: str): # Auto-detects transport: # - http/https URL → streamable-http # - file path → stdio client = Client(url_or_path) async with client: # Perform initialization await client.ping() return client ``` --- ## Development Environment **Python Environment:** venv (per CLAUDE.md) ```bash python3.11 -m venv .venv source .venv/bin/activate # Linux/Mac pip install -e ".[dev]" ``` **Python Version:** 3.11+ **Package Management:** - Primary: pip - Optional: uv for faster installs (compatible with venv) **Testing Framework:** pytest ```bash pytest # Run all tests pytest --cov=src --cov-report=html # With coverage pytest -v # Verbose output ``` **Code Quality:** ```bash black src/ tests/ # Code formatting ruff check src/ tests/ # Linting mypy src/ # Type checking ``` **Local Development:** ```bash # Run server locally via stdio (only mode) python -m mcp_test_mcp # Or let Claude Code launch it automatically via MCP configuration ``` --- ## Deployment Stack **Deployment Model:** Local only - not deployed **Rationale:** - mcp-test-mcp is a **local development tool** for Claude Code/Desktop - Runs as a subprocess on the developer's machine - No server deployment needed **Installation:** ```bash # Install as Python package pip install mcp-test-mcp # Or install from source git clone <repo> cd mcp-test-mcp pip install -e . ``` **Configuration:** Add to Claude Code/Desktop MCP settings: ```json { "mcpServers": { "mcp-test-mcp": { "command": "python", "args": ["-m", "mcp_test_mcp"], "transport": "stdio" } } } ``` **Container/OpenShift Deployment:** Not applicable (local tool only) **CI/CD:** Standard Python package distribution (PyPI or internal package repo) --- ## Project Structure ``` mcp-test-mcp/ ├── pyproject.toml # Python package config ├── README.md # Project documentation ├── LICENSE # License file ├── .gitignore # Git ignore patterns ├── src/ │ └── mcp_test_mcp/ │ ├── __init__.py │ ├── __main__.py # Entry point for python -m │ ├── server.py # FastMCP server setup │ ├── connection.py # Connection manager │ ├── models.py # Pydantic models │ └── tools/ # Tool implementations │ ├── __init__.py │ ├── connection.py # connect, disconnect, status │ ├── tools.py # list_tools, call_tool │ ├── resources.py # list_resources, read_resource │ └── prompts.py # list_prompts, get_prompt ├── tests/ │ ├── __init__.py │ ├── conftest.py # Pytest fixtures │ ├── test_server.py # Server tests │ ├── test_connection.py # Connection manager tests │ └── test_tools/ # Tool tests │ ├── test_connection_tools.py │ ├── test_tool_tools.py │ ├── test_resource_tools.py │ └── test_prompt_tools.py └── docs/ # Additional documentation ├── usage.md # Usage guide └── examples/ # Example configurations └── claude-code-config.json # Claude Code MCP config ``` --- ## Deferred Decisions The following will be decided in `/propose` or during implementation: **Logging Implementation:** - Specific logging library (loguru vs standard logging) - Log format (JSON vs text) - Log aggregation strategy **Error Handling Details:** - Custom exception hierarchy - Error response formats - Retry strategies **Timeout Configuration:** - Default timeout values (tentatively 30s connect, 60s call) - Timeout customization via environment variables - Backoff strategies **Minor Utilities:** - URL validation library - Datetime formatting approach - Statistics tracking implementation **Documentation Generation:** - API documentation format - Usage examples format - Contribution guidelines **Note:** Major frameworks are locked here; specific packages within those frameworks will be chosen during implementation based on current best practices and latest stable versions. --- ## Open Questions **Timeout Defaults:** - **Question:** Are 30s (connect) and 60s (tool call) appropriate defaults? - **Tentative:** Yes, but make configurable via environment variables - **Resolution:** Will finalize in `/propose` with specific ENV var names **Error Verbosity:** - **Question:** How much error detail to return from target servers? - **Tentative:** Full errors with context (which server, which tool, when) - **Resolution:** Will specify exact format in `/propose` **Statistics Tracking:** - **Question:** What statistics to track beyond basic counters? - **Tentative:** Just counts (tools called, resources read, prompts retrieved) - **Resolution:** Can add timing histograms in Phase 2 if needed --- ## Next Steps 1. ✅ Review this tech stack document 2. ⏳ Resolve any open questions 3. ⏳ Run `/propose` to create detailed technical proposal 4. ⏳ Implementation using selected technologies 5. ⏳ Testing with pytest (80%+ coverage) 6. ⏳ Package as Python package for distribution **This tech stack is ready for `/propose` to create the detailed implementation design.**

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/rdwj/mcp-test-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server