Docs
/

@leumas/mcp-bridge

The stdio ⇄ streamable-HTTP bridge — one line in any coding agent's config connects it to a Leumas install, ours or the customer's. Carries no tools of its own.

@leumas/mcp-bridge

<!-- npm:strip -->

Published to npm as leumas-mcp — unscoped, zero dependencies, its two @leumas/* imports inlined by pnpm bridge:build. This package stays private in the workspace for ever; the published manifest is derived, so the two cannot drift. pnpm bridge:release is the gate.

<!-- /npm:strip -->

One line in any coding agent's config, pointed at any Leumas install.

leumas-api speaks MCP over streamable HTTP. Coding agents are not uniform about it — some speak it, some only spawn a subprocess and talk newline-delimited JSON-RPC over its stdio, and the ones that do both configure HTTP differently from each other. This is the subprocess.

leumas-mcp --url https://api.leumas.tech        # Leumas-hosted
leumas-mcp --url http://localhost:3000          # the customer's own Studio
leumas-mcp --url http://localhost:3000 --site my-app   # one hosted MCP server

Because the endpoint is an argument, "our infrastructure or yours" is the same line with a different URL. There is no second server, and no second thing to keep in sync.

What it does, and what it refuses to do

It forwards. Every message goes out verbatim and every response comes back verbatim, so a tool added to an install appears here with no release of this package. That is not laziness — the moment a bridge knows what a tool is, it can be wrong about one.

The one exception, and its physical reason

leumas__deploy is implemented here, not on the server, because the files are on this machine. A remote tool cannot see your dist/, and handing it the bytes as an argument is capped by the /mcp body limit and inflated 4/3 by base64 on top — a mistake this repo has already paid for once, at 78 MB against a 2 MB limit.

It is one tool rather than five because a deploy is an ordered sequence — mint a session, create the site, push N files, retarget, publish — and an agent handed five ordered tools gets the order wrong. The failure is a live site pointed at a half-uploaded build, with nothing reporting an error. So the sequence is code.

leumas__deploy { folder: "/path/to/my-app", name: "my-app" }
  → walks the folder, strips the wrapper, skips node_modules and .env
  → mints a deploy credential scoped to one site and one build directory
  → uploads into builds/<new>, so the live build is untouched throughout
  → points the site at it in ONE write, and publishes
  → returns the live URL

This is the exception that has a physical reason, not the start of a habit. Everything else forwards.

The two rules

1 · stdout is the protocol. One JSON message per line and nothing else, ever. A stray banner or progress line is a parse error inside the agent, and what the person sees is "the MCP server failed to start" with nothing naming the cause. Every human-readable notice goes to stderr — including the usage text, which is why --help writes nothing to stdout.

2 · an HTTP failure must become a JSON-RPC error. The agent is waiting on an id. A 401, a 403 from the gateway scope check, a 502 from a proxy, a refused connection — none of those produce a JSON-RPC envelope of their own. A bridge that logs one and moves on leaves that request pending for ever: the agent does not time out, it simply never answers the person. So every non-2xx, every 200 with a non-JSON body, and every thrown fetch is translated, carrying the id it answers and quoting what the server actually said.

A notification is the one thing that is never answered — not even when it is refused. Answering one makes several clients error out.

Which endpoint a URL means

You passIt posts toWhy
https://api.leumas.tech…/mcp/rpca bare origin means the whole gateway
+ --site abc…/mcp/s/abcone hosted server — the only form that works on a local appliance, where there is no DNS for a subdomain to resolve through
https://api.leumas.tech/mcp/s/abcitselfan explicit path is honoured as given

A URL that does not parse throws. Posting nowhere silently is indistinguishable from a server that has no tools.

Credentials

--key, or $LEUMAS_API_KEY. Mint one at <origin>/connect; it is scoped mcp and reaches the MCP planes and nothing else.

A missing key is a warning, not a refusal — against a local appliance the caller may already be the owner over a session, and a hosted server may be deliberately public. The server's own 401 is a better error than one this bridge could invent, because it is the one that is actually true.

Verify

pnpm smoke:mcp-bridge

Framing and failure are checked on injected streams and a fake fetch; the last section boots the API in-process, mints a key through POST /keys/agent, and drives the real bin/leumas-mcp.mjs as a child process — because neither "does the credential exist" nor "does the spawned binary speak the protocol" can be seen by reading the code.

What it exports

6 exports: 0 components, 0 hooks, 6 helpers. Import from @leumas/mcp-bridge.

forwardmainparseArgsresolveEndpointrunBridgetransportError
Source shared/packages/mcp-bridge/README.md (no-git)markdownjson
Generated from the Leumas repository. Every page cites the file it came from.leumas.techllms.txt