Reference
MCP endpoint, authentication, resources, and tools.
For setup instructions, see Connect.
Endpoint
| URL | https://api.reforma.ai/mcp |
| Transport | Streamable HTTP, stateless JSON-RPC |
| Protocol | MCP specification |
Authentication
Reforma MCP uses OAuth 2.1 with PKCE S256.
To revoke a client, open Profile → Security and login → Connected apps in Reforma.
Project lifecycle
Most tools operate on a project sandbox.
A typical session is:
- Call
list_projects. - Call
open_projectwith a projectidfrom a workspace whereeditableistrue. - Use that
project_idfor subsequent project tools.
open_project always provisions or reuses the project's dev sandbox. If editable is false, the sandbox is not started.
The Reforma editor and MCP share the same sandbox and worktree.
If the sandbox has been idle for one hour, it is stopped automatically. Call open_project again to resume.
Resources
| URI | Description |
|---|---|
reforma://fonts | Font rules and available font configuration. Fonts belong under app/fonts; do not use next/font, CDN font links, or font @imports elsewhere. |
reforma://tokens | Project design tokens. |
reforma://project | Project-level implementation rules. After open_project, prefer AGENTS.md from the worktree when it exists. |
Tools
Unless noted otherwise, project tools require a positive integer project_id, an editable workspace, and an active sandbox created by open_project.
create_upload and complete_upload require a project_id, but do not require the sandbox to be running.
The worktree lives in Reforma's cloud sandbox.
Identity and projects
get_me
Returns the signed-in Reforma user.
Arguments: none.
{
"id": 1,
"email": "[email protected]",
"name": "You"
}list_projects
Returns projects the signed-in user belongs to, grouped by workspace. Connecting and listing are not plan-gated.
Each workspace includes editable. It is true when the workspace is on a Pro plan and the user can edit it. Call open_project only when editable is true.
Unpaid workspaces also include billingUrl (https://app.reforma.ai/workspace/{id}/billing). Send the user there to upgrade.
Arguments: none.
{
"workspaces": [
{
"id": 1,
"name": "Acme",
"status": "active",
"editable": true,
"projects": [
{
"id": 10,
"name": "Site",
"status": "active",
"workspaceId": 1
}
]
}
]
}Pass a project id from an editable workspace to open_project.
open_project
Provisions or reuses the project's dev sandbox and returns its preview URL. The workspace must be editable. Otherwise the sandbox is not started.
If the workspace is on Free, the error includes https://app.reforma.ai/workspace/{id}/billing. Send the user there to upgrade. Do not retry.
| Argument | Description |
|---|---|
project_id | Required project ID. |
{
"id": "…",
"previewUrl": "https://…",
"status": "active"
}Files
File paths are relative to the project sandbox unless an absolute project path is supplied.
read
Reads UTF-8 text or PDF files.
Text is returned in windows of up to 200 lines by default. PDFs use pages instead of lines. The total field indicates whether more content remains.
| Argument | Description |
|---|---|
path | File to read. |
limit | Optional. Maximum lines for text or pages for PDF. Default: 200. |
offset | Optional. 1-based starting line or page. |
write
Creates or overwrites a file.
| Argument | Description |
|---|---|
path | Destination path. |
content | Complete file contents. |
edit
Replaces text in an existing file.
Read the file before editing it. Multiple replacements for the same file can be sent in one call.
| Argument | Description |
|---|---|
path | Existing file. |
edits | Between 1 and 32 { search, replace } operations. |
replace_all | Optional. Replace every occurrence of each search value. |
list_directory
Lists files and directories. sizeBytes is returned for files only.
| Argument | Description |
|---|---|
path | Optional. Defaults to the project root. |
recursive | Optional. Default: false. |
only_files | Optional. Default: false. |
glob
Finds paths matching one or more glob patterns. Results are ordered newest first.
| Argument | Description |
|---|---|
pattern | Required array of glob patterns, OR'd together. Example: ["**/*.ts", "app/**/*.tsx"]. |
path | Optional directory to search. |
recursive | Optional. Default: true. |
only_files | Optional. Default: true. |
grep
Runs ripgrep against the project worktree.
| Argument | Description |
|---|---|
pattern | Required regular expression. Alternation is supported. |
path | Optional file or directory. |
glob | Optional path filters, for example ["*.ts"]. |
type | Optional ripgrep file type, for example js. |
output_mode | Optional: files_with_matches, content, or count. |
case_insensitive | Optional. |
multiline | Optional. |
create_directory
Creates a directory.
| Argument | Description |
|---|---|
path | Directory to create. |
move_file
Moves or renames a file or directory.
| Argument | Description |
|---|---|
from_path | Existing path. |
to_path | Destination path. |
overwrite | Optional. |
remove_file
Removes one or more paths.
| Argument | Description |
|---|---|
paths | Required array of paths. |
Shell and dependencies
bash
Runs a command in the project sandbox.
Each invocation has its own working directory unless cwd is provided. Quote paths containing spaces and use shell operators such as && when commands must run sequentially.
Foreground commands default to a 120-second timeout and may run for up to 600 seconds.
Background commands return:
{
"id": "…",
"pid": 123,
"log": "…"
}Use the returned id to poll or stop the process. Do not use the OS pid.
| Argument | Description |
|---|---|
command | Command to run. Required unless polling or killing by id. |
description | Short human-readable label. Required with command. |
background | Optional. Run asynchronously and return a process registry id. |
id | Process registry ID used for polling or stopping a background command. |
kill | Optional. Stop the process identified by id. |
timeout | Optional timeout in milliseconds. |
cwd | Optional working directory. |
tailLines | Optional number of trailing stdout/stderr lines to retain. |
A successful stop reports status: killed on the kill call.
install_deps
Installs project dependencies using Bun and restarts the managed development server.
Use this tool instead of running bun install through bash.
| Argument | Description |
|---|---|
packages | Optional package names to add. Omit to install or update existing dependencies. |
dev | Optional. Add packages as devDependencies. |
force | Optional. Uses bun --force. |
resetLockfile | Optional. Uses bun update --no-cache. Ignored when packages is provided. |
reason | Optional logging context. |
The response includes the executed command, Bun output, and whether the development server was restarted.
read_lints
Formats and validates changed files.
The tool runs:
biome check --write
tsc --noEmitBecause Biome runs with --write, this tool may modify files.
| Argument | Description |
|---|---|
paths | Optional files or directories to check. Omit to run against the whole workspace. |
Prefer passing only the files or directories changed during the task.
Development server
The project's Next.js development server is managed by Reforma.
Do not start or stop it using bash.
dev_server_status
Returns the current development server state and recent logs.
| Argument | Description |
|---|---|
tailLines | Optional number of recent log lines. |
dev_server_restart
Restarts the managed development server.
| Argument | Description |
|---|---|
reason | Optional logging context. |
Assets
There are two ways to add an asset, depending on where the source file lives.
Use import_asset when the source is already reachable by Reforma:
- an
http://orhttps://URL; - a file under
public/; - a scratch file under
/tmp/reforma.
Use create_upload → upload the bytes → complete_upload when the file exists on the client machine, such as a generated image, screenshot, or video.
Do not send file bytes through JSON-RPC or data URLs.
import_asset
Imports an existing asset into Reforma.
| Argument | Description |
|---|---|
source | HTTP(S) URL, public/ path, or absolute /tmp/reforma scratch path. |
destination | Optional: cdn or filesystem. Default for images: cdn. |
path | Required for explicit filesystem destinations. Fonts belong under app/fonts/assets/*.woff2. |
filename | Optional basename when path is omitted or points to a directory. |
Scratch files can only be imported to the CDN.
create_upload
Creates a presigned PUT URL for a client-local file.
Maximum file size: 50 MB.
The PUT URL expires after 15 minutes.
| Argument | Description |
|---|---|
project_id | Required project ID. |
filename | Basename including extension, for example hero.png. |
content_type | MIME type, for example image/png. |
size | Exact file size in bytes. |
{
"asset_id": "…",
"put_url": "https://…",
"headers": {
"Content-Type": "image/png"
},
"expires_in": 900
}Upload the file bytes directly to put_url:
curl -T ./hero.png \
-H "Content-Type: image/png" \
"$PUT_URL"complete_upload
Confirms that the uploaded object exists and adds it to Reforma's CDN.
Call this only after the PUT request succeeds.
| Argument | Description |
|---|---|
project_id | Required project ID. |
asset_id | asset_id returned by create_upload. |
{
"ok": true,
"destination": "cdn",
"id": "…",
"url": "https://cdn…/…",
"filename": "hero.png",
"mediaType": "image/png",
"size": 12
}If the object has not been uploaded yet, the call fails instead of creating an empty asset.
Versions and publishing
commit
Creates a version checkpoint.
| Argument | Description |
|---|---|
message | Required short imperative commit message. |
Before creating the checkpoint, Reforma runs lint validation.
If validation fails, no version is created and the response returns reason=lint with diagnostics.
If there are no uncheckpointed changes, the call is a no-op with reason=clean. Autosave may already have created the latest checkpoint.
Use list_versions to inspect the current state.
list_versions
Returns the project's current, draft, and published versions.
This is the same version state shown in the Reforma version panel.
No arguments other than project_id.
publish
Publishes the project using the same pipeline as the Reforma Publish button.
The call waits until deployment succeeds or fails.
On success, it returns the live URL. On failure, it returns deployment logs.
No arguments other than project_id.