π STDIO Wrapper (mcpgateway.wrapper
)¶
mcpgateway.wrapper
ships inside the main PyPI package and re-publishes your Gateway's tools / prompts / resources over stdin β stdout
, while connecting securely to the gateway using SSE
+ JWT
.
Perfect for clients that can't open SSE streams or attach JWT headers (e.g. Claude Desktop, Cline, Continue, custom CLI scripts).
π Key Highlights¶
- Dynamic catalog - auto-syncs from one or more
.../servers/{id}
Virtual Server endpoints - Full MCP protocol -
initialize
,ping
,tools/call
, streaming content, resources and prompts/template rendering - Transparent proxy - stdio β Gateway β tool, results stream back to stdout
- Secure - wrapper keeps using your JWT to talk to the Gateway
π Launch Options¶
Ensure you have a valid JWT token:
export MCPGATEWAY_BEARER_TOKEN=$(python3 -m mcpgateway.utils.create_jwt_token \
--username admin --exp 10080 --secret my-test-key)
Configure the wrapper via ENV variables:
export MCP_AUTH=${MCPGATEWAY_BEARER_TOKEN}
export MCP_SERVER_URL='http://localhost:4444/servers/UUID_OF_SERVER_1/mcp' # select a virtual server
export MCP_TOOL_CALL_TIMEOUT=120 # tool call timeout in seconds (optional - default 90)
export MCP_WRAPPER_LOG_LEVEL=INFO # DEBUG | INFO | OFF
Configure via Pip or Docker. Note that lauching the wrapper should be done from an MCP Client (ex: via the JSON configuration).
Launching it in your terminal (ex: python3 -m mcpgateway.wrapper
) is useful for testing.
The wrapper now waits for JSON-RPC on stdin and emits replies on stdout.
β Environment Variables¶
Variable | Purpose | Default |
---|---|---|
MCP_SERVER_URL | Comma-sep list of /servers/{id} endpoints | - |
MCP_AUTH | Bearer token the wrapper forwards to Gateway | - |
MCP_TOOL_CALL_TIMEOUT | Per-tool timeout (seconds) | 90 |
MCP_WRAPPER_LOG_LEVEL | OFF , INFO , DEBUG , … | INFO |
π₯ GUI Client Config JSON Snippets¶
You can run mcpgateway.wrapper
from any MCP client, using either python3
, uv
, uvx
, uvx
, pipx
, docker
, or podman
entrypoints.
The MCP Client calls the entrypoint, which needs to have the mcp-contextforge-gateway
module installed, able to call mcpgateway.wrapper
and the right env
settings exported (MCP_SERVER_URL
and MCP_AUTH
at a minimum).
{
"mcpServers": {
"mcpgateway-wrapper": {
"command": "python3",
"args": ["-m", "mcpgateway.wrapper"],
"env": {
"MCP_AUTH": "<paste-token>",
"MCP_SERVER_URL": "http://localhost:4444/servers/UUID_OF_SERVER_1"
}
}
}
}
Use your venv's Python
Replace /path/to/python
with the exact interpreter in your venv (e.g. $HOME/.venv/mcpgateway/bin/python3
) - where the mcp-contextforge-gateway
module is installed.
Add to Settings β Continue: MCP Servers:
{
"mcpgateway-wrapper": {
"command": "/path/to/python",
"args": ["-m", "mcpgateway.wrapper"],
"env": {
"MCP_AUTH": "<token>",
"MCP_SERVER_URL": "http://localhost:4444/servers/UUID_OF_SERVER_1"
}
}
}
(Replace /path/to/python
with your venv interpreter.)
{
"mcpServers": {
"mcpgateway-wrapper": {
"disabled": false,
"timeout": 60,
"type": "stdio",
"command": "uv",
"args": [
"run",
"--directory",
"REPLACE_WITH_PATH_TO_REPO",
"-m",
"mcpgateway.wrapper"
],
"env": {
"MCP_SERVER_URL": "http://localhost:4444/servers/UUID_OF_SERVER_1",
"MCP_AUTH": "REPLACE_WITH_MCPGATEWAY_BEARER_TOKEN",
"MCP_WRAPPER_LOG_LEVEL": "OFF"
}
}
}
}
π Local Development¶
π MCP Inspector¶
π Example call flow¶
- Wrapper maps
get_system_time
β tool ID 123 in the catalog. - Sends RPC to the Gateway with your JWT token.
- Gateway executes the tool and returns JSON β wrapper β stdout.
π§ͺ Manual JSON-RPC Smoke-test¶
The wrapper speaks plain JSON-RPC over stdin/stdout, so you can exercise it from any terminal-no GUI required. Open two shells or use a tool like jq -c | nc -U
to pipe messages in and view replies.
Step-by-step request sequence
# 1οΈβ£ Initialize session
{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},
"clientInfo":{"name":"demo","version":"0.0.1"}
}}
# 2οΈβ£ Ack initialisation (required by MCP)
{"jsonrpc":"2.0","method":"notifications/initialized","params":{}}
# 3οΈβ£ Prompts
{"jsonrpc":"2.0","id":4,"method":"prompts/list"}
{"jsonrpc":"2.0","id":5,"method":"prompts/get",
"params":{"name":"greeting","arguments":{"user":"Bob"}}}
# 4οΈβ£ Resources
{"jsonrpc":"2.0","id":6,"method":"resources/list"}
{"jsonrpc":"2.0","id":7,"method":"resources/read",
"params":{"uri":"https://example.com/some.txt"}}
# 5οΈβ£ Tools (list / call)
{"jsonrpc":"2.0","id":2,"method":"tools/list"}
{"jsonrpc":"2.0","id":3,"method":"tools/call",
"params":{"name":"get_system_time","arguments":{"timezone":"Europe/Dublin"}}}
Sample responses you should see
# Initialise
{"jsonrpc":"2.0","id":1,"result":{
"protocolVersion":"2025-03-26",
"capabilities":{
"experimental":{},
"prompts":{"listChanged":false},
"resources":{"subscribe":false,"listChanged":false},
"tools":{"listChanged":false}
},
"serverInfo":{"name":"mcpgateway-wrapper","version":"0.6.0"}
}}
# Empty tool list
{"jsonrpc":"2.0","id":2,"result":{"tools":[]}}
# ...after adding tools (example)
{"jsonrpc":"2.0","id":2,"result":{
"tools":[
{
"name":"get_system_time",
"description":"Get current time in a specific timezone",
"inputSchema":{
"type":"object",
"properties":{
"timezone":{
"type":"string",
"description":"IANA timezone name (e.g. 'Europe/London')."
}
},
"required":["timezone"]
}
}
]
}}
# Tool invocation
{"jsonrpc":"2.0","id":3,"result":{
"content":[
{
"type":"text",
"text":"{ \"timezone\": \"Europe/Dublin\", \"datetime\": \"2025-06-08T21:47:07+01:00\", \"is_dst\": true }"
}
],
"isError":false
}}