-
Notifications
You must be signed in to change notification settings - Fork 47
Description
Summary
After the null-destructure fix for #469 (shipped in rc266), there is a second crash in _buildNativeTools() when MCP tools are present. MCP tool inputSchema objects (raw JSON Schema) are passed to the Vercel AI SDK without wrapping, causing asSchema() to misidentify them as Zod schemas and crash.
Error
TypeError: Cannot read properties of undefined (reading 'typeName')
at parseDef (dist/index.js:58179)
at zodToJsonSchema (dist/index.js)
at get jsonSchema (dist/index.js)
at Array.map (<anonymous>)
at prepareToolsAndToolChoice (dist/index.js:46751)
at streamStep (dist/index.js)
Wrapped by:
NoOutputGeneratedError [AI_NoOutputGeneratedError]: No output generated. Check the stream for errors.
Steps to Reproduce
- Configure ProbeAgent with any MCP tools (e.g., via SSE or stdio MCP server)
- Update to rc266 (which fixes the null-destructure from Bug: _buildNativeTools crashes with TypeError when MCP tools are present in toolImplementations #469)
- Call
ProbeAgent.answer()with any prompt - Crash occurs before the first AI call, during
prepareToolsAndToolChoice()
Debug output confirms tools load successfully — the crash happens when streamText() processes them:
[DEBUG] All Tools Initialized
[DEBUG] Native tools: 2, MCP tools: 4
[DEBUG] Available tools:
[DEBUG] - analyze_all
[DEBUG] - readImage
[DEBUG] - __tools___slack-send-dm (MCP)
[DEBUG] - __tools___slack-search (MCP)
[DEBUG] - __tools___slack-read-thread (MCP)
[DEBUG] - __tools___slack-download-file (MCP)
Root Cause
In _buildNativeTools(), MCP tools are added to nativeTools as raw objects, not wrapped with tool():
// _buildNativeTools(), line ~354328:
if (this.mcpBridge && !options._disableTools) {
const mcpTools = this.mcpBridge.getVercelTools(
this._filterMcpTools(this.mcpBridge.getToolNames())
);
for (const [name, mcpTool] of Object.entries(mcpTools)) {
nativeTools[name] = mcpTool; // ⚠️ Raw object, not a tool() instance
}
}MCPManager.getVercelTools() returns plain objects with raw JSON Schema:
// MCPManager.getVercelTools():
{
description: tool.description,
inputSchema: tool.inputSchema, // Raw JSON Schema: { type: "object", properties: {...} }
execute: async (args) => { ... }
}When Vercel AI SDK's prepareToolsAndToolChoice() processes these, it calls asSchema(tool.inputSchema):
function asSchema(schema) {
return schema == null
? jsonSchema({ properties: {}, additionalProperties: false })
: isSchema(schema) ? schema // ❌ No — raw JSON Schema lacks schemaSymbol
: typeof schema === "function" ? schema() // ❌ No — it's an object
: zodSchema(schema); // ⬅️ Falls through here!
}isSchema() checks for a schemaSymbol property and validate method — raw JSON Schema objects don't have these. So asSchema() falls through to zodSchema(), which calls zodToJsonSchema() → parseDef() → reads def.typeName → undefined → crash.
Compare with native tools — wrapTool() correctly handles this:
const wrapTool = (toolName, schema, description, executeFn) => {
// ✅ Checks for Zod (_def), otherwise wraps with jsonSchema()
const resolvedSchema = schema && schema._def ? schema : jsonSchema(schema);
return tool({
description,
inputSchema: resolvedSchema,
execute: ...
});
};MCP tools bypass wrapTool() entirely and are added as raw objects without schema wrapping.
Suggested Fix
Wrap MCP tools with tool() and jsonSchema() before adding to nativeTools:
if (this.mcpBridge && !options._disableTools) {
const mcpTools = this.mcpBridge.getVercelTools(
this._filterMcpTools(this.mcpBridge.getToolNames())
);
for (const [name, mcpTool] of Object.entries(mcpTools)) {
nativeTools[name] = tool({
description: mcpTool.description,
inputSchema: jsonSchema(mcpTool.inputSchema),
execute: mcpTool.execute,
});
}
}Or fix at the source in MCPManager.getVercelTools():
getVercelTools() {
const tools = {};
for (const [name, tool] of this.tools.entries()) {
tools[name] = {
description: tool.description,
inputSchema: jsonSchema(tool.inputSchema), // Wrap at source
execute: async (args) => { ... }
};
}
return tools;
}Relationship to #469
This is the second of two bugs introduced by the _buildNativeTools refactor:
| # | Issue | Status | Version |
|---|---|---|---|
| 1 | #469 — _getToolSchemaAndDescription() returns null for MCP tool names → null destructure |
Fixed in rc266 | rc265 |
| 2 | This issue — MCP tools added as raw objects, JSON Schema misidentified as Zod | Open | rc266 |
Both stem from the same root cause: _buildNativeTools doesn't properly handle MCP tools that were injected into toolImplementations during initializeMCP().
Environment
- Probe version: 0.6.0-rc266
- Runtime: Node.js, bundled via ncc
- Trigger: Any
ProbeAgent.answer()call when MCP tools are configured