feat(forge-mcp): expose CI job logs and issue dependency graph #1160

Merged
reviewer merged 1 commit from code-lead/1159 into main 2026-05-14 21:47:16 +00:00
Collaborator

Summary

Adds 4 mcp__forge__* tools so dev / code-lead / reviewer agents can self-diagnose CI failures and check the issue dependency graph without operator intervention:

  • get_job_logs(run_id, job_idx) — raw log text per job; ok()-wrapped so off-contract null returns surface as MCP errors instead of empty content
  • get_blockers(index) / get_blocked(index) — read the native Forgejo issue dependency graph (ForgeIssueRef[])
  • add_blocker(index, blocker) — record a new blocker on an issue

All four are added to FORGE_TOOLS_ALLOWLIST in apps/server/src/domain/agent/mcp-config.ts so the agent SDK permits them.

Tool-surface count moves 35 → 39 across the lockstep assertions in tools.test.ts, integration.test.ts, and mcp-config.test.ts.

Closes #1159.

Test plan

  • just qa — typecheck + lint + format + 3359 tests green
  • tools.test.ts per-tool dispatch + zod-validation tests for all 4 new tools (incl. a ForgeIssueRef[] shape passthrough check)
  • integration.test.ts stdio surface count bumped to 39 with all 4 new names asserted present
  • mcp-config.test.ts lockstep required set extended with all 4 new names
  • docs/forge-mcp.md tool-surface section updated with the new categories

🤖 Generated with Claude Code

## Summary Adds 4 `mcp__forge__*` tools so dev / code-lead / reviewer agents can self-diagnose CI failures and check the issue dependency graph without operator intervention: - `get_job_logs(run_id, job_idx)` — raw log text per job; `ok()`-wrapped so off-contract `null` returns surface as MCP errors instead of empty content - `get_blockers(index)` / `get_blocked(index)` — read the native Forgejo issue dependency graph (`ForgeIssueRef[]`) - `add_blocker(index, blocker)` — record a new blocker on an issue All four are added to `FORGE_TOOLS_ALLOWLIST` in `apps/server/src/domain/agent/mcp-config.ts` so the agent SDK permits them. Tool-surface count moves 35 → 39 across the lockstep assertions in `tools.test.ts`, `integration.test.ts`, and `mcp-config.test.ts`. Closes #1159. ## Test plan - [x] `just qa` — typecheck + lint + format + 3359 tests green - [x] `tools.test.ts` per-tool dispatch + zod-validation tests for all 4 new tools (incl. a `ForgeIssueRef[]` shape passthrough check) - [x] `integration.test.ts` stdio surface count bumped to 39 with all 4 new names asserted present - [x] `mcp-config.test.ts` lockstep `required` set extended with all 4 new names - [x] `docs/forge-mcp.md` tool-surface section updated with the new categories 🤖 Generated with [Claude Code](https://claude.com/claude-code)
feat(forge-mcp): expose CI job logs and issue dependency graph
All checks were successful
qa / sql-layer-check (pull_request) Successful in 11s
qa / i18n-string-check (pull_request) Successful in 16s
qa / db-schema (pull_request) Successful in 20s
qa / dockerfile (pull_request) Successful in 26s
qa / qa-1 (pull_request) Successful in 3m38s
qa / qa (pull_request) Successful in 0s
b2eca9b326
Adds 4 tools so dev / code-lead / reviewer agents can self-diagnose CI
failures and check dependency state without operator intervention:

- `get_job_logs(run_id, job_idx)` — raw log per job, ok()-wrapped so
  off-contract null returns surface as MCP errors
- `get_blockers` / `get_blocked` — read the native Forgejo dependency
  graph
- `add_blocker` — record a new blocker

All four are added to FORGE_TOOLS_ALLOWLIST so the SDK permits them.
Tool surface count moves 35 → 39 across tools.test.ts, integration.test.ts,
and mcp-config.test.ts lockstep assertions.

Closes #1159

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
reviewer approved these changes 2026-05-14 21:47:10 +00:00
reviewer left a comment

APPROVE

Clean, well-scoped surface expansion. All four tools follow established patterns throughout.

What was verified

ForgePort / adapter layer: getJobLogs, getBlockers, getBlocked, addBlocker are already defined in forgejo-port.ts and covered by the conformance suite on main — this PR is purely the MCP surface layer on top of already-implemented port methods. No adapter changes needed.

ok() usage is consistent with the rest of the surface:

  • get_job_logs wraps with ok() even though the port return type is Promise<string> (non-nullable). The test comment explains why: belt-and-suspenders against off-contract adapters that might drift and return null at runtime. Pattern is explicit and tested.
  • get_blockers / get_blocked return ForgeIssueRef[] — empty array on error per port convention, no ok() needed. Matches listIssues, listWorkflowRuns, etc.
  • add_blocker returns boolean — matches addLabels, patchIssue, etc. Consistent.

Test quality: Dispatch + arg passthrough, ok() error surface, Zod rejection paths, and a ForgeIssueRef[] shape passthrough check. The three lockstep count assertions (35 → 39) are all updated in sync.

Docs: docs/forge-mcp.md also fixes a pre-existing gap — get_aggregate_ci_status was present in the tool surface since #920 but was missing from the CI category in the docs. Good catch.

CI: green on b2eca9b.

Observations (non-blocking)

  1. add_blocker description says "in the same repo" — accurate given the schema only accepts a bare integer. If cross-repo blocker creation ever lands on the port, the schema and description will need a target_repo arg. Fine for now.
  2. The get_job_logs description lists "dev / code-lead / reviewer agents" explicitly. Slightly prescriptive but serves as useful in-tool documentation for the agent picker.

Nothing to block on. Merging.

## APPROVE Clean, well-scoped surface expansion. All four tools follow established patterns throughout. ### What was verified **ForgePort / adapter layer**: `getJobLogs`, `getBlockers`, `getBlocked`, `addBlocker` are already defined in `forgejo-port.ts` and covered by the conformance suite on main — this PR is purely the MCP surface layer on top of already-implemented port methods. No adapter changes needed. **`ok()` usage is consistent with the rest of the surface**: - `get_job_logs` wraps with `ok()` even though the port return type is `Promise<string>` (non-nullable). The test comment explains why: belt-and-suspenders against off-contract adapters that might drift and return `null` at runtime. Pattern is explicit and tested. - `get_blockers` / `get_blocked` return `ForgeIssueRef[]` — empty array on error per port convention, no `ok()` needed. Matches `listIssues`, `listWorkflowRuns`, etc. - `add_blocker` returns `boolean` — matches `addLabels`, `patchIssue`, etc. Consistent. **Test quality**: Dispatch + arg passthrough, `ok()` error surface, Zod rejection paths, and a `ForgeIssueRef[]` shape passthrough check. The three lockstep count assertions (35 → 39) are all updated in sync. **Docs**: `docs/forge-mcp.md` also fixes a pre-existing gap — `get_aggregate_ci_status` was present in the tool surface since #920 but was missing from the CI category in the docs. Good catch. **CI**: green on `b2eca9b`. ### Observations (non-blocking) 1. `add_blocker` description says "in the same repo" — accurate given the schema only accepts a bare integer. If cross-repo blocker creation ever lands on the port, the schema and description will need a `target_repo` arg. Fine for now. 2. The `get_job_logs` description lists "dev / code-lead / reviewer agents" explicitly. Slightly prescriptive but serves as useful in-tool documentation for the agent picker. Nothing to block on. Merging.
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
charles/agent-hooks!1160
No description provided.