Agent Chat & MCP Server
memrynote can run an in-app Agent Chat backed by a provider-neutral agent backend. Claude CLI is the first full backend, local OpenAI-compatible servers can be used for BYO local models, and the Codex CLI backend uses the same contract when enabled. After a vault opens, the desktop app keeps the Agent runtime idle until Agent Chat or Agent MCP is opened. At that point it starts a local MCP endpoint on 127.0.0.1 with a random port, then gives the selected backend only the vault tools for the current conversation.
Opening the Agent MCP settings uses the same lazy start path as opening Agent Chat. If the runtime is still starting, memrynote retries the status check until the vault-scoped endpoint, bearer token, and tool list are ready to copy.
The Agent runtime and MCP endpoint are scoped to the open vault. Closing or switching vaults stops active turns, clears pending tool approvals, and restarts the Agent services for the next vault. The MCP endpoint is stopped with the vault even if the Agent runtime itself failed to start, so the next vault always gets a fresh endpoint and bearer token instead of the previous vault's.
The same MCP endpoint can also be copied into other desktop AI clients for vault read tools.
Open Settings -> AI Assistant -> Agent MCP to copy the current endpoint and bearer token. Open Settings -> AI Assistant -> Agent Permissions to set the default Agent Chat access mode and action-confirmation behavior.
Agent Chat
Open the right sidebar, choose Agent, and pick a provider. The compact Day/Agent switch keeps the active view highlighted at the top of the right sidebar, and switching to Agent takes effect on the first click even when the sidebar opened on the Day view. The assistant backend still starts up on first use rather than at launch, so the panel can show a brief loading state while providers and conversation history are detected. The Agent header includes a new-conversation button, a history menu for switching back to recent conversations, and a pop-out button for moving the current conversation into a workspace tab. Popped-out conversations keep the generated conversation title as the tab name, use the same centered reading column as notes, and leave the right sidebar ready for a new chat. The popped-out tab keeps the scroll bar at the window edge while the chat content stays centered, and the tab name is the only conversation title shown in that workspace view. Assistant responses render as full-width text in both the sidebar and popped-out tabs instead of bordered bubbles, with text aligned to the prompt input. For Claude CLI, memrynote checks that claude is available on PATH, that it reports version 2.1.0 or newer, and that the Agent disclosure has been accepted; the Codex CLI and the Antigravity CLI (agy, version 1.2.7 or newer) are detected the same way. On macOS and Linux, memrynote resolves your login shell's PATH at startup, so CLIs installed in shell-managed locations (~/.local/bin, Homebrew, nvm, volta) are still found when the app is launched from the Dock or Finder rather than from a terminal. These checks run in the background rather than pausing the app, and a successful check is reused for a few minutes so a burst of turns does not re-run it. A failed check is never remembered: if you install or upgrade a CLI while memrynote is running, the next message or provider check picks it up without a restart. If the CLI is removed, replaced, or loses its executable bit between that check and the moment a turn actually starts, the turn ends right away with a Claude CLI failed to start: ... (or Codex CLI failed to start: ..., Antigravity CLI failed to start: ...) error naming the reason, and the conversation is free to accept a new message as soon as the CLI is back. A CLI that is not detected is not hidden: the composer's model picker still lists the Claude, Codex and Antigravity sections with a muted "Not detected — set up in Settings…" row that opens Settings -> AI Assistant -> Agent Permissions, where a CLI agents group shows the live detection status of each CLI (version when found) alongside install and sign-in instructions (claude login / codex login / a first interactive agy run).
Antigravity models carry their own reasoning tier in the model id (gemini-3.1-pro-high versus -low), so picking an Antigravity model replaces the separate reasoning control rather than adding to it. Any model id your Google account can reach can be typed in, not only the listed presets.
When the model exposes its reasoning (Claude thinking, Codex reasoning summaries, and local models that stream reasoning), the reply opens with a "Thinking…" block that follows the reasoning as it arrives. Once the answer starts, the block folds into a "Thought for Ns" line you can click to reopen. The reasoning is stored encrypted with the reply and is only displayed: it is never sent back to the model in later turns or in conversation summaries. Antigravity does not report its reasoning, so its replies show the plain thinking indicator.
Unlike the other two CLIs, Antigravity has no per-run configuration flag: it reads MCP servers from ~/.gemini/config/mcp_config.json and tool permissions from a project file, both at process start. So the first Antigravity turn registers one app-managed entry named memry in that file (every other MCP server there is preserved) and writes a memry-agent-vault / memry-agent-computer project that grants the vault tools and denies shell commands. No credential is written to either file: the endpoint token and the turn's single-use write capability travel in the spawned process's environment, which the bridge it launches inherits. A mcp_config.json that cannot be parsed is left untouched and the turn fails with a message naming the file. If you already had an MCP server named memry there, it is replaced by the app-managed one. Your own agy sessions also list the memry server; outside a running memrynote turn its tools report that no turn is active. For local models, configure a compatible server in Settings -> AI Assistant -> Agent Permissions first. If the global AI switch is off in Settings -> AI, the Agent tab and Agent MCP current-note bridge are hidden and inactive.
Agent Chat can:
- keep local conversation history in the vault database
- attach the active note as context for a turn
- mention notes, tasks, journals, inbox items, and calendar events inline in a prompt with
@ - stream assistant text back into the sidebar, with each new word resolving out of a soft blur
- link returned or created memrynote items directly in assistant replies, showing cited items as inline citation chips and listing all of them behind a source count under the reply
- fold a turn's tool calls, tool results, and optional approvals into one collapsed activity row
- stop an in-flight turn
- compact older conversation history when a prompt grows too large
Naming a new conversation and compacting its history both run the CLI in the background. A CLI that prints a lot of diagnostic output while doing so no longer stalls the turn: memrynote reads that output as it arrives rather than waiting for the CLI to finish. If the CLI then fails, the tail of that output is written to the local log, the conversation falls back to a title derived from your first message, and the turn continues with its history uncompacted — your message and the conversation are never lost.
Conversation history is stored encrypted, so every message you send has to decrypt the transcript before the agent can see it. memrynote reads and decrypts that history once per message and reuses it for the rest of the turn, so sending a message into a long conversation costs the same single pass whether or not the turn also compacts. Long conversations stay responsive instead of getting slower with every reply.
While a turn runs, its tool calls collapse into a single activity row instead of stacking one row per step, so a long turn no longer pushes the answer off screen. The row names the tool the agent is running, counts the steps so far, and shows a spinner until the turn ends. Once the turn is done the row settles to a step count, and selecting it expands the individual tool calls with their parameters and results. A tool that needs your approval keeps the row open, because the Allow and Deny buttons live inside it.
Tool activity is saved with the conversation, encrypted in the vault database like the rest of the transcript. Reopening a conversation later — after a restart, after a sync, or after memrynote has dropped an older transcript from memory — still shows which tools ran, with what parameters, and whether each one succeeded, failed, or was denied. The saved record is deliberately smaller than the live one: it keeps the tool name, its identifying parameters (long values are shortened), and the outcome, but not the tool's returned data. Only tools that finished are recorded, so a turn stopped mid-tool leaves no half-finished row behind. Conversations from before this was added simply show no tool rows; nothing else about them changes. Saved tool rows are a record for you, not context for the assistant — they are never replayed into a later prompt.
When a tool result includes a real memrynote reference, Agent Chat renders that item as a clickable mention instead of plain text. Lists link each returned note, task, inbox item, journal entry, calendar event, project, or folder that has a navigable reference. Create and update confirmations also link the affected item when the tool returns its ID or journal date. Inbox snooze confirmations use the same explicit inbox item reference as other inbox writes.
Every finished reply carries an action row. Copy hands you the markdown the assistant wrote, not the flattened text on screen, so it pastes into a note with its formatting intact; the button acknowledges the copy for a moment and then returns. Next to it, replies that cited memrynote items show the first few item icons and a source count — 3 sources — that expands into the full list. Each row in that list opens the item and names its type on the right. A reply that cited nothing shows only Copy.
A link the reply also cited renders as an inline citation chip: a compact pill carrying the item's icon and its title, shortened when the title is long. Source references arrive over the course of a turn, so a link can appear as running text first and settle into a chip a moment later, without the text around it being redrawn. Links memrynote did not cite stay as ordinary item mentions.
Both the blur-in on streaming text and the chip's arrival stand down when your system asks for reduced motion; the reply still updates, it just does so without the movement.
memrynote only links explicit tool-provided references. Plain titles without an ID or date stay as normal text. Uncited item mentions use memrynote's standard link color, show a dotted underline on hover, and display the matching item icon before the title. Each link shows exactly one icon: the item's own icon when it has one, otherwise the icon for its type. Note icons are read directly from the vault, so a linked note shows the same custom icon it has in the sidebar even while the reply is still streaming, and regardless of which agent backend produced the link. When a backend writes an item's emoji into the link text itself, memrynote moves that emoji into the icon slot rather than showing it next to a generic one. Inbox items use their capture-type icon, and journal, calendar, and task links use the same visual language as the main app surfaces.
Press Enter to send the prompt. Press Shift+Enter to insert a new line in the prompt box.
When a CLI backend is selected, send stays disabled until that CLI has actually been detected — including the brief check that runs as a conversation opens. A send button that is greyed out for a moment on open, or that stays greyed out, means the CLI has not been found; the CLI agents group in settings shows the detection status and the install hint.
Type @ in the prompt to open the mention picker. Notes, tasks, journals, inbox items, and calendar events appear with their item icons, and calendar events are read from the local calendar with archived events hidden. Choosing a result replaces the active @ query with one inline tag, so a prompt such as summarize @Star Wars Movies keeps the referenced item visibly attached inside the prompt. Mention tags submit as readable @Title text plus an encrypted structured attachment reference.
The picker waits for a brief pause in typing before it searches, so typing a long mention runs one search rather than one per character. The list always reflects the last thing you typed — a slower search for an earlier query is discarded rather than shown.
The prompt box uses the operating-system text editing menu, so Cut, Copy, Paste, Select All, and native right-click editing work like other text fields.
Dictating a prompt
The microphone in the prompt bar records a prompt and types it for you. Click it once to start recording — the icon turns red and nothing else on the bar moves. Click it again to stop; the icon becomes a spinner while the audio is transcribed, then the text is appended to whatever is already in the prompt box.
Dictation uses the same engine as inbox voice memos, so it needs a transcription backend configured first — see Voice Transcription. Audio recorded here is transcribed and discarded; it does not create an inbox item. If the microphone is blocked at the operating-system level, memrynote points you at the relevant privacy settings.
Connected tools
While Google Calendar is not linked, a tray peeks out below the prompt box offering it. Clicking the Google Calendar icon opens the same consent dialog as the Connect Google button on the calendar page, and the tray disappears once the account is linked — from either place.
Stop requests are scoped to the active conversation across Claude, Codex, and local providers. Automatic title generation and conversation summaries run through the selected backend without exposing memrynote MCP tools.
Stop works from the moment you send a turn, including the pause before the backend starts answering — while a local provider is being checked for streaming and tool support, or while Claude or Codex is launching. Pressing stop in that window ends the turn there instead of letting it run to completion in the background.
Stopping a turn — and quitting memrynote while one is running — asks the chat backend to shut down first, and forces it to close if it has not stopped shortly afterwards. Quitting waits for that to finish, so a backend is never left running in the background after memrynote is gone. A backend that has to be forced closed does not get to finish writing its own scratch files, so the unfinished reply is lost; your message and the rest of the conversation are kept.
The prompt bar holds four controls. The + button opens the mention picker and the per-turn permissions menu; a dot on the button means at least one permission differs from your defaults. The first chip shows the active provider and model, and its menu switches either. The second chip sets reasoning effort. The microphone dictates a prompt by voice, and the arrow sends the turn.
The provider is pinned per conversation; changing it after messages exist updates the conversation and records the switch in the chat history. Claude and Codex expose prompt-time reasoning effort settings, with provider-specific settings shown only for the active provider. The permissions menu starts from your default Agent Permissions setting, then lets you send a single turn as Vault only or Computer access, and optionally allow web search for that turn.
Vault only keeps the CLI backend constrained to memrynote vault tools. Computer access gives the backend broader local CLI access for that turn. Web search is passed through only when the selected backend supports it.
Claude and Codex conversations also have a per-conversation model selector. memrynote starts Claude on opus and Codex on the highest suggested GPT version, then passes the selected model through to the CLI for each turn. The built-in model list is only a shortcut for common CLI aliases; type a custom model ID when you want to pin another CLI-supported model.
Local model support uses OpenAI-compatible HTTP APIs. memrynote ships presets for Ollama, LM Studio, and llama.cpp server, plus a Custom endpoint. Local tool access is gated by a capability probe. If the model can emit tool calls and continue after a tool result, memrynote enables the full vault tool set. If the probe fails, local chat can still answer from attached context, but vault tool calls stay disabled.
The probe costs a couple of model generations, so memrynote runs it once and reuses the verdict for up to ten minutes instead of repeating it on every message. Changing the preset, base URL, model, or API key re-checks immediately, and an unreachable provider is never remembered — start your local server and the next message picks it up. If you swap the model behind an unchanged configuration, press Probe Tools in Settings to force a fresh check.
If the configured local provider is not running, the model picker returns no discovered models instead of treating the settings page as an Agent runtime error. Start the provider, then load models or test the connection again.
When no conversation is selected yet, the prompt box stays available. Sending the first prompt creates a new Agent Chat conversation, attaches the active note when one is open, and streams the reply into the sidebar.
New conversations start with a temporary title. When you send the first prompt, the selected chat backend also generates a short conversation title. memrynote stores that title on the encrypted conversation row and refreshes the sidebar title without giving the title-generation subprocess access to memrynote MCP tools.
If a turn fails partway through — a window closing while the reply is still streaming, for example — memrynote stops the chat backend it started for that turn instead of leaving it running in the background. The unfinished reply is lost, but your message and the rest of the conversation are kept, so you can send the prompt again. A turn that is simply taking a long time is never stopped this way. The same applies when a turn fails before the reply even starts streaming, such as a disk or database error while saving the empty reply.
Conversation rows, message bodies, and message attachments are encrypted at rest before they are written to SQLite. Free accounts keep agent chat history local-only. Paid accounts can sync finalized conversations and terminal messages through memrynote Sync; in-progress streaming messages are not enqueued until the turn finishes.
If memrynote cannot verify the local vault key for the current database, Agent Chat stays unavailable instead of opening unreadable conversation history. A fresh local vault can initialize a new local key without sign-in; an existing vault with a mismatched or missing keychain key must be recovered through the normal vault recovery flow.
Connection
The endpoint is:
http://127.0.0.1:<port>/mcpExternal MCP clients must send:
Authorization: Bearer <token>The token is generated in memory for the current app launch. It is not saved to disk, changes when memrynote restarts, and can be rotated manually from settings. Missing or stale tokens receive 401.
The localhost MCP endpoint can serve overlapping Agent Chat turns and external read requests. memrynote keeps the URL/token stable for the app session, but handles each MCP request with an isolated transport so one client connection does not block another.
If the operating system refuses a connection to the endpoint — for example when the app has run out of file handles — memrynote records the failure in the app log as an AgentMcpServer error and keeps the endpoint listening on the same URL and token. Individual client connections can be dropped, but Agent Chat and external clients can reconnect without restarting the app or reopening the vault.
Client-specific config keys vary. Use the copied URL as the MCP server URL and the copied token as a Bearer authorization header. External clients are read-only. The token admits a client to the read tools; it does not admit it to the write tools.
Every vault write has to be authorised by a turn memrynote itself is running. When Agent Chat starts a turn it mints a fresh single-use write capability, hands it only to the backend it spawns for that turn, and destroys it when the turn ends. The write tools accept nothing else. An external client holding the endpoint token, or a stale capability from a turn that has already finished, is refused with PERMISSION_DENIED and the reason that writes need a running memrynote Agent turn. A conversation id is not a credential: knowing one, even a real one, does not let a client write.
External clients still see the write tools listed. They are advertised to every client because memrynote's own Claude CLI, Codex CLI, Antigravity CLI, and local-model backends discover their tools from that same list. Calling one without an active turn fails rather than writes.
A write is only approved for a conversation that still exists. A conversation that has been deleted — including one deleted on another device and carried here by sync — no longer counts as an existing conversation, so its write tools are refused rather than writing into a record that is gone from your chat history everywhere.
Closing the vault or quitting the app destroys every live write capability, so a backend that somehow outlives its turn cannot write afterwards.
Tools
Read tools are available to Agent Chat and external MCP clients:
vault_search_notesvault_read_notevault_list_foldervault_get_current_notevault_list_tasksvault_get_taskvault_list_projectsvault_get_projectvault_list_statusesvault_get_journal_entryvault_list_journal_entriesvault_list_inbox_itemsvault_get_inbox_itemvault_get_tagsvault_list_canvasesvault_read_canvasvault_read_canvas_elementsvault_desktop_read
Notes and filed files
Filing a PDF, image, audio file, or video into the vault indexes it alongside your markdown notes, so it can turn up in vault_search_notes. Every search hit therefore carries a file_type:
markdown— a real note.vault_read_notereturns its content.pdf,image,audio,video— a filed file. There is no markdown to read, sovault_read_noterefuses it with aVALIDATIONerror naming the file type instead of returning bytes for the client to treat as text.vault_update_noterefuses it the same way, so an agent cannot overwrite a filed document with markdown.
vault_add_html_artifact lets an agent put a diagram, chart, or small interactive explanation in a note. The HTML is saved as an attachment of that note and appended as a file block, which renders it inline in the same sandbox as an .html file you attach yourself: scripts run, https: resources load, but the page cannot read the vault or the app. It syncs like any other attachment. The HTML is capped at 512 KB and the call needs your approval.
Pass file_types to narrow the search up front — ["markdown"] for notes only, or ["pdf", "image"] to look for filed documents. The filter runs inside the search query, so limit counts only matching rows. Omit file_types to search every file type.
Notes indexed by older memrynote versions have no recorded file type; those are always treated as markdown, so upgrading never hides existing notes.
Create, update, delete, archive, move, and reorder tools require Agent Chat context. They pause for inline approval unless you set the Agent Permissions confirmation to Always allow:
vault_create_notevault_rename_notevault_delete_notevault_create_foldervault_rename_foldervault_delete_foldervault_create_taskvault_delete_taskvault_complete_taskvault_uncomplete_taskvault_archive_taskvault_unarchive_taskvault_move_taskvault_reorder_tasksvault_duplicate_taskvault_convert_task_to_subtaskvault_convert_subtask_to_taskvault_create_projectvault_update_projectvault_delete_projectvault_archive_projectvault_reorder_projectsvault_create_statusvault_update_statusvault_delete_statusvault_reorder_statusesvault_create_journal_entryvault_update_journal_entryvault_delete_journal_entryvault_add_to_inboxvault_update_inbox_itemvault_snooze_inbox_itemvault_archive_inbox_itemvault_unarchive_inbox_itemvault_delete_inbox_itemvault_add_inbox_tagvault_remove_inbox_tagvault_update_notevault_add_html_artifactvault_update_taskvault_add_tagvault_remove_tagvault_move_to_foldervault_add_canvas_itemvault_remove_canvas_itemvault_create_canvasvault_draw_on_canvasvault_edit_canvas_elementsvault_desktop_write
Canvas
| Tool | What it does |
|---|---|
vault_list_canvases | Every canvas, with how many items sit on each |
vault_read_canvas | One canvas: the notes/tasks/events on it (with titles) and any text written on it |
vault_read_canvas_elements | The shapes on one canvas: ids, position, size, text, colors, arrow bindings |
vault_create_canvas | Create an empty canvas |
vault_add_canvas_item | Put existing notes/tasks/events on a canvas as cards |
vault_remove_canvas_item | Take a card off a canvas |
vault_draw_on_canvas | Draw shapes, text, arrows, lines, freedraw, frames, images and embeds |
vault_edit_canvas_elements | Move, restyle, retext or delete elements already on a canvas |
Canvas tools need the Spatial Canvas feature turned on (Settings → Features). With it off they return a message saying so rather than failing silently.
There are two ways to read a canvas, for two different questions. vault_read_canvas answers "what is on this canvas" — the notes, tasks and events, with their titles, and any text written on it. It returns no geometry, because a scene is mostly coordinates and style properties and dumping that into an agent's context crowds out everything useful. Long canvases cap the amount of text returned and say so with texts_truncated. vault_read_canvas_elements answers the other question — "where is everything" — and is the read to use before drawing: an element id from it is what an arrow binds to and what an edit changes.
Drawing
vault_draw_on_canvas takes Excalidraw's own element skeletons, in camelCase, so anything you can draw by hand you can ask for: rectangles, ellipses, diamonds, text, arrows, lines, freedraw, frames, images and embeds, with the full style vocabulary (strokeColor, backgroundColor, fillStyle, strokeWidth, strokeStyle, roughness, opacity, roundness, fontSize, fontFamily).
Two things make it a diagram rather than a pile of shapes:
- Refs. Give an element a
refand other elements in the same call can point at it. The response maps every ref to the id it became, so the next call can keep building on it. - Real bindings. An arrow with
startandend— either{"ref": "..."}for something in the same call or{"elementId": "..."}for something already on the canvas — is bound on both sides. It follows the shapes when you drag them, exactly like an arrow you drew yourself. Frames work the same way: children can be new elements or ones already there.
An agent cannot mint entity cards this way. A card is a rectangle carrying the entity reference that canvas_entity_refs is rebuilt from, so cards go through vault_add_canvas_item, which checks that the note/task/event actually exists. vault_edit_canvas_elements will move and restyle a card, but not rewrite its text — that text lives in the note.
Images need a fileId already attached to the canvas; agents cannot upload binaries.
Adding an item applies to the open editor when you have that canvas open, so the card appears while you watch instead of being overwritten by the next autosave. A canvas nobody has open is updated directly, and the write is rejected if it changed in the meantime. If the result is too large to sync, the tool response says so.
Some canvas operations are deliberately unavailable through vault_desktop_read / vault_desktop_write:
canvas.get— returns the whole scene; usevault_read_canvasorvault_read_canvas_elementscanvas.update— replaces the entire scene with no version check, which would overwrite whatever you have open; use the item and drawing toolscanvas.librarySave— saves the shape library as one whole list, so a partial one deletes shapescanvas.uploadAsset— binary image upload, no agent path yet
An arrow an agent draws is a picture, not a stored relationship. It is bound, it moves with the shapes, and it is genuinely useful on a diagram — but nothing queries it. When you want a connection the rest of the app can follow, use wiki links between notes or the project link layer; the arrow is the drawing of that connection, not the connection.
vault_desktop_read and vault_desktop_write cover the remaining desktop CRUD surface through an allowlisted desktop API operation name plus an args array. They are used for desktop domains such as templates, saved filters, bookmarks, reminders, calendar events, folder views, properties, tags, search reasons, inbox conversions, project links, and settings. The write bridge uses the same in-app approval flow as named write tools. Security-sensitive and system operations stay outside the allowlist, including account/auth flows, provider connect/disconnect/refresh actions, app updater actions, external open/reveal actions, import dialogs, OS settings panes, telemetry, feedback and diagnostics reporting, and raw secret writes. Unsupported or unavailable desktop API operations return a structured MCP error instead of falling back to an arbitrary desktop call.
notes.resolveWikiTarget follows a wiki link the way the editor does: Meeting#Decisions resolves to the note Meeting and reports heading: "Decisions", while a note genuinely titled Sprint #4 still resolves to itself. notes.resolveByTitle stays a plain title lookup and returns nothing for a target carrying a heading, so use notes.resolveWikiTarget when the string came out of a [[…]].
Inbox items convert through the bridge into any of the four targets the app itself offers: inbox.convertToNote, inbox.convertToTask, inbox.convertToEvent, and inbox.convertToReminder. notes.applyTemplate applies a template the agent can already read through templates.get to an existing note.
settings.getFeaturesSettings reports which surfaces are turned on — home, inbox, journal, tasks, calendar, graph, and spatial canvas — so an agent can tell whether an action is even available before suggesting it, and settings.setFeaturesSettings toggles them. settings.getInboxSettings and settings.setInboxSettings cover the daily inbox review reminder.
Tag categories are reachable through the same bridge. tags.listCategories is a read operation that returns {"success": true, "categories": [...]}, where each entry carries its id, name, sort order, and tag count. tags.createCategory, tags.renameCategory, tags.deleteCategory, and tags.reorder are write operations behind the usual approval flow; tags.createCategory returns {"success": true, "category": {...}} and the other three return {"success": true}. Like the rest of the desktop bridge, these operations report their own failures as {"success": false, "error": "..."} rather than raising an MCP error, so check success before reading the payload. tags.reorder applies a drag result — tag-to-category assignments, category ordering, or both in one transaction — and is the only way to move a tag into a category. Deleting a category keeps its tags and makes them uncategorized.
vault_get_tags returns each tag with its color, icon, sort_order, category_id, and category_name. Both category fields are null for an uncategorized tag.
Calendar desktop reads accept the same single-object shape as the renderer bridge. For example: calendar.listEvents accepts args: [{}], and calendar.getRange accepts either args: ["2026-05-14", "2026-06-14"] or args: [{"startAt": "2026-05-14T00:00:00.000Z", "endAt": "2026-06-15T00:00:00.000Z"}].
Google-integration operations — calendar sources, provider status, Google calendar lists, promoting external events, and Google calendar settings — are excluded from the agent allowlists outright.
Events from external calendars are gated on explicit user consent, asked separately for each calendar service (Google, subscribed calendars, CalDAV). calendar.getRange builds the list of services whose events it may return (externalProviders) from the stored answers, never from the caller: an agent that passes includeExternal: true still gets native-only results unless the user allowed at least one service, and then only that service's events. Not asked yet, declined, or a settings read that failed all count as not allowed. See Calendar → AI Access Is Asked Per Calendar Service.
Google user data is never used to train or improve AI models, in line with the Google API Services User Data Policy (Limited Use).
Read tool calls are accepted automatically. The chat shows each one as compact, subdued text with a readable label such as Reading note or Reading tasks. Click the label to open or close the details area with the raw MCP tool name, parameters, and results.
Changes are different. Ask before changes is the default, so memrynote pauses the turn and shows inline approval controls inside the tool row. A row waiting on you opens itself and folds back once you answer, so a paused turn is never hidden behind a collapsed summary. You can approve the request once, grant it a standing approval, reject it, or edit it before approving. Write requests that present no active-turn capability — every external MCP client, and any call arriving after its turn ended — continue to be denied, whichever confirmation setting you choose.
A paused request always shows what it would change, in the shape that fits the item:
- Field changes for tasks, projects, statuses, inbox items, tags, moves and renames. Each changed column is one row: the value now, then the value the agent proposes. A value that is not set yet reads as such rather than as an empty string.
- A body diff for the text of a new note or inbox item. The changed words are highlighted in place and long runs of untouched lines are collapsed, so a one-word edit reads as a one-word edit. Edits to an existing note or journal entry are reviewed in the note itself instead; see Reviewing an edit in the note.
- What would be lost for deletes. A delete has no "after", so the card names the item and what goes with it instead.
Each preview reads the item as it stands right now, not as the agent last saw it, so the value in the "before" position is what the write is actually about to land on. Field rows list only the columns that move: an agent request often repeats every column it read, and those are left out.
A body diff also offers Edit before applying, which opens the proposed markdown in a text box. Applying from there replaces the whole body with what you see, so an append you edited is applied as the finished document rather than appended a second time. Field changes and deletes have no text box; use Edit and allow on the tool row to change raw arguments instead.
Reviewing an edit in the note
When the agent wants to change the body of an existing note or journal entry, the change is shown in that note, not in the chat. The note's text is drawn with the change in place: added words are highlighted, removed words are struck through, and each changed block has a bar at its start. A bar at the bottom of the note offers Accept, Edit and Reject.
- Accept applies the change as shown.
- Edit turns the suggestion into an editable copy. Add, change or delete anything, switch back with Show changes to see the result against the current note, then Accept edits. Your copy stays on this device until you accept it: nothing reaches the note, the vault file or your other devices before that.
- Reject refuses the change and puts the note back as it was.
While a change is under review the note's own editor is set aside, and it comes back exactly as you left it once you decide. If the note changes underneath the review, from sync or another window, the changes are recomputed against the new version. If you were already editing the suggestion, the bar tells you, and you can start over from the latest version or keep your copy.
The chat row points at the note while this happens. If the note is not open, the row offers Open note (or Open journal) to see the change, or Accept to apply it without looking.
Note and journal edits ask every time. They cannot be given a standing approval, and one granted before this change is ignored; Settings → Agent → Always allowed marks it as such, and Revoke still removes it. Only the global Always allow confirmation setting skips the review.
Always allow
Always allow on a paused request asks how long it should last:
- Always allow in this chat ends with the conversation. Nothing survives it.
- Always allow in this vault outlives the chat and is listed under Settings → Agent → Always allowed, where Revoke takes it back. The list is per vault and stays on this machine; it is never synced.
Deletes always ask. A standing approval is a promise about work you can still look at afterwards, and a delete is the one write where that is not true, so the gate refuses to trust a delete tool at either scope and the menu says so.
If you prefer the old behaviour, set tool confirmations to Always allow in Settings → Agent. That setting is per install and applies to every conversation.
If you had never touched this setting before upgrading, you now get asked where you previously did not. An explicit Always allow choice you made earlier is kept.
Stopping the turn while an approval is waiting counts as a denial: the pending request is refused, the tool never runs, and the approval controls disappear. Nothing is written to your vault.
An approval you never answer expires after 30 minutes. The controls disappear, the tool never runs, and the tool row is marked as expired rather than denied — the agent is told the request timed out, not that you refused it. Take as long as you need to read a request or its diff; half an hour is there so a prompt left open overnight does not keep the request waiting forever, not to hurry you. If a request expires and you still want it, ask the agent again.
Project Links
vault_list_projects returns each project's icon, home_note_id, and linked_counts (notes, files, events) alongside task_count. Nonzero linked_counts are the signal that a project has a hub link layer worth reading; task_count alone says nothing about it.
The hub's link layer is reachable through the desktop bridge. Reads, via vault_desktop_read:
| Operation | Args | Answers |
|---|---|---|
tasks.listProjectContents | [projectId] | Which notes, files, and events a project holds |
tasks.listProjectLinks | [projectId] | The raw link rows, including pin state |
tasks.listForItem | [itemType, itemId] | Which projects a note, file, or event belongs to |
itemType is one of note, file, or calendar_event.
Writes, via vault_desktop_write, behind the same approval flow as other writes:
| Operation | Args |
|---|---|
tasks.linkProjectItem | [{ projectId, itemType, itemId }] |
tasks.unlinkProjectItem | [{ projectId, itemType, itemId }] |
tasks.setProjectLinkPinned | [{ projectId, itemId, pinned }] |
tasks.setProjectHomeNote | [{ projectId, noteId }] |
tasks.captureUrlToProject | [{ projectId, url }] |
tasks.importFilesToProject | [{ projectId, sourcePaths }] |
setProjectHomeNote takes noteId: null to clear the project's home note, the same way the hub's own overview rail does.
captureUrlToProject fetches the page title over the network, and importFilesToProject copies files from paths you supply into the vault — both on caller-supplied input, like the already available inbox.captureLink and notes.importFiles. Operations that open native UI or hand an item to the OS stay out of the allowlist.
importFilesToProject waits for the indexer to assign an id to each imported file, so importing several large files at once can exceed the bridge's ten-second window. The import still completes; the tool call reports a timeout. Import in smaller batches to see the result.
Current Note
vault_get_current_note can snapshot the active note when the request is associated with a memrynote window. Plain external clients do not have that window context, so the tool returns null instead of guessing.
Privacy
The MCP server binds only to localhost. Read tools still expose the content they return to the client you configure, so only paste the token into clients you trust on this machine. Write tools still require an active Agent Chat conversation context, and by default that conversation pauses and shows you the change before it is written. The in-app tool confirmation setting is what decides that; setting it to Always allow accepts the call without a preview.
Provider privacy depends on the selected backend:
- Claude and Codex providers may send prompts, attachments, and tool results through that provider.
- Local loopback providers keep model prompts on this machine, except for the actual tool effects memrynote applies inside the vault after approval.
- Custom non-loopback endpoints send data to the configured endpoint and must be explicitly enabled with the not-fully-local warning.