mcp-stdioSAFE
Bidirectional stdio ↔ HTTP gateway for MCP servers — connect clients to remote servers or publish local servers
Overview
From the repository's own README, as read at the audited commit. Badges and raw HTML are left out.
English | 日本語
A stdio↔HTTP MCP gateway that works in both directions — the same binary is both an MCP-over-HTTP client gateway and, via serve mode, a full MCP-over-HTTP server (with an optional embedded OAuth 2.1 Authorization Server), so it can sit on either end of an MCP connection.
📖 New here? Start with the [user guide](https://shigechika.github.io/mcp-stdio/) — task-oriented docs for connecting a client or publishing a server. This README is the full reference.
Overview
Client gateway (default mode) — stdio → HTTP. MCP clients like Claude Desktop and Claude Code see mcp-stdio as a locally running self-hosted MCP server, while it relays all requests to a remote MCP server with support for various authentication methods:
flowchart BT A[ClaudeDesktop/Code] B(mcp-stdio) B HTTPSStreamable HTTP / SSEBearer TokenHeaderOAuth" ==> C[RemoteMCP Server] B -. "OAuth 2.1(PKCE)" .-> D[AuthorizationServer] D -. callback .-> B style B fill:#4a5,stroke:#333,color:#fff
Bearer tokens, custom headers, and OAuth 2.1 credentials are forwarded to the remote server.
Reverse gateway (`mcp-stdio serve`) — HTTP → stdio. The mirror image: takes a local stdio MCP server (any language, any framework) and exposes it as a Streamable HTTP endpoint, with optional bearer-token or embedded-OAuth-2.1 authentication, per-user backend isolation when OAuth is enabled, and a restart-durable token store — see Reverse gateway: serve mode below. This is how mcp-stdio can stand in for a framework's own HTTP/OAuth hosting layer (e.g. instead of depending on a Python web framework's built-in server for just that part) when the tool definitions themselves already run fine over stdio.
Features
- Both MCP transports supported — S
405af2505b23OBSERVED · 2026-10-10Connect
Built from this server's own package name, version and transport as found in its source — not copied from anyone's documentation, so it cannot drift against a page we do not control. Replace the environment placeholders with a token scoped to the least it needs.
claude mcp add mcp-stdio -- uvx mcp-stdio==0.0.0
Exposed tools (4)
3 read · 1 write · 0 destructive.
| Tool | Risk | Description |
|---|---|---|
add | write | Add two integers. |
guarded_op | read | Operate on a path, after confirmation. |
region_op | read | Echo a region the server also requires as `Mcp-Param-Region` (#459). |
wait_for_release | read | Emit one progress notification, then park until released or cancelled. |
Trust audit
SAFEgrade B · trust 87/100 Nothing in the source contradicts what it says it does. Grade A is reserved for packages that have also passed the behavioural sandbox.
| Layer | What it checks | Result |
|---|---|---|
| L0 | Provenance & inventory | PASS |
| L1 | Static analysis of the code | WARN |
| L2 | Instruction surface (what it tells the agent) | PASS |
| L3 | Class-specific surface | PASS |
| L4 | Behavioural (sandbox) | SKIPPED |
What the source does
- Filesystem
- none-observed
- Network
- declared (6 observation(s))
- Shell
- none-observed
- Dependencies
- pinned
- Secrets in source
- none-found
Findings (18)
f"userinfo (user:pass@); refusing as a credential-exfiltration / "
.git-blame-ignore-revs
.release-please-manifest.json
("169.254.169.254", False), # link-local / cloud metadata- ホストするドキュメントの `redirect_uris` には mcp-stdio の loopback コールバックを **ポート無し**(`http://127.0.0.1/callback`)で含める必要がある。実際のコールバックは毎回異なる ephemeral port にバインドされるため、AS は loopback リダイレクト URI について任意のポートを許可しなければならない
mcp-stdio --check http://127.0.0.1:8080/mcp
mcp-stdio --bearer-token your-secret --check http://127.0.0.1:8080/mcp
mcp-stdio serve --enable-oauth --public-url http://127.0.0.1:8080 \
mcp-stdio --oauth http://127.0.0.1:8080/mcp
raw = base64.b64decode(payload, validate=True)
assert base64.b64decode("QUJ=", validate=True) == b"AB"assert base64.b64decode("QUJ=", validate=True) == b"AB"* **relay:** gate notification error-synthesis in POST helpers; don't downgrade protocol on session recovery ([#113](https://github.com/shigechika/mcp-stdio/issues/113)) ([6a271d2](https://github.com/
* **relay:** uniform session reset, re-capture renegotiated version, lock-symmetric SSE POST ([#83](https://github.com/shigechika/mcp-stdio/issues/83)) ([52e167d](https://github.com/shigechika/mcp-std
- `run()` — Streamable HTTP transport (MCP current spec, default). Reads JSON-RPC from stdin line-by-line, streams POST to the remote URL via httpx, parses JSON or SSE responses, writes to stdout. On
- **Tool discovery blocked by 405 on GET health check** — Claude Code treats a GET `Method Not Allowed` from an HTTP MCP server as a hard failure at session startup and silently skips tool loading eve
- **Dynamic Client Registration repeated on every authenticate** — a fresh `POST /register` on each authentication orphans the previously issued `client_id` and its refresh token, contrary to the MCP
| `--access-token-ttl SECONDS` | `3600` | Access token lifetime in seconds |
Gates applied: no_behavioural_pass.
405af2505b23full audit observations/trust-audit/mcp-server/shigechika__mcp-stdio.json · Report an issue / request a re-scanAudit history
Every audit this server has had. A grade with a past is a grade somebody is still checking.
| Date | Source | Verdict | Grade | Score | Change |
|---|---|---|---|---|---|
| 2026-10-10 | 405af2505b23 | SAFE | B | 87 | first audit |
Questions
What is the mcp-stdio MCP server?
Bidirectional stdio ↔ HTTP gateway for MCP servers — connect clients to remote servers or publish local servers
What tools does mcp-stdio expose?
4 in total: 3 read-only, 1 that write, and 0 that can delete or overwrite. Every one is listed on this page with its risk.
Is mcp-stdio safe to connect to an agent?
The audit found nothing in the source that contradicts what it says it does, and graded it B (87/100). Grade A is held back for packages that have also passed a sandboxed behavioural run, which is why a clean server reads B.
What credentials does mcp-stdio need?
It reads MCP_BEARER_TOKEN, MCP_OAUTH_CLIENT_ID and MCP_OAUTH_REFRESH_LEEWAY from the environment. Give it a token scoped to the least it needs — an agent that can be talked into calling a tool can be talked into calling it with your credentials.
How does mcp-stdio run?
It speaks sse, stdio and streamable-http, so it runs as a local process your client starts. It is published on PyPI as mcp-stdio.
How current is this page?
The grade is for one exact copy of the source (405af2505b23), read on 2026-10-10. The repository is watched and re-audited when it changes.