-
Notifications
You must be signed in to change notification settings - Fork 30
Open
Labels
bugSomething isn't workingSomething isn't working
Description
What happened?
This library is fantastic, thank you for all the work on it. One minor thing I ran into while testing: when a tool’s JSON Schema uses a union type, running:
php artisan mcp:test-tool tool_name --input='{"param":"value"}'
throws:
ErrorException
Array to string conversion
at vendor/opgginc/laravel-mcp-server/src/Console/Commands/TestMcpToolCommand.php:167
163▕ $type = $propSchema['type'] ?? 'any';
164▕ $description = $propSchema['description'] ?? '';
165▕ $required = in_array($propName, $schema['required'] ?? []) ? '(required)' : '(optional)';
166▕
➜ 167▕ $this->line("{$indent}- {$propName}: {$type} {$required}");
This happens because $type can be an array (e.g., ["integer","null"]) and is interpolated directly into a string.
How to reproduce the bug
Sample failing schema snippet:
"results_size" => [
"description" => "The number of results to return. Defaults to 25.",
"type" => ["integer", "null"],
"minimum" => 0,
"maximum" => 500,
],
Command:
php artisan mcp:test-tool tool_name --input='{"param":"value"}'
Expected behavior
- The schema is printed without errors.
- Union types print cleanly, e.g., integer | null.
- Nested object/array properties are displayed even when type is a union such as ["object","null"] or ["array","null"].
Actual behavior
- Command crashes with “Array to string conversion” at line 167 in TestMcpToolCommand::displaySchema.
Proposed fix
Normalize type for display and separately detect whether the property is (or may be) an object or array. Also handle items.type being an array.
protected function displaySchema(array $schema, string $indent = ''): void
{
if (!isset($schema['properties']) || !is_array($schema['properties'])) {
return;
}
foreach ($schema['properties'] as $propName => $propSchema) {
$typeRaw = $propSchema['type'] ?? 'any';
$description = $propSchema['description'] ?? '';
$required = in_array($propName, $schema['required'] ?? [], true) ? '(required)' : '(optional)';
// Normalize type for display (string) and detection (array)
$typeList = is_array($typeRaw) ? $typeRaw : [$typeRaw];
$typeList = array_values(array_filter($typeList)); // tidy
$typeForDisplay = $typeList ? implode(' | ', $typeList) : 'any';
$this->line("{$indent}- {$propName}: {$typeForDisplay} {$required}");
if ($description) {
$this->line("{$indent} Description: {$description}");
}
// Determine if the schema includes object/array among union types
$isObject = in_array('object', $typeList, true);
$isArray = in_array('array', $typeList, true);
// If this is an object with nested properties
if ($isObject && isset($propSchema['properties']) && is_array($propSchema['properties'])) {
$this->line("{$indent} Properties:");
$this->displaySchema($propSchema, $indent . ' ');
}
// If this is an array with items
if ($isArray && isset($propSchema['items']) && is_array($propSchema['items'])) {
$itemsTypeRaw = $propSchema['items']['type'] ?? 'any';
$itemsTypeList = is_array($itemsTypeRaw) ? $itemsTypeRaw : [$itemsTypeRaw];
$itemsTypeForDisplay = $itemsTypeList ? implode(' | ', $itemsTypeList) : 'any';
$this->line("{$indent} Items: {$itemsTypeForDisplay}");
// Array items might themselves be objects with properties
if (isset($propSchema['items']['properties']) && is_array($propSchema['items']['properties'])) {
$this->line("{$indent} Item Properties:");
$this->displaySchema($propSchema['items'], $indent . ' ');
}
}
}
}Package Version
1.4.2
PHP Version
8.4.11
Laravel Version
11.45.2
Which operating systems does this happen with?
Linux, macOS
Notes
No response
Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't working