Authoring MCP skills¶
A skill is a markdown file that teaches an agent how and when to use a tool.
At boot the MCP server injects each active skill into the description of the
tool(s) it applies to, so the methodology travels with the tool — no
hand-rolled instructions: block required.
This guide is the operator-facing spec for the skill surface: the three text channels and when to use each, where skills live, the frontmatter schema (and which keys are load-bearing), how gating works, and the size limits. For manifests in general (tools, embedders, source roots) see MCP Servers.
TL;DR¶
Opt in:
skills: truein your manifest.Drop a
<tool>.md(or cross-tool<topic>.md) into a<basename>.skills/directory next to your manifest.Give it frontmatter — at minimum
name, plusreferences_tools(which tools it rides on) and usuallyapplies_when(when it should be silent).Put the routing heuristic in
description(one paragraph: when to reach for this tool vs a sibling) and the how-to in the markdown body.
# my_graph_mcp.yaml
name: my_graph
skills: true # turn the skill system on
<!-- my_graph.skills/find_papers.md -->
---
name: find_papers
description: "TRIGGER when the user asks to find / list / filter papers by
author, year, or topic. SKIP for citation-graph traversal (that's a plain
cypher_query MATCH on the CITES edge)."
references_tools: [cypher_query]
applies_when:
graph_has_node_type: [Paper]
---
# Finding papers
Papers carry `title`, `year`, `venue`, and an `author` list...
The three text channels — pick the right one¶
Three manifest mechanisms put text in front of an agent. They have different lifecycles; putting text in the wrong one is the usual mistake.
Channel |
Manifest key |
When the agent sees it |
Use for |
|---|---|---|---|
Init instructions |
|
Once, in the MCP |
One-time orientation that doesn’t need to re-surface. Keep it short. |
Overview preamble |
|
Prepended to every bare |
A sticky reminder tied to schema discovery. |
Skills |
|
Injected into the tool description of every tool a skill applies to. Re-read whenever the agent inspects tools ( |
Per-tool and cross-tool methodology + routing. This is where most guidance belongs. |
Rule of thumb: if the guidance is about how to use a tool, it’s a skill. If
it’s one-time setup context, it’s instructions:. If it’s a reminder that
should ride the schema, it’s overview_prefix:.
Two automatic prefixes also ride the init channel and are closed to operator extension (documented here so you don’t go looking for a hook):
the mode banner (
[kglite-mode] …) — states which conditional tools are registered for the active mode; re-surfaced on baregraph_overview().the batch-load hint (
[kglite-batch-load-hint]) — tells deferred-loading clients to bulk-fetch tool schemas. Include its marker in yourinstructions:to suppress it; you cannot add to it.
Where skills come from (the layers)¶
Skills load from four layers. On a name collision the higher layer wins, so
you can override a bundled skill by shipping one of the same name:
kglite-bundled (lowest) — compiled into the
kglite-mcp-serverbinary fromcrates/kglite-mcp-server/skills/(registered explicitly inmain.rs). The bundled set today:cypher_query,graph_overview,read_code_source,save_graph,explore,code_graph_analysis,code_graph_views. Adding to this set is a kglite change; operators add their own skills via the project layer below — no rebuild.framework defaults — from the mcp-methods crate.
project layer — a
<basename>.skills/directory next to your manifest. Formy_graph_mcp.yamlthat’smy_graph_mcp.skills/. This is the operator’s home: drop skill files here, no code changes.operator-declared paths (highest) — extra directories listed in
skills:(see next section).
The skills: manifest value¶
skills: is polymorphic:
Value |
Meaning |
|---|---|
absent / |
Skills off. No injection, |
|
On: kglite-bundled + framework defaults + the |
|
On, and also load skills from |
|
List form: |
Frontmatter schema¶
Frontmatter is YAML between --- fences. mcp-methods parses exactly these keys;
everything else is ignored (see “load-bearing vs decorative” below).
Key |
Type |
Required |
Meaning |
|---|---|---|---|
|
string |
yes |
Skill identity. Also the tool it injects into by name match (so a skill named |
|
string |
no |
The routing heuristic — TRIGGER/SKIP guidance. Injected into the tool description under a |
|
(the markdown after the frontmatter) |
no |
The methodology. Injected under |
|
list of strings |
no |
Extra tools this skill injects into, beyond its name match. Load-bearing. A |
|
bool (default |
no |
|
|
mapping |
no |
Gating predicate — see below. Absent = always active. |
applies_when — gate a skill to the graphs it fits¶
applies_when keeps a skill silent on graphs it doesn’t apply to (e.g. a
code-graph skill stays off a legal/finance domain graph). Predicates are
AND-combined; an absent predicate is “satisfied”. Re-evaluated against the
live graph on each request, so it tracks post-boot mutations (a workspace
activating a repo).
Predicate |
True when |
|---|---|
|
the graph has any of these node labels |
|
nodes of type |
|
tool |
|
manifest extension |
applies_when:
graph_has_node_type: [Function, Class] # code-tree graphs only
Load-bearing vs decorative keys¶
Only the keys in the table above are read. Several keys appear in older bundled files for human documentation but the loader ignores them — copying them into your skill does nothing:
applies_to(version floors likemcp_methods: ">=0.3.36") — decorative. Activation is not gated on it;applies_when+ the layer the file lives in are what gate a skill.references_arguments,references_properties— decorative.
(references_tools is read — don’t confuse it with the decorative
references_* keys.)
How a skill reaches the agent¶
For each active skill with auto_inject_hint: true, its routing + methodology
are appended to the description of every tool it attaches to — its name-match
tool and every tool in references_tools:
<the tool's own description>
<!-- mcp-skill:find_papers -->
## When to use
<the skill's `description`>
## Methodology
<the skill's body>
A tool can carry several skills (its own + any that reference it); each is
injected once. This rides tools/list, which every MCP client exposes to
the agent.
Warning
Do not rely on prompts/get for agentic retrieval. Skills are also
registered as MCP prompts, but the prompts/* plane was designed for
human-invoked slash commands in chat UIs and is not exposed to the agent
in Claude Code / Claude Desktop / Cursor / Continue. The tool-description
injection above is the channel agents actually read; the prompt registration
is a fallback for the rare custom integration that surfaces prompts.
Size limits¶
The injected body is capped at 16 KB (hard) with a 4 KB soft target — keep bodies tight; 16 KB × N tools is real context cost on every
tools/list. Past 16 KB the body is truncated with a marker.The
description(routing) is small by design and never truncated — it is the highest-value half, so lead with it.
If your methodology is longer than the cap, that’s a signal to split it: a
focused routing description plus a tight body beats a wall of text the agent
skims.
Worked example: a cross-tool orchestration skill¶
The bundled code_graph_analysis skill is the canonical cross-tool pattern —
named after no tool, gated to code graphs, attached to several tools at once:
---
name: code_graph_analysis
description: "TRIGGER for any structural question about a codebase — what
calls / defines / extends / imports X... Map structure with the graph FIRST
(graph_overview → cypher_query → explore), then drop to grep/read_source
only to confirm a detail. Never grep to discover what the graph encodes."
references_tools: [cypher_query, graph_overview, explore, grep, read_source]
applies_when:
graph_has_node_type: [Function, Class]
---
# Code-graph analysis: the sequencing strategy
...
On a code graph it rides all five tool descriptions; on a domain graph
(no Function/Class) it is silent. That is the whole point of skills over
instructions:: gated, per-tool, re-surfacing, and zero hand-maintenance.