Skip to content

Commit ee197a6

Browse files
author
klapaudius
committed
Refactor annotation handling to use ToolAnnotation class
Replaced array-based annotations with the ToolAnnotation class for improved structure and consistency. Updated ToolInterface, implementations, tests, and documentation to align with this change. This enhances clarity and sets a foundation for future extensibility of tool annotations.
1 parent bf94a4f commit ee197a6

File tree

8 files changed

+112
-13
lines changed

8 files changed

+112
-13
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,8 @@ This helps you rapidly develop and debug tools by:
147147
- Displaying formatted results or detailed error information
148148
- Supporting complex input types including objects and arrays
149149

150+
**For deep diving into tools creation please take a look at dedicated documentation [Here](https://github.com/klapaudius/symfony-mcp-server/blob/master/docs/building_tools.md)**
151+
150152
### Visualizing MCP Tools with Inspector
151153

152154
You can also use the Model Context Protocol Inspector to visualize and test your MCP tools:
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
<?php
2+
3+
namespace KLP\KlpMcpServer\Services\ToolService\Annotation;
4+
5+
class ToolAnnotation
6+
{
7+
/**
8+
* @var string A human-readable title for the tool, useful for UI display
9+
*/
10+
private string $title;
11+
12+
/**
13+
* @var bool If true, indicates the tool does not modify its environment
14+
*/
15+
private bool $readOnlyHint;
16+
17+
/**
18+
* @var bool If true, the tool may perform destructive updates (only meaningful when readOnlyHint is false)
19+
*/
20+
private bool $destructiveHint;
21+
22+
/**
23+
* @var bool If true, calling the tool repeatedly with the same arguments has no additional effect (only meaningful when readOnlyHint is false);
24+
*/
25+
private bool $idempotentHint;
26+
27+
/**
28+
* @var bool If true, the tool may interact with an “open world” of external entities;
29+
*/
30+
private bool $openWorldHint;
31+
32+
public function __construct(
33+
?string $title = null,
34+
?bool $readOnlyHint = null,
35+
?bool $destructiveHint = null,
36+
?bool $idempotentHint = null,
37+
?bool $openWorldHint = null
38+
)
39+
{
40+
$this->title = $title ?? '-';
41+
$this->readOnlyHint = $readOnlyHint ?? false;
42+
$this->destructiveHint = $destructiveHint ?? true;
43+
$this->idempotentHint = $idempotentHint ?? false;
44+
$this->openWorldHint = $openWorldHint ?? true;
45+
}
46+
47+
public function getTitle(): string
48+
{
49+
return $this->title;
50+
}
51+
52+
public function isReadOnlyHint(): bool
53+
{
54+
return $this->readOnlyHint;
55+
}
56+
57+
public function setReadOnlyHint(bool $readOnlyHint): void
58+
{
59+
$this->readOnlyHint = $readOnlyHint;
60+
}
61+
62+
public function isDestructiveHint(): bool
63+
{
64+
return $this->destructiveHint;
65+
}
66+
67+
public function isIdempotentHint(): bool
68+
{
69+
return $this->idempotentHint;
70+
}
71+
72+
public function isOpenWorldHint(): bool
73+
{
74+
return $this->openWorldHint;
75+
}
76+
77+
public function toArray(): array
78+
{
79+
return [
80+
'title' => $this->title,
81+
'readOnlyHint' => $this->isReadOnlyHint(),
82+
'destructiveHint' => $this->isDestructiveHint(),
83+
'idempotentHint' => $this->isIdempotentHint(),
84+
'openWorldHint' => $this->isOpenWorldHint(),
85+
];
86+
}
87+
}

src/Services/ToolService/Examples/HelloWorldTool.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace KLP\KlpMcpServer\Services\ToolService\Examples;
44

5+
use KLP\KlpMcpServer\Services\ToolService\Annotation\ToolAnnotation;
56
use KLP\KlpMcpServer\Services\ToolService\ToolInterface;
67

78
class HelloWorldTool implements ToolInterface
@@ -30,9 +31,9 @@ public function getInputSchema(): array
3031
];
3132
}
3233

33-
public function getAnnotations(): array
34+
public function getAnnotations(): ToolAnnotation
3435
{
35-
return [];
36+
return new ToolAnnotation;
3637
}
3738

3839
public function execute(array $arguments): string

src/Services/ToolService/Examples/VersionCheckTool.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace KLP\KlpMcpServer\Services\ToolService\Examples;
44

