Value Objects Quick Reference
Quick reference guide for the MCP Client Value Object API.
Core Classes
| Class |
Purpose |
Immutable |
Tool |
Single MCP tool with metadata |
✅ Yes |
ToolBuilder |
Builder for creating/modifying tools |
⚠️ Mutable |
ToolCollection |
Collection of tools |
⚠️ Mutable |
InputSchema |
JSON Schema for tool inputs |
✅ Yes |
LockedDefinition |
Snapshot of locked tool |
✅ Yes |
use Drupal\mcp_client\Entity\McpServer;
$server = McpServer::load('my_server');
$tools = $server->getTools(); // ToolCollectionInterface
$tool = $server->getTool('search_files'); // ?ToolInterface
$exists = $server->hasTool('search_files'); // bool
| Method |
Returns |
Description |
name() |
string |
Tool name |
description() |
string |
Tool description |
enabled() |
bool |
Is enabled? |
locked() |
bool |
Is locked? |
getInputSchema() |
InputSchemaInterface |
Input schema |
getOperation() |
?ToolOperation |
Operation type |
getLockedDefinition() |
?LockedDefinitionInterface |
Locked definition |
toBuilder() |
ToolBuilder |
Create builder from tool |
toArray() |
array |
Export to array |
use Drupal\mcp_client\ValueObject\ToolBuilder;
use Drupal\tool\Tool\ToolOperation;
// ✅ Correct - use builder pattern
$enabled = $tool->toBuilder()
->setEnabled(TRUE)
->build();
// Chain multiple modifications (creates only ONE object)
$modified = $tool->toBuilder()
->setEnabled(TRUE)
->setOperation(ToolOperation::READ)
->setLocked(TRUE)
->build();
// ❌ Wrong - properties are readonly
$tool->enabled = TRUE; // Fatal error!
| Method |
Returns |
Description |
setName($name) |
self |
Set tool name |
setDescription($desc) |
self |
Set description |
setInputSchema($schema) |
self |
Set input schema |
setEnabled($bool) |
self |
Set enabled state |
setLocked($bool) |
self |
Set locked state |
setOperation($op) |
self |
Set operation type |
setLockedDefinition($def) |
self |
Set locked definition |
build() |
Tool |
Build immutable Tool |
Collection Methods
| Method |
Returns |
Description |
get($name) |
?ToolInterface |
Get tool by name |
has($name) |
bool |
Check if exists |
add($tool) |
void |
Add tool |
remove($name) |
void |
Remove tool |
all() |
ToolInterface[] |
Get all as array |
count() |
int |
Count tools |
toArray() |
array |
Export to array |
Common Patterns
use Drupal\mcp_client\ValueObject\ToolCollection;
$tool = $server->getTool('search_files');
$enabled = $tool->toBuilder()
->setEnabled(TRUE)
->build();
$tools = $server->getTools();
$newCollection = new ToolCollection(...$tools->all());
$newCollection->remove('search_files');
$newCollection->add($enabled);
$server->setTools($newCollection);
$server->save();
$tools = array_map(
fn($t) => $t->toBuilder()->setEnabled(TRUE)->build(),
$server->getTools()->all()
);
$server->setTools(new ToolCollection(...$tools));
$server->save();
$tools = $server->getTools();
// Only enabled
$enabled = array_filter($tools->all(), fn($t) => $t->enabled());
// By operation
$reads = array_filter($tools->all(),
fn($t) => $t->getOperation() === ToolOperation::READ
);
use Drupal\mcp_client\ValueObject\LockedDefinition;
$tool = $server->getTool('search_files');
$lockedDef = new LockedDefinition(
$tool->name(),
$tool->description(),
$tool->getInputSchema()
);
$locked = $tool->toBuilder()
->setLocked(TRUE)
->setLockedDefinition($lockedDef)
->build();
// Then update collection and save...
Schema Methods
| Method |
Returns |
Description |
getProperties() |
array |
All properties |
getProperty($name) |
?array |
Single property |
isRequired($name) |
bool |
Is required? |
toArray() |
array |
Export to array |
Inspect Schema
$schema = $tool->getInputSchema();
// Get all properties
foreach ($schema->getProperties() as $name => $def) {
$type = $def['type'];
$required = $schema->isRequired($name);
echo "$name: $type" . ($required ? ' (required)' : '') . "\n";
}
// Check specific property
if ($schema->getProperty('query')) {
echo "Has 'query' parameter\n";
}
use Drupal\mcp_client\ValueObject\{Tool, InputSchema};
$schema = new InputSchema(
type: 'object',
properties: [
'path' => ['type' => 'string', 'description' => 'File path'],
],
required: ['path']
);
$tool = new Tool(
name: 'my_tool',
description: 'My custom tool',
inputSchema: $schema,
enabled: TRUE
);
Import/Export
// Export
$data = $tool->toArray();
$json = json_encode($data);
// Import
$tool = Tool::fromArray(json_decode($json, TRUE));
// Collection
$toolsArray = $server->getTools()->toArray();
$collection = ToolCollection::fromArray($toolsArray);
Type Hints
Always use interfaces:
use Drupal\mcp_client\ValueObject\{
ToolInterface,
ToolCollectionInterface,
InputSchemaInterface,
LockedDefinitionInterface
};
function processTools(ToolCollectionInterface $tools): void {
foreach ($tools as $tool) {
if ($tool instanceof ToolInterface) {
// Work with tool
}
}
}
Best Practices
- ✅ Type hint with interfaces
- ✅ Always save after modifications
- ✅ Check existence before access
- ✅ Batch operations (save once)
- ✅ Use builder pattern for changes
- ✅ Chain builder methods for efficiency
Common Mistakes
// ❌ Modifying in loop and losing changes
foreach ($tools as $tool) {
$tool = $tool->toBuilder()->setEnabled(TRUE)->build(); // Lost!
}
// ✅ Collect modifications
$modified = [];
foreach ($tools as $tool) {
$modified[] = $tool->toBuilder()->setEnabled(TRUE)->build();
}
$server->setTools(new ToolCollection(...$modified));
// ❌ Forgetting to call build()
$tool = $tool->toBuilder()->setEnabled(TRUE); // Returns builder, not Tool!
// ✅ Always call build()
$tool = $tool->toBuilder()->setEnabled(TRUE)->build();
// ❌ Forgetting to save
$server->setTools($newCollection);
// Missing: $server->save();
// ❌ Direct property modification
$tool->enabled = TRUE; // Error!
// ✅ Use builder pattern
$tool = $tool->toBuilder()->setEnabled(TRUE)->build();
Need More Help?