community-ff-mcp 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +300 -0
- package/build/api/flutterflow.d.ts +11 -0
- package/build/api/flutterflow.js +61 -0
- package/build/index.d.ts +2 -0
- package/build/index.js +78 -0
- package/build/prompts/dev-workflow.d.ts +2 -0
- package/build/prompts/dev-workflow.js +68 -0
- package/build/prompts/generate-page.d.ts +2 -0
- package/build/prompts/generate-page.js +37 -0
- package/build/prompts/inspect-project.d.ts +2 -0
- package/build/prompts/inspect-project.js +30 -0
- package/build/prompts/modify-component.d.ts +2 -0
- package/build/prompts/modify-component.js +40 -0
- package/build/resources/docs.d.ts +2 -0
- package/build/resources/docs.js +76 -0
- package/build/resources/projects.d.ts +3 -0
- package/build/resources/projects.js +60 -0
- package/build/tools/find-component-usages.d.ts +21 -0
- package/build/tools/find-component-usages.js +216 -0
- package/build/tools/find-page-navigations.d.ts +26 -0
- package/build/tools/find-page-navigations.js +220 -0
- package/build/tools/get-api-endpoints.d.ts +2 -0
- package/build/tools/get-api-endpoints.js +126 -0
- package/build/tools/get-app-settings.d.ts +2 -0
- package/build/tools/get-app-settings.js +169 -0
- package/build/tools/get-app-state.d.ts +2 -0
- package/build/tools/get-app-state.js +96 -0
- package/build/tools/get-component-summary.d.ts +22 -0
- package/build/tools/get-component-summary.js +195 -0
- package/build/tools/get-custom-code.d.ts +2 -0
- package/build/tools/get-custom-code.js +380 -0
- package/build/tools/get-data-models.d.ts +2 -0
- package/build/tools/get-data-models.js +266 -0
- package/build/tools/get-editing-guide.d.ts +7 -0
- package/build/tools/get-editing-guide.js +185 -0
- package/build/tools/get-general-settings.d.ts +2 -0
- package/build/tools/get-general-settings.js +116 -0
- package/build/tools/get-in-app-purchases.d.ts +2 -0
- package/build/tools/get-in-app-purchases.js +51 -0
- package/build/tools/get-integrations.d.ts +2 -0
- package/build/tools/get-integrations.js +137 -0
- package/build/tools/get-page-by-name.d.ts +3 -0
- package/build/tools/get-page-by-name.js +56 -0
- package/build/tools/get-page-summary.d.ts +22 -0
- package/build/tools/get-page-summary.js +205 -0
- package/build/tools/get-project-config.d.ts +2 -0
- package/build/tools/get-project-config.js +216 -0
- package/build/tools/get-project-setup.d.ts +2 -0
- package/build/tools/get-project-setup.js +212 -0
- package/build/tools/get-theme.d.ts +2 -0
- package/build/tools/get-theme.js +199 -0
- package/build/tools/get-yaml-docs.d.ts +6 -0
- package/build/tools/get-yaml-docs.js +116 -0
- package/build/tools/get-yaml.d.ts +2 -0
- package/build/tools/get-yaml.js +53 -0
- package/build/tools/list-files.d.ts +3 -0
- package/build/tools/list-files.js +49 -0
- package/build/tools/list-pages.d.ts +25 -0
- package/build/tools/list-pages.js +101 -0
- package/build/tools/list-projects.d.ts +3 -0
- package/build/tools/list-projects.js +23 -0
- package/build/tools/search-project-files.d.ts +2 -0
- package/build/tools/search-project-files.js +69 -0
- package/build/tools/sync-project.d.ts +3 -0
- package/build/tools/sync-project.js +147 -0
- package/build/tools/update-yaml.d.ts +3 -0
- package/build/tools/update-yaml.js +24 -0
- package/build/tools/validate-yaml.d.ts +3 -0
- package/build/tools/validate-yaml.js +39 -0
- package/build/utils/batch-process.d.ts +2 -0
- package/build/utils/batch-process.js +10 -0
- package/build/utils/cache.d.ts +58 -0
- package/build/utils/cache.js +199 -0
- package/build/utils/decode-yaml.d.ts +7 -0
- package/build/utils/decode-yaml.js +31 -0
- package/build/utils/page-summary/action-summarizer.d.ts +24 -0
- package/build/utils/page-summary/action-summarizer.js +291 -0
- package/build/utils/page-summary/formatter.d.ts +13 -0
- package/build/utils/page-summary/formatter.js +129 -0
- package/build/utils/page-summary/node-extractor.d.ts +24 -0
- package/build/utils/page-summary/node-extractor.js +227 -0
- package/build/utils/page-summary/tree-walker.d.ts +6 -0
- package/build/utils/page-summary/tree-walker.js +55 -0
- package/build/utils/page-summary/types.d.ts +58 -0
- package/build/utils/page-summary/types.js +4 -0
- package/build/utils/parse-folders.d.ts +9 -0
- package/build/utils/parse-folders.js +29 -0
- package/build/utils/resolve-data-type.d.ts +2 -0
- package/build/utils/resolve-data-type.js +18 -0
- package/build/utils/topic-map.d.ts +7 -0
- package/build/utils/topic-map.js +122 -0
- package/docs/ff-yaml/00-overview.md +166 -0
- package/docs/ff-yaml/01-project-files.md +2309 -0
- package/docs/ff-yaml/02-pages.md +572 -0
- package/docs/ff-yaml/03-components.md +784 -0
- package/docs/ff-yaml/04-widgets/README.md +122 -0
- package/docs/ff-yaml/04-widgets/button.md +444 -0
- package/docs/ff-yaml/04-widgets/container.md +358 -0
- package/docs/ff-yaml/04-widgets/dropdown.md +579 -0
- package/docs/ff-yaml/04-widgets/form.md +256 -0
- package/docs/ff-yaml/04-widgets/image.md +276 -0
- package/docs/ff-yaml/04-widgets/layout.md +355 -0
- package/docs/ff-yaml/04-widgets/misc.md +553 -0
- package/docs/ff-yaml/04-widgets/text-field.md +326 -0
- package/docs/ff-yaml/04-widgets/text.md +302 -0
- package/docs/ff-yaml/05-actions.md +953 -0
- package/docs/ff-yaml/06-variables.md +849 -0
- package/docs/ff-yaml/07-data.md +591 -0
- package/docs/ff-yaml/08-custom-code.md +736 -0
- package/docs/ff-yaml/09-theming.md +638 -0
- package/docs/ff-yaml/10-editing-guide.md +497 -0
- package/docs/ff-yaml/README.md +105 -0
- package/package.json +59 -0
- package/skills/community-ff-mcp/SKILL.md +201 -0
- package/skills/ff-widget-patterns.md +141 -0
- package/skills/ff-yaml-dev.md +70 -0
package/README.md
ADDED
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
# community-ff-mcp
|
|
2
|
+
|
|
3
|
+
MCP server for the FlutterFlow Project API. Enables AI-assisted FlutterFlow development through Claude and other MCP-compatible clients.
|
|
4
|
+
|
|
5
|
+
## What This MCP Does Best
|
|
6
|
+
|
|
7
|
+
This MCP excels at **reading, exploring, and understanding** your FlutterFlow projects. Here's what it's great at:
|
|
8
|
+
|
|
9
|
+
- **Project exploration** — Browse your projects, pages, components, and file structure
|
|
10
|
+
- **Understanding functionality** — Get clear summaries of what a page or component does, including its widget tree, actions, parameters, and state
|
|
11
|
+
- **Tracing usage** — Find everywhere a component is used, or every navigation action that leads to a page
|
|
12
|
+
- **Inspecting configuration** — View theme settings, API endpoints, data models, custom code, app state, integrations, and more
|
|
13
|
+
- **Searching** — Search project files by keyword, prefix, or regex to find exactly what you need
|
|
14
|
+
- **YAML reference** — Built-in documentation for FlutterFlow's YAML schema, so your AI assistant can understand and generate valid YAML
|
|
15
|
+
- **Guided editing** — A workflow guide (`get_editing_guide`) that walks through the correct steps before making any YAML changes
|
|
16
|
+
|
|
17
|
+
> **In short:** Think of it as giving your AI assistant full read access to your FlutterFlow project, plus careful write access when needed.
|
|
18
|
+
|
|
19
|
+
## Quick Start
|
|
20
|
+
|
|
21
|
+
### 1. Get Your FlutterFlow API Token
|
|
22
|
+
|
|
23
|
+
You need a FlutterFlow API token to authenticate. Here's how to get one:
|
|
24
|
+
|
|
25
|
+
1. Open [FlutterFlow](https://app.flutterflow.io/) and log in
|
|
26
|
+
2. Click your **profile picture** (bottom-left corner)
|
|
27
|
+
3. Go to **Account Settings**
|
|
28
|
+
4. Scroll to the **API Token** section
|
|
29
|
+
5. Click **Copy** to copy your token
|
|
30
|
+
|
|
31
|
+
> **Note:** The API token requires a **paid FlutterFlow subscription** (Standard plan or above). Free-tier accounts do not have API access.
|
|
32
|
+
|
|
33
|
+
### 2. Add to Your MCP Client
|
|
34
|
+
|
|
35
|
+
Choose your AI client below and follow the setup instructions.
|
|
36
|
+
|
|
37
|
+
<details>
|
|
38
|
+
<summary><strong>Claude Code (CLI)</strong></summary>
|
|
39
|
+
|
|
40
|
+
Run this command to add the MCP server:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
claude mcp add flutterflow -e FLUTTERFLOW_API_TOKEN=your_token_here -- npx -y community-ff-mcp
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Replace `your_token_here` with the token you copied in step 1.
|
|
47
|
+
|
|
48
|
+
This adds the server to your project's `.claude/settings.json`. You can also manually edit the config:
|
|
49
|
+
|
|
50
|
+
```json
|
|
51
|
+
{
|
|
52
|
+
"mcpServers": {
|
|
53
|
+
"flutterflow": {
|
|
54
|
+
"command": "npx",
|
|
55
|
+
"args": ["-y", "community-ff-mcp"],
|
|
56
|
+
"env": {
|
|
57
|
+
"FLUTTERFLOW_API_TOKEN": "your_token_here"
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
</details>
|
|
65
|
+
|
|
66
|
+
<details>
|
|
67
|
+
<summary><strong>Claude Desktop</strong></summary>
|
|
68
|
+
|
|
69
|
+
Open **Settings > Developer > Edit Config** and add:
|
|
70
|
+
|
|
71
|
+
```json
|
|
72
|
+
{
|
|
73
|
+
"mcpServers": {
|
|
74
|
+
"flutterflow": {
|
|
75
|
+
"command": "npx",
|
|
76
|
+
"args": ["-y", "community-ff-mcp"],
|
|
77
|
+
"env": {
|
|
78
|
+
"FLUTTERFLOW_API_TOKEN": "your_token_here"
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Replace `your_token_here` with your token. Restart Claude Desktop after saving.
|
|
86
|
+
|
|
87
|
+
</details>
|
|
88
|
+
|
|
89
|
+
<details>
|
|
90
|
+
<summary><strong>Cursor</strong></summary>
|
|
91
|
+
|
|
92
|
+
Open **Settings > MCP** and add a new server with this configuration:
|
|
93
|
+
|
|
94
|
+
```json
|
|
95
|
+
{
|
|
96
|
+
"mcpServers": {
|
|
97
|
+
"flutterflow": {
|
|
98
|
+
"command": "npx",
|
|
99
|
+
"args": ["-y", "community-ff-mcp"],
|
|
100
|
+
"env": {
|
|
101
|
+
"FLUTTERFLOW_API_TOKEN": "your_token_here"
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
</details>
|
|
109
|
+
|
|
110
|
+
<details>
|
|
111
|
+
<summary><strong>Windsurf / Other MCP Clients</strong></summary>
|
|
112
|
+
|
|
113
|
+
Add the following to your MCP configuration file (check your client's docs for the exact location):
|
|
114
|
+
|
|
115
|
+
```json
|
|
116
|
+
{
|
|
117
|
+
"mcpServers": {
|
|
118
|
+
"flutterflow": {
|
|
119
|
+
"command": "npx",
|
|
120
|
+
"args": ["-y", "community-ff-mcp"],
|
|
121
|
+
"env": {
|
|
122
|
+
"FLUTTERFLOW_API_TOKEN": "your_token_here"
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
</details>
|
|
130
|
+
|
|
131
|
+
### 3. Start Building
|
|
132
|
+
|
|
133
|
+
Ask your AI assistant to list your FlutterFlow projects, inspect pages, or explore your app — it handles the rest.
|
|
134
|
+
|
|
135
|
+
**Example prompts to get started:**
|
|
136
|
+
- *"List my FlutterFlow projects"*
|
|
137
|
+
- *"Show me all the pages in project X"*
|
|
138
|
+
- *"What does the HomePage do? Walk me through its widget tree"*
|
|
139
|
+
- *"Where is the PaywallCard component used?"*
|
|
140
|
+
- *"What API endpoints are configured?"*
|
|
141
|
+
- *"Show me the theme colors"*
|
|
142
|
+
|
|
143
|
+
## How It Works Under the Hood
|
|
144
|
+
|
|
145
|
+
This MCP is designed to make AI agents as effective as possible when working with FlutterFlow. Here's what makes it work well:
|
|
146
|
+
|
|
147
|
+
### Smart Local Caching
|
|
148
|
+
|
|
149
|
+
Instead of hitting the FlutterFlow API for every question, the MCP downloads your entire project once (`sync_project`) and caches it locally. After that, most tools read from the cache — making them **instant and free of API rate limits**. If you've made changes in FlutterFlow, just re-sync to refresh the cache.
|
|
150
|
+
|
|
151
|
+
### Built-in Documentation
|
|
152
|
+
|
|
153
|
+
AI models don't natively understand FlutterFlow's internal structure. This MCP ships with **21 reference documents** covering every widget type, action, variable, theme setting, and editing pattern. The AI can look up exactly how a Button, Column, or Navigation action is structured — so it doesn't have to guess.
|
|
154
|
+
|
|
155
|
+
### Guided Editing Workflow
|
|
156
|
+
|
|
157
|
+
Before making any change, the AI can call `get_editing_guide` with a plain-English description of what it wants to do (e.g., *"change the button color on the login page"*). The MCP returns the exact steps, relevant documentation, and rules to follow — reducing the chance of mistakes.
|
|
158
|
+
|
|
159
|
+
### 25 Purpose-Built Tools
|
|
160
|
+
|
|
161
|
+
Rather than one generic "read project" tool, the MCP provides **25 specialized tools** — each designed for a specific task. Want to know where a component is used? There's a dedicated tool for that. Want to see all navigation actions pointing to a page? There's one for that too. This means the AI always picks the right tool for the job instead of downloading everything and searching through it.
|
|
162
|
+
|
|
163
|
+
## Limitations and Cautions
|
|
164
|
+
|
|
165
|
+
### Be Careful with Edits
|
|
166
|
+
|
|
167
|
+
This MCP can make changes to your FlutterFlow project, but **edits should be treated with care**:
|
|
168
|
+
|
|
169
|
+
- **Always review before pushing** — Ask your AI assistant to show you exactly what it plans to change before it pushes anything. Make sure you understand the change.
|
|
170
|
+
- **There's no undo button for API changes** — Changes are applied immediately to your project. You can roll back using FlutterFlow's version history, but it's better to prevent a bad edit than to fix one.
|
|
171
|
+
- **Start with read-only tasks** — Get comfortable asking questions about your project (page summaries, component usage, theme inspection) before asking the AI to modify anything.
|
|
172
|
+
- **Smaller edits are safer** — Editing a single widget is safer than replacing an entire page. The AI knows to make targeted changes, but it's good to be aware.
|
|
173
|
+
|
|
174
|
+
### What the FlutterFlow API Can't Do
|
|
175
|
+
|
|
176
|
+
These are limitations in FlutterFlow's own API. They affect any tool that connects to FlutterFlow, not just this MCP.
|
|
177
|
+
|
|
178
|
+
- **Custom code can be read but not edited** — The AI can read your custom actions, custom functions, and custom widgets, but it **cannot push code changes** back to FlutterFlow. The API doesn't support it properly — attempting to push code corrupts the FlutterFlow editor. Instead, the AI will show you the modified code and you copy-paste it into the FlutterFlow code editor.
|
|
179
|
+
- **Unlocked `main.dart` can't be updated** — If you've unlocked `main.dart` for raw Dart editing, the AI can read it but can't push code changes. Startup/shutdown action lists can still be modified.
|
|
180
|
+
- **Platform config files are indirect** — You can't directly edit `AndroidManifest.xml`, `Info.plist`, or `build.gradle`. Instead, you configure hooks and settings in FlutterFlow, which generates those files for you. The AI can read and modify those hooks.
|
|
181
|
+
- **Editing platform config files requires extra care** — FlutterFlow groups all platform config files together internally. If the AI pushes a change to just one (e.g., Android Manifest), FlutterFlow may delete the others (e.g., ProGuard rules, Gradle config). The MCP handles this by always including all existing files in the same push, but it's something to be aware of.
|
|
182
|
+
- **Disabling conditional actions works differently** — In the FlutterFlow editor, you can toggle a conditional action on/off with a switch. The API handles this slightly differently, so the AI uses a workaround that achieves the same result.
|
|
183
|
+
- **Validation isn't perfect** — The validation step catches most errors, but occasionally something that passes validation can still fail when pushed. This is rare, but it's why reviewing changes before pushing is important.
|
|
184
|
+
- **Project list may be incomplete** — The API may not return all projects you have access to, especially shared or team projects. If a project is missing, copy its ID directly from the FlutterFlow editor (click the project name in the top-left corner) and paste it into your AI prompt.
|
|
185
|
+
|
|
186
|
+
### General Limitations
|
|
187
|
+
|
|
188
|
+
- **No live sync** — The MCP works with a snapshot of your project. It doesn't watch for changes you make in the FlutterFlow editor in real time. If you've been editing in FlutterFlow, re-sync before asking the AI to make changes.
|
|
189
|
+
- **Very large pages** — Some extremely large pages may fail to load. The AI can work around this by loading individual widgets instead of the whole page.
|
|
190
|
+
- **Cache can go stale** — If you edit your project in FlutterFlow after syncing, the AI's local copy is outdated. Re-run the sync (the AI will tell you when it detects stale data).
|
|
191
|
+
|
|
192
|
+
> For the full technical details on each API limitation, see [`docs/flutterflow-api-limitations.md`](docs/flutterflow-api-limitations.md).
|
|
193
|
+
|
|
194
|
+
## Tools
|
|
195
|
+
|
|
196
|
+
### Discovery and Exploration
|
|
197
|
+
|
|
198
|
+
| Tool | Description |
|
|
199
|
+
|------|-------------|
|
|
200
|
+
| `list_projects` | List all FlutterFlow projects for your account |
|
|
201
|
+
| `list_project_files` | List YAML file keys in a project (supports prefix filter) |
|
|
202
|
+
| `list_pages` | List all pages with human-readable names, scaffold IDs, and folders |
|
|
203
|
+
| `search_project_files` | Search file keys by keyword, prefix, or regex |
|
|
204
|
+
| `sync_project` | Bulk download all project YAML to local cache for fast offline reads |
|
|
205
|
+
|
|
206
|
+
### Reading and Understanding
|
|
207
|
+
|
|
208
|
+
| Tool | Description |
|
|
209
|
+
|------|-------------|
|
|
210
|
+
| `get_page_by_name` | Fetch a page by its human-readable name |
|
|
211
|
+
| `get_project_yaml` | Download specific YAML files by file key |
|
|
212
|
+
| `get_page_summary` | Quick page overview from cache — widget tree, actions, params, state |
|
|
213
|
+
| `get_component_summary` | Quick component overview from cache — widget tree, actions, params |
|
|
214
|
+
| `find_component_usages` | Find all pages and components where a given component is used |
|
|
215
|
+
| `find_page_navigations` | Find all actions that navigate to a given page |
|
|
216
|
+
|
|
217
|
+
### Project Configuration
|
|
218
|
+
|
|
219
|
+
| Tool | Description |
|
|
220
|
+
|------|-------------|
|
|
221
|
+
| `get_theme` | Theme colors, typography, breakpoints, and widget defaults |
|
|
222
|
+
| `get_app_state` | App state variables, constants, and environment settings |
|
|
223
|
+
| `get_api_endpoints` | API endpoint definitions — method, URL, variables, headers, response |
|
|
224
|
+
| `get_data_models` | Data structs, enums, Firestore collections, and Supabase tables |
|
|
225
|
+
| `get_custom_code` | Custom actions, functions, widgets, AI agents, and app-action components |
|
|
226
|
+
| `get_general_settings` | App Details, App Assets, Nav Bar & App Bar settings |
|
|
227
|
+
| `get_project_setup` | Firebase, Languages, Platforms, Permissions, Dependencies |
|
|
228
|
+
| `get_app_settings` | Authentication, Push Notifications, Mobile/Web Deployment |
|
|
229
|
+
| `get_in_app_purchases` | Stripe, Braintree, RevenueCat, Razorpay configuration |
|
|
230
|
+
| `get_integrations` | Supabase, SQLite, GitHub, Algolia, Google Maps, AdMob, and more |
|
|
231
|
+
|
|
232
|
+
### Editing
|
|
233
|
+
|
|
234
|
+
| Tool | Description |
|
|
235
|
+
|------|-------------|
|
|
236
|
+
| `get_editing_guide` | Get the recommended workflow and docs for an editing task — **call this before modifying any YAML** |
|
|
237
|
+
| `get_yaml_docs` | Search/retrieve FlutterFlow YAML reference docs by topic or file |
|
|
238
|
+
| `validate_yaml` | Validate YAML content before pushing — **always call before `update_project_yaml`** |
|
|
239
|
+
| `update_project_yaml` | Push YAML changes to a project |
|
|
240
|
+
|
|
241
|
+
## Resources
|
|
242
|
+
|
|
243
|
+
| Resource | URI | Description |
|
|
244
|
+
|----------|-----|-------------|
|
|
245
|
+
| Docs Index | `ff://docs` | List all available YAML reference documentation files |
|
|
246
|
+
| Doc File | `ff://docs/{path}` | Read a specific YAML reference doc (e.g. `ff://docs/04-widgets/button`) |
|
|
247
|
+
|
|
248
|
+
## Prompts
|
|
249
|
+
|
|
250
|
+
| Prompt | Description |
|
|
251
|
+
|--------|-------------|
|
|
252
|
+
| `generate-page` | Generate a new page from a description |
|
|
253
|
+
| `modify-component` | Modify an existing component |
|
|
254
|
+
| `inspect-project` | Summarize project structure |
|
|
255
|
+
| `flutterflow-dev-workflow` | Efficient workflow guide for AI-assisted FlutterFlow development |
|
|
256
|
+
|
|
257
|
+
## Built-in YAML Reference
|
|
258
|
+
|
|
259
|
+
This MCP ships with a comprehensive FlutterFlow YAML reference catalog that AI models can access at runtime:
|
|
260
|
+
|
|
261
|
+
- **`get_yaml_docs` tool** — Search by topic (e.g. `get_yaml_docs(topic: "Button")`) or browse the full index
|
|
262
|
+
- **`ff://docs` resources** — Direct access to all 21 reference docs covering widgets, actions, variables, theming, and editing workflows
|
|
263
|
+
|
|
264
|
+
See [docs/ff-yaml/](docs/ff-yaml/) for the full catalog.
|
|
265
|
+
|
|
266
|
+
## AI Agent Skill
|
|
267
|
+
|
|
268
|
+
This MCP includes a [skills.sh](https://skills.sh)-compatible skill for AI agents. Install it to teach your AI assistant how to use FlutterFlow MCP effectively:
|
|
269
|
+
|
|
270
|
+
```bash
|
|
271
|
+
npx skills add mohn93/ff-mcp --skill community-ff-mcp
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
Compatible with Claude Code, Cursor, GitHub Copilot, Codex, Goose, Windsurf, and 12+ other AI agents. The skill provides tool orchestration workflows, critical YAML rules, and detailed reference documentation for widgets, actions, data binding, theming, and more.
|
|
275
|
+
|
|
276
|
+
## Claude Code Skills
|
|
277
|
+
|
|
278
|
+
You can also copy Claude Code-specific skills from [`skills/`](skills/) into your project's `.claude/skills/` directory:
|
|
279
|
+
|
|
280
|
+
- **`ff-yaml-dev.md`** — Core workflow: reading, editing, and creating FlutterFlow pages/components
|
|
281
|
+
- **`ff-widget-patterns.md`** — Quick reference for common widget YAML patterns and snippets
|
|
282
|
+
|
|
283
|
+
## Development
|
|
284
|
+
|
|
285
|
+
```bash
|
|
286
|
+
git clone https://github.com/mohn93/ff-mcp.git
|
|
287
|
+
cd ff-mcp
|
|
288
|
+
npm install
|
|
289
|
+
npm run build
|
|
290
|
+
npm run dev # watch mode
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
## Requirements
|
|
294
|
+
|
|
295
|
+
- Node.js 18+
|
|
296
|
+
- FlutterFlow API token (paid FlutterFlow subscription required)
|
|
297
|
+
|
|
298
|
+
## License
|
|
299
|
+
|
|
300
|
+
MIT
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare class FlutterFlowClient {
|
|
2
|
+
private token;
|
|
3
|
+
constructor(token: string);
|
|
4
|
+
private request;
|
|
5
|
+
listProjects(projectType?: string, deserializeResponse?: boolean): Promise<unknown>;
|
|
6
|
+
listPartitionedFileNames(projectId: string): Promise<unknown>;
|
|
7
|
+
getProjectYamls(projectId: string, fileName?: string): Promise<unknown>;
|
|
8
|
+
validateProjectYaml(projectId: string, fileKey: string, fileContent: string): Promise<unknown>;
|
|
9
|
+
updateProjectByYaml(projectId: string, fileKeyToContent: Record<string, string>): Promise<unknown>;
|
|
10
|
+
}
|
|
11
|
+
export declare function createClient(): FlutterFlowClient;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
const FF_API_BASE = "https://api.flutterflow.io/v2";
|
|
2
|
+
export class FlutterFlowClient {
|
|
3
|
+
token;
|
|
4
|
+
constructor(token) {
|
|
5
|
+
this.token = token;
|
|
6
|
+
}
|
|
7
|
+
async request(method, endpoint, body) {
|
|
8
|
+
const url = `${FF_API_BASE}${endpoint}`;
|
|
9
|
+
const headers = {
|
|
10
|
+
Authorization: `Bearer ${this.token}`,
|
|
11
|
+
"Content-Type": "application/json",
|
|
12
|
+
};
|
|
13
|
+
const res = await fetch(url, {
|
|
14
|
+
method,
|
|
15
|
+
headers,
|
|
16
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
17
|
+
});
|
|
18
|
+
if (!res.ok) {
|
|
19
|
+
const errorText = await res.text();
|
|
20
|
+
throw new Error(`FlutterFlow API error ${res.status}: ${errorText}`);
|
|
21
|
+
}
|
|
22
|
+
return res.json();
|
|
23
|
+
}
|
|
24
|
+
async listProjects(projectType, deserializeResponse) {
|
|
25
|
+
return this.request("POST", "/l/listProjects", {
|
|
26
|
+
project_type: projectType,
|
|
27
|
+
deserialize_response: deserializeResponse ?? true,
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
async listPartitionedFileNames(projectId) {
|
|
31
|
+
return this.request("GET", `/listPartitionedFileNames?projectId=${encodeURIComponent(projectId)}`);
|
|
32
|
+
}
|
|
33
|
+
async getProjectYamls(projectId, fileName) {
|
|
34
|
+
let endpoint = `/projectYamls?projectId=${encodeURIComponent(projectId)}`;
|
|
35
|
+
if (fileName) {
|
|
36
|
+
endpoint += `&fileName=${encodeURIComponent(fileName)}`;
|
|
37
|
+
}
|
|
38
|
+
return this.request("GET", endpoint);
|
|
39
|
+
}
|
|
40
|
+
async validateProjectYaml(projectId, fileKey, fileContent) {
|
|
41
|
+
return this.request("POST", "/validateProjectYaml", {
|
|
42
|
+
projectId,
|
|
43
|
+
fileKey,
|
|
44
|
+
fileContent,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
async updateProjectByYaml(projectId, fileKeyToContent) {
|
|
48
|
+
return this.request("POST", "/updateProjectByYaml", {
|
|
49
|
+
projectId,
|
|
50
|
+
fileKeyToContent,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
export function createClient() {
|
|
55
|
+
const token = process.env.FLUTTERFLOW_API_TOKEN;
|
|
56
|
+
if (!token) {
|
|
57
|
+
throw new Error("FLUTTERFLOW_API_TOKEN environment variable is required. " +
|
|
58
|
+
"Get your token from FlutterFlow > Account Settings > API Token.");
|
|
59
|
+
}
|
|
60
|
+
return new FlutterFlowClient(token);
|
|
61
|
+
}
|
package/build/index.d.ts
ADDED
package/build/index.js
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
+
import { createClient } from "./api/flutterflow.js";
|
|
5
|
+
import { registerListProjectsTool } from "./tools/list-projects.js";
|
|
6
|
+
import { registerListFilesTool } from "./tools/list-files.js";
|
|
7
|
+
import { registerGetYamlTool } from "./tools/get-yaml.js";
|
|
8
|
+
import { registerValidateYamlTool } from "./tools/validate-yaml.js";
|
|
9
|
+
import { registerUpdateYamlTool } from "./tools/update-yaml.js";
|
|
10
|
+
import { registerListPagesTool } from "./tools/list-pages.js";
|
|
11
|
+
import { registerGetPageByNameTool } from "./tools/get-page-by-name.js";
|
|
12
|
+
import { registerSyncProjectTool } from "./tools/sync-project.js";
|
|
13
|
+
import { registerGetPageSummaryTool } from "./tools/get-page-summary.js";
|
|
14
|
+
import { registerGetComponentSummaryTool } from "./tools/get-component-summary.js";
|
|
15
|
+
import { registerFindComponentUsagesTool } from "./tools/find-component-usages.js";
|
|
16
|
+
import { registerFindPageNavigationsTool } from "./tools/find-page-navigations.js";
|
|
17
|
+
import { registerResources } from "./resources/projects.js";
|
|
18
|
+
import { registerDocsResources } from "./resources/docs.js";
|
|
19
|
+
import { registerGeneratePagePrompt } from "./prompts/generate-page.js";
|
|
20
|
+
import { registerModifyComponentPrompt } from "./prompts/modify-component.js";
|
|
21
|
+
import { registerInspectProjectPrompt } from "./prompts/inspect-project.js";
|
|
22
|
+
import { registerDevWorkflowPrompt } from "./prompts/dev-workflow.js";
|
|
23
|
+
import { registerGetYamlDocsTool } from "./tools/get-yaml-docs.js";
|
|
24
|
+
import { registerGetAppStateTool } from "./tools/get-app-state.js";
|
|
25
|
+
import { registerGetApiEndpointsTool } from "./tools/get-api-endpoints.js";
|
|
26
|
+
import { registerGetDataModelsTool } from "./tools/get-data-models.js";
|
|
27
|
+
import { registerGetCustomCodeTool } from "./tools/get-custom-code.js";
|
|
28
|
+
import { registerGetThemeTool } from "./tools/get-theme.js";
|
|
29
|
+
import { registerGetEditingGuideTool } from "./tools/get-editing-guide.js";
|
|
30
|
+
import { registerSearchProjectFilesTool } from "./tools/search-project-files.js";
|
|
31
|
+
import { registerGetGeneralSettingsTool } from "./tools/get-general-settings.js";
|
|
32
|
+
import { registerGetProjectSetupTool } from "./tools/get-project-setup.js";
|
|
33
|
+
import { registerGetAppSettingsTool } from "./tools/get-app-settings.js";
|
|
34
|
+
import { registerGetInAppPurchasesTool } from "./tools/get-in-app-purchases.js";
|
|
35
|
+
import { registerGetIntegrationsTool } from "./tools/get-integrations.js";
|
|
36
|
+
const server = new McpServer({
|
|
37
|
+
name: "ff-mcp",
|
|
38
|
+
version: "0.1.0",
|
|
39
|
+
});
|
|
40
|
+
const client = createClient();
|
|
41
|
+
// Register tools
|
|
42
|
+
registerListProjectsTool(server, client);
|
|
43
|
+
registerListFilesTool(server, client);
|
|
44
|
+
registerGetYamlTool(server);
|
|
45
|
+
registerValidateYamlTool(server, client);
|
|
46
|
+
registerUpdateYamlTool(server, client);
|
|
47
|
+
registerListPagesTool(server, client);
|
|
48
|
+
registerGetPageByNameTool(server, client);
|
|
49
|
+
registerSyncProjectTool(server, client);
|
|
50
|
+
registerGetPageSummaryTool(server);
|
|
51
|
+
registerGetComponentSummaryTool(server);
|
|
52
|
+
registerFindComponentUsagesTool(server);
|
|
53
|
+
registerFindPageNavigationsTool(server);
|
|
54
|
+
registerGetYamlDocsTool(server);
|
|
55
|
+
registerGetAppStateTool(server);
|
|
56
|
+
registerGetApiEndpointsTool(server);
|
|
57
|
+
registerGetDataModelsTool(server);
|
|
58
|
+
registerGetCustomCodeTool(server);
|
|
59
|
+
registerGetThemeTool(server);
|
|
60
|
+
registerGetEditingGuideTool(server);
|
|
61
|
+
registerSearchProjectFilesTool(server);
|
|
62
|
+
registerGetGeneralSettingsTool(server);
|
|
63
|
+
registerGetProjectSetupTool(server);
|
|
64
|
+
registerGetAppSettingsTool(server);
|
|
65
|
+
registerGetInAppPurchasesTool(server);
|
|
66
|
+
registerGetIntegrationsTool(server);
|
|
67
|
+
// Register resources
|
|
68
|
+
registerResources(server, client);
|
|
69
|
+
registerDocsResources(server);
|
|
70
|
+
// Register prompts
|
|
71
|
+
registerGeneratePagePrompt(server);
|
|
72
|
+
registerModifyComponentPrompt(server);
|
|
73
|
+
registerInspectProjectPrompt(server);
|
|
74
|
+
registerDevWorkflowPrompt(server);
|
|
75
|
+
// Start server
|
|
76
|
+
const transport = new StdioServerTransport();
|
|
77
|
+
await server.connect(transport);
|
|
78
|
+
console.error("FlutterFlow MCP server running on stdio");
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export function registerDevWorkflowPrompt(server) {
|
|
3
|
+
server.prompt("flutterflow-dev-workflow", "Efficient workflow guide for developing FlutterFlow apps through MCP tools. References the full YAML docs catalog via get_yaml_docs tool.", {
|
|
4
|
+
projectId: z
|
|
5
|
+
.string()
|
|
6
|
+
.optional()
|
|
7
|
+
.describe("Optional project ID to include in instructions"),
|
|
8
|
+
}, ({ projectId }) => ({
|
|
9
|
+
messages: [
|
|
10
|
+
{
|
|
11
|
+
role: "user",
|
|
12
|
+
content: {
|
|
13
|
+
type: "text",
|
|
14
|
+
text: `You are an expert FlutterFlow developer using MCP tools to read and modify FlutterFlow projects.
|
|
15
|
+
|
|
16
|
+
## Documentation
|
|
17
|
+
|
|
18
|
+
This MCP server includes a comprehensive FlutterFlow YAML reference catalog. Use the \`get_yaml_docs\` tool to look up any schema, pattern, or convention:
|
|
19
|
+
|
|
20
|
+
- \`get_yaml_docs(topic: "Button")\` — Widget schemas (Button, Text, TextField, Container, etc.)
|
|
21
|
+
- \`get_yaml_docs(topic: "actions")\` — Action chains, triggers, navigation
|
|
22
|
+
- \`get_yaml_docs(topic: "variables")\` — Data binding, variable sources
|
|
23
|
+
- \`get_yaml_docs(topic: "theming")\` — Colors, typography, dimensions
|
|
24
|
+
- \`get_yaml_docs(topic: "editing")\` — Read/edit/add workflows and anti-patterns
|
|
25
|
+
- \`get_yaml_docs()\` — Full index of all available docs
|
|
26
|
+
|
|
27
|
+
Always consult the docs before writing YAML. They contain validated schemas, field references, enum values, and real examples from production projects.
|
|
28
|
+
|
|
29
|
+
## Efficient Workflow
|
|
30
|
+
|
|
31
|
+
${projectId ? `**Project ID:** \`${projectId}\`\n` : ""}
|
|
32
|
+
### Reading / Inspecting
|
|
33
|
+
\`\`\`
|
|
34
|
+
list_projects → sync_project → get_page_summary / get_component_summary
|
|
35
|
+
\`\`\`
|
|
36
|
+
|
|
37
|
+
### Editing Existing Widgets
|
|
38
|
+
\`\`\`
|
|
39
|
+
list_pages → get_page_by_name → (node-level fetch) → validate_yaml → update_project_yaml
|
|
40
|
+
\`\`\`
|
|
41
|
+
|
|
42
|
+
### Adding New Widgets
|
|
43
|
+
\`\`\`
|
|
44
|
+
list_pages → get_page_by_name → update widget-tree-outline + push individual node files → validate_yaml → update_project_yaml
|
|
45
|
+
\`\`\`
|
|
46
|
+
|
|
47
|
+
## Critical YAML Rules
|
|
48
|
+
|
|
49
|
+
1. **Always update both \`inputValue\` AND \`mostRecentInputValue\`** — they must stay in sync.
|
|
50
|
+
- **Exceptions:** \`fontWeightValue\` and \`fontSizeValue\` only accept \`inputValue\`.
|
|
51
|
+
2. **Use node-level file keys** for targeted edits, not the full page YAML.
|
|
52
|
+
3. **Always validate before pushing** — call \`validate_yaml\` first.
|
|
53
|
+
4. **Adding widgets requires node-level files** — push the tree outline + individual nodes together.
|
|
54
|
+
5. **Column has no \`mainAxisSize\`** — use \`minSizeValue: { inputValue: true }\` instead.
|
|
55
|
+
6. **AppBar \`templateType\`** — only \`LARGE_HEADER\` is valid. Control height via \`toolbarHeight\`.
|
|
56
|
+
7. **TextField keyboard types** — use \`EMAIL_ADDRESS\`, not \`EMAIL\`.
|
|
57
|
+
|
|
58
|
+
## Anti-Patterns
|
|
59
|
+
|
|
60
|
+
- Do NOT call \`list_project_files\` to find pages — use \`list_pages\` instead.
|
|
61
|
+
- Do NOT fetch pages one-by-one — use \`get_page_by_name\`.
|
|
62
|
+
- Do NOT edit full page YAML for a single widget — use node-level file keys.
|
|
63
|
+
- Do NOT guess YAML field names — use \`get_yaml_docs\` to look them up.`,
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
],
|
|
67
|
+
}));
|
|
68
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export function registerGeneratePagePrompt(server) {
|
|
3
|
+
server.prompt("generate-page", "Generate a new FlutterFlow page from a natural language description", {
|
|
4
|
+
projectId: z.string().describe("The FlutterFlow project ID"),
|
|
5
|
+
description: z
|
|
6
|
+
.string()
|
|
7
|
+
.describe("Natural language description of the page to create"),
|
|
8
|
+
}, ({ projectId, description }) => ({
|
|
9
|
+
messages: [
|
|
10
|
+
{
|
|
11
|
+
role: "user",
|
|
12
|
+
content: {
|
|
13
|
+
type: "text",
|
|
14
|
+
text: `You are an expert FlutterFlow developer. Generate a new page for the FlutterFlow project.
|
|
15
|
+
|
|
16
|
+
## Instructions
|
|
17
|
+
|
|
18
|
+
1. First, use the list_project_files tool with projectId "${projectId}" to understand the existing project structure.
|
|
19
|
+
2. Use \`get_editing_guide\` with a description of the page you want to create to get the correct YAML schemas, workflow steps, and critical rules.
|
|
20
|
+
3. Then, use get_project_yaml to read a few existing pages to understand the YAML schema and conventions used in this project.
|
|
21
|
+
4. Based on the following description, generate valid FlutterFlow YAML for a new page:
|
|
22
|
+
|
|
23
|
+
**Page Description:** ${description}
|
|
24
|
+
|
|
25
|
+
5. Use validate_yaml to check your generated YAML is valid.
|
|
26
|
+
6. If validation passes, use update_project_yaml to push the new page to the project.
|
|
27
|
+
7. If validation fails, fix the errors and try again.
|
|
28
|
+
|
|
29
|
+
## Important
|
|
30
|
+
- Follow the exact YAML structure you observed in existing pages.
|
|
31
|
+
- Use consistent naming conventions matching the project.
|
|
32
|
+
- YAML content must be single-line strings with escaped newlines (\\n).`,
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
],
|
|
36
|
+
}));
|
|
37
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export function registerInspectProjectPrompt(server) {
|
|
3
|
+
server.prompt("inspect-project", "Read and summarize a FlutterFlow project's structure, pages, and components", {
|
|
4
|
+
projectId: z.string().describe("The FlutterFlow project ID"),
|
|
5
|
+
}, ({ projectId }) => ({
|
|
6
|
+
messages: [
|
|
7
|
+
{
|
|
8
|
+
role: "user",
|
|
9
|
+
content: {
|
|
10
|
+
type: "text",
|
|
11
|
+
text: `You are an expert FlutterFlow developer. Inspect and summarize the FlutterFlow project.
|
|
12
|
+
|
|
13
|
+
## Instructions
|
|
14
|
+
|
|
15
|
+
1. Use list_project_files with projectId "${projectId}" to get all files.
|
|
16
|
+
2. Use get_project_yaml to read key files like "app-details", "folders", and "authentication".
|
|
17
|
+
3. Read a sample of page and component files to understand the app structure.
|
|
18
|
+
4. Provide a clear summary including:
|
|
19
|
+
- App name and details
|
|
20
|
+
- Number of pages and their names
|
|
21
|
+
- Number of components and their names
|
|
22
|
+
- Data models / collections
|
|
23
|
+
- Authentication setup
|
|
24
|
+
- Any custom code files
|
|
25
|
+
- Overall architecture observations`,
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
],
|
|
29
|
+
}));
|
|
30
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export function registerModifyComponentPrompt(server) {
|
|
3
|
+
server.prompt("modify-component", "Read an existing FlutterFlow component and modify it based on instructions", {
|
|
4
|
+
projectId: z.string().describe("The FlutterFlow project ID"),
|
|
5
|
+
fileName: z
|
|
6
|
+
.string()
|
|
7
|
+
.describe("The YAML file name of the component to modify"),
|
|
8
|
+
changes: z
|
|
9
|
+
.string()
|
|
10
|
+
.describe("Description of changes to make to the component"),
|
|
11
|
+
}, ({ projectId, fileName, changes }) => ({
|
|
12
|
+
messages: [
|
|
13
|
+
{
|
|
14
|
+
role: "user",
|
|
15
|
+
content: {
|
|
16
|
+
type: "text",
|
|
17
|
+
text: `You are an expert FlutterFlow developer. Modify an existing component in the FlutterFlow project.
|
|
18
|
+
|
|
19
|
+
## Instructions
|
|
20
|
+
|
|
21
|
+
1. Use get_project_yaml with projectId "${projectId}" and fileName "${fileName}" to read the current component YAML.
|
|
22
|
+
2. Use \`get_editing_guide\` with a description of the changes you want to make to get the correct YAML schemas and critical rules.
|
|
23
|
+
3. Understand the current structure and widget tree.
|
|
24
|
+
4. Apply the following changes:
|
|
25
|
+
|
|
26
|
+
**Requested Changes:** ${changes}
|
|
27
|
+
|
|
28
|
+
5. Use validate_yaml to verify your modified YAML is valid.
|
|
29
|
+
6. If validation passes, use update_project_yaml to push the changes.
|
|
30
|
+
7. If validation fails, fix the errors and try again.
|
|
31
|
+
|
|
32
|
+
## Important
|
|
33
|
+
- Preserve all existing structure you are not modifying.
|
|
34
|
+
- YAML content must be single-line strings with escaped newlines (\\n).
|
|
35
|
+
- Only change what was requested — do not refactor or reorganize.`,
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
],
|
|
39
|
+
}));
|
|
40
|
+
}
|