pyp6xer_resource_utilization
Summarize resource loading by comparing planned, actual, and remaining quantities and costs for project resources.
Instructions
Summarise resource loading: planned vs actual vs remaining quantities and costs.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| cache_key | No | Cache key identifying the loaded XER file (set when calling pyp6xer_load_file) | default |
| proj_id | No | Project ID or short name; uses first project if omitted | |
| rsrc_name | No | Filter by resource name (partial match) |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| result | Yes |
Implementation Reference
- server.py:1140-1196 (handler)The pyp6xer_resource_utilization tool handler function. Aggregates resource loading data (planned vs actual vs remaining quantities and costs) from the XER file, optionally filtered by project ID and resource name. Returns utilization percentages and cost summaries.
@mcp.tool(annotations=ToolAnnotations(readOnlyHint=True, destructiveHint=False, idempotentHint=True, openWorldHint=False)) def pyp6xer_resource_utilization( cache_key: Annotated[str, Field(description="Cache key identifying the loaded XER file (set when calling pyp6xer_load_file)")] = "default", proj_id: Annotated[str | None, Field(description="Project ID or short name; uses first project if omitted")] = None, rsrc_name: Annotated[str | None, Field(description="Filter by resource name (partial match)")] = None, ctx: Context = None, ) -> str: """Summarise resource loading: planned vs actual vs remaining quantities and costs. Args: cache_key: Cache key of the loaded file. proj_id: Optional project filter. rsrc_name: Filter to a specific resource name (substring match). """ xer = _get_xer(ctx, cache_key) if proj_id: task_rsrcs = _get_project(xer, proj_id).resources else: task_rsrcs = [tr for t in xer.tasks.values() for tr in t.resources.values()] # Aggregate by resource by_rsrc: dict = {} for tr in task_rsrcs: name = tr.resource.name if rsrc_name and rsrc_name.lower() not in name.lower(): continue if name not in by_rsrc: by_rsrc[name] = { "resource": name, "type": tr.resource.type, "assignments": 0, "target_qty": 0.0, "actual_qty": 0.0, "remain_qty": 0.0, "target_cost": 0.0, "actual_cost": 0.0, "remain_cost": 0.0, "at_completion_cost": 0.0, } s = by_rsrc[name] s["assignments"] += 1 s["target_qty"] += tr.target_qty s["actual_qty"] += tr.act_reg_qty + tr.act_ot_qty s["remain_qty"] += tr.remain_qty s["target_cost"] += tr.target_cost s["actual_cost"] += tr.act_total_cost s["remain_cost"] += tr.remain_cost s["at_completion_cost"] += tr.act_total_cost + tr.remain_cost for s in by_rsrc.values(): s["utilization_pct"] = ( round(s["actual_qty"] / s["target_qty"] * 100, 1) if s["target_qty"] else None ) items = sorted(by_rsrc.values(), key=lambda x: -x["target_cost"]) return json.dumps({"total_resources": len(items), "resources": items}, indent=2) - server.py:1140-1146 (registration)Registration of pyp6xer_resource_utilization as an MCP tool via the @mcp.tool decorator with annotations for read-only, non-destructive, idempotent behavior.
@mcp.tool(annotations=ToolAnnotations(readOnlyHint=True, destructiveHint=False, idempotentHint=True, openWorldHint=False)) def pyp6xer_resource_utilization( cache_key: Annotated[str, Field(description="Cache key identifying the loaded XER file (set when calling pyp6xer_load_file)")] = "default", proj_id: Annotated[str | None, Field(description="Project ID or short name; uses first project if omitted")] = None, rsrc_name: Annotated[str | None, Field(description="Filter by resource name (partial match)")] = None, ctx: Context = None, ) -> str: