com.furrowforms/furrow-forms
REMOTE · API.FURROWFORMS.COM · 2 COMPONENTS
Form backend an agent runs end to end: provision forms, snippets, spam, signed webhooks.
Available components
Last scanned (21 hours ago)
Scores higher than 99% of remote servers
Reachable. Last reached 4 Nov 2026.
Category Workflow Automation
How this component scores in each security and reliability category. Every signal is checked automatically against the live server, and we only credit what we can confirm. How we score → Why this is hard to score →
Endpoint Security97
- The endpoint's TLS certificate is valid, in date, and uses a strong key. View diagnostics → Pass
- Authorisation is enforced on tool calls, advertised via RFC 9728 protected-resource metadata. Discovery is public, which costs nothing: no tool can be invoked without a token. View diagnostics → Pass
- HTTPS is enforced; there's no plaintext access path. View diagnostics → Pass
- The HSTS (Strict-Transport-Security) header is present. View diagnostics → Pass
- DNSSEC check failed: this domain isn't protected by DNSSEC. See how to fix → View diagnostics → Fail
- The authorisation server supports Client ID Metadata Documents, the current MCP client-registration mechanism. View diagnostics → Pass
Transport & Reachability100
- Verified streamable-http transport via a live MCP handshake. View diagnostics → Pass
Schema Quality & AI Usability77
- 100% of prompts and resources have a non-trivial description (not blank, and not just the item's name).Pass
- AI-judged instruction clarity (excellent).Pass
- Context-footprint check failed: tool/resource definitions use about 9586 tokens (~259/item across 37 items; 29 tools + 8 resources), over budget; trim descriptions and params. See how to fix → Fail
- Usage-examples check failed: none of the tools include examples. See how to fix → Fail
Stability & Change Management100
- No destabilizing schema changes in the last 30 days.Pass
Tool Coverage100
- 100% of tools have a non-trivial description (not blank, and not just the tool's name).Pass
- 100% of tool parameters carry a description.Pass
Tool Safety100
- No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.Pass
- We read all 29 captured tool definition(s), and no name or description among them implies an irreversible operation.Pass
- An AI judge read all 31 captured unit(s) of tool text and found none that tries to manipulate the model reading it.Pass
Capabilities100
- Implements a current MCP spec version (2026-07-28).Pass
Every change we have recorded for this component, newest first. Security-relevant changes are always shown. ▲ marks a change for the better, ▼ a change for the worse; unmarked changes are neutral.
- 30 Oct 26 0
- Tool “update_form” rewrote its description, which is the text the model reads security
- Tool “update_project” rewrote its description, which is the text the model reads security
- New tool “move_client” functional
- “create_form” added an optional parameter “notify_cc_override” cosmetic
- “create_project” added an optional parameter “notify_bcc” cosmetic
- “create_project” added an optional parameter “notify_cc” cosmetic
- “create_form” added an optional parameter “notify_bcc_override” cosmetic
- “update_form” added an optional parameter “notify_bcc_override” cosmetic
- “update_form” added an optional parameter “notify_cc_override” cosmetic
- “update_project” added an optional parameter “notify_bcc” cosmetic
- “bootstrap_site” added an optional parameter “notify_cc” cosmetic
- “update_project” added an optional parameter “notify_cc” cosmetic
- “bootstrap_site” added an optional parameter “notify_bcc” cosmetic
- 29 Oct 26 0
- The server rewrote its instructions, which are the text every model session reads security
- Tool “update_form” rewrote its description, which is the text the model reads security
- Tool “update_project” rewrote its description, which is the text the model reads security
- Tool “bootstrap_site” rewrote its description, which is the text the model reads security
- Tool “create_project” rewrote its description, which is the text the model reads security
- Tool “create_upgrade_link” rewrote its description, which is the text the model reads security
- Tool “get_account” rewrote its description, which is the text the model reads security
- Tool “get_project” rewrote its description, which is the text the model reads security
- Tool “get_snippet” rewrote its description, which is the text the model reads security
- Tool “update_account” rewrote its description, which is the text the model reads security
- Schema quality: 7544 → 8763 ▼ functional
- New resource “testing” functional
- New resource “text-alerts” functional
- New tool “test_sms” functional
- “update_form” added an optional parameter “notify_phones_override” cosmetic
- “update_project” added an optional parameter “notify_phones” cosmetic
- “bootstrap_site” added an optional parameter “notify_phones” cosmetic
- “create_form” added an optional parameter “notify_phones_override” cosmetic
- “create_project” added an optional parameter “notify_phones” cosmetic
- “update_account” added an optional parameter “sms” cosmetic
- “update_project” reworded the description of “notify_emails” cosmetic
- “bootstrap_site” reworded the description of “notify_emails” cosmetic
- “create_project” reworded the description of “notify_emails” cosmetic
- 3 Oct 26 +1
- Stability: 0.97 → pass security
- 28 Sept 26 0
- We updated how we score, so this day's move reflects our rubric, not a change to the server See what changed → functional
- 25 Sept 26 0
- We updated how we score, so this day's move reflects our rubric, not a change to the server See what changed → functional
- 22 Sept 26 0
- Tool “get_account” rewrote its description, which is the text the model reads security
- Tool “update_account” rewrote its description, which is the text the model reads security
- “update_account” added an optional parameter “ai” cosmetic
- 4 Sept 26 0
- Stability: unverified → 0.03 ▲ functional
- 3 Sept 26 0
- Injection markers: unverified → pass ▲ security
- Transport: unverified → pass ▲ security
- First check of Judged manipulation: pass security
- Authorization: Authorisation is enforced on tool calls, advertised via RFC 9728 protected-resource metadata. Discovery is public, which costs nothing: no tool can be invoked without a token. security
- Tool coverage: unverified → 100 ▲ functional
- Schema quality: unverified → 100 ▲ functional
- MCP protocol: unverified → pass ▲ functional
- First check of Schema quality: fail functional
- First check of Tool coverage: 100 functional
- First check of Schema quality: fail functional
- First check of Schema quality: excellent functional
- First check of Destructive annotations: pass functional
Diagnostic detail from the automated scan of this channel: what the scanner observed at each step, so you can see exactly where a check passed or failed. It is informational only and never changes the trust score.
Captured 4 Nov 2026 · Probed https://api.furrowforms.com/mcp
TLS valid
Negotiated TLS 1.3 with TLS_AES_128_GCM_SHA256 .
| Subject | Issuer | Valid from | Valid until | Key | Signature | Serial |
|---|---|---|---|---|---|---|
| CN=api.furrowforms.com | CN=WE1,O=Google Trust Services,C=US | 16 Oct 2026 | 14 Jan 2027 | ECDSA 256 | ECDSA-SHA256 | 1cd803c8aaee6c6f1327c721388a68af |
| SANs: api.furrowforms.com | ||||||
| CN=WE1,O=Google Trust Services,C=US (CA) | CN=GTS Root R4,O=Google Trust Services LLC,C=US | 13 Dec 2023 | 20 Feb 2029 | ECDSA 256 | ECDSA-SHA384 | 7ff31977972c224a76155d13b6d685e3 |
| CN=GTS Root R4,O=Google Trust Services LLC,C=US (CA) | CN=GlobalSign Root CA,OU=Root CA,O=GlobalSign nv-sa,C=BE | 15 Nov 2023 | 28 Jan 2028 | ECDSA 384 | SHA256-RSA | 7fe530bf331343bedd821610493d8a1b |
Background: What to check on a remote MCP endpoint →
DNSSEC insecure
Validation of api.furrowforms.com. — Not signed
| Zone | DS | Keys | Algorithms | Outcome |
|---|---|---|---|---|
| . | trust_anchor | 20326, 38696 | 8, 8 | Verified |
| com. | present | 19718 | 13 | Verified |
| furrowforms.com. | absent | Unsigned (proven) parent-signed NSEC/NSEC3 proves an unsigned delegation |
Authentication Enforced and verified
The endpoint asked for a token and published valid RFC 9728 metadata describing how to get one.
| Result | Enforced and verified |
|---|---|
| Enforced | On tool calls |
| HTTP status | 200 |
WWW-Authenticate challenge Bearer resource_metadata="https://api.furrowforms.com/.well-known/oauth-protected-resource/mcp", scope="openid profile email offline_access"
Bearer resource_metadata="https://api.furrowforms.com/.well-known/oauth-protected-resource/mcp", scope="openid profile email offline_access" | Header | Value |
|---|---|
| strict-transport-security | max-age=15552000; includeSubDomains |
| content-security-policy | default-src 'self'; script-src 'none'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; frame-ancestors 'none'; base-uri 'self'; form-action 'self'; object-src 'none' |
| x-content-type-options | nosniff |
| x-frame-options | DENY |
| referrer-policy | strict-origin-when-cross-origin |
Protected resource metadata
| Document | https://api.furrowforms.com/.well-known/oauth-protected-resource/mcp |
|---|---|
| Retrieved | Yes |
| Resource | https://api.furrowforms.com/mcp |
| Authorisation server | https://api.furrowforms.com/api/auth |
Background: How OAuth 2.1 works in the 2026 MCP spec →
Transports 2 probes
| Transport | URL | Outcome | Status | Location |
|---|---|---|---|---|
| streamable-http | https://api.furrowforms.com/mcp | Verified | 200 | |
| http (plaintext) | http://api.furrowforms.com/mcp | HTTPS enforced | 301 | https://api.furrowforms.com/mcp |
The tools this component advertises to a client, with an estimated token cost for each. Expand a tool to see its parameters and schema. The per-tool counts are indicative and are not scored directly; the schema's total context footprint is one signal in Schema Quality & AI Usability. A tool's description is untrusted text the model reads on every call, which is what makes this list a security surface and not just an inventory: how tool poisoning works →
archive_client Archive client ~49
Use to archive a client. Do not use this as a hard delete. There is no unarchive tool in v1.
| Name | Type | Req | Description |
|---|---|---|---|
| client_id | string | yes | Client id from list_clients or create_client. |
No output schema declared.
No examples provided.
archive_form Archive form ~49
Use to archive a form so public submit returns 404. Do not use this as a hard delete.
| Name | Type | Req | Description |
|---|---|---|---|
| form_id | string | yes | Form id from list_forms, create_form, or bootstrap_site. |
No output schema declared.
No examples provided.
archive_project Archive project ~62
Use to archive a website. Archived projects reject public submit. Do not use this as a hard delete. There is no unarchive tool in v1.
| Name | Type | Req | Description |
|---|---|---|---|
| project_id | string | yes | Project (website) id from list_projects, create_project, or bootstrap_site. |
No output schema declared.
No examples provided.
bootstrap_site Bootstrap site ~1,359
Use this to stand up a client, one website (project), and its forms in a single call. Before calling, ask the human who should receive notification emails (notify_emails has no default; empty means nobody is emailed), thank-you page vs on-page message, and whether to add Turnstile — see furrow://docs/workflow. name/slug are the client; optional project_name/project_slug default to the same. Free accounts cannot create a fourth active project — call create_upgrade_link if bootstrap_site returns plan_limit. Operator tokens (all workspaces) must pass team_id from list_teams. Team-scoped tokens may omit team_id and cannot target another workspace. Idempotent on client, project, and form slugs. Site settings (domains, Turnstile, notify emails, webhook, email templates, uploads) live on the project. Email templates support {{project.name}}, {{project.slug}}, {{form.name}}, {{form.slug}}, {{count}} (1-based clean submissions on this form, including the current one), and any submission field such as {{name}} or {{email}}. Use a fallback with {{name | "New submission"}}. Missing fields render empty and never error. Do not pass HTML; Furrow renders one owned layout. Plans are capacity, not a feature ladder. Free: one workspace, 100 clean submissions/month pooled on the team, 3 active (non-archived) projects, 30-day submission retention, and email.footer_mode / branding.mode stay furrow (other values return plan_limit). Yearly ($199/year): extra workspaces, 10,000 submissions/month, unlimited projects, 730-day retention, branding.mode furrow | off | agency. Expansion packs are $99/year each and add 5,000 submissions/month on a yearly account. MCP, webhooks, snippets, inheritance, Turnstile, and email templates stay available on free. Spam, honeypot, and rejected posts do not count. Use create_upgrade_link to hand a human a Stripe Checkout (or Customer Portal) URL. Pass product=expansion on a yearly team to add a pack. Checkbox groups, select multiple, and other multi-value HT…
| Name | Type | Req | Description |
|---|---|---|---|
| allowed_domains | array | – | Hostnames allowed to post to this project's forms (example.com, www.example.com). Empty accepts any origin. |
| default_redirect_url | – | – | Where classic HTML posts redirect after success. Null returns JSON/inline success instead. |
| object | – | Notification email template for the project: subject, from_name, intro, footer_mode, include_meta. | |
| forms | array | – | Forms to create or update on the site, matched by slug. Re-running is safe. |
| from_name | – | – | Legacy From display name. Prefer email.from_name. |
| honeypot_field | string | – | Name of the hidden honeypot input the snippet emits. Defaults to _gotcha. |
| name | string | yes | Client (company) display name. |
| notify_bcc | array | – | Bcc'd on every notification email (max 10), hidden from the other recipients — use it when an agency wants a silent copy of a client's leads. Copies only: an email still needs at least one notify_ema… |
| notify_cc | array | – | Cc'd on every notification email (max 10). Copies only: an email still needs at least one notify_emails address, and an address on more than one list is sent once (To, then Cc, then Bcc). Copies get… |
| notify_emails | array | – | Addresses that receive each clean submission (max 10). Inherited by every form. Required unless webhook_url is set — ask the human which inbox should get submissions. |
| notify_phones | array | – | E.164 numbers that get a short "new lead, check your email" text per clean submission (max 5). Inherited by every form. Never sent for spam. Text messages need the team's own Twilio account first (up… |
| project_name | string | – | Website display name. Defaults to the client name. |
| project_slug | string | – | Website slug. Defaults to the client slug. |
| rate_limit_per_ip | integer | – | Max submissions per IP within rate_limit_window_s. |
| rate_limit_window_s | integer | – | Rate-limit window in seconds (max 86400). |
| require_turnstile | boolean | – | Reject submissions that lack a valid Turnstile token. |
| slug | string | yes | Lowercase hyphenated identifier, unique per team. Used for idempotent re-runs. |
| team_id | string | – | Team id from list_teams. Required for operator tokens and OAuth logins; team-scoped frw_ tokens may omit it. |
| turnstile_secret | – | – | Cloudflare Turnstile secret used to verify tokens server-side. Null removes it. |
| turnstile_site_key | – | – | Cloudflare Turnstile site key for the frontend widget. Null removes it. |
| upload_allowed_types | array | – | Allowed upload MIME types, e.g. application/pdf or image/*. |
| upload_max_file_bytes | integer | – | Max bytes per file (up to 25 MB). |
| upload_max_files | integer | – | Max files per submission (up to 20). |
| upload_max_total_bytes | integer | – | Max total upload bytes per submission (up to 50 MB). |
| uploads_enabled | boolean | – | Accept multipart file fields on this project's forms. |
| webhook_secret | – | – | HMAC-SHA256 secret for the X-Furrow-Signature header. Omit to have one generated and returned. |
| webhook_url | – | – | Public https endpoint that receives a signed JSON POST per clean submission. Null disables it. |
No output schema declared.
No examples provided.
create_client Create client ~184
Use to add a client (company) by slug. Idempotent on slug unless strict is true. Operator tokens (all workspaces) must pass team_id from list_teams. Team-scoped tokens may omit team_id and cannot target another workspace. Prefer bootstrap_site when also creating a website and forms. Do not put Turnstile or webhooks on a client — those live on the project.
| Name | Type | Req | Description |
|---|---|---|---|
| name | string | yes | Client (company) display name. |
| slug | string | yes | Lowercase hyphenated identifier, unique per team. Used for idempotent re-runs. |
| strict | boolean | – | When true, fail if the slug already exists instead of returning the existing record. |
| team_id | string | – | Team id from list_teams. Required for operator tokens and OAuth logins; team-scoped frw_ tokens may omit it. |
No output schema declared.
No examples provided.
create_form Create form ~590
Use to add a form under an existing project_id. Idempotent on slug unless strict is true. Overrides are nullable; omit them to inherit project notify emails, webhook, redirect, require_turnstile, and email templates. Pass email.subject / email.intro to override notification copy for this form only. Pass webhook_url_override to send this form to a different URL. Field contract labels (label) are used on notification emails. Checkbox groups, select multiple, and other multi-value HTML fields must use a [] suffix on the name (name="services[]") or only the last checked value is stored. Put services[] on field_contract.name too. JSON/fetch should send a real array without brackets ({ "services": ["a", "b"] }) and must not use Object.fromEntries(formData) — use formData.getAll("services"). Single checkbox, select, or combobox: no brackets. File inputs use multipart POST (name="resume[]" for multiple). Enable uploads on the project first. Downloads are the project inbox at files_url, with the form slug as a folder — never put that URL in a public snippet.
| Name | Type | Req | Description |
|---|---|---|---|
| object | – | Per-form subject and intro overrides for the notification email. | |
| field_contract | – | – | Declared fields (name, type, label, report). Drives get_snippet and the email layout. Null clears it. |
| name | string | yes | Form display name, e.g. Contact or Quote request. |
| notify_bcc_override | – | – | Bcc for this form only. Empty array sends no Bcc. Null inherits the project's notify_bcc. |
| notify_cc_override | – | – | Cc for this form only. Empty array sends no Cc. Null inherits the project's notify_cc. |
| notify_emails_override | – | – | Recipients for this form only. Null inherits the project's notify_emails. |
| notify_phones_override | – | – | Text-alert numbers for this form only (E.164). Empty array silences texts for this form. Null inherits the project's notify_phones. Text messages need the team's own Twilio account first (update_acco… |
| project_id | string | yes | Project (website) id from list_projects, create_project, or bootstrap_site. |
| redirect_url_override | – | – | Success redirect for this form only. Null inherits default_redirect_url. |
| require_turnstile_override | boolean|null | – | Force Turnstile on or off for this form. Null inherits the project setting. |
| slug | string | yes | Lowercase hyphenated identifier, unique per project. Used for idempotent re-runs. |
| strict | boolean | – | When true, fail if the slug already exists instead of returning the existing record. |
| webhook_secret_override | – | – | HMAC secret for this form's webhook. Null inherits the project secret. |
| webhook_url_override | – | – | Webhook endpoint for this form only. Null inherits the project webhook. |
No output schema declared.
No examples provided.
create_project Create project ~1,144
Use to add one website under an existing client_id. Idempotent on slug unless strict is true. Free accounts are limited to 3 active (non-archived) projects; yearly is unlimited. If create_project returns plan_limit, call create_upgrade_link and hand the human the Stripe URL. Prefer bootstrap_site when the client does not exist yet. Optional email sets notification templates (subject, from_name, intro, footer_mode, include_meta). Free accounts keep footer_mode furrow; other values return plan_limit. Set uploads_enabled on the project to accept files. Email templates support {{project.name}}, {{project.slug}}, {{form.name}}, {{form.slug}}, {{count}} (1-based clean submissions on this form, including the current one), and any submission field such as {{name}} or {{email}}. Use a fallback with {{name | "New submission"}}. Missing fields render empty and never error. Do not pass HTML; Furrow renders one owned layout. Plans are capacity, not a feature ladder. Free: one workspace, 100 clean submissions/month pooled on the team, 3 active (non-archived) projects, 30-day submission retention, and email.footer_mode / branding.mode stay furrow (other values return plan_limit). Yearly ($199/year): extra workspaces, 10,000 submissions/month, unlimited projects, 730-day retention, branding.mode furrow | off | agency. Expansion packs are $99/year each and add 5,000 submissions/month on a yearly account. MCP, webhooks, snippets, inheritance, Turnstile, and email templates stay available on free. Spam, honeypot, and rejected posts do not count. Use create_upgrade_link to hand a human a Stripe Checkout (or Customer Portal) URL. Pass product=expansion on a yearly team to add a pack. File inputs use multipart POST (name="resume[]" for multiple). Enable uploads on the project first. Downloads are the project inbox at files_url, with the form slug as a folder — never put that URL in a public snippet. Do not put Turnstile keys on a form.
| Name | Type | Req | Description |
|---|---|---|---|
| allowed_domains | array | – | Hostnames allowed to post to this project's forms (example.com, www.example.com). Empty accepts any origin. |
| client_id | string | yes | Client id from list_clients or create_client. |
| default_redirect_url | – | – | Where classic HTML posts redirect after success. Null returns JSON/inline success instead. |
| object | – | Notification email template for the project: subject, from_name, intro, footer_mode, include_meta. | |
| from_name | – | – | Legacy From display name. Prefer email.from_name. |
| honeypot_field | string | – | Name of the hidden honeypot input the snippet emits. Defaults to _gotcha. |
| name | string | yes | Project (website) display name. |
| notify_bcc | array | – | Bcc'd on every notification email (max 10), hidden from the other recipients — use it when an agency wants a silent copy of a client's leads. Copies only: an email still needs at least one notify_ema… |
| notify_cc | array | – | Cc'd on every notification email (max 10). Copies only: an email still needs at least one notify_emails address, and an address on more than one list is sent once (To, then Cc, then Bcc). Copies get… |
| notify_emails | array | – | Addresses that receive each clean submission (max 10). Inherited by every form. Required unless webhook_url is set — ask the human which inbox should get submissions. |
| notify_phones | array | – | E.164 numbers that get a short "new lead, check your email" text per clean submission (max 5). Inherited by every form. Never sent for spam. Text messages need the team's own Twilio account first (up… |
| rate_limit_per_ip | integer | – | Max submissions per IP within rate_limit_window_s. |
| rate_limit_window_s | integer | – | Rate-limit window in seconds (max 86400). |
| require_turnstile | boolean | – | Reject submissions that lack a valid Turnstile token. |
| slug | string | yes | Lowercase hyphenated identifier, unique per client. Used for idempotent re-runs. |
| strict | boolean | – | When true, fail if the slug already exists instead of returning the existing record. |
| turnstile_secret | – | – | Cloudflare Turnstile secret used to verify tokens server-side. Null removes it. |
| turnstile_site_key | – | – | Cloudflare Turnstile site key for the frontend widget. Null removes it. |
| upload_allowed_types | array | – | Allowed upload MIME types, e.g. application/pdf or image/*. |
| upload_max_file_bytes | integer | – | Max bytes per file (up to 25 MB). |
| upload_max_files | integer | – | Max files per submission (up to 20). |
| upload_max_total_bytes | integer | – | Max total upload bytes per submission (up to 50 MB). |
| uploads_enabled | boolean | – | Accept multipart file fields on this project's forms. |
| webhook_secret | – | – | HMAC-SHA256 secret for the X-Furrow-Signature header. Omit to have one generated and returned. |
| webhook_url | – | – | Public https endpoint that receives a signed JSON POST per clean submission. Null disables it. |
No output schema declared.
No examples provided.
create_upgrade_link Create upgrade link ~396
Use when a free team is blocked on the 3-project, 100-submission, or one-workspace limit, or when a human should upgrade to yearly ($199/year) so you can keep adding projects, workspaces, and storing new submissions. Returns a Stripe Checkout URL to hand the human. If the team is already yearly, omit product to get a Stripe Customer Portal URL, or pass product=expansion for a $99/year pack that adds 5,000 submissions/month. Do not change plan in the database — Stripe webhooks do that. Plans are capacity, not a feature ladder. Free: one workspace, 100 clean submissions/month pooled on the team, 3 active (non-archived) projects, 30-day submission retention, and email.footer_mode / branding.mode stay furrow (other values return plan_limit). Yearly ($199/year): extra workspaces, 10,000 submissions/month, unlimited projects, 730-day retention, branding.mode furrow | off | agency. Expansion packs are $99/year each and add 5,000 submissions/month on a yearly account. MCP, webhooks, snippets, inheritance, Turnstile, and email templates stay available on free. Spam, honeypot, and rejected posts do not count. Use create_upgrade_link to hand a human a Stripe Checkout (or Customer Portal) URL. Pass product=expansion on a yearly team to add a pack. Operator tokens (all workspaces) must pass team_id from list_teams. Team-scoped tokens may omit team_id and cannot target another workspace.
| Name | Type | Req | Description |
|---|---|---|---|
| product | string | – | yearly starts the $199/year plan; expansion adds a $99/year 5,000-submission pack to a yearly team. |
| team_id | string | – | Team id from list_teams. Required for operator tokens and OAuth logins; team-scoped frw_ tokens may omit it. |
No output schema declared.
No examples provided.
get_account Get account ~331
Use to read the team's plan, usage this month, limits, expansion_packs, retention_days, branding, and AI spam filter (ai.typesafe_key_set, ai.notify_suspected_spam), and text alerts (sms.configured, provider, account_sid, from). The TypeSafe key and Twilio Auth Token are never returned. Plans are capacity, not a feature ladder. Free: one workspace, 100 clean submissions/month pooled on the team, 3 active (non-archived) projects, 30-day submission retention, and email.footer_mode / branding.mode stay furrow (other values return plan_limit). Yearly ($199/year): extra workspaces, 10,000 submissions/month, unlimited projects, 730-day retention, branding.mode furrow | off | agency. Expansion packs are $99/year each and add 5,000 submissions/month on a yearly account. MCP, webhooks, snippets, inheritance, Turnstile, and email templates stay available on free. Spam, honeypot, and rejected posts do not count. Use create_upgrade_link to hand a human a Stripe Checkout (or Customer Portal) URL. Pass product=expansion on a yearly team to add a pack. Operator tokens (all workspaces) must pass team_id from list_teams. Team-scoped tokens may omit team_id and cannot target another workspace. Do not use this to list projects — call list_projects.
| Name | Type | Req | Description |
|---|---|---|---|
| team_id | string | – | Team id from list_teams. Required for operator tokens and OAuth logins; team-scoped frw_ tokens may omit it. |
No output schema declared.
No examples provided.
get_client Get client ~46
Use to inspect one client. Do not use to list that client's sites — call list_projects with client_id.
| Name | Type | Req | Description |
|---|---|---|---|
| client_id | string | yes | Client id from list_clients or create_client. |
No output schema declared.
No examples provided.
get_form Get form ~126
Use to read a form plus resolved and inherited settings, including resolved.email and resolved.uploads. files_url is the private inbox folder for this form under the project inbox (do not put it in a public snippet). Turnstile always inherits from the project (inherited.turnstile is true). Form webhook_url_override is nullable; null means inherit the project webhook. Forms may override email.subject and email.intro only. Do not use to generate embed code — call get_snippet.
| Name | Type | Req | Description |
|---|---|---|---|
| form_id | string | yes | Form id from list_forms, create_form, or bootstrap_site. |
No output schema declared.
No examples provided.
get_project Get project ~265
Use to inspect one website's settings, domains, webhook URL, email templates, upload policy, plan, usage this month, limits, retention_days, and branding. Returns stored values plus resolved.email. Secrets are never returned. Plans are capacity, not a feature ladder. Free: one workspace, 100 clean submissions/month pooled on the team, 3 active (non-archived) projects, 30-day submission retention, and email.footer_mode / branding.mode stay furrow (other values return plan_limit). Yearly ($199/year): extra workspaces, 10,000 submissions/month, unlimited projects, 730-day retention, branding.mode furrow | off | agency. Expansion packs are $99/year each and add 5,000 submissions/month on a yearly account. MCP, webhooks, snippets, inheritance, Turnstile, and email templates stay available on free. Spam, honeypot, and rejected posts do not count. Use create_upgrade_link to hand a human a Stripe Checkout (or Customer Portal) URL. Pass product=expansion on a yearly team to add a pack. Do not use to list forms — call list_forms.
| Name | Type | Req | Description |
|---|---|---|---|
| project_id | string | yes | Project (website) id from list_projects, create_project, or bootstrap_site. |
No output schema declared.
No examples provided.
get_snippet Get form snippet ~349
Use after the form exists to get copy-paste html, astro, or next code that posts to /s/:publicKey. Do not invent a submit URL — this tool returns it. Snippets are single-value inputs; write checkbox groups and multi-selects yourself. Checkbox groups, select multiple, and other multi-value HTML fields must use a [] suffix on the name (name="services[]") or only the last checked value is stored. Put services[] on field_contract.name too. JSON/fetch should send a real array without brackets ({ "services": ["a", "b"] }) and must not use Object.fromEntries(formData) — use formData.getAll("services"). Single checkbox, select, or combobox: no brackets. File inputs use multipart POST (name="resume[]" for multiple). Enable uploads on the project first. Downloads are the project inbox at files_url, with the form slug as a folder — never put that URL in a public snippet. After dropping the snippet, add visitor-facing success UI: a thank-you page plus default_redirect_url for classic HTML POST, or an on-page message when using fetch/{ok:true}. Do not leave visitors looking at JSON. See furrow://docs/submit-success. Hardcode submit_url as returned; the public key is not a secret. Do not move it into .env / NEXT_PUBLIC_* / PUBLIC_* or ask the human to set environment variables. See furrow://docs/testing.
| Name | Type | Req | Description |
|---|---|---|---|
| form_id | string | yes | Form id from list_forms, create_form, or bootstrap_site. |
| framework | string | yes | Snippet flavor: html (plain form), astro (component), or next (React client component). |
No output schema declared.
No examples provided.
get_submission Get submission ~76
Use to read one stored submission by id, including file metadata and files_url (the form inbox). Do not use this for live submit tests — POST to /s/:publicKey instead. Do not expect signed bucket URLs — download from the inbox.
| Name | Type | Req | Description |
|---|---|---|---|
| submission_id | string | yes | Submission id from list_submissions or a webhook payload. |
No output schema declared.
No examples provided.
list_clients List clients ~149
Use to browse clients (companies). Operator tokens (all workspaces) must pass team_id from list_teams. Team-scoped tokens may omit team_id and cannot target another workspace. Do not use to list websites — call list_projects with client_id. Archived clients are hidden unless status=all or archived.
| Name | Type | Req | Description |
|---|---|---|---|
| cursor | string | – | Opaque cursor from the previous page's next_cursor. |
| limit | integer | – | Page size, max 100. |
| status | string | – | Filter by archive state. Defaults to active. |
| team_id | string | – | Team id from list_teams. Required for operator tokens and OAuth logins; team-scoped frw_ tokens may omit it. |
No output schema declared.
No examples provided.
list_forms List forms ~179
Use to list forms. Pass project_id for one website or client_id for one company (team is inferred). Otherwise Operator tokens (all workspaces) must pass team_id from list_teams. Team-scoped tokens may omit team_id and cannot target another workspace. Do not use to read resolved inheritance — call get_form.
| Name | Type | Req | Description |
|---|---|---|---|
| client_id | string | – | Only forms under this client's projects. |
| cursor | string | – | Opaque cursor from the previous page's next_cursor. |
| limit | integer | – | Page size, max 100. |
| project_id | string | – | Only forms in this project. |
| status | string | – | Filter by archive state. Defaults to active. |
| team_id | string | – | Team id from list_teams. Required for operator tokens and OAuth logins; team-scoped frw_ tokens may omit it. |
No output schema declared.
No examples provided.
list_projects List projects ~176
Use to browse websites. Pass client_id to list one client's sites (team is inferred). Without client_id, Operator tokens (all workspaces) must pass team_id from list_teams. Team-scoped tokens may omit team_id and cannot target another workspace. Do not use to read one project's settings — call get_project. Archived projects are hidden unless status=all or archived.
| Name | Type | Req | Description |
|---|---|---|---|
| client_id | string | – | Only projects under this client. |
| cursor | string | – | Opaque cursor from the previous page's next_cursor. |
| limit | integer | – | Page size, max 100. |
| status | string | – | Filter by archive state. Defaults to active. |
| team_id | string | – | Team id from list_teams. Required for operator tokens and OAuth logins; team-scoped frw_ tokens may omit it. |
No output schema declared.
No examples provided.
list_submissions List submissions ~217
Use to inspect recent posts. Available on free and yearly. Pass project_id or form_id to infer the team; omit both and Operator tokens (all workspaces) must pass team_id from list_teams. Team-scoped tokens may omit team_id and cannot target another workspace. Free teams prune submissions after 30 days; yearly after 730 days. Do not use to read a single submission — call get_submission.
| Name | Type | Req | Description |
|---|---|---|---|
| cursor | string | – | Opaque cursor from the previous page's next_cursor. |
| form_id | string | – | Only submissions to this form. |
| limit | integer | – | Page size, max 100. |
| project_id | string | – | Only submissions in this project. |
| since | string | – | ISO 8601 timestamp; only submissions created after this instant. |
| spam | string | – | Which submissions to return. Defaults to clean. |
| team_id | string | – | Team id from list_teams. Required for operator tokens and OAuth logins; team-scoped frw_ tokens may omit it. |
No output schema declared.
No examples provided.
list_teams List teams ~96
Use to see workspaces this token can act on. A team-scoped frw_ token returns that team only. An operator token or an MCP OAuth login returns every team you belong to — pass team_id on list_clients, create_client, and bootstrap_site. Creating another workspace is dashboard-only after signing in and requires a yearly plan; free accounts stay on one team. Do not use this to list clients — call list_clients.
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
move_client Move client to another team ~204
Use when the human asks to move a client (company) and all its projects, forms, submissions, and files into another workspace they own. Public keys, snippets, inbox links, and webhook secrets stay the same, so the live site needs no change. Needs an owner of both teams (dashboard session or operator token; team-scoped tokens cannot). Refused when the destination has a client with the same slug (pass slug), when a free destination would pass 3 projects, or when the client has text alert numbers and the destination has no Twilio. Confirm the destination team name with the human first. Do not use this to rename or archive.
| Name | Type | Req | Description |
|---|---|---|---|
| client_id | string | yes | Client id from list_clients or create_client. |
| slug | string | – | New client slug, only when the destination team already has a client with this one. |
| team_id | string | yes | Destination team id from list_teams. You must own it and the client's current team. |
No output schema declared.
No examples provided.
rotate_project_inbox Rotate project inbox link ~67
Use when a project's private inbox URL may have leaked. Issues a new inbox key; every previously shared inbox link stops working immediately. get_project returns the new files_url.
| Name | Type | Req | Description |
|---|---|---|---|
| project_id | string | yes | Project (website) id from list_projects, create_project, or bootstrap_site. |
No output schema declared.
No examples provided.
test_sms Test SMS ~157
Use after setting notify_phones to send one test text to each of the project's numbers through the team's Twilio account. Returns per-number results with Twilio's error when one fails. Fails if the team has no Twilio account (update_account sms) or the project has no notify_phones. A successful result means Twilio accepted it; ask the human to confirm it arrived, since unregistered US senders are filtered by carriers after Twilio accepts. Error codes and fixes are in furrow://docs/text-alerts. Do not use this to test email or the webhook — call test_webhook for the webhook.
| Name | Type | Req | Description |
|---|---|---|---|
| project_id | string | yes | Project (website) id from list_projects, create_project, or bootstrap_site. |
No output schema declared.
No examples provided.
test_webhook Test webhook ~87
Use to POST a signed webhook.test event to the project's webhook URL. Available on free and yearly. Do not use this to inspect past deliveries — that is REST GET /api/projects/:id/webhook-deliveries. Fails if no webhook URL and secret are set.
| Name | Type | Req | Description |
|---|---|---|---|
| project_id | string | yes | Project (website) id from list_projects, create_project, or bootstrap_site. |
No output schema declared.
No examples provided.
update_account Update account ~623
Use to rename the workspace, set branding, configure the AI spam filter, or connect the team's own Twilio account for new-lead text alerts. Pass sms { account_sid, auth_token, from } to save Twilio (auth_token is write-only; omit it later to keep the saved one; sms: null disconnects). Numbers to text are notify_phones on the project. US senders must finish A2P 10DLC or toll-free verification in Twilio or carriers drop the texts. To set it up with a human who has never used Twilio, follow furrow://docs/text-alerts. Pass ai.typesafe_api_key to save this team's TypeSafe key (null clears it; the key is write-only). ai.notify_suspected_spam (default true) emails notify addresses with a Potential spam label for every spam catch — rule-based or Jev — except exact duplicates; set it false to silence both. Spam never sends a webhook. Free accounts keep branding.mode and email.footer_mode at furrow; asking for anything else returns plan_limit — tell the human the custom footer is a Yearly feature and offer create_upgrade_link. Yearly may set branding.mode to furrow, off, or agency (name + optional link + optional logo; Furrow keeps the layout, no raw HTML). Plans are capacity, not a feature ladder. Free: one workspace, 100 clean submissions/month pooled on the team, 3 active (non-archived) projects, 30-day submission retention, and email.footer_mode / branding.mode stay furrow (other values return plan_limit). Yearly ($199/year): extra workspaces, 10,000 submissions/month, unlimited projects, 730-day retention, branding.mode furrow | off | agency. Expansion packs are $99/year each and add 5,000 submissions/month on a yearly account. MCP, webhooks, snippets, inheritance, Turnstile, and email templates stay available on free. Spam, honeypot, and rejected posts do not count. Use create_upgrade_link to hand a human a Stripe Checkout (or Customer Portal) URL. Pass product=expansion on a yearly team to add a pack. Operator tokens (all workspaces) must pass team_id from list_teams.…
| Name | Type | Req | Description |
|---|---|---|---|
| ai | object | – | AI spam filter. Off until this team saves its own TypeSafe key. One Jev call per heuristics-clean submission. |
| branding | object | – | Account-wide branding for notification emails and hosted pages. |
| name | string | – | New workspace display name. |
| sms | – | – | The team's own Twilio account for new-lead text alerts. Null removes it. Numbers to text live on the project (notify_phones). |
| team_id | string | – | Team id from list_teams. Required for operator tokens and OAuth logins; team-scoped frw_ tokens may omit it. |
No output schema declared.
No examples provided.
update_client Update client ~61
Use to rename a client. Do not use this to change domains, Turnstile, or webhooks — call update_project.
| Name | Type | Req | Description |
|---|---|---|---|
| client_id | string | yes | Client id from list_clients or create_client. |
| name | string | – | New client display name. |
No output schema declared.
No examples provided.
update_form Update form ~637
Use to patch form overrides. Pass null on an override to inherit again. Set email.subject or email.intro to override project notification copy for this form only; from_name, footer_mode, and include_meta stay on the project. Email templates support {{project.name}}, {{project.slug}}, {{form.name}}, {{form.slug}}, {{count}} (1-based clean submissions on this form, including the current one), and any submission field such as {{name}} or {{email}}. Use a fallback with {{name | "New submission"}}. Missing fields render empty and never error. Do not pass HTML; Furrow renders one owned layout. Set webhook_url_override to override the project webhook for this form. notify_cc_override / notify_bcc_override replace the project's copies ([] sends none). notify_phones_override replaces the project's text-alert numbers ([] silences texts for this form). Do not use this to change Turnstile keys — those live on the project. Checkbox groups, select multiple, and other multi-value HTML fields must use a [] suffix on the name (name="services[]") or only the last checked value is stored. Put services[] on field_contract.name too. JSON/fetch should send a real array without brackets ({ "services": ["a", "b"] }) and must not use Object.fromEntries(formData) — use formData.getAll("services"). Single checkbox, select, or combobox: no brackets. File inputs use multipart POST (name="resume[]" for multiple). Enable uploads on the project first. Downloads are the project inbox at files_url, with the form slug as a folder — never put that URL in a public snippet.
| Name | Type | Req | Description |
|---|---|---|---|
| object | – | Per-form subject and intro overrides for the notification email. | |
| field_contract | – | – | Declared fields (name, type, label, report). Drives get_snippet and the email layout. Null clears it. |
| form_id | string | yes | Form id from list_forms, create_form, or bootstrap_site. |
| name | string | – | New form display name. |
| notify_bcc_override | – | – | Bcc for this form only. Empty array sends no Bcc. Null inherits the project's notify_bcc. |
| notify_cc_override | – | – | Cc for this form only. Empty array sends no Cc. Null inherits the project's notify_cc. |
| notify_emails_override | – | – | Recipients for this form only. Null inherits the project's notify_emails. |
| notify_phones_override | – | – | Text-alert numbers for this form only (E.164). Empty array silences texts for this form. Null inherits the project's notify_phones. Text messages need the team's own Twilio account first (update_acco… |
| redirect_url_override | – | – | Success redirect for this form only. Null inherits default_redirect_url. |
| require_turnstile_override | boolean|null | – | Force Turnstile on or off for this form. Null inherits the project setting. |
| webhook_secret_override | – | – | HMAC secret for this form's webhook. Null inherits the project secret. |
| webhook_url_override | – | – | Webhook endpoint for this form only. Null inherits the project webhook. |
No output schema declared.
No examples provided.
update_project Update project ~1,131
Use to patch website settings. Nested email sets notification templates: email.subject, email.from_name, email.intro, email.footer_mode (furrow | minimal | off), email.include_meta. Optional branding updates the team (mode furrow | off | agency on yearly only; other modes return plan_limit on free). Set uploads_enabled and upload_allowed_types here — forms inherit them. notify_cc and notify_bcc copy every notification email (Bcc stays hidden from the client — use it for an agency's quiet copy); forms inherit them. notify_phones (E.164) get a short new-lead text per clean submission once the team has Twilio set up (update_account sms); forms inherit them. Email templates support {{project.name}}, {{project.slug}}, {{form.name}}, {{form.slug}}, {{count}} (1-based clean submissions on this form, including the current one), and any submission field such as {{name}} or {{email}}. Use a fallback with {{name | "New submission"}}. Missing fields render empty and never error. Do not pass HTML; Furrow renders one owned layout. Plans are capacity, not a feature ladder. Free: one workspace, 100 clean submissions/month pooled on the team, 3 active (non-archived) projects, 30-day submission retention, and email.footer_mode / branding.mode stay furrow (other values return plan_limit). Yearly ($199/year): extra workspaces, 10,000 submissions/month, unlimited projects, 730-day retention, branding.mode furrow | off | agency. Expansion packs are $99/year each and add 5,000 submissions/month on a yearly account. MCP, webhooks, snippets, inheritance, Turnstile, and email templates stay available on free. Spam, honeypot, and rejected posts do not count. Use create_upgrade_link to hand a human a Stripe Checkout (or Customer Portal) URL. Pass product=expansion on a yearly team to add a pack. File inputs use multipart POST (name="resume[]" for multiple). Enable uploads on the project first. Downloads are the project inbox at files_url, with the form slug as a folder — never put that URL in…
| Name | Type | Req | Description |
|---|---|---|---|
| allowed_domains | array | – | Replace the allowed hostnames. Empty array accepts any origin. |
| branding | object | – | Per-project branding override for notification emails and hosted pages. |
| default_redirect_url | – | – | Where classic HTML posts redirect after success. Null returns JSON/inline success instead. |
| object | – | Notification email template for the project: subject, from_name, intro, footer_mode, include_meta. | |
| from_name | – | – | Legacy From display name. Prefer email.from_name. |
| honeypot_field | string | – | Name of the hidden honeypot input the snippet emits. Defaults to _gotcha. |
| name | string | – | New project display name. |
| notify_bcc | array | – | Bcc'd on every notification email (max 10), hidden from the other recipients — use it when an agency wants a silent copy of a client's leads. Copies only: an email still needs at least one notify_ema… |
| notify_cc | array | – | Cc'd on every notification email (max 10). Copies only: an email still needs at least one notify_emails address, and an address on more than one list is sent once (To, then Cc, then Bcc). Copies get… |
| notify_emails | array | – | Replace the notification recipients (max 10). Cannot be emptied while the project has no webhook_url. |
| notify_phones | array | – | Replace the text-alert numbers (E.164, max 5). Empty array turns texts off. Text messages need the team's own Twilio account first (update_account sms). |
| project_id | string | yes | Project (website) id from list_projects, create_project, or bootstrap_site. |
| rate_limit_per_ip | integer | – | Max submissions per IP within rate_limit_window_s. |
| rate_limit_window_s | integer | – | Rate-limit window in seconds (max 86400). |
| require_turnstile | boolean | – | Reject submissions that lack a valid Turnstile token. |
| turnstile_secret | – | – | Cloudflare Turnstile secret used to verify tokens server-side. Null removes it. |
| turnstile_site_key | – | – | Cloudflare Turnstile site key for the frontend widget. Null removes it. |
| upload_allowed_types | array | – | Allowed upload MIME types, e.g. application/pdf or image/*. |
| upload_max_file_bytes | integer | – | Max bytes per file (up to 25 MB). |
| upload_max_files | integer | – | Max files per submission (up to 20). |
| upload_max_total_bytes | integer | – | Max total upload bytes per submission (up to 50 MB). |
| uploads_enabled | boolean | – | Accept multipart file fields on this project's forms. |
| webhook_secret | – | – | HMAC-SHA256 secret for the X-Furrow-Signature header. Omit to have one generated and returned. |
| webhook_url | – | – | Public https endpoint that receives a signed JSON POST per clean submission. Null disables it. |
No output schema declared.
No examples provided.
update_team Update team ~136
Use to rename a team. Operator tokens (all workspaces) must pass team_id from list_teams. Team-scoped tokens may omit team_id and cannot target another workspace. Do not use this to create another workspace — that is dashboard-only and requires yearly. For plan, usage, retention, and branding, call get_account / update_account. Do not use this to change clients or projects.
| Name | Type | Req | Description |
|---|---|---|---|
| name | string | yes | New team (workspace) display name. |
| team_id | string | – | Team id from list_teams. Required for operator tokens and OAuth logins; team-scoped frw_ tokens may omit it. |
No output schema declared.
No examples provided.
upsert_project_webhook Upsert project webhook ~138
Use to set or replace the project webhook URL. Available on free and yearly. A signing secret is generated once if the project has none. Forms inherit this unless webhook_url_override is set. Do not use this for a one-off delivery — call test_webhook.
| Name | Type | Req | Description |
|---|---|---|---|
| project_id | string | yes | Project (website) id from list_projects, create_project, or bootstrap_site. |
| webhook_secret | – | – | HMAC-SHA256 secret for X-Furrow-Signature. Omit to have one generated and returned. |
| webhook_url | – | yes | Public https endpoint that receives a signed JSON POST per clean submission. Null disables it. |
No output schema declared.
No examples provided.
How do I install the com.furrowforms/furrow-forms MCP server?
com.furrowforms/furrow-forms is a hosted endpoint at https://api.furrowforms.com/mcp, so there is nothing to install locally. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.
remote · api.furrowforms.com
claude mcp add --transport http com-furrowforms-furrow-forms 'https://api.furrowforms.com/mcp'
What is the com.furrowforms/furrow-forms MCP server?
com.furrowforms/furrow-forms is an MCP server listed in the public MCP registry as com.furrowforms/furrow-forms. Form backend an agent runs end to end: provision forms, snippets, spam, signed webhooks. This page covers its hosted endpoint (https://api.furrowforms.com/mcp).
Is the com.furrowforms/furrow-forms MCP server safe to use?
com.furrowforms/furrow-forms scores 95 out of 100 on VerifyMCP. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.
What tools does the com.furrowforms/furrow-forms MCP server expose?
com.furrowforms/furrow-forms exposes 29 tools: list_teams, update_team, get_account, update_account, create_upgrade_link, and 24 more. Their descriptions and schemas cost roughly 9,084 tokens of context every time the server is loaded.
Does the com.furrowforms/furrow-forms MCP server require authentication?
Yes. com.furrowforms/furrow-forms asked us for credentials when we connected, so you will need to authorise it in your MCP client before it can do anything.
Is the com.furrowforms/furrow-forms MCP server still maintained?
com.furrowforms/furrow-forms is still listed as active in the MCP registry. We last reached this channel on 4 November 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.