import { a as OAuthTokensSchema, i as OAuthTokenRevocationRequestSchema, n as OAuthClientInformationFullSchema, r as OAuthClientMetadataSchema } from "./src-CracgD9q.mjs";
import express from "express";
import { rateLimit } from "express-rate-limit";
import * as z from "zod/v4";
import cors from "cors";
import crypto from "node:crypto";
import { verifyChallenge } from "pkce-challenge";

//#region src/auth/errors.ts
/**
* Base class for all OAuth errors
*/
var OAuthError = class extends Error {
	static errorCode;
	constructor(message, errorUri) {
		super(message);
		this.errorUri = errorUri;
		this.name = this.constructor.name;
	}
	/**
	* Converts the error to a standard OAuth error response object
	*/
	toResponseObject() {
		const response = {
			error: this.errorCode,
			error_description: this.message
		};
		if (this.errorUri) response.error_uri = this.errorUri;
		return response;
	}
	get errorCode() {
		return this.constructor.errorCode;
	}
};
/**
* Invalid request error - The request is missing a required parameter,
* includes an invalid parameter value, includes a parameter more than once,
* or is otherwise malformed.
*/
var InvalidRequestError = class extends OAuthError {
	static errorCode = "invalid_request";
};
/**
* Invalid client error - Client authentication failed (e.g., unknown client, no client
* authentication included, or unsupported authentication method).
*/
var InvalidClientError = class extends OAuthError {
	static errorCode = "invalid_client";
};
/**
* Invalid grant error - The provided authorization grant or refresh token is
* invalid, expired, revoked, does not match the redirection URI used in the
* authorization request, or was issued to another client.
*/
var InvalidGrantError = class extends OAuthError {
	static errorCode = "invalid_grant";
};
/**
* Unauthorized client error - The authenticated client is not authorized to use
* this authorization grant type.
*/
var UnauthorizedClientError = class extends OAuthError {
	static errorCode = "unauthorized_client";
};
/**
* Unsupported grant type error - The authorization grant type is not supported
* by the authorization server.
*/
var UnsupportedGrantTypeError = class extends OAuthError {
	static errorCode = "unsupported_grant_type";
};
/**
* Invalid scope error - The requested scope is invalid, unknown, malformed, or
* exceeds the scope granted by the resource owner.
*/
var InvalidScopeError = class extends OAuthError {
	static errorCode = "invalid_scope";
};
/**
* Access denied error - The resource owner or authorization server denied the request.
*/
var AccessDeniedError = class extends OAuthError {
	static errorCode = "access_denied";
};
/**
* Server error - The authorization server encountered an unexpected condition
* that prevented it from fulfilling the request.
*/
var ServerError = class extends OAuthError {
	static errorCode = "server_error";
};
/**
* Temporarily unavailable error - The authorization server is currently unable to
* handle the request due to a temporary overloading or maintenance of the server.
*/
var TemporarilyUnavailableError = class extends OAuthError {
	static errorCode = "temporarily_unavailable";
};
/**
* Unsupported response type error - The authorization server does not support
* obtaining an authorization code using this method.
*/
var UnsupportedResponseTypeError = class extends OAuthError {
	static errorCode = "unsupported_response_type";
};
/**
* Unsupported token type error - The authorization server does not support
* the requested token type.
*/
var UnsupportedTokenTypeError = class extends OAuthError {
	static errorCode = "unsupported_token_type";
};
/**
* Invalid token error - The access token provided is expired, revoked, malformed,
* or invalid for other reasons.
*/
var InvalidTokenError = class extends OAuthError {
	static errorCode = "invalid_token";
};
/**
* Method not allowed error - The HTTP method used is not allowed for this endpoint.
* (Custom, non-standard error)
*/
var MethodNotAllowedError = class extends OAuthError {
	static errorCode = "method_not_allowed";
};
/**
* Too many requests error - Rate limit exceeded.
* (Custom, non-standard error based on RFC 6585)
*/
var TooManyRequestsError = class extends OAuthError {
	static errorCode = "too_many_requests";
};
/**
* Invalid client metadata error - The client metadata is invalid.
* (Custom error for dynamic client registration - RFC 7591)
*/
var InvalidClientMetadataError = class extends OAuthError {
	static errorCode = "invalid_client_metadata";
};
/**
* Insufficient scope error - The request requires higher privileges than provided by the access token.
*/
var InsufficientScopeError = class extends OAuthError {
	static errorCode = "insufficient_scope";
};
/**
* Invalid target error - The requested resource is invalid, missing, unknown, or malformed.
* (Custom error for resource indicators - RFC 8707)
*/
var InvalidTargetError = class extends OAuthError {
	static errorCode = "invalid_target";
};
/**
* A utility class for defining one-off error codes
*/
var CustomOAuthError = class extends OAuthError {
	constructor(customErrorCode, message, errorUri) {
		super(message, errorUri);
		this.customErrorCode = customErrorCode;
	}
	get errorCode() {
		return this.customErrorCode;
	}
};
/**
* A full list of all OAuthErrors, enabling parsing from error responses
*/
const OAUTH_ERRORS = {
	[InvalidRequestError.errorCode]: InvalidRequestError,
	[InvalidClientError.errorCode]: InvalidClientError,
	[InvalidGrantError.errorCode]: InvalidGrantError,
	[UnauthorizedClientError.errorCode]: UnauthorizedClientError,
	[UnsupportedGrantTypeError.errorCode]: UnsupportedGrantTypeError,
	[InvalidScopeError.errorCode]: InvalidScopeError,
	[AccessDeniedError.errorCode]: AccessDeniedError,
	[ServerError.errorCode]: ServerError,
	[TemporarilyUnavailableError.errorCode]: TemporarilyUnavailableError,
	[UnsupportedResponseTypeError.errorCode]: UnsupportedResponseTypeError,
	[UnsupportedTokenTypeError.errorCode]: UnsupportedTokenTypeError,
	[InvalidTokenError.errorCode]: InvalidTokenError,
	[MethodNotAllowedError.errorCode]: MethodNotAllowedError,
	[TooManyRequestsError.errorCode]: TooManyRequestsError,
	[InvalidClientMetadataError.errorCode]: InvalidClientMetadataError,
	[InsufficientScopeError.errorCode]: InsufficientScopeError,
	[InvalidTargetError.errorCode]: InvalidTargetError
};

