MCP server for AI agents
A read-only MCP server that lets an AI agent inspect queue health, find jobs and read metrics.
Skyline ships a read-only MCP server, so an AI agent can
answer "why is the emails queue backed up?" or "find the failed ChargeCheckout for checkout
123 and show me the exception" from the same data the dashboard reads — without you pasting screenshots into a chat
window.
Installing it#
The server is built on laravel/mcp, which
Skyline suggests rather than requires: it needs PHP 8.2+ and Laravel 11.45+ or 12.41+, which is a narrower
range than Skyline itself supports. Install it in your application and the server registers itself.
composer require laravel/mcp
Without that package nothing is registered, whatever config/horizon.php says.
The tools#
| Tool | What it returns |
|---|---|
queue-overview |
Whether Horizon is running, jobs per minute, recent and failed counts, and every queue's backlog, wait, processes, time to clear and paused state. |
list-supervisors |
Master supervisors and their pools, with processes per queue, pool options, paused queues and uptime. |
list-jobs |
Jobs in one status — pending, reserved, delayed, completed, failed or silenced — filtered by queue, search phrase or tag, with a cursor for paging. |
get-job |
One job in full: arguments, attempts and limits, timings, earlier attempt failures, the worker that ran it, retries and the exception. |
get-metrics |
Throughput, runtime and running totals per job class or queue, or one class's or queue's snapshot history. |
get-trends |
Backlog, failures and wait per queue over the trends window, plus worker restarts by reason when insights are enabled. |
list-batches / get-batch |
Batches with their progress, searchable by name or id, and a batch's failed jobs. |
Connecting a local agent#
The local server runs over stdio, so it reaches no further than the machine the agent runs on. For Claude Code:
claude mcp add skyline -- php artisan mcp:start skyline
Other clients take the same command. php artisan mcp:inspector skyline opens the MCP Inspector, which is
the quickest way to try the tools yourself before handing them to an agent.
Serving it over HTTP#
To let a remote agent connect, turn on the web server. It is off by default.
HORIZON_MCP_WEB_ENABLED=true
It is served at /horizon/mcp — or {horizon.path}/mcp if you moved the dashboard — on the
dashboard's domain. Every request must pass the viewHorizon gate, exactly like the dashboard. Agents
have no browser session, so list the middleware that authenticates their tokens:
'mcp' => [
'enabled' => env('HORIZON_MCP_ENABLED', true),
'web' => [
'enabled' => env('HORIZON_MCP_WEB_ENABLED', false),
'path' => env('HORIZON_MCP_PATH'), // defaults to "{horizon.path}/mcp"
'domain' => env('HORIZON_MCP_DOMAIN'), // defaults to horizon.domain
'middleware' => ['auth:sanctum'], // or Passport's 'auth:api'
],
'exception_length' => 4000,
],
The middleware runs ahead of the gate check, so the gate then sees the user the token belongs to — allow that user in
viewHorizon as you would a person. Laravel's
MCP authentication docs cover setting up
Sanctum or Passport for MCP clients. See also
Security & access.
exception_length caps how much of a stack trace a tool returns unless the agent asks for the whole
thing.
What it deliberately will not do#
-
It is read-only. No tool retries, stops, deletes or pauses anything. An agent can tell you the
emailsqueue needs draining; it cannot drain it. -
Payloads are never exposed. A job's serialized command holds its real property values, so agents
see only the arguments Skyline stores separately — with
job_arguments.hiddenkeys masked as[hidden]— plus an allowlist of payload metadata (tries, timeout, backoff, tags). - Search and queue filters scan the retention window, like the dashboard's search box. Tags are only indexed for failed jobs and monitored tags.
In the local environment the viewHorizon gate admits everyone, just as it does for the
dashboard. Don't turn the web server on for a machine that is reachable from outside while
APP_ENV=local.
Set HORIZON_MCP_ENABLED=false to register nothing at all, even with laravel/mcp installed.