UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

110 lines (109 loc) 4.79 kB
import { m as requesterMcpOAuthIdentity } from "./mcp-oauth-store-rMpCI-eU.js"; import { s as readMcpOAuthCredentialsStatus, u as startMcpOAuthAuthorization } from "./mcp-oauth-bxRFfdN1.js"; import { n as resolveMcpTransportConfig } from "./mcp-transport-config-mph-T0Ys.js"; import { Type } from "typebox"; //#region src/agents/agent-bundle-mcp-requester-connect.ts async function connectRequesterOAuthServer(params) { if (!params.publicOrigin) { const message = `MCP server "${params.serverName}" needs requester sign-in, but gateway.publicOrigin is not configured. Ask the operator to set the public Gateway HTTP(S) origin.`; return { content: [{ type: "text", text: message }], details: { status: "error", error: message, mcpServer: params.serverName } }; } const result = await startMcpOAuthAuthorization(requesterMcpOAuthIdentity(params.serverName, params.server.url, params.requesterScope), params.server, { redirectUrl: new URL("/oauth/mcp/callback", params.publicOrigin).href }); if (result.status === "authorized") return { content: [{ type: "text", text: `MCP server "${params.serverName}" is connected. Its tools become available on the next message.` }], details: { mcpServer: params.serverName } }; return { content: [{ type: "text", text: `Connect MCP server "${params.serverName}" at ${result.authorizationUrl}\nAfter sign-in completes, the server's tools become available on the next message.` }], details: { mcpConnect: { serverName: params.serverName, authorizationUrl: result.authorizationUrl } } }; } function buildRequesterConnectCatalog(servers, safeServerNamesByServer) { const entries = [...servers.entries()]; return { version: 1, generatedAt: Date.now(), servers: Object.fromEntries(entries.map(([serverName]) => [serverName, { serverName, safeServerName: safeServerNamesByServer.get(serverName), launchSummary: "Requester OAuth", toolCount: 1 }])), tools: entries.map(([serverName]) => ({ serverName, safeServerName: safeServerNamesByServer.get(serverName) ?? serverName, toolName: "connect", description: `Connect your ${serverName} account.`, fallbackDescription: `Connect your ${serverName} account.`, inputSchema: Type.Object({}) })) }; } /** Builds the per-message requester sign-in surface without opening MCP transports. */ async function createRequesterMcpConnect(params) { const servers = /* @__PURE__ */ new Map(); const authorizedServerNames = []; for (const serverName of [...params.serverNames].toSorted((a, b) => a.localeCompare(b))) { const resolved = resolveMcpTransportConfig(serverName, params.mcpServers[serverName], { logWarnings: false }); if (resolved?.kind !== "http" || resolved.auth !== "oauth" || resolved.oauth?.identity !== "per-requester") continue; servers.set(serverName, resolved); if ((await readMcpOAuthCredentialsStatus(requesterMcpOAuthIdentity(serverName, resolved.url, params.requesterScope))).state === "authorized") authorizedServerNames.push(serverName); } if (servers.size === 0) return; const configFingerprint = JSON.stringify({ config: params.configFingerprint, authorizedServerNames, publicOrigin: params.cfg?.gateway?.publicOrigin }); return { catalog: buildRequesterConnectCatalog(servers, params.safeServerNamesByServer), authorizedServerNames, configFingerprint, createExecute(serverName) { const server = servers.get(serverName); return server ? async () => await connectRequesterOAuthServer({ serverName, server, requesterScope: params.requesterScope, publicOrigin: params.cfg?.gateway?.publicOrigin }) : void 0; } }; } /** Adds transient connect entries only for servers absent from the live catalog. */ function mergeMcpConnectCatalog(liveCatalog, requesterConnect) { const connectCatalog = requesterConnect?.catalog; if (!connectCatalog) return liveCatalog; const missingServerNames = new Set(Object.keys(connectCatalog.servers).filter((serverName) => !Object.hasOwn(liveCatalog.servers, serverName))); if (missingServerNames.size === 0) return liveCatalog; return { ...liveCatalog, generatedAt: Math.max(liveCatalog.generatedAt, connectCatalog.generatedAt), servers: { ...liveCatalog.servers, ...Object.fromEntries(Object.entries(connectCatalog.servers).filter(([serverName]) => missingServerNames.has(serverName))) }, tools: [...liveCatalog.tools, ...connectCatalog.tools.filter((tool) => missingServerNames.has(tool.serverName))].toSorted((left, right) => left.safeServerName.localeCompare(right.safeServerName) || left.toolName.localeCompare(right.toolName) || left.serverName.localeCompare(right.serverName)) }; } //#endregion export { mergeMcpConnectCatalog as n, createRequesterMcpConnect as t };