UNPKG

@civic/hub-bridge

Version:

Stdio <-> HTTP/SSE MCP bridge with Civic auth handling

98 lines 4.36 kB
import { AbstractHook } from "@civic/hook-common"; import { CallToolResultSchema, InitializeResultSchema, ListToolsResultSchema, ListResourcesResultSchema, ListResourceTemplatesResultSchema, ReadResourceResultSchema } from "@modelcontextprotocol/sdk/types.js"; import { CLIAuthProviderSingleton } from "../auth/cli-auth-provider-singleton.js"; export class HubAuthFailureInterceptor extends AbstractHook { transportInterface = null; constructor() { super(); } setTransportInterface(transportInterface) { this.transportInterface = transportInterface; } get name() { return "HubAuthFailureInterceptor"; } async handleAuthFailure(error, originalRequest, responseSchema) { console.error("Error in HubAuthFailureInterceptor:", JSON.stringify(error, null, 2)); if (!this.transportInterface) { return { resultType: "continue", }; } // Unauthorized error. Wait for authorization code and retry if (error.message.includes("Unauthorized")) { const authProvider = CLIAuthProviderSingleton.getInstance(); await authProvider.waitForAuthorizationCode(); const response = await this.transportInterface.request(originalRequest, responseSchema); return { resultType: "respond", response }; } // (Civic) Token refresh error: clear tokens and retry if (error.message.includes("grant request is invalid")) { const authProvider = CLIAuthProviderSingleton.getInstance(); // clear tokens await authProvider.clearTokens(); // retry request (triggers auth) let response; try { response = await this.transportInterface.request(originalRequest, responseSchema); } catch (e) { // Unauthorized error. Wait for authorization code and retry if (e instanceof Error && e.message.includes("Unauthorized")) { const authProvider = CLIAuthProviderSingleton.getInstance(); await authProvider.waitForAuthorizationCode(); // we don't catch this anymore response = await this.transportInterface.request(originalRequest, responseSchema); } else { // Re-throw non-Unauthorized errors throw e; } } if (response) { return { resultType: "respond", response }; } } return { resultType: "continue", }; } ; // eslint-disable-next-line @typescript-eslint/no-unused-vars async processCallToolError(error, originalCallToolRequest, _originalRequestExtra) { return this.handleAuthFailure(error, originalCallToolRequest, CallToolResultSchema); } ; // eslint-disable-next-line @typescript-eslint/no-unused-vars async processInitializeError(error, originalRequest, _originalRequestExtra) { return this.handleAuthFailure(error, originalRequest, InitializeResultSchema); } ; // eslint-disable-next-line @typescript-eslint/no-unused-vars async processListToolsError(error, originalRequest, _originalRequestExtra) { return this.handleAuthFailure(error, originalRequest, ListToolsResultSchema); } ; // eslint-disable-next-line @typescript-eslint/no-unused-vars async processListResourcesError(error, originalRequest, _originalRequestExtra) { return this.handleAuthFailure(error, originalRequest, ListResourcesResultSchema); } ; // eslint-disable-next-line @typescript-eslint/no-unused-vars async processListResourceTemplatesError(error, originalRequest, _originalRequestExtra) { return this.handleAuthFailure(error, originalRequest, ListResourceTemplatesResultSchema); } ; // eslint-disable-next-line @typescript-eslint/no-unused-vars async processReadResourceError(error, originalRequest, _originalRequestExtra) { return this.handleAuthFailure(error, originalRequest, ReadResourceResultSchema); } ; } //# sourceMappingURL=hub-auth-failure-interceptor.js.map