fix: normalize MCP tool schemas missing properties field for OpenAI Responses API#58299
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 68e02c9449
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| "type" in schema && | ||
| !("properties" in schema) && | ||
| !Array.isArray(schema.anyOf) && | ||
| !Array.isArray(schema.oneOf) | ||
| ) { |
There was a problem hiding this comment.
Restrict properties injection to object schemas
This branch now adds properties: {} for any schema that merely has a type key, not just type: "object". If a tool declares a scalar/array root schema (for example type: "string"), the function rewrites it to an invalid combination like {"type":"string","properties":{}}, which can cause provider-side schema validation failures. The fix should gate this path on schema.type === "object" (or equivalent) before injecting properties.
Useful? React with 👍 / 👎.
Greptile SummaryThis PR fixes a real crash path where MCP tools with no parameters produce Changes:
Minor note: The condition in Confidence Score: 5/5Safe to merge — the fix directly addresses a confirmed crash and all remaining feedback is a minor style suggestion. The fix is correct and well-targeted. Both normalization paths are covered by tests. The only finding is a P2 inconsistency: No files require special attention beyond the minor guard tightening noted in
|
| Filename | Overview |
|---|---|
| src/agents/pi-tools.schema.ts | Adds a new branch to inject properties: {} for bare { type: "object" } schemas. Logic is correct for real-world MCP tool schemas; the guard could be tightened to schema.type === "object" to match the stricter check used in convertTools. |
| src/agents/openai-ws-message-conversion.ts | Correctly injects properties: {} only for type === "object" schemas missing a properties field; clean and minimal change with no regressions. |
| src/agents/pi-tools.schema.test.ts | Adds 3 well-scoped test cases covering: no-parameter MCP tool injection, preservation of existing properties, and additionalProperties-only schema. All cases are correct. |
| src/agents/openai-ws-stream.test.ts | Adds 2 test cases for convertTools — injection for missing-properties schemas and preservation for schemas that already have properties. Both are correct and align with the production fix. |
Prompt To Fix All With AI
This is a comment left during a code review.
Path: src/agents/pi-tools.schema.ts
Line: 139-150
Comment:
**Missing `type === "object"` guard — inconsistency with `convertTools`**
The sibling fix in `convertTools` explicitly narrows the injection to `params.type === "object"`:
```ts
params.type === "object" && !("properties" in params)
```
The condition added here is broader — it fires for *any* schema that has a `type` field but no `properties` field, including `{ type: "string" }`, `{ type: "array" }`, etc. For those non-object types, injecting `properties: {}` would produce invalid JSON Schema.
In practice all top-level tool schemas coming from MCP are `type: "object"`, so this is unlikely to cause a real-world bug today, but adding the narrower guard keeps the two paths consistent and future-proof:
```suggestion
if (
"type" in schema &&
schema.type === "object" &&
!("properties" in schema) &&
!Array.isArray(schema.anyOf) &&
!Array.isArray(schema.oneOf)
) {
const schemaWithProperties = { ...schema, properties: {} };
return preserveToolMeta({
...tool,
parameters: applyProviderCleaning(schemaWithProperties),
});
}
```
How can I resolve this? If you propose a fix, please make it concise.Reviews (1): Last reviewed commit: "fix: normalize MCP tool schemas missing ..." | Re-trigger Greptile
| if ( | ||
| "type" in schema && | ||
| !("properties" in schema) && | ||
| !Array.isArray(schema.anyOf) && | ||
| !Array.isArray(schema.oneOf) | ||
| ) { | ||
| const schemaWithProperties = { ...schema, properties: {} }; | ||
| return preserveToolMeta({ | ||
| ...tool, | ||
| parameters: applyProviderCleaning(schemaWithProperties), | ||
| }); | ||
| } |
There was a problem hiding this comment.
Missing
type === "object" guard — inconsistency with convertTools
The sibling fix in convertTools explicitly narrows the injection to params.type === "object":
params.type === "object" && !("properties" in params)The condition added here is broader — it fires for any schema that has a type field but no properties field, including { type: "string" }, { type: "array" }, etc. For those non-object types, injecting properties: {} would produce invalid JSON Schema.
In practice all top-level tool schemas coming from MCP are type: "object", so this is unlikely to cause a real-world bug today, but adding the narrower guard keeps the two paths consistent and future-proof:
| if ( | |
| "type" in schema && | |
| !("properties" in schema) && | |
| !Array.isArray(schema.anyOf) && | |
| !Array.isArray(schema.oneOf) | |
| ) { | |
| const schemaWithProperties = { ...schema, properties: {} }; | |
| return preserveToolMeta({ | |
| ...tool, | |
| parameters: applyProviderCleaning(schemaWithProperties), | |
| }); | |
| } | |
| if ( | |
| "type" in schema && | |
| schema.type === "object" && | |
| !("properties" in schema) && | |
| !Array.isArray(schema.anyOf) && | |
| !Array.isArray(schema.oneOf) | |
| ) { | |
| const schemaWithProperties = { ...schema, properties: {} }; | |
| return preserveToolMeta({ | |
| ...tool, | |
| parameters: applyProviderCleaning(schemaWithProperties), | |
| }); | |
| } |
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/agents/pi-tools.schema.ts
Line: 139-150
Comment:
**Missing `type === "object"` guard — inconsistency with `convertTools`**
The sibling fix in `convertTools` explicitly narrows the injection to `params.type === "object"`:
```ts
params.type === "object" && !("properties" in params)
```
The condition added here is broader — it fires for *any* schema that has a `type` field but no `properties` field, including `{ type: "string" }`, `{ type: "array" }`, etc. For those non-object types, injecting `properties: {}` would produce invalid JSON Schema.
In practice all top-level tool schemas coming from MCP are `type: "object"`, so this is unlikely to cause a real-world bug today, but adding the narrower guard keeps the two paths consistent and future-proof:
```suggestion
if (
"type" in schema &&
schema.type === "object" &&
!("properties" in schema) &&
!Array.isArray(schema.anyOf) &&
!Array.isArray(schema.oneOf)
) {
const schemaWithProperties = { ...schema, properties: {} };
return preserveToolMeta({
...tool,
parameters: applyProviderCleaning(schemaWithProperties),
});
}
```
How can I resolve this? If you propose a fix, please make it concise.…esponses API
Tools with no parameters produce { type: "object" } schemas without a
properties field. The OpenAI Responses API rejects these, silently
crashing entire sessions.
Add properties: {} injection in normalizeToolParameters() and
convertTools() to ensure all object-type schemas include a properties
field.
Closes openclaw#58246
68e02c9 to
b69047d
Compare
|
Related work from PRtags group Title: Open PR duplicate: MCP schema properties + auto-reset override self-heal composite
|
Summary
{ type: "object" }schemas without apropertiesfield. The OpenAI Responses API rejects these schemas, silently crashing entire sessions.properties: {}injection innormalizeToolParameters()(pi-tools.schema.ts) andconvertTools()(openai-ws-message-conversion.ts) to ensure all object-type schemas include apropertiesfield.Changes
src/agents/pi-tools.schema.ts: Added branch innormalizeToolParameters()to injectproperties: {}for bare{ type: "object" }schemas before union/variant handling.src/agents/openai-ws-message-conversion.ts: ModifiedconvertTools()to check and normalize parameters before passing to the OpenAI Responses API.src/agents/pi-tools.schema.test.ts: Added 3 test cases for schema normalization.src/agents/openai-ws-stream.test.ts: Added 2 test cases forconvertToolsnormalization.Closes #58246