Add MCP entry point to an existing project
Use when
- User wants Claude Desktop, Cursor, or any MCP-compatible AI client to interact with the app.
- User says "expose this to MCP" / "add MCP tools" / "let AI query the data".
- User invokes
/nts-add-mcp.
Prerequisite check
This skill requires Better Auth to be wired (the OAuth provider behind the MCP plugin). Before doing anything else:
- Check for
src/server/auth/index.ts— abort if missing. - Check that Better Auth is in
package.jsondependencies — abort if missing.
If auth isn't wired, tell the user to run /nts-add-auth first.
What this skill does
- Adds the
mcpplugin to the Better Auth config. - Creates
src/app/api/mcp/route.ts— the Streamable HTTP endpoint, wrapped inwithMcpAuth. - Creates
src/app/.well-known/oauth-authorization-server/route.tsandsrc/app/.well-known/oauth-protected-resource/route.tsfor discovery. - Creates
src/server/mcp/registry.ts— the tool dispatch table. - Creates
src/server/mcp/tools/_example-search.ts— one worked tool wrapping a service. - Creates a Prisma migration to add the three OAuth tables (
oauth_application,oauth_access_token,oauth_consent). - Updates
CLAUDE.mdto document the MCP entry point. - Adds dev tunnel instructions to the README (Claude Desktop only accepts HTTPS connectors).
Confirmation flow
Before writing:
- Verify project structure (Better Auth present,
src/app/api/exists). - Pick the example tool — default is "search the first table the user has". If unclear, pick
example_searchagainst the_examplemodule if it exists. - Show the file list. Confirm.
File contents
Update src/server/auth/index.ts
Find the plugins: [...] array and add mcp({ loginPage: "/login" }):
import { mcp } from "better-auth/plugins/mcp";
export const auth = betterAuth({
// ... existing config
plugins: [
// ... existing plugins
mcp({ loginPage: "/login" }),
],
});
Create src/app/api/mcp/route.ts
Use the template at assets/mcp-route.ts.template from the scaffold-internal-tool skill (the content is portable — just substitute {{IF_*}} for the present case).
Create src/app/.well-known/oauth-authorization-server/route.ts
import { auth } from "@/server/auth";
export async function GET() {
return Response.json(await auth.api.getMcpOAuthMetadata());
}
(Better Auth's mcp plugin exposes this metadata helper — version may differ; check better-auth/plugins/mcp exports if the name changed.)
Create src/server/mcp/registry.ts and src/server/mcp/tools/_example-search.ts
Use the templates mcp-registry.ts.template and mcp-tool-example.ts.template from the scaffold-internal-tool skill.
Create migration
Run:
pnpm prisma migrate dev --name add_mcp_oauth_tables
Better Auth's CLI can generate the Prisma model declarations for the OAuth tables — see Better Auth docs for the current command (typically npx @better-auth/cli generate).
Update CLAUDE.md
Add to the stack section:
- **MCP:** Streamable HTTP at `/api/mcp`, Better Auth `mcp` plugin as OAuth provider. Tools in `src/server/mcp/tools/`.
Add to "Useful commands":
- Local MCP testing: Claude Desktop only accepts HTTPS connectors. Tunnel via `cloudflared tunnel --url http://localhost:3000` and update `BETTER_AUTH_URL` + `next.config.ts` `allowedDevOrigins` to the tunnel host while testing.
How to add more tools later
Tell the user (and put this in CLAUDE.md too):
To add an MCP tool:
- Create
src/server/mcp/tools/<tool-name>.tsexporting{ description, inputSchema, handler }.- The handler should validate its input via the same Zod schema as the corresponding tRPC procedure, then call the service method with the OAuth-derived
userId.- Register in
src/server/mcp/registry.ts.- Restart
pnpm dev. Test from Claude Desktop's MCP servers UI.
Verification
pnpm install
pnpm prisma migrate dev
pnpm tsc --noEmit
pnpm build
Don't try to actually exercise the MCP flow from this session — that requires an MCP client. Tell the user how to test it manually.