Skip to content

Commit 2cea024

Browse files
more mcp?
1 parent 0ada00b commit 2cea024

2 files changed

Lines changed: 33 additions & 16 deletions

File tree

web/pioreactorui/mcp.py

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,6 @@ def clear_session(self, session_id: str) -> None:
7979

8080
def get_from_leader(endpoint: str) -> dict:
8181
"""Wrapper around `get_from_leader` to handle errors and callback checks."""
82-
logger.debug(endpoint)
8382
try:
8483
r = _get_from_leader(endpoint)
8584
r.raise_for_status()
@@ -102,7 +101,6 @@ def get_from_leader(endpoint: str) -> dict:
102101

103102
def post_into_leader(endpoint: str, json: dict | None = None) -> dict:
104103
"""Wrapper around `post_into_leader` to handle errors."""
105-
logger.debug(endpoint, json)
106104
try:
107105
r = _post_into_leader(endpoint, json=json)
108106
r.raise_for_status()
@@ -139,8 +137,6 @@ def patch_into_leader(endpoint: str, json: dict | None = None) -> dict:
139137
# ---------------------------------------------------------------------------
140138
# MCP **tools** (thin wrappers around existing REST routes)
141139
# ---------------------------------------------------------------------------
142-
143-
144140
@mcp.tool()
145141
def list_experiments() -> dict:
146142
"""List all experiments (name, creation timestamp, description, hours since creation)."""
@@ -149,7 +145,7 @@ def list_experiments() -> dict:
149145

150146
@mcp.tool()
151147
def list_workers(active_only: bool) -> dict:
152-
"""Return the cluster inventory. If *active_only*, filter by `is_active`."""
148+
"""Return the cluster inventory (aka workers). If *active_only*, filter by `is_active`."""
153149
workers = get_from_leader("/api/workers")
154150
return {"workers": [w for w in workers if w.get("is_active")] if active_only else workers}
155151

@@ -163,7 +159,7 @@ def list_workers_experiment_assignments(active_only: bool) -> dict:
163159

164160
@mcp.tool()
165161
def list_jobs_available(unit: str) -> dict:
166-
"""Return the unit's available jobs that can be run and settings that can be viewed or changed. Can use "$broadcast" for all units."""
162+
"""Return the unit/worker's available jobs that can be run and settings that can be viewed or changed. Can use "$broadcast" for all units."""
167163
return get_from_leader(f"/api/units/{unit}/jobs/discover")
168164

169165

@@ -177,7 +173,7 @@ def run_job(
177173
env: Dict[str, str] | None = None,
178174
config_overrides: List[List[str]] | None = None,
179175
) -> dict:
180-
"""Launch *job* on *unit* within *experiment* via leader REST API. Can use "$broadcast" for all units."""
176+
"""Launch *job* on *unit/worker* within *experiment* via leader REST API. Can use "$broadcast" for all units."""
181177
payload = {
182178
"options": options or {},
183179
"args": args or [],
@@ -192,7 +188,7 @@ def run_job(
192188

193189
@mcp.tool()
194190
def update_job(unit: str, job: str, experiment: str, settings: dict[str, Any]) -> dict:
195-
"""Update settings for a job on a unit within an experiment. Can use "$broadcast" for all units."""
191+
"""Update settings for a job on a unit/worker within an experiment. Can use "$broadcast" for all units."""
196192
return patch_into_leader(
197193
f"/api/workers/{unit}/jobs/update/job_name/{job}/experiments/{experiment}",
198194
json={"settings": settings},
@@ -201,7 +197,7 @@ def update_job(unit: str, job: str, experiment: str, settings: dict[str, Any]) -
201197

202198
@mcp.tool()
203199
def stop_job(unit: str, job: str, experiment: str) -> dict:
204-
"""Stop *job* on *unit*; optionally scope to *experiment*. Can use "$broadcast" for all units."""
200+
"""Stop *job* on *unit/worker*; optionally scope to *experiment*. Can use "$broadcast" for all units."""
205201
endpoint = f"/api/workers/{unit}/jobs/stop/job_name/{job}/experiments/{experiment}"
206202
return post_into_leader(endpoint)
207203

@@ -214,13 +210,13 @@ def stop_all_jobs_in_experiment(experiment: str) -> dict:
214210

215211
@mcp.tool()
216212
def stop_all_jobs_on_unit(unit: str, experiment: str) -> dict:
217-
"""Stop all jobs on a specific unit for a given experiment. Can use "$broadcast" for all units."""
213+
"""Stop all jobs on a specific unit/worker for a given experiment. Can use "$broadcast" for all units."""
218214
return post_into_leader(f"/api/workers/{unit}/jobs/stop/experiments/{experiment}")
219215

220216

221217
@mcp.tool()
222218
def running_jobs(unit: str) -> dict:
223-
"""Return list of running jobs on *unit*. Can use "$broadcast" for all units."""
219+
"""Return list of running jobs on *unit/worker*. Can use "$broadcast" for all units."""
224220
return get_from_leader(f"/api/workers/{unit}/jobs/running")
225221

226222

@@ -238,13 +234,13 @@ def blink(unit: str) -> dict:
238234

239235
@mcp.tool()
240236
def reboot_unit(unit: str) -> dict:
241-
"""Reboot a specific unit. Can use "$broadcast" for all units."""
237+
"""Reboot a specific unit/worker. Can use "$broadcast" for all units."""
242238
return post_into_leader(f"/api/units/{unit}/system/reboot")
243239

244240

245241
@mcp.tool()
246242
def shutdown_unit(unit: str) -> dict:
247-
"""Shutdown a specific unit. Can use "$broadcast" for all units."""
243+
"""Shutdown a specific unit/worker. Can use "$broadcast" for all units."""
248244
return post_into_leader(f"/api/units/{unit}/system/shutdown")
249245

250246

@@ -307,18 +303,39 @@ def get_time_series_column(experiment: str, data_source: str, column: str, lookb
307303

308304

309305
@mcp.tool()
306+
def list_experiment_profiles() -> dict:
307+
"""List available experiment profiles (filename, fullpath, and parsed metadata)."""
308+
return get_from_leader("/api/contrib/experiment_profiles")
309+
310+
311+
@mcp.tool()
312+
def run_experiment_profile(
313+
unit: str,
314+
profile: str,
315+
experiment: str,
316+
dry_run: bool = False,
317+
) -> dict:
318+
"""Execute an experiment profile on a unit/worker within an experiment. Can use "$broadcast" for all units. Optionally dry-run."""
319+
options = {"dry-run": None} if dry_run else {}
320+
args = ["execute", profile, experiment]
321+
return run_job(unit, "experiment_profile", experiment, options=options, args=args)
322+
323+
324+
# MCP **resources** for config: list of config.ini files, config contents, and unit configuration
325+
# ---------------------------------------------------------------------------
326+
@mcp.resource(path="configs", name="list_config_inis")
310327
def list_config_inis() -> dict:
311328
"""List available config.ini files (global and unit-specific)."""
312329
return get_from_leader("/api/configs")
313330

314331

315-
@mcp.tool()
332+
@mcp.resource(path="configs/{filename}", name="get_config_ini")
316333
def get_config_ini(filename: str) -> dict:
317334
"""Retrieve the contents of a specific config.ini file."""
318335
return get_from_leader(f"/api/configs/{filename}")
319336

320337

321-
@mcp.tool()
338+
@mcp.resource(path="units/{unit}/configuration", name="get_unit_configuration")
322339
def get_unit_configuration(unit: str) -> dict:
323340
"""Get merged configuration for a given unit (global and unit-specific)."""
324341
return get_from_leader(f"/api/units/{unit}/configuration")

web/static/js/main.fdca88b4.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)