feat(mcp-server): scheduler_pend_reasons tool — bjobs -p equivalent

New read-only tool that answers "why is my job waiting": lists PEND jobs (or
one by id) and translates each job's pending_reason into a human-readable
scenario (LSF bjobs -p style). Maps the PREASON_* codes surfaced by the
PEND-reason work (4e2ac86): no_resource / match_fail / limit_global /
limit_host / queue_closed / queue_draining / time_window / host_unavail.

- internal/pendreason.go: pending_reason JSON parsing (mirrors apiserver
  rawPendReason) + reasonScenario() translation + bjobs -p style summary.
- internal/app.go: HandlePendReasons — id param for one job, else pending
  list filtered by queue/owner/limit.
- cmd/main.go: register scheduler_pend_reasons (read-only).
- 5 unit tests (known/unknown codes, parse from JSON, missing reason,
  summary format). go test ./... + go vet clean.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
lei.chen 2026-08-15 03:25:28 +00:00
parent 0e9609af6d
commit 67abbfa492
4 changed files with 264 additions and 0 deletions

View file

@ -159,6 +159,17 @@ func main() {
mcp.WithDestructiveHintAnnotation(false),
), app.HandleEstimateWaitTime)
// ── scheduler_pend_reasons (bjobs -p equivalent) ──
s.AddTool(mcp.NewTool("scheduler_pend_reasons",
mcp.WithDescription("Explain why PEND (queued) jobs are waiting — the bjobs -p equivalent. Lists pending jobs (or one by id) and translates each job's PEND reason into a human-readable scenario (no_resource, match_fail, limit_host/global, queue_closed, host_unavail, ...)."),
mcp.WithString("id", mcp.Description("Specific job id to explain (optional; defaults to all pending jobs)")),
mcp.WithString("queue", mcp.Description("Filter by queue name")),
mcp.WithString("owner", mcp.Description("Filter by job owner username")),
mcp.WithNumber("limit", mcp.Description("Max results to return")),
mcp.WithReadOnlyHintAnnotation(true),
mcp.WithDestructiveHintAnnotation(false),
), app.HandlePendReasons)
// ── write tools (Phase 1) ──
// Write tools are annotated destructive so the MCP client (e.g. Claude
// Code) prompts the user for confirmation before executing them — the