MCP gateways
WiseWig deploys MCP as two independent Cloudflare Workers. This is an infrastructure security boundary, not catalog filtering inside one privileged process.
Anonymous public service
@wise-wig/public-mcp-worker serves Streamable HTTP at /mcp. Its Wrangler bindings are intentionally limited to:
PUBLIC_CONTENT, a KV namespace populated only after a successful publish;PUBLIC_MCP, the Agents SDK session Durable Object; andPUBLIC_RATE, an IP-hash rate-limit Durable Object.
It has no D1, tenant workspace, R2, identity secret, form-submission store, outbound plugin runner, or service binding. The core tools read/search the published structured document. Plugin tools are indexed only when their manifest declares visibility: public, no private permission, and exactly the public_content data scope. Invocation repeats that check against the published index and bounds output.
OAuth private service
@wise-wig/private-mcp-worker is a separate OAuth 2.1 authorization server and protected MCP resource. It proxies identity to the installation’s configured OAuth/OIDC provider using S256 PKCE and one-time state, then requires an explicit site-scoped consent. Unknown scopes are dropped; site.write is removed when the current membership cannot edit content. Existing grants are displayed and may be revoked from the consent screen.
Tokens contain encrypted site grant properties, but these are never trusted as lasting authorization. Every tool invocation reloads current D1 roles for the exact tenant/site, checks the OAuth scope and framework permission, consumes a tenant/user Durable Object quota, and records an audit event. Mutations use the shared guarded-command path for schema validation, confirmation, idempotency, optimistic versions, authorization, and audit.
Private plugin tools are derived only from enabled installed manifests. A mutation additionally requires a declared write capability, a private tool permission allowed by the current role, a declared storage collection, and explicit confirmation. This enables a plugin such as sermons to offer public research through the public index and authenticated record creation through private tenant storage without sharing bindings.
Deployment invariants
Deploy and review the two generated binding files independently. Never add a privileged binding to the public Worker for convenience. Publishing copies a sanitized document, searchable text, and eligible public plugin descriptors to PUBLIC_CONTENT; no draft, membership, submission, audit, or engagement value belongs in that record.
Both Workers use the Agents SDK McpAgent Streamable HTTP transport. The private Worker uses Cloudflare’s OAuthProvider; access tokens last one hour and refresh grants 30 days by default. Environment-specific operators must configure OAuth endpoints, D1/KV identifiers, remote tenant workspace binding, and secrets before deployment.