Releases: docdyhr/macwhisper-mcp-server
Releases · docdyhr/macwhisper-mcp-server
Release list
v1.2.0
Added
transcribe_audioaccepts an optionallanguageargument (ISO 639-1 code,
or"auto"), passed through as--languagetomw.MACWHISPER_LANGUAGE_DEFAULTSenv var maps directories to a default
language (e.g.~/Desktop/DK=da) — files in a matching directory (or its
subdirectories) get--languageautomatically, most-specific match wins.
An explicitlanguageargument always overrides the directory default.
Applies to bothtranscribe_audioand watch-folder transcriptions.- New
engineargument ontranscribe_audio("macwhisper"default, or
"whisper-cpp") — an independent transcription backend using a standalone
whisper-clibinary that does not go through MacWhisper at all. New
MACWHISPER_WHISPERCPP_BINARY/MACWHISPER_WHISPERCPP_MODEL_DIRenv vars.
v1 supports.wav/.mp3/.flacinput only; see README for setup and
limitations.list_models()now also lists whisper-cpp models when
MACWHISPER_WHISPERCPP_MODEL_DIRis configured.
Changed
transcribe.pynow validates the request and dispatches to a new
engines.pymodule (MacWhisper and whisper-cpp backends); behavior of the
MacWhisper path is unchanged. Test mock target forsubprocess.Popenmoved
frommacwhisper_mcp.transcribetomacwhisper_mcp.enginesaccordingly.- The 10 MB output cap is now a single shared
MAX_OUTPUT_BYTESconstant in
config.py, imported bytranscribe.pyandwatcher.pyso the two paths
can never enforce different limits.
Fixed
cancel_transcriptionno longer raisesIndexError(surfaced to the client
as an error) when the running transcription finishes and clears the proc
list in the gap between cancel's non-empty check and its subscript. Cancel
now uses a single atomic subscript and degrades to "no transcription
running" instead.__version__is now read from the installed distribution metadata instead of
a hardcoded literal, so it can no longer drift frompyproject.tomlon
semantic-release bumps.start_watchnow rejects a watch session when the "done" directory falls
outside the configured allow-list (previously it silently wrote there). The
done directory is overridable via the newMACWHISPER_WATCH_DONE_DIRenv
var; the default remains<incoming>/../done.
v1.1.1
What's changed
Changed
- fastmcp bumped 3.2.4 → 3.4.2. No API changes affect this server; the bump picks up upstream bug fixes and performance improvements.
Fixed
- Access-denied error messages now include the allow-listed paths so the LLM (and user) understand why a path was rejected without requiring a separate `list_allowed_paths()` call.
- `transcribe_audio` tool description clarifies that files must be on the local filesystem, not in Claude's container — suppresses a common LLM fallback.
- Disabled FastMCP's built-in update-check nag on server startup (`FASTMCP_CHECK_FOR_UPDATES=off` is no longer required in the Claude Desktop config).
- CodeQL CI workflow now triggers on the correct branch (`main`).
Documentation
- Added Homebrew tap as the recommended install method:
```bash
brew tap docdyhr/tap
brew install docdyhr/tap/macwhisper-mcp-server
``` - Claude Desktop config simplified: `"command": "macwhisper-mcp"` (no hardcoded venv path) when installed via Homebrew or `pip install`.
- MIT `LICENSE` file added to repo root.
Full changelog: https://github.com/docdyhr/macwhisper-mcp-server/blob/main/CHANGELOG.md
v1.1.0
Added
list_models()MCP tool — runsmw models listand returns installed
MacWhisper models with display names; the active model is marked[active].
Model IDs returned can be passed directly totranscribe_audio(model=…).persistparameter ontranscribe_audio— passpersist=trueto save the
transcription to MacWhisper's history database (mw --persist).tests/test_server.py— 13 tests covering all 8 MCP tools includinglist_models
andpersist, concurrency lock, lock-release-on-exception, and cancel.
Fixed
watcher.py: apply 10 MB output size cap to watcher transcriptions, matching
the existing cap intranscribe.py.publish.yml: publish job now requires tests to pass (newtestjob thatbuild
depends on), preventing broken releases viaworkflow_dispatch.ci.yml: correctedcache-dependency-pathfrom stalerequirements*.txtto
pyproject.toml.pyproject.toml: narrowedrequires-pythonfrom>=3.10to>=3.13to match
the Python version actually tested and supported..gitignore: addedserver.json(MCP Registry publish artifact).
Documentation
- README: added Homebrew install path,
mw versionverify command, updated tools
table withlist_modelsandpersist. - CLAUDE.md: updated status, layout, known quirks, and mock path conventions to
reflect current codebase.
v1.0.0 — First stable release
First stable public release. All five development phases complete: MVP → hardening
→ structured output → ergonomics → security. 7 MCP tools, 33 tests, fully local.
Security
- Resolve-before-validate in
transcribe(). Path symlinks are now fully resolved
before extension and allow-list checks, closing a TOCTOU race where a symlink could
change between validation and CLI invocation. - Null-byte rejection. Paths containing
\x00are rejected immediately in
transcribe()before any filesystem access. - Model identifier sanitization. The
modelparameter is now validated against
[a-zA-Z0-9_:.-]+before being passed to the CLI, preventing argument injection. - No allow-list leakage in errors. "Access denied" messages no longer include the
full allow-list; this was an information-disclosure issue. start_watch()folder validation. The folder path is now checked against the
allow-list before starting the watcher; previously any directory could be watched.- Symlink rejection in watcher.
FolderWatcher._scan()skips symbolic links;
a symlink insideincoming/pointing outside the allow-list could otherwise cause
MacWhisper to read arbitrary files. MACWHISPER_LOG_PATHmust be under$HOME.Config.from_env()rejects log
paths outside the user's home directory to prevent log-file hijacking.- Output size cap.
transcribe()raisesTranscribeErrorifmwstdout exceeds
10 MB, guarding against runaway output consuming memory.