flutterflow-mcp
This server does not currently have a deployable release on Glama. Follow the repository's setup instructions to install and configure it for your MCP client, including any required credentials and local dependencies.
flutterflow-mcp
flutterflow-mcp is an original FlutterFlow MCP server built around a command-palette model.
What Orbit Is
Orbit is different from multi-tool MCP servers by design:
One primary tool:
orbitCommand palette verbs inside
cmd(help,snapshots.create,changeset.apply, etc.)SQLite snapshot cache with persisted indices/graphs
Policy engine (
orbit.policy.json+ env overrides)Transactional ChangeSet flow:
new -> add -> preview -> validate -> apply
Related MCP server: community-ff-mcp
Features
Node.js 18+ TypeScript strict implementation
MCP stdio transport for Claude Desktop/Cursor/Windsurf/Claude Code/Codex
Separate HTTP health/status/policy service on port
8080FlutterFlow API adapter (set
FLUTTERFLOW_API_TOKENfor remote reads/writes)SQLite snapshot store (files, hashes, symbols, edges)
Navigation + component usage graph index
Safe editing policy engine with manual-approval mode
Orbit schema pack resources:
orbit://schema/indexorbit://schema/doc/{id}orbit://schema/snippet/{id}
Quick Start
1) Install
npm i2) Configure env (optional for local startup)
export FLUTTERFLOW_API_TOKEN=your_token_hereWithout a token, the MCP server still starts, but commands that call FlutterFlow APIs (for example projects.list, snapshots.create, snapshots.refresh) will return a missing-token error until you set it.
Optional API path overrides:
export FLUTTERFLOW_API_BASE_URL=https://api.flutterflow.io/v2
export FLUTTERFLOW_API_LIST_PROJECTS_PATH=/l/listProjects
export FLUTTERFLOW_API_LIST_PARTITIONED_FILES_PATH=/listPartitionedFileNames
export FLUTTERFLOW_API_PROJECT_YAMLS_PATH=/projectYamls
export FLUTTERFLOW_API_VALIDATE_PROJECT_YAML_PATH=/validateProjectYaml
export FLUTTERFLOW_API_UPDATE_PROJECT_YAML_PATH=/updateProjectByYaml
export FLUTTERFLOW_API_MIN_INTERVAL_MS=10003) Run
npm startThis starts:
MCP server over stdio
HTTP server on
http://localhost:8080
Endpoints:
GET /healthGET /statusGET /policy
If the HTTP port is already in use, Orbit now continues with MCP stdio and logs a warning to stderr. You can disable HTTP endpoints entirely with:
export ORBIT_HTTP_ENABLED=0MCP Client Setup
Use npm start as your MCP command.
Claude Desktop / Cursor / Windsurf
Use templates/mcp-config.local.json as a base:
{
"mcpServers": {
"ff_orbit_mcp": {
"command": "npm",
"args": ["start"],
"cwd": "/absolute/path/to/ff-mcp",
"env": {
"FLUTTERFLOW_API_TOKEN": "YOUR_TOKEN"
}
}
}
}Claude Code
Use project config file .mcp.json (you can copy templates/claude-code.mcp.json):
{
"mcpServers": {
"ff_orbit_mcp": {
"command": "npm",
"args": ["start"],
"cwd": "/absolute/path/to/ff-mcp",
"env": {
"FLUTTERFLOW_API_TOKEN": "YOUR_TOKEN"
}
}
}
}Or add it with CLI:
claude mcp add -s project -e FLUTTERFLOW_API_TOKEN=YOUR_TOKEN ff_orbit_mcp -- npm startCodex (CLI / App)
Option A: add via CLI:
codex mcp add ff_orbit_mcp --env FLUTTERFLOW_API_TOKEN=YOUR_TOKEN -- node /absolute/path/to/ff-mcp/dist/main.jsBuild once before using the command above:
npm run buildOption B: add to ~/.codex/config.toml (see templates/codex-config.toml):
[mcp_servers.ff_orbit_mcp]
command = "npm"
args = ["start"]
cwd = "/absolute/path/to/ff-mcp"
env = { FLUTTERFLOW_API_TOKEN = "YOUR_TOKEN" }
enabled = trueAgent Rule Pack
This repository now includes a clone-ready rule/setup pack for agents:
Rules:
.cursor/rules/Playbook:
docs/agent-playbook.mdMCP config templates:
templates/mcp-config.local.json,templates/mcp-config-remote.json,templates/claude-code.mcp.json,templates/codex-config.tomlInstaller script:
scripts/install-cursor-rules.sh
Install rules into another repo:
./scripts/install-cursor-rules.sh /absolute/path/to/target-projectOrbit Command Palette
Primary tool signature:
orbit({
cmd: string,
args?: object,
snapshot?: string,
format?: "json" | "explain"
})Discover commands:
orbit({ cmd: "help" })Core groups:
Discovery:
projects.list,snapshots.create,snapshots.refresh,snapshots.refreshSlow,snapshots.ensureFresh,snapshots.info,snapshots.lsAPI capabilities:
api.capabilitiesQuery:
search,page.create,page.scaffold,page.get,page.update,page.preflightDelete,page.remove(recommended),page.delete(low-level),page.clone,component.get,component.extractFromWidget,component.instance.insert,tree.locate,tree.subtree,tree.find(alias),tree.validate,tree.repair,graph.nav,graph.usage,pages.list,textfields.list,widget.get,widget.getMany,widgets.list,widgets.find,widgets.findText,widgets.updateMany,widgets.copyPaste,widget.create,widget.insert,widget.wrap,widget.unwrap,widget.duplicate,widget.deleteSubtree,widget.replaceType,widget.removeChildren,widget.move,widget.moveMany,widget.reorder,widget.action.list,widget.action.get,widget.bindAction,widget.bindData,widget.set,widget.delete,selection.get,selection.clear,intent.run,routes.list,routes.listByPage,routes.validate,routes.upsert,routes.delete,settings.getSummaries:
summarize.page,summarize.component,summarize.projectEditing:
changeset.new,changeset.add,changeset.preview,changeset.validate,changeset.apply,changeset.applySafe,changeset.rollback,changeset.revert,changeset.dropSchema:
schema.search,schema.read,schema.snippet
High-ROI recipes
Generate best-practice pages with deterministic recipes (preview-first):
orbit({ cmd:"page.scaffold", args:{ name:"login2", recipe:"auth.login", preview:true } })orbit({ cmd:"page.scaffold", args:{ name:"preferences", recipe:"settings.basic", params:{ toggles:["Notifications","Dark mode"] }, apply:true } })orbit({ cmd:"intent.run", args:{ text:"create a list page called products with search", preview:true } })
Duplicate a widget twice:
orbit({ cmd:"widget.duplicate", args:{ nameOrId:"login", nodeId:"id-Text_a", count:2, apply:true } })
Insert a widget in one call:
orbit({ cmd:"widget.insert", args:{ nameOrId:"login", type:"Divider", beforeNodeId:"id-Button_b", apply:true } })
Batch-update text widgets:
orbit({ cmd:"widgets.updateMany", args:{ nameOrId:"login", filter:{ type:"Text" }, set:{ text:"James NC" }, apply:true } })
Find widgets with one canonical search command:
orbit({ cmd:"widgets.find", args:{ nameOrId:"login", type:"TextField", textContains:"Password" } })
Batch get exact widgets:
orbit({ cmd:"widget.getMany", args:{ nameOrId:"login", nodeIds:["id-Text_a","id-Button_b"] } })
Route a button to another page:
orbit({ cmd:"routes.upsert", args:{ nameOrId:"login", nodeId:"id-Button_b", toPageNameOrId:"DailyDashboard", apply:true } })
Inspect and validate page routes:
orbit({ cmd:"routes.listByPage", args:{ nameOrId:"login", direction:"both" } })orbit({ cmd:"routes.validate", args:{ nameOrId:"login", strict:true } })
Batch move and unwrap widgets:
orbit({ cmd:"widget.moveMany", args:{ nameOrId:"login", nodeIds:["id-Text_b","id-Text_c"], afterNodeId:"id-Button_b", apply:true } })orbit({ cmd:"widget.unwrap", args:{ nameOrId:"login", nodeId:"id-Row_wrap", apply:true } })
List/get widget trigger actions:
orbit({ cmd:"widget.action.list", args:{ nameOrId:"login", nodeId:"id-Button_b" } })orbit({ cmd:"widget.action.get", args:{ nameOrId:"login", nodeId:"id-Button_b", trigger:"ON_TAP" } })
Ensure snapshot freshness before read/write:
orbit({ cmd:"snapshots.ensureFresh", args:{ staleMinutes:30 } })
Use sticky selection in conversational follow-ups:
orbit({ cmd:"selection.get" })orbit({ cmd:"intent.run", args:{ text:"unwrap this", apply:true } })
Safe apply orchestration:
orbit({ cmd:"changeset.applySafe", args:{ changesetId:"chg_x", confirm:true } })
Rollback latest applied changeset:
orbit({ cmd:"changeset.rollback", args:{ latestApplied:true, confirm:true, apply:true } })
Safer page delete flow:
orbit({ cmd:"page.preflightDelete", args:{ nameOrId:"login2" } })orbit({ cmd:"page.remove", args:{ nameOrId:"login2", apply:true } })page.removeattempts hard delete first, and can fall back to archive mode if FlutterFlow rejects delete payloads.
Validate/repair tree integrity:
orbit({ cmd:"tree.validate", args:{ nameOrId:"login" } })orbit({ cmd:"tree.repair", args:{ nameOrId:"login", fixOrphans:true, fixMissingNodes:true, apply:true } })
Optional support tools:
orbit_policy_getorbit_policy_set(disabled unlessORBIT_ALLOW_POLICY_WRITE=1)orbit_export_changeset
Snapshot Workflow
orbit({cmd:"projects.list"})orbit({cmd:"snapshots.create", args:{projectId:"..."}})Query against
snapshotidRun
snapshots.refreshbefore sensitive changes to avoid stale decisions (now throttled by default to reduce 429s)
Orbit snapshots are point-in-time and may be stale.
When FlutterFlow returns versionInfo (partitionerVersion, projectSchemaFingerprint), Orbit stores it and uses it for smarter incremental refresh decisions.
If FlutterFlow is rate-limiting refresh (429), prefer budgeted crawl mode:
orbit({ cmd:"snapshots.refreshSlow", args:{ passes:4, pauseMs:15000, maxFetch:25, concurrency:1, sleepMs:250 } })orbit({ cmd:"snapshots.refresh", args:{ mode:"full", fetchStrategy:"bulk" } })for low-request full sync attemptsorbit({ cmd:"snapshots.refresh", args:{ mode:"full", fetchStrategy:"file", maxFetch:5, concurrency:1, sleepMs:1000 } })for chunked full sync without relisting each pass (chunkedFulldefaults to true for full+file)
Safe Editing Workflow
changeset.newchangeset.add(one or many patches)changeset.preview(diff + risk)changeset.validate(YAML + structure + policy)changeset.applywithconfirm:true(includes remotevalidateProjectYamlchecks before push)
If policy requires manual approval, apply is refused and a manual payload is returned.
Policy Engine
Default file: orbit.policy.json
Fields:
allowProjectsallowFileKeyPrefixesdenyFileKeyPrefixesmaxFilesPerApplymaxLinesChangedrequireManualApprovalallowPlatformConfigEditssafeMode:readOnly | guidedWrite | fullWrite
Env overrides:
ORBIT_POLICY_ALLOW_PROJECTSORBIT_POLICY_ALLOW_FILE_PREFIXESORBIT_POLICY_DENY_FILE_PREFIXESORBIT_POLICY_MAX_FILES_PER_APPLYORBIT_POLICY_MAX_LINES_CHANGEDORBIT_POLICY_REQUIRE_MANUAL_APPROVALORBIT_POLICY_ALLOW_PLATFORM_CONFIG_EDITSORBIT_POLICY_SAFE_MODEORBIT_ALLOW_POLICY_WRITE=1(to enableorbit_policy_set)
Fly.io Deployment
flyctl launch
flyctl secrets set FLUTTERFLOW_API_TOKEN=your_token_here
flyctl deployfly.toml is configured with auto-suspend:
auto_start_machines = trueauto_stop_machines = "suspend"min_machines_running = 0
Development
npm run build
npm test
npm startSecurity Notes
Keep
FLUTTERFLOW_API_TOKENonly in environment variables or secret managers.Snapshot DB can include full project YAML and should be treated as sensitive data.
orbit.policy.jsonshould be code-reviewed because it controls write boundaries.Built-in read-only guards deny direct apply for custom code and unlocked
lib/main.dart.
FlutterFlow Project APIs Coverage
Orbit supports all currently documented FlutterFlow Project APIs (v2) through the adapter layer:
POST/GET /l/listProjectsGET /listPartitionedFileNamesGET /projectYamls(includingprojectYamlBytesbase64 zip decoding)POST /validateProjectYamlPOST /updateProjectByYaml
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
Related MCP Connectors
MCP server for interacting with the Supabase platform
One MCP server for all your MCP servers: code mode, per-tool permissions, approvals and audit.
MCP server for AI agents to plan, verify, and deploy Cloudflare-native apps.
Nifty's MCP server — exposes tasks, projects, messages, and files as tools for AI agents.
Related MCP Servers
- AlicenseCqualityBmaintenanceA Model Context Protocol server that connects Flutter apps with AI coding assistants like Cursor, Claude, and Cline, enabling AI-powered analysis of widget trees, navigation, and layout issues.62398MIT
- AlicenseAqualityDmaintenanceEnables AI-assisted FlutterFlow development by reading, exploring, and understanding FlutterFlow projects through Claude and other MCP-compatible clients.2553 npm10MIT
- AlicenseAqualityDmaintenanceAn MCP server that wraps Flutter CLI tools into structured, agent-friendly tools for AI coding agents, with features like two-phase test results, output capping, and managed app lifecycle.1516 npm4MIT
- FlicenseBqualityDmaintenanceMCP server that fetches Figma data (file trees, nodes, images, components, styles, variables) and serves as a foundation for Flutter code generation.13-