Skip to content

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

Getting Tools

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

Tool Methods

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

Modifying Tools (Builder Pattern)

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!

ToolBuilder Methods

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

Enable a Tool

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();

Enable All Tools

$tools = array_map(
  fn($t) => $t->toBuilder()->setEnabled(TRUE)->build(),
  $server->getTools()->all()
);
$server->setTools(new ToolCollection(...$tools));
$server->save();

Filter Tools

$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
);

Lock a Tool

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";
}

Creating Tools

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

  1. Type hint with interfaces
  2. Always save after modifications
  3. Check existence before access
  4. Batch operations (save once)
  5. Use builder pattern for changes
  6. 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?