Skip to main content
Glama

voicememos-mcp

An MCP server for Apple Voice Memos on macOS. It transcribes memos with Soniox and keeps the speech engine's word-level confidence, so uncertain words stay visibly marked instead of being silently guessed. Claude (or any MCP client) can then list, read and search the transcripts.

Design goals:

  • A visible guess beats a gap, and a gap beats a confident wrong word. Every word is kept; low-confidence words are marked.

  • Least privilege. Only a small background worker reads the Voice Memos container. The MCP server reads transcript files and holds no secrets.

  • Lossless storage. The engine's raw response is stored verbatim next to a canonical word-level JSON. Markdown is rendered from it, so the threshold can change later without paying for a new transcription.

How it works

iPhone ──iCloud──▶ Voice Memos on the Mac
                        │  (Full Disk Access, read-only)
                        ▼
              worker (launchd)  ── audio ──▶ Soniox  (file and transcript deleted after use)
                        │
                        ├─▶ OUTPUT_DIR/2026/2026-10-13_2135_title_1a2b3c4d.{md,json}
                        ├─▶ DATA_DIR/library.json, state.json, jobs/
                        └─▶ Roam daily note (optional, append-only token)

Claude ──MCP──▶ voicememos-mcp serve  ── reads ──▶ library.json + transcripts
                        └── writes ──▶ DATA_DIR/queue/  (picked up by the worker)

The worker runs when the recordings folder or the queue changes, and every 30 minutes.

Related MCP server: voice-memo-hub

Uncertainty notation

Markdown

Meaning

word (?)

best guess, confidence below the threshold

[?: w1 w2 w3 w4]

several consecutive uncertain words (guesses kept)

{a|b}

two engines heard different things: primary engine first, second reader after

{a b|∅}, {∅|b}

only one of the engines heard something here

[?]

something was said, nothing usable was recognised

[?: word ×N]

the engine produced the same word N times in a row (4+), usually a loop over music or noise; JSON flag repetition

[12:34] / [1:02:03]

time in the recording at the start of a paragraph, at most once a minute (VOICEMEMOS_TIMESTAMP_EVERY_S)

This follows conversation-analysis (Jefferson) practice, where (word) marks an uncertain hearing, (a)/(b) alternative hearings and ( ) unhearable talk.

Each transcript's JSON keeps, per word, conf (0..1), optional ranked alts, and a basis explaining where the uncertainty comes from:

  • asr_confidence: measured by the speech engine,

  • reader_disagreement: independent engines disagreed,

  • self_report: a model said it was unsure (not calibrated).

The semantics match PAGE XML (TextEquiv@conf, alternatives ranked by index) and can be exported to TEI (<unclear cert>, <choice>) or ALTO (WC, ALTERNATIVE). No existing standard keeps everything a speech engine returns (sub-word tokens, per-token language, timings), which is why the raw response is stored as well.

Speakers

With VOICEMEMOS_DIARIZATION=1 (default), Soniox separates speakers. Single-speaker memos look the same as before; conversations get one paragraph per turn:

**S1:** How did it go?
**S2:** Fine (?), thanks.

Speakers are numbered in order of appearance; the labels only hold within one memo and nobody is named. The JSON keeps per-speaker word counts and shares (speakers) and the speaker of every word.

Voiceprint (optional)

To show your name instead of S1, the worker can recognise your voice locally. A small speaker model (3D-Speaker CAM++ trained on a large Chinese and English corpus, run with sherpa-onnx; about 28 MB, downloaded once and checked against a pinned SHA-256) turns speech into an embedding; your voiceprint is the average embedding of a few memos where only you speak.

Why this model: on a small test set of Finnish and English memos (one owner, recorded on three phones over eight years, with and without earphones, plus other speakers), VoxCeleb-trained models (WeSpeaker ResNet34/ResNet293, CAM++) scored another Finnish speaker almost as high as the owner, so the recording conditions weighed more than the voice. CAM++ "common advanced" kept a clear gap (owner 0.56 to 0.77 on held-out memos, the other speaker 0.32), NVIDIA TitaNet-L came second. This is one person's data, so treat it as a sanity check, not a benchmark; VOICEMEMOS_VOICEPRINT_MODEL also accepts wespeaker_en_voxceleb_resnet34_LM. Changing the model requires enrolling again.

  1. voicememos_voiceprint(action="status") suggests enrollment memos: transcribed with diarization, one speaker, 30 s to 15 min, spread over the years. Check that only you speak in them.

  2. voicememos_voiceprint(action="enroll", memos=[...], name="...") (4-6 memos from different years, devices and places). Enrollment scores each memo against a voiceprint built from the others; the lowest score sets the match threshold, so it reflects how much your own voice varies between recordings.

  3. New memos are identified as they are transcribed; action="identify" applies the voiceprint to existing transcripts.

Labels: your name when a speaker's similarity reaches the match threshold and is clearly above any other speaker; Name (?) for a possible match; otherwise S1, S2. Single-speaker memos get a header line ("Voiceprint: matches Name (similarity 0.93)"). Scores are kept in the JSON (speakers[...].voiceprint, voiceprint).

Cost: about 30 seconds of speech per speaker is embedded, so identification takes roughly a second per memo regardless of its length.