//#endregion
//#region src/auth/middleware/allowedMethods.ts
/**
* Middleware to handle unsupported HTTP methods with a 405 Method Not Allowed response.
*
* @param allowedMethods Array of allowed HTTP methods for this endpoint (e.g., ['GET', 'POST'])
* @returns Express middleware that returns a 405 error if method not in allowed list
*/
function allowedMethods(allowedMethods$1) {
	return (req, res, next) => {
		if (allowedMethods$1.includes(req.method)) {
			next();
			return;
		}
		const error = new MethodNotAllowedError(`The method ${req.method} is not allowed for this endpoint`);
		res.status(405).set("Allow", allowedMethods$1.join(", ")).json(error.toResponseObject());
	};
}

//#endregion
//#region src/auth/handlers/authorize.ts
const LOOPBACK_HOSTS = new Set([
	"localhost",
	"127.0.0.1",
	"[::1]"
]);
/**
* Validates a requested redirect_uri against a registered one.
*
* Per RFC 8252 §7.3 (OAuth 2.0 for Native Apps), authorization servers MUST
* allow any port for loopback redirect URIs (localhost, 127.0.0.1, [::1]) to
* accommodate native clients that obtain an ephemeral port from the OS. For
* non-loopback URIs, exact match is required.
*
* @see https://datatracker.ietf.org/doc/html/rfc8252#section-7.3
*/
function redirectUriMatches(requested, registered) {
	if (requested === registered) return true;
	let req, reg;
	try {
		req = new URL(requested);
		reg = new URL(registered);
	} catch {
		return false;
	}
	if (!LOOPBACK_HOSTS.has(req.hostname) || !LOOPBACK_HOSTS.has(reg.hostname)) return false;
	return req.protocol === reg.protocol && req.hostname === reg.hostname && req.pathname === reg.pathname && req.search === reg.search;
}
const ClientAuthorizationParamsSchema = z.object({
	client_id: z.string(),
	redirect_uri: z.string().optional().refine((value) => value === void 0 || URL.canParse(value), { message: "redirect_uri must be a valid URL" })
});
const RequestAuthorizationParamsSchema = z.object({
	response_type: z.literal("code"),
	code_challenge: z.string(),
	code_challenge_method: z.literal("S256"),
	scope: z.string().optional(),
	state: z.string().optional(),
	resource: z.string().url().optional()
});
function authorizationHandler({ provider, issuerUrl, rateLimit: rateLimitConfig }) {
	const issuer = issuerUrl?.href;
	const router = express.Router();
	router.use(allowedMethods(["GET", "POST"]));
	router.use(express.urlencoded({ extended: false }));
	if (rateLimitConfig !== false) router.use(rateLimit({
		windowMs: 900 * 1e3,
		max: 100,
		standardHeaders: true,
		legacyHeaders: false,
		message: new TooManyRequestsError("You have exceeded the rate limit for authorization requests").toResponseObject(),
		...rateLimitConfig
	}));
	router.all("/", async (req, res) => {
		res.setHeader("Cache-Control", "no-store");
		let client_id, redirect_uri, client;
		try {
			const result = ClientAuthorizationParamsSchema.safeParse(req.method === "POST" ? req.body : req.query);
			if (!result.success) throw new InvalidRequestError(result.error.message);
			client_id = result.data.client_id;
			redirect_uri = result.data.redirect_uri;
			client = await provider.clientsStore.getClient(client_id);
			if (!client) throw new InvalidClientError("Invalid client_id");
			if (redirect_uri !== void 0) {
				const requested = redirect_uri;
				if (!client.redirect_uris.some((registered) => redirectUriMatches(requested, registered))) throw new InvalidRequestError("Unregistered redirect_uri");
			} else if (client.redirect_uris.length === 1) redirect_uri = client.redirect_uris[0];
			else throw new InvalidRequestError("redirect_uri must be specified when client has multiple registered URIs");
		} catch (error) {
			if (error instanceof OAuthError) {
				const status = error instanceof ServerError ? 500 : 400;
				res.status(status).json(error.toResponseObject());
			} else {
				const serverError = new ServerError("Internal Server Error");
				res.status(500).json(serverError.toResponseObject());
			}
			return;
		}
		let state;
		try {
			const parseResult = RequestAuthorizationParamsSchema.safeParse(req.method === "POST" ? req.body : req.query);
			if (!parseResult.success) throw new InvalidRequestError(parseResult.error.message);
			const { scope, code_challenge, resource } = parseResult.data;
			state = parseResult.data.state;
			let requestedScopes = [];
			if (scope !== void 0) requestedScopes = scope.split(" ");
			await provider.authorize(client, {
				state,
				scopes: requestedScopes,
				redirectUri: redirect_uri,
				codeChallenge: code_challenge,
				resource: resource ? new URL(resource) : void 0,
				issuer
			}, issuer ? withIssOnCallbackRedirect(res, redirect_uri, issuer) : res);
		} catch (error) {
			if (error instanceof OAuthError) res.redirect(302, createErrorRedirect(redirect_uri, error, state, issuer));
			else {
				const serverError = new ServerError("Internal Server Error");
				res.redirect(302, createErrorRedirect(redirect_uri, serverError, state, issuer));
			}
		}
	});
	return router;
}
/**
* Wraps `res.redirect` so that when the provider redirects to the client's validated
* `redirect_uri` (i.e. the OAuth authorization response), `iss` is appended per RFC 9207.
* Only redirects whose origin and path match `redirectUri` are touched; an `iss` already
* set by the provider is preserved. This is what backs the
* `authorization_response_iss_parameter_supported: true` metadata claim without requiring
* `OAuthServerProvider.authorize()` implementations to change.
*/
function withIssOnCallbackRedirect(res, redirectUri, issuer) {
	const cb = new URL(redirectUri);
	const appendIss = (url) => {
		let target;
		try {
			target = new URL(url);
		} catch {
			return url;
		}
		if (target.origin === cb.origin && target.pathname === cb.pathname && !target.searchParams.has("iss")) {
			target.searchParams.set("iss", issuer);
			return target.href;
		}
		return url;
	};
	const original = res.redirect.bind(res);
	res.redirect = ((statusOrUrl, maybeUrl) => {
		if (typeof statusOrUrl === "number") original(statusOrUrl, appendIss(String(maybeUrl)));
		else if (typeof maybeUrl === "number") original(appendIss(statusOrUrl), maybeUrl);
		else original(appendIss(statusOrUrl));
	});
	return res;
}
/**
* Helper function to create redirect URL with error parameters
*/
function createErrorRedirect(redirectUri, error, state, issuer) {
	const errorUrl = new URL(redirectUri);
	errorUrl.searchParams.set("error", error.errorCode);
	errorUrl.searchParams.set("error_description", error.message);
	if (error.errorUri) errorUrl.searchParams.set("error_uri", error.errorUri);
	if (state) errorUrl.searchParams.set("state", state);
	if (issuer) errorUrl.searchParams.set("iss", issuer);
	return errorUrl.href;
}

