skill-mcp
skill-mcp
Local stdio MCP server that helps an agent pick which local SKILL.md files to use — and keeps the context small.
Replacement for the deleted skillbind CLI: MCP-only, no host adapters, no marketplace.
30-second demo
Drop more than three
SKILL.mdfiles into~/.claude/skills(or another configured root).Call
suggest_skillswith a prompt. You get at most 3names[]ready for bind. If nothing matches:This directory has no matching skill for that prompt.Call
bind_skillswith those names (hard max 3).Call
write_host_contract. ClaudeCLAUDE.mdand Cursor.cursor/rulesnow list only the bound skills and forbid the rest.
{ "prompt": "fix login redirect" }{ "names": ["auth-login", "auth-oauth", "auth-token"] }Release v0.2.0
Notes: GitHub Release v0.2.0. This README is part of that release.
Why the cap is hard
Max 3 bound skills. A larger token budget never raises that cap.
Default budget is 4000 tokens (CJK-aware: Han, Hiragana, Katakana, Hangul). Budget can only drop more candidates.
Lean by default:
name/description/path. FullSKILL.mdbody is opt-in viaread_skill.Default roots:
~/.claude/skills,~/.agents/skills,~/.codex/skills,~/.config/opencode/skills.
Install (Mac / local attach)
Requires Node 20+. The one-shot script builds the server and writes absolute-path MCP snippets, then merges them into Claude Desktop and Cursor configs when those files can be created:
git clone https://github.com/tsumon/skill-mcp.git
cd skill-mcp
./scripts/install.sh./scripts/install.sh runs npm install, npm run build, then node dist/install-cli.js. It writes:
docs/output/claude-desktop.mcp.jsondocs/output/cursor.mcp.json
Those files use an absolute args path to dist/index.js on this machine. Restart Claude Desktop / Cursor.
Mac Claude Desktop file: ~/Library/Application Support/Claude/claude_desktop_config.json
Linux: ~/.config/Claude/claude_desktop_config.json
Cursor: ~/.cursor/mcp.json
Do not paste a relative ./dist/index.js. Use the generated file, or replace the args entry with the absolute path printed by the installer.
Optional env vars:
SKILL_MCP_ROOTS— comma-separated user roots (overrides defaults)SKILL_MCP_PROJECT_ROOTS/SKILL_MCP_PLUGIN_ROOTS— extra roots with project / plugin shadowing tiersSKILL_MCP_STATE_DIR— global binding directory (default~/.config/skill-mcp)SKILL_MCP_PROJECT_DIR— project bind root (default cwd)SKILL_MCP_SESSION_ID— in-memory session bind keySKILL_MCP_EMBEDDINGS—auto(default) /on/off. Ollama is a soft dependency.
Optional single-file binary (bun compile):
./scripts/pack.sh
# dist-pack/skill-mcp — point host args at this absolute pathFallback if bun is missing: npm run build && node dist/index.js. Details in docs/PACKAGING.md.
Host contract (takes effect)
get_binding still returns a contract string, and skill-mcp://binding/contract is the same text. v0.2.0 also writes host files in one shot so Claude Code and Cursor actually load it:
node dist/index.js write-contract
# or MCP tool write_host_contractWrites:
<stateDir>/HOST-CONTRACT.md(canonical)<project>/CLAUDE.md(managedskill-mcp-contractblock)<project>/.cursor/rules/skill-mcp-contract.mdc(alwaysApply: true)
The generated files list only the currently bound skills and say not to load any other SKILL.md. Empty binding: do not load any skill until the user binds.
Empty suggest
When no skill matches the prompt, suggest_skills sets none: true and:
empty_message:This directory has no matching skill for that prompt.empty_message_zh:该目录下没有匹配该提示的技能。
It does not invent names to bind.
G — Auto-uninstall (dry-run / --apply)
Targets idle user-tier skills (not in the current binding) and shadowed user-tier copies.
Mode | What happens |
Default / MCP without | Dry-run. Reports candidates. Does not move or delete. |
| Moves each candidate into |
node dist/index.js archive-idle
node dist/index.js archive-idle --applyMCP: archive_idle with no args is dry-run; { "apply": true } archives.
Never silent-deletes. Bound skills stay. Project-tier skills stay. Recover by copying back from archive/.
H — Native skills bypass (toggle / restore / risk)
Claude Code otherwise stuffs every local skill description into the listing. Optional bypass writes skillOverrides: { "<name>": "name-only" } into ~/.claude/settings.json so the host listing keeps names but drops descriptions. skill-mcp then suggest/bind/read progressively.
Command | Effect |
| Backup current settings, write name-only overrides |
| Restore the backup in one step |
node dist/index.js native-skills enable
node dist/index.js native-skills restoreRisk: this is a routing fight with Claude Code native skills. Name-only hides descriptions from the model listing; it does not delete SKILL.md files. Plugin skills are not covered by skillOverrides. If routing feels wrong, restore immediately. skill-mcp never changes this setting unless you call enable.
Core tools
list_skills
Catalog SKILL.md files from configured roots. Duplicate names are shadowed (project beats user beats plugin). Shadowed rows include a plain-language shadow_message.
suggest_skills
Lexically rank skills for a prompt (optional Ollama embeddings). Returns at most 3. names is ready for bind_skills.
bind_skills
Persist a lean binding. More than 3 names is an error. Optional scope: session / project / global (default). Priority: session > project > global.
Other tools
Tool | Purpose |
| Resolved lean binding + |
| Inject Claude + Cursor rule files |
| Why those skills are bound |
| Reload roots without restarting |
| Per skill ( |
| Explicit full |
| Dry-run: roots, counts, binding path |
| Dry-run idle/shadowed user skills; |
|
|
Eval and CI
Offline goldens (ZH / JA / KO plus multi-skill conflicts):
npm test
npx tsc --noEmit
npm run eval.github/workflows/ci.yml runs those on pull requests and main.
Invariants
Max 3 bound skills; budget never raises the cap
Not a marketplace; no ranker retrain
Lean list / suggest / bind — no full bodies by default
Local stdio MCP only
G never silent-deletes; default dry-run
H is optional and one-step reversible
License
MIT
中文说明见 README.zh-CN.md.