Install
$ agentstack add mcp-jsliapark-brandvoice-mcp ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
brandvoice-mcp
[](https://pypi.org/project/brandvoice-mcp/) [](https://pypi.org/project/brandvoice-mcp/) [](https://opensource.org/licenses/MIT)
An MCP server that learns your writing style and makes every AI client sound like you.
Quick start
Install
pip install brandvoice-mcp
Configure Claude Desktop
Add to your claude_desktop_config.json (macOS: ~/Library/Application Support/Claude/claude_desktop_config.json):
{
"mcpServers": {
"brandvoice": {
"command": "python",
"args": ["-m", "brandvoice_mcp"],
"env": {
"ANTHROPIC_API_KEY": "sk-ant-...",
"OPENAI_API_KEY": "sk-..."
}
}
}
}
Set ANTHROPIC_API_KEY and OPENAI_API_KEY in the env block (both required for normal use: Claude for analysis/alignment, OpenAI for chunk embeddings). The server will exit with a clear error if either is missing.
Teach it your voice
In Claude Desktop, ask the model to use ingest_samples with real writing:
> Use the ingest_samples tool to learn my writing style from this blog post: [paste content]
The server chunks the text, stores embeddings in ChromaDB, and (for samples of about 50+ words) runs LLM style analysis. Shorter snippets are still stored for retrieval but skip style analysis to avoid unreliable profiles.
Write in your voice
Before any writing task, call get_voice_context with your task and platform. The returned prompt_injection is wrapped in ... — prepend it to your request or system prompt.
> Use get_voice_context for a LinkedIn post about React performance, then write it in my voice.
Check alignment
After drafting text, call check_alignment with the draft. You get a 0–100 score, drift flags, and rewrite hints against your stored profile and samples.
> Use check_alignment on this draft: [paste text]
Tools reference
| Tool | Description | |------|-------------| | ingest_samples | Ingest writing; chunk, embed, and update style profile when thresholds are met | | get_voice_context | Voice guidelines, similar samples, and prompt_injection for a task | | set_guidelines | Merge explicit brand voice rules (pillars, tone, vocabulary, etc.) | | check_alignment | Score how well content matches your voice | | get_profile | Full profile: learned style (including profile_source), guidelines, counts | | list_samples | Paginated list of ingested samples (each row includes the Chroma document id for delete_samples) | | delete_samples | Delete samples by sample_ids (from list_samples) or set all to true to clear the collection; refreshes or resets the learned profile |
How it works
Ingestion: Text is split into chunks, embedded with OpenAI (default text-embedding-3-small), and stored in a local ChromaDB collection (writing_samples) for similarity search. The aggregate learned style and explicit guidelines live in ~/.brandvoice/profile.json (human-readable, separate from vectors) so a vector DB issue does not silently wipe your profile alongside embeddings.
Style analysis: For sufficiently long samples, Claude analyzes tone and patterns (including humor, technical depth, and warmth scores used in get_voice_context). If the API fails, a heuristic fallback runs; profile_source records "llm" vs "heuristic". After enough stored chunks (see BRANDVOICE_PROFILE_THRESHOLD), each qualifying ingest re-merges the corpus via Claude (prompts/corpus_aggregate.md) into a single aggregate profile; on failure, the latest per-sample LLM snapshot is used when available.
Writing assistance: For a task, the server retrieves your profile and the top similar chunks, then builds prompt_injection from markdown templates under brandvoice_mcp/prompts/.
Configuration
| Variable | Default | Description | |----------|---------|-------------| | ANTHROPIC_API_KEY | (required) | Anthropic API key (style analysis, alignment) | | OPENAI_API_KEY | (required) | OpenAI API key (chunk embeddings; Anthropic has no embeddings API) | | BRANDVOICE_DATA_DIR | ~/.brandvoice | Data directory (profile.json, Chroma persistence) | | BRANDVOICE_EMBEDDING_MODEL | text-embedding-3-small | OpenAI embedding model name | | BRANDVOICE_ANALYSIS_MODEL | claude-sonnet-4-6 | Model for style analysis | | BRANDVOICE_PROFILE_THRESHOLD | 5 | Minimum stored samples before aggregate profile can update after an LLM-analyzed ingest |
> Model deprecation: If the default claude-sonnet-4-6 is deprecated or unavailable in your region, set BRANDVOICE_ANALYSIS_MODEL to a supported model ID (e.g. claude-opus-4-6 or claude-haiku-4-5-20251001). Claude 4 model IDs use no date suffix; check Anthropic's model documentation for the current list.
Limitations
- Single client: Designed for one MCP client at a time. Multiple clients sharing the same
~/.brandvoicedirectory may hit SQLite/Chroma lock errors. - API costs: Style analysis and alignment use Anthropic; chunk embeddings use OpenAI. Each
ingest_samplesandcheck_alignmentconsumes tokens; budget accordingly.
Requirements
- Python 3.11+
- Anthropic API key (
ANTHROPIC_API_KEY) — LLM calls - OpenAI API key (
OPENAI_API_KEY) — embeddings for ChromaDB similarity search
Development
git clone https://github.com/jsliapark/brandvoice-mcp.git
cd brandvoice-mcp
pip install -e ".[dev]"
pytest
Architecture (overview)
MCP client (Claude Desktop, Cursor, …)
│ stdio
▼
brandvoice-mcp server
│
├── profile.json ← aggregate learned style + explicit guidelines
└── ChromaDB ← writing_samples (embeddings + chunks)
Manual testing in a terminal
The server speaks JSON-RPC on stdin/stdout. When you run python -m brandvoice_mcp, it should block until the client disconnects or you press Ctrl+C — there is no interactive prompt.
- Do not type in that terminal while the server is running; random text is not valid JSON-RPC and you will see errors like
Invalid JSON/JSONRPCMessagevalidation errors. - Do not run two copies of the server on the same stdio session.
- If you use Cursor / Claude Desktop with this project, let only the IDE spawn the process — don’t also run
python -m brandvoice_mcpin a terminal unless you are debugging with a real MCP client attached.
If python -m brandvoice_mcp crashes with Server has no attribute tool, your checkout is on the old low-level Server API — use FastMCP (from mcp.server import FastMCP) and sync __main__.py to call run_server() without asyncio.run (see current server.py on main).
For a local run, export both ANTHROPIC_API_KEY and OPENAI_API_KEY (see Configuration above).
License
MIT — see [LICENSE](LICENSE).
Source & license
This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: jsliapark
- Source: jsliapark/brandvoice-mcp
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.