快速了解
它能做什么
通过 JSON-RPC 在 Shell 脚本或 CI 中直接调用任何 stdio MCP 服务的工具。
本站提供的是中文说明,不代表该项目或 Plugin 自身提供中文界面;语言支持请以上游文档为准。
选择前先看
该技能提供可直接改造的 Python 客户端模式:启动 stdio MCP 服务、发送 initialize 与 initialized 消息、列出可用工具、调用工具并读取响应。还包含 uvx、npx 启动示例,以及 MiniMax MCP 的完整示例。
适合谁
需要在 Shell、CI 运行器、工作节点或未预加载 MCP 工具的会话中访问 MCP 工具的开发者。
常见任务
- 在将 stdio MCP 服务加入运行环境前先进行测试。
- 从 CI 任务或 Shell 脚本调用 MCP 工具。
- 列出 MCP 服务的工具 schema 并调用选定工具。
- 排查 JSON-RPC 握手、超时、环境变量和响应解析问题。
权限与数据
会启动本地子进程,并通过标准输入和标准输出交换 JSON-RPC 消息。
权限- 需要执行所选 MCP 服务启动器及其软件包的权限。
- 仅在目标服务需要时读写相应位置,例如配置的输出目录。
- 工具参数和服务响应会经过本地脚本的标准输入/输出流。
- 环境变量可能包含服务专用凭据。
- 所选 MCP 服务可能会连接其自身的外部服务;MiniMax 示例使用具备网页搜索能力的服务。
- 通用客户端模式本身不要求凭据。
- 具体 MCP 服务可能需要凭据;MiniMax 示例需要 MINIMAX_API_KEY。
局限
- 仅适用于 stdio 传输;HTTP/SSE MCP 服务需要不同的客户端方案。
- 使用 OAuth 或动态注册的服务可能需要本技能未涵盖的令牌刷新处理。
- 文档中的纯 Shell 示例明确不如 Python 客户端稳健。
- 根据所提供的许可证,商业使用仓库软件需要另行取得商业许可证。
DSHub 已核对
- 固定 GitHub 提交中的技能文档已被采集。
- 文档包含作者声明已端到端验证的 MiniMax MCP 示例。
DSHub 未核对
- DSHub 未执行该客户端、安装软件包或验证任何目标 MCP 服务。
- 未独立验证其与特定 MCP 服务、凭据和传输方式的兼容性。
固定版本安装
主要操作
这个独立 Skill没有 DSH Plugin 安装操作,请根据源码文档使用真实交付方式。
维护者原文
Skill 使用说明
name: mobius-mcp-stdio-invocation
description: Invoke any MCP (Model Context Protocol) server directly from the CLI via stdio JSON-RPC, with no Claude Code / harness dependency. Use when you need to call MCP tools (web search, image understanding, file ops, custom tools) from a shell script, CI job, or a session that doesn't have the MCP auto-loaded. Covers: installing uv/uvx (or npx), spawning the server, the JSON-RPC 2.0 handshake, tools/list discovery, tools/call invocation, and result parsing — with the MiniMax minimax-coding-plan-mcp package as a verified worked example.
MCP stdio invocation from the CLI
MCP servers speak JSON-RPC 2.0 over stdio — the server's stdin is the request stream, stdout is the response stream, stderr is for human logs. Any process that can spawn a subprocess and read/write its stdio can be an MCP client. You do not need Claude Code, Cursor, or any harness to use them.
This SKILL is the recipe for "I want to call MCP tool X, from a shell, right now."
When to use
- Your session has no
mcp__*tools registered (e.g. a CI runner, a worker session, an ad-hoc bash turn). - You want to script MCP tool calls in a pipeline.
- The MCP server supports stdio transport (most do; SSE/HTTP transports are a separate path).
- You want to verify an MCP works before registering it with
claude mcp add.
If the server is already loaded into your harness as mcp__server__tool, just call it directly — don't reinvent the stdio pipe.
Protocol summary (MCP 2024-11-05)
Three-step handshake, then arbitrary tools/list / tools/call:
1. request initialize → response with serverInfo + capabilities
2. notify notifications/initialized (no response, just a fire-and-forget)
3. request tools/list → response with tool schemas
request tools/call → response with content blocks
All frames are single-line JSON. One request → one response, matched by id. Notifications (no id) get no reply. Use select() or non-blocking reads to avoid deadlock when the server logs to stderr.
Frame shapes
// request
{"jsonrpc":"2.0","id":1,"method":"initialize","params":{...}}
// notification
{"jsonrpc":"2.0","method":"notifications/initialized","params":{}}
// success response
{"jsonrpc":"2.0","id":1,"result":{...}}
// error response
{"jsonrpc":"2.0","id":1,"error":{"code":-32601,"message":"Method not found"}}
tools/call result is result.content — an array of content blocks. Text blocks are stringified JSON that you must re-parse:
{"result":{"content":[{"type":"text","text":"{\n \"organic\": [...]\n}"}]}}
Install the launcher
MCP servers are usually published as a Python or Node package with a command entry point.
| Ecosystem | Install | Spawn command |
|---|---|---|
PyPI (uvx) |
curl -LsSf https://astral.sh/uv/install.sh | sh (one-time) |
uvx --from <pkg> <entrypoint> -y |
npm (npx) |
comes with Node | npx -y <pkg> |
uvx and npx both (1) create an ephemeral venv/cache, (2) install the package on first run, (3) execute the entrypoint, (4) clean up on exit. The -y flag auto-confirms any "install?" prompt.
After installing uvx, verify with which uvx → expect a path like /home/<user>/.local/bin/uvx.
Generic Python harness
Drop this into a script and point it at any stdio MCP server. Replace COMMAND, ENV, and the tool name you want to call.
# mcp_invoke.py — minimal MCP stdio client
import json, os, subprocess, sys, time, select
COMMAND = ["uvx", "--from", "<PACKAGE>", "<ENTRYPOINT>", "-y"] # e.g. uvx --from minimax-coding-plan-mcp minimax-coding-plan-mcp -y
ENV_OVERRIDES = { # MCP-specific env vars; the server reads these
# "API_KEY_ENV_NAME": "sk-...",
# "BASE_URL_ENV_NAME": "https://...",
}
def call_tool(name, arguments, *, timeout=60):
env = os.environ.copy()
env.update(ENV_OVERRIDES)
proc = subprocess.Popen(
COMMAND,
stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
env=env, text=True, bufsize=1,
)
def send(req):
proc.stdin.write(json.dumps(req) + "\n"); proc.stdin.flush()
def recv(timeout_s=timeout):
end = time.time() + timeout_s
while time.time() < end:
r,_,_ = select.select([proc.stdout], [], [], 0.5)
if r:
line = proc.stdout.readline()
if line: return json.loads(line)
raise TimeoutError("no MCP response")
try:
send({"jsonrpc":"2.0","id":1,"method":"initialize","params":{
"protocolVersion":"2024-11-05",
"capabilities":{},
"clientInfo":{"name":"mcp-invoke","version":"0.1.0"},
}})
recv() # initialize result
send({"jsonrpc":"2.0","method":"notifications/initialized","params":{}})
send({"jsonrpc":"2.0","id":2,"method":"tools/call","params":{
"name": name, "arguments": arguments,
}})
return recv()
finally:
proc.terminate()
try: proc.wait(timeout=5)
except subprocess.TimeoutExpired: proc.kill()
if __name__ == "__main__":
result = call_tool("<tool_name>", {"<arg>": "<value>"})
print(json.dumps(result, ensure_ascii=False, indent=2))
Discovery variant: list tools first
If you don't know the tool names, swap the tools/call for tools/list:
send({"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}})
tools_resp = recv()
for t in tools_resp["result"]["tools"]:
print(t["name"], "—", t.get("description","")[:80])
Then drive tools/call based on what you see.
Worked example: MiniMax Token Plan MCP
Verified end-to-end on 2026-06-10 in an imac-test session that had no MCP auto-loaded.
| Field | Value |
|---|---|
| Package | minimax-coding-plan-mcp (PyPI) |
| Server | Minimax v1.27.2, protocol 2024-11-05 |
| Env vars | MINIMAX_API_KEY (required), MINIMAX_API_HOST (default https://api.minimaxi.com), MINIMAX_MCP_BASE_PATH (local output dir, must exist + writable), MINIMAX_API_RESOURCE_MODE (url / local) |
| Tools | web_search(query), understand_image(prompt, image_url) |
Spawn command:
MINIMAX_API_KEY="sk-cp-..." \
MINIMAX_API_HOST="https://api.minimaxi.com" \
MINIMAX_MCP_BASE_PATH="/tmp/mcp-out" \
MINIMAX_API_RESOURCE_MODE="url" \
uvx --from minimax-coding-plan-mcp minimax-coding-plan-mcp -y
Call shape (web_search):
{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{
"name":"web_search",
"arguments":{"query":"<3-5 keywords, include date for time-sensitive>"}
}}
Response shape (web_search result is a stringified JSON inside content[0].text):
{
"result": {
"content": [
{"type": "text", "text": "{\"organic\":[{\"title\":...,\"link\":...,\"snippet\":...,\"date\":...}],\"related_searches\":[...],\"base_resp\":{...}}"}
]
}
}
So: r["result"]["content"][0]["text"] → json.loads(...) → organic[].
Real latency observation: web_search for a current-events query round-trips in 5–15 s (it's a search backend call, not local compute).
Recipe: register for future sessions (optional)
Once you've verified the server works over stdio, you can pin it to user-level Claude Code so future sessions auto-load it. The update-config skill (or claude mcp add on the CLI) writes ~/.claude.json:
claude mcp add -s user MiniMax \
--env MINIMAX_API_KEY=sk-cp-... \
--env MINIMAX_API_HOST=https://api.minimaxi.com \
-- uvx minimax-coding-plan-mcp -y
After this, new sessions get mcp__MiniMax__web_search and mcp__MiniMax__understand_image tools. The current session won't pick it up — MCPs are loaded at Claude Code startup.
Common pitfalls
- No response, then timeout — server is waiting for the
initializednotification and you didn't send it. Always send the notification betweeninitializeand any other request. - Method not found (
-32601) — wrong protocol version ininitialize.2024-11-05is the current default; some older servers want2024-10-07or2025-03-26. Check the server's docs. - Response looks like a dict, not a list — you got a
resultobject; the actual tool output isresult.content[0].text(always a string, often JSON inside). - Stderr is silent — many MCP servers log useful info (retry counts, rate limits) to stderr. Tee it:
stderr=subprocess.PIPEand read on timeout. - Env var not picked up — servers usually read env only at startup. Set them before spawning. Mutating
os.environafterPopenis too late. uvxnot found — install with the one-liner above; it lands in~/.local/bin/uvx, which is not on every shell's defaultPATH. Prefixexport PATH="$HOME/.local/bin:$PATH".- Server hangs after first call — JSON-RPC needs newline-delimited frames.
text=True, bufsize=1and a"\n"after everyjson.dumps(req)are mandatory. - Output files cluttering the repo —
MINIMAX_MCP_BASE_PATHdefaults to./.trashfor the MiniMax MCP; point it at/tmp/...or your.imac/scratch/to keep the project clean. - Auth key leakage in logs — many MCP servers log the env var name (not the value) on startup. Fine, but don't
set -xthe parent shell if the value is sensitive.
Pattern: shell-only quick call
If you don't want a Python script, you can drive the JSON-RPC stream straight from bash with jq + heredocs. Less robust (no error handling) but useful for one-offs:
KEY="sk-cp-..."
{
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"cli","version":"0"}}}'
echo '{"jsonrpc":"2.0","method":"notifications/initialized","params":{}}'
echo '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"web_search","arguments":{"query":"today news"}}}'
sleep 20
} | MINIMAX_API_KEY="$KEY" MINIMAX_API_HOST="https://api.minimaxi.com" \
MINIMAX_MCP_BASE_PATH="/tmp/mcp-out" \
uvx --from minimax-coding-plan-mcp minimax-coding-plan-mcp -y \
2>/dev/null | head -1
The first line of stdout is the initialize response; you'll need a longer-lived pipe (e.g. coproc or a temp file per request) to map request ids to responses properly. Use the Python harness for anything non-trivial.
Generalizing beyond MiniMax
The exact same recipe works for any stdio MCP server. Substitutions:
| What you change | Where |
|---|---|
COMMAND list |
["uvx", "--from", "<pkg>", "<entry>", "-y"] or ["npx", "-y", "<pkg>"] |
ENV_OVERRIDES |
whatever env vars the server's docs list (auth keys, base URLs, output paths) |
name in tools/call |
the tool name from tools/list |
arguments in tools/call |
the JSON schema from tools/list |
If tools/list returns nested argument schemas (objects, enums, arrays), feed them straight into the arguments dict — the harness serializes them for you.
When not to use this
- The MCP server is HTTP/SSE transport, not stdio. The handshake is different; you'll need an HTTP client.
- The server requires OAuth / dynamic client registration. Stdio servers usually take a static API key; OAuth servers (e.g. some Google/Microsoft ones) need a token-refresh loop.
- The tool produces binary outputs (audio, video, images). Stdio JSON-RPC can carry base64, but it's clumsy — for big media, prefer the underlying HTTP API directly.
- You're already in a session where the MCP is auto-loaded. Just use the registered
mcp__server__tool— no subprocess needed.
有意识地管理
安装与管理
前置条件与目标 Profile
目标: 终端 Profile
交付方式: Skill 文件 — https://raw.githubusercontent.com/nutshellai-tech/mobius/1eb8750d2d9012e1f50a18f7c60c2ad040c04889/skills/mobius-mcp-stdio-invocation/SKILL.md。
兼容性与访问范围
Works with stdio-transport MCP servers; no harness is required: Not declared in supplied evidence。
风险事实
证据与编辑审查Manifest、Bundle patch、分发与新鲜度
不可变证据
审查状态与源码活动
在核对来源内容和不可变发布记录后,已由人工批准发布。AI 参与了内容草稿生成,最终发布决定由人工完成。
人工审查于 2026/9/4 UTC 11:38。GitHub 事实核对日期: 2026/9/3 UTC 15:47。
自当前证据基线以来,没有记录到重要源码变化。