Skip to main content
Glama
YuvrajSinghBhadoria2

OpenCode Voice MCP Server

🎀 OpenCode Voice MCP Server

Voice Input for AI Coding Assistants

License: MIT npm version GitHub stars GitHub issues MCP Compatible

Speak your prompts. No typing required.

Installation β€’ Quick Start β€’ Tools β€’ Configuration β€’ Architecture β€’ Contributing


✨ Features

Feature

Description

🎀 Voice Recording

Record audio from microphone with configurable duration

πŸ—£οΈ Speech-to-Text

Transcribe using local Whisper model (100% offline)

⌨️ Auto-Typing

Type transcribed text at cursor position

πŸ”’ Privacy First

No cloud API β€” audio never leaves your machine

🌍 Multi-Language

Support for 99+ languages via Whisper

πŸ”Œ MCP Standard

Works with OpenCode, Claude Code, Cursor, and more

Related MCP server: Claude Voice Commands

πŸ“¦ Installation

# Install globally
npm install -g @yuvarjbhado/voice-mcp

# Or use with npx (no install required)
npx @yuvarjbhado/voice-mcp

Prerequisites

# Install recording tool
brew install sox

# Install transcription engine
pip install faster-whisper
# Install recording tool
sudo apt install sox

# Install transcription engine
pip install faster-whisper
# Install FFmpeg (via scoop)
scoop install ffmpeg

# Install transcription engine
pip install faster-whisper

πŸš€ Quick Start

Step 1: Configure MCP Server

Add to your MCP config file:

Tool

Config Location

OpenCode

~/.config/opencode/config.json

Claude Code

~/.claude/claude_desktop_config.json

Cursor

~/.cursor/mcp.json

OpenCode (use mcp key):

{
  "mcp": {
    "voice": {
      "command": "npx",
      "args": ["-y", "@yuvarjbhado/voice-mcp"]
    }
  }
}

Claude Desktop / Cursor (use mcpServers key):

{
  "mcpServers": {
    "voice": {
      "command": "npx",
      "args": ["-y", "@yuvarjbhado/voice-mcp"]
    }
  }
}

Step 2: Restart Your Tool

Restart OpenCode, Claude Code, or Cursor to load the MCP server.

Step 3: Use Voice Input

@voice voice_transcribe
@voice voice_type
@voice voice_status

πŸ› οΈ Tools

voice_transcribe

Record audio from microphone and transcribe to text.

{
  "name": "voice_transcribe",
  "arguments": {
    "duration": 10,
    "language": "en"
  }
}

Parameter

Type

Default

Description

duration

number

10

Recording duration in seconds

language

string

auto

Language code (e.g., en, es, fr)

Returns: Transcribed text as string.


voice_type

Record audio, transcribe to text, and type it at the cursor position.

{
  "name": "voice_type",
  "arguments": {
    "duration": 10,
    "language": "en"
  }
}

Parameter

Type

Default

Description

duration

number

10

Recording duration in seconds

language

string

auto

Language code

Returns: Confirmation message with typed text.


voice_status

Check if voice recording and transcription are available.

{
  "name": "voice_status",
  "arguments": {}
}

Returns:

{
  "recording": "rec",
  "transcription": "faster-whisper (local)",
  "platform": "darwin",
  "ready": true
}

βš™οΈ Configuration

Environment Variables

Variable

Description

Default

WHISPER_MODEL

Whisper model size

base

WHISPER_DEVICE

Device to use (cpu, cuda, auto)

auto

WHISPER_COMPUTE

Compute type (int8, float16, float32)

int8

Model Sizes

Model

Size

Speed

Accuracy

VRAM

tiny

~75MB

⚑⚑⚑⚑

⭐⭐

~1GB

base

~150MB

⚑⚑⚑

⭐⭐⭐

~1GB

small

~500MB

⚑⚑

⭐⭐⭐⭐

~2GB

medium

~1.5GB

⚑

⭐⭐⭐⭐⭐

~5GB

large-v3

~3GB

🐌

⭐⭐⭐⭐⭐

~10GB

Recommendation: Use base for best balance of speed and accuracy.

πŸ—οΈ Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                        MCP Client                               β”‚
β”‚                  (OpenCode / Claude Code / Cursor)              β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                           β”‚ JSON-RPC
                           β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    Voice MCP Server                             β”‚
