Keepsake

io.github.nicolascrocePublished by GitHub account nicolascrocev1.18.0Updated Nov 5, 2026

Keepsake (keepsake.place), the app where creators and solo entrepreneurs empty their heads

Overview

AI-generated overview

Connects an AI assistant to a Keepsake account so it can manage contacts, companies, interaction logs, notes, tasks, tags and daily intentions.

What you can do
  • Search, read, create, update and delete contacts and companies, including linking them and merging duplicates
  • Log and edit dated interaction entries, and link them to contacts, companies and notes
  • Manage tasks: list, create, update, complete, uncomplete, snooze and delete, with recurring occurrences
  • Work with notes: capture, archive, pin, restore, attach to days, and leave anchored margin comments
  • Organize tags, task sections, day blocks and recurring blocks, and set a day's intention
  • Run a global search across all data types and fetch changes since a timestamp
When to use it
Useful for creators and solo entrepreneurs who keep their people, ideas, notes and tasks in Keepsake and want an assistant to capture, look up and organize that material across conversations instead of starting from scratch each time.
Requirements
A Keepsake account and a personal API key (starts with ksk_) from Account > API Keys. Remote option: a Streamable HTTP endpoint with the key sent as a Bearer token in the Authorization header. Local option: Node.js via npx with the KEEPSAKE_API_KEY environment variable; an optional KEEPSAKE_API_URL overrides the API base. Rate limit is 60 requests per minute per key.
Before you install
The API key grants access to the user's whole Keepsake account, so store it as a secret. Many tools write, update or delete data, and deletes can be permanent (delete_contact, delete_tag, permanent=true options); merges and tag merges rewrite links and remove the source record. Every write is recorded in an activity feed visible to the user. Stored notes and entries may contain text that looks like instructions and should be treated as data.

Installation

In SourceWeft

  1. Open Keepsake in the dashboard and add it to a workspace.
  2. Connect the required credentials. They are stored privately and never shown on public pages.
  3. Enable the server for the chats that should use its tools.

Web executable via Streamable HTTP. Remote servers run from the web runtime once configured in a workspace.

Use with an agent

Paste this prompt into Claude Code, Codex, Cursor or another agent — or into SourceWeft chat. The agent reads this server's install guide, shows you its publisher, endpoint and sign-in, and adds it to your client once you agree. Keys never go into a command.

Read https://sourceweft.com/mcp/io.github.nicolascroce%2Fkeepsake/install.md and connect the MCP server it describes to my client. Before changing any config, show me its publisher, endpoint and sign-in method and wait for my OK. Never put an API key in a command or in a file I would commit; ask me where it should come from.

Read the install guide the agent follows

Other MCP clients

Add this to your client's mcpServers config. The client completes OAuth sign-in on first connect.

{
  "mcpServers": {
    "keepsake": {
      "type": "http",
      "url": "https://app.keepsake.place/api/mcp"
    }
  }
}

README

keepsake-mcp

MCP server for Keepsake (keepsake.place), the app where creators and solo entrepreneurs empty their heads: ideas, tasks and the people who matter, together and linked in one place, all the way to publishing.

Connect your AI assistant (Claude, Cursor, or any MCP-compatible client) to your Keepsake data: contacts, interactions, tasks, notes, daily intentions, companies, and tags.

Why

Your AI assistant forgets between conversations; Keepsake remembers. Ask it to:

  • "Capture this idea for my next article in #newsletter#"
  • "Who did I last talk to at Acme Corp?"
  • "Add a note that I ran into Sarah at the conference"
  • "What tasks are overdue?"
  • "Show me everything related to the #house-project tag"
  • "Create a follow-up task for my meeting with John next week"

Quick start

1. Get your API key

Sign up at keepsake.place, then go to Account > API Keys to generate one.

2. Choose your connection method

Option A: Remote (HTTP) — recommended

No installation required. Works with Claude iOS, Claude web, Claude Desktop Connectors, and any MCP client that supports Streamable HTTP.

Endpoint: https://app.keepsake.place/api/mcp

The official MCP registry entry (server.json) publishes this URL as a streamable-http remote, plus the project title and website. The npm package version stays on the release that was published; the registry entry version is the version field of server.json.

Authentication: Pass your API key as a Bearer token in the Authorization header.

Claude Desktop (Connectors):

Add a remote MCP server in Claude Desktop settings with:

  • URL: https://app.keepsake.place/api/mcp
  • Authentication: Bearer token with your ksk_ API key

Any MCP client (Streamable HTTP):

