Phaedo Mcp

io.github.phaedo-labs由 GitHub 帳號 phaedo-labs 發布v0.3.23更新於 Nov 8, 2026

Make AI apps answer your way, check with you before acting, and get approvals on your phone.

概覽

AI 產生的概覽

為 AI 助理提供你的個人偏好側寫,讓回覆符合你的風格,並在執行動作前先徵求你的同意。

可以做什麼
  • 載入並注入個人側寫,讓回覆符合你偏好的長度、語氣和格式
  • 在代理執行動作前查詢側寫,並記錄你核准、拒絕或修改的決定
  • 把不確定的動作推送到已配對的手機,即時選擇核准、拒絕或修改,再輪詢結果
  • 用常設授權做快速預檢,並請求簽署付款授權,回傳前會驗證簽章
  • 以資源形式讀取側寫,或用一鍵提示詞插入側寫
適用情境
適合希望 Claude Desktop、Claude Code、Cursor 等 MCP 用戶端遵循你的個人風格,並在合併、部署、發布或花錢等重要動作前先詢問你的情境。也適合需要手機核准或簽署付款權限的代理工作流程。
執行需求
透過 npm 套件 phaedo-mcp 以 stdio 在本機執行,需要 Node.js(Claude Desktop 自帶)。需要一份側寫:來自尚未公開的 Phaedo 手機應用程式,或由你自己的 Claude Code 工作階段產生的初始側寫;也可載入範例側寫試用。與手機配對需應用程式在同一個 Wi-Fi 下可連線,或使用輸入的配對碼。
安裝前請注意
核准與付款權限依賴手機應用程式,一旦記錄決定,代理即可代你行動。本機狀態目錄保存金鑰檔案和加密的側寫快取,README 說明原始金鑰存放在磁碟上。選用掛鉤會讀取 Claude Code 工作階段紀錄,並寫入指令檔到其他工具的設定目錄;擷取需主動開啟且只保留計數。請安裝 0.3.0 或更新版本,早期 0.2.x 版本無法啟動。

安裝

在 SourceWeft 中

  1. 開啟 儀表板中的 Phaedo Mcp,將其新增到工作區。
  2. 為需要使用其工具的對話啟用該服務。

Desktop only,透過 STDIO。 STDIO 服務會啟動本機處理程序,因此需要 SourceWeft 桌面主機。

其他 MCP 客戶端

參照 儲存庫 中的啟動說明。

README

Phaedo MCP server (phaedo-mcp)

Phaedo learns how you write, work and decide, and keeps that profile on your phone. This server lets your AI apps use it: Claude Desktop, Claude Code, Cursor, and any other app that supports MCP. With it, they can:

  • Answer the way you like — your preferred length, tone and format, without you repeating it in every chat.
  • Check with you before acting — an AI agent asks Phaedo whether you'd want it to go ahead. When it's unsure, your phone gets an approve / deny card.
  • Learn from your answers — each approve or deny teaches it how you want work handled when you're not watching.
  • Get your signature for purchases — you sign a spending permission on your phone with Face ID; the agent never holds the key.

Your profile comes from your phone encrypted. The copy kept on this computer, for when your phone is offline, is encrypted too.

What you need

  1. A profile, from either:
    • the Phaedo phone app — your full profile lives there. The app isn't open to the public yet; phaedo.so has a link to hear when it is.
    • your own Claude Code sessions — no phone needed. Phaedo builds a starter profile on this computer from how you work in Claude Code (see Install).
  2. Node.js, free from nodejs.org (the LTS button), for Claude Code and other apps. Claude Desktop brings its own.

With neither, there is no profile, and the server says so plainly rather than guessing. You can still try Phaedo with a made-up example profile.

Install

Claude Code (and Cowork) — run these two commands in Terminal:

bash
claude plugin marketplace add phaedo-labs/phaedo-mcp
bash
claude plugin install phaedo@phaedo

Then start a new Claude Code session. That's all: Phaedo loads your profile at the start of each session, checks with you before Claude merges, deploys or publishes, and learns from how you work. Without the phone app, it builds a starter profile from your own sessions (for example, that you want short answers without headers). It starts thin and grows as you work. In Claude Code, type /phaedo:status to see how far along it is, and /phaedo:pair to pair the phone app.

Claude Desktop — download phaedo.mcpb and double-click it. Claude Desktop shows what it installs and asks you to confirm. Node.js comes with Claude Desktop, so nothing else is needed. Desktop uses the same profile and pairing as the Claude Code plugin on this computer.

Other apps (Cursor and others) — see Use your own profile in other apps below, or the manual setup under Reference.

