Documentation
A condensed reference. For the complete guide, see the README on GitHub.
Skills on disk
Skills live under DATA_DIR/skills/ in either of two shapes. Both use YAML frontmatter
(name, description) followed by the markdown body.
Flat file
A single <name>.md โ the simplest skill:
---
name: commit-messages
description: Write clear, conventional git commit messages.
---
# Writing good commit messages
...the skill body...
Directory (Claude Code convention)
A <name>/SKILL.md plus any supporting files โ reference docs, scripts, templates:
skills/pdf-forms/
โโโ SKILL.md # frontmatter + body
โโโ reference.md # supporting file
โโโ scripts/fill.py # nested supporting file
Supporting files are listed on the skill and referenced in the rendered tool output, so the agent knows
they exist. Manage them from the web UI's file tree โ create, upload, rename, delete, or export the whole
skill as a .zip โ or edit them directly on disk.
Frontmatter
The name must be a slug: lowercase letters, digits, ., _,
- (max 64 chars). It doubles as the MCP tool name (dots sanitized to _) and the
resource URI (skill://<name>). description is surfaced as the MCP
tool/resource description. An optional tags key (a comma-separated string or a YAML list)
organises skills and feeds the search_skills filter. Unknown frontmatter keys are preserved
across round-trips.
Workspaces
A workspace is a named subset of skills served at its own /mcp/w/<slug>
endpoint. It is a JSON file at DATA_DIR/config/workspaces/<slug>.json:
{
"name": "Backend",
"slug": "backend",
"enabled": true, // false = the /mcp/w/<slug> endpoint 404s
"description": "Skills for backend work.",
"skills": ["commit-messages", "pdf-forms"]
}
Served at /mcp/w/backend over HTTP and via --workspace backend over stdio.
The slug is derived from the name and doubles as the filename. Manage workspaces from the
Workspaces page in the web UI, or edit the files directly โ changes are picked up
automatically.
Configuration
Everything lives under DATA_DIR (default ./data locally,
/data in Docker). Config files are written atomically with mode 0600. Edits on
disk are watched (debounced) and hot-reloaded; you can also force a re-read:
curl -X POST -H "Authorization: Bearer $MCP_SKILLS_TOKEN" \
http://localhost:3000/api/reload
data/
โโโ config/
โ โโโ settings.json # port, auth token, auth/authoring toggles, tool mode, httpLiveUpdates
โ โโโ workspaces/
โ โโโ <slug>.json # one file per workspace
โโโ skills/
โโโ <name>.md # flat-file skill
โโโ <name>/ # directory-format skill
โโโ SKILL.md
โโโ <supporting files>
Environment variables
| Variable | Default | Description |
|---|---|---|
DATA_DIR | ./data | Root directory for skills and config |
PORT | 3000 | HTTP listen port (or settings.json) |
MCP_SKILLS_TOKEN | โ | Bearer token; overrides settings.json |
SECURE_LOCAL_NET | false | true disables auth entirely (trusted networks only) |
If no token is configured and SECURE_LOCAL_NET is not set, a random token is generated into
settings.json on first run and logged once.
REST API
Management API under /api, bearer auth, JSON in/out. Errors are non-2xx with
{ "error": "...", "detail": "..." }.
| Method & path | Purpose |
|---|---|
GET /api/status | Version, uptime, skill/workspace counts, auth mode, port |
GET /api/settings | Read auth/authoring toggles, tool mode, live updates |
PATCH /api/settings | Update authoringEnabled / skillToolMode / httpLiveUpdates |
GET /api/skills | List skills (summaries) |
POST /api/skills | Create a skill |
POST /api/skills/import | Import an uploaded .md / directory / zip |
GET /api/skills/:name | Get a skill (with body) |
PATCH /api/skills/:name | Update body/description, or rename |
DELETE /api/skills/:name | Delete a skill |
GET /api/skills/:name/export | Download the skill as a .zip |
GET /api/skills/:name/files/content?path= | Read one supporting file |
PUT /api/skills/:name/files | Add/overwrite a supporting file (promotes to a dir) |
POST /api/skills/:name/folders | Create an empty sub-folder |
POST /api/skills/:name/files/move | Rename / move a file or folder |
DELETE /api/skills/:name/files?path= | Delete a file or folder |
GET/POST /api/workspaces | List / create workspaces |
GET/PATCH/DELETE /api/workspaces/:slug | Get / update / delete a workspace |
POST /api/reload | Re-read all config from disk |
MCP endpoints
| Endpoint | Purpose |
|---|---|
ALL /mcp | Every skill โ each as a tool and a skill:// resource |
ALL /mcp/w/<slug> | A workspace's skills only |
mcp-skills-stdio | stdio transport; --data-dir, optional --workspace <slug> |
The HTTP endpoints speak streamable HTTP and require the bearer token (unless authEnabled is
false). Disabled workspaces return 404; auth failures return 401 before any MCP handling.
Discovering skills
Every endpoint exposes two discovery meta-tools. list_skills returns a JSON catalogue of the
available skills โ name, description, format, tags,
supporting files, updatedAt, and the tool name to call to load each
โ without any skill bodies. search_skills returns the same shape, filtered by a free-text
query (matched against name, description, tags, and body) and/or a tags filter.
An agent discovers what's on offer first, then calls the named tool (or reads the matching
skill://<name> resource) to pull the full contents.
Tool modes
How skills are advertised as tools is set globally (and overridable per workspace) via
skillToolMode:
per-skill(default) โ one no-arg tool per skill; calling it returns that skill's body.loaderโ a singleload_skill(name)tool, so the advertised tool count stays fixed no matter how many skills the endpoint serves.
Resources
Every skill is also an MCP resource at skill://<name>, and each bundled supporting file at
skill://<name>/<path> (path segments percent-encoded so names with spaces or
% round-trip). The endpoint advertises RFC 6570 resource templates
(skill://{name} and skill://{name}/{+path}) with argument completion
over skill names and file paths, and resources/list is paginated with opaque
cursors.
Clients that subscribe receive live updates
(notifications/resources/list_changed and resources/updated) when skills change on
disk. This is always on over stdio. Over HTTP it needs stateful sessions โ enable
httpLiveUpdates in settings and the server keeps a session per client (via
Mcp-Session-Id) and pushes over SSE; otherwise HTTP stays stateless and clients re-poll
resources/list.
Authoring over MCP
When authoring is enabled (the default), every endpoint also exposes tools for agents to write and refine
their own skills โ create_skill, update_skill, rename_skill,
delete_skill, and supporting-file tools (write_skill_file,
read_skill_file, create_skill_folder, move_skill_file,
delete_skill_file). A skill authored through a workspace endpoint is scoped to that workspace by
default; skills authored at the root /mcp are global. Toggle the whole feature with
authoringEnabled in settings.
Security notes
- The auth token is plaintext in
settings.json. Files are mode0600, but anyone with read access toDATA_DIRcan read it. Protect the directory. - One bearer token guards everything. Treat it like a password. Set it via
MCP_SKILLS_TOKEN. - Don't expose the server directly to the internet โ it speaks plain HTTP. Put it behind a TLS-terminating reverse proxy, or bind to localhost / a private network.
- Skills are content, not code โ the server serves markdown; it doesn't execute supporting scripts. But agents may act on what a skill tells them, so treat skill content as trusted instructions.