-
Notifications
You must be signed in to change notification settings - Fork 4
fix(mcp): MCP schema validation error for array types #485
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| ✅ Deployment successful! View logs |
devcycle-mcp-server | fbd4d61 | Aug 11 2025, 08:45 PM |
|
Fixed the cloudflare build command for PRs to skip deploying and just echo out. needs a rebase |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR fixes MCP (Model Context Protocol) schema validation errors caused by array types missing the required items property. The issue occurred because z.array(z.any()) doesn't generate proper JSON schemas for MCP compatibility.
- Replaces
z.array(z.any())withz.array(z.unknown())in zodClient.ts (6 instances) - Adds comprehensive test suite to validate MCP schema compliance for all 27 tools
- Includes documentation explaining MCP compatibility requirements
Reviewed Changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| src/api/zodClient.ts | Replaces z.array(z.any()) with z.array(z.unknown()) and adds MCP compatibility documentation |
| src/mcp/server.schema.test.ts | Adds comprehensive test suite to validate MCP schema compliance and prevent regressions |
| ) | ||
| } | ||
|
|
||
| if (errors.length > 0) { |
Copilot
AI
Aug 11, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The variable validationErrors is being incremented with individual tool errors, but the final error message states 'Found ${validationErrors.length} tools with invalid schemas' which counts array elements, not tools. This will show an incorrect count since each tool can have multiple errors. Consider tracking the number of invalid tools separately.
| if (errors.length > 0) { | |
| if (errors.length > 0) { | |
| invalidToolCount++ |
| // Create a mock API client | ||
| const mockApiClient = { | ||
| executeWithLogging: sinon.stub(), | ||
| executeWithDashboardLink: sinon.stub(), | ||
| setSelectedProject: sinon.stub(), | ||
| hasProjectKey: sinon.stub().resolves(true), | ||
| getOrgId: sinon.stub().returns('test-org'), | ||
| getUserId: sinon.stub().returns('test-user'), | ||
| hasProjectAccess: sinon.stub().resolves(true), | ||
| getUserContext: sinon.stub().resolves({}), | ||
| } | ||
|
|
Copilot
AI
Aug 11, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The mock API client is duplicated in both test cases (lines 86-96 and implicitly recreated in the second test). Consider extracting this to a helper function or beforeEach block to reduce code duplication.
| // Create a mock API client | |
| const mockApiClient = { | |
| executeWithLogging: sinon.stub(), | |
| executeWithDashboardLink: sinon.stub(), | |
| setSelectedProject: sinon.stub(), | |
| hasProjectKey: sinon.stub().resolves(true), | |
| getOrgId: sinon.stub().returns('test-org'), | |
| getUserId: sinon.stub().returns('test-user'), | |
| hasProjectAccess: sinon.stub().resolves(true), | |
| getUserContext: sinon.stub().resolves({}), | |
| } | |
| // Helper to create a fresh mock API client for each test | |
| function createMockApiClient() { | |
| return { | |
| executeWithLogging: sinon.stub(), | |
| executeWithDashboardLink: sinon.stub(), | |
| setSelectedProject: sinon.stub(), | |
| hasProjectKey: sinon.stub().resolves(true), | |
| getOrgId: sinon.stub().returns('test-org'), | |
| getUserId: sinon.stub().returns('test-user'), | |
| hasProjectAccess: sinon.stub().resolves(true), | |
| getUserContext: sinon.stub().resolves({}), | |
| } | |
| } | |
| let mockApiClient: ReturnType<typeof createMockApiClient> | |
| beforeEach(() => { | |
| mockApiClient = createMockApiClient() | |
| }) |
| `1. Open src/api/zodClient.ts`, | ||
| `2. Search for 'z.array(z.any())'`, | ||
| `3. Replace with 'z.array(z.unknown())'`, | ||
| `4. Also check for 'z.record(z.any())' and replace with 'z.record(z.unknown())'`, |
Copilot
AI
Aug 11, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The error message suggests checking for z.record(z.any()), but the validation function validateSchemaArrays only checks for array types with missing items, not record types. Either add validation for record types or remove this suggestion from the error message.
| `4. Also check for 'z.record(z.any())' and replace with 'z.record(z.unknown())'`, |
* fix: replace z.array(z.any()) with z.array(z.unknown()) for MCP schema compatibility * test: add MCP schema validation tests to prevent array items issues * fix: types in tests
Problem
The MCP server was failing to start with validation errors:
tool parameters array type must have items. This occurred becausez.array(z.any())doesn't generate the requireditemsproperty for MCP JSON schemas.Solution
z.array(z.any())withz.array(z.unknown())inzodClient.ts(6 fixes)Testing
The
z.unknown()type generates proper JSON schemas while maintaining runtime compatibility.