SIGNALS Documentation
API Reference

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\ExecuteEndpoint and curated MCP tools (CuratedApiTool)
  • App\Console\Commands\Api\SignalsApiCommand (call action)
  • 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.