WhatsApp MCP Platform
Provides a Model Context Protocol server for WhatsApp, enabling session management, webhook normalization, and tenant-based message operations through a public API and private control plane.
README
Normal
Normal is a personal platform that lets approved AI clients work with a connected WhatsApp account through the Model Context Protocol.
Each User owns one Personal Account. A Personal Account can hold up to three WhatsApp Connections and can grant each MCP Client access to an explicit set of Connections and capabilities. Read access and send access are separate permissions. Every outbound message requires confirmation in the MCP Client.
The platform is currently built for a private beta. Privacy, deletion, auditability, and safe recovery are part of the core design, not optional layers added later.
What is in this repo
This is a Bun and Turbo monorepo with five deployable apps:
| Path | Purpose | Runtime |
|---|---|---|
apps/web |
Product UI, connection management, and OAuth consent | Next.js on Vercel |
apps/api |
Public HTTP API, OAuth server, MCP endpoint, webhook ingestion, and scheduled reconciliation | Cloudflare Workers |
apps/provider-control |
Private boundary for provider session provisioning and control | Cloudflare Workers |
apps/deletion-coordinator |
Continues deletion after access and key use have stopped | Cloudflare Workers |
apps/restore-coordinator |
Reconciles restored data with deletion markers and recovery rules | Cloudflare Workers |
Shared code is split by responsibility:
| Path | Purpose |
|---|---|
packages/domain |
Pure domain rules and state transitions |
packages/contracts |
MCP, API, health, handle, and service binding schemas |
packages/db |
Drizzle schema, migrations, RLS aware repositories, and database tools |
packages/wasender |
Thin provider adapter for sessions, control, media, and webhook normalization |
infra |
OpenTofu configuration for Cloudflare, Vercel, Neon, and AWS KMS |
scripts |
Deployment, validation, recovery, observability, and launch gate tooling |
The API Worker is the public data plane. Provider credentials stay behind the private provider-control service binding. Neon is the authoritative data store, while Cloudflare bindings handle edge protocol state, queues, and encrypted webhook payloads.
Requirements
You need:
- Bun 1.3.14
- Node.js 20 or newer for supporting tools
- Wrangler through the pinned workspace dependency
- OpenTofu for infrastructure validation
- Chromium and its host dependencies for browser tests
For local provider or deployment work, you will also need access to the relevant Clerk, Cloudflare, Neon, AWS, Vercel, and Wasender environments.
Local setup
Install the pinned dependencies:
bun install --frozen-lockfile
Create local secret files only for the apps you plan to run:
cp apps/api/.dev.vars.example apps/api/.dev.vars
cp apps/provider-control/.dev.vars.example apps/provider-control/.dev.vars
cp apps/web/.env.example apps/web/.env.local
The example files document the required values. Never commit .dev.vars, .env.local, credentials, tokens, phone numbers, provider payloads, or decrypted message content.
Start the web app and API Worker together:
bun run dev
You can also run one workspace directly:
bun run --cwd apps/web dev
bun run --cwd apps/api dev
bun run --cwd apps/provider-control dev
If a real external webhook needs to reach your local Worker, run the configured Cloudflare tunnel in another terminal:
bun run dev:tunnel
Verification
Run the normal checks before opening a pull request:
bun run format:check
bun run lint
bun run typecheck
bun run test
bun run build
The complete infrastructure and deployment validation set is:
bun run validate:infra
bun run manifests:validate
bun run infra:validate
bun run observability:validate
bun run launch:gate
Install the pinned browser once before the first full test run:
bun x playwright install --with-deps chromium
Tests intentionally exercise production shaped boundaries. Worker tests run in the Cloudflare runtime, browser tests use a production Next.js build, and database tests apply real migrations with production RLS policies. Test composition roots must never become selectable from a production build.
For focused work, use Turbo filters or workspace commands:
bun run test --filter=@whatsapp-mcp/api
bun run typecheck --filter=@whatsapp-mcp/web
bun run --cwd packages/db test
Database changes
Database code and migrations live in packages/db. Set the environment described in docs/configuration.md, then use:
bun run db:check
bun run db:migrate
Treat migration changes as security sensitive. Preserve tenant foreign keys, runtime role grants, fixed search paths, RLS policies, deletion behavior, and restore behavior. Tests must exercise the actual production migration path.
Architecture and operations
Start with these documents:
CONTEXT.mddefines the product language and invariants.docs/architecture.mdmaps the production boundaries and primary data flows.docs/mcp-contract.mddefines MCP tools, resources, authorization, errors, and pagination.docs/configuration.mdlists runtime configuration and secret ownership.docs/testing.mdexplains the public boundary test strategy.docs/wasender-seam.mddefines the provider boundary.docs/stored-media-container.mddescribes encrypted Stored Media.docs/adrrecords architectural decisions.docs/runbookscontains deployment, incident, recovery, security, and teardown procedures.
The most important rules are simple:
- Use the terms in
CONTEXT.mdin code, tests, and docs. - Keep provider details behind
packages/wasenderandapps/provider-control. - Fail closed when identity, authorization, audit, quota, encryption, or configuration is unavailable.
- Never retry an outbound send when provider acceptance is ambiguous.
- Keep logs and telemetry free of message content, credentials, full phone numbers, provider identifiers, and tenant identifiers unless an approved contract explicitly allows them.
- Make deletion and restore behavior explicit for every new persisted record.
Deployment
Development, preview, and production have separate configuration and infrastructure authority. Do not deploy by improvising commands from local manifests.
Follow docs/runbooks/deployment.md, validate the rendered manifests, and run the deployment smoke checks after a release. Production recovery, key rotation, replay, break glass access, and environment teardown each have dedicated runbooks under docs/runbooks.
Sandcastle
Sandcastle can run issue agents in isolated Docker worktrees. After authenticating Docker, GitHub CLI, and Codex:
bun run sandcastle:build-image
bun run sandcastle
Agent specific issue and triage guidance lives in docs/agents.
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
mcp-server-qdrant
这个仓库展示了如何为向量搜索引擎 Qdrant 创建一个 MCP (Managed Control Plane) 服务器的示例。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器