McpClientService
The model's tool calls: {@see GatedToolCalls} shaped for {@see AgentOrchestrator}. Gate, registry and recorder live in milpa/tool-runtime — a model is ONE caller of tools, a governed door is another, and both ask the same question before each call (greenhouse decisions/0225). What this class adds is the model's own concern: the {@see OptionTable}, which takes options off the catalogue and marks a refusal that names one of them.
McpClientService::__construct()
public function __construct(Milpa\ToolRuntime\ToolRegistry $internalRegistry, ?Milpa\ToolRuntime\Gate\ToolCallGate $gate = null, ?Milpa\ToolRuntime\Gate\ToolCallRecorder $recorder = null, ?Milpa\AiGateway\OptionTable $table = null):Parameters
| Name | Type | Description |
|---|---|---|
| $internalRegistry | Milpa\ToolRuntime\ToolRegistry | |
| $gate | (GateContract | null) | consulted before every call; may refuse it. Without a gate the loop runs as it ran: the absence of a policy cannot be a new policy |
| $recorder | (RecorderContract | null) | told after, with what the tool answered |
| $table | (OptionTable | null) | which options are still on the table. Without one the catalogue is the whole registry, which is how it ran before |
McpClientService::callTool()
public function callTool(string $name, array $args): ?mixedThe refusal leaves this class under this package's name. Consumers released against it catch {@see ToolCallRefusedException}; a catch of the base {@see ToolCallRefused} (greenhouse decisions/0225) catches this too. Message and `optionRemoved` travel unchanged — a governed pause must not turn into a plain step failure because the class moved.
Parameters
| Name | Type | Description |
|---|---|---|
| $name | string | |
| $args | array<string, mixed> |