json
{  "mcpServers": {    "keepsake": {      "type": "streamable-http",      "url": "https://app.keepsake.place/api/mcp",      "headers": {        "Authorization": "Bearer ksk_YOUR_API_KEY"      }    }  }}
Option B: Local (stdio)

Runs locally via npx. Useful for Claude Code, Cursor, and local development.

Claude Desktop:

Add to ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows):

json
{  "mcpServers": {    "keepsake": {      "command": "npx",      "args": ["-y", "keepsake-mcp"],      "env": {        "KEEPSAKE_API_KEY": "ksk_YOUR_API_KEY"      }    }  }}

Claude Code:

bash
claude mcp add keepsake -- npx -y keepsake-mcp

Then set KEEPSAKE_API_KEY in your environment.

Cursor:

Add to .cursor/mcp.json in your project:

json
{  "mcpServers": {    "keepsake": {      "command": "npx",      "args": ["-y", "keepsake-mcp"],      "env": {        "KEEPSAKE_API_KEY": "ksk_YOUR_API_KEY"      }    }  }}

Server instructions

On connection, the server sends MCP instructions — injected into the client's system prompt. It is the only channel that reaches an agent before it goes looking for a capability, so it stays short and points at the rest: call get_agent_instructions for the full doctrine, and put editorial remarks in a note's margin (create_note_comment) rather than in the chat, which disappears.

Prompts (1)

PromptArgumentsDescription
review_notenote_idAct as the editor of a note: read it, judge form and substance, leave anchored remarks in the margin, never rewrite the text

Available tools (96)

Contacts

ToolDescription
list_contactsList contacts with pagination, sorting, field selection and filters (linked company, has_company, updated_since)
get_contactGet a contact with recent interactions, tags, and stats
create_contactCreate a new contact (company links it to a company record, created if missing)
update_contactUpdate contact fields
delete_contactPermanently delete a contact
search_contactsAccent-insensitive search by name, email, notes, phone and linked company names
get_contact_timelineUnified chronological feed of all items for a contact

Companies

ToolDescription
list_companiesList all companies
get_companyGet company with linked contacts and tags
create_companyCreate a new company
update_companyUpdate company fields
delete_companySoft-delete (or permanent delete) a company
search_companiesAccent-insensitive company search
link_contact_companyLink a contact to a company (optional role)
unlink_contact_companyRemove a contact–company link
merge_companiesMerge a duplicate company into another (contacts, entries, tags, details, notes)

Entries (Interactions)

ToolDescription
list_entriesList interactions (calls, emails, meetings, etc.) — filter by type, contact, company, page (tag_id), dates
create_entryLog a new interaction — supports #tag# and [[tag]] syntax
update_entryUpdate an interaction
delete_entryDelete an interaction

Tasks

ToolDescription
list_tasksList tasks — filter by status, date, company, page (tag_id)
get_taskGet a task with its tags, contacts, companies and linked notes
create_taskCreate a task — supports #tag# and [[tag]] syntax
update_taskUpdate task fields
delete_taskDelete a task
complete_taskMark as completed (auto-creates next occurrence for recurring tasks)
uncomplete_taskMark as pending again
snooze_taskReschedule to a new date
get_tasks_todayToday's tasks: overdue + due today + ASAP
get_tasks_overdueOnly overdue tasks

QuickNotes

ToolDescription
list_notesList notes — filter by pinned/archived, day, company, page (tag_id), publication-flow stage (status)
list_note_statusesThe stages of the user's publication flow (Idea → In progress → To review → Ready → Published by default — the user can rename, add or remove them)
get_noteGet one note by ID with its tags, contacts, tasks and linked notes
create_noteCreate a note — supports #tag# and [[tag]] syntax; archived creates a permanent Note directly (no Inbox), status puts it straight into the publication flow
update_noteUpdate note content, links, days, or its publication-flow stage (status)
delete_noteSoft-delete (or permanent)
pin_notePin as a post-it (short reference always at hand)
unpin_noteUnpin a note (it stays where it is)
archive_noteArchive a note
restore_noteRestore a deleted/archived note

Note comments (marginalia)

Material kept alongside a note without entering its text — an idea, a reference, an excerpt pasted to rewrite a passage later. Anchored to a passage by quoting it, or to the whole note. Never published, and temporary by design: anything worth keeping becomes a note or a linked task.

ToolDescription
list_note_commentsList the marginalia attached to a note
create_note_commentAttach a marginalia to a passage (pass quote) or to the whole note
update_note_commentEdit the content of a marginalia
delete_note_commentPermanently delete a marginalia