//#endregion
//#region src/auth/handlers/metadata.ts
function metadataHandler(metadata) {
	const router = express.Router();
	router.use(cors());
	router.use(allowedMethods(["GET", "OPTIONS"]));
	router.get("/", (req, res) => {
		res.status(200).json(metadata);
	});
	return router;
}

//#endregion
//#region src/auth/handlers/register.ts
const DEFAULT_CLIENT_SECRET_EXPIRY_SECONDS = 720 * 60 * 60;
function clientRegistrationHandler({ clientsStore, clientSecretExpirySeconds = DEFAULT_CLIENT_SECRET_EXPIRY_SECONDS, rateLimit: rateLimitConfig, clientIdGeneration = true }) {
	if (!clientsStore.registerClient) throw new Error("Client registration store does not support registering clients");
	const router = express.Router();
	router.use(cors());
	router.use(allowedMethods(["POST"]));
	router.use(express.json());
	if (rateLimitConfig !== false) router.use(rateLimit({
		windowMs: 3600 * 1e3,
		max: 20,
		standardHeaders: true,
		legacyHeaders: false,
		message: new TooManyRequestsError("You have exceeded the rate limit for client registration requests").toResponseObject(),
		...rateLimitConfig
	}));
	router.post("/", async (req, res) => {
		res.setHeader("Cache-Control", "no-store");
		try {
			const parseResult = OAuthClientMetadataSchema.safeParse(req.body);
			if (!parseResult.success) throw new InvalidClientMetadataError(parseResult.error.message);
			const clientMetadata = parseResult.data;
			const isPublicClient = clientMetadata.token_endpoint_auth_method === "none";
			const clientSecret = isPublicClient ? void 0 : crypto.randomBytes(32).toString("hex");
			const clientIdIssuedAt = Math.floor(Date.now() / 1e3);
			const secretExpiryTime = clientSecretExpirySeconds > 0 ? clientIdIssuedAt + clientSecretExpirySeconds : 0;
			const clientSecretExpiresAt = isPublicClient ? void 0 : secretExpiryTime;
			let clientInfo = {
				...clientMetadata,
				client_secret: clientSecret,
				client_secret_expires_at: clientSecretExpiresAt
			};
			if (clientIdGeneration) {
				clientInfo.client_id = crypto.randomUUID();
				clientInfo.client_id_issued_at = clientIdIssuedAt;
			}
			clientInfo = await clientsStore.registerClient(clientInfo);
			res.status(201).json(clientInfo);
		} catch (error) {
			if (error instanceof OAuthError) {
				const status = error instanceof ServerError ? 500 : 400;
				res.status(status).json(error.toResponseObject());
			} else {
				const serverError = new ServerError("Internal Server Error");
				res.status(500).json(serverError.toResponseObject());
			}
		}
	});
	return router;
}

