Skill Router
Routes prompts to skills from the forcedotcom/sf-skills library, which can be cloned and indexed as the router's skill catalog. Skills cover Salesforce tasks such as generating custom/formula fields and permission sets with field-level security, letting an agent load the relevant Salesforce skill file for a given task prompt.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Skill Routerfind the right skill for writing a jest unit test for the parser"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Skill Router
Point a coding agent at the skills a prompt needs before it acts. One job loads one skill. Two jobs load both. The rest of the library stays on disk.
You keep skills as SKILL.md files. This repo compares a prompt with their names and descriptions and returns the skills to load. If nothing is a confident match, it returns an empty list. Empty means: do not pretend a skill applied.
Works with any skill catalog. The files in skills/ are samples so you can run the router immediately. Point it at skills you wrote, or at skills/ from forcedotcom/sf-skills. The samples are not the library. The router is.
How a prompt is routed
flowchart LR
P[Prompt] --> R[Skill router]
R -->|one job| S[Load that skill]
R -->|two jobs| M[Load both skills]
R -->|weak match| A[Return nothing]The match is a normal keyword match, weighted so a rare word counts more than a common one. The code is in lib/score.mjs. It does not read the skill body when it chooses. A skill is included when the prompt uses that skill’s job phrase, such as “formula field” or “code coverage.” The body is loaded afterward, via read_skill, for every skill in the set.
Related MCP server: mcp-skills
Requirements
Node.js 18 or newer
No
npm installto run the router
Try it
git clone https://github.com/lparuchuru-titan/skill-router.git
cd skill-router
node scripts/generate-index.mjsAsk the server which skills a task needs:
printf '%s\n' \
'{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}' \
'{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"find_skill","arguments":{"query":"write a jest unit test for the parser"}}}' \
| node mcp/server.mjsIn the reply, look for "skill": "write-unit-tests". A prompt like "what is a good lasagna recipe" should come back as [].
A prompt with two jobs should name both skills. Try Add a formula field for renewal date and grant field-level security on the sales permission set. The list should include platform-custom-field-generate and platform-permission-set-generate.
Check the whole gold set:
node eval/run-eval.mjs --gate 80That exits non-zero if the returned set stops matching the skills the prompt needs at least 80 percent of the time, or if an out-of-scope prompt fires.
Use it from an agent
The agent should do this on a task prompt:
Call
find_skillwith the user's words.If the list is empty, answer directly. Do not invent a skill.
Call
read_skillon every name in the list, and follow each file. One prompt can need one skill or several. The list is the set to load, not a menu of alternatives.
Claude Code
From the repo root, using your real checkout path:
claude mcp add skill-router --scope user \
-e SKILL_ROUTER_ROOT="$PWD" \
-- node "$PWD/mcp/server.mjs"Cursor, or any other MCP client
Put this in the client's MCP config. Replace the path.
{
"mcpServers": {
"skill-router": {
"command": "node",
"args": ["/absolute/path/to/skill-router/mcp/server.mjs"],
"env": {
"SKILL_ROUTER_ROOT": "/absolute/path/to/skill-router"
}
}
}
}A copy of that block is in mcp/example.mcp.json.
Tools
Tool | When to call it | What you get back |
| First, with the user's task | The skills to load, as a list. One, or several. Read every name. |
| Once per returned skill | The full |
| When you need the catalog | Name and one-line summary. Optional substring filter. |
| A loaded skill has a notes folder | Topic hits inside that skill. |
| After | One note. |
find_skill arguments: query (required), limit (optional, default 5).
Add a skill
flowchart LR
A[Write SKILL.md] --> B[Regenerate the index]
B --> C[Add a gold prompt and run the eval]
C --> D[The next matching prompt loads it]Create
skills/<name>/SKILL.md:
---
name: review-a-migration
description: Review a database migration for locks, backfill, and rollback.
keywords: database migration, schema change, backfill
---
# Review a migration
1. Name the lock risk and the rollback.
2. Do not invent a migration tool that is not in the repo.The description is what the score reads. The keywords line holds the job phrases, separated by commas. A prompt that contains one of those phrases loads this skill. If the same prompt also contains another skill’s phrase, both load. Words in the description alone do not add a second skill. The body is the procedure, loaded only after this skill is chosen.
Add one line to
eval/prompts.jsonlthat must return the new skill. If a real prompt needs this skill and another, add a line whoseexpectedarray lists both. Add an out-of-scope line too if the new words are broad ("expected": []means the router must abstain).Rebuild and test:
node scripts/generate-index.mjs
node eval/run-eval.mjs --gate 80If the exact set drops under 80 percent, or a negative prompt returns a skill, the new description is overlapping a neighbor. Fix the description before you add the next skill. You do not edit the ranker.
To point the router at skills you already have, pass that folder. For the Salesforce skills library, clone it and pass its skills directory:
Run this from the skill-router folder. It clones the Salesforce library next to the router and rewrites the local index. The sample files in skills/ stay where they are.
git clone https://github.com/forcedotcom/sf-skills.git
node scripts/generate-index.mjs --skills-dir sf-skills/skills --out-dir .A folder of skills you wrote is the same command with your path. If the clone is somewhere else, pass that path instead of sf-skills/skills. Then set SKILL_ROUTER_SKILLS_DIR to that same folder when you start the server. Those files need a name and a description. Add a keywords line, comma-separated job phrases, on any skill a prompt should load beside another. Without that line, a prompt still loads the single best match. Retune SKILL_ROUTER_FLOOR with the eval. A floor that worked on this sample catalog will be wrong for a much larger one.
Optional: hint before the turn starts
hooks/route-hint.mjs prints one line when it is confident, and prints nothing otherwise. It will not block the session if the index is missing.
echo '{"prompt":"write a jest unit test for the parser"}' | node hooks/route-hint.mjs
node hooks/review-log.mjsWire it only if you want the nudge on every prompt. Calling find_skill from the agent is the default.
Environment
Variable | Purpose | Default |
| Checkout that holds | Parent of |
| Skills live outside the checkout |
|
| Abstain unless the top score clears this |
|
| Hook only: a matched word must be this distinctive |
|
| Hook log path, or |
|
What is in the repo
skills/*/SKILL.md procedures the agent loads after a hit
router/intents.json phrase list used only by the eval comparison
router/skills-index.json generated catalog
ROUTER.md generated table of the same catalog
mcp/server.mjs stdio MCP server
eval/ gold prompts; a prompt may expect one skill or several
hooks/route-hint.mjs optional one-line hint
docs/ the blog postWhy the match stays on the name and the description
The numbers live in eval/results.md, written by node eval/compare.mjs from eval/prompts.jsonl (75 task prompts, 5 of them asking for two skills, 12 worded differently from the skill, plus 10 that must get no skill) and the sample skills in this repo. The count is the size of that sample, not a limit on your catalog. Quote that file if it disagrees with this table. “Only the skills asked for” means the skills returned are the skills the prompt needs, with none missing and no extras. The shipped row is the one that reads the name and the one-line description. Rare words count more than common ones. The code is in lib/score.mjs.
How we picked | Right skill first | Only the skills asked for | Unrelated prompts answered |
Phrase list. First match wins. | 80% (60/75) | 73.3% (55/75) | 0/10 |
Count the words in common. | 84% (63/75) | 9.3% (7/75) | 0/10 |
Name and one-line description. This is what ships. | 84% (63/75) | 84% (63/75) | 0/10 |
Name, description, and the whole skill file. | 84% (63/75) | 84% (63/75) | 3/10 |
Every prompt that uses the skill’s own words hits, including all 5 prompts that ask for two skills. Of the 12 prompts worded differently, 4 return nothing and 8 return a different skill. They avoid the skill’s vocabulary. Counting shared words puts the right skill first just as often here, and then returns neighboring skills the prompt did not ask for. Searching the whole skill file starts answering prompts that should get nothing. There is no embedding scorer in this repo.
Blog post
docs/Load-the-Right-Skill-First.docx is the external write-up. The skills in the repo are samples. The post is about how a prompt loads one skill or several, including from skills you wrote or from forcedotcom/sf-skills.
License
MIT. Copyright 2026 Lakshmikanth Paruchuru.
This server cannot be deployed
Maintenance
Related MCP Connectors
Search and load AI agent skills. Free metadata; full content requires a Pro or Studio account.
Search verified Claude Code plugins and skills; fetch portable SKILL.md sources. Read-only.
Search your team's shared AI-skill library, get install commands, and save skills from your agent.
Sharebench — search & pull AI skills, agents, prompts & playbooks (SKILL.md) into any MCP client
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables LLMs to dynamically discover and execute tools through a structured skills system. Serves as a documentation hub where skills are defined in directories, allowing progressive loading and interpretation of capabilities.MIT
- AlicenseNot gradedqualityFmaintenanceProvides dynamic, context-aware code assistant skills through hybrid RAG (vector + knowledge graph), enabling runtime skill discovery, automatic toolchain-based recommendations, and on-demand loading from multiple git repositories.20MIT
- AlicenseNot gradedqualityDmaintenanceEnables AI agents to semantically search and retrieve relevant skills from a local Markdown skill database, reducing context waste by loading only needed skills through tiered detail levels and tool calls.15 npm6MIT
- AlicenseAqualityDmaintenanceRoutes SKILL.md libraries to any MCP client, enabling task matching and skill loading with embedding-based scoring, keyword fallback, and context-window discipline.58 npmMIT