π 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="Bearer ${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": "Bearer <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": "Bearer <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": "Bearer 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.8.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
}}