//#endregion
//#region src/auth/middleware/clientAuth.ts
const ClientAuthenticatedRequestSchema = z.object({
	client_id: z.string(),
	client_secret: z.string().optional()
});
function authenticateClient({ clientsStore }) {
	return async (req, res, next) => {
		try {
			const result = ClientAuthenticatedRequestSchema.safeParse(req.body);
			if (!result.success) throw new InvalidRequestError(String(result.error));
			const { client_id, client_secret } = result.data;
			const client = await clientsStore.getClient(client_id);
			if (!client) throw new InvalidClientError("Invalid client_id");
			if (client.client_secret) {
				if (!client_secret) throw new InvalidClientError("Client secret is required");
				if (client.client_secret !== client_secret) throw new InvalidClientError("Invalid client_secret");
				if (client.client_secret_expires_at && client.client_secret_expires_at < Math.floor(Date.now() / 1e3)) throw new InvalidClientError("Client secret has expired");
			}
			req.client = client;
			next();
		} catch (error) {
			if (error instanceof OAuthError) {
				const status = error instanceof ServerError ? 500 : 400;
				res.status(status).json(error.toResponseObject());
			} else {
				const serverError = new ServerError("Internal Server Error");
				res.status(500).json(serverError.toResponseObject());
			}
		}
	};
}

//#endregion
//#region src/auth/handlers/revoke.ts
function revocationHandler({ provider, rateLimit: rateLimitConfig }) {
	if (!provider.revokeToken) throw new Error("Auth provider does not support revoking tokens");
	const router = express.Router();
	router.use(cors());
	router.use(allowedMethods(["POST"]));
	router.use(express.urlencoded({ extended: false }));
	if (rateLimitConfig !== false) router.use(rateLimit({
		windowMs: 900 * 1e3,
		max: 50,
		standardHeaders: true,
		legacyHeaders: false,
		message: new TooManyRequestsError("You have exceeded the rate limit for token revocation requests").toResponseObject(),
		...rateLimitConfig
	}));
	router.use(authenticateClient({ clientsStore: provider.clientsStore }));
	router.post("/", async (req, res) => {
		res.setHeader("Cache-Control", "no-store");
		try {
			const parseResult = OAuthTokenRevocationRequestSchema.safeParse(req.body);
			if (!parseResult.success) throw new InvalidRequestError(parseResult.error.message);
			const client = req.client;
			if (!client) throw new ServerError("Internal Server Error");
			await provider.revokeToken(client, parseResult.data);
			res.status(200).json({});
		} catch (error) {
			if (error instanceof OAuthError) {
				const status = error instanceof ServerError ? 500 : 400;
				res.status(status).json(error.toResponseObject());
			} else {
				const serverError = new ServerError("Internal Server Error");
				res.status(500).json(serverError.toResponseObject());
			}
		}
	});
	return router;
}

//#endregion
//#region src/auth/handlers/token.ts
const TokenRequestSchema = z.object({ grant_type: z.string() });
const AuthorizationCodeGrantSchema = z.object({
	code: z.string(),
	code_verifier: z.string(),
	redirect_uri: z.string().optional(),
	resource: z.string().url().optional()
});
const RefreshTokenGrantSchema = z.object({
	refresh_token: z.string(),
	scope: z.string().optional(),
	resource: z.string().url().optional()
});
function tokenHandler({ provider, rateLimit: rateLimitConfig }) {
	const router = express.Router();
	router.use(cors());
	router.use(allowedMethods(["POST"]));
	router.use(express.urlencoded({ extended: false }));
	if (rateLimitConfig !== false) router.use(rateLimit({
		windowMs: 900 * 1e3,
		max: 50,
		standardHeaders: true,
		legacyHeaders: false,
		message: new TooManyRequestsError("You have exceeded the rate limit for token requests").toResponseObject(),
		...rateLimitConfig
	}));
	router.use(authenticateClient({ clientsStore: provider.clientsStore }));
	router.post("/", async (req, res) => {
		res.setHeader("Cache-Control", "no-store");
		try {
			const parseResult = TokenRequestSchema.safeParse(req.body);
			if (!parseResult.success) throw new InvalidRequestError(parseResult.error.message);
			const { grant_type } = parseResult.data;
			const client = req.client;
			if (!client) throw new ServerError("Internal Server Error");
			switch (grant_type) {
				case "authorization_code": {
					const parseResult$1 = AuthorizationCodeGrantSchema.safeParse(req.body);
					if (!parseResult$1.success) throw new InvalidRequestError(parseResult$1.error.message);
					const { code, code_verifier, redirect_uri, resource } = parseResult$1.data;
					const skipLocalPkceValidation = provider.skipLocalPkceValidation;
					if (!skipLocalPkceValidation) {
						if (!await verifyChallenge(code_verifier, await provider.challengeForAuthorizationCode(client, code))) throw new InvalidGrantError("code_verifier does not match the challenge");
					}
					const tokens = await provider.exchangeAuthorizationCode(client, code, skipLocalPkceValidation ? code_verifier : void 0, redirect_uri, resource ? new URL(resource) : void 0);
					res.status(200).json(tokens);
					break;
				}
				case "refresh_token": {
					const parseResult$1 = RefreshTokenGrantSchema.safeParse(req.body);
					if (!parseResult$1.success) throw new InvalidRequestError(parseResult$1.error.message);
					const { refresh_token, scope, resource } = parseResult$1.data;
					const scopes = scope?.split(" ");
					const tokens = await provider.exchangeRefreshToken(client, refresh_token, scopes, resource ? new URL(resource) : void 0);
					res.status(200).json(tokens);
					break;
				}
				default: throw new UnsupportedGrantTypeError("The grant type is not supported by this authorization server.");
			}
		} catch (error) {
			if (error instanceof OAuthError) {
				const status = error instanceof ServerError ? 500 : 400;
				res.status(status).json(error.toResponseObject());
			} else {
				const serverError = new ServerError("Internal Server Error");
				res.status(500).json(serverError.toResponseObject());
			}
		}
	});
	return router;
}

