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 分