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
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:
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)
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
POST /api/v1/mcpServer placement
app, existing auth, controllers, and middleware. No deployment overhead, no auth delegation complexity.The
app.inject()patternapp.inject(), the same pattern used by test files.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
app.inject()call runs as that user with their existing permissions.Tool definitions
list-teams,list-applications,list-instances,get-instance,list-instance-types,list-stacks,list-blueprints,get-instance-status,check-name-availabilitycreate-application,create-instance(auto-starts),manage-instance(start/stop/restart/suspend),update-instance-settings,create-snapshotdelete-instance,delete-applicationopen-editor,open-instancereadOnlyHint,destructiveHint) should map cleanly to PAT scope restrictions so scope enforcement is straightforward.Tool organization
What this story does NOT cover
Open questions
References
forge/ee/routes/mcpServer/index.jsandforge/ee/lib/mcp/platformAutomations.js(reference only, not to be reused as-is)forge/routes/api/for the HTTP API contracts that tools will call via `app.inject()