//#endregion
//#region src/auth/router.ts
const allowInsecureIssuerUrl = process.env.MCP_DANGEROUSLY_ALLOW_INSECURE_ISSUER_URL === "true" || process.env.MCP_DANGEROUSLY_ALLOW_INSECURE_ISSUER_URL === "1";
if (allowInsecureIssuerUrl) console.warn("MCP_DANGEROUSLY_ALLOW_INSECURE_ISSUER_URL is enabled - HTTP issuer URLs are allowed. Do not use in production.");
const checkIssuerUrl = (issuer) => {
	if (issuer.protocol !== "https:" && issuer.hostname !== "localhost" && issuer.hostname !== "127.0.0.1" && !allowInsecureIssuerUrl) throw new Error("Issuer URL must be HTTPS");
	if (issuer.hash) throw new Error(`Issuer URL must not have a fragment: ${issuer}`);
	if (issuer.search) throw new Error(`Issuer URL must not have a query string: ${issuer}`);
};
const createOAuthMetadata = (options) => {
	const issuer = options.issuerUrl;
	const baseUrl = options.baseUrl;
	checkIssuerUrl(issuer);
	const authorization_endpoint = "/authorize";
	const token_endpoint = "/token";
	const registration_endpoint = options.provider.clientsStore.registerClient ? "/register" : void 0;
	const revocation_endpoint = options.provider.revokeToken ? "/revoke" : void 0;
	return {
		issuer: issuer.href,
		service_documentation: options.serviceDocumentationUrl?.href,
		authorization_endpoint: new URL(authorization_endpoint, baseUrl || issuer).href,
		response_types_supported: ["code"],
		code_challenge_methods_supported: ["S256"],
		token_endpoint: new URL(token_endpoint, baseUrl || issuer).href,
		token_endpoint_auth_methods_supported: ["client_secret_post", "none"],
		grant_types_supported: ["authorization_code", "refresh_token"],
		scopes_supported: options.scopesSupported,
		revocation_endpoint: revocation_endpoint ? new URL(revocation_endpoint, baseUrl || issuer).href : void 0,
		revocation_endpoint_auth_methods_supported: revocation_endpoint ? ["client_secret_post"] : void 0,
		registration_endpoint: registration_endpoint ? new URL(registration_endpoint, baseUrl || issuer).href : void 0,
		authorization_response_iss_parameter_supported: options.provider.authorizationResponseIssParameterSupported ?? true
	};
};
/**
* Installs standard MCP authorization server endpoints, including dynamic client registration and token revocation (if supported).
* Also advertises standard authorization server metadata, for easier discovery of supported configurations by clients.
* Note: if your MCP server is only a resource server and not an authorization server, use mcpAuthMetadataRouter instead.
*
* By default, rate limiting is applied to all endpoints to prevent abuse.
*
* This router MUST be installed at the application root, like so:
*
*  const app = express();
*  app.use(mcpAuthRouter(...));
*/
function mcpAuthRouter(options) {
	const oauthMetadata = createOAuthMetadata(options);
	const router = express.Router();
	router.use(new URL(oauthMetadata.authorization_endpoint).pathname, authorizationHandler({
		provider: options.provider,
		issuerUrl: options.issuerUrl,
		...options.authorizationOptions
	}));
	router.use(new URL(oauthMetadata.token_endpoint).pathname, tokenHandler({
		provider: options.provider,
		...options.tokenOptions
	}));
	router.use(mcpAuthMetadataRouter({
		oauthMetadata,
		resourceServerUrl: options.resourceServerUrl ?? options.baseUrl ?? new URL(oauthMetadata.issuer),
		serviceDocumentationUrl: options.serviceDocumentationUrl,
		scopesSupported: options.scopesSupported,
		resourceName: options.resourceName
	}));
	if (oauthMetadata.registration_endpoint) router.use(new URL(oauthMetadata.registration_endpoint).pathname, clientRegistrationHandler({
		clientsStore: options.provider.clientsStore,
		...options.clientRegistrationOptions
	}));
	if (oauthMetadata.revocation_endpoint) router.use(new URL(oauthMetadata.revocation_endpoint).pathname, revocationHandler({
		provider: options.provider,
		...options.revocationOptions
	}));
	return router;
}
function mcpAuthMetadataRouter(options) {
	checkIssuerUrl(new URL(options.oauthMetadata.issuer));
	const router = express.Router();
	const protectedResourceMetadata = {
		resource: options.resourceServerUrl.href,
		authorization_servers: [options.oauthMetadata.issuer],
		scopes_supported: options.scopesSupported,
		resource_name: options.resourceName,
		resource_documentation: options.serviceDocumentationUrl?.href
	};
	const rsPath = new URL(options.resourceServerUrl.href).pathname;
	router.use(`/.well-known/oauth-protected-resource${rsPath === "/" ? "" : rsPath}`, metadataHandler(protectedResourceMetadata));
	router.use("/.well-known/oauth-authorization-server", metadataHandler(options.oauthMetadata));
	return router;
}
/**
* Helper function to construct the OAuth 2.0 Protected Resource Metadata URL
* from a given server URL. This replaces the path with the standard metadata endpoint.
*
* @param serverUrl - The base URL of the protected resource server
* @returns The URL for the OAuth protected resource metadata endpoint
*
* @example
* getOAuthProtectedResourceMetadataUrl(new URL('https://api.example.com/mcp'))
* // Returns: 'https://api.example.com/.well-known/oauth-protected-resource/mcp'
*/
function getOAuthProtectedResourceMetadataUrl(serverUrl) {
	const u = new URL(serverUrl.href);
	const rsPath = u.pathname && u.pathname !== "/" ? u.pathname : "";
	return new URL(`/.well-known/oauth-protected-resource${rsPath}`, u).href;
}

