noumen 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +767 -51
- package/dist/a2a/index.d.ts +148 -0
- package/dist/a2a/index.js +579 -0
- package/dist/a2a/index.js.map +1 -0
- package/dist/acp/index.d.ts +129 -0
- package/dist/acp/index.js +498 -0
- package/dist/acp/index.js.map +1 -0
- package/dist/agent-BrkbZyOT.d.ts +1028 -0
- package/dist/cache-DVqaCX8v.d.ts +38 -0
- package/dist/chunk-2ZTGQLYK.js +356 -0
- package/dist/chunk-2ZTGQLYK.js.map +1 -0
- package/dist/chunk-42PHHZUA.js +132 -0
- package/dist/chunk-42PHHZUA.js.map +1 -0
- package/dist/chunk-4SQA2UCV.js +26 -0
- package/dist/chunk-4SQA2UCV.js.map +1 -0
- package/dist/chunk-5GEX6ZSB.js +179 -0
- package/dist/chunk-5GEX6ZSB.js.map +1 -0
- package/dist/chunk-7ZMN7XJE.js +94 -0
- package/dist/chunk-7ZMN7XJE.js.map +1 -0
- package/dist/chunk-AMYIJSAZ.js +57 -0
- package/dist/chunk-AMYIJSAZ.js.map +1 -0
- package/dist/chunk-BGG2E6JD.js +10 -0
- package/dist/chunk-BGG2E6JD.js.map +1 -0
- package/dist/chunk-BZSFUEWM.js +43 -0
- package/dist/chunk-BZSFUEWM.js.map +1 -0
- package/dist/chunk-CPFHEPW4.js +139 -0
- package/dist/chunk-CPFHEPW4.js.map +1 -0
- package/dist/chunk-D43BWEZA.js +346 -0
- package/dist/chunk-D43BWEZA.js.map +1 -0
- package/dist/chunk-DGUM43GV.js +11 -0
- package/dist/chunk-DGUM43GV.js.map +1 -0
- package/dist/chunk-JACGEMTF.js +43 -0
- package/dist/chunk-JACGEMTF.js.map +1 -0
- package/dist/chunk-JX7CLUCV.js +21 -0
- package/dist/chunk-JX7CLUCV.js.map +1 -0
- package/dist/chunk-KXDB56YW.js +39 -0
- package/dist/chunk-KXDB56YW.js.map +1 -0
- package/dist/chunk-KY6ZPWHO.js +112 -0
- package/dist/chunk-KY6ZPWHO.js.map +1 -0
- package/dist/chunk-NBDFQYUZ.js +7992 -0
- package/dist/chunk-NBDFQYUZ.js.map +1 -0
- package/dist/chunk-OGXNFXFA.js +196 -0
- package/dist/chunk-OGXNFXFA.js.map +1 -0
- package/dist/chunk-QTJ7VTJY.js +1994 -0
- package/dist/chunk-QTJ7VTJY.js.map +1 -0
- package/dist/chunk-UVSSQBDY.js +192 -0
- package/dist/chunk-UVSSQBDY.js.map +1 -0
- package/dist/chunk-Y45R3PQL.js +684 -0
- package/dist/chunk-Y45R3PQL.js.map +1 -0
- package/dist/cli/index.d.ts +1 -0
- package/dist/cli/index.js +868 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/client/index.d.ts +64 -0
- package/dist/client/index.js +409 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client-CRRO2376.js +10 -0
- package/dist/client-CRRO2376.js.map +1 -0
- package/dist/headless-Q7XHHZIW.js +143 -0
- package/dist/headless-Q7XHHZIW.js.map +1 -0
- package/dist/history-snip-64GYP4ZL.js +12 -0
- package/dist/history-snip-64GYP4ZL.js.map +1 -0
- package/dist/index.d.ts +1305 -418
- package/dist/index.js +384 -1757
- package/dist/index.js.map +1 -1
- package/dist/jsonrpc/index.d.ts +54 -0
- package/dist/jsonrpc/index.js +34 -0
- package/dist/jsonrpc/index.js.map +1 -0
- package/dist/lsp/index.d.ts +36 -0
- package/dist/lsp/index.js +16 -0
- package/dist/lsp/index.js.map +1 -0
- package/dist/lsp-PS3BWIHC.js +8 -0
- package/dist/lsp-PS3BWIHC.js.map +1 -0
- package/dist/manager-DLXK63XC.js +8 -0
- package/dist/manager-DLXK63XC.js.map +1 -0
- package/dist/mcp/index.d.ts +111 -0
- package/dist/mcp/index.js +104 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp-auth-AEI2R4ZC.js +9 -0
- package/dist/mcp-auth-AEI2R4ZC.js.map +1 -0
- package/dist/ollama-YNXAYP3R.js +18 -0
- package/dist/ollama-YNXAYP3R.js.map +1 -0
- package/dist/provider-factory-34MSWJZ3.js +20 -0
- package/dist/provider-factory-34MSWJZ3.js.map +1 -0
- package/dist/providers/anthropic.d.ts +19 -0
- package/dist/providers/anthropic.js +33 -0
- package/dist/providers/anthropic.js.map +1 -0
- package/dist/providers/bedrock.d.ts +39 -0
- package/dist/providers/bedrock.js +54 -0
- package/dist/providers/bedrock.js.map +1 -0
- package/dist/providers/gemini.d.ts +16 -0
- package/dist/providers/gemini.js +224 -0
- package/dist/providers/gemini.js.map +1 -0
- package/dist/providers/openai.d.ts +18 -0
- package/dist/providers/openai.js +8 -0
- package/dist/providers/openai.js.map +1 -0
- package/dist/providers/openrouter.d.ts +16 -0
- package/dist/providers/openrouter.js +23 -0
- package/dist/providers/openrouter.js.map +1 -0
- package/dist/providers/vertex.d.ts +40 -0
- package/dist/providers/vertex.js +64 -0
- package/dist/providers/vertex.js.map +1 -0
- package/dist/render-GRN4ZSSW.js +14 -0
- package/dist/render-GRN4ZSSW.js.map +1 -0
- package/dist/resolve-XM52G7YE.js +14 -0
- package/dist/resolve-XM52G7YE.js.map +1 -0
- package/dist/server/index.d.ts +128 -0
- package/dist/server/index.js +626 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server-Cg1yWGaV.d.ts +96 -0
- package/dist/spinner-OJNR6NFO.js +8 -0
- package/dist/spinner-OJNR6NFO.js.map +1 -0
- package/dist/types-2kTLUCnD.d.ts +107 -0
- package/dist/types-3c88cRKH.d.ts +547 -0
- package/dist/types-CwKKucOF.d.ts +620 -0
- package/dist/types-DwdzmXfs.d.ts +107 -0
- package/dist/types-NIyVwQ4h.d.ts +109 -0
- package/dist/types-QwfylltH.d.ts +71 -0
- package/package.json +134 -6
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/mcp/client.ts","../src/mcp/auth/provider.ts","../src/mcp/auth/callback-server.ts","../src/mcp/auth/storage.ts"],"sourcesContent":["import { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport { StdioClientTransport } from \"@modelcontextprotocol/sdk/client/stdio.js\";\nimport { StreamableHTTPClientTransport } from \"@modelcontextprotocol/sdk/client/streamableHttp.js\";\nimport { SSEClientTransport } from \"@modelcontextprotocol/sdk/client/sse.js\";\nimport { WebSocketClientTransport } from \"@modelcontextprotocol/sdk/client/websocket.js\";\nimport { UnauthorizedError } from \"@modelcontextprotocol/sdk/client/auth.js\";\nimport type { OAuthClientProvider } from \"@modelcontextprotocol/sdk/client/auth.js\";\nimport type { Tool as McpSdkTool } from \"@modelcontextprotocol/sdk/types.js\";\nimport type { Tool, ToolResult } from \"../tools/types.js\";\nimport type { ContentPart } from \"../session/types.js\";\nimport { maybeResizeAndDownsampleImageBuffer } from \"../utils/image-resizer.js\";\nimport type {\n McpServerConfig,\n McpHttpServerConfig,\n McpSseServerConfig,\n McpConnection,\n McpToolInfo,\n} from \"./types.js\";\nimport type { TokenStorage, McpOAuthConfig } from \"./auth/types.js\";\nimport { NoumenOAuthProvider } from \"./auth/provider.js\";\nimport { findAvailablePort } from \"./auth/callback-server.js\";\nimport { InMemoryTokenStorage } from \"./auth/storage.js\";\nimport { buildMcpToolName } from \"./normalization.js\";\n\nconst DEFAULT_TOOL_TIMEOUT_MS = 60_000;\nconst MAX_TEXT_RESULT_BYTES = 1_024 * 1_024; // 1 MB\n\nexport interface McpClientManagerOptions {\n /**\n * Default token storage used for servers that declare `oauth` config\n * but no custom `authProvider`. Falls back to InMemoryTokenStorage.\n */\n tokenStorage?: TokenStorage;\n /**\n * Called when a server requires interactive OAuth and the user must\n * visit an authorization URL. Passed through to NoumenOAuthProvider.\n */\n onAuthorizationUrl?: (url: string) => void | Promise<void>;\n}\n\nexport class McpClientManager {\n private connections: Map<string, McpConnection> = new Map();\n private serverConfigs: Record<string, McpServerConfig>;\n private tokenStorage: TokenStorage;\n private onAuthorizationUrl?: (url: string) => void | Promise<void>;\n\n constructor(\n mcpServers: Record<string, McpServerConfig>,\n options?: McpClientManagerOptions,\n ) {\n this.serverConfigs = mcpServers;\n this.tokenStorage = options?.tokenStorage ?? new InMemoryTokenStorage();\n this.onAuthorizationUrl = options?.onAuthorizationUrl;\n }\n\n async connect(): Promise<void> {\n const entries = Object.entries(this.serverConfigs);\n const results = await Promise.allSettled(\n entries.map(([name, config]) => this.connectToServer(name, config)),\n );\n\n for (let i = 0; i < results.length; i++) {\n const result = results[i];\n const name = entries[i][0];\n if (result.status === \"rejected\") {\n this.connections.set(name, {\n name,\n client: null,\n status: \"failed\",\n config: entries[i][1],\n cleanup: async () => {},\n });\n }\n }\n }\n\n private async connectToServer(\n name: string,\n config: McpServerConfig,\n ): Promise<void> {\n const client = new Client({ name: `noumen-${name}`, version: \"0.1.0\" });\n let transport: StdioClientTransport | StreamableHTTPClientTransport | SSEClientTransport | WebSocketClientTransport;\n let cleanup: () => Promise<void>;\n\n const configType = \"type\" in config ? config.type : \"stdio\";\n\n switch (configType) {\n case \"http\": {\n const httpConfig = config as McpHttpServerConfig;\n const url = new URL(httpConfig.url);\n const authProvider = await this.resolveAuthProvider(name, httpConfig);\n transport = new StreamableHTTPClientTransport(url, {\n authProvider: authProvider ?? undefined,\n requestInit: httpConfig.headers\n ? { headers: httpConfig.headers }\n : undefined,\n });\n cleanup = async () => { await transport.close(); };\n break;\n }\n\n case \"sse\": {\n const sseConfig = config as McpSseServerConfig;\n const url = new URL(sseConfig.url);\n const authProvider = await this.resolveAuthProvider(name, sseConfig);\n transport = new SSEClientTransport(url, {\n authProvider: authProvider ?? undefined,\n requestInit: sseConfig.headers\n ? { headers: sseConfig.headers }\n : undefined,\n });\n cleanup = async () => { await transport.close(); };\n break;\n }\n\n case \"websocket\": {\n const wsConfig = config as { url: string };\n const url = new URL(wsConfig.url);\n transport = new WebSocketClientTransport(url);\n cleanup = async () => { await transport.close(); };\n break;\n }\n\n default: {\n const stdioConfig = config as {\n command: string;\n args?: string[];\n env?: Record<string, string>;\n };\n transport = new StdioClientTransport({\n command: stdioConfig.command,\n args: stdioConfig.args,\n env: stdioConfig.env\n ? ({ ...process.env, ...stdioConfig.env } as Record<string, string>)\n : undefined,\n });\n cleanup = async () => { await transport.close(); };\n break;\n }\n }\n\n try {\n await client.connect(transport);\n } catch (err) {\n if (err instanceof UnauthorizedError) {\n this.connections.set(name, {\n name,\n client,\n status: \"needs-auth\",\n config,\n cleanup,\n });\n return;\n }\n throw err;\n }\n\n this.connections.set(name, {\n name,\n client,\n status: \"connected\",\n config,\n cleanup,\n });\n }\n\n /**\n * Resolve an OAuthClientProvider for an HTTP or SSE server config.\n * Returns null if the server doesn't require authentication.\n */\n private async resolveAuthProvider(\n serverName: string,\n config: McpHttpServerConfig | McpSseServerConfig,\n ): Promise<OAuthClientProvider | null> {\n if (config.authProvider) return config.authProvider;\n if (!config.oauth) return null;\n\n const oauth = config.oauth;\n const serverKey = `${serverName}|${config.url}`;\n const port = await findAvailablePort(oauth.callbackPort);\n\n return new NoumenOAuthProvider(serverKey, {\n storage: this.tokenStorage,\n clientId: oauth.clientId,\n clientSecret: oauth.clientSecret,\n callbackPort: port,\n onAuthorizationUrl: this.onAuthorizationUrl,\n clientMetadata: {\n redirect_uris: [`http://localhost:${port}/callback`],\n client_name: `noumen-${serverName}`,\n grant_types: [\"authorization_code\", \"refresh_token\"],\n response_types: [\"code\"],\n scope: oauth.scopes,\n },\n });\n }\n\n async getTools(): Promise<Tool[]> {\n const tools: Tool[] = [];\n\n for (const [serverName, conn] of this.connections) {\n if (conn.status !== \"connected\" || !conn.client) continue;\n\n try {\n const result = await conn.client.listTools();\n for (const mcpTool of result.tools) {\n tools.push(this.mapMcpTool(serverName, mcpTool));\n }\n } catch {\n // Server failed to list tools; skip it\n }\n }\n\n return tools;\n }\n\n private mapMcpTool(serverName: string, mcpTool: McpSdkTool): Tool {\n const qualifiedName = buildMcpToolName(serverName, mcpTool.name);\n\n const parameters = (mcpTool.inputSchema ?? {\n type: \"object\" as const,\n properties: {},\n }) as Tool[\"parameters\"];\n\n const mcpInfo: McpToolInfo = {\n serverName,\n toolName: mcpTool.name,\n };\n\n return {\n name: qualifiedName,\n description: mcpTool.description ?? \"\",\n parameters,\n mcpInfo,\n call: async (args: Record<string, unknown>): Promise<ToolResult> => {\n return this.callTool(serverName, mcpTool.name, args);\n },\n };\n }\n\n async callTool(\n serverName: string,\n toolName: string,\n args: Record<string, unknown>,\n options?: { timeoutMs?: number },\n ): Promise<ToolResult> {\n const conn = this.connections.get(serverName);\n if (!conn || conn.status !== \"connected\" || !conn.client) {\n return {\n content: `MCP server \"${serverName}\" is not connected`,\n isError: true,\n };\n }\n\n try {\n const timeoutMs = options?.timeoutMs ?? DEFAULT_TOOL_TIMEOUT_MS;\n const abortController = new AbortController();\n const timer = setTimeout(() => abortController.abort(), timeoutMs);\n\n let result: Awaited<ReturnType<Client[\"callTool\"]>>;\n try {\n result = await conn.client.callTool(\n { name: toolName, arguments: args },\n undefined,\n { signal: abortController.signal },\n );\n } finally {\n clearTimeout(timer);\n }\n\n const contentBlocks = result.content as Array<{\n type: string;\n text?: string;\n data?: string;\n mimeType?: string;\n blob?: string;\n }> | undefined;\n\n if (!contentBlocks) {\n return { content: JSON.stringify(result), isError: result.isError === true };\n }\n\n const parts: ContentPart[] = [];\n for (const block of contentBlocks) {\n if (block.type === \"text\") {\n parts.push({ type: \"text\", text: block.text ?? \"\" });\n } else if (block.type === \"image\" && block.data) {\n const imageBuffer = Buffer.from(block.data, \"base64\");\n const ext = block.mimeType?.split(\"/\")[1] || \"png\";\n try {\n const resized = await maybeResizeAndDownsampleImageBuffer(\n imageBuffer,\n imageBuffer.length,\n ext,\n );\n parts.push({\n type: \"image\",\n data: resized.buffer.toString(\"base64\"),\n media_type: `image/${resized.mediaType}`,\n });\n } catch {\n parts.push({\n type: \"image\",\n data: block.data,\n media_type: block.mimeType ?? \"image/png\",\n });\n }\n } else if (block.type === \"resource\" && block.blob) {\n const isImage = block.mimeType?.startsWith(\"image/\") ?? false;\n if (isImage) {\n const imageBuffer = Buffer.from(block.blob, \"base64\");\n const ext = block.mimeType?.split(\"/\")[1] || \"png\";\n try {\n const resized = await maybeResizeAndDownsampleImageBuffer(\n imageBuffer,\n imageBuffer.length,\n ext,\n );\n parts.push({\n type: \"image\",\n data: resized.buffer.toString(\"base64\"),\n media_type: `image/${resized.mediaType}`,\n });\n } catch {\n parts.push({\n type: \"image\",\n data: block.blob,\n media_type: block.mimeType ?? \"image/png\",\n });\n }\n } else {\n parts.push({ type: \"text\", text: JSON.stringify(block) });\n }\n } else {\n parts.push({ type: \"text\", text: JSON.stringify(block) });\n }\n }\n\n // If all parts are text, flatten to a single string for simpler downstream handling\n if (parts.every((p) => p.type === \"text\")) {\n let text = parts\n .map((p) => (p as { text: string }).text)\n .join(\"\\n\");\n if (Buffer.byteLength(text, \"utf-8\") > MAX_TEXT_RESULT_BYTES) {\n text = text.slice(0, MAX_TEXT_RESULT_BYTES) + \"\\n...[output truncated]\";\n }\n return { content: text, isError: result.isError === true };\n }\n\n return { content: parts, isError: result.isError === true };\n } catch (err) {\n const isAbort =\n err instanceof DOMException && err.name === \"AbortError\";\n const message = isAbort\n ? `MCP tool \"${toolName}\" on server \"${serverName}\" timed out`\n : err instanceof Error ? err.message : String(err);\n return { content: message, isError: true };\n }\n }\n\n getConnectionStatus(): Array<{\n name: string;\n status: string;\n toolCount?: number;\n }> {\n return Array.from(this.connections.values()).map((c) => ({\n name: c.name,\n status: c.status,\n }));\n }\n\n /**\n * Returns server names that are in `needs-auth` status and require\n * interactive OAuth before they can be used.\n */\n getServersNeedingAuth(): string[] {\n return Array.from(this.connections.entries())\n .filter(([, conn]) => conn.status === \"needs-auth\")\n .map(([name]) => name);\n }\n\n /**\n * Reconnect a server by closing its existing connection and\n * establishing a new one. Useful after completing OAuth.\n */\n async reconnect(serverName: string): Promise<void> {\n const conn = this.connections.get(serverName);\n if (conn) {\n await conn.cleanup().catch(() => {});\n this.connections.delete(serverName);\n }\n\n const config = this.serverConfigs[serverName];\n if (!config) return;\n\n try {\n await this.connectToServer(serverName, config);\n } catch {\n this.connections.set(serverName, {\n name: serverName,\n client: null,\n status: \"failed\",\n config,\n cleanup: async () => {},\n });\n }\n }\n\n /**\n * Trigger interactive OAuth for a `needs-auth` server, then reconnect.\n * Runs the full MCP SDK auth orchestrator with a local callback server.\n *\n * Returns the authorization URL if the flow requires user interaction,\n * or null if the server connected without browser auth (e.g. cached tokens).\n */\n async performAuth(\n serverName: string,\n options?: { signal?: AbortSignal },\n ): Promise<{ authUrl?: string }> {\n const config = this.serverConfigs[serverName];\n if (!config) {\n throw new Error(`Unknown MCP server: ${serverName}`);\n }\n\n const configType = \"type\" in config ? config.type : \"stdio\";\n if (configType !== \"http\" && configType !== \"sse\") {\n throw new Error(\n `OAuth is only supported for HTTP and SSE transports, got: ${configType}`,\n );\n }\n\n const httpConfig = config as McpHttpServerConfig | McpSseServerConfig;\n if (!httpConfig.oauth && !httpConfig.authProvider) {\n throw new Error(\n `Server \"${serverName}\" has no OAuth configuration`,\n );\n }\n\n let capturedAuthUrl: string | undefined;\n const originalCallback = this.onAuthorizationUrl;\n\n this.onAuthorizationUrl = async (url: string) => {\n capturedAuthUrl = url;\n if (originalCallback) await originalCallback(url);\n };\n\n try {\n await this.reconnect(serverName);\n } finally {\n this.onAuthorizationUrl = originalCallback;\n }\n\n return { authUrl: capturedAuthUrl };\n }\n\n async close(): Promise<void> {\n const cleanups = Array.from(this.connections.values()).map((c) =>\n c.cleanup().catch(() => {}),\n );\n await Promise.all(cleanups);\n this.connections.clear();\n }\n}\n","import { randomBytes } from \"node:crypto\";\nimport { exec } from \"node:child_process\";\nimport type {\n OAuthClientProvider,\n OAuthDiscoveryState,\n} from \"@modelcontextprotocol/sdk/client/auth.js\";\nimport type {\n OAuthTokens,\n OAuthClientMetadata,\n OAuthClientInformationMixed,\n} from \"@modelcontextprotocol/sdk/shared/auth.js\";\nimport type { TokenStorage, OAuthProviderOptions } from \"./types.js\";\n\n/**\n * OAuthClientProvider implementation backed by noumen's pluggable\n * TokenStorage. Handles all persistence (tokens, client info, PKCE\n * verifiers, discovery state) through the storage interface and\n * delegates browser/UI concerns to configurable callbacks.\n */\nexport class NoumenOAuthProvider implements OAuthClientProvider {\n private serverKey: string;\n private storage: TokenStorage;\n private _clientMetadata: OAuthClientMetadata;\n private _callbackPort: number;\n private _onAuthorizationUrl?: (url: string) => void | Promise<void>;\n private _signal?: AbortSignal;\n private _preRegisteredClientId?: string;\n private _preRegisteredClientSecret?: string;\n private _state: string | null = null;\n\n constructor(serverKey: string, options: OAuthProviderOptions) {\n this.serverKey = serverKey;\n this.storage = options.storage;\n this._clientMetadata = options.clientMetadata;\n this._callbackPort = options.callbackPort ?? 3118;\n this._onAuthorizationUrl = options.onAuthorizationUrl;\n this._signal = options.signal;\n this._preRegisteredClientId = options.clientId;\n this._preRegisteredClientSecret = options.clientSecret;\n }\n\n get redirectUrl(): string {\n return `http://localhost:${this._callbackPort}/callback`;\n }\n\n get clientMetadata(): OAuthClientMetadata {\n return this._clientMetadata;\n }\n\n async state(): Promise<string> {\n if (!this._state) {\n this._state = randomBytes(32).toString(\"base64url\");\n }\n return this._state;\n }\n\n async clientInformation(): Promise<OAuthClientInformationMixed | undefined> {\n if (this._preRegisteredClientId) {\n const info: OAuthClientInformationMixed = {\n client_id: this._preRegisteredClientId,\n };\n if (this._preRegisteredClientSecret) {\n (info as Record<string, unknown>).client_secret =\n this._preRegisteredClientSecret;\n }\n return info;\n }\n\n const data = await this.storage.load(this.serverKey);\n return data?.clientInformation;\n }\n\n async saveClientInformation(\n clientInformation: OAuthClientInformationMixed,\n ): Promise<void> {\n const data = (await this.storage.load(this.serverKey)) ?? {};\n data.clientInformation = clientInformation;\n await this.storage.save(this.serverKey, data);\n }\n\n async tokens(): Promise<OAuthTokens | undefined> {\n const data = await this.storage.load(this.serverKey);\n if (!data?.tokens) return undefined;\n\n const REFRESH_BUFFER_MS = 5 * 60 * 1000;\n if (\n data.expiresAt &&\n data.tokens.refresh_token &&\n Date.now() >= data.expiresAt - REFRESH_BUFFER_MS\n ) {\n return undefined;\n }\n return data.tokens;\n }\n\n async saveTokens(tokens: OAuthTokens): Promise<void> {\n const data = (await this.storage.load(this.serverKey)) ?? {};\n data.tokens = tokens;\n if (tokens.expires_in != null) {\n data.expiresAt = Date.now() + tokens.expires_in * 1000;\n }\n await this.storage.save(this.serverKey, data);\n }\n\n async redirectToAuthorization(authorizationUrl: URL): Promise<void> {\n const urlStr = authorizationUrl.toString();\n\n if (this._onAuthorizationUrl) {\n await this._onAuthorizationUrl(urlStr);\n return;\n }\n\n openBrowser(urlStr);\n }\n\n async saveCodeVerifier(codeVerifier: string): Promise<void> {\n const data = (await this.storage.load(this.serverKey)) ?? {};\n data.codeVerifier = codeVerifier;\n await this.storage.save(this.serverKey, data);\n }\n\n async codeVerifier(): Promise<string> {\n const data = await this.storage.load(this.serverKey);\n return data?.codeVerifier ?? \"\";\n }\n\n async invalidateCredentials(\n scope: \"all\" | \"client\" | \"tokens\" | \"verifier\" | \"discovery\",\n ): Promise<void> {\n if (scope === \"all\") {\n this._state = null;\n await this.storage.delete(this.serverKey);\n return;\n }\n\n const data = await this.storage.load(this.serverKey);\n if (!data) return;\n\n switch (scope) {\n case \"client\":\n delete data.clientInformation;\n break;\n case \"tokens\":\n delete data.tokens;\n delete data.expiresAt;\n break;\n case \"verifier\":\n delete data.codeVerifier;\n break;\n case \"discovery\":\n delete data.discoveryState;\n break;\n }\n await this.storage.save(this.serverKey, data);\n }\n\n async saveDiscoveryState(state: OAuthDiscoveryState): Promise<void> {\n const data = (await this.storage.load(this.serverKey)) ?? {};\n data.discoveryState = state;\n await this.storage.save(this.serverKey, data);\n }\n\n async discoveryState(): Promise<OAuthDiscoveryState | undefined> {\n const data = await this.storage.load(this.serverKey);\n return data?.discoveryState;\n }\n}\n\nfunction openBrowser(url: string): void {\n const platform = process.platform;\n const cmd =\n platform === \"darwin\"\n ? \"open\"\n : platform === \"win32\"\n ? \"start\"\n : \"xdg-open\";\n exec(`${cmd} ${JSON.stringify(url)}`);\n}\n","import * as http from \"node:http\";\n\nconst DEFAULT_FALLBACK_PORT = 3118;\nconst EPHEMERAL_PORT_MIN = 49152;\nconst EPHEMERAL_PORT_MAX = 65535;\nconst MAX_PORT_ATTEMPTS = 50;\nconst CALLBACK_TIMEOUT_MS = 5 * 60 * 1000;\n\n/**\n * Find an available local port for the OAuth callback server.\n * Tries the preferred port first, then random ephemeral ports.\n */\nexport async function findAvailablePort(preferred?: number): Promise<number> {\n if (preferred != null) {\n const ok = await isPortAvailable(preferred);\n if (ok) return preferred;\n }\n\n for (let i = 0; i < MAX_PORT_ATTEMPTS; i++) {\n const port =\n EPHEMERAL_PORT_MIN +\n Math.floor(Math.random() * (EPHEMERAL_PORT_MAX - EPHEMERAL_PORT_MIN + 1));\n const ok = await isPortAvailable(port);\n if (ok) return port;\n }\n\n return DEFAULT_FALLBACK_PORT;\n}\n\nfunction isPortAvailable(port: number): Promise<boolean> {\n return new Promise((resolve) => {\n const server = http.createServer();\n server.once(\"error\", () => resolve(false));\n server.listen(port, \"127.0.0.1\", () => {\n server.close(() => resolve(true));\n });\n });\n}\n\nexport interface OAuthCallbackResult {\n code: string;\n state?: string;\n}\n\n/**\n * Lightweight HTTP server on localhost that receives the OAuth redirect\n * callback. Validates the state parameter when expected and resolves\n * with the authorization code.\n */\nexport class OAuthCallbackServer {\n private server: http.Server | null = null;\n private port = 0;\n\n /**\n * Start listening on a local port and return a promise that resolves\n * when the authorization callback is received.\n */\n async start(options?: {\n expectedState?: string;\n callbackPort?: number;\n signal?: AbortSignal;\n }): Promise<{\n port: number;\n redirectUri: string;\n waitForCallback: () => Promise<OAuthCallbackResult>;\n }> {\n const port = await findAvailablePort(options?.callbackPort);\n this.port = port;\n const redirectUri = `http://localhost:${port}/callback`;\n\n const callbackPromise = new Promise<OAuthCallbackResult>(\n (resolve, reject) => {\n const server = http.createServer((req, res) => {\n if (!req.url?.startsWith(\"/callback\")) {\n res.writeHead(404);\n res.end(\"Not found\");\n return;\n }\n\n const parsed = new URL(req.url, `http://localhost:${port}`);\n const code = parsed.searchParams.get(\"code\") ?? undefined;\n const state = parsed.searchParams.get(\"state\") ?? undefined;\n const error = parsed.searchParams.get(\"error\") ?? undefined;\n const errorDescription = parsed.searchParams.get(\"error_description\") ?? undefined;\n\n if (error) {\n res.writeHead(400, { \"Content-Type\": \"text/html\" });\n res.end(\n `<html><body><h1>Authorization Error</h1><p>${escapeHtml(error)}: ${escapeHtml(errorDescription ?? \"\")}</p></body></html>`,\n );\n cleanup();\n reject(new Error(`OAuth error: ${error} - ${errorDescription ?? \"\"}`));\n return;\n }\n\n if (!code) {\n res.writeHead(400, { \"Content-Type\": \"text/html\" });\n res.end(\n \"<html><body><h1>Error</h1><p>Missing authorization code.</p></body></html>\",\n );\n cleanup();\n reject(new Error(\"Missing authorization code in callback\"));\n return;\n }\n\n if (options?.expectedState && state !== options.expectedState) {\n res.writeHead(400, { \"Content-Type\": \"text/html\" });\n res.end(\n \"<html><body><h1>Error</h1><p>State parameter mismatch.</p></body></html>\",\n );\n cleanup();\n reject(new Error(\"OAuth state mismatch\"));\n return;\n }\n\n res.writeHead(200, { \"Content-Type\": \"text/html\" });\n res.end(\n \"<html><body><h1>Authorization Successful</h1><p>You can close this window.</p></body></html>\",\n );\n cleanup();\n resolve({ code, state });\n });\n\n this.server = server;\n\n const timeout = setTimeout(() => {\n cleanup();\n reject(new Error(\"OAuth callback timeout\"));\n }, CALLBACK_TIMEOUT_MS);\n\n const cleanup = () => {\n clearTimeout(timeout);\n this.close();\n };\n\n if (options?.signal) {\n if (options.signal.aborted) {\n cleanup();\n reject(new Error(\"OAuth callback aborted\"));\n return;\n }\n options.signal.addEventListener(\n \"abort\",\n () => {\n cleanup();\n reject(new Error(\"OAuth callback aborted\"));\n },\n { once: true },\n );\n }\n\n server.listen(port, \"127.0.0.1\");\n server.unref();\n },\n );\n\n return { port, redirectUri, waitForCallback: () => callbackPromise };\n }\n\n close(): void {\n if (this.server) {\n try {\n this.server.close();\n } catch {\n // already closed\n }\n this.server = null;\n }\n }\n}\n\nfunction escapeHtml(s: string): string {\n return s\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\");\n}\n","import * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\nimport type { TokenStorage, OAuthTokenData } from \"./types.js\";\n\n/**\n * In-memory token storage. Suitable for tests, short-lived processes,\n * and situations where persistence across restarts is not needed.\n */\nexport class InMemoryTokenStorage implements TokenStorage {\n private store = new Map<string, OAuthTokenData>();\n\n async load(serverKey: string): Promise<OAuthTokenData | undefined> {\n return this.store.get(serverKey);\n }\n\n async save(serverKey: string, data: OAuthTokenData): Promise<void> {\n this.store.set(serverKey, data);\n }\n\n async delete(serverKey: string): Promise<void> {\n this.store.delete(serverKey);\n }\n}\n\n/**\n * File-backed token storage. Persists all server tokens to a single JSON\n * file so they survive process restarts. Each server key maps to its own\n * entry in the file.\n */\nexport class FileTokenStorage implements TokenStorage {\n private filePath: string;\n\n constructor(filePath?: string) {\n this.filePath =\n filePath ??\n path.join(\n process.env.HOME ?? process.env.USERPROFILE ?? \".\",\n \".noumen\",\n \"mcp-oauth-tokens.json\",\n );\n }\n\n async load(serverKey: string): Promise<OAuthTokenData | undefined> {\n const all = await this.readAll();\n return all[serverKey];\n }\n\n async save(serverKey: string, data: OAuthTokenData): Promise<void> {\n const all = await this.readAll();\n all[serverKey] = data;\n await this.writeAll(all);\n }\n\n async delete(serverKey: string): Promise<void> {\n const all = await this.readAll();\n delete all[serverKey];\n await this.writeAll(all);\n }\n\n private async readAll(): Promise<Record<string, OAuthTokenData>> {\n try {\n const raw = await fs.readFile(this.filePath, \"utf-8\");\n return JSON.parse(raw) as Record<string, OAuthTokenData>;\n } catch {\n return {};\n }\n }\n\n private async writeAll(data: Record<string, OAuthTokenData>): Promise<void> {\n await fs.mkdir(path.dirname(this.filePath), { recursive: true });\n await fs.writeFile(this.filePath, JSON.stringify(data, null, 2), \"utf-8\");\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#!/usr/bin/env node
|