Fix MCP tool array params to include required 'items' property
What does this MR do and why?
Fixes MCP tool array params to include required 'items' property
Updated ApiTool to generate valid JSON Schema for array parameters. Added test to ensure all MCP tools comply with JSON Schema spec.
Array needs to have items https://json-schema.org/understanding-json-schema/reference/array#items
The bug is reproducible in Copilot chat and leads to the following error
Failed to validate tool mcp_gitlab-mcp_create_issue: Error: tool parameters array type must have items. Please open a Github issue for the MCP server or extension which provides this tool
References
Related to #578261 (closed)
How to set up and validate locally
From gdk rails c run:
manager = Mcp::Tools::Manager.new
tool = manager.get_tool(name: 'create_issue')
puts JSON.pretty_generate(tool.input_schema)
That returns the tool's schema.
Before
"assignee_ids": {
"type": "array",
"description": "The array of user IDs to assign issue"
}
(full output)
{
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "The ID or URL-encoded path of the project"
},
"title": {
"type": "string",
"description": "The title of an issue"
},
"description": {
"type": "string",
"description": "The description of an issue"
},
"assignee_ids": {
"type": "array",
"description": "The array of user IDs to assign issue"
},
"milestone_id": {
"type": "integer",
"description": "The ID of a milestone to assign issue"
},
"labels": {
"type": "string",
"description": "Comma-separated list of label names"
},
"confidential": {
"type": "boolean",
"description": "Boolean parameter if the issue should be confidential"
},
"epic_id": {
"type": "integer",
"description": "The ID of an epic to associate the issue with"
}
},
"required": [
"id",
"title"
],
"additionalProperties": false
}
After
"assignee_ids": {
"type": "array",
"items": {
"type": "integer"
},
"description": "The array of user IDs to assign issue"
}
(full output)
{
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "The ID or URL-encoded path of the project"
},
"title": {
"type": "string",
"description": "The title of an issue"
},
"description": {
"type": "string",
"description": "The description of an issue"
},
"assignee_ids": {
"type": "array",
"items": {
"type": "integer"
},
"description": "The array of user IDs to assign issue"
},
"milestone_id": {
"type": "integer",
"description": "The ID of a milestone to assign issue"
},
"labels": {
"type": "string",
"description": "Comma-separated list of label names"
},
"confidential": {
"type": "boolean",
"description": "Boolean parameter if the issue should be confidential"
},
"epic_id": {
"type": "integer",
"description": "The ID of an epic to associate the issue with"
}
},
"required": [
"id",
"title"
],
"additionalProperties": false
}
The state of all the other tools
I've also checked other tools we have, and there are no other tools that use an array type.
manager = Mcp::Tools::Manager.new
manager.list_tools.each do |name, tool|
schema = tool.input_schema
array_params = schema[:properties].select do |param_name, param_def|
param_def[:type] == 'array' || param_def[:type].to_s.include?('array')
end
puts "Tool: #{name}"
if array_params.any?
puts " Has array parameters:"
array_params.each do |param_name, param_def|
has_items = param_def.key?(:items)
status = has_items ? "VALID" : "INVALID"
puts " #{status} #{param_name}: #{param_def.inspect}"
end
else
puts " No array params"
end
end
puts
Before
Tool: create_issue
Has array parameters:
INVALID assignee_ids: {:type=>"array", :description=>"The array of user IDs to assign issue"}
(full output)
Tool: get_mcp_server_version
No array params
Tool: get_pipeline_jobs
No array params
Tool: get_issue
No array params
Tool: create_issue
Has array parameters:
INVALID assignee_ids: {:type=>"array", :description=>"The array of user IDs to assign issue"}
Tool: create_merge_request
No array params
Tool: get_merge_request
No array params
Tool: get_merge_request_commits
No array params
Tool: get_merge_request_diffs
No array params
Tool: get_merge_request_pipelines
No array params
Tool: gitlab_search
No array params
Tool: semantic_code_search
No array params
After
Tool: create_issue
Has array parameters:
VALID assignee_ids: {:type=>"array", :items=>{:type=>"integer"}, :description=>"The array of user IDs to assign issue"}
(full output)
Tool: get_mcp_server_version
No array params
Tool: get_pipeline_jobs
No array params
Tool: get_issue
No array params
Tool: create_issue
Has array parameters:
VALID assignee_ids: {:type=>"array", :items=>{:type=>"integer"}, :description=>"The array of user IDs to assign issue"}
Tool: create_merge_request
No array params
Tool: get_merge_request
No array params
Tool: get_merge_request_commits
No array params
Tool: get_merge_request_diffs
No array params
Tool: get_merge_request_pipelines
No array params
Tool: gitlab_search
No array params
Tool: semantic_code_search
No array params
MR acceptance checklist
Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.