Skip to main content

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.

AspectOpenSWMM approach“Gold standard” fit
FormatAnthropic-style SKILL.md + frontmatterAligns with Agent Skills / Cursor skill authoring
DiscoveryAuto-scan */SKILL.mdLow ceremony, easy to add skills
MCP exposureResources + use_skill promptCorrect workaround for “no skill primitive”
DistributionPackage data + optional plugin skills/ pathSingle source of truth, two consumers
ContentExplicit MCP tool names, verify steps, guardrailsHigh quality for LLM orchestration

It is not the gold standard for every environment:

  1. 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.
  2. Production DWD chat — instructions are composed in dwd-api-fastapi/app/agent/instructions/*.md and loaded at startup; that is your current “skill layer” for CopilotKit/MAF.
  3. MAF today wires MCPStreamableHTTPTool (tools), not necessarily MCP resources/prompts. OpenSWMM assumes a client that can read swmm://skills or invoke use_skill. If MAF only surfaces tools, bundled MCP skills are invisible unless you add something like get_skill_index / get_skill_body tools 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:

DesignWhereWhen it fits
Bundled SKILL.md + resources/promptskills/__init__.pyLong multi-step expert workflows; version with server; optional plugin auto-load
Parametric MCP promptsprompts/workflows.pyShorter, parameterized templates (analyze_model(inp_path))
Server instructionsserver.pyAlways-on routing hints (e.g. “use capacity-assessment for X”)
Namespaced tool sub-serversMany *_mcp mountsCapabilities, not workflows—skills call these
Reference assets onlyreferences/*.json, templatesSchemas/contracts without a full skill narrative
Server-side orchestrationGym envs, enginesLoops 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_stride loops).
  • 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.md from dwd-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_model to 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 in 00_core.md)
  • Run lifecycle: create/clone scenario → update → run_scenario → poll get_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 + optional references/
  • Small skills/__init__.py: discover, expose index + body (resources/prompt or thin tools if MAF only sees tools)
  • Mount sub-server on main FastMCP (like mcp.mount(skills_mcp))
  • Rich description frontmatter (when to use / when not)
  • Include skills in deploy packaging (compress.py / wheel data) if they live under dwd-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:

  1. API enforcement
  2. Tool shape / composite tools
  3. Middleware / CopilotKit context
  4. Composed instructions (playbooks)
  5. 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:

ConcernBest home for DWD
Twin/scenario rules, UI selection, presentation00_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, authAPI + MCP tools (not skill prose alone)
Heavy numerics / control loopsAPI/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, … not lifecycle_*.
    • 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​

  1. Adopt OpenSWMM’s mechanical pattern in dwd-mcp-fastmcp if you want versioned, portable workflow docs next to tools—but add get_skill / list_skills tools if production MAF only attaches MCP tools.
  2. 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.
  3. 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.
  4. When porting SWMM skills, rewrite workflows for API semantics first; only then decide whether reference code lives in references/ or in dwd-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.