npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@formbuilder-cloud/mcp

v0.1.1

Published

MCP server for formBuilder Cloud: lets AI agents (Claude, Cursor, VS Code) create, validate and publish forms, get embed snippets and read submissions through the form builder API, with an API key (FORMBUILDER_API_KEY).

Readme

@formbuilder-cloud/mcp

The MCP server for formBuilder Cloud, the form builder API and headless forms backend. It lets an AI agent (Claude, Cursor, VS Code Copilot, any MCP client) create a form from a formBuilder definition, validate and publish it, get the embed snippet, and read the submissions back, with nothing but an API key. It runs locally over stdio and calls the same /v1 API as the SDK and the fb CLI, under the same scopes and limits.

Not published yet. @formbuilder-cloud/mcp is not on npm until Kevin releases it (mcp/RELEASING.md), so the npx commands below fail until then. From a checkout: npm ci && npm -w mcp run build, then use node /path/to/formbuilder-cloud/mcp/dist/bin.js as the command.

Install

You need Node.js 20 or later and a management key (fb_mgmt_…). A workspace owner mints one on the dashboard's API keys page. Use scope read to let the agent only look, and write to let it create and publish. The server reads the key from FORMBUILDER_API_KEY. Set it in your MCP client's configuration, never in a file you commit.

No account yet? Where the API enables sandboxes, one request with no key gives a 7-day sandbox with an expiring write management key: fb sandbox create (the CLI), or curl -X POST https://api.formbuilder.online/v1/sandbox/sessions -H 'Content-Type: application/json' -d '{"keys":true}' and take keys.management.key. Configure the server with that key like any other; it stops working when the sandbox expires. The server itself has no sandbox tool: a tool would put a new secret into the conversation, and the server only ever reads its key from the environment (see docs/agent-quickstart.md in the repository).

Claude Code

claude mcp add formbuilder-cloud --env FORMBUILDER_API_KEY="$FORMBUILDER_API_KEY" -- npx -y @formbuilder-cloud/mcp

Add --scope user to make it available in every project.

Claude Desktop

In claude_desktop_config.json (Settings → Developer → Edit Config):

{
  "mcpServers": {
    "formbuilder-cloud": {
      "command": "npx",
      "args": ["-y", "@formbuilder-cloud/mcp"],
      "env": { "FORMBUILDER_API_KEY": "<YOUR_MANAGEMENT_KEY>" }
    }
  }
}

Cursor

In ~/.cursor/mcp.json (every project), or .cursor/mcp.json in a project you do not commit the key to:

{
  "mcpServers": {
    "formbuilder-cloud": {
      "command": "npx",
      "args": ["-y", "@formbuilder-cloud/mcp"],
      "env": { "FORMBUILDER_API_KEY": "<YOUR_MANAGEMENT_KEY>" }
    }
  }
}

VS Code

In .vscode/mcp.json. VS Code prompts for the key once and stores it securely, so this file can be committed:

{
  "inputs": [
    { "type": "promptString", "id": "formbuilder-api-key", "description": "formBuilder Cloud management key (fb_mgmt_…)", "password": true }
  ],
  "servers": {
    "formbuilder-cloud": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@formbuilder-cloud/mcp"],
      "env": { "FORMBUILDER_API_KEY": "${input:formbuilder-api-key}" }
    }
  }
}

Other clients

