{"_id":"@agentkitai/formbridge-mcp-server","_rev":"3-9eaed7cca06a0fe073344c8c24316c15","name":"@agentkitai/formbridge-mcp-server","dist-tags":{"latest":"0.4.1"},"versions":{"0.3.0":{"name":"@agentkitai/formbridge-mcp-server","version":"0.3.0","keywords":["mcp","model-context-protocol","formbridge","intake","schema","ai-agent","tool-server"],"author":{"name":"Amit Paz"},"license":"MIT","_id":"@agentkitai/formbridge-mcp-server@0.3.0","maintainers":[{"name":"amit-paz","email":"amit.paz@gmail.com"}],"homepage":"https://github.com/agentkitai/formbridge#readme","bugs":{"url":"https://github.com/agentkitai/formbridge/issues"},"dist":{"shasum":"63dd3714f6d5e41a8e021d22465b797b6111d584","tarball":"https://registry.npmjs.org/@agentkitai/formbridge-mcp-server/-/formbridge-mcp-server-0.3.0.tgz","fileCount":323,"integrity":"sha512-xefdAVHdspCypBRW9MYNBUSeOwPzfPdjeIpgG9BbzwIaOHQL2osB586K8lIANa795w7aKDEuybfw077H8mTHTQ==","signatures":[{"sig":"MEYCIQDXNziZtPAWRTZLlDRqnn3eL+otP6KnAxz9RwTJRgJT/wIhAL3Kk6xgfUSGvGRP9t+0LBDXDHaYmFG+BmekJeg9tOxC","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":921837},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18.0.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"2bd30b08b5f4642ec78674662f9101bbf237869a","scripts":{"dev":"tsc -p tsconfig.build.json --watch","lint":"eslint src/","test":"vitest","build":"tsc -p tsconfig.build.json","clean":"rm -rf dist","test:run":"vitest run","typecheck":"tsc --noEmit","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"amit-paz","email":"amit.paz@gmail.com"},"overrides":{"fast-uri":"^3.1.2","path-to-regexp":"^8.4.0","fast-xml-parser":"5.3.5","express-rate-limit":"^8.5.1"},"repository":{"url":"git+https://github.com/agentkitai/formbridge.git","type":"git"},"workspaces":["packages/*"],"_npmVersion":"11.5.2","description":"FormBridge MCP Server - Mixed-mode agent-human form submission","directories":{},"_nodeVersion":"24.12.0","dependencies":{"ajv":"^8.12.0","zod":"^3.25.0","hono":"^4.12.25","jose":"^6.1.3","pino":"^10.3.1","ajv-formats":"^3.0.1","prom-client":"^15.1.3","@hono/node-server":"^1.19.13","zod-to-json-schema":"^3.22.4","@modelcontextprotocol/sdk":"^1.0.0","@agentkitai/formbridge-shared":"*"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"pg":"^8.13.0","tsup":"^8.0.1","eslint":"^9.39.2","vitest":"^1.0.0","globals":"^17.2.0","@types/pg":"^8.11.0","@eslint/js":"^9.39.2","typescript":"^5.3.0","@types/node":"^20.0.0","@types/uuid":"^10.0.0","pino-pretty":"^13.1.3","@types/ioredis":"^4.28.10","better-sqlite3":"^12.6.2","@changesets/cli":"^2.29.8","typescript-eslint":"^8.54.0","@aws-sdk/client-s3":"^3.980.0","@vitest/coverage-v8":"^1.2.0","eslint-plugin-react":"^7.37.5","@types/better-sqlite3":"^7.6.13","eslint-config-prettier":"^10.1.8","eslint-plugin-react-hooks":"^7.0.1","@aws-sdk/s3-request-presigner":"^3.980.0"},"peerDependencies":{"pg":"^8.13.0"},"optionalDependencies":{"ioredis":"^5.9.3"},"peerDependenciesMeta":{"pg":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/formbridge-mcp-server_0.3.0_1782502815999_0.6538927338574103","host":"s3://npm-registry-packages-npm-production"}},"0.4.0":{"name":"@agentkitai/formbridge-mcp-server","version":"0.4.0","keywords":["mcp","model-context-protocol","formbridge","intake","schema","ai-agent","tool-server"],"author":{"name":"Amit Paz"},"license":"MIT","_id":"@agentkitai/formbridge-mcp-server@0.4.0","maintainers":[{"name":"amit-paz","email":"amit.paz@gmail.com"}],"homepage":"https://github.com/agentkitai/formbridge#readme","bugs":{"url":"https://github.com/agentkitai/formbridge/issues"},"dist":{"shasum":"27935bef1e3230687631c3e6d66c4574b88c3378","tarball":"https://registry.npmjs.org/@agentkitai/formbridge-mcp-server/-/formbridge-mcp-server-0.4.0.tgz","fileCount":331,"integrity":"sha512-eCrInFc0ZcVzUSeGng6t70dWlytT9xM/Loe7eAaZVSqQkpLv9wDlpKXe1L2tFoTPwLp31kY2d+sxKmaPw+ARvg==","signatures":[{"sig":"MEQCIC3cntKv7yGa6jylVC84zdLyNIxkyDiAugRCyPiGDVdCAiBnUx8CG9mAYbvKQ/zmQEMM3c5UA7SkaEVxRo2qma8o4A==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@agentkitai%2fformbridge-mcp-server@0.4.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":965454},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18.0.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"0461c925dfd1dbdaa25a23b111f1fb50954a5488","scripts":{"dev":"tsc -p tsconfig.build.json --watch","lint":"eslint src/","test":"vitest","build":"tsc -p tsconfig.build.json","clean":"rm -rf dist","test:run":"vitest run","typecheck":"tsc --noEmit","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:b87e06a4-e953-4a76-80eb-c8844f54a31d"}},"overrides":{"fast-uri":"^3.1.2","path-to-regexp":"^8.4.0","fast-xml-parser":"5.3.5","express-rate-limit":"^8.5.1"},"repository":{"url":"git+https://github.com/agentkitai/formbridge.git","type":"git"},"workspaces":["packages/*"],"_npmVersion":"11.18.0","description":"FormBridge MCP Server - Mixed-mode agent-human form submission","directories":{},"_nodeVersion":"24.18.0","dependencies":{"ajv":"^8.12.0","zod":"^3.25.0","hono":"^4.12.25","jose":"^6.1.3","pino":"^10.3.1","ajv-formats":"^3.0.1","prom-client":"^15.1.3","@hono/node-server":"^1.19.13","zod-to-json-schema":"^3.22.4","@modelcontextprotocol/sdk":"^1.0.0","@agentkitai/formbridge-shared":"*"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"pg":"^8.13.0","tsup":"^8.0.1","eslint":"^9.39.2","vitest":"^1.0.0","globals":"^17.2.0","@types/pg":"^8.11.0","@eslint/js":"^9.39.2","typescript":"^5.3.0","@types/node":"^20.0.0","@types/uuid":"^10.0.0","pino-pretty":"^13.1.3","@types/ioredis":"^4.28.10","better-sqlite3":"^12.6.2","@changesets/cli":"^2.29.8","typescript-eslint":"^8.54.0","@aws-sdk/client-s3":"^3.980.0","@vitest/coverage-v8":"^1.2.0","eslint-plugin-react":"^7.37.5","@types/better-sqlite3":"^7.6.13","eslint-config-prettier":"^10.1.8","eslint-plugin-react-hooks":"^7.0.1","@aws-sdk/s3-request-presigner":"^3.980.0"},"peerDependencies":{"pg":"^8.13.0"},"optionalDependencies":{"ioredis":"^5.9.3"},"peerDependenciesMeta":{"pg":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/formbridge-mcp-server_0.4.0_1783178857589_0.7123251058233067","host":"s3://npm-registry-packages-npm-production"}},"0.4.1":{"name":"@agentkitai/formbridge-mcp-server","version":"0.4.1","description":"FormBridge MCP Server - Mixed-mode agent-human form submission","type":"module","main":"./dist/index.js","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"import":"./dist/index.js","types":"./dist/index.d.ts"}},"scripts":{"build":"tsc -p tsconfig.build.json","dev":"tsc -p tsconfig.build.json --watch","typecheck":"tsc --noEmit","test":"vitest","test:run":"vitest run","test:coverage":"vitest run --coverage","lint":"eslint src/","clean":"rm -rf dist"},"keywords":["mcp","model-context-protocol","formbridge","intake","schema","ai-agent","tool-server"],"author":{"name":"Amit Paz"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/agentkitai/formbridge.git"},"homepage":"https://github.com/agentkitai/formbridge#readme","bugs":{"url":"https://github.com/agentkitai/formbridge/issues"},"dependencies":{"@agentkitai/formbridge-shared":"*","@hono/node-server":"^1.19.13","@modelcontextprotocol/sdk":"^1.0.0","ajv":"^8.12.0","ajv-formats":"^3.0.1","hono":"^4.12.25","jose":"^6.1.3","pino":"^10.3.1","prom-client":"^15.1.3","zod":"^3.25.0","zod-to-json-schema":"^3.22.4"},"overrides":{"express-rate-limit":"^8.5.1","fast-uri":"^3.1.2","fast-xml-parser":"5.3.5","path-to-regexp":"^8.4.0"},"devDependencies":{"@aws-sdk/client-s3":"^3.980.0","@aws-sdk/s3-request-presigner":"^3.980.0","@changesets/cli":"^2.29.8","@eslint/js":"^9.39.2","@types/better-sqlite3":"^7.6.13","@types/ioredis":"^4.28.10","@types/node":"^20.0.0","@types/pg":"^8.11.0","@types/uuid":"^10.0.0","@vitest/coverage-v8":"^1.2.0","better-sqlite3":"^12.6.2","eslint":"^9.39.2","eslint-config-prettier":"^10.1.8","eslint-plugin-react":"^7.37.5","eslint-plugin-react-hooks":"^7.0.1","globals":"^17.2.0","pg":"^8.13.0","pino-pretty":"^13.1.3","tsup":"^8.0.1","typescript":"^5.3.0","typescript-eslint":"^8.54.0","vitest":"^1.0.0"},"workspaces":["packages/*"],"optionalDependencies":{"ioredis":"^5.9.3"},"engines":{"node":">=18.0.0"},"publishConfig":{"access":"public"},"peerDependencies":{"pg":"^8.13.0"},"peerDependenciesMeta":{"pg":{"optional":true}},"gitHead":"875f2feaa2fc057e05bcf42771d124636adc88cb","_id":"@agentkitai/formbridge-mcp-server@0.4.1","_nodeVersion":"24.18.0","_npmVersion":"12.0.2","dist":{"integrity":"sha512-9BYBBCgKjsJqpb16QlAAiyQR3HAC3jKYVJxhwk90OiqGyIImRlKnmyzExbPUSnMyBtmUTu15+B8ILDtd9xveQA==","shasum":"e2dd10e3cf9e5ff6d878c8bc92cb18e050e03798","tarball":"https://registry.npmjs.org/@agentkitai/formbridge-mcp-server/-/formbridge-mcp-server-0.4.1.tgz","fileCount":335,"unpackedSize":982317,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@agentkitai%2fformbridge-mcp-server@0.4.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIDl4Pin3Ak0Zk+SSZhMznWKVLMoagcHzwPqXrUJMeGISAiA5cxMXXiZnpneJuIa3QOtUfp3FZSpzlWivuJe3enARvQ=="}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:b87e06a4-e953-4a76-80eb-c8844f54a31d"}},"directories":{},"maintainers":[{"name":"amit-paz","email":"amit.paz@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/formbridge-mcp-server_0.4.1_1785686924690_0.11437045116283717"},"_hasShrinkwrap":false}},"time":{"created":"2026-06-26T19:40:15.835Z","modified":"2026-08-02T16:08:45.256Z","0.3.0":"2026-06-26T19:40:16.201Z","0.4.0":"2026-07-04T15:27:37.766Z","0.4.1":"2026-08-02T16:08:44.930Z"},"bugs":{"url":"https://github.com/agentkitai/formbridge/issues"},"author":{"name":"Amit Paz"},"license":"MIT","homepage":"https://github.com/agentkitai/formbridge#readme","keywords":["mcp","model-context-protocol","formbridge","intake","schema","ai-agent","tool-server"],"repository":{"type":"git","url":"git+https://github.com/agentkitai/formbridge.git"},"description":"FormBridge MCP Server - Mixed-mode agent-human form submission","maintainers":[{"name":"amit-paz","email":"amit.paz@gmail.com"}],"readme":"# FormBridge\n\nMixed-mode agent-human form submission infrastructure. AI agents fill what they know, humans complete the rest — with full field-level attribution, approval workflows, and webhook delivery.\n\n[![CI](https://github.com/agentkitai/formbridge/actions/workflows/ci.yml/badge.svg)](https://github.com/agentkitai/formbridge/actions/workflows/ci.yml)\n[![TypeScript](https://img.shields.io/badge/TypeScript-5.9-blue.svg)](https://www.typescriptlang.org/)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![Node.js](https://img.shields.io/badge/Node.js-%3E%3D18-green.svg)](https://nodejs.org/)\n[![Tests](https://img.shields.io/badge/tests-1427%20passing-brightgreen.svg)](#testing)\n[![@agentkitai/formbridge-create](https://img.shields.io/npm/v/@agentkitai/formbridge-create?label=%40formbridge%2Fcreate)](https://www.npmjs.com/package/@agentkitai/formbridge-create)\n[![@agentkitai/formbridge-form-renderer](https://img.shields.io/npm/v/@agentkitai/formbridge-form-renderer?label=%40formbridge%2Fform-renderer)](https://www.npmjs.com/package/@agentkitai/formbridge-form-renderer)\n[![@agentkitai/formbridge-schema-normalizer](https://img.shields.io/npm/v/@agentkitai/formbridge-schema-normalizer?label=%40formbridge%2Fschema-normalizer)](https://www.npmjs.com/package/@agentkitai/formbridge-schema-normalizer)\n[![@agentkitai/formbridge-shared](https://img.shields.io/npm/v/@agentkitai/formbridge-shared?label=%40formbridge%2Fshared)](https://www.npmjs.com/package/@agentkitai/formbridge-shared)\n[![@agentkitai/formbridge-templates](https://img.shields.io/npm/v/@agentkitai/formbridge-templates?label=%40formbridge%2Ftemplates)](https://www.npmjs.com/package/@agentkitai/formbridge-templates)\n\n<p align=\"center\">\n  <img src=\"docs/public/demo.gif\" alt=\"FormBridge Demo\" width=\"700\">\n</p>\n\n## The Problem\n\nAI agents can gather _most_ of the data for a form — but some fields need a human: signatures, file uploads, identity verification, subjective preferences. Existing form tools force you to choose: fully automated _or_ fully manual. Nothing handles the handoff.\n\n## How FormBridge Works\n\n```\nAgent                          FormBridge                        Human\n  │                               │                                │\n  ├─ POST /submissions ──────────►│  Creates draft, returns         │\n  │  (fills known fields)         │  resumeToken + handoff URL      │\n  │                               │                                │\n  │                               │◄──── Opens link ────────────────┤\n  │                               │  Pre-filled form with           │\n  │                               │  attribution badges             │\n  │                               │                                │\n  │                               │◄──── Fills remaining fields ────┤\n  │                               │◄──── Submits ──────────────────┤\n  │                               │                                │\n  │  ◄── Webhook delivery ───────┤  Validated, approved,           │\n  │      (HMAC-signed)            │  delivered to destination       │\n```\n\n1. **Agent creates** a submission and fills fields it knows\n2. **FormBridge generates** a secure resume URL with a rotating token\n3. **Human opens** the link — sees pre-filled fields with \"filled by agent\" badges\n4. **Human completes** remaining fields, uploads files, submits\n5. **Submission flows** through validation → optional approval gates → webhook delivery\n6. **Every field** tracks who filled it (agent, human, or system) and when\n\n## Packages\n\n| Package | npm | Description |\n|---------|-----|-------------|\n| `@agentkitai/formbridge-mcp-server` | — | Core server — HTTP API, MCP tools, submission lifecycle, storage backends (main package) |\n| `@agentkitai/formbridge-create` | [![npm](https://img.shields.io/npm/v/@agentkitai/formbridge-create)](https://www.npmjs.com/package/@agentkitai/formbridge-create) | CLI scaffolding tool (`npx @agentkitai/formbridge-create`) |\n| `@agentkitai/formbridge-form-renderer` | [![npm](https://img.shields.io/npm/v/@agentkitai/formbridge-form-renderer)](https://www.npmjs.com/package/@agentkitai/formbridge-form-renderer) | React components and hooks for rendering forms and resuming agent-started submissions |\n| `@agentkitai/formbridge-schema-normalizer` | [![npm](https://img.shields.io/npm/v/@agentkitai/formbridge-schema-normalizer)](https://www.npmjs.com/package/@agentkitai/formbridge-schema-normalizer) | Converts Zod, JSON Schema, and OpenAPI specs into a unified IntakeSchema IR |\n| `@agentkitai/formbridge-shared` | [![npm](https://img.shields.io/npm/v/@agentkitai/formbridge-shared)](https://www.npmjs.com/package/@agentkitai/formbridge-shared) | Shared utilities across packages |\n| `@agentkitai/formbridge-templates` | [![npm](https://img.shields.io/npm/v/@agentkitai/formbridge-templates)](https://www.npmjs.com/package/@agentkitai/formbridge-templates) | Ready-made intake templates (vendor onboarding, IT access, customer intake, expense report, bug report) |\n| `@agentkitai/formbridge-admin-dashboard` | — | React SPA for managing intakes, reviewing submissions, and configuring approvals |\n\n## Quick Start\n\n### Installation\n\nThe core server package (`@agentkitai/formbridge-mcp-server`) is not yet published to npm. Install it from source:\n\n```bash\ngit clone https://github.com/agentkitai/formbridge.git\ncd formbridge\nnpm install\nnpm run build\n```\n\nThe companion packages (`@agentkitai/formbridge-create`, `@agentkitai/formbridge-form-renderer`, `@agentkitai/formbridge-schema-normalizer`, `@agentkitai/formbridge-shared`, `@agentkitai/formbridge-templates`) are published and can be installed directly from npm.\n\n### Option 1: HTTP API Server\n\n```typescript\nimport { createFormBridgeApp } from '@agentkitai/formbridge-mcp-server';\nimport { serve } from '@hono/node-server';\n\nconst app = createFormBridgeApp({\n  intakes: [{\n    id: 'contact-form',\n    version: '1.0.0',\n    name: 'Contact Form',\n    schema: {\n      type: 'object',\n      properties: {\n        name:    { type: 'string', title: 'Full Name' },\n        email:   { type: 'string', format: 'email', title: 'Email' },\n        message: { type: 'string', title: 'Message' },\n      },\n      required: ['name', 'email', 'message'],\n    },\n    destination: {\n      type: 'webhook',\n      name: 'Contact API',\n      config: { url: 'https://api.example.com/contacts', method: 'POST' },\n    },\n  }],\n});\n\nserve({ fetch: app.fetch, port: 3000 });\nconsole.log('FormBridge running on http://localhost:3000');\n```\n\n**Full submission lifecycle:**\n\n```bash\n# 1. Agent creates a submission with known fields\ncurl -X POST http://localhost:3000/intake/contact-form/submissions \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n    \"actor\": { \"kind\": \"agent\", \"id\": \"gpt-4\" },\n    \"idempotencyKey\": \"req_abc123\",\n    \"initialFields\": { \"name\": \"John Doe\", \"email\": \"john@example.com\" }\n  }'\n# → { ok: true, submissionId: \"sub_...\", resumeToken: \"rtok_...\", state: \"draft\" }\n\n# 2. Human completes remaining fields via resume token\ncurl -X PATCH http://localhost:3000/intake/contact-form/submissions/sub_.../fields \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n    \"resumeToken\": \"rtok_...\",\n    \"actor\": { \"kind\": \"human\", \"id\": \"user-1\" },\n    \"fields\": { \"message\": \"I'd like to learn more about your product.\" }\n  }'\n\n# 3. Submit the completed form\ncurl -X POST http://localhost:3000/intake/contact-form/submissions/sub_.../submit \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n    \"resumeToken\": \"rtok_...\",\n    \"actor\": { \"kind\": \"human\", \"id\": \"user-1\" }\n  }'\n# → Triggers validation, approval (if configured), and webhook delivery\n```\n\n### Option 2: MCP Server (for AI agents)\n\n```typescript\nimport { FormBridgeMCPServer } from '@agentkitai/formbridge-mcp-server';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { z } from 'zod';\n\nconst server = new FormBridgeMCPServer({\n  name: 'my-formbridge',\n  version: '1.0.0',\n});\n\nserver.registerIntake({\n  id: 'vendor_onboarding',\n  version: '1.0.0',\n  name: 'Vendor Onboarding',\n  description: 'Register new vendors',\n  schema: z.object({\n    companyName: z.string().describe('Legal company name'),\n    taxId:       z.string().describe('Tax identification number'),\n    contact:     z.string().email().describe('Primary contact email'),\n    w9Upload:    z.string().optional().describe('W-9 form upload (human-only)'),\n  }),\n  destination: {\n    type: 'webhook',\n    name: 'Vendor System',\n    config: { url: 'https://api.example.com/vendors', method: 'POST' },\n  },\n});\n\n// Each intake auto-generates 4 MCP tools:\n//   vendor_onboarding__create   — Start a new submission\n//   vendor_onboarding__set      — Update fields\n//   vendor_onboarding__validate — Check completeness\n//   vendor_onboarding__submit   — Submit for processing\n\nconst transport = new StdioServerTransport();\nawait server.getServer().connect(transport);\n```\n\n### Option 3: React Form Renderer\n\n```tsx\nimport { FormBridgeForm, ResumeFormPage } from '@agentkitai/formbridge-form-renderer';\n\n// Standalone form\nfunction ContactPage() {\n  return (\n    <FormBridgeForm\n      schema={contactSchema}\n      endpoint=\"http://localhost:3000\"\n      actor={{ kind: 'human', id: 'user-1' }}\n      onSuccess={(data, submissionId) => {\n        console.log('Submitted:', submissionId);\n      }}\n    />\n  );\n}\n\n// Resume an agent-started form (pre-filled fields + attribution badges)\nfunction ResumePage() {\n  const token = new URLSearchParams(location.search).get('token');\n  return (\n    <ResumeFormPage\n      resumeToken={token}\n      endpoint=\"http://localhost:3000\"\n    />\n  );\n}\n```\n\n### Option 4: CLI Scaffolding\n\n```bash\n# Interactive — walks you through setup\nnpx @agentkitai/formbridge-create\n\n# Non-interactive\nnpx @agentkitai/formbridge-create --name my-intake --schema zod --interface http,mcp\n```\n\n## Features\n\n### Core\n- **Submission State Machine** — `draft → in_progress → submitted → finalized` with configurable transitions\n- **Field Attribution** — Every field tracks which actor (agent, human, system) set it and when\n- **Resume Tokens** — Secure, rotating tokens for handoff URLs (rotated on every state change)\n- **Idempotent Submissions** — Duplicate requests with the same key return the existing submission\n- **Schema Normalization** — Accept Zod schemas, JSON Schema, or OpenAPI specs as input\n\n### Collaboration\n- **Mixed-Mode Forms** — Agents fill what they can, humans complete the rest\n- **Conditional Fields** — Show/hide fields based on other field values (dynamic schema)\n- **Multi-Step Wizard** — Progressive disclosure with step indicators and navigation\n- **File Upload Protocol** — Signed URL negotiation for secure file handling (S3-compatible)\n\n### Production\n- **Approval Gates** — Configurable review workflows that pause submissions until approved/rejected\n- **Webhook Delivery** — HMAC-signed payloads with exponential backoff and delivery tracking\n- **Event Stream** — Append-only audit trail for every state change, field update, and action\n- **Auth & RBAC** — API key auth, OAuth provider, role-based access control, rate limiting\n- **Multi-Tenancy** — Tenant isolation with configurable storage and access boundaries\n- **Pluggable Storage** — In-memory (dev), SQLite (single-server), PostgreSQL (multi-replica HA), S3 (file uploads)\n\n### Developer Experience\n- **MCP Server** — Auto-generates MCP tools from intake definitions for AI agent integration\n- **Admin Dashboard** — React SPA for managing intakes, reviewing submissions, analytics\n- **CLI Scaffolding** — `npx @agentkitai/formbridge-create` generates a ready-to-run project\n- **5 Starter Templates** — Vendor onboarding, IT access request, customer intake, expense report, bug report\n- **VitePress Docs** — API reference, guides, walkthroughs, and concept docs\n- **CI/CD** — GitHub Actions for lint, typecheck, and tests on Node 18/20/22\n\n## API Reference\n\n### Endpoints\n\n| Method | Path | Description |\n|--------|------|-------------|\n| `GET` | `/health` | Health check |\n| `GET` | `/intake/:id/schema` | Get intake schema |\n| `POST` | `/intake/:id/submissions` | Create submission |\n| `GET` | `/intake/:id/submissions/:subId` | Get submission |\n| `PATCH` | `/intake/:id/submissions/:subId` | Update fields |\n| `POST` | `/intake/:id/submissions/:subId/submit` | Submit |\n| `GET` | `/submissions/:subId/events` | Get event stream |\n| `POST` | `/submissions/:subId/approve` | Approve submission |\n| `POST` | `/submissions/:subId/reject` | Reject submission |\n| `POST` | `/intake/:id/submissions/:subId/uploads` | Request file upload URL |\n| `POST` | `/intake/:id/submissions/:subId/uploads/:uploadId/confirm` | Confirm file upload |\n| `GET` | `/submissions/:subId/deliveries` | List webhook deliveries for a submission |\n| `GET` | `/webhooks/deliveries/:deliveryId` | Get a single webhook delivery |\n| `GET` | `/analytics/summary` | Submission analytics summary |\n| `GET` | `/analytics/volume` | Submission volume over time |\n| `GET` | `/analytics/funnel` | Submission funnel by state |\n| `GET` | `/analytics/intakes` | Per-intake metrics |\n\n### Submission States\n\n```\ndraft → in_progress → submitted → finalized\n          │  ↘ awaiting_upload\n          ↘ needs_review → approved → submitted/finalized\n                        ↘ rejected\n```\n\n- **draft** — Newly created, being filled by agent and/or human\n- **in_progress** — Fields are being set\n- **awaiting_upload** — Waiting for a file upload to complete\n- **submitted** — All required fields complete, pending review (or auto-approved)\n- **needs_review** — Paused at an approval gate awaiting a reviewer decision\n- **approved** — Passed approval gates\n- **rejected** — Rejected by reviewer (terminal)\n- **finalized** — Completed and delivered to destination (terminal)\n- **cancelled** / **expired** — Terminal states for cancelled or TTL-expired submissions\n\n## Storage Backends\n\nFormBridge supports multiple storage backends, selected via the `FORMBRIDGE_STORAGE` environment variable.\n\n| Backend | Value | Use Case | Dependency |\n|---------|-------|----------|------------|\n| In-Memory | `memory` (default) | Development, testing | None |\n| SQLite | `sqlite` | Single-server production | `better-sqlite3` |\n| PostgreSQL | `postgres` | Multi-replica HA deployments | `pg` |\n\n### PostgreSQL Configuration\n\n```bash\n# Required\nexport FORMBRIDGE_STORAGE=postgres\nexport DATABASE_URL=postgresql://user:password@host:5432/formbridge\n\n# Optional: install pg driver\nnpm install pg\n```\n\n```typescript\nimport { PostgresStorage } from '@agentkitai/formbridge-mcp-server';\n\nconst storage = new PostgresStorage({\n  connectionString: process.env.DATABASE_URL!,\n  maxConnections: 20,        // default: 10\n  idleTimeoutMillis: 30000,  // default: 30000\n});\nawait storage.initialize(); // runs migrations automatically\n\n// Or use the factory:\nimport { createStorageFromEnv } from '@agentkitai/formbridge-mcp-server';\nconst storage = await createStorageFromEnv(); // reads FORMBRIDGE_STORAGE + DATABASE_URL\n```\n\nThe PostgreSQL schema uses proper Postgres types: `UUID` for IDs, `JSONB` for structured data, and `TIMESTAMPTZ` for timestamps. The migration file is at `migrations/001_init.sql`.\n\n## Architecture\n\n```\n┌──────────────────────────────────────────────────────────┐\n│                     FormBridge Core                       │\n│                                                          │\n│  ┌─────────────┐  ┌──────────────┐  ┌────────────────┐  │\n│  │   Intake     │  │  Submission  │  │   Approval     │  │\n│  │  Registry    │  │   Manager    │  │   Manager      │  │\n│  └─────────────┘  └──────────────┘  └────────────────┘  │\n│  ┌─────────────┐  ┌──────────────┐  ┌────────────────┐  │\n│  │   Event      │  │   Webhook    │  │   Condition    │  │\n│  │   Store      │  │   Manager    │  │   Evaluator    │  │\n│  └─────────────┘  └──────────────┘  └────────────────┘  │\n│                                                          │\n│  ┌─────────────────────────────────────────────────────┐ │\n│  │              Storage Layer                           │ │\n│  │  Memory (dev) │ SQLite (prod) │ S3 (file uploads)   │ │\n│  └─────────────────────────────────────────────────────┘ │\n│                                                          │\n│  ┌──────────────────┐  ┌──────────────────────────────┐  │\n│  │   HTTP API        │  │   MCP Server                 │  │\n│  │   (Hono)          │  │   (Stdio + SSE transports)   │  │\n│  └──────────────────┘  └──────────────────────────────┘  │\n│                                                          │\n│  ┌──────────────────┐  ┌──────────────────────────────┐  │\n│  │   Auth / RBAC     │  │   Rate Limiting              │  │\n│  │   Multi-tenancy   │  │   CORS                       │  │\n│  └──────────────────┘  └──────────────────────────────┘  │\n└──────────────────────────────────────────────────────────┘\n\n┌────────────────────┐  ┌────────────────────────────────┐\n│  React Form        │  │  Admin Dashboard               │\n│  Renderer          │  │  (React SPA)                   │\n└────────────────────┘  └────────────────────────────────┘\n\n┌────────────────────┐  ┌────────────────────────────────┐\n│  CLI Scaffolding   │  │  Schema Normalizer             │\n│  (create-formbridge)│  │  (Zod/JSONSchema/OpenAPI → IR) │\n└────────────────────┘  └────────────────────────────────┘\n```\n\n## Project Structure\n\n```\nsrc/\n  auth/           # API key auth, OAuth, RBAC, rate limiting, tenant isolation\n  core/           # Business logic — submission manager, approval gates, events,\n                  #   state machine, condition evaluator, webhook delivery\n  mcp/            # MCP server, tool generator, stdio + SSE transports\n  middleware/     # Hono middleware (CORS, error handling)\n  routes/         # HTTP route handlers (submissions, approvals, uploads, events,\n                  #   webhooks, analytics, health)\n  storage/        # Storage backends (memory, SQLite, S3) + migration utility\n  types/          # TypeScript types and intake contract spec\n\npackages/\n  admin-dashboard/    # React SPA — intake management, submission review, analytics\n  create-formbridge/  # CLI tool — interactive + non-interactive project scaffolding\n  form-renderer/      # React components — FormBridgeForm, ResumeFormPage, WizardForm\n  schema-normalizer/  # Converts Zod, JSON Schema, OpenAPI → unified IntakeSchema IR\n  shared/             # Shared utilities across packages\n  templates/          # 5 starter templates with full schema definitions\n  demo/               # Demo app with sample intakes and pre-configured workflows\n\ndocs/               # VitePress documentation site\ntests/              # 1,427 tests across 59 files\n.github/workflows/  # CI (lint + typecheck + tests on Node 18/20/22) + release\n```\n\n## Development\n\n```bash\n# Install dependencies\nnpm install\n\n# Run all 1,427 tests\nnpm run test:run\n\n# Watch mode\nnpm test\n\n# Type checking (zero errors)\nnpm run typecheck\n\n# Lint (ESLint flat config v9)\nnpm run lint\n\n# Build\nnpm run build\n\n# Run the demo app\ncd packages/demo && npm run dev\n```\n\n## Testing\n\nThe test suite covers:\n\n- **Core logic** — Submission lifecycle, state machine transitions, approval workflows, field attribution\n- **API endpoints** — Full HTTP request/response testing for all routes\n- **MCP server** — Tool generation, server initialization, transport handling\n- **Storage backends** — Memory, SQLite, and S3 storage with edge cases\n- **CLI scaffolding** — End-to-end CLI tests (interactive + non-interactive)\n- **Schema normalization** — Zod, JSON Schema, and OpenAPI conversion\n- **Condition evaluation** — Dynamic field visibility rules\n- **Webhook delivery** — HMAC signing, retry logic, delivery tracking\n\n```\n1,427 tests passing across 59 test files\n```\n\n(Two upload-path tests assert POSIX `/` separators and fail on Windows; they pass on Linux/macOS, which is what CI runs.)\n\n## Roadmap\n\n- [x] npm package publishing (5 packages live on npm)\n- [x] PostgreSQL storage backend\n- [ ] Real-time collaboration (WebSocket field locking)\n- [ ] Email notifications for pending approvals\n- [ ] Form analytics dashboard with charts\n- [ ] Hosted cloud version\n\n## Contributing\n\nContributions welcome! Please open an issue first to discuss what you'd like to change.\n\n```bash\ngit clone https://github.com/agentkitai/formbridge.git\ncd formbridge\nnpm install\nnpm run test:run   # All tests pass\nnpm run typecheck  # Zero errors\nnpm run lint       # Clean\n```\n\n\n## 🧰 AgentKit Ecosystem\n\n| Project | Description | |\n|---------|-------------|-|\n| [AgentLens](https://github.com/agentkitai/agentlens) | Observability & audit trail for AI agents | |\n| [Lore](https://github.com/agentkitai/lore) | Cross-agent memory and lesson sharing | |\n| [AgentGate](https://github.com/agentkitai/agentgate) | Human-in-the-loop approval gateway | |\n| **FormBridge** | Agent-human mixed-mode forms | ⬅️ you are here |\n| [AgentEval](https://github.com/agentkitai/agenteval) | Testing & evaluation framework | |\n| [agentkit-cli](https://github.com/agentkitai/agentkit-cli) | Unified CLI orchestrator | |\n\n## License\n\n[MIT](./LICENSE) © 2026 Amit Paz\n","readmeFilename":"README.md"}