trackmcp
Back to directory

Intelligent MCP (Model Context Protocol) router that selects tools via embeddings, semantic search, and RAG over a Qdrant vector database. Python · FastAPI · Qdrant · Docker.

2 stars PythonOthers Updated Jul 16, 2026
agentic-aiai-toolsembeddingsfastapillmmcpmodel-context-protocolpythonqdrantragvector-search

Documentation

MCP Deck

CI

Your command deck for MCP servers. MCP Deck is an intelligent MCP (Model

Context Protocol) router: it spawns your child MCP servers, embeds their

tools, and exposes them to an MCP client through a single connection —

either proxying every tool directly (namespaced) or, via the `find_tools`

meta-tool, letting the client ask "what tool should I use for X?" and get

back the most relevant ones instead of the whole list.

There are two ways to run it:

  • `mcpdeck serve` — an MCP server over stdio for Claude Desktop / Claude

Code (or any MCP client). This is the integration most people want.

  • `mcpdeck start` — a standalone dashboard/router process with a Gradio

web UI, useful for development, debugging tool selection, and inspecting

child-server health outside of an MCP client.

Install via `uvx`/`uv tool install` from git as shown below, or once a

tagged release is published to PyPI, `uv tool install mcpdeck` /

`uvx mcpdeck`.

Prerequisites

  • Python 3.11+
  • **uv** — provides

the `uvx` and `uv` commands used throughout this README. If you only have

`pipx`, run `pipx install uv` to get `uvx`.

Apple Silicon) — needed to run Qdrant, which backs vector-based tool

selection. Optional if you only ever use `--no-setup` against an

already-running Qdrant, or don't need tool-selection routing at all.

  • **LM Studio** (optional) — for local embeddings and

LLM-based tool selection. Without it, MCP Deck falls back to a bundled

`sentence-transformers` model automatically.

Use with Claude Desktop / Claude Code

This is the `mcpdeck serve` path: an MCP server over stdio that exposes every

child tool as `{server}__{tool}` plus a `find_tools` meta-tool. `stdout` is

reserved for the JSON-RPC protocol — all logs and human-readable output go to

stderr, so this is safe to run under any MCP client's process supervisor.

Add to your MCP client config (Claude Desktop's

`claude_desktop_config.json`, or Claude Code's `.mcp.json`):

json
{
  "mcpServers": {
    "mcpdeck": {
      "command": "uvx",
      "args": [
        "--from",
        "git+https://github.com/anirudhlath/mcpdeck",
        "mcpdeck",
        "serve",
        "--mcp-servers-json",
        "/absolute/path/to/mcp-servers.json"
      ]
    }
  }
}

`mcp-servers.json` uses the same `mcpServers` shape Claude Desktop itself

uses, so you can point `--mcp-servers-json` at your existing Claude Desktop

config to re-expose the same child servers through MCP Deck's tool-selection

layer:

json
{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/files"]
    }
  }
}

Working from a local checkout instead of git+https (e.g. while developing)?

Point `uv run --project` at it instead of `uvx`:

json
{
  "mcpServers": {
    "mcpdeck": {
      "command": "uv",
      "args": [
        "run",
        "--project",
        "/path/to/mcpdeck",
        "mcpdeck",
        "serve",
        "--mcp-servers-json",
        "/absolute/path/to/mcp-servers.json"
      ]
    }
  }
}

`serve` supports `--setup` (default `--no-setup`) if you want it to also

detect/start a container runtime and Qdrant before serving — see

`mcpdeck serve --help`. Restart Claude Desktop / Claude Code after editing

the config.

The Gradio web UI is disabled on the `serve` path even if your config sets

`web_ui.enabled: true` — Gradio's `launch()` prints to stdout, which would

corrupt the JSON-RPC channel. Use `mcpdeck start` when you want the dashboard.

`find_tools` and tool namespacing

Every child tool is published under `{server_name}__{tool_name}` (dots aren't

legal in MCP tool names, so `server.tool` becomes `server__tool`; any other

disallowed character is replaced with `-`, and the name is truncated to the

MCP-mandated 64 characters). Call these directly like any other MCP tool.

`find_tools` is a built-in meta-tool, always listed first, that runs MCP

Deck's intelligent selection (vector / LLM / RAG, depending on config and what

initialized successfully) against a natural-language query:

json
{"name": "find_tools", "arguments": {"query": "read a file from disk", "max_results": 5}}

It returns a JSON list of `{"name": ..., "description": ..., "server": ...}`

for the most relevant tools, which you then call directly by their namespaced

name. This is the main point of MCP Deck: instead of a client seeing every

tool from every child server at once, it can ask for just the ones relevant

to the current task.

Quick Start (dashboard mode)

Run the dashboard/router (`start`) straight from this repository with `uvx`:

bash
# Automatic setup: detects Docker/Apple Container, starts Qdrant, opens the
# web UI on http://localhost:8080
uvx --from git+https://github.com/anirudhlath/mcpdeck mcpdeck

# With explicit config
uvx --from git+https://github.com/anirudhlath/mcpdeck mcpdeck \
    --config my-config.yaml --mcp-servers-json my-servers.json

# Or install it as a persistent CLI tool
uv tool install git+https://github.com/anirudhlath/mcpdeck
mcpdeck

Running `mcpdeck` with no arguments (or with top-level flags like

`--config`/`--web-ui`, with no subcommand) runs `start`. On startup it will:

  • Detect and set up a container runtime (Docker or Apple Container Framework)
  • Start the Qdrant vector database (unless `--no-setup`)
  • Auto-detect an existing `mcp-servers.json` or Claude Desktop config in

standard locations (read-only — it does not write or modify your Claude

Desktop config)

  • Start the MCP Deck server with the web UI at `http://localhost:8080`

Architecture

mermaid
flowchart TD
    subgraph Server["MCP Deck server"]
        Engine["Routing engine(primary strategy + fallback)"]
        Vector["Vector search router"]
        LLM["LLM router"]
        RAG["RAG router"]
        Pipeline["RAG pipeline(doc chunking + retrieval)"]
        Emb["Embedding service"]
        Manager["Child server manager"]
        Engine --> Vector
        Engine --> LLM
        Engine --> RAG
        RAG --> Pipeline
        Vector --> Emb
        Pipeline --> Emb
        Engine -->|selected tools / proxied calls| Manager
    end

    Client["MCP client(Claude Desktop / Claude Code)"] -->|"MCP over stdio(mcpdeck serve)"| Engine

    Vector --> Qdrant[("Qdranttool + doc embeddings")]
    Pipeline --> Qdrant
    Emb -->|primary| LMS["LM Studioembeddings + local LLM"]
    Emb -.->|fallback| ST["sentence-transformers(local model)"]
    LLM --> LMS
    Pipeline --> LMS

    Manager --> C1["Child MCP server(e.g. filesystem)"]
    Manager --> C2["Child MCP server(e.g. github)"]
    Manager --> C3["Child MCP server(...)"]

Main components (all under `src/mcpdeck/`):

  • North-bound MCP server (`server/mcp_stdio.py`): the `mcpdeck serve`

entry point — wraps `MetaMCPServer` in the MCP stdio protocol, publishes

`{server}__{tool}` names, and provides `find_tools`

  • Server core (`server/meta_server.py`): initializes and owns every other

component; resilient startup means a failed embedding/vector-store/LLM/RAG

component is logged as a warning and left `None` rather than crashing —

child tools are still exposed even with no Qdrant/LM Studio running

  • Routing strategies (`routing/`): vector search (`vector_router.py`),

LLM selection (`llm_router.py`), and RAG-based selection (`rag_router.py`)

  • RAG pipeline (`rag/pipeline.py`): chunks and indexes child-server

documentation, retrieves relevant context, and augments selection queries

  • Embedding service (`embeddings/service.py`): LM Studio embeddings when

available, with automatic sentence-transformers fallback and local caching

  • Vector store (`vector_store/qdrant_client.py`): Qdrant-based storage and

similarity search for tool and documentation embeddings

  • Child server manager (`child_servers/`): spawns and manages the

lifecycle of downstream MCP servers and proxies tool calls to them

  • Web interface (`web_ui/`): Gradio-based real-time monitoring and

configuration dashboard (`start` only; not used by `serve`)

  • Health / auto-setup (`health/`): infrastructure detection, health

checks, and automatic Docker/Apple Container + Qdrant setup

Features

Intelligent Tool Selection

  • Vector Search (default): fast semantic similarity using embeddings
  • LLM Selection: AI-powered tool selection using a local LLM (LM Studio)
  • RAG-Based Selection: context-augmented selection using retrieved

child-server documentation

Automatic Setup (`start` / `--setup`)

  • Container runtime detection: Apple Container Framework on Apple Silicon

macOS, or Docker elsewhere

  • Starts Qdrant automatically
  • Auto-detects an existing `mcp-servers.json` or Claude Desktop config

Web Dashboard (`start` only)

  • Real-time server monitoring and logs
  • Interactive configuration editor
  • Tool usage analytics and metrics
  • Child server status monitoring
  • Optional HTTP basic auth (`web_ui.auth_enabled` + `username`/`password`;

fails closed — the UI refuses to start if enabled without both credentials)

Configuration

Auto-Detection

`mcpdeck start` (and bare `mcpdeck`) looks for configuration files in these

locations when `--config`/`--mcp-servers-json` aren't given:

Main Config (mcpdeck.yaml):

  • `./config/mcpdeck.yaml`
  • `./mcpdeck.yaml`
  • `~/.mcpdeck/config.yaml`
  • `./config/meta-server.yaml` (legacy, pre-rename)
  • `./meta-server.yaml` (legacy, pre-rename)
  • `~/.meta-mcp/config.yaml` (legacy, pre-rename)
  • `/etc/meta-mcp/config.yaml` (legacy, pre-rename)

MCP Servers Config (JSON), read-only — never written to:

  • `./mcp-servers.json`
  • `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS)
  • `~/.config/claude/claude_desktop_config.json` (Linux/Windows)
  • `~/.claude/claude_desktop_config.json`

`mcpdeck serve` does not auto-detect a Claude Desktop `mcp-servers.json`

(pass `--mcp-servers-json` explicitly — see the Claude Desktop/Code section

above), but when `--config` is omitted it still searches the same main-config

locations as `start`, in the order listed above (falling back to built-in

defaults if none exist).

Creating Custom Config

`mcp-servers.json` (Claude Desktop format):

json
{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/files"]
    },
    "fetch": {
      "command": "uvx",
      "args": ["mcp-server-fetch"]
    }
  }
}

`mcpdeck.yaml` (every field is real and validated — unknown fields are

rejected; see `examples/simple-config.yaml` and `examples/advanced-config.yaml`

for complete, working examples):

yaml
strategy:
  primary: "vector"      # vector, llm, or rag
  fallback: "vector"     # fallback strategy
  vector_threshold: 0.4  # similarity threshold
  max_tools: 10          # max tools to return

web_ui:
  enabled: true
  port: 8080
  auth_enabled: false    # set true + username/password for basic auth

embeddings:
  # Primary: LM Studio (optional). Canonical endpoint form ends in /v1 —
  # /v1/ and /v1/embeddings are also accepted and normalized.
  lm_studio_endpoint: "http://localhost:1234/v1"
  lm_studio_model: "nomic-embed-text-v1.5"

  # Fallback: local sentence-transformers model (automatic)
  fallback_model: "all-MiniLM-L6-v2"

vector_store:
  type: "qdrant"
  host: "localhost"
  port: 6333

Validate any config file before relying on it:

bash
uv run mcpdeck validate-config path/to/mcpdeck.yaml

Commands

code
mcpdeck [OPTIONS] COMMAND [ARGS]...

Running `mcpdeck` with no subcommand, or with a top-level flag (e.g.

`mcpdeck --config x.yaml --web-ui`), routes to `start`.

CommandPurpose
`serve`Run the MCP server over stdio for Claude Desktop/Code (see above)
`start`Dashboard/full-stack mode with auto-setup + web UI (default command)
`run`Start the server without auto-setup or config auto-detection
`validate-config FILE`Validate a configuration file
`list-strategies`List available tool-selection strategies
`debug-vector`Run a test query against the vector search index
`regenerate-embeddings`Recompute tool embeddings (`--force` to clear and rebuild)
`init-config`Write a default `mcpdeck.yaml`
`health`Check system health and dependencies

Every command supports `--help` for its exact flags, e.g.

`mcpdeck serve --help`. When running via `uvx`, prefix these with

`uvx --from git+https://github.com/anirudhlath/mcpdeck`.

`health`

bash
uv run mcpdeck health                    # text output, exits non-zero on issues
uv run mcpdeck health --output-format json
uv run mcpdeck health --fix --setup-docker --download-models

Docker

`docker-compose.yml` runs Qdrant plus the `mcpdeck` dashboard service

(built from the repo `Dockerfile`, using `config/docker.yaml` which binds the

web UI to `0.0.0.0:8080` and points `vector_store.host` at the `qdrant`

service):

bash
docker-compose up -d
# Web UI: http://localhost:8080
# Qdrant: http://localhost:6333/collections

The container's `CMD` is `mcpdeck start --no-setup --config

/app/config/docker.yaml` (Qdrant is provided by compose, so setup is skipped);

its `HEALTHCHECK` curls `http://localhost:8080/` (the Gradio dashboard root —

there is no `/health` HTTP endpoint).

For running Qdrant via Apple's container framework instead of Docker, see

`docs/apple-container-setup.md`.

Development

bash
git clone https://github.com/anirudhlath/mcpdeck.git
cd mcpdeck

uv sync --extra dev
uv run pre-commit install

uv run pytest
uv run ruff check src/ tests/
uv run ruff format src/ tests/
uv run mypy src/
# or all at once:
./scripts/check-all.sh

# Run the stdio server against a local checkout:
uv run mcpdeck serve --no-setup --mcp-servers-json path/to/mcp-servers.json --log-level DEBUG

# Run dashboard mode against a local checkout:
uv run mcpdeck start --log-level DEBUG

Tests are marked `unit`, `integration` (may spawn real subprocesses; no

Docker/Qdrant required — resilient init is exercised directly), and `slow`.

Troubleshooting

Qdrant connection failed

bash
curl http://localhost:6333/collections
uv run mcpdeck health --setup-docker

Upgrading from before v0.2.0: vector-store point IDs and embedding cache

keys changed (the old scheme used a per-process salted hash that produced

duplicate points on every restart). Run this once after upgrading:

bash
uv run mcpdeck regenerate-embeddings --force

No MCP servers found: create an `mcp-servers.json` file, or point

`--mcp-servers-json` at an existing Claude Desktop config.

Web UI not accessible: check the port isn't already in use

(`lsof -i :8080`) or pick another with `--port`.

LM Studio not being used: confirm the endpoint responds at

`http://localhost:1234/v1/models`, and that `lm_studio_endpoint` is set (it's

`null`/unset by default — the fallback `sentence-transformers` model is used

unless you configure it explicitly).

Logs: stderr in `serve` mode; `./logs/mcpdeck.log` and the web UI's log

viewer in `start`/`run` mode (path from `logging.file` in your config).

Security Considerations

  • Run child servers with minimal privileges
  • Use environment variables for sensitive configuration (`${VAR}` expansion

in child-server `env` blocks)

  • Review child server configurations before use
  • Enable `web_ui.auth_enabled` (+ `username`/`password`) if the dashboard is

reachable beyond localhost

Contributing

1. Fork the repository and clone your fork

2. `uv sync --extra dev && uv run pre-commit install`

3. Create a feature branch, make your changes with tests (pre-commit runs

Ruff format/lint and mypy on commit)

4. `./scripts/check-all.sh` before opening a PR

License

MIT License - see LICENSE file for details.

Frequently asked questions

What is mcpdeck?

mcpdeck is Intelligent MCP (Model Context Protocol) router that selects tools via embeddings, semantic search, and RAG over a Qdrant vector database. Python · FastAPI · Qdrant · Docker.

How do I install mcpdeck?

Open the GitHub repository and follow its README. Most MCP servers are added to your client's MCP config, then called by your agent.

Is mcpdeck open source?

Yes — it is hosted on GitHub at https://github.com/anirudhlath/mcpdeck and has 2 stars.

Related MCP tools

Run your own MCP server? See who uses it and what to fix.

Measure it with TrackMCP