Known other voices. A relative can sound close enough to pass the threshold on their own. Add such a voice from one speaker of a memo, e.g. voicememos_voiceprint(action="add_other", memos=["<id>"], speaker="S1", name="<name>"). Known other voices are never shown as labels; they only stop a speaker from being labelled as you when that speaker is as close, or nearly as close, to a known other voice. Run action="identify" again afterwards; action="remove_other", name="<name>" removes one.

The voiceprint is biometric data. It is stored only in DATA_DIR/voiceprint.json (file mode 600), never in transcripts, and the MCP tools report only a summary. Delete that file to remove it.

Spoken markers

Say a marker word to collect a sentence as an idea, task or question (voicememos_markers, and a "Markers" list at the top of the transcript).

Without a wake word, any sentence that starts with a marker word counts ("Idea: ..."). That also catches ordinary sentences, so a wake word is better:

VOICEMEMOS_MARKERS="idea*=Idea,question*=Question,task*=Task,remind*=Reminder"
VOICEMEMOS_MARKER_WAKE="dictate*"
VOICEMEMOS_MARKER_END="end"
VOICEMEMOS_CONTEXT_TERMS="Dictate"   # helps the engine hear the wake word
  • "Dictate idea: ..." or "Dictate. Ideas, ..." – punctuation or a pause may separate the words, and * accepts inflected forms.

  • A marker covers one sentence. If the marker word ends a sentence on its own, the next sentence is taken. For more, close with "Dictate end"; the next marker also closes one.

  • A wake or marker word heard with low confidence is not dropped: the marker is kept, shown as Idea (?) and has uncertain_trigger in the JSON.

  • New rules apply to memos transcribed (or rewritten by a second reading or voiceprint run) after the change; older transcripts keep their markers.

Second reader

Gemini models return text without word confidence, so they cannot drive the (?) marks. They are useful as an independent second reader: where two engines disagree, at least one is wrong. voicememos-mcp second-read (or the voicememos_second_read tool) sends the audio of already transcribed memos to a Gemini model (default gemini-4-argon), aligns its text with the primary words and marks the differences as {a|b}. The primary engine is not called again, and the raw second text is kept in the JSON (readers).