β”‚                     (Node.js)                                   β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”‚
β”‚  β”‚ voice_record β”‚  β”‚voice_transcribeβ”‚ β”‚  voice_type  β”‚         β”‚
β”‚  β”‚    Tool      β”‚  β”‚     Tool     β”‚  β”‚    Tool      β”‚         β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜         β”‚
β”‚         β”‚                 β”‚                 β”‚                   β”‚
β”‚         β–Ό                 β–Ό                 β–Ό                   β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”       β”‚
β”‚  β”‚              Audio Recording Layer                   β”‚       β”‚
β”‚  β”‚         (sox / ffmpeg / macOS rec)                  β”‚       β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜       β”‚
β”‚                            β”‚                                    β”‚
β”‚                            β–Ό                                    β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”       β”‚
β”‚  β”‚           Transcription Engine                      β”‚       β”‚
β”‚  β”‚      (faster-whisper / OpenAI API)                  β”‚       β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜       β”‚
β”‚                            β”‚                                    β”‚
β”‚                            β–Ό                                    β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”       β”‚
β”‚  β”‚              Output Layer                           β”‚       β”‚
β”‚  β”‚    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”        β”‚       β”‚
β”‚  β”‚    β”‚ Return Text β”‚  β”‚ Type at Cursor      β”‚        β”‚       β”‚
β”‚  β”‚    β”‚   (MCP)     β”‚  β”‚ (osascript/xdotool) β”‚        β”‚       β”‚
β”‚  β”‚    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜        β”‚       β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜       β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Data Flow

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  User   │───▢│  Micro- │───▢│  Whisper    │───▢│  Text   β”‚
β”‚  Speaks β”‚    β”‚  phone  β”‚    β”‚  Transcribe β”‚    β”‚  Output β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
     β”‚              β”‚               β”‚                β”‚
     β”‚              β”‚               β”‚                β”‚
     β–Ό              β–Ό               β–Ό                β–Ό
  "Hello      Records 16kHz    Processes with    Returns text
   world"     mono audio      base model        or types it

πŸ”§ Development

Setup

# Clone repository
git clone https://github.com/YuvrajSinghBhadoria2/opencode-voice-mcp.git
cd opencode-voice-mcp

# Install dependencies
npm install

# Build
npm run build

# Run in development
npm run dev

Project Structure

opencode-voice-mcp/
β”œβ”€β”€ src/
β”‚   └── index.ts          # MCP server implementation
β”œβ”€β”€ dist/
β”‚   └── index.js          # Compiled output
β”œβ”€β”€ package.json          # Package configuration
β”œβ”€β”€ tsconfig.json         # TypeScript config
β”œβ”€β”€ build.sh              # Build script
└── publish.sh            # npm publish script

Available Scripts

Command

Description

npm run build

Compile TypeScript to JavaScript

npm run dev

Run in development mode with tsx

npm run start

Run compiled server

./publish.sh

Build and publish to npm

🀝 Contributing

Contributions are welcome! Please follow these steps:

  1. Fork the repository

  2. Create a feature branch (git checkout -b feat/amazing-feature)

  3. Commit your changes (git commit -m 'feat: add amazing feature')

  4. Push to the branch (git push origin feat/amazing-feature)

  5. Open a Pull Request

Development Guidelines

  • Follow TypeScript best practices

  • Add tests for new features

  • Update documentation as needed

  • Use conventional commit messages

πŸ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.

πŸ™ Acknowledgments


Built with ❀️ for the developer community

Report Bug β€’ Request Feature β€’ Discussions

Available Tools

3 tools
voice_statusA

Check if voice recording and transcription are available.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A3.5/5.0
Behavior2/5

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

With no annotations provided, the description carries the full burden of behavioral disclosure. 'Check' implies a read-only operation, but it does not specify side effects, output format, or error behavior. The lack of detail about what the tool returns or how it behaves is a significant gap.

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?

The description is a single, concise sentence that directly states the tool's function. It contains no unnecessary words or repetition, making it efficient and front-loaded.

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?

Given the tool's simplicity (0 parameters, no output schema), the description is adequate but has gaps. It does not explain what 'available' means or what format the result takes, which is left to the agent to infer. With no annotations or output schema, more detail on the return value would improve completeness.

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 input schema is empty, so there are no parameters to explain. Baseline for 0 params is 4, and the description is not required to add parameter details. The description adds meaning beyond the schema by clarifying the tool's purpose.

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 clearly states the tool's function: checking availability of voice recording and transcription. The verb 'check' and the resource 'voice recording and transcription' are specific, and the purpose is distinct from sibling tools like voice_transcribe and voice_type, which perform actions rather than check status.

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?

The description does not provide any guidance on when to use this tool versus alternatives. It does not mention prerequisites, context, or exclusions. The sibling tool names imply a distinction, but the description itself offers no usage direction.

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

voice_transcribeA

Record audio from microphone and transcribe to text. Returns the transcribed text.

