Skip to main content
Glama

๏ปฟ

Agnostic MCP HTTP/SSE Proxy Server (SDK v2.0.0+)

A highly extensible, API-agnostic Model Context Protocol (MCP) proxy gateway built using Python's modern MCP SDK 2.0.0+, FastAPI, and Starlette.

This server acts as a centralized routing engine that discovers, sanitizes, namespaces, and executes tools published across multiple independent, downstream remote HTTP/SSE or unified gateway MCP servers (such as Yahoo Finance or AlphaVantage) without hardcoding explicit routes or functions.

๐ŸŒŸ Key Features

  • Agnostic Schema Discovery: Merges dynamic tool capabilities across distinct downstream endpoints seamlessly.

  • Isolation Namespacing: Auto-prefixes remote tools using the syntax {server_name}__{original_tool_name} to isolate environments and prevent asset collisions.

  • Protocol Failure Resilience: Automatically strips conflicting output_schema fields from non-compliant remote servers to prevent runtime deserialization exceptions.

  • Production-Grade Project Layout: Fully modularized layout cleanly separating configurations, server logic, network routers, and telemetry wrappers.

  • Daily Rotating Local Logging: Built-in rolling log files saved to a dedicated logs/ directory with explicit date-stamps.


๐Ÿ“‚ Project Architecture Layout

The codebase implements a decoupled design pattern to ensure straightforward maintainability:

mcp_proxy/
โ”‚
โ”œโ”€โ”€ config/
โ”‚   โ”œโ”€โ”€ __init__.py
โ”‚   โ””โ”€โ”€ manager.py       # Handles reading/persisting proxy_servers.json relative to the module
โ”‚
โ”œโ”€โ”€ observability/
โ”‚   โ”œโ”€โ”€ __init__.py
โ”‚   โ””โ”€โ”€ tracker.py       # Async context manager placeholder for tiktoken and future MLflow metrics
โ”‚
โ”œโ”€โ”€ core/
โ”‚   โ”œโ”€โ”€ __init__.py
โ”‚   โ””โ”€โ”€ proxy.py         # Primary MCP server engine and namespaced call routing loops
โ”‚
โ”œโ”€โ”€ api/
โ”‚   โ”œโ”€โ”€ __init__.py
โ”‚   โ””โ”€โ”€ routes.py        # Connects raw Starlette routes bypassing FastAPI middleware issues
โ”‚
โ”œโ”€โ”€ logs/
โ”‚   โ””โ”€โ”€ mcp_proxy.log    # Active file logging sink (daily timestamp rotated)
โ”‚
โ”œโ”€โ”€ .gitignore           # Eradicates runtime cache and configuration leakage to VCS trackers
โ”œโ”€โ”€ proxy_servers.json   # Local flat registry containing active remote endpoints
โ””โ”€โ”€ main.py              # Application lifecycle entry point (Uvicorn launchpad)

๐Ÿ› ๏ธ Quick Start

1. Installation

Clone the repository, initialize your virtual environment, and install dependencies utilizing trusted host flags to bypass SSL roadblocks:

# Create and activate environment
python -m venv venv
./venv/Scripts/activate # On Windows Powershell

# Install dependencies securely
pip install -r requirements.txt

2. Configure Downstream Servers

Populate the configuration registry file inside the config/ directory. Create config/proxy_servers.json:

{
  "yahoo_finance": "https://gateway.mcpservers.org/yahoo-finance/mcp",
  "alphavantage_mcp": "http://localhost:8001/mcp"
}

3. Launch the Server

Execute the uvicorn launchpad from the root project directory:

python main.py

The server will bind to http://localhost:8000. It configures /sse for event streaming listeners and /messages for JSON-RPC message passing.


๐Ÿงช cURL Testing Sequences

The proxy operates using asynchronous Server-Sent Events (SSE). Testing requires a two-step approach: opening a persistent listening stream channel first, followed by sending JSON-RPC payloads containing an active tracking token.

Step 1: Open the Streaming Monitor Connection

Open a first terminal window. Run this command to initialize a long-lived channel listener:

curl -N -v http://localhost:8000/sse

(The -N flag forces cURL to disable output buffering, ensuring events print immediately).

Look closely at the very first lines outputted by this terminal. You will see an initialization frame declaring your unique connection session token:

event: endpoint
data: /messages?session_id=89be6f2dca5a4529813589b27464da91

Copy your unique session_id code string.


Step 2: Fetch the Consolidated Tools List

Open a second terminal window and push a tools/list JSON-RPC request frame. Replace the session_id parameter at the end of the URL with your copied token:

curl -X POST "http://localhost:8000/messages?session_id=PASTE_YOUR_SESSION_ID_HERE" \
     -H "Content-Type: application/json" \
     -d '{
       "jsonrpc": "2.0",
       "method": "tools/list",
       "id": "list-check-101",
       "params": {}
     }'
  • POST Terminal: Returns {"status": "accepted"} and terminates immediately.

  • SSE Terminal 1: Will instantly emit the complete unified tool array, displaying namespaced keys like yahoo_finance__get_stock_price.


Step 3: Execute a Proxied Tool Call

To invoke an environment-isolated remote tool, execute a tools/call JSON-RPC payload in your second terminal window, embedding the target parameters inside the flat schema layout:

curl -X POST "http://localhost:8000/messages?session_id=PASTE_YOUR_SESSION_ID_HERE" \
     -H "Content-Type: application/json" \
     -d '{
       "jsonrpc": "2.0",
       "method": "tools/call",
       "id": "tool-execution-202",
       "params": {
         "name": "yahoo_finance__get_stock_price",
         "arguments": {
           "ticker": "AAPL"
         }
       }
     }'
  • POST Terminal: Returns {"status": "accepted"} immediately.

  • SSE Terminal 1: Asynchronously displays the operational output data block received from the target backend node, mapped to matching "id": "tool-execution-202".


Step 4: Interrogate Internal Proxy Management Tools

You can check proxy states or update bindings on-the-fly using native management tools:

List Registered Upstream Hosts

curl -X POST "http://localhost:8000/messages?session_id=PASTE_YOUR_SESSION_ID_HERE" \
     -H "Content-Type: application/json" \
     -d '{
       "jsonrpc": "2.0",
       "method": "tools/call",
       "id": "management-list",
       "params": {
         "name": "proxy_list_servers",
         "arguments": {}
       }
     }'

Dynamically Register a New Remote Server

curl -X POST "http://localhost:8000/messages?session_id=PASTE_YOUR_SESSION_ID_HERE" \
     -H "Content-Type: application/json" \
     -d '{
       "jsonrpc": "2.0",
       "method": "tools/call",
       "id": "management-add",
       "params": {
         "name": "proxy_add_server",
         "arguments": {
           "name": "crypto_tracker",
           "url": "http://localhost:8090/mcp"
         }
       }
     }'

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/anjani78/mcp_proxy'

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