Integrations

MimicScribe connects your meetings to the tools around them. AI agents reach them through an MCP server; macOS itself reaches them through App Intents — Spotlight, Shortcuts, and Siri; it writes a Markdown note into your Obsidian or Logseq vault; and it can POST to a webhook. All configured in Settings > Integrations, along with the URL import helper that pulls audio out of a video or podcast page.

For saving a meeting out by hand — Markdown, subtitles, JSON, CSV — see Exporting & sharing.

Automatic recording is documented here too, though it’s configured in Settings > Meeting > Automatic Recording. It connects to nothing — it watches which app takes your microphone and starts the recording for you.

Quick setup: If you’re already using an AI agent like Claude Code, Gemini CLI, or Codex, you can ask it to set this up for you. Try: “Set up the MimicScribe MCP server. Read the docs at mimicscribe.app/llms-full.txt for instructions.” Your agent will read this page and configure everything automatically.


MCP Server

The Model Context Protocol (MCP) server lets AI agents interact with your meeting data directly. Agents can search past meetings, pull action items, prepare context for upcoming meetings, and more — all without you copying and pasting.

What can agents do with it?

After meetings — ask your agent to work with what was discussed:

  • “What did we decide about pricing in yesterday’s meeting?”
  • “List all my action items from this week”
  • “Write a follow-up email based on the client call from Monday”
  • “Create Jira tickets for the action items from the planning meeting”
  • “Draft a project status update from my meetings this past week”

Fix and re-export — correct who-said-what, then send the cleaned copy somewhere new, in one instruction:

  • “In yesterday’s client call, ‘Speaker 2’ is Jane Okafor — rename her, then save a clean copy to my Obsidian vault”
  • “All the microphone speech in the standup is me — merge it into ‘Marshall’, then re-export the summary to Notion”
  • “Drop the phantom noise speaker from the interview and email me the corrected transcript”
  • “‘Alice’ and ‘Bob’ are swapped in the planning meeting — fix them and update the doc I made from it”

The agent reads the meeting, applies the speaker correction, waits for MimicScribe to re-attribute and regenerate the summary, then re-reads the corrected meeting and writes it wherever you asked, with no copy-paste or manual relabeling. See Correcting speaker attribution.

Import recordings — have your agent transcribe files from disk:

  • “Transcribe the recording from yesterday’s client call — it’s in ~/Downloads/client-call.m4a”
  • “Import all the audio files in ~/Meetings/ and summarize what was discussed”
  • “Get word-level timestamps for this podcast episode so I can cut the filler words”

Before meetings — have your agent prepare context:

  • “Prep my next meeting — look up the attendees in our CRM, set the context, and pick the right summary template”
  • “I have a meeting with jane@acme.com in 30 minutes. Look up our past meetings with anyone from Acme, check their website, and set the context in MimicScribe.”
  • “Add our product pricing page as a reference source so the assistant has it during sales calls”
  • “Add our company’s org chart and key terminology as reference context for all my meetings”

How do I tell it which meeting I mean?

Every meeting-scoped tool takes the reference you’d actually say out loud, not just a UUID. get_meeting_data, get_action_items, correct_meeting, and update_meeting all accept the same grammar:

You passIt resolves to
A UUIDThat meeting, exactly.
meeting://<uuid> or mimicscribe://meeting/<uuid>The same — the URIs resources/list and the app hand out.
latest (also last, most recent, my last meeting, …)The newest meeting by start time.
focus (also current, open, the meeting I have open)The meeting the app last displayed.
An ISO8601 date — 2026-09-01Every meeting that started on that local calendar day.
Any other textMatched against meeting titles.

Two rules to know before your agent leans on it:

  • It does no natural-language date parsing. “Yesterday” is the agent’s job to convert — pass the ISO date. The alias lists above are matched on the whole argument, never as a substring, so a meeting genuinely titled “Last Call With Legal” stays findable by its name.
  • Ambiguity is an error, never a silent pick. If a title fragment or a date matches more than one meeting, the tool returns ambiguous_meeting_reference with a candidate list — id, title, ISO date, local time, duration, speakers — and the instruction to ask you which one. An agent that picks the first is doing it wrong.

Deletion is the exception: update_meeting with delete: true takes a UUID and nothing else. Reading the wrong meeting wastes a turn; deleting it can’t be undone through MCP.

One more thing an interpreted reference can hide: if “latest” also matched an offline meeting the server can’t see, the response says so explicitly rather than quietly resolving to the second-newest.

Available tools

ToolPurpose
search_meetingsSearch by keyword or list recent meetings. Returns summaries and metadata.
get_meeting_dataGet detailed data for a specific meeting — summary, transcript, action items, or all of them. On live-recorded meetings, speakers and transcript lines are tagged with the capture channel they came from — (mic) (this Mac’s microphone — you) or (remote) (system audio — other participants or played media) — so an agent can repair attribution without guessing. Each participant in the metadata is also tagged (you) (the app’s primary user) or (unnamed) (an un-attributed placeholder like “Speaker 2”), so an agent can build an attendee list and link real people without guessing who’s who. See Capture channels and Who’s who.
get_action_itemsPull action items across multiple meetings, filtered by date or assignee. Each item carries a stable id (upsert into a task tool without duplicating). Pages with limit/offset; totalCount says how many match.
list_speakersList saved speaker profiles across all meetings — name, isPrimaryUser, meeting count, and last seen. Use to seed CRM contacts or find who to research before a call.
get_meeting_contextRead the current meeting prep state — context text and the selected summary template, from any source (user input or prior agent writes). Agents must check this before setting context to avoid overwriting the user’s notes.
set_meeting_contextSet context for an upcoming meeting — attendee roles, goals, background, deal info. Overwrites all existing context, including user-typed notes. Always call get_meeting_context first and preserve existing content. Expires after a configurable TTL (default: 3 hours). Optional template_id also selects the summary template governing the post-meeting output.
list_templatesList every summary template — built-in (Simple, Walkthrough, By Participant, Decisions & Open Questions) and user-custom — with full section-by-section summary instructions. Call this first if you want to pick a template_id to pass to set_meeting_context.
transcribe_with_speakersQueue an audio or video file for ASR + on-device diarization. Returns anonymous speaker IDs (“Speaker 1”, “Speaker 2”) with word-level timestamps and preserved filler words. It makes no Gemini calls and doesn’t count against the AI cap. Use when you need raw timestamped words and speaker separation without real names.
transcribe_attributedQueue an audio or video file for AI speaker attribution. Returns a compact transcript with real speaker names (from voice profiles or transcript context) and an attributionSource field per speaker. It skips the summary and action items and isn’t saved to the library. Use when you want a polished script without polluting the user’s meeting history.
import_meetingQueue an audio or video file for full meeting import. Runs the complete pipeline (diarization + attribution + summary + action items) and persists the result to the user’s library. Optional offline: true skips Gemini and saves as offline mode — the user can backfill via “Generate Summary Now”. Use when the user wants this saved as a meeting.
get_import_statusCheck the status of recent file imports, corrections, and meeting updates. Returns a unified recentResults array with type discriminator (transcription / attributed_transcript / meeting / correction / meeting_update), plus recentFailures and recentRejections. Call after a notification to see what happened.
get_transcript_resultRetrieve a completed transcribe_with_speakers or transcribe_attributed result by id. One getter for both — the result id carries no store marker, so you don’t have to remember which tool you queued. Returns {type, result}; pass format for a ready-to-save document instead of JSON.
set_context_sourceManage persistent reference documents — add, replace, or remove sources (URLs, files, or raw text) that are semantically retrieved during meetings. Sources are chunked, embedded, and matched to what’s being discussed.
correct_meetingFix speaker attribution on a completed meeting — rename, merge, swap, or remove a speaker’s turns. The app re-validates the change, applies it, and regenerates the summary. See Correcting speaker attribution.
update_meetingEdit a meeting’s library metadata: rename it (title), or delete it (delete: true). Exactly one action per call. Works on offline meetings when offline access is enabled. Deletion is permanent with no MCP undo — confirm with the user first. Queued and applied by the app; poll get_import_status (type meeting_update).
delete_meetingPermanently delete a meeting from your library. Strict privilege separation from update_meeting: requires the meeting’s exact UUID (never interpreted references like latest) and explicit confirm: true. Deletion is permanent with no MCP undo — confirm with the user first. Queued and applied by the app; poll get_import_status (type meeting_update).
write_meeting_summaryWrite or overwrite an AI-generated meeting summary, key decisions, overview, and action items. Preserves pre-edit restore points in the change ledger, updates SQLite FTS5 search, and regenerates local on-device vector embeddings. Stamped with summarySource: "agent". Queued and applied by the app; poll get_import_status (type summary_write).
update_action_itemsUpdate existing action items (lifecycle state: open, completed, dismissed; task text, owner, due date) or append new action items without rewriting the entire summary. Preserves pre-edit restore points in the change ledger, updates FTS5 search, and re-indexes vector embeddings. Queued and applied by the app; poll get_import_status (type action_items_update).

