@iqai/adk 0.0.2 → 0.0.3

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/dist/index.mjs CHANGED
@@ -2023,11 +2023,19 @@ __export(tools_exports, {
2023
2023
  GoogleSearch: () => GoogleSearch,
2024
2024
  HttpRequestTool: () => HttpRequestTool,
2025
2025
  LoadMemoryTool: () => LoadMemoryTool,
2026
+ McpError: () => McpError,
2027
+ McpErrorType: () => McpErrorType,
2028
+ McpToolset: () => McpToolset,
2026
2029
  ToolContext: () => ToolContext,
2027
2030
  TransferToAgentTool: () => TransferToAgentTool,
2028
2031
  UserInteractionTool: () => UserInteractionTool,
2032
+ adkToMcpToolType: () => adkToMcpToolType,
2029
2033
  buildFunctionDeclaration: () => buildFunctionDeclaration,
2030
- createFunctionTool: () => createFunctionTool
2034
+ createFunctionTool: () => createFunctionTool,
2035
+ getMcpTools: () => getMcpTools,
2036
+ jsonSchemaToDeclaration: () => jsonSchemaToDeclaration,
2037
+ mcpSchemaToParameters: () => mcpSchemaToParameters,
2038
+ normalizeJsonSchema: () => normalizeJsonSchema
2031
2039
  });
2032
2040
  init_base_tool();
2033
2041
  init_function_tool();
@@ -2768,6 +2776,702 @@ var LoadMemoryTool = class extends BaseTool {
2768
2776
  }
2769
2777
  };
2770
2778
 
2779
+ // src/tools/mcp/client.ts
2780
+ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
2781
+ import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
2782
+ import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
2783
+
2784
+ // src/tools/mcp/types.ts
2785
+ var McpErrorType = /* @__PURE__ */ ((McpErrorType2) => {
2786
+ McpErrorType2["CONNECTION_ERROR"] = "connection_error";
2787
+ McpErrorType2["TOOL_EXECUTION_ERROR"] = "tool_execution_error";
2788
+ McpErrorType2["RESOURCE_CLOSED_ERROR"] = "resource_closed_error";
2789
+ McpErrorType2["TIMEOUT_ERROR"] = "timeout_error";
2790
+ McpErrorType2["INVALID_SCHEMA_ERROR"] = "invalid_schema_error";
2791
+ return McpErrorType2;
2792
+ })(McpErrorType || {});
2793
+ var McpError = class extends Error {
2794
+ constructor(message, type, originalError) {
2795
+ super(message);
2796
+ this.name = "McpError";
2797
+ this.type = type;
2798
+ this.originalError = originalError;
2799
+ }
2800
+ };
2801
+
2802
+ // src/tools/mcp/utils.ts
2803
+ function withRetry(fn, instance, reinitMethod, maxRetries = 1) {
2804
+ return async (...args) => {
2805
+ let attempt = 0;
2806
+ while (attempt <= maxRetries) {
2807
+ try {
2808
+ return await fn.apply(instance, args);
2809
+ } catch (error) {
2810
+ const isClosedResourceError = error instanceof Error && (error.message.includes("closed") || error.message.includes("ECONNRESET") || error.message.includes("socket hang up"));
2811
+ if (!isClosedResourceError || attempt >= maxRetries) {
2812
+ throw error;
2813
+ }
2814
+ console.warn(
2815
+ `Resource closed, reinitializing (attempt ${attempt + 1}/${maxRetries + 1})...`
2816
+ );
2817
+ try {
2818
+ await reinitMethod(instance);
2819
+ } catch (reinitError) {
2820
+ console.error("Error reinitializing resources:", reinitError);
2821
+ throw new Error(`Failed to reinitialize resources: ${reinitError}`);
2822
+ }
2823
+ attempt++;
2824
+ }
2825
+ }
2826
+ throw new Error("Unexpected end of retry loop");
2827
+ };
2828
+ }
2829
+
2830
+ // src/tools/mcp/client.ts
2831
+ var McpClientService = class {
2832
+ constructor(config) {
2833
+ this.client = null;
2834
+ this.transport = null;
2835
+ this.isClosing = false;
2836
+ this.config = config;
2837
+ }
2838
+ /**
2839
+ * Initializes and returns an MCP client based on configuration.
2840
+ * Will create a new client if one doesn't exist yet.
2841
+ */
2842
+ async initialize() {
2843
+ if (this.isClosing) {
2844
+ throw new McpError(
2845
+ "Cannot initialize a client that is being closed",
2846
+ "resource_closed_error" /* RESOURCE_CLOSED_ERROR */
2847
+ );
2848
+ }
2849
+ if (this.client) {
2850
+ return this.client;
2851
+ }
2852
+ try {
2853
+ if (!this.transport) {
2854
+ this.transport = await this.createTransport();
2855
+ }
2856
+ const client = new Client(
2857
+ {
2858
+ name: this.config.name,
2859
+ version: "0.0.1"
2860
+ },
2861
+ {
2862
+ capabilities: {
2863
+ prompts: {},
2864
+ resources: {},
2865
+ tools: {}
2866
+ }
2867
+ }
2868
+ );
2869
+ const connectPromise = client.connect(this.transport);
2870
+ if (this.config.timeout) {
2871
+ const timeoutPromise = new Promise((_, reject) => {
2872
+ setTimeout(() => {
2873
+ reject(
2874
+ new McpError(
2875
+ `MCP client connection timed out after ${this.config.timeout}ms`,
2876
+ "timeout_error" /* TIMEOUT_ERROR */
2877
+ )
2878
+ );
2879
+ }, this.config.timeout);
2880
+ });
2881
+ await Promise.race([connectPromise, timeoutPromise]);
2882
+ } else {
2883
+ await connectPromise;
2884
+ }
2885
+ if (this.config.debug) {
2886
+ console.log("\u2705 MCP client connected successfully");
2887
+ }
2888
+ this.client = client;
2889
+ return client;
2890
+ } catch (error) {
2891
+ await this.cleanupResources();
2892
+ if (!(error instanceof McpError)) {
2893
+ console.error("Failed to initialize MCP client:", error);
2894
+ throw new McpError(
2895
+ `Failed to initialize MCP client: ${error instanceof Error ? error.message : String(error)}`,
2896
+ "connection_error" /* CONNECTION_ERROR */,
2897
+ error instanceof Error ? error : void 0
2898
+ );
2899
+ }
2900
+ throw error;
2901
+ }
2902
+ }
2903
+ /**
2904
+ * Creates a transport based on the configuration.
2905
+ */
2906
+ async createTransport() {
2907
+ try {
2908
+ if (this.config.transport.mode === "sse") {
2909
+ if (this.config.debug) {
2910
+ console.log(
2911
+ "\u{1F680} Initializing MCP client in SSE mode",
2912
+ this.config.transport.serverUrl
2913
+ );
2914
+ }
2915
+ const headers = {
2916
+ ...this.config.transport.headers || {},
2917
+ ...this.config.headers || {}
2918
+ };
2919
+ return new SSEClientTransport(
2920
+ new URL(this.config.transport.serverUrl),
2921
+ {
2922
+ requestInit: {
2923
+ headers,
2924
+ ...this.config.timeout ? { timeout: this.config.timeout } : {}
2925
+ }
2926
+ }
2927
+ );
2928
+ }
2929
+ if (this.config.debug) {
2930
+ console.log(
2931
+ "\u{1F680} Initializing MCP client in STDIO mode",
2932
+ this.config.transport.command
2933
+ );
2934
+ }
2935
+ return new StdioClientTransport({
2936
+ command: this.config.transport.command,
2937
+ args: this.config.transport.args,
2938
+ env: this.config.transport.env
2939
+ });
2940
+ } catch (error) {
2941
+ throw new McpError(
2942
+ `Failed to create transport: ${error instanceof Error ? error.message : String(error)}`,
2943
+ "connection_error" /* CONNECTION_ERROR */,
2944
+ error instanceof Error ? error : void 0
2945
+ );
2946
+ }
2947
+ }
2948
+ /**
2949
+ * Re-initializes the MCP client when a session is closed.
2950
+ * Used by the retry mechanism.
2951
+ */
2952
+ async reinitialize() {
2953
+ if (this.config.debug) {
2954
+ console.log("\u{1F504} Reinitializing MCP client after closed connection");
2955
+ }
2956
+ await this.cleanupResources();
2957
+ this.client = null;
2958
+ this.transport = null;
2959
+ await this.initialize();
2960
+ }
2961
+ /**
2962
+ * Cleans up resources associated with this client service.
2963
+ * Similar to Python's AsyncExitStack.aclose() functionality.
2964
+ */
2965
+ async cleanupResources() {
2966
+ try {
2967
+ this.isClosing = true;
2968
+ if (this.client) {
2969
+ try {
2970
+ if (typeof this.client.close === "function") {
2971
+ await this.client.close();
2972
+ }
2973
+ } catch (err) {
2974
+ }
2975
+ }
2976
+ if (this.transport && typeof this.transport.close === "function") {
2977
+ await this.transport.close();
2978
+ }
2979
+ if (this.config.debug) {
2980
+ console.log("\u{1F9F9} Cleaned up MCP client resources");
2981
+ }
2982
+ } catch (error) {
2983
+ console.error("Error cleaning up MCP resources:", error);
2984
+ } finally {
2985
+ this.client = null;
2986
+ this.transport = null;
2987
+ this.isClosing = false;
2988
+ }
2989
+ }
2990
+ /**
2991
+ * Call an MCP tool with retry capability if the session is closed.
2992
+ */
2993
+ async callTool(name, args) {
2994
+ try {
2995
+ const wrappedCall = withRetry(
2996
+ async function() {
2997
+ const client = await this.initialize();
2998
+ return client.callTool({
2999
+ name,
3000
+ arguments: args
3001
+ });
3002
+ },
3003
+ this,
3004
+ async (instance) => await instance.reinitialize(),
3005
+ this.config.retryOptions?.maxRetries || 2
3006
+ );
3007
+ return await wrappedCall();
3008
+ } catch (error) {
3009
+ if (!(error instanceof McpError)) {
3010
+ throw new McpError(
3011
+ `Error calling tool "${name}": ${error instanceof Error ? error.message : String(error)}`,
3012
+ "tool_execution_error" /* TOOL_EXECUTION_ERROR */,
3013
+ error instanceof Error ? error : void 0
3014
+ );
3015
+ }
3016
+ throw error;
3017
+ }
3018
+ }
3019
+ /**
3020
+ * Closes and cleans up all resources.
3021
+ * Should be called when the service is no longer needed.
3022
+ * Similar to Python's close() method.
3023
+ */
3024
+ async close() {
3025
+ if (this.config.debug) {
3026
+ console.log("\u{1F51A} Closing MCP client service");
3027
+ }
3028
+ await this.cleanupResources();
3029
+ }
3030
+ /**
3031
+ * Checks if the client is currently connected
3032
+ */
3033
+ isConnected() {
3034
+ return !!this.client && !this.isClosing;
3035
+ }
3036
+ };
3037
+
3038
+ // src/tools/mcp/create-tool.ts
3039
+ init_base_tool();
3040
+
3041
+ // src/tools/mcp/schema-conversion.ts
3042
+ function adkToMcpToolType(tool) {
3043
+ const declaration = tool.getDeclaration();
3044
+ const params = declarationToJsonSchema(declaration);
3045
+ return {
3046
+ name: tool.name,
3047
+ description: tool.description || "",
3048
+ inputSchema: {
3049
+ type: "object",
3050
+ properties: params
3051
+ }
3052
+ };
3053
+ }
3054
+ function declarationToJsonSchema(declaration) {
3055
+ if (!declaration.parameters) {
3056
+ return {};
3057
+ }
3058
+ if (declaration.parameters.properties) {
3059
+ return declaration.parameters.properties;
3060
+ }
3061
+ return declaration.parameters;
3062
+ }
3063
+ function jsonSchemaToDeclaration(name, description, schema) {
3064
+ let parameters;
3065
+ if (schema) {
3066
+ if (typeof schema === "object" && "type" in schema && typeof schema.type === "string") {
3067
+ parameters = schema;
3068
+ } else {
3069
+ parameters = {
3070
+ type: "object",
3071
+ properties: schema
3072
+ };
3073
+ }
3074
+ } else {
3075
+ parameters = {
3076
+ type: "object",
3077
+ properties: {}
3078
+ };
3079
+ }
3080
+ return {
3081
+ name,
3082
+ description,
3083
+ parameters
3084
+ };
3085
+ }
3086
+ function normalizeJsonSchema(schema) {
3087
+ if (!schema) {
3088
+ return { type: "object", properties: {} };
3089
+ }
3090
+ const normalizedSchema = { ...schema };
3091
+ if (!normalizedSchema.type) {
3092
+ normalizedSchema.type = determineSchemaType(normalizedSchema);
3093
+ }
3094
+ switch (normalizedSchema.type) {
3095
+ case "object":
3096
+ return normalizeObjectSchema(normalizedSchema);
3097
+ case "array":
3098
+ return normalizeArraySchema(normalizedSchema);
3099
+ case "string":
3100
+ return normalizeStringSchema(normalizedSchema);
3101
+ case "number":
3102
+ case "integer":
3103
+ return normalizeNumberSchema(normalizedSchema);
3104
+ case "boolean":
3105
+ return { type: "boolean" };
3106
+ case "null":
3107
+ return { type: "null" };
3108
+ default:
3109
+ return normalizedSchema;
3110
+ }
3111
+ }
3112
+ function determineSchemaType(schema) {
3113
+ if (schema.properties || schema.required || schema.additionalProperties !== void 0) {
3114
+ return "object";
3115
+ }
3116
+ if (schema.items) {
3117
+ return "array";
3118
+ }
3119
+ if (schema.enum !== void 0) {
3120
+ if (schema.enum.length === 0) return "string";
3121
+ const firstItem = schema.enum[0];
3122
+ if (typeof firstItem === "string") return "string";
3123
+ if (typeof firstItem === "number") return "number";
3124
+ if (typeof firstItem === "boolean") return "boolean";
3125
+ return "string";
3126
+ }
3127
+ if (schema.minLength !== void 0 || schema.maxLength !== void 0 || schema.pattern) {
3128
+ return "string";
3129
+ }
3130
+ if (schema.minimum !== void 0 || schema.maximum !== void 0 || schema.exclusiveMinimum !== void 0 || schema.exclusiveMaximum !== void 0) {
3131
+ return schema.multipleOf === void 0 || schema.multipleOf % 1 === 0 ? "integer" : "number";
3132
+ }
3133
+ return "object";
3134
+ }
3135
+ function normalizeObjectSchema(schema) {
3136
+ const normalizedSchema = {
3137
+ type: "object",
3138
+ properties: {}
3139
+ };
3140
+ if (schema.properties) {
3141
+ normalizedSchema.properties = {};
3142
+ for (const [key, value] of Object.entries(schema.properties)) {
3143
+ normalizedSchema.properties[key] = normalizeJsonSchema(
3144
+ value
3145
+ );
3146
+ }
3147
+ }
3148
+ if (schema.required) normalizedSchema.required = schema.required;
3149
+ if (schema.additionalProperties !== void 0)
3150
+ normalizedSchema.additionalProperties = schema.additionalProperties;
3151
+ if (schema.title) normalizedSchema.title = schema.title;
3152
+ if (schema.description) normalizedSchema.description = schema.description;
3153
+ return normalizedSchema;
3154
+ }
3155
+ function normalizeArraySchema(schema) {
3156
+ const normalizedSchema = {
3157
+ type: "array"
3158
+ };
3159
+ if (schema.items) {
3160
+ normalizedSchema.items = normalizeJsonSchema(
3161
+ schema.items
3162
+ );
3163
+ }
3164
+ if (schema.minItems !== void 0)
3165
+ normalizedSchema.minItems = schema.minItems;
3166
+ if (schema.maxItems !== void 0)
3167
+ normalizedSchema.maxItems = schema.maxItems;
3168
+ if (schema.uniqueItems !== void 0)
3169
+ normalizedSchema.uniqueItems = schema.uniqueItems;
3170
+ if (schema.title) normalizedSchema.title = schema.title;
3171
+ if (schema.description) normalizedSchema.description = schema.description;
3172
+ return normalizedSchema;
3173
+ }
3174
+ function normalizeStringSchema(schema) {
3175
+ const normalizedSchema = {
3176
+ type: "string"
3177
+ };
3178
+ if (schema.minLength !== void 0)
3179
+ normalizedSchema.minLength = schema.minLength;
3180
+ if (schema.maxLength !== void 0)
3181
+ normalizedSchema.maxLength = schema.maxLength;
3182
+ if (schema.pattern) normalizedSchema.pattern = schema.pattern;
3183
+ if (schema.format) normalizedSchema.format = schema.format;
3184
+ if (schema.enum) normalizedSchema.enum = schema.enum;
3185
+ if (schema.title) normalizedSchema.title = schema.title;
3186
+ if (schema.description) normalizedSchema.description = schema.description;
3187
+ return normalizedSchema;
3188
+ }
3189
+ function normalizeNumberSchema(schema) {
3190
+ const normalizedSchema = {
3191
+ type: schema.type
3192
+ };
3193
+ if (schema.minimum !== void 0) normalizedSchema.minimum = schema.minimum;
3194
+ if (schema.maximum !== void 0) normalizedSchema.maximum = schema.maximum;
3195
+ if (schema.exclusiveMinimum !== void 0)
3196
+ normalizedSchema.exclusiveMinimum = schema.exclusiveMinimum;
3197
+ if (schema.exclusiveMaximum !== void 0)
3198
+ normalizedSchema.exclusiveMaximum = schema.exclusiveMaximum;
3199
+ if (schema.multipleOf !== void 0)
3200
+ normalizedSchema.multipleOf = schema.multipleOf;
3201
+ if (schema.enum) normalizedSchema.enum = schema.enum;
3202
+ if (schema.title) normalizedSchema.title = schema.title;
3203
+ if (schema.description) normalizedSchema.description = schema.description;
3204
+ return normalizedSchema;
3205
+ }
3206
+ function mcpSchemaToParameters(mcpTool) {
3207
+ let schema;
3208
+ if (mcpTool.inputSchema) {
3209
+ schema = mcpTool.inputSchema;
3210
+ } else if (mcpTool.parameters) {
3211
+ schema = mcpTool.parameters;
3212
+ }
3213
+ if (!schema) {
3214
+ return {
3215
+ type: "object",
3216
+ properties: {}
3217
+ };
3218
+ }
3219
+ return normalizeJsonSchema(schema);
3220
+ }
3221
+
3222
+ // src/tools/mcp/create-tool.ts
3223
+ async function createTool(mcpTool, client) {
3224
+ try {
3225
+ return new McpToolAdapter(mcpTool, client);
3226
+ } catch (error) {
3227
+ if (!(error instanceof McpError)) {
3228
+ throw new McpError(
3229
+ `Failed to create tool from MCP tool: ${error instanceof Error ? error.message : String(error)}`,
3230
+ "invalid_schema_error" /* INVALID_SCHEMA_ERROR */,
3231
+ error instanceof Error ? error : void 0
3232
+ );
3233
+ }
3234
+ throw error;
3235
+ }
3236
+ }
3237
+ var McpToolAdapter = class extends BaseTool {
3238
+ constructor(mcpTool, client) {
3239
+ const metadata = mcpTool.metadata || {};
3240
+ super({
3241
+ name: mcpTool.name || `mcp_${Date.now()}`,
3242
+ description: mcpTool.description || "MCP Tool",
3243
+ isLongRunning: metadata.isLongRunning ?? false,
3244
+ shouldRetryOnFailure: metadata.shouldRetryOnFailure ?? false,
3245
+ maxRetryAttempts: metadata.maxRetryAttempts ?? 3
3246
+ });
3247
+ this.clientService = null;
3248
+ this.mcpTool = mcpTool;
3249
+ this.client = client;
3250
+ if (client.reinitialize && typeof client.reinitialize === "function") {
3251
+ this.clientService = client;
3252
+ }
3253
+ }
3254
+ getDeclaration() {
3255
+ try {
3256
+ const parameters = mcpSchemaToParameters(this.mcpTool);
3257
+ return {
3258
+ name: this.name,
3259
+ description: this.description,
3260
+ parameters
3261
+ };
3262
+ } catch (error) {
3263
+ throw new McpError(
3264
+ `Failed to convert schema for tool ${this.name}: ${error instanceof Error ? error.message : String(error)}`,
3265
+ "invalid_schema_error" /* INVALID_SCHEMA_ERROR */,
3266
+ error instanceof Error ? error : void 0
3267
+ );
3268
+ }
3269
+ }
3270
+ async runAsync(args, _context) {
3271
+ if (process.env.DEBUG === "true") {
3272
+ console.log(`Executing MCP tool ${this.name} with args:`, args);
3273
+ }
3274
+ try {
3275
+ if (typeof this.mcpTool.execute === "function") {
3276
+ return await this.mcpTool.execute(args);
3277
+ }
3278
+ if (this.clientService) {
3279
+ return await this.clientService.callTool(this.name, args);
3280
+ }
3281
+ if (this.client && typeof this.client.callTool === "function") {
3282
+ if (this.shouldRetryOnFailure) {
3283
+ const executeWithRetry = withRetry(
3284
+ async () => {
3285
+ return await this.client.callTool({
3286
+ name: this.name,
3287
+ arguments: args
3288
+ });
3289
+ },
3290
+ this,
3291
+ async () => {
3292
+ console.warn(
3293
+ `MCP tool ${this.name} encountered a closed resource, but cannot reinitialize client.`
3294
+ );
3295
+ },
3296
+ this.maxRetryAttempts
3297
+ );
3298
+ return await executeWithRetry();
3299
+ }
3300
+ const result = await this.client.callTool({
3301
+ name: this.name,
3302
+ arguments: args
3303
+ });
3304
+ return result;
3305
+ }
3306
+ throw new McpError(
3307
+ `Cannot execute MCP tool ${this.name}: No execution method found`,
3308
+ "tool_execution_error" /* TOOL_EXECUTION_ERROR */
3309
+ );
3310
+ } catch (error) {
3311
+ if (!(error instanceof McpError)) {
3312
+ console.error(`Error executing MCP tool ${this.name}:`, error);
3313
+ throw new McpError(
3314
+ `Error executing MCP tool ${this.name}: ${error instanceof Error ? error.message : String(error)}`,
3315
+ "tool_execution_error" /* TOOL_EXECUTION_ERROR */,
3316
+ error instanceof Error ? error : void 0
3317
+ );
3318
+ }
3319
+ throw error;
3320
+ }
3321
+ }
3322
+ };
3323
+
3324
+ // src/tools/mcp/index.ts
3325
+ var McpToolset = class {
3326
+ constructor(config, toolFilter = null) {
3327
+ this.clientService = null;
3328
+ this.toolFilter = null;
3329
+ this.tools = [];
3330
+ this.isClosing = false;
3331
+ this.config = config;
3332
+ this.toolFilter = toolFilter;
3333
+ this.clientService = new McpClientService(config);
3334
+ }
3335
+ /**
3336
+ * Checks if a tool should be included based on the tool filter.
3337
+ * Similar to Python's _is_selected method.
3338
+ */
3339
+ isSelected(tool, context) {
3340
+ if (!this.toolFilter) {
3341
+ return true;
3342
+ }
3343
+ if (typeof this.toolFilter === "function") {
3344
+ return this.toolFilter(tool, context);
3345
+ }
3346
+ if (Array.isArray(this.toolFilter)) {
3347
+ return this.toolFilter.includes(tool.name);
3348
+ }
3349
+ return true;
3350
+ }
3351
+ /**
3352
+ * Initializes the client service and establishes a connection.
3353
+ */
3354
+ async initialize() {
3355
+ if (this.isClosing) {
3356
+ throw new McpError(
3357
+ "Cannot initialize a toolset that is being closed",
3358
+ "resource_closed_error" /* RESOURCE_CLOSED_ERROR */
3359
+ );
3360
+ }
3361
+ if (!this.clientService) {
3362
+ this.clientService = new McpClientService(this.config);
3363
+ }
3364
+ await this.clientService.initialize();
3365
+ return this.clientService;
3366
+ }
3367
+ /**
3368
+ * Retrieves tools from the MCP server and converts them to BaseTool instances.
3369
+ * Similar to Python's get_tools method.
3370
+ */
3371
+ async getTools(context) {
3372
+ try {
3373
+ if (this.isClosing) {
3374
+ throw new McpError(
3375
+ "Cannot get tools from a toolset that is being closed",
3376
+ "resource_closed_error" /* RESOURCE_CLOSED_ERROR */
3377
+ );
3378
+ }
3379
+ if (this.tools.length > 0 && !this.config.cacheConfig?.enabled === false) {
3380
+ return this.tools;
3381
+ }
3382
+ if (!this.clientService) {
3383
+ await this.initialize();
3384
+ }
3385
+ const client = await this.clientService.initialize();
3386
+ const toolsResponse = await client.listTools();
3387
+ if (!toolsResponse.tools || !Array.isArray(toolsResponse.tools)) {
3388
+ console.warn("MCP server returned no tools or invalid tools array");
3389
+ return [];
3390
+ }
3391
+ const tools = [];
3392
+ for (const mcpTool of toolsResponse.tools) {
3393
+ if (this.isSelected(mcpTool, context)) {
3394
+ try {
3395
+ const tool = await createTool(mcpTool, client);
3396
+ tools.push(tool);
3397
+ } catch (toolError) {
3398
+ console.error(
3399
+ `Failed to create tool from MCP tool "${mcpTool.name}":`,
3400
+ toolError
3401
+ );
3402
+ }
3403
+ }
3404
+ }
3405
+ if (this.config.cacheConfig?.enabled !== false) {
3406
+ this.tools = tools;
3407
+ }
3408
+ return tools;
3409
+ } catch (error) {
3410
+ if (!(error instanceof McpError)) {
3411
+ console.error("Error retrieving MCP tools:", error);
3412
+ throw new McpError(
3413
+ `Error retrieving MCP tools: ${error instanceof Error ? error.message : String(error)}`,
3414
+ "connection_error" /* CONNECTION_ERROR */,
3415
+ error instanceof Error ? error : void 0
3416
+ );
3417
+ }
3418
+ throw error;
3419
+ }
3420
+ }
3421
+ /**
3422
+ * Converts ADK tools to MCP tool format for bidirectional support
3423
+ */
3424
+ convertADKToolsToMCP(tools) {
3425
+ return tools.map((tool) => adkToMcpToolType(tool));
3426
+ }
3427
+ /**
3428
+ * Refreshes the tool cache by clearing it and fetching tools again
3429
+ */
3430
+ async refreshTools(context) {
3431
+ this.tools = [];
3432
+ return this.getTools(context);
3433
+ }
3434
+ /**
3435
+ * Closes the connection to the MCP server.
3436
+ * Similar to Python's close method.
3437
+ */
3438
+ async close() {
3439
+ if (this.isClosing) {
3440
+ return;
3441
+ }
3442
+ try {
3443
+ this.isClosing = true;
3444
+ if (this.clientService) {
3445
+ await this.clientService.close();
3446
+ this.clientService = null;
3447
+ }
3448
+ this.tools = [];
3449
+ if (this.config.debug) {
3450
+ console.log("\u2705 MCP toolset closed successfully");
3451
+ }
3452
+ } catch (error) {
3453
+ console.error("Error closing MCP toolset:", error);
3454
+ } finally {
3455
+ this.isClosing = false;
3456
+ }
3457
+ }
3458
+ /**
3459
+ * Disposes of all resources. This method should be called when the toolset is no longer needed.
3460
+ * Provides alignment with disposal patterns common in TypeScript.
3461
+ */
3462
+ async dispose() {
3463
+ await this.close();
3464
+ }
3465
+ };
3466
+ async function getMcpTools(config, toolFilter) {
3467
+ const toolset = new McpToolset(config, toolFilter);
3468
+ try {
3469
+ return await toolset.getTools();
3470
+ } finally {
3471
+ await toolset.close().catch((err) => console.error("Error closing toolset:", err));
3472
+ }
3473
+ }
3474
+
2771
3475
  // src/models/index.ts
2772
3476
  var models_exports = {};
2773
3477
  __export(models_exports, {
@@ -5690,6 +6394,9 @@ export {
5690
6394
  LangGraphAgent,
5691
6395
  LoadMemoryTool,
5692
6396
  LoopAgent,
6397
+ McpError,
6398
+ McpErrorType,
6399
+ McpToolset,
5693
6400
  memory_exports as Memory,
5694
6401
  models_exports as Models,
5695
6402
  OAuth2Credential,
@@ -5712,10 +6419,15 @@ export {
5712
6419
  TransferToAgentTool,
5713
6420
  UserInteractionTool,
5714
6421
  VERSION,
6422
+ adkToMcpToolType,
5715
6423
  buildFunctionDeclaration,
5716
6424
  cloneSession,
5717
6425
  createFunctionTool,
5718
6426
  generateSessionId,
6427
+ getMcpTools,
6428
+ jsonSchemaToDeclaration,
6429
+ mcpSchemaToParameters,
6430
+ normalizeJsonSchema,
5719
6431
  registerProviders,
5720
6432
  validateSession
5721
6433
  };