QUESTPIE
GuidesConnect an agent

Deploy it and connect Claude

Claude's remote connectors run from Anthropic's cloud, so they cannot reach localhost. This is the public deployment they need and the checks that prove it works before you add the connector.

View markdown

The editor worked because it runs on the same machine as the dev server. A remote connector does not, so http://localhost:3000/api/mcp is unreachable to it. The desktop app is no exception. Everything below is the same app, on a real domain.

Set the deployed origin

Production environment
APP_URL=https://cms.example.com
BETTER_AUTH_SECRET=<a-strong-production-secret>
DATABASE_URL=<production-postgres-url>

APP_URL has to match the public origin exactly. Access tokens carry <APP_URL>/api/mcp as their audience, and verification rejects a token whose audience does not match. BETTER_AUTH_SECRET has a default in the starter's env schema. That default is for your laptop, not for a server.

Ship the schema as migrations

Fix the starter's migration path first. Codegen only discovers migrations in src/questpie/server/migrations, and questpie migrate runs only what codegen found. The starter's cli.migrations.directory sends new files to src/migrations instead, where nothing reads them. Delete that line from src/questpie/server/questpie.config.ts.

Then write the migration in development, read it, and commit it:

bun run migrate:create

Apply only committed files at deploy time:

bun run migrate

`migrate`, never `push`

questpie push writes the schema straight to whatever database it is pointed at. Keep it out of container commands, init containers, CI deploy steps and runbooks. --force does not make it safer.

Prove the endpoint before you connect

Discovery sits under the handler's base path, which is /api in the starters:

curl https://cms.example.com/api/.well-known/oauth-protected-resource
curl https://cms.example.com/api/.well-known/oauth-authorization-server

Both return JSON. Then check the endpoint itself:

curl -i -X POST https://cms.example.com/api/mcp

It must answer 401 with a WWW-Authenticate: Bearer resource_metadata="..." header. That header is what starts the OAuth flow in a compliant client. Use POST. A GET on /api/mcp returns 405 and tells you nothing.

A `200` there is a hole

POST /api/mcp with no session and no token must never succeed. If it does, the endpoint is answering unauthenticated callers and every tool you exposed is public.

Also confirm that /api/auth/oauth2/register, /admin/login and /admin/oauth/consent all resolve on the same deployment. A client walks through all three during its first connection.

Add the connector

Claude's remote connectors speak Streamable HTTP, run OAuth, and register themselves. So the endpoint URL is the whole configuration. Add https://cms.example.com/api/mcp as a custom connector and leave the advanced client ID and secret fields empty. Anthropic documents the individual and organization flows in Get started with custom connectors using remote MCP.

Then connect it. You sign in with a real account from this app and approve the scopes on your own consent screen. Nothing about that step is Anthropic's.

Do not put this server in claude_desktop_config.json. That file is for local stdio servers. This one is remote.

What the client can ask for

Of your resource scopes, the authorization server metadata lists only the coarse umbrellas, such as collections:read and collections:write. The granular per-resource scopes stay grantable but unlisted. Discovery does not enumerate your data model.

Consent can only narrow. The signed-in user's .access() rules run unchanged underneath, so the effective permission is the intersection of the two.

Next

Back to Connect an AI agent for the config and the custom tool. MCP over OAuth 2.1 covers registration, consent and token verification in full.

On this page