Capture channels (mic / remote)

Every live-recorded meeting captures two separate audio channels: your microphone and the system audio (everyone else on the call, plus any media you play). MimicScribe keeps that provenance and surfaces it to agents on get_meeting_data, where speakers and transcript lines carry a channel tag. (get_transcript_result exposes the same information as an optional channel field, but only for dual-channel sources — the files the two transcription tools take today are single-channel, so it’s empty there.)

The tags are:

  • mic — this Mac’s microphone: the device owner (you).
  • remote — system audio: other participants, or played-back media.
  • mixed — the segment spans both channels or its provenance couldn’t be resolved. Treat as unknown — only mic and remote are reliable evidence.

This comes straight from the recording hardware, so an agent can repair attribution with zero AI calls. The canonical example: “everything on the mic channel is the same person — me,” turned into a merge via correct_meeting. It also disambiguates a name the AI attributed to the wrong side.

Tags are omitted where the label already names its channel (the diarizer’s own "Mic 1", "Remote 2" families) — so a tagged line is one whose speaker was renamed or AI-attributed, i.e. exactly where the channel would otherwise be invisible. File imports are single-channel and carry no tags — there’s no separate mic/system stream in an imported file.

Who’s who: you and unnamed

On top of the channel tag, get_meeting_data’s participant list marks two things an agent would otherwise have to guess:

  • (you) — the app’s primary user. Exclude this person when building a list of other attendees, like a CRM contact list.
  • (unnamed) — a placeholder the diarizer assigned that nobody renamed, like Speaker 2 or Remote 1. Not a real identification — don’t link it or file it as a contact.

A participant with neither tag is an attributed real name. In this line:

**Speakers:** Jane Okafor (remote), Marshall (mic, you), Speaker 2 (remote, unnamed)

Jane is an attendee to link, Marshall is you, and “Speaker 2” is unresolved. These tags are what let an agent file a meeting into another tool without asking you who each speaker was.

Filing meetings into your tools

For Notion, your CRM, task managers, and most other tools, your agent does the filing — using what these tools return. There’s no per-tool connector to configure; the mapping below is what a capable agent needs to do the filing itself. (Two things MimicScribe can do without an agent: write Markdown notes into an Obsidian vault, Logseq graph, or any folder — see Markdown notes folder — and POST each meeting to a URL for Zapier/Make/n8n — see Webhook.)

Two output shapes carry the material. get_meeting_data returns Markdown:

# Q3 Planning Sync

**Date:** Jul 16, 2026 at 2:30 PM
**Duration:** 45m
**Speakers:** Jane Okafor (remote), Marshall (mic, you), Speaker 2 (remote, unnamed)
**Status:** completed
**Tags:** pricing, roadmap

## Summary

The team agreed to ship the revised pricing before the board review...

## Action Items

- **Marshall**: Send the revised pricing deck
  - Due: 2026-07-20

get_action_items returns the same items as structured JSON, across one or many meetings:

{
	"actionItems": [
		{
			"owner": "Marshall",
			"task": "Send the revised pricing deck",
			"due": "2026-07-20",
			"type": "task",
			"confidence": "firm",
			"meetingId": "…",
			"meetingTitle": "Q3 Planning Sync",
			"meetingDate": "2026-07-16T14:30:00Z"
		}
	],
	"returnedCount": 1
}

Obsidian. You don’t need an agent for this one — MimicScribe can write a note into your vault automatically (Markdown notes folder below). An agent is still useful for retroactive filing (backlinking a meeting to a contact you’re researching right now) or one-off exports outside your normal vault location: pull get_meeting_data and write the Markdown yourself — date and duration become YAML front-matter fields, participants tagged as real names become [[wikilinks]] (skip (you) and (unnamed)), and the summary and action items are the body.

Notion. Same data, filed as a database page: map date, participants, and tags to database properties, and render the summary and action items as blocks (action items as to-do blocks). Do this through the Notion API — Notion’s plain-Markdown import flattens the structure.

CRM (HubSpot, Attio, Salesforce). The participant tags do the work here. Every participant except your (you) entry and any (unnamed) placeholder is a real attendee — map them to contacts, log the summary as an activity note on the account, and turn get_action_items into follow-up tasks carrying their owner and due date.

Task managers and Apple Notes. For tasks, skip the transcript entirely and pull get_action_items: each item already carries an owner, a due date, and a firm / tentative confidence — send the firm ones to Things, Todoist, or Reminders and drop the tentative ones unless you want maybes. For Apple Notes, paste the summary rather than raw Markdown; Notes renders rich text, so the prose lands clean and the ## headings don’t show through.

Resources

The server also exposes meetings as MCP resources. Calling resources/list returns the 20 most recent meetings as meeting://{id} URIs. Calling resources/read with a URI returns the meeting content:

  • meeting://{id} — full transcript as markdown
  • meeting://{id}/summary — AI-generated summary
  • meeting://{id}/action-items — structured action items as JSON
  • meeting://{id}/segments — structured transcript as JSON (speakers + timestamped segments), for importers that can’t parse prose

Resources are read-only. Most agents will find the tools (search_meetings, get_meeting_data) more convenient, but resources provide an alternative access pattern for MCP clients that prefer it.

Notifications

The MCP server sends notifications/resources/list_changed when meetings change — new meetings ready, imports completed or failed, meetings deleted or merged. After receiving a notification, agents should determine what changed:

  • For imports: call get_import_status to see outcomes (success with meeting ID, rejected, or failed with reason)
  • For everything else: call search_meetings to see the current meeting list, or resources/list to re-fetch resources

The notification includes structured details in its params for MCP clients that support reading them. Not all clients do — the tool-based approach above works universally.

When notifications fire:

EventWhenHow to check
Live meeting readyUser closes the summary view (after any speaker corrections)search_meetings to find new meeting
Meeting import succeededimport_meeting enrichment completesget_import_status → recentResults (type==“meeting”) → get_meeting_data
Diarized transcript readytranscribe_with_speakers finishesget_import_status → recentResults (type==“transcription”) → get_transcript_result
Attributed transcript readytranscribe_attributed finishesget_import_status → recentResults (type==“attributed_transcript”) → get_transcript_result
Import rejectedBilling cap reached before processingget_import_status → recentRejections for reason
Import failedTranscription or enrichment erroredget_import_status → recentFailures for reason
Meeting deletedUser deletes a meetingsearch_meetings to see updated list
Meetings mergedUser merges multiple meetingssearch_meetings to see updated list
Correction appliedcorrect_meeting request finished (applied, partial, or failed)get_import_status → recentResults (type==“correction”) → get_meeting_data

Notification params (for custom MCP clients): The list_changed notification carries optional params with arrays describing what changed. Presence of each key indicates the event type:

  • meetings[] — {id, title, sourceFilename?} — meeting ready (live recording or import_meeting completion)
  • transcriptions[] — {filename, resultId} — transcribe_with_speakers completed (use get_transcript_result with resultId)
  • attributedTranscripts[] — {filename, resultId} — transcribe_attributed completed (use get_transcript_result with resultId)
  • rejections[] — {filename, reason} — import blocked before processing
  • failures[] — {filename, reason} — import errored during processing
  • deleted[] — {id, title} — meeting removed
  • merged[] — {id, title, replacedIds[]} — meetings combined into one
  • corrections[] — {meetingId, title?, requestId, status, reason?} — a correct_meeting request finished (status: applied / partial / failed)

