Skip to main content
Glama

Mac Say MCP - TypeScript Edition

MCP Server for text-to-speech using macOS say command, written in TypeScript and built with esbuild.

Features

  • 🎡 Text-to-Speech: Convert text to speech instantly

  • πŸ”Š Audio File Generation: Save TTS as AIFF, WAV, or MP4 files

  • πŸ—£οΈ Voice Management: List and demo system voices

  • βš™οΈ System Info: Get TTS capabilities and configuration

  • πŸš€ TypeScript: Full type safety and modern development experience

  • πŸ“¦ Fast Build: Lightning-fast builds with esbuild

Related MCP server: tts-mcp

Quick Start

Installation

Local Development

# Install dependencies
npm install

# Build the project
npm run build

# Start the server
npm start

Global Installation

# Install globally from npm (when published)
npm install -g mac-say-mcp

# Or install from local directory
npm install -g .

# Use directly
mac-say-mcp

NPM Package Installation

For MCP clients, you can use the npm package directly with npx:

{
  "mcpServers": {
    "mac-say-mcp": {
      "command": "npx",
      "args": ["-y", "mac-say-mcp@latest"],
      "env": {
        "TTS_DEFAULT_VOICE": "Alex",
        "TTS_DEFAULT_RATE": "200"
      }
    }
  }
}

This approach:

  • βœ… Always uses the latest published version

  • βœ… No need for local builds or global installation

  • βœ… Automatic package installation with -y flag

  • βœ… Perfect for CI/CD and shared configurations

Development

# Type checking
npm run typecheck

# Build in watch mode
npm run build:watch

# Development mode (watch + restart)
npm run dev

Available Scripts

  • npm run build - Build the TypeScript code with esbuild

  • npm run build:watch - Build in watch mode for development

  • npm run start - Build and start the MCP server

  • npm run dev - Development mode with auto-rebuild

  • npm run clean - Clean build artifacts

  • npm run typecheck - Run TypeScript type checking

  • npm run prod - Production build with minification

MCP Tools

1. tts_speak

Convert text to speech and play immediately:

{
  "name": "tts_speak",
  "arguments": {
    "text": "Hello, world!",
    "voice": "Alex",
    "rate": 200
  }
}

2. tts_save_audio

Save text-to-speech as audio file:

{
  "name": "tts_save_audio", 
  "arguments": {
    "text": "Hello, world!",
    "filename": "greeting",
    "voice": "Samantha",
    "rate": 180,
    "format": "wav"
  }
}

3. tts_list_voices

List available system voices:

{
  "name": "tts_list_voices",
  "arguments": {
    "language": "en"
  }
}

4. tts_voice_demo

Play a demo with specific voice:

{
  "name": "tts_voice_demo",
  "arguments": {
    "voice": "Victoria",
    "text": "This is a voice demonstration"
  }
}

5. tts_system_info

Get system TTS information:

{
  "name": "tts_system_info",
  "arguments": {}
}

Configuration

Set default voice and rate via environment variables:

TTS_DEFAULT_VOICE=Samantha TTS_DEFAULT_RATE=180 npm start

Or via command line:

node dist/index.js --defaultRate 250

MCP Client Setup

Note: Replace /path/to/mac-say-mcp with the actual path to your project directory. Use pwd in the project directory to get the full path.

Claude Desktop

Add to your claude_desktop_config.json:

{
  "mcpServers": {
    "mac-say-mcp": {
      "command": "node",
      "args": ["/path/to/mac-say-mcp/dist/index.js"],
      "env": {
        "TTS_DEFAULT_VOICE": "Alex",
        "TTS_DEFAULT_RATE": "200"
      }
    }
  }
}

VS Code MCP Extension

{
  "mcp.servers": [
    {
      "name": "mac-say-mcp",
      "command": "npx",
      "args": ["-y", "mac-say-mcp@latest"]
    }
  ]
}

Cursor IDE

Add to your Cursor settings or create a .cursormcp configuration file:

{
  "mcpServers": {
    "mac-say-mcp": {
      "command": "npx",
      "args": ["-y", "mac-say-mcp@latest"],
      "env": {
        "TTS_DEFAULT_VOICE": "Alex",
        "TTS_DEFAULT_RATE": "200"
      }
    }
  }
}

