UNPKG

@toolbox-sdk/core

Version:
194 lines 8.75 kB
// Copyright 2026 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); }; var _McpHttpTransportV20250326_instances, _McpHttpTransportV20250326_sendRequest; import { AxiosError } from 'axios'; import { McpHttpTransportBase } from '../transportBase.js'; import * as types from './types.js'; import { logApiError, ProtocolNegotiationError } from '../../errorUtils.js'; import { warnIfHttpAndHeaders } from '../../utils.js'; import { v4 as uuidv4 } from 'uuid'; import { VERSION } from '../../version.js'; export class McpHttpTransportV20250326 extends McpHttpTransportBase { constructor() { super(...arguments); _McpHttpTransportV20250326_instances.add(this); this._sessionId = null; } async initializeSession(headers) { const params = { protocolVersion: this._protocolVersion, capabilities: {}, clientInfo: { name: this._clientName || 'toolbox-core-js', version: this._clientVersion || VERSION, }, }; const result = await __classPrivateFieldGet(this, _McpHttpTransportV20250326_instances, "m", _McpHttpTransportV20250326_sendRequest).call(this, this._mcpBaseUrl, types.InitializeRequest, params, headers); if (!result) { const error = new Error('Initialization failed: No response'); logApiError('MCP Initialization Error', error); throw error; } this._serverVersion = result.serverInfo.version; if (result.protocolVersion !== this._protocolVersion) { throw new ProtocolNegotiationError(result.protocolVersion); } if (!result.capabilities.tools) { const error = new Error("Server does not support the 'tools' capability."); logApiError('MCP Initialization Error', error); throw error; } // Extract session ID from extra fields (v2025-03-26 specific) // Session ID is captured from headers in #sendRequest if (!this._sessionId) { const error = new Error('Server did not return a Mcp-Session-Id during initialization.'); logApiError('MCP Initialization Error', error); throw error; } await __classPrivateFieldGet(this, _McpHttpTransportV20250326_instances, "m", _McpHttpTransportV20250326_sendRequest).call(this, this._mcpBaseUrl, types.InitializedNotification, {}, headers); } async toolsList(toolsetName, headers) { await this.ensureInitialized(headers); const url = this.appendToolsetPath(toolsetName); const result = await __classPrivateFieldGet(this, _McpHttpTransportV20250326_instances, "m", _McpHttpTransportV20250326_sendRequest).call(this, url, types.ListToolsRequest, {}, headers); if (!result) { const error = new Error('Failed to list tools: No response from server.'); logApiError(`Error listing tools from ${url}`, error); throw error; } if (this._serverVersion === null) { const error = new Error('Server version not available.'); logApiError('Error listing tools', error); throw error; } const toolsMap = {}; for (const tool of result.tools) { toolsMap[tool.name] = this.convertToolSchema(tool); } return { serverVersion: this._serverVersion, tools: toolsMap, // Cast to verify structure compliance or rely on structural typing }; } async toolGet(toolName, headers) { const manifest = await this.toolsList(undefined, headers); if (!manifest.tools[toolName]) { const error = new Error(`Tool '${toolName}' not found.`); logApiError(`Error getting tool ${toolName}`, error); throw error; } return { serverVersion: manifest.serverVersion, tools: { [toolName]: manifest.tools[toolName], }, }; } async toolInvoke(toolName, arguments_, headers) { await this.ensureInitialized(headers); if (Object.keys(headers).length > 0) { warnIfHttpAndHeaders(this._mcpBaseUrl, headers); } const params = { name: toolName, arguments: arguments_, }; const result = await __classPrivateFieldGet(this, _McpHttpTransportV20250326_instances, "m", _McpHttpTransportV20250326_sendRequest).call(this, this._mcpBaseUrl, types.CallToolRequest, params, headers); if (!result) { const error = new Error(`Failed to invoke tool '${toolName}': No response from server.`); logApiError(`Error invoking tool ${toolName}`, error); throw error; } return this.processToolResultContent(result.content); } } _McpHttpTransportV20250326_instances = new WeakSet(), _McpHttpTransportV20250326_sendRequest = async function _McpHttpTransportV20250326_sendRequest(url, request, paramsOverride, headers) { const params = paramsOverride || request.params; let payload; const isNotification = !('getResultModel' in request); const method = request.method; if (isNotification) { payload = { jsonrpc: '2.0', method, params: params, }; } else { payload = { jsonrpc: '2.0', id: uuidv4(), method, params: params, }; } // Inject Session ID into headers if available (v2025-03-26 specific) const reqHeaders = { ...(headers || {}) }; if (request.method !== 'initialize' && this._sessionId) { reqHeaders['Mcp-Session-Id'] = this._sessionId; } try { const response = await this._session.post(url, payload, { headers: reqHeaders, }); if (request.method === 'initialize') { const sessionId = response.headers['mcp-session-id'] || response.headers['Mcp-Session-Id']; if (sessionId) { this._sessionId = sessionId; } } if (response.status !== 200 && response.status !== 204 && response.status !== 202) { const errorText = JSON.stringify(response.data); throw new Error(`API request failed with status ${response.status} (${response.statusText}). Server response: ${errorText}`); } if (response.status === 204 || response.status === 202) { return null; } const jsonResp = response.data; if (jsonResp.error) { const errResult = types.JSONRPCErrorSchema.safeParse(jsonResp); let message = `MCP request failed: ${JSON.stringify(jsonResp.error)}`; let code = 'MCP_ERROR'; if (errResult.success) { const err = errResult.data.error; message = `MCP request failed with code ${err.code}: ${err.message}`; code = String(err.code); } throw new AxiosError(message, code, response.config, response.request, response); } // Parse Result if (!isNotification && 'getResultModel' in request) { const rpcRespResult = types.JSONRPCResponseSchema.safeParse(jsonResp); if (rpcRespResult.success) { const resultModel = request.getResultModel(); return resultModel.parse(rpcRespResult.data.result); } throw new Error('Failed to parse JSON-RPC response structure'); } return null; } catch (error) { logApiError(`Error posting data to ${url}:`, error); throw error; } }; //# sourceMappingURL=mcp.js.map