Standard MCP clients that ignore notification params can use the tool-based fallback above. These params are an optimization for clients that can parse them.

File import

Agents can import audio and video files for processing. The MimicScribe app must be running — the MCP server queues the request, and the app picks it up. Each of the three tools takes either a local path or an https url (the app downloads it, then processes it the same way). Three tools cover three distinct use cases:

ToolPipelineLibraryGeminiUse for
transcribe_with_speakersASR + on-device diarization (anonymous IDs, fillers preserved)NoNoRaw timestamped words with speaker separation (subtitle gen, alignment, agent QA)
transcribe_attributedASR + diarization + AI speaker attribution (no summary)NoYesPolished named-speaker transcript without saving to the library
import_meetingFull pipeline + persisted to library (or offline: true to defer)YesYes*Anything the user wants saved as a meeting in their MimicScribe library

* import_meeting with offline: true skips Gemini and saves the meeting in offline mode — the user can backfill the summary later via “Generate Summary Now”. Use this for the cap-exhaustion recovery path.

Each write tool returns immediately with { status: "queued", requestId, filename } (plus offline echo for import_meeting). The app processes the file asynchronously, sends a notifications/resources/list_changed when complete, and exposes the result through get_import_status. Match queued requests to results by filename + createdAt ordering.

Workflow: fetching a transcription result

Both transcription tools use the same three steps and the same getter:

  1. Call transcribe_with_speakers or transcribe_attributed with the path
  2. On notification (or polling), call get_import_status — look in recentResults for type=="transcription" or type=="attributed_transcript"
  3. Call get_transcript_result with the resultId

There is one getter because a result id is a bare UUID with no store marker in it, and “I called the wrong getter for the tool I queued” was a routine failure when there were two. get_transcript_result tries both stores and tells you which one answered:

{ "type": "transcription" | "attributed_transcript", "result": { … } }

type echoes the pipeline that produced the payload, so an agent doesn’t have to infer it from which fields happen to be present. Pass format (markdown, txt, srt, vtt, json, csv) to get a ready-to-save document instead of the JSON envelope — JSON is the only shape carrying per-word data or attribution provenance, so prefer it when you need either.

type: "transcription" — from transcribe_with_speakers:

{
	"filename": "interview.m4a",
	"durationSeconds": 1823.5,
	"createdAt": "2026-03-29T10:00:00Z",
	"text": "hello um welcome to the show today...",
	"speakers": [
		{ "id": "Speaker 1", "totalDurationSeconds": 1102.3 },
		{ "id": "Speaker 2", "totalDurationSeconds": 721.2 }
	],
	"segments": [
		{
			"speakerId": "Speaker 1",
			"start": 0.24,
			"end": 2.8,
			"text": "hello um welcome to the show",
			"words": [
				{ "word": "hello", "start": 0.24, "end": 0.56, "confidence": 0.97 },
				{ "word": "um", "start": 0.64, "end": 0.88, "confidence": 0.85 },
				{ "word": "welcome", "start": 1.04, "end": 1.52, "confidence": 0.99 }
			]
		}
	]
}

Speaker IDs are always anonymous ("Speaker 1", "Speaker 2", …) — they are never real names. Filler words (um, uh, like) are preserved. Payload is roughly 80–120 KB per hour of audio.

type: "attributed_transcript" — from transcribe_attributed:

{
	"filename": "standup.mp4",
	"durationSeconds": 940.2,
	"createdAt": "2026-03-29T10:15:00Z",
	"speakers": [
		{
			"name": "Alice",
			"attributionSource": "voiceProfile",
			"totalDurationSeconds": 412.6
		},
		{
			"name": "Bob",
			"attributionSource": "transcript",
			"totalDurationSeconds": 327.4
		},
		{
			"name": "Speaker C",
			"attributionSource": "fallback",
			"totalDurationSeconds": 200.2
		}
	],
	"transcript": [
		{
			"speaker": "Alice",
			"start": 0.5,
			"end": 12.3,
			"text": "Hi everyone — let's start with the deploy status."
		}
	]
}

attributionSource reports how each speaker name was derived:

  • voiceProfile — matched a registered voice profile in MimicScribe (highest confidence)
  • transcript — name inferred from speech context (someone addressed by name)
  • fallback — no identification possible; the label is generic (e.g., “Speaker C”)

Always surface attributionSource to users for fallback speakers — those names are not real identifications. Filler words are filtered on this path. Payload is roughly 8–12 KB per hour, safe to pass through agent context even for multi-hour recordings.

Degraded mode. If no AI provider was reachable, the result carries attributionDegraded: true and a degradedReason, the speakers are anonymous cluster labels, and the text is on-device rather than model-cleaned. A normal result omits both fields. Name the speakers from context yourself rather than presenting the cluster labels as identifications.

Workflow: import_meeting

  1. Call import_meeting with the path (and offline: true if the user wants to skip Gemini)
  2. On notification (or polling), call get_import_status — look for type=="meeting"
  3. Call get_meeting_data with the meetingId to read the summary, transcript, and action items

import_meeting with offline: false runs the full pipeline (the same one used for live meetings) and counts against the AI cap. With offline: true, the meeting saves with diarization only and skips Gemini — useful when the cap is exhausted or the user has opted out of AI for this meeting. The user can backfill the summary later by tapping “Generate Summary Now” in the app.

Result lifecycle

transcribe_with_speakers and transcribe_attributed results are ephemeral — stored for 24 hours, then garbage-collected. No meeting is created in the user’s library; if get_transcript_result comes back “not found”, the result has expired (or the id was never issued) and the agent should re-queue with the original write tool. A malformed id gets its own distinct error rather than being reported as an expiry, so an agent doesn’t go re-queue work that was never queued.

import_meeting results are permanent — the meeting lives in the user’s library and is searchable via search_meetings. Offline meetings are hidden from MCP tools by default unless the user enables “Allow connected AI tools to access offline meetings” in Settings > Integrations. When enabled, connected AI tools can read offline meetings and change them: rename and delete (update_meeting, delete_meeting — deletion requires an exact UUID), correct speakers and facts (correct_meeting, which skips cloud summary regeneration for offline meetings), write a summary (write_meeting_summary), and update action items (update_action_items). With the setting off, those calls return the local_mode_meeting error code. MimicScribe never sends offline audio or transcripts to its own cloud features regardless of this setting.

Billing & caps

MCP tool calls are unlimited on every plan until January 1, 2027; from then the Free tier gets 100 calls per week (resets Monday; Pro and paid plans are unlimited). The per-feature limits below also apply:

ToolCounts against AI cap?Free-tier weekly limit (shared bucket)
transcribe_with_speakersNo — on-device onlyNo cap
transcribe_attributedYes — one AI call20 file transcriptions/week, shared with import_meeting
import_meetingYes (attribution + summary)20 file transcriptions/week, shared with transcribe_attributed
import_meeting (offline)No — AI skippedNo AI-cap charge

The file-transcription bucket is separate from the MCP-calls cap — from January 1, 2027 a file import draws on both.

correct_meeting counts as one call against the shared MCP cap (paid plans are unlimited). It doesn’t draw the file-transcription bucket, but the summary regeneration it triggers runs through the meeting AI provider like any other meeting summary.

If import_meeting is rejected due to a cap, retry the same path with offline: true — the meeting saves without Gemini and the user can backfill the summary later.

Shared details

Supported formats: M4A, WAV, MP3, MP4, MOV, and any format readable by AVFoundation. Minimum 3 seconds, maximum 4 hours of audio. The file path must be absolute and accessible to the MimicScribe app — files on the local disk work; files on network volumes may not.

Meeting processing status values (import_meeting only — the two transcription paths complete in one step):

StatusMeaning
pending_enrichmentDiarized; Gemini summary pending
processingGemini enrichment in progress
completedFully processed — transcript, speakers, summary, and action items available
offline_modeSaved without AI — user can backfill via “Generate Summary Now” in the app
billing_blockedTranscript saved but Gemini enrichment requires an active subscription

Queueing: Multiple files can be queued at once — they process sequentially across all three tools (only one Neural Engine task runs at a time). If a meeting is being recorded, queued imports pause and resume automatically when the meeting ends. Agents can poll get_import_status if they don’t support notifications.

