Local stdio MCP scaffold for microphone-to-whisper transcription
Project description
SpeakToMe MCP
SpeakToMe MCP is a local Python MCP server for Linux. It records from a microphone on the same machine, transcribes the captured audio with a local faster-whisper small model, and returns the finished transcript to an MCP host over stdio.
Scope
- Linux only for v1
- stdio transport only
- local microphone capture through
sounddevice - local transcription through
faster-whisper - manual start and stop flow only
- final transcript returned when
stop_listeningfinishes - one active in-memory session at a time
Prerequisites
You need:
- Linux
- Python 3.11 or newer
- a working microphone input device
- system audio libraries required by
sounddevice, usually PortAudio plus ALSA or PipeWire user-space packages on Linux
If you want the uv workflow, install uv. If sounddevice cannot open devices, install the PortAudio runtime or development package used by your distro, then confirm your normal desktop audio stack is working.
Install
Install from PyPI
pip install speaktome-mcp
Install from GitHub
pip install git+https://github.com/alma3lol/SpeakToMeMCP.git
Install from local source or an unpacked source archive
Download the repository source, or unpack a release source archive, then run:
pip install .
Install a development environment with uv
uv sync --locked --all-extras --dev
Run and verify the CLI
Installed console script:
speaktome-mcp --help
Start the server with the installed console script:
speaktome-mcp
Module entrypoint fallback:
python -m speaktome_mcp --help
The server only supports stdio. Running speaktome-mcp without extra flags starts the stdio MCP server.
MCP host configuration
This server is meant to be launched by an MCP host that can start a stdio process.
Example using the installed console script
{
"command": "speaktome-mcp",
"args": []
}
Example using a local uv-managed checkout
{
"command": "uv",
"args": ["run", "speaktome-mcp"]
}
Example using the module entrypoint
{
"command": "python",
"args": ["-m", "speaktome_mcp"]
}
The host owns process startup and shutdown. SpeakToMe MCP does not expose a separate network service. It stays in a local stdio process and returns completed tool responses to the host.
Startup behavior and first run expectations
The server eagerly loads the transcription backend during startup instead of waiting for the first tool call.
What that means in practice:
- startup can take longer than a minimal scaffold because the local Whisper model is prepared before the server reports ready
- first run may take noticeably longer if the
smallmodel is not already cached locally - first-run model preparation or download may require network access to obtain model assets
- model load failures happen at startup, not halfway through a recording session
The runtime transcription backend is the local faster-whisper small model.
Recording lifecycle
The server enforces one active session at a time:
idle -> recording -> transcribing -> idle
Important behavior:
start_listeningonly works while the server isidlestop_listeningonly works for the currently active session idstop_listeningreturns the final transcript directly- audio is buffered in memory only for the active session
Tool contract
The MCP surface exposes exactly four tools:
list_microphone_devicesstart_listeningstop_listeningget_server_status
All tools return a structured envelope.
Success shape:
{
"ok": true,
"tool": "tool_name",
"data": {}
}
Error shape:
{
"ok": false,
"tool": "tool_name",
"error": {
"code": "error_code",
"message": "human readable message",
"details": {}
}
}
Known error codes used by the contract:
invalid_argumentinvalid_stateno_active_sessionsession_mismatchruntime_failure
list_microphone_devices
Arguments: none
Success data:
{
"devices": [
{
"id": 0,
"name": "Built-in Microphone",
"max_input_channels": 1,
"default_sample_rate": 48000,
"is_default": true
}
]
}
Notes:
- only input-capable devices are listed
idis the value to pass back intostart_listening(device_id=...)is_defaultreflects the current default input device if one is available
start_listening
Arguments:
device_id: int | null = nullsample_rate: int | null = null
Behavior:
- if
device_idis omitted, the server tries the default input device, then falls back to the first available input device - if
sample_rateis omitted, the selected device's default sample rate is used - starts one active in-memory recording session and returns a generated
session_id
Success data:
{
"session_id": "2ac2d8b7-7d88-4c1c-a6ab-2f2a4ecf97e6",
"device_id": 0,
"sample_rate": 48000,
"state": "recording"
}
Common contract failures:
invalid_argumentifdevice_idis negative orsample_rateis not a positive integerinvalid_stateif a session is already recording or transcribingruntime_failurefor device open failures and other runtime backend errors
stop_listening
Arguments:
session_id: str
Behavior:
- validates that the requested session matches the active recording
- stops capture
- converts the captured mono
int16PCM bytes into an in-memory WAV stream for transcription - runs one local transcription pass
- returns the transcript directly in the tool response
Success data:
{
"session_id": "2ac2d8b7-7d88-4c1c-a6ab-2f2a4ecf97e6",
"transcript": "hello from whisper",
"state": "idle"
}
Common contract failures:
invalid_argumentifsession_idis emptyno_active_sessionif nothing is currently recordingsession_mismatchif the provided session id does not match the active oneinvalid_stateif the server is not currently in therecordingstateruntime_failureif audio stop or transcription fails
get_server_status
Arguments: none
Success data:
{
"state": "idle",
"active_session_id": null
}
state is one of idle, recording, or transcribing.
Practical usage flow
- Call
list_microphone_devicesto inspect available inputs. - Call
start_listeningwith an optionaldevice_idand optionalsample_rate. - Wait while the user speaks.
- Call
stop_listeningwith the returnedsession_id. - Read the final transcript from
data.transcript.
Development
Create a local development environment:
uv sync --locked --all-extras --dev
Run the project from the checkout:
uv run speaktome-mcp
Check the module entrypoint from the checkout:
uv run python -m speaktome_mcp --help
Testing
Run the test suite with:
uv run pytest -q
Privacy and data handling
- microphone audio is captured locally on the Linux machine running the server
- transcription is performed locally with
faster-whisper - the project does not use a cloud transcription API
- audio for the active session is buffered in memory only while that session is running
- the current implementation does not intentionally persist active-session audio or transcripts to disk
- first-run model preparation or download may contact model distribution infrastructure so the required model assets can be cached locally
You should still treat the machine, the MCP host, and any host-side logs as part of your privacy boundary. A host application may log tool calls or transcript results even though this server itself keeps only in-memory active-session buffers.
Troubleshooting
No microphone device available
Symptoms:
list_microphone_devicesreturns an emptydevicesliststart_listeningfails because no usable input device is available
What to check:
- confirm the microphone is connected and recognized by Linux
- confirm the device is exposed to the same user session that launches the MCP host
- confirm your Linux audio stack is installed and running
PortAudio or audio backend problems
Symptoms:
- device listing fails
- recording start fails with a
runtime_failure - the underlying error mentions PortAudio, ALSA, PipeWire, or device open failures
What to check:
- install the PortAudio packages used by your distro
- confirm ALSA or PipeWire is available in the same user session that launches the MCP host
- if the MCP host runs inside a container, VM, or sandbox, confirm the microphone device is actually passed through
Microphone permission denied
Symptoms:
- device listing or recording start fails with a
runtime_failure - the underlying reason mentions permission denial
What to check:
- allow microphone access in your desktop or sandbox environment if one is in use
- retry from the same Linux user session that can normally access the microphone
Model startup or load failure
Symptoms:
- the server process exits during startup instead of staying available to the host
- startup errors mention the faster-whisper model failing to load
What to check:
- run your install command again to confirm the Python environment is complete
- make sure the machine can complete the first-run model preparation step
- if the model is not already cached, confirm temporary network access is available so model assets can be fetched
- retry after confirming the local Python environment can import
faster_whisper
Because the model is loaded eagerly, these failures happen before the first recording starts.
Release and download options
You can use this project in several public distribution forms:
- install the published package with
pip install speaktome-mcp - install directly from GitHub with
pip install git+https://github.com/alma3lol/SpeakToMeMCP.git - download the repository source or a GitHub release source archive, unpack it, then run
pip install .
If you want to inspect a tagged release before installing, check the GitHub Releases page for source archives and packaged artifacts.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file speaktome_mcp-0.1.0.tar.gz.
File metadata
- Download URL: speaktome_mcp-0.1.0.tar.gz
- Upload date:
- Size: 99.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0bd067228df85bad9e2b453dd556e19e865f4400c79483265b58049939b20309
|
|
| MD5 |
a4bba5378887f061487f3a5e182876f7
|
|
| BLAKE2b-256 |
5195d0ffae51286a7cfe960b80b3ebc441c68948541e3f3a72c480da9127d3aa
|
Provenance
The following attestation bundles were made for speaktome_mcp-0.1.0.tar.gz:
Publisher:
release.yml on alma3lol/SpeakToMeMCP
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
speaktome_mcp-0.1.0.tar.gz -
Subject digest:
0bd067228df85bad9e2b453dd556e19e865f4400c79483265b58049939b20309 - Sigstore transparency entry: 2032449391
- Sigstore integration time:
-
Permalink:
alma3lol/SpeakToMeMCP@62cb8c99f248938778d27accc6f820ba8afe6621 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/alma3lol
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@62cb8c99f248938778d27accc6f820ba8afe6621 -
Trigger Event:
push
-
Statement type:
File details
Details for the file speaktome_mcp-0.1.0-py3-none-any.whl.
File metadata
- Download URL: speaktome_mcp-0.1.0-py3-none-any.whl
- Upload date:
- Size: 17.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b67200a07fb069e0a32a867de70e9c215524286d4bd51ffd43105afd0a786af0
|
|
| MD5 |
43c3358dc3cf7668a058312f8e27a350
|
|
| BLAKE2b-256 |
8472a3a739dbbc3aaaeb738ccfa79f3ca087fed15b05d664bc8d4e7d9201b527
|
Provenance
The following attestation bundles were made for speaktome_mcp-0.1.0-py3-none-any.whl:
Publisher:
release.yml on alma3lol/SpeakToMeMCP
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
speaktome_mcp-0.1.0-py3-none-any.whl -
Subject digest:
b67200a07fb069e0a32a867de70e9c215524286d4bd51ffd43105afd0a786af0 - Sigstore transparency entry: 2032449631
- Sigstore integration time:
-
Permalink:
alma3lol/SpeakToMeMCP@62cb8c99f248938778d27accc6f820ba8afe6621 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/alma3lol
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@62cb8c99f248938778d27accc6f820ba8afe6621 -
Trigger Event:
push
-
Statement type: