skill-router-mcp
skill-router-mcp
Skill routing for SKILL.md libraries, served over MCP to any agent.
Point it at a directory of Agent Skills
(SKILL.md files with YAML frontmatter) and any MCP client — Claude Code,
Cursor, Windsurf, Codex, or your own agent — can discover skills, match a task
to the best one, and load instructions on demand without blowing its context
window.
match_skill("create a word document")
→ [{ name: "docx", score: 0.85, requires: ["filesystem", "python"] }, ...]
get_skill("docx")
→ full SKILL.md instructions (token-capped, section-aware)Why this exists (honest version)
Claude Code and Codex now load Agent Skills natively, and several MCP skill
servers already exist (skillz,
mcp-skill-hub,
skillserver,
Skills Over MCP). What none of them do is
rank skills against a task query — they rely on the host LLM picking from
descriptions, which degrades as skill libraries grow. This project's focus is
the routing layer: a scored match_skill backed by local embeddings (Ollama +
nomic-embed-text, with automatic keyword fallback), plus strict path
security and context-window discipline.
Measured on a 48-query labeled benchmark over 16 skills (queries written before measuring, not tuned):
Engine | Top-1 | Top-3 | MRR | ms/query |
keyword | 77.1% | 85.4% | 0.813 | ~1 |
semantic (nomic-embed-text) | 93.8% | 97.9% | 0.958 | ~69 |
Both engines score 100% on queries that share words with the skill
description — the gap is entirely on paraphrased (62.5% → 93.8%) and
indirect (68.8% → 87.5%) queries like "combine several invoices into a
single file for printing" → pdf. Reproduce with npm run benchmark.
Every match_skill response reports which engine produced the ranking
(semantic or keyword), so fallback is never silent.
Quick start
Run it straight from npm — no clone, no build:
SKILLS_ROOT=/path/to/skills npx skill-router-mcpWire it into Claude Code (.mcp.json in your project):
{
"mcpServers": {
"skill-router": {
"command": "npx",
"args": ["skill-router-mcp"],
"env": { "SKILLS_ROOT": "/absolute/path/to/your/skills" }
}
}
}Semantic matching is optional — install Ollama and
ollama pull nomic-embed-text to enable it; otherwise it falls back to
keyword matching automatically.
From source
git clone https://github.com/anujkumar8076/skill-router-mcp
cd skill-router-mcp
npm install && npm run build
SKILLS_ROOT=/path/to/skills node dist/index.jsTools
Tool | Purpose |
| All skills — name + description only (cheap, call first) |
| Top-k skills for a task, with 0–1 scores and |
| Full SKILL.md, capped at |
| One H2 section — for skills too big for one fetch |
| Force re-index (a chokidar watcher also auto-reindexes) |
SEP-2640 resources
Skills are also served through the MCP Resources primitive per the Skills Over MCP Working Group draft (SEP-2640), so any spec-aware host can consume them without knowing this server's tools:
skill://index.json— enumerable discovery index (Agent Skills discovery schema 0.2.0)skill://<name>/SKILL.md— each skill as atext/markdownresource, withrequires/works_infrontmatter exposed under theio.modelcontextprotocol.skills/_metaprefixThe
io.modelcontextprotocol/skillsextension capability is declared at initialization
Resource reads pass through the same allowlist validation as the tools.
Skill format
Standard Agent Skills format, with two optional routing fields:
---
name: docx
description: "Use when the user wants to create or edit Word documents."
requires: [filesystem, python] # tools the agent needs to execute this skill
works_in: [claude_code] # environments the skill is known to work in
---
# Instructions...Agents should check requires against their own toolset before loading a
skill — this server delivers instructions; your agent supplies execution.
Configuration
Env var | Default | Meaning |
|
| Directory scanned (recursively) for |
|
| Token cap on |
|
| Set |
|
|
|
|
| Ollama endpoint for embeddings |
|
| Embedding model ( |
Skill vectors are cached by content hash in
~/.cache/skill-router-mcp/embeddings.json, so restarts and re-indexes only
embed skills whose text changed. If Ollama goes down mid-session, matching
degrades to keyword automatically — routing never hard-fails.
Security model
Allowlist, not paths. Skill names are sanitized to
[a-z0-9_-], looked up in an index built at startup, and the resolved file is canonicalized and verified to live insideSKILLS_ROOT. User input never constructs a path.Rejected lookups are logged to stderr.
Trust boundary: skill content is injected into your agent's context. Only point
SKILLS_ROOTat skills you trust — a 2026 study of 31k marketplace skills found ~26% contained prompt-injection or exfiltration patterns.Index-time content lint. Every skill is scanned for suspicious patterns: prompt injection ("ignore previous instructions"), concealment ("don't tell the user"), exfiltration (send-to-URL, known exfil endpoints), credential access (
~/.ssh,.env, API-key harvesting), pipe-to-shell, decode-and-execute, destructive commands, and opaque base64 blobs. Findings are logged at index time, shown aslint_warningsinlist_skills, and attached toget_skillresponses before the content so a reviewing agent sees the warning first. The lint flags — it never blocks — and rules favor precision over recall.
Roadmap
Embedding-based
match_skill(local, Ollamanomic-embed-text) behind theMatcherinterface, with content-hash caching + keyword fallbackRouting benchmark: keyword vs. embeddings on a 48-query labeled set — see benchmark/RESULTS.md
Index-time content lint for suspicious skill patterns (10 rules, surfaced in
list_skillsandget_skill)SEP-2640 alignment:
skill://resources,skill://index.jsondiscovery index, and the skills extension capability
Development
npm test # vitest: security, indexer, matchers, content
npm run build # tsc → dist/
node scripts/smoke.mjs # drive the built server over stdio with real queries
npm run benchmark # keyword vs semantic routing accuracy (needs Ollama)MIT
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/anujkumar8076/skill-router-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server