Skip to main content

Lazy-loading skill discovery for Claude Code via MCP - mirrors Anthropic's Tool Search Tool pattern for Skills.

Project description

๐Ÿ“ก skills-radar

Lazy-loading skill discovery for Claude Code (and other MCP clients). Stop bleeding context tokens on skills you might never use.

skills-radar is a local MCP server that mirrors Anthropic's MCP Tool Search Tool pattern - but for Skills. Instead of preloading every skill's metadata into the system prompt at session start (default Claude Code behavior), skills-radar exposes two tools (search_skills, load_skill) so the agent fetches only what's relevant to the current task.

Why this exists: Anthropic shipped Tool Search for MCP tools in late 2025 (85% token reduction, +8.6% accuracy on Opus 4.5). They haven't shipped the equivalent for Skills yet. With 80+ skills across personal, project, and plugin scopes, your /doctor is probably bleeding 5-10k tokens before you type a word. This fixes that.

Status: ๐Ÿšง v0.1 in active development. Spec: SPEC.md. MVP target: ~3-4h after spec approval.


Two deployment modes

Pick one based on your workflow:

Mode A - Docker Desktop running 24/7 (recommended for shared / cross-platform / Linux / Windows)

One container, every Claude Code session in every project connects to the same http://localhost:6580/mcp. Container has persistent ChromaDB volume + bind-mounted skill paths read-only + watcher on (baked config). Healthy in ~1 second after docker compose up.

git clone https://github.com/darco81/skills-radar
cd skills-radar
docker compose up -d --build

claude mcp add --transport http skills-radar http://localhost:6580/mcp
# Restart Claude Code - /mcp shows skills-radar connected.

