Go to app

MCP server

The Model Context Protocol (MCP) server lets AI agents read and edit your forms, send requests and read the answers, with one tool per action.


MCP is an open standard that lets AI tools call outside services. Formstep hosts an MCP server that any client with remote MCP support can connect to, such as Claude, ChatGPT and Cursor. To connect one step by step, see Connect an AI agent.

Connection

text
URL:  https://api.formstep.io/api/mcp   (POST, streamable HTTP)
Auth: Bearer <token>

Two kinds of bearer token work:

  • An API token (fs_...), for your own scripts and headless agents.

  • An OAuth access token (fso_...), issued by the OAuth flow. Most clients get one for you when you sign in.

Both reach exactly one workspace. A tool call that names another workspace, or a form in one, fails with FORBIDDEN. OAuth tokens also carry scopes: mcp:read reaches the tools that only read, and mcp:write reaches every tool. tools/list shows only the tools a token may call, and any other call answers 403 with insufficient_scope. API tokens have no scopes and reach every tool.

Tool calls share the limit of 120 a minute per token with the REST API. Only tools/call counts; initialize, tools/list, prompts/* and resources/* are free. Over the limit, the call still returns HTTP 200, with a failed tool result carrying RATE_LIMITED and retryAfterMs. Poll on a timer, never in a loop.

Tools

The server describes its own tools on tools/list, each with a full schema, and clients that load schemas on demand fetch one when a task needs it. The tools cover forms and the editor, themes, settings, share links, translations, folders, webhooks, analytics, submissions and requests. Longer guides, such as every question type or how logic rules work, are served as skill:// resources and through the load_skill tool, so an agent reads them when it needs them.

Requests

An agent sends a request the same way code does: fields_list, then request_create, with the same parameters as the REST API. Create requests from code covers the parameters and what is different over MCP, and Inline forms covers building the form in the same call.

Callbacks or polling

With a callbackUrl, Formstep POSTs once when the request ends, signed with the workspace's request signing secret; see Request callbacks. That secret is shown only on the OAuth and API Keys page, and never returned over MCP or the API. An agent that runs on its own, with nobody to set up a receiver, therefore cannot verify a callback. It should leave out callbackUrl and poll request_get every few minutes until status leaves pending, then read answers and outcome. expiresAt bounds how long that is worth doing.

Tools that ask first

Every tool carries the MCP hints readOnlyHint, destructiveHint and openWorldHint. These are marked destructive, because undoing them takes another call or is not possible: form_delete, form_unpublish, workspaceFolder_delete, editor_deleteElement, translationLanguage_delete and request_cancel. So are the tools that send something outside the workspace, such as request_create, and the tools that replace a stored value, such as form_publish, formTheme_set and editor_updateElement. Most clients ask before running them, but the prompt is the client's choice, so check its approval settings if you need a hard stop.

Limitations

A tool call cannot carry a file. Images are set by URL: covers, logos and image blocks take an http(s):// or data:image URL. A per-request document is the exception: document_create returns an upload URL that a client with HTTP access can PUT the file to, as in Documents for one recipient. To turn a PDF or a screenshot into a form, use the built-in AI chat.

Connecting with an API token

Most clients sign in with OAuth: add the URL with no header and follow Connect an AI agent, which also has the setup for Cursor. A client that cannot open a browser, such as a script, a CI job or a headless agent, sends an API token as a header instead. Claude Code, from the command line:

bash
claude mcp add --transport http formstep https://api.formstep.io/api/mcp \
  --header "Authorization: Bearer fs_YOUR_TOKEN"

Or in a project's .mcp.json. Other clients take the same URL and header; see their documentation for where.

.mcp.json
json
{
  "mcpServers": {
    "formstep": {
      "type": "http",
      "url": "https://api.formstep.io/api/mcp",
      "headers": {
        "Authorization": "Bearer fs_YOUR_TOKEN"
      }
    }
  }
}

Using OAuth instead of API tokens

An app that connects on behalf of a user should use OAuth instead of asking for a pasted token. Formstep is an OAuth 2.1 authorization server with mandatory PKCE (S256) and opaque tokens: no JWTs and no implicit grant. Claude, Claude Code and other clients discover it all from the MCP endpoint, so the URL with no header is enough: the 401 points at /.well-known/oauth-protected-resource, and the client takes it from there.

The flow, for a client you write yourself:

  1. GET /.well-known/oauth-protected-resource, then GET /.well-known/oauth-authorization-server for the endpoint URLs, scopes and supported auth methods.

  2. POST /oauth/register with your redirect_uris (dynamic client registration, no credentials needed). You get a client_id, plus a client_secret if you asked for anything other than token_endpoint_auth_method: "none". Redirect URIs must be HTTPS, or HTTP on localhost. Registration is capped at 20 an hour per IP.

  3. Send the user to /oauth/authorize with response_type=code, your client_id, the registered redirect_uri, scope=mcp:read mcp:write offline_access, state, and a code_challenge with code_challenge_method=S256. They sign in, pick one workspace, and authorize.

  4. Exchange the code at POST /oauth/token with grant_type=authorization_code and your code_verifier, within 60 seconds. A code works once.

  5. Call the MCP endpoint with Authorization: Bearer fso_.... Access tokens last 1 hour. Refresh tokens last 30 days and rotate on every use; reusing a spent refresh token revokes the whole chain, so always store the newest one.

POST /oauth/revoke (RFC 7009) revokes an access or refresh token.

Connected apps

Every OAuth connection is listed under Connected apps on the OAuth and API Keys page, with when it was connected and last used. Connections are personal: only the user who authorized one sees it, and workspace admins cannot see or revoke another member's. Disconnecting revokes every token the app holds for that workspace at once. A user who leaves or is removed from the workspace loses all their connections to it.

For what an agent can do with it, see the MCP server overview.