Correcting speaker attribution

correct_meeting is the one MCP tool that writes back to a saved meeting. Everything else reads or queues new work — this fixes an existing one. It closes the loop behind the Fix and re-export prompts above: an agent can read a meeting, correct who-said-what, and hand you (or another app) a cleaned copy without you touching the app.

The agent never edits the transcript directly. It proposes a small list of operations; MimicScribe re-validates each one against the meeting’s current speaker roster and applies it deterministically, then regenerates the summary and action items so they reflect the new names.

Operations:

KindFieldsEffect
renamefrom, toGive a speaker a real name. If to is already a speaker, this becomes a merge (flagged in the response).
mergefrom, toFold one speaker’s turns into another — e.g. two mic clusters that are both you.
swapfrom, toExchange two speakers’ labels in one step (use this instead of a temp-name shuffle).
removetargetDelete a speaker’s turns entirely — a phantom or noise “speaker” the diarizer invented.

Labels must match what get_meeting_data returns (case-insensitive). Combined with channel tags, the agent has everything it needs to fix attribution — often without an AI call of its own.

Workflow:

  1. Call get_meeting_data to read the current roster (and channel tags).
  2. Call correct_meeting with the meeting id and an operations array. It returns immediately with { status: "queued", requestId } after pre-validating every op.
  3. On the correction notification (or by polling get_import_status for type == "correction" with your requestId), check the status:
    • applied — done; re-fetch with get_meeting_data to see the corrected transcript and summary.
    • partial — the speaker changes landed but the summary regeneration failed. Do not resubmit the operations (they already applied); the summary is stale until the user regenerates it in the app.
    • a failure appears in recentFailures.
  4. Re-read the corrected meeting and do whatever the user asked next — export it, email it, file tickets.

Rules and guardrails:

  • One request at a time per meeting. All ops in a single request resolve against the same roster snapshot — chained renames or temp-name staging in one batch will not work. For exchanged labels, use swap. Wait for the outcome before the next request.
  • Merges and removes are destructive. The user can undo them in the app, but there is no undo through MCP — confirm intent with the user before a destructive op.
  • Renames can follow the voice forward. Pass enrollVoiceProfile: true (default false) to also update the saved voice profile, so the name attaches to that voice in future meetings. This is not covered by the in-app undo — only set it once the user has confirmed the name.
  • “My mic is always me” locks the mic channel. If the meeting was recorded with that setting on, renaming, swapping, removing, or merging the mic speaker into someone else is refused with mic_locked. Merging another speaker into the mic speaker is allowed.
  • Not for wording or factual fixes. correct_meeting only moves speaker labels around. It deliberately rejects transcript-wording edits, factual summary corrections, and “there was really only one speaker” — those have unbounded blast radius. If the user is exporting the meeting, apply that kind of fix in the exported copy and tell them the stored meeting is unchanged. To fix the stored meeting itself, they type the correction into that meeting’s Q&A box in MimicScribe.
  • Offline meetings are corrected without a summary refresh. With “Allow connected AI tools to access offline meetings” on, speaker corrections apply to offline meetings too. The summary isn’t regenerated for them, so an existing one keeps its wording.

Errors are structured — { error: <code>, message } — so agents branch on the stable code, not the prose. Codes: invalid_meeting_id, invalid_operations, unsupported_kind, provider_off, meeting_not_found, local_mode_meeting, not_completed, op_unbound, would_empty_transcript, mic_locked. On op_unbound the message echoes the current roster, so an agent can correct the labels and retry in one turn. Every op is validated before anything changes — a request either applies in full or fails whole, never halfway.

Meeting prep

Agents can set context before a meeting starts, enriching the AI assistant with background information it wouldn’t otherwise have. Agent-set context and user-typed prep notes (from the app’s “Prepare for Meeting” feature) share the same store — both are visible to agents and to the user.

A typical agent workflow:

  1. Call get_meeting_context to check for existing content (could be user prep notes or another agent’s context)
  2. Research attendees (from a CRM, email threads, past MimicScribe meetings, etc.)
  3. To shape the post-meeting summary, either call list_templates and pick a template_id (a saved summary view — e.g. Walkthrough or By Participant), or pass summary_format free-text rules to shape this one meeting without a saved view
  4. Call set_meeting_context — preserve any existing content verbatim at the top, append your additions below, and pass template_id or summary_format to shape the summary
  5. When the user starts their next meeting, MimicScribe automatically injects the context and applies the chosen view (or formatting rules) to the summary

Important: set_meeting_context overwrites the entire context slot. If the user has already typed prep notes in the app and your agent doesn’t call get_meeting_context first, those notes will be lost. Agents should always read before writing.

View and format semantics on re-writes: When you omit template_id (or summary_format), any previously-staged value is preserved — a safe default for get → append → set flows. Pass an empty string to explicitly clear it and fall back to the global default. A template_id that isn’t a known view returns an error; always source ids from list_templates rather than hardcoding. If both template_id and summary_format are set, the saved view wins. A view the user picks in the app is always respected at meeting start — agent-staged values only apply when the user hasn’t made a pick.

Context set by agents expires after 3 hours by default (configurable via ttl_minutes, max 24 hours). Prep notes saved by the user via the app do not expire. The maximum context size is 50,000 characters. Only one slot of context exists at a time — setting new context overwrites whatever was there. The context is cleared when a meeting ends and won’t carry over to subsequent meetings.

Reference documents

Agents can manage persistent reference documents that are semantically retrieved during meetings. Unlike meeting prep context (which is consumed once and expires), reference documents persist across all meetings and are automatically matched to what’s being discussed.

Use set_context_source to add URLs, local files, or raw text as reference sources. The app chunks, embeds, and indexes each source — during meetings, the most relevant chunks are injected into AI prompts based on the conversation.

A typical agent workflow:

  1. Call set_context_source with operation: "upsert", a title, source_type, and content
  2. The source appears immediately in the response. Processing (chunking + embedding) takes 5-15 seconds.
  3. Call with operation: "list" to check status — look for status: "ready"

Source types:

TypeContent
urlA web page URL — the app fetches and processes the page content
fileAn absolute local file path — the app reads and processes the file
textRaw text provided inline — best for company info, org charts, or content from any source

What makes good reference context: company background, product documentation, org charts, competitive landscape, key terminology glossaries, project briefs, or prior meeting summaries. Structure text with markdown headers — headers become the semantic search keys, so make them descriptive.

Sources are managed by title (case-insensitive). Upserting with an existing title replaces that source. Maximum 10 sources, up to 200,000 characters each. Sources added through the app UI can be viewed by agents but can only be removed through the app.

Reference documents vs. prep notes: Use set_context_source for persistent material reused across many meetings (product docs, org charts, glossaries). Use set_meeting_context for per-meeting prep notes that should expire (today’s attendees, agenda, deal stage). For best results, use both.

Configuration

Open Settings > Integrations in MimicScribe and click Copy Configuration to get the MCP config JSON for your agent client. The configuration looks like this:

{
	"mcpServers": {
		"mimicscribe": {
			"command": "/Applications/MimicScribe.app/Contents/MacOS/mimicscribe",
			"args": ["--mcp-server"]
		}
	}
}

The MCP Server card has a master switch. It’s on by default. Turn it off and the server still starts and lists its tools to a connecting agent, but every request to read or import a meeting is refused with a message telling the agent (and you) that MCP is turned off in Settings — no meeting content leaves your Mac. A freshly connecting agent sees the change immediately; an agent with a long-lived connection open may take a few seconds to pick it up (or reconnect to be sure). No app restart is needed either way.

CLI agents can be configured with a single command:

AgentCommand
Claude Codeclaude mcp add mimicscribe -- /Applications/MimicScribe.app/Contents/MacOS/mimicscribe --mcp-server
Gemini CLIgemini mcp add mimicscribe /Applications/MimicScribe.app/Contents/MacOS/mimicscribe --mcp-server
Codex CLIcodex mcp add mimicscribe -- /Applications/MimicScribe.app/Contents/MacOS/mimicscribe --mcp-server

For Gemini CLI, if the server shows as “Disconnected,” run gemini trust in your working directory.

