Floot MCP
Vendor MCP45 toolsOAuth 2.1/DCRDeveloper ToolsAIAutomationProductivityConnect to Floot MCP to build, deploy, and manage full-stack AI-generated web apps directly from your AI workflows.
Floot MCP connector
-
Install the SDK
Section titled “Install the SDK”Terminal window npm install @scalekit-sdk/nodeTerminal window pip install scalekit -
Set your credentials
Section titled “Set your credentials”Add your Scalekit credentials to your
.envfile. Find values in app.scalekit.com > Developers > API Credentials..env SCALEKIT_ENVIRONMENT_URL=<your-environment-url>SCALEKIT_CLIENT_ID=<your-client-id>SCALEKIT_CLIENT_SECRET=<your-client-secret> -
Authorize and make your first call
Section titled “Authorize and make your first call”quickstart.ts import { ScalekitClient } from '@scalekit-sdk/node'import 'dotenv/config'const scalekit = new ScalekitClient(process.env.SCALEKIT_ENV_URL,process.env.SCALEKIT_CLIENT_ID,process.env.SCALEKIT_CLIENT_SECRET,)const actions = scalekit.actionsconst connector = 'flootmcp'const identifier = 'user_123'// Generate an authorization link for the userconst { link } = await actions.getAuthorizationLink({ connectionName: connector, identifier })console.log('Authorize Floot MCP:', link)process.stdout.write('Press Enter after authorizing...')await new Promise(r => process.stdin.once('data', r))// Make your first callconst result = await actions.executeTool({connector,identifier,toolName: 'flootmcp_get_guide',toolInput: {},})console.log(result)quickstart.py import osfrom scalekit.client import ScalekitClientfrom dotenv import load_dotenvload_dotenv()scalekit_client = ScalekitClient(env_url=os.getenv("SCALEKIT_ENV_URL"),client_id=os.getenv("SCALEKIT_CLIENT_ID"),client_secret=os.getenv("SCALEKIT_CLIENT_SECRET"),)actions = scalekit_client.actionsconnection_name = "flootmcp"identifier = "user_123"# Generate an authorization link for the userlink_response = actions.get_authorization_link(connection_name=connection_name,identifier=identifier,)print("Authorize Floot MCP:", link_response.link)input("Press Enter after authorizing...")# Make your first callresult = actions.execute_tool(tool_input={},tool_name="flootmcp_get_guide",connection_name=connection_name,identifier=identifier,)print(result)
What you can do
Section titled “What you can do”Connect this agent connector to let your agent:
- File write, rename, edit — Create or fully overwrite a file in a Floot project
- Annotation view — View a screenshot annotation the user drew on the app preview (annotationId comes from get_current_context)
- Asset upload, card upload — Upload a binary asset (image, font, audio, …) to the project’s hosted storage
- Update project metadata — Update project settings (current values appear at the top of list_files)
- App unpublish, publish — Take the published app offline and release its subdomain — destructive, confirm with the user first
- Typecheck records — Typecheck the project (incremental tsc on the project VM)
Tool list
Section titled “Tool list”Use the exact tool names from the Tool list below when you call execute_tool. If you’re not sure which name to use, list the tools available for the current user first.
flootmcp_add_dependency#Add npm packages to the project (validated against Floot's supported set — rejected packages get a supported alternative named; some versions are pinned/substituted). Avoid node-gyp/native packages (exception: sharp is supported, auto-pinned), WASM modules, and packages bundling large binaries (e.g. ffmpeg/ffprobe); pure JS/TS preferred. A bare `kysely` installs 0.26.3, the version the generated db/schema helpers are written against; pass an explicit `kysely@<version>` only when upgrading it deliberately. Installs on the project VM and persists resolved versions. After a slow install completes as a job, call add_dependency again with the same packages — the second call is fast and persists.2 params
Add npm packages to the project (validated against Floot's supported set — rejected packages get a supported alternative named; some versions are pinned/substituted). Avoid node-gyp/native packages (exception: sharp is supported, auto-pinned), WASM modules, and packages bundling large binaries (e.g. ffmpeg/ffprobe); pure JS/TS preferred. A bare `kysely` installs 0.26.3, the version the generated db/schema helpers are written against; pass an explicit `kysely@<version>` only when upgrading it deliberately. Installs on the project VM and persists resolved versions. After a slow install completes as a job, call add_dependency again with the same packages — the second call is fast and persists.
packagesarrayrequiredThe npm package names to install, optionally with a version (e.g. "package@1.2.3"). Provide at least one. Packages are validated against Floot's supported set — an unsupported package is rejected with a supported alternative suggested. Avoid native/node-gyp packages, WASM modules, and packages bundling large binaries; pure JS/TS packages are preferred.projectIdstringrequiredThe unique identifier of the Floot project to add dependencies to. Obtain it from create_project or a project listing.flootmcp_apply_patch#Apply a V4A patch to a Floot project — create, update, and delete multiple files in ONE atomic operation. Format: "*** Begin Patch" envelope with "*** Add File: path" (+ prefixed lines), "*** Update File: path" (hunks: optional "@@ anchor" locator, space-prefixed context, -/+ lines, optional "*** End of File"), "*** Delete File: path", then "*** End Patch". Paths follow the Floot item scheme (see read_file). To replace a file wholesale use Add File on its own — Add OVERWRITES. Never Delete+Add the same path: Delete is item-scoped (deleting components/X.tsx deletes the whole item, its .module.css included), so it is both unnecessary before an Add and destructive to the siblings. Move to: is not supported — to RENAME, Add File at the new path and Delete File the old one. Keep each patch MODEST (a few files / few hundred lines): chat clients cap per-message output, and a patch cut off mid-way is rejected whole ("missing *** End Patch") — split big changes across several apply_patch calls.3 params
Apply a V4A patch to a Floot project — create, update, and delete multiple files in ONE atomic operation. Format: "*** Begin Patch" envelope with "*** Add File: path" (+ prefixed lines), "*** Update File: path" (hunks: optional "@@ anchor" locator, space-prefixed context, -/+ lines, optional "*** End of File"), "*** Delete File: path", then "*** End Patch". Paths follow the Floot item scheme (see read_file). To replace a file wholesale use Add File on its own — Add OVERWRITES. Never Delete+Add the same path: Delete is item-scoped (deleting components/X.tsx deletes the whole item, its .module.css included), so it is both unnecessary before an Add and destructive to the siblings. Move to: is not supported — to RENAME, Add File at the new path and Delete File the old one. Keep each patch MODEST (a few files / few hundred lines): chat clients cap per-message output, and a patch cut off mid-way is rejected whole ("missing *** End Patch") — split big changes across several apply_patch calls.
patchstringrequiredThe full V4A patch text, wrapped in a "*** Begin Patch" / "*** End Patch" envelope. Inside, use "*** Add File: <path>" with '+' prefixed lines to create a file (Add overwrites if the path exists), "*** Update File: <path>" with diff hunks (optional "@@ anchor" locator, space-prefixed context lines, '-'/'+' changed lines, optional "*** End of File") to modify one, and "*** Delete File: <path>" to remove one. Do not Delete and Add the same path in one patch — to rename a file, Add the new path and Delete the old one. Keep each patch to a few files or a few hundred lines; a patch cut off mid-way is rejected in its entirety.projectIdstringrequiredThe unique identifier of the Floot project to apply the patch to. Obtain it from create_project or a project listing.expected_versionintegeroptionalOptimistic-concurrency guard for the project. If any file the patch touches has changed since the version you last read, the patch is rejected instead of silently clobbering the newer content. Omit it to skip this check.flootmcp_cancel_request#Withdraw a pending request you created — a credential request from request_external_resource, a custom-domain setup request from publish_app, or an open screenshot job from screenshot_preview (jobId from that tool). Only pending requests can be cancelled — completed ones are final. Use when the user says to stop or they don't want to proceed.2 params
Withdraw a pending request you created — a credential request from request_external_resource, a custom-domain setup request from publish_app, or an open screenshot job from screenshot_preview (jobId from that tool). Only pending requests can be cancelled — completed ones are final. Use when the user says to stop or they don't want to proceed.
jobIdstringrequiredThe ID of the pending request or job to cancel — the credential request ID, the custom-domain setup request ID, or the jobId returned by screenshot_preview.projectIdstringrequiredThe Floot project ID that the pending request belongs to.flootmcp_card_upload_asset#Internal bridge for the upload card (not for agents — use request_user_upload / upload_asset). phase 'presign' mints the PUT URL for the picked file; phase 'complete' verifies the object landed and finishes the request_user_upload call with the publicUrl.6 params
Internal bridge for the upload card (not for agents — use request_user_upload / upload_asset). phase 'presign' mints the PUT URL for the picked file; phase 'complete' verifies the object landed and finishes the request_user_upload call with the publicUrl.
jobIdstringrequiredThe job id returned by request_user_upload that this call is completing.phasestringrequiredWhich step of the upload-card flow to perform: "presign" mints the PUT URL for the picked file, "complete" verifies the object landed and finishes the pending request.projectIdstringrequiredThe Floot project ID this upload belongs to.content_typestringoptionalMIME type of the file, required for the presign phase.file_namestringoptionalFile name for the asset being uploaded, required for the presign phase.size_bytesintegeroptionalExact byte size of the file, required for the presign phase.flootmcp_copy_file#Copy one or more items to new names (e.g. {from:'components/Card', to:'components/BigCard'}). Item names without extensions; same type only. Importers of the source are left unchanged. Pass several copies to apply them in one call.3 params
Copy one or more items to new names (e.g. {from:'components/Card', to:'components/BigCard'}). Item names without extensions; same type only. Importers of the source are left unchanged. Pass several copies to apply them in one call.
copiesarrayrequiredOne or more copy operations, each with a "from" and "to" item name (folder path allowed, no file extension). Importers of the source item are left unchanged — only the new copy is created. Example: [{"from": "components/Card", "to": "components/BigCard"}].projectIdstringrequiredThe Floot project ID containing the items to copy.expected_versionintegeroptionalOptional expected current file-tree version, for optimistic concurrency. If provided and it no longer matches the project's current version, the copy is rejected instead of racing with a concurrent edit.flootmcp_create_checkpoint#Create a NAMED checkpoint — a labeled restore point the user sees in the project's Checkpoints panel and can revert to later. All file/dependency changes since the previous checkpoint are grouped under it. Call this AFTER completing a coherent unit of work (a feature, a fix, a requested change set) — not after every file write. Give it a short user-meaningful title describing what was accomplished (e.g. 'Added login page with email auth'), optionally a description with detail. No-op when nothing changed since the last checkpoint. Restoring a checkpoint reverts code and project config only — database rows, uploaded assets and published deployments are not rolled back.3 params
Create a NAMED checkpoint — a labeled restore point the user sees in the project's Checkpoints panel and can revert to later. All file/dependency changes since the previous checkpoint are grouped under it. Call this AFTER completing a coherent unit of work (a feature, a fix, a requested change set) — not after every file write. Give it a short user-meaningful title describing what was accomplished (e.g. 'Added login page with email auth'), optionally a description with detail. No-op when nothing changed since the last checkpoint. Restoring a checkpoint reverts code and project config only — database rows, uploaded assets and published deployments are not rolled back.
projectIdstringrequiredThe Floot project ID to create the checkpoint in.titlestringrequiredShort, user-meaningful title describing what was accomplished since the previous checkpoint, e.g. "Added login page with email auth".descriptionstringoptionalOptional longer description with more detail about the change set covered by this checkpoint.flootmcp_create_project#Create a new Floot project (pre-seeded with the shared component library) and return its id. `initial_prompt` is the USER'S ORIGINAL REQUEST verbatim — it grounds the project (served back as <project-instructions> in list_files) and is preserved for the record; don't paraphrase it away. The result renders a live preview card for the user and includes the first-build playbook: a fresh project is EMPTY until pages are written, so a session normally continues straight into get_guides("design") and the first page rather than ending at the card.2 params
Create a new Floot project (pre-seeded with the shared component library) and return its id. `initial_prompt` is the USER'S ORIGINAL REQUEST verbatim — it grounds the project (served back as <project-instructions> in list_files) and is preserved for the record; don't paraphrase it away. The result renders a live preview card for the user and includes the first-build playbook: a fresh project is EMPTY until pages are written, so a session normally continues straight into get_guides("design") and the first page rather than ending at the card.
initial_promptstringrequiredThe user's original request that started this project, passed through verbatim (not paraphrased or summarized). It is stored with the project and served back as project instructions later, so it should read exactly as the user wrote it. Between 1 and 16000 characters.namestringrequiredThe display name for the new Floot project. Between 1 and 80 characters.flootmcp_delete_file#Delete a project file. Deleting an item's main code file (e.g. components/Foo.tsx) removes the whole item including its css/tests; deleting an aux file (e.g. Foo.module.css) only clears that part.3 params
Delete a project file. Deleting an item's main code file (e.g. components/Foo.tsx) removes the whole item including its css/tests; deleting an aux file (e.g. Foo.module.css) only clears that part.
pathstringrequiredPath to the file within the project, following the Floot item scheme. Deleting an item's main code file (e.g. components/Foo.tsx) removes the whole item, including its associated CSS and test files; deleting only an auxiliary file (e.g. Foo.module.css) clears just that part.projectIdstringrequiredThe unique identifier of the Floot project that contains the file to delete. Obtain it from create_project or a project listing.expected_versionintegeroptionalOptimistic-concurrency guard: the file's last-known version number. If the file has changed since then (a concurrent edit, or a prior tool call already modified it), the delete is rejected instead of silently removing newer content. Omit it to skip this check.flootmcp_edit_file#Replace old_string with new_string in a project file. old_string must match the current content exactly (including whitespace) and be unique unless replace_all is set. Prefer this over write_file for changes to existing files.8 params
Replace old_string with new_string in a project file. old_string must match the current content exactly (including whitespace) and be unique unless replace_all is set. Prefer this over write_file for changes to existing files.
pathstringrequiredPath to the file within the project, following the Floot item scheme (for example, a component's main source file). Identifies which file to edit.projectIdstringrequiredThe unique identifier of the Floot project that contains the file to edit. Obtain it from create_project or a project listing.expected_versionintegeroptionalOptimistic-concurrency guard: the file's last-known version number, as previously returned by a read or edit of this file. If the file has changed since then (a concurrent edit, or a prior tool call already modified it), the edit is rejected instead of silently overwriting the newer content. Omit it to skip this check.new_strstringoptionalAlternate field name for new_string — the replacement text. Provide either new_string or new_str (not both), paired with the matching old_string or old_str.new_stringstringoptionalThe text that replaces old_string in the file. Needed together with old_string for the edit to actually change anything, even though the schema marks both optional to accommodate the old_str/new_str alias pair.old_strstringoptionalAlternate field name for old_string. Provide either old_string or old_str (not both), paired with the matching new_string or new_str.old_stringstringoptionalThe exact text to find and replace in the file, including whitespace. Must match the current file content exactly, and must be unique in the file unless replace_all is true. Needed together with new_string for the edit to actually change anything, even though the schema marks both optional to accommodate the old_str/new_str alias pair.replace_allbooleanoptionalWhen true, replaces every occurrence of old_string (or old_str) in the file instead of requiring the match to be unique. When false (the default), the edit fails if old_string appears more than once.flootmcp_execute_sql#Run a WRITE SQL statement against the project's Postgres database — CREATE/ALTER TABLE, INSERT, UPDATE, DELETE, DROP, migrations. Destructive statements are allowed but your MCP client will show the user the SQL and ask them to approve it (they can allow once or for the session). Schema-changing statements (CREATE/ALTER/DROP of tables, types, …) automatically re-pull the typed schema helper and return the updated schema — no separate pull_database_schema call needed. Pass `database` only if the project has more than one. The query runs in a single transaction by default; set no_transaction for statements that cannot run inside a transaction block (VACUUM, CREATE INDEX CONCURRENTLY, …). Queries are killed after 90 seconds either way.4 params
Run a WRITE SQL statement against the project's Postgres database — CREATE/ALTER TABLE, INSERT, UPDATE, DELETE, DROP, migrations. Destructive statements are allowed but your MCP client will show the user the SQL and ask them to approve it (they can allow once or for the session). Schema-changing statements (CREATE/ALTER/DROP of tables, types, …) automatically re-pull the typed schema helper and return the updated schema — no separate pull_database_schema call needed. Pass `database` only if the project has more than one. The query runs in a single transaction by default; set no_transaction for statements that cannot run inside a transaction block (VACUUM, CREATE INDEX CONCURRENTLY, …). Queries are killed after 90 seconds either way.
projectIdstringrequiredThe Floot project ID whose Postgres database the statement should run against.querystringrequiredA write SQL statement to run — CREATE/ALTER TABLE, INSERT, UPDATE, DELETE, DROP, or a migration. Destructive statements are allowed but the calling MCP client will prompt the user to approve the SQL before it runs. Queries are killed after 90 seconds.databasestringoptionalOptional database name to run the statement against. Only needed when the project has more than one database; if omitted, the project's single/default database is used.no_transactionbooleanoptionalRun the statement without wrapping it in a transaction. Required for statements Postgres rejects inside a transaction block, such as VACUUM or CREATE INDEX CONCURRENTLY. Defaults to false, meaning the statement runs in a single transaction.flootmcp_fetch#Fetch a search result by id: a project overview ('<projectId>') or a file ('<projectId>:<path>'). For direct access to a known file or project, read_file/list_files give more detail.1 param
Fetch a search result by id: a project overview ('<projectId>') or a file ('<projectId>:<path>'). For direct access to a known file or project, read_file/list_files give more detail.
idstringrequiredThe search result id to fetch, as returned by the search tool: a project id alone (e.g. "proj_8f3a1c") for a project overview, or "<projectId>:<path>" (e.g. "proj_8f3a1c:pages/dashboard.tsx") for a specific file within that project.flootmcp_generate_image#Generate AI image assets directly into the project. Each image is written to the project's own asset storage and registered in its asset manifest; the tool returns the project-relative asset paths (/_cdn/static/...), which only resolve on the app's own domain — reference them in code or set one as the app/PWA icon via update_project_metadata (iconUrl). Use this for PROJECT-SPECIFIC imagery (mascots, tailored illustrations, app/PWA icons, imagery in a particular style); for generic stock imagery (nature, textures, generic people) use Unsplash URLs instead; if you already HAVE an image as a local file (generated or downloaded yourself), use upload_asset. Generate BEFORE building the components that use the images.2 params
Generate AI image assets directly into the project. Each image is written to the project's own asset storage and registered in its asset manifest; the tool returns the project-relative asset paths (/_cdn/static/...), which only resolve on the app's own domain — reference them in code or set one as the app/PWA icon via update_project_metadata (iconUrl). Use this for PROJECT-SPECIFIC imagery (mascots, tailored illustrations, app/PWA icons, imagery in a particular style); for generic stock imagery (nature, textures, generic people) use Unsplash URLs instead; if you already HAVE an image as a local file (generated or downloaded yourself), use upload_asset. Generate BEFORE building the components that use the images.
imagesarrayrequiredArray of 1-4 images to generate, each with a name and prompt. Each image is written to the project's own asset storage and registered in its asset manifest.projectIdstringrequiredThe Floot project ID to generate the images into.flootmcp_get_current_context#What the user is looking at RIGHT NOW in their open Floot editor: the active page/component, the preview element they selected (mapped to source file:line), the preview device size, whether they drew a screenshot annotation for you, whether they REVERTED recent changes (undoing edits — re-read before editing if so), and any requests they queued via editor action buttons ("Fix with Floot" etc.). Call this FIRST when the user refers to something without naming it ("this", "here", "the button"), reports a problem without saying where ("it's broken", "looks wrong"), or implies they triggered something in Floot ("go", "I clicked fix", "I undid that"). Cheap and text-only. With several windows open, one answers (the result says which) — but a selection made in ANY window is merged in, so a "no selection" from the answering window plus a deposited selection from another window means the deposited one is what the user means. If it reports a pending annotation, call view_annotation to see the image.1 param
What the user is looking at RIGHT NOW in their open Floot editor: the active page/component, the preview element they selected (mapped to source file:line), the preview device size, whether they drew a screenshot annotation for you, whether they REVERTED recent changes (undoing edits — re-read before editing if so), and any requests they queued via editor action buttons ("Fix with Floot" etc.). Call this FIRST when the user refers to something without naming it ("this", "here", "the button"), reports a problem without saying where ("it's broken", "looks wrong"), or implies they triggered something in Floot ("go", "I clicked fix", "I undid that"). Cheap and text-only. With several windows open, one answers (the result says which) — but a selection made in ANY window is merged in, so a "no selection" from the answering window plus a deposited selection from another window means the deposited one is what the user means. If it reports a pending annotation, call view_annotation to see the image.
projectIdstringrequiredThe Floot project ID whose open editor's current context should be retrieved.flootmcp_get_guide#Compatibility alias of get_guides — the identical tool under its common misspelling. Prefer get_guides; see it for full usage.3 params
Compatibility alias of get_guides — the identical tool under its common misspelling. Prefer get_guides; see it for full usage.
projectIdstringoptionalThe Floot project id to work on. Pass this whenever you're loading a guide for use on a specific project — some guides auto-inject their seed code into this project the first time they're loaded (idempotent; existing files are never overwritten).topicstringoptionalThe id of a single Floot guide to fetch (e.g. "floot-overview"). Omit both topic and topics to list all available guides instead.topicsarrayoptionalAn array of guide ids to fetch multiple guides in one call.flootmcp_get_guides#Floot documentation for agents. Call with no arguments to list available guides. Pass `topic` for one guide (e.g. topic:'floot-overview') or `topics` (an array of ids) to fetch several at once. floot-overview explains how Floot projects work — read it before your first code change. Skill guides that ship seed code (marked in the list) AUTO-INJECT it into the project the first time they're loaded with a projectId — pass projectId whenever you're working on a project; idempotent, never overwrites existing files.3 params
Floot documentation for agents. Call with no arguments to list available guides. Pass `topic` for one guide (e.g. topic:'floot-overview') or `topics` (an array of ids) to fetch several at once. floot-overview explains how Floot projects work — read it before your first code change. Skill guides that ship seed code (marked in the list) AUTO-INJECT it into the project the first time they're loaded with a projectId — pass projectId whenever you're working on a project; idempotent, never overwrites existing files.
projectIdstringoptionalThe Floot project id to work on. Pass this whenever you're loading a guide for use on a specific project — some guides auto-inject their seed code into this project the first time they're loaded (idempotent; existing files are never overwritten).topicstringoptionalThe id of a single Floot guide to fetch (e.g. "floot-overview"). Omit both topic and topics to list all available guides instead.topicsarrayoptionalAn array of guide ids to fetch multiple guides in one call.flootmcp_get_job_status#Poll a pending tool call by its jobId. Each poll either returns the final result (succeeded/failed/cancelled), or reports the call as still running — call it again until you get the result. Failed calls return their stored error message. A jobId belongs to exactly ONE task: it never blocks other tools or other jobs (run them freely in parallel), and once terminal it is frozen history — a NEW user request means a fresh call on the originating tool, never re-polling an old jobId. Legacy v!/b! job ids are also accepted.2 params
Poll a pending tool call by its jobId. Each poll either returns the final result (succeeded/failed/cancelled), or reports the call as still running — call it again until you get the result. Failed calls return their stored error message. A jobId belongs to exactly ONE task: it never blocks other tools or other jobs (run them freely in parallel), and once terminal it is frozen history — a NEW user request means a fresh call on the originating tool, never re-polling an old jobId. Legacy v!/b! job ids are also accepted.
jobIdstringrequiredThe job ID returned by a previous long-running tool call to poll for its result. Legacy job ids prefixed "v!" or "b!" are also accepted.wait_secondsintegeroptionalOptional number of seconds to keep this poll open waiting for the job to reach a terminal state before responding. If omitted, the poll returns immediately with the job's current status.flootmcp_get_logs#Your FIRST step when debugging any runtime problem — a 500, a failed request, a blank page, or 'it doesn't work' from the user. Call this before theorizing from an error message alone. Reads the project's runtime logs. source 'server' (default): the dev backend's request logs from the last hour — method, URL, status, duration, and per-request server log lines (pass log_reference_id from a previous listing for one request's full logs); includes background jobs (queueTask/scheduled/failure). source 'browser': console output AND client-side network requests (each fetch as `⇄ METHOD url → status`, with the error body for failed/4xx/5xx ones — the client-side view server logs miss, e.g. CORS/timeouts/third-party calls) captured from the user's open editor session. A browser network line's `ref=<id>` is a log_reference_id you can pass back with source 'server' for that request's full server logs. Empty if no editor is open. NOT CloudWatch: entries live ~1 hour and cover the dev backend + live session only — for the PUBLISHED app's logs, use run_code_in_vm's `_floot.getProdBackendLogs` (details: get_guides('prod-backend-logs')).4 params
Your FIRST step when debugging any runtime problem — a 500, a failed request, a blank page, or 'it doesn't work' from the user. Call this before theorizing from an error message alone. Reads the project's runtime logs. source 'server' (default): the dev backend's request logs from the last hour — method, URL, status, duration, and per-request server log lines (pass log_reference_id from a previous listing for one request's full logs); includes background jobs (queueTask/scheduled/failure). source 'browser': console output AND client-side network requests (each fetch as `⇄ METHOD url → status`, with the error body for failed/4xx/5xx ones — the client-side view server logs miss, e.g. CORS/timeouts/third-party calls) captured from the user's open editor session. A browser network line's `ref=<id>` is a log_reference_id you can pass back with source 'server' for that request's full server logs. Empty if no editor is open. NOT CloudWatch: entries live ~1 hour and cover the dev backend + live session only — for the PUBLISHED app's logs, use run_code_in_vm's `_floot.getProdBackendLogs` (details: get_guides('prod-backend-logs')).
projectIdstringrequiredThe unique identifier of the Floot project whose logs should be read. Obtain it from create_project or a project listing.limitintegeroptionalThe maximum number of log entries to return, from 1 to 50.log_reference_idstringoptionalA reference id copied from a previous log entry (a server request id, or the ref=<id> shown on a browser network line) to fetch the full server-side logs for that one request.sourcestringoptionalWhich log stream to read. "server" (the default) returns the dev backend's request logs from the last hour — method, URL, status, duration, and background job activity. "browser" returns console output and client-side network requests captured from the user's currently open editor session; it is empty if no editor session is open.flootmcp_get_preview_url#Show the user a live preview card and return the preview link. On an EXISTING project this is typically called EARLY, before the first change, so the user watches edits live from the start; the result is informational and a working session normally continues past it. Do NOT call it right after create_project — that result already showed the same card; calling both duplicates it. The preview URL carries an access token in its query string and only works shared EXACTLY as returned (no Floot login, view-only — which is also what lets it open on a phone); it live-updates as you edit, so it also suits an in-app browser tab if your client has one. The result additionally includes the sandbox API base for your own headless /_api/* testing — the frontend does not render there and it is not a user-facing URL; the preview link is the one meant for the user. Floot HOSTS the app — to go to production use publish_app; never suggest deploying a Floot app to an external host.1 param
Show the user a live preview card and return the preview link. On an EXISTING project this is typically called EARLY, before the first change, so the user watches edits live from the start; the result is informational and a working session normally continues past it. Do NOT call it right after create_project — that result already showed the same card; calling both duplicates it. The preview URL carries an access token in its query string and only works shared EXACTLY as returned (no Floot login, view-only — which is also what lets it open on a phone); it live-updates as you edit, so it also suits an in-app browser tab if your client has one. The result additionally includes the sandbox API base for your own headless /_api/* testing — the frontend does not render there and it is not a user-facing URL; the preview link is the one meant for the user. Floot HOSTS the app — to go to production use publish_app; never suggest deploying a Floot app to an external host.
projectIdstringrequiredThe Floot project ID to get a live, view-only preview link for.flootmcp_get_publish_status#Read-only publish snapshot for a project: published (true/false, with the live URL when published), customDomains (the user's own domains attached to the project — apex and www are listed separately; empty when none), paid (the workspace owner has a paid plan, which allows removing the Floot badge), plan (free | pro | power — `paid` cannot tell Pro from Power), nativeBuilds (the owner's remaining monthly iOS/Android app-build allowance; `unlimited` is true on plans where the ceiling is only a fair-use backstop, and while an Action Boost is live (`boostUntil` says until when; builds started before then never count toward the allowance) — read this BEFORE passing mobile: true, and on a metered plan build only when the user asked for a native/TestFlight/Play build), displayFlootLogo (whether the live app shows the 'Made with Floot' badge; true until a paid owner turns it off), and mobileBuild (the published app's latest native app build: building, succeeded, or failed with what to fix — an app build finishes minutes AFTER the publish job it rode on, so read this to learn how it ended before telling the user it worked). This is the ONLY tool that reports attached custom domains — read it before telling a user whether their domain is connected, and never conclude a domain is unattached from any other output. The publish card calls this on load to render fresh state; also check it before publishing to know whether publish_app will publish fresh or publish the live app again.1 param
Read-only publish snapshot for a project: published (true/false, with the live URL when published), customDomains (the user's own domains attached to the project — apex and www are listed separately; empty when none), paid (the workspace owner has a paid plan, which allows removing the Floot badge), plan (free | pro | power — `paid` cannot tell Pro from Power), nativeBuilds (the owner's remaining monthly iOS/Android app-build allowance; `unlimited` is true on plans where the ceiling is only a fair-use backstop, and while an Action Boost is live (`boostUntil` says until when; builds started before then never count toward the allowance) — read this BEFORE passing mobile: true, and on a metered plan build only when the user asked for a native/TestFlight/Play build), displayFlootLogo (whether the live app shows the 'Made with Floot' badge; true until a paid owner turns it off), and mobileBuild (the published app's latest native app build: building, succeeded, or failed with what to fix — an app build finishes minutes AFTER the publish job it rode on, so read this to learn how it ended before telling the user it worked). This is the ONLY tool that reports attached custom domains — read it before telling a user whether their domain is connected, and never conclude a domain is unattached from any other output. The publish card calls this on load to render fresh state; also check it before publishing to know whether publish_app will publish fresh or publish the live app again.
projectIdstringrequiredThe Floot project ID to read the publish snapshot for.flootmcp_list_files#List a Floot project's virtual file tree with sizes, plus its dependencies, current version (pass the version to write tools as expected_version), and current project metadata — title, description, app icon (iconUrl), splash screen, mobile app id, SSR, iOS Info.plist overrides, share target (iOS + Android), native system bars. This is where to look up those settings; update_project_metadata changes them.1 param
List a Floot project's virtual file tree with sizes, plus its dependencies, current version (pass the version to write tools as expected_version), and current project metadata — title, description, app icon (iconUrl), splash screen, mobile app id, SSR, iOS Info.plist overrides, share target (iOS + Android), native system bars. This is where to look up those settings; update_project_metadata changes them.
projectIdstringrequiredThe Floot project id whose virtual file tree, dependencies, current version, and project metadata should be listed. Get this from list_projects.flootmcp_list_projects#List your Floot projects (id, name, last-updated, whether an app icon is set), most recently updated first. name_filter is a case-insensitive substring match on the stored name, which is often not the name the user uses for a project — on a small account a filter that matches nothing returns the whole list instead.2 params
List your Floot projects (id, name, last-updated, whether an app icon is set), most recently updated first. name_filter is a case-insensitive substring match on the stored name, which is often not the name the user uses for a project — on a small account a filter that matches nothing returns the whole list instead.
limitintegeroptionalMaximum number of projects to return, most recently updated first. Must be between 1 and 100.name_filterstringoptionalCase-insensitive substring filter matched against a project's stored name. Note: this is often not the name the user calls the project by, so on an account with only a few projects, a filter that doesn't match anything returns the full list instead of an empty result.flootmcp_list_resources#List the env vars a project's code can use and the resources behind them: (1) resources CONNECTED to the project — usable as process.env.<NAME> in endpoint code now; (2) the owner's other account-level credentials — reusable, but not usable in code until connected; (3) everything Floot can add. Call it to learn what env vars exist before writing backend code, and BEFORE provisioning or requesting any credential (the owner may already have the one you need). Pass query (case-insensitive substring over names, descriptions, types, and env var names) to filter when the account has many resources. Read-only. Details: get_guides('resources').2 params
List the env vars a project's code can use and the resources behind them: (1) resources CONNECTED to the project — usable as process.env.<NAME> in endpoint code now; (2) the owner's other account-level credentials — reusable, but not usable in code until connected; (3) everything Floot can add. Call it to learn what env vars exist before writing backend code, and BEFORE provisioning or requesting any credential (the owner may already have the one you need). Pass query (case-insensitive substring over names, descriptions, types, and env var names) to filter when the account has many resources. Read-only. Details: get_guides('resources').
projectIdstringrequiredThe Floot project id whose available resources (connected env vars, other account-level credentials, and everything Floot can add) should be listed. Get this from list_projects.querystringoptionalCase-insensitive substring filter matched against resource names, descriptions, types, and env var names. Use it to narrow the list on an account with many connected resources.flootmcp_provision_resource#Provision a Floot-managed backend resource for the project — fully server-side (Floot mints all secrets; no keys to paste). Also seeds the working code for it. Available:
- database — A Floot-managed Postgres database (Neon). FLOOT_DATABASE_URL is set for the app.
- auth — Email/password + session auth (JWT_SECRET, auto-provisions a database if none). Injects auth pages, endpoints, and helpers.
- oauth-login — Sign in with Google via Floot's brokered OAuth (FLOOT_OAUTH). Injects OAuth provider classes, login buttons, helpers.
- microsoft-login — Sign in with Microsoft via Floot's brokered login (FLOOT_MICROSOFT_LOGIN). Injects button + auth endpoints.
- google-integration — Google API access (Gmail/Calendar/etc.) via Floot's brokered Google OAuth (FLOOT_GOOGLE_INTEGRATIONS). Injects Connect button + endpoints.
- microsoft-integration — Microsoft Graph access (Outlook/Teams/etc.) via Floot's brokered Microsoft OAuth (FLOOT_MICROSOFT_INTEGRATIONS). Injects Connect button + endpoints.
- push-notifications — Web + native push (FLOOT_PUSH). Mints VAPID keys, injects helpers/pushClient (subscribe/unsubscribe) + a service worker.
Enum values not listed above are beta-gated and unavailable on most accounts. SENDING email from the app is NOT a resource — the builtin @floot/email handles it with zero setup (get_guides("email")). For a user's OWN external key (their OpenAI key, an external database), this is NOT the tool — use request_external_resource instead. Idempotent: re-running returns the existing resource and skips seed files that already exist.2 params
Provision a Floot-managed backend resource for the project — fully server-side (Floot mints all secrets; no keys to paste). Also seeds the working code for it. Available: - database — A Floot-managed Postgres database (Neon). FLOOT_DATABASE_URL is set for the app. - auth — Email/password + session auth (JWT_SECRET, auto-provisions a database if none). Injects auth pages, endpoints, and helpers. - oauth-login — Sign in with Google via Floot's brokered OAuth (FLOOT_OAUTH). Injects OAuth provider classes, login buttons, helpers. - microsoft-login — Sign in with Microsoft via Floot's brokered login (FLOOT_MICROSOFT_LOGIN). Injects button + auth endpoints. - google-integration — Google API access (Gmail/Calendar/etc.) via Floot's brokered Google OAuth (FLOOT_GOOGLE_INTEGRATIONS). Injects Connect button + endpoints. - microsoft-integration — Microsoft Graph access (Outlook/Teams/etc.) via Floot's brokered Microsoft OAuth (FLOOT_MICROSOFT_INTEGRATIONS). Injects Connect button + endpoints. - push-notifications — Web + native push (FLOOT_PUSH). Mints VAPID keys, injects helpers/pushClient (subscribe/unsubscribe) + a service worker. Enum values not listed above are beta-gated and unavailable on most accounts. SENDING email from the app is NOT a resource — the builtin @floot/email handles it with zero setup (get_guides("email")). For a user's OWN external key (their OpenAI key, an external database), this is NOT the tool — use request_external_resource instead. Idempotent: re-running returns the existing resource and skips seed files that already exist.
projectIdstringrequiredThe Floot project ID to provision the resource for.resourcestringrequiredWhich Floot-managed backend resource to provision for the project, e.g. database or auth. See the tool description for what each option sets up; some enum values are beta-gated and unavailable on most accounts.flootmcp_publish_app#Publish the app to production — call for the first publish, to publish again after changes the user wants live, and to set up a custom domain. Omit domain and the user gets the publish form in the editor. Pass mobile: true whenever the user mentions iOS, Android, TestFlight, App Store, Google Play, or a mobile/native app — with no store account connected that returns a Connect card; with one connected it publishes with the store builds attached. A refusal with payments_onboarding_required means the project owner has not finished payments setup: give the owner the onboarding link from the refusal first, and pass skipPaymentsOnboarding: true only when the user says to publish without payments. Read get_guides('publishing') for modes, inputs, and statuses before your first call.7 params
Publish the app to production — call for the first publish, to publish again after changes the user wants live, and to set up a custom domain. Omit domain and the user gets the publish form in the editor. Pass mobile: true whenever the user mentions iOS, Android, TestFlight, App Store, Google Play, or a mobile/native app — with no store account connected that returns a Connect card; with one connected it publishes with the store builds attached. A refusal with payments_onboarding_required means the project owner has not finished payments setup: give the owner the onboarding link from the refusal first, and pass skipPaymentsOnboarding: true only when the user says to publish without payments. Read get_guides('publishing') for modes, inputs, and statuses before your first call.
projectIdstringrequiredThe Floot project ID to publish. Get this from list_projects, get_project, or the project you just created.add_anotherbooleanoptionalcustom_domain only: the project ALREADY has a custom domain and the user has explicitly asked for an ADDITIONAL one. Without it, a custom_domain call on a project that already has domains returns those domains instead of opening the wizard — so a user whose domain is already connected is told so rather than sent to add it again.domainstringoptionalfloot_subdomain only: subdomain label (lowercase, digits, hyphens, max 40). Omit to show the user the publish form instead; on a published app a different subdomain is refused (unpublish_app first, confirming with the user). Ignored for custom_domain — the wizard collects the domain.domain_typestringoptionalOmit for the floot subdomain (shows the publish form in the editor when domain is omitted). 'custom_domain' for domain setup — a paid-plan feature (get_publish_status reports `paid`); it fails for free accounts.include_made_with_flootbooleanoptionalfalse removes the 'Made with Floot' badge (paid plans only — fails for free accounts). Omit to keep the current setting.mobilebooleanoptionalSet true whenever the request mentions iOS, Android, TestFlight, App Store, Google Play, Play Store, a native or mobile app, or a phone build — they all mean a mobile build. No store account connected → returns a Connect card (nothing published). Connected → publishes the web app with the store builds attached; the job completes when the web build is live. Omitted on a live app follows the project's saved setting: on plans with unlimited app builds that setting decides (mobile switched off stays web-only); on metered plans omitted always means web-only, and true spends one of a small monthly allowance (the remaining count comes back in the result) — read get_publish_status for the plan and allowance first. Passing true or false also updates the saved setting; omitting leaves it alone.skipPaymentsOnboardingbooleanoptionaltrue publishes although the owner's payments setup is unfinished; the app's payment screens stay unavailable until it is done.flootmcp_pull_database_schema#Introspect the database and write a typed schema helper the app uses for queries (kysely on current projects; some legacy projects use drizzle or snake_case kysely — the pull matches whatever the project already uses). Usually NOT needed after execute_sql — schema-changing statements re-pull automatically. Use it to refresh manually, or with helper_name to generate the helper for an additional/external database. The helper is GENERATED — never hand-edit it or cast around its types: if a column's type is too loose (e.g. role as string when code expects "user" | "admin"), fix the DATABASE (CREATE TYPE … AS ENUM + ALTER COLUMN … TYPE) and re-pull, and the union type falls out.3 params
Introspect the database and write a typed schema helper the app uses for queries (kysely on current projects; some legacy projects use drizzle or snake_case kysely — the pull matches whatever the project already uses). Usually NOT needed after execute_sql — schema-changing statements re-pull automatically. Use it to refresh manually, or with helper_name to generate the helper for an additional/external database. The helper is GENERATED — never hand-edit it or cast around its types: if a column's type is too loose (e.g. role as string when code expects "user" | "admin"), fix the DATABASE (CREATE TYPE … AS ENUM + ALTER COLUMN … TYPE) and re-pull, and the union type falls out.
projectIdstringrequiredThe Floot project ID whose database schema should be introspected and re-pulled.databasestringoptionalName of a specific database to pull the schema for, used when the project has more than one configured database (for example an additional or external database). Leave unset to use the project's primary database.helper_namestringoptionalName to give the generated schema helper, used when generating a helper for an additional or external database alongside the project's main one. Leave unset to regenerate the default helper.flootmcp_query_database#Run a READ-ONLY SQL query against the project's Postgres database (SELECT, EXPLAIN, etc.). Writes are rejected — use execute_sql for those. Returns JSON: `{rows, rowCount, command, truncated?}` (or `{results: [...]}` for multi-statement queries). Pass `database` only if the project has more than one.3 params
Run a READ-ONLY SQL query against the project's Postgres database (SELECT, EXPLAIN, etc.). Writes are rejected — use execute_sql for those. Returns JSON: `{rows, rowCount, command, truncated?}` (or `{results: [...]}` for multi-statement queries). Pass `database` only if the project has more than one.
projectIdstringrequiredThe Floot project ID whose Postgres database should be queried.querystringrequiredA read-only SQL statement to run (SELECT, EXPLAIN, etc.). Write statements are rejected — use execute_sql for those.databasestringoptionalOptional database name to run the query against. Only needed when the project has more than one database; if omitted, the project's single/default database is used.flootmcp_read_file#Read a file from a Floot project (cat -n style). Paths follow the item scheme: components/Name.tsx, components/Name.module.css, helpers/Name.tsx, pages/name.tsx, pages/name.pageLayout.tsx, endpoints/route_POST.ts, endpoints/route_POST.schema.ts, static/file.txt, base.css. Use offset/limit for large files. Pass include_references:true to also list which project files reference this one (static import graph plus queueTask/runCode name references and, for endpoints, URL-path string usage) — check it before renaming or deleting a file, or use rename_file which rewrites importers itself. Hosted assets are readable too: pass the project-relative asset path (/_cdn/<name>, as returned by upload_asset / generate_image or used in the app's <img src>; private/<name> for private storage) and a png/jpeg/gif/webp image is returned as an image you can see (≤3.75 MB), text-typed assets as text, other binaries as a size/type summary. For a .ts/.tsx file, the file's CURRENT type errors are appended when the project's compute VM is already warm (so you see latent errors before editing); pass diagnostics:"off" to skip, or "wait" to boot the VM and force the check.6 params
Read a file from a Floot project (cat -n style). Paths follow the item scheme: components/Name.tsx, components/Name.module.css, helpers/Name.tsx, pages/name.tsx, pages/name.pageLayout.tsx, endpoints/route_POST.ts, endpoints/route_POST.schema.ts, static/file.txt, base.css. Use offset/limit for large files. Pass include_references:true to also list which project files reference this one (static import graph plus queueTask/runCode name references and, for endpoints, URL-path string usage) — check it before renaming or deleting a file, or use rename_file which rewrites importers itself. Hosted assets are readable too: pass the project-relative asset path (/_cdn/<name>, as returned by upload_asset / generate_image or used in the app's <img src>; private/<name> for private storage) and a png/jpeg/gif/webp image is returned as an image you can see (≤3.75 MB), text-typed assets as text, other binaries as a size/type summary. For a .ts/.tsx file, the file's CURRENT type errors are appended when the project's compute VM is already warm (so you see latent errors before editing); pass diagnostics:"off" to skip, or "wait" to boot the VM and force the check.
pathstringrequiredThe project-relative path of the file to read, following Floot's item scheme (e.g. components/Name.tsx, pages/name.tsx, endpoints/route_POST.ts, static/file.txt) or a hosted asset path (e.g. /_cdn/<name>).projectIdstringrequiredThe Floot project id containing the file to read. Get this from list_projects.diagnosticsstringoptionalControls whether current TypeScript/TSX type errors for the file are appended to the result: "auto" (default) includes them only if the project's compute VM is already warm, "off" skips the check, and "wait" boots the VM if needed and forces the check.include_referencesbooleanoptionalWhen true, also returns the list of project files that reference this file (the static import graph, plus queueTask/runCode name references and, for endpoints, URL-path string usage). Useful before renaming or deleting a file.limitintegeroptionalMaximum number of lines to return, up to 5000. Use together with offset to page through a large file.offsetintegeroptional1-based line number to start reading from. Use together with limit to page through a large file.flootmcp_read_files#Read MULTIPLE files from a Floot project in ONE call — much cheaper than repeated read_file (the whole project is loaded once, one round-trip). Prefer this whenever you need several files together (e.g. an endpoint + its .schema.ts + the hook that calls it, or orienting in a feature). Pass up to 20 paths (same item scheme as read_file; /_cdn/<name> asset paths are accepted too and images come back as image blocks). Each file is returned cat -n style under a header. Each .ts/.tsx file's current type errors are appended when the compute VM is warm (diagnostics:"off" to skip, "wait" to force). include_references:true appends each file's referencing files (same analysis as read_file). Output is capped overall; if the batch is too large, whole files at the end are omitted and listed by name so you can read them individually.5 params
Read MULTIPLE files from a Floot project in ONE call — much cheaper than repeated read_file (the whole project is loaded once, one round-trip). Prefer this whenever you need several files together (e.g. an endpoint + its .schema.ts + the hook that calls it, or orienting in a feature). Pass up to 20 paths (same item scheme as read_file; /_cdn/<name> asset paths are accepted too and images come back as image blocks). Each file is returned cat -n style under a header. Each .ts/.tsx file's current type errors are appended when the compute VM is warm (diagnostics:"off" to skip, "wait" to force). include_references:true appends each file's referencing files (same analysis as read_file). Output is capped overall; if the batch is too large, whole files at the end are omitted and listed by name so you can read them individually.
pathsarrayrequiredThe project-relative paths of the files to read together in one call, up to 20, using the same item scheme as read_file (e.g. components/Name.tsx, endpoints/route_POST.ts) or hosted asset paths (e.g. /_cdn/<name>).projectIdstringrequiredThe Floot project id containing the files to read. Get this from list_projects.diagnosticsstringoptionalControls whether current TypeScript/TSX type errors for each file are appended to the result: "auto" (default) includes them only if the project's compute VM is already warm, "off" skips the check, and "wait" boots the VM if needed and forces the check.include_referencesbooleanoptionalWhen true, also appends the list of project files that reference each returned file (the same analysis as read_file).limitintegeroptionalMaximum number of lines to return per file, up to 5000.flootmcp_remove_dependency#Remove npm packages from a Floot project's dependency record (record-only; nothing runs).2 params
Remove npm packages from a Floot project's dependency record (record-only; nothing runs).
packagesarrayrequiredThe npm package names to remove from the project's dependency record. Provide at least one package name; this only updates the recorded dependency list and does not run any install/uninstall command.projectIdstringrequiredThe unique identifier of the Floot project whose dependency record should be updated. Obtain it from create_project or a project listing.flootmcp_rename_file#Rename one or more items and automatically rewrite every file that imports them. Use item names WITHOUT extensions (e.g. {from:'components/OldName', to:'components/NewName'}). Preferred over delete+create — preserves content and fixes importers. Same type only. Pass several renames to apply them atomically in ONE pass; importer rewrites are resolved across the whole batch (including chains where one rename's target is another's source).3 params
Rename one or more items and automatically rewrite every file that imports them. Use item names WITHOUT extensions (e.g. {from:'components/OldName', to:'components/NewName'}). Preferred over delete+create — preserves content and fixes importers. Same type only. Pass several renames to apply them atomically in ONE pass; importer rewrites are resolved across the whole batch (including chains where one rename's target is another's source).
projectIdstringrequiredThe Floot project ID containing the items to rename.renamesarrayrequiredOne or more rename operations, each with a "from" and "to" item name (folder path allowed, no file extension). All renames in the array are applied atomically in one pass, and importer rewrites are resolved across the whole batch. Example: [{"from": "components/OldName", "to": "components/NewName"}].expected_versionintegeroptionalOptional expected current file-tree version, for optimistic concurrency. If provided and it no longer matches the project's current version, the rename is rejected instead of racing with a concurrent edit.flootmcp_request_external_resource#Request the USER'S OWN external credential for this project — their OpenAI or Anthropic API key, an external Postgres connection string, or any other service's key (type GENERIC, e.g. Stripe/Resend — secret_env_vars is REQUIRED for GENERIC and the call is refused without it; a var the user can only produce LATER, like a webhook signing secret, goes in optional_env_vars so the dialog doesn't demand it up front). NOT for Floot-managed resources (database/auth/push/oauth/…) — use provision_resource for those; they need no user input. REUSE FIRST: if the project owner already has a matching credential on their account (list_resources section 2), this connects it silently and returns the env var names — no link, no user action, nothing to poll. Pass the name exactly as list_resources shows it to make that happen. Reusing a POSTGRES credential also seeds helpers/db, installs the query stack, and pulls the typed schema helper, so do NOT write those yourself afterwards. Otherwise it returns a secure connect link: SHOW it to the user (UI-capable hosts render a Connect button automatically; on terminal hosts with shell access open it in the user's default browser yourself and paste the URL as plain text) and ask them to open it. The call completes only when the user finishes the connect flow — it never expires. Do NOT block on it: request the credential EARLY, keep building everything that doesn't need the secret (the env var names are known now — reference process.env.X in code before the secret exists), and check the request between tasks; the user may never connect it, and the build must not stall. NEVER ask the user to paste a secret into the chat. On completion you get the env var names — never the secret values. Re-calling with the same type returns the same pending request. If the credential is already connected and holds every value you asked for, you get those env var names and their value SHAPES back immediately and the user is not interrupted — to reopen a dialog because a stored value is wrong, re-call with `instructions` saying what is wrong.6 params
Request the USER'S OWN external credential for this project — their OpenAI or Anthropic API key, an external Postgres connection string, or any other service's key (type GENERIC, e.g. Stripe/Resend — secret_env_vars is REQUIRED for GENERIC and the call is refused without it; a var the user can only produce LATER, like a webhook signing secret, goes in optional_env_vars so the dialog doesn't demand it up front). NOT for Floot-managed resources (database/auth/push/oauth/…) — use provision_resource for those; they need no user input. REUSE FIRST: if the project owner already has a matching credential on their account (list_resources section 2), this connects it silently and returns the env var names — no link, no user action, nothing to poll. Pass the name exactly as list_resources shows it to make that happen. Reusing a POSTGRES credential also seeds helpers/db, installs the query stack, and pulls the typed schema helper, so do NOT write those yourself afterwards. Otherwise it returns a secure connect link: SHOW it to the user (UI-capable hosts render a Connect button automatically; on terminal hosts with shell access open it in the user's default browser yourself and paste the URL as plain text) and ask them to open it. The call completes only when the user finishes the connect flow — it never expires. Do NOT block on it: request the credential EARLY, keep building everything that doesn't need the secret (the env var names are known now — reference process.env.X in code before the secret exists), and check the request between tasks; the user may never connect it, and the build must not stall. NEVER ask the user to paste a secret into the chat. On completion you get the env var names — never the secret values. Re-calling with the same type returns the same pending request. If the credential is already connected and holds every value you asked for, you get those env var names and their value SHAPES back immediately and the user is not interrupted — to reopen a dialog because a stored value is wrong, re-call with `instructions` saying what is wrong.
projectIdstringrequiredThe Floot project ID to request the external credential for.typestringrequiredWhich kind of external credential to request from the project owner. Use GENERIC for any service not covered by the other options (e.g. Stripe, Resend).instructionsstringoptionalExplanation shown to the user in the connect dialog describing why the credential is needed and where they can find it.namestringoptionalDisplay name shown in the connect dialog, required when type is GENERIC, e.g. "Stripe".optional_env_varsarrayoptionalEnvironment variable name(s) the user may leave blank at connect time and provide later, e.g. a webhook signing secret that only exists after the webhook endpoint is created.secret_env_varsarrayoptionalEnvironment variable name(s) the secret(s) should be exposed as, required for GENERIC requests (the call is refused without it), e.g. ["STRIPE_SECRET_KEY"]. Only list variables the user can provide right away.flootmcp_request_user_upload#Show the user an inline upload card so they can hand you a file from their device (image/font/audio/…) — it lands in the project's hosted assets and the card gives you the hosted publicUrl. This is the path for any file the user has: an image they attached in this chat (attachments never reach MCP servers — you see them through vision only, so the user re-picks the same file here), a file on their machine, or a user-provided file you hold but can't upload yourself (over the 3 MB inline cap with no S3 egress — the card uploads from their browser, which is never egress-blocked). Returns a jobId — poll get_job_status; it stays running until they upload, then returns the publicUrl to reference in code. When you show the card, tell the user in a sentence why you're asking — e.g. that you can see their image but the file itself doesn't reach Floot, so re-adding it here is a one-click step — and ask them to say "uploaded" when done in case your polling ends before they finish. For files you hold yourself, use upload_asset; for AI-generated imagery, use generate_image.2 params
Show the user an inline upload card so they can hand you a file from their device (image/font/audio/…) — it lands in the project's hosted assets and the card gives you the hosted publicUrl. This is the path for any file the user has: an image they attached in this chat (attachments never reach MCP servers — you see them through vision only, so the user re-picks the same file here), a file on their machine, or a user-provided file you hold but can't upload yourself (over the 3 MB inline cap with no S3 egress — the card uploads from their browser, which is never egress-blocked). Returns a jobId — poll get_job_status; it stays running until they upload, then returns the publicUrl to reference in code. When you show the card, tell the user in a sentence why you're asking — e.g. that you can see their image but the file itself doesn't reach Floot, so re-adding it here is a one-click step — and ask them to say "uploaded" when done in case your polling ends before they finish. For files you hold yourself, use upload_asset; for AI-generated imagery, use generate_image.
projectIdstringrequiredThe Floot project ID the uploaded file should be added to.descriptionstringoptionalText shown to the user in the upload card explaining what file you're asking for, e.g. "the logo image you attached".flootmcp_run_code_in_browser#Run a TypeScript snippet inside the RUNNING APP's preview document in the user's open Floot editor (`document`/`window` ARE the live app's DOM — query `document` directly; do NOT look for a preview iframe, there is none from the snippet's point of view). This is the CANONICAL way to read the live app's DOM — measuring elements, reading computed styles, inspecting rendered output. If you ALSO have your own browser/DevTools automation, it CANNOT reach into the Floot preview (it renders in a cross-origin iframe — your clicks silently no-op and its DOM is invisible to you), so use THIS tool for anything inside the app, not those. `_floot.*` helpers are available. The snippet MUST `export default async function` and return a string — the returned value is the tool result (unlike run_code_in_vm, which is a plain script returning stdout). It can import project files by relative path from the root (e.g. `./helpers/foo`). Requires the user to have the project open in the editor — fails fast with guidance if no browser is connected; prefer run_code_in_vm for anything that doesn't need the DOM. Simple interaction checks work well: element.click() a button, await a beat, then read the resulting DOM/state to verify a flow end-to-end — do this instead of asking the user to test basic interactions. Multi-step e2e journeys and typed text input are where simulation gets unreliable (React controlled inputs ignore assigned values) — leave THOSE to the user.2 params
Run a TypeScript snippet inside the RUNNING APP's preview document in the user's open Floot editor (`document`/`window` ARE the live app's DOM — query `document` directly; do NOT look for a preview iframe, there is none from the snippet's point of view). This is the CANONICAL way to read the live app's DOM — measuring elements, reading computed styles, inspecting rendered output. If you ALSO have your own browser/DevTools automation, it CANNOT reach into the Floot preview (it renders in a cross-origin iframe — your clicks silently no-op and its DOM is invisible to you), so use THIS tool for anything inside the app, not those. `_floot.*` helpers are available. The snippet MUST `export default async function` and return a string — the returned value is the tool result (unlike run_code_in_vm, which is a plain script returning stdout). It can import project files by relative path from the root (e.g. `./helpers/foo`). Requires the user to have the project open in the editor — fails fast with guidance if no browser is connected; prefer run_code_in_vm for anything that doesn't need the DOM. Simple interaction checks work well: element.click() a button, await a beat, then read the resulting DOM/state to verify a flow end-to-end — do this instead of asking the user to test basic interactions. Multi-step e2e journeys and typed text input are where simulation gets unreliable (React controlled inputs ignore assigned values) — leave THOSE to the user.
codestringrequiredA TypeScript module (not a function body) that exports a default async function returning a string; that returned string is the tool result. It runs at the project root, so other project files can be imported by relative path. Do not use a top-level `return` and do not use React hooks. Example:
export default async function () {
const el = document.querySelector("main");
return JSON.stringify({ width: el?.clientWidth ?? null });
}projectIdstringrequiredThe Floot project ID whose open preview the snippet should run against. This is the project's stable identifier, not a project name.flootmcp_run_code_in_vm#Run a Node.js snippet on the project's compute VM (headless — no browser needed). The project's npm dependencies are importable; network access works, so you can call the project's /_api/* endpoints (get_preview_url → apiBaseUrl). ESM by default; bare require() snippets run as CJS. Returns stdout+stderr.
Calls to the project's /_api/* are rate-guarded exactly like the browser preview: more than 20 calls to one endpoint or 150 total within 5s rejects that fetch and every later /_api/* fetch in the snippet with 'Backend endpoint is called too frequently'. This is a hard guard, not a retry hint — do NOT loop fetch() over rows/ids or fire many parallel calls; batch into one endpoint call, or use _floot.runSQLQuery for bulk reads/writes.
Runs in an ISOLATED temp dir, NOT the project root, with NO access to the project's environment: `process.env` carries none of the project's env vars or secrets (only PATH/HOME/NODE_ENV are set — anything like `process.env.POSTHOG_API_KEY` reads back `undefined`), and project source files are NOT importable by relative path (`import './helpers/foo'` fails with ERR_MODULE_NOT_FOUND — only npm dependencies resolve; contrast run_code_in_browser, which runs at the project root and CAN import project files). For anything that needs project secrets, env config, or DB access, use the `_floot` helpers below (they proxy to the project's server context) or fetch the project's /_api/* endpoints over the network — those run server-side WITH the full env; the VM snippet itself never sees it.
A `_floot` global is available with project-scoped server-data helpers (no DB creds needed, no HTTP wiring): `await _floot.runSQLQuery({ query, resourceName?, reasonAndExplanationForNotReadOnly?, dryRun? })` (omit the reason for a read-only query; pass it to allow NON-DESTRUCTIVE writes — INSERT, CREATE TABLE, additive ALTER — e.g. programmatic seeding loops. DESTRUCTIVE statements — DELETE/UPDATE/TRUNCATE/DROP — are rejected here because the user never sees snippet SQL; run those through the execute_sql tool, where the statement appears in the tool call for approval. Resolves to `{rows, rowCount, command, truncated?}` — or `{results: [...]}` for multi-statement queries), `getHostingUsage({days?})`, `getLambdaUsage({days?})`, `getPushHistory({subscription?,from?,to?,offset?})`, `getProdBackendLogs({filter?,from?,to?,nextToken?,limit?})` (the PUBLISHED app's backend CloudWatch logs; details: get_guides('prod-backend-logs')), `storageList(prefix)` (prefix MUST start with "public/" or "private/" — e.g. storageList("public/") to list everything public), `storageGetUrl(key)`, `storageGetFileSizes(visibility, continuationToken?)`, `storageUpload({filename,sizeBytes,contentType})`, `storageDelete(key)`, and `getFileById(id)` (returns `{url, fileName, contentType}` — fetch the url for bytes). Same surface as runCodeInBrowser's `_floot`, minus the DOM/editor-only helpers.3 params
Run a Node.js snippet on the project's compute VM (headless — no browser needed). The project's npm dependencies are importable; network access works, so you can call the project's /_api/* endpoints (get_preview_url → apiBaseUrl). ESM by default; bare require() snippets run as CJS. Returns stdout+stderr. Calls to the project's /_api/* are rate-guarded exactly like the browser preview: more than 20 calls to one endpoint or 150 total within 5s rejects that fetch and every later /_api/* fetch in the snippet with 'Backend endpoint is called too frequently'. This is a hard guard, not a retry hint — do NOT loop fetch() over rows/ids or fire many parallel calls; batch into one endpoint call, or use _floot.runSQLQuery for bulk reads/writes. Runs in an ISOLATED temp dir, NOT the project root, with NO access to the project's environment: `process.env` carries none of the project's env vars or secrets (only PATH/HOME/NODE_ENV are set — anything like `process.env.POSTHOG_API_KEY` reads back `undefined`), and project source files are NOT importable by relative path (`import './helpers/foo'` fails with ERR_MODULE_NOT_FOUND — only npm dependencies resolve; contrast run_code_in_browser, which runs at the project root and CAN import project files). For anything that needs project secrets, env config, or DB access, use the `_floot` helpers below (they proxy to the project's server context) or fetch the project's /_api/* endpoints over the network — those run server-side WITH the full env; the VM snippet itself never sees it. A `_floot` global is available with project-scoped server-data helpers (no DB creds needed, no HTTP wiring): `await _floot.runSQLQuery({ query, resourceName?, reasonAndExplanationForNotReadOnly?, dryRun? })` (omit the reason for a read-only query; pass it to allow NON-DESTRUCTIVE writes — INSERT, CREATE TABLE, additive ALTER — e.g. programmatic seeding loops. DESTRUCTIVE statements — DELETE/UPDATE/TRUNCATE/DROP — are rejected here because the user never sees snippet SQL; run those through the execute_sql tool, where the statement appears in the tool call for approval. Resolves to `{rows, rowCount, command, truncated?}` — or `{results: [...]}` for multi-statement queries), `getHostingUsage({days?})`, `getLambdaUsage({days?})`, `getPushHistory({subscription?,from?,to?,offset?})`, `getProdBackendLogs({filter?,from?,to?,nextToken?,limit?})` (the PUBLISHED app's backend CloudWatch logs; details: get_guides('prod-backend-logs')), `storageList(prefix)` (prefix MUST start with "public/" or "private/" — e.g. storageList("public/") to list everything public), `storageGetUrl(key)`, `storageGetFileSizes(visibility, continuationToken?)`, `storageUpload({filename,sizeBytes,contentType})`, `storageDelete(key)`, and `getFileById(id)` (returns `{url, fileName, contentType}` — fetch the url for bytes). Same surface as runCodeInBrowser's `_floot`, minus the DOM/editor-only helpers.
codestringrequiredThe Node.js snippet to execute on the project's compute VM. Runs as ESM by default (top-level require() falls back to CJS). The project's npm dependencies are importable and a project-scoped `_floot` helper global is available (SQL queries, storage, usage stats, prod logs); project source files are NOT importable by relative path in this sandbox. Network access works, so the snippet can call the project's own /_api/* endpoints, subject to the same rate limits as the browser preview. The call returns whatever the snippet writes to stdout/stderr.projectIdstringrequiredThe unique identifier of the Floot project whose VM should run this code. Obtain it from create_project or a project listing.timeout_secondsintegeroptionalHow long to let the snippet run before it is terminated, from 1 to 120 seconds. Omit to use the server's default timeout.flootmcp_run_tests#Run the project's Jasmine spec files (helpers/*.spec.tsx) headlessly on the project VM (jsdom — no browser needed). Frontend AND backend code is testable: specs may render components (@testing-library/react) or import endpoint handlers/backend helpers and call them directly. Limits: fetch throws inside tests (mock with spyOn(globalThis, "fetch")), process.env secrets are absent, and specs importing @floot/* service modules are skipped (no mocks yet). Returns per-file PASS/FAIL with failing expectations. Defaults to all spec files except hook specs (file name contains "use" — those need real React scheduling and are excluded, matching the in-editor checker); pass `paths` to run specific spec files, including hook specs.2 params
Run the project's Jasmine spec files (helpers/*.spec.tsx) headlessly on the project VM (jsdom — no browser needed). Frontend AND backend code is testable: specs may render components (@testing-library/react) or import endpoint handlers/backend helpers and call them directly. Limits: fetch throws inside tests (mock with spyOn(globalThis, "fetch")), process.env secrets are absent, and specs importing @floot/* service modules are skipped (no mocks yet). Returns per-file PASS/FAIL with failing expectations. Defaults to all spec files except hook specs (file name contains "use" — those need real React scheduling and are excluded, matching the in-editor checker); pass `paths` to run specific spec files, including hook specs.
projectIdstringrequiredThe unique identifier of the Floot project whose tests should run. Obtain it from create_project or a project listing.pathsarrayoptionalSpecific spec file paths (within the project) to run. Omit to run all spec files except hook specs (files whose name contains "use"), matching the in-editor checker's default. Pass hook spec paths explicitly here to include them.flootmcp_screenshot_preview#Capture a screenshot of the user app. Call it whenever you want to SEE what the app currently looks like (layout, styling, rendered state) or want to debug the app.1 param
Capture a screenshot of the user app. Call it whenever you want to SEE what the app currently looks like (layout, styling, rendered state) or want to debug the app.
projectIdstringrequiredThe Floot project ID whose open preview window should be screenshotted.flootmcp_search#Search your Floot projects and their code. Returns result ids usable with fetch. For richer options, list_projects enumerates projects and search_code does code-level search.1 param
Search your Floot projects and their code. Returns result ids usable with fetch. For richer options, list_projects enumerates projects and search_code does code-level search.
querystringrequiredThe search text to match against your Floot projects and their code. Accepts plain keywords or phrases, e.g. "stripe checkout" or "dashboard layout". Matches are returned as result ids you can pass to the fetch tool.flootmcp_search_code#Search a Floot project's files (string or regex) with optional glob filters (e.g. ['components/*', 'endpoints/**']). Returns file:line excerpts plus filename matches; capped at 40 results.4 params
Search a Floot project's files (string or regex) with optional glob filters (e.g. ['components/*', 'endpoints/**']). Returns file:line excerpts plus filename matches; capped at 40 results.
projectIdstringrequiredThe Floot project id to search within. Get this from list_projects.querystringrequiredThe text or regular expression to search for within the project's files.globarrayoptionalOptional glob patterns to restrict the search to matching files, e.g. ["components/*", "endpoints/**"].regexbooleanoptionalWhen true, treat query as a regular expression instead of a plain string.flootmcp_typecheck#Typecheck the project (incremental tsc on the project VM). Type errors don't block the app from running.2 params
Typecheck the project (incremental tsc on the project VM). Type errors don't block the app from running.
projectIdstringrequiredThe unique identifier of the Floot project to typecheck. Obtain it from create_project or a project listing.pathsarrayoptionalSpecific file paths (within the project) to typecheck. Omit to typecheck the whole project.flootmcp_unpublish_app#Take the published app offline and release its subdomain — destructive, confirm with the user first. Details: get_guides('publishing').1 param
Take the published app offline and release its subdomain — destructive, confirm with the user first. Details: get_guides('publishing').
projectIdstringrequiredThe Floot project ID whose published app should be taken offline. Get this from list_projects or get_project.flootmcp_update_project_metadata#Update project settings (current values appear at the top of list_files). Keys: title (2-100 chars), description, iconUrl, splashUrl, mobileAppId, enableSSR (boolean), flootAiDisallowed (boolean — true opts the project out of @floot/ai), and iOS Info.plist purpose strings (NS…UsageDescription — set to a string, or null to remove) plus boolean Info.plist keys (UIViewControllerBasedStatusBarAppearance — set to a boolean, or null to restore the template default). Invalid keys/values are reported and skipped. NOTE: these take effect on the published app only after the next publish (publish_app, or the user's Publish button). The iosInfoPlist keys only affect builds made before the first iOS publish; after the iOS app is published, edit the project file `static/__dev/native/ios-info.plist` directly with write_file/edit_file (see get_guides('ios-info-plist')). Likewise, after the first Android publish, edit `static/__dev/native/android-manifest.xml` directly for manifest changes (see get_guides('android-manifest')). `shareTarget` makes the native app appear in the iOS and Android share sheets (other apps can share photos/videos/files/text into it): pass { enabled: true, mimeTypes?, allowMultiple? } to register, { enabled: false } to remove; receiving the shared items still needs the handler in app code — read get_guides('share-target') first and ship both together. `nativeSystemBars` controls how the native app treats the status bar / Android navigation bar: mode 'inset' (default) keeps the app below the bars and paints the exposed strips `color` (default black — set it to the app's header color for a seamless look); mode 'edge-to-edge' runs the app under the bars, which REQUIRES the app to pad by var(--safe-area-inset-top/bottom) itself — read get_guides('native-system-bars') first and ship both changes together. Not superseded by the __dev/native files. `serverMemoryMb` sets the memory (MB) of the project's server Lambda, which runs every endpoint, queued task, scheduled job and SSR render (default 1024 MB; 2048 for the published app when SSR is on — the dev backend never bumps). EXPERT SETTING — NEVER change it on your own initiative or as a side effect of another request, only when the user explicitly asks to change the server memory AND understands the trade-off: too low and the backend stops working entirely (killed out-of-memory); Lambda CPU scales with memory, so a lower value also makes every request slower and — because compute is billed per GB-second of billed duration — can cost MORE, not less; a higher value costs more per millisecond. Allowed range 512–4096 MB, whole MB (if a size turns out not to be available for the app's server, the deploy fails and the error names this setting). It applies to the dev backend at the next backend deploy and to the published app at the next publish. Pass null to restore the default. Read get_guides('server-memory') before changing it. `analyticsMode` controls the built-in visitor analytics tracker every published app includes (the project's Analytics tab): 'storage' (default) keeps a 30-minute session id in the visitor's localStorage, which is device storage that needs consent under EU ePrivacy / UK PECR — an app with EU/UK visitors pairs it with a consent banner that calls window.flootAnalytics.setMode(); 'memory' keeps the id in memory only (nothing stored on the device, no consent needed, but a reload or new tab counts as a new session); 'off' sends no analytics at all. Only change it when the user asks about analytics, cookies, consent or privacy for their published app; it takes effect at the next publish. Read get_guides('analytics') for the consent-banner API before changing it.6 params
Update project settings (current values appear at the top of list_files). Keys: title (2-100 chars), description, iconUrl, splashUrl, mobileAppId, enableSSR (boolean), flootAiDisallowed (boolean — true opts the project out of @floot/ai), and iOS Info.plist purpose strings (NS…UsageDescription — set to a string, or null to remove) plus boolean Info.plist keys (UIViewControllerBasedStatusBarAppearance — set to a boolean, or null to restore the template default). Invalid keys/values are reported and skipped. NOTE: these take effect on the published app only after the next publish (publish_app, or the user's Publish button). The iosInfoPlist keys only affect builds made before the first iOS publish; after the iOS app is published, edit the project file `static/__dev/native/ios-info.plist` directly with write_file/edit_file (see get_guides('ios-info-plist')). Likewise, after the first Android publish, edit `static/__dev/native/android-manifest.xml` directly for manifest changes (see get_guides('android-manifest')). `shareTarget` makes the native app appear in the iOS and Android share sheets (other apps can share photos/videos/files/text into it): pass { enabled: true, mimeTypes?, allowMultiple? } to register, { enabled: false } to remove; receiving the shared items still needs the handler in app code — read get_guides('share-target') first and ship both together. `nativeSystemBars` controls how the native app treats the status bar / Android navigation bar: mode 'inset' (default) keeps the app below the bars and paints the exposed strips `color` (default black — set it to the app's header color for a seamless look); mode 'edge-to-edge' runs the app under the bars, which REQUIRES the app to pad by var(--safe-area-inset-top/bottom) itself — read get_guides('native-system-bars') first and ship both changes together. Not superseded by the __dev/native files. `serverMemoryMb` sets the memory (MB) of the project's server Lambda, which runs every endpoint, queued task, scheduled job and SSR render (default 1024 MB; 2048 for the published app when SSR is on — the dev backend never bumps). EXPERT SETTING — NEVER change it on your own initiative or as a side effect of another request, only when the user explicitly asks to change the server memory AND understands the trade-off: too low and the backend stops working entirely (killed out-of-memory); Lambda CPU scales with memory, so a lower value also makes every request slower and — because compute is billed per GB-second of billed duration — can cost MORE, not less; a higher value costs more per millisecond. Allowed range 512–4096 MB, whole MB (if a size turns out not to be available for the app's server, the deploy fails and the error names this setting). It applies to the dev backend at the next backend deploy and to the published app at the next publish. Pass null to restore the default. Read get_guides('server-memory') before changing it. `analyticsMode` controls the built-in visitor analytics tracker every published app includes (the project's Analytics tab): 'storage' (default) keeps a 30-minute session id in the visitor's localStorage, which is device storage that needs consent under EU ePrivacy / UK PECR — an app with EU/UK visitors pairs it with a consent banner that calls window.flootAnalytics.setMode(); 'memory' keeps the id in memory only (nothing stored on the device, no consent needed, but a reload or new tab counts as a new session); 'off' sends no analytics at all. Only change it when the user asks about analytics, cookies, consent or privacy for their published app; it takes effect at the next publish. Read get_guides('analytics') for the consent-banner API before changing it.
projectIdstringrequiredThe Floot project ID whose metadata should be updated.analyticsModestringoptionalBuilt-in visitor analytics mode for the published app. "storage" (default) keeps a session id in the visitor's localStorage; "memory" keeps it in memory only with no device storage; "off" disables analytics entirely. Leave unset to make no change.nativeSystemBarsobjectoptionalNative status bar / navigation bar handling for the native app. Pass {mode:"inset"|"edge-to-edge", color?, iconStyle?}; omit this field to leave the current configuration unchanged.serverMemoryMbstringoptionalMemory in MB (512-4096) allocated to the project's server Lambda, which runs every endpoint, queued task, scheduled job and SSR render. This is an expert setting — only change it on an explicit user request; leave unset to make no change, or pass null to restore the platform default.shareTargetobjectoptionalShare-sheet target configuration so the native app can receive photos, videos, files or text shared from other apps. Pass {enabled:true, mimeTypes?, allowMultiple?} to register it, or {enabled:false} to remove it; omit this field entirely to leave the current configuration unchanged.updatesobjectoptionalFlat project metadata fields to update, as a JSON object of key/value pairs (see the tool description for the full list of supported keys such as title, description, iconUrl, splashUrl, mobileAppId, enableSSR, flootAiDisallowed, and the iOS Info.plist keys). Only the keys included are changed; invalid keys or values are reported and skipped.flootmcp_upload_asset#Upload a binary asset (image, font, audio, …) to the project's hosted storage. This uploads bytes you actually hold — a file you generated, downloaded, or read yourself. Chat attachments don't qualify: the user's attachments never reach MCP servers (you see attached images through vision only; there is no file, id, or URL behind them you can read), so for those use request_user_upload instead and the user re-picks the file in a card that uploads from their browser. Three modes. ChatGPT conversation files — a generated image, a file ChatGPT itself holds: pass the file as the `file` parameter and the host attaches a download link itself; this server fetches the bytes directly, at full quality (nothing goes through your sandbox or through base64 in arguments; content_type and size_bytes are optional here). Never downscale or re-encode a generated image to fit the inline cap — pass it as `file` instead. Files up to 3 MB you hold yourself — pass content_base64 plus size_bytes (the decoded byte count) and the upload completes in this call, returning publicUrl. Larger files — pass size_bytes alone to get an uploadUrl; PUT the raw bytes to it with the same content_type and exact byte count (e.g. `curl -X PUT -H 'Content-Type: image/png' --data-binary @file.png '<uploadUrl>'`), then reference publicUrl. Some sandboxes (claude.ai Cowork, ChatGPT containers) block egress to S3: if the PUT fails in any way — connection failure, proxy error, or a response without an x-amz-request-id header — that block is permanent for the session, so switch paths instead of retrying or re-encoding smaller: the `file` parameter in ChatGPT for any file that exists in this conversation, content_base64 for files under 3 MB, request_user_upload for user-provided files, or a PUT from inside the project VM via run_code_in_vm (re-mint the URL first; it is short-lived). For AI imagery generated fresh, use generate_image. A single file can be at most 100 MB via the presigned mode (the inline content_base64 mode is capped at 3 MB).6 params
Upload a binary asset (image, font, audio, …) to the project's hosted storage. This uploads bytes you actually hold — a file you generated, downloaded, or read yourself. Chat attachments don't qualify: the user's attachments never reach MCP servers (you see attached images through vision only; there is no file, id, or URL behind them you can read), so for those use request_user_upload instead and the user re-picks the file in a card that uploads from their browser. Three modes. ChatGPT conversation files — a generated image, a file ChatGPT itself holds: pass the file as the `file` parameter and the host attaches a download link itself; this server fetches the bytes directly, at full quality (nothing goes through your sandbox or through base64 in arguments; content_type and size_bytes are optional here). Never downscale or re-encode a generated image to fit the inline cap — pass it as `file` instead. Files up to 3 MB you hold yourself — pass content_base64 plus size_bytes (the decoded byte count) and the upload completes in this call, returning publicUrl. Larger files — pass size_bytes alone to get an uploadUrl; PUT the raw bytes to it with the same content_type and exact byte count (e.g. `curl -X PUT -H 'Content-Type: image/png' --data-binary @file.png '<uploadUrl>'`), then reference publicUrl. Some sandboxes (claude.ai Cowork, ChatGPT containers) block egress to S3: if the PUT fails in any way — connection failure, proxy error, or a response without an x-amz-request-id header — that block is permanent for the session, so switch paths instead of retrying or re-encoding smaller: the `file` parameter in ChatGPT for any file that exists in this conversation, content_base64 for files under 3 MB, request_user_upload for user-provided files, or a PUT from inside the project VM via run_code_in_vm (re-mint the URL first; it is short-lived). For AI imagery generated fresh, use generate_image. A single file can be at most 100 MB via the presigned mode (the inline content_base64 mode is capped at 3 MB).
file_namestringrequiredDestination file name for the asset, including its extension, e.g. "logo.png". Must start with an alphanumeric character and contain only letters, digits, dots, underscores and hyphens.projectIdstringrequiredThe Floot project ID to upload the asset into.content_base64stringoptionalThe file's bytes, base64-encoded, for files up to 3 MB decoded. When set, the upload completes in this call and returns publicUrl.content_typestringoptionalMIME type of the file, e.g. "image/png". Required unless the file parameter (ChatGPT conversation files) is used, in which case it is only a hint.fileobjectoptionalChatGPT only: a file from this conversation (e.g. a generated image). The ChatGPT host fills download_url/file_id when you reference the file; the values are host-issued and cannot be constructed by hand — on clients without file-parameter support, leave this unset and use the other modes.size_bytesintegeroptionalExact byte count of the file, measured from the file itself. Required unless the file parameter is used. Must exactly match the decoded length for content_base64, or the number of bytes PUT to the presigned URL.flootmcp_view_annotation#View a screenshot annotation the user drew on the app preview (annotationId comes from get_current_context). Returns the annotated image — the user's drawings/text point at what they mean. Annotations expire after ~1 day.2 params
View a screenshot annotation the user drew on the app preview (annotationId comes from get_current_context). Returns the annotated image — the user's drawings/text point at what they mean. Annotations expire after ~1 day.
annotationIdstringrequiredThe annotation's ID, as reported by get_current_context when the user has a pending screenshot annotation.projectIdstringrequiredThe Floot project ID the annotation belongs to.flootmcp_write_file#Create or fully overwrite a file in a Floot project. Content is written literally. Paths must follow the item scheme (see read_file); invalid paths are rejected with the rule they broke. Pass expected_version (from list_files/read_file) to detect concurrent edits. Writing components/Name.module.css sets the css of components/Name — other properties of the item are preserved.4 params
Create or fully overwrite a file in a Floot project. Content is written literally. Paths must follow the item scheme (see read_file); invalid paths are rejected with the rule they broke. Pass expected_version (from list_files/read_file) to detect concurrent edits. Writing components/Name.module.css sets the css of components/Name — other properties of the item are preserved.
contentstringrequiredThe full file content to write, exactly as it should appear on disk. This is a full overwrite — Floot writes the content literally, replacing anything already at path.pathstringrequiredThe project-relative path to write, following Floot's item scheme (e.g. components/Name.tsx, components/Name.module.css, pages/name.tsx, endpoints/route_POST.ts, static/file.txt). Invalid paths are rejected with the rule they broke.projectIdstringrequiredThe Floot project id containing the file to write. Get this from list_projects.expected_versionintegeroptionalThe project's current version, from list_files or read_file, used to detect concurrent edits. If provided and the project has moved on since, the write is rejected instead of silently overwriting someone else's change.