Alternatively, use the built-in MCP server configuration in Cursor:

  1. Open Cursor Settings

  2. Go to "MCP Servers"

  3. Add a new server:

    • Name: mac-say-mcp

    • Command: npx

    • Args: -y mac-say-mcp@latest

Zencoder

For Zencoder AI assistant integration, add to your MCP configuration:

{
  "servers": {
    "mac-say-mcp": {
      "command": "npx",
      "args": ["-y", "mac-say-mcp@latest"],
      "description": "Text-to-speech server using macOS say command",
      "env": {
        "TTS_DEFAULT_VOICE": "Alex",
        "TTS_DEFAULT_RATE": "200"
      }
    }
  }
}

Development Architecture

Project Structure

mac-say-mcp/
β”œβ”€β”€ src/
β”‚   └── index.ts          # TypeScript source code
β”œβ”€β”€ dist/
β”‚   └── index.js          # Compiled JavaScript (generated)
β”œβ”€β”€ audio/                # Generated audio files
β”œβ”€β”€ tsconfig.json         # TypeScript configuration
β”œβ”€β”€ build.js              # esbuild configuration
└── package.json          # Dependencies and scripts

Type Safety

Full TypeScript support with:

  • Interface definitions for all MCP tools

  • Type guards for runtime parameter validation

  • Strict type checking enabled

  • Modern ES2022 target

Build Process

  • esbuild for fast compilation and bundling

  • External dependencies preserved (MCP SDK)

  • ES Modules output for Node.js compatibility

  • Source maps in development mode

  • Minification in production mode

Audio Formats

Format

Extension

Quality

Size

AIFF

.aiff

High

Large

WAV

.wav

High

Large

MP4

.mp4

Good

Small

Voice Parameters

  • Rate: 50-500 words per minute

  • Voices: System-dependent (174 on typical macOS)

  • Languages: Multiple languages supported

Error Handling

  • Parameter validation with descriptive errors

  • Type-safe error responses

  • Graceful handling of missing voices

  • File system error recovery

Requirements

  • macOS: Required for say command

  • Node.js: 18.0.0 or higher

  • TypeScript: 5.3.0 or higher

  • esbuild: 0.19.0 or higher

Release Management

This project uses automated releases with release-it and conventional changelog generation.

Creating Releases

# Patch release (1.0.0 β†’ 1.0.1) - for bug fixes
npm run release:patch

# Minor release (1.0.0 β†’ 1.1.0) - for new features  
npm run release:minor

# Major release (1.0.0 β†’ 2.0.0) - for breaking changes
npm run release:major

# Test release without publishing
npm run release:dry

# Local testing (no publish/push)
npm run release:local:dry

Changelog Generation

The project automatically generates:

  • CHANGELOG.md from conventional commit messages

  • GitHub Release Notes from the latest changelog entries

# Generate changelog for latest version only
npm run changelog

# Update entire CHANGELOG.md file
npm run changelog:all

Commit Message Format

Use conventional commits for automatic changelog generation:

# Features
git commit -m "feat: add new voice filtering option"

# Bug fixes  
git commit -m "fix: resolve audio file generation error"

# Documentation
git commit -m "docs: update installation instructions"

# Breaking changes
git commit -m "feat!: change TTS API interface"

Release Process

  1. Make changes with conventional commit messages

  2. Run tests and type checking: npm run typecheck

  3. Create release: npm run release:patch (or minor/major)

  4. Automatic steps:

    • Version bump in package.json

    • CHANGELOG.md update

    • Git commit and tag

    • GitHub release with changelog

    • npm package publication

Contributing

  1. Make changes in src/index.ts

  2. Use conventional commit messages

  3. Run npm run typecheck to verify types

  4. Test with npm run build && npm start

  5. Update documentation as needed

License

MIT License - see LICENSE file for details.

Troubleshooting

Build Issues

# Clear build cache
npm run clean
npm run build

Type Errors

# Check TypeScript errors
npm run typecheck

Runtime Issues

# Test say command directly
say -v Alex "Hello world"
say -v "?" # List voices

Audio File Issues

# Check audio directory permissions
ls -la audio/