Codex also supports adding to ~/.codex/config.toml:

[mcp_servers.mimicscribe]
command = "/Applications/MimicScribe.app/Contents/MacOS/mimicscribe"
args = ["--mcp-server"]

Desktop and IDE agents — paste the JSON config above into the appropriate settings file:

AgentConfig location
Claude Desktopclaude_desktop_config.json (Claude menu > Settings > Developer > Edit Config)
Cursor~/.cursor/mcp.json or .cursor/mcp.json in your project
Windsurf~/.codeium/windsurf/mcp_config.json or Windsurf Settings > Cascade > MCP Servers
Zed~/.config/zed/settings.json (use key "context_servers" instead of "mcpServers")

VS Code (GitHub Copilot) uses a slightly different format in .vscode/mcp.json:

{
	"servers": {
		"mimicscribe": {
			"type": "stdio",
			"command": "/Applications/MimicScribe.app/Contents/MacOS/mimicscribe",
			"args": ["--mcp-server"]
		}
	}
}

Requires VS Code 1.99+ and Copilot Agent Mode.

Any other MCP client that supports stdio transport will work — use the JSON config from Settings > Integrations.

Remote access via SSH

The MCP server uses stdio (standard input/output), which means it runs locally by default. If you need to access your meetings from another machine — for example, from a cloud-hosted agent or a remote workstation — you can use SSH:

ssh user@your-mac.local "/Applications/MimicScribe.app/Contents/MacOS/mimicscribe --mcp-server"

Configure your MCP client to use this SSH command instead of the local binary path. The SSH connection handles authentication and encryption — no additional security configuration is needed.

Requirements: Enable Remote Login on your Mac (System Settings > General > Sharing > Remote Login). The MimicScribe app must be installed at the path specified in the command.

Troubleshooting MCP

Agent can’t connect or shows “server exited”: MimicScribe needs to have been launched at least once to create its database. Open the app, then restart your agent client.

Agent can’t find any meetings: Make sure you’ve recorded at least one meeting. The MCP server reads from the same database as the app.

Agent shows stale data: The MCP server reads the database directly, so data is always current. For live meetings, the server waits to notify agents until you close the summary view — so if you’re still reviewing or correcting speakers, the agent won’t have the latest version yet. Close the summary when you’re done to trigger the notification.

Wrong binary path: If you moved MimicScribe from /Applications/, update the command path in your MCP configuration. You can find the correct path in Settings > Integrations.


App Intents

MimicScribe exposes your meetings to macOS itself through Apple’s App Intents: they show up in Spotlight, and you can drive recording and pull up meetings from Shortcuts and Siri. There’s nothing to wire up — the Shortcuts and Siri actions are available as soon as the app has launched once, and Spotlight indexing is on by default.

This is a local integration. MimicScribe doesn’t send your meeting data anywhere for it — the Spotlight index is an on-device macOS index, and the Shortcuts and Siri actions run against your local library. (If you invoke an action by voice, Siri’s own speech processing is Apple’s, not MimicScribe’s.)

Meetings in Spotlight

With Spotlight indexing on (the default), every finished meeting is searchable straight from ⌘Space — and not just by title. MimicScribe indexes the title, the summary, the meeting’s tags, action-item owners, speaker names, and the full transcript text, so you can find a meeting by something that was said in it. Click a result to open the meeting in MimicScribe.

  • Offline meetings are indexed too — a local, on-device transcript is exactly what Spotlight should be able to find.
  • Only unfinished meetings are left out — anything still processing or permanently failed has no transcript to index yet. Everything else, online or offline, is in.
  • The index is on-device, never expires, and deleting a meeting removes it.
  • A very long meeting has the first 100,000 characters of its transcript indexed for Spotlight. This is a Spotlight-index bound only; search inside MimicScribe reads the whole transcript.

Control it in Settings > Integrations, under the Spotlight, Shortcuts & Siri card — the Show meetings in Spotlight switch. It’s on by default; turning it off removes every meeting from the index. This switch only affects Spotlight — the Shortcuts and Siri actions below keep working either way.

Shortcuts and Siri

MimicScribe ships seven actions. Find them in the Shortcuts app under MimicScribe, or trigger the voice-enabled ones with Siri:

ActionWhat it doesSiri
Record MeetingStart a recording (optional title). Opens the app.Yes
Stop RecordingStop and save the current recording.Yes
Toggle Meeting RecordingStart if idle, stop if recording.Yes
Search MeetingsReturn meetings matching a keyword, optionally scoped to a date range. Uses the same search as the app.Yes
Get Action ItemsReturn a meeting’s action items (defaults to your most recent; tentative items excluded unless you opt in).Yes
Get Meeting SummaryReturn a meeting’s summary (defaults to your most recent).Shortcuts only
Open MeetingOpen a specific meeting in the app.Shortcuts only

Siri fills in the app name, so phrases look like:

  • “Record a meeting with MimicScribe” · “Start recording meeting in MimicScribe”
  • “Stop recording in MimicScribe” · “Finish recording in MimicScribe”
  • “Toggle meeting recording in MimicScribe”
  • “Search meetings in MimicScribe” · “Find meetings in MimicScribe”
  • “Get action items from MimicScribe” · “What are my action items in MimicScribe”

Open Meeting and Get Meeting Summary take a specific meeting as input, so a blind Siri phrase can’t tell which one you mean — they’re reachable from the Shortcuts app, where you pick the meeting, and are built to chain (e.g. Search Meetings → Get Meeting Summary → append to a note). Like the app’s own window, all of these actions can see every meeting in your library, including offline ones.

Automations to try

Because these are real App Intents, you can chain them in the Shortcuts app or fire them from an Automation — a time of day, a calendar event starting, a Focus turning on, or a tap on your Home Screen or Apple Watch. A few that people find useful:

  • One-tap record. A single-action shortcut that runs Toggle Meeting Recording, pinned to the menu bar, your Home Screen, or an Apple Watch complication — start and stop without reaching for the app.
  • Morning action-item briefing. A daily Automation that runs Get Action Items on your most recent meeting and reads the result aloud or drops it into Reminders — your follow-ups, before the day starts.
  • Meeting → note. Chain Search Meetings → Get Meeting Summary → Append to Note (or a Slack message, or an email) to file a recap wherever your team lives, right after the call.
  • Hands-free start. Trigger Record Meeting from a Focus mode or a calendar event so recording begins the moment your meeting does — or just say “Record a meeting with MimicScribe.”
  • Ask Siri for the recap. “What are my action items in MimicScribe” reads your latest follow-ups back to you, no app switch.

Every action reads or controls your on-device library, so these run without sending your meetings anywhere.

Automatic recording

Beta. This is the newest part of MimicScribe and the part most likely to change. It recognises three native apps and a list of meeting sites, and anything it does not recognise it leaves alone. Please report a call it misses, or anything it starts that was not a meeting.

MimicScribe can notice when you are in a call and catch it from the start. It lives in Settings > Meeting > Automatic Recording, not under Integrations, because it does not connect to anything: it watches your Mac locally and decides whether to record.

Nothing is armed until you turn on the master switch at the top of the pane, and nothing listens before a recording is running.

While an automatic recording is running, the menu bar shows “Capturing audio” with the elapsed time. MimicScribe does not record you silently, and that is the signal — an automatic start deliberately never steals focus or opens a window, so the menu bar is where you check. To throw one away, open MimicScribe and discard it from the meeting; discarding deletes the audio and the database row together.

Apps

Three, and only three: Microsoft Teams, Slack, and Zoom. Each is recognised by a signal that was measured on a real call, with an idle control to prove it does not fire when the app is merely open. Teams and Slack are detected from a power assertion macOS exposes while a call is up; Zoom from the helper process it runs only during a meeting.

Two consequences of that standard:

  • These apps need no Accessibility permission. macOS tells MimicScribe the app is in a call, so nothing has to read your screen or your windows.
  • An app that is not on the list does nothing at all. It will not record and will not prompt you. The list is the complete set of apps that can act, which is what makes it a list worth reading.

