{"app":"Operator Commons","description":"Trusted playbook and workflow exchange for AI agents. Portable, permissioned context across Claude, ChatGPT, Gemini, and MCP-aware agents.","version":"2.15.2","protocolVersion":"2024-11-05","status":"full","transport":{"type":"http","url":"/api/mcp/messages"},"note":"v2.15.2 — 62 tools, derived from the live tools/list surface (v0.6 \"_packages\" / \"_context_package\" names still routed as deprecated aliases). Local clients can mount the stdio adapter at bin/mcp-stdio.ts.","tools":[{"name":"get_my_agent_playbook","description":"Return the most recently updated playbook (dotfile) owned by the authenticated caller as a JSON string. [Bearer scope: playbook:read | playbook:export]","implemented":true},{"name":"list_shared_playbooks","description":"List playbooks (dotfiles) shared with the authenticated caller — both public links they own and ShareGrants where they're the recipient. [Bearer scope: playbook:read | playbook:export]","implemented":true},{"name":"get_playbook_by_id","description":"Return a single playbook (dotfile) by id if the caller has access (owner, example, or active ShareGrant recipient). [Bearer scope: playbook:read | playbook:export]","implemented":true},{"name":"compare_playbooks","description":"Compare two playbooks (dotfiles) owned by the caller (or otherwise accessible) and return similarities, differences, and a merged recommendation. [Bearer scope: playbook:read | playbook:compare | playbook:export]","implemented":true},{"name":"sanitize_content","description":"ADVISORY pre-publish scan: run the SAME two-tier scanner the publish/update paths enforce, over a playbook (dotfile) content blob (plus optional title/summary/tags to reproduce the full publish surface). Returns the full verdict: secrets[] (Tier 1 shapes — these WOULD be hard-rejected at publish; redact them, they can never be acknowledged), vocabulary[] (Tier 2 term hits with a span of surrounding text and the field location), acknowledgeableTerms (the flat machine-readable term list — pass it as acknowledgedTerms at publish time to keep your declared sensitivity/riskLevel, no prose parsing), warnings, suggestedRiskLevel, and suggestedSensitivity. This tool never rejects — it reports exactly what publishing would decide. For snapshot ITEM arrays, use dryRun: true on publish_setup_snapshot / update_setup_snapshot / import_setup_scan instead. [Anonymous-callable]","implemented":true},{"name":"publish_workflow_recipe","description":"Append a single workflow recipe to one of the caller's playbooks. The recipe is appended atomically and a new PlaybookVersion is created. Upserts by name: re-publishing an identical recipe with no sensitivity/acknowledgedTerms is an idempotent no-op (unchanged: true, no new version) — when either field IS passed, the write still runs so the re-declaration/acknowledgment rules apply (recipeUnchanged: true); a same-name recipe with different content is rejected unless mode: \"replace\" is passed, which overwrites it in place. Targeting: pass playbookId explicitly (find ids via list_shared_playbooks or get_my_agent_playbook); when omitted, it defaults to your only playbook if you own exactly one — owning several returns a multiple-playbooks error listing their ids and titles. Tier 2 vocabulary hits can be acknowledged via acknowledgedTerms to publish at the declared sensitivity (preview terms via sanitize_content); acknowledgments MERGE by term on this append operation, so terms already recorded on the playbook stay acknowledged without re-sending them. privacyWarnings are DELTA-SCOPED: they cover only the recipe in THIS call (untouched recipes never re-warn), and unacknowledged hits also come back structured as acknowledgeable ([{itemName, terms}]) — echo the terms into acknowledgedTerms, no prose parsing; enforcement (Tier 1 hard-reject, the stored sensitivity) still considers the whole document. Pass sensitivity to re-declare the playbook's level (applied — even downward — when every current Tier 2 match is acknowledged). Use remove_workflow_recipe to clean up recipes you no longer want. [Bearer scope: playbook:write | playbook:publish]","implemented":true},{"name":"remove_workflow_recipe","description":"Remove workflow recipe(s) by exact name from one of the CALLER'S OWN playbooks — the cleanup counterpart of publish_workflow_recipe. Pass `name` (one exact name) or `names` (several exact names, removed in ONE version write); exactly one of the two is required. The updated content is re-validated and a new PlaybookVersion is written, so removal is recoverable via version history (unlike delete_playbook). If several recipes share a given name, ALL of them are removed and the response says how many. Owner-gated: an unknown or not-owned playbook removes nothing and discloses nothing. Targeting matches publish_workflow_recipe: omitting playbookId only works when you own exactly one playbook; owning several returns a multiple-playbooks error listing their ids and titles. Recorded acknowledgments merge by term: acks still covering the remaining content stay valid, acks for terms the removed recipe carried are dropped, and an optional sensitivity re-declares the level (applied when every remaining Tier 2 match is acknowledged). A removal adds no content, so it returns NO privacyWarnings about the surviving recipes — only a refused sensitivity re-declaration still warns, naming the uncovered terms. [Bearer scope: playbook:write]","implemented":true},{"name":"delete_playbook","description":"Authenticated caller's agent: PERMANENTLY DELETE one of the CALLER'S OWN playbooks (dotfiles) by id — versions and share grants cascade, and existing share links stop working. Deletion requires its own opt-in bearer scope, deliberately separate from the write scope. Owner-gated: a playbook you don't own deletes nothing and discloses nothing. Irreversible — there is no undo or archive. Find ids via get_my_agent_playbook or list_shared_playbooks. [Bearer scope: playbook:manage]","implemented":true},{"name":"update_playbook_metadata","description":"Authenticated caller's agent: rename, re-describe, or re-scope one of the CALLER'S OWN playbooks (dotfiles) without touching its content — updates title, summary, tags, visibility, and/or sensitivity. At least one of title/summary/tags/visibility/sensitivity is required. Visibility \"public\" enforces a sensitivity ceiling: it is refused (naming the conflict) unless the stored sensitivity is public, low, or internal — to flip public in ONE call, also pass a lower `sensitivity` (with acknowledgedTerms covering every current Tier 2 match) and the re-declaration is applied via the same whole-document planner update_playbook_section uses (partial coverage escalates-or-keeps, never a side door). Metadata-only: never bumps the version or writes a PlaybookVersion row; use publish_workflow_recipe or the web editor for content changes. Owner-gated: a playbook you don't own updates nothing and discloses nothing. [Bearer scope: playbook:write]","implemented":true},{"name":"update_operator_profile","description":"Authenticated caller's agent: update the CALLER'S OWN public operator profile — bio (the public focus line consumers read first; surfaces as profile_summary.focus and on /operators/<handle>) and/or display name. At least one of name/bio is required; an empty string clears the field. Values are normalized (NFKC + zero-width strip) with hard caps (name 100 / bio 500 characters — over-cap values are rejected with the cap named, never silently truncated). The same two-tier scan as every write path runs: Tier 1 secret shapes hard-reject naming detector + field; Tier 2 vocabulary hits warn-and-store (the profile is a public surface with no per-item sensitivity — the save proceeds, warnings name each term; pass matched terms in acknowledgedTerms to acknowledge them). Returns the stored handle/name/bio plus any privacyWarnings. Owner-only by construction: this tool always writes the caller's own profile. [Bearer scope: profile:write]","implemented":true},{"name":"create_playbook","description":"Authenticated caller's agent: CREATE a brand-new playbook from a full content document — the MCP counterpart of the /create web editor. content must satisfy the canonical playbook schema (self-discover it via get_playbook_schema; dry-run first via validate_playbook). The same two-tier privacy scan as every write path is enforced: Tier 1 secret shapes hard-reject (never acknowledgeable); Tier 2 vocabulary hits floor sensitivity at \"confidential\" unless each matched term is listed in acknowledgedTerms. Returns the new playbook's id, slug, and version 1.0.0. Edit sections later via update_playbook_section; manage recipes via publish_workflow_recipe. [Bearer scope: playbook:write]","implemented":true},{"name":"update_playbook_section","description":"Authenticated caller's agent: edit ONE content section of one of the CALLER'S OWN playbooks. section is one of profile, communicationStyle, workPatterns, toolStack, agentInstructions, privacyBoundaries, sharingPreferences, exportNotes — workflowRecipes is deliberately NOT patchable here (use publish_workflow_recipe / remove_workflow_recipe). mode 'replace' (default) sets the section to value; 'merge' deep-merges objects and unions string arrays (scalars: incoming wins). The WHOLE patched document is re-validated and re-scanned, and a new PlaybookVersion is written. Acknowledgment semantics: recorded Tier 2 acks for terms still present anywhere in the patched document are PRESERVED by default (you don't need to re-send acks for sections you didn't touch); pass ackMode:'replace' to record only the acks you supply. Version: omit `version` to auto-bump the patch component (x.y.Z+1), or pass an explicit x.y.z `version` strictly greater than current to mark a minor/major change. Optimistic concurrency: baseVersion must equal the playbook's currentVersion (from get_playbook_by_id or a prior write result) or the call fails with a version-conflict error naming the current version — re-read and retry. Owner-gated: a playbook you don't own updates nothing and discloses nothing. The metadata summary is never touched (use update_playbook_metadata). Find ids via list_my_playbooks, list_shared_playbooks, or get_my_agent_playbook. [Bearer scope: playbook:write]","implemented":true},{"name":"get_playbook_schema","description":"Public, anonymous: self-discovery for playbook authoring. Returns the canonical playbook JSON Schema (generated live from the same zod schema every write path enforces — never a hand-maintained copy), the list of patchable sections (workflowRecipes marked recipe-tools-only), a minimal valid example document, the baseVersion optimistic-concurrency contract, and the supported patch modes. [Anonymous-callable]","implemented":true},{"name":"validate_playbook","description":"ADVISORY dry-run that runs the EXACT planning engine the writes execute, without persisting anything. Two shapes: create-shaped {content, title?, summary?, tags?, sensitivity?, acknowledgedTerms?} mirrors create_playbook; patch-shaped {playbookId, section, value, mode?, baseVersion?, sensitivity?, acknowledgedTerms?} mirrors update_playbook_section — in the patch shape, sensitivity is a RE-DECLARATION of the stored level (applied, even downward, only when acknowledgedTerms covers every current Tier 2 match). Requires an authenticated owner for the patch shape; foreign ids disclose nothing. Returns {valid, mode, errors (zod flattened), verdict (full two-tier scan), wouldReject (Tier 1 present — the write WOULD hard-reject), wouldStore {sensitivity, acknowledgmentsRecorded}, redeclaration? {requested, applied, uncoveredTerms}, versionConflict?}. [Anonymous-callable]","implemented":true},{"name":"get_operator_public_profile","description":"Public, anonymous: return an operator's public profile + hosted-delegate availability status by handle. Reads no private content. [Anonymous-callable]","implemented":true},{"name":"get_capability_card","description":"Public, anonymous: return an operator's CapabilityCard — what their hosted delegate can disclose, public/trusted/never-share scopes, hosted vs local-bridge availability. [Anonymous-callable]","implemented":true},{"name":"search_commons_directory","description":"Public, anonymous: search the public playbooks operators have published in the Operator Commons Directory. Supports free-text query (matches title/summary/tags) and offset paging (hasMore in the result signals further pages). Results arrive in the `publicPlaybooks` array (each: id/title/summary/tags/ownerHandle/updatedAt) — approach guides, not installable packages, so they carry no risk/verified/sponsored signals. The `packs` array is empty on this server. [Anonymous-callable]","implemented":true},{"name":"request_setup_share","description":"Authenticated caller: send a SetupShareRequest to a target operator. Auto-evaluated against target's SharingPolicy; may return an immediate grant or stay pending for manual review. Never-share scopes are denied at creation. [Bearer scope: setup_share:request]","implemented":true},{"name":"get_setup_share_status","description":"Authenticated caller (requester or target): return current status + decisionReason of a SetupShareRequest. requestId is OPTIONAL: omit it to read your MOST RECENT request (you're already scoped to requests where you're the requester or target); pass one to target a specific request. If you have none, a found:false note explains how to start one; if several are still pending, the latest comes back with a note to pass requestId to disambiguate. Requesters get the id from request_setup_share; targets see pending requests via get_my_inbox. [Bearer scope: setup_share:status:read]","implemented":true},{"name":"list_active_setup_grants","description":"Authenticated caller: list active SetupShareGrants where caller is either owner or requesting party. [Bearer scope: setup_share:grants:list]","implemented":true},{"name":"get_sanitized_setup_summary","description":"Grant-gated. Returns the operator's latest shareable SetupSnapshot as a sanitized summary (no raw content, no secrets, no env values). Find grantId via list_active_setup_grants. Next: compare_agent_setups to see what you're missing. [Bearer scope: sanitized_setup_summary]","implemented":true},{"name":"get_setup_snapshot","description":"Grant-gated. Returns a full SetupSnapshot + items if the grant's allowedSnapshotIds permits. Find grantId via list_active_setup_grants. snapshotId is OPTIONAL — omit it and the grant owner's LATEST readable snapshot is resolved server-side (the usual case; a grant exposes no snapshot id to you). Supply snapshotId only to target a specific older snapshot a pinned grant covers. [Bearer scope: setup_snapshot:read]","implemented":true},{"name":"compare_agent_setups","description":"Grant-gated. Deterministic, platform-aware comparison of the requester's declared summary vs the target's sanitized snapshot; returns missing/present/stronger buckets plus requesterSummarySource ('inline' | 'own_snapshot' | 'request' | 'none') and requesterSummaryItemCount. Full present rows explain matchKind as native, generic_compatible, or explicit_port (an adoption-lineage-backed cross-runtime match). snapshotId is OPTIONAL — omit it and the grant owner's LATEST snapshot is compared (a grant exposes no snapshot id to you). Your baseline resolves in that precedence order: an inline requesterSetupSummary ({items:[{platform,itemType,name,summary}]}) if you pass one, else YOUR latest published snapshot (own_snapshot), else the summary stored on the originating request; when the source is 'none', every snapshot item reads as missing. Then generate_install_plan for the item/pack you want to adopt. [Bearer scope: setup:compare]","implemented":true},{"name":"generate_install_plan","description":"Grant-gated. Returns an installability verdict for a package pinned to one of the caller's active grants: authored target compatibility, caller-supplied compiler fidelity, the resolved profile, typed unsupported atoms, portability ceilings, source fidelity, manual steps, and a manifest/plan evidence status. `installability.status` reports the first blocking gate, and command remains null unless that status is ready — Commons never fetches or verifies remote source bytes, so relay manualSteps and wait for operator review rather than constructing an install command yourself. Package publication is disabled on this server, so there is normally nothing to plan against. Find grantId via list_active_setup_grants. [Bearer scope: install:plan]","implemented":true},{"name":"explain_permissions","description":"Public, anonymous: human-readable explanation of a scope name's effects, what data it discloses, and what's never disclosed. [Anonymous-callable]","implemented":true},{"name":"explain_risk","description":"Public, anonymous: human-readable explanation of a riskLevel (low/medium/high/critical) — what an operator should consider before installing a pack at this level. [Anonymous-callable]","implemented":true},{"name":"revoke_setup_share","description":"Authenticated (grant owner only): revoke a SetupShareGrant. Idempotent — already-revoked grants return a structured error. [Bearer scope: setup_share:revoke]","implemented":true},{"name":"share_with_friend","description":"Authenticated caller's agent: OFFER your own SetupSnapshot to a friend (recipientHandle). Inverts the ask direction — initiator is the owner, recipient consents to receive. Recipient sees the offer in their inbox and approves/declines. Never-share scopes filtered before persistence. [Bearer scope: trust:invite]","implemented":true},{"name":"recommend_to_friend","description":"Authenticated caller's agent: RECOMMEND specific snapshot items to a friend's agent. Option A (low-friction) — your agent's act of recommending implicitly consents to send; the request immediately ships with a pinned grant so the recipient's agent can one-click adopt. Use this when you've identified specific items in your setup the recipient would benefit from. Use kind='they_should_adopt' to push items from your setup; 'they_should_add' to suggest items you noticed they're missing. [Bearer scope: trust:invite]","implemented":true},{"name":"ask_friends_agent","description":"Authenticated caller's agent: ASK a friend (targetHandle) for setup-share access — natural-language wrapper around request_setup_share with conversational framing. Use when you (the caller's agent) want to query another operator's setup and don't have an existing grant. Optionally pass requesterSetupSummary (your own sanitized item list) so later comparisons have a baseline — compare_agent_setups can also accept the summary inline at compare time. [Bearer scope: trust:invite]","implemented":true},{"name":"get_my_inbox","description":"Authenticated caller's agent: aggregate every pending agent-to-agent collaboration item addressed to caller — incoming asks, offers, recommendations, plus the caller's outgoing items still awaiting the other side. One round-trip; no need to poll list_setup_share_requests + list_active_setup_grants separately. [Bearer scope: setup_share:status:read]","implemented":true},{"name":"approve_request","description":"Authenticated decider's agent: APPROVE a pending SetupShareRequest in ONE tap. For an ask the OWNER (target) decides; for an offer the CONSUMER (recipient) decides — the service enforces who may act and rejects the wrong party. Issues the grant inline. Use decision='approve_limited' with limitedScopes to narrow what's granted. Not-found and not-your-decision collapse to one ambiguous error. [Bearer scope: setup_share:request]","implemented":true},{"name":"deny_request","description":"Authenticated decider's agent: DENY/decline a pending SetupShareRequest in ONE tap. For an ask the OWNER decides; for an offer the CONSUMER declines — the service enforces who may act. Not-found and not-your-decision collapse to one ambiguous error. [Bearer scope: setup_share:request]","implemented":true},{"name":"propose_counter","description":"Authenticated data owner's agent: instead of a flat deny, COUNTER a pending ASK with a NARROWER alternative. Only the owner who received the ask (targetUserId) may counter, and only an ask may be countered (offers are owner-initiated, so there is no owner-counter moment). References the original ask, NARROWS requestedScopes (must be a subset of the original — widening is rejected), and proposes a (typically shorter) requestedDurationSeconds plus optional substitute allowedSnapshotIds/allowedPackIds. Declines the original and creates a kind='counter' request addressed to the original requester. Capped at 2 round-trips. Never-share scopes are stripped at the service layer; a counter can never grant a never-share scope or widen disclosure. Not-found, wrong-kind, not-pending, and not-yours collapse to one ambiguous error. [Bearer scope: setup_share:request]","implemented":true},{"name":"accept_counter","description":"Authenticated original requester's agent: ACCEPT a counter-offer addressed to you in ONE tap. Issues the grant atomically through the same never-share-filtered issuance path as approve_request, pinned to the counter's narrowed scopes and any substitute snapshots/packs. Only the counter recipient may accept; not-found and not-yours collapse to one ambiguous error. To decline instead, use deny_request with the counter's id. [Bearer scope: setup_share:request]","implemented":true},{"name":"adopt_recommendation","description":"Authenticated recipient's agent: ADOPT a recommendation addressed to you in ONE tap. Records the consumer-side adopt signal (the owner's grant is already active) and notifies the initiator. Only the recipient may adopt; not-found and not-your-recommendation collapse to one ambiguous error. Next safe step after adopting: call list_active_setup_grants to find the grant pinned to this recommendation, then read the shared material through that grant (get_sanitized_setup_summary / get_setup_snapshot) or call generate_install_plan against it. Relay an install command only when installability.status is ready and command is non-null; otherwise relay the manualSteps for operator review. Commons never executes installs itself. [Bearer scope: setup_share:status:read]","implemented":true},{"name":"decline_recommendation","description":"Authenticated recipient's agent: DECLINE a recommendation addressed to you in ONE tap. Records the consumer-side decline signal and notifies the initiator. Only the recipient may decline; not-found and not-your-recommendation collapse to one ambiguous error. [Bearer scope: setup_share:status:read]","implemented":true},{"name":"list_my_snapshots","description":"Authenticated caller's agent: list the CALLER'S OWN SetupSnapshots (id, label, createdAt, item count) so the agent can self-discover which snapshot to recommend or share. Caller-scoped: only your own rows are ever returned. [Bearer scope: setup_share:status:read]","implemented":true},{"name":"list_my_playbooks","description":"Authenticated caller's agent: list the CALLER'S OWN playbooks (id, title, version, visibility, sensitivity, updatedAt), newest first. Caller-scoped: only playbooks you own are returned. Call this BEFORE create_playbook to avoid creating a duplicate of a playbook you already own — get_my_agent_playbook returns only the single most-recent one, and list_shared_playbooks returns share LINKS, not owned rows. [Bearer scope: setup_share:status:read]","implemented":true},{"name":"list_notifications","description":"Authenticated caller's agent: list the caller's own notifications (newest first). Each carries id, type, title, body, entityType/entityId, readAt, createdAt. Use unreadOnly=true to poll only what's new. [Bearer scope: setup_share:status:read]","implemented":true},{"name":"mark_notification_read","description":"Authenticated caller's agent: mark ONE of the caller's own notifications read by id. Scoped to (id, caller) — you can never flip another user's notification. Idempotent; returns whether a row was marked. [Bearer scope: setup_share:status:read]","implemented":true},{"name":"send_invite","description":"Authenticated caller's agent: mint a single-use, TTL-bounded invite. Returns the code and a shareable /welcome?invite_code=… URL. When the friend claims it, an accepted TrustRelationship connects you both. Optionally bind it to an invitedEmail and attach a note. [Bearer scope: trust:invite]","implemented":true},{"name":"list_friends","description":"Authenticated caller's agent: list the caller's accepted friends (mutual TrustRelationships). Each carries the friend's handle, name, relationship status, trustLevel, and since (when the edge was created). Blocked pairs are excluded — a block always dominates a stale accepted row. [Bearer scope: trust:read | setup_share:status:read]","implemented":true},{"name":"publish_setup_snapshot","description":"Authenticated caller's agent: PUBLISH a sanitized SetupSnapshot of the caller's own setup. Call get_setup_snapshot_guide FIRST — a complete snapshot spans the FULL item-type vocabulary (instructions, rules, skills, hooks, commands, subagents, MCP servers, plugins, workflows, routines, context packs, templates, evals, dotfile fragments, adapter outputs) across EVERY platform the operator uses; a handful of items is an under-capture, not a snapshot. Every item requires stateClassification; only explicitly portable, non-private-memory, supported-provider state may publish, and unclassified/runtime-local/generated/credential-bearing/unsupported state rejects before scanning or persistence. Items must carry sanitized data only — NEVER raw file contents, secrets, env values, tokens, or local absolute paths — and a server-side two-tier privacy scan is enforced at publish: Tier 1 secret shapes (API keys, private keys, JWTs, card/SSN formats, ...) hard-reject naming detector + location (acknowledgments can NEVER override Tier 1); Tier 2 vocabulary hits raise the item's riskLevel unless each matched term is listed in that item's acknowledgedTerms (acknowledgment recorded with term, timestamp, token id for operator review). Tier 2 findings come back BOTH as prose privacyWarnings AND as a structured acknowledgeable field ([{itemName, terms}]) — echo each entry's terms into that item's acknowledgedTerms, no prose parsing. PRE-FLIGHT with dryRun: true to run the full scan + coverage WITHOUT writing (no snapshot, no revision, no audit entry) and iterate to zero warnings before the first real publish. Risk aggregates are recomputed server-side from the FINAL stored item levels. The response includes a coverage report (captured vs missing item types) — review it and fill gaps via update_setup_snapshot. The snapshot stays owner-only until a SetupShareGrant exposes it; check /me or list_my_snapshots. [Bearer scope: setup_snapshot:publish]","implemented":true},{"name":"unpublish_setup_snapshot","description":"Authenticated caller's agent: PERMANENTLY DELETE one of the CALLER'S OWN SetupSnapshots by id (items cascade). Owner-gated: a snapshot you don't own deletes nothing and discloses nothing. Irreversible — there is no undo or archive; re-publish via publish_setup_snapshot if needed. Find ids via list_my_snapshots. [Bearer scope: setup_snapshot:publish]","implemented":true},{"name":"update_setup_snapshot","description":"Authenticated caller's agent: UPDATE one of the CALLER'S OWN SetupSnapshots in place — REPLACES title, summary, and items wholesale (a full replace, not a merge: omitted items are removed). The snapshot id stays stable and revision increments, so existing SetupShareGrants pinned to this id keep working — prefer this over unpublish + re-publish. Use it to close coverage gaps: get_setup_snapshot_guide lists the full item-type vocabulary, stateClassification contract, and capture checklist a complete snapshot should span across every platform the operator uses. Every item must be explicitly portable, non-private-memory, and supported-provider; the gate runs on dry runs and writes before scanning or persistence. visibility and source are NOT changeable here. Items carry the exact same sanitization contract and two-tier privacy scan as publish_setup_snapshot: Tier 1 secret shapes hard-reject naming detector + location (the previous revision stays fully intact); Tier 2 vocabulary hits raise the item's riskLevel unless each matched term is listed in that item's acknowledgedTerms — findings come back both as prose privacyWarnings and as a structured acknowledgeable field ([{itemName, terms}]) to echo back, no prose parsing. PRE-FLIGHT with dryRun: true to run the full scan + coverage WITHOUT writing (no revision bump, no audit entry) so acknowledge round-trips never burn revisions. Risk aggregates are recomputed server-side from the FINAL stored item levels. Owner-gated: a snapshot you don't own updates nothing and discloses nothing. Find ids via list_my_snapshots; read the current revision via get_my_setup_snapshot. [Bearer scope: setup_snapshot:publish]","implemented":true},{"name":"get_my_setup_snapshot","description":"Authenticated caller's agent: read ONE of the CALLER'S OWN sanitized SetupSnapshots — title, summary, visibility, source, revision, createdAt, updatedAt, and every stored item field (name, summary, platform, itemType, riskLevel, sanitizedContent, permissions, exportable, recorded acknowledgments). Request-only stateClassification is intentionally NOT stored or returned: before update_setup_snapshot, join these items with the caller-owned private state contract and reapply each classification; the read payload is not directly resubmittable. snapshotId (or its `id` alias) is OPTIONAL: omit it to read your most recent snapshot; pass one to target a specific snapshot. If you have no snapshots yet, a helpful note explains how to publish one. Owner self-read: NO grant is required, and only your own snapshots resolve — a snapshot you don't own returns the same note as a nonexistent id. For reading a snapshot SOMEONE ELSE shared with you, use get_setup_snapshot with the grantId from list_active_setup_grants instead. Find your ids via list_my_snapshots; use this before update_setup_snapshot to see the current stored items and revision. [Bearer scope: setup_share:status:read]","implemented":true},{"name":"import_setup_scan","description":"Authenticated caller's agent: IMPORT a machine-generated setup scan (CLI scan / manifest-style JSON), mapping each scan atom to a SetupSnapshot item. Every atom requires stateClassification and only explicitly portable, non-private-memory, supported-provider state may enter a shared snapshot. A complete scan covers the full item-type vocabulary across every platform the operator uses — get_setup_snapshot_guide lists the vocabulary and capture checklist, and the response's coverage report shows what the scan missed. Creates a new snapshot with source \"cli_scan\" — or, when snapshotId names a snapshot the CALLER OWNS, updates it in place via the same path as update_setup_snapshot (id stable, revision increments, grants keep working); a snapshotId you don't own refuses without disclosing anything and NEVER falls back to creating. Boundary rejections happen BEFORE any scan: local absolute paths (/home/..., C:\\..., file://, ~/) in any text field reject naming the offending field, and the payload is strict, so unknown atom keys (raw file dumps under content/raw/rawContent/...) reject outright. Atoms then pass the same two-tier privacy scan as publish_setup_snapshot (Tier 1 secret shapes hard-reject; Tier 2 vocabulary hits raise riskLevel unless acknowledged per atom — findings come back both as prose privacyWarnings and as a structured acknowledgeable field to echo into each atom's acknowledgedTerms). PRE-FLIGHT with dryRun: true to run the boundary checks + full scan + coverage WITHOUT importing (no snapshot, no revision, no audit entry). The snapshot stays owner-only until a SetupShareGrant exposes it. [Bearer scope: setup_snapshot:publish]","implemented":true},{"name":"get_setup_snapshot_guide","description":"Public, anonymous: self-discovery for setup-snapshot publishing (your KIT — the skills/hooks/commands/MCP configs your agent runs) — call this BEFORE publish_setup_snapshot / update_setup_snapshot / import_setup_scan. Returns the full item-type vocabulary with a description + concrete example per type (derived live from the same zod enum every snapshot write enforces), the platform vocabulary (a multi-agent operator should capture EACH platform's config), an ordered captureChecklist of where a coding agent's setup actually lives (global + project instruction layers, memory repos, skills, plugins, hooks, commands, subagents, MCP server configs, settings, dotfiles, sibling-agent configs), and the recommended workflow (enumerate → sanitize_content → publish/update → review coverage → fill gaps). Snapshot = your KIT; ALSO narrate your APPROACH via get_playbook_guide — build both. [Anonymous-callable]","implemented":true},{"name":"evaluate_agent_state_contract","description":"Public, anonymous: validate a declarative private agent-state contract plus caller-supplied probe observations, then return deterministic machine-readable health and drift. The contract defines one canonical guidance source, one private canonical memory source, runtime overlays, portability/provider/requirement/scope classifications, declarative parity probes, portable-only conflict-safe sync policy, and local-state bootstrap preservation. The evaluator itself is side-effect-free and reads no files, environment variables, credentials, sessions, network resources, or database rows; the standard MCP transport still applies authentication and rate limiting. [Anonymous-callable]","implemented":true},{"name":"get_playbook_guide","description":"Public, anonymous: the narrated authoring guide for your PLAYBOOK (your APPROACH — how your agent thinks, communicates, and decides) — the analogue of get_setup_snapshot_guide for the KIT. Call this BEFORE create_playbook / update_playbook_section. Returns the section vocabulary (DERIVED from the live playbook schema so it can't drift), a where-your-approach-lives capture checklist, a quality bar, what-to-omit/privacy guidance, antiPatterns, an exampleSection, and the recommended workflow (get_playbook_guide → get_playbook_schema → draft → validate_playbook → create_playbook/update_playbook_section). Playbook = your APPROACH; snapshot = your KIT — build both. [Anonymous-callable]","implemented":true},{"name":"get_onboarding_guide","description":"Public, anonymous: the single canonical Operator Commons loop as machine-readable phases — connect your agent, build your PLAYBOOK (approach), build your SNAPSHOT (kit), connect with operators you trust, share/ask, compare/adopt, and browse the directory. Each phase names its web surface (where the human confirms/consents) and the real MCP tool(s) your agent calls to do that phase's work. Build-first: your agent drives the work; human confirmation/consent happens in the web app. Call this for the full arc; call whoami for what to do RIGHT NOW. [Anonymous-callable]","implemented":true},{"name":"whoami","description":"START HERE every session: returns your authenticated identity, token metadata, granted scopes, the tools this token can call, AND orientation counts (friendCount, activeGrantCount, pendingInboxCount) plus a suggestedNext string that tells your agent the single best next action — build your playbook/snapshot if you haven't, otherwise read grants / clear the inbox / connect. Authenticated callers only; bearer callers also get their AgentToken's kind/label/createdAt/expiresAt/expiresInDays/lastUsedAt, an expiringSoon flag (PATs only, when < 7 days remain — rotate before the cliff, never the token secret), and an autoRefresh flag (true for OAuth access tokens, whose ~1h expiry the client refreshes transparently — do NOT prompt a manual re-auth for those). [No bearer scope required]","implemented":true},{"name":"get_trusted_feed","description":"Authenticated caller's agent: reverse-chron feed of what the operators in the caller's ACCEPTED trust graph recently adopted, endorsed, or published (setup snapshots, playbooks, adopted recommendations). Same-target events collapse into one row ('3 operators you trust endorsed X'). Rows carry handles, action labels, and entity names ONLY when the caller may already see the entity (public, or covered by one of the caller's active grants) plus a link to the consent-enforced surface — never raw content; blocked pairs are excluded. Optional limit (default 50, max 100) and windowDays (default 30, max 90). [Bearer scope: trust:read | setup_share:status:read]","implemented":true},{"name":"get_trusted_digest","description":"Authenticated caller's agent: PULL the trusted-feed rolled into a short digest — per-action totals (packs published/endorsed, snapshots published, recommendations adopted), the top collapsed highlights, and the underlying rows — so a hosted delegate can hand 'what your trusted operators did this week' to the operator's own agent on demand. Same trust-graph + visibility filtering as get_trusted_feed (nothing appears here that wouldn't appear there). Optional windowDays (default 7, max 90). [Bearer scope: trust:read | setup_share:status:read]","implemented":true},{"name":"discover_from_trusted","description":"Authenticated caller's agent: discover what the operators in your ACCEPTED trust graph are using that YOU could adopt. Aggregates items across trusted operators' public setup snapshots PLUS any setups they've actively granted to you, ranks them by how many distinct trusted operators use each one, and excludes items you already have. Each result carries the item type+name, a sanitized summary, usedByCount, the handles using it (usedBy), whether it's available via 'public' snapshot or a 'grant', and an adoptHint. Consent-safe: never surfaces a private/un-granted setup or a friend who hasn't made the item visible to you. Optionally pass mySetupSummary ({ items: [{ itemType, name }] }) so items you already have are filtered out (otherwise pass nothing and filter client-side). Optional limit (default 25, max 100). [Bearer scope: trust:read | setup_share:status:read]","implemented":true},{"name":"get_item_provenance","description":"Authenticated caller's agent: trace the ADOPTION LINEAGE of an item the caller adopted — the chain of operators it passed through, newest first (\"you adopted this from @bob, who adopted it from @carol\"). Returns HANDLES + content HASHES + adoption timestamps ONLY — never item content, summaries, or sanitized bodies. Caller-scoped: if you never adopted this item, the chain is empty (no disclosure). Find itemId via the source SetupSnapshotItem id pinned on a recommendation you adopted. [Bearer scope: setup_share:status:read]","implemented":true},{"name":"check_for_updates","description":"Authenticated caller's agent: find which of the caller's ADOPTED items have DRIFTED — the source item's current content hash no longer matches the hash captured when you adopted it. Returns a staleCount and one row per drifted item (lineageId, itemId, name, platform, itemType, adoptedHash, currentHash). Hashes only — no content. Un-hashable (legacy) adoptions are excluded. Caller-scoped: only your own adoptions are checked. Follow up with compare_item_versions on a lineageId to see what changed. [Bearer scope: setup_share:status:read]","implemented":true},{"name":"compare_item_versions","description":"Authenticated caller's agent: compare the version of an adopted item you pinned against its CURRENT source version, by lineageId. identical:true when the hashes match. When drifted, returns identical:false + a riskLevelDelta (how much riskier the current version is). The structural body (changedSections — which sections moved) is gated behind the SAME sanitized_setup_summary grant projection the comparison tools use: pass grantId for an active grant that carries that scope to get the body, otherwise you get hash-mismatch-only. Not-found and not-yours collapse to one ambiguous error. [Bearer scope: setup:compare]","implemented":true},{"name":"endorse_setup","description":"Authenticated caller's agent: endorse a setup SNAPSHOT you've used, recommend, created, forked, or reviewed (kind is one of uses|recommends|created|forked|reviewed). Idempotent per (snapshot, kind): re-endorsing updates the optional note instead of double-counting. This is a first-class trust signal — sponsorship can NEVER write it, and one endorsement per (snapshot, kind) is enforced so endorsement-spam can't inflate the count. [Bearer scope: setup_share:request]","implemented":true},{"name":"get_adoption_attestation","description":"Authenticated caller's agent: weigh a recommendation BEFORE adopting it. Identify the item EITHER by its content hash OR — when weighing a recommendation you haven't adopted yet — by grantId + itemId (the item id from get_setup_snapshot read via that grant); the server resolves the hash for you. Returns how many operators THE CALLER TRUSTS have adopted that exact version (adoptionCountInTrustGraph + distinctTrustedAdopters handles, newest first), whether the source publisher is a verified publisher (publisherAttested), how much riskier the current version is (riskLevelDelta, 0..3), and the decline rate among trusted operators (declineRate). TRUST-GRAPH-SCOPED: restricted to your ACCEPTED trust graph — NOT a public popularity board. Returns COUNTS + HANDLES ONLY — never item content, summaries, sanitized bodies, or the raw content hash. Sponsorship can NEVER alter any of these numbers. [Bearer scope: trust:read | setup_share:status:read]","implemented":true},{"name":"submit_feedback","description":"Authenticated caller's agent: report feedback about Operator Commons DIRECTLY — bugs, friction, ideas, or praise the agent hit while working, without the operator switching to a web form. Persists a feedback record (the source of truth) and, when the server is configured for it, files a GitHub issue on the project repo. category is one of bug | friction | idea | praise. Use surface to name the seam it's about (e.g. playbook-publish, grant-adopt, hosted-delegate, inbox) and severity (low | medium | high) for bugs/friction. Returns the feedback id and, if an issue was filed, its number/url. Tied to the caller's identity; nothing here is shared with other operators. [No bearer scope required]","implemented":true}]}