Skip to content

Expose idfkit agent references over MCP (idfkit#160)#73

Open
samuelduchesne wants to merge 2 commits into
mainfrom
claude/idfkit-issue-160-Eupti
Open

Expose idfkit agent references over MCP (idfkit#160)#73
samuelduchesne wants to merge 2 commits into
mainfrom
claude/idfkit-issue-160-Eupti

Conversation

@samuelduchesne
Copy link
Copy Markdown
Collaborator

Companion to idfkit/idfkit#160 (PR idfkit/idfkit#TBD).

Summary

  • idfkit://references/ returns a JSON index of available topics (slug, title, description, URI) plus the bundled SKILL.md dispatch document.
  • idfkit://references/{topic} returns the raw markdown for a single topic.
  • New src/idfkit_mcp/tools/references.py reads the docs via importlib.resources from the installed idfkit. Cached with functools.cache (the wheel layout doesn't change at runtime). Returns an empty index when the installed idfkit predates the references, so this PR is self-sufficient and the next idfkit pin bump surfaces the docs automatically.
  • src/idfkit_mcp/server.py registers the two resources alongside the existing tool surface.
  • Tests cover metadata parsing, the loader, both resources (when refs are present), and the graceful-fallback path (when they're absent). Total 13 new tests across the file.

Security

The {topic} segment comes off the MCP URI; idfkit://references/..%2F..%2F..%2Fetc%2Fpasswd would have resolved outside the bundled tree under naive path joining. The resource now validates topic against ^[a-z0-9][a-z0-9-]*$ before any filesystem access; the parametrized test covers .., foo/bar, leading dash, uppercase, and the empty string. Defense in depth — the MCP transport may or may not normalize ...

Test plan

  • make check — ruff, pyright, deptry: clean
  • make test — 240 passed, 9 skipped (skips are integration paths that need the new references in the installed idfkit; they'll exercise on the next pin bump)
  • Manual MCP probe: idfkit://references/ returns the empty index against the currently pinned idfkit==0.12.2; the topic resource raises Invalid reference topic for .., foo/bar, etc.
  • After idfkit/idfkit#TBD merges and releases, bump idfkit here and watch the 9 skipped tests turn green

Generated by Claude Code

claude added 2 commits May 23, 2026 19:08
…kit#160)

Add two new resources backed by the agent reference docs shipped inside
the idfkit wheel under .agents/skills/developing-with-idfkit/:

  idfkit://references/          — index (slug, title, description per topic
                                  + SKILL.md dispatch document)
  idfkit://references/{topic}   — raw markdown for a single topic

The new tools/references.py module reads from the installed idfkit via
importlib.resources, so there's no vendored copy and no path hardcoding —
when idfkit bumps to a version that ships the references, the resources
surface them automatically. Older idfkit versions are handled gracefully:
the index returns count=0 and the topic resource raises a clear ValueError.

Tests cover metadata parsing, the loader, both resources (when references
are available), and the no-references fallback path. The integration tests
skip cleanly when the installed idfkit predates the references, so the
suite passes against the current idfkit==0.12.2 pin and will exercise the
full path once the pin is bumped.
…esource

The idfkit://references/{topic} resource was joining the raw topic
string onto the references directory. A URI like
idfkit://references/..%2F..%2F..%2Fetc%2Fpasswd would resolve outside
the bundled references tree (any .md-suffixed file readable by the
server process). The MCP transport may or may not normalize ..; this
is defense in depth.

Validate topic against ^[a-z0-9][a-z0-9-]*$ before path-joining;
return ValueError("Invalid reference topic '{topic}'.") otherwise.
Parametrized test covers .., parent-relative paths, slashes, leading
dash, uppercase, and the empty string.

Refs idfkit#160.
github-actions Bot added a commit that referenced this pull request May 23, 2026
@github-actions
Copy link
Copy Markdown
Contributor

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.

2 participants