Skip to content
Developers · Concept Intermediate

MCP server

Give an AI client live, scoped access to a Sluicio cell over the Model Context Protocol — the remote (Streamable HTTP) and local (stdio) transports, scoped viewer service-account tokens, the tool catalogue, and the one tool that writes (a proposal a human must approve).

SLSluicio team 9 min read Updated Jul 2026

A Sluicio cell exposes a Model Context Protocol server, so an AI client — Claude, Cursor, your own agent platform — can answer questions about the cell from live data: which integrations are unhealthy right now?, show me the order-bus system’s members, we paged at 03:10 — what were the traces doing?

It is not a copy of your telemetry handed to a model. Every tool is a call against the same /api/v1 REST surface the UI uses, executed as the caller’s token — so an assistant sees exactly what that token would see in the browser, and nothing more. There is no second source of truth and no MCP-side filtering to keep in step with your access rules.

Three things are worth deciding before you wire it up:

  • Which transport — remote HTTP for a deployed cell, stdio for a client that spawns a local process.
  • Which token, and how tightly scoped — this is the decision that actually bounds what the assistant can read.
  • Whether the assistant may file proposals — the one thing it can do besides read, and even that changes nothing until a human approves it.
Remote — Streamable HTTPLocal — stdio
EndpointPOST https://<your-host>/api/v1/mcpthe cell-mcp binary on the client’s host
Ships withevery deployment — it’s mounted on cell-apibuilt from the app repo
AuthAuthorization: Bearer <token>, or OAuthSLUICIO_TOKEN env var
Use it fordeployed cells, sandboxed clientsclients that spawn a host process

