# Connect AI agents (MCP)

Volly exposes a [Model Context Protocol](https://modelcontextprotocol.io) (MCP)
server, so AI agents like Claude can create, deploy, and manage your Volly apps
directly — no browser uploads. Build a tool with Claude, then say "publish this
to Volly" and it happens in the same conversation.

The server lives at:

```text
https://app.volly.so/mcp
```

It uses Streamable HTTP and signs you in with OAuth — there are **no API keys
to create or paste**. When a client connects for the first time, it opens your
browser to sign in to Volly and approve access. The agent then acts as you: it
can only see and change what your Volly account can, and the same workspace
roles and app visibility rules apply.

## Claude.ai

1. Open **Settings → Connectors**.
2. Choose **Add custom connector** and enter `https://app.volly.so/mcp`.
3. A browser window opens to sign in to Volly and approve access. Approve, and
   you're connected.

Volly's tools are then available in any chat — ask Claude to list your apps or
publish what it just built.

## Claude Code

```bash
claude mcp add --transport http volly https://app.volly.so/mcp
```

Then run `/mcp` inside Claude Code to complete the sign-in flow in your
browser.

## Cursor and other MCP clients

Any client that supports remote MCP servers with OAuth works. For Cursor, add
this to your `mcp.json`:

```json
{
  "mcpServers": {
    "volly": {
      "url": "https://app.volly.so/mcp"
    }
  }
}
```

:::note
You must have finished Volly onboarding (created or joined a workspace) before
the tools will work — otherwise every call returns a "finish onboarding"
error.
:::

## What agents can do

| Tool                | What it does                                                      |
| ------------------- | ----------------------------------------------------------------- |
| `list_apps`         | List the apps you can see in your workspace                       |
| `get_app`           | Fetch one app's details                                           |
| `create_app`        | Create a new app (name, slug, visibility)                         |
| `update_app`        | Edit an app's name, visibility, or README                         |
| `delete_app`        | Delete an app                                                     |
| `list_deployments`  | List an app's deployment history, newest first                    |
| `list_app_files`    | List the files in an app's current deployment                     |
| `get_app_file`      | Read a deployed file (text inline, binary via a download link)    |
| `request_upload`    | Get a short-lived URL to upload a bundle to                       |
| `deploy_app`        | Publish an uploaded bundle — live, or as a private draft          |
| `deploy_app_inline` | Deploy small files passed inline (for agents that can't upload)   |
| `publish_draft`     | Make an app's pending draft build live                            |
| `discard_draft`     | Drop an app's pending draft without publishing it                 |
| `list_resources`    | See the [data resources](https://volly.so/docs/external-resources) an app can use |
| `list_comments`     | Read the comments viewers left on an app                          |

Access is scoped to two permissions you approve at connect time: **read your
apps** (`apps:read`) and **create and update apps** (`apps:write`).

## How a deploy works

When you ask an agent to publish something, it runs the same flow you'd do in
the browser:

1. `create_app` — registers the app in your workspace (first deploy only).
2. `request_upload` — Volly returns a short-lived upload URL (valid for 15
   minutes).
3. The agent uploads your `.zip` bundle, single `.html` file, or single
   `.jsx`/`.tsx` React component to that URL.
4. `deploy_app` — Volly validates the bundle and publishes it, returning the
   live URL.

Bundles follow the same rules as browser uploads — see
[Publish an app](https://volly.so/docs/publishing-apps) for what a bundle needs and the size
limits. `deploy_app_inline` exists only for web-based agents that can't make
their own HTTP uploads; everything else should use the upload flow.

Ask the agent to "deploy it as a draft" and it passes the `draft` option
instead — the build lands on a private preview URL and the live app is
untouched until you (or the agent) publish it. See
[Test updates with drafts](https://volly.so/docs/drafts).

## Updating an existing app

Agents don't need the original source files to change an app that's already
live. `list_app_files` shows everything in the current deployment — paths,
sizes, and a content hash per file, so an agent can tell what changed —
and `get_app_file` returns a file's contents: small text files come back
directly, larger or binary files as a short-lived download link. The agent
edits what it fetched and redeploys; every deploy fully replaces the previous
build at the same URL.

So "fix the typo on my dashboard's homepage" works in one conversation: the
agent reads the deployed `index.html`, makes the edit, and publishes it back.

## Troubleshooting

### Claude.ai: make uploads faster and cheaper

By default, Claude.ai limits which websites Claude is allowed to reach while
it works. Volly's upload location isn't on that list, so when you ask Claude
to publish an app it can't hand the file over directly. Instead it copies the
whole file into your conversation to send it — which is slower and uses up
noticeably more of your AI usage, especially for larger apps.

You can let Claude send files to Volly directly, which makes publishing faster
and uses far fewer tokens. It's a one-time change:

1. In Claude.ai, open **Settings → Capabilities**
   ([open it here](https://claude.ai/settings/capabilities)).
2. Find **Allow network egress**, and under **Domain allowlist** either:
   - add `*.r2.cloudflarestorage.com` to the allowed domains, or
   - switch the setting to **All domains**.

That's it — the next time you publish, uploads take the fast path
automatically.

:::note
This only applies to Claude.ai in the browser. Claude Code and other
desktop tools already upload directly, so there's nothing to change.
:::

## Disconnecting

Remove the connector from your MCP client (for example, delete it under
**Settings → Connectors** in Claude.ai) and the client discards its access.