This TypeScript version provides better development experience with type safety, modern tooling, and fast builds while maintaining full compatibility with the original MCP server functionality.

Available Tools

5 tools
tts_list_voicesA

List all available voices on the system

ParametersJSON Schema
NameRequiredDescriptionDefault
languageNoFilter voices by language (optional)

TDQS

A3.6/5.0
Behavior3/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. The verb 'list' implies a read-only operation, but the description does not mention output format, potential filtering effects, or other behavioral traits. It is minimally transparent but not misleading.

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, direct sentence that wastes no words. Every word contributes to conveying the tool's purpose, making it highly concise and well-structured.

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?

Given the tool's simplicity (one optional parameter, no output schema), the description is nearly complete. It clearly states the action and object, though it omits explicit mention of the return value. For a list operation, the return is obvious enough, so slight incompleteness is acceptable.

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 schema provides 100% coverage for the 'language' parameter with a clear description. The tool description adds no extra meaning about parameters, so the baseline of 3 applies.

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 'List all available voices on the system' uses a specific verb (list) and resource (voices), clearly distinguishing it from siblings like tts_speak (speak text) and tts_save_audio (save audio). It fully answers what the tool does.

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 provides no guidance on when to use this tool versus alternatives or any exclusions. It simply states the function, leaving the agent to infer usage from the name and sibling context.

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

tts_save_audioC

Convert text to speech and save as audio file

ParametersJSON Schema
NameRequiredDescriptionDefault
rateNoSpeaking rate in words per minute (default: 200)
textYesText to convert to speech
voiceNoVoice to use (optional, default: Alex)
formatNoAudio format: aiff, wav, mp4aiff
filenameYesName for the audio file (without extension)

TDQS

C2.9/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 behavioral burden, but it only states the basic action. It fails to disclose that this writes a file to disk, any permissions or limitations, or whether it overwrites existing filesβ€”important for an AI agent to know.

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 with no redundant words. It front-loads the primary action and is appropriately sized for a simple tool, though it could include more detail without losing conciseness.

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

Completeness2/5

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

Despite the schema covering parameters, the description lacks essential context for an agent deciding to invoke this tool. It doesn't explain the output (e.g., confirmed file path), usage scenarios, or caveats like file overwriting. The tool is relatively complex (5 params, no output schema), and the description under-delivers.

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 descriptive text for all five parameters (e.g., 'Speaking rate in words per minute', 'Audio format: aiff, wav, mp4'), so the description adds no additional semantic value beyond what's 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?

The description clearly states the tool's functionβ€”converting text to speech and saving to a fileβ€”which distinguishes it from sibling tools like tts_speak (likely playback) and tts_list_voices. However, it doesn't mention the selectable formats or voice options, which are present in the schema.

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 provides no guidance on when to use this tool versus its siblings (tts_speak, tts_list_voices, etc.). It doesn't specify use cases such as 'when you need a playable file' or 'for audio file archives.'

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

tts_speakA

Convert text to speech and play it immediately

ParametersJSON Schema
NameRequiredDescriptionDefault
rateNoSpeaking rate in words per minute (default: 200)
textYesText to convert to speech
voiceNoVoice to use (optional, default: Alex)

TDQS

A3.6/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. It only states 'play it immediately', omitting details about potential audio output, blocking behavior, errors, or return values. This is insufficient for an agent to anticipate side effects.

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 communicates the essential function without any wasted words. It is perfectly sized for the simplicity of the tool.

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

Completeness2/5

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

Given no annotations, no output schema, and a simple one-line description, the tool lacks critical context such as whether 'play' produces audible output, how the agent will know if the text is too long, or confirmation of completion. The description is minimal and leaves significant gaps for an AI agent to use it correctly.

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 full descriptions for all three parameters, so the baseline is 3. The description adds no additional semantic detail about parameters beyond what the schema already states, like the default voice or rate constraints.

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 ('Convert text to speech') and the immediate behavior ('play it immediately'), which distinguishes it from sibling tools like tts_save_audio. It is specific about both the resource and the scope.

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 usage for immediate playback with 'play it immediately', which provides clear context for when to use the tool. However, it does not explicitly mention alternatives or when not to use it, stopping short of full guidance.

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

tts_system_infoC

Get information about text-to-speech capabilities

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

