mcp-gway
Use MCP Gateway’s Code Mode to lazily discover, inspect, and execute tools from connected MCP servers through one aggregated endpoint.
List virtual
.pyistub files for connected CodeMode servers and tools.Read server- or tool-level stubs to get authoritative callable names and signatures.
Fetch detailed documentation for a specific server tool.
Execute Python-like Starlark code in a sandbox, calling MCP tools as
Server.tool_name(param=value).Run up to 50 independent tool calls in one bounded parallel fan-out, with partial results if some calls fail.
Manage multiple local/remote MCP servers via one registry, CLI, and HTTP/SSE endpoint with admin UI, OAuth, security, and observability features.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@mcp-gwaylist all connected MCP servers"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
MCP Gateway
One endpoint for every MCP server your agent needs — fetch tool schemas on demand instead of loading everything upfront.
MCP Gateway aggregates multiple MCP servers behind a single headless HTTP/SSE endpoint. Its Code Mode exposes five MCP meta-tools (listToolFiles, readToolFile, getToolDocs, executeTool, callManyTool) so agents discover signatures lazily and fan out bounded parallel calls without leaving the MCP surface. The host-side Python call_many helper remains available for direct code use, but the MCP contract exposes callManyTool as the fifth meta-tool.
CLI:
mcp-gway(canonical) ormgw(alias)Admin UI:
mcp-gway serve --transport http→ http://127.0.0.1:8080/
Why MCP Gateway
Fewer wasted tokens — Agents fetch only the schemas they need, when they need them.
One connection to manage — Add, remove, or refresh servers in a single registry; agents connect to one endpoint.
Safe local-first defaults — Binds to
127.0.0.1by default, screens local commands via an allowlist, masks secrets, and CSRF-protects the admin dashboard.
Related MCP server: MCPHub
Who It's For
Agent developers wiring Pi, Antigravity, Claude Desktop, Cursor, or any MCP-compatible client to multiple MCP servers through one gateway.
Operators running local-first infrastructure who want a CLI and dashboard with health probes, Prometheus metrics, and structured JSON logs.
Quick Start
Install:
pip install mcp-gwayAdd a server:
mcp-gway add files --type local --command "npx -y @modelcontextprotocol/server-filesystem /path/to/dir"List servers:
mcp-gway listServe HTTP:
mcp-gway serve --transport httpConnect: Point your agent to
http://127.0.0.1:8080/mcp
For more examples and transports, see the CLI Reference and Integrations.
Features
Multi-Server Aggregation — Connect to multiple MCP servers (local or remote) and expose them through a single endpoint. One URL for every agent; one registry to manage.
Code Mode — Five MCP meta-tools let LLMs discover schemas on demand, execute them in a hermetic sandbox, and fan out bounded parallel calls without loading all tool definitions upfront.
OAuth 2.0 Support — Built-in OAuth flow with Dynamic Client Registration (RFC 7591), secure token storage, and automated
/.well-known/oauth-protected-resourcediscovery metadata (RFC 8707) for OAuth-capable MCP clients.Hexagonal Architecture — Strict separation between pure domain models/ports, application use cases, and infrastructure adapters for isolated unit testability without running servers.
Hermetic Sandbox — Starlark-based sandbox for safe, constrained code execution.
MCP Protocol Compliant — Implements the Model Context Protocol over HTTP, SSE, and stdio.
Local-First Security — Local-first design with SSRF guards, command allow-lists, and CSRF protection.
Built-In Observability — Structured JSON logs, Prometheus metrics, and health probes built in.
Documentation
Configuration & Usage — add servers, transports, and OAuth
CLI Reference — commands, options, and the admin dashboard
Code Mode — lazy-discovery meta-tools and the sandbox
Security — local-first controls and command allow-lists
Observability — JSON logs, Prometheus metrics, health probes
Integrations — Claude Desktop, Pi, Antigravity, OpenCode
Architecture — system diagram and transports
Development — tests, lint, and pre-commit
Development
uv sync --all-groups
uv run pytest -v # 688 testsSee docs/development.md for checks, probes, and pre-commit.
License
Available Tools
5 toolscallManyToolA
Runs up to 50 tool calls in one bounded fan-out (8 concurrent) and returns results in input order. Use it when several calls are independent - across servers or within one - and you want one round trip instead of N. Each item is {server, tool, arguments}; server and tool names are the ones readToolFile shows. A failed item returns ok=false with its error and never cancels its siblings, so a partial result is still usable. Do NOT use it when one call depends on another call's result: write an executeTool script for that.
| Name | Required | Description | Default |
|---|---|---|---|
| calls | Yes | Independent tool calls to run in parallel. Results come back in this order. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does well: it discloses the 50-call cap, 8-way concurrency, result ordering, and failure isolation ("ok=false with its error and never cancels its siblings"). It stops short of timeout behavior, recursion/nesting rules, and whether calls count against any quota.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core behavior, then usage, then failure semantics, then the exclusion — a sensible ordering with no filler sentences. It runs five sentences where four would do, and the readToolFile reference introduces noise.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers usage conditions, limits, ordering, and partial-failure behavior, which is most of what an agent needs to call this safely. With no output schema, the description should say what a successful item looks like (it only documents the ok=false case).
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema already documents the calls array and its server/tool/arguments members, making 3 the baseline. The description adds item shape and ordering semantics, but its claim that server and tool names are "the ones readToolFile shows" is at odds with the schema, which points to listToolFiles — a small ambiguity rather than clear added value.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ("Runs up to 50 tool calls in one bounded fan-out") plus the two defining traits: 8-way concurrency and input-order results. An agent can distinguish it from executeTool and from the file-listing siblings without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit use condition ("when several calls are independent - across servers or within one") and an explicit exclusion plus the alternative ("Do NOT use it when one call depends on another call's result: write an executeTool script"). Names the sibling to switch to.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
executeToolA
Executes Python-like (Starlark) code in a sandboxed interpreter with MCP tool access as Server.tool_name(param=value) (e.g., result = Filesystem.read_file(path=".")). Final step of listToolFiles -> readToolFile -> (optional) getToolDocs -> executeTool; read the stub first and use the exact callable name shown. Security: L1 code validation (no imports/classes/file-IO/network primitives), L2 sandboxed runtime (no external modules, no filesystem/network/process access except via MCP tools, memory isolation), L3 bounded execution timeout, L4 Tool ACL (only tools_to_execute-allowed CodeMode servers/tools are visible). STARLARK RULES: no try/except/raise, no classes, no imports, no f-strings (use % formatting), no is (use ==), synchronous calls only, dict access via result["key"], assign output to result. Each call runs in a FRESH ISOLATED SCOPE (no state persists); print() output is captured to logs. Returns {"result": ..., "logs": [...]}.
| Name | Required | Description | Default |
|---|---|---|---|
| code | Yes | Starlark code calling tools as result = Server.tool_name(param="value") — assign `result` to your final answer |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden and does so: it discloses the four security layers (validation, sandbox, timeout, Tool ACL), states that each call runs in a fresh isolated scope with no persistence, that print() is captured to logs, and that it returns {result, logs}. That is exactly the mutation/execution-risk context an agent needs.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with what the tool does, then workflow, then security, then syntax rules – a logical order with no filler sentences. It is dense and long for a one-param tool, but each block (workflow, ACL, Starlark rules) maps to a distinct failure mode an agent would otherwise hit.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite having no output schema and no annotations, the description specifies the return shape ({result, logs}), the isolation model, the timeout bound, and the ACL gate. Nothing material is missing for an agent to call this correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the single param's description already says to assign `result`, so the baseline would be 3. The description adds real value by constraining the code syntax (no imports/classes/try-except, % formatting, == not `is`, dict access via result["key"]), which genuinely shapes what goes into `code`.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Executes Python-like (Starlark) code in a sandboxed interpreter') plus the distinctive capability of calling MCP tools as Server.tool_name(param=value). Named siblings (listToolFiles, readToolFile, getToolDocs) are positioned in the workflow, so an agent can tell this apart from the discovery tools without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit ordered workflow: listToolFiles -> readToolFile -> (optional) getToolDocs -> executeTool, plus the operational instruction to read the stub first and use the exact callable name shown. It effectively names the alternatives and the precondition that selects this one over them.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
getToolDocsA
Get detailed documentation for a specific tool including full parameter descriptions, types, and usage examples. Use this when the compact signature from readToolFile is not sufficient to understand how to use a tool. Requires both server name and tool name as parameters (e.g., server="filesystem", tool="read_file").
| Name | Required | Description | Default |
|---|---|---|---|
| tool | Yes | The tool you want to explore, like read_file | |
| server | Yes | The server that owns the tool, like filesystem |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are present, so the description carries the burden; it discloses that both server and tool are required and shows the keying convention (server+tool) needed to address a doc record. It doesn't state whether unknown tool names error or return empty, which is the one behavioral gap for a lookup tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, front-loaded with what is returned before the routing condition. The inline server/tool example partly duplicates the schema's own examples, a small redundancy, but nothing is padded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a two-parameter documentation lookup with a fully described schema and no output schema, the description says what comes back (param descriptions, types, examples), when to use it, and what it requires. An agent has everything needed to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so both parameters are already documented with the same filesystem/read_file examples. The description repeats that both are required but adds no format, casing, or ambiguity-resolution guidance beyond the schema, so baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('Get detailed documentation for a specific tool') and enumerates what the output contains (full parameter descriptions, types, usage examples). It also explicitly contrasts with the sibling readToolFile's compact signature, so an agent can distinguish the two without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit trigger ('when the compact signature from readToolFile is not sufficient') and names the alternative tool that covers the other case. Nothing is left to inference about when to escalate from readToolFile to this tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
listToolFilesA
Lists the virtual .pyi stub files for connected CodeMode MCP servers (CodeMode VFS). Default server-level binding returns servers/.pyi per server (e.g., servers/filesystem.pyi); tool-level binding returns servers//.pyi per tool. The filename stem is the exact callable name for executeTool. Workflow: listToolFiles -> readToolFile -> (optional) getToolDocs -> executeTool. In code, call tools as Server.tool_name(param=value) (e.g., Filesystem.read_file(path=".")). CALL THIS FIRST when the user names a server, tool, or capability not in your visible tool list — connected MCP servers are only discoverable here. Do NOT claim a server or capability is unavailable until listToolFiles confirms it is unavailable, then offer the closest alternative from the visible list or explain that it is not connected.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does so: it discloses that the files are virtual VFS stubs, the exact path shape for both server-level and tool-level binding, and the naming contract tying the filename stem to the callable name for executeTool. It also states the discovery scope limit (connected servers only) and the call syntax used downstream.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core statement, then workflow, then the invocation-syntax note; the ordering is good and no sentence is filler. The 'In code, call tools as Server.tool_name(param=value)' sentence drifts into executeTool's territory and is the one piece that could be trimmed or moved.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Zero params, no output schema, and no annotations — so the description must supply everything, and it does: what is returned (path patterns per binding mode), how those paths map to callable names, and where this tool sits in the discovery sequence. Nothing needed to invoke it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so there is nothing for the description to disambiguate and the baseline of 4 applies. The description does useful adjacent work by explaining that output shape varies by binding mode, but that is return-value context rather than parameter meaning.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Lists the virtual .pyi stub files for connected CodeMode MCP servers') and immediately explains the two binding modes that determine what gets listed. This clearly separates it from readToolFile, getToolDocs, and executeTool, which all operate on files this tool enumerates.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit ordered workflow (listToolFiles -> readToolFile -> optional getToolDocs -> executeTool) plus a hard trigger: 'CALL THIS FIRST when the user names a server, tool, or capability not in your visible tool list.' It also supplies a negative rule — do not claim unavailability until this tool confirms it — which is exactly the when-not guidance agents need.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
readToolFileA
Reads a virtual .pyi stub: servers/.pyi for the full server signature list, or servers//.pyi for a single tool (both listed by listToolFiles). Matching is case-insensitive and the .pyi extension is optional. Returns the authoritative callable name and arguments for executeTool as Server.tool_name(param=value). If the compact signature is insufficient, use getToolDocs. Workflow: listToolFiles -> readToolFile -> (optional) getToolDocs -> executeTool.
| Name | Required | Description | Default |
|---|---|---|---|
| endLine | No | Where to stop reading — useful for large servers (leave empty for full view). | |
| fileName | Yes | Stub to read - e.g., servers/filesystem.pyi or servers/filesystem/read_file.pyi | |
| startLine | No | Where to start reading — useful for large servers (leave empty for full view). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the burden and does disclose key behavior: case-insensitive matching, optional .pyi extension, and that the returned signatures are authoritative for executeTool calls. It stops short of error behavior (what happens for an unknown fileName) and does not restate that the operation is non-mutating beyond the verb 'Reads'.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core action and path forms, then constraints, then the workflow sequence. Dense but every sentence carries information; the only mild redundancy is restating the two path shapes that also appear in the schema example.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema and no annotations, so the description must supply the return semantics, which it does ('returns the authoritative callable name and arguments'). Workflow and alternatives are covered; the remaining gap is failure behavior for an invalid or unlisted fileName.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3, but the description adds semantics the schema lacks: fileName values must come from listToolFiles, matching is case-insensitive, and the extension is optional. startLine/endLine are covered by the schema descriptions, so no further description text is required.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Reads') and a specific resource (a virtual .pyi stub), and enumerates the two accepted path shapes (servers/<server>.pyi and servers/<server>/<tool>.pyi). It also names the sibling (listToolFiles) that produces valid inputs, so an agent can distinguish it from listToolFiles and getToolDocs immediately.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit workflow chain: listToolFiles -> readToolFile -> (optional) getToolDocs -> executeTool, plus a concrete condition for escalating ('If the compact signature is insufficient, use getToolDocs'). Both when-to-use and when-to-use-an-alternative are stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
4 tool updates
v6.1.1- Removed
callMany - Added
callManyTool - Added
executeTool - Removed
executeToolCode
5 tool updates
v4.10.2- First observed
callMany - First observed
executeToolCode - First observed
getToolDocs - First observed
listToolFiles - First observed
readToolFile
TDQS
Scored across 5 tools
Each tool occupies a distinct step in the discovery-to-execution workflow: listing stubs, reading signatures, fetching detailed docs, executing a script, and fan-out execution. The boundaries between executeTool and callManyTool are explicitly clarified by dependency/fan-out guidance. No two tools appear to do the same thing.
All names use camelCase with a verb+object pattern (get, list, read, execute, call). There are minor deviations in object naming, such as singular/plural differences and the inserted 'Many' in callManyTool, but the convention is still readable and predictable.
Five tools is well-scoped for a gateway server that needs discovery, documentation inspection, single execution, and batch execution. Each tool has a clear role and none feels redundant or missing from the core workflow.
The surface covers the full gateway lifecycle: discover connected servers/tools, read authoritative callable signatures, fetch deeper documentation, execute a single script, and fan out independent calls. No obvious operational gap or dead end is apparent for the stated CodeMode gateway purpose.
Maintenance
Related MCP Connectors
Managed MCP gateway with OAuth, per-agent permissions, shared accounts and activity logs.
Host any HTTP API as a standard MCP server; auto-distribute to 12+ mainstream agent platforms.
- MeandrOAuthcom.meandr
MCP gateway and cloud hosting for MCP servers, agents and apps like RAG, managed from your agent.
One OAuth connector for your team's remote MCP servers, with Tool Packs, guardrails and logs.
Related MCP Servers
- AlicenseBqualityCmaintenanceAggregates multiple MCP servers via a single interface with token optimization and multiple operating modes (Gateway, Meta, Proxy, Search, Code).78MIT
- AlicenseNot gradedqualityBmaintenanceCentralized management and routing of multiple MCP servers via unified Streamable HTTP/SSE endpoints, with granular group visibility, smart routing, and authentication.2,698 npmApache 2.0
- AlicenseNot gradedqualityAmaintenanceAggregates and routes requests across multiple backend MCP servers, exposing their combined tools and resources through unified SSE, Streamable HTTP, or Stdio endpoints. Supports optional Web UI management, granular tool control, and endpoint authentication.105 npmMIT
- AlicenseNot gradedqualityAmaintenanceEnables aggregating and routing multiple backend MCP resource servers so clients can access their combined tools and resources through a unified SSE, Streamable HTTP, or Stdio interface, with optional authentication and web-based management.105 npmMIT