//#endregion
//#region src/auth/providers/proxyProvider.ts
/**
* Implements an OAuth server that proxies requests to another OAuth server.
*/
var ProxyOAuthServerProvider = class {
	_endpoints;
	_verifyAccessToken;
	_getClient;
	_fetch;
	skipLocalPkceValidation = true;
	/**
	* The proxy redirects the browser to the upstream AS's authorize endpoint with
	* `redirect_uri = params.redirectUri`, so the upstream — not this proxy — issues the
	* callback. The proxy cannot append its own `iss`, and any `iss` the upstream emits is the
	* upstream's issuer, not `issuerUrl`. Advertise `false` so the metadata does not over-claim —
	* a callback *without* `iss` then passes validation. Note: an upstream that *does* emit its
	* own `iss` will still mismatch this proxy's issuer and be rejected by RFC 9207 clients
	* regardless of this flag.
	*/
	authorizationResponseIssParameterSupported = false;
	revokeToken;
	constructor(options) {
		this._endpoints = options.endpoints;
		this._verifyAccessToken = options.verifyAccessToken;
		this._getClient = options.getClient;
		this._fetch = options.fetch;
		if (options.endpoints?.revocationUrl) this.revokeToken = async (client, request) => {
			const revocationUrl = this._endpoints.revocationUrl;
			if (!revocationUrl) throw new Error("No revocation endpoint configured");
			const params = new URLSearchParams();
			params.set("token", request.token);
			params.set("client_id", client.client_id);
			if (client.client_secret) params.set("client_secret", client.client_secret);
			if (request.token_type_hint) params.set("token_type_hint", request.token_type_hint);
			const response = await (this._fetch ?? fetch)(revocationUrl, {
				method: "POST",
				headers: { "Content-Type": "application/x-www-form-urlencoded" },
				body: params.toString()
			});
			await response.body?.cancel();
			if (!response.ok) throw new ServerError(`Token revocation failed: ${response.status}`);
		};
	}
	get clientsStore() {
		const registrationUrl = this._endpoints.registrationUrl;
		return {
			getClient: this._getClient,
			...registrationUrl && { registerClient: async (client) => {
				const response = await (this._fetch ?? fetch)(registrationUrl, {
					method: "POST",
					headers: { "Content-Type": "application/json" },
					body: JSON.stringify(client)
				});
				if (!response.ok) {
					await response.body?.cancel();
					throw new ServerError(`Client registration failed: ${response.status}`);
				}
				const data = await response.json();
				return OAuthClientInformationFullSchema.parse(data);
			} }
		};
	}
	async authorize(client, params, res) {
		const targetUrl = new URL(this._endpoints.authorizationUrl);
		const searchParams = new URLSearchParams({
			client_id: client.client_id,
			response_type: "code",
			redirect_uri: params.redirectUri,
			code_challenge: params.codeChallenge,
			code_challenge_method: "S256"
		});
		if (params.state) searchParams.set("state", params.state);
		if (params.scopes?.length) searchParams.set("scope", params.scopes.join(" "));
		if (params.resource) searchParams.set("resource", params.resource.href);
		targetUrl.search = searchParams.toString();
		res.redirect(targetUrl.toString());
	}
	async challengeForAuthorizationCode(_client, _authorizationCode) {
		return "";
	}
	async exchangeAuthorizationCode(client, authorizationCode, codeVerifier, redirectUri, resource) {
		const params = new URLSearchParams({
			grant_type: "authorization_code",
			client_id: client.client_id,
			code: authorizationCode
		});
		if (client.client_secret) params.append("client_secret", client.client_secret);
		if (codeVerifier) params.append("code_verifier", codeVerifier);
		if (redirectUri) params.append("redirect_uri", redirectUri);
		if (resource) params.append("resource", resource.href);
		const response = await (this._fetch ?? fetch)(this._endpoints.tokenUrl, {
			method: "POST",
			headers: { "Content-Type": "application/x-www-form-urlencoded" },
			body: params.toString()
		});
		if (!response.ok) {
			await response.body?.cancel();
			throw new ServerError(`Token exchange failed: ${response.status}`);
		}
		const data = await response.json();
		return OAuthTokensSchema.parse(data);
	}
	async exchangeRefreshToken(client, refreshToken, scopes, resource) {
		const params = new URLSearchParams({
			grant_type: "refresh_token",
			client_id: client.client_id,
			refresh_token: refreshToken
		});
		if (client.client_secret) params.set("client_secret", client.client_secret);
		if (scopes?.length) params.set("scope", scopes.join(" "));
		if (resource) params.set("resource", resource.href);
		const response = await (this._fetch ?? fetch)(this._endpoints.tokenUrl, {
			method: "POST",
			headers: { "Content-Type": "application/x-www-form-urlencoded" },
			body: params.toString()
		});
		if (!response.ok) {
			await response.body?.cancel();
			throw new ServerError(`Token refresh failed: ${response.status}`);
		}
		const data = await response.json();
		return OAuthTokensSchema.parse(data);
	}
	async verifyAccessToken(token) {
		return this._verifyAccessToken(token);
	}
};

//#endregion
//#region src/auth/middleware/bearerAuth.ts
/**
* Middleware that requires a valid Bearer token in the Authorization header.
*
* This will validate the token with the auth provider and add the resulting auth info to the request object.
*
* If resourceMetadataUrl is provided, it will be included in the WWW-Authenticate header
* for 401 responses as per the OAuth 2.0 Protected Resource Metadata spec.
*/
function requireBearerAuth({ verifier, requiredScopes = [], resourceMetadataUrl }) {
	const buildWwwAuthHeader = (errorCode, message) => {
		let header = `Bearer error="${errorCode}", error_description="${message}"`;
		if (requiredScopes.length > 0) header += `, scope="${requiredScopes.join(" ")}"`;
		if (resourceMetadataUrl) header += `, resource_metadata="${resourceMetadataUrl}"`;
		return header;
	};
	return async (req, res, next) => {
		try {
			const authHeader = req.headers.authorization;
			if (!authHeader) throw new InvalidTokenError("Missing Authorization header");
			const [type, token] = authHeader.split(" ");
			if (!type || type.toLowerCase() !== "bearer" || !token) throw new InvalidTokenError("Invalid Authorization header format, expected 'Bearer TOKEN'");
			const authInfo = await verifier.verifyAccessToken(token);
			if (requiredScopes.length > 0) {
				if (!requiredScopes.every((scope) => authInfo.scopes.includes(scope))) throw new InsufficientScopeError("Insufficient scope");
			}
			if (typeof authInfo.expiresAt !== "number" || Number.isNaN(authInfo.expiresAt)) throw new InvalidTokenError("Token has no expiration time");
			else if (authInfo.expiresAt < Date.now() / 1e3) throw new InvalidTokenError("Token has expired");
			req.auth = authInfo;
			next();
		} catch (error) {
			if (error instanceof InvalidTokenError) {
				res.set("WWW-Authenticate", buildWwwAuthHeader(error.errorCode, error.message));
				res.status(401).json(error.toResponseObject());
			} else if (error instanceof InsufficientScopeError) {
				res.set("WWW-Authenticate", buildWwwAuthHeader(error.errorCode, error.message));
				res.status(403).json(error.toResponseObject());
			} else if (error instanceof ServerError) res.status(500).json(error.toResponseObject());
			else if (error instanceof OAuthError) res.status(400).json(error.toResponseObject());
			else {
				const serverError = new ServerError("Internal Server Error");
				res.status(500).json(serverError.toResponseObject());
			}
		}
	};
}

//#endregion
export { TooManyRequestsError as A, InvalidTargetError as C, OAuthError as D, OAUTH_ERRORS as E, UnsupportedGrantTypeError as M, UnsupportedResponseTypeError as N, ServerError as O, UnsupportedTokenTypeError as P, InvalidScopeError as S, MethodNotAllowedError as T, InsufficientScopeError as _, mcpAuthMetadataRouter as a, InvalidGrantError as b, revocationHandler as c, metadataHandler as d, authorizationHandler as f, CustomOAuthError as g, AccessDeniedError as h, getOAuthProtectedResourceMetadataUrl as i, UnauthorizedClientError as j, TemporarilyUnavailableError as k, authenticateClient as l, allowedMethods as m, ProxyOAuthServerProvider as n, mcpAuthRouter as o, redirectUriMatches as p, createOAuthMetadata as r, tokenHandler as s, requireBearerAuth as t, clientRegistrationHandler as u, InvalidClientError as v, InvalidTokenError as w, InvalidRequestError as x, InvalidClientMetadataError as y };
//# sourceMappingURL=auth-afgVqjNE.mjs.map