Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/mcp/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import {
SERVER_VERSION,
} from '../const.js';
import { addRemoveTools, betaTools, callActorGetDataset, defaultTools, getActorsAsTools } from '../tools/index.js';
import { actorNameToToolName } from '../tools/utils.js';
import { actorNameToToolName, decodeDotPropertyNames } from '../tools/utils.js';
import type { ActorMcpTool, ActorTool, HelperTool, ToolEntry } from '../types.js';
import { connectMCPClient } from './client.js';
import { EXTERNAL_TOOL_CALL_TIMEOUT_MSEC } from './const.js';
Expand Down Expand Up @@ -407,6 +407,9 @@ export class ActorsMcpServer {
msg,
);
}
// Decode dot property names in arguments before validation,
// since validation expects the original, non-encoded property names.
args = decodeDotPropertyNames(args);
log.info(`Validate arguments for tool: ${tool.tool.name} with arguments: ${JSON.stringify(args)}`);
if (!tool.tool.ajvValidate(args)) {
const msg = `Invalid arguments for tool ${tool.tool.name}: args: ${JSON.stringify(args)} error: ${JSON.stringify(tool?.tool.ajvValidate.errors)}`;
Expand Down
2 changes: 2 additions & 0 deletions src/tools/actor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
actorNameToToolName,
addEnumsToDescriptionsWithExamples,
buildNestedProperties,
encodeDotPropertyNames,
filterSchemaProperties,
fixedAjvCompile,
getToolSchemaID,
Expand Down Expand Up @@ -128,6 +129,7 @@ export async function getNormalActorsAsTools(
actorDefinitionPruned.input.properties = filterSchemaProperties(actorDefinitionPruned.input.properties);
actorDefinitionPruned.input.properties = shortenProperties(actorDefinitionPruned.input.properties);
actorDefinitionPruned.input.properties = addEnumsToDescriptionsWithExamples(actorDefinitionPruned.input.properties);
actorDefinitionPruned.input.properties = encodeDotPropertyNames(actorDefinitionPruned.input.properties);
// Add schema $id, each valid JSON schema should have a unique $id
// see https://json-schema.org/understanding-json-schema/basics#declaring-a-unique-identifier
actorDefinitionPruned.input.$id = schemaID;
Expand Down
37 changes: 37 additions & 0 deletions src/tools/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -242,3 +242,40 @@ export function shortenProperties(properties: { [key: string]: ISchemaProperties

return properties;
}

/**
* Fixes dot notation in the property names of schema properties.
*
* Some providers, such as Anthropic, allow only the following characters in property names: `^[a-zA-Z0-9_-]{1,64}$`.
*
* @param properties - The schema properties to fix.
* @returns {Record<string, ISchemaProperties>} The schema properties with fixed names.
*/
export function encodeDotPropertyNames(properties: Record<string, ISchemaProperties>): Record<string, ISchemaProperties> {
const encodedProperties: Record<string, ISchemaProperties> = {};
for (const [key, value] of Object.entries(properties)) {
// Replace dots with '-dot-' to avoid issues with property names
const fixedKey = key.replace(/\./g, '-dot-');
encodedProperties[fixedKey] = value;
}
return encodedProperties;
}

/**
* Restores original property names by replacing '-dot-' with '.'.
*
* This is necessary to decode the property names that were encoded to avoid issues with providers
* that do not allow dots in property names.
*
* @param properties - The schema properties with encoded names.
* @returns {Record<string, ISchemaProperties>} The schema properties with restored names.
*/
export function decodeDotPropertyNames(properties: Record<string, unknown>): Record<string, unknown> {
const decodedProperties: Record<string, unknown> = {};
for (const [key, value] of Object.entries(properties)) {
// Replace '-dot-' with '.' to restore original property names
const decodedKey = key.replace(/-dot-/g, '.');
decodedProperties[decodedKey] = value;
}
return decodedProperties;
}