57 lines
1.9 KiB
Markdown
57 lines
1.9 KiB
Markdown
# 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`](../../shared/pi-ask-bridge.ts), which:
|
|
|
|
1. Opens a Unix-domain socket per chat session.
|
|
2. Generates an `--mcp-config` JSON pointing here, with `PI_ASK_SOCKET=<sock>`.
|
|
3. Translates `ask` requests off the socket into
|
|
`askSingleQuestionWithInlineNote` / `askQuestionsWithTabs` calls 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.
|
|
|
|
```jsonc
|
|
// → 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" }
|
|
```
|