Apps that used to appear here and no longer do: Webex and FaceTime, which provided no signal that distinguished a call from being open; Discord, whose only signal fires the moment you join a voice channel and sit silently; and Teams classic, which was never watched on a real call. A row that cannot fire, or that nobody verified, is worse than no row, because in the pane it looks identical to one that works. That is about the native apps only — Webex in a browser is still covered, as one of the default Meeting Sites below.

Meeting Sites

For calls in a browser, the unit is the meeting service, not the browser: Google Meet, Zoom, Teams, and so on. A site matches on its address, and optionally on words in the window title for a service whose host you cannot predict. You can add your own.

Seven sites ship on by default: Google Meet, Zoom, Microsoft Teams, Webex, Slack huddles, Whereby, and Around. Webex is on this list even though it was dropped from the Apps list above — the two are separate questions. The native Webex app gave no signal that told a call apart from being open; webex.com in a browser is matched by address like any other site, and the browser’s own live-call signal supplies the rest.

Two of those seven can never fire on their address alone. app.slack.com is all of Slack and around.co is a product website, so for those the window title has to confirm (“Huddle”, “Around”) before anything can start. A custom site you add yourself is matched on its address — adding it is itself the statement that the host is meeting-shaped.

Recording a browser call needs both a matched site and evidence that a call is actually live, so a Meet tab left open in the background does not trigger anything.

Sites need Accessibility permission and apps do not, which is why Apps comes first in the pane. Decline the permission and the three apps above keep working; only site matching goes quiet. Firefox is unsupported for site matching.

Stopping

An automatic recording stops on its own when the call ends, after five minutes of silence on both sides, or when your Mac sleeps.

How quickly “the call ended” counts depends on which signal started it, because each signal ends differently and they are not equally trustworthy. One number can’t cover all of them:

How the call was detectedStops afterWhy that number
Safari, and the calling tab was closed~3 secondsA closed tab has nothing to come back with, so waiting is pure delay. Still three polls, not one, because a single failed read of the tab list was seen mid-call.
Microsoft Teams, Slack, Zoom — an app signal disappearing~5 secondsThese signals track the call itself: they appear on join, vanish on leave, and don’t blink while a call is healthy.
Chrome, Brave, Edge, Arc, Vivaldi — the browser’s call signal ends~5 secondsSame signal class as the apps. A single flaky read resets the timer rather than spending it, so what’s being waited out is a signal confidently absent five polls running.
Safari, tab still open but no longer calling~5 secondsThe tab could start calling again, so it gets the full grace rather than the closed-tab shortcut.

A recording started by automatic recording always ends on one of the rows above, or on the silence and sleep backstops. Firefox is the one browser with no measured signal at all, so automatic recording never starts a call there in the first place.

Five seconds is a judgment call. Nobody has measured it. It has to survive a genuine reconnect, where a wifi blip tears a call down and rebuilds it, and nobody has killed wifi mid-call and timed how long the signal stays away. It sat at fifteen seconds for a day, and at forty-five before that; users said forty-five felt broken, twice, so too long has a cost too.

If a call drops and comes back within a couple of minutes, the recording that follows is treated as a continuation rather than a fresh meeting, so a reconnect does not cost you the tail of your call.

A meeting you started yourself is never stopped for you, however long it goes quiet: a break in a workshop recording should not end the recording. Stopping one is always your call.

Two cleanup rules:

  • An automatic recording you discard, or one that auto-stopped with under two minutes of audio, is deleted completely: audio and database row. That is the escape hatch for a false positive.
  • A Stop you tap yourself always saves, however short. You said yes; that wins.

Markdown notes folder (Obsidian, Logseq, or any folder)

MimicScribe can write a Markdown note for every meeting straight into a folder on your Mac — no agent, no MCP client, nothing to script. Turn it on in Settings > Integrations > Markdown notes folder, point it at a folder, and every meeting from then on gets a file.

This is a purely local file write — the note’s delivery never touches the network. What the note contains depends on how you generate summaries (see What each lane sends).

Setup

  1. Open Settings > Integrations and find the Markdown notes folder card.
  2. If MimicScribe finds an Obsidian vault or a Logseq graph on your Mac, it lists it under Quick setup as a button labeled Obsidian: <vault name> or Logseq: <graph name> — click it and the folder fills in (<vault>/Meetings for Obsidian, <graph>/pages for Logseq). Obsidian is read from its own local vault list; Logseq has no such list, so detection is a best-effort check of the default graph locations (~/Documents/logseq, ~/logseq, the iCloud Logseq folder) — nothing is sent anywhere to detect either.
  3. No vault or graph detected, or want a different location? Pick or paste any folder path directly. For a Logseq graph that wasn’t auto-detected, point at its pages folder.
  4. Turn on the auto-save switch at the top of the card.

From then on, a note appears in the folder as soon as a meeting finishes processing.

What flavor you get

The output format follows where the folder sits, not a setting you pick. MimicScribe walks up from the destination folder looking for a vault/graph marker, so a subfolder is detected exactly like the root:

DestinationWhat you get
Inside an Obsidian vault (any folder under one containing .obsidian/)YAML front matter, then the body. people:, assignees: and journal: create real graph edges (Obsidian 1.4+). Bookmarked moments get a ## Flagged Moments list that transcludes each marked turn from the transcript below it, so the words live in the note once. Action items render as Tasks-plugin checkboxes (- [ ] …), with a 📅 yyyy-MM-dd due marker when a date was extracted.
Inside a Logseq graph (any folder under one containing logseq/)Logseq’s native key:: value page properties as the first block, then the body. Attendees linked the same way as Obsidian. Point this at your graph’s pages folder — Logseq only indexes pages/ and journals/, so a note dropped in the graph root won’t show up in Logseq’s UI.
Anywhere elseThe same YAML front matter + a human-readable header (Start/End/Duration/Participants) — valid Markdown everywhere, just without the vault-specific linking.

All three flavors write the same facts; only the syntax differs. Obsidian and plain Markdown get YAML front matter (key: value), Logseq gets its own page-property block (key:: value) as the first block of the file. Here is every key, and which flavor emits it:

KeyObsidianLogseqPlainWhat it holds
title✓—✓The meeting’s display title. Logseq omits it on purpose: the page name is the filename, and title:: would override it and collide across two recordings of the same recurring meeting.
date✓✓✓yyyy-MM-dd of the recording, in the meeting’s own timezone.
start✓✓✓The full start timestamp. date is derivable from it and stays because queries already read it.
timezone✓✓✓The IANA zone the meeting was recorded in — only when the meeting was stamped with one. Never guessed.
imported✓✓✓File imports only. The day you dragged the file in, which is what the filename carries. date stays on the day the audio was made.
duration✓✓✓Human-readable, e.g. "45m".
duration_minutes✓—✓The same number, numeric, so Dataview and Bases can sort on it.
meeting-id✓✓✓The stable id. This is what lets a later re-export follow the note if you rename the meeting in the app instead of leaving a duplicate behind.
source✓✓✓recording, file_import, or text_import.
source-filename✓✓✓The imported file’s name, when there was one.
people✓——Every voice in the recording. A name you’ve attributed is a quoted "[[Wikilink]]"; a placeholder the diarizer assigned is plain text and never linked, so it can’t mint a page for someone who doesn’t exist.
attendees—✓—The same roster, comma-joined, linked the same way.
participants——✓The same roster as plain names, attributed ones first.
assignees✓✓—Who owes something — the subset of the roster that action items are assigned to, and the one a Base can act on.
journal✓——"[[yyyy-MM-dd]]" pointing at the day’s daily note, using your vault’s own daily-note path and format. Omitted rather than guessed when that format has a token this can’t render.
flags✓✓✓How many moments you bookmarked, numeric — only when there’s at least one, so flags > 0 is the query. There is deliberately no flagged tag: flags: 1 and flags: 9 would be the same tag.
action_items✓✓✓How many action items the meeting produced, always present — action_items: 0 is the useful one. Underscored, not hyphenated, because Dataview reads action-items > 0 as a subtraction.
tags✓✓✓See below.

Tags are namespaced. The list is always meeting first, then the meeting’s own search tags as meeting/<tag> — not bare. So a meeting tagged “Q3 Planning” and “budget review” writes:

tags:
  - meeting
  - meeting/q3-planning
  - meeting/budget-review

