import { discoverAuthorizationServerMetadata, discoverOAuthProtectedResourceMetadata, exchangeAuthorization, registerClient, startAuthorization } from "@modelcontextprotocol/sdk/client/auth.js";

//#region src/utils/auth-detection.ts
/**
* Centralized authentication detection utilities for MCP tools
* Uses proper MCP OAuth specification (RFC 9728 + RFC 8414) for discovery
*/
/**
* Discovers OAuth scopes from server metadata, with preference for resource metadata scopes
*/
function discoverScopes(resourceMetadata, metadata) {
	const resourceScopes = resourceMetadata?.scopes_supported;
	const oauthScopes = metadata?.scopes_supported;
	const scopes = (resourceScopes?.length ? resourceScopes : oauthScopes) || [];
	return scopes.length > 0 ? scopes.join(" ") : void 0;
}
/**
* MCP Dynamic OAuth metadata discovery utility
* Implements RFC9728 (Protected Resource Metadata Discovery) + RFC8414 (Authorization Server Metadata Discovery)
*/
async function discoverMcpMetadata(mcpServerUrl, logger) {
	try {
		let resourceMetadata = null;
		let authServerUrl = new URL("/", mcpServerUrl);
		try {
			resourceMetadata = await discoverOAuthProtectedResourceMetadata(mcpServerUrl);
			if (resourceMetadata?.authorization_servers?.length && resourceMetadata.authorization_servers[0]) authServerUrl = new URL(resourceMetadata.authorization_servers[0]);
		} catch {}
		const metadata = await discoverAuthorizationServerMetadata(authServerUrl.href);
		if (!metadata) throw new Error("Failed to discover OAuth authorization server metadata");
		logger?.debug({
			tokenEndpoint: metadata.token_endpoint,
			authEndpoint: metadata.authorization_endpoint
		}, "MCP metadata discovery successful");
		const discoveredScopes = discoverScopes(resourceMetadata ?? void 0, metadata);
		return {
			success: true,
			metadata,
			...resourceMetadata && { resourceMetadata },
			...discoveredScopes && { scopes: discoveredScopes }
		};
	} catch (err) {
		const errorMessage = err instanceof Error ? err.message : String(err);
		logger?.debug({ error: errorMessage }, "MCP metadata discovery failed");
		return {
			success: false,
			error: errorMessage
		};
	}
}
/**
* Initiate MCP OAuth flow using the official MCP SDK
*/
async function initiateMcpOAuthFlow({ mcpServerUrl, redirectUri, state, clientName = "Inkeep Agent Framework", clientUri = "https://inkeep.com", logoUri, defaultClientId = "mcp-client", logger }) {
	const discoveryResult = await discoverMcpMetadata(mcpServerUrl, logger);
	if (!discoveryResult.success || !discoveryResult.metadata) throw new Error(`OAuth not supported by this server: ${discoveryResult.error}`);
	const { metadata, resourceMetadata, scopes: discoveredScopes } = discoveryResult;
	const clientMetadata = {
		redirect_uris: [redirectUri],
		token_endpoint_auth_method: "none",
		grant_types: ["authorization_code", "refresh_token"],
		response_types: ["code"],
		client_name: clientName,
		client_uri: clientUri,
		...logoUri && { logo_uri: logoUri }
	};
	let clientInformation;
	if (metadata.registration_endpoint) clientInformation = await registerClient(mcpServerUrl, {
		metadata,
		clientMetadata
	});
	else clientInformation = {
		client_id: defaultClientId,
		...clientMetadata
	};
	const resource = resourceMetadata?.resource ? new globalThis.URL(resourceMetadata.resource) : void 0;
	const authResult = await startAuthorization(mcpServerUrl, {
		metadata,
		clientInformation,
		redirectUrl: redirectUri,
		state,
		scope: discoveredScopes || "",
		...resource && { resource }
	});
	logger?.debug({
		authorizationUrl: authResult.authorizationUrl.href,
		scopes: discoveredScopes,
		clientId: clientInformation.client_id
	}, "MCP OAuth flow initiated successfully");
	return {
		authorizationUrl: authResult.authorizationUrl.href,
		codeVerifier: authResult.codeVerifier,
		state,
		clientInformation,
		metadata,
		resourceUrl: resource?.href || void 0,
		...discoveredScopes && { scopes: discoveredScopes }
	};
}
/**
* Exchange authorization code for tokens using MCP SDK
*/
async function exchangeMcpAuthorizationCode({ mcpServerUrl, metadata, clientInformation, authorizationCode, codeVerifier, redirectUri, resourceUrl, logger }) {
	const resource = resourceUrl ? new globalThis.URL(resourceUrl) : void 0;
	const tokens = await exchangeAuthorization(mcpServerUrl, {
		metadata,
		clientInformation,
		authorizationCode,
		codeVerifier,
		redirectUri,
		...resource && { resource }
	});
	logger?.debug({
		tokenType: tokens.token_type,
		hasRefreshToken: !!tokens.refresh_token,
		expiresIn: tokens.expires_in
	}, "MCP token exchange successful");
	return {
		access_token: tokens.access_token,
		refresh_token: tokens.refresh_token,
		expires_at: tokens.expires_in ? new Date(Date.now() + tokens.expires_in * 1e3) : void 0,
		token_type: tokens.token_type || "Bearer",
		scope: tokens.scope
	};
}
/**
* Detect if MCP OAuth authentication is specifically required for a tool
* Uses proper MCP OAuth specification discovery methods
*/
const detectAuthenticationRequired = async ({ serverUrl, error, logger }) => {
	try {
		const discoveryResult = await discoverMcpMetadata(serverUrl, logger);
		if (discoveryResult.success && discoveryResult.metadata) {
			logger?.info({ serverUrl }, "MCP OAuth support confirmed via metadata discovery");
			return true;
		}
	} catch (discoveryError) {
		logger?.debug({ discoveryError }, "MCP OAuth metadata discovery failed");
	}
	logger?.debug({ error: error?.message }, "No MCP OAuth authentication requirement detected");
	return false;
};

//#endregion
export { exchangeMcpAuthorizationCode as n, initiateMcpOAuthFlow as r, detectAuthenticationRequired as t };
//# sourceMappingURL=auth-detection.js.map