Pros: one moving piece, recoverable via docker compose restart, runs on Linux/Windows/macOS, isolated. Limitation on macOS: no MLX inside the container (Linux container can't reach the Apple GPU). Use Mode B for the full MLX stack.

Mode B - Native install (recommended for the 100% local Apple Silicon MLX stack)

stdio subprocess per Claude Code session, OR a long-running HTTP server.

pip install 'skills-radar[mlx]'                # MLX extras for Apple Silicon
skills-radar config-init
skills-radar index

# stdio (auto-starts per CC session):
claude mcp add skills-radar -- skills-radar serve --transport stdio --watch

# OR HTTP, long-running (Mode A behavior natively, with MLX):
skills-radar serve --transport http --watch &
claude mcp add --transport http skills-radar http://localhost:6580/mcp

Pros: full MLX rewriter + reranker on Apple Silicon (4096-dim Qwen3 embedder, MoE Qwen3-Coder for rerank), zero Ollama, zero network. Mac arm64 only.

Recovering token budget (both modes)

{ "skillOverrides": { "*": "name-only" } }

Now Claude only sees skill names in the prompt (~1k tokens for 80 skills), and queries skills-radar for full descriptions when needed.


How it works - Two-Tier Discovery

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ Claude Code session                                    โ”‚
โ”‚  System prompt: mini-index (~1k tokens, names only)    โ”‚
โ”‚  MCP tools: search_skills, load_skill                  โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
           โ”‚
           โ–ผ  intent: clear?
   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
   โ”‚ obvious name?         โ”‚
   โ””โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”˜
        โ”‚ yes         โ”‚ no/ambiguous
        โ–ผ             โ–ผ
 load_skill(name)  search_skills(query)
                       โ”‚
                       โ–ผ
              top-k matches w/ score
                       โ”‚
                       โ–ผ agent picks best
                  load_skill(best.name)
        โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
        โ”‚ Full SKILL.md content    โ”‚
        โ”‚ + trust tier + warnings  โ”‚
        โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Tier 1 (always, ~1k tokens): mini-index of skill names + 1-line summaries. Tier 2 (on demand): full SKILL.md body, fetched only when agent commits to using it.

Result: from ~6k tokens loaded upfront to ~1k tokens + on-demand. ~83% savings, and you can scale to 500 skills without your prompt suffering.


Features

  • ๐Ÿ” Hybrid retrieval - BM25 (lexical) + dense embeddings (semantic), 70/30 by default
  • ๐Ÿ”ฅ Hot reload - drop a SKILL.md, indexed in <1s via watchdog (no Claude restart)
  • ๐Ÿ›ก๏ธ Threat model day-one - trust tiers (TRUSTED / VERIFIED / USER / UNTRUSTED), prompt-injection scanning, size limits, XML-injection stripping
  • ๐Ÿชถ Light by default - sentence-transformers (90MB) + ChromaDB (zero deps)
  • ๐Ÿ”Œ Pluggable - swap embedder (sentence-transformers, MLX [planned], Voyage [planned], OpenAI [planned]); swap store (ChromaDB default, Qdrant [planned])
  • ๐ŸŒ Multi-client - Claude Code, Cursor, Claude Desktop, custom MCP agents
  • ๐Ÿ“ก Streamable HTTP transport (stateless_http=True, json_response=True) for production; stdio for local dev
  • ๐Ÿค– Optional local-LLM query rewriter (Ollama) - rewrites ambiguous queries into richer keyword phrases before embedding
  • โœˆ๏ธ Air-gapped friendly - pre-baked Docker image, offline HF Hub flags
  • ๐Ÿงช 2-tool MCP surface - search_skills + load_skill. Mirrors Anthropic's Tool Search Tool pattern. Eats own dogfood: tool descriptions stay under 200 chars.
  • ๐Ÿšฆ Conditional activation - Hermes-style deterministic pre-filters: platforms gating at index time, requires_tools / fallback_for_tools exposed in search results for client-side policy

Conditional activation

Skills can declare activation conditions in frontmatter - namespaced under metadata.radar.* (agentskills.io convention, same pattern as Hermes' metadata.hermes.*), with top-level fallback:

---
name: figma-compare
description: Compare Figma design with staging implementation.
metadata:
  radar:
    platforms: [macos, linux]      # skipped at index time on other hosts
    requires_tools: [figma-mcp]    # exposed in search results, not filtered
    fallback_for_tools: [web-search]
---

platforms is enforced server-side at index time. requires_tools / fallback_for_tools are exposed, not enforced - the server can't know the client's toolset, so environment policy is the consuming agent's call (same contract as the trust field).

In Docker, set the platform explicitly in ~/.config/skills-radar/config.yaml - auto-detect inside the container reports linux, not the platform of the user whose skills are indexed:

platform: macos

Production deployment

For shared / multi-client / Docker deployments, run the Streamable HTTP transport instead of stdio.

Bare-metal

skills-radar serve --transport http --host 0.0.0.0 --port 6580 --watch

Defaults match MCP Python SDK guidance: stateless_http=True, json_response=True - pair both for horizontal scaling behind a load balancer.

Docker

docker compose up -d --build

The bundled Dockerfile pre-bakes the embedding model so containers start in ~2s instead of doing a 30-60s first-run download. Defaults to non-root uid 1000, offline HF Hub flags, strict sanitization (UNTRUSTED tier + strip_live_exec=true) - community skills mounted via Docker shouldn't be allowed to run host-level commands.

docker-compose.yml mounts your ~/.claude/skills and plugin cache read-only and persists the ChromaDB store as a named volume.

Verify

curl -X POST http://127.0.0.1:6580/mcp \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json,text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"client","version":"0.1.0"}}}'

Should return 200 OK with the server capabilities + tool list.


Local-LLM query rewriter (optional, opt-in)

If you have Ollama running locally, you can have it rewrite ambiguous queries (especially multi-language ones) into richer English keyword phrases before they hit the embedder. Big quality boost for free.

# ~/.config/skills-radar/config.yaml
retrieval:
  rewriter:
    enabled: true
    backend: ollama
    model: gemma4:e4b      # or any small local model with low latency
    url: http://localhost:11434
    timeout: 5.0

Resilient by design: any HTTP error, timeout, or parse failure falls back to the raw query. Off by default - search works exactly as before unless you opt in.


Project status

Phase Status Tag
Spec & architecture โœ… Done -
F1 - MVP (search + load, in-mem) โœ… Done v0.1.0a0
F2 - Production (hot-reload, HTTP, threat model, Docker, integration tests) โœ… Done v0.2.0
F3 - Public release (PyPI, GitHub Actions, FtF post) ๐Ÿ”„ In progress -
F4 - Polish (MLX backend, telemetry, TUI, more backends) โณ Backlog post-1.0

See SPEC.md for full PRD. See docs/ for architecture deep dive, threat model, writing-skills guide, context engineering rationale, and onboarding.


Acknowledgments / Prior art

This project stands on shoulders. Worth checking out:

What skills-radar does differently: 2-tool surface (mirroring Anthropic's pattern), Anthropic-aligned defaults, air-gapped friendly, multi-client by design.


License

MIT (planned). See LICENSE once published.


Author

Built by Dariusz Kowalski - SDET, accessibility advocate, context-engineering enthusiast.

Part of the SDET ecosystem: sdet.it ยท cdat.sdet.it ยท brain.sdet.it (soon)

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

skills_radar-0.5.0a0.tar.gz (107.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

skills_radar-0.5.0a0-py3-none-any.whl (62.0 kB view details)

Uploaded Python 3

File details

Details for the file skills_radar-0.5.0a0.tar.gz.

File metadata

  • Download URL: skills_radar-0.5.0a0.tar.gz
  • Upload date:
  • Size: 107.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for skills_radar-0.5.0a0.tar.gz
Algorithm Hash digest
SHA256 f2038fafd9cc00a10fd3d7c715e4ea8b797ae7d2149adb86d503d7aeab0d8000
MD5 caffa97948cac02496d07e1ffb69b5be
BLAKE2b-256 ed76c522a860151e5589770c0a7f9f834d3501e93af0de2bfa7aa07d90760972

See more details on using hashes here.

Provenance

The following attestation bundles were made for skills_radar-0.5.0a0.tar.gz:

Publisher: publish.yml on darco81/skills-radar

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file skills_radar-0.5.0a0-py3-none-any.whl.

File metadata

  • Download URL: skills_radar-0.5.0a0-py3-none-any.whl
  • Upload date:
  • Size: 62.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for skills_radar-0.5.0a0-py3-none-any.whl
Algorithm Hash digest
SHA256 781b7dbac5fcf936468ce585457df4d5f0ce1af4bdcdd4dd0eb5580214ed2442
MD5 87ecd0fa983e661b3e2960134f21761d
BLAKE2b-256 a75f88f7be6421477aea98cf602af104ab60ab31ad7cb02cd753500330cdc7aa

See more details on using hashes here.

Provenance

The following attestation bundles were made for skills_radar-0.5.0a0-py3-none-any.whl:

Publisher: publish.yml on darco81/skills-radar

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page