Each tag is lowercased, spaces collapsed to -, and other punctuation stripped; non-ASCII letters are kept (meeting/münchen, meeting/会議室), and a tag with no letters at all is dropped because Obsidian rejects all-numeric tags. Write your Dataview queries against meeting/…, not the bare keyword. These are one-off keywords a language model invented for one meeting, and a few hundred meetings would put a few hundred of them beside your own hand-made tags in the tag pane — nested, they collapse under meeting and stay searchable, since Obsidian’s #meeting matches #meeting/roadmap too.

Offline meetings are included

An offline meeting still gets a note. Audio, transcription, and speaker ID always run on your Mac, and an offline meeting is never sent to a cloud AI. Its note is transcript-only unless you add a summary with AI that runs on your Mac, and nothing on the way from recording to the file in your vault leaves your Mac.

For an AI summary that never leaves your Mac, point your AI endpoint at a local model (Settings → AI & Data, e.g. Ollama on localhost). Online meetings then get their summary automatically, and an offline meeting can use it through Generate with Your AI. The note carries the summary and action items.

Editing a note after it’s written

MimicScribe writes the note when the meeting’s summary finishes, and keeps it in sync with the app after that — a speaker correction, a rename, or a summary you generate later all update the file in place. The moment you edit the note yourself in your vault, it’s yours: MimicScribe detects the change and never touches that file again, so nothing it does afterward can silently overwrite your edit.

Ticking a checkbox is not an edit. Action items are exported as checkboxes so you can tick them. Under a plain byte comparison, ticking one would hand the file over to you and silently stop every later correction from reaching it. So ownership is decided on a canonical projection of the file rather than its raw bytes, and a short list of marks your tools make by themselves are erased from both sides before the comparison:

  • - [ ] → - [x] — any status character between the brackets, including the Tasks plugin’s custom ones (/, -, >).
  • The Tasks plugin’s ✅ 2026-09-03 / ❌ 2026-09-03 completion stamp on that same click.
  • Logseq flipping TODO → DONE (or DOING, NOW, LATER, WAITING, CANCELED), and the :LOGBOOK: drawer it writes underneath.
  • Logseq’s own per-block bookkeeping — id::, collapsed::.
  • A trailing ^block-id, which Obsidian appends to any line you link to from another note.

Those marks also survive the next refresh: when a line changed only in one of those ways, the file’s version of it wins and your tick is carried forward rather than reset. Everything else — a sentence you rewrote, a bullet you added, a section you deleted — still hands the note to you permanently.

The 📅 yyyy-MM-dd due marker is deliberately not on that list. MimicScribe writes it from the action item’s own due date, so ignoring it would both hide a due-date correction and freeze a stale date on your page.

Want an edited note back in sync with the app? Re-export that meeting with Export Transcript… and save Markdown over it — that’s an explicit hand-back, and auto-save picks it up again from there.

Exporting existing meetings

Just turned this on and want your back-catalog in your vault too? Click Export existing meetings… in the same card. It writes a note for every meeting you’ve already recorded — offline ones included — skipping anything still processing. It’s independent of the auto-save switch, so you can run it any time you point the folder at a new location. Safe to re-run: it refreshes any note you haven’t edited (picking up corrections, renames, or a summary generated since), and never touches one you have — so re-running after you’ve hand-edited notes in your vault won’t clobber them.

Manual one-off export

Don’t want auto-save at all, or need a note somewhere outside your usual folder? Every meeting has an Export Transcript… action (transcript detail view, sidebar right-click, or the review overlay) that opens a save panel offering six formats — Markdown, plain text, SRT and WebVTT subtitles, JSON, and CSV. See Exporting & sharing for what each one contains.

Pick Markdown and you get the vault note exactly as auto-save would have written it: same renderer, so the flavor still follows whatever folder you save into, and saving over a note you’d edited is the explicit hand-back described above. The other five formats are plain document writes — they don’t touch vault-note ownership and don’t hand anything back to auto-save.


URL import helper (yt-dlp)

There’s one more card on Settings > Integrations, and it exists because MimicScribe downloads a third-party executable onto your Mac — you’re entitled to see that it happened, know which copy is in use, and remove it.

When it’s used. A link pointing straight at a media file — an .mp3, an .m4a, an .mp4 — is downloaded directly and the helper isn’t involved. Anything else is a page: a podcast episode, a conference talk, a video with a player on it. Pulling audio out of a page is what yt-dlp does, so that’s the path that uses it. This applies to URL imports from the app and to the url argument on the MCP import tools alike.

How the copy is managed. MimicScribe downloads the helper from its official GitHub release, verifies its SHA-256 before running it, refreshes it weekly, and single-flights the whole thing so two imports can’t race. The card shows the path it resolved and the version.

If you already have your own yt-dlp — a Homebrew install, say — that one wins and MimicScribe never modifies, updates, or removes it. The card says “Using your own install” so it’s clear this app isn’t the thing managing it, and it doesn’t offer to install a second copy alongside.

Nothing installs itself. A managed copy only ever comes into existence because a person pressed the button, either on this card or on the offer that appears in the import sheet. Installing an executable needs your consent, and pressing the button is how you give it. An agent asking for a page import over MCP gets a link to the setting, never a silent install. If you’re setting up an agent, install it here first — otherwise the agent’s first page import stops to ask a question you’re not there to answer.

If MimicScribe installed it, the card has a Remove button.


Webhook

Point MimicScribe at any URL and it POSTs a JSON payload there whenever a meeting finishes , which is how you connect Zapier, Make, n8n, or anything else that can receive a webhook. It needs no agent or client software. Unlike the notes folder, this is the one lane that leaves your Mac over the network, so read What each lane sends before turning it on.

Setup

  1. Open Settings > Integrations > Webhook.
  2. Paste your endpoint URL. It must be https:// — plain http:// is only accepted for localhost/127.0.0.1, for a local automation runner like a self-hosted n8n.
  3. Optionally set a signing secret — this adds an X-MimicScribe-Signature header so your endpoint can verify the request really came from MimicScribe. It’s stored in your login Keychain, not in plain preferences.
  4. Click Send test event to POST a sample payload and confirm your endpoint receives it — the result (HTTP 200, or the error) shows right in the card. This works before you flip the switch on, so you can verify the wiring first.
  5. Turn the webhook on.

What fires, and when

EventFires whenNotes
meeting.completedA meeting’s AI summary finishesFires promptly.
meeting.updatedAnything about a saved meeting changes afterwardCoalesced — a burst of edits inside an ~8-second window becomes one POST, not one per edit.
meeting.testYou click Send test event in SettingsA synthetic sample payload, not a real meeting, so your endpoint can tell it apart.

meeting.updated is broader than “you corrected a speaker.” It hangs off the app’s internal “this meeting was edited” signal, which has around nineteen call sites, and it deliberately fires on all of them. Expect a POST from at least:

  • Any speaker correction, rename, merge, swap, or removal — from the app or from correct_meeting.
  • A summary regenerated, a summary generated later on an offline meeting, a Q&A correction applied.
  • Renaming the meeting’s title. Nothing about the transcript changed; you’ll still get an updated.
  • A moment bookmarked or unbookmarked from a saved transcript, not just during recording.
  • Edits made in Settings → Speaker Profiles, including undoing a profile merge or a co-enrollment. One gesture there can touch many meetings and emit an updated for each one.

That’s intentional. A webhook owns nothing downstream, so it is cheaper to fire and let you upsert than to guess which changes you care about. But size your endpoint for it: filter on event if you only want completions, and never let an updated create a second record.

Offline meetings are never sent, even if they have a summary. Their local Markdown note, if you use the folder-drop above, still gets written; that’s a local file, not network traffic.

Every payload carries the meeting’s id and the event name. Treat it as an upsert-by-id contract: apply an updated payload by overwriting whatever record you created from the matching completed payload, rather than creating a second one.

What happens if my endpoint is down?

There are no retries, so design around that. Each event is one POST with a 30-second timeout. If your endpoint is unreachable, returns a 500, or times out, that event is gone — nothing is queued, nothing is re-sent, and the app does not warn you.