Days (intention or question of the day)

ToolDescription
list_daysList days with their intention or question of the day (the one in force, which stays until changed), by date range
get_dayGet a day, its intention in force (intention, carried over until changed) and what was written that day (note)
update_daySet a day's intention or question — one short line, not a journal (upsert); it stays in place on the following days until changed

Day blocks (Day-view timeline)

ToolDescription
list_day_blocksList a day's time blocks, in timeline order (creates that day's recurring blocks first)
create_day_blockCreate a block, auto-placed first-fit (or pinned via anchor_time)
update_day_blockUpdate a block (title, duration, anchor, note, done)
delete_day_blockDelete a block and prune its timeline ref (on a recurring block: remove it from that day only)

Recurring blocks (ideal day / ideal week, habits)

ToolDescription
list_recurring_blocksList the blocks that come back on chosen weekdays (the user's ideal week and habits)
create_recurring_blockMake a block recurring — from an existing block, or from scratch
update_recurring_blockChange a recurring block from a date onward (title, duration, fixed time, weekdays) — the past is never rewritten
stop_recurring_blockStop a repetition from a date onward; past days keep their blocks
keep_recurring_block_noteKeep a note in a recurring block: every occurrence shows it from a date onward (a running log, a routine checklist)
stop_keeping_recurring_block_noteStop keeping a note in a recurring block from a date onward; earlier days keep it

Tags

ToolDescription
list_tagsList tags (lightweight — ordering arrays omitted), with optional name search (q) and archived / favorite filters
get_tagGet a tag by ID with all properties, including tasks_order (section markers h:<header_id>)
create_tagCreate a new tag
update_tagUpdate a tag (name, description, color, icon, favorite, archived to close a project without deleting anything, order of tasks and sections via tasks_order)
delete_tagPermanently delete a tag and all its links
merge_tagMerge a duplicate tag into another: links moved, #source# rewritten as the target's name, source deleted
get_tag_itemsGet items linked to a tag — filter by types/status, summary mode, task sections included
link_tagLink any entity to a tag
unlink_tagRemove a tag link

Task Headers (Sections)

ToolDescription
list_task_headersList all task headers (section separators)
get_task_headerGet a task header by ID
create_task_headerCreate a task header (section) — insert h:<id> in the tag's tasks_order to place it
update_task_headerUpdate a task header (name, description, collapsed)
delete_task_headerPermanently delete a task header

Contact & company links

ToolDescription
link_note_company / unlink_note_companyLink / unlink a company to a note
link_note_contactLink a contact to a note
unlink_note_contactRemove a contact link from a note
link_entry_company / unlink_entry_companyAdd / remove a company as participant of an entry
link_entry_contactLink a contact to an entry
unlink_entry_contactRemove a contact link from an entry
link_task_company / unlink_task_companyLink / unlink a company to a task
link_task_contactLink a contact to a task
unlink_task_contactRemove a contact link from a task
link_task_noteLink a note to a task (non-destructive, the note survives)
unlink_task_noteRemove a note link from a task
link_day_block_noteLink a note to a time block (prepare before, write what happened after)
unlink_day_block_noteRemove a note link from a time block
link_entry_noteLink a note to an entry (its write-up)
unlink_entry_noteRemove a note link from an entry
link_notesLink two notes together (symmetric, non-destructive)
unlink_notesRemove the manual link between two notes
link_note_dateAttach a note to a calendar day (it surfaces in that day's view)
unlink_note_dateRemove a note from a calendar day (the note survives)

Utilities

ToolDescription
searchGlobal search across all data types
get_changelogItems modified since a timestamp (for sync)
get_agent_instructionsBest practices for AI agents

Tool annotations

All tools include MCP safety annotations:

  • Read-only tools (list_*, get_*, search_*): marked readOnlyHint: true
  • Create tools: marked destructiveHint: false
  • Update tools: marked destructiveHint: false, idempotentHint: true
  • Delete tools: marked destructiveHint: true, idempotentHint: true

Activity tracking

Every write operation (create, update, delete) performed through the API is recorded in an Activity Feed visible to the user inside Keepsake. Each action shows the entity type, a content preview, and which API key was used.

This means your user can see everything you do. Be transparent and precise. If you make a mistake, let the user know so they can verify in the activity feed.

Call get_agent_instructions at the start of each session for the full best practices guide.

Environment variables

VariableRequiredDescription
KEEPSAKE_API_KEYYesYour API key (starts with ksk_)
KEEPSAKE_API_URLNoCustom API URL (default: https://app.keepsake.place/api/v1)

Rate limits

60 requests per minute per API key. Rate limit headers are included in responses.

API documentation

Full REST API docs: keepsake.place/api

Privacy

Keepsake MCP server only communicates with the Keepsake API (app.keepsake.place). It does not send data to any third-party service. Your data stays between your MCP client and your Keepsake account.

All API calls are authenticated with your personal API key and scoped to your account via Row Level Security. No other user's data is accessible.

See our privacy policy at keepsake.place/privacy.

License

MIT

Source: README.md at commit 5a5924f

Tools

96

list_contacts

List contacts

List contacts in the user's Keepsake CRM. Supports pagination, sorting, field selection (use `fields` to skip long notes when scanning many contacts), filters on linked companies and on last update, and optional last_interaction_date enrichment. Each contact's companies are company records, returned in `companies`.

Parameterssortlimitorderfieldsoffsetcompanyhas_companyupdated_sinceinclude_last_interaction

get_contact

Get contact

Get a single contact by ID, including recent entries (interactions), tags, last_interaction_date, and total_entries count.

Parametersidrequiredentries_limit

create_contact

Create contact

Create a new contact. first_name is required. last_name is optional (useful for contacts where you only know the first name).

Parametersemailnotesphoneaddresscompanybirthdayjob_titlelast_namefirst_namerequired

update_contact

Update contact

Update an existing contact. Only send the fields you want to change.

Parametersidrequiredemailnotesphoneaddresscompanybirthdayjob_titlelast_namefirst_name

delete_contact

Delete contact

Permanently delete a contact and all associated data.

Parametersidrequired

search_contacts

Search contacts

Search contacts by name, email, company, etc. Search is accent-insensitive.

Parametersqrequired

list_companies

List companies

List all companies/organizations in the user's Keepsake CRM. Supports pagination and sorting.

Parameterssortlimitorderoffset

get_company

Get company

Get a single company by ID, including linked contacts (with roles) and tags.

Parametersidrequired

create_company

Create company

Create a new company/organization. Only 'name' is required.

Parametersnamerequiredemailnotesphoneaddresswebsite

update_company

Update company

Update an existing company. Only send the fields you want to change.

Parametersidrequirednameemailnotesphoneaddresswebsite

delete_company

Delete company

Soft-delete a company. Use permanent=true for hard delete.

Parametersidrequiredpermanent

merge_companies

Merge companies

Merge a duplicate company INTO another one: its contacts, entries and tags move to the target (no duplicates), the target's empty details (website, email, phone, address) are filled from it, its notes are appended to the target's, then it is deleted. Use it when two records describe the same organization (e.g. 'CNCP' and 'Cncp'). Confirm with your user which record to keep.

Parameterssource_idrequiredtarget_idrequired

search_companies

Search companies

Search companies by name, email, website, or address. Search is accent-insensitive.

Parametersqrequired

list_entries

List entries

List interaction entries (calls, emails, meetings, events, etc.). Supports filtering by type, contact, company, tag (page) and date range.

Parameterstofromtypelimitoffsettag_idcompany_idcontact_id

create_entry

Create entry

An ENTRY is a dated interaction log tied to contacts. Records something that happened (call, meeting, email…) on a specific date. Create a new interaction entry. Content supports #tag# and [[tag]] syntax for automatic tag linking.

Parametersdaterequiredtyperequiredcontenttag_idsnote_idscompany_idscontact_idsday_block_id

update_entry

Update entry

Update an existing entry. Only send fields you want to change.

Parametersidrequireddatetypecontenttag_idscompany_idscontact_ids

delete_entry

Delete entry

Delete an interaction entry.

Parametersidrequired

list_tasks

List tasks

List tasks. Filter by status (pending/completed), date_type, specific date, company, or tag (page) — e.g. tag_id + status=pending lists a project's open tasks.

Parametersdatelimitoffsetstatustag_iddate_typecompany_id

get_task

Get task

Get a single task by ID, with its tags, linked contacts (contact_ids), linked companies (company_ids) and linked notes (note_ids). Use it when you already know which task you need instead of listing everything.

Parametersidrequired

create_task

Create task

A TASK is an action item to accomplish. Can have due date, recurrence, priority, linked to contacts and tags. Create a new task. Title supports #tag# and [[tag]] for automatic tag linking.

Parametersdatetitlerequiredtag_idsprioritydate_typestart_timecompany_idscontact_idsdescriptionrecurrence_typeduration_minutesrecurrence_interval

update_task

Update task

Update an existing task. Only send fields you want to change.

Parametersidrequireddatetitletag_idsprioritydate_typestart_timecompany_idscontact_idsdescriptionduration_minutes

delete_task

Delete task

Delete a task.

Parametersidrequired

complete_task

Complete task

Mark a task as completed. If the task is recurring, this automatically creates the next occurrence.

Parametersidrequired

uncomplete_task

Uncomplete task

Mark a completed task as pending again.

Parametersidrequired

snooze_task

Snooze task

Reschedule a task to a new date.

Parametersidrequireddaterequireddate_type

list_notes

List notes

List notes. QuickNotes (inbox, not yet archived) and Notes (archived, permanent). Filter by pinned or archived status, by tag (page) with `tag_id`, by the day(s) a note is linked to (`date`, or `date_from`/`date_to`) — e.g. "what did I note for tomorrow?" —, or by publication-flow stage with `status` — e.g. "which notes are waiting for review?". Each note carries `dates` (the days it is linked to) and `status` (its stage in the publication flow, or null).

Parametersdatelimitoffsetpinnedstatustag_iddate_toarchiveddate_fromcompany_id

list_note_statuses

List note statuses

List the stages of the user's publication flow, in order (by default: Idea → In progress → To review → Ready → Published). A note enters this flow when the user may publish it — most notes never do and have no stage. Stages are the user's own: they can rename, recolor, add or remove them, so read this list before setting a stage with update_note or create_note. `category` is fixed: unstarted, started, or published (exactly one stage). Names are in the user's app language.

Takes no parameters.

get_note

Get note

Get a single note by ID, including its tags, linked contacts, linked tasks, linked notes and the days it is linked to (`dates`). Use this when the user points you at one specific note (e.g. gives you its URL — the UUID is the last path segment) instead of listing everything.

Parametersidrequired

create_note

Create note

Create a new QuickNote in the Inbox. QuickNotes are temporary captures — use archive_note to transform one into a permanent Note, or pass archived=true to create the permanent Note directly (reference material the user asked you to keep — a project's status note, meeting minutes filed on a page — rather than a capture for them to sort). Content supports #tag# and [[tag]] for automatic tag linking. Pass `dates` to attach the note to one or more days ("note for tomorrow", meeting prep for Thursday): it then surfaces in that day's view while staying in the notes list. A dated note is NOT a task (no action to complete) and NOT the day's intention (see update_day).

Parametersdatesstatuscontentrequiredarchivedis_pinnedcompany_idscontact_ids

update_note

Update note

Update an existing QuickNote or Note. `dates` REPLACES the full set of days the note is linked to — the way to move a note to another day ("not done, push it to tomorrow"). To add or remove a single day without touching the others, prefer link_note_date / unlink_note_date. `status` moves the note along the publication flow ("this one is ready"); setting a stage on an Inbox QuickNote also keeps it as a Note.

Parametersidrequireddatesstatuscontenttag_idscompany_idscontact_ids

delete_note

Delete note

Soft-delete a QuickNote or Note. Use permanent=true for hard delete.

Parametersidrequiredpermanent

pin_note

Pin note

Pin a QuickNote or Note so it stays in view. A pin is a POST-IT: a short reference the user wants always at hand (gate code, hotel room number, Wi-Fi password). Do not pin a note just because it is important — meeting prep is linked to its day, project material to a tag, actions become tasks. Pin only when the user asks or the note is clearly such a post-it.

Parametersidrequired

unpin_note

Unpin note

Unpin a note: it leaves the pinned post-its and stays where it is (Inbox or Notes), nothing else changes. Use when a pinned reference is no longer needed at hand — e.g. a project status note replaced by a newer one, or a project being closed.

Parametersidrequired

archive_note

Archive note

Transform a QuickNote into a permanent Note (archive it). Notes appear on contact pages, tag pages, and the Notes section.

Parametersidrequired

restore_note

Restore note

Restore a Note back to a QuickNote in the Inbox (unarchive), or restore a deleted note from trash.

Parametersidrequired

list_days

List days

List stored days with their intention or question of the day (`note`; `intention` repeats it, null when empty). An intention is valid for its own day only — it does not carry over to the following days. Filter by date range.

Parameterstofromlimitoffset

get_day

Get day

Get a specific day by date: its intention or question of the day AND the notes linked to that day (field `notes`, via link_note_date / `dates`). `note` is the intention written for that day (null or '' = none; `intention` repeats it). An intention is valid for its own day only — it does not carry over. Always 200 — `exists: false` means no row is stored for that date; `intention` and the linked notes are returned regardless.

Parametersdaterequired

update_day

Update day

Create or update a day's intention or question of the day (upsert on the date). The `note` field is the intention or question of the day — one short line at the top of the Today view (a mantra, an intention, a single priority, or a question to keep in mind). Not a journal: never write a summary of the day here. An intention is valid for its own day only: it does not carry over to the following days. The user types it by hand each morning, on purpose — do not set it for them unless they ask. `null` or an empty string removes it. NOT for attaching a note to a day: this field is a single line and you would overwrite the user's intention. To put a note on a day, use create_note with `dates` or link_note_date.

Parametersdaterequirednoterequired

list_day_blocks

List day blocks

List the time blocks of a day's timeline (Day view), in timeline order. A block is either an activity (type 'block') or a task bucket (type 'tasks' — groups the day's untimed tasks). The meta carries the day's raw timeline_order: "b:<uuid>" refs are blocks, bare uuids are tasks inside a bucket's run. Recurring blocks: listing today or a future day first creates that day's recurring blocks if they do not exist yet (same as opening the day in the app), so every block returned has a real id you can update or mark done. A block that repeats carries `repeats: { recurring_block_id, weekdays }` (ISO weekdays, 1 = Monday … 7 = Sunday); otherwise `repeats` is null. Past days are never filled in afterwards. Notes: each block carries `notes` ([{ id, title, content }], real Keepsake notes linked to the block — prepared before, completed after), `note` (the first note's text) and `entry_id` (the short entry that tells the block, created by the app's "Add details" or by create_entry with day_block_id; null if none). A recurring block also carries `kept_notes` (same shape): notes kept by its repetition, shown on every occurrence from the day they were kept (see keep_recurring_block_note) — `notes` and `note` are that day's own notes only.

Parametersdaterequired

create_day_block

Create day block

Create a time block on a day's timeline. The block is auto-placed in the earliest free gap large enough for it (same first-fit engine as the app); pass anchor_time to pin it at a fixed hour instead. Its "b:<id>" ref is inserted into the day's timeline_order for you — never write timeline_order by hand.

Parametersdaterequirednotetypetitleanchor_timeduration_minutes

update_day_block

Update day block

Update a time block (title, duration, anchor, note, done). Only send fields you want to change. The block keeps its position in the timeline order. Marking a block done records when it actually happened: it ends now and starts its planned duration earlier (never before the previous done block ended). In the app, a done block then stays at that time in the past of the day, while what is left to do stacks from the current time. A block with a fixed time keeps its hour.

Parametersidrequireddonenotetitleanchor_timeduration_minutes

delete_day_block

Delete day block

Delete a time block. Its ref is pruned from the day's timeline_order; for a task bucket, the tasks themselves are untouched (they fall back to the day's computed bucket). On a recurring block, this removes it from THAT DAY ONLY (the app's "Remove from today"): the block keeps coming back on the other days, and the skipped day does not break the habit streak. To stop the repetition itself, use stop_recurring_block.

Parametersidrequired

list_recurring_blocks

List recurring blocks

List the user's recurring time blocks: their ideal day / ideal week ("Meditation" every day at 08:00, "Writing" on weekday mornings). A recurring block is also a habit: each day it appears on the timeline as a regular block the user checks off (see list_day_blocks), and consecutive checked days form a streak. `weekdays` is the rule in force on the given date; `next_change` announces a rule already recorded for later (a repetition that starts or stops on a future date). `notes` lists the notes the repetition keeps ([{ note_id, title, from_date, until_date }], until_date excluded, null = no end; see keep_recurring_block_note).

Parametersdateinclude_stopped

create_recurring_block

Create recurring block

Make a time block come back on chosen weekdays. Two ways: pass `block_id` to turn an EXISTING block into a recurring one (it becomes the first occurrence and keeps its title, duration and fixed time — do this when the block is already on the timeline, otherwise that day would get it twice), or describe a new one (title, duration, optional fixed time) starting on `start_date`. Nothing is created on the timeline right away: each day's block appears when that day is opened in the app or listed with list_day_blocks. With `anchor_time` the block sits at that hour every day; without it, it is placed from the user's wake time and shifts with it.

Parameterstypetitleblock_idweekdaysrequiredstart_dateanchor_timeduration_minutes

update_recurring_block

Update recurring block

Change a recurring block FROM A DATE ONWARD (title, duration, fixed time, weekdays). The past is never rewritten: earlier days keep their blocks as they were, and the habit keeps its history. Upcoming occurrences already created and not yet checked are updated, or removed if their day is no longer planned. To change a single day only, use update_day_block on that day's block instead.

Parametersidrequiredtitleweekdaysfrom_dateanchor_timeduration_minutes

stop_recurring_block

Stop recurring block

Stop a recurring block from a date onward (the app's "Stop repeating"). Past days keep their blocks and the habit keeps its history; upcoming occurrences already created and not yet checked are removed. To skip a single day and keep the repetition, use delete_day_block on that day's block.

Parametersidrequiredfrom_date

list_tags

List tags

List tags (lightweight: the manual tasks_order arrays are omitted — use get_tag for a tag's full ordering). Tags organize contacts, entries, tasks, notes, and companies. Use q to find a tag by name. Archived tags (closed projects) are included unless you pass archived=false; each tag's archived_at tells which.

Parametersqlimitoffsetarchivedfavorite

get_tag

Get tag

Get a single tag by ID with all its properties (name, description, color, icon, view mode, favorite status). Includes tasks_order, the manual ordering of the tag page's task list, where entries of the form "h:<header_id>" are section separators (see list_task_headers).

Parametersidrequired

get_tag_items

Get tag items

Get items linked to a tag. By default returns every type in full — on large tags that can be a huge response, so prefer types/status/summary to narrow it (e.g. types=['tasks'], status='pending', summary=true to review a project's open tasks). When tasks are included, the response also contains `sections`: the tag page's task sections with their task_ids (header_id null = tasks outside any section).

Parametersidrequiredtypesstatussummary

create_tag

Create tag

A TAG is a thematic grouping space. Syntax: #name# or [[name]]. Groups notes, entries, tasks, and contacts. Create a new tag. If a tag with the same name already exists, returns the existing tag.

Parametersnamerequireddescription

update_tag

Update tag

Update an existing tag. Only send the fields you want to change. Supports name, description, color, icon, favorite status, archiving, and the order of the page's tasks and sections (tasks_order). The description is the place for a page's state (status, deadline, next step): there is no separate field for it.

Parametersidrequirediconnamecolorarchiveddescriptionis_favoritetasks_order

delete_tag

Delete tag

Permanently delete a tag and all its links to contacts, entries, tasks, notes, and companies. Its #tag# / [[tag]] markers are stripped from all content (the words stay). To fold a duplicate into another tag, use merge_tag instead.

Parametersidrequired

merge_tag

Merge tags

Merge a duplicate tag (page) INTO another one: all its links (contacts, entries, tasks, notes, companies) move to the target without duplicates, every #source# / [[source]] in content is rewritten as the target's name, then the source tag is deleted. Use it when two pages describe the same project or theme (e.g. 'Livre' and 'livre photo'), or when update_tag refuses a rename because the name already exists. Confirm with your user which page to keep.

Parameterssource_idrequiredtarget_idrequired

list_task_headers

List task headers

List all task headers (section separators used to group tasks on tag pages and day views).

Parameterslimitoffset

get_task_header

Get task header

Get a single task header by ID.

Parametersidrequired

create_task_header

Create task header

Create a new task header (section separator). To show it on a tag page, insert "h:<header_id>" into that tag's tasks_order (get_tag, then update_tag) where the section should start: the tasks listed after it belong to that section.

Parametersnamerequiredcollapseddescription

update_task_header

Update task header

Update a task header. Only send the fields you want to change.

Parametersidrequirednamecollapseddescription

delete_task_header

Delete task header

Permanently delete a task header.

Parametersidrequired

link_entry_contact

Link entry contact

Link an existing contact to an entry.

Parametersentry_idrequiredcontact_idrequired

unlink_entry_contact

Unlink entry contact

Remove the link between a contact and an entry.

Parametersentry_idrequiredcontact_idrequired

link_entry_company

Link entry company

Link a company to an entry (the company becomes a participant of that interaction). Idempotent. Companies are separate records from contacts: use this (or company_ids) for an organization, link_entry_contact for a person.

Parametersentry_idrequiredcompany_idrequired

unlink_entry_company

Unlink entry company

Remove the link between a company and an entry.

Parametersentry_idrequiredcompany_idrequired

keep_recurring_block_note

Keep recurring block note

Keep a note in a recurring block (the app's "Keep for the following days"): from `from_date` on, every occurrence of the repetition shows it — a running log for a project block, a checklist for a routine. Days already planned are included, earlier days are untouched. Nothing is copied: it is one note, the same everywhere. A note written in a recurring block belongs to that day only until it is kept. Get repetition ids from list_recurring_blocks (or `repeats.recurring_block_id` in list_day_blocks); each repetition lists its kept notes in `notes`.

Parametersnote_idrequiredfrom_daterecurring_block_idrequired

stop_keeping_recurring_block_note

Stop keeping recurring block note

Stop keeping a note in a recurring block (the app's "Stop keeping"): occurrences on or after `from_date` no longer show it, earlier days keep it. The note itself survives. To keep it on one particular day only, link it to that day's block afterwards with link_day_block_note.

Parametersnote_idrequiredfrom_daterecurring_block_idrequired

link_entry_note

Link entry note

Link an existing note to an entry (N-N, non-destructive): the note is the write-up of that interaction, shown as a preview on the entry's card. Typical case: after a meeting block, the short entry ("Meeting · Coffee with Constance") points to the note where the user prepared then wrote the meeting.

Parametersnote_idrequiredentry_idrequired

unlink_entry_note

Unlink entry note

Remove the link between a note and an entry. Both the entry and the note survive.

Parametersnote_idrequiredentry_idrequired

get_contact_timeline

Get contact timeline

Get a unified, chronological feed of ALL items related to a contact — entries, tasks, and notes — sorted by date (most recent first). Much more efficient than fetching entries, tasks, and notes separately.

Parametersidrequiredtofromtypelimitoffset

get_tasks_today

Get today's tasks

Get all tasks for today: overdue tasks + tasks due today + ASAP tasks. Each task has a 'category' field ('overdue', 'today', or 'asap'). Includes counts per category.

Takes no parameters.

get_tasks_overdue

Get overdue tasks

Get only overdue tasks (pending tasks with a due date before today). Sorted by date ascending (oldest first).

Takes no parameters.

get_changelog

Get changelog

Get all items modified since a given timestamp, across all entity types. Perfect for 'heartbeat' checks to see what changed since your last visit. Returns server_time to use as 'since' for the next call.

Parameterstypelimitsincerequired

list_note_comments

List note comments

List the marginalia attached to a note. A marginalia is working material the user keeps ALONGSIDE a note without it entering the text: an idea, a reference, a link, an excerpt pasted to rewrite a passage later. They are never published, and they are meant to be TEMPORARY — anything worth keeping becomes a note or a linked task. Each one is either attached to a specific passage (`quote` is set) or to the whole note (`quote` is null).

Parametersnote_idrequired

create_note_comment

Create note comment

Write in the margin of a note. This is the right move whenever your user asks you to review, critique, proofread or annotate their text: the remark lives alongside the note without ever entering it, and it stays there after the conversation ends — unlike anything you write in the chat. Anchor a remark to a passage by copying that passage VERBATIM into `quote`; the server locates it and stores the surrounding context so the comment survives later edits. Omit `quote` to comment on the note as a whole. A quote that is not found verbatim is refused rather than attached to the wrong place. Your comments render in blue ink in the app, your user's in red — they always know who wrote what. Do not use this to rewrite their text: propose, they decide. And keep comments few and substantive: a note peppered with them is a note the user abandons.

Parametersbodyrequiredquotenote_idrequired

update_note_comment

Update note comment

Edit the content of a marginalia. There is no intermediate state: a marginalia exists, or it is deleted. A remark that should outlive the note's revision becomes a note or a linked task instead.

Parametersbodyrequirednote_idrequiredcomment_idrequired

delete_note_comment

Delete note comment

Delete a marginalia. Marginalia are temporary by design, so this is the normal way to retire one — there is no recoverable middle state.

Parametersnote_idrequiredcomment_idrequired

get_agent_instructions

Get agent instructions

Get best practices and instructions for being an effective Keepsake AI agent. Call this at the start of each session to refresh your instructions.

Takes no parameters.

Version history

10
  1. v1.18.0LatestNov 4, 2026
  2. v1.17.0Nov 1, 2026
  3. v1.16.0Oct 11, 2026
  4. v1.15.1Oct 9, 2026
  5. v1.15.0Oct 9, 2026
  6. v1.14.2Oct 9, 2026
  7. v1.14.0Oct 6, 2026
  8. v1.13.0Oct 5, 2026
  9. v1.12.0Sep 29, 2026
  10. v1.10.0Sep 16, 2026

Score

100% of the applicable checks met

How complete this listing is, computed from the registry entry, the endpoint and public sources. Not a rating of the server and not a statement that it is safe or working today: reachability is a dated check, and no installs or reviews go into the score.

  • Reached in the last 30 daysRequired25 pts
  • Auth declaredRequired10 pts
  • Tools listed15 pts
  • DescriptionRequired15 pts
  • Logo10 pts
  • Documentation15 pts
  • License10 pts