Operation Invoker
Shared in-process HTTP-kernel transport for invoking v1 API operations from MCP, the Artisan CLI, and the API Explorer.
Overview
App\Services\Api\OperationInvoker executes a v1 API operation in-process through Laravel's full HTTP kernel. MCP meta-tools, curated tools, signals:api call, and the web API Explorer all share this transport so they mirror an external Sanctum client: the same middleware stack (auth, throttling, metering, idempotency, logging) and the same ability/permission checks.
It is not a registration registry — there is no register() catalogue. The invoker is a singleton-friendly service that turns a catalogue method/URI (plus auth credentials) into an OperationInvocationResult.
Public surface
| Method | Purpose |
|---|---|
invoke() |
Run one API call and return status, headers, decoded body, and duration |
Accepted invocation shape
$result = app(OperationInvoker::class)->invoke(
auth: $plainTextToken, // string|NewAccessToken|PersonalAccessToken|User
method: 'GET',
uri: '/api/v1/catalogue_items/{catalogue_item}',
pathParams: ['catalogue_item' => 42],
query: ['per_page' => 10],
body: [], // JSON-encoded for non-GET when non-empty
idempotencyKey: null, // optional Idempotency-Key header
headers: [], // Authorization is always overwritten
);
Auth credentials may be:
| Type | Behaviour |
|---|---|
| Plain-text bearer string | Used as-is |
NewAccessToken |
Uses its plain-text value |
PersonalAccessToken |
Mints a short-lived sibling token with the same abilities, deleted after the call (Explorer metering attribution) |
User |
Mints a short-lived wildcard (*) token, deleted after the call |
Result shape
OperationInvocationResult is a readonly value object:
| Property / method | Meaning |
|---|---|
status |
HTTP status code |
headers |
Multi-value response headers |
body |
Decoded JSON, raw string, or null when empty |
durationMs |
Wall-clock duration |
successful() |
true when status is 2xx |
json() |
Body when it is an array, otherwise null |
Consumers
App\Mcp\Tools\ExecuteEndpointand curated MCP tools (CuratedApiTool)App\Console\Commands\Api\SignalsApiCommand(callaction)App\Actions\Api\ExecuteExplorerRequest(API Console Explorer)
Worked example
$token = $user->createToken('cli', ['catalogue-items:read'])->plainTextToken;
$result = app(OperationInvoker::class)->invoke(
auth: $token,
method: 'GET',
uri: '/api/v1/catalogue_items',
query: ['per_page' => 5],
);
$result->successful(); // true on 2xx
$result->json()['catalogue_items'] ?? [];
Missing abilities or gate permissions surface as ordinary HTTP 403 responses in the result — the invoker does not throw for API-level authorization failures.