Spaces:
Runtime error
Runtime error
| """Public tool surface for the PCSWMM Engineering MCP. | |
| This product retains its PCSWMM-engineering identity while supporting controlled deterministic evidence backends. The public workflow starts from a | |
| structured package exported by the PCSWMM Engineering SDK. The legacy | |
| uploaded-INP functions remain available internally so the service can perform | |
| an independent SWMM verification, but they are not published as MCP tools. | |
| """ | |
| from __future__ import annotations | |
| from pathlib import Path | |
| from typing import Any, Callable | |
| from sessions import STORE | |
| import tools as core | |
| from pcswmm_bridge import extract_inp_content | |
| from revision_pipeline import revision_summary_text | |
| from deterministic_evidence_adapter import ( | |
| build_mcp_package_from_evidence, selected_figure_payloads, validate_evidence_directory, | |
| ) | |
| def connect_active_pcswmm_project( | |
| package: dict | str, | |
| submission_type: str = "model_only_review", | |
| submission_number: str = "1", | |
| previous_submission_reference: str = "", | |
| auto_verify: bool = False, | |
| ) -> dict: | |
| """Connect the active PCSWMM project package and optionally verify it independently. | |
| The package must be exported by the PCSWMM Engineering SDK and should include | |
| project identity, active scenario context, engineering findings, and the exact | |
| INP text when independent verification is requested. | |
| """ | |
| ingested = core.ingest_pcswmm_package( | |
| package=package, | |
| session_id="", | |
| create_model_session=True, | |
| ) | |
| session_id = ingested["session_id"] | |
| configured = core.configure_submission( | |
| session_id=session_id, | |
| submission_type=submission_type, | |
| submission_number=submission_number, | |
| previous_submission_reference=previous_submission_reference, | |
| ) | |
| verification: dict[str, Any] = { | |
| "status": "not_run", | |
| "reason": "auto_verify=False", | |
| } | |
| normalized = STORE.get(session_id).data.get("pcswmm_package", {}) | |
| has_inp = bool(extract_inp_content(normalized)) | |
| if auto_verify: | |
| if not has_inp: | |
| verification = { | |
| "status": "not_run", | |
| "reason": "The PCSWMM package does not contain INP text.", | |
| } | |
| else: | |
| verification = core.run_simulation(session_id) | |
| return { | |
| "session_id": session_id, | |
| "product": "PCSWMM Engineering MCP", | |
| "active_project": ingested["validation"], | |
| "submission": configured, | |
| "independent_verification": verification, | |
| "revision_review": ingested.get("revision_review", {}), | |
| "next_step": ( | |
| "Call review_active_pcswmm_model, inspect findings, then generate_pcswmm_swmr." | |
| ), | |
| } | |
| def connect_deterministic_calgary_evidence( | |
| evidence_dir: str, | |
| submission_type: str = "model_only_review", | |
| submission_number: str = "1", | |
| auto_attach_figures: bool = True, | |
| max_figures: int = 12, | |
| ) -> dict: | |
| """Connect an existing deterministic PCSWMM evidence directory to this MCP. | |
| This is the backend-neutral bridge for local workflows used by PCSWMM, PySWMM, Claude Desktop, | |
| ChatGPT Work, and Codex. The engineer runs PCSWMM and the native SDK first; | |
| this tool then ingests the resulting evidence directory without recalculating | |
| model values. | |
| """ | |
| check = validate_evidence_directory(evidence_dir) | |
| if not check["valid"]: | |
| raise ValueError("Invalid evidence directory: " + "; ".join(check["missing"])) | |
| package = build_mcp_package_from_evidence(evidence_dir) | |
| result = connect_active_pcswmm_project( | |
| package=package, | |
| submission_type=submission_type, | |
| submission_number=submission_number, | |
| auto_verify=False, | |
| ) | |
| session_id = result["session_id"] | |
| session = STORE.get(session_id) | |
| session.data["deterministic_evidence_dir"] = check["evidence_dir"] | |
| attached = [] | |
| if auto_attach_figures: | |
| for payload in selected_figure_payloads(evidence_dir, max_figures=max_figures): | |
| attached.append(core.attach_figure( | |
| session_id=session_id, | |
| image_base64=payload["image_base64"], | |
| caption=payload["caption"], | |
| section=payload["section"], | |
| )) | |
| result.update({ | |
| "evidence_directory": check, | |
| "attached_primary_figures": len(attached), | |
| "next_step": ( | |
| "Call review_active_pcswmm_model, set_pcswmm_report_details, " | |
| "get_pcswmm_submission_readiness, then generate_pcswmm_swmr." | |
| ), | |
| }) | |
| return result | |
| def generate_calgary_swmr_from_evidence( | |
| evidence_dir: str, | |
| project_name: str = "", | |
| client: str = "", | |
| consultant: str = "", | |
| prepared_by: str = "", | |
| outline_plan_no: str = "", | |
| submission_type: str = "model_only_review", | |
| submission_number: str = "1", | |
| include_model_appendix: bool = True, | |
| max_figures: int = 12, | |
| ) -> dict: | |
| """One-command City of Calgary SWMR draft from a prior deterministic evidence run. | |
| Reuses the existing MCP review and report engines. It does not introduce a | |
| parallel SWMR generator and does not rerun PCSWMM. | |
| """ | |
| connected = connect_deterministic_calgary_evidence( | |
| evidence_dir=evidence_dir, | |
| submission_type=submission_type, | |
| submission_number=submission_number, | |
| auto_attach_figures=True, | |
| max_figures=max_figures, | |
| ) | |
| session_id = connected["session_id"] | |
| session = STORE.get(session_id) | |
| package = session.data.get("pcswmm_package", {}) or {} | |
| project = package.get("project", {}) or {} | |
| resolved_project = project_name or str(project.get("project_name") or "PCSWMM Project") | |
| details = { | |
| "client": client or project.get("client") or "Not provided", | |
| "consultant": consultant or project.get("consultant") or "Not provided", | |
| "prepared_by": prepared_by or project.get("prepared_by") or "Not provided", | |
| "outline_plan_no": outline_plan_no or project.get("outline_plan_number") or "Not provided", | |
| "municipality": project.get("municipality") or "City of Calgary", | |
| } | |
| core.set_report_details(session_id, details) | |
| review = review_active_pcswmm_model(session_id) | |
| readiness = core.get_submission_readiness(session_id) | |
| report = generate_pcswmm_swmr( | |
| session_id=session_id, | |
| project_name=resolved_project, | |
| client=str(details["client"]), | |
| consultant=str(details["consultant"]), | |
| prepared_by=str(details["prepared_by"]), | |
| outline_plan_no=str(details["outline_plan_no"]), | |
| include_model_appendix=include_model_appendix, | |
| ) | |
| return { | |
| "session_id": session_id, | |
| "project_name": resolved_project, | |
| "review": review, | |
| "submission_readiness": readiness, | |
| "report": report, | |
| "evidence_directory": connected["evidence_directory"], | |
| "attached_primary_figures": connected["attached_primary_figures"], | |
| "note": "Draft generated from deterministic PCSWMM evidence for professional engineering review.", | |
| } | |
| def connect_pyswmm_calgary_evidence( | |
| evidence_dir: str, | |
| submission_type: str = "model_only_review", | |
| submission_number: str = "1", | |
| auto_attach_figures: bool = True, | |
| max_figures: int = 12, | |
| ) -> dict: | |
| """Connect deterministic evidence produced by the PySWMM Calgary backend. | |
| Reuses the existing PCSWMM-engineering MCP review, readiness, figure, response | |
| matrix, and SWMR tools. Hydraulic values are not recalculated during connection. | |
| """ | |
| result = connect_deterministic_calgary_evidence( | |
| evidence_dir=evidence_dir, | |
| submission_type=submission_type, | |
| submission_number=submission_number, | |
| auto_attach_figures=auto_attach_figures, | |
| max_figures=max_figures, | |
| ) | |
| session = STORE.get(result["session_id"]) | |
| package = session.data.get("pcswmm_package", {}) or {} | |
| backend = (package.get("source") or {}).get("backend") | |
| result["backend"] = backend or "PySWMM / EPA SWMM" | |
| result["workflow"] = "PySWMM deterministic evidence -> existing PCSWMM-engineering MCP" | |
| return result | |
| def generate_calgary_swmr_from_pyswmm_evidence( | |
| evidence_dir: str, | |
| project_name: str = "", | |
| client: str = "", | |
| consultant: str = "", | |
| prepared_by: str = "", | |
| outline_plan_no: str = "", | |
| submission_type: str = "model_only_review", | |
| submission_number: str = "1", | |
| include_model_appendix: bool = True, | |
| max_figures: int = 12, | |
| ) -> dict: | |
| """Generate a City of Calgary SWMR draft from PySWMM deterministic evidence.""" | |
| result = generate_calgary_swmr_from_evidence( | |
| evidence_dir=evidence_dir, project_name=project_name, client=client, | |
| consultant=consultant, prepared_by=prepared_by, outline_plan_no=outline_plan_no, | |
| submission_type=submission_type, submission_number=submission_number, | |
| include_model_appendix=include_model_appendix, max_figures=max_figures, | |
| ) | |
| result["backend"] = "PySWMM / EPA SWMM" | |
| result["note"] = ( | |
| "Draft generated by the existing PCSWMM-engineering MCP from deterministic " | |
| "PySWMM/EPA SWMM evidence for professional engineering review." | |
| ) | |
| return result | |
| def validate_active_pcswmm_project(session_id: str) -> dict: | |
| """Validate the connected PCSWMM package and report available capabilities.""" | |
| result = core.validate_pcswmm_package(session_id) | |
| session = STORE.get(session_id) | |
| result["independent_results_available"] = bool(session.data.get("results")) | |
| result["active_project_connected"] = True | |
| return result | |
| def run_independent_pcswmm_verification(session_id: str) -> dict: | |
| """Independently rerun the active PCSWMM model through the isolated SWMM worker.""" | |
| session = STORE.get(session_id) | |
| if not session.data.get("pcswmm_package"): | |
| raise ValueError("This session is not connected to a PCSWMM engineering package.") | |
| if not session.data.get("inp_path"): | |
| raise ValueError( | |
| "The PCSWMM package did not include INP content; independent execution is unavailable." | |
| ) | |
| return core.run_simulation(session_id) | |
| def optimize_pcswmm_design( | |
| session_id: str, | |
| objective: dict | str, | |
| variables: dict | str | None = None, | |
| candidates: list | str | None = None, | |
| constraints: dict | str | None = None, | |
| outfall_link_id: str = "", | |
| max_evaluations: int = 24, | |
| ) -> dict: | |
| """Screen candidate designs against FIXED City of Calgary design-standard | |
| constraints and rank the feasible ones by a VARIABLE design objective. | |
| Requires run_independent_pcswmm_verification to have been called first on | |
| this session (optimization re-simulates the model, so it needs the same | |
| INP text and base run that independent verification requires). | |
| objective: {"metric": "maximum_link_velocity" | "maximum_modelled_depth_ratio" | |
| | "maximum_node_flooding" | "peak_link_flow" | |
| | "maximum_storage_volume" | "maximum_storage_depth" | |
| | "peak_subcatchment_runoff" | "total_conduit_volume_m3", | |
| "direction": "minimize" | "maximize"} | |
| variables: grid-search mode -- {"conduit_diameter_overrides": | |
| {"C1": [0.3, 0.375, 0.45]}, "storage_depth_overrides": | |
| {"ST1": [1.0, 1.5]}}; every combination is evaluated, capped | |
| by max_evaluations. Supported categories: | |
| conduit_diameter_overrides, conduit_roughness_overrides, | |
| storage_depth_overrides. | |
| candidates: shortlist mode -- a list of fully-formed override dicts to | |
| evaluate directly instead of a grid. Supply either variables | |
| or candidates, not conceptually both. | |
| constraints: overrides merged onto the fixed COC defaults (max_depth_ratio, | |
| min_velocity_mps, max_velocity_mps, max_node_flooding_cms, | |
| max_continuity_error_pct, max_allowable_outfall_flow_cms). | |
| These defaults are commonly-used stormwater design thresholds, | |
| NOT a transcription of a specific City of Calgary SWMDM or | |
| Industry Bulletin edition -- confirm every value against | |
| current criteria before treating a PASS as compliance. | |
| outfall_link_id: the link ID whose peak flow is checked against | |
| max_allowable_outfall_flow_cms, if that constraint is set. | |
| """ | |
| if not isinstance(objective, dict) and not isinstance(objective, str): | |
| raise ValueError('objective must be an object like {"metric": ..., "direction": ...}') | |
| return core.optimize_design( | |
| session_id=session_id, | |
| objective=objective, | |
| variables=variables, | |
| candidates=candidates, | |
| constraints=constraints, | |
| outfall_link_id=outfall_link_id, | |
| max_evaluations=max_evaluations, | |
| ) | |
| def get_pcswmm_overland_flow_assessment( | |
| session_id: str, | |
| major_link_ids: list | str | None = None, | |
| ) -> dict: | |
| """Extract peak Q/v/d for major-system (overland) flow routes from the | |
| connected model and screen them against the Alberta Environment / City | |
| of Calgary depth-velocity criteria (SWMDM 2011, Table 3-20/Figure 3-23), | |
| returning the Table-11-13-style tabulation and a Figure-11-3-style chart | |
| ready to attach to the SWMR via attach_pcswmm_figure -- the extraction | |
| and calculation step consultants have otherwise had to do by hand from | |
| raw model output. | |
| major_link_ids: optional list of link IDs to treat as the major/overland | |
| system, matching your own drawing classification. If omitted, overland | |
| routes are auto-detected from the INP by cross-section shape | |
| (TRAPEZOIDAL, RECT_OPEN, TRIANGULAR, IRREGULAR, STREET). | |
| Requires run_independent_pcswmm_verification to have been called first | |
| on this session (this reads the same simulated node/link results). | |
| Returns: detection_method, the depth-velocity curve and its source | |
| citation, a unit_system flag, the tabulated per-link results (native | |
| model units), and chart_png_base64 -- a ready-to-attach PNG chart. | |
| """ | |
| return core.get_overland_flow_assessment(session_id, major_link_ids=major_link_ids) | |
| def get_pcswmm_discharge_volume_summary( | |
| session_id: str, | |
| locations: list | str | None = None, | |
| outfall_node_ids: list | str | None = None, | |
| ) -> dict: | |
| """Table 11-12-style permissible-discharge/runoff-volume summary per | |
| location/manhole, plus cumulative system volume at one or more outfalls | |
| (City of Calgary SWMDM 2011, Section 11.1.7.2.8 item iv). | |
| Requires run_independent_pcswmm_verification to have been called first | |
| on this session. | |
| From the model: Invert, Obvert, maximum HGL, and Runoff Volume (a | |
| trapezoidal integration of that node's simulated inflow, independently | |
| validated against the SWMM engine's own continuity totals to 9 | |
| significant figures) are computed directly. Area is auto-summed from | |
| subcatchments draining to that node unless overridden. | |
| NOT computed, by design -- must be supplied if wanted in the table: | |
| permissible Discharge Rate (L/s/ha, a City-assigned/design value) and | |
| Storage Volume (a preliminary on-site storage result, e.g. from the | |
| wbscc or calgary-storm-retention tools). Omitted fields are left blank | |
| with a note, never fabricated. | |
| locations: [{"node_id": "MH17-3", "location_label": "Site 1", | |
| "manhole_number": "17-3", "area_ha": 1.2 (optional override), | |
| "discharge_rate_lps_ha": 50 (optional), "storage_volume_m3": 120 | |
| (optional)}, ...] | |
| outfall_node_ids: outfall node IDs to compute cumulative volume for; if | |
| omitted, every OUTFALLS node in the model is used. | |
| """ | |
| return core.get_discharge_volume_summary( | |
| session_id, locations=locations, outfall_node_ids=outfall_node_ids | |
| ) | |
| def get_active_pcswmm_project(session_id: str) -> dict: | |
| """Return connected PCSWMM project, package, scenario, and execution identity.""" | |
| session = STORE.get(session_id) | |
| validation = session.data.get("pcswmm_validation", {}) | |
| package = session.data.get("pcswmm_package", {}) | |
| project = package.get("project") or package.get("project_summary") or {} | |
| source = package.get("source") or {} | |
| metadata = (session.data.get("results") or {}).get("metadata", {}) | |
| return { | |
| "session_id": session_id, | |
| "project": project, | |
| "source": source, | |
| "package_validation": validation, | |
| "active_scenario": package.get("active_scenario") or project.get("active_scenario"), | |
| "pcswmm_sdk_version": source.get("sdk_version") or package.get("sdk_version"), | |
| "independent_execution": { | |
| "available": bool(session.data.get("results")), | |
| "run_id": metadata.get("run_id"), | |
| "model_sha256": metadata.get("model_sha256"), | |
| "results_usable": metadata.get("results_usable"), | |
| "engine": "EPA SWMM / pyswmm isolated local worker", | |
| }, | |
| } | |
| def review_active_pcswmm_model(session_id: str) -> dict: | |
| """Run the consolidated deterministic review of the connected active PCSWMM model.""" | |
| session = STORE.get(session_id) | |
| if not session.data.get("pcswmm_package"): | |
| raise ValueError("No active PCSWMM project is connected to this session.") | |
| package_validation = core.validate_pcswmm_package(session_id) | |
| package = session.data.get("pcswmm_package", {}) or {} | |
| revision = session.data.get("revision_review", {}) or {} | |
| submission_type = str(session.data.get("submission_type", "first_submission")) | |
| revision_applicable = submission_type in {"revised_submission", "final_submission"} or bool(revision.get("object_impacts")) | |
| revision_review = ( | |
| {"applicable": True, "summary": revision_summary_text(revision), **revision} | |
| if revision.get("object_impacts") | |
| else { | |
| "applicable": False, | |
| "status": "not_applicable" if not revision_applicable else "missing", | |
| "message": ( | |
| "Revision review is not applicable to this first/model-only submission." | |
| if not revision_applicable else | |
| "A revised/final submission requires a baseline snapshot and structured revision review." | |
| ), | |
| } | |
| ) | |
| review: dict[str, Any] = { | |
| "session_id": session_id, | |
| "package_validation": package_validation, | |
| "revision_review": revision_review, | |
| "pcswmm_engineering_review": package.get("engineering_review", {}), | |
| "pcswmm_result_summary": (package.get("results", {}) or {}), | |
| } | |
| if session.data.get("results"): | |
| review.update({ | |
| "execution_reconciliation": core.get_reconciliation(session_id), | |
| "calgary_screening": core.calgary_screening(session_id), | |
| "engineering_findings": core.preliminary_design_review(session_id), | |
| "node_results": core.get_node_results(session_id, limit=20), | |
| "link_results": core.get_link_results(session_id, limit=20), | |
| }) | |
| else: | |
| review["independent_verification"] = { | |
| "status": "not_available", | |
| "reason": "Run run_independent_pcswmm_verification before relying on hydraulic conclusions.", | |
| } | |
| reasoning = ((package.get("engineering_review") or {}).get("reasoning_narrative")) | |
| review["executive_summary"] = ( | |
| revision_summary_text(revision) if revision.get("object_impacts") | |
| else (reasoning or "PCSWMM-native engineering review completed from the active project package.") | |
| ) | |
| review["disclaimer"] = ( | |
| "Deterministic engineering screening for professional review; not a sealed design determination." | |
| ) | |
| return review | |
| def get_pcswmm_node_results( | |
| session_id: str, | |
| node_type: str = "", | |
| sort_by: str = "Depth Ratio", | |
| limit: int = 20, | |
| ) -> dict: | |
| """Return independently verified node results for the active PCSWMM project.""" | |
| return core.get_node_results(session_id, node_type=node_type, sort_by=sort_by, limit=limit) | |
| def get_pcswmm_link_results( | |
| session_id: str, | |
| sort_by: str = "Peak Velocity (m/s)", | |
| limit: int = 20, | |
| ) -> dict: | |
| """Return independently verified link results for the active PCSWMM project.""" | |
| return core.get_link_results(session_id, sort_by=sort_by, limit=limit) | |
| def get_pcswmm_subcatchment_results(session_id: str, limit: int = 30) -> dict: | |
| """Return independently verified subcatchment results for the active PCSWMM project.""" | |
| return core.get_subcatchment_results(session_id, limit=limit) | |
| def get_pcswmm_timeseries( | |
| session_id: str, | |
| object_type: str, | |
| object_id: str, | |
| variable: str, | |
| ) -> dict: | |
| """Return a bounded time series for an active PCSWMM project object.""" | |
| return core.get_timeseries(session_id, object_type, object_id, variable) | |
| def review_pcswmm_revision(session_id: str) -> dict: | |
| """Return the normalized baseline-to-revised PCSWMM impact assessment.""" | |
| return core.get_design_revision_review(session_id) | |
| def configure_pcswmm_submission( | |
| session_id: str, | |
| submission_type: str = "first_submission", | |
| submission_number: str = "1", | |
| previous_submission_reference: str = "", | |
| certified_checklist_attached: bool = False, | |
| no_objections_letter_attached: bool = False, | |
| prior_approved_report_attached: bool = False, | |
| correspondence_appendix_attached: bool = False, | |
| clean_copy: bool = False, | |
| ) -> dict: | |
| """Configure the Calgary submission route for the active PCSWMM project.""" | |
| return core.configure_submission( | |
| session_id=session_id, | |
| submission_type=submission_type, | |
| submission_number=submission_number, | |
| previous_submission_reference=previous_submission_reference, | |
| certified_checklist_attached=certified_checklist_attached, | |
| no_objections_letter_attached=no_objections_letter_attached, | |
| prior_approved_report_attached=prior_approved_report_attached, | |
| correspondence_appendix_attached=correspondence_appendix_attached, | |
| clean_copy=clean_copy, | |
| ) | |
| def set_pcswmm_city_comments( | |
| session_id: str, | |
| comments: list | str, | |
| report_changes: dict | str = {}, | |
| ) -> dict: | |
| """Attach City comments and documented changes to the active PCSWMM project session.""" | |
| return core.set_city_comments(session_id, comments, report_changes) | |
| def build_pcswmm_city_response_matrix(session_id: str) -> dict: | |
| """Build the evidence-linked City comment response matrix for the PCSWMM project.""" | |
| return core.build_city_comment_response_matrix(session_id) | |
| def get_pcswmm_submission_readiness(session_id: str) -> dict: | |
| """Apply staged draft, engineer-review, and submission-readiness gates.""" | |
| return core.get_submission_readiness(session_id) | |
| def get_pcswmm_hydraulic_summary(session_id: str) -> dict: | |
| """Return critical deterministic hydraulic results without rerunning the model.""" | |
| return core.get_hydraulic_summary(session_id) | |
| def set_pcswmm_report_details(session_id: str, details: dict | str) -> dict: | |
| """Set project, client, consultant, author, and report metadata.""" | |
| return core.set_report_details(session_id, details) | |
| def set_pcswmm_report_configuration(session_id: str, configuration: dict | str) -> dict: | |
| """Set confirmed report criteria and presentation options.""" | |
| return core.set_report_configuration(session_id, configuration) | |
| def attach_pcswmm_figure( | |
| session_id: str, | |
| image_base64: str, | |
| caption: str, | |
| section: str = "Engineering Review", | |
| ) -> dict: | |
| """Attach a PCSWMM profile, graph, map, or engineering figure to the report.""" | |
| return core.attach_figure(session_id, image_base64, caption, section) | |
| def _native_pcswmm_swmr(session, project_name: str, client: str, consultant: str, | |
| prepared_by: str, outline_plan_no: str, | |
| include_model_appendix: bool) -> dict: | |
| """Generate a structured consultant-demonstration SWMR from PCSWMM-native evidence.""" | |
| from pcswmm_native_report import generate_native_swmr | |
| return generate_native_swmr( | |
| session=session, project_name=project_name, client=client, consultant=consultant, | |
| prepared_by=prepared_by, outline_plan_no=outline_plan_no, | |
| include_model_appendix=include_model_appendix, | |
| ) | |
| def generate_pcswmm_swmr( | |
| session_id: str, | |
| project_name: str, | |
| client: str = "", | |
| consultant: str = "", | |
| prepared_by: str = "", | |
| outline_plan_no: str = "", | |
| include_model_appendix: bool = True, | |
| ) -> dict: | |
| """Generate an SWMR from PCSWMM evidence; use the full reconciled engine when optional verification exists.""" | |
| session = STORE.get(session_id) | |
| if not session.data.get("pcswmm_package"): | |
| raise ValueError("A connected PCSWMM project is required.") | |
| if session.data.get("results"): | |
| return core.generate_report( | |
| session_id=session_id, project_name=project_name, client=client, | |
| consultant=consultant, prepared_by=prepared_by, | |
| outline_plan_no=outline_plan_no, | |
| include_model_appendix=include_model_appendix, | |
| ) | |
| return _native_pcswmm_swmr(session, project_name, client, consultant, prepared_by, | |
| outline_plan_no, include_model_appendix) | |
| def list_pcswmm_sessions() -> dict: | |
| """List local PCSWMM Engineering MCP sessions.""" | |
| return core.list_sessions() | |
| def close_pcswmm_session(session_id: str) -> dict: | |
| """Close a PCSWMM Engineering MCP session and remove temporary working files.""" | |
| return core.close_session(session_id) | |
| PCSWMM_TOOL_REGISTRY: dict[str, Callable[..., dict]] = { | |
| fn.__name__: fn | |
| for fn in [ | |
| connect_active_pcswmm_project, | |
| connect_deterministic_calgary_evidence, | |
| connect_pyswmm_calgary_evidence, | |
| generate_calgary_swmr_from_evidence, | |
| generate_calgary_swmr_from_pyswmm_evidence, | |
| validate_active_pcswmm_project, | |
| get_active_pcswmm_project, | |
| run_independent_pcswmm_verification, | |
| optimize_pcswmm_design, | |
| get_pcswmm_overland_flow_assessment, | |
| get_pcswmm_discharge_volume_summary, | |
| review_active_pcswmm_model, | |
| get_pcswmm_node_results, | |
| get_pcswmm_link_results, | |
| get_pcswmm_subcatchment_results, | |
| get_pcswmm_timeseries, | |
| review_pcswmm_revision, | |
| configure_pcswmm_submission, | |
| set_pcswmm_city_comments, | |
| build_pcswmm_city_response_matrix, | |
| get_pcswmm_submission_readiness, | |
| get_pcswmm_hydraulic_summary, | |
| set_pcswmm_report_details, | |
| set_pcswmm_report_configuration, | |
| attach_pcswmm_figure, | |
| generate_pcswmm_swmr, | |
| list_pcswmm_sessions, | |
| close_pcswmm_session, | |
| ] | |
| } | |