/mcp URL — no token in the URL, and
every request carrying the signed-in user’s own identity.
Getting there is mostly mechanical: four small files, a few wrangler commands, and
some log-reading. So you don’t have to do it by hand. Each section hands its work to
a coding agent as a ready-made prompt — you supply two URLs and a couple of clicks in
Xano, and the agent does the rest.
Everything between here and there is context: who this is for, how the pieces fit, and
the two URLs to have ready. Skip to the first prompt
if you’d rather start building and backfill the reasoning later.
Who is this for?
Two things decide it: what your client can send, and whether you need each user to arrive as themselves rather than as one shared token. Your Xano server doesn’t come into it./authorize,
no /token, and no discovery document for a client to find. What they do have is
per-tool authentication: set a tool’s Authentication to user authentication and
Xano validates a Xano user-table JWT on the Authorization header natively, populating
$auth. That’s the mechanism this whole page is built on.
Xano issues those JWTs perfectly well — that’s security.create_auth_token behind your own
/auth/login. They just aren’t reachable through an OAuth handshake. The Worker supplies
that missing front end: it speaks OAuth to the client, exchanges the sign-in for a Xano user
JWT, and forwards that upstream.
A token in the URL won’t work on Claude surfaces. Add a connector URL with the token in
it and Claude sends you to an OAuth consent page that can’t complete — it runs an OAuth
handshake for every custom connector, and a Xano MCP server has no authorization server to
hand it off to. The MCP spec also prohibits access tokens in the URI query string, and has
since the 2025-06-18 revision; the current 2026-07-28 revision keeps that ban. Either
way, a token in a URL is one shared credential that lands in logs, proxies, and browser
history.
What about the Request headers field in Anthropic's docs?
What about the Request headers field in Anthropic's docs?
The spec details, if you want them
The spec details, if you want them
401 and not a 200,
PKCE, DCR versus CIMD, and what the current MCP 2026-07-28 revision changed, including DCR
being deprecated in favor of Client ID Metadata Documents — is in
Manual setup.You don’t need any of it to follow this page. @cloudflare/workers-oauth-provider satisfies
all of it out of the box, and the verification prompt below confirms it on your deployment.How it works
Two hops, no URL tokens:- Client → Worker: a Worker-issued OAuth access token.
- Worker → Xano: that user’s own Xano user-table JWT.
$auth.
Why a transparent proxy instead of Cloudflare's McpAgent
Why a transparent proxy instead of Cloudflare's McpAgent
McpAgent runs on Durable Objects, which require a paid Workers plan. A stateless
reverse proxy keeps the MCP session on Xano — the Worker only round-trips the
Mcp-Session-Id header — so this runs on Cloudflare’s free plan.What you need
A Xano MCP server with at least one tool, a Cloudflare account (free plan is enough), and Node.js 18+ —wrangler runs through npx.
The prompts on this page are written for a coding agent working against your Xano
workspace files, so you also want the Developer
MCP and the Xano CLI set up in
that agent, with xano workspace pull already run — that local path is what the first
prompt asks you to paste.
Plus the two URLs below. These are the only values an agent can’t discover for you, so
collect them before you start.
mcp appears twice. Copy it rather than assembling it by hand — a wrong
shape 404s instead of erroring usefully.POST /auth/login → copy the full URL of any endpoint in it and drop everything after
the /api:{canonical} segment.That endpoint must return { authToken } from security.create_auth_token. No
trailing slash.Reading the parts, and the CLI alternative
Reading the parts, and the CLI alternative
{instance-host} — the hostname of your Xano instance, like
x8ki-letl-twmt.n7.xano.io. Only the path differs. If you ever need it on its own,
open Instance Settings from the instance selection screen; the host is everything
between https:// and the first / in the URLs shown there.In the stream URL, the {canonical} segment is your MCP server’s ID, and the
/mcp/stream that follows it is literal — which is why mcp appears twice.Both canonicals also live in your pulled workspace files, if you’d rather not click
through the dashboard:The work, and who does it
The build splits cleanly in two, and it’s worth knowing which is which before you let an agent loose — they touch completely different things.In Xano — gate your tools
Xano is what actually decides whether a tool call is allowed — the Worker only forwards a JWT to it. So this side comes first: get your tools onto native user authentication. Get it wrong and the Worker will happily proxy calls to tools that never check anything. How much there is to do depends on where you’re starting. If your tools have no authentication yet, this is a dashboard toggle and nothing else. If you built your own checks — a validation function in each tool’s stack, middleware on your tools, or an MCP server trigger reading a token off the connection — native authentication replaces them, and leaving them in place can lock out the very users you’re about to onboard. This is also the first of the prompt cards. Each one says what its prompt does; Copy prompt puts the full instruction on your clipboard — 20 to 40 lines, with the exact commands and what counts as passing.Audits how your tools authenticate today, proposes what native user authentication replaces, and verifies enforcement.
Authorization header to confirm Xano rejects it.
On Cloudflare — build and deploy the Worker
Four small files, deployed to your own Cloudflare account.@cloudflare/workers-oauth-provider does the OAuth heavy lifting: metadata documents,
/token, /register, PKCE enforcement, token issuance and rotation, and the 401 challenge.
Dynamic client registration — the /register endpoint — is deprecated as of the
2026-07-28 spec revision in favor of Client ID Metadata Documents, but it’s retained for
backward compatibility through at least a twelve-month window and Claude still supports it
out of the box. It’s the right thing to have, and to check for, today.
Scaffolds the four-file Worker and drives wrangler end to end — KV namespace, deploy, secrets.
src/index.ts, src/authorize.ts, src/proxy.ts and
wrangler.jsonc, then runs the whole wrangler sequence — login, create the KV namespace,
deploy to learn your workers.dev host, set the three secrets, redeploy. It will stop and
ask when wrangler login needs your browser. Your two URLs go in as secrets, not code, so
the same Worker can front a different Xano MCP later.
Runs the discovery and 401 checks, then reads the wrangler tail output for you.
curls the three discovery
endpoints to confirm the Worker is spec-compliant, then tails the Worker logs while you
connect with the MCP Inspector
(npx @modelcontextprotocol/inspector — you run this part) and tells you the first line
that deviates from a healthy run. Skipping it just means a later failure is harder to
attribute: this is what separates “the Worker is broken” from “the client is
misconfigured.” Every check is written out command by command in Step 4 — Test with the
MCP Inspector,
if you’d rather run them yourself.
Connect a client
Add a custom connector pointing at your Worker:initialize succeeding proves nothing, because Xano’s
authentication toggle gates tool calls only and an unauthenticated initialize still
returns 200.
If it doesn’t: connect with the MCP Inspector before you start changing Worker code.
It runs the same handshake outside your client, so it tells you which of the two is
actually at fault — about five minutes, and optional. Step 4 — Test with the MCP
Inspector
has the commands and the healthy log sequence to compare against.
Troubleshooting
Takes your failing symptom and works the table against your live Worker.
curl checks — then matches your symptom against the nine known failure modes and says
what rules the others out. The same causes are written out as a scannable table in Manual
setup if you’d rather
search for your error text yourself.
Stop the daily re-login (optional)
Kills the 24-hour re-login: adds a Xano refresh endpoint and wires it into tokenExchangeCallback.
POST /auth/refresh endpoint to your Xano auth group
and wires the Worker’s tokenExchangeCallback to call it. Worth running once you’re past
testing.
Add a consent screen (optional)
As built, the Worker treats a successful login as consent — you sign in and the grant is issued. That’s fine while you’re the only user. Once anyone else can reach the Worker, they should see what they’re approving and be able to say no.Inserts an explicit approve/deny step between login and grant issuance, with CSRF protection, and brands the pages.
/authorize into login → consent → grant. Deny becomes a real
outcome — the client gets an access_denied redirect rather than a grant it never asked
the user about — and the approve path gains CSRF protection, so a third-party page can’t
forge an approval on a signed-in user’s behalf. It also brands both pages with your display
name and icon, which is what people actually see during the handshake.
Skip it and the Worker still works exactly as before; you just have no consent record and
no deny path, which is only safe while you’re the only user.
Other limitations worth knowing about
Other limitations worth knowing about
- Gate every tool. Only tools set to user authentication are protected.
- One MCP server per Worker as written. To front several, select
XANO_MCP_STREAM_URLby request path and useapiHandlers(a route → handler map) instead of a singleapiHandler. - Connector icons are resolved from the HTML your Worker serves at
/, and are cached per domain. See Icons and display name.