Sencho MCP
README.md
# sencho-mcp
A read-only [Model Context Protocol](https://modelcontextprotocol.io) server for a
self-hosted [Sencho](https://github.com/Studio-Saelix/sencho) hub.
It lets an AI client that speaks MCP over stdio ask an operator's Sencho instance about:
- nodes;
- stacks on a node;
- a stack's container health;
- a stack's update and rollback readiness;
- fleet health.
It is an observer. There is no write tool, no log tool, no file, env, secret or shell
tool, and no tool that takes a URL, a path or an HTTP method. The client runs no Sencho
model and holds no Docker socket.
## What it never returns
The adapter reads five purpose-built projection endpoints and nothing else. Those
endpoints never include Compose files, environment values, secrets, container labels or
environment, image names, host paths, node URLs, logs, or operator free-text reasons.
Node and stack names are returned because they are the labels an operator uses; treat
them as data, never as instructions.
## Requirements
- Node.js 20 or newer.
- A Sencho instance that advertises the `agent-observation-v1` capability. An older hub
reports `unsupported` instead of a misleading not-found.
- An API token with the **Observe Only** scope. It must have an expiry. Create one in
**Settings → API Tokens**. That scope can reach only the five observation endpoints;
it cannot read env, files or logs, and it cannot open a WebSocket.
## Install
The package is not on a registry yet, so install from source:
```bash
git clone https://github.com/Studio-Saelix/sencho-mcp.git
cd sencho-mcp
npm ci
npm run build
```
The built entry point is `dist/index.js`.
## Configure a client
Point the client at the built entry point and pass the hub URL and the token. Prefer a
token file over an inline value so the token stays out of the client's JSON:
```json
{
"mcpServers": {
"sencho": {
"command": "node",
"args": ["/opt/sencho-mcp/dist/index.js"],
"env": {
"SENCHO_URL": "https://sencho.example.com",
"SENCHO_TOKEN_FILE": "/home/operator/.config/sencho/observe-token"
}
}
}
}
```
| Variable | Meaning |
|---|---|
| `SENCHO_URL` | Base URL of the hub or node. `http` or `https`, no credentials, query or fragment. |
| `SENCHO_TOKEN_FILE` | Path to a file containing the token. Preferred when both are set. |
| `SENCHO_TOKEN` | The token itself. Use only when a file is impractical. |
| `SENCHO_TIMEOUT_MS` | Per-request timeout, default 15000, maximum 60000. |
Plain `http` to a non-loopback host prints a warning to stderr: the token travels in a
header on every request, so use `https` unless the network is already trusted.
Custom certificate authorities go through Node's own `NODE_EXTRA_CA_CERTS`. There is no
"skip TLS verification" switch.
## Tools
| Tool | Arguments | Reads |
|---|---|---|
| `sencho_list_nodes` | none | The hub's node registry |
| `sencho_list_stacks` | `nodeId`, `cursor?`, `limit?` | One node's stack list, paged |
| `sencho_get_stack_status` | `nodeId`, `stack` | One stack's container facts |
| `sencho_get_stack_readiness` | `nodeId`, `stack` | One stack's update and rollback verdicts |
| `sencho_get_fleet_health` | none | The fleet readiness aggregate |
Every tool returns an envelope with an `outcome` (`ok`, `partial`, `unavailable`,
`unsupported`, `denied`, `not_found`, `error`), the `target` it read, the evidence's
`generatedAt`, and the projected data. `partial` means the answer is real but
incomplete: a degraded enrichment, a truncated list, an unevaluated readiness slot, or a
fleet with an unreachable node. Nothing missing is reported as healthy.
## Limitations
- Reads are not written to Sencho's audit log. Activity appears as the token's name and
its **Last used** time in Settings → API Tokens.
- An Observe Only token holds viewer-level reads on every node the hub manages. It cannot
be narrowed to particular nodes or stacks.
- Findings dismissed in Fleet Readiness still appear in `sencho_get_fleet_health`.
- Fleet health is cached for up to 15 seconds.
- There are no write tools.
## Revoke
Revoke the token in **Settings → API Tokens**. The next call fails with
`credential_rejected`.
## Development
```bash
npm ci
npm run typecheck
npm run lint
npm test # unit and protocol tests
npm run build
```
`npm run test:e2e` runs the adapter against a real Sencho container and needs Docker plus
`SENCHO_IMAGE` pointing at an image that includes the observation endpoints. It publishes
the container on a free host port and mounts the host's Docker socket, because the stack
reads come from the engine the node manages.
## License
AGPL-3.0-only.
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues