diff --git a/src/agents/pi-tools.schema.test.ts b/src/agents/pi-tools.schema.test.ts index 81c56a7f0dd..bcaa1074402 100644 --- a/src/agents/pi-tools.schema.test.ts +++ b/src/agents/pi-tools.schema.test.ts @@ -4,6 +4,22 @@ import { normalizeToolParameters } from "./pi-tools.schema.js"; import type { AnyAgentTool } from "./pi-tools.types.js"; describe("normalizeToolParameters", () => { + it("normalizes truly empty schemas to type:object with properties:{} (MCP parameter-free tools)", () => { + const tool: AnyAgentTool = { + name: "get_flux_instance", + label: "get_flux_instance", + description: "Get current Flux instance status", + parameters: {}, + execute: vi.fn(), + }; + + const normalized = normalizeToolParameters(tool); + + const parameters = normalized.parameters as Record; + expect(parameters.type).toBe("object"); + expect(parameters.properties).toEqual({}); + }); + it("injects properties:{} for type:object schemas missing properties (MCP no-param tools)", () => { const tool: AnyAgentTool = { name: "list_regions", diff --git a/src/agents/pi-tools.schema.ts b/src/agents/pi-tools.schema.ts index 902c6ad0937..ea6d4145b71 100644 --- a/src/agents/pi-tools.schema.ts +++ b/src/agents/pi-tools.schema.ts @@ -133,6 +133,12 @@ export function normalizeToolParameterSchema( ? "oneOf" : null; if (!variantKey) { + // Handle truly empty schemas (no type, no properties, no unions) — + // OpenAI requires `type: "object"` with `properties` for tool schemas. + // MCP tools with parameter-free schemas may return `{}` or minimal objects. + if (!("type" in schemaRecord) && !("properties" in schemaRecord)) { + return applyProviderCleaning({ type: "object", properties: {}, ...schemaRecord }); + } return schema; } const variants = schemaRecord[variantKey] as unknown[];