In-depth architectural comparison of the Formio MCP and Salesforce Metadata MCP MCP servers. Compare execution transports, security boundaries, tool capabilities, quality scores, and ready-to-paste client installation snippets for Claude, Cursor, Windsurf, and VS Code.
At a Glance & Executive Verdict
Formio MCP
Developer Tools · Local stdio
Quality: 60/100 (Good) | Auth: No auth required
Salesforce Metadata MCP
Developer Tools · Local stdio
Quality: 63/100 (Good) | Auth: No auth required
Verdict Summary: Choose Formio MCP if you need specialized Developer Tools tools running via a local process. Choose Salesforce Metadata MCP if your workspace requires Developer Tools integration with local subprocess execution. Both servers can be configured concurrently in your client's mcpServers manifest.
Which MCP Server Should You Choose?
Choose Formio MCP when:
You need dedicated capabilities in the Developer Tools domain.
You prefer local stdio subprocess transport architecture.
Your security boundary fits: No auth required (Free / Open Source).
Say hello — a connectivity check that confirms the server is running and reachable. Needs no Form.io project or credentials, so it is the first thing to try when other tools fail.
form_create
Create a new form in the Form.io project mapped to the user's current working directory. IMPORTANT: Before calling this tool, use the formio-schema skill to construct a properly structured Form.io form JSON definition based on the user's requirements. The skill documents all component types, validation options, layout patterns, and conditional logic available in Form.io. New forms default to `revisions: 'original'` so form change history is preserved. NOT for: creating a draft revision of an existing form. When the user says "create/save a draft", "draft <change>", call form_update with `formId` and `draft: true` instead.
form_get
Fetch a single form definition from the Form.io project mapped to the user's current working directory, by form ID or path. Pass `draft: true` to fetch the form's current in-flight draft instead of the published form.
form_list
List forms from the Form.io project mapped to the user's current working directory with optional filtering and pagination.
Ready-to-Paste Client Configurations
Paste either (or both) of these JSON server blocks into your client config file (e.g. claude_desktop_config.json or ~/.cursor/mcp.json).
Formio MCP is categorized under Developer Tools and uses a local stdio subprocess. In contrast, Salesforce Metadata MCP belongs to Developer Tools using local stdio subprocess. Select Formio MCP when you need capabilities focused on developer tools and Salesforce Metadata MCP when you require tools for developer tools.
Fetch a single immutable form revision from the Form.io project mapped to the current working directory. `version` accepts either the revision `_vid` (e.g. "3") or the revision document `_id` (24-character hex). To revert the live form to this revision, pass its `form` body to `form_update` with a `note` like `Revert to v<vid>`.
form_revisions_list
List immutable published revision summaries for a single form in the Form.io project mapped to the current working directory. Returns compact revision metadata (_vid, _id, modified, user, _vnote) for the form identified by `formIdOrPath`. To inspect a specific revision body, call `form_revision_get` with the desired `_vid`. To revert the live form to a prior revision, pass that revision body to `form_update` with a `note` like `Revert to v<vid>`.
form_update
Update an existing form in the Form.io project mapped to the user's current working directory. IMPORTANT: Before calling this tool, first use form_get to fetch the current form definition, then use the formio-schema skill to understand the schema so that you can apply the requested modifications (add, remove, or modify fields and settings), and finally call this tool with the complete updated form JSON. `draft`, `publish`, and `revert` are mutually exclusive — pass at most one. If `revisions` in the response differs from the stored value, the per-form revisions-mode gate prompted the USER and they chose.
project_export
Export the complete template (roles, resources, forms, actions) of the Form.io project mapped to the user's current working directory as a portable JSON document. Use this to snapshot a project before importing changes.
project_get
Report which Form.io project the given working directory resolves to, which deployment hosts it, and which layer supplied each — the preflight to run before the first tool call that reads from or writes to a deployment. Answers from inside this server, using the same resolver every other tool uses, so what it reports is what the next call targets. There is no need to run any shell command to ask this. Branch on `status`. "ok" means both URLs resolved and you may proceed. "not-configured" means nothing is mapped for this directory: relay the message, ask the user for the single value it names, record it with project_set, and call this again. "base-url-unresolved" means the project IS recorded and only its deployment is missing — ask for the Base URL alone and do NOT re-ask for the Project URL. Reads only. It resolves and reports; project_set is what records a choice.
project_import
Import a template JSON into the existing Form.io project mapped to the user's current working directory, merging roles, resources, forms, and actions in one call. Use the formio-resource-planner skill to construct the template before calling this tool. WARNING: import merges into the existing project — use project_export first to snapshot.
project_set
Set the active Form.io project for the given working directory by recording its URL in ~/.formio/projects.json You MUST call this tool whenever the user asks to set, change, or switch the active Form.io project — do not merely acknowledge the request in text. Persisting the choice requires the tool call. The chosen URL is persisted to ~/.formio/projects.json keyed by the cwd argument when provided (or the MCP server process cwd otherwise). Pass the `cwd` argument whenever you know the user's current working directory — the server process cwd is fixed at spawn and may not match where the user actually is. Every Form.io tool resolves its project on each call, so a mapping written here needs no restart. It takes effect only where the mapping is the record that WINS, though: under a committed formio.json the mapping is the fallback if that file goes away, and this call reports the pair that actually resolves rather than the one it recorded. Read `ok` and `projectUrl` on the result rather than assuming the write governs. You normally pass only projectUrl. The base URL — which builds the portal-login URL and keys the cached token — is derived from it — https://api.form.io for a project on a form.io host, and the parent path for a project addressed as a sub-directory — so there is nothing to supply. Pass baseUrl ONLY when the server reports that it cannot be determined, which happens for a project URL that carries no path on a customer domain: there the deployment is a sibling sub-domain and nothing in the project URL names it. Do not ask the user for a base URL before the server says it needs one. This tool writes the machine-local mapping, which is keyed by absolute path and therefore does not survive a clone. To record the target with the code instead — versioned, visible in a diff, and shared with everyone who clones the repository — write a committed formio.json yourself, in the application's own folder: a JSON object holding {"projectUrl": "..."}, plus "baseUrl" only when it cannot be derived. This server reads that file and never writes it. Resolution is by scope, narrowest first, and precedence runs: a committed formio.json, then the working-directory mapping, then FORMIO_PROJECT_URL in the environment, which is the weakest of the three. So a mapping written here DOES override an environment value, and a committed file overrides both.
role_create
Create a new role in the Form.io project mapped to the user's current working directory.
+9 more tools listed on main page
Salesforce Metadata MCP Tools (20)
sf_create_custom_object
Creates a new Salesforce Custom Object using the Metadata API. The object name must end with '__c'. Use this when a user asks to create a new object, entity, or table in Salesforce.
sf_create_custom_field
Creates a new custom field on an existing Salesforce object. The field API name must end with '__c'. Supports all field types: Text, Number, Picklist, Lookup, etc.
sf_add_picklist_values
Adds new picklist values to an existing Picklist or MultiselectPicklist field without removing existing values. Use when a user wants to add new options to a dropdown.
sf_create_approval_process
Creates or updates a Salesforce Approval Process via the Metadata API. Define who can submit, approval steps with approvers, entry criteria, and what happens on approval or rejection.
sf_create_validation_rule
Creates or updates a Salesforce Validation Rule on any object via the Metadata API. The errorConditionFormula returns TRUE when data is INVALID. Use for data quality enforcement.
sf_create_workflow_field_update
Creates a Workflow Field Update action that can be referenced by Approval Processes, Workflow Rules, or Flows. Sets a field to a literal value, formula result, or null.
sf_create_formula_field
Creates a formula field on any Salesforce object. Supports all return types (Text, Number, Currency, Date, DateTime, Checkbox, Percent) and the full Salesforce formula language: IF/AND/OR/NOT, BLANKVALUE, TEXT, VALUE, DATE, DATEVALUE, TODAY, NOW, date functions (MONTH/YEAR/DAY), math (FLOOR/CEILING/MOD), string functions (LEN/LEFT/RIGHT/MID/TRIM/UPPER/LOWER/CONTAINS/BEGINS), record type and picklist functions (ISPICKVAL, ISNULL, ISBLANK), cross-object field references (e.g. Account.Owner.Name), and VLOOKUP. Complex multi-line formulas are fully supported.
sf_deploy_metadata
Deploys a set of metadata components directly to the org using the Metadata API SOAP deploy operation. Builds a package.xml and deployment zip in memory. Supports validate-only (checkOnly:true) for pre-deployment validation without making changes. Specify runTests to execute test classes during deployment (required for production). Polls until complete or timeout.
sf_check_deploy_status
Checks the status of an in-progress or recently completed metadata deployment by async job ID. Returns the status (Pending, InProgress, Succeeded, Failed, Canceled), component successes, failures, and test results. Use with the deploy ID returned from sf_deploy_metadata.
sf_retrieve_metadata
Retrieves metadata components from the org and returns their actual file contents. Use this to read existing configuration before making changes, to back up metadata, or to check what is really deployed rather than what you think is deployed. Waits for the async retrieve to finish and unpacks the resulting zip, returning each file's path and source. Large files are truncated. Accepts 'components' (array), or 'metadataType'+'componentName' as a single-item shortcut, or a raw 'packageXml' document — provide exactly one form.
sf_delete_metadata
Permanently deletes one or more metadata components of a given type via the Metadata API's deleteMetadata call — works for CustomObject, CustomField, Flow, GenAiFunction, GenAiPlugin, GenAiPlannerBundle, Bot, ApexClass, and most other metadata types. There was previously no way to remove anything created by this MCP server (sf_deploy_metadata only supports adding/updating components, not destructiveChanges) — diagnostic or abandoned metadata had nowhere to go. Deletes each fullName independently: check the response's deleted/errors lists rather than assuming all all-or-nothing. Some types have dependency order requirements (e.g. delete a Bot's GenAiFunction/GenAiPlugin/GenAiPlannerBundle before the Bot itself, delete CustomField before its parent CustomObject) — Salesforce will reject a delete that still has dependents, naming them in the error.
sf_query_records
Executes a SOQL query against the org and returns matching records. Provide the full SOQL string in the query param. Use for reading data, checking existing records before creating, or verifying changes.
Supports aggregate queries — GROUP BY with COUNT(), SUM(), AVG(), MAX(), MIN(), e.g.:
'SELECT StageName, COUNT(Id), SUM(Amount) FROM Opportunity GROUP BY StageName'
Aggregate results come back as regular records with the aggregate expressions as field keys (e.g. "expr0").
Row cap: 'limit' defaults to 200 and is a ceiling, not a hint. If the SOQL carries its own LIMIT the smaller of the two applies, so a LIMIT in the query can tighten the cap but never raise it. When rows are cut off the response sets truncated: true and reports appliedLimit and limitSource, so a capped result is never mistaken for a complete one.