MCP server for Echoes storytelling platform with Narrative Knowledge Graph
Project description
Echoes MCP Server
Model Context Protocol server for AI integration with Echoes storytelling platform.
Features
- Narrative Knowledge Graph: Automatically extracts characters, locations, events, and their relationships
- Semantic Search: Find relevant chapters using natural language queries
- Entity Search: Search for characters, locations, and events
- Relation Search: Explore relationships between entities
- Arc Isolation: Each arc is a separate narrative universe - no cross-arc contamination
- Statistics: Aggregate word counts, POV distribution, and more
- Dynamic Prompts: Reusable prompt templates with placeholder substitution
Architecture
Arc Isolation
Each arc in a timeline is treated as a separate narrative universe:
- Entities are scoped to arcs:
bloom:CHARACTER:Alice≠work:CHARACTER:Alice - Relations are internal to arcs:
bloom:Alice:LOVES:Bob - Searches can be filtered by arc to avoid cross-arc contamination
This is important for multi-arc timelines where the same character may have different knowledge/experiences in different arcs.
Data Model
Timeline (content directory)
└── Arc (story universe)
└── Episode (story event)
└── Chapter (individual .md file)
Requirements
- Python 3.11-3.13 (3.14 not yet supported by spaCy)
- ~2GB disk space for models (spaCy Italian + embeddings)
Installation
pip install echoes-mcp-server
Or with uv (recommended):
uv add echoes-mcp-server
The Italian spaCy model (it_core_news_lg) is downloaded automatically on first use.
Usage
CLI
# Count words in a markdown file
echoes words-count ./content/arc1/ep01/ch001.md
# Index timeline content
echoes index ./content
# Index only a specific arc
echoes index ./content --arc bloom
# Get statistics
echoes stats
echoes stats --arc arc1 --pov Alice
# Search (filters by arc to avoid cross-arc contamination)
echoes search "primo incontro" --arc bloom
echoes search "Alice" --type entities --arc bloom
Environment Variables
# Custom embedding model (default: paraphrase-multilingual-MiniLM-L12-v2)
export ECHOES_EMBEDDING_MODEL=sentence-transformers/all-MiniLM-L6-v2
# HuggingFace token for gated models
export HF_TOKEN=hf_xxx
# Gemini API key for entity/relation extraction (optional)
# Get your key at https://aistudio.google.com/apikey
export GEMINI_API_KEY=your_api_key
MCP Server
Configure in your MCP client (e.g., Claude Desktop, Kiro CLI):
{
"mcpServers": {
"echoes": {
"command": "echoes-mcp-server",
"cwd": "/path/to/timeline"
}
}
}
Or with uvx (no installation required):
{
"mcpServers": {
"echoes": {
"command": "uvx",
"args": ["echoes-mcp-server"],
"cwd": "/path/to/timeline"
}
}
}
Available Tools
| Tool | Description |
|---|---|
words-count |
Count words and statistics in a markdown file |
index |
Index timeline content into LanceDB |
search-semantic |
Semantic search on chapters |
search-entities |
Search characters, locations, events |
search-relations |
Search relationships between entities |
stats |
Get aggregate statistics |
Available Prompts
The server provides dynamic prompts that load templates from ../.github/.kiro/prompts/ and optionally append timeline-specific overrides from ./.kiro/prompts/.
| Prompt | Arguments | Description |
|---|---|---|
new-chapter |
arc, chapter | Create a new chapter for a timeline arc |
revise-chapter |
arc, chapter | Revise an existing chapter |
expand-chapter |
arc, chapter, target | Expand a chapter to target word count |
new-character |
name | Create a new character sheet |
new-episode |
arc, episode | Create a new episode outline |
new-arc |
name | Create a new story arc |
Prompts support placeholder substitution ({ARC}, {CHAPTER}, {TIMELINE}, etc.) and validate arguments (e.g., arc must exist, chapter must be a number).
Development
Setup
# Clone the repository
git clone https://github.com/echoes-io/mcp-server.git
cd mcp-server
# Install uv if you haven't
curl -LsSf https://astral.sh/uv/install.sh | sh
# Create venv with Python 3.13 (required for spaCy compatibility)
uv venv --python 3.13
# Install dependencies
uv sync --all-extras
# The spaCy model downloads automatically on first use, or install manually:
uv pip install https://github.com/explosion/spacy-models/releases/download/it_core_news_lg-3.8.0/it_core_news_lg-3.8.0-py3-none-any.whl
Commands
# Run tests
uv run pytest
# Run tests with coverage
uv run pytest --cov
# Lint
uv run ruff check .
# Format
uv run ruff format .
# Type check
uv run mypy src/
Demo
Test with real timeline content:
# Create symlinks to timeline repos (adjust paths as needed)
cd demo
ln -s ../../timeline-anima/content anima
ln -s ../../timeline-eros/content eros
# Run demo
uv run python demo/run_demo.py
Example output:
============================================================
📚 Timeline: ANIMA
============================================================
📖 Chapters found: 55
📝 Total words: 199,519
📁 Arcs: ['anima', 'matilde']
👤 POVs: ['nic']
============================================================
📚 Timeline: EROS
============================================================
📖 Chapters found: 465
📝 Total words: 733,034
📁 Arcs: ['ale', 'ele', 'gio', 'ro', 'work']
👤 POVs: ['Ele', 'Nic', 'ale', 'angi', 'gio', 'nic', 'ro', 'vi']
============================================================
🔍 NER Demo (Named Entity Recognition)
============================================================
📄 Sample: anima/ep01/ch001
🏷️ Entities found: 33
LOC: Malpensa, Terminal 2
ORG: LinkedIn, Ryanair
PER: GioGio, Cristo
Project Structure
src/echoes_mcp/
├── __init__.py # Package version
├── cli.py # CLI interface (click)
├── server.py # MCP server
├── database/
│ ├── lancedb.py # LanceDB operations
│ └── schemas.py # Pydantic schemas
├── indexer/
│ ├── scanner.py # Filesystem scanner
│ ├── extractor.py # Entity extraction (Gemini/spaCy)
│ ├── embeddings.py # Embedding models
│ └── spacy_utils.py # spaCy with auto-download
├── prompts/
│ ├── handlers.py # Prompt loading and MCP integration
│ ├── substitution.py # Placeholder replacement
│ └── validation.py # Arc/argument validation
└── tools/
├── words_count.py # Word counting
├── stats.py # Statistics
├── search.py # Search operations
└── index.py # Indexing tool
demo/
├── run_demo.py # Demo script
├── anima -> ... # Symlink to timeline-anima/content
└── eros -> ... # Symlink to timeline-eros/content
Tech Stack
| Purpose | Tool |
|---|---|
| Package manager | uv |
| Linter/Formatter | Ruff |
| Type checker | mypy |
| Testing | pytest |
| Vector DB | LanceDB |
| Embeddings | sentence-transformers |
| NER | spaCy (Italian model) |
| Entity Extraction | Gemini 3 Flash (primary) / spaCy (fallback) |
| Knowledge Graph | LlamaIndex |
Node.js Comparison
If you're coming from Node.js:
| Node/npm | Python/uv |
|---|---|
npm install |
uv sync |
npm add pkg |
uv add pkg |
npm run test |
uv run pytest |
npx cmd |
uv run cmd |
package.json |
pyproject.toml |
node_modules/ |
.venv/ |
| Biome | Ruff |
| Vitest | pytest |
License
MIT
Part of the Echoes project - a multi-POV digital storytelling platform.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file echoes_mcp_server-5.4.0.tar.gz.
File metadata
- Download URL: echoes_mcp_server-5.4.0.tar.gz
- Upload date:
- Size: 305.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
055ce6fc858700b8fe49250a00fbbe582543ab2206f1f643b08a99bb50c399f7
|
|
| MD5 |
39855bf18a829faebd9009246403b27b
|
|
| BLAKE2b-256 |
636b1cbcd45c3bb1050d2dba8e7a3a04e4e02dd369769ef6812965361f1046fc
|
Provenance
The following attestation bundles were made for echoes_mcp_server-5.4.0.tar.gz:
Publisher:
ci.yml on echoes-io/mcp-server
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
echoes_mcp_server-5.4.0.tar.gz -
Subject digest:
055ce6fc858700b8fe49250a00fbbe582543ab2206f1f643b08a99bb50c399f7 - Sigstore transparency entry: 779004383
- Sigstore integration time:
-
Permalink:
echoes-io/mcp-server@40f9341dd06253f80b9b3252d44884722ebc71c9 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/echoes-io
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@40f9341dd06253f80b9b3252d44884722ebc71c9 -
Trigger Event:
push
-
Statement type:
File details
Details for the file echoes_mcp_server-5.4.0-py3-none-any.whl.
File metadata
- Download URL: echoes_mcp_server-5.4.0-py3-none-any.whl
- Upload date:
- Size: 29.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
06f4209fd907a166a4f532f1a2afa6419c488fa601fc51b4cb1e5436d5d09fcb
|
|
| MD5 |
8623846c376b872fdf7498051587537c
|
|
| BLAKE2b-256 |
fbcc7d5135cacaa824215219e1dee6b9b6a4a714be17411f4cfb84d42ca2f209
|
Provenance
The following attestation bundles were made for echoes_mcp_server-5.4.0-py3-none-any.whl:
Publisher:
ci.yml on echoes-io/mcp-server
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
echoes_mcp_server-5.4.0-py3-none-any.whl -
Subject digest:
06f4209fd907a166a4f532f1a2afa6419c488fa601fc51b4cb1e5436d5d09fcb - Sigstore transparency entry: 779004384
- Sigstore integration time:
-
Permalink:
echoes-io/mcp-server@40f9341dd06253f80b9b3252d44884722ebc71c9 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/echoes-io
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@40f9341dd06253f80b9b3252d44884722ebc71c9 -
Trigger Event:
push
-
Statement type: