Meta MCP Server

by anirudhlath

Not rated
GitHub

About

An MCP server for intelligent tool routing, using a Qdrant vector database and LM Studio for embeddings.

Details

Author
anirudhlath
Categories
Developer Tools, Other, Knowledge Base

Setup

Install Meta MCP Server in your MCP client (Claude Desktop, Cursor, Windsurf, and others).

Repository: https://github.com/anirudhlath/meta-mcp

Follow the installation instructions in the repository README, then restart your MCP client.

An MCP server for intelligent tool routing, using a Qdrant vector database and LM Studio for embeddings.

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 thefind_toolsmeta-tool, letting the client ask "what tool should I use for X?" and get back the most relevant ones instead of the whole list.

- 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 viauvx/uv tool installfrom git as shown below, or once a tagged release is published to PyPI,uv tool install mcpdeck/uvx mcpdeck.

- Python 3.11+
- uv— provides theuvxanduvcommands used throughout this README. If you only havepipx, runpipx install uvto getuvx.
- Docker or
Apple Container(macOS Apple Silicon) — needed to run Qdrant, which backs vector-based tool selection. Optional if you only ever use--no-setupagainst 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 bundledsentence-transformersmodel automatically.

This is themcpdeck servepath: an MCP server over stdio that exposes every child tool as{server}__{tool}plus afind_toolsmeta-tool.stdoutis 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'sclaude_desktop_config.json, or Claude Code's.mcp.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.jsonuses the samemcpServersshape Claude Desktop itself uses, so you can point--mcp-servers-jsonat your existing Claude Desktop config to re-expose the same child servers through MCP Deck's tool-selection layer:

