diff --git a/README.md b/README.md
index 76bc0637ee..98bfb68f7e 100644
--- a/README.md
+++ b/README.md
@@ -10,7 +10,7 @@ Instead of using one model for everything, Codebuff coordinates specialized agen
-Codebuff beats Claude Code at 61% vs 53% on [our evals](evals/README.md) across 175+ coding tasks over multiple open-source repos that simulate real-world tasks.
+Codebuff beats Claude Code at 61% vs 53% on [our evals](evals/buffbench/README.md) across 175+ coding tasks over multiple open-source repos that simulate real-world tasks.
## Freebuff: the free coding agent
diff --git a/packages/agent-runtime/src/__tests__/prompts-schema-handling.test.ts b/packages/agent-runtime/src/__tests__/prompts-schema-handling.test.ts
index 6d371bf59e..429f5005a9 100644
--- a/packages/agent-runtime/src/__tests__/prompts-schema-handling.test.ts
+++ b/packages/agent-runtime/src/__tests__/prompts-schema-handling.test.ts
@@ -247,6 +247,43 @@ describe('Schema handling error recovery', () => {
expect(toolSet['problematic_tool']).toBeDefined()
})
+ test('getToolSet preserves MCP JSON Schema properties', async () => {
+ const customToolDefs = {
+ marionette__connect: {
+ description: 'Connect to the VM service',
+ inputSchema: {
+ type: 'object',
+ properties: {
+ uri: {
+ type: 'string',
+ description: 'VM service URI',
+ },
+ },
+ required: ['uri'],
+ additionalProperties: false,
+ },
+ endsAgentStep: true,
+ },
+ }
+
+ const toolSet = await getToolSet({
+ toolNames: [],
+ additionalToolDefinitions: async () => customToolDefs,
+ agentTools: {},
+ skills: {},
+ })
+
+ const inputSchema = toolSet['marionette__connect']?.inputSchema as {
+ properties?: Record
+ }
+
+ expect(inputSchema).toBeDefined()
+ expect(inputSchema.properties).toBeDefined()
+ expect(inputSchema.properties?.uri).toEqual(
+ expect.objectContaining({ type: 'string' }),
+ )
+ })
+
test('ensureZodSchema converts JSON Schema to Zod schema', () => {
const jsonSchema = {
type: 'object',
diff --git a/packages/agent-runtime/src/tools/prompts.ts b/packages/agent-runtime/src/tools/prompts.ts
index c87aaf875d..8f54f14533 100644
--- a/packages/agent-runtime/src/tools/prompts.ts
+++ b/packages/agent-runtime/src/tools/prompts.ts
@@ -392,13 +392,14 @@ export async function getToolSet(params: {
const toolDefinitions = await additionalToolDefinitions()
for (const [toolName, toolDefinition] of Object.entries(toolDefinitions)) {
const clonedDef = cloneDeep(toolDefinition)
- // Custom tool inputSchema may be JSON Schema (from SDK) or Zod (from MCP)
- // Ensure it's a Zod schema for the AI SDK
- const zodSchema = ensureZodSchema(clonedDef.inputSchema)
- const safeSchema = ensureJsonSchemaCompatible(zodSchema)
+ // Custom tool inputSchema may be JSON Schema (from SDK) or Zod (from MCP).
+ // Keep the original schema object on the tool definition so nested JSON
+ // Schema details like `properties` survive registration unchanged. Use a
+ // Zod conversion only for description generation.
+ ensureZodSchema(clonedDef.inputSchema)
toolSet[toolName] = {
...clonedDef,
- inputSchema: safeSchema,
+ inputSchema: cloneDeep(clonedDef.inputSchema),
} as (typeof toolSet)[string]
}