skill-vault
<p align="center">
<img src="assets/skill-vault.png" width="200" alt="Skill Vault">
</p>
<h1 align="center">Skill Vault</h1>
<p align="center">
<b>A self-hostable, semantic skill registry for AI agents โ over a single MCP endpoint.</b><br/>
Query the skills you need when you need them. Keep context small. Trust what you pull.
</p>
<p align="center">
<a href="https://www.apache.org/licenses/LICENSE-2.0"><img alt="License: Apache-2.0" src="https://img.shields.io/badge/license-Apache--2.0-blue.svg"></a>
<a href="https://www.python.org/"><img alt="Python" src="https://img.shields.io/badge/python-3.11+-3776AB.svg"></a>
<a href="https://www.python.org/"><img alt="MCP" src="https://img.shields.io/badge/MCP-FastMCP-8A2BE2.svg"></a>
<a href="https://pytest.org/"><img alt="Tests" src="https://img.shields.io/badge/tests-111%20passing-brightgreen.svg"></a>
<a href="https://pytest.org/"><img alt="Coverage" src="https://img.shields.io/badge/coverage-88%25-brightgreen.svg"></a>
<a href="https://github.com/vikasudasi/skill-vault/actions"><img alt="CI" src="https://img.shields.io/github/actions/workflow/status/vikasudasi/skill-vault/ci.yml?branch=main"></a>
</p>
---
# Skill Vault
Stop shipping a thousand skill files into your agent's context. Point your agent at **one** MCP endpoint; it pulls exactly the skills it needs, on demand, and can verify they haven't been tampered with.
- **One endpoint.** `search_skills("postgres schema migration")` โ ranked, lightweight skill *cards* โ `get_skill(id)` for the full body only when needed.
- **Private + public.** Every agent gets its own personal skill vault *and* read access to a curated global store.
- **Trusted supply chain.** Skills are content-addressed (sha256) and optionally ed25519-signed. A `verified` tier means a curator vouched for the content โ not just that someone uploaded it.
- **Self-hosted.** SQLite + local embeddings + optional pgvector. No managed service, no third party sees your skills, no per-query cost.
---
<details>
<summary><b>๐ Table of Contents</b></summary>
1. [The Problem](#the-problem)
2. [The Solution](#the-solution)
3. [Features](#features)
4. [Why Skill Vault](#why-skill-vault) *(positioning vs skills-mcp / agentregistry)*
5. [Architecture](#architecture)
6. [Quickstart](#quickstart)
7. [MCP Configuration](#mcp-configuration)
8. [Trust & Security Model](#trust--security-model)
9. [API Reference](#api-reference)
10. [CLI](#cli)
11. [Roadmap](#roadmap)
12. [FAQ](#faq)
13. [Contributing](#contributing)
14. [License](#license)
</details>
---
## The Problem
**Every skill costs context.** Progressive-disclosure skill systems pay roughly **~50 tokens per skill** just to keep the *description* in context, and far more for the full instructions.
| # of skills in context | ~tokens of pure skill metadata |
|---|---|
| 100 | 5k |
| 1,000 | 50k |
| 10,000 | **500k+ โ exceeds most context windows** |
Local skill files don't sync across machines, teams, or agents. Thousands of files also become a maintenance nightmare โ duplicated, stale, unversioned, and unverified (you have no idea who wrote them or whether they're safe to follow).
---
## The Solution
Skill Vault is a **registry + retrieval layer**, not another file format.
- Skills live in a centralized, versioned, content-addressed store.
- The agent wires in **exactly one MCP endpoint**.
- `search_skills(query)` returns light **cards** (name + one-liner + trust tier + cosine score) โ cheap.
- `get_skill(id)` returns the **full SKILL.md body** only for the skill the agent actually wants.
- A **personal vault** lets each agent push its own hard-won capabilities and pull them back anywhere, alongside the curated global library.
The result: an agent with access to **10,000 skills** carries only **~50 tokens** of registry description in context, and retrieves the one it needs *at the moment it needs it*.
---
## Features
- ๐งญ **Semantic search** โ local `all-MiniLM-L6-v2` embeddings (384-d) over skill name, description, tags, and triggers; ranked by cosine similarity. Embed *metadata*, not whole bodies, to keep the index small.
- ๐ **Per-agent identity** โ API keys (sha256-at-rest, shown once at onboarding) with `global` / `personal` / owner-only scope enforcement at the tool layer.
- ๐ฆ **Private skill vaults** โ every agent publishes and retrieves its own skills; cross-agent private access is always denied.
- ๐ **Trust & supply chain** โ sha256 content hashing (integrity pin) + optional ed25519 signatures. Trust tiers: `verified` (curator-signed) ยท `user` (owner's own) ยท `public` (community).
- ๐งฌ **Versioned & immutable** โ skills are versioned, content-addressed, forward-only. Previous versions remain addressable and hash-pinned.
- ๐ฅ๏ธ **Web dashboard + homepage** โ agent management, onboarding, per-agent skill browser, key rotation/revocation, and a ready-to-copy `/configure` guide.
- ๐ฑ **17 curated seed skills** (with one `verified` sample) so the registry is useful out of the box.
- ๐ **Self-hosted & transport-flexible** โ stdio for local agents, streamable-HTTP/SSE for remote. SQLite + sqlite-vec by default; pgvector drop-in for scale-out.
---
## Why Skill Vault
There are two adjacent tools worth benchmarking against. We occupy the open middle: **self-hosted + per-agent identity + verifiable supply chain.**
| Dimension | **Skill Vault** | skills-mcp | agentregistry |
|---|---|---|---|
| Hosting | **Self-hosted** (your infra) | Managed (Cloudflare Worker) | Self-hosted (org) |
| Vector store | **SQLite + sqlite-vec** (or pgvector) | Qdrant (managed) | Varies |
| Embeddings | **Local, free, private** | Managed API | โ |
| Per-agent identity | โ
**Yes** (API key, hash-at-rest) | โ No (shared public library) | Partially (org accounts) |
| Private per-agent vault | โ
**Yes** | โ No | โ Not per-agent |
| Trust / supply chain | โ
**verified/user/public + ed25519 sigs** | โ ๏ธ Limited | โ ๏ธ Governance only |
| Content integrity | โ
**sha256 + client verification** | โ | โ ๏ธ |
| Skill versioning | โ
**Immutable versions** | Partially | Yes |
| Primary purpose | **Capability registry + retrieval** | Shared free skill library | Org catalog/governance |
**The short version:** *skills-mcp* is a big shared library with no identity and no verification; *agentregistry* is org governance with no per-agent personal vaults. **Skill Vault is both a personal capability vault and a verifiable public registry** โ for a single agent or a whole team, on your own hardware.
---
## Architecture
```mermaid
flowchart LR
subgraph "Your Agent"
A[AI Agent / LLM]
end
subgraph "Skill Vault"
MCP["MCP endpoint<br/><b>skill-vault serve</b><br/>stdio / streamable-http"]
TOOLS["MCP Tools<br/>search ยท get ยท publish ยท update<br/>delete ยท list_mine ยท list_global"]
AUTH["Auth<br/>API-key resolve ยท scope<br/>rate-limit"]
INDEX["Semantic Index<br/>embeddings + cosine rank"]
TRUST["Trust Layer<br/>sha256 hash ยท ed25519 sig<br/>verified/user/public"]
DB[("SQLite<br/>skills ยท versions ยท keys ยท trust<br/>+ sqlite-vec sidecar")]
WEB["Web + Dashboard<br/><b>skill-vault web</b><br/>FastAPI / uvicorn"]
MCP --> TOOLS
TOOLS --> AUTH
TOOLS --> INDEX
TOOLS --> TRUST
TOOLS --> DB
INDEX --> DB
TRUST --> DB
MCP --- WEB
WEB --> DB
end
A -->|"one endpoint"| MCP
A -.->|"retrieve SKILL.md content"| GET["get_skill(id)"]
```
**Flow:** the agent calls the MCP endpoint once โ the tool layer authenticates the caller and enforces scope โ the semantic index ranks matching skill *cards* โ the trust layer reports + verifies integrity โ SQLite persists everything. For full-body retrieval, `get_skill(id)` re-derives the content hash and **refuses to return tampered content**.
Two processes share one data path: `skill-vault serve` (MCP, `:8000/mcp`) and `skill-vault web` (dashboard, `:8080`).
---
## Quickstart
### From source
```bash
git clone https://github.com/vikasudasi/skill-vault.git
cd skill-vault
make install # creates .venv + installs deps
# 1. Initialize the database
.venv/bin/skill-vault init
# 2. Seed the curated library (17 skills, incl. 1 verified)
.venv/bin/skill-vault seed
# 3. Run the local MCP server (stdio) for one agent
.venv/bin/skill-vault serve
```
For a remote/HTTP setup (web + MCP):
```bash
.venv/bin/skill-vault serve --transport streamable-http # :8000/mcp
.venv/bin/skill-vault web # :8080
```
### Docker
```bash
docker compose up --build
# MCP streamable-http: http://localhost:8000/mcp
# Dashboard: http://localhost:8080/dashboard
```
### Create your first agent + key
```bash
.venv/bin/skill-vault onboard --name "my-agent"
# prints a raw api key (sv_...) ONCE โ save it
```
Or via the dashboard: `http://<host>:8080/dashboard/onboard`
---
## MCP Configuration
Add Skill Vault to any MCP-capable client. **Server name:** `skill-vault`.
### Local / stdio
```json
{
"mcpServers": {
"skill-vault": {
"command": "/absolute/path/to/.venv/bin/skill-vault",
"args": ["serve"]
}
}
}
```
### Remote / streamable-http
```json
{
"mcpServers": {
"skill-vault": {
"url": "https://your-host/mcp",
"headers": { "Authorization": "Bearer sv_YOUR_AGENT_KEY" }
}
}
}
```
> **Auth note:** Skill Vault passes the agent key as a **per-tool argument** (`agent_key=...`) for private/global operations โ no connection-level key header is strictly required. On streamable-http, forward the `Authorization` header for convenience.
On the running instance, the `/configure` page renders copy-paste-ready snippets for both transports.
---
## Trust & Security Model
### Integrity (content-addressed)
Every skill version stores `content_hash = sha256(canonical(skill))`. On `get_skill`, the server **re-derives** the hash and compares โ if the stored body doesn't match its pin, the server raises `SV_INTEGRITY` and never returns tampered content.
### Signatures (verifiable supply chain)
Skills can additionally carry an **ed25519 signature** over the canonical payload, produced by a curator holding `SKILL_VAULT_CURATOR_KEY`. Consumers call `verify` (or read the `verified` flag on `get_skill`) before following a pulled skill.
### Trust tiers
| Tier | Meaning |
|---|---|
| `verified` | Curator-signed โ a known verifier vouched for the exact content |
| `user` | Owner's own personal skill |
| `public` | Community/global, unsigned |
Hosts control what they serve via `SKILL_VAULT_TRUST_ALLOW` (default `verified,user`). The trust scope/crypto is policy-driven so enterprise governance (RBAC/audit/policy) can be layered on without rearchitecting.
### Security posture
- API keys stored **sha256-hashed only** โ raw keys never persisted, shown once at onboarding.
- Per-key **rate limiting** on the public endpoint.
- Dashboard uses **HTTP Basic** with credentials distinct from agent keys.
- Remote access expected behind **TLS** (Caddy/nginx/Traefik) โ see [Deployment](docs/DEPLOYMENT.md).
- Vulnerability reporting: see [SECURITY.md](SECURITY.md).
---
## API Reference
All tools return a JSON tool-result. Errors use stable codes.
| Code | Meaning |
|---|---|
| `SV_UNAUTHENTICATED` | Missing/invalid agent key |
| `SV_FORBIDDEN` | Valid key, no access (cross-agent/private) |
| `SV_NOT_FOUND` | Skill/version not found |
| `SV_INVALID_SKILL` | Malformed skill / missing required frontmatter |
| `SV_INTEGRITY` | Content hash mismatch (tamper) |
| `SV_RATE_LIMITED` | Key over quota |
| `SV_CONFLICT` | Duplicate name in scope |
### `search_skills(query, scope="global", limit=10, min_trust=None, agent_key=None)`
Semantic search. Returns lightweight **cards** `(id, name, description, tags, trust, score, version)`. `scope`: `global` (no key needed) ยท `all` / `personal` (requires `agent_key`).
### `get_skill(id, version=None, agent_key=None)`
Full SKILL.md body + `{trust, verified, content_hash}`. Re-verifies integrity; raises `SV_INTEGRITY` on mismatch. Global skills readable by anyone; personal only by owner.
### `publish_skill(skill, visibility="personal", agent_key)`
`skill = {name, description, tags[], triggers[], body, meta{}}`. Creates a new skill (version 1, hashed, `user` or `public` tier). `SV_CONFLICT` if name exists in the agent's scope โ use `update_skill`.
### `update_skill(id, skill, agent_key)`
Owner/curator only. Appends a new **immutable version** (`version = max+1`), updates `current_version_id`. Previous versions stay addressable and hash-pinned.
### `delete_skill(id, agent_key)`
Owner-only removal (keeps version history for audit).
### `list_my_skills(agent_key, scope="all")`
Cards (no bodies) for the authenticated agent's personal vault (+ optionally global).
### `list_global_skills(limit=20, offset=0)`
Paged cards from the curated global store โ no key needed.
---
## CLI
```
skill-vault init Initialize DB + apply migrations
skill-vault migrate Apply pending forward-only migrations
skill-vault onboard Create an agent + issue first API key (shown once)
skill-vault whoami Resolve an API key to an identity
skill-vault seed Seed curated skills from the library (--curator-key to sign)
skill-vault reindex (Re)embed skill versions into the vector index
skill-vault verify Check integrity + signature for a skill version
skill-vault curator gen-key Generate a curator ed25519 keypair
skill-vault serve Run the MCP server (stdio or --transport streamable-http)
skill-vault web Run the web dashboard (FastAPI/uvicorn)
skill-vault backup Snapshot DB + vector sidecars
skill-vault restore Restore a snapshot
```
Examples:
```bash
# Sign seed skills as verified
export SKILL_VAULT_CURATOR_KEY="<base64 ed25519 privkey>"
.venv/bin/skill-vault seed
# One-command public launcher (no systemd)
./scripts/run-public.sh
```
---
## Roadmap
**Now / current release (v0.1)**
- โ
Core MCP registry + semantic search + auth + trust
- โ
Web dashboard, homepage, `/configure`
- โ
Deployment (two-process, Docker, systemd, backup/restore)
- โ
Test suite (111 tests, 88% cov) + CI
- โ
Seed library (17 skills)
**Next**
- ๐ฆ Release automation, signed release tags, PyPI publishing
- ๐งช More curated skills + community submission flow
- ๐ฌ pgvector backend hardening + horizontal scale notes
- ๐ Usage analytics / skill health signals
**Later (open-core tier, monetization deferred)**
- ๐ Org governance: SSO, RBAC, audit, compliance policies
- ๐ค Shared public library federation / multi-tenant hosting
- ๐ Native agent integrations beyond the MCP tool surface
---
## FAQ
**Q: How is this different from just pasting a folder of skills into my agent?**
A: A folder floods context with every skill's description (~50 tokens each) and doesn't sync or verify. Skill Vault keeps only a tiny registry endpoint in context and retrieves the one skill you need *at the moment* โ verified.
**Q: Do I need a GPU or an embedding API key?**
A: No. Embeddings run locally via `all-MiniLM-L6-v2` (sentence-transformers). Works on a CPU-only box.
**Q: Is my data sent anywhere?**
A: No third party *by default*. Everything runs on your host; the default vector backend is local SQLite. (If you opt into `pgvector`, it goes to your own Postgres.)
**Q: Who can see my personal skills?**
A: Only you. Cross-agent private access is always rejected at the tool layer, and scope filtering happens at query time.
**Q: What does "verified" actually mean?**
A: A skill with a valid ed25519 signature from a curator whose public key you trust. It proves the *exact content* you pulled is what the curator signed โ nothing more, nothing less.
**Q: Can one agent access another agent's vault?**
A: No, unless the skills are `global`. Personal scope is owner-only, always.
**Q: How do I run this in production?**
A: See [Deployment](docs/DEPLOYMENT.md) โ two processes behind a TLS reverse proxy, with systemd units and a no-systemd fallback launcher.
---
## Contributing
Contributions are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for the full guide.
**Quick pointers:**
- Python โฅ 3.11, `from __future__ import annotations`, type hints throughout.
- Run the gates before submitting: `make check` (ruff + format + mypy) and `pytest` with โฅ85% coverage.
- Add skills to `skill_vault/data/skills/` (see the format of existing entries) and run `skill-vault seed` to ingest.
- Open an issue first for behaviour changes; keep PRs focused.
---
## License
Copyright ยฉ 2026 Vik Udasi. Licensed under the **Apache License, Version 2.0**. See [LICENSE](LICENSE). You may use, modify, and distribute this software, including in commercial products; attribution required.
TDQS
Scored across 7 tools
Each tool targets a distinct operation: search, fetch, publish, update, delete, and two separate list scopes. The only potential overlap is between search_skills and get_skill, but search returns relevant results while get returns full content by id. No tool ambiguously duplicates another.
All tools follow a consistent verb_noun pattern with snake_case: delete_skill, search_skills, get_skill, publish_skill, update_skill, list_my_skills, list_global_skills. The pluralization correctly reflects whether the tool returns multiple items or operates on one.
With exactly 7 tools, the set covers the core operations for a skill vault without being bloated or sparse. Each tool earns its place in the lifecycle (create, read, update, delete, search, list). This is a well-scoped collection for the server's purpose.
The toolset provides complete CRUD coverage: publish (create), get and list (read), update (update), and delete (delete). Additionally, search and the differentiation between personal and global lists round out the expected workflows for a vault. No missing operations that would force agents to work around gaps.