5+
use KLP\KlpMcpServer\Services\ToolService\Annotation\ToolAnnotation;
56
use KLP\KlpMcpServer\Services\ToolService\ToolInterface;
67
use stdClass;
78
use Symfony\Component\HttpKernel\Kernel;
@@ -27,9 +28,9 @@ public function getInputSchema(): array
2728
];
2829
}
2930

30-
public function getAnnotations(): array
31+
public function getAnnotations(): ToolAnnotation
3132
{
32-
return [];
33+
return new ToolAnnotation;
3334
}
3435

3536
public function execute(array $arguments): string

src/Services/ToolService/ToolInterface.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
namespace KLP\KlpMcpServer\Services\ToolService;
44

5+
use KLP\KlpMcpServer\Services\ToolService\Annotation\ToolAnnotation;
6+
57
interface ToolInterface
68
{
79
/**
@@ -15,7 +17,7 @@ public function getDescription(): string;
1517

1618
public function getInputSchema(): array;
1719

18-
public function getAnnotations(): array;
20+
public function getAnnotations(): ToolAnnotation;
1921

2022
public function execute(array $arguments): mixed;
2123
}

src/Services/ToolService/ToolRepository.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -124,14 +124,12 @@ public function getToolSchemas(): array
124124
'required' => [],
125125
];
126126
}
127-
if (! empty($tool->getAnnotations())) {
128-
$injectArray['annotations'] = $tool->getAnnotations();
129-
}
130127

131128
$schemas[] = [
132129
'name' => $tool->getName(),
133130
'description' => $tool->getDescription(),
134131
'inputSchema' => $tool->getInputSchema(),
132+
'annotations' => $tool->getAnnotations()->toArray(),
135133
...$injectArray,
136134
];
137135
}

src/stubs/tool.stub

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace {{ namespace }};
44

5+
use KLP\KlpMcpServer\Services\ToolService\Annotation\ToolAnnotation;
56
use KLP\KlpMcpServer\Services\ToolService\ToolInterface;
67

78
class {{ className }} implements ToolInterface
@@ -49,11 +50,11 @@ class {{ className }} implements ToolInterface
4950
/**
5051
* Get the tool annotations.
5152
*
52-
* @return array
53+
* @return ToolAnnotation
5354
*/
54-
public function getAnnotations(): array
55+
public function getAnnotations(): ToolAnnotation
5556
{
56-
return [];
57+
return new ToolAnnotation;
5758
}
5859

5960
/**

tests/Services/ToolService/ToolRepositoryTest.php

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace KLP\KlpMcpServer\Tests\Services\ToolService;
44

55
use InvalidArgumentException;
6+
use KLP\KlpMcpServer\Services\ToolService\Annotation\ToolAnnotation;
67
use KLP\KlpMcpServer\Services\ToolService\ToolInterface;
78
use KLP\KlpMcpServer\Services\ToolService\ToolRepository;
89
use PHPUnit\Framework\Attributes\Small;
@@ -235,7 +236,7 @@ public function test_get_tool_schemas_includes_annotations_if_present(): void
235236
$tool->method('getName')->willReturn('toolWithAnnotations');
236237
$tool->method('getDescription')->willReturn('Tool with annotations');
237238
$tool->method('getInputSchema')->willReturn(['type' => 'object']);
238-
$tool->method('getAnnotations')->willReturn(['tag' => 'example', 'version' => '1.0']);
239+
$tool->method('getAnnotations')->willReturn(new ToolAnnotation);
239240

240241
$this->toolRepository->register($tool);
241242

@@ -245,6 +246,12 @@ public function test_get_tool_schemas_includes_annotations_if_present(): void
245246
$this->assertSame('toolWithAnnotations', $schemas[0]['name']);
246247
$this->assertSame('Tool with annotations', $schemas[0]['description']);
247248
$this->assertSame(['type' => 'object'], $schemas[0]['inputSchema']);
248-
$this->assertSame(['tag' => 'example', 'version' => '1.0'], $schemas[0]['annotations']);
249+
$this->assertSame([
250+
'title' => '-',
251+
'readOnlyHint' => false,
252+
'destructiveHint' => true,
253+
'idempotentHint' => false,
254+
'openWorldHint' => true
255+
], $schemas[0]['annotations']);
249256
}
250257
}

0 commit comments

Comments
 (0)