Notion Custom MCP Builder
Build or assess a hosted MCP server that Notion can reach. Treat the repository, the deployed endpoint, and the Notion connection as three separate states that require separate evidence.
Start safely
- Read every applicable
AGENTS.md; inspect the canonical repo, branch, worktree status, and existing docs before editing. - State the requested tools, upstream service, user workflow, and done condition. Separate read, write, destructive, send, delete, deploy, DNS, secret, GitHub, and Notion-connection actions.
- Do not interpret preparation or a general “continue” as approval for an external mutation. Immediately before each external action, present the exact target, operation, impact, and rollback limitation and wait for exact approval.
- Refresh current official MCP SDK, Notion, selected runtime, deployment-provider, and package-version evidence before choosing APIs. Do not copy a version from this skill as proof that it is still current.
Route the request
Read inventory-and-routing.md, then route in two independent stages. If the user has not fixed a provider, run node scripts/route-deployment.mjs --spec <request.json> and read deployment-routing.md.
- Runtime first: choose web-standard Edge, portable Node container, or host-attached Node. Do not choose a provider before runtime requirements are known.
- Provider second: preserve an explicit user choice when compatible; otherwise explain the exact incompatibility and offer ranked adapters.
- Ordinary portable default: stateless Node v2 container. Read node-v2.md and use
assets/node-container-template/. - Edge/Fetch requirement with no local executable or filesystem: stateless Cloudflare Worker v2. Read worker-v2.md.
- Browser profile, device, mounted host path, or truly host-resident process: host-attached Node v2. Use
assets/node-v2-template/. - Cross-request business state: add DO, D1, R2, Queue, Workflow, or durable local storage for that business state; do not introduce protocol-session state by default.
- Existing
McpAgentor monolithic@modelcontextprotocol/sdkv1 server: audit and plan a staged migration. Read legacy-v1-migration.md; never use it as a new-project template. - Multi-user or per-user authorization: design OAuth and resource confinement before scaffold. Do not silently substitute a shared Bearer token.
For any tool implementation, read tool-contracts.md. For auth, permissions, secrets, or external operations, read security-and-approvals.md. Before claiming completion, read testing-and-release.md.
When preparing this skill package itself for distribution, read distribution.md. Publishing the skill is a separate external action from creating or deploying any generated MCP server.
Workflow
- Write
server-spec.mdor an equivalent plan in the project root. Record runtime rationale, catalog, annotations and human execution policy, upstream scopes, auth mode, sync/async choice, storage and retention, dedupe/rate keys, output delivery, secrets by name only, and local/staging/production gates. - For a new server, copy the runtime template first, then only the selected provider adapter. Keep MCP/tool code provider-neutral. For an existing server, preserve its behavior until the audit identifies a supported change path.
- Define an exact catalog revision and expected tool list. Use bounded, Notion-friendly schemas; explicit four-field annotations; stable structured errors; text plus
structuredContent; and server-side permission, idempotency, and rate enforcement. - Run local build, unit, transport, catalog, auth, 404, Host/Origin, dedupe, async, output, secret-scan, dependency, and dry-run gates appropriate to the runtime.
- Run smoke in increasing authority: list-only, approved read-only upstream, then separately approved write. Never make write smoke the default.
- Produce a provider-specific deploy preview containing repo/branch/commit, provider/account/project/service/hostname, secret names, resources and migrations, routes, Notion impact, cost/user impact, and rollback limits. Stop before GitHub push, image push, deploy, resource creation, DNS/Tunnel, secret writes, Notion registration/reconnect, or write smoke.
- After separately approved apply actions, prove source commit = remote commit = deployed revision; endpoint auth/catalog/read behavior; and the actual Notion connection, tool visibility, and execution policy. Server smoke alone is not Notion UI proof.
Included resources
assets/node-container-template/: portable stateless Node/Docker starter for managed container services and VPS.assets/worker-v2-template/: stateless CloudflarecreateMcpHandlerstarter for the Edge lane.assets/node-v2-template/: host-attached Node starter with loopback, Host/Origin, token-file, and durable file-job primitives.assets/deployment-adapters/: thin provider configuration copied only after runtime selection.scripts/route-deployment.mjs: deterministic runtime and provider candidate router.scripts/inventory.mjs: read-only repo/runtime/catalog inventory.scripts/validate-catalog.mjs: expected catalog versus livetools/listand annotation validation.scripts/scan-secrets.mjs: tracked-file and optional history scan that reports only path/type evidence.scripts/check-portability.mjs: reject personal absolute paths and generated dependency/build directories before skill distribution.scripts/smoke-readonly.mjs: initialize,tools/list, ping, and optionally one catalog-declared read-only call.
The skill package is distributable; generated MCP servers are separate projects. Never bundle the skill author's provider credentials, account IDs, domains, tokens, or deployment state. Keep generated project files only when they support the user’s requested server. Do not create a GitHub repo, remote provider resource, image registry entry, Tunnel, DNS record, secret, or Notion connection during scaffold or validation.