Skip to content

feat: load skills from a directory tree - #1409

Open
DaleSeo wants to merge 3 commits into
mainfrom
DaleSeo/skills-fs
Open

DaleSeo wants to merge 3 commits into
mainfrom
DaleSeo/skills-fs

Conversation

@DaleSeo

@DaleSeo DaleSeo commented Oct 29, 2026 •

Copy link
Copy Markdown
Member

Motivation and Context

Follows #1392.

It adds SkillCatalog behind a new skills-fs feature. It loads each folder under a root that contains a SKILL.md, then handles skills/list, skills/get, resources/read, and resources/directory/read using an in-memory snapshot. The module docs explain how to connect it to a ServerHandler. I also added inline comments explaining the design decisions.

How Has This Been Tested?

Add tests

Breaking Changes

None.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • 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

@DaleSeo
DaleSeo added this pull request to stack #1410 October 29, 2026 19:36
@github-actions github-actions Bot added T-test Testing related changes T-config Configuration file changes T-core Core library changes T-handler Handler implementation changes labels Oct 29, 2026
@github-actions
github-actions Bot requested a review from gocamille October 29, 2026 19:36
@github-actions

Copy link
Copy Markdown
Contributor

@gocamille is on triage rotation this week and is the reviewer for this one.

Labels come from the PR labeler. Please review the change.

Automated triage. Labels are a first pass and the assigned maintainer has the final say.

Base automatically changed from DaleSeo/skills-support to main October 29, 2026 20:54
@DaleSeo
DaleSeo force-pushed the DaleSeo/skills-fs branch 2 times, most recently from 81be0d8 to a17dc19 Compare October 29, 2026 20:56
@DaleSeo
DaleSeo removed this pull request from stack #1410 October 29, 2026 20:59
@DaleSeo DaleSeo linked an issue Oct 29, 2026 that may be closed by this pull request
@github-actions github-actions Bot added the T-documentation Documentation improvements label Oct 29, 2026
}

#[derive(Debug)]
struct CatalogFile {

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

The snapshot stores the full contents of every file, not just the metadata. That uses more memory, but resources/read always returns the exact bytes used to calculate the digests, even if a file changes on disk after it’s loaded.


impl Snapshot {
fn load(root: &Path) -> Result<Self, SkillCatalogError> {
let handle = Dir::open_ambient_dir(root, ambient_authority()).map_err(|source| {

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Every listing and read goes through this root handle, cap-std, never through a joined path. Checking file types while walking the directory and then reading files later with std::fs left a window where a file or folder could be replaced with a symlink, which might lead outside the root. cap-std prevents access outside the handle on both Unix and Windows.

files.sort_by(|a, b| a.uri.cmp(&b.uri));

let total: u64 = files.iter().map(|file| file.size).sum();
if files.len() > SKILL_FILE_LIMIT || total > SKILL_BYTE_LIMIT {

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

“Over the limit” means the skill is skipped, not just flagged with a warning. The spec says servers SHOULD NOT serve it, since conforming hosts aren’t required to load it. If people need to serve larger skills, we can add an opt-in later.

@DaleSeo
DaleSeo marked this pull request as ready for review October 29, 2026 21:49
@DaleSeo
DaleSeo requested a review from a team as a code owner October 29, 2026 21:50
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 29, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-30T00:04:04.683367Z 61ebd49 New commits
🔒 Security Review ✅ Completed 2026-10-30T00:05:33.107527Z 61ebd49 New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@DaleSeo DaleSeo self-assigned this Oct 29, 2026

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e8b5386c3d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +310 to +311
let bytes = handle
.read(&entry.path)

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 Badge Enforce skill limits before reading all file contents

When a skill contains a very large file or an excessive number of files, loading reads and retains every file in bytes_of before build_skill checks SKILL_BYTE_LIMIT and SKILL_FILE_LIMIT. A skill containing a multi-gigabyte asset can therefore exhaust the server's memory during startup or reload instead of being skipped at the documented 16 MiB limit; even skills that will subsequently be rejected are fully loaded. Check file counts before loading and enforce the byte budget with bounded reads so oversized skills cannot exhaust memory before validation.

Useful? React with 👍 / 👎.

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

T-config Configuration file changes T-core Core library changes T-documentation Documentation improvements T-handler Handler implementation changes T-test Testing related changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support the Skills extension (SEP-2640)

1 participant