|
| 1 | +# Using `_meta` for Skill Resources |
| 2 | + |
| 3 | +> Guidelines for structured metadata on skill resources served over MCP. |
| 4 | +
|
| 5 | +**Issue:** [#55](https://github.com/modelcontextprotocol/experimental-ext-skills/issues/55) |
| 6 | +**Status:** Draft |
| 7 | +**Related:** [Skill URI Scheme Proposal](skill-uri-scheme.md) |
| 8 | + |
| 9 | +--- |
| 10 | + |
| 11 | +## Overview |
| 12 | + |
| 13 | +The [Skill URI Scheme Proposal](skill-uri-scheme.md) defines a `skill://` URI convention for identifying skill resources over MCP, and notes that servers MAY use the `_meta` field for additional skill metadata — but doesn't specify what keys would be useful or how `_meta` relates to other metadata surfaces. |
| 14 | + |
| 15 | +Skills exposed as MCP resources already have multiple metadata surfaces: `Resource` fields (`name`, `description`, `uri`), `annotations` (`audience`, `priority`), and [Agent Skills frontmatter](https://agentskills.io/specification) in the resource content. Before defining any `_meta` keys, it's important to establish clear boundaries between these surfaces to avoid duplication and fragmentation. |
| 16 | + |
| 17 | +This document establishes scoping principles for when `_meta` is appropriate, defines a namespace convention for skill-related keys, surveys how existing implementations handle skill metadata, and identifies candidate keys for future standardization. |
| 18 | + |
| 19 | +## Metadata Surfaces for Skill Resources |
| 20 | + |
| 21 | +Skill resources have four distinct metadata surfaces. Understanding which metadata goes where is essential before using `_meta`. |
| 22 | + |
| 23 | +| Surface | Fields | Purpose | Who uses it | |
| 24 | +| :--- | :--- | :--- | :--- | |
| 25 | +| **Resource fields** | `name`, `description`, `uri`, `mimeType`, `size` | Structural identity — what the resource is | Protocol layer, all clients | |
| 26 | +| **`annotations`** | `audience`, `priority`, `lastModified` | Display and routing hints — how the client should treat it | Client UX, model routing | |
| 27 | +| **Frontmatter** | `name`, `description`, `allowed-tools`, `compatibility`, etc. | Skill-level semantics — what the skill does and how it behaves | Skill-aware clients, all implementations | |
| 28 | +| **`_meta`** | Extensible key-value object | Additional metadata not covered by the above surfaces | Varies by use case | |
| 29 | + |
| 30 | +### Scoping Principles |
| 31 | + |
| 32 | +**Don't duplicate information across surfaces.** Each piece of metadata should have one authoritative home: |
| 33 | + |
| 34 | +- A skill's name and description belong in `Resource.name` and `Resource.description` |
| 35 | +- Audience routing belongs in `annotations` |
| 36 | +- Skill-level semantics (version, invocation mode, allowed tools) belong in **frontmatter** — these properties apply to skills regardless of whether they are served over MCP, and frontmatter is the mechanism defined by the [Agent Skills specification](https://agentskills.io/specification) for expressing them |
| 37 | +- Distribution-level concerns (inter-server dependencies, provenance, packaging) may be better addressed at the **plugin or distribution layer** rather than per-resource `_meta` |
| 38 | + |
| 39 | +**Prefer existing surfaces over `_meta`.** The bar for adding a `_meta` key should be high: the metadata must not fit cleanly into Resource fields, `annotations`, frontmatter, or a distribution-layer mechanism. `_meta` is the right choice when metadata is specific to the MCP transport context and has no natural home elsewhere. |
| 40 | + |
| 41 | +**Keep `_meta` lightweight.** Well-built clients will cache skill resources locally and use `annotations.lastModified` plus change notifications to stay current. Metadata reads will greatly outnumber content reads, so `_meta` should be kept lean. If clients need skill-level properties (version, invocation mode, allowed tools), they read them from the cached resource content — not from a duplicated `_meta` projection. |
| 42 | + |
| 43 | +### What Not to Put in `_meta` |
| 44 | + |
| 45 | +- **`name` / `description`** — Use `Resource.name` and `Resource.description` |
| 46 | +- **Skill-level semantics** — Fields like `version`, `invocation`, `allowed-tools`, `compatibility`, `model`, `hooks`, `argument-hint`, and `context`/`agent` belong in frontmatter. Duplicating these in `_meta` creates sync risk and blurs the boundary between transport and content. Even as a "materialized view," the duplication is a net pessimization if clients are caching resource content anyway. |
| 47 | +- **Content** — `_meta` is for metadata about the skill, not the skill instructions themselves. Skill content is the resource body. |
| 48 | + |
| 49 | +### Using `annotations` for Skill Resources |
| 50 | + |
| 51 | +Skill resources SHOULD populate `annotations` for effective client behavior: |
| 52 | + |
| 53 | +- **`audience`**: Use `["assistant"]` for skills consumed only by the model. Use `["user", "assistant"]` for skills that may also be displayed in a skill browser or management UI. |
| 54 | +- **`priority`**: Use higher values (e.g., `0.8`) for the primary SKILL.md resource and lower values (e.g., `0.3`) for supporting reference files. This helps clients decide what to load first in progressive disclosure. |
| 55 | +- **`lastModified`**: ISO 8601 timestamp. Enables cache invalidation when skill content changes. |
| 56 | + |
| 57 | +## Namespace Convention |
| 58 | + |
| 59 | +When `_meta` keys are needed for skill resources, implementations SHOULD use the `io.modelcontextprotocol.skills/` reverse-domain prefix. This: |
| 60 | + |
| 61 | +- **Follows the MCP spec:** The [2025-11-25 specification](https://modelcontextprotocol.io/specification/2025-11-25/server/resources) recommends reverse DNS notation for `_meta` keys (e.g., `com.example/key` rather than `example.com/key`). Keys without a namespace prefix are valid but risk collisions. |
| 62 | +- **Signals MCP-layer semantics:** These keys describe how skills relate to the MCP ecosystem, distinct from skill-level behavior in frontmatter. |
| 63 | +- **Avoids collisions:** Implementation-specific keys (like FastMCP's `fastmcp` key) can coexist alongside namespaced keys without conflict. |
| 64 | + |
| 65 | +Implementation-specific keys MAY use their own namespace (e.g., `com.fastmcp/` or a top-level scoped key like `fastmcp`), but SHOULD NOT use the `io.modelcontextprotocol.skills/` prefix for non-standardized keys. |
| 66 | + |
| 67 | +## Survey of Existing Implementations |
| 68 | + |
| 69 | +Four implementations illustrate the current state of skill metadata in the ecosystem. Each has made different choices about what metadata to surface and how. |
| 70 | + |
| 71 | +### NimbleBrain |
| 72 | + |
| 73 | +[NimbleBrain](https://github.com/NimbleBrainInc/skills) exposes skills as `skill://` resources directly on their MCP servers, with skill content colocated alongside the tools it describes. Five reference servers ([mcp-ipinfo](https://github.com/NimbleBrainInc/mcp-ipinfo), [mcp-webfetch](https://github.com/NimbleBrainInc/mcp-webfetch), [mcp-pdfco](https://github.com/NimbleBrainInc/mcp-pdfco), [mcp-folk](https://github.com/NimbleBrainInc/mcp-folk), [mcp-brave-search](https://github.com/NimbleBrainInc/mcp-brave-search)) independently converged on this pattern. |
| 74 | + |
| 75 | +At the registry layer, NimbleBrain uses a `skill` field in registry `_meta` to support `.skill` artifact bundles (ZIP containing SKILL.md + manifest.json). The individual skill resources on the servers don't currently carry `_meta` keys — metadata lives at the registry level rather than per-resource. |
| 76 | + |
| 77 | +> "Skills living as skill:// resources on the server itself was the natural endpoint of that consolidation. The skill context is colocated with the tools it describes, versioned together, shipped together." — [Mat Goldsborough](https://github.com/mgoldsborough) (NimbleBrain), via Discord |
| 78 | +
|
| 79 | +### FastMCP 3.0 |
| 80 | + |
| 81 | +[FastMCP](https://gofastmcp.com/servers/providers/skills) added native skills support in version 3.0 with a pull-based resource update model. FastMCP uses a `fastmcp` key in `_meta` containing structured metadata including tags, version, and a skill sub-object with the skill name and manifest flag. This is an implementation-specific namespace — not reverse-DNS prefixed, but scoped under a single top-level key to avoid collisions. |
| 82 | + |
| 83 | +### Agent Skills Specification |
| 84 | + |
| 85 | +The [Agent Skills specification](https://agentskills.io/specification) defines 6 allowed top-level fields in SKILL.md YAML frontmatter: `name`, `description`, `license`, `compatibility`, `allowed-tools`, and `metadata`. The `metadata` field is a flat `dict[str, str]` intended as the extension point for client-specific data. |
| 86 | + |
| 87 | +However, multiple implementations already ship fields beyond this set. `disable-model-invocation` is supported by Claude Code, Cursor, and VS Code Copilot. `user-invocable` is supported by Claude Code and VS Code Copilot. Claude Code additionally supports `model`, `context`, `agent`, `hooks`, and `argument-hint`. The gap between spec and implementation is significant — non-spec fields are already shipping in three independent implementations. |
| 88 | + |
| 89 | +The agentskills community has also proposed open frontmatter with namespacing guidance ([agentskills#211](https://github.com/agentskills/agentskills/issues/211)), where non-standard fields would be prefixed with `{AGENT_NAME}-` or nested under `{AGENT_NAME}:` (e.g., `claude:model`). This reinforces keeping skill-level semantics in frontmatter while reserving `_meta` for concerns that frontmatter cannot address. |
| 90 | + |
| 91 | +### Summary |
| 92 | + |
| 93 | +| Implementation | Metadata surface | Namespace approach | Skill-specific keys | |
| 94 | +| :--- | :--- | :--- | :--- | |
| 95 | +| NimbleBrain | Registry `_meta` | `skill` field | Bundle metadata (manifest.json) | |
| 96 | +| FastMCP 3.0 | Resource `_meta` | `fastmcp` top-level key | `tags`, `version`, `skill.name`, `skill.is_manifest` | |
| 97 | +| Agent Skills spec | YAML frontmatter | Flat + `metadata` dict | `name`, `description`, `license`, `compatibility`, `allowed-tools` | |
| 98 | + |
| 99 | +**Key observations:** |
| 100 | + |
| 101 | +- FastMCP uses a non-namespaced but scoped key (`fastmcp`) — valid but doesn't follow the MCP spec's reverse DNS recommendation |
| 102 | +- NimbleBrain's metadata lives at the registry layer, not per-resource — complementary to per-resource `_meta` |
| 103 | +- The Agent Skills spec's `metadata` dict is flat `dict[str, str]`, which can't express lists or nested objects — MCP's `_meta` can |
| 104 | +- Skill-level semantics (version, invocation, tools) are well-served by frontmatter; most metadata needs for skills today don't require `_meta` |
| 105 | + |
| 106 | +## Example: Skill Resource Without `_meta` |
| 107 | + |
| 108 | +Most skill resources won't need `_meta` keys. Resource fields, `annotations`, and frontmatter cover the common cases. This example uses the `skill://` URI convention from the [Skill URI Scheme Proposal](skill-uri-scheme.md). |
| 109 | + |
| 110 | +```json |
| 111 | +{ |
| 112 | + "resources": [ |
| 113 | + { |
| 114 | + "uri": "skill://ipinfo/usage", |
| 115 | + "name": "ipinfo-usage", |
| 116 | + "description": "Tool selection guidance and context reuse patterns for IP lookup tools.", |
| 117 | + "mimeType": "text/markdown", |
| 118 | + "annotations": { |
| 119 | + "audience": ["assistant"], |
| 120 | + "priority": 0.8, |
| 121 | + "lastModified": "2026-03-01T12:00:00Z" |
| 122 | + } |
| 123 | + }, |
| 124 | + { |
| 125 | + "uri": "skill://code-review/SKILL.md", |
| 126 | + "name": "code-review", |
| 127 | + "description": "Structured code review workflow with checklist-driven analysis and inline annotations.", |
| 128 | + "mimeType": "text/markdown", |
| 129 | + "annotations": { |
| 130 | + "audience": ["assistant"], |
| 131 | + "priority": 0.8, |
| 132 | + "lastModified": "2026-02-15T09:30:00Z" |
| 133 | + } |
| 134 | + }, |
| 135 | + { |
| 136 | + "uri": "skill://code-review/references/security-checklist.md", |
| 137 | + "name": "code-review-security-checklist", |
| 138 | + "description": "OWASP-aligned security review checklist for code review skill.", |
| 139 | + "mimeType": "text/markdown", |
| 140 | + "annotations": { |
| 141 | + "audience": ["assistant"], |
| 142 | + "priority": 0.3, |
| 143 | + "lastModified": "2026-02-15T09:30:00Z" |
| 144 | + } |
| 145 | + } |
| 146 | + ] |
| 147 | +} |
| 148 | +``` |
| 149 | + |
| 150 | +Skill-level metadata (version, allowed tools, invocation mode) lives in the SKILL.md frontmatter, read from the resource content. The `annotations.priority` field differentiates the primary skill from supporting content, enabling clients to load the main skill first and defer references until needed. |
| 151 | + |
| 152 | +## Candidate Keys for Future Standardization |
| 153 | + |
| 154 | +The following areas have been identified as potential uses for `_meta` on skill resources. Each requires further discussion to determine whether `_meta` is the right home — some may be better addressed at the distribution/plugin layer, in frontmatter, or in MCP itself. |
| 155 | + |
| 156 | +| Area | Description | Open Questions | Community References | |
| 157 | +| :--- | :--- | :--- | :--- | |
| 158 | +| **Provenance** | Server origin, authorship, canonical source for skills aggregated across servers | Could be solved at the plugin/distribution layer instead of per-resource. Also applies to non-MCP skills, suggesting frontmatter may be more appropriate. | [Skill URI Scheme Proposal](skill-uri-scheme.md) | |
| 159 | +| **Dependencies** | Inter-skill and inter-server dependency declarations for host-mediated resolution | Plugin-level dependency resolution may be more appropriate than per-skill declarations. Versioning is also an open MCP-wide concern (see server versioning SEPs). | [agentskills#21](https://github.com/agentskills/agentskills/issues/21), [agentskills#195](https://github.com/agentskills/agentskills/issues/195) | |
| 160 | +| **Input/output schemas** | Typed contracts for skills-as-tools bridge | May belong in frontmatter if applicable to non-MCP skills. | [agentskills#136](https://github.com/agentskills/agentskills/issues/136), [agentskills#61](https://github.com/agentskills/agentskills/issues/61) | |
| 161 | +| **Content integrity** | Hash for verifying skill content hasn't been modified in transit | Potentially MCP-transport-specific; no frontmatter equivalent. | — | |
| 162 | +| **Activation triggers** | File patterns, keywords, or intents that trigger skill loading | Likely a skill-level concern better addressed in frontmatter. | [agentskills#57](https://github.com/agentskills/agentskills/issues/57), [agentskills#64](https://github.com/agentskills/agentskills/issues/64) | |
| 163 | + |
| 164 | +The general razor for evaluating candidates: **does this metadata also apply to non-MCP skills?** If so, it should be solved in frontmatter rather than `_meta`, to avoid fragmenting the skills ecosystem across transport mechanisms. |
| 165 | + |
| 166 | +## Relationship to Other Work |
| 167 | + |
| 168 | +### Skill URI Scheme (PR #53) |
| 169 | + |
| 170 | +The [Skill URI Scheme Proposal](skill-uri-scheme.md) defines the `skill://` URI convention for identifying skill resources. The URI scheme determines *how skills are addressed*; this document establishes conventions for *what metadata they carry* in `_meta`, when `_meta` is warranted at all. |
| 171 | + |
| 172 | +### Agent Skills Spec Frontmatter |
| 173 | + |
| 174 | +Frontmatter remains the authoritative source for skill-level semantics. This document intentionally does not recommend `_meta` keys that duplicate frontmatter. The [open frontmatter proposal (agentskills#211)](https://github.com/agentskills/agentskills/issues/211) and ongoing convergence across implementations (Claude Code, Cursor, VS Code Copilot) will continue to expand what frontmatter can express — reducing the surface area where `_meta` is needed. |
| 175 | + |
| 176 | +### Plugin and Distribution Layer |
| 177 | + |
| 178 | +Concerns like provenance, inter-server dependencies, and packaging may be more naturally addressed at the plugin or distribution layer (e.g., Claude Code plugins) rather than per-resource `_meta`. The distribution layer can express inter-server *and* inter-skill dependencies, with a broader scope than individual skill resources. This document acknowledges that deferred candidates may migrate to that layer as it matures. |
| 179 | + |
| 180 | +### Registry `skills.json` Proposal |
| 181 | + |
| 182 | +The [registry `skills.json` proposal](https://github.com/modelcontextprotocol/registry/discussions/895) addresses discovery metadata at the registry layer — categories, search tags, server-skill pairing. Registry metadata helps users *find* skills; `_meta` (when used) provides per-resource context at runtime. |
| 183 | + |
| 184 | +### SEP-2076: Skills as a First-Class Primitive |
| 185 | + |
| 186 | +[SEP-2076](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2076) proposes `skills/list` and `skills/get` as protocol methods. The scoping principles and namespace convention in this document apply regardless of whether skills are exposed as resources or as protocol primitives — `_meta` is available on both. |
| 187 | + |
| 188 | +## References |
| 189 | + |
| 190 | +- [MCP Resources Specification (2025-11-25)](https://modelcontextprotocol.io/specification/2025-11-25/server/resources) — Resource schema, `annotations`, `_meta` field |
| 191 | +- [Agent Skills Specification](https://agentskills.io/specification) — Frontmatter field definitions |
| 192 | +- [Skill URI Scheme Proposal](skill-uri-scheme.md) — `skill://` URI convention |
| 193 | +- [SEP-2076: Skills as MCP Primitives](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2076) — `skills/list` and `skills/get` proposal |
| 194 | +- [Registry `skills.json` Discussion](https://github.com/modelcontextprotocol/registry/discussions/895) — Registry-layer skill metadata |
| 195 | +- [agentskills#211: Open Frontmatter with Namespacing](https://github.com/agentskills/agentskills/issues/211) — Namespace convention for non-standard fields |
| 196 | +- [FastMCP Skills Support](https://gofastmcp.com/servers/providers/skills) — FastMCP 3.0 skills provider |
| 197 | +- [NimbleBrain Skills](https://github.com/NimbleBrainInc/skills) — Registry-integrated skill bundles |
0 commit comments