Skip to main content
Glama
README.md
# mcp-skillbox

> **⚠️ Archived** — This repository is archived. Its functionality (skill discovery via `list_skills`/`search_skills`/`load_skill`) has been consolidated into the [opencode-beanie-plugin](https://github.com/beremaran/opencode-beanie-plugin) (feature: `skillbox`). Please use that instead.

An MCP (Model Context Protocol) server that aggregates agent skills from [skills.sh](https://skills.sh) and compatible GitHub skill repositories and exposes exactly three tools — `list_skills`, `search_skills`, `load_skill` — so agents can discover and load skills **without bloating their context window**: metadata-first browsing (compact summaries, no descriptions by default), and full skill content fetched only on demand, with byte caps and size reporting.

## Features

- **Context-budget design**: `list_skills` and `search_skills` return compact metadata only (no descriptions by default); full skill content is fetched only via `load_skill`, on demand.
- **Description truncation** at 300 chars when descriptions are requested (`include_description`).
- **`size_bytes` reporting** on every loaded file, plus `max_bytes` caps — both per-call (`load_skill`) and registry-level (`SKILL_MAX_BYTES`).
- **TTL caching** (list/search 60s, details 5 min, GitHub trees 10 min) to cut API calls.
- **Resilient HTTP**: retries with exponential backoff + jitter, timeouts, and `Retry-After` handling for 429s.
- **Registry abstraction** with two adapters: skills.sh (OIDC token mode, richer data incl. install counts) and GitHub (unauthenticated mode that works out of the box).
- **Optional skills.sh OIDC token mode** for install counts and leaderboard data.

## Tools

| Tool | Purpose | Key params | Context cost |
| --- | --- | --- | --- |
| `list_skills` | Browse available skills; compact metadata (id, name, source, installs) | `view`, `page`, `per_page`, `include_description` | Low (no descriptions by default; ≤300 chars if requested) |
| `search_skills` | Find skills by keyword in name/description | `query` (min 2 chars), `limit`, `owner`, `include_description` | Low (≤300-char previews) |
| `load_skill` | Fetch the FULL `SKILL.md` plus optional supporting files | `id`, `include_supporting_files`, `max_bytes` | High — the only expensive call; use only after picking a skill |

> `load_skill` is the only context-heavy call; `list_skills`/`search_skills` are intentionally cheap.

## How it works / architecture

`src/server.ts` registers the 3 tools; `factory.createRegistry()` picks the adapter (auto: token → skills.sh, else GitHub); each adapter implements the `SkillRegistry` interface (`listSkills`/`searchSkills`/`loadSkill`); both use TTL caches and retry/backoff. GitHub mode reads repo trees via the GitHub API and fetches `SKILL.md` files from `raw.githubusercontent.com`.

```
┌─────────────┐   stdio JSON-RPC   ┌───────────────────────────────┐
│  Agent /    │ ◄────────────────► │  mcp-skillbox  (src/server.ts) │
│ MCP client  │                    │  list_skills / search_skills  │
└─────────────┘                    │  / load_skill   (3 tools)     │
                                   └───────────────┬───────────────┘
                                                   │  SkillRegistry
                                   ┌───────────────▼───────────────┐
                                   │ factory.createRegistry(config)│
                                   │  auto: token ? skills.sh      │
                                   │        : github               │
                        └──────┬──────────────────────────────────┬────────┘
                               │                                  │
                              ┌▼───────────────────────┐   ┌──────▼─────────────────┐
                              │ skills.sh API          │   │ GitHub API (trees)     │
                              │ /api/v1/*              │   │ + raw.githubusercontent│
                              │ Bearer OIDC            │   │ (unauthenticated)      │
                              └────────────────────────┘   └────────────────────────┘
                         TTL caches + retry/backoff live in both adapters
```

## Requirements

- Node.js >= 18
- npm

## Install & run

```
npm install
npm run build
npm run smoke:mcp   # optional end-to-end check over a real stdio MCP session
```

## MCP client configuration

mcp-skillbox speaks MCP over stdio; register it in any MCP-capable client. All configs below assume a local checkout; swap in `npx -y github:beremaran/mcp-skillbox` (works today; once published, `npx -y mcp-skillbox`).

### Claude Code

Add to `.mcp.json` (project) or `~/.claude.json` (user):

```json
{
  "mcpServers": {
    "skillbox": {
      "command": "npx",
      "args": ["-y", "mcp-skillbox"],
      "env": {
        "SKILLS_SH_TOKEN": "your-vercel-oidc-token"
      }
    }
  }
}
```

For local development use the built artifact directly:

```json
{
  "mcpServers": {
    "skillbox": {
      "command": "node",
      "args": ["/absolute/path/to/agent-skillbox/dist/index.js"],
      "env": {}
    }
  }
}
```

Equivalent CLI form:

```
claude mcp add skillbox -- npx -y mcp-skillbox
claude mcp add skillbox -- node /absolute/path/to/agent-skillbox/dist/index.js
```

### opencode

Add to `opencode.json` under the `mcp` key. Verified schema (opencode 1.18.x): a local stdio server uses `"type": "local"` and `command` is an **ARRAY** of strings (executable + args together — there is no separate `args` key):

```json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "skillbox": {
      "type": "local",
      "command": ["node", "/absolute/path/to/agent-skillbox/dist/index.js"],
      "enabled": true,
      "environment": {
        "SKILLS_SH_TOKEN": "your-vercel-oidc-token"
      }
    }
  }
}
```

### Cursor / VS Code / any stdio MCP client

Generic `mcpServers` shape:

```json
{
  "mcpServers": {
    "skillbox": {
      "command": "node",
      "args": ["/absolute/path/to/agent-skillbox/dist/index.js"]
    }
  }
}
```

### Published package

From the public GitHub repo (works today): `npx -y github:beremaran/mcp-skillbox` (command `npx`, args `["-y", "github:beremaran/mcp-skillbox"]`). Once published to npm, any client can also use `npx -y mcp-skillbox` (command `npx`, args `["-y", "mcp-skillbox"]`).

## Environment variables

| Variable | Default | Description |
| --- | --- | --- |
| `SKILLS_SH_TOKEN` | (none) | Optional. Enables the skills.sh API mode with richer data (install counts, leaderboard views). Obtainable from a Vercel project via OIDC, per the skills.sh docs. |
| `SKILL_REGISTRY` | `auto` | `auto` (token present → skills.sh, else GitHub), `skills-sh`, or `github`. |
| `SKILL_GITHUB_SOURCES` | `vercel-labs/skills, anthropics/skills, obra/superpowers, mattpocock/skills, microsoft/azure-skills, supabase/agent-skills, prisma/skills` | Comma-separated `owner/repo` list for GitHub mode. |
| `SKILL_MAX_BYTES` | `200000` | Registry-level byte cap applied to loaded skill content. |
| `GITHUB_TOKEN` | (none) | Optional GitHub token; sent as Authorization on `api.github.com` calls to raise API rate limits. |
| `SKILL_DEBUG` | (none) | Set to `1` or `true` to log registry selection and diagnostics to stderr. |

## How registry selection works

In `auto` mode: if `SKILLS_SH_TOKEN` is set → skills.sh registry (its API requires `Authorization: Bearer <VERCEL_OIDC_TOKEN>`; requests without it get 401, rate limit ~600 req/min). Otherwise → GitHub registry using the public GitHub API + `raw.githubusercontent.com`, which works immediately with no credentials. `SKILL_REGISTRY=github` or `=skills-sh` forces a specific adapter (skills-sh without a token throws a clear `RegistryAuthError`).

## Example agent conversation (context-budget behavior)

```
Agent:  I need to add tests for a React component. Let me find a skill.

Agent → search_skills({ query: "react testing", include_description: true })

mcp-skillbox → { count: 3, results: [
  { id: "vercel-labs/agent-skills/react-testing",  name: "React Testing",       source: "vercel-labs/agent-skills", description: "Setup and patterns for testing React components with Vitest..." },
  { id: "mattpocock/skills/react-hooks-testing",   name: "React Hooks Testing", source: "mattpocock/skills",        description: "Best practices for testing custom React hooks in isolation..." },
  { id: "prisma/skills/e2e-testing",               name: "E2E Testing",         source: "prisma/skills",             description: "End-to-end testing setup for web apps..." }
] }

Agent:  "react-testing" is the best fit.

Agent → load_skill({ id: "vercel-labs/agent-skills/react-testing" })

mcp-skillbox → { id: "vercel-labs/agent-skills/react-testing", name: "React Testing", files: [
  { path: "SKILL.md", size_bytes: 8421, contents: "# React Testing\n..." }
] }

Agent:  Uses the full SKILL.md instructions to write the tests.
```

The agent only ever paid for the full content of the skill it actually used — the two losing skills cost nothing beyond their ~300-char previews.

## Development

- `npm test` — vitest unit/integration tests (8 files)
- `npm run typecheck` — `tsc --noEmit`
- `npm run build` — emit `dist/`
- `npm run dev` — watch build
- `npm run smoke` — real-network GitHub registry smoke (`tsx src/smoke.ts`)
- `npm run smoke:mcp` — full end-to-end MCP smoke over stdio (`node scripts/mcp-smoke.mjs`; spawns `dist/index.js`, lists 3 tools, calls `list_skills` + `load_skill` for real)
- Tests live in `tests/` (cache, factory, frontmatter, github, http, index, server, skills-sh).

> **IMPORTANT**: The `@modelcontextprotocol/sdk` root import is broken in v1.30.0 — always import from subpaths (`@modelcontextprotocol/sdk/server/mcp.js`, `/server/stdio.js`, `/client/index.js`, `/inMemory.js`). The `registerTool(name, config, callback)` form is the tool-registration API.

## Limitations & roadmap

- skills.sh install counts/leaderboard require the OIDC token; GitHub mode has no install counts.
- GitHub unauthenticated API rate limits (~60 req/hr for contents/trees) — mitigated by tree caching (10 min TTL) and fetching file contents from `raw.githubusercontent.com` (which is not rate-limited the same way).
- No write/install tools yet. Roadmap: install skills to a target directory, packs support, multi-registry federation, HTTP/SSE transport, resource endpoints for installed skills.

## License

MIT — see [LICENSE](LICENSE).

TDQS

A4.2/5.0

Scored across 3 tools

Disambiguation5/5

Each tool has a distinct role: list for browsing, search for finding by keyword, load for retrieving full content. There is no overlap in functionality or purpose.

Naming Consistency4/5

Tools follow a verb_noun pattern, but 'list_skills' and 'search_skills' use plural while 'load_skill' uses singular. This minor inconsistency is predictable and does not cause confusion.

Tool Count5/5

With 3 tools, the server is well-scoped for a skill registry: browse, search, and retrieve full content. Each tool serves a necessary function without unnecessary bloat.

Completeness5/5

The tool surface covers the full workflow for discovering and using skills: listing available skills, searching them, and loading the full content when needed. No obvious gaps exist for the stated purpose.

Maintenance

ActivitySlowing
ResponsivenessNo issues