---
title: "MCP setup"
description: "Connect Claude Code and other MCP clients to the quickforms MCP server."
---

> Documentation Index
> Fetch the complete documentation index at: https://docs.getquickforms.com/llms.txt
> Use this file to discover all available pages before exploring further.

# MCP setup

quickforms runs a streamable HTTP MCP server at `https://YOUR-QUICKFORMS-HOST/mcp`. It uses the same team API keys as the [REST API](https://docs.getquickforms.com/api/), with the same [API key abilities and team roles](https://docs.getquickforms.com/api/#key-abilities): read-only tools need the `read` ability, and anything that changes data needs `write` and an admin or owner role.

## Claude Code

```bash
claude mcp add --transport http quickforms https://YOUR-QUICKFORMS-HOST/mcp \
  --header "Authorization: Bearer YOUR_API_KEY"
```

## Other clients

Most clients that support remote MCP servers accept a config like this. Check your client's docs for the exact file and key names.

```json title="mcp.json"
{
  "mcpServers": {
    "quickforms": {
      "type": "http",
      "url": "https://YOUR-QUICKFORMS-HOST/mcp",
      "headers": {
        "Authorization": "Bearer YOUR_API_KEY"
      }
    }
  }
}
```

## Tools

The server is called `quickforms` (version `1.0.0`) and has 19 tools.

| Tool | Arguments | What it does |
| --- | --- | --- |
| `list-forms` | None | List the forms in your team, newest first, with endpoint URL, mode and submission count. |
| `get-form` | `form_id` | Get one form: schema, settings, endpoint URL, embed snippets and sandbox key. The webhook secret is returned by `create-form` and `rotate-webhook-secret` only. |
| `list-form-templates` | None | List the ready-made [templates](https://docs.getquickforms.com/creating-forms/#start-from-a-template) with their key, name, summary, category and field labels. |
| `generate-form` | `prompt`, `save` | Design a form with the [AI form builder](https://docs.getquickforms.com/creating-forms/#describe-it-to-the-ai-form-builder) from a plain-English `prompt`. Returns a draft (fields, description, smart rules, success message, autoresponder) to review and pass to `create-form`, or creates the form straight away with `save: true`. |
| `create-form` | `template`, `name`, `description`, `mode`, `schema`, `draft`, `turnstile_secret`, `stripe_secret`, `webhook_url`, `settings` | Create a form from a name, schema and optional description, mode, webhook URL and settings. Pass `template` with a key from `list-form-templates` to start from a template: its fields and settings are used, anything else you pass overrides them, and `name` and `schema` become optional. Pass `draft: true` to create it unpublished. |
| `update-form` | `form_id`, `name`, `description`, `mode`, `is_active`, `schema`, `draft`, `turnstile_secret`, `stripe_secret`, `webhook_url`, `settings` | Update a form, including its description. Only the keys you pass change. Passing schema replaces the whole field list. Pass `draft: true` to keep the changes as a draft instead of making them live. |
| `publish-form` | `form_id`, `discard` | Publish a form: make its saved draft live, or put a never-published form live. Pass `discard: true` to throw the draft away instead and keep the live version as it is. |
| `rotate-webhook-secret` | `form_id` | Replace a form's webhook signing secret and return the form with the new one. The old secret stops working straight away. |
| `rotate-sandbox-key` | `form_id` | Replace a form's sandbox key and return the form with the new one. The old key stops working straight away. |
| `send-test-submission` | `form_id`, `data` | Send a sandbox test submission. Validated and stored, every email and webhook simulated. Runs against the form's draft, if it has one. |
| `create-form-links` | `form_id`, `links` | Create [personal links](https://docs.getquickforms.com/personal-links/) to a form's hosted page, 1 to 500 at once, each with optional `label`, `email`, `prefill`, `metadata`, `max_submissions` (default 1, `null` for unlimited) and `expires_at`. |
| `list-form-links` | `form_id`, `status`, `email`, `revoke_link_id` | List up to 200 of a form's newest personal links with their status, filtered by `status` or `email`. Pass `revoke_link_id` to revoke that link instead. |
| `list-submissions` | `form_id`, `sandbox`, `spam`, `link_id`, `confirmation`, `failed_rules`, `search`, `since`, `until`, `fields`, `page`, `per_page` | List submissions with sandbox, spam, failed_rules, confirmation (`pending`, `confirmed` or `expired`), `link_id`, search, since/until and exact field filters, paginated. |
| `get-submission` | `submission_id` | Get one submission with every delivery and attempt. Sandbox deliveries include the payload that would have been sent. |
| `confirm-submission` | `submission_id`, `action` | [Double opt-in](https://docs.getquickforms.com/double-opt-in/): `action` is `confirm` or `resend`. `confirm` confirms a pending submission and releases its held emails and webhooks. `resend` sends a new confirmation email with a fresh link, and also revives an expired submission. |
| `review-submission` | `submission_id`, `spam` | Mark a submission as spam or not spam. Marking a flagged submission as not spam releases its held emails and webhooks. Marking a delivered one as spam only labels it. |
| `redeliver` | `delivery_id` | Queue a fresh attempt for a live email or webhook delivery. Sandbox deliveries, and ones whose payload has been cleared by retention, can't be redelivered. |
| `list-partial-submissions` | `form_id`, `status`, `sandbox`, `days` | The completion funnel for a form and its 50 most recent [partial submissions](https://docs.getquickforms.com/partial-submissions/). Filter by `status` (`in_progress`, `abandoned` or `completed`). |
| `manage-destination` | `action`, `form_id`, `destination_id`, `type`, `name`, `enabled`, `config`, `mapping`, `conditions`, `data` | List, create, update, delete and preview a form's [destinations](https://docs.getquickforms.com/destinations/), or list the destination types. |
| `get-form-analytics` | `form_id`, `days` | Anonymous [analytics](https://docs.getquickforms.com/analytics/) for a form: views, visitors, starts, live submissions, conversion rate, a daily series and the top UTM sources, campaigns, referrer domains and ad click IDs. |

> **Note**
>
> A typical session: ask your agent to create a form (from a description, a template or its own schema), send a test submission and show you the webhook that would have been sent.
>
> `send-test-submission` is always sandbox, so it is safe to let an agent run it against a live form.

## Drafts

Pass `draft: true` to `create-form` or `update-form` to keep changes unpublished. Live submissions keep using the published version, while `send-test-submission` runs against the draft. When the draft is right, call `publish-form`, or `publish-form` with `discard: true` to throw it away. See [drafts and publishing](https://docs.getquickforms.com/drafts-and-publishing/).

## Settings

`settings` on `create-form` and `update-form` accepts every key in the REST API's [form settings](https://docs.getquickforms.com/api/#form-settings) table, including routing rules, reply-to, Altcha, geo filters, disposable email blocking, payments and partial submissions.

## Hosted forms

`create-form` and `update-form` accept `settings.hosted` (`enabled`, `layout`, `appearance`, `accent`, `font`, `radius`, `background`, `title`, `intro`, `submit_label`, `logo_url`, `favicon_url`, `show_branding`) to change the [hosted form page](https://docs.getquickforms.com/hosted-forms/). Only the keys you pass change. `get-form` returns the settings and the page's URL.

## Personal links

`create-form-links` takes `form_id` and a `links` list. It returns each link with its `url`, ready to send. `list-form-links` shows which links are `open`, `completed`, `expired` or `revoked`, and revokes one with `revoke_link_id`. `create-form` and `update-form` accept `settings.require_link` to only accept submissions through links. Submissions made through a link have `link_id` and the link's details in `meta.link`. Pass `link_id` to `list-submissions` to see a link's submissions. See [personal links](https://docs.getquickforms.com/personal-links/).

## Spam

Submissions get two separate checks from the [spam filter](https://docs.getquickforms.com/spam-filter/): the base spam check sets `spam: true`, and breaking the form's smart rules sets `failed_rules: true`. Either one holds the deliveries. Pass `spam` or `failed_rules` (`true` or `false`) to `list-submissions` to filter by either check, and use `review-submission` to release a false positive. Marking a submission as not spam clears both flags. `create-form` and `update-form` accept `description` and `settings.spam` (`enabled`, `threshold`, `rules`).

## Webhook events

`create-form` and `update-form` accept `settings.webhook.events`, a list of the [webhook events](https://docs.getquickforms.com/webhooks/#events) to send: `submission.created`, `submission.held`, `submission.deleted`, `submission.confirmation_expired` and `payment.needs_attention`. The default is `submission.created` only.

## Double opt-in

`create-form` and `update-form` accept `settings.confirmation` (`enabled`, `email_field`, `subject`, `body`, `button_label`, `expires_hours`, `on_expiry`, `redirect_url`, `confirmed_message`). On those forms a submission only sends a confirmation email until the person clicks its link, and submissions have `confirmation_status` (`null`, `pending`, `confirmed` or `expired`) and `confirmed_at`. Pass `confirmation` to `list-submissions` to filter by status, and use `confirm-submission` to confirm on the person's behalf or resend the email. See [double opt-in](https://docs.getquickforms.com/double-opt-in/).

## Spam protection

`create-form` and `update-form` accept `settings.honeypot_field` and `settings.honeypot_fields`, a list of up to 5 extra [honeypots](https://docs.getquickforms.com/spam-protection/#honeypots) with realistic names such as `website` or `fax`. Passing `honeypot_fields` replaces the whole list, and a honeypot named like one of the form's fields is rejected.

`get-form` returns `settings.turnstile` (`enabled`, `site_key`) and `turnstile_secret_set`, but never the [Turnstile](https://docs.getquickforms.com/spam-protection/#cloudflare-turnstile) secret key. Set the secret key with `turnstile_secret` on `create-form` or `update-form`. It is write-only.

## Creating forms

`generate-form` is limited to 30 generated forms an hour per user by default (`QUICKFORMS_FORM_BUILDER_PER_HOUR`). Past that it returns an error saying to try again later. It needs the AI form builder to be configured on the server (see [configuration](https://docs.getquickforms.com/creating-forms/#configuration)). See [creating forms](https://docs.getquickforms.com/creating-forms/) for the template list and examples.

## Payments

`create-form` and `update-form` accept `stripe_secret`, your Stripe secret key (`sk_` or a restricted `rk_` key). It is write-only: `get-form` returns `stripe_secret_set` instead. Switch payments on with `settings.payment` (`enabled`, `publishable_key`, `currency`, `amount` in the smallest currency unit, or `amount_field` plus `prices`, and `description`). See [payments](https://docs.getquickforms.com/payments/).

## Partial submissions

With `settings.partials` on (`enabled`, `abandon_after_minutes`, `retention_days`), the embed and hosted page save progress while people fill the form in. `list-partial-submissions` returns a `funnel` (`started`, `completed`, `abandoned`, `in_progress`, `completion_rate` and `drop_off`, the fields where people stop) over the last `days` (1 to 365, default 30), and `data`, the 50 most recently active partial submissions. Pass `sandbox: true` for sandbox ones. See [partial submissions](https://docs.getquickforms.com/partial-submissions/).

## Destinations

`manage-destination` takes an `action`:

| Action | Needs | What it does |
| --- | --- | --- |
| `types` | Nothing | The destination types with their config fields and mapping targets. |
| `list` | `form_id` | The form's destinations, oldest first. |
| `create` | `form_id`, `type`, `name`, `config` | Add a destination. Optional `enabled`, `mapping` and `conditions`. |
| `update` | `destination_id` | Change `name`, `enabled`, `config`, `mapping` or `conditions`. Only the keys you pass change. |
| `delete` | `destination_id` | Delete the destination. |
| `preview` | `destination_id` | A dry run showing exactly what would be sent, with secrets redacted. Pass `data` with sample field values. Without it, it uses the latest submission, or made-up values when there are none. Nothing is sent. |

Secrets in `config` are write-only and come back masked. `mapping` maps each target key to a template with `{{field}}` placeholders, plus `{{_form_name}}`, `{{_submission_id}}`, `{{_submitted_at}}` and `{{_summary}}`. `conditions` is a list of `{field, operator, value}`, all of which must match, with `operator` one of `equals`, `not_equals`, `contains`, `is_set` or `is_empty`. Deliveries are retried and logged like webhooks, and simulated in sandbox. See [destinations](https://docs.getquickforms.com/destinations/).

## Analytics

`get-form-analytics` takes `form_id` and `days` (1 to 365, default 30). It returns `views`, `visitors`, `starts`, `submissions`, `conversion_rate`, a daily `series`, and the top `sources`, `campaigns`, `referrers` and `click_ids` behind live submissions. The same data as [`GET /api/v1/forms/{form}/analytics`](https://docs.getquickforms.com/api/#get-apiv1formsformanalytics). See [analytics](https://docs.getquickforms.com/analytics/) and [tracking](https://docs.getquickforms.com/tracking/).

Source: https://docs.getquickforms.com/mcp/index.mdx
