VoiceBrief MCP
# VoiceBrief MCP
A self-hosted [Model Context Protocol](https://modelcontextprotocol.io) server
that answers spoken stock-fact questions — "what's Apple's revenue", "tell me
about Tesla's financials" — grounded in the company's actual SEC 10-K filing,
not a guess from a language model's training data.
Built for a voice agent, not a screen: every answer is a single natural
sentence with units spelled out in full. No markdown, no tables, no `$391B` —
a text-to-speech engine has no reliable way to pronounce an abbreviated unit
letter, so this server never emits one.
```
> "What's Apple's revenue?"
< "AAPL's revenue, from its most recent SEC filing, is $416 billion."
> "Tell me about Tesla's financials."
< "Based on TSLA's most recent SEC filing, it reported revenue of $97.7
billion, earnings per share of $2.01, a market cap of $1.0 trillion,
and a book value per share of $19.32."
```
## Why this exists
Voice assistants answering finance questions today either hallucinate a
number or read out a screen-shaped string a TTS engine mangles ("three
ninety one point zero B"). This server closes both gaps: it pulls figures
straight from [SEC EDGAR's public XBRL API](https://www.sec.gov/edgar) —
free, no key, no auth — and formats them the way a person would actually say
them out loud (`lib/spokenNumbers.js`).
It runs as a normal MCP stdio server, which means it works with any MCP
client, not just one voice platform — Claude Desktop, an Alexa+ skill's
agent runtime, Cursor, or anything else that speaks the protocol.
## Run it
No account, no API key, no cloud dependency beyond `sec.gov` and a free
quote endpoint.
```bash
git clone https://github.com/mjaack/voicebrief-mcp.git
cd voicebrief-mcp
node src/server.js
```
Point any MCP client at it over stdio. For Claude Desktop
(`claude_desktop_config.json`):
```json
{
"mcpServers": {
"voicebrief": {
"command": "node",
"args": ["/absolute/path/to/voicebrief-mcp/src/server.js"]
}
}
}
```
## Tools
| Tool | Use for |
|---|---|
| `get_stock_metric` | One specific figure: `revenue`, `eps`, `book_value_per_share`, `market_cap`, `total_assets`, `total_liabilities`, `price`. |
| `get_stock_snapshot` | A short spoken overview of the company's key figures. |
Both accept a company name or ticker (`"Apple"` or `"AAPL"`) and resolve it
against SEC EDGAR's own ticker list — no hardcoded company map to fall out of
date.
## Protocol conformance
Implements [MCP spec revision 2025-11-25](https://modelcontextprotocol.io/specification/2025-11-25):
- **Version negotiation** — echoes back an older version a client pins
(`2025-06-18`, `2025-03-26`) rather than forcing the latest.
- **[SEP-1303](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/1303)** — a bad argument (missing company, invalid metric) comes
back as a normal tool result with `isError: true`, so the calling model can
read what went wrong and self-correct, instead of a JSON-RPC protocol error
it can only fail on.
- **JSON Schema 2020-12** — every `inputSchema` declares the `$schema`
dialect explicitly.
`test/protocol.test.js` spawns the server as a real subprocess and drives the
actual stdio handshake — `initialize`, `tools/list`, `tools/call` — the same
way a real MCP client does, rather than unit-testing the handler functions in
isolation.
## Test
```bash
npm test
```
12 tests: pure-formatting unit tests for the spoken-number logic
(`test/voiceStockBrief.test.js`, no network) plus the end-to-end protocol
suite above, including one live call to SEC EDGAR to confirm the whole path
returns a real, current figure.
## License
MIT.
TDQS
Scored across 2 tools
get_stock_metric targets a single, specified metric while get_stock_snapshot returns a fixed multi-metric overview, so their primary intents are distinct. There is slight overlap because the snapshot includes several metrics that could also be requested individually, but the descriptions clearly separate specific from broad questions.
Both tools follow the same get_stock_<noun> pattern with clear, parallel names. There is no style mixing or vague verbing between the two.
Two tools is below the typical 3-15 well-scoped range and the server feels minimal, though its narrow voice-brief purpose limits the need for many tools. Each tool earns its place, but the set remains borderline thin.
All advertised metrics are directly queryable via get_stock_metric, and get_stock_snapshot covers the common broad summary. Custom multi-metric requests require repeated calls, but there are no dead ends for the stated domain.