{ "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)? Pointuv run --projectat it instead ofuvx:

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

servesupports--setup(default--no-setup) if you want it to also detect/start a container runtime and Qdrant before serving — seemcpdeck serve --help. Restart Claude Desktop / Claude Code after editing the config.

The Gradio web UI isdisabled on theservepatheven if your config setsweb_ui.enabled: true— Gradio'slaunch()prints to stdout, which would corrupt the JSON-RPC channel. Usemcpdeck startwhen you want the dashboard.

Every child tool is published under{server_name}__{tool_name}(dots aren't legal in MCP tool names, soserver.toolbecomesserver__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_toolsis 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:

{"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.

Run the dashboard/router (start) straight from this repository withuvx:

# 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

Runningmcpdeckwith no arguments (or with top-level flags like--config/--web-ui, with no subcommand) runsstart. 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 existingmcp-servers.jsonor Claude Desktop config in standard locations (read-only — it doesnotwrite or modify your Claude Desktop config)
- Start the MCP Deck server with the web UI athttp://localhost:8080

flowchart TD subgraph Server["MCP Deck server"] Engine["Routing engine<br/>(primary strategy + fallback)"] Vector["Vector search router"] LLM["LLM router"] RAG["RAG router"] Pipeline["RAG pipeline<br/>(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<br/>(Claude Desktop / Claude Code)"] -->|"MCP over stdio<br/>(mcpdeck serve)"| Engine Vector --> Qdrant[("Qdrant<br/>tool + doc embeddings")] Pipeline --> Qdrant Emb -->|primary| LMS["LM Studio<br/>embeddings + local LLM"] Emb -.->|fallback| ST["sentence-transformers<br/>(local model)"] LLM --> LMS Pipeline --> LMS Manager --> C1["Child MCP server<br/>(e.g. filesystem)"] Manager --> C2["Child MCP server<br/>(e.g. github)"] Manager --> C3["Child MCP server<br/>(...)"]

Main components (all undersrc/mcpdeck/):

- North-bound MCP server(server/mcp_stdio.py): themcpdeck serveentry point — wrapsMetaMCPServerin the MCP stdio protocol, publishes{server}__{tool}names, and providesfind_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 leftNonerather 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 (startonly; not used byserve)
- Health / auto-setup(health/): infrastructure detection, health checks, and automatic Docker/Apple Container + Qdrant setup

- 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

- Container runtime detection: Apple Container Framework on Apple Silicon macOS, or Docker elsewhere
- Starts Qdrant automatically
- Auto-detects an existingmcp-servers.jsonor Claude Desktop config

- 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)

mcpdeck start(and baremcpdeck) looks for configuration files in these locations when--config/--mcp-servers-jsonaren't given:

- ./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 servedoes not auto-detect a Claude Desktopmcp-servers.json(pass--mcp-servers-jsonexplicitly — see the Claude Desktop/Code section above), but when--configis omitted it still searches the same main-config locations asstart, in the order listed above (falling back to built-in defaults if none exist).

mcp-servers.json(Claude Desktop format):

{ "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; seeexamples/simple-config.yamlandexamples/advanced-config.yamlfor complete, working examples):

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:

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

Runningmcpdeckwith no subcommand, or with a top-level flag (e.g.mcpdeck --config x.yaml --web-ui), routes tostart.

Every command supports--helpfor its exact flags, e.g.mcpdeck serve --help. When running viauvx, prefix these withuvx --from git+https://github.com/anirudhlath/mcpdeck.

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-compose.ymlruns Qdrant plus themcpdeckdashboard service (built from the repoDockerfile, usingconfig/docker.yamlwhich binds the web UI to0.0.0.0:8080and pointsvector_store.hostat theqdrantservice):

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

The container'sCMDismcpdeck start --no-setup --config /app/config/docker.yaml(Qdrant is provided by compose, so setup is skipped); itsHEALTHCHECKcurlshttp://localhost:8080/(the Gradio dashboard root — there is no/healthHTTP endpoint).

For running Qdrant via Apple's container framework instead of Docker, seedocs/apple-container-setup.md.

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 markedunit,integration(may spawn real subprocesses; no Docker/Qdrant required — resilient init is exercised directly), andslow.

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:

uv run mcpdeck regenerate-embeddings --force

No MCP servers found: create anmcp-servers.jsonfile, or point--mcp-servers-jsonat 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 athttp://localhost:1234/v1/models, and thatlm_studio_endpointis set (it'snull/unset by default — the fallbacksentence-transformersmodel is used unless you configure it explicitly).

Logs: stderr inservemode;./logs/mcpdeck.logand the web UI's log viewer instart/runmode (path fromlogging.filein your config).

- Run child servers with minimal privileges
- Use environment variables for sensitive configuration (${VAR}expansion in child-serverenvblocks)
- Review child server configurations before use
- Enableweb_ui.auth_enabled(+username/password) if the dashboard is reachable beyond localhost
- Fork the repository and clone your fork
- uv sync --extra dev && uv run pre-commit install
- Create a feature branch, make your changes with tests (pre-commit runs Ruff format/lint and mypy on commit)
- ./scripts/check-all.shbefore opening a PR

MIT License - seeLICENSEfile for details.

This is a web browser that enables your coding agent, such as Claude Code, to visit websites on your behalf and assist you in identifying bugs or creating UI test cases.

Explore and understand codebases through conversation by breaking files into logical chunks for searching and querying without embeddings.

A server for text classification using static embeddings from Model2Vec, supporting multiple transports like stdio and HTTP/SSE.

Local code analysis MCP server with 25+ tools: semantic search, call graph tracing, dependency analysis, and symbol navigation. Built with Tree-sitter and CozoDB. Supports Go, Python, JS, TS.

A local-first code indexer that enhances LLMs with deep code understanding. It integrates with AI assistants via the Model Context Protocol (MCP) and supports AI-powered semantic search.

A knowledge management tool for code repositories using vector embeddings, powered by a local Ollama service.

Codebase memory for coding agents, with no embeddings and no API key. A deterministic AST index answers "which files are relevant to this task?" in milliseconds, and agents write durable notes about the repo that are content-hash checked — a note flags itself stale the moment the code it describes changes. Notes are markdown inside the repo, so they commit and review alongside your code.

A server for managing structured project context using SQLite, with support for vector embeddings for semantic search and Retrieval Augmented Generation (RAG).

Transforms raw code into polished solutions with optimized performance and vector embeddings support.

Persistent memory with semantic search, hit-based ranking, universal import, and a knowledge marketplace

A Python-based server that locally indexes codebases using ChromaDB to provide semantic search for tools like Cursor.

No reviews yet — be the first

Sign in to leave a review

Use Google, GitHub, or an email account so ratings stay tied to real people.

Email sign in

No reviews posted yet.