fix: add missing items property to array-type parameter schemas#83
fix: add missing items property to array-type parameter schemas#83charryshun wants to merge 2 commits intoRootly-AI-Labs:mainfrom
Conversation
VS Code GitHub Copilot Agent Mode strictly validates MCP tool schemas against the JSON Schema spec and rejects any array-typed parameter that lacks an `items` property, producing errors like: Failed to validate tool mcp_rootly-mcp_createEscalationPath: Error: tool parameters array type must have items. Fixes Rootly-AI-Labs#82 Changes: - Add `_ensure_array_items(schema)` to spec_transform.py — a recursive helper that walks any schema dict and fills in `"items": {}` wherever `"type": "array"` appears without a sibling `items` key. Recurses into object properties, array items, allOf/anyOf/oneOf, and additionalProperties. - Call it from `_filter_openapi_spec` as a post-processing pass over every parameter schema and request body schema in the filtered paths, so all 99+ generated tools are covered. - Add tests/unit/test_spec_transform.py with 12 unit tests covering the helper directly and its integration in _filter_openapi_spec. No MCP protocol behaviour, tool functionality, or client compatibility is affected — only the JSON Schema shape of the generated inputSchema. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Greptile SummaryThis PR adds a recursive Confidence Score: 5/5Safe to merge — targeted spec normalization fix with no regressions and good test coverage. All findings are P2 style suggestions (tuple-validation items list and No files require special attention.
|
| Filename | Overview |
|---|---|
| src/rootly_mcp_server/spec_transform.py | Adds _ensure_array_items recursive helper and post-processing pass in _filter_openapi_spec; logic is correct and handles the primary cases well, with minor gaps for tuple-validation items lists and the not keyword. |
| tests/unit/test_spec_transform.py | New test file with 12 unit tests covering bare arrays, existing items, nested objects, array-of-arrays, deep nesting, allOf/anyOf/oneOf, empty schemas, and request body integration — good coverage for the added functionality. |
Prompt To Fix All With AI
This is a comment left during a code review.
Path: src/rootly_mcp_server/spec_transform.py
Line: 568-570
Comment:
**Tuple-validation `items` list not recursed into**
When `items` is a JSON Schema array (tuple validation, e.g. `"items": [{"type": "string"}, {"type": "array"}]`), the current check skips recursion entirely, so any nested array schema inside that list won't receive the `items: {}` fix. This is unlikely in the Rootly spec, but worth a guard:
```suggestion
# Recurse into items (array element schema or tuple-validation list)
if "items" in schema:
if isinstance(schema["items"], dict):
_ensure_array_items(schema["items"])
elif isinstance(schema["items"], list):
for item_schema in schema["items"]:
_ensure_array_items(item_schema)
```
How can I resolve this? If you propose a fix, please make it concise.
---
This is a comment left during a code review.
Path: src/rootly_mcp_server/spec_transform.py
Line: 572-580
Comment:
**`not` keyword not covered**
The `not` keyword (e.g. `"not": {"type": "array"}`) is a valid JSON Schema combinator and could contain an array schema without `items`. Adding it alongside `allOf`/`anyOf`/`oneOf` would make coverage complete:
```suggestion
# Recurse into combination keywords
for keyword in ("allOf", "anyOf", "oneOf"):
for sub in schema.get(keyword, []):
_ensure_array_items(sub)
# Recurse into `not` schema
if_not = schema.get("not")
if isinstance(if_not, dict):
_ensure_array_items(if_not)
# Recurse into additionalProperties if it is a schema dict
additional = schema.get("additionalProperties")
if isinstance(additional, dict):
_ensure_array_items(additional)
```
How can I resolve this? If you propose a fix, please make it concise.Reviews (1): Last reviewed commit: "fix: add missing items property to array..." | Re-trigger Greptile
…ray_items
Address greptile review suggestions:
- Recurse into items when it is a list (JSON Schema tuple validation),
not just when it is a dict, so nested array schemas in positional
item validators also receive the items:{} fix.
- Recurse into the `not` keyword alongside allOf/anyOf/oneOf, covering
the full set of JSON Schema combinators.
Add two matching unit tests.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
Thanks for the review! Both suggestions were valid — applied in 6f1c14c:
Two new unit tests cover these cases ( |
Summary
tool parameters array type must have itemsfor all 99+ generated MCP tools_ensure_array_items(schema)tospec_transform.py— a recursive helper that walks any schema dict and fills in"items": {}wherever"type": "array"appears without a siblingitemskey_filter_openapi_specas a post-processing pass over every parameter schema and request body schema in the filtered pathstests/unit/test_spec_transform.pywith 12 unit testsFixes #82
Why
The JSON Schema spec (and VS Code Copilot Agent Mode's strict validator) require every
"type": "array"node to include an"items"property. The Rootly OpenAPI spec sometimes omits it, causing errors like:Approach
The fix is entirely in the spec normalization layer (
spec_transform.py), applied before FastMCP generates tools — so no MCP protocol behaviour, tool functionality, or client compatibility with Cursor/Claude Code/other clients is affected.Missing
itemsis filled with{}(accepts any element type), which is the minimally-restrictive JSON Schema default.Test plan
tests/unit/test_spec_transform.py— all pass🤖 Generated with Claude Code