What Phaedo reads stays on this computer: each Claude Code session is reduced to counts (like "asked for a shorter answer, 4 times"), and the text itself is discarded. If you pair the phone app later, your full profile replaces the starter one and keeps what it learned.

Try it with the example profile (no phone needed)

This loads a made-up person's profile, so you can see what Phaedo adds before you have your own.

Claude Code — run this in Terminal (it applies to all your projects):

bash
claude mcp add -s user phaedo -e PHAEDO_FINGERPRINT=sample -- npx -y phaedo-mcp

Claude Desktop — open Settings → Developer → Edit Config, add the phaedo entry below inside mcpServers, save, then quit and reopen Claude Desktop:

json
{  "mcpServers": {    "phaedo": {      "command": "npx",      "args": ["-y", "phaedo-mcp"],      "env": { "PHAEDO_FINGERPRINT": "sample" }    }  }}

If Claude Desktop reports that the server failed to start, it couldn't find npx. Replace "npx" with the full path that this prints:

bash
which npx

Then start a new chat and ask: "Load my Phaedo profile." To stop using the example, delete the env line in Claude Desktop, or in Claude Code run claude mcp remove -s user phaedo and add it again without -e …. The server will then tell you there's no profile until you pair your phone.

Use your own profile in other apps (with the phone app)

  1. Get this folder. On the GitHub page, click Code → Download ZIP, unzip it, and open the mcp folder inside.

  2. Run the installer.

    • macOS: double-click installers/macos/Install Phaedo MCP.command. If macOS says it can't be opened, right-click it and choose Open.
    • Windows: double-click installers/windows/Install Phaedo MCP.bat.
    • Linux: run bash installers/linux/install-phaedo-mcp.sh.

    It adds Phaedo to Claude Desktop, Cursor and Claude Code — keeping your other settings, and backing each file up first — then starts pairing. (In Claude Code and Claude Desktop, the plugin and the .mcpb above are simpler; use one route per app, not both.)

  3. Pair with your phone. Open Phaedo on your phone. On the same Wi-Fi, approve "Phaedo MCP Server" and check that the code matches the one in Terminal. On a different network, tap Pair with code and type the code Terminal shows.

  4. Quit and reopen your AI apps, start a new chat, and ask: "Load my Phaedo profile."

You can disconnect this computer at any time from the Agents screen on your phone.

Learn from your ChatGPT or Claude history

bash
npm run import -- ~/Downloads/your-export.zip

Get the file from ChatGPT (Settings → Data controls → Export data) or Claude (Settings → Privacy → Export data); each emails a zip. Phaedo reads the last year of conversations (--all for everything, --dry-run to count first) through the same on-device detectors as Claude Code capture, keeps only the counts, and discards the text — delete the export afterwards. Importing the same file again replaces, never doubles. Paired: the patterns go to your phone. Not paired: they become your starter profile. In the Claude Code plugin, it's /phaedo:import.

See what Phaedo learned — keep it or remove it

bash
npm run learned

Lists what Phaedo inferred from how you work (not your interview answers or your rules), one plain sentence each, and flags pairs that disagree ("favor speed" vs "favor quality"). npm run learned -- --remove 3,5 stops those shaping answers and decisions on this computer — the list is applied every time the profile loads, so a pattern your sessions keep showing stays removed. --keep all marks the rest reviewed; --forgotten and --restore <n> undo. /phaedo:status says when there are new things to look at. To remove something from the phone's profile itself, use the Phaedo app. In the Claude Code plugin, it's /phaedo:learned.

Give agents without MCP the same profile

Codex, Copilot CLI, Gemini CLI and Antigravity each read a personal instructions file at the start of every session. One command writes a short version of your profile (your rules and how you like answers) into each one found on this computer:

bash
npm run rules

It goes into ~/.codex/AGENTS.md, ~/.copilot/copilot-instructions.md and ~/.gemini/GEMINI.md (shared by Gemini CLI and Antigravity), inside a marked block; the rest of each file is left alone. Cursor has no personal file, so name a project: npm run rules -- --project ~/code/app writes .cursor/rules/phaedo.mdc and keeps it out of git. Phaedo refreshes these files whenever a Claude Code session starts with Phaedo on, and only those you set up. npm run rules -- --dry-run shows the text first; npm run rules -- --remove takes it out. In the Claude Code plugin, it's /phaedo:rules.


Reference

Everything below is for developers: the full tool list, how the profile is loaded, and the test suite.

The server implements the MCP binding of the Anamnesis protocol (docs/protocol/mcp-binding.md §3.1):