C2.4/5.0
Behavior1/5

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

No annotations are present, and the description does not disclose any behavioral traits such as whether the call is read-only, what data it returns, or any potential side effects. The agent has no context about what to expect.

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

Conciseness3/5

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

The description is a single short sentence, but it is under-specified. It is not verbose, yet it lacks useful structure or key details that would make it valuable beyond the tool name.

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

Completeness2/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 parameter details, the description is the only source of information. It does not explain what kind of information is returned or how it relates to the operations in sibling tools, leaving a significant gap.

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 has zero parameters, so the schema defines nothing. Per rubric, the baseline for 0 parameters is 4. The description does not need to clarify parameter meaning, though it could describe what 'capabilities' means.

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

Purpose3/5

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

The description uses the verb 'get' and identifies the resource as 'text-to-speech capabilities,' but it is vague about what specific information is provided. It distinguishes from sibling tools (speak, save, list voices) by domain, but does not define the scope of 'capabilities.'

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 offers no guidance on when to use this tool compared to tts_list_voices or other siblings. No mention of prerequisites, use cases, or alternatives.

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

tts_voice_demoA

Play a demo phrase with a specific voice

ParametersJSON Schema
NameRequiredDescriptionDefault
textNoCustom text for demo (optional)Hello, this is a voice demonstration.
voiceYesVoice name to demo

TDQS

A3.6/5.0
Behavior3/5

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

With no annotations, the description carries the burden of explaining behavior. 'Play' makes it clear this is an audio output action, and 'demo phrase' suggests a fixed default. It does not mention optional text behavior, side effects, or return values, but for a simple playback tool this is minimally sufficient.

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, self-contained sentence that immediately conveys the core action. No wasted words and the most important qualifier ('demo phrase') is front-loaded.

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 simple playback tool with a straightforward schema, the description is almost complete. It omits an explanation of default text behavior and whether any audio output is asynchronous, but given the tool's simplicity and sibling context, these gaps are minor.

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 fully covers both parameters with clear descriptions (text defaulting to a demo phrase, voice being the voice name). The description adds no extra parameter meaning, but the schema already provides 100% coverage, so the baseline of 3 applies.

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 uses a specific verb ('Play') and resource ('demo phrase') with a qualifier ('with a specific voice'), clearly indicating the tool's function. It distinguishes from siblings like tts_speak (general text) and tts_save_audio (saving), though not explicitly naming alternatives.

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 this tool is for demos or quick testing of a particular voice, which gives some context. However, it does not explicitly state when to prefer this over tts_speak or provide exclusion criteria, so its usage guidance remains implicit rather than explicit.

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. Dates show when Glama detected each change.

  1. 5 tool updatesv1.0.3
    • First observedtts_list_voices
    • First observedtts_save_audio
    • First observedtts_speak
    • First observedtts_system_info
    • First observedtts_voice_demo

TDQS

A3.5/5.0
Disambiguation5/5

Each tool has a distinct purpose: speaking text, saving to audio, listing voices, demoing a voice, and system info. The only potential overlap between tts_speak and tts_voice_demo is resolved by voice_demo's specific focus on testing a voice with a fixed phrase.

Naming Consistency4/5

All tools share the tts_ prefix and use snake_case, but the pattern is mixed: tts_speak, tts_save_audio, and tts_list_voices are verb-first, while tts_voice_demo and tts_system_info are noun-first compounds. This prevents a perfect score despite overall readability.

Tool Count5/5

Five tools is well-scoped for a focused text-to-speech server, covering core operations without unnecessary bloat or missing essentials.

Completeness5/5

The set covers the full TTS workflow: listing voices, speaking text, saving audio, demoing voices, and checking system capabilities. No obvious gaps exist for the stated domain.

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    An MCP server that leverages the Microsoft Edge TTS service to provide high-quality text-to-speech capabilities across over 80 languages. It enables users to generate audio files, query available voices, and create subtitle files using natural language commands.
    -
  • A
    license
    Not graded
    quality
    D
    maintenance
    An MCP server that converts text into lifelike speech using Microsoft Edge's Text-to-Speech service, supporting customizable voice, rate, volume, and pitch.
    4
    MIT

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/viktor-silakov/mac-say-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server