Atlas / MCP servers / shigechika / mcp-stdio

mcp-stdioSAFE

mcp/shigechika/mcp-stdio

Bidirectional stdio ↔ HTTP gateway for MCP servers — connect clients to remote servers or publish local servers

Verdict
SAFE
Grade
B
Trust score
87 /100
Exposed tools
4 3r · 1w · 0d
Transport
sse · stdio · streamable-http
License
MIT
Stars
8
01

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
Read from source at commit 405af2505b23OBSERVED · 2026-10-10
02

Connect

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-code (pypi)
claude mcp add mcp-stdio -- uvx mcp-stdio==0.0.0
03

Exposed tools (4)

3 read · 1 write · 0 destructive.

ToolRiskDescription
addwriteAdd two integers.
guarded_opreadOperate on a path, after confirmation.
region_opreadEcho a region the server also requires as `Mcp-Param-Region` (#459).
wait_for_releasereadEmit one progress notification, then park until released or cancelled.
04

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.

LayerWhat it checksResult
L0Provenance & inventoryPASS
L1Static analysis of the codeWARN
L2Instruction surface (what it tells the agent)PASS
L3Class-specific surfacePASS
L4Behavioural (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)

MEDIUMNetwork egress · net.beacon_words · CWE-200, CWE-319
src/mcp_stdio/oauth.py:322
f"userinfo (user:pass@); refusing as a credential-exfiltration / "
LOWInventory / provenance · inv.hidden_file · CWE-1104
.git-blame-ignore-revs
.git-blame-ignore-revs
Why it matters. hidden member outside the usual dotfiles
Fix. review its purpose
LOWInventory / provenance · inv.hidden_file · CWE-1104
.release-please-manifest.json
.release-please-manifest.json
Why it matters. hidden member outside the usual dotfiles
Fix. review its purpose
LOWNetwork egress · net.metadata_ip · CWE-200, CWE-319
tests/test_server.py:4349
("169.254.169.254", False),  # link-local / cloud metadata
Why it matters. cloud metadata endpoint: the classic SSRF credential grab
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
README.ja.md:63
- ホストするドキュメントの `redirect_uris` には mcp-stdio の loopback コールバックを **ポート無し**(`http://127.0.0.1/callback`)で含める必要がある。実際のコールバックは毎回異なる ephemeral port にバインドされるため、AS は loopback リダイレクト URI について任意のポートを許可しなければならない
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
README.ja.md:307
mcp-stdio --check http://127.0.0.1:8080/mcp
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
README.ja.md:348
mcp-stdio --bearer-token your-secret --check http://127.0.0.1:8080/mcp
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
README.ja.md:357
mcp-stdio serve --enable-oauth --public-url http://127.0.0.1:8080 \
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
README.ja.md:359
mcp-stdio --oauth http://127.0.0.1:8080/mcp
LOWObfuscation / stealth · obf.decode_call · CWE-506, CWE-94
src/mcp_stdio/relay.py:792
raw = base64.b64decode(payload, validate=True)
LOWObfuscation / stealth · obf.decode_call · CWE-506, CWE-94
tests/test_relay.py:10498
assert base64.b64decode("QUJ=", validate=True) == b"AB"
LOWObfuscation / stealth · obf.decode_call · CWE-506, CWE-94
tests/test_server_modern.py:761
assert base64.b64decode("QUJ=", validate=True) == b"AB"
LOWPrompt injection · prompt.transfer_instruction · CWE-94, CWE-1427
CHANGELOG.md:482
* **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/
Why it matters. an instruction to move sensitive data to an outside destination
Fix. remove; a skill never needs the user's secrets off the machine
LOWPrompt injection · prompt.transfer_instruction · CWE-94, CWE-1427
CHANGELOG.md:499
* **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
Why it matters. an instruction to move sensitive data to an outside destination
Fix. remove; a skill never needs the user's secrets off the machine
LOWPrompt injection · prompt.transfer_instruction · CWE-94, CWE-1427
CLAUDE.md:49
- `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
Why it matters. an instruction to move sensitive data to an outside destination
Fix. remove; a skill never needs the user's secrets off the machine
LOWPrompt injection · prompt.transfer_instruction · CWE-94, CWE-1427
WORKAROUNDS.md:19
- **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
Why it matters. an instruction to move sensitive data to an outside destination
Fix. remove; a skill never needs the user's secrets off the machine
LOWPrompt injection · prompt.transfer_instruction · CWE-94, CWE-1427
WORKAROUNDS.md:26
- **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
Why it matters. an instruction to move sensitive data to an outside destination
Fix. remove; a skill never needs the user's secrets off the machine
INFOPrompt injection · prompt.credential_read · CWE-94, CWE-1427
docs/reference.md:123
| `--access-token-ttl SECONDS` | `3600` | Access token lifetime in seconds |
Why it matters. asks the agent to read credentials

Gates applied: no_behavioural_pass.

Audited 2026-10-10 · audit v0.4.1 · source sha 405af2505b23full audit observations/trust-audit/mcp-server/shigechika__mcp-stdio.json · Report an issue / request a re-scan
05

Audit history

Every audit this server has had. A grade with a past is a grade somebody is still checking.

DateSourceVerdictGradeScoreChange
2026-10-10405af2505b23SAFEB87first audit
06

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.

Advertisement