From 9f2e513bbb7fb463586c745e039e26be292fc062 Mon Sep 17 00:00:00 2001 From: MQ Date: Fri, 13 Jun 2025 11:51:53 +0200 Subject: [PATCH] fix ajv compile also for MCP proxy tools --- src/mcp/proxy.ts | 3 ++- src/tools/actor.ts | 23 ++--------------------- src/tools/utils.ts | 22 ++++++++++++++++++++++ 3 files changed, 26 insertions(+), 22 deletions(-) diff --git a/src/mcp/proxy.ts b/src/mcp/proxy.ts index 37952242..327a057d 100644 --- a/src/mcp/proxy.ts +++ b/src/mcp/proxy.ts @@ -1,6 +1,7 @@ import type { Client } from '@modelcontextprotocol/sdk/client/index.js'; import Ajv from 'ajv'; +import { fixedAjvCompile } from '../tools/utils.js'; import type { ActorMcpTool, ToolEntry } from '../types.js'; import { getMCPServerID, getProxyMCPServerToolName } from './utils.js'; @@ -26,7 +27,7 @@ export async function getMCPServerTools( name: getProxyMCPServerToolName(serverUrl, tool.name), description: tool.description || '', inputSchema: tool.inputSchema, - ajvValidate: ajv.compile(tool.inputSchema), + ajvValidate: fixedAjvCompile(ajv, tool.inputSchema), }; const wrap: ToolEntry = { diff --git a/src/tools/actor.ts b/src/tools/actor.ts index b1ccd4cf..6619b0c2 100644 --- a/src/tools/actor.ts +++ b/src/tools/actor.ts @@ -1,5 +1,4 @@ import type { Client } from '@modelcontextprotocol/sdk/client/index.js'; -import type { ValidateFunction } from 'ajv'; import { Ajv } from 'ajv'; import type { ActorCallOptions, ActorRun, Dataset, PaginatedList } from 'apify-client'; import { z } from 'zod'; @@ -27,6 +26,7 @@ import { addEnumsToDescriptionsWithExamples, buildNestedProperties, filterSchemaProperties, + fixedAjvCompile, getToolSchemaID, markInputPropertiesAsRequired, shortenProperties, @@ -34,25 +34,6 @@ import { const ajv = new Ajv({ coerceTypes: 'array', strict: false }); -// source https://github.com/ajv-validator/ajv/issues/1413#issuecomment-867064234 -function fixedCompile(schema: object): ValidateFunction { - const validate = ajv.compile(schema); - ajv.removeSchema(schema); - - // Force reset values that aren't reset with removeSchema - /* eslint-disable no-underscore-dangle */ - /* eslint-disable @typescript-eslint/no-explicit-any */ - (ajv.scope as any)._values.schema!.delete(schema); - (ajv.scope as any)._values.validate!.delete(validate); - const schemaIdx = (ajv.scope as any)._scope.schema.indexOf(schema); - const validateIdx = (ajv.scope as any)._scope.validate.indexOf(validate); - if (schemaIdx !== -1) (ajv.scope as any)._scope.schema.splice(schemaIdx, 1); - if (validateIdx !== -1) (ajv.scope as any)._scope.validate.splice(validateIdx, 1); - /* eslint-enable @typescript-eslint/no-explicit-any */ - /* eslint-enable no-underscore-dangle */ - return validate; -} - // Define a named return type for callActorGetDataset export type CallActorGetDatasetResult = { actorRun: ActorRun; @@ -182,7 +163,7 @@ export async function getNormalActorsAsTools( actorFullName: result.actorFullName, description: `${result.description} Instructions: ${ACTOR_ADDITIONAL_INSTRUCTIONS}`, inputSchema: result.input || {}, - ajvValidate: fixedCompile(result.input || {}), + ajvValidate: fixedAjvCompile(ajv, result.input || {}), memoryMbytes: memoryMbytes > ACTOR_MAX_MEMORY_MBYTES ? ACTOR_MAX_MEMORY_MBYTES : memoryMbytes, }, }; diff --git a/src/tools/utils.ts b/src/tools/utils.ts index ed4f3c5c..bb191354 100644 --- a/src/tools/utils.ts +++ b/src/tools/utils.ts @@ -1,3 +1,6 @@ +import type { ValidateFunction } from 'ajv'; +import type Ajv from 'ajv'; + import { ACTOR_ENUM_MAX_LENGTH, ACTOR_MAX_DESCRIPTION_LENGTH } from '../const.js'; import type { IActorInputSchema, ISchemaProperties } from '../types.js'; @@ -12,6 +15,25 @@ export function getToolSchemaID(actorName: string): string { return `https://apify.com/mcp/${actorNameToToolName(actorName)}/schema.json`; } +// source https://github.com/ajv-validator/ajv/issues/1413#issuecomment-867064234 +export function fixedAjvCompile(ajvInstance: Ajv, schema: object): ValidateFunction { + const validate = ajvInstance.compile(schema); + ajvInstance.removeSchema(schema); + + // Force reset values that aren't reset with removeSchema + /* eslint-disable no-underscore-dangle */ + /* eslint-disable @typescript-eslint/no-explicit-any */ + (ajvInstance.scope as any)._values.schema!.delete(schema); + (ajvInstance.scope as any)._values.validate!.delete(validate); + const schemaIdx = (ajvInstance.scope as any)._scope.schema.indexOf(schema); + const validateIdx = (ajvInstance.scope as any)._scope.validate.indexOf(validate); + if (schemaIdx !== -1) (ajvInstance.scope as any)._scope.schema.splice(schemaIdx, 1); + if (validateIdx !== -1) (ajvInstance.scope as any)._scope.validate.splice(validateIdx, 1); + /* eslint-enable @typescript-eslint/no-explicit-any */ + /* eslint-enable no-underscore-dangle */ + return validate; +} + /** * Builds nested properties for object types in the schema. *