mac-say-mcp
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@mac-say-mcpspeak 'Hello, world!' in a friendly voice"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
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 startGlobal 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-mcpNPM 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
-yflagβ 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 devAvailable Scripts
npm run build- Build the TypeScript code with esbuildnpm run build:watch- Build in watch mode for developmentnpm run start- Build and start the MCP servernpm run dev- Development mode with auto-rebuildnpm run clean- Clean build artifactsnpm run typecheck- Run TypeScript type checkingnpm 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 startOr via command line:
node dist/index.js --defaultRate 250MCP Client Setup
Note: Replace
/path/to/mac-say-mcpwith the actual path to your project directory. Usepwdin 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:
Open Cursor Settings
Go to "MCP Servers"
Add a new server:
Name:
mac-say-mcpCommand:
npxArgs:
-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 scriptsType 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 |
| High | Large |
WAV |
| High | Large |
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
saycommandNode.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:dryChangelog 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:allCommit 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
Make changes with conventional commit messages
Run tests and type checking:
npm run typecheckCreate release:
npm run release:patch(or minor/major)Automatic steps:
Version bump in package.json
CHANGELOG.md update
Git commit and tag
GitHub release with changelog
npm package publication
Contributing
Make changes in
src/index.tsUse conventional commit messages
Run
npm run typecheckto verify typesTest with
npm run build && npm startUpdate documentation as needed
License
MIT License - see LICENSE file for details.
Troubleshooting
Build Issues
# Clear build cache
npm run clean
npm run buildType Errors
# Check TypeScript errors
npm run typecheckRuntime Issues
# Test say command directly
say -v Alex "Hello world"
say -v "?" # List voicesAudio 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 toolstts_list_voicesA
List all available voices on the system
| Name | Required | Description | Default |
|---|---|---|---|
| language | No | Filter voices by language (optional) |
TDQS
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.
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.
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.
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.
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.
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
| Name | Required | Description | Default |
|---|---|---|---|
| rate | No | Speaking rate in words per minute (default: 200) | |
| text | Yes | Text to convert to speech | |
| voice | No | Voice to use (optional, default: Alex) | |
| format | No | Audio format: aiff, wav, mp4 | aiff |
| filename | Yes | Name for the audio file (without extension) |
TDQS
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.
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.
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.
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.
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.
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
| Name | Required | Description | Default |
|---|---|---|---|
| rate | No | Speaking rate in words per minute (default: 200) | |
| text | Yes | Text to convert to speech | |
| voice | No | Voice to use (optional, default: Alex) |
TDQS
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.
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.
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.
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.
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.
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
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
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.
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.
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.
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.
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.
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
| Name | Required | Description | Default |
|---|---|---|---|
| text | No | Custom text for demo (optional) | Hello, this is a voice demonstration. |
| voice | Yes | Voice name to demo |
TDQS
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.
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.
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.
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.
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.
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.
5 tool updates
v1.0.3- First observed
tts_list_voices - First observed
tts_save_audio - First observed
tts_speak - First observed
tts_system_info - First observed
tts_voice_demo
TDQS
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.
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.
Five tools is well-scoped for a focused text-to-speech server, covering core operations without unnecessary bloat or missing essentials.
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
MCP server for Text-to-Speech
MCP server exposing the AceDataCloud Fish Audio API (text-to-speech with voice conditioning)
MCP server for Speech-to-Text
AI voice generation: text-to-speech and voice cloning from any MCP client.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceAn 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.-
- AlicenseNot gradedqualityDmaintenanceProfile-driven MCP server for Google Cloud Text-to-Speech that exposes tools to synthesize text to speech, run diagnostics, and stop playback, with voice and settings locked per profile.1MIT
- AlicenseNot gradedqualityDmaintenanceAn MCP server that converts text into lifelike speech using Microsoft Edge's Text-to-Speech service, supporting customizable voice, rate, volume, and pitch.4MIT
- FlicenseNot gradedqualityBmaintenanceText-to-speech MCP server using Microsoft Edge TTS, supporting multiple voices and async processing.-
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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