Remote is the recommended path. Because the endpoint is mounted on the API service, it exists wherever cell-api does — the dev docker-compose, the single-host Caddy setup whose /api/* rule already proxies to cell-api, and the Helm chart on the same ingress. No separate service, no extra port, no proxy rule, no TLS certificate. It also works from clients that run sandboxed and cannot reach a local binary or localhost at all.

Add it in your client as a custom / remote MCP connector, pointing at:

https://<your-host>/api/v1/mcp

The cell shows you its own connector URL on Developers → API & MCP, computed from the live origin, so you can copy it rather than assembling it by hand.

To check the endpoint answers before involving a client at all:

Terminal window
curl -sS https://sluicio.example.com/api/v1/mcp \
-H "Authorization: Bearer $SLUICIO_TOKEN" \
-H "Content-Type: application/json" \
-H "MCP-Protocol-Version: 2025-06-18" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

The transport is stateless — no session is created and none is issued, every request carries its own token, and each dispatch stands alone. A cell restart mid-conversation therefore breaks nothing. GET and DELETE answer 405 with a body saying why: there are no sessions to delete, and no server-initiated messages to stream (for push, see below).

For clients that spawn a host process — classic desktop chat clients, Cursor — build the stdio server from an app-repo checkout:

Terminal window
make mcp # builds bin/cell-mcp

Then point the client’s mcpServers block at it. The binary is a thin client: it talks to your cell over the same REST API, so it needs a base URL and a token.

{
"mcpServers": {
"sluicio": {
"command": "/path/to/bin/cell-mcp",
"env": {
"SLUICIO_BASE_URL": "https://sluicio.example.com",
"SLUICIO_TOKEN": "con_sa_…"
}
}
}
}

This is the part that matters. An MCP connection is exactly as broad as the token behind it, so the token is the security boundary.

Authenticate with an ordinary Sluicio Bearer token, and use a scoped viewer service-account token — created under Settings → Service accounts, where you name the account, give it a role, and issue a token (shown once, with an optional expiry). Two independent limits then apply, and they’re the same two Sluicio applies to people:

  • The role caps what it may do. A token’s effective role is the lower of the account’s role and the token’s own access cap, so a read-only cap makes the connection read-only at the API’s own gates — not by convention, and not reversibly by anything the client sends.
  • The account’s group memberships bound what it may see — per signal. A service account joins groups exactly like a user and resolves visibility the same way, including per-signal narrowing. So you can hand an assistant team A’s logs and metrics and nothing else: it won’t see team B’s services in a listing, in a search result, or in a trace.

MCP inherits all of this from the REST API automatically. There is nothing on the MCP side to configure, and no way for a tool to reach past it.

Prefer a service account over a personal access token: it isn’t tied to an employee’s access, an admin manages its lifecycle, and its scope is chosen deliberately rather than inherited from whoever happened to set it up. Tokens are stored hashed and shown once — see the security model.

OAuth is supported for connectors that require it instead of a static token: the cell serves protected-resource and authorization-server discovery metadata, dynamic client registration, an authorize/consent screen, and a token endpoint. The resulting access is scoped identically — the authenticated principal is still an ordinary Sluicio identity.

The catalogue is deliberately small; a short list keeps a model’s tool selection accurate. Every tool declares an output schema and returns structured content alongside its text, so a client knows the shape of an answer before it asks, and every tool carries annotations (readOnlyHint, destructiveHint and friends) so a client can present the read surface as safe — and tell the one writer apart from the rest.

Start with sluicio_cell_brief. One call answers what am I looking at, and is anything wrong?: the org and environment name; counts of integrations, systems and services with how many are unhealthy, erroring or quiet; what is firing right now, worst first, each with its runbook where the rule has one; services carrying traffic that no alert rule watches; and how many proposals are waiting for review. An agent orients in one round trip instead of five.

ToolWhat it returns
sluicio_cell_briefStart here. Org and environment, counts, what’s firing now (worst first, with runbooks), unwatched services, pending proposals
sluicio_list_integrationsIntegrations with rolled-up health
sluicio_get_integrationOne integration, with per-service health
sluicio_list_servicesDiscovered services, health, and service facets
sluicio_list_systemsSystems with rolled-up health
sluicio_get_systemOne system and its member services
sluicio_system_typesThe system-types catalog, each with its docs URL
sluicio_healthWhat’s unhealthy and why — entities grouped with their failing checks
sluicio_errorsThe “in trouble” feed
sluicio_error_reportErrors since a given time, grouped with the causing checks
sluicio_alert_instancesRecent alert-rule firings with state and severity
sluicio_digestThe since-last-visit digest
sluicio_metric_catalogMetric catalog search
sluicio_metric_seriesOne metric’s time series, per service
sluicio_search_tracesTrace search by service, errors-only, or free text
sluicio_get_traceOne trace by id — all its spans
sluicio_search_logsLog search by query, severity, service, integration or attributes
sluicio_usage_reportThe admin usage report — per-signal coverage and storage estimates (admin token only)
sluicio_propose_check_tuningFiles a proposal to retune an alert rule — see below

Results respect the token’s scope everywhere, including search: a log query that would match a service outside the token’s groups simply doesn’t match it.

Everything above reads. The single exception is sluicio_propose_check_tuning, which lets an assistant propose a tuning change to an existing alert rule — its threshold, severity, sustain window, or whether it’s enabled at all.

Proposing changes nothing. The tool files a proposal: a stored, reviewable change request carrying the assistant’s stated reasoning and a before/after diff, which someone with edit rights approves or rejects in the Proposals inbox. Only that approval applies it, through the same code path as an edit made by hand.

Three properties make this safe enough to exist in an otherwise read-only catalogue:

  • A rationale is required. A proposal with no reason isn’t reviewable, so the tool refuses to file one. The reasoning is shown to the reviewer verbatim — “fired 40 times in 24 h, every instance auto-resolved within two minutes” is reviewable; “threshold seems low” is not.
  • The cell snapshots the current values itself rather than trusting the ones the caller reports. If a human edits the rule while a proposal is pending, approval is blocked as drift instead of silently reverting their edit.
  • Proposals expire. An unreviewed proposal lapses after two weeks rather than sitting in the inbox looking actionable, because approving reasoning nobody can still check is worse than losing it.

Every change an assistant makes is recorded in the audit log marked as originating from MCP, so an admin can filter for what did the agents do? The marker is set inside the cell rather than read from a header, so a caller can neither disguise its own writes as an agent’s nor an agent’s as its own.

Rate limits. Token-authenticated callers get a generous per-caller ceiling — 600 requests per minute with a burst of 120, keyed on the service account rather than the individual token, so minting a second token doesn’t buy more budget. It exists to protect the telemetry database from a looping agent, not to ration normal use. A blocked call returns 429 with Retry-After; browser sessions are never limited.

Cross-origin browser calls must carry a Bearer token. A page open in a user’s browser can POST to the endpoint, and the browser will attach their session cookie unasked. Refusing ambient credentials from a foreign origin closes that without an origin allowlist that would lock out legitimate browser-based clients.

Protocol versions. The cell speaks 2025-06-18, and also 2025-03-26 and 2024-11-05. An unknown revision gets a 400 naming what the cell does speak, rather than a silent mismatch later.

MCP is request/response: an agent asks, the cell answers. If you want the cell to tell you when something happens — an alert firing, a new service appearing, a configuration change — don’t poll a tool on a timer. Use event subscriptions or an alert webhook instead: they survive a disconnect where a held connection would not, and they cost the cell nothing while nothing is happening.