Files
dotfiles/pi/.pi/agent/extensions/pi-ask-mcp/README.md
2026-04-24 14:22:59 +02:00

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:

  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.

// → 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" }