Skip to main content
Glama

Skills MCP

Serves Agent Skills over MCP, so any client can discover and read them — including clients that only speak tools.

Skills are declared as pinned dependencies in skills.toml and fetched at image build time. Nothing is fetched at runtime.

docker run -p 8000:8000 kubed/skills-mcp:latest

Point a client at http://localhost:8000/mcp and it gets four tools — never one per skill. Skills are data behind read_skill, not entries in the tool list.

tool

returns

cost

list_packs()

every pack and its groups, with counts

~75 tokens

list_skills(pack)

name: description for that pack or group

~1–2k tokens

read_skill(skill, file)

one skill's instructions, manifest, or a file

one skill

read_pack_file(pack, file)

a file the pack ships outside any skill

one file

Each layer is cheap enough to call speculatively and narrow enough that the next one stays small:

list_packs()                        →  grafana (50), n8n (14), penpot (12), and grafana's 7 groups
list_skills(pack="grafana-lgtm")    →  6 skills, ~945 tokens
read_skill(skill="loki")            →  the instructions to follow
read_skill(skill="loki", file="_manifest")  →  what else it ships

Pack-level files

The Agent Skills spec keeps a skill self-contained: references are "relative paths from the skill root". Some kits ignore that. Penpot's twelve skills point at shared/* from 190 places, so served on their own they are a maze of dead links.

A source can declare those directories in skills.toml, and they are served by read_pack_file — never as skills:

extras = ["shared", "workflows"]

Nothing about a skill changes. read_skill still serves each skill's own directory completely, and the two spaces do not overlap: a skill's files are unreachable through read_pack_file, and pack files are absent from any skill's _manifest.

Related MCP server: skillsmcp

Filtering to one pack

pack accepts either a source (n8n, grafana, penpot) or one of its groups (grafana-core, grafana-lgtm). That is the soft filter, chosen per call.

For a hard scope there are two levers, and both are ceilings the model cannot widen past.

Per client — the X-Skill-Pack header. Set it once in the client's connection config and that client sees one pack, whatever it asks for. This is how one deployment serves several single-pack agents:

X-Skill-Pack: penpot

In n8n that is a Header Auth credential on the MCP Client Tool node — a plumbed constant on the node, not something the model fills in.

Per deployment — SKILL_PACKS. Scopes the whole instance; the rest of the catalogue is not loaded at all:

SKILL_PACKS=n8n

They compose: the header narrows within whatever SKILL_PACKS already allows.

Why three tools and not resources

MCP has three primitives — tools, resources and prompts. Skills map naturally onto resources, and SkillsDirectoryProvider still publishes them that way for clients that speak the resource half of the protocol. But many clients only implement tools — n8n's MCP Client Tool is one — and to those a resource-only server looks empty.

FastMCP ships a generic ResourcesAsTools bridge for exactly that, but it is too expensive here: it lists three entries per skill (SKILL.md, _manifest, and a file template), each repeating the skill's full description. For 64 skills that is 192 entries and ~16k tokens on every listing call — the opposite of what skills are for. The three tools above are hand-rolled to give the same access for a fraction of it.

Skills as dependencies

skills.toml is the source of truth:

[[source]]
name = "n8n"
repo = "https://github.com/n8n-io/skills.git"
ref  = "180b8415e3b73f78828cfa01e908e67f89f2a139"
path = "skills"

ref is a commit, so an image is reproducible. path is the subdirectory holding the skill folders — not the repo root. skills/ is gitignored; upstream markdown is never vendored into this repo, so a skill bump reviews as a one-line ref change.

Currently served: 64 skills from n8n-io/skills and grafana/skills.

Fetch them locally:

python scripts/fetch_skills.py            # fetch at the pinned refs
python scripts/fetch_skills.py --update   # repin everything to upstream HEAD

The Update Skills workflow runs that weekly and opens a PR.

Adding a source

Add a [[source]] block, then one COPY line in the Dockerfile's skills stage. A source may nest its skills at any depth — the server discovers roots by walking for SKILL.md, because SkillsDirectoryProvider itself does not recurse.

Configuration

variable

default

meaning

SKILLS_DIR

/skills

directory to scan

SKILL_PACKS

(all)

comma-separated packs to serve; hard scope

TRANSPORT

http

http or stdio

HOST

0.0.0.0

bind address

PORT

8000

port

GET /health reports status, the packs served, and the skill count.

Deploying

kubectl apply -k .

Runs in the flow namespace as skills-mcp:8000. There is no authentication: every skill served is public markdown, the server has no write path and holds no credentials.

Development

pip install -e .[test]
pytest

License

MIT

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

No tool schema history has been recorded yet.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/kubed-io/skills-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server