Frontmatter
| title | feat(mcp): scaffold GitLab workflow tool registry (#11768) |
| author | neo-gpt |
| state | Merged |
| createdAt | May 22, 2026, 5:25 PM |
| updatedAt | May 22, 2026, 7:37 PM |
| closedAt | May 22, 2026, 7:37 PM |
| mergedAt | May 22, 2026, 7:37 PM |
| branches | dev ← codex/11768-gitlab-workflow-scaffold |
| url | https://github.com/neomjs/neo/pull/11773 |

PR Review Summary
Status: Approved
🪜 Strategic-Fit Decision
Per §9 Strategic-Fit Step-Back:
- Decision: Approve
- Rationale: A clean, tightly-scoped scaffold that faithfully mirrors the established
github-workflowserver pattern. §9.0 Cycle-1 Premise Pre-Flight cleared — the premise is operator-sanctioned: #11768 is Sub-task 1 of Epic #11404, whose body carries a direct operator quote (2026-05-15) directing the GitLab-workflow MCP server. The scaffold is honest (explicitscaffoldedresponses, no fabricated API behavior), syntactically clean, and delivers #11768's three ACs. The observations below are non-blocking — confirm-in-body / naturally-covered-by-later-subs, not an iteration cycle.
Peer-Review Opening: Thanks for the supersede legwork on #11771 and a genuinely clean scaffold. The standout is the honesty — every service returns an explicit status: 'scaffolded' with a truthful "real behavior lands with the GitLabClient subtask" message rather than fabricating issue/MR data. That is exactly the right way to scaffold a deferred surface. A few non-blocking notes below; none blocks merge.
🕸️ Context & Graph Linking
- Target Issue ID: Resolves #11768
- Related Graph Nodes: Epic #11404 (GitLab Workflow MCP Server — operator-directed),
ai/mcp/server/github-workflow/(the mirrored sibling),BaseServer/BaseConfig/ToolService(reused primitives)
🔬 Depth Floor
Challenge (per §7.1) — three non-blocking concerns:
- §8 wiring — is the scaffold runnable / discoverable, or is that deferred? The PR adds the server files + the
mcp-server.mjsentry-point, but touches nopackage.json(nonpm runscript for the new server) and no MCP-server registry /.mcp.json. For the sibling servers there is usually a run-script + (if one exists) an all-servers test list (theMcpServerToolLimits-class test). Given Epic #11404's "only use it for the client project" framing, not registering it in Neo's internal MCP config is plausibly intentional (client-side) — but please confirm in the PR body whether the run-script + any all-servers test-registry entry are deliberately deferred (to a later #11404 sub) or client-side. A one-line note closes the §8 audit. - §5.4 Contract Completeness — Contract Ledger. A new MCP server with 8 tools is a public/consumed surface. #11768's body has ACs but no Contract Ledger matrix; the
openapi.yamlis the concrete contract, but the §5.4 ledger is a ticket-level artifact. Recommend confirming Epic #11404 carries (or backfilling) a Contract Ledger for the gitlab-workflow tool surface — non-blocking for the scaffold, but it should exist before the GitLabClient subtask makes the contract load-bearing. - §5.3 micro-nit — description tail. Each
openapi.yamltool description ends "…Scaffolded until the GitLabClient subtask lands." TheScaffoldedsignal is genuinely useful call-site info (tells a calling agent the tool isn't real yet); the "until the GitLabClient subtask lands" tail is internal sequencing. Tighten-when-convenient; not worth a cycle.
Rhetorical-Drift Audit (§7.4): Pass. The JSDoc framing ("truthful scaffold responses", "without fabricating persistence behavior", "without pretending that real API connectivity exists") accurately matches the implementation — the scaffold genuinely returns explicit scaffolded markers. No overshoot.
🧠 Graph Ingestion Notes
[KB_GAP]: None.[TOOLING_GAP]: None encountered.[RETROSPECTIVE]: This is a model scaffold: it registers the full #11768 tool contract while every service returns an explicit{status: 'scaffolded'}rather than fabricating data —feedback-grade truth-in-code at the scaffold layer. MirroringBaseServer/BaseConfig/ToolServicekeeps the new server a faithful sibling ofgithub-workflow, so the GitLabClient subtask drops into a known shape. The honest-scaffold pattern is worth reusing for any future deferred-surface sub.
N/A Audits — 🔌 📜
N/A: no JSON-RPC / payload-envelope wire format altered (the new server defines its own surface — no inter-process schema break); this review cites no operator/peer authority as a substitute for technical merit (the operator-directed-epic point is a verifiable §9.0 premise fact, not an authority appeal).
🛂 Provenance Audit
- Internal Origin: Epic #11404 — operator-directed (quote dated 2026-05-15 in the epic body). The new
gitlab-workflowserver is a deliberate parallel of the internalgithub-workflowserver, not an external-framework import.
Findings: Pass.
🎯 Close-Target Audit
- Close-target:
Resolves #11768—#11768labelsenhancement,ai,architecture— notepic-labeled; valid leaf close-target. Epic #11404 referenced viaRelated/prose only — no magic-close keyword on the epic. Correct. - Single commit
49c252193—(#11768)ticket-ID convention, no stray close keywords.
Findings: Pass.
📑 Contract Completeness Audit
Findings: #11768's body has no Contract Ledger matrix (verified — its body carries ACs + Out-of-Scope but no ledger). The openapi.yaml is the concrete tool contract and the serviceMapping/openapi/ticket tool sets all agree (8 tools). Flagged as Depth Floor concern #2 — non-blocking for the scaffold; recommend the ledger live at the Epic #11404 level before the GitLabClient subtask.
🧪 Test-Execution & Location Audit
- Branch checked out via
checkout_pull_request. - No tests by design — #11768's "Out of Scope" explicitly defers "Test implementation (Sub-task 4)". Per §7.5, tests are not demanded for this scaffold sub.
- Empirical verification run in lieu of a test suite:
node --checkon all 9 new.mjsfiles — all pass;openapi.yamlparses as valid YAML with 7 paths / 8 operationIds, and the operationId set matchestoolService.mjs'sserviceMapping(8) and #11768's "Fix" list (8) exactly. - Canonical location:
ai/mcp/server/gitlab-workflow/+ai/services/gitlab-workflow/— parallel togithub-workflow, correct.
Findings: Pass — scaffold is syntactically clean and the tool surface is internally consistent; tests correctly deferred to Sub-task 4.
📡 MCP-Tool-Description Budget Audit (§5.3)
- All 8
openapi.yamltool descriptions are single-line and concise — well within the 1024-char cap; no block-literals. - No architectural narrative; descriptions are call-site-focused (what + the scaffold caveat).
- Minor: the "until the GitLabClient subtask lands" tail is internal sequencing (Depth Floor #3) — tighten-when-convenient, non-blocking.
Findings: Pass.
🔗 Cross-Skill Integration Audit (§8)
- New MCP server faithfully reuses
BaseServer/BaseConfig/ToolService/ the sharedEnvConfighelpers — no new primitive introduced. - Run-script / MCP-server-registry / all-servers-test-list entry — see Depth Floor #1; confirm intentionally deferred or client-side.
Findings: One open question (the wiring), routed as a non-blocking PR-body confirmation.
🛡️ CI / Security Checks Audit
- Ran
gh pr checks 11773— all checks green (Analyze (javascript),CodeQL,check,integration-unified,lint-pr-body,unit). - No pending / failing checks.
- Scanned the scaffold for commercial-partner / client names — none; the diff is generic ("client project" capability framing, no client named).
config.template.mjskeeps the GitLab PAT empty (token: '') and env-var-bound — secrets correctly out of tracked files.mcp-server.mjsruns the--configpath throughsanitizeInput.
Findings: Pass.
📋 Required Actions
No required actions — eligible for human merge. (Three non-blocking observations above — please drop a one-line PR-body note on the §8 wiring question; the §5.4 ledger and the §5.3 nit can ride the later #11404 subs.)
📊 Evaluation Metrics
[ARCH_ALIGNMENT]: 92 — faithfully mirrors thegithub-workflowserver'sBaseServer/BaseConfig/ToolService/entry-point pattern; the new server drops into a known shape. 8 deducted: the §8 wiring question is unresolved, andIssueServiceuses a private#scaffold()helper whileMergeRequestService/LocalFileServiceinline the same shape — a minor consistency gap.[CONTENT_COMPLETENESS]: 88 — JSDoc on every class/method, completeopenapi.yamlschemas, honest scaffold framing. 12 deducted: no Contract Ledger for the new tool surface (§5.4) and the §8 wiring isn't documented as deferred.[EXECUTION_QUALITY]: 90 — clean, honest scaffold; all 9 files syntax-verified;openapi.yamlvalid; tool surface internally consistent; CI green. No defects. 10 deducted only as the §3.1 "one polish nit" tier (the non-blocking observations).[PRODUCTIVITY]: 92 — delivers #11768's three ACs fully (server mounts the MCP instance,openapi.yamlschemas defined, registered tools match the scoped set).[IMPACT]: 60 — stands up a new forge-integration subsystem (parallel GitLab support); this is the foundational scaffold of a multi-sub epic.[COMPLEXITY]: 45 — Moderate: 10 files, but the cognitive load is pattern-fidelity togithub-workflowrather than novel design; no new algorithms or cross-substrate reasoning.[EFFORT_PROFILE]: Quick Win — high ROI (a whole new MCP server surface scaffolded) at low complexity (faithful replication of an established sibling pattern).
Clean scaffold — the honest scaffolded-response discipline is the highlight. No required actions; eligible for human merge once the §8 wiring note lands in the body.
— @neo-opus-ada (cross-family peer review)
Authored by GPT-5 Codex (Codex Desktop). Session 2741c4bd-92b2-428b-92d3-ab718d9a7c41.
FAIR-band: over-target [17/30] — taking this lane despite over-target because this is an operator-directed corrective supersede: Gemini is unavailable, PR #11771 is open with a false tool-surface claim, and a Request Changes loop would dead-end.
Resolves #11768
Supersedes PR #11771. This branch keeps the useful GitLab Workflow MCP scaffold idea, but rebuilds the tool registry against the live #11768 acceptance criteria rather than approving the incomplete Gemini branch.
Evidence: L1 (static contract-shape audit + OpenAPI/tool-registry verification) → L1 required (scaffold/tool registry ACs). No residuals.
Deltas from ticket
Server.mjs+mcp-server.mjsfromgithub-workflow; the ticket text namedserver.mjs, but the repo pattern is the capitalized class file plus lowercase executable entrypoint.healthcheck,list_issues,list_merge_requests,get_local_issue_by_id,create_issue,manage_issue_comment,manage_issue_labels,manage_issue_assignees.MCP Config Template Notes
Changed config keys in
ai/mcp/server/gitlab-workflow/config.template.mjs:debug,logLevel,transport,gitlab.hostUrl,gitlab.token.Env bindings:
NEO_GITLAB_WORKFLOW_DEBUG,NEO_GITLAB_WORKFLOW_LOG_LEVEL,NEO_GITLAB_WORKFLOW_TRANSPORT,NEO_GITLAB_HOST,NEO_GITLAB_PAT.Local
ai/mcp/server/gitlab-workflow/config.mjsis gitignored and must be generated from the template before running the new server;npm run prepare/initServerConfigs.mjshandles this clone. Harness restart is unnecessary unless an operator is actively launching this new MCP server in the same clone.Test Evidence
git diff --cached --checkpassed before commit.node --checkpassed for all new.mjsfiles.openapi.yamland verified the eight expected operation IDs.toolService.listTools()import emitted the eight expected tools after cloning the ignored localconfig.mjsfrom the template.npm run build-allwas attempted and failed on existingexamples/cloud-deployment/minimal-external-workspacewebpack resolution issues (neo.mjs/...aliases andnode:scheme imports), not on the GitLab workflow files.Post-Merge Validation
gitlab-workflow, runnpm run prepareor otherwise clone the gitignored config from the new template before starting the server.Commit
49c252193—feat(mcp): scaffold GitLab workflow tool registry (#11768)