Skip to content

Story 1: MCP Platform Tools Server #7422

Description

@cstns

Description

Summary

Expose FlowFuse platform management capabilities as MCP tools that external AI agents (Claude Desktop, Cursor, Claude Code) and the built-in expert agent can call. This is the foundational piece: a single HTTP endpoint that accepts MCP tool calls, authenticates via scoped PATs, and executes platform actions on behalf of the user.

Context

The platform needs a backend API surface for agentic orchestration. The product decision (#371) was to expose backend-callable endpoints rather than automating the frontend or extracting frontend logic into atomic actions. A single backend surface serves both the first-party expert and external "bring-your-own-agent" integrations, so orchestration logic is built once.

Requirements

Endpoint and transport

  • Single endpoint: POST /api/v1/mcp
  • Stateless Streamable HTTP. Each request is a self-contained JSON-RPC call with a Bearer token. No server-side sessions, no SSE, no session affinity needed.
  • From the load balancer's perspective, MCP traffic looks like ordinary REST traffic. Horizontally scalable with no shared state.
  • Each request creates a fresh McpServer instance and transport. The overhead of constructing and registering tools per request is negligible (microseconds of map insertions with references to module-level constants) compared to the actual tool execution cost (database queries, HTTP route processing).

Server placement

  • Lives inside Forge as an EE plugin. Direct access to app, existing auth, controllers, and middleware. No deployment overhead, no auth delegation complexity.
  • A separate microservice was considered and rejected for phase 1. The plugin approach is faster to ship and reuses existing infrastructure. The coupling cost is acceptable because MCP tools don't call controllers directly (see app.inject pattern below).

The app.inject() pattern

  • MCP tool handlers do not call controllers or services directly. They call existing HTTP routes through Fastify's in-process app.inject(), the same pattern used by test files.
  • This means every tool call goes through the full route lifecycle: middleware, validation, auth checks, audit logging. Routes stay untouched. Bug fixes in routes automatically apply to MCP tools.
  • The coupling is to the HTTP API contract (URL paths, request/response shapes), which is a more stable contract than internal controller signatures.
  • The PAT is passed through in the inject call's headers. The route's auth middleware resolves the user, and the existing preHandlers / needsPermission() checks enforce the user's actual RBAC (team membership, role, resource-level permissions). The MCP server is a passthrough for auth.

Authentication and authorization

  • Auth via scoped PATs (Add PAT (Personal Acces Tokens) scopes #7411). The PAT carries the user's identity. Every app.inject() call runs as that user with their existing permissions.
  • No MCP-specific RBAC layer. The platform already enforces what the user can and can't do through route-level permission checks. The MCP server doesn't need to duplicate or second-guess this.
  • The only access control specific to MCP is PAT scope enforcement: a read-only PAT can only call read-annotated tools. A non-read-only PAT can call all tools; route-level RBAC inside app.inject() handles the rest. This is a binary model (read-only vs not), not a multi-tier permission scheme. See Add PAT (Personal Acces Tokens) scopes #7411 for details.
  • PAT scopes are the mechanism for users to self-restrict what their agent can do. A user with full write access might create a read-only PAT as a safety net. That's a user choice, not a platform RBAC decision.

Tool definitions

  • Tools are a curated subset of the platform API, organized as semantic MCP tools with Zod schemas.
  • The POC defined 18 tools across read, write, and destructive categories:
    • Read: list-teams, list-applications, list-instances, get-instance, list-instance-types, list-stacks, list-blueprints, get-instance-status, check-name-availability
    • Write: create-application, create-instance (auto-starts), manage-instance (start/stop/restart/suspend), update-instance-settings, create-snapshot
    • Destructive: delete-instance, delete-application
    • Navigation: open-editor, open-instance
  • The exact tool surface for phase 1 needs to be enumerated (raised by dimitrieh on Define requirements #7368). The principle should be: tools that an agent would plausibly need for common orchestration workflows.
  • Tool annotations (readOnlyHint, destructiveHint) should map cleanly to PAT scope restrictions so scope enforcement is straightforward.

Tool organization

  • Tool definitions should be modular from the start. The POC put all 18 tools in one file (601 lines). As the surface grows (device management, pipelines, BOM, etc.), a single file won't scale.
  • Consider organizing by domain (team tools, instance tools, snapshot tools, etc.) with auto-registration. This should be designed upfront, not retrofitted.

What this story does NOT cover

  • Flow tools (NR instance MCP tools bridged through the browser). See Story 3.
  • UI tools (Vue Router navigation, browser-side actions). See Story 3.
  • OAuth2 authentication for external agents. See Story 2.
  • Audit logging specifics. See Story 4.

Open questions

  • Exact tool surface for phase 1 (which tools ship, which wait)
  • Tool organization structure (by domain, by capability tier, or other)

References

  • POC: PR feat: MCP platform server (proof of concept) #7414, specifically forge/ee/routes/mcpServer/index.js and forge/ee/lib/mcp/platformAutomations.js (reference only, not to be reused as-is)
  • Existing route patterns: routes in forge/routes/api/ for the HTTP API contracts that tools will call via `app.inject()

Metadata

Metadata

Assignees

Labels

storyA user-oriented description of a feature

Type

No type
No fields configured for issues without a type.

Projects

Status
In Progress

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions