-
Notifications
You must be signed in to change notification settings - Fork 1
Libraries
A library is the first segment of every URI served — skill://grafana/… —
and a client sees the catalogue one library at a time. A library holds no
material of its own: it picks plugins, and every field is in
Configuration.
libraries:
- name: grafana
description: Observability skills — Grafana, Loki and friends.
source: github://grafana/skills?ref=51d33e71e191b409bbd25fc7be2684c610d18166
- name: ops
description: Everything anybody here publishes about running things.
plugins: [house-runbooks]
pluginSelector:
categories: [operations]
tags: ["oncall,runbooks", lgtm]A library has a name, an optional description, and any of three ways to pick plugins. Their union is the library.
| Written | Means |
|---|---|
source: <address> |
a marketplace: every entry of the marketplace.json published there |
plugins: [a, b@other] |
those plugins by name, yours or a marketplace's |
pluginSelector: {categories, tags} |
every plugin matching the query, marketplace entries included |
source and pluginSelector on one library is refused at load: a marketplace
library's shape is the catalogue's, and a query would have to run before the
catalogue had been read. source plus a named plugins: list is fine — that
adds beside the catalogue without reshaping it.
A library carries no tags and no category of its own. Tagging is what a
plugin does, so ?tags=observability reaches a library only through what its
plugins say, and ?library=grafana is how a client asks for Grafana. See
Scoping.
pluginSelector:
categories: [design, engineering] # any of these
tags: ["ui,tokens", penpot] # (ui and tokens) or penpotAcross the two fields it is AND, as in every faceted search: a category and a
set of tags narrow each other. Within categories it can only be OR — a plugin
has exactly one category, so "in design and engineering" would match nothing,
and a comma in one is refused. Within tags a comma means all of and
separate items mean any of. That is one comma rule for the YAML and for the
query string alike.
What a tag matches is a plugin's tags and its keywords together: which of
the two a publisher reached for is not a distinction worth making to whoever is
searching.
A library whose source is an address is read as somebody else's catalogue.
It is looked for at .claude-plugin/marketplace.json,
.github/plugin/marketplace.json and .agents/plugins/marketplace.json, first
found. A library whose source holds none of them carries an error in
/health naming what was looked for, and still serves whatever
its plugins: list adds beside it.
Every entry becomes a plugin with the entry's own name, description, category,
tags and version, and an id of <entry>@<library> — so two catalogues may
publish a testing and both are reachable. An entry's own skills list is what
that plugin serves, which is how Grafana's seven plugins arrive already split
and how its repository's template skill stays out without a glob written here.
Where an entry's source may point:
| Form | Read as |
|---|---|
"./", "./plugins/x"
|
a subdirectory of the marketplace's own tree — one clone for the catalogue and all of it |
{source: github, repo, ref|sha} |
that repository, through your declared git source for github.com |
{source: url, url, ref|sha} |
that repository, through the declared source it sits under |
{source: git-subdir, url, path, ref|sha} |
the same, at path inside it |
A catalogue does not get to introduce a host: an entry naming a repository under
no declared source is skipped, because a host is where a credential and a
refresh interval are configured. npm and archive entries are skipped —
nothing here unpacks a package — and a command entry always is, because
nothing fetched is ever executed. strict: false entries, where the entry
would replace the plugin's own manifest, are skipped until something we pull
publishes one.
Every skip carries its reason under the library's skipped in
/health, so a plugin an operator expected and cannot find says
why, and one bad entry never costs the rest of the catalogue.
- Every marketplace is read, and its entries join the set of known plugins beside the ones the config declares.
-
Every library is resolved against that whole set: its marketplace's
entries, then its
plugins:names, then itspluginSelector, deduplicated, in that order.
The order is the point. A selector runs over marketplace plugins too, so a query of your own can regroup somebody else's catalogue into a library of your own without copying anything.
No field of a marketplace entry can be overridden. To change anything about one — its category, its tags, which of its files are served — declare your own plugin against the same repository and pick what you want:
plugins:
- name: penpot-shared
category: design
source: github://penpot/penpot-ai-kit?ref=efbefc935ee43804502976aa5ec9659a8bb7e207
skills: []
prompts: []
files: ["shared/**/*", "workflows/**/*"]
libraries:
- name: penpot
source: github://penpot/penpot-ai-kit?ref=efbefc935ee43804502976aa5ec9659a8bb7e207
plugins: [penpot-shared]The cost is nil in fetches: the address is the same URL at the same ref, so the catalogue's plugin and yours share one clone. What you get is a plugin that is yours — your category, your tags, your globs — beside one that stays exactly what its publisher published.
Two plugins in one library can mint the same skill URI, the same library-level
file URI or the same prompt name. Only one of the two could ever be read, so the
later one in the library's order fails in that library and says what it
collided with, under the library's conflicts in /health. The earlier one
serves unaffected, and the failed plugin serves normally in every other library
it belongs to.
Inside a single plugin the same clash is not a conflict: the first of two skills
or prompts at one name serves, and each thing left out is listed under that
plugin's skipped.
Home · Config file · Plugins · Scoping · Configuration
Configuration, Tools and Endpoints are generated by scripts/generate_wiki.py from the config models, a live server's tool list and the OpenAPI document — so they describe the server that shipped, not the one someone remembered. Prose for a generated page goes in wiki/notes/<page>.notes.md.
mcp-kb · MIT
Getting started
The config file
What clients get
Reference