
Your agent needs to work with Typeform. It needs to pull NPS out of last quarter's survey, push respondents into a contact list, and fire an automation when someone marks themselves as churn risk. Typeform ships a hosted MCP server and three REST APIs. Most tool comparisons in this series describe an MCP server that covers a slice of a bigger API. Typeform inverts that: each path owns capabilities the other cannot reach, and picking wrong means discovering a hard wall halfway through the build.
The two paths were built at different times for different consumers, and it shows in what each one can touch. Establish the objects before comparing them.
Typeform hosts the server itself at https://api.typeform.com/mcp. It exposes 63 tools across five domains: accounts-* and workspaces-* for resolving where you are, forms-* for building and publishing, insights-* for response analytics, automations-* for workflow construction, and contacts-* for the contacts database. A submit_feedback tool rounds out the set.
Transport is streamable HTTP only. There is no SSE endpoint, and clients configured for SSE fail on connect rather than degrading. Authorization is OAuth 2.0, prompted on first connect. Typeform's own help-center changelog announced the server as beta, and the developer docs carry no GA badge, so treat the contract as one that can still move.
There is no single "Typeform API." There are three, and agents need to reason about them separately. The Create API covers forms, workspaces, themes, images, videos, translations, and custom messages. The Responses API covers response retrieval, advanced filtered search, response deletion, and file, audio, and video downloads. The Webhooks API covers form-level webhook registration and delivery history.
Auth is OAuth 2.0 Authorization Code with granular scopes such as forms:read, responses:read, and webhooks:write, or a personal access token for single-account use. Reference material lives on the Typeform developer platform.
Four dimensions decide this: what the agent can reach, what auth model you inherit, what you own operationally, and which scenario you are actually building for.
The overlap is narrower than the marketing on either side suggests. Form creation and publishing exist on both. Almost everything else lives on exactly one path.
Contacts, Automations, and Insights have no REST equivalent. They do not appear in Typeform's OAuth scope table for the REST APIs, they have no reference section in the developer portal, and Typeform's own "not yet supported" notes route MCP gaps to the Create, Responses, and Webhooks APIs, never to a contacts or automations endpoint.
That has a concrete consequence. If your agent's job is "read the exit survey, segment the detractors into a contact list, and trigger a win-back email automation," there is no REST fallback. MCP is the integration.
The reverse holds for data volume and presentation. insights-public_list returns row-level data for a single field at a time, so anything resembling an export, a warehouse sync, or a right-to-be-forgotten deletion runs through the Responses API.
Styling is the other gap worth planning around. An agent can build a form's entire structure over MCP and still hand the user something wearing the default theme, because themes, images, and brand kits are Create API territory. For a customer-facing form builder, that is a visible defect, not a footnote.
Auth is where the two paths diverge most sharply, and where the choice becomes irreversible for certain agent shapes.
Typeform MCP supports OAuth 2.0 exclusively. Personal access tokens are explicitly not supported for MCP connections. There is no service-account shortcut and no client-credentials path.
Worse for least privilege: users cannot currently customize the scopes they grant. Connecting to the MCP server means granting every scope the server accepts, including contacts:write and automations:write, even if your agent only reads NPS. Your scoping has to happen above the token, at the tool layer.
The authorization server does support dynamic client registration at POST https://api.typeform.com/oauth/register, PKCE with S256, and public clients with token_endpoint_auth_method: none. Ask for offline_access if the agent has to act after the first access token expires; the REST OAuth apps use offline for the same thing, and mixing them up is a quiet source of missing refresh tokens.
One requirement catches teams late. Typeform's authorization server rejects any redirect URI whose domain is not on its allowlist, so dynamic client registration fails until Typeform adds your domain.
Localhost and 127.0.0.1 work for development, and the major AI clients are pre-approved, which is why the server feels frictionless in Claude or ChatGPT and then blocks the first deploy of your own product. Building a Typeform connector into a multi-tenant B2B product means submitting a connector request and waiting.
The REST side is conventional. You register an OAuth app, request only the scopes you need, and users see exactly that on the consent screen. Personal access tokens cover single-account and internal automation.
That matters most for background agents. A nightly job that exports yesterday's responses has no user to click a consent screen, and MCP has no answer for it. REST does.
Typeform accounts sit in three regions with three MCP endpoints: the default at api.typeform.com, EU data center 1 at api.eu.typeform.com, and EU data center 2 at api.typeform.eu. The two EU endpoints are not interchangeable.
api.eu.typeform.com is an EU resource served by the main authorization server. api.typeform.eu is a separate stack with its own issuer, endpoints, and signing keys, and an access token issued by one is invalid at the other. accounts-list_accounts returns a region per account. Resolve it once at authorization, store it alongside the token, and route on it. Probing endpoints and falling back on failure reads to your customer as an outage.
Managed hosting removes some work and adds some. The useful question is what breaks at 2am and who is on the hook for it.
Several MCP tools exist to be called before others, and skipping them means guessing. accounts-list_accounts resolves the account_id nearly every other tool needs. forms-public_get_capabilities returns the field types and logic operators the editing tools accept. insights-public_discover returns the queryable fields and measures for a given form.
Form editing is a four-call chain: capabilities, then forms-public_validate_patch which returns a validation_token, then forms-public_patch_form which requires that token, then forms-public_publish_form. Validation is mandatory, not a dry run. A connector that stops at patch_form leaves the user's edits invisible, which reads as a bug in your product.
Budget accordingly. One user intent frequently costs three to five tool calls, and each one is a model round trip plus a network hop. This overhead is one reason MCP can be significantly more expensive than simpler interfaces — worth understanding before committing to the architecture.
tools/list is identical for every account and safe to cache, so there is no per-user capability negotiation. Feature access is enforced when a tool is called instead, which means the same tool succeeds for one tenant and fails for another.
Two error codes carry it: FEATURE_UNAVAILABLE and PAYMENT_REQUIRED. Branch on the top-level code, never on the prose, and surface the details array to your user. "Video answers is not on your plan" is actionable; "payment required" is not.
MCP schemas change when Typeform updates the hosted server, and you consume that contract without controlling its cadence. The REST APIs are versioned conventionally, so you migrate on your schedule.
For a deterministic pipeline where an unexpected schema change is an incident, that difference decides the architecture. Typeform's own changelog introduced the MCP server as beta, and the tool surface has already expanded once.
Both lists below are Typeform-specific. Generic MCP advice will not help you here, because the capability split is the deciding factor more often than developer ergonomics.
Here is the part that survives whichever path you pick. Both hand you a credential per user and then walk away.
MCP's OAuth flow gives you an access token and, if you asked for offline_access, a refresh token. The REST path gives you an OAuth token or a personal access token. In both cases the token type differs and the infrastructure requirement is identical.
In a multi-tenant B2B agent, every user who connects Typeform produces another credential to encrypt, isolate per tenant, refresh before expiry, revoke on offboarding, and route to the right regional endpoint. At 40 users that is a table. At 4,000 it is a system. Our write-up on access control for multi-tenant AI agents covers why bolting this on later fails.
Scalekit's Typeform MCP connector handles the per-user OAuth flow, stores tokens in an AES-256 vault namespaced per tenant, and refreshes them automatically, so credentials never enter your agent runtime or the model context. The connector ships live, which means the allowlist and dynamic client registration plumbing sits on Scalekit's side rather than in an OAuth client you have to get approved.
The MCP versus API decision does not change any of that. For the REST-only gaps, the same connected-account model extends through custom tools and bring your own connector, so the export job and the interactive agent share one credential store and one audit trail.
Scalekit's catalog currently ships one Typeform connector, typeformmcp, which fronts Typeform's hosted MCP server. The setup below builds a read-only survey analytics agent in Python with LangChain.
Two dependencies and three environment variables. Find the credential values in the Scalekit dashboard under Developers, then API Credentials.
The connection_name string is the single most common integration error. It has to match the dashboard value character for character.
Look up or create the connected account, then send the user through Typeform's consent screen only if the account is not already ACTIVE.
In production, handle the redirect with actions.verify_connected_account_user using the auth_request_id from the callback query string rather than blocking on stdin.
Typeform's most common first-call failure is a missing account_id. Get it out of the way with a direct execute_tool call before the agent loop starts.
Store the region value alongside the connected account. That is the field that decides which Typeform endpoint the user's future calls belong to.
Typeform's OAuth consent grants every scope, including contact deletion and automation publishing. Scoping therefore has to happen at the tool layer, and tool_names is where you do it. The agent below is read-only by construction: five tools out of 63.
actions.langchain.get_tools returns native StructuredTool objects for the tools this user's connected account is authorized to call, so there is no schema conversion step. For the raw schemas behind a custom adapter, scalekit_client.tools.list_scoped_tools returns the same surface untranslated.
Bind the tools and run the loop. No Scalekit-specific logic appears past initialization.
The instruction to call discover first is not decoration. Field IDs are per-form, and insights-public_discover is what resolves them. For a broader look at how LangChain tool calling works and where it stops, that post covers the full pattern including multi-tenant credential resolution.
The tool-list approach above works well for a single connector. Multi-tool agents and multi-tenant products need something stricter, which is what virtual MCP servers provide.
Every tool on an MCP server consumes context on every run. Scalekit's own estimate puts a typical tool description at roughly 200 tokens, which puts Typeform's 63 tools north of 12,000 tokens before the agent does any work.
Typeform's descriptions run long. The email-step tool alone ships several hundred words of HTML structure rules. Scoping to the five or ten tools an agent role actually needs is a cost decision as much as a security one.
A virtual MCP server is a scoped endpoint declaring which connections and which tools are exposed. Define it once per agent role, get a static URL, then mint a short-lived session token bound to one user before each run.
That is the shape multi-tenant products need: one definition serving every customer, with the credential resolving per run.
Each URL is pre-authenticated for exactly one user. Sharing a process-wide URL across a multi-user deployment runs every request as whoever authorized it — the failure mode described in our post on when to use a virtual MCP server.
Mastra has native MCP support, so it pulls the tool list and Zod schemas straight from the URL. Fetch the current user's URL from your backend, never a shared constant.
Typeform's hosted server is a good piece of infrastructure. It is also, by design, indifferent to which of your tenants is calling it.
A shared token looks fine in a demo. In production, every Typeform action in the audit trail resolves to one service account, and nobody can answer who deleted the contact list.
Scalekit resolves the real user credential server-side before each call and logs the call against the person who authorized it, with 90 days of history and SIEM export. That covers who triggered it, which tool ran, and what came back. The reasoning behind that model is in our post on agent tool observability.
Typeform is rarely the only tool. A survey agent typically reads Typeform, posts a digest to Slack, and writes back to a CRM, and each of those is another OAuth implementation to build, refresh, and revoke.
With a connected-account model, every connector in the catalog inherits the same vault and the same log. Adding Google Forms or Slack to the survey agent is a connection, not a new auth project.
When a Typeform user revokes access, the connection is invalidated on the next tool call. Requests for that user fail with a clear error, other users in the tenant are unaffected, and the event is logged.
That is the behaviour a security review asks about, and it is difficult to retrofit onto a token table. For more on this, see how to handle token refresh for AI agents and our deep dive on token vaults for agent workflows.
Start from the capability, not the protocol. If the agent touches Contacts, Automations, or response analytics, Typeform MCP is the only public surface, and the OAuth-only constraint comes with it. If the agent exports responses in bulk, styles forms, manages workspaces, or runs unattended, the REST APIs are the only surface.
Most production Typeform agents end up needing both. That is the real planning insight: budget for two integrations, not one, and build the credential layer to serve them together rather than twice.
The token lifecycle does not care which you picked. That is the piece worth putting on infrastructure that already handles per-user isolation, refresh, revocation, and attribution.
Browse the Scalekit Typeform MCP connector or read the connector documentation for the full 63-tool surface and quickstart. Usage tiers are on the pricing page.
The same tradeoffs for neighbouring platforms are covered in Jotform MCP vs Jotform API and Tally MCP vs Tally API.
Building something on Typeform and want another pair of eyes on the auth model? Talk to us for direct help.