Skip to main content
Glama

MyPenny

penny_write

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. Write something new to the user's memory. Choosing entityType — walk this ladder top to bottom, first match wins:

  1. 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.

  2. 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.

  3. 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.

  4. 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.

  5. 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. Tag 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 MyPenny skill.

When 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 for which that note would be a useful retrieval result. Derive them FROM the content you're about to write — three different ways the user might ask, in conversation, something this memory should answer. 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 retrieval 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?"].

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
goalNoentityType:"rhythm" (required) — natural-language instruction: what the run should do. On entityType:"skill" this is `instructions`.
kindNoentityType:"tracker" (required) — habit | metric | goal | log | status | custom.
nameNoRequired 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.
tagsNoentityType:"task" — tags to attach.
unitNoentityType:"tracker" — unit of measure.
actorNoentityType:"task"/"area"/"project"/"heading" — who took the action (me|agent), written to the activity ledger.
childNoentityType:"tag_relation" (required) — the child tag.
notesNonote: 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.
orderNoentityType:"task"/"area"/"project"/"heading" — sort order.
ownerNoentityType:"task" — assignee.
patchNoProject sparse changes; omitted fields stay. Max 25 step/resource changes.
scopeNoProfile: global|workspace. Projects: private; workspace requires workspaceId.
titleNoentityType:"task" (required) or "heading" (required) — the title/label.
areaIdNoentityType:"project" (required) — the area the project belongs to.
parentNoentityType:"tag_relation" (required) — the parent tag in the child_of edge.
sourceNoentityType:"note"/"tracker_entry" — provenance label (defaults 'conversation' / 'agent-mcp').
statusNoentityType:"task" — initial status.
whenAtNoentityType:"task"/"project" — schedule date (ms epoch).
contentNoentityType:"profile" (required) — the block content.
deliverNoentityType:"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' }.
entriesNotracker_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.
noteIdsNoentityType:"tracker_entry" — archival note ids to attach; or "tracker_note_link" (required) — the notes to link.
payloadNoentityType:"tracker_entry" (required unless `entries` is used) — the structured data point; shape is tracker-defined.
postureNoentityType:"skill" with a `trigger` set (or legacy "rhythm") — read | propose | act (defaults 'read').
skillIdNoentityType:"skill_invoke" (required, or pass `name`) — the skill to run now. entityType:"skill_run" — the skill to begin a run of (or pass `name`).
triggerNoentityType:"skill": optional schedule (required for rhythm), requires deliver. MyPenny 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[]}}.
deadlineNoentityType:"task"/"project" — hard due date (ms epoch).
rhythmIdNoentityType:"rhythm_run" — the rhythm to begin a run of (or pass `name`).
agentNoteNoentityType:"tracker_entry" (single-entry form only) — short caption on this one data point (not searchable).
blockNameNoentityType:"profile" (required) — the profile block name to upsert.
dependsOnNoentityType:"task" — full replacement set of taskIds that must complete first.
headingIdNoentityType:"task" — heading to file the task under.
linkNotesNoentityType:"task" — note ids to link to this task.
projectIdNoentityType:"task" — parent project; or "heading" — the project it belongs to (required).
reasoningNoentityType:"tag_relation" — short justification (typically a user quote) for the edge.
trackerIdNoentityType:"tracker_entry" (required) — the tracker to log against.
entityTypeYesWhat to create. Walk the ladder in the tool description; first match wins.
recordedAtNoentityType:"tracker_entry" (single-entry form only) — observation time (ms epoch; defaults to now).
recurrenceNoentityType:"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.
targetSpecNoentityType:"tracker" — JSON target spec, interpreted at retrieval (e.g. { kind: 'daily_minimum', value: 10000 }).
whenBucketNoentityType:"task"/"project" — undated bucket; mutually exclusive with whenAt.
descriptionNoentityType:"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.
interactionNoproject_interaction: actor decision; read first, update with expectedUpdatedAt.
operationIdNoProject receipt key; identical retries only.
instructionsNoentityType:"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".
retrievalPlanNoentityType:"skill" (or legacy "rhythm") — OPTIONAL deterministic steps [{ tool, args }] for a bounded tier.
trackerEntryIdNoentityType:"tracker_note_link" (required) — the logged tracker entry to attach notes to.
expectedRevisionNoProject edit revision from Brief; reconcile conflicts.
expectedUpdatedAtNoSource version from the read.

Schema Changelog

Changes observed during successful MCP inspections.

  1. First observed

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=false, destructiveHint=false, idempotentHint=false, so the description doesn't need to restate mutation. It adds substantial behavioral context beyond annotations: the confidence calibration ladder (0.95→0.20), the requirement for exactly three sampleQuestions in the user's voice, the tracker duplicate-name rejection behavior, the batch-write limits (100 items), and the 'receipts report each saved/failed item; do not claim all saved from a partial result' warning. It doesn't fully disclose all side effects (e.g., what happens on partial batch failure beyond receipts), but for a 49-param tool this is strong coverage.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long (roughly 500 words), but every sentence earns its place given the tool's 16 entityTypes and 49 parameters. It is front-loaded with the core purpose and the decision ladder, then progressively details each branch. The numbered ladder structure makes it scannable. It loses one point for density — the profile-block paragraph and the skill paragraph pack multiple rules into single sentences, which could be split for easier parsing — but it is not bloated or repetitive.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with 16 entityTypes, 49 parameters, nested objects, and no output schema, the description is remarkably complete. It covers the decision procedure (ladder), the data-quality requirements (confidence, sampleQuestions), the sibling routing (penny_edit, penny_delete), the batch semantics, and the project revision flow (expectedRevision, operationId). The only minor gap is that it doesn't describe the return shape, but with no output schema and the receipts warning, the agent has enough to call correctly. Nothing critical is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description adds meaning beyond the schema by explaining the entityType ladder that determines which parameters are relevant, and by giving concrete examples for sampleQuestions ('What citation style should I use for the paper?'). It also clarifies semantic nuances the schema can't: 'A tracker name does NOT upsert (unlike skill)', 'profile blocks are upserts', and 'a note is the fallback, not the default'. It doesn't document every one of the 49 parameters, but the schema already does that; the description's job is to explain selection logic, which it does thoroughly.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a vivid, specific verb phrase ('Save the moment something durable emerges') and immediately names the resource ('the user's memory'). It then enumerates the full entityType ladder with concrete examples (decision, preference, plan, correction, to-do, measurement), which distinguishes this write tool from siblings like penny_read and penny_edit. The 'first match wins' ladder is a clear decision procedure, not a vague restatement.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description is explicit about when to use this tool vs alternatives: it says to use penny_edit for modifications, penny_delete for trashing, and names the profile-block upsert path. It gives conditional routing ('if no tracker fits, propose one before logging', 'when unsure between a note and the above, prefer the specific type'). It also states when NOT to save (pending_share_approval is a proposal, not a save). This is the strongest possible usage guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

Resources