Skip to main content

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_listening finishes
  • 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 small model 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_listening only works while the server is idle
  • stop_listening only works for the currently active session id
  • stop_listening returns the final transcript directly
  • audio is buffered in memory only for the active session

Tool contract

The MCP surface exposes exactly four tools:

  1. list_microphone_devices
  2. start_listening
  3. stop_listening
  4. get_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_argument
  • invalid_state
  • no_active_session
  • session_mismatch
  • runtime_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
  • id is the value to pass back into start_listening(device_id=...)
  • is_default reflects the current default input device if one is available

start_listening

Arguments:

  • device_id: int | null = null
  • sample_rate: int | null = null

Behavior:

  • if device_id is omitted, the server tries the default input device, then falls back to the first available input device
  • if sample_rate is 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_argument if device_id is negative or sample_rate is not a positive integer
  • invalid_state if a session is already recording or transcribing
  • runtime_failure for 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 int16 PCM 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_argument if session_id is empty
  • no_active_session if nothing is currently recording
  • session_mismatch if the provided session id does not match the active one
  • invalid_state if the server is not currently in the recording state
  • runtime_failure if 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

  1. Call list_microphone_devices to inspect available inputs.
  2. Call start_listening with an optional device_id and optional sample_rate.
  3. Wait while the user speaks.
  4. Call stop_listening with the returned session_id.
  5. 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_devices returns an empty devices list
  • start_listening fails 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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

speaktome_mcp-0.1.0.tar.gz (99.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

speaktome_mcp-0.1.0-py3-none-any.whl (17.1 kB view details)

Uploaded Python 3

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

Hashes for speaktome_mcp-0.1.0.tar.gz
Algorithm Hash digest
SHA256 0bd067228df85bad9e2b453dd556e19e865f4400c79483265b58049939b20309
MD5 a4bba5378887f061487f3a5e182876f7
BLAKE2b-256 5195d0ffae51286a7cfe960b80b3ebc441c68948541e3f3a72c480da9127d3aa

See more details on using hashes here.

Provenance

The following attestation bundles were made for speaktome_mcp-0.1.0.tar.gz:

Publisher: release.yml on alma3lol/SpeakToMeMCP

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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

Hashes for speaktome_mcp-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b67200a07fb069e0a32a867de70e9c215524286d4bd51ffd43105afd0a786af0
MD5 43c3358dc3cf7668a058312f8e27a350
BLAKE2b-256 8472a3a739dbbc3aaaeb738ccfa79f3ca087fed15b05d664bc8d4e7d9201b527

See more details on using hashes here.

Provenance

The following attestation bundles were made for speaktome_mcp-0.1.0-py3-none-any.whl:

Publisher: release.yml on alma3lol/SpeakToMeMCP

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page