API documentation

The trust status of an MCP server, by its URL — over REST, or speaking MCP directly with your agent. Enough to drop into a pipeline, your own gateway, or any system that needs to decide who to trust without opening a dashboard by hand.

This is the integration reference. If you're looking for what we watch for and how we detect it, that explanation lives in How Centinela works.

Authentication

Every request carries your key in the X-API-Key header. Get one from your account → API keys — it's shown only once when you create it, copy it then.

curl "https://centinela.llimalabs.com/api/v1/status?url=https://example.com/mcp" \
  -H "X-API-Key: cnt_your_key_here"

Without the header, or with an invalid/revoked key, the request returns 401.

GET /api/v1/status

Returns the trust status of a specific MCP server — one you actually watch (you have an active subscription), from the public catalog or your own private one. Being in the public catalog isn't enough on its own: you need to subscribe first from your dashboard, same as your plan's server limit requires.

Parameters

NameTypeDescription
urlquery, requiredThe exact URL of a server you watch — from the public catalog (subscribed) or your own private one, matching the URL you registered when subscribing.

Response

{
  "url": "https://example.com/mcp",
  "in_catalog": true,
  "status": "sano",
  "findings_count": 0,
  "worst_severity": ""
}
FieldMeaning
statussano (healthy), revisar (needs review), peligroso (dangerous), auth (auth required), no_responde (unreachable), or sin_revisar (not scanned yet).
in_catalogtrue if it's from the public catalog, false if it's your own private server.
findings_countFindings from the most recent scan only.
worst_severitylow, medium, high, or empty if there are none.

Local CLI (servers without a URL)

If you use an MCP server that only runs on your own machine — configured with command + args in your AI client, no URL at all — Centinela can't reach it on its own: there's no network address to connect to. The local CLI (centinela-agent) solves exactly that: it installs on your machine, finds those servers, launches them the same way your AI client already does, and sends the result to your account — same dashboard, same alerts, same analysis as any other server.

Supported clients

Automatically detects servers configured in Claude Desktop, Claude Code, Cursor, Windsurf, Cline, OpenCode, and Codex CLI.

Installation

Download the binary for your system and make it executable:

curl -Lo centinela-agent https://centinela.llimalabs.com/downloads/centinela-agent-linux-amd64
chmod +x centinela-agent
SystemFile
macOS (Apple Silicon)centinela-agent-darwin-arm64
macOS (Intel)centinela-agent-darwin-amd64
Linux (x86_64)centinela-agent-linux-amd64
Linux (ARM64)centinela-agent-linux-arm64
Windows (x86_64)centinela-agent-windows-amd64.exe

Usage

./centinela-agent login cnt_your_key_here
./centinela-agent scan

login saves your API key (the same one you already use for the rest of this API, see Authentication above) to ~/.centinela/config.json. If you'd rather not keep it on disk (in a CI pipeline, say), export CENTINELA_API_KEY before scan and skip login entirely.

scan looks through each supported client's config, launches every server it finds, asks it for its tool list, and sends that to your account. Along the way, if it recognizes the server as coming from an npm package (npx/npm) or a PyPI one (uvx/pipx/python -m), it also cross-checks that package identity against known vulnerabilities — if it can't tell (a custom binary, Docker...), it still scans, just without that extra signal.

The CLI's own console output is currently only in Spanish (as shown below) — the findings themselves are already available in both languages on your dashboard.

Encontrados 2 servidor(es) MCP local(es).

→ claude-desktop · filesystem (npx)... 6 herramienta(s), sin hallazgos
→ cursor · git (uvx)... 4 herramienta(s), 1 hallazgo(s)

Listo. Revisa el detalle en https://centinela.llimalabs.com/dashboard

Each local server shows up on your dashboard just like one with its own URL, labeled 🖥️ Local server · [client] instead of an address, so it stands out at a glance. Running scan again re-scans the same servers without duplicating rows — handy to run by hand after touching your AI client's config, or to drop into your own cron.

Errors

CodeReason
400Missing the url parameter.
401Missing the X-API-Key header, or the key is invalid/revoked.
404You don't watch any server with that URL — you need to subscribe first, even if it's in the public catalog. Never returns data for someone else's private server, even if you know its exact URL.
429Your plan's monthly limit was reached — counted across all your keys.

Plan limits

API requests per month, summed across all your keys — not per individual key.

PlanRequests/month
Free100
Starter500
Pro2,000
BusinessUnlimited

You can see your own usage this month and each key's history from your account.

MCP server

Centinela is also, itself, an MCP server: if you're working with an agent that speaks that protocol, you can give it direct access to check_server_trust instead of it calling the API over HTTP by hand. Useful when the agent itself will decide, on the fly, whether to use another MCP server you've just pointed it at.

Available on paid plans (Starter, Pro, and Business) — on the Free plan, the tool responds with an error explaining that you need to upgrade. The REST API (GET /api/v1/status) stays available on Free, with its own monthly limit.

The endpoint is https://centinela.llimalabs.com/mcp (streamable-HTTP transport), and requires the same X-API-Key header as the rest of the API — the same key you already created, nothing new to generate.

{
  "mcpServers": {
    "centinela": {
      "url": "https://centinela.llimalabs.com/mcp",
      "headers": { "X-API-Key": "cnt_your_key_here" }
    }
  }
}

Tool: check_server_trust

Takes the URL of an MCP server and returns its trust status — same as GET /api/v1/status, with the same restriction: it only works for servers you already watch from your account, not any random URL.

FieldDescription
urlInput, required. The exact URL of the server to check.
statusOutput. Same values as the REST API.
findings_count / worst_severityOutput. Findings from the most recent scan.

Without a subscription to the queried server, the tool returns an error visible to the agent (not a silent failure) explaining that you need to subscribe first. Counts toward your plan's same monthly limit as the REST API.

Webhooks

A POST to your own URL the moment a new finding (medium or high severity) shows up on a server you watch — to feed into Slack, PagerDuty, or your own system, without relying on email. It fires under the same criteria email already uses, so you'll never get a double alert for the exact same finding across both channels and then nothing else.

Available on paid plans (Starter, Pro, and Business). Managed from your account → Webhooks — the signing secret is shown only once, when you create it.

Request body

{
  "event": "findings.new",
  "server_id": 42,
  "server_name": "example-mcp",
  "generated_at": "2026-08-25T18:00:00Z",
  "findings": [
    { "category": "hidden_unicode", "severity": "high", "tool_name": "search", "description": "..." }
  ]
}

Verifying the signature

Every request carries the X-Centinela-Signature header: sha256= followed by the HMAC-SHA256 of the raw body, in hexadecimal, keyed with your secret — same mechanism Stripe uses with us, in reverse: here, we're the one signing. Recompute the HMAC of the received body and compare it to the header before trusting the request.

No automatic retries if your URL fails or times out — every attempt (success, error code, or no response) is logged in your account's delivery history so you can diagnose your own receiver. Email keeps working as a backup, so a down webhook never leaves you without alerts.