Skip to content

Commit af3d238

Browse files
author
DDEV User
committed
feat(schema): add top-level title to Tool
Mirror PR modelcontextprotocol#278's Prompt change for Tool: - Add optional ?string $title to Mcp\Schema\Tool between $name and $inputSchema. fromArray() now reads $data['title']; jsonSerialize() emits 'title' right after 'name'. The @phpstan-type ToolData gains title?: string. - Add ?string $title to the #[McpTool] attribute between $name and $description. - Note ToolAnnotations::$title as deprecated-for-display in favor of Tool::$title per MCP spec 2025-06-18 (PHPDoc only, field retained for BC). Phase 1 of plan 01--tool-title-spec-compliance. Later phases update Discoverer, Builder::addTool(), ArrayLoader, and the conformance fixture to match the new signature.
1 parent 7af5a34 commit af3d238

3 files changed

Lines changed: 20 additions & 12 deletions

File tree

src/Capability/Attribute/McpTool.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ class McpTool
2222
{
2323
/**
2424
* @param string|null $name The name of the tool (defaults to the method name)
25+
* @param string|null $title Optional human-readable title for display in UI
2526
* @param string|null $description The description of the tool (defaults to the DocBlock/inferred)
2627
* @param ToolAnnotations|null $annotations Optional annotations describing tool behavior
2728
* @param ?Icon[] $icons Optional list of icon URLs representing the tool
@@ -30,6 +31,7 @@ class McpTool
3031
*/
3132
public function __construct(
3233
public ?string $name = null,
34+
public ?string $title = null,
3335
public ?string $description = null,
3436
public ?ToolAnnotations $annotations = null,
3537
public ?array $icons = null,

src/Schema/Tool.php

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
* }
3434
* @phpstan-type ToolData array{
3535
* name: string,
36+
* title?: string,
3637
* inputSchema: ToolInputSchema,
3738
* description?: string|null,
3839
* annotations?: ToolAnnotationsData,
@@ -47,6 +48,7 @@ class Tool implements \JsonSerializable
4748
{
4849
/**
4950
* @param string $name the name of the tool
51+
* @param ?string $title Optional human-readable title for display in UI
5052
* @param ?string $description A human-readable description of the tool.
5153
* This can be used by clients to improve the LLM's understanding of
5254
* available tools. It can be thought of like a "hint" to the model.
@@ -58,6 +60,7 @@ class Tool implements \JsonSerializable
5860
*/
5961
public function __construct(
6062
public readonly string $name,
63+
public readonly ?string $title,
6164
public readonly array $inputSchema,
6265
public readonly ?string $description,
6366
public readonly ?ToolAnnotations $annotations,
@@ -95,19 +98,21 @@ public static function fromArray(array $data): self
9598
}
9699

97100
return new self(
98-
$data['name'],
99-
$inputSchema,
100-
isset($data['description']) && \is_string($data['description']) ? $data['description'] : null,
101-
isset($data['annotations']) && \is_array($data['annotations']) ? ToolAnnotations::fromArray($data['annotations']) : null,
102-
isset($data['icons']) && \is_array($data['icons']) ? array_map(Icon::fromArray(...), $data['icons']) : null,
103-
isset($data['_meta']) && \is_array($data['_meta']) ? $data['_meta'] : null,
104-
$outputSchema,
101+
name: $data['name'],
102+
title: isset($data['title']) && \is_string($data['title']) ? $data['title'] : null,
103+
inputSchema: $inputSchema,
104+
description: isset($data['description']) && \is_string($data['description']) ? $data['description'] : null,
105+
annotations: isset($data['annotations']) && \is_array($data['annotations']) ? ToolAnnotations::fromArray($data['annotations']) : null,
106+
icons: isset($data['icons']) && \is_array($data['icons']) ? array_map(Icon::fromArray(...), $data['icons']) : null,
107+
meta: isset($data['_meta']) && \is_array($data['_meta']) ? $data['_meta'] : null,
108+
outputSchema: $outputSchema,
105109
);
106110
}
107111

108112
/**
109113
* @return array{
110114
* name: string,
115+
* title?: string,
111116
* inputSchema: ToolInputSchema,
112117
* description?: string,
113118
* annotations?: ToolAnnotations,
@@ -118,10 +123,11 @@ public static function fromArray(array $data): self
118123
*/
119124
public function jsonSerialize(): array
120125
{
121-
$data = [
122-
'name' => $this->name,
123-
'inputSchema' => $this->inputSchema,
124-
];
126+
$data = ['name' => $this->name];
127+
if (null !== $this->title) {
128+
$data['title'] = $this->title;
129+
}
130+
$data['inputSchema'] = $this->inputSchema;
125131
if (null !== $this->description) {
126132
$data['description'] = $this->description;
127133
}

src/Schema/ToolAnnotations.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
class ToolAnnotations implements \JsonSerializable
2929
{
3030
/**
31-
* @param ?string $title a human-readable title for the tool
31+
* @param ?string $title a human-readable title for the tool — deprecated for display in favor of `Mcp\Schema\Tool::$title` per MCP spec revision 2025-06-18; retained for backward compatibility
3232
* @param ?bool $readOnlyHint if true, the tool does not modify its environment
3333
* @param ?bool $destructiveHint If true, the tool may perform destructive updates to its environment. If false, the tool performs only additive updates.
3434
* @param ?bool $idempotentHint If true, calling the tool repeatedly with the same arguments will have no additional effect on the its environment. (This property is meaningful only when `readOnlyHint == false`)

0 commit comments

Comments
 (0)