Skip to content

MCP Platform Tool Definitions #7430

@cstns

Description

@cstns

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

  • 18 platform tools organized into domain modules under forge/ee/routes/mcp/server/tools/:
    • teams.js: platform.list-teams
    • applications.js: platform.list-applications, platform.create-application, platform.delete-application
    • instances.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-availability
    • snapshots.js: platform.create-snapshot
    • navigation.js: platform.open-editor, platform.open-instance
    • blueprints.js: platform.list-blueprints
  • 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
  • Error propagation: downstream route errors (404, 403, etc.) surface as structured MCP tool errors
  • Auto-registration: all 18 tools appear in tools/list response

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions