UNPKG

@cyanheads/pubmed-mcp-server

Version:

A Model Context Protocol (MCP) server enabling AI agents to intelligently search, retrieve, and analyze biomedical literature from PubMed via NCBI E-utilities. Built on the mcp-ts-template for robust, production-ready performance.

46 lines (45 loc) 2.49 kB
/** * @fileoverview Provides utility functions for authorization, specifically for * checking token scopes against required permissions for a given operation. * @module src/mcp-server/transports/auth/core/authUtils */ import { BaseErrorCode, McpError } from "../../../../types-global/errors.js"; import { logger, requestContextService } from "../../../../utils/index.js"; import { authContext } from "./authContext.js"; /** * Checks if the current authentication context contains all the specified scopes. * This function is designed to be called within tool or resource handlers to * enforce scope-based access control. It retrieves the authentication information * from `authContext` (AsyncLocalStorage). * * @param requiredScopes - An array of scope strings that are mandatory for the operation. * @throws {McpError} Throws an error with `BaseErrorCode.INTERNAL_ERROR` if the * authentication context is missing, which indicates a server configuration issue. * @throws {McpError} Throws an error with `BaseErrorCode.FORBIDDEN` if one or * more required scopes are not present in the validated token. */ export function withRequiredScopes(requiredScopes) { const store = authContext.getStore(); if (!store || !store.authInfo) { // This is a server-side logic error; the auth middleware should always populate this. throw new McpError(BaseErrorCode.INTERNAL_ERROR, "Authentication context is missing. This indicates a server configuration error.", requestContextService.createRequestContext({ operation: "withRequiredScopesCheck", error: "AuthStore not found in AsyncLocalStorage.", })); } const { scopes: grantedScopes, clientId } = store.authInfo; const grantedScopeSet = new Set(grantedScopes); const missingScopes = requiredScopes.filter((scope) => !grantedScopeSet.has(scope)); if (missingScopes.length > 0) { const context = requestContextService.createRequestContext({ operation: "withRequiredScopesCheck", required: requiredScopes, granted: grantedScopes, missing: missingScopes, clientId: clientId, subject: store.authInfo.subject, }); logger.warning("Authorization failed: Missing required scopes.", context); throw new McpError(BaseErrorCode.FORBIDDEN, `Insufficient permissions. Missing required scopes: ${missingScopes.join(", ")}`, { requiredScopes, missingScopes }); } }