ParametersJSON Schema
NameRequiredDescriptionDefault
durationNoRecording duration in seconds (default: 10)
languageNoLanguage code for transcription (e.g., 'en', 'es', 'fr'). Default: auto-detect

TDQS

A3.7/5.0
Behavior2/5

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

No annotations are provided, so the description must carry the transparency burden. It discloses only the primary behavior (recording and transcribing) but omits any prerequisites, such as microphone permissions, whether audio is stored, error handling, or potential side effects. This is a significant gap for a tool that records audio.

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?

The description is concise, consisting of two short sentences: 'Record audio from microphone and transcribe to text. Returns the transcribed text.' No unnecessary information is included, and the main action is front-loaded.

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?

The tool has only two optional parameters and no output schema, so the description is mostly adequate. However, it lacks additional context that would be valuable, such as recording duration defaults, language auto-detection behavior, or any limitations. The schema covers parameter details, but the description remains minimal for a tool with no annotations.

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

Parameters3/5

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

The input schema provides descriptions for both parameters (duration and language), achieving 100% schema description coverage. The description adds no additional meaning about these parameters or their behavior, so the baseline score of 3 is appropriate.

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 clearly states the action: 'Record audio from microphone and transcribe to text.' It specifies the verb (record/transcribe), resource (microphone), and output (text). This distinguishes it from sibling tools 'voice_status' and 'voice_type', which likely handle different voice-related functions.

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

Usage Guidelines4/5

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

The description implies a clear usage context: when you need audio transcribed. It does not explicitly mention alternatives or exclusions, but the action is straightforward enough that the use case is evident. Since it says 'Record audio from microphone and transcribe to text,' there is no ambiguity about when to use it.

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

voice_typeA

Record audio, transcribe to text, and type it at the cursor position in the active window.

ParametersJSON Schema
NameRequiredDescriptionDefault
durationNoRecording duration in seconds (default: 10)
languageNoLanguage code for transcription

TDQS

A3.7/5.0
Behavior3/5

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

No annotations are provided, so the description must carry the burden. It discloses the mutating action by stating it types at the cursor position, but it lacks context about prerequisites like microphone access, failure modes, or side effects beyond typing. This is adequate but not comprehensive.

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?

The description is a single, tightly crafted sentence that efficiently communicates the entire workflow. It is front-loaded with the core action and contains no redundant wording.

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 annotations and no output schema, the description should explain return values and operational requirements. It does not mention what the tool returns after typing, nor does it address active-window prerequisites. It covers the main purpose but leaves gaps in resource/return value details.

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

Parameters3/5

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

The input schema already provides full descriptions for both parameters (duration and language), with 100% coverage. The description does not add additional semantic meaning, adhering to the baseline for high schema coverage.

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 verb+resource: 'Record audio, transcribe to text, and type it at the cursor position in the active window.' This clearly differentiates from siblings like voice_transcribe (which only transcribes) and voice_status (which likely reports 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 description implies usage for dictation-to-text insertion but does not explicitly state when to choose this over voice_transcribe or any exclusions. It provides context for what the tool does but not guidance on alternatives, so it stays at the 'implied usage' level.

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. 3 tool updatesv1.0.0
    • First observedvoice_status
    • First observedvoice_transcribe
    • First observedvoice_type

TDQS

A3.7/5.0

Scored across 3 tools

Disambiguation3/5

voice_transcribe and voice_type both perform recording and transcription, differing only in whether the result is typed into the active window. This creates some overlap, though voice_status is clearly distinct. Descriptions clarify the intended use.

Naming Consistency4/5

The voice_ prefix is consistent across all tools, but the suffix alternates between a verb (transcribe, type) and a noun (status), slightly breaking the uniform verb pattern. Overall, the naming is predictable and readable.

Tool Count5/5

With only three tools, the server is tightly scoped to the core voice capture and transcription workflows. Each tool serves a clear purpose, and the count feels appropriate for the narrow domain.

Completeness4/5

The server covers the primary actions of transcribing and typing, plus a status check. Missing optional features like language selection or audio device configuration, but these are not essential to the main workflow.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    C
    maintenance
    Enables natural voice interaction with Claude Code through speech-to-text, supporting wake word activation and multiple backends like Whisper and Google. It allows users to execute commands and control their coding environment hands-free via their microphone.
    2
    -
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables continuous voice conversation with AI coding assistants by locally transcribing speech with Whisper and delivering utterances as text prompts.
    1
    MIT
  • A
    license
    A
    quality
    D
    maintenance
    Local speech-to-text transcription using Microsoft's VibeVoice-ASR model with speaker diarization, enabling audio transcription directly in AI tools like Claude Code, Cursor, and OpenCode.
    3
    2
    MIT