skillsearch-mcp
README.md
# 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.5` via 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 `ffmpeg` or `14234` are found
```
user query ──▶ embed (bge-small-zh) ──┐
keyword grams (4/2-gram) ─┴─▶ RRF ──▶ top-k skills + paths
```
## Why
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](https://ollama.com) running locally with the embedding model:
```bash
ollama pull quentinz/bge-small-zh-v1.5
```
## Install
```bash
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 |
| --- | --- | --- |
| `SKILLSEARCH_SKILLS_DIR` | `~/skills` | Skill/knowledge root(s). Multiple dirs separated by `;` (Windows) or `:` (Unix). Scanned recursively for `SKILL.md` files. |
| `SKILLSEARCH_DB` | `~/.cache/skillsearch/vector_index.db` | Where the index lives. Rebuilds automatically when skills change (mtime-based). |
| `OLLAMA_URL` | `http://127.0.0.1:11434` | Ollama endpoint. |
| `EMBED_MODEL` | `quentinz/bge-small-zh-v1.5` | 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
```bash
claude mcp add skillsearch -- python -m skillsearch_mcp
```
or in `.mcp.json`:
```json
{
"mcpServers": {
"skillsearch": {
"command": "python",
"args": ["-m", "skillsearch_mcp"],
"env": { "SKILLSEARCH_SKILLS_DIR": "/path/to/skills" }
}
}
}
```
### Codex
```bash
codex mcp add skillsearch -- python -m skillsearch_mcp
```
or `~/.codex/config.toml`:
```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:
```markdown
---
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_index` pass), 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
This server cannot be deployed
Maintenance
ActivitySlowing
ResponsivenessNo issues