You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Python SDK/docs spell custom MCP server keys install_cmd/run_cmd but the gateway only accepts installCmd/runCmd #1899
Summary: the Python SDK's type hints and the docs spell the custom MCP server config keys install_cmd / run_cmd, but the sandbox's mcp-gateway only recognizes installCmd / runCmd. The SDK passes the dict through verbatim, so the documented Python form is silently ignored and the server never starts.
Versions:e2b 2.50.0 (Python), mcp-gateway template on 2026-09-19.
Inside the sandbox, /var/log/mcp-gateway/gateway.log:
{"level":"warn","caller":"gateway/tools.go:81","msg":"GitHub server missing run command","component":"TOOLS","server":"github/tenuo-ai/tenuo-demos"}
/tmp/installed.txt is never created and tools/list does not include the server. With the same dict spelled installCmd / runCmd, the gateway clones the repo, runs the install command, and advertises the tool as github/tenuo-ai/tenuo-demos-<tool>.
Where the snake_case spelling comes from
e2b/sandbox/sandbox_api.py: GitHubMcpServerConfig declares run_cmd: str and install_cmd: NotRequired[str].
The SDK starts the gateway with mcp-gateway --config <json.dumps(mcp)> (see Sandbox.create), i.e. the keys reach the gateway exactly as typed.
Suggested fix (either):
Have the SDK map install_cmd → installCmd and run_cmd → runCmd before serializing, the way other snake_case fields are mapped to wire names; or
Change the type hints and the Python docs to the camelCase keys the gateway accepts.
Option 1 keeps the documented Python form working. A gateway-side warning that names the offending key would also have made this a two-minute find instead of a log dive.
affected_area: python-sdk/sandbox_api (GitHubMcpServerConfig) + docs "Custom MCP servers" Python example
actionable: yes
needs_clarification: false
summary: The Python SDK types and docs use install_cmd/run_cmd for custom GitHub MCP server config, but the dict is serialized verbatim to mcp-gateway --config, which only accepts installCmd/runCmd, so the documented Python form is silently ignored; fix by mapping keys to camelCase before serialization (preferred, keeps documented form working) or by aligning the type hints and docs with the gateway's keys.
Thanks for the thorough report and repro, @aimable100 — the gateway log line makes the root cause very clear.
I'd like to take this on. My plan is option 1 from the issue: have the SDK map install_cmd/run_cmd to the installCmd/runCmd wire names before serializing (matching how the other snake_case fields are mapped), so the documented Python form keeps working, and align the docs example. I'll apply the equivalent change across the JS SDK and the sync/async Python SDKs per the repo's contribution notes.
If a maintainer would rather go with option 2 (camelCase keys everywhere), happy to adjust.
Thank you again for the report, @aimable100 — your repro made this straightforward to confirm and fix.
I've opened a PR implementing option 1 from the issue: the Python SDK now maps the documented run_cmd / install_cmd keys to the runCmd / installCmd wire names the gateway expects, in both the sync and async create() paths: #1901
The mapping only touches github/owner/repo entries, leaves base server entries and unknown keys (like envs) alone, and the caller's dict is never mutated. Happy to adjust if you'd prefer option 2 (camelCase type hints/docs) instead.
Activity
devin-ai-integration commentedon Sep 26, 2026
Triage
GitHubMcpServerConfig) + docs "Custom MCP servers" Python exampleinstall_cmd/run_cmdfor custom GitHub MCP server config, but the dict is serialized verbatim tomcp-gateway --config, which only acceptsinstallCmd/runCmd, so the documented Python form is silently ignored; fix by mapping keys to camelCase before serialization (preferred, keeps documented form working) or by aligning the type hints and docs with the gateway's keys.Written by Devin
Kylinny commentedon Sep 26, 2026
Thanks for the thorough report and repro, @aimable100 — the gateway log line makes the root cause very clear.
I'd like to take this on. My plan is option 1 from the issue: have the SDK map
install_cmd/run_cmdto theinstallCmd/runCmdwire names before serializing (matching how the other snake_case fields are mapped), so the documented Python form keeps working, and align the docs example. I'll apply the equivalent change across the JS SDK and the sync/async Python SDKs per the repo's contribution notes.If a maintainer would rather go with option 2 (camelCase keys everywhere), happy to adjust.
Kylinny commentedon Sep 26, 2026
Thank you again for the report, @aimable100 — your repro made this straightforward to confirm and fix.
I've opened a PR implementing option 1 from the issue: the Python SDK now maps the documented
run_cmd/install_cmdkeys to therunCmd/installCmdwire names the gateway expects, in both the sync and asynccreate()paths: #1901The mapping only touches
github/owner/repoentries, leaves base server entries and unknown keys (likeenvs) alone, and the caller's dict is never mutated. Happy to adjust if you'd prefer option 2 (camelCase type hints/docs) instead.linear-code commentedon Sep 27, 2026
SDK-116
fix(python-sdk): map GitHub MCP server keys to gateway wire names
fix(python-sdk): map GitHub MCP server keys to gateway wire names