1.9 KiB
pi-ask-mcp
A minimal MCP stdio server that gives Claude one tool — ask — which routes
structured questions back to pi's native ask UI instead of using Claude's
built-in AskUserQuestion.
This is not a regular pi extension. It is a subprocess of claude, which is
itself a subprocess of the chat-claude extension. The pi-side counterpart is
shared/pi-ask-bridge.ts, which:
- Opens a Unix-domain socket per chat session.
- Generates an
--mcp-configJSON pointing here, withPI_ASK_SOCKET=<sock>. - Translates
askrequests off the socket intoaskSingleQuestionWithInlineNote/askQuestionsWithTabscalls and writes the result back.
Architecture
pi
└── chat-claude
├── pi-ask-bridge (UDS server, owns ui.custom)
└── claude -p ... --mcp-config <generated.json> --disallowed-tools AskUserQuestion
└── pi-ask-mcp/server.js (this file)
↳ on tools/call ask → connect $PI_ASK_SOCKET → ask → reply
Why a hand-written MCP server
No @modelcontextprotocol/sdk dependency, no transpile step, no
node_modules. The MCP stdio protocol is small enough (~6 method handlers)
that writing it directly keeps the file self-contained and trivially
portable. Claude CLI spawns it via node server.js.
Wire format
Stdio (with Claude): JSON-RPC 2.0 over newline-delimited JSON.
Socket (with pi-ask-bridge): NDJSON, one request → one response, then close.
// → pi
{ "id": "uuid", "type": "ask",
"questions": [
{ "id": "auth", "question": "Auth method?",
"options": [{"label": "OAuth"}, {"label": "API key"}],
"multi": false, "recommended": 0 }
] }
// ← pi (success)
{ "id": "uuid", "type": "result",
"results": [{ "id": "auth", "selectedOptions": ["OAuth"] }] }
// ← pi (cancel / error)
{ "id": "uuid", "type": "error", "message": "cancelled" }