Skip to main content
New in version 3.0.0 An agent skill is a folder with a SKILL.md file of instructions and any supporting files those instructions refer to. Agents usually load skills from a local folder, so every machine needs its own copy and every copy drifts. Serving skills from an MCP server keeps one maintained copy in your repository: agents that connect read the current version, and an update ships when you deploy the server. FastMCP serves a skills folder in two ways at once:
  • As resources. Each skill’s files are ordinary MCP resources under skill:// URIs. Every MCP client can list and read them today.
  • Through Skills discovery. Since FastMCP 4.1.2, the MCP Skills extension adds skills/list and skills/get, which return each skill’s frontmatter and a manifest of its files with sizes and SHA-256 digests. A host that supports the extension can offer your skills to its agent without a separate install step. This support is experimental in FastMCP, and few hosts read it yet.
The rest of this page builds one server that does both, then shows what each kind of client sees.

Lay out the skills folder

Keep skills in a folder in the repository that owns them, one folder per skill. The folder name is the skill’s name and becomes its URI.
Start each SKILL.md with Agent Skills frontmatter. Skills discovery requires a name equal to the folder name, made of lowercase letters, digits, and single hyphens, and a description of up to 1,024 characters. The description is what an agent reads to decide whether the skill applies, so say when to use it.
Refer to supporting files by their path relative to the skill folder, as references/testing.md does above. Clients resolve that path against the skill’s URI.

Serve the folder

SkillsDirectoryProvider publishes every skill folder under a root directory. Setting experimental_skills=True on it, and registering SkillsExtension with the same provider instance, also turns on Skills discovery.
Save this as server.py next to the skills/ folder and run python server.py. The server can carry tools, resources, and prompts as usual; skills are one more provider. To serve skills as resources only, leave out experimental_skills=True and the SkillsExtension line. To turn discovery off again later, remove both.

Read skills as resources

Any MCP client sees each skill as two listed resources: its SKILL.md and a synthetic _manifest.
Supporting files are not listed one by one. Each skill exposes a resource template, skill://server-authoring/{path*}, and the manifest names the files that template serves:
Read a supporting file by joining its path onto the skill’s URI, such as skill://server-authoring/references/testing.md. To list every file as its own resource instead, see supporting files.

Install skills into a local agent

Agents that only read skills from disk can still use a served copy. sync_skills() downloads every skill on the server into a local skills folder, and download_skill() downloads one. Both skip skills that already exist unless you pass overwrite=True.
fastmcp.utilities.skills also provides list_skills(), which lists skill names from the resource listing, and get_skill_manifest(), which reads one manifest. These helpers work with any server that publishes skills as resources, with or without discovery.

Discover skills with the Skills extension

A client that opts into the extension can ask the server for its skills directly. Discovery requires a connection on a modern MCP protocol version, which Client negotiates by default.
Listing returns metadata only. The agent reads the files it needs through resources/read, and should check each file against its manifest record before using it:
A mismatch means the file changed between discovery and the read. Refresh the entry with client.get_skill(uri) and read again. client.list_skills() follows every page of skills/list; use list_skills_mcp() to fetch one page at a time. The client methods only transport entries. Deciding when to load a skill, asking a user to approve it, and running anything it describes are the host’s job.

Configure the provider

Search several roots

Pass a list to serve more than one folder. When the same skill name appears in more than one root, the first root wins in resource mode. In discovery mode, duplicate skill paths are omitted from skills/list.

List supporting files as resources

With the default supporting_files="template", clients find supporting files through each skill’s manifest. Set supporting_files="resources" to list every file in resources/list as well, for clients that expect a flat resource list.

Pick up edits without restarting

In resource mode the provider scans its roots once. Set reload=True to re-scan on every request while you edit skills locally; it adds a directory scan to each request, so leave it off in production. Discovery mode ignores reload and always serves current files.

Serve one skill

SkillProvider serves a single skill folder, for a server that ships exactly one skill.
SkillProvider serves resources only; Skills discovery reads from SkillsDirectoryProvider.

Serve a coding agent’s skills folder

Vendor providers are SkillsDirectoryProvider subclasses whose roots are fixed to a coding agent’s default skills folder. They take the same options except roots.

What discovery mode changes

Setting experimental_skills=True makes the provider stricter, because a discovery entry promises exact bytes:
  • Validation. A skill without valid frontmatter is left out of skills/list with a warning, but its files stay readable as resources. Frontmatter must have unique string keys and JSON-compatible values; timestamps, binary values, non-finite numbers, and YAML aliases are rejected.
  • Nested skills. A skill folder inside another skill, such as skills/team/review/SKILL.md, gets its own entry with the URI skill://team/review/SKILL.md. The parent’s manifest includes the nested files too.
  • Exact reads. Files are read from disk on every request and returned byte for byte, including CRLF line endings and binary content. Reads that discovery depends on bypass ResponseCachingMiddleware.
  • Limits. A skill with more than 512 files or 16 MiB in total is omitted. Skill roots and their contents must not be symbolic links.
  • Everything is published. Every file in a skill folder becomes part of the skill, including hidden files, so keep version control and editor files out of skill folders.
  • Generic resource descriptions. Listed resources carry descriptions such as Skill: server-authoring instead of the frontmatter description, so a malformed file can’t break resource listing. The author’s description appears in the discovery entry.
The manifest is a point-in-time record, not a filesystem snapshot. If a file changes between discovery and a read, the digest check above catches it. Without the flag, the provider keeps its permissive resource-mode behavior: frontmatter is optional, the description falls back to the first line of the file, links to skill folders elsewhere on disk are followed, and the first root wins on duplicate names.

Access control

Skills discovery respects the same rules as resource reads. A skill is omitted from skills/list when any of its files is hidden from the caller or denied by Middleware.check_resource_access, the hook that AuthMiddleware and the default on_read_resource use. Implement custom resource authorization in that hook so discovery can apply it; restrictions applied in other middleware hooks are invisible to discovery.

Current limits

Skills discovery currently serves skills from SkillsDirectoryProvider instances registered directly on the server you run.
  • SkillsExtension raises when the server or the skills provider has transforms, including namespaces, or when the provider is not registered directly on the same server.
  • Skills in a mounted server are served as resources through the parent, but the parent does not list them in skills/list.
  • A proxy in front of the server forwards the skill files as resources, but not skills/list or skills/get.
  • The optional directoryRead capability is not implemented.
Resource mode has none of these limits. Serve skills as resources everywhere, and add discovery on the server that clients connect to directly.