The command is npx -y @formbuilder-cloud/mcp (stdio) with FORMBUILDER_API_KEY in its environment. FORMBUILDER_BASE_URL points it at another API, such as the dev stack (http://localhost:8190). Like the SDK, the server accepts only https: URLs, plus http: for loopback hosts (localhost, *.localhost, 127.0.0.0/8, [::1]). A URL with credentials, a query or a fragment is refused, and so is a key with spaces or non-ASCII characters. In each case the server exits with code 1 before sending anything, and the message echoes neither the URL nor the key.

From an empty workspace to an embedded form

Ask your agent something like "Create a contact form with name, email and message in formBuilder Cloud, publish it and give me the embed code." With a write key it can do it all through this server:

  1. whoami: the key's scope and workspace.
  2. list_projects, or create_project in an empty workspace.
  3. validate_definition: checks the field array against the form-definition JSON Schema, locally.
  4. create_form in the project (optionally with the definition).
  5. update_draft: saves the definition. Its answer's publish_check lists anything publishing would refuse.
  6. publish_form: the first version goes live.
  7. get_embed_snippet: HTML, npm, plain-fetch and curl snippets for the form.

The snippets carry the placeholder <YOUR_fb_col_KEY>. A person mints a collection key for the form (dashboard → API keys, or fb keys mint --kind collection --form <id> with the CLI) and puts it in its place. A collection key is public by design: it ships in the page. This server never mints keys.

Then, after a test submission: list_submissions, get_submission, export_submissions and get_usage.

Tools

Tool names are a contract (FB-09 R-2): renaming one is a breaking change. Each tool's input schema is generated from the API's OpenAPI document (npm -w mcp run generate), so arguments, limits and enums are the API's own.

| Tool | What it does | API | Key scope | Hints | |---|---|---|---|---| | whoami | The key's kind (never the key), scope and workspace | GET /v1/me | read | read-only | | list_projects | Projects of the workspace, one page | GET /v1/workspaces/{ws}/projects | read | read-only | | create_project | A new project | POST /v1/workspaces/{ws}/projects | write | not idempotent | | list_forms | Forms of the workspace (filter by project, name, status), one page | GET /v1/workspaces/{ws}/forms | read | read-only | | get_form | A form, plus its draft definition and etag | GET /v1/forms/{f} (+ /draft) | read | read-only | | create_form | A new form in a project, optionally with a draft | POST /v1/projects/{p}/forms | write | not idempotent | | update_draft | Replaces the draft; answers publish_check. if_match for a conditional save | PUT /v1/forms/{f}/draft | write | destructive (replaces the draft), idempotent | | validate_definition | Checks a definition against the JSON Schema, locally (no request) | none | none | read-only | | publish_form | Publishes the draft as a new version (unchanged draft: the active version again) | POST /v1/forms/{f}:publish | write | idempotent | | get_embed_snippet | Embed snippets with the key placeholder | GET /v1/forms/{f}/embed | read | read-only | | list_submissions | Submissions of a form, newest first, one page, with filters | GET /v1/forms/{f}/submissions | read | read-only | | get_submission | One submission with its values and deliveries | GET /v1/submissions/{id} | read | read-only | | export_submissions | CSV or NDJSON export, capped (see below) | GET /v1/forms/{f}/submissions/export | read | read-only | | get_usage | Production usage for a month and the six before it | GET /v1/workspaces/{ws}/usage | read | read-only |

Every tool answers with structuredContent and the same JSON as text. Lists default to 20 items a page (the API allows up to 100). To get the next page, pass next_cursor back as cursor. There are no delete tools.

Errors come back as tool results with isError: true, so the agent can read and fix them. An API error keeps its RFC 7807 members: a stable type URI (documented at that URI and in the error-catalog resource), status, detail, hint, per-field errors, retryable and retry_after_seconds. The server's own errors use urn:formbuilder-cloud:mcp:<network|timeout|invalid-request|cancelled|internal>. The SDK already retries safe requests (at most 3 attempts, honouring Retry-After).

Exports are capped

export_submissions never streams a whole export into the conversation. It reads the API's export only up to max_bytes (default 64 KiB, at most 256 KiB), cuts it after the last complete record (a CSV cell that spans lines is never split), then cancels the download. The answer says truncated, how many submissions it holds, and total_submissions when the whole export fit. For a full export, narrow the filters (accepted_from, accepted_to, version), or use the CLI (fb submissions export --output file.csv) or the dashboard. Exports count against the API's limit of 10 a minute. CSV comes without a byte order mark. JSON exports are not offered here, because a capped JSON document would not parse; use ndjson.

Keys and least privilege

| Key in FORMBUILDER_API_KEY | Tools listed | |---|---| | Management key, scope write | All 14 | | Management key, scope read | All 14. The write tools (create_project, create_form, update_draft, publish_form) get the API's 403, and the error says a write key is needed | | Collection key (fb_col_…) | Only validate_definition. A collection key can only submit to its one form, so management tools are not listed and calling one is refused by the protocol. The key is never sent anywhere | | None | Only validate_definition. The server's instructions tell the agent to ask for a management key |

The key kind comes from the key's prefix, so starting the server sends no request. The scope is only known to the API, which enforces it. A management key acts at most as an editor, so owner-only operations (management keys, members, deleting submissions) are out of reach anyway.

Resources

Static and bundled in the package (no network request):

| URI | What | |---|---| | formbuilder-cloud://schemas/form-definition.v1.json | The form-definition JSON Schema (draft 2020-12), the document the API serves at /v1/schemas/form-definition.v1.json | | formbuilder-cloud://docs/form-definition-schema.md | Field types, attributes, limits and examples | | formbuilder-cloud://docs/errors.json | The error catalog (every problem type, its status, whether it is retryable, how to fix it) | | formbuilder-cloud://docs/webhooks.md | Receiving and verifying webhook deliveries | | formbuilder-cloud://docs/mcp-quickstart.md | This README |

Security and privacy

  • The key goes out only as Authorization: Bearer to the configured API, over https: (or http: on loopback). It is never logged. It never appears in a tool result, a resource or an error message: any full fb_mgmt_…/fb_col_… key in a result is replaced by its kind, e.g. fb_mgmt_[redacted].
  • stdout carries only MCP protocol frames. Logs (one start-up line, internal errors) go to stderr.
  • Submitted values are untrusted. They come from whoever filled in the form. The submission tools say so in their descriptions: an agent should treat them as data, never as instructions.
  • No telemetry. No install ping, no update check. The only requests are the ones your tool calls make. They identify themselves only by User-Agent: formbuilder-mcp/<version> (FB-09 R-5).

Not here (yet)

  • A hosted endpoint (https://api.formbuilder.online/mcp, Streamable HTTP) is planned but not built. Kevin approved stdio first and the hosted endpoint later, behind an off-by-default flag with API-key auth (decision-register item 29, 2026-10-21). The specs do not define its authentication, Origin and session rules or its limits yet.
  • OAuth. Authentication is API keys only; OAuth comes after the hosted endpoint.
  • Key minting and any delete operation, including a sandbox tool (#33): get a sandbox key with the CLI or curl instead, as above.

Development

npm -w mcp run generate          # the tool input schemas from api/openapi.json (CI checks they are current)
npm -w mcp run typecheck
npm -w mcp run build             # dist/ + dist/resources/ (builds sdk/dist first when missing)
npm -w mcp test                  # unit tests with a mocked API; with PG_URL also the e2e suite
npm -w mcp run check:pack        # npm pack --dry-run: files, bin, UNLICENSED, server.json, --version

mcp/test/e2e.test.ts runs the built server as a child process, driven by the MCP SDK's client, against the real API on an ephemeral port. It follows the journey above, from an empty workspace to the embed snippet, then reads back an SDK submission.

server.json is the entry for the official MCP registry. Publishing it is Kevin's step, after the npm release (mcp/RELEASING.md).

Licence

Proprietary: UNLICENSED. Copyright (c) 2026 Kevin Chappell. All rights reserved. You may use it only with the formBuilder Cloud service, under the terms of that service (LICENSE).