SurfaceNameReturns
toolphaedo_request_injection§9.2 request → §9.3 Injection Response
resourcephaedo://fingerprint/projectiondefault projection (all layers, standard)
promptphaedoone-click /phaedo — inserts the projection as a message
toolphaedo_consult§10.2 request → §10.3 Consultation signal (never layer content)
toolphaedo_check_authorizationdeterministic-only pre-flight: does a standing authorization (§10.5) already decide this action? (no inference)
toolphaedo_escalaterun the consult and, on a blocking signal (escalate, or a consequential clarify), wake the subject's paired device for a live approve / deny / modify; returns a request_id (non-blocking). Safe default on no answer: hold.
toolphaedo_escalation_statuspoll an escalation by request_id; on resolution records the subject's live decision as the §10.6 outcome automatically (a real-time approve/deny is the strongest act-as-me signal).
toolphaedo_record_outcome§10.6 — record what the SUBJECT decided about a consulted action (approved/rejected/modified/unknown). A rejected/modified outcome teaches the act-as-me channel (how the user wants delegated work handled).
toolphaedo_sign_mandate§8.3 — ask the subject to sign an AP2 Intent Mandate built from their standing authorizations (a verifiable payment credential). Deposits the request and returns a request_id + the unsigned mandate (non-blocking). The subject signs on their phone in the Secure Enclave, or declines.
toolphaedo_sign_statuspoll a phaedo_sign_mandate request by request_id (+ the returned mandate); returns the mandate carrying a verified signature once signed, refused if declined, or pending/expired. The signature is checked against the subject's published signing key before it is returned.

The projection is rendered by the same context-block.js the extension injects, so MCP injection is byte-identical to web injection.

Status

The phases below track the fingerprint source (how the server obtains the fingerprint). The consultation, real-time escalation, act-as-me / delegation, and receipts-audit surfaces (the tools table above) shipped on top of these across the 0.2.x line, and the §8.3 signing pair in 0.3.0 — see CHANGELOG.md.

