skillsearch-mcp
skillsearch-mcp
Semantic skill-library search as an MCP server. Given a natural-language query, it finds the most relevant skills (or any Markdown knowledge files) in your local skill directories — works out of the box with Claude Code, Codex, Cursor, and any MCP client.
Built on a small, local-first stack:
Embeddings:
bge-small-zh-v1.5via Ollama (works for Chinese + English)Storage: SQLite (WAL) — vector blobs + keyword columns, no heavy vector DB
Ranking: dual-channel Reciprocal Rank Fusion (cosine + substring keywords), so both semantic intent and exact terms like
ffmpegor14234are found
user query ──▶ embed (bge-small-zh) ──┐
keyword grams (4/2-gram) ─┴─▶ RRF ──▶ top-k skills + pathsWhy
Claude Code and Codex already have filesystem access. What they lack is a fast way to answer "which of my 100+ skills/knowledge files matches this task?". This server turns your skill library into a searchable index that any MCP client can query in ~100ms (local Ollama).
Requirements
Python 3.10+
Ollama running locally with the embedding model:
ollama pull quentinz/bge-small-zh-v1.5Install
pip install skillsearch-mcp # from PyPI (once published)
# or from source
git clone https://github.com/<you>/skillsearch-mcp.git
cd skillsearch-mcp && pip install -e .Configuration
Environment variables:
Variable | Default | Description |
|
| Skill/knowledge root(s). Multiple dirs separated by |
|
| Where the index lives. Rebuilds automatically when skills change (mtime-based). |
|
| Ollama endpoint. |
|
| Embedding model. Any Ollama embedding model works, but index must be rebuilt after changing it (server does this automatically via meta check). |
Client setup
Claude Code
claude mcp add skillsearch -- python -m skillsearch_mcpor in .mcp.json:
{
"mcpServers": {
"skillsearch": {
"command": "python",
"args": ["-m", "skillsearch_mcp"],
"env": { "SKILLSEARCH_SKILLS_DIR": "/path/to/skills" }
}
}
}Codex
codex mcp add skillsearch -- python -m skillsearch_mcpor ~/.codex/config.toml:
[mcp_servers.skillsearch]
command = "python"
args = ["-m", "skillsearch_mcp"]
env = { SKILLSEARCH_SKILLS_DIR = "/path/to/skills" }Tools
skill_search(query, k=5)
Semantic search. Returns top-k matching skills with name, score, description, and absolute path. k is capped at 10.
skill_list()
List every indexed skill (name + description + path). Useful for exploration or for clients that want a full inventory.
Skill file format
Any directory containing SKILL.md files is indexed. A minimal example:
---
name: ffmpeg-video-batch-processing
description: ffmpeg video batch processing — watermark, compress, rename
---
# ffmpeg video batch processing
...full content...name and description from the frontmatter are used for search. Files
under .archive, .git, references, assets, templates,
node_modules are skipped.
How indexing works
On first query the server scans
SKILLSEARCH_SKILLS_DIR, embeds the first 512 chars of each skill, and stores vectors in SQLite (WAL).On subsequent queries it only re-indexes files whose mtime changed (cheap
update_indexpass), and prunes deleted ones.Query path: embed the query with the retrieval prefix, cosine-search the vector table, run 4-gram/2-gram substring scoring over name/description/ full_text, then fuse both rankings with RRF.
License
MIT