MCP OAuth Starter
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@MCP OAuth Starteradd a note: buy milk and eggs"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
MCP OAuth Starter
A Next.js starter for an app that AI assistants (ChatGPT, Claude) connect to over MCP, with a real OAuth 2.1 server, per-user data, and a Disconnect button that cuts access immediately.
The example domain is notes. Swap it for yours; the auth, OAuth and MCP plumbing stays.
Extracted from two apps running in production: English Coach (single owner) and PaceBeep (multi-user).
What you get
Accounts: email + password (Better Auth), optional "Continue with Google", account deletion.
OAuth 2.1 server for agents: dynamic client registration (ChatGPT registers itself), PKCE, a consent screen, discovery metadata (RFC 8414 / RFC 9728),
issin the callback (RFC 9207).MCP server at
/mcp(MCP TypeScript SDK v2, stateless): four example tools, reads markedreadOnlyHint, writes idempotent.Dashboard: your data, what the assistant wrote ("by assistant"), connected assistants with Disconnect.
Postgres with plain SQL migrations, applied on every Vercel build.
Related MCP server: Reflect MCP Server
How a connection works
ChatGPT Your app (Next.js on Vercel)
│ POST /mcp (no token) ────────────► 401 + WWW-Authenticate: resource_metadata=…
│ GET /.well-known/oauth-protected-resource/mcp → "auth server is <url>/api/auth"
│ GET /.well-known/oauth-authorization-server/api/auth → endpoints
│ POST /api/auth/oauth2/register ─► client_id (dynamic client registration)
│ browser → /api/auth/oauth2/authorize (PKCE, resource=<url>/mcp)
│ → /login → /oauth/consent → user clicks Allow
│ POST /api/auth/oauth2/token ────► JWT access token (aud = <url>/mcp) + refresh token
│ POST /mcp (Bearer) ─────────────► 1. JWT valid? (JWKS signature, issuer, audience, expiry)
│ 2. consent row for (user, client) still there?
│ 3. tools run as that user onlySecurity properties
Property | How it's enforced |
A token only works for this MCP server | Access tokens carry |
Disconnect cuts access immediately | JWTs stay valid until they expire, so |
Disconnect also kills refresh tokens |
|
One user's disconnect never affects another | The shared |
Users only see their own rows | Every query in |
Retries don't duplicate | Writes take a |
Google can't be used to take over an account | With Google enabled, new accounts come only from Google (verified email), so nobody can pre-register a password account on your email. |
No secrets in the repo |
|
Run locally
Requires Node 22+ and Docker.
npm install
npm run db:up # postgres:17 on port 55434
cp .env.example .env.local # set BETTER_AUTH_SECRET (openssl rand -hex 32)
npm run db:migrate
npm run devOpen http://localhost:3000, create an account and add a note.
Environment
Variable | Required | Notes |
| yes | Postgres. Vercel + Neon sets it (plus |
| yes |
|
| locally | Public base URL. On Vercel it defaults to the production domain. |
| no |
|
| no | Enables "Continue with Google". Redirect URI: |
Deploy
With the button above: Vercel copies the repo to your GitHub, creates a Neon database (env prefix DATABASE) and asks for BETTER_AUTH_SECRET. The build runs db/migrations/*.sql before next build.
By hand: import the repo in Vercel, add Storage → Neon with env prefix DATABASE, set BETTER_AUTH_SECRET, deploy. If you use a custom domain, set BETTER_AUTH_URL to it.
Connect an assistant
ChatGPT: Settings → Security and login → Developer mode, then Plugins → Add → create an MCP app with URL https://<your-app>/mcp and authentication OAuth. ChatGPT registers itself, sends you to sign in and approve, and then lists the tools.
Claude: Settings → Connectors → Add custom connector → https://<your-app>/mcp.
Make it yours
File | Change |
| Your tables. Keep |
| Your data functions. Every one takes the user id. Shared by the web UI and the MCP tools. |
| Your tools, and the |
| Your dashboard and server actions. |
| What the consent screen says the assistant may do. |
| Public pages (e.g. |
Before a public launch with Google sign-in you'll need a privacy policy and terms page. PaceBeep has an example.
Gotchas worth knowing
proxy.tsmust skip/api/auth,/mcpand/.well-known. Otherwise the discovery requests get redirected to/loginand the assistant can't find the auth server.The issuer has a path (
/api/auth), so authorization server metadata lives at/.well-known/oauth-authorization-server/api/auth(RFC 8414 path insertion), not at the root.Don't set
legacy: "reject"increateMcpHandler. ChatGPT speaks protocol2025-06-18.Revoking a JWT means checking state per request. That's one indexed query on
/mcp, and it's what makes Disconnect real.Vercel Sensitive env vars can't be pulled locally (
vercel env pullreturns empty values), so migrations run in thevercel-buildscript, where they're available.Use
clock_timestamp()forcreated_atwhen several rows are inserted in one transaction:now()is the same for all of them and they lose their order.
Built with
Next.js 16, TypeScript, Tailwind 4, Better Auth (+ @better-auth/mcp), MCP TypeScript SDK v2, Postgres (Neon), Vercel.
License
MIT – see LICENSE.
This server cannot be deployed
Maintenance
Related MCP Connectors
- OpenOakOAuthorg.openoak
Secure AI access to OpenOak tasks, notes, and Kanban boards.
Portable AI memory you own. Keep memories and notes across Claude, ChatGPT, and other AI tools.
Governed memory and workspace for any AI: tasks, calendar, mail and pages, with per-action consent.
- Meeting.aiOAuthai.meeting
Let AI assistants record meetings and work with notes, transcripts, contacts, and Drive.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables AI assistants to search and read your Evernote notes using natural language queries through secure OAuth authentication. Supports containerized deployment with production-ready security features.10 npm56MIT
- FlicenseNot gradedqualityDmaintenanceEnables AI assistants like Claude to interact with Reflect notes through OAuth authentication, allowing users to retrieve graph lists and append content to daily notes.1-
- FlicenseNot gradedqualityDmaintenanceEnables AI assistants to create notes, save links, append to daily notes, and manage knowledge graphs in Reflect via the Reflect Notes API, with OAuth2 authentication and token management.3-
- AlicenseNot gradedqualityDmaintenanceProvides AI assistants with secure access to Notion workspaces, enabling page management, search, block operations, and user management.2,648 npmMIT