Install 0.3.0 or later. 0.2.0, 0.2.1 and 0.2.2 were published with three modules missing from the package, so they exit with ERR_MODULE_NOT_FOUND instead of starting. 0.3.0 is the first working release since 0.1.1, and test-package-closure.mjs now boots the packed tarball in CI.

  • Phase 1a (this cut): reads the fingerprint from a local JSON file (see Fingerprint source). Lets injection work in a real client today, no crypto.
  • Phase 1b-i (done): the spec-faithful key boundary — authorize → pull /v1/profile → unwrap the §7.2 envelope from the paired phone, reusing the repo crypto modules (protocol/envelope/kdf/identity.js) in node. The decrypted fingerprint stays in memory (never written to disk). Auto-selected when a pairing record is configured (see Fingerprint source). Plan + decisions: ../docs/roadmap/mcp-1b-plan.md.
  • Phase 1b-iii (done): encrypted at-rest cache — a successful phone pull caches the fingerprint as ciphertext under a server-held key; when the phone is unreachable the server serves that cache, so it works phone-absent (frictionless default; mirrors the extension's Option C — defense-in-depth, NOT phone-gated). State dir defaults to ~/.phaedo-mcp/ (override PHAEDO_MCP_STATE_DIR); holds a 0600 key file + ciphertext-only cache. Revocation is honored: if the phone rejects this client (revoked / invalid credentials → 4xx), the cache is purged and the pull fails — a revoked agent can't keep serving a cached copy. The cache only covers the phone being genuinely unreachable (network/timeout). v1 caveat: the raw key is on disk (weaker than the extension's non-extractable key) — OS-keychain is a hardening follow-up.
  • Per-agent revocable pairing (built, device-verify pending): the server pairs itself with the phone as its own SAS-approved, revocable client — npm run pair (LAN auto-discovery or relay typed-code, mirroring the extension). Needs the phone's multi-client support (spec §8.4 v0.1.6) + the phone Agents/revoke screen. Obviates hand-copying the pairing record. Plan: ../docs/roadmap/mcp-revocable-approval-plan.md. Phone-gated unlock stays a deferred enterprise mode behind a config flag.

Conversation capture is opt-in. The MCP protocol never hands a server the conversation, so the server itself learns nothing from your chats (binding §5). Consultation, escalation and phaedo_record_outcome record decisions, not conversation text. Capture happens only through things you turn on: the Claude Code hooks (npm run setup:code-hook; see Capture from Claude Code / Cowork below) and, on a Mac, the separately installed accessibility reader that feeds capture-a11y.js. Both read on this computer, keep only signal names and counts, and discard the text. Local stdio only; standard mode only (enhanced-privacy/Stained-Glass and remote HTTP/SSE are out of this cut).

Install & test

From npm (published). The server is on the registry as phaedo-mcp — run it without cloning:

bash
npx phaedo-mcp              # run the server directly over stdio# or install the `phaedo-mcp` command globally:npm install -g phaedo-mcp

Most users never start the server by hand — point your MCP client at it with the one-click install below, which wires phaedo-mcp into Claude Desktop / Cursor / Claude Code for you. The cd mcp / npm run … commands in the rest of this README are for working from a clone of this repo (development & the smoke suite):

bash
cd mcpnpm installnpm test             # full suite (smoke + phone + cache + pairing + consult + …)npm run smoke        # 1a: unit + live stdio integration (23 checks)npm run smoke:phone  # 1b-i: mock-phone authorize→pull→decrypt→project (12 checks)npm run smoke:cache  # 1b-iii: encrypted at-rest cache + phone-absent fallback (11 checks)npm run smoke:pair   # P3: self-pairing crypto vs a mock phone (pair_key + SAS match)

Pair with the phone

bash
cd mcpnpm run pair

The server generates its own long-term identity (identity.json, 0600, gitignored) and pairs with the phone vault as a distinct client named "Phaedo MCP Server":

  • Same Wi-Fi: it finds the phone automatically — approve "Phaedo MCP Server" on the phone and confirm the SAS matches what the terminal prints.
  • Off-network: it prints an XXXX-XXXX code; on the phone tap Pair with code, type it, then confirm the SAS.

On success it writes pairing.json and pulls your fingerprint autonomously thereafter. Revoke anytime from the phone's Agents screen.

Fingerprint source

loadFingerprint() auto-selects, so server.js/projection.js never change:

Phase 1b — phone (preferred). If a pairing record is configured, the server pulls the live fingerprint from the paired phone over the encrypted boundary. A record is found via PHAEDO_PAIRING (path) or mcp/pairing.json. Run npm run pair (see Pair with the phone) to create it — the server pairs itself with the phone as its own revocable client. pairing.json holds pair_key (a long-term secret) and is gitignored. The phone app must be foregrounded/reachable at the configured endpoint. (You can still hand-copy pairing.sample.json → pairing.json from the extension's phaedo_local_pairing if you prefer.)

Phase 1a — local JSON. With no pairing record, reads a vault payload from PHAEDO_FINGERPRINT (a path, or the word sample for the shipped mcp/sample-fingerprint.json), then mcp/fingerprint.json. With neither, a starter profile: the Claude Code capture state on this computer folded onto an empty fingerprint (id starter-local), served only if it learned something. With nothing captured, there is no profile: every tool returns a plain-language decryption_failed error saying so. The sample is never served unless asked for by name — until 0.3.1 it was the silent fallback, so a fresh npx phaedo-mcp injected a made-up person's style without saying so. The file looks like this:

json
{  "phaedo_fingerprint": { "layers": { ... }, "fingerprint_id": "...", "persona_strength": 0.6 },  "phaedo_behavioral_signals": { ... },  "phaedo_linguistic_profile": { "messageCount": 64, ... },  "phaedo_session_metrics": { "sessionCount": 6, ... }}

One-click install (recommended)

The installer finds the MCP clients you already have (Claude Desktop, Cursor, Claude Code), adds Phaedo to each — preserving your other servers, backing the file up first — and then runs the one-time phone pairing.

  • macOS: double-click installers/macos/Install Phaedo MCP.command.
  • Windows: double-click installers/windows/Install Phaedo MCP.bat.
  • Linux: bash installers/linux/install-phaedo-mcp.sh.

(The launcher installs dependencies the first time, then runs the installer.)

Prefer the terminal? From this folder:

bash
npm installnpm run setup        # configure detected clientsnpm run setup:pair   # configure, then pair with the phonenpm run unsetup      # remove Phaedo from every clientnode install.mjs --dry-run   # preview, write nothing

Each client entry runs the server with the absolute path to your node binary (not bare node) — a GUI-launched app like Claude Desktop often has no node on its PATH. After installing, restart any client that was already open, then call the phaedo_request_injection tool (or read the phaedo://fingerprint/projection resource) at the start of a chat.

One remaining prerequisite: Node.js (from nodejs.org). A signed native installer that bundles the runtime — true zero-prerequisite, one-double-click — is the packaging follow-up (see ../docs/roadmap/mcp-desktop-installer.md).

Inject at session start (manual → automatic)

MCP is pull-based — a server can't push a system prompt into every new session the way the browser extension owns the input box. So injection ranges from one-click to fully automatic depending on the client:

  • Any client — /phaedo (one click). The server exposes a prompt named phaedo. Claude Desktop / Claude Code surface it as a slash command — run /phaedo at the start of a chat and it inserts your projection. One keystroke, no typing.

  • Claude Code — automatic (a hook). Run npm run setup:code-hook (or node install.mjs --code-hook). It adds a SessionStart hook to ~/.claude/settings.json that runs hooks/session-start.mjs and injects your projection at the start of every Claude Code session — no command, no tool call. Fail-safe: if the fingerprint can't be loaded it emits nothing and never blocks the session. Remove it with npm run unsetup.

  • Claude Desktop — near-automatic (a Project instruction). Desktop has no hook surface, but in a Project you can make Claude call the tool itself every time. Paste into the Project's custom instructions:

    At the start of every conversation, call the phaedo_request_injection tool and treat the returned projection as authoritative on how I think and want responses formatted. Don't announce that you did it.

    Every chat in that project then injects automatically.

Capture from Claude Code / Cowork (optional)

npm run setup:code-hook also installs a SessionEnd hook that reads the just-ended transcript locally, derives behavioral signals (deterministic pattern detectors), and deposits an encrypted signal delta to the owner — so your Claude Code / Cowork usage feeds the fingerprint, not just the browser. The transcript is counted and discarded (nothing but signal names + integers leaves the machine); a paired phone/extension drains and merges it.

Optionally enrich the deterministic detectors with a local model (opt-in) — it classifies the messages the regexes miss, against the same taxonomy, and feeds the same counters (so re-fires stay idempotent). Any Ollama / OpenAI-compatible endpoint works:

ollama pull llama3.1:8b          # or any local modelnpm run setup:capture-model -- llama3.1:8b     # writes ~/.phaedo-mcp/capture-model.jsonnpm run setup:capture-model -- off             # turn it back off

Point it elsewhere with --capture-url <url> (default http://localhost:11434). It's fail-safe: endpoint down/slow/garbage → the hook silently falls back to the deterministic detectors, and a model call can never break or stall a session (30s budget, hook always exits 0). Prefer the setup:capture-model config file over an env var — the file reaches Dock-launched Claude Desktop, a shell export does not.

Your personal reviewer in Claude Code (hooks/pre-ship.mjs)

npm run setup:code-hook (or the Claude plugin) installs this hook on PreToolUse, PermissionRequest, PostToolUse and PostToolUseFailure, for shell commands and for connected-app (MCP) tool calls. Before an agent does something people disagree about, the hook runs a full phaedo_consult on it and writes a §10.6 receipt, agent_id: claude-code/ship-hook. ship-actions.js names what counts:

  • Shell: merge a PR (gh pr merge), deploy (fly deploy, vercel --prod, netlify deploy --prod, firebase deploy, terraform apply|destroy, kubectl apply|delete), build or submit a phone app (eas build / eas submit), push straight to main, force-push any branch, delete a remote branch, open a PR, comment on or review a PR or issue, publish a package (npm/pnpm/yarn/bun publish, cargo publish, twine upload, gem push; never --dry-run), create a GitHub release.
  • Connected apps: any tool whose name says it sends, replies, forwards, posts, publishes, comments, shares or invites; pays, purchases, transfers or checks out; deletes, purges, destroys or trashes; or merges — through any MCP server except Phaedo's own. The receipt records who or what the call targets (recipient, channel, subject, amount), never a message body.

Every other command or tool is ignored in about 50 ms.

Why it matters in auto mode. Auto mode's reviewer judges an action by its type and lets routine ones through. Phaedo asks the other question — would this person want to see this one? — and when the answer is yes it returns ask, which forces a real prompt even in auto mode, with the reason in your terms: "it can't be undone", "it spends $250", or "your rule: ask me before posting in #eng". When the answer is no, it stays quiet.

  • It only ever adds friction. It never returns allow. A permissive answer leaves Claude Code's own permission flow untouched; escalate / clarify / decline returns ask, so the action comes to you with one plain line saying why.
  • Outcomes are yours, never inferred. The hook records approved only when it has evidence you were asked: Claude Code fired PermissionRequest for that call, and the call then ran. In auto mode that counts only when Phaedo itself asked (the prompt it forced is yours; any other is the classifier's); in dontAsk, never. Decline and that is recorded too: Claude Code fires no hook for a decline, but it marks it in the session's own transcript, so at your next message (or when the turn ends) the hook reads the end of the transcript for its open calls and records rejected — or modified if you said what to do instead. Only a person's no counts (auto mode's classifier saying no, or quitting the app, records nothing), and an outcome the agent already recorded is kept. No prompt shown, nothing recorded; the agent is told so, and records your reaction only if you give one.
  • What a merge changes. Before gh pr merge the hook reads the PR from GitHub (read-only): failing or unfinished checks, a large diff (> 1,000 code lines or > 20 files), or a sensitive path (CI/deploy config, auth/crypto/secrets by name, or your repo's .phaedo-sensitive list, read from the base branch) make it high-stakes. It can raise the stakes, never lower them.
  • Stale profile. It reads the at-rest profile cache (so it never pings your phone); when that copy is over 14 days old the agent tells you once a day, with the refresh: npm run pull and approve on the phone.
  • See what it has done: npm run ship-readout (-- --days 90 to widen).
  • Fail-safe: any error, timeout (12 s) or unusable profile → no output, the command runs as if the hook weren't there.

The same check in Cursor, Copilot CLI, Codex and Gemini CLI (hooks/agent-hook.mjs)

bash
cd ~/phaedo/mcp && npm run setup:agent-hooks

This adds Phaedo's check to each of these agents found on this computer, beside any hooks you already have: ~/.cursor/hooks.json, ~/.copilot/hooks/phaedo.json, ~/.codex/hooks.json and ~/.gemini/settings.json. The same actions are reviewed, with the same consult and the same decision records (each names the agent that asked).

  • Cursor and Copilot CLI can show a confirmation prompt, so you get one, with the reason.
  • Codex and Gemini CLI can't prompt from a hook, so Phaedo pauses the action once with the reason; the agent asks you in the chat, and the same command run again within 15 minutes goes through. It never blocks twice in a row and never says yes on your behalf.
  • Codex skips new hooks until you trust them: run /hooks in Codex once and trust Phaedo's.
  • Antigravity has no hooks, so it gets your profile (npm run rules) but not this check.
  • Outcomes aren't recorded automatically in these agents yet; npm run ship-readout shows what they asked.
  • npm run unsetup (uninstall) takes them all out.

Consult at decision points (phaedo_consult, §10)

Beyond injecting style, an agent can ask the fingerprint how the user's pattern bears on a decision — without ingesting the fingerprint. phaedo_consult takes a §10.2 request and returns a §10.3 signal, never layer content (§10.4 boundary):

jsonc
// request (tool arguments){ "consultation_type": "action_approval",  "action_descriptor": { "domain": "financial", "reversible": false, "magnitude": "high",                         "summary": "Approve $12k vendor payment outside terms." },  "context": { "evidence_provided": ["invoice", "po_match"] } }
// response{ "signal": "escalate", "confidence": 0.81,  "rationale_hint": "On irreversible, high-magnitude actions in the financial domain, the subject favors caution and human review.",  "deference_level": "high" }
  • consultation_type: action_approval · domain_risk_check · escalation_default · voice_draft.
  • signal: proceed · proceed_with_note · clarify · escalate · decline · insufficient_signal (abstain — either the fingerprint has no coverage for this action, or the relevant decision dimension is under an open §4.7 conflict the subject is still reconciling and is withheld; fall back to your own default or escalate to the subject).
  • deference_level (high/medium/low) = how strongly to weight it; sparse data → low.

Fast pre-flight (phaedo_check_authorization, §10.5)

Before paying for a full consult, an agent can ask whether one of your standing authorizations already decides the action — a deterministic-only check (no inference, no model):

jsonc
// request:  { "action_descriptor": { "domain": "financial", "reversible": false, "amount": 12000 } }// matched:  { "authorization_matched": true, "signal": "escalate", "rule_id": "irreversible-spend-over-5k-escalate",//            "rationale_hint": "Per your standing rule: Any irreversible spend over $5,000 goes to me…" }// no match: { "authorization_matched": false, "signal": null, "rule_id": null,//            "rationale_hint": "No standing authorization matches this action; run phaedo_consult…" }

A match is your pre-decision (confidence 1.0, deference high). On no match, fall back to phaedo_consult or your own default. Same §10.4 boundary — only the rule's decision crosses.

Receipts (§10.6) — your on-device audit trail

Every resolved consultation (abstains included, plus matched pre-flights) writes one encrypted, append-only receipt to ~/.phaedo-mcp/receipts.enc — which agent asked what, and what your oracle answered. Receipts never leave the device; the store is ciphertext under its own derived key (phaedo:receipts:enc:v0.1), capped (default 5,000, oldest evicted; PHAEDO_RECEIPTS_CAP to change). Only one field is ever mutable after write: user_action (what you actually did — feeds future agreement tracking). Quick readout on your own machine:

bash
cd mcp && npm run receipts                          # decrypts locally, lists the last 50 (with a short id per line)node receipts.js mark <id|prefix|latest> approved   # record what YOU did → approved | rejected | modified | unknownnpm run agreement                                   # per-domain agreement rate (oracle vs your actual decisions)npm run asks                                        # are you being asked less? last 4 weeks vs the 4 beforenpm run asks -- --weeks 12 --table                  # …week by week

npm run asks is the number Phaedo is judged by: how often it brought an action to you, whether that is falling, how often you reversed what it decided alone, and which asks were about things that could be undone and you approved as-is (the asks it should learn to drop). /phaedo:status adds the headline once each half of the window holds 5 checks.

user_action is subject-authored: set it from what you decided, not from whether an agent proceeded. Until receipts carry one, npm run agreement shows — (no data ≠ 0%); each one you mark makes the rate live. Metric definition: ../docs/architecture/agreement-metric.md.

Two resolvers, both local. The default is a deterministic rule engine — resilient cue extraction (reads §4.2 signals, then keyword-scans the relevant layers' interview text), relevance-scoped per consultation type, with confidence/deference grounded in real cue coverage. Nothing leaves the device; always available.

Model judge (richest context — ON by default, local). The judge reasons over the full projection via a local Ollama / OpenAI-compatible endpoint and returns a §10.3 signal. Any failure/timeout/parse error falls back to the rule engine, so the model can only improve on, never break, the floor (and a missing model never breaks consultation). The §10.4 boundary is enforced on parse.

The judge is off by default — the rule engine answers. Measured 2026-10-18 against one cached profile, llama3.1:8b answered a $12k irreversible payment clarify 0.9 on one run and proceed_with_note 0.9 on the next, where the rules say clarify every time. Opt in at install time once a model has earned it:

bash
npm run setup                              # model judge OFF (rule engine) — the defaultnode install.mjs --model-judge             # ON, auto-detect a local Ollama chat modelnode install.mjs --consult-model qwen2.5:7b   # ON, pinnednode install.mjs --consult-url http://localhost:11434   # custom endpoint

Auto-detect prefers llama3.1:8b when installed and never picks an extraction fine-tune or an embedding model (nomic-embed-text cannot answer a chat prompt).

Use a general chat model (NOT the extraction fine-tune). To run it: ollama pull llama3.1:8b. Raw env (if configuring a client by hand): PHAEDO_CONSULT_MODEL, PHAEDO_CONSULT_MODEL_URL, PHAEDO_CONSULT_API_KEY (OpenAI-compatible endpoints only).

voice_draft always redirects to the injection projection (generation is out of scope). A retrieval/scoping reranker is the next upgrade (../docs/roadmap/mcp-server.md).

Deference policies (guardrails that make delegation safe)

The user can author standing rules that override the inferred signal — per-domain / magnitude / reversibility (spec §10.5). e.g. "always escalate irreversible spend/legal", "auto-proceed low-stakes reversible writing".

Author them in the browser: open policy-editor.html (double-click — it's self-contained), build rules with the form, and Download / Copy the result to mcp/consult-policies.json. The server auto-reads that file — no env, just restart the client. (Override the path with PHAEDO_CONSULT_POLICIES; see consult-policies.sample.json.) Portable alternative: put the rules in the vault under phaedo_consult_policies so they travel with you (in-app authoring is a follow-up).

effect: escalate/require_human · decline · autoproceed (all at deference: high) · bias_cautious/bias_bold (nudge one step). The matched rule's note becomes the rationale_hint ("Per your standing rule: …"), so the agent sees why. Policies never apply to voice_draft and never widen the §10.4 boundary.

Connect a client manually (advanced)

The installer writes exactly this. The minimal paired entry needs no env — pairing.json next to server.js drives the source automatically.

Claude Desktop — add to claude_desktop_config.json:

json
{  "mcpServers": {    "phaedo": {      "command": "/absolute/path/to/node",      "args": ["/absolute/path/to/phaedo/mcp/server.js"]    }  }}

For the Phase-1a demo (no phone), add "env": { "PHAEDO_FINGERPRINT": "/absolute/path/to/your/fingerprint.json" }. Restart Claude Desktop, then call phaedo_request_injection at the start of a chat and prepend the returned projection.

Claude Code — .mcp.json in a project, or:

bash
claude mcp add phaedo -- /absolute/path/to/node /absolute/path/to/phaedo/mcp/server.js

來源:mcp/README.md,提交 4bd0750

工具

8

phaedo_request_injection

Request a Phaedo fingerprint injection

Returns the user's Phaedo cognitive-fingerprint projection as a system-prompt block to insert at the start of an AI session, so the assistant responds in the user's style. Call once at session start and prepend the returned `projection`.

輸入參數modeconsumer_idsession_contextrequested_layers

phaedo_consult

Consult the Phaedo fingerprint at a decision point

Ask how the user would want an action handled, before you take it on their behalf — without reading their profile. Call it BEFORE any consequential action you are about to take for the user: merging or deploying, publishing or posting, sending a message, paying or committing money, deleting, or changing an account or setting. Describe the action in action_descriptor (domain, reversible, magnitude, a short summary; amount when money moves) and bind it to the exact call with action_binding. Returns a signal (proceed | proceed_with_note | clarify | escalate | decline | insufficient_signal), a confidence, a short rationale_hint, a deference_level (how strongly to weight it) and a receipt_id. Keep the receipt_id: when the user reacts to what you did — confirms it, overrides it, or wants it done differently — record that with phaedo_record_outcome.

輸入參數contextagent_idaction_bindingagent_credentialaction_descriptorconsultation_type必填

phaedo_check_authorization

Check standing authorizations for an action

Deterministic pre-flight: check whether one of the user's standing authorizations already decides this action — escalate, decline, or pre-approve — without running the full consultation. Returns authorization_matched plus the authorized signal and the rule that fired. If no rule matches, fall back to phaedo_consult or your own default.

輸入參數agent_idaction_bindingagent_credentialaction_descriptorconsultation_type

phaedo_record_outcome

Record what the subject decided about a consulted action

Record what the USER decided about an action you consulted Phaedo on: approved | rejected | modified | unknown. Call it when the user reacts to that action — they confirm it (approved), refuse or undo it (rejected), or want it done differently (modified). Always pass the receipt_id that phaedo_consult (or a Phaedo hook) gave you; without it the most recent receipt is marked, which may be a different action. Record what the user chose, never whether you proceeded: silence is not approval, and an approval you inferred teaches nothing. A rejected/modified outcome teaches Phaedo how the user wants delegated work handled (the act-as-me channel).

輸入參數outcome必填agent_idreceipt_idagent_credential

phaedo_escalate

Escalate a blocking decision to the subject in real time

When you're acting autonomously for the user and hit a decision you shouldn't make alone, escalate it to them live instead of guessing. Runs the consultation and, only if the signal is blocking (escalate/clarify), wakes the user's phone for an approve/deny/modify. Returns a request_id immediately — then poll phaedo_escalation_status and DO NOT PROCEED until it resolves (if the user doesn't answer in time, hold). Use for consequential, hard-to-undo actions.

輸入參數contextagent_idaction_bindingagent_credentialaction_descriptorconsultation_type

phaedo_escalation_status

Check whether the subject has decided an escalation

Poll an escalation you opened with phaedo_escalate. Returns resolved + the decision (approve | deny | modify) once the user answers, pending while you should keep waiting, or expired once the window lapsed (then HOLD — do not proceed). A resolved decision is recorded automatically as the act-as-me outcome.

輸入參數expires_atreceipt_idrequest_id必填

phaedo_sign_mandate

Ask the subject to sign a payment authorization (AP2 Intent Mandate)

Request the user's cryptographic signature on an AP2 Intent Mandate built from their standing authorizations — a credential a merchant or payments network can verify. Returns a request_id and the unsigned mandate immediately; then poll phaedo_sign_status with BOTH, and DO NOT treat the mandate as authorized until it returns signed. The user signs on their phone (Face ID, key in the Secure Enclave); they may also decline. Use only when you need a verifiable payment credential — not for ordinary consultations.

輸入參數agent_idprompt_playback

phaedo_sign_status

Check whether the subject has signed the mandate

Poll a request from phaedo_sign_mandate. Pass the request_id AND the mandate that call returned. Returns signed + the mandate carrying the verified signature once the user signs, refused if they declined, pending while you should keep waiting, or expired once the window lapsed. A signed result is verified against the user's published signing key before it is returned.

輸入參數mandate必填expires_atrequest_id必填

版本歷史

8
  1. v0.3.22Nov 7, 2026
  2. v0.3.21Nov 4, 2026
  3. v0.3.19Nov 1, 2026
  4. v0.3.14Oct 29, 2026
  5. v0.3.4Oct 23, 2026
  6. v0.3.3Oct 21, 2026
  7. v0.3.0Sep 21, 2026
  8. v0.2.2Sep 16, 2026

評分

已滿足適用檢查項的 50%

該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。

  • 近 30 天內可連通25 分

    請保持端點能夠回應 MCP 握手;SourceWeft 每 30 天探測一次。

  • 已宣告認證方式10 分

    請在註冊中心條目中宣告憑證請求標頭,或保持端點能夠回應探測,以便判定其認證方式。

  • 已列出工具15 分

    請讓伺服器在無憑證時回應 tools/list,或發布可在沙箱中無憑證啟動的軟體包。

  • 描述必需15 分
  • 圖示10 分
  • 文件15 分
  • 授權條款10 分