You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Implement the 18 platform tools as modular, domain-organized definitions under forge/ee/routes/mcp/server/tools/, wire up auto-registration into the endpoint handler from #7429, and add PAT scope enforcement based on tool annotations. This task may be broken into smaller sub-tasks if needed for ease of implementation and testing.
Each module exports an array of { name, description, inputSchema, annotations, handler } entries
Each tool handler uses app.inject() to call the corresponding existing HTTP route, forwarding the caller's PAT in the Authorization header
Tool annotations follow the MCP spec: readOnlyHint, destructiveHint, idempotentHint, openWorldHint
Shared helpers (_helpers.js)
inject({ app, method, url, payload, headers }): wraps app.inject(), forwards the Authorization header from the original request
assertOk(response, actionLabel): throws a structured error if the inject response status is >= 400, including the downstream error message and status code
Auto-registration (tools/index.js)
Discovers and aggregates all tool modules in the tools/ directory (excluding index.js and _helpers.js)
Exports a flat array of all tool definitions for the endpoint handler to iterate over
PAT scope enforcement
Before calling a tool handler, the endpoint checks the PAT's scope (from request.session.scope, as defined by Add PAT (Personal Acces Tokens) scopes #7411) against the tool's annotations
Read-annotated tools (readOnlyHint: true) are allowed by any PAT scope tier
Write-annotated tools (readOnlyHint: false, destructiveHint: false) require a write-capable PAT scope
Destructive-annotated tools (destructiveHint: true) require a delete-capable PAT scope
If the PAT scope is insufficient, reject with a structured error before the tool handler runs
Route-level RBAC (team membership, role, resource permissions) is handled by the existing route preHandlers inside app.inject(). No MCP-specific RBAC layer.
Tests
Each domain module: verify tools return expected results for valid requests via app.inject()
PAT scope enforcement: read-only PAT can call read tools, cannot call write/destructive tools
PAT scope enforcement: write PAT can call write tools, cannot call destructive tools
Destructive tools: verify the downstream route is called correctly
Summary
Implement the 18 platform tools as modular, domain-organized definitions under
forge/ee/routes/mcp/server/tools/, wire up auto-registration into the endpoint handler from #7429, and add PAT scope enforcement based on tool annotations. This task may be broken into smaller sub-tasks if needed for ease of implementation and testing.Prerequisites
Requirements
Tool definitions
forge/ee/routes/mcp/server/tools/:teams.js:platform.list-teamsapplications.js:platform.list-applications,platform.create-application,platform.delete-applicationinstances.js:platform.list-instances,platform.get-instance,platform.get-instance-status,platform.list-instance-types,platform.list-stacks,platform.create-instance,platform.manage-instance,platform.update-instance-settings,platform.delete-instance,platform.check-name-availabilitysnapshots.js:platform.create-snapshotnavigation.js:platform.open-editor,platform.open-instanceblueprints.js:platform.list-blueprints{ name, description, inputSchema, annotations, handler }entriesapp.inject()to call the corresponding existing HTTP route, forwarding the caller's PAT in the Authorization headerreadOnlyHint,destructiveHint,idempotentHint,openWorldHintShared helpers (
_helpers.js)inject({ app, method, url, payload, headers }): wrapsapp.inject(), forwards the Authorization header from the original requestassertOk(response, actionLabel): throws a structured error if the inject response status is >= 400, including the downstream error message and status codeAuto-registration (
tools/index.js)tools/directory (excludingindex.jsand_helpers.js)PAT scope enforcement
request.session.scope, as defined by Add PAT (Personal Acces Tokens) scopes #7411) against the tool's annotationsreadOnlyHint: true) are allowed by any PAT scope tierreadOnlyHint: false,destructiveHint: false) require a write-capable PAT scopedestructiveHint: true) require a delete-capable PAT scopeapp.inject(). No MCP-specific RBAC layer.Tests
app.inject()tools/listresponseReferences
app.inject():forge/routes/api/andforge/ee/routes/