Labsco
MCP SERVER

MCP Server + Asgardeo

by sagara-gunathunga

A remote MCP server on Cloudflare Workers where Asgardeo decides who sees which tool.

Identity, Access, Secrets & Encryption
Summary
The interesting part is what the user cannot see.

Most auth samples stop at logging the user in. This one carries roles from Asgardeo into tool listing, so a user without the `manager` role never sees the reportees tool at all — a cleaner failure mode than an authorised call that returns an error. Two setup steps catch people out: the callback URL has to be added to the Asgardeo application twice, once for `http://localhost:8788/callback` and again for the deployed Worker URL, and Cursor needs `mcp-remote` in front because it does not do MCP authentication itself.

What it is

A working sample of an authenticated remote MCP server. It runs on Cloudflare Workers and sits between two OAuth roles at once: an OAuth server to your MCP clients, and an OAuth/OIDC client to your Asgardeo organization.

What you get
  • Login before tool use: connecting a client redirects the user to Asgardeo and back
  • Role-scoped tool visibility — every authenticated user gets `userInfo`, while `getDirectReportees` appears only for users holding the `manager` role, and stays invisible to everyone else
  • A deployable path end to end: `npm run dev` locally on `http://localhost:8788`, then `npx wrangler@latest deploy` to a workers.dev URL
  • SSE transport, testable from the MCP Inspector or the Cloudflare Workers AI LLM Playground
Requirements

An Asgardeo account and a Cloudflare account, plus Node.js version 18.x or higher. In Asgardeo, register a Traditional Web Application over OpenID Connect and note the client id, the client secret and your organization name. Locally these go in a `.dev.vars` file as `ASGARDEO_CLIENT_ID`, `ASGARDEO_CLIENT_SECRET`, `ASGARDEO_BASE_URL` and `ASGARDEO_SCOPE`; for deployment they are set as Wrangler secrets along with a `COOKIE_ENCRYPTION_KEY`. You also create a KV namespace bound as `OAUTH_KV` and paste its id into `wrangler.jsonc`.