voicememos-mcp report (or voicememos_compare_readers) compares the readers per language (Soniox's language tags decide whether a memo is Finnish, English or mixed):

  • word agreement and difference rate,

  • disagreements per 100 words,

  • calibration: how many disagreements fall on words the primary engine already marked uncertain, and how many uncertain words the second reader confirmed,

  • a random sample of disagreements with time offsets, as a listening checklist. Agreement says nothing about who is right; listening does.

The alignment is a word-level sequence diff that ignores case and punctuation. In Finnish it also treats common spoken and written forms of the same word as equal (mä/minä, oon/olen, sit/sitten, niinku/niinkuin, …): one reader tends to write what was said, the other what was meant, and that is not a hearing disagreement. Only whole words with one obvious written form are folded, never suffixes (huomasin/huomasi stays a disagreement), and forms that are also English words (sun, sit) are folded only in words tagged Finnish. Reports re-align stored readings with the current rules. Different word splitting (compounds, numbers written as digits or words) still shows up as disagreement.

With VOICEMEMOS_SECOND_READER=gemini-low only memos whose primary transcript has low certainty (15 % or more of the words marked) get a second reading automatically: the noisy car memos, not the clear ones. gemini reads every new memo.

Recordings longer than VOICEMEMOS_SECOND_READER_MAX_MIN (60) are read in parts of about VOICEMEMOS_SECOND_READER_CHUNK_MIN (30) minutes. Cuts fall in a pause between words, preferably after a sentence, never inside a word. With gemini-low only the parts whose own certainty is low are read. Each part is aligned with the same span of the primary words; the transcript (JSON and Markdown) stays one piece. One request per part keeps each answer well below the model's default output limit (65,536 tokens for Gemini 4 Argon) and avoids drift in very long generations.

For memos transcribed earlier: voicememos_second_read(since="2000-01-01", only_uncertain=True) (or voicememos-mcp second-read --only-uncertain --queue) reads only memos with low certainty, and long recordings only in their parts with low certainty. Memos already read are skipped.

A reading that agrees with the primary words on less than a tenth of the words (VOICEMEMOS_SECOND_READER_MIN_AGREEMENT, default 0.1) is rejected: the model has written something other than the recording (seen once: a made-up exercise plan, agreement 0.04, for a quiet meditation memo). Nothing is marked, earlier marks from that reader are removed, and its text is kept in the JSON with the reason. The floor is low on purpose: on very hard recordings (loud music, a disguised voice) genuine readings agreed only 0.17–0.19 and were sometimes better than the primary engine. For long recordings the check is done per part.

When the reader stops early (finish reason RECITATION – its copyright filter, typically triggered by music or radio in the background – or MAX_TOKENS and similar), the primary words after the end of its text are left uncompared instead of being marked {word|∅}. If the model refuses one part of a long recording, that part stays unread and the other parts are kept.

After such rule changes, voicememos-mcp second-read --realign --queue (or voicememos_second_read(since="2000-01-01", realign=True)) aligns the stored readings again with the current rules. No audio is sent and no API is called.

Transcripts start with a short reading guide that asks language models not to present marked words as certain, and to propose corrections visibly (word→suggestion (?)).

Requirements

  • macOS 14 or later with Voice Memos iCloud sync enabled on the iPhone and the Mac (open Voice Memos on the Mac once).

  • uv

  • A Soniox API key.

  • Optional: ffmpeg for lossless .qta handling (otherwise afconvert is used). Needed for memos longer than 298 minutes, which are transcribed in parts.

Install

git clone https://github.com/<you>/voicememos-mcp.git
cd voicememos-mcp
./install.sh          # creates ~/.config/voicememos-mcp/config.env on the first run
$EDITOR ~/.config/voicememos-mcp/config.env
./install.sh          # again, to apply the configuration

install.sh installs the MCP server with uv tool, creates a separate virtualenv for the worker, stores the Soniox key in the Keychain, installs the launchd job and adds this to claude_desktop_config.json:

"voicememos": { "command": "/Users/<you>/.local/bin/voicememos-mcp", "args": ["serve"] }

Where transcripts live

macOS protects Documents, Desktop, Downloads and iCloud Drive. MCP servers started by Claude Desktop do not appear to inherit the app's own permissions, so the server could not read transcripts kept there (voicememos_status then reports output_readable: false). The default folder is therefore ~/Library/Application Support/voicememos-mcp/transcripts, which needs no permission. To see the transcripts in Documents, add a symbolic link; the files stay where the server can read them:

ln -s ~/Library/Application\ Support/voicememos-mcp/transcripts ~/Documents/voice-memos

Finder and editors follow the link. Spotlight and iCloud Drive generally do not follow symbolic links, so the transcripts are not indexed there or uploaded with Documents.

Full Disk Access

The Voice Memos container is protected by macOS privacy controls. Only the worker needs access, and it gets it through a tiny compiled launcher (launcher/launcher.c, built by launcher/build-launcher.sh) that install.sh builds into ~/Library/Application Support/voicememos-mcp/bin/voicememos-worker. Grant Full Disk Access to that file once (install.sh prints the path and opens the settings pane), then run launchctl kickstart -k gui/$(id -u)/local.voicememos-mcp.sync.

Why a launcher:

  • macOS ties the permission to the exact binary. Granting it to a Python interpreter breaks with every Python update, and it would cover every script run with that interpreter.

  • The launcher starts the worker as a child process, and macOS attributes the child's file access to it, as it does for programs started from Terminal. It runs one compiled-in command and ignores arguments, so it cannot be used to run anything else.

  • install.sh rebuilds it only when its source or the worker path changes, so the grant survives updates. Without a C compiler (xcode-select --install) the installer falls back to granting the interpreter.

  • To keep the grant even when the launcher has to be rebuilt, sign it with your own certificate: run FDA_LAUNCHER_SIGN_IDENTITY="<certificate name>" ./install.sh once and grant the permission one last time. Later installs reuse the identity. How to create the certificate, and what it means for security, is in the fda-launcher template.

The MCP server does not need Full Disk Access. Do not grant it to Claude Desktop: every local MCP server it starts would inherit it.

Check the setup with voicememos-mcp check (from Terminal; Terminal may have different permissions than the launchd job) and the worker log in ~/Library/Application Support/voicememos-mcp/logs/.

Configuration

All settings are in ~/.config/voicememos-mcp/config.env; see config.example.env for every option. The most important:

Setting

Default

VOICEMEMOS_LANGUAGES

en

language hints, e.g. fi,en

VOICEMEMOS_CONTEXT_TERMS

names and rare terms the engine should know

VOICEMEMOS_CONF_THRESHOLD

0.70

words below this are marked

VOICEMEMOS_OUTPUT_DIR

~/Library/Application Support/voicememos-mcp/transcripts

outside Documents on purpose, see Where transcripts live

VOICEMEMOS_SINCE

only auto-transcribe memos from this date on

VOICEMEMOS_EXCLUDE_FOLDERS

Voice Memos folders hidden from everything

VOICEMEMOS_EXCLUDE_TITLE_REGEX

titles hidden from everything

VOICEMEMOS_MARKERS

idea=Idea,task=Task,...

spoken words that tag a sentence; * accepts inflected forms (question*=Question)

VOICEMEMOS_MARKER_WAKE

wake word required before a marker word, e.g. dictate*; empty = marker word alone

VOICEMEMOS_MARKER_END

end word after the wake word that closes a longer marker, e.g. end

VOICEMEMOS_DIARIZATION

1

separate speakers in conversations

VOICEMEMOS_VOICEPRINT_NAME

your name, shown when the voiceprint recognises you

VOICEMEMOS_SECOND_READER

gemini = second reading for every new memo, gemini-low = only for memos with low certainty

VOICEMEMOS_SECOND_READER_MODEL

gemini-4-argon

VOICEMEMOS_SECOND_READER_MAX_MIN

60

longer recordings are read in parts

VOICEMEMOS_SECOND_READER_CHUNK_MIN

30

approximate length of a part

VOICEMEMOS_SECOND_READER_MAX_TOTAL_MIN

600

longer memos get no automatic second reading

VOICEMEMOS_SEGMENT_LONG

1

split memos longer than the engine accepts (see Limitations)

VOICEMEMOS_SEGMENT_MARGIN_MIN

5

parts are at most VOICEMEMOS_MAX_DURATION_MIN (298) minus this

VOICEMEMOS_SEGMENT_SILENCE_WINDOW_MIN

10

move each cut to the longest silence this close to the even split

VOICEMEMOS_ROAM_ENABLED

0

append new transcripts to Roam daily notes

Excluded memos are never transcribed, and the MCP tools cannot see them, not even their titles.

MCP tools

Tool

voicememos_status

counts by status, worker health, configuration, warnings

voicememos_list

memos newest first; filter by date, title, status; paging

voicememos_read

one transcript as Markdown, plain text or word-level JSON; optional threshold re-renders without re-transcribing; paging for long memos

voicememos_search

case-insensitive search (or regex) over transcripts and titles, with snippets

voicememos_markers

sentences tagged with a spoken marker ("Idea: ...") across memos

voicememos_transcribe

queue memos (by id or date range) for background transcription; returns a job id

voicememos_second_read

queue an independent Gemini reading of transcribed memos

voicememos_compare_readers

per-language comparison of the readers, with a listening checklist

voicememos_voiceprint

voiceprint status and enrollment suggestions, enroll, identify

voicememos_transcribe_status

job progress, or recent jobs

Memo status values: transcribed, pending (will be transcribed automatically), not_transcribed (outside VOICEMEMOS_SINCE; use voicememos_transcribe), not_downloaded (audio still in iCloud; play it once in Voice Memos on the Mac), segmenting (longer than the engine accepts; being transcribed in parts), failed (after VOICEMEMOS_MAX_ATTEMPTS tries; for a memo in parts, of one part), too_long (long, and splitting is off or ffmpeg is missing; listed under skipped in worker.json and as a warning in voicememos_status), deleted.

Command line

voicememos-mcp check                         # paths, permissions, keys
voicememos-mcp sync --dry-run --limit 1      # one memo, print only, save nothing
voicememos-mcp sync --memo 1a2b3c4d --redo   # transcribe one memo again
voicememos-mcp transcribe-file memo.m4a --threshold 0.6 --threshold 0.8   # calibration
voicememos-mcp second-read --since 2026-01-01 --limit 20   # add the second reader
voicememos-mcp report                        # compare readers per language
voicememos-mcp voiceprint status             # enrollment state and suggestions
voicememos-mcp launchd-plist                 # print the launchd job definition

Calibrating the threshold

Pick 5-10 different recordings (quiet room, car, mixed languages) and run transcribe-file with thresholds 0.6, 0.7 and 0.8. Choose the value at which wrong words stop slipping through unmarked. Extra marks on correct words are cheap; an unmarked wrong word is expensive. voicememos_read(..., threshold=...) lets you compare on stored transcripts without new API calls.

Privacy and security

  • With the second reader, audio also goes to the Gemini API, including any other voices in the recording. Large files uploaded through the Files API are deleted right after the request.

  • Audio goes to Soniox for transcription. The uploaded file and the transcription are deleted from Soniox right after the transcript is fetched, also when something fails. Soniox offers an EU endpoint (SONIOX_BASE_URL=https://api.eu.soniox.com), which needs an EU project.

  • Nothing in the Voice Memos container is modified. The database is opened read-only.

  • Secrets live in the Keychain or the environment. The package never writes them to a file (you can put them in config.env yourself, but the Keychain is the safer place).

  • With the default VOICEMEMOS_WORKER=launchd, the MCP server has no secrets and no access to Voice Memos; it can only queue requests. In inprocess mode it does both itself.

  • Roam uses an append-only token, which cannot read or delete anything.

Limitations

  • Tested with the Voice Memos database of macOS 26. Column names are detected at runtime, but older or newer versions may differ.

  • Memos whose audio has not been downloaded from iCloud cannot be transcribed until they are played once on the Mac.

  • Soniox accepts at most 300 minutes per file. Longer memos are cut with ffmpeg (stream copy, no re-encoding) into the fewest parts of at most 293 minutes, at a silence near the even split, transcribed part by part and merged: time stamps run through the whole recording and the front matter gets segments and segment_bounds_s. Finished parts are kept in tmp/<memo id>/ until the memo is done, so a failed part is the only one sent again. Diarization labels hold within one part only (S1a, S1b; Soniox gives no speaker embeddings to match them across parts); the voiceprint is applied to every part.

  • The Roam Append API request format follows public examples; test with one memo first.

Roadmap

  • Adjudication: a third pass that listens to the disputed segment and picks a reading.

  • Export to TEI (spoken text) and WebVTT.

Development

uv venv && uv pip install -e ".[test]"
.venv/bin/pytest

License

MIT

Available Tools

10 tools
voicememos_compare_readersA

Compare primary engine and second reader per language (agreement, calibration, samples).

Writes a Markdown report with a listening checklist and returns the summary.

Args: since: only memos recorded on or after this date (YYYY-MM-DD). until: only memos recorded on or before this date (YYYY-MM-DD). samples: disagreements to sample per language (max 50).

NameRequiredDescriptionDefault
sinceNo
untilNo
samplesNo

TDQS

A3.8/5.0
Behavior4/5

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

With no annotations present, the description carries the full burden and does disclose the key side effect: it writes a Markdown report (with a listening checklist) and returns only a summary. That non-obvious write-then-summarize behavior is exactly what an agent needs. It does not say where the report file lands or whether it overwrites prior reports.

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

Conciseness4/5

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

Front-loaded summary sentence followed by a compact Args block that maps one-to-one to the parameters. No filler; the only structural quibble is that the report-writing behavior sits in the second line rather than being grouped with the summary.

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

Completeness4/5

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

No output schema exists, and the description does state the return surface ('returns the summary') plus the artifact produced, which is the critical gap covered. Remaining omissions—report output path and handling of the samples cap—are modest for a zero-required-parameter reporting tool.

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

Parameters4/5

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

Schema coverage is 0%, so the description must compensate, and it largely does: it defines 'since'/'until' as inclusive date bounds in YYYY-MM-DD and 'samples' as disagreements to sample per language with a max of 50. It omits the schema's default of 15 for samples and doesn't clarify what happens if since > until or if the max is exceeded (clamped vs. error).

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

Purpose4/5

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

Opens with a specific verb+resource: 'Compare primary engine and second reader per language', and enumerates the comparison dimensions (agreement, calibration, samples). This clearly distinguishes it from siblings like voicememos_second_read (which presumably produces one reading) and voicememos_transcribe, though it never names those siblings explicitly.

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

Usage Guidelines3/5

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

Usage is only implied by the phrasing 'compare primary engine and second reader', suggesting it is run after a second read exists. There is no explicit statement of when to use it, when not to, or which sibling to call first to populate the second reader.

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

voicememos_listB

List memos, newest first.

Args: limit: page size (max 200). offset: start index for paging. since: only memos recorded on or after this date (YYYY-MM-DD). until: only memos recorded on or before this date (YYYY-MM-DD). title: case-insensitive substring of the title. status: transcribed, pending, segmenting (longer than the engine accepts: being transcribed in parts), not_transcribed, not_downloaded, failed or too_long (long and cannot be split: splitting off or ffmpeg missing).

NameRequiredDescriptionDefault
limitNo
sinceNo
titleNo
untilNo
offsetNo
statusNo

TDQS

B3.3/5.0
Behavior3/5

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

With no annotations, the description carries the full burden. It discloses the default ordering ('newest first') and explains the meaning of each status value, which is genuinely useful behavior context. It does not state that this is a read-only/non-destructive operation, nor describe the returned fields or pagination edge cases (e.g., offset without limit).

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

Conciseness4/5

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

The first sentence front-loads the purpose and ordering, and the arg list is compact. The verbose `status` explanation is justified because the schema has no enums, though it makes the block slightly long.

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

Completeness3/5

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

For a six-parameter list tool with no annotations and no output schema, the description covers filtering semantics but omits safety profile (read-only), shape of returned memo records, and how paging interacts with ordering. Adequate but not fully complete.

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

Parameters4/5

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

Schema description coverage is 0%, and the description compensates well: it documents all six parameters, gives date formats for `since`/`until` (YYYY-MM-DD), clarifies substring/case-insensitivity for `title`, and enumerates the meaningful `status` values with explanations. Minor ambiguity remains about whether `status` accepts a single value or a list, and the `limit` default of 20 is only in the schema.

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

Purpose4/5

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

Names a specific verb and resource ('List memos') and adds ordering ('newest first'), which an agent can act on immediately. It does not, however, distinguish this from the sibling `voicememos_search`, so the agent must guess which listing tool to choose.

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

Usage Guidelines2/5

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

There is no explicit statement of when to use this versus `voicememos_search` or the read/status siblings. The filter parameters imply a browsing use case, but the agent is left to infer that from the arg docs alone.

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

voicememos_markersB

Sentences the user tagged by starting them with a spoken marker word (e.g. "Idea: ...").

Args: since: only memos recorded on or after this date (YYYY-MM-DD). until: only memos recorded on or before this date (YYYY-MM-DD). label: only this marker label. limit: maximum number of markers returned.

NameRequiredDescriptionDefault
labelNo
limitNo
sinceNo
untilNo

TDQS

B3.1/5.0
Behavior2/5

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

No annotations exist, so the description carries the full behavioral burden, yet it never states that this is a read-only operation, whether results are ordered, how pagination beyond the limit behaves, or what the output records look like. The marker concept is explained, which is useful, but core behavioral traits are absent.

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

Conciseness4/5

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

The core definition is front-loaded in a single sentence with a concrete example, followed by a tightly formatted Args list. No wasted sentences, though the concept sentence could state the retrieval action more explicitly.

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

Completeness3/5

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

With no output schema and no annotations, the description should say more about the return shape, ordering, and pagination. It explains what markers are and how to filter, which is adequate minimum context for a simple query, but not complete.

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

Parameters4/5

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

Schema description coverage is 0%, so the description must compensate, and it does define all four parameters with useful meaning: since/until bounds with YYYY-MM-DD format, label as a filter, and limit as maximum markers returned. The default limit of 50 is not stated, and case-sensitivity of label is unspecified, keeping it from a 5.

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

Purpose4/5

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

The description clearly identifies the resource: sentences the user tagged with a spoken marker word, with an illustrative example. It distinguishes itself from siblings like voicememos_list or voicememos_search by being specifically about tagged markers, though the retrieval verb is only implied rather than stated.

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

Usage Guidelines2/5

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

There is no guidance on when to use this tool versus voicememos_list, voicememos_search, or voicememos_read. The agent must infer from the name and the marker concept alone. No prerequisites or exclusions are stated.

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

voicememos_readA

Read one transcript with uncertainty marks.

Args: memo: memo id from voicememos_list (8 characters is enough). format: 'markdown' (with header), 'text' (transcript only) or 'json' (word-level data). threshold: confidence threshold for marking words (default from config); re-renders without re-transcribing. offset: character offset for long transcripts (see next_offset). max_chars: maximum characters returned (1000-100000).

NameRequiredDescriptionDefault
memoYes
formatNomarkdown
offsetNo
max_charsNo
thresholdNo

TDQS

A3.8/5.0
Behavior4/5

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

With no annotations, the description carries the full burden and does well: it discloses that changing the threshold re-renders without re-transcribing, that long transcripts are paginated via offset/max_chars with a 1000-100000 bound, and that three output formats exist. It stops short of stating read-only semantics or rate/auth constraints, but the key behavioral traits are covered.

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

Conciseness4/5

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

The purpose is front-loaded in one sentence, then parameters are listed compactly with no filler. The Args block is slightly verbose but every line carries information an agent cannot get from the schema.

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

Completeness4/5

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

For a read tool with no output schema, this describes the return content (transcript with uncertainty marks, header in markdown) and pagination behavior. The dangling 'next_offset' reference and the absence of any statement about what json word-level data looks like are minor omissions.

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

Parameters4/5

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

Schema coverage is 0%, so the description must document all five parameters, and it does: memo accepts an 8-char prefix, format enumerates markdown/text/json, threshold defaults from config and only re-renders, offset is a character offset, and max_chars has an explicit range. The only gap is that offset references a 'next_offset' value that is never defined, since no output schema exists.

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

Purpose4/5

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

The first line states a specific verb and resource: read one transcript, with the distinguishing trait of uncertainty marks. It is clearly not list/search/compare, but it doesn't explicitly contrast itself with the closest sibling read tool, voicememos_second_read.

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

Usage Guidelines3/5

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

Usage is implied through the prerequisite chain ('memo id from voicememos_list') and through the pagination hint ('see next_offset'), but there is no explicit when-to-use-this-versus-alternative guidance against second_read or compare_readers.

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

voicememos_second_readA

Queue a second, independent reading (Gemini) of already transcribed memos.

Disagreements with the primary engine appear as {a|b} in the transcript. Returns a job_id.

Args: memos: memo ids. since: or: memos recorded on or after this date (YYYY-MM-DD). until: or: memos recorded on or before this date (YYYY-MM-DD). model: Gemini model id (default from config, e.g. gemini-4-argon). redo: read again even if a second reading exists. limit: at most this many memos (oldest first). only_uncertain: only memos with low certainty; long recordings (read in parts) only in their parts with low certainty. realign: no new reading; align the stored readings again with the current rules.

NameRequiredDescriptionDefault
redoNo
limitNo
memosNo
modelNo
sinceNo
untilNo
realignNo
only_uncertainNo

TDQS

A4.2/5.0
Behavior4/5

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

With no annotations, the description carries the full behavioral burden and does well: it discloses asynchronous queuing and a returned job_id, the output format of disagreements ({a|b}), redo semantics, the realign mode that performs no new reading, and edge behavior for long recordings under only_uncertain. It stops short of mentioning permissions or how to poll the queued job.

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

Conciseness4/5

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

The purpose is front-loaded in the first sentence, followed by an organized Args list. It is appropriately sized for an eight-parameter tool, though the 'or:' formatting in since/until is slightly awkward and a few notes could be tightened.

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

Completeness4/5

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

For an async job tool with no output schema, the description provides the essential return value (job_id), all parameter semantics, and important behavioral modes. It could be more complete by noting that memos must already be transcribed, what happens if they are not, or which sibling status tool to use to retrieve the job result.

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

Parameters5/5

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

Schema description coverage is 0%, so the description must compensate for all eight parameters, and it does: memos, since, until, model, redo, limit, only_uncertain, and realign are each explained with meaning and important nuances (date filtering is OR, limit applies oldest first, long recordings only in low-certainty parts).

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

Purpose5/5

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

The description states a specific action — queue a second, independent Gemini reading — on a specific resource: already transcribed memos. It also distinguishes the outcome from the primary engine by explaining that disagreements appear as {a|b} in the transcript, making it identifiable against siblings like voicememos_read or voicememos_compare_readers.

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

Usage Guidelines3/5

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

Usage is implied by 'second, independent reading' and 'already transcribed memos', and parameter notes (redo, realign, only_uncertain) somewhat guide behavior. However, there is no explicit guidance on when to prefer this over voicememos_compare_readers, voicememos_read, or when a second reading is unnecessary.

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

voicememos_statusA

Library size, transcription status counts, worker health and configuration.

NameRequiredDescriptionDefault

No parameters

TDQS

A3.5/5.0
Behavior3/5

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

With no annotations, the description carries the full behavioral burden. It discloses the categories of information returned, which is useful, but does not state that the tool is read-only, side-effect-free, or whether any permissions or rate limits apply.

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

Conciseness4/5

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

The description is a single, front-loaded sentence with no wasted words. It is essentially a noun phrase rather than a full sentence, but every item listed earns its place.

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

Completeness3/5

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

For a zero-argument status tool, the description adequately names the returned categories, but without an output schema it leaves the return format and granularity (aggregate counts versus per-file details) unclear. It also does not help an agent choose it over voicememos_transcribe_status.

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

Parameters4/5

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

The tool takes zero parameters, so the schema imposes no additional semantic burden. The description appropriately does not discuss parameter syntax.

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

Purpose4/5

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

The description enumerates the specific status content returned: library size, transcription status counts, worker health, and configuration. It is clear what the tool reports, though it does not explicitly differentiate itself from voicememos_transcribe_status.

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

Usage Guidelines3/5

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

The listed contents imply a diagnostic or overview use case, but there is no explicit guidance on when to use this versus voicememos_transcribe_status or other status-adjacent siblings.

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

voicememos_transcribeA

Queue memos for transcription in the background. Returns a job_id immediately.

Args: memos: memo ids to transcribe. since: or: all memos recorded on or after this date (YYYY-MM-DD). until: or: all memos recorded on or before this date (YYYY-MM-DD). redo: transcribe again even if a transcript exists. push_roam: also append the transcripts to Roam daily notes (if Roam is configured).

NameRequiredDescriptionDefault
redoNo
memosNo
sinceNo
untilNo
push_roamNo

TDQS

A3.8/5.0
Behavior4/5

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

With no annotations, the description carries the burden well: it discloses asynchronous background execution, an immediate job_id return, the default skip-if-transcript-exists behavior implied by redo, and the conditional Roam side effect. It omits failure behavior, cost/rate implications of transcription, and how to check job completion.

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

Conciseness4/5

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

Front-loaded with the two facts an agent needs (what it does, what it returns), then a scannable Args list. The stray 'or:' artifacts and blank-line formatting add mild noise but nothing is wasted.

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

Completeness4/5

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

For a 5-parameter, no-annotation, no-output-schema tool, the description covers the async contract, the return value, and every parameter's meaning. The main missing piece is the follow-up workflow for the returned job_id, which matters for a background job tool.

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

Parameters4/5

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

Schema coverage is 0%, so the description must compensate and largely does — it explains all five parameters including the YYYY-MM-DD date format, the redo semantics, and that push_roam only applies if Roam is configured. Minor gaps: no statement that memos and since/until are alternatives, and the 'or:' phrasing is garbled.

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

Purpose4/5

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

The description opens with a specific verb+resource+mode: 'Queue memos for transcription in the background', plus the immediate return value 'job_id'. That clearly separates it from voicememos_transcribe_status and voicememos_read, though no sibling is named explicitly.

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

Usage Guidelines3/5

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

The Args block implies two selection modes (explicit memo ids vs. since/until date range) and flags redo for re-transcription, which gives usable context. However, it never says when to prefer this over alternatives, nor does it point to voicememos_transcribe_status for polling the returned job_id.

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

voicememos_transcribe_statusA

Progress of a transcription job, or the 10 most recent jobs when job_id is omitted.

NameRequiredDescriptionDefault
job_idNo

TDQS

A3.6/5.0
Behavior3/5

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

No annotations exist, so the description carries the full burden. It does disclose a real behavioral trait beyond the name — the default of returning the 10 most recent jobs when job_id is omitted — but says nothing about read-only nature, what 'progress' values look like, or whether terminal states (completed/failed) are distinguishable.

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

Conciseness5/5

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

One sentence, front-loaded with the primary mode and finishing with the conditional fallback. Nothing is wasted and the branching condition is stated precisely.

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

Completeness3/5

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

For a single optional-param read tool this covers both invocation modes, but with no output schema and no annotations, an agent still cannot tell what a 'progress' response contains or how to detect completion — the key question for a status tool.

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

Parameters4/5

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

Schema description coverage is 0%, so the description must compensate for the single job_id parameter, and it does: it explains the omission case and the result-set cap. It does not describe the expected job_id format or where an agent obtains one, leaving a small gap.

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

Purpose4/5

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

Names the resource ('transcription job') and the information returned ('progress'), and the fallback behavior makes the dual mode explicit. It does not reference the sibling voicememos_transcribe, which submits jobs, so the agent must infer the pairing itself.

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

Usage Guidelines3/5

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

The dual-mode sentence implies you call it with a job_id to poll progress and without one to list recent jobs, but there is no explicit when-to-use guidance, no note that it should be called after voicememos_transcribe, and no mention of a sibling for other listing needs.

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

voicememos_voiceprintA

Recognise the owner's voice with a local voiceprint.

Args: action: 'status' (enrollment state, thresholds and suggested enrollment memos), 'enroll' (build the voiceprint from memos where only the owner speaks), 'identify' (apply it to already transcribed memos), 'add_other' (store a known other voice, e.g. a relative who sounds similar, from one speaker of one memo; it is never shown by name, it only prevents mistaking that person for the owner) or 'remove_other' (by name). memos: memo ids for 'enroll' (2+, ideally 4-6 from different years), 'identify', or one memo for 'add_other'. since: for 'identify': memos recorded on or after this date (YYYY-MM-DD). until: for 'identify': memos recorded on or before this date (YYYY-MM-DD). name: the owner's name for 'enroll' (default from config); the other person's name for 'add_other' / 'remove_other'. speaker: for 'add_other' in a multi-speaker memo: the speaker label (S1, S2, ...).

NameRequiredDescriptionDefault
nameNo
memosNo
sinceNo
untilNo
actionNostatus
speakerNo

TDQS

A4.3/5.0
Behavior4/5

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

With no annotations, the description must carry behavioral disclosure, and it does disclose meaningful traits: processing is local, the other-voice entry is 'never shown by name' (a privacy/semantics guarantee), and name defaults from config. It stops short of saying what enrollment persists, what each action returns, or how failures are reported — notable gaps for a state-mutating action set.

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

Conciseness4/5

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

The one-line purpose is front-loaded and the Args block is organized rather than rambling; every clause carries actionable detail. It is slightly verbose in the parentheticals ('e.g. a relative who sounds similar'), but no sentence is pure filler.

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

Completeness3/5

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

Six parameters, no annotations, and no output schema means the description is the only source of truth, and while parameters are fully explained, the return shape of 'status' and 'identify' is only hinted at ('enrollment state, thresholds and suggested enrollment memos'). An agent can invoke it correctly but cannot predict what comes back or what errors to expect.

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

Parameters5/5

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

Schema coverage is 0%, so the description does all the work, and all six parameters are documented with per-action scope: 'memos' means different things for enroll/identify/add_other, 'since'/'until' are restricted to 'identify' with a YYYY-MM-DD format, and 'name'/'speaker' are disambiguated by action. This is exactly the compensation a 0% coverage schema requires.

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

Purpose4/5

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

Opens with a specific verb and resource: 'Recognise the owner's voice with a local voiceprint,' and the Args block enumerates five mutually exclusive actions, which frames the tool's full scope. It doesn't explicitly name or contrast with siblings (voicememos_transcribe, voicememos_second_read), but the voiceprint domain is distinctive enough that confusion is unlikely.

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

Usage Guidelines5/5

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

Each action carries its own when-to-use condition: 'enroll' requires memos where only the owner speaks, 'identify' applies to already transcribed memos, 'add_other' exists specifically to prevent mistaking a similar-sounding relative for the owner. It even specifies data thresholds (2+ memos, ideally 4-6 from different years) and that 'speaker' is only needed for multi-speaker memos, leaving little to inference.

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

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 10 tool updatesv0.6.6
    • First observedvoicememos_compare_readers
    • First observedvoicememos_list
    • First observedvoicememos_markers
    • First observedvoicememos_read
    • First observedvoicememos_search
    • First observedvoicememos_second_read
    • First observedvoicememos_status
    • First observedvoicememos_transcribe
    • First observedvoicememos_transcribe_status
    • First observedvoicememos_voiceprint

TDQS

A3.7/5.0

Scored across 10 tools

Disambiguation4/5

Most tools have clearly distinct purposes: listing, reading, searching, marker extraction, transcription, job status, comparison, and voiceprint operations are separated by resource and action. The only mild ambiguity is between voicememos_status and voicememos_transcribe_status, though the descriptions make library status vs. job progress clear.

Naming Consistency4/5

All tools use the same voicememos_ prefix and snake_case style, making the set predictable to scan. There is minor variation between verb-like names (list, read, search, transcribe) and noun-like names (status, markers, voiceprint), but the convention remains readable and consistent overall.

Tool Count5/5

Ten tools is a well-scoped size for a domain covering memo retrieval, transcription workflows, search, markers, second-reader comparison, and voiceprint handling. Each tool earns its place without obvious redundancy or bloat.

Completeness4/5

The tool surface covers the core lifecycle well: listing and reading memos, searching, extracting markers, queuing transcription, checking job progress, running a second reading, comparing readers, and managing voiceprints. Minor gaps exist around memo management such as deleting, renaming, or exporting memos, but these are not central to the apparent transcription-analysis purpose.

Maintenance

ActivityMaintained
ResponsivenessUnresponsive

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables read-first interaction with Apple Voice Memos: search transcripts, review action candidates, mark reviewed, prepare tasks for Codex, and render digests.
    1
    Apache 2.0
  • A
    license
    Not graded
    quality
    A
    maintenance
    Exposes local, fully offline transcription with speaker diarization, voice-based speaker relabeling, environment diagnostics, and read-only workspace search as MCP tools for clients such as Claude Code and Claude Desktop. All audio, text, and voice embeddings stay on the user's Apple Silicon Mac, with no accounts, API keys, or cloud calls.
    2,051 PyPI
    9
    MIT