Skip to content

Add SkillCatalog and FilesystemSkillProvider for serving skills from a directory - #3795

Open
vijaydeepsinha wants to merge 13 commits into
modelcontextprotocol:mainfrom
vijaydeepsinha:issue-3683-file-system-support
Open

vijaydeepsinha wants to merge 13 commits into
modelcontextprotocol:mainfrom
vijaydeepsinha:issue-3683-file-system-support

Conversation

@vijaydeepsinha

Copy link
Copy Markdown
Contributor

Fixes #3683

Adds an optional helper that serves a directory of skills through the existing Skills extension, without changing the protocol or the Skills API. mcp/server/skills.py becomes a package; from mcp.server.skills import Skills and the handler aliases still work.

Motivation and Context

Serving skills from disk currently means writing handlers and registering every file as a resource by hand. This adds:

  • SkillProvider: a small protocol for listing and reading files.
  • FilesystemSkillProvider: a local-directory provider that skips symlinks and junctions and runs blocking I/O in a worker thread.
  • SkillCatalog: a Skills extension that scans a provider once, validates each skill, and answers skills/list, skills/get and optionally resources/directory/read. Manifest digests always match what resources/read serves, and a file that changed after load is refused.

Optional pagination (page_size) and SEP-2549 cache hints (ttl_ms, cache_scope) are supported.

Server usage

from pathlib import Path

import anyio
import yaml

from mcp.server.mcpserver import MCPServer
from mcp.server.skills import FilesystemSkillProvider, SkillCatalog


async def main() -> None:
    catalog = await SkillCatalog.load(
        FilesystemSkillProvider(Path("skills")),
        parse_frontmatter=yaml.safe_load,
        directory_read=True,
    )
    server = MCPServer("my-server", extensions=[catalog])
    await server.run_stdio_async()


anyio.run(main)

How Has This Been Tested?

  • ./scripts/test: 100% coverage, strict-no-cover clean.
  • ruff format --check, ruff check, pyright: clean.
  • Manually through Postman against a real server, on both the legacy 2025-11-25 and the 2026-07-28 protocol versions: list/get/read, pagination, and directory reads enabled and disabled.

Conformance

Ran the SEP-2640 scenarios from @modelcontextprotocol/conformance@0.2.0-alpha.12 (the first release that includes them; the version pinned in CI, alpha.11, has none) against real servers built with SkillCatalog + FilesystemSkillProvider:

Scenario Checks Result
sep-2640-skills-enumeration (skills/list + skills/get) 32 ✅ 32/32
sep-2640-skills-manifest (SKILL.md resource metadata) 6 ✅ 6/6
sep-2640-skills-directory (resources/directory/read) 7 ✅ 7/7
  • With --page-size 2: the same 32/32, 6/6 and 7/7, including skills-list-pagination (4 pages), skills-list-entry-atomic (7 skills, none split across pages) and directory-read-pagination.
  • With directory reads disabled: enumeration 32/32, manifest 6/6; the directory scenario reports its checks as not applicable, as specified.
  • Forcing each spec version with --force --spec-version: 2026-07-28 runs and passes all 32 enumeration checks. 2025-11-25 passes 30 of 30 applicable checks; the two cache-attribute checks (ttlMs/cacheScope, 2026-07-28+ only) are skipped. Manifest 6/6 and directory 7/7 on both.

Breaking Changes

None.

Types of changes

  • New feature (non-breaking change which adds functionality)
  • Documentation update

Checklist

  • I am assigned to the linked issue
  • I have disclosed any AI assistance and can explain the change in my own words
  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

Additional context

  • The SDK has no YAML dependency; the example uses PyYAML.

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 13 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="src/mcp/server/skills/provider.py">

<violation number="1" location="src/mcp/server/skills/provider.py:19">
P2: `FilesystemSkillProvider` omits dot-prefixed files, so it cannot satisfy this “every file” contract. Align the protocol with the intended hidden-file behavior or make the provider enumerate those files.</violation>
</file>

Reply to a comment to ask cubic a question or push back. It learns from your replies.

Re-trigger cubic

Comment thread src/mcp/server/skills/provider.py Outdated
"""

async def list_files(self) -> Sequence[str]:
"""Return the path of every file, recursively.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: FilesystemSkillProvider omits dot-prefixed files, so it cannot satisfy this “every file” contract. Align the protocol with the intended hidden-file behavior or make the provider enumerate those files.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At src/mcp/server/skills/provider.py, line 19:

<comment>`FilesystemSkillProvider` omits dot-prefixed files, so it cannot satisfy this “every file” contract. Align the protocol with the intended hidden-file behavior or make the provider enumerate those files.</comment>

<file context>
@@ -0,0 +1,31 @@
+    """
+
+    async def list_files(self) -> Sequence[str]:
+        """Return the path of every file, recursively.
+
+        Directories are not listed, and each path appears once.
</file context>

Comment thread src/mcp/server/skills/filesystem.py Resolved
Comment thread src/mcp/server/skills/catalog.py Resolved
Comment thread docs/advanced/skills.md Resolved
Comment thread docs/advanced/skills.md Resolved

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add a filesystem backed provider for the Skills extension

1 participant