# Bundling skills with the MCP server This document describes how predefined *skills* (Anthropic Agent Skills, the `SKILL.md` format) are authored, where they live, and how they are distributed so that they are discoverable. ## What a skill is (and what MCP is not) A skill is a folder containing a `SKILL.md` file: YAML frontmatter (`name`, `description`) plus a markdown body of instructions, optionally with supporting `scripts/` and `references/`. Skills are consumed by the *agent runtime* (Claude Code / Cowork), which reads `SKILL.md` from disk and decides when to load it based on the `description`. Important: **MCP has no native "skill" primitive.** The protocol exposes tools, resources, and prompts only. An MCP server therefore cannot make a client auto-load a skill over the wire. We support two distribution paths, and they are complementary: 1. **Plugin bundling** — the native path for Claude Code / Cowork auto-discovery. 2. **MCP resource/prompt exposure** — lets *any* MCP client pull the skill text, even outside Claude Code. ## Where skills live (canonical location) ``` src/openswmm_mcp/skills/ __init__.py # auto-discovery loader (skills_mcp sub-server) / SKILL.md # required: frontmatter + instructions scripts/ # optional: helper scripts the skill references references/ # optional: long-form reference material ``` Skills live **inside the package** so they ship in the wheel as package data. This is verified: a built wheel contains `openswmm_mcp/skills//SKILL.md`. No extra `pyproject.toml` configuration is required — hatchling includes non-`.py` files under the package automatically. ## Authoring a new skill 1. Create `src/openswmm_mcp/skills//SKILL.md`. 2. Frontmatter must include `name` and a high-signal `description`. The description is the trigger: state when to use the skill *and* when not to, with concrete keywords. See `calibrate-model/SKILL.md` for the house style. 3. Write the body as an ordered, tool-driven workflow that references the actual MCP tool names (e.g. `lifecycle_open_model`, `geopackage_compare_sim_vs_observed`). Follow the project file-IO policy: intermediate outputs go to user-reviewable locations, not temp dirs. 4. Nothing else to wire up — the loader discovers it at import time. ## How skills are exposed over MCP `src/openswmm_mcp/skills/__init__.py` defines a `skills_mcp` sub-server, mounted (no namespace) in `server.py`. It scans `*/SKILL.md` once at import and exposes: - Resource `swmm://skills` — JSON index of `{name, description}`. - Resource `swmm://skills/{skill_name}` — the full `SKILL.md` body. - Prompt `use_skill(skill_name)` — injects a skill body into the conversation. This makes skills discoverable from any MCP client (read the index resource, then fetch a specific skill). ## Native auto-discovery via a Claude Code / Cowork plugin For Claude Code / Cowork to auto-load these skills (so the agent picks them up by `description` without being told), package the server as a plugin and point the plugin's `skills/` at this directory. A plugin bundles the MCP server and the skills together: ``` openswmm-plugin/ .claude-plugin/plugin.json # manifest; declares the MCP server skills/ -> ../src/openswmm_mcp/skills # same skills, one source of truth ``` Keep `src/openswmm_mcp/skills/` as the single source of truth and reference it from the plugin (symlink or build step) rather than duplicating `SKILL.md` files. Confirm the current plugin manifest schema and skills-path convention against the Claude Code plugin documentation before publishing, as the format evolves. ## Summary - Author skills as folders under `src/openswmm_mcp/skills/`. - They ship in the wheel automatically and are exposed over MCP as resources + a prompt. - For native agent auto-discovery, distribute the server as a plugin whose `skills/` points at the same directory.