Demo/Section 5/Three patterns. That's the engineering surface.
Section 5 · Step 1

Three patterns. That's the engineering surface.

MCP server auth middleware. Agent-side token acquisition. Connection token fetching in tool handlers. Everything else is configuration in Descope.

loan-ops-mcp/src/middleware/auth.ts
ts
// loan-ops-mcp/src/middleware/auth.ts
import { jwtVerify, createRemoteJWKSet } from "jose";

const JWKS = createRemoteJWKSet(
  new URL("https://auth.northwind.com/.well-known/jwks.json"),
);

export async function requireUser(req, res, next) {
  const token = req.headers.authorization?.replace(/^Bearer\s+/i, "");
  if (!token) return res.status(401).json({ error: "no_token" });

  try {
    const { payload } = await jwtVerify(token, JWKS, {
      issuer: "https://auth.northwind.com",
      audience: "loan-ops-mcp",
    });

    req.user = {
      sub: payload.sub,
      roles: Array.isArray(payload.roles) ? payload.roles : [],
      scopes:
        typeof payload.scope === "string"
          ? payload.scope.split(" ").filter(Boolean)
          : Array.isArray(payload.scopes)
            ? payload.scopes
            : [],
      clientId: payload.client_id ?? payload.azp ?? "unknown-client",
      tenant: payload.tenantId,
    };
    next();
  } catch {
    return res.status(401).json({ error: "invalid_token" });
  }
}

export function requireScope(required: string) {
  return (req, res, next) => {
    if (!req.user?.scopes.includes(required)) {
      return res.status(403).json({
        error: "insufficient_scopes",
        required,
        had: req.user?.scopes,
      });
    }
    next();
  };
}
Take-away

Two functions: validate the token, check the scope. The MCP server doesn't own access logic — it validates what Descope decided.

What the audience just saw
  • Section 1: An MCP server that didn't need a new permission model — it reads Okta roles via Descope and checks scopes per tool.
  • Section 2: Agents that don't hold secrets. Credentials retrieved on demand, user-delegated or machine, same SDK shape.
  • Section 3: A single Agent Directory across MCP, AgentCore, n8n, and custom agents — with real revocation that invalidates tokens immediately.
  • Section 4: Policy conditions written against the Okta groups Northwind already maintains — extended into the MCP layer.