I made it one-shot rather than adding a retry queue because a retry queue that survives quits and reboots is a real piece of infrastructure, and this is a webhook, not a delivery guarantee. Two things follow for you:

  • The failure is visible, but you have to look. Every attempt — success or failure, with the status code or the error — is recorded in Settings → Network Log for the current session. That’s where to check when a Zap stopped firing.
  • Don’t make the webhook your only copy. If a meeting has to reach your system, have the consumer reconcile against search_meetings or the notes folder rather than trusting that every POST landed.

Use Send test event before you rely on it. It posts a sample payload and shows the result (HTTP 200, or the error) in the card, and it works before you turn the switch on.

Payload shape

{
	"event": "meeting.completed",
	"meeting": {
		"id": "3f2e1a9b-6c4d-4b8a-9e2f-1a2b3c4d5e6f",
		"title": "Q3 Planning Sync",
		"date": "2026-07-16T14:30:00Z",
		"durationSeconds": 2712.4,
		"tags": ["pricing", "roadmap"],
		"participants": [
			{ "name": "Jane Okafor", "placeholder": false },
			{ "name": "Marshall", "placeholder": false },
			{ "name": "Speaker 2", "placeholder": true }
		],
		"summary": {
			"overview": "Pricing changes agreed ahead of the board review.",
			"body": "The team agreed to ship the revised pricing before the board review..."
		},
		"actionItems": [
			{
				"id": "9c1e2b7a-…",
				"owner": "Marshall",
				"task": "Send the revised pricing deck",
				"due": "2026-07-20",
				"dueDescription": null,
				"dueTimezone": null,
				"type": "task",
				"confidence": "firm"
			}
		],
		"flaggedMoments": [
			{
				"id": "b7d3c8f1-…",
				"offsetSeconds": 734.2,
				"timestamp": "12:14",
				"excerpt": "Jane Okafor: We can't commit to the June date until legal signs off."
			}
		]
	}
}

participants[].placeholder is true for a diarizer label nobody renamed (e.g. Speaker 2) — the same signal MCP agents use, so your automation can skip unresolved speakers when creating contacts.

flaggedMoments[] holds the moments you bookmarked, during the meeting or afterwards from the saved transcript, each with the lines spoken at that point. The array is empty on most meetings. A moment marked during silence arrives with an empty excerpt rather than being dropped, so your count matches what you see in the app.

The full transcript is never sent — it’s the largest and most edit-sensitive part of a meeting, deliberately excluded from network egress. A flagged moment carries only the lines at the instant you marked.

Request headers:

HeaderValue
Content-Typeapplication/json
X-MimicScribe-Eventmeeting.completed, meeting.updated, or meeting.test (the Settings test button)
User-AgentMimicScribe/<version>
X-MimicScribe-Signaturesha256=<hex HMAC-SHA256 of the raw request body> — only present if you set a signing secret

Discord

Discord’s incoming webhooks don’t render arbitrary JSON — they need a content string or an embeds array, and ignore everything else. So when the URL you paste is a Discord webhook (https://discord.com/api/webhooks/...), MimicScribe automatically sends a Discord message embed instead of the raw payload above: the meeting title as the embed title, the summary overview as the description, and action items and tags as fields. Paste the URL, click Send test event, and a card appears in the channel — no relay or formatter in between. (A signing secret still adds the signature header; Discord ignores it, which is harmless.)

Verifying the signature

The signature is an HMAC-SHA256 of the raw request body bytes under your secret — verify against the bytes you received, not a re-serialized copy of the parsed JSON (re-serializing can reorder keys or change whitespace, changing the hash).

Node.js:

import crypto from 'node:crypto';

function isValidSignature(rawBody, signatureHeader, secret) {
	if (!signatureHeader?.startsWith('sha256=')) return false;
	const expected = crypto
		.createHmac('sha256', secret)
		.update(rawBody)
		.digest('hex');
	const provided = signatureHeader.slice('sha256='.length);
	const a = Buffer.from(expected, 'hex');
	const b = Buffer.from(provided, 'hex');
	return a.length === b.length && crypto.timingSafeEqual(a, b);
}

Python:

import hashlib
import hmac

def is_valid_signature(raw_body: bytes, signature_header: str, secret: str) -> bool:
    if not signature_header or not signature_header.startswith("sha256="):
        return False
    expected = hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
    provided = signature_header.removeprefix("sha256=")
    return hmac.compare_digest(expected, provided)

Both compare with a constant-time function (crypto.timingSafeEqual / hmac.compare_digest), so a mismatched signature can’t be brute-forced by timing.

Example: Zapier

  1. Create a Zap with trigger Webhooks by Zapier > Catch Hook. Zapier gives you a unique URL.
  2. Paste that URL into MimicScribe’s webhook field and turn it on.
  3. Let one real meeting complete, then use Zapier’s “test trigger” so it learns the payload fields (meeting__title, meeting__summary__body, meeting__action_items[], …).
  4. Add a Filter step so only event = meeting.completed continues, if you don’t want an action on every later edit too.
  5. Add your action — e.g. Slack: Send Channel Message pulling in meeting__title and meeting__summary__body.

Example: Make

  1. New scenario > Webhooks > Custom webhook > Add to generate a URL.
  2. Paste it into MimicScribe, enable the webhook.
  3. Run Determine data structure by letting one real meeting complete — Make reads the shape automatically.
  4. Filter the route on event equals meeting.completed.
  5. Add a destination — e.g. Notion: Create a Database Item, mapping meeting.title → Name and meeting.summary.body → a text property, with an iterator over meeting.actionItems[].

Example: n8n (self-hosted)

  1. Add a Webhook node (method POST), copy its Production URL. Because n8n runs locally, http://localhost:… is accepted.
  2. Paste into MimicScribe, enable the webhook, set a signing secret.
  3. Add a Code node to verify X-MimicScribe-Signature against the raw body (n8n runs on Node, so the crypto snippet above applies — check your n8n version’s API for raw-body access) and reject the run on mismatch.
  4. Add an IF node checking {{$json["event"]}} === "meeting.completed".
  5. Wire your destination node — Notion, Google Sheets, or a task-manager node reading actionItems.

What each lane sends, and where

MimicScribe has a few ways data can move, and only some touch the network. This doesn’t change based on which integration you use — it’s the same rule everywhere:

LaneWhat happensEver leaves your Mac?
Recording, transcription, speaker IDAudio capture, ASR, and diarizationNever. Always on-device, whatever else you configure.
Text AI (summary + action items)Runs via Gemini (default), Apple’s on-device model, a custom AI endpoint you configure, or is skippedYour choice. Gemini and most custom endpoints are cloud calls. Apple’s on-device model runs entirely on your Mac, and a custom endpoint can point at a local model (e.g. Ollama on localhost), which also keeps it on-device. An offline meeting never uses a cloud AI here.
Automatic recordingWatches for a call in progress, then starts a recordingNever. Process names, call signals, and browser tab titles and addresses are all read from macOS on-device and are never sent anywhere. No audio is read by this lane at all. Reading browser tabs is part of matching a Meeting Site and happens whenever the master switch is on and you’ve granted Accessibility — there’s no separate switch for it, and turning the master switch off stops all of it.
Markdown notes folderWrites a Markdown file to a folder you choseNever — a local file write. The file’s contents reflect what the text-AI lane did for that meeting (transcript-only if offline, full summary otherwise).
WebhookPOSTs summary + action items + participant names to a URL you provideYes, by design — that’s the point. Never sends the transcript. Never fires for offline meetings. HTTPS only, except localhost.
MCPLocal stdio between MimicScribe and your agent processNot by MimicScribe — the exchange is local. What your agent then does with the data (emails it, pastes it into a cloud doc, calls an API) is the agent’s own action, outside MimicScribe’s control.
App Intents (Spotlight, Shortcuts, Siri)Indexes meetings into the local macOS Spotlight index; Shortcuts/Siri actions read and control your on-device libraryNot by MimicScribe — the Spotlight index is a local macOS index and the actions run on-device. If you invoke an action by voice, Siri’s own speech processing is Apple’s, not MimicScribe’s.

The short version: recording and transcription are always private. Whether a meeting’s summary touches the network is a setting you control per meeting (Offline) or globally (which AI endpoint you point at). Once a summary exists, only the webhook — and only if you turn it on — sends it anywhere; the notes folder and MCP are both local-machine operations.