Skip to main content
Glama

ep-mcp

Expertise-as-a-Service over the Model Context Protocol.

An MCP server that turns any ExpertPack into a live, queryable knowledge service. Any MCP-compatible agent (Claude Desktop, Cursor, Windsurf, Claude.ai, custom hosts) can connect and retrieve high-quality, provenance-rich domain expertise via standardized tools.

🌐 expertpack.ai Β· πŸ“¦ ExpertPack Framework Β· πŸ“– Architecture

97.6% retrieval hit rate / 0 full misses on a 22-question benchmark against a production v4.1 atomic-conceptual pack (658 chunks). Prior v4.0 baseline on the same pack and eval set: 65.1%.

Features

  • Schema-aware hybrid retrieval: BM25 + vector search (sqlite-vec), metadata boosting, MMR re-ranking, adaptive threshold filtering, length penalty

  • requires: expansion (schema v4.1 atomic-conceptual): When a top-K atom's frontmatter declares requires: [B, C], the referenced atoms are auto-appended to results as additional SearchResults flagged requires_expanded=True. Directional (Aβ†’B does not imply Bβ†’A), transitive up to 2 hops, capped at 3 atoms and 3,500 cumulative tokens, appended after the max_results slice so it never displaces top-K.

  • Intent-aware routing: Automatic query classification (ENTITY/HOW/WHY/WHEN/GENERAL) adjusts vector/BM25 fusion weights per query β€” no LLM required

  • Query embedding cache: SQLite-backed cache keyed by (model, dimension, sha256(query)) β€” warm query latency drops from ~4s (live Gemini API) to ~1ms

  • Deep graph traversal: Optional multi-hop BFS expansion over knowledge graph edges with per-hop score decay and drift prevention

  • Reserved-slot graph merge: Configurable protected slots in the final top-K reserved for graph-expanded neighbors so related files surface even against dominant core results

  • BM25 fallback mode: Embedding provider outage degrades gracefully to lexical-only search (coverage + density + path + length scoring) instead of a hard error

  • Cross-encoder reranker: Optional second-pass precision reranker (disabled by default, ~70ms warm latency when enabled)

  • Provenance-first: Every result includes id, content_hash, verified_at, source_file

  • Reconstruct mode (RFC-003): Opt-in reconstruct=true / reconstruct: true enriches results with fragment_id, line_range, original_markdown, span-level content_hash, excerpt, stale, and byte offsets so agents can prove exactly what source text grounded an answer

  • EP-native chunking: Files are treated as atomic retrieval units (split at ##/### only for oversized content). Split chunks keep the original span as content/span_hash, carry a computed line_range, and record a heading_path (0.7.0+)

  • Heading paths (0.7.0+): every hit carries heading_path (e.g. ["Routing", "Setup", "Ports"]) so an H3 hit keeps its H2 parent; ep_read(path, section=..., neighbors=true) reads just that section plus its previous/next siblings

  • Freshness (0.7.0+, ExpertPack Core 4.2): hits and ep_read carry verified_age_days, age_stale (verified_at older than the file's refresh or the manifest freshness.refresh_cycle), expired and expires_at (volatile TTL). stale keeps its old meaning β€” index drift (file changed since indexing, reconstruct mode only). Optional down-rank via retrieval.freshness_penalty (default 0.0 = off)

  • Skills over MCP (0.7.0+, opt-in): set mcp.skills.enabled: true in a pack's manifest.yaml to declare the io.modelcontextprotocol/skills extension (SEP-2640). Each pack becomes one skill at skill://{slug}/SKILL.md (generated) with every non-on_demand file served verbatim at skill://{slug}/{path}; skills/list / skills/get publish the manifest with SHA-256 digests, sizes, ttlMs and cacheScope. Host support is still thin, so the ep_* tools remain the primary path

  • Frontmatter aware: Strips metadata for embedding, extracts type, tags, requires, etc. for boosting/expansion/filtering

  • Incremental indexing: Content-hash based staleness detection β€” only re-embeds changed files

  • Multi-pack support: Path-based routing at /packs/{slug}/mcp

  • Graph-aware retrieval: optional post-retrieval expansion via _graph.yaml adjacency, including accepted ontology/entity nodes when graph export provides them

  • context_prefix (RFC-004): sidecar situating strings are prepended at index time for embed + BM25 only; returned/reconstruct text stays the original atom body

  • Tier / navigation filter: retrieval_strategy: navigation, _index.md, source-coverage.md, and context.on_demand files are excluded from the RAG pool (still readable via ep_read / resources)

  • Tools:

    • ep_search β€” primary hybrid retrieval tool

    • ep_read β€” load a whole atom by path or provenance id (consume-loop step 2)

    • ep_list_topics β€” browse pack structure and available content types

    • ep_graph_traverse

    • Multi-pack stdio support: All tools accept a pack parameter for routing when multiple packs are configured. Single-pack configs make pack optional (defaults to the only configured pack).

  • Resources:

    • ep://{slug}/manifest

    • ep://{slug}/authority

    • ep://{slug}/files

    • ep://{slug}/file/{+path} (raw content with frontmatter)

    • skill://{slug}/SKILL.md, skill://{slug}/{+path} (only when mcp.skills.enabled: true)

  • Transports: Streamable HTTP (primary, cloud-ready), stdio (local dev)

    • stdio multi-pack support (0.6.0+): When using --transport stdio with multiple packs configured, all tools accept an optional pack parameter (slug string) to specify which pack to query. For single-pack configurations, the pack parameter is optional and defaults to the only configured pack. This allows MCP hosts (Cursor, Claude Desktop) to use a single stdio process for multiple packs instead of requiring one process per pack.

  • HTTP endpoint: GET /search (for non-MCP HTTP clients)

  • Golden retrieval eval (0.7.0+): tests/eval/ β€” YAML query sets (expected best-first, must_not, category) scored as recall@1/3/5, MRR and must_not violations per pack and category. Skipped in the default run; pytest tests/eval -m golden --golden <dir> --packs-root <dir> with EP_EVAL_TODAY=2026-10-20 and optional EP_EVAL_MIN="recall@5=0.9,mrr=0.7", or python tests/eval/golden_eval.py --golden <dir> --today 2026-10-20

  • Auth: API key (Phase 1), designed for OAuth 2.1 (Phase 2)

Related MCP server: KaaS

Quick Start

Installation

git clone https://github.com/brianhearn/ep-mcp.git
cd ep-mcp
pip install -e .[dev]

Configuration

Create config.yaml with at minimum:

server:
  host: "127.0.0.1"
  port: 8000
  log_level: "info"
  # Required for public Host headers (SDK v2 DNS-rebinding protection).
  # See DEPLOYMENT.md β€” omit and Streamable HTTP returns 421.
  mcp_allowed_hosts:
    - "localhost"
    - "localhost:*"
    - "127.0.0.1"
    - "127.0.0.1:*"

packs:
  - slug: "my-pack"
    path: "/path/to/your/expertpack"
    api_keys:
      - "your-secret-key-here"

embedding:
  provider: "gemini"           # "gemini" (default) or "azure-openai"
  model: "gemini-embedding-001"

For the full configuration reference β€” embedding providers, retrieval tuning (mmr_lambda, min_score, default_max_results, graph expansion, reranker, requires: expansion, etc.), production systemd setup, and deployment gotchas β€” see DEPLOYMENT.md.

Running

ep-mcp serve --config config.yaml

The server builds/updates the SQLite index (FTS5 + sqlite-vec) on startup. 0.5.0 requires a rebuild of existing indexes (index_features=context_prefix_v1+nav_filter_v1); startup does this automatically, or delete <pack>/.ep-mcp/ first.

The GET /search HTTP endpoint is available at:

GET /search?q=<query>&pack=<slug>&n=10

Add &reconstruct=true to include original markdown spans and provenance blocks for verification.

with header Authorization: Bearer <key>.

Environment Variables

Only the key for your configured embedding provider is required.

Variable

Required

Description

GEMINI_API_KEY

If embedding.provider: gemini

Gemini embedding API key

AZURE_OPENAI_ENDPOINT

If embedding.provider: azure-openai

Azure OpenAI resource endpoint

AZURE_OPENAI_API_KEY

If embedding.provider: azure-openai

Azure OpenAI API key

EP_MCP_KEY_{SLUG}

Optional

Per-pack API key override (uppercase slug, hyphens→underscores)

EP_MCP_REMOTE_HOST

Optional

Deploy target for scripts/deploy.sh

EP_MCP_REMOTE_SRC

Optional

Remote source path for deploy.sh

EP_MCP_REMOTE_SITE_PKG

Optional

Remote site-packages path for deploy.sh

Tech Stack

  • Language: Python 3.12+

  • MCP Framework: official mcp SDK v2 (MCPServer, spec 2026-07-28, dual-era with 2025 clients)

  • Storage: SQLite with FTS5 + sqlite-vec

  • Embeddings: Gemini (default), configurable Azure OpenAI / OpenAI providers

  • Web: Starlette + Uvicorn (for Streamable HTTP)

  • CLI: Click

See pyproject.toml for exact dependencies.

Project Structure

See ARCHITECTURE.md for detailed module breakdown, retrieval pipeline, indexing strategy, and design decisions.

  • expertpack.ai β€” Framework website, community packs, and documentation

  • ExpertPack β€” Schema framework, validation tools, Obsidian compatibility, community packs

  • ExpertPacks β€” Published knowledge packs (private)

  • EasyTerritory MCP (future) β€” Domain-specific layer built on top of this repo + ezt-designer pack

License

Apache 2.0 Β© 2026 Brian Hearn

Author

Brian Hearn β€” Built in 3 days (April 10–11, 2026).

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    A
    maintenance
    Exposes a compiled Markdown knowledge base to any MCP-capable coding agent through a single ask tool, returning cited answers grounded in full wiki articles over stdio or streamable HTTP.
    -
  • F
    license
    Not graded
    quality
    A
    maintenance
    Exposes a compiled Markdown knowledge base to MCP-capable coding agents through a single ask tool that returns cited, Markdown-formatted answers grounded in whole wiki articles rather than embedded fragments. Runs locally over stdio or remotely over streamable HTTP with optional bearer-token authentication.
    -
  • F
    license
    Not graded
    quality
    A
    maintenance
    Exposes a compiled Markdown knowledge base to MCP-capable coding agents through a single ask tool that returns cited answers grounded in whole wiki articles rather than embedded fragments. Supports local stdio and remote streamable-HTTP transports, with optional bearer-token authentication on the network transport.
    -
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables MCP-capable agents to search and answer over a local hybrid-retrieval knowledge base as tools, covering querying, grounded answering, index stats, corpus listing, and adding a website. Runs over stdio for local clients or HTTP for remote ones.
    MIT