mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 08:20:43 +00:00
fix(gateway): normalize MCP object schemas
This commit is contained in:
@@ -70,9 +70,9 @@ export function buildMcpToolSchema(tools: McpLoopbackTool[]): McpToolSchemaEntry
|
||||
}
|
||||
if (raw.type !== "object") {
|
||||
raw.type = "object";
|
||||
if (!raw.properties) {
|
||||
raw.properties = {};
|
||||
}
|
||||
}
|
||||
if (!raw.properties) {
|
||||
raw.properties = {};
|
||||
}
|
||||
return {
|
||||
name: tool.name,
|
||||
|
||||
@@ -1,8 +1,20 @@
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { getFreePortBlockWithPermissionFallback } from "../test-utils/ports.js";
|
||||
|
||||
type MockGatewayTool = {
|
||||
name: string;
|
||||
description: string;
|
||||
parameters: Record<string, unknown>;
|
||||
execute: (...args: unknown[]) => Promise<{ content: Array<{ type: string; text: string }> }>;
|
||||
};
|
||||
|
||||
type MockGatewayScopedTools = {
|
||||
agentId: string;
|
||||
tools: MockGatewayTool[];
|
||||
};
|
||||
|
||||
const resolveGatewayScopedToolsMock = vi.hoisted(() =>
|
||||
vi.fn(() => ({
|
||||
vi.fn<(...args: unknown[]) => MockGatewayScopedTools>(() => ({
|
||||
agentId: "main",
|
||||
tools: [
|
||||
{
|
||||
@@ -112,6 +124,43 @@ describe("mcp loopback server", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("adds empty properties for object schemas that omit properties", async () => {
|
||||
resolveGatewayScopedToolsMock.mockReturnValue({
|
||||
agentId: "main",
|
||||
tools: [
|
||||
{
|
||||
name: "schema_probe",
|
||||
description: "exercise no-argument MCP schemas",
|
||||
parameters: { type: "object" },
|
||||
execute: async () => ({
|
||||
content: [{ type: "text", text: "ok" }],
|
||||
}),
|
||||
},
|
||||
],
|
||||
});
|
||||
server = await startMcpLoopbackServer(0);
|
||||
const runtime = getActiveMcpLoopbackRuntime();
|
||||
|
||||
const response = await sendRaw({
|
||||
port: server.port,
|
||||
token: runtime ? resolveMcpLoopbackBearerToken(runtime, false) : undefined,
|
||||
headers: {
|
||||
"content-type": "application/json",
|
||||
"x-session-key": "agent:main:main",
|
||||
},
|
||||
body: JSON.stringify({ jsonrpc: "2.0", id: 1, method: "tools/list" }),
|
||||
});
|
||||
const payload = (await response.json()) as {
|
||||
result?: { tools?: Array<{ inputSchema?: Record<string, unknown> }> };
|
||||
};
|
||||
|
||||
expect(response.status).toBe(200);
|
||||
expect(payload.result?.tools?.[0]?.inputSchema).toEqual({
|
||||
type: "object",
|
||||
properties: {},
|
||||
});
|
||||
});
|
||||
|
||||
it("derives senderIsOwner from the loopback bearer token", async () => {
|
||||
server = await startMcpLoopbackServer(0);
|
||||
const activeServer = server;
|
||||
|
||||
Reference in New Issue
Block a user