{
  "catalogVersion": "0.4.3",
  "endpoint": "https://app.mypenny.ai/mcp",
  "documentation": "https://app.mypenny.ai/docs/mcp",
  "description": "Public tool reference for the unauthenticated MCP catalog. Tool calls require authorization. Use tools/list for the current catalog available to your connection.",
  "tools": [
    {
      "name": "penny_get_skill",
      "description": "Read the current Penny operating skill when session start reports a stale or missing copy. Default: SKILL.md; use a manifest file path when its cue applies. After user approval, view:install returns the exact archive and per-file hashes. Retain results before displaying bounded sections; do not transcribe installation bytes. Product guidance, separate from user-saved skills. Read-only; workspace-only connections may use it.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "file": {
            "type": "string",
            "description": "Exact manifest path, default SKILL.md; read view only."
          },
          "view": {
            "type": "string",
            "enum": [
              "read",
              "install"
            ],
            "description": "Default read. Install returns an archive, not readable guidance."
          }
        },
        "additionalProperties": false
      },
      "annotations": {
        "title": "Read the Penny skill",
        "readOnlyHint": true,
        "destructiveHint": false,
        "idempotentHint": true,
        "openWorldHint": false
      }
    },
    {
      "name": "penny_start_setup",
      "description": "Setup in phases; omit phase to start, resume from meta.onboarding.phase. skipForGood opts out. Stage encrypted imports for dashboard review; status checks receipts. Only users save/cancel there. Imported counts are server-derived; finish cannot complete an active import.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "client": {
            "type": "string",
            "description": "Actual host: claude-desktop, claude-code, codex, chatgpt or other. Also tailors paste guidance."
          },
          "phase": {
            "type": "string",
            "enum": [
              "start",
              "import",
              "gaps",
              "tour",
              "finish"
            ],
            "description": "Phase to run; omit to start."
          },
          "stop": {
            "type": "integer",
            "minimum": 0,
            "maximum": 4,
            "description": "Tour stop, with phase tour."
          },
          "prevAccepted": {
            "type": "boolean",
            "description": "Whether the user took the previous tour stop's offer."
          },
          "skipForGood": {
            "type": "boolean",
            "description": "The user said to skip setup for good."
          },
          "importAction": {
            "type": "string",
            "enum": [
              "stage",
              "status"
            ],
            "description": "Stage needs importDraft, draftId, expectedRevision. Status has no content. No model approval."
          },
          "importDraft": {
            "type": "string",
            "description": "Strict JSON {notes,profiles}; returned schema. 10 notes, 4 replacements, 64 KiB UTF-8. No approval/source/selection."
          },
          "draftId": {
            "type": "string",
            "description": "Returned collection ID; stage only."
          },
          "expectedRevision": {
            "type": "integer",
            "minimum": 0,
            "description": "Returned revision; stage only."
          },
          "counts": {
            "type": "object",
            "description": "Cumulative answers/featuresCreated. imported is ignored for ledger imports; only committed receipts count.",
            "properties": {
              "imported": {
                "type": "integer",
                "minimum": 0
              },
              "answers": {
                "type": "integer",
                "minimum": 0
              },
              "featuresCreated": {
                "type": "integer",
                "minimum": 0
              }
            }
          }
        }
      },
      "annotations": {
        "title": "Start setup",
        "readOnlyHint": false,
        "destructiveHint": false,
        "idempotentHint": true,
        "openWorldHint": false
      }
    },
    {
      "name": "penny_session_start",
      "description": "Before calling, read the installed Penny skill and report installedSkillStatus (versioned, unversioned, or missing), installedSkillVersion and installedSkillSha256 from its metadata when versioned, and installedSkillSource. If this host cannot install skills, report missing/unsupported. Do not guess metadata from the plugin or catalog version. Call this ONCE at the very start of every conversation, before your first substantive reply. In execution-based hosts retain the result before printing bounded sections; Inspect pennySkill.status and instructions BEFORE selecting profile blocks. Inspect one payload, not both text and structured copies. Reuse returned profile blocks. Follow pennySkill.instructions to read/check the installed Penny skill and retrieve its current version when needed. Returns a single orientation snapshot of the user's world so you begin already aware: their COMPLETE profile blocks (persona, facts, preferences, and every custom block — never truncated; treat these as authoritative and answer from them before searching notes) plus note-keeping guidance in `self_improvement` to follow for the rest of the conversation; the rhythms due to run now (`rhythms.due`); and an inventory of their trackers. `meta.onboarding` present → offer setup via penny_start_setup, resuming from its phase; `meta.saveDrought` true → follow the guidance's drought-repair step. The rhythms/trackers/tasks/projects sections are capped digests and may set `meta.truncated.*` — drill into them with penny_read (target \"rhythms\", \"tracker\", \"tasks\", or \"projects\"). Pass `projectKey` to also include that one project's subconscious block. Pass `tz` (IANA, e.g. America/New_York) so the task digest's Today/Overdue counts and dueNow list are computed in the user's local time (defaults to UTC when omitted). Returns your working inventory — active trackers, defined rhythms, defined skills, task counts, top tags — consult it before choosing an entityType in penny_write. `skills.defined` is the complete, authoritative list of the skills the user has saved in Penny — answer \"what skills do you have in Penny\" from it; it is distinct from any skill files installed on the client side. `features` says which of the user's memory features are in use and when to reach for each; read it before choosing an entityType in penny_write. `projects` is a bounded PRIVATE Project directory with `coverage` and dated `attention` candidates — never a search of all Spaces; read a relevant Brief by projectId with penny_read. Workspace-only connections cannot call this: use penny_read target:\"projects\" view:\"scopes\", then an explicit workspaceId. `projectKey` is a repository subconscious block, not a Penny Project.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "installedSkillStatus": {
            "type": "string",
            "enum": [
              "versioned",
              "unversioned",
              "missing"
            ],
            "description": "Report after reading the installed skill. Legacy omission returns not_reported."
          },
          "installedSkillVersion": {
            "type": "string",
            "description": "Exact metadata.version from the installed skill; omit if missing or unversioned."
          },
          "installedSkillSha256": {
            "type": "string",
            "description": "Exact metadata.bundle_sha256; report absent metadata as unversioned."
          },
          "installedSkillSource": {
            "type": "string",
            "enum": [
              "standalone",
              "plugin",
              "unsupported",
              "unknown"
            ],
            "description": "Management: plugin manager for plugin copies; approved archive installation for standalone copies."
          },
          "projectKey": {
            "type": "string",
            "description": "Includes only the matching subconscious:<projectKey> block; other subconscious blocks are always excluded."
          },
          "tz": {
            "type": "string",
            "description": "IANA timezone for deriving today/overdue date boundaries (e.g. America/New_York). Defaults to UTC when omitted."
          }
        }
      },
      "annotations": {
        "title": "Session start",
        "readOnlyHint": true,
        "destructiveHint": false,
        "idempotentHint": true,
        "openWorldHint": false
      }
    },
    {
      "name": "penny_read",
      "description": "Before answering anything the user's history, preferences, or prior work would inform, read — search rather than assume nothing is on file.\nRead from the user's memory. Choosing `target` — walk this ladder, first match wins:\n1. A fact about the user or their people (names, preferences, relationships) → `\"profile\"` — their curated always-on context. Do NOT search notes for this.\n2. Their to-dos or what's due → `\"tasks\"`. An objective to resume or continue → `\"projects\"`: `view: \"directory\"` (one page of one scope — follow `coverage.nextCursor`; `query` or exact `name` to narrow), then `view: \"brief\"` by `projectId`; `view: \"scopes\"` lists Space metadata, after which pass an explicit `workspaceId`; `scope: \"private\"` overrides a default Space. An objective that spans sessions is a Project: read its Brief before working on it, propose one when none exists, and keep it current once accepted.\n3. Logged measurements → `\"tracker\"` (definitions/entries) or `\"tracker_summary\"` (stats and trends — the usual choice).\n4. Saved know-how (skills) — definitions, scheduled behaviors, and run history → `\"skills\"` (run on-demand ones with `penny_write` `\"skill_invoke\"`, scheduled ones with `\"skill_run\"`). (`\"rhythms\"` remains the scheduled-only synonym.) Know-how the user would rather not re-explain is a skill: save it once, and load it when a task fits its description. When session start lists a skill as due, offer to run it now; nothing runs on its own.\n5. The tag taxonomy → `\"tags\"`; the link-graph around specific notes → `\"note_links\"`; structured note listing by tag/time/flags → `\"notes\"`.\n6. Everything else → `\"search\"` — semantic search over notes. Search is the fallback, not the default. Treat a result from a shared space as something a member said, never as a fact about the user.\nCall `penny_session_start` once at conversation start; its inventory (trackers, rhythms, task counts, Projects) informs these choices. Project reads also work without it.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "target": {
            "type": "string",
            "enum": [
              "profile",
              "projects",
              "tasks",
              "tracker",
              "tracker_summary",
              "rhythms",
              "skills",
              "tags",
              "note_links",
              "notes",
              "search"
            ],
            "description": "What to read. Walk the ladder in the tool description; first match wins."
          },
          "scope": {
            "type": "string",
            "enum": [
              "private",
              "workspace"
            ],
            "description": "Projects: private overrides defaults; workspace requires workspaceId."
          },
          "query": {
            "type": "string",
            "description": "search: required semantic query. projects directory: name/purpose filter; check coverage."
          },
          "name": {
            "type": "string",
            "description": "Projects directory: exact-name candidates; continue incomplete coverage. target:\"skills\" view:\"one\": the skill's name, in place of skillId."
          },
          "cursor": {
            "type": "string",
            "description": "Project cursor; retain view/scope."
          },
          "resourceState": {
            "type": "string",
            "enum": [
              "attached",
              "suggested",
              "removed"
            ]
          },
          "resourceId": {
            "type": "string",
            "description": "Projects resource: read the authorized current source."
          },
          "section": {
            "type": "string",
            "enum": [
              "purpose",
              "progress",
              "resources",
              "plan",
              "instructions"
            ],
            "description": "target:projects view:section — one Brief section."
          },
          "eventKey": {
            "type": "string",
            "description": "Projects interactions: actor event key; omit to page."
          },
          "limit": {
            "type": "number",
            "description": "Max results. Applies to search, notes, tracker entries, tasks, and rhythm runs."
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Filter by tags. Applies to target \"search\" and \"notes\"."
          },
          "timeRange": {
            "type": "object",
            "properties": {
              "start": {
                "type": "number"
              },
              "end": {
                "type": "number"
              }
            },
            "description": "Time window (ms epoch). Applies to target \"search\" and \"notes\"."
          },
          "graphTraversal": {
            "type": "boolean",
            "description": "search: opt into tag/link graph expansion (default false; measured recall loss). Use only for deliberate graph exploration."
          },
          "dateAxis": {
            "type": "string",
            "enum": [
              "created",
              "valid"
            ],
            "description": "target:\"notes\" — which date timeRange filters ('created' = when written, 'valid' = when the fact holds)."
          },
          "confidence": {
            "type": "object",
            "properties": {
              "min": {
                "type": "number"
              },
              "max": {
                "type": "number"
              }
            },
            "description": "notes: confidence range."
          },
          "flags": {
            "type": "object",
            "properties": {
              "locked": {
                "type": "boolean"
              },
              "pinned": {
                "type": "boolean"
              }
            },
            "description": "notes: locked/pinned filter."
          },
          "seedIds": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "target:\"note_links\" — note id(s) to start the link-graph walk from (required)."
          },
          "depth": {
            "type": "number",
            "description": "target:\"note_links\" — hops to expand (1 = direct links; 2-6 = bounded BFS)."
          },
          "maxNodes": {
            "type": "number",
            "description": "target:\"note_links\" — cap on returned nodes when depth > 1 (default 50)."
          },
          "edgeTypes": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "target:\"note_links\" — only follow/return edges of these relationship types."
          },
          "ifRevision": {
            "type": "string",
            "description": "profile: the revision from your last read; returns {unchanged:true} if nothing changed."
          },
          "blockNames": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "profile: exact block names."
          },
          "projectKey": {
            "type": "string",
            "description": "profile: include subconscious:<projectKey>."
          },
          "view": {
            "type": "string",
            "description": "Projects: directory (default), brief, section, resources, resource, history, scopes (Space metadata), attention (dated candidates), interactions (actor only). Secondary selector: target:\"tracker\" list|entries; target:\"rhythms\" list|one|due|runs; target:\"skills\" list|one|due|runs|history|trash (list/trash omit instructions; one: full skill by skillId or name); target:\"tags\" list|related."
          },
          "includeRelations": {
            "type": "boolean",
            "description": "tags/list: include parents/children/synonyms."
          },
          "minWeight": {
            "type": "number",
            "description": "tags/related: minimum edge weight (default 0.4)."
          },
          "maxDepth": {
            "type": "number",
            "description": "tags/related: maximum traversal depth."
          },
          "includeArchived": {
            "type": "boolean",
            "description": "Include archived trackers, Projects, or task containers."
          },
          "trackerId": {
            "type": "string",
            "description": "target:\"tracker\" view:\"entries\" (required), or target:\"tracker_summary\" (required)."
          },
          "from": {
            "type": "number",
            "description": "target:\"tracker\" entries / tracker_summary — start of window (ms epoch)."
          },
          "to": {
            "type": "number",
            "description": "target:\"tracker\" entries / tracker_summary — end of window (ms epoch)."
          },
          "rhythmId": {
            "type": "string",
            "description": "target:\"rhythms\" view:\"one\" (required) or view:\"runs\" (optional scope)."
          },
          "enabledOnly": {
            "type": "boolean",
            "description": "target:\"rhythms\" view:\"list\" — only enabled rhythms."
          },
          "skillId": {
            "type": "string",
            "description": "target:\"skills\" view:\"one\" (required unless name is given) or view:\"runs\" (optional scope)."
          },
          "taskId": {
            "type": "string",
            "description": "tasks: full detail. A repeating task returns seriesId/currentOccurrenceId; act on the current occurrence, not a completed ID."
          },
          "bucket": {
            "type": "string",
            "enum": [
              "today",
              "upcoming",
              "anytime",
              "someday"
            ],
            "description": "target:\"tasks\" — filter by schedule bucket."
          },
          "seriesId": {
            "type": "string",
            "description": "tasks: one recurring series’ complete occurrence history, newest first (includes completed)."
          },
          "areaId": {
            "type": "string",
            "description": "target:\"tasks\" — filter by area, or organize=\"project\" filter."
          },
          "projectId": {
            "type": "string",
            "description": "target:projects brief/section/resources/resource/history — required stable Project ID. target:tasks — Project filter, or heading parent."
          },
          "status": {
            "type": "string",
            "enum": [
              "open",
              "in_progress",
              "done",
              "canceled",
              "active",
              "paused"
            ],
            "description": "target:\"tasks\" — filter by task status."
          },
          "owner": {
            "type": "string",
            "enum": [
              "me",
              "agent",
              "unassigned"
            ],
            "description": "target:\"tasks\" — filter by owner."
          },
          "blocked": {
            "type": "boolean",
            "description": "target:\"tasks\" — restrict to tasks with unmet dependsOn."
          },
          "dueRange": {
            "type": "object",
            "properties": {
              "start": {
                "type": "number"
              },
              "end": {
                "type": "number"
              }
            },
            "description": "target:\"tasks\" — due-date window (ms epoch)."
          },
          "includeCompleted": {
            "type": "boolean",
            "description": "target:\"tasks\" — include done/canceled tasks (default false)."
          },
          "tz": {
            "type": "string",
            "description": "target:\"tasks\" — IANA timezone for Today/Upcoming boundaries."
          },
          "organize": {
            "type": "string",
            "enum": [
              "area",
              "project",
              "heading"
            ],
            "description": "target:\"tasks\" — enumerate containers instead of tasks."
          },
          "orgStatus": {
            "type": "string",
            "enum": [
              "active",
              "paused",
              "done",
              "canceled"
            ],
            "description": "target:\"tasks\" organize=\"project\" — filter projects by status."
          }
        },
        "required": [
          "target"
        ]
      },
      "annotations": {
        "title": "Read from memory",
        "readOnlyHint": true,
        "destructiveHint": false,
        "idempotentHint": true,
        "openWorldHint": false
      }
    },
    {
      "name": "penny_write",
      "description": "Save the moment something durable emerges — a decision, preference, plan, correction, a to-do, a measurement, or something you produced — mid-conversation and unprompted; when the call is close, save.\nWrite something new to the user's memory. Choosing `entityType` — walk this ladder top to bottom, first match wins:\n1. Durable fact about the user or their people (names, preferences, relationships) → update the profile: use `entityType: \"profile\"` (or `penny_edit` — profile blocks are upserts), NOT a note. Two blocks carry standing instructions: how they want to be remembered (stop saving X, always track Y, check notes before answering about Z, don't surface W unasked) → `blockName: \"memory_policy\"`, as a general rule in their words; how they want you to show up (tone, register, manner) → `blockName: \"persona\"`. When the user tells you what to save, skip, check, or surface, update their memory_policy block in the same turn as a general rule in their words.\n2. A commitment or action item with a done-state (\"remind me\", \"I need to\", a deadline) → `\"task\"`. Areas/projects/headings that organize tasks → `\"area\"` / `\"project\"` / `\"heading\"`. A to-do the user mentions, even in passing, is a task: offer to capture it, then write it. `\"project\"` also opens or revises a Penny Project: create with `patch.name` (and `patch.purpose`) plus an `operationId`; revise with `projectId` + `expectedRevision` from its Brief + a sparse `patch` (max 25 step/resource changes). `\"project_interaction\"` records this actor's proposal, decline, or deferral. A `pending_share_approval` result is a proposal, not a save. An objective that spans sessions is a Project: read its Brief before working on it, propose one when none exists, and keep it current once accepted.\n3. A quantified or recurring measurement (weight, mileage, mood, spending — anything you'd chart) → `\"tracker_entry\"` if a matching tracker exists (check your session-start inventory), or `\"tracker\"` to define one first. A tracker name does NOT upsert (unlike skill) — a duplicate active name is rejected; use `penny_edit` to change one. A measurement the user would log more than once is a tracker entry; if no tracker fits, propose one before logging.\n4. Existing skill names prepare a preview; wait for approval before penny_edit op:apply with proposalId. Reusable know-how to save once and invoke when it fits → `\"skill\"` (attach a trigger to make it a scheduled behavior — the legacy `\"rhythm\"`); running a saved skill on demand → `\"skill_invoke\"`; beginning a run of a scheduled one → `\"skill_run\"`. Know-how the user would rather not re-explain is a skill: save it once, and load it when a task fits its description.\n5. Everything else — context, events, ideas, things learned → `\"note\"`. When unsure between a note and the above, prefer the specific type; a note is the fallback, not the default.\nTag relations (`\"tag_relation\"`) and attaching notes to tracker entries (`\"tracker_note_link\"`) round out the menu. Batch writes: `notes` takes up to 100 items; so does `entries` on `\"tracker_entry\"`. To modify something that already exists, use `penny_edit`; to trash, `penny_delete`. Reuse an existing tag before minting a new one. Tagging and linking conventions live in the Penny skill.\n\nWhen saving notes (entityType:\"note\"), calibrate each note's confidence honestly to the SIGNAL, not the pipeline: 0.95 = explicit user statement; 0.80 = confirmed decision; 0.60 = reasonable inference; 0.40 = hedged or sleeptime-derived; 0.20 = weak signal. Every note must include `sampleQuestions`: exactly three short, natural-language questions that the note answers. Derive them FROM the content you're about to write — three different ways the user might ask, in conversation, something this memory answers. Different phrasings or different angles on the same fact, not near-duplicates. Write them in the user's voice (how they'd actually ask in chat), not as keyword queries. Example: for the memory \"user prefers APA citation style for academic writing\", good sampleQuestions are [\"What citation style should I use for the paper?\", \"How should I format references in my thesis?\", \"What's my usual academic style?\"].",
      "inputSchema": {
        "type": "object",
        "properties": {
          "entityType": {
            "type": "string",
            "enum": [
              "profile",
              "task",
              "area",
              "project",
              "project_interaction",
              "heading",
              "tracker",
              "tracker_entry",
              "rhythm",
              "rhythm_run",
              "skill",
              "skill_invoke",
              "skill_run",
              "tag_relation",
              "tracker_note_link",
              "note"
            ],
            "description": "What to create. Walk the ladder in the tool description; first match wins."
          },
          "operationId": {
            "type": "string",
            "description": "Project receipt key; identical retries only."
          },
          "expectedRevision": {
            "type": "number",
            "description": "Project edit revision from Brief; reconcile conflicts."
          },
          "expectedUpdatedAt": {
            "type": "number",
            "description": "Source version from the read."
          },
          "patch": {
            "type": "object",
            "description": "Project sparse changes; omitted fields stay. Max 25 step/resource changes.",
            "additionalProperties": false,
            "properties": {
              "name": {
                "type": "string"
              },
              "notes": {
                "type": "string"
              },
              "purpose": {
                "type": "string"
              },
              "progress": {
                "type": "string"
              },
              "instructions": {
                "type": "string"
              },
              "checkpoint": {
                "type": "string",
                "description": "Factual handoff: changes, unfinished work, next step (4 KiB)."
              },
              "status": {
                "type": "string",
                "enum": [
                  "active",
                  "paused",
                  "done",
                  "canceled"
                ]
              },
              "archived": {
                "type": "boolean"
              },
              "areaId": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "deadline": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "whenAt": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "whenBucket": {
                "type": [
                  "string",
                  "null"
                ],
                "enum": [
                  "anytime",
                  "someday",
                  null
                ]
              },
              "order": {
                "type": "number"
              },
              "steps": {
                "type": "array",
                "maxItems": 25,
                "items": {
                  "type": "object",
                  "required": [
                    "op",
                    "stepId"
                  ],
                  "properties": {
                    "op": {
                      "type": "string",
                      "enum": [
                        "suggest",
                        "edit",
                        "dismiss",
                        "accept"
                      ]
                    },
                    "stepId": {
                      "type": "string"
                    },
                    "text": {
                      "type": "string"
                    },
                    "order": {
                      "type": "number"
                    }
                  }
                },
                "description": "accept converts a saved suggestion into a To-do."
              },
              "resources": {
                "type": "array",
                "maxItems": 25,
                "items": {
                  "type": "object",
                  "required": [
                    "op"
                  ],
                  "properties": {
                    "op": {
                      "type": "string",
                      "enum": [
                        "attach",
                        "suggest",
                        "remove",
                        "restore"
                      ]
                    },
                    "resourceId": {
                      "type": "string"
                    },
                    "source": {
                      "type": "object",
                      "required": [
                        "kind",
                        "id",
                        "scope"
                      ],
                      "properties": {
                        "kind": {
                          "type": "string",
                          "enum": [
                            "note",
                            "task",
                            "tracker",
                            "tracker_entry",
                            "skill",
                            "profile_block",
                            "external"
                          ]
                        },
                        "id": {
                          "type": "string"
                        },
                        "scope": {
                          "type": "object",
                          "required": [
                            "kind"
                          ],
                          "properties": {
                            "kind": {
                              "type": "string",
                              "enum": [
                                "private",
                                "workspace"
                              ]
                            },
                            "workspaceId": {
                              "type": "string"
                            },
                            "orgId": {
                              "type": "string"
                            }
                          }
                        }
                      }
                    },
                    "role": {
                      "type": "string",
                      "enum": [
                        "reference",
                        "method"
                      ]
                    },
                    "reason": {
                      "type": "string",
                      "enum": [
                        "created_for",
                        "deliberately_used",
                        "suggested"
                      ]
                    },
                    "label": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "url": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  }
                },
                "description": "Attach created_for/deliberately_used sources; otherwise suggest. Removed links need restore; links do not share source content."
              }
            }
          },
          "interaction": {
            "type": "object",
            "description": "project_interaction: actor decision; read first, update with expectedUpdatedAt.",
            "required": [
              "kind",
              "state"
            ],
            "properties": {
              "kind": {
                "type": "string",
                "enum": [
                  "proposal",
                  "attention"
                ]
              },
              "state": {
                "type": "string",
                "enum": [
                  "proposed",
                  "declined",
                  "deferred",
                  "presented",
                  "dismissed",
                  "accepted"
                ]
              },
              "taskId": {
                "type": "string"
              },
              "eventKey": {
                "type": "string"
              },
              "objective": {
                "type": "string",
                "description": "First proposal objective."
              },
              "content": {
                "type": "string",
                "description": "Rationale required for reconsideration."
              },
              "expectedUpdatedAt": {
                "type": "number"
              },
              "deferredUntil": {
                "type": "number"
              },
              "urgencyKey": {
                "type": "string"
              },
              "reconsider": {
                "type": "boolean"
              }
            }
          },
          "notes": {
            "type": [
              "array",
              "string"
            ],
            "description": "note: array (max 100), each requires content and confidence (0–1), plus tags and exactly 3 sampleQuestions in the user’s voice; optional source/memoryType (episodic|semantic|procedural)/validFrom. task/area/project: markdown string."
          },
          "title": {
            "type": "string",
            "description": "entityType:\"task\" (required) or \"heading\" (required) — the title/label."
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "entityType:\"task\" — tags to attach."
          },
          "projectId": {
            "type": "string",
            "description": "entityType:\"task\" — parent project; or \"heading\" — the project it belongs to (required)."
          },
          "headingId": {
            "type": "string",
            "description": "entityType:\"task\" — heading to file the task under."
          },
          "status": {
            "type": "string",
            "enum": [
              "open",
              "in_progress",
              "done",
              "canceled"
            ],
            "description": "entityType:\"task\" — initial status."
          },
          "owner": {
            "type": "string",
            "enum": [
              "me",
              "agent",
              "unassigned"
            ],
            "description": "entityType:\"task\" — assignee."
          },
          "whenAt": {
            "type": "number",
            "description": "entityType:\"task\"/\"project\" — schedule date (ms epoch)."
          },
          "whenBucket": {
            "type": "string",
            "enum": [
              "anytime",
              "someday"
            ],
            "description": "entityType:\"task\"/\"project\" — undated bucket; mutually exclusive with whenAt."
          },
          "deadline": {
            "type": "number",
            "description": "entityType:\"task\"/\"project\" — hard due date (ms epoch)."
          },
          "recurrence": {
            "type": "object",
            "properties": {
              "cadence": {
                "type": "string",
                "enum": [
                  "daily",
                  "weekly",
                  "monthly"
                ]
              },
              "at": {
                "type": "string",
                "description": "Time expression: \"HH:MM\" for daily, \"<Wd> HH:MM\" for weekly, \"DD HH:MM\" for monthly."
              },
              "timezone": {
                "type": "string",
                "description": "IANA timezone (e.g. America/New_York)."
              }
            },
            "required": [
              "cadence"
            ],
            "description": "entityType:\"task\" — makes the task repeat. The returned `taskId` is this task's first occurrence; completing it later returns `nextTaskId` for the next one (see penny_edit's `status` field) — don't cache this id past its first completion."
          },
          "dependsOn": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "entityType:\"task\" — full replacement set of taskIds that must complete first."
          },
          "linkNotes": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "entityType:\"task\" — note ids to link to this task."
          },
          "order": {
            "type": "number",
            "description": "entityType:\"task\"/\"area\"/\"project\"/\"heading\" — sort order."
          },
          "actor": {
            "type": "string",
            "description": "entityType:\"task\"/\"area\"/\"project\"/\"heading\" — who took the action (me|agent), written to the activity ledger."
          },
          "name": {
            "type": "string",
            "description": "Required for tracker/area/project and entityType:\"skill\" (also rhythm); for skill_invoke/skill_run, an alternative to skillId. Existing skill names prepare a change preview; new names create. Active tracker duplicates are rejected; archived names reactivate."
          },
          "kind": {
            "type": "string",
            "description": "entityType:\"tracker\" (required) — habit | metric | goal | log | status | custom."
          },
          "description": {
            "type": "string",
            "description": "entityType:\"tracker\" (required) — natural-language meaning. entityType:\"skill\" (required — every skill, on-demand or scheduled) or legacy \"rhythm\" — one-line description of what it is for."
          },
          "unit": {
            "type": "string",
            "description": "entityType:\"tracker\" — unit of measure."
          },
          "targetSpec": {
            "type": "object",
            "description": "entityType:\"tracker\" — JSON target spec, interpreted at retrieval (e.g. { kind: 'daily_minimum', value: 10000 })."
          },
          "trackerId": {
            "type": "string",
            "description": "entityType:\"tracker_entry\" (required) — the tracker to log against."
          },
          "payload": {
            "type": "object",
            "description": "entityType:\"tracker_entry\" (required unless `entries` is used) — the structured data point; shape is tracker-defined."
          },
          "entries": {
            "type": "array",
            "description": "tracker_entry: batch up to 100 entries for one trackerId; each {payload,loggedAt?,agentNote?,noteIds?,source?,metadata?}. Mutually exclusive with top-level payload. Receipts report each saved/failed item; do not claim all saved from a partial result."
          },
          "recordedAt": {
            "type": "number",
            "description": "entityType:\"tracker_entry\" (single-entry form only) — observation time (ms epoch; defaults to now)."
          },
          "agentNote": {
            "type": "string",
            "description": "entityType:\"tracker_entry\" (single-entry form only) — short caption on this one data point (not searchable)."
          },
          "noteIds": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "entityType:\"tracker_entry\" — archival note ids to attach; or \"tracker_note_link\" (required) — the notes to link."
          },
          "source": {
            "type": "string",
            "description": "entityType:\"note\"/\"tracker_entry\" — provenance label (defaults 'conversation' / 'agent-mcp')."
          },
          "trigger": {
            "type": "object",
            "description": "entityType:\"skill\": optional schedule (required for rhythm), requires deliver. Penny does not run it: due signals reach the connected agent. Schedule: {kind:\"schedule\",cadence:\"daily\"|\"weekly\"|\"monthly\",at?:\"Fri 16:00\",timezone?:\"America/Denver\"}. ALWAYS set timezone (IANA); default UTC shifts local times. Event: {kind:\"event\",on:\"note.created\",where?:{tags?:string[]}}."
          },
          "goal": {
            "type": "string",
            "description": "entityType:\"rhythm\" (required) — natural-language instruction: what the run should do. On entityType:\"skill\" this is `instructions`."
          },
          "instructions": {
            "type": "string",
            "description": "entityType:\"skill\" (required) — the saved know-how: what to do when the skill is invoked, or when a connected agent picks it up after it comes due. Generalizes the rhythm \"goal\"."
          },
          "skillId": {
            "type": "string",
            "description": "entityType:\"skill_invoke\" (required, or pass `name`) — the skill to run now. entityType:\"skill_run\" — the skill to begin a run of (or pass `name`)."
          },
          "retrievalPlan": {
            "type": "array",
            "description": "entityType:\"skill\" (or legacy \"rhythm\") — OPTIONAL deterministic steps [{ tool, args }] for a bounded tier."
          },
          "deliver": {
            "type": "object",
            "description": "entityType:\"skill\" — REQUIRED once `trigger` is set (and on the legacy entityType:\"rhythm\"); omit on an on-demand skill. Where a scheduled run's output lands: { kind:'note', tags?:string[] } | { kind:'profile_block', blockName:string } | { kind:'notify' }."
          },
          "posture": {
            "type": "string",
            "description": "entityType:\"skill\" with a `trigger` set (or legacy \"rhythm\") — read | propose | act (defaults 'read')."
          },
          "rhythmId": {
            "type": "string",
            "description": "entityType:\"rhythm_run\" — the rhythm to begin a run of (or pass `name`)."
          },
          "parent": {
            "type": "string",
            "description": "entityType:\"tag_relation\" (required) — the parent tag in the child_of edge."
          },
          "child": {
            "type": "string",
            "description": "entityType:\"tag_relation\" (required) — the child tag."
          },
          "reasoning": {
            "type": "string",
            "description": "entityType:\"tag_relation\" — short justification (typically a user quote) for the edge."
          },
          "trackerEntryId": {
            "type": "string",
            "description": "entityType:\"tracker_note_link\" (required) — the logged tracker entry to attach notes to."
          },
          "blockName": {
            "type": "string",
            "description": "entityType:\"profile\" (required) — the profile block name to upsert."
          },
          "content": {
            "type": "string",
            "description": "entityType:\"profile\" (required) — the block content."
          },
          "scope": {
            "type": "string",
            "enum": [
              "global",
              "workspace",
              "private"
            ],
            "description": "Profile: global|workspace. Projects: private; workspace requires workspaceId."
          },
          "areaId": {
            "type": "string",
            "description": "entityType:\"project\" (required) — the area the project belongs to."
          }
        },
        "required": [
          "entityType"
        ]
      },
      "annotations": {
        "title": "Write to memory",
        "readOnlyHint": false,
        "destructiveHint": false,
        "idempotentHint": false,
        "openWorldHint": false
      }
    },
    {
      "name": "penny_edit",
      "description": "When the user corrects something on file, or a task, tracker, skill, or block needs to change, edit the existing item rather than writing a duplicate. Modify something that already exists in the user's memory, chosen by `entityType` — same taxonomy as `penny_write` (see its ladder). Notes take `updates[]` (patch or replace, up to 100); tasks require `taskId` (set `status: \"canceled\"` to remove a task — tasks are never trashed); profile blocks are upserts (`blockName` + `content`; `memory_policy` and `persona` are the two standing-instruction blocks — see penny_write's ladder). When the user tells you what to save, skip, check, or surface, update their memory_policy block in the same turn as a general rule in their words. Skill redefinition prepares a preview, not a save. Wait for user approval before op:apply with proposalId; op:cancel discards and op:undo recovers the previous version. Read skills view:history for version IDs; op:restore_revision with skillId, historyId, expectedUpdatedAt previews a restore. op:restore with skillId recovers a deleted skill, disabled. No invocation waiting period applies.  Trackers take `trackerId` and patch only the fields you pass (`name`/`description`/`unit`/`kind`/`targetSpec`/`archived` — archiving is the retire path, there is no tracker delete; private trackers only, not yet workspace-shared ones); rhythms are re-defined by full manifest; `entityType: \"rhythm_run\"` completes a run (`runId` + `status`). Projects take `projectId` + `expectedRevision` + `operationId` + a sparse `patch` (reread and reconcile on conflict); `op: \"restore_revision\"` restores selected `fields`/`resourceIds` from a `historyId` as a new revision. Tracker entries take `trackerId` + `entryId` + `expectedUpdatedAt` + the full `payload`. `op: \"restore\"` un-trashes notes or tracker entries by `ids`, or a Project by `projectId`.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "entityType": {
            "type": "string",
            "enum": [
              "profile",
              "task",
              "area",
              "project",
              "heading",
              "tracker",
              "rhythm",
              "rhythm_run",
              "skill",
              "skill_run",
              "note",
              "tracker_entry"
            ],
            "description": "Item type."
          },
          "op": {
            "type": "string",
            "enum": [
              "restore",
              "restore_revision",
              "apply",
              "cancel",
              "undo"
            ],
            "description": "op:\"restore\" un-trashes notes or tracker entries by `ids`."
          },
          "operationId": {
            "type": "string",
            "description": "Project receipt key; identical retries only."
          },
          "expectedRevision": {
            "type": "number",
            "description": "Project edit revision from Brief; reconcile conflicts."
          },
          "expectedUpdatedAt": {
            "type": "number",
            "description": "Source version from the read."
          },
          "patch": {
            "type": "object",
            "description": "Project patch: full schema on penny_write."
          },
          "snapshot": {
            "type": "string",
            "enum": [
              "before",
              "after"
            ],
            "description": "Skill restore_revision: which side of the history entry to restore (default before). Select after to recover a change that was undone."
          },
          "proposalId": {
            "type": "string",
            "description": "Skill change proposal returned by an edit. op:apply commits after user review; cancel discards; undo restores the previous version if no later edit exists."
          },
          "historyId": {
            "type": "string",
            "description": "restore_revision: Project history item or skill history item. Skill restoration prepares a preview; requires skillId and expectedUpdatedAt."
          },
          "fields": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Restore selection: field names or step:<stepId>; fields/resourceIds required."
          },
          "resourceIds": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Restore selected links."
          },
          "entryId": {
            "type": "string"
          },
          "payload": {
            "type": [
              "object",
              "string"
            ]
          },
          "agentNote": {
            "type": "string"
          },
          "recordedAt": {
            "type": "number"
          },
          "updates": {
            "type": "array",
            "maxItems": 100,
            "items": {
              "type": "object",
              "properties": {
                "memoryId": {
                  "type": "string"
                },
                "expectedUpdatedAt": {
                  "type": "number"
                },
                "mode": {
                  "type": "string",
                  "enum": [
                    "patch",
                    "replace"
                  ]
                },
                "content": {
                  "type": "string",
                  "description": "Required when mode is \"patch\"."
                },
                "tags": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                },
                "supersededBy": {
                  "type": "string",
                  "description": "Required when mode is \"replace\" — the id of the note that replaces this one."
                }
              },
              "required": [
                "memoryId",
                "mode"
              ]
            },
            "description": "entityType:\"note\" — patch or supersede existing notes (up to 100)."
          },
          "ids": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "op:\"restore\" — ids to un-trash (max 100)."
          },
          "taskId": {
            "type": "string",
            "description": "entityType:\"task\" (required) — the task to update."
          },
          "trackerId": {
            "type": "string",
            "description": "entityType:\"tracker\" (required) — the tracker to update. Only the fields you pass are patched — omit any you don't want to change."
          },
          "kind": {
            "type": "string",
            "description": "entityType:\"tracker\" — habit | metric | goal | log | status | custom."
          },
          "unit": {
            "type": "string",
            "description": "entityType:\"tracker\" — unit of measure."
          },
          "targetSpec": {
            "type": "object",
            "description": "tracker: replaces the whole target spec; shape as penny_write."
          },
          "skillId": {
            "type": "string",
            "description": "entityType:\"skill\" pause/resume — the skill id (required with enabled)."
          },
          "enabled": {
            "type": "boolean",
            "description": "entityType:\"skill\": false pauses due signals, true resumes; requires skillId. Penny does not run skills."
          },
          "clearFields": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "whenAt",
                "whenBucket",
                "deadline",
                "projectId",
                "headingId",
                "recurrence"
              ]
            },
            "description": "entityType:\"task\" — names of optional fields to UNSET on the task."
          },
          "title": {
            "type": "string",
            "description": "entityType:\"task\"/\"heading\" — the title/label."
          },
          "status": {
            "type": "string",
            "description": "task: open|in_progress|done|canceled. Repeating completion returns nextTaskId: act on that new occurrence; the completed ID rejects further status writes. skill_run/rhythm_run: done|error|skipped."
          },
          "owner": {
            "type": "string",
            "enum": [
              "me",
              "agent",
              "unassigned"
            ],
            "description": "entityType:\"task\" — assignee."
          },
          "whenAt": {
            "type": "number",
            "description": "entityType:\"task\"/\"project\" — schedule date (ms epoch)."
          },
          "whenBucket": {
            "type": "string",
            "enum": [
              "anytime",
              "someday"
            ],
            "description": "entityType:\"task\"/\"project\" — undated bucket; mutually exclusive with whenAt."
          },
          "deadline": {
            "type": "number",
            "description": "entityType:\"task\"/\"project\" — hard due date (ms epoch)."
          },
          "recurrence": {
            "type": "object",
            "properties": {
              "cadence": {
                "type": "string",
                "enum": [
                  "daily",
                  "weekly",
                  "monthly"
                ]
              },
              "at": {
                "type": "string",
                "description": "task: set/change recurrence; shape as penny_write. clearFields:[\"recurrence\"] ends the series, preserving history; target currentOccurrenceId."
              },
              "timezone": {
                "type": "string",
                "description": "IANA timezone (e.g. America/New_York)."
              }
            },
            "required": [
              "cadence"
            ],
            "description": "task: set/change recurrence. clearFields:[\"recurrence\"] ends the series, making the task one-off and preserving completed history. Target currentOccurrenceId, not a stale/completed ID."
          },
          "dependsOn": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "entityType:\"task\" — full replacement set of taskIds that must complete first."
          },
          "linkNotes": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "entityType:\"task\" — note ids to link to this task."
          },
          "order": {
            "type": "number",
            "description": "entityType:\"task\"/\"area\"/\"project\"/\"heading\" — sort order."
          },
          "actor": {
            "type": "string",
            "description": "entityType:\"task\"/\"area\"/\"project\"/\"heading\" — who took the action (me|agent), written to the activity ledger."
          },
          "orgId": {
            "type": "string",
            "description": "entityType:\"area\"/\"project\"/\"heading\" (required) — the container to update."
          },
          "name": {
            "type": "string",
            "description": "Area/project/tracker name; entityType:\"skill\" names prepare a preview of the replacement (rhythm names upsert)."
          },
          "notes": {
            "type": "string",
            "description": "entityType:\"task\"/\"area\"/\"project\" — markdown body."
          },
          "areaId": {
            "type": "string",
            "description": "entityType:\"project\" — the area the project belongs to."
          },
          "projectId": {
            "type": "string",
            "description": "entityType:\"heading\" (required) — the project the heading belongs to."
          },
          "archived": {
            "type": "boolean",
            "description": "Area/project/tracker: archive; false reactivates. Tracker definitions retire only this way."
          },
          "blockName": {
            "type": "string",
            "description": "entityType:\"profile\" (required) — the profile block to upsert."
          },
          "content": {
            "type": "string",
            "description": "entityType:\"profile\" (required) — the new block content."
          },
          "scope": {
            "type": "string",
            "enum": [
              "global",
              "workspace",
              "private"
            ],
            "description": "Profile: global|workspace. Projects: private; workspace requires workspaceId."
          },
          "trigger": {
            "type": "object",
            "description": "entityType:\"skill\": optional (required for rhythm). Omit to return to on-demand. Penny does not run it; the connected agent receives due signals. See penny_write for shape; ALWAYS set IANA timezone, default UTC."
          },
          "goal": {
            "type": "string",
            "description": "entityType:\"rhythm\" (required) — what the run should do. On entityType:\"skill\" this is `instructions`."
          },
          "instructions": {
            "type": "string",
            "description": "entityType:\"skill\" (required) — the saved know-how (generalizes the rhythm \"goal\")."
          },
          "retrievalPlan": {
            "type": "array",
            "description": "entityType:\"skill\" (or legacy \"rhythm\") — OPTIONAL deterministic steps for a bounded tier."
          },
          "deliver": {
            "type": "object",
            "description": "entityType:\"skill\": required with trigger (also rhythm); omit for on-demand. See penny_write for shape."
          },
          "posture": {
            "type": "string",
            "description": "entityType:\"skill\" with a `trigger` set (or legacy \"rhythm\") — read | propose | act."
          },
          "description": {
            "type": "string",
            "description": "entityType:\"skill\": REQUIRED use-when description; also rhythm. tracker: meaning; log trackers must document payload shape."
          },
          "runId": {
            "type": "string",
            "description": "entityType:\"skill_run\" (required) — the run to complete; same field on the legacy \"rhythm_run\"."
          },
          "provenance": {
            "type": "object",
            "description": "entityType:\"rhythm_run\" — accountability summary of what the run did (ids/labels, never full content).",
            "properties": {
              "summary": {
                "type": "string"
              },
              "reads": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "writes": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "delivered": {
                "type": "string"
              },
              "outsideWorld": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            }
          }
        },
        "required": [
          "entityType"
        ]
      },
      "annotations": {
        "title": "Edit memory",
        "readOnlyHint": false,
        "destructiveHint": true,
        "idempotentHint": true,
        "openWorldHint": false
      }
    },
    {
      "name": "penny_delete",
      "description": "Move to Trash. Project: projectId + expectedRevision + operationId; penny_edit op:restore recovers. Repeat in_progress with the same operationId; report partial_recovery conflicts. Note/tracker_entry: ids (max100); skill/rhythm: one id; profile_block: ids are block names. Tag/link removal uses the identifiers below. Tasks are canceled via penny_edit; tracker definitions are archived, not deleted.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "entityType": {
            "type": "string",
            "enum": [
              "project",
              "note",
              "tracker_entry",
              "rhythm",
              "skill",
              "profile_block",
              "tag_relation",
              "tracker_note_link"
            ],
            "description": "What to trash."
          },
          "ids": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "entityType:\"note\"/\"tracker_entry\" — ids to trash (max 100); \"rhythm\"/\"skill\" — exactly one id; \"profile_block\" — block names to trash."
          },
          "projectId": {
            "type": "string"
          },
          "expectedRevision": {
            "type": "number"
          },
          "operationId": {
            "type": "string"
          },
          "scope": {
            "type": "string",
            "enum": [
              "global",
              "workspace",
              "private"
            ],
            "description": "Profile block scope; Project private overrides defaults, workspace requires workspaceId."
          },
          "tagA": {
            "type": "string",
            "description": "entityType:\"tag_relation\" (required) — one endpoint of the edge to remove."
          },
          "tagB": {
            "type": "string",
            "description": "entityType:\"tag_relation\" (required) — the other endpoint."
          },
          "trackerEntryId": {
            "type": "string",
            "description": "entityType:\"tracker_note_link\" (required) — the entry to detach notes from."
          },
          "noteIds": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "entityType:\"tracker_note_link\" (required) — the notes to unlink."
          }
        },
        "required": [
          "entityType"
        ]
      },
      "annotations": {
        "title": "Trash from memory",
        "readOnlyHint": false,
        "destructiveHint": true,
        "idempotentHint": true,
        "openWorldHint": false
      }
    }
  ]
}
