From Payload MCP OAuth
Install and configure @brainwebuk/payload-plugin-mcp-oauth — OAuth 2.1 + PKCE + Dynamic Client Registration for a Payload @payloadcms/plugin-mcp server, so it can be added as a Custom Connector in Claude.ai. Use when adding OAuth to a Payload MCP app; wiring the plugin, proxy/middleware, or env; or debugging the install (consent 401 "Authentication required", SQLite push "no such column: oauth_clients_id", missing OAuth admin collections, "must be registered AFTER mcpPlugin", or OAuth tokens 401 while API keys work).
How this skill is triggered — by the user, by Claude, or both
Slash command
/payload-mcp-oauth:installThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Adds OAuth 2.1 + PKCE + Dynamic Client Registration to an existing
@brainwebuk/payload-plugin-mcp-oauthAdds OAuth 2.1 + PKCE + Dynamic Client Registration to an existing
@payloadcms/plugin-mcp MCP server. Additive — the API-key flow keeps
working. Always prefer the latest version (the install path has had several
fixes; use >= 0.3.3).
@payloadcms/plugin-mcp already installed and working.Install: pnpm add @brainwebuk/payload-plugin-mcp-oauth
Register it AFTER mcpPlugin(), sharing ONE options object (most common footgun):
const mcpOptions = {
collections: { posts: { enabled: { find: true, create: true, update: true } } },
}
plugins: [
mcpPlugin(mcpOptions),
payloadMcpOAuth({
issuer: process.env.NEXT_PUBLIC_SERVER_URL!,
mcpPluginOptions: mcpOptions, // ← the SAME reference, never a copy/spread
}),
]
A copy/spread silently breaks OAuth token auth (API keys keep working, so it's
easy to miss). Registering it before mcpPlugin() throws on boot.
Add the proxy — Next 16: src/proxy.ts; Next 14/15: src/middleware.ts.
Re-export the handler but declare config as a local literal (never
re-export config — it 500s every route on Next 16):
export { mcpOAuthMiddleware as proxy } from '@brainwebuk/payload-plugin-mcp-oauth/middleware'
export const config = {
matcher: ['/', '/.well-known/oauth-authorization-server', '/.well-known/oauth-protected-resource'],
}
Env: set NEXT_PUBLIC_SERVER_URL (public HTTPS origin; used as the OAuth
issuer) and PMOAUTH_TOKEN_PEPPER (openssl rand -hex 32; required ≥ 32 chars
in production). Ensure Payload's serverURL equals NEXT_PUBLIC_SERVER_URL —
the consent flow relies on a first-party session cookie matching that origin.
Apply the schema — pick ONE workflow, don't mix:
pnpm payload migrate:create then pnpm payload migrate.
If you already booted the app once before installing, on SQLite either
upgrade to >= 0.3.2 or reset the dev DB (rm your.db*) so the schema is
created fresh.curl <issuer>/.well-known/oauth-authorization-server returns JSON metadata.userCollection).Agents only know what the server tells them. On mcpPlugin() set
serverOptions.instructions (how to use the server + non-obvious field rules),
per-collection description, and field admin.description (these flow into the
generated tool schemas). For gnarly create flows, define an MCP prompt. A Claude Skill
cannot reach a connecting web agent — instructions/prompts are the
protocol-native bridge.
401 access_denied / "Authentication required" — upgrade
to >= 0.3.1 (a Referrer-Policy: no-referrer bug made the browser send
Origin: null). If it persists, serverURL/NEXT_PUBLIC_SERVER_URL must
exactly match the browser origin (scheme, host, no trailing slash).SQLITE_ERROR: no such column: oauth_clients_id (rebuilding
payload_locked_documents_rels) — upgrade to >= 0.3.2, or reset the dev DB,
or add the plugin before the first boot.mcpPluginOptions wasn't the same
object reference passed to both plugins.must be registered AFTER mcpPlugin() — fix plugin order. (On >= 0.3.3
it's fine to leave payloadMcpOAuth registered while the MCP plugin is
disabled — it no-ops instead of crashing.)createPages is missing — enable that op in
collections.<slug>.enabled (create/update/delete); enabled: true
turns on all of them.For the full reference see the package's INSTALL_FOR_AGENTS.md and README.
npx claudepluginhub brainweb/payload-mcp-oauth --plugin payload-mcp-oauthProvides CDSS development patterns for drug interaction checking, dose validation, clinical scoring (NEWS2, qSOFA), and alert classification integrated into EMR workflows.