MCP Server
Connect Claude, ChatGPT, Claude Code, Cursor or your own agent to your organization's Agents, Flows and Apps over the Model Context Protocol, to run them, to build and publish them, and to provision end users.
MCP Server
Every organization has an MCP server. Connect an AI client to it and that client can run your published Agents, Flows and Apps as tools, create and edit them from your editor, and, for admins, manage end users, plans, groups and Portals. It is the same surface as the External API, shaped for a model to use.
https://builder.formwise.ai/mcpThat one address works for every organization. When a client signs in, FormWise asks which of your workspaces to connect (it skips the question if you belong to one), and the connection then acts in that workspace only. A personal key already belongs to one workspace, so it needs no choice. The same address, with a copy button and the setup steps below filled in for each client, is in Settings → API under MCP server.
Each organization also has an address of its own, with the workspace fixed in it. Use those to keep several workspaces connected at the same time: see Connecting more than one workspace.
Availability
The MCP server is available on the Creator, Pro and Agency plans and on every AppSumo tier, and is rolling out one workspace at a time: until it is enabled for your organization, the address answers 403 api_disabled. During a free trial you can connect and build: create, edit and publish Agents, Flows and Apps, and work with Knowledgebases. Running them from a connected client (run_agent, run_flow, run_draft, run_test_cases, compare_models and the per-Agent tools) unlocks after your first payment; until then, test in the builder. whoami reports this as runs. The REST API, organization keys and the Portal-level server remain on Pro and Agency. Every connection is tied to a member of your organization: what a client can do follows that member's role, and removing the member from the organization ends their connections on the next call.
Connecting
Pick your client. Most sign in through a browser and take only the address. Cursor, and clients that send a header, use a personal key instead.
Works on web, desktop and mobile once added.
- Open claude.ai/settings/connectors in a browser tab.
- Choose Add custom connector and paste
https://builder.formwise.ai/mcp. - Leave the other settings as they are. Sign in to FormWise when asked, choose the workspace if you are asked, and approve.
Connecting more than one workspace
A connection acts in one workspace. If you belong to several and want them all available at once, give each its own connection using that organization's own address:
https://builder.formwise.ai/api/v1/orgs/<your-org-slug>/mcpIt is the same server as https://builder.formwise.ai/mcp, with the workspace named in the address, so signing in does not ask which one. Each organization's address is on its MCP server card in Settings → API, under Tools on this address. Add one connector per workspace and name each so you and the model can tell them apart:
claude mcp add --transport http formwise-acme https://builder.formwise.ai/api/v1/orgs/acme/mcp
claude mcp add --transport http formwise-globex https://builder.formwise.ai/api/v1/orgs/globex/mcpIn Claude and ChatGPT, add a second custom connector with the second organization's address. The two kinds of address are separate: a connection approved at one does not work at the other, and each appears under Connected apps in the workspace it acts in. Personal keys work at either address and always act in the workspace they were created in. Existing connections made at an organization's own address keep working; nothing needs to be reconnected.
Set up with AI
Would you rather be walked through it? Paste this into your AI assistant. Copy setup prompt on the MCP server card in Settings → API gives you the same prompt.
I want to connect an AI client to my FormWise organization's MCP server. Walk me through it one step at a time and wait for me after each step.
Read the setup guide first: https://docs.formwise.ai/llms.mdx/api/mcp.mdx
What you need to know:
- My MCP address is https://builder.formwise.ai/mcp
- Ask which client I am connecting (Claude, ChatGPT, Claude Code, VS Code, Cursor or something else), then give me that client's steps from the guide exactly as written, including anything I have to turn on first. Do not shorten them or rename the menus.
- If I belong to more than one workspace, the sign-in asks me which one to connect.
- Claude, ChatGPT, Claude Code and VS Code sign in through a browser, so do not ask me for an API key for those.
- Cursor, and any client that sends a header, needs a personal key. I create it under Settings, API, Keys. Never ask me to paste a key into this chat. Tell me where it goes and I will put it there myself.
- If you can run commands or edit config files where you are running, offer to do the step for me and show me the command first.
- When we are done, have me confirm by asking the connected client to call the whoami tool.
- If something fails, check the Troubleshooting section of the guide before guessing.Connected apps and disconnecting
Each sign-in connection appears under Connected apps on the MCP server card, with the app's name, when it connected and when it was last used. Disconnect, in the row's menu, ends it immediately: the app's access stops on its next request. Personal keys are listed under Keys on the same card and are revoked there.
From your own code
Agent frameworks and API calls send a personal key as a bearer token. Create one under Keys in Settings → API (see Authentication).
Pass the server as an MCP connector on a Messages call (beta header anthropic-beta: mcp-client-2025-11-20); Claude calls the tools during the request. The server goes in mcp_servers and its toolset in tools, under the same name.
{
"model": "claude-opus-5",
"max_tokens": 16000,
"messages": [{ "role": "user", "content": "Run our weekly pipeline review agent." }],
"mcp_servers": [
{
"type": "url",
"url": "https://builder.formwise.ai/mcp",
"name": "formwise",
"authorization_token": "fw_live_..."
}
],
"tools": [{ "type": "mcp_toolset", "mcp_server_name": "formwise" }]
}Troubleshooting
| What you see | What to do |
|---|---|
| "refused to connect" in the Claude browser extension's side panel | Sign-in cannot run inside the panel. Add the connector from a normal browser tab at claude.ai; it is then available in the extension too. |
403 api_disabled | The MCP server is not enabled for your organization yet. See the availability note above. |
403 feature_not_available when connecting | Your plan does not include the MCP server. It is on Creator, Pro, Agency and the AppSumo tiers. |
A run is refused with feature_not_available | Your workspace is on a free trial. Building works; runs from a connected client unlock after the first payment. Test in the builder, or start your plan under Settings → Billing. |
| Cursor's sign-in fails or never opens | Cursor connects with a personal key. Follow the Cursor steps above. |
| A tool you expect is missing | Ask the client to call whoami. It reports your role and the tool families on the connection; see Choosing tool families. |
| The client is connected to the wrong workspace | A connection acts in the one workspace chosen at sign-in. Disconnect it under Connected apps and connect again, choosing the other workspace, or add a second connection with that workspace's own address (see Connecting more than one workspace). |
| It worked, then stopped | The connection was disconnected, the key was revoked, or the member left the organization. Connect again. |
Organization keys are not accepted by the MCP server: every connection must be a person. Use an organization key with the REST API for headless jobs instead.
What the client can do
The tool list is built for the connected member on every request, so a newly published Agent shows up on the next call and a tool the member's role doesn't allow is simply absent. Call whoami in any client to see the organization, your role and what you can do.
Every id argument also takes the object's exact name or slug (an end user's email, a Portal's entry key, a version's name), resolved inside your organization. When nothing matches, the error names up to five near matches so the model can correct itself in one step; when two objects share a name, it lists both with their ids. Ids from another organization, or from anything the connection cannot see, never resolve.
Agents and Apps
| Tool | What it does |
|---|---|
list_agents | Every published Agent and App, with ids |
run_agent | Send a message to an Agent or App by id |
agent_<name>, app_<name> | One dedicated tool per published Agent or App, so the client sees them by name, while you can run ten or fewer (see Choosing tool families) |
A run returns a reply and a conversationId. A client that passes the id back continues the same conversation with the history restored on the server; omitting it starts fresh. Each run spends your organization's credits, exactly like a run in the builder.
Flows
| Tool | What it does |
|---|---|
list_flows | Every published Flow with the inputs it takes |
run_flow | Run a Flow by id with its inputs |
flow_<name> | One dedicated tool per published Flow whose parameters are the Flow's questions, under the same ten-or-fewer rule as the Agent tools |
This is the part built for models. A Flow that asks for a company name, a plan tier and a team size becomes a tool with those three parameters, typed (choices become an enumeration, numbers are numbers, required questions are required), so the client fills them in and the Flow runs as if the person had submitted the form. Inputs are validated before anything runs or is charged. A Flow with no questions is talked to like an Agent.
Knowledgebases
Your Knowledgebases are searchable directly, with no Agent in between, so a connected client can look something up, quote its source, and file notes back for your Agents to use on later runs. The guide Use FormWise as a data layer walks through the loop client by client.
The tools use the API's names: a page is what the app calls a Doc, and a source is what the app calls a File.
| Tool | What it does |
|---|---|
list_knowledgebases | Every Knowledgebase you can read, with source and page counts |
get_knowledgebase_outline | The folders of a Knowledgebase, each with its one-line description, page count and the files filed in it, plus unfiled top-level pages and files: the place to start looking |
search_knowledgebase | Search documents, pages and your own memories, in one Knowledgebase or all of them; every result carries a citation |
list_pages, read_page | The page index of a Knowledgebase (with parentPageId, the files filed in that folder or page), and one page in full |
list_sources, get_source | The ingested documents of a Knowledgebase, whether each is searchable, and the folder or page each is filed in (parentPageId); get_source is one document with its ingestion status brought up to date, for polling after an upload |
list_changes | What was added or updated since a point in time, oldest first, with a cursor to continue |
create_knowledgebase | A new, empty Knowledgebase (members and above; plans may cap how many, and the tool says so) |
save_page, append_page | File notes: save_page creates a page (no id) or edits one in place with anchored operations (with id); append_page adds to the end of one (members and above) |
upload_source | Add a document, not a note: inline markdown or text, or a public URL, indexed through the same path as a builder upload; pass parentPageId to file it in a folder or page (members and above) |
move_source | File a document in a folder or page of the same Knowledgebase, or pass parentPageId: null to unfile it (members and above) |
create_folder, move_page | Group pages: make a folder, then create pages inside it or move existing ones in; list_pages shows the tree |
A document uploaded with upload_source goes through exactly the path a file uploaded in the builder takes: the original is kept, the row is attached to the Knowledgebase under the plan's sources-per-Knowledgebase cap, and the indexing service is handed the content. Indexing is not instant, so the answer is processing with the source's id; get_source reports ready once it can be searched, and list_changes shows it as created and then ready. A URL is checked to be a public http(s) address before anything fetches it. When the organization reviews agent writes, an upload waits as pending_review in the Page reviews inbox (find it with the search box), out of every search, until a person approves it (which starts indexing) or rejects it (which deletes it). The builder marks files added this way "via MCP" or "via API". Without parentPageId the document is filed nowhere and shows on the Knowledgebase's Home. Indexing is free; the same holds for POST /v1/knowledgebases/{id}/sources, which also takes a file as multipart/form-data.
Searching documents spends one of your organization's credits per call; pages, reads and the changes feed are free, and the tool says so. Pages are also offered as resources (formwise://knowledgebases/<id>/pages/<page-id>), so clients that support resources can attach a page as context without a tool call. There is no page or Knowledgebase delete over MCP. Edits are anchored: save_page with an id takes a list of operations (replace, insert before or after, prepend, append, replace a range) that name the exact text to change, each anchor must appear exactly once, and a miss refuses the whole call with nothing changed, so the model never re-sends a page it has only partly read. When your organization reviews agent writes a write comes back as pending_review and waits for a person in the dashboard. Pages written this way are read by your Agents later, so the tools tell the model to treat content copied from the web or from messages as untrusted before saving it.
One tool to create or update
Creating and updating are the same tool: save_agent, save_flow, save_app and save_page create when called without an id and update the draft (or page) when called with one, the way Linear's save_issue works. Fewer tools means less schema in every request and fewer wrong picks. The earlier create_*, update_* and edit_page names are still accepted for one release and mapped on arrival, marked the same way as legacy argument names; they no longer appear in the tool list.
Argument names
Every tool argument and result field is camelCase (knowledgebaseId, pageId, conversationId, nextCursor), the same spelling as the REST authoring and Knowledgebase endpoints. The snake_case names the run and knowledge tools shipped with, and notebookIds on set_agent_knowledge, are still accepted for one release and mapped on arrival; a call that uses them is marked +legacy in the knowledgebase activity log so you can see when your clients have moved over.
Keeping answers small
Every list tool pages: it answers { items, nextCursor }, takes limit (default 50, max 200) and cursor, and a walk with the cursor is gapless because the cursor names the last item handed out rather than a position. fields keeps only the named fields on each item, and an unknown name is refused with the list of valid ones, so the model never guesses. list_pages, list_sources and the list_authored_* tools also take updatedSince.
The big reads take view. The default, summary, is what a model plans with: get_flow_draft returns the questions, inputs and a node outline without the node document; get_agent_draft and get_app_draft preview their long texts (the first 2 KB, with the total size) and count starters and test cases; read_page previews the markdown; get_execution names the tools called without their arguments. Pass view: "full" when the whole thing is needed, which is always the case before an anchored patch.
Choosing tool families
MCP has no lazy loading: every tool's schema reaches the model on every request, and a model picks the right tool less reliably as the list grows. A connection can therefore ask for only the families it needs. The tools are grouped into five:
| Family | What it holds |
|---|---|
run | list_agents, run_agent, list_flows, run_flow, get_execution |
authoring | Drafts, versions, publishing, testing, integrations and templates for Agents, Flows and Apps |
knowledge | Everything under Knowledgebases |
provisioning | End users, groups, plans and Portals (admins) |
agents | The dedicated agent_<name>, app_<name> and flow_<name> tools |
Add ?tools= to the address with a comma-separated list, for example …/mcp?tools=knowledge,run for a research client or …/mcp?tools=run for an operator that only runs what is already published. Tools on this address on the MCP server card in Settings → API offers the choice as checkboxes and writes it into the address and every setup step; a client that signs in through a browser sees the requested families on the approval screen. A personal key created while a choice is made remembers it, so that key registers the same families at the plain address. whoami and search_docs are always present, and whoami reports toolFamilies, so a model can explain why a tool is missing.
The choice only narrows. Your role still decides what a family may contain, a family the role does not allow registers nothing, an unknown family name is refused with the valid ones, and the address and the key's stored list combine as their intersection.
The dedicated agents family has one more rule: it is registered only while the connection can run ten or fewer published Agents, Apps and Flows in total. Past that, list_agents and run_agent (and the Flow pair) carry the load, so a large organization never pushes dozens of schemas into every request. run_agent and run_flow always reach everything that is published.
Limiting a connection to some Knowledgebases
A role is all or nothing: a member who can read Knowledgebases can read every one the organization has. A connection does not have to be. When you create a personal key with the Knowledgebases family on, Keys on the MCP server card offers Knowledgebases a key may reach: leave it at all of them, or tick the ones this key is for, and the key can then list, search, read and write those and nothing else. A client that signs in through a browser makes the same choice on its approval screen, and the approval names what was chosen. Organization API keys under API keys take the same choice, which applies to the REST endpoints under /v1/knowledgebases too.
The list only narrows. It is checked against the organization when it is saved, so a key never names a Knowledgebase that is not yours, and it is intersected with the organization's Knowledgebases on every call, so one that is later deleted simply drops out. A Knowledgebase outside the list answers not_found, the same as one that does not exist, and a search over all never includes it. search_agent_knowledge previews only the attached Knowledgebases inside the list. whoami reports knowledgebases as "all" or the list of ids, so a model can explain a short list_knowledgebases. Existing keys and connections are unchanged.
Retrying a create
A client that times out and retries a create would make two pages, two drafts, two end users. Every create (save_page, create_folder, create_knowledgebase, save_agent, save_flow and save_app without an id, provision_end_user) takes an idempotencyKey: any unique string up to 64 characters. A retry with the same key within 24 hours returns the first result again, marked replayed: true, and writes nothing; the same key with different arguments is conflict. Keys are scoped to your organization and to the tool, so the same key on create_folder and on save_page is two requests. The REST API takes the same thing as an Idempotency-Key header.
How the tools describe themselves
Every tool's description follows one checklist so a model can act on it without guessing: a title, at most 600 characters, the cost named in one sentence (Free. or Spends the organization's credits.), every id argument naming the tool that hands the id out, every pair of arguments that cannot be combined saying so on both halves, and the recovery step for each error it can return (not_found names the list tool to call; conflict says to read again). The server instructions carry the rules that apply to every call: send real newlines rather than the two characters \n, read before you write, pass expectedUpdatedAt on edits and an idempotencyKey on a create you might retry.
The docs
Every connection also gets search_docs: this documentation, searchable from the client, so the model answers "how does FormWise handle X" from a page it can cite rather than from memory. It reads the same index the search box on this site uses, touches none of your organization's data, and is free.
End users, groups, plans and Portals (admins)
Members with the admin or owner role also get the provisioning tools: list and provision end users, list plans, create and manage user groups and their members and grants, list Portals, and admit or un-admit groups at a Portal. They follow the REST provisioning endpoints: provisioning can add people to groups and, when asked, email them an invite. Revoking an identity, adjusting bonus credits and removing a plan are REST-only. Every change is recorded against the member who made it. Removals are marked as destructive so agent clients confirm before acting; creates and additions are safe to retry.
Build and edit from your editor
Members with the member role or above can also create, edit, test and publish the organization's own Agents, Flows and Apps through the same server, so Claude Code, Cursor or a script can manage them. The tools appear only for a caller whose key carries the write scope (agents:write, flows:write, apps:write) and whose current role allows it; viewers never see them, and only admins and owners see delete_*.
Drafts and publishing
Every edit changes a draft. Nothing reaches end users until you publish, and publishing is always an explicit call: publish_agent, publish_flow or publish_app. That makes the loop safe to run from a model:
get_agent_draft,get_flow_draftorget_app_draftto read the current draft. Each returnsupdatedAt.- Edit with
save_agentorsave_app(pass theid; without one they create), or the Flow tools (save_flowfor the name,set_flow_questions,add_flow_node,update_flow_node,delete_flow_node,replace_flow_workflow). Pass theupdatedAtyou read asexpectedUpdatedAt; if someone else changed the draft in the meantime the call is refused withconflictand nothing is written. Read again and retry. Long prompts are edited in place rather than re-sent:save_agenttakessystemInstructionPatchandupdate_flow_nodetakespromptPatch, the same anchored operations assave_page, applied to the prompt as it currently is. run_draftruns the unpublished draft once, billed to the organization like any run. Its conversations never mix with the published version's. The result carries atrace: which model ran, the names of the pieces the prompt was built from, the tools available and called, and the credits spent.get_executionreturns the same trace for any run by itsexecutionId.run_test_casesruns up to ten cases through the quality judge, using the tool's rubric or each case'sexpectedBehavior, and reports pass or fail per case with the agent node to fix. Save cases once withset_test_cases(or havegenerate_test_casespropose them) and a rubric withset_quality_rubric; thenrun_test_caseswith no cases runs the saved suite.compare_modelsruns the same suite on two to four models and reports pass rate, latency and credits per run. All of these need the quality checker on your plan.diff_agent_draftshows what publishing would change for end users: the prompt as a unified diff, then model, capabilities, sub-agents, integrations and starters.publish_*snapshots the draft as a new version and makes it live.list_*_versionsshows every version and who published it;restore_*_versionre-publishes an earlier one;revert_*_draftundoes the last edit.
Putting it on a website
Publishing hands back where the thing now lives. publish_agent, publish_flow and publish_app return a share block, and get_share_links returns the same block for anything you can read, at any time:
| Field | What it is |
|---|---|
link | The public page, on your custom domain when you have one |
embedCode | An iframe of that page, ready to paste into a site's HTML |
published | Whether anything is served there yet |
embedding | anywhere, listed_sites (only the sites in allowedSites) or off |
linkOpensDirectly | False when the link is refused outside an embed, which is the case with listed_sites |
notes | Anything the person should be told, in plain words |
So a coding agent can publish an Agent and add it to the site it is working on in one session. Pass embedOn to get_share_links with the site the embed is going on (https://www.example.com) and embedOn.allowed says whether it will load there, before anything is deployed. Embedding is open by default. When a workspace has limited it to listed sites or turned it off, the tools report that and say where to change it; the list itself is edited in the builder, in the Agent, Flow or App's domain settings.
An App can only be published once its adviser and every member are published; the refusal lists what to publish first. Models are chosen from list_models, which returns each model's engine, purpose, credits per run and capabilities, the builder's presets, and marks the ones your organization cannot use.
Building an Agent
Read the resource agent://guide (also get_agent_guide) first. It explains how the run-time prompt is composed from your instructions and the platform's pieces, what each built-in capability does and costs, the defaults a new Agent gets (web search and web scrape are on until you turn them off), and a prompt skeleton. list_agent_templates offers starting points, each with instructions, identity, capabilities, starters and test cases that work together; pass one as template to save_agent and override any field.
An Agent needs things to know and to do. set_agent_knowledge attaches Knowledgebases, and search_agent_knowledge shows what the Agent's own retrieval returns for a question, before anyone asks it.
For services, describe the job to suggest_integrations ("send the invoice by email", "log the call in the CRM") and it returns the toolkits and the exact actions that do it, each marked connected or not, with a suggested approval level per action. list_integrations is the keyword search for a name you already know, and get_integration_actions lists one toolkit's actions. set_agent_integrations attaches them to an Agent, naming the actions and when the end user must approve each; set_flow_node_integrations does the same for an agent node inside a Flow. When a toolkit is not connected yet, the result carries a connectUrl (admins and owners; get_connect_link mints one on its own). Give the link to the person: it opens the same sign-in the builder's popup runs, and once they finish, the Agent can use the service. Attaching a toolkit also enables it for your organization's runs, the same step the builder takes when it connects one.
Writing a Flow from scratch
A Flow is a document of ordered nodes. The server publishes its schema as the resource flow://schema (also get_flow_schema): the document shape and rules, every node type with its fields and an example, and the question types. A Flow's questions are its run parameters, so set_flow_questions is also how you define what a caller passes.
Activity
Every change made this way is recorded with who made it, from which surface (dashboard, API, MCP or the assistant) and what changed, under Activity → Tool changes in the sidebar. Each draft also reports its last change, and each version its publisher.
A snippet for your CLAUDE.md
Call get_setup_snippet and paste the result into your repository's CLAUDE.md (or any agent instructions file). It tells a coding agent to read before it writes, to test before it publishes, and to ask before it deletes. The same operations are available as plain HTTP under /v1 for scripts and CI.
The Portal-level server
Your end users get their own MCP server, per Portal, at the Portal's address followed by /mcp (on a custom domain, on that domain). It exposes the Agents, Flows and Apps their plan unlocks, runs spend their plan's credits, and it is whitelabeled: nothing in it names FormWise. It is off by default. Turn it on per Portal under the Portal's access settings (Allow MCP connections), and mark which plans include it in the plan editor (Include MCP access). Once both are on, subscribers find their connection address and their connected apps under Account settings → Connected apps in the Portal.
End users connect the same ways members do, and the card walks them through it client by client. Clients that sign in (Claude, ChatGPT, Claude Code, VS Code) go through the Portal's own sign-in and approve the connection. Cursor, and clients that send a header, use a personal API key the end user creates on the same card. Keys carry a neutral sk_live_ prefix, belong to one person at one Portal, and are checked against that person's standing and plan on every request, so a key stops working when the plan lapses and starts again when it is renewed. Each person can hold up to five keys per Portal and revoke any of them there.
Without MCP
The same capabilities are plain HTTP. The OpenAPI specification works with generic OpenAPI-to-MCP bridges and typed client generators if you would rather integrate that way.
API Overview
Run your published Agents, Flows and Apps, and provision end-user accounts, plans and access, from your own systems with the FormWise External API.
Use FormWise as a data layer
Connect Claude, ChatGPT, Claude Code, Cursor, your own agents and your backend to the same Knowledgebases your FormWise Agents use, to search them, to see what changed, and to write back.