Skip to content

Commit 5e6e618

Browse files
authored
fix: fixed ajv compile also for MCP proxy tools (#140)
fix ajv compile also for MCP proxy tools
1 parent 2a01189 commit 5e6e618

File tree

3 files changed

+26
-22
lines changed

3 files changed

+26
-22
lines changed

src/mcp/proxy.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type { Client } from '@modelcontextprotocol/sdk/client/index.js';
22
import Ajv from 'ajv';
33

4+
import { fixedAjvCompile } from '../tools/utils.js';
45
import type { ActorMcpTool, ToolEntry } from '../types.js';
56
import { getMCPServerID, getProxyMCPServerToolName } from './utils.js';
67

@@ -26,7 +27,7 @@ export async function getMCPServerTools(
2627
name: getProxyMCPServerToolName(serverUrl, tool.name),
2728
description: tool.description || '',
2829
inputSchema: tool.inputSchema,
29-
ajvValidate: ajv.compile(tool.inputSchema),
30+
ajvValidate: fixedAjvCompile(ajv, tool.inputSchema),
3031
};
3132

3233
const wrap: ToolEntry = {

src/tools/actor.ts

Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import type { Client } from '@modelcontextprotocol/sdk/client/index.js';
2-
import type { ValidateFunction } from 'ajv';
32
import { Ajv } from 'ajv';
43
import type { ActorCallOptions, ActorRun, Dataset, PaginatedList } from 'apify-client';
54
import { z } from 'zod';
@@ -27,32 +26,14 @@ import {
2726
addEnumsToDescriptionsWithExamples,
2827
buildNestedProperties,
2928
filterSchemaProperties,
29+
fixedAjvCompile,
3030
getToolSchemaID,
3131
markInputPropertiesAsRequired,
3232
shortenProperties,
3333
} from './utils.js';
3434

3535
const ajv = new Ajv({ coerceTypes: 'array', strict: false });
3636

37-
// source https://github.com/ajv-validator/ajv/issues/1413#issuecomment-867064234
38-
function fixedCompile(schema: object): ValidateFunction<unknown> {
39-
const validate = ajv.compile(schema);
40-
ajv.removeSchema(schema);
41-
42-
// Force reset values that aren't reset with removeSchema
43-
/* eslint-disable no-underscore-dangle */
44-
/* eslint-disable @typescript-eslint/no-explicit-any */
45-
(ajv.scope as any)._values.schema!.delete(schema);
46-
(ajv.scope as any)._values.validate!.delete(validate);
47-
const schemaIdx = (ajv.scope as any)._scope.schema.indexOf(schema);
48-
const validateIdx = (ajv.scope as any)._scope.validate.indexOf(validate);
49-
if (schemaIdx !== -1) (ajv.scope as any)._scope.schema.splice(schemaIdx, 1);
50-
if (validateIdx !== -1) (ajv.scope as any)._scope.validate.splice(validateIdx, 1);
51-
/* eslint-enable @typescript-eslint/no-explicit-any */
52-
/* eslint-enable no-underscore-dangle */
53-
return validate;
54-
}
55-
5637
// Define a named return type for callActorGetDataset
5738
export type CallActorGetDatasetResult = {
5839
actorRun: ActorRun;
@@ -182,7 +163,7 @@ export async function getNormalActorsAsTools(
182163
actorFullName: result.actorFullName,
183164
description: `${result.description} Instructions: ${ACTOR_ADDITIONAL_INSTRUCTIONS}`,
184165
inputSchema: result.input || {},
185-
ajvValidate: fixedCompile(result.input || {}),
166+
ajvValidate: fixedAjvCompile(ajv, result.input || {}),
186167
memoryMbytes: memoryMbytes > ACTOR_MAX_MEMORY_MBYTES ? ACTOR_MAX_MEMORY_MBYTES : memoryMbytes,
187168
},
188169
};

src/tools/utils.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
import type { ValidateFunction } from 'ajv';
2+
import type Ajv from 'ajv';
3+
14
import { ACTOR_ENUM_MAX_LENGTH, ACTOR_MAX_DESCRIPTION_LENGTH } from '../const.js';
25
import type { IActorInputSchema, ISchemaProperties } from '../types.js';
36

@@ -12,6 +15,25 @@ export function getToolSchemaID(actorName: string): string {
1215
return `https://apify.com/mcp/${actorNameToToolName(actorName)}/schema.json`;
1316
}
1417

18+
// source https://github.com/ajv-validator/ajv/issues/1413#issuecomment-867064234
19+
export function fixedAjvCompile(ajvInstance: Ajv, schema: object): ValidateFunction<unknown> {
20+
const validate = ajvInstance.compile(schema);
21+
ajvInstance.removeSchema(schema);
22+
23+
// Force reset values that aren't reset with removeSchema
24+
/* eslint-disable no-underscore-dangle */
25+
/* eslint-disable @typescript-eslint/no-explicit-any */
26+
(ajvInstance.scope as any)._values.schema!.delete(schema);
27+
(ajvInstance.scope as any)._values.validate!.delete(validate);
28+
const schemaIdx = (ajvInstance.scope as any)._scope.schema.indexOf(schema);
29+
const validateIdx = (ajvInstance.scope as any)._scope.validate.indexOf(validate);
30+
if (schemaIdx !== -1) (ajvInstance.scope as any)._scope.schema.splice(schemaIdx, 1);
31+
if (validateIdx !== -1) (ajvInstance.scope as any)._scope.validate.splice(validateIdx, 1);
32+
/* eslint-enable @typescript-eslint/no-explicit-any */
33+
/* eslint-enable no-underscore-dangle */
34+
return validate;
35+
}
36+
1537
/**
1638
* Builds nested properties for object types in the schema.
1739
*

0 commit comments

Comments
 (0)