Agent Skills -- Composer
Take a look at hydrotrek-ssc-suite/openswmm.mcp/src/openswmm_mcp/skills implementation. Is this the gold standard way of implementing agent skills? Are there any alternative skill designs that could have been used in the same environment?
We are implementing our own MCP server under hydrotrek-dwd-suite/dwd-mcp-fastmcp that will serve as a kind of parallel to the openswmm_mcp implementation. The use cases are similar since our DWD stack is built on the EPANET engine which is very similar to the SWMM engine. In our implementation, however, we are API based with cross-network API calls instead of in-memory and cross-process operations that you would see in the openswmm_mcp design.
For our Fast MCP server, would our skills be designed the same way openswmm_mcp designs theirs, or is there a better design fit for Fast MCP?
Here is a concise read of what OpenSWMM does, how that compares to “agent skills” in general, and what fits DWD’s API-based Fast MCP stack.
What OpenSWMM is doing
OpenSWMM treats skills as static, folder-based SKILL.md files shipped inside the Python package, discovered at import time, and exposed over MCP because MCP has no first-class “skill” type—only tools, resources, and prompts.
"""Auto-discovered SWMM Agent Skills, exposed over MCP.
Skills are folder-based: each lives at ``<skill-name>/SKILL.md`` inside this
package, optionally alongside supporting ``scripts/`` or ``references/`` files.
...
Because MCP has no native "skill" primitive, skills are surfaced two ways:
* As **resources** -- ``swmm://skills`` lists them and
``swmm://skills/{skill_name}`` returns a skill's full ``SKILL.md`` body.
...
* As a **prompt** -- ``use_skill(skill_name)`` injects the skill body into the
conversation for clients with a prompt UI.
Each skill is a long, tool-named playbook: frontmatter (name, rich description for triggering), ordered steps, verification checkpoints, guardrails, and optional references/ (schemas, templates, even reference Python like control_loop.py). The root server instructions tell the model to consult swmm://skills before improvising with raw tools.
That matches the house style documented in openswmm.mcp/docs/developer/SKILLS.md: one canonical tree under src/openswmm_mcp/skills/, wheel packaging, plugin symlink for Claude Code auto-discovery, MCP resources + prompt for everyone else.
So: strong pattern for “domain workflows co-located with the MCP server,” not a universal “gold standard” for every agent runtime.
Is this the gold standard?
For MCP + portable Agent Skills (SKILL.md), yes—this is a reference implementation.
| Aspect | OpenSWMM approach | “Gold standard” fit |
|---|---|---|
| Format | Anthropic-style SKILL.md + frontmatter | Aligns with Agent Skills / Cursor skill authoring |
| Discovery | Auto-scan */SKILL.md | Low ceremony, easy to add skills |
| MCP exposure | Resources + use_skill prompt | Correct workaround for “no skill primitive” |
| Distribution | Package data + optional plugin skills/ path | Single source of truth, two consumers |
| Content | Explicit MCP tool names, verify steps, guardrails | High quality for LLM orchestration |
It is not the gold standard for every environment:
- Cursor IDE skills (
~/.cursor/skills,.cursor/skills) — same file shape, different loader; your DWD guide already says these do not feed the production MAF agent. - Production DWD chat — instructions are composed in
dwd-api-fastapi/app/agent/instructions/*.mdand loaded at startup; that is your current “skill layer” for CopilotKit/MAF. - MAF today wires
MCPStreamableHTTPTool(tools), not necessarily MCP resources/prompts. OpenSWMM assumes a client that can readswmm://skillsor invokeuse_skill. If MAF only surfaces tools, bundled MCP skills are invisible unless you add something likeget_skill_index/get_skill_bodytools or merge playbook text into MAF instructions.
So OpenSWMM is gold standard for “skills shipped with the MCP server + multi-client MCP”; for DWD in-app chat, your own guide’s MAF-first stack is the intentional primary design.
Alternative skill designs (same MCP/FastMCP environment)
OpenSWMM already uses several patterns side by side:
| Design | Where | When it fits |
|---|---|---|
Bundled SKILL.md + resources/prompt | skills/__init__.py | Long multi-step expert workflows; version with server; optional plugin auto-load |
| Parametric MCP prompts | prompts/workflows.py | Shorter, parameterized templates (analyze_model(inp_path)) |
Server instructions | server.py | Always-on routing hints (e.g. “use capacity-assessment for X”) |
| Namespaced tool sub-servers | Many *_mcp mounts | Capabilities, not workflows—skills call these |
| Reference assets only | references/*.json, templates | Schemas/contracts without a full skill narrative |
| Server-side orchestration | Gym envs, engines | Loops that should not be N× chat round-trips |
Other alternatives you could use without abandoning FastMCP:
- Composite MCP tools — e.g.
run_scenario_and_wait,clone_and_run_baseline— encode API/async semantics once instead of in prose. - Backend jobs + poll tools — calibration, optimization, or “market control” as worker/API jobs; skill describes job config + status tools (fits API latency and auth better than
lifecycle_strideloops). - Playbooks only in FastAPI — same markdown content as skills, but SSOT under
app/agent/instructions/(what DWD does now for lifecycle/twin/scenario). - Build-time sync — generate
NN_playbook.mdfromdwd-mcp-fastmcp/skills/*/SKILL.md(or the reverse) so you do not maintain two copies by hand.
DWD API-based vs OpenSWMM in-process: what changes in skill content
OpenSWMM skills assume a session-centric, in-engine model:
lifecycle_open_model,lifecycle_run_simulation,lifecycle_step_simulation/lifecycle_stride- Bulk live reads (
nodes_get_depths_bulk, …) - Hotstart branching, in-memory edits,
building_write_modelto disk - Tight control loops and gym envs on the same process
Your DWD MCP layer is twin/scenario + HTTP, with runs as 202 + status, results from Parquet/API after Completed, network via get_network_*, and DWD_LIVE_SELECTION in MAF for UI context. Any SWMM-parity skill (calibration, capacity, “operational optimization”) needs rewritten workflows around:
twin_id/scenario_id(never display names; respect live selection rules in00_core.md)- Run lifecycle: create/clone scenario → update →
run_scenario→ pollget_scenario/ status (your playbook already points here) - No assuming stepwise simulation or cheap in-memory experiment branches unless the API adds them
- Chatty loops: prefer polling helpers or server-side jobs over “call get_node_timeseries 500 times”
- Artifacts: reports/dashboards may be “generate from API exports” rather than local Plotly HTML from engine snapshots—unless you add API endpoints for that
The operational-optimization skill’s references/control_loop.py + stride loop is the clearest mismatch: that logic belongs in a worker/service (or a dedicated API) for DWD, with the skill describing config, job submission, and interpretation—not an outer Python loop driven by the LLM over MCP.
Should DWD Fast MCP copy OpenSWMM’s skill design?
Reuse the packaging/discovery pattern; do not treat it as the sole production playbook layer for in-app chat.
What to reuse from OpenSWMM (good fit for Fast MCP)
skills/<name>/SKILL.md+ optionalreferences/- Small
skills/__init__.py: discover, expose index + body (resources/prompt or thin tools if MAF only sees tools) - Mount sub-server on main
FastMCP(likemcp.mount(skills_mcp)) - Rich
descriptionfrontmatter (when to use / when not) - Include skills in deploy packaging (
compress.py/ wheel data) if they live underdwd-mcp-fastmcp
That keeps parity with OpenSWMM for developers, docs-as-code, and any MCP client that can read resources.
What fits DWD better than mirroring OpenSWMM end-to-end
Your chat-agent-mcp-development-guide.md already orders:
- API enforcement
- Tool shape / composite tools
- Middleware / CopilotKit context
- Composed instructions (playbooks)
- Avoid huge routing tables in prose when tools + manifest suffice
For production chat, app/agent/instructions/ should remain the reliable SSOT for multi-step behavior, because it is always in the MAF system prompt. MCP-bundled skills are optional unless you verify MAF exposes resources/prompts or you add get_skill tools and teach the model to call them.
A practical split:
| Concern | Best home for DWD |
|---|---|
| Twin/scenario rules, UI selection, presentation | 00_core.md + middleware |
| Common user flows (create/run, fireflow, leakage) | Numbered playbooks (15_scenario_lifecycle.md, future 20_calibration.md, …) |
| Long SWMM-like workflows (calibration, capacity report) | Either playbook or MCP skill body—one SSOT, synced or generated |
| Async run/wait, caps, auth | API + MCP tools (not skill prose alone) |
| Heavy numerics / control loops | API/worker, not LLM-orchestrated stride |
“Better design fit” summary
- Same as OpenSWMM: folder
SKILL.md, discovery, ship with server, references for schemas/templates. - Different from OpenSWMM:
- Primary orchestration narrative for Copilot → MAF playbooks (or playbooks generated from skills).
- Skill steps reference
list_twins,run_scenario,get_model_summary, … notlifecycle_*. - Emphasize async jobs, polling, and composite tools in both skills and tool design.
- Defer in-process patterns (hotstart clone, stride control, gym on session) unless DWD APIs gain equivalents.
Recommendation
- Adopt OpenSWMM’s mechanical pattern in
dwd-mcp-fastmcpif you want versioned, portable workflow docs next to tools—but addget_skill/list_skillstools if production MAF only attaches MCP tools. - Do not rely on MCP skills alone for in-app chat; extend
dwd-api-fastapi/app/agent/instructions/for each major EPANET-parity use case (calibration, capacity, etc.), keeping them short and pointing at MCP tool docstrings. - Pick one SSOT for long workflows (playbook-only, skill-only with codegen into playbooks, or skill fetched via MCP tool)—avoid duplicating
calibrate-model-sized docs in two places. - When porting SWMM skills, rewrite workflows for API semantics first; only then decide whether reference code lives in
references/or indwd-worker-python/ FastAPI.
If you want, we can map OpenSWMM’s three skills to a concrete DWD tool checklist (which exist today vs need API/MCP/worker) in a follow-up—still in Ask mode, no code changes.