mcp-say
v1.0.1
Published
Provide professional 'say' command MCP services.
Maintainers
Readme
mcp-say
macOS say command exposed as an MCP server. Use it from Cursor, Claude Code, Codex, or any MCP client to list voices, speak text, or return synthesized audio.
Requirements
- macOS — the
saycommand is only available on macOS - Node.js 18+ — required when installing from npm
- ffmpeg (optional) — required for mp3, re-encoded wav, pcm, ogg, opus, aac output
Install
Run with npx (recommended)
No global install needed:
npx -y mcp-sayMCP clients should use the same command in their server config (see below).
Install globally
npm install -g mcp-say
# or
pnpm add -g mcp-sayThen run:
mcp-sayInstall from source
git clone https://github.com/SmilingXinyi/mcp-say.git
cd mcp-say
pnpm install
pnpm build
node build/index.jsMCP configuration
mcp-say uses stdio by default. Point your MCP client at npx -y mcp-say, or at mcp-say if installed globally.
After editing a config file, restart the client (or start a new Claude Code / Codex session) so the server reloads.
Cursor
Config file locations:
- Global:
~/.cursor/mcp.json - Project:
.cursor/mcp.json
{
"mcpServers": {
"mcp-say": {
"command": "npx",
"args": ["-y", "mcp-say"]
}
}
}Global install variant:
{
"mcpServers": {
"mcp-say": {
"command": "mcp-say",
"args": []
}
}
}Verify in Settings → Tools & MCP. The server should show a green connected status. If npx is not found from the Cursor GUI, use the full path from which npx.
Claude Code
Project config (recommended for teams — commit .mcp.json to the repo):
Create .mcp.json in the project root:
{
"mcpServers": {
"mcp-say": {
"type": "stdio",
"command": "npx",
"args": ["-y", "mcp-say"]
}
}
}Or add via CLI:
claude mcp add mcp-say --scope project -- npx -y mcp-sayUser-wide config (all projects, only on your machine):
claude mcp add mcp-say --scope user -- npx -y mcp-sayCheck status with /mcp inside Claude Code. Project-scoped servers require a one-time approval on first use.
Codex
Config file locations:
- Global:
~/.codex/config.toml - Project:
.codex/config.toml(trusted projects only)
[mcp_servers.mcp-say]
command = "npx"
args = ["-y", "mcp-say"]
enabled = trueOr add via CLI:
codex mcp add mcp-say -- npx -y mcp-sayVerify with:
codex mcp listInside a Codex session, run /mcp to inspect connected servers and tools.
Remote SSE mode (optional)
For HTTP clients instead of stdio, run the server separately and connect over SSE:
MCP_TRANSPORT=sse MCP_PORT=3000 npx -y mcp-sayCursor example (remote URL):
{
"mcpServers": {
"mcp-say": {
"url": "http://localhost:3000/mcp"
}
}
}Claude Code example:
{
"mcpServers": {
"mcp-say": {
"type": "http",
"url": "http://localhost:3000/mcp"
}
}
}Codex example:
[mcp_servers.mcp-say]
url = "http://localhost:3000/mcp"
enabled = trueEndpoints:
GET /mcporGET /sse— establish SSE sessionPOST /messages?sessionId=<id>— send MCP messages
| Variable | Default | Description |
| ---------------- | ----------- | -------------------------------------------------- |
| MCP_TRANSPORT | stdio | stdio, sse, or remote |
| MCP_HOST | localhost | Bind host for SSE mode |
| MCP_PORT | 3000 | Bind port for SSE mode |
| MCP_AUTH_TOKEN | — | When set, requires Authorization: Bearer <token> |
Security notes for SSE mode
- Keep the server bound to
localhostunless you explicitly need remote access. - Always set
MCP_AUTH_TOKENwhen exposing SSE beyond your machine. say_to_filecan write to any absolute path the server process can access; only enable this server in trusted environments.
Tools
| Tool | Description | Best for |
| -------------- | ------------------------------------------------------ | -------------------------------- |
| list_voices | List installed TTS voices with locale filter | Discovering available voices |
| say | Speak text through the server speakers | Local stdio / server-side alerts |
| say_to_file | Write audio to a server filesystem path | Persisting files on the server |
| say_to_audio | Return synthesized audio as MCP audio content (base64) | Remote SSE clients |
Choosing a tool
Local stdio (Cursor / Claude Code / Codex)
- Quick playback →
say - Save to disk →
say_to_file - Agent needs audio bytes →
say_to_audio
Remote SSE client
- Use
say_to_audio— the client receives base64 audio in the tool result and decodes it locally say_to_filewrites to the server path; remote clients cannot read those filessayplays on the server speakers only
Develop
pnpm install
pnpm build
pnpm debug
# or: npx @modelcontextprotocol/inspector node build/index.jsTest
pnpm test # all tests
pnpm test:unit # unit tests only
pnpm test:integration # integration tests onlymacOS-only integration tests (real say / ffmpeg) run automatically on darwin and are skipped on other platforms.
Publish to npm
The package ships compiled JavaScript (build/), not the Bun binary.
pnpm build
npm publish --access publicprepublishOnly runs pnpm build automatically before publish. The files field ensures only build/ and README.md are included in the tarball.
Optional: local binary bundle
For a standalone executable without Node at runtime, see bundle.sh after installing bun:
pnpm build:bin
./mcp-sayThis is intended for local distribution. The npm package uses build/index.js via the bin field.
