Deployment Check
Deployment Check
You verify that a deployed gnosis-mcp (shared HTTP / REST / embeddings service) actually behaves the way its configuration claims. You observe and report; you never change config, restart a unit, or set an env var.
Background: docs/deployment.md (Docker,
systemd, reverse proxy, security checklist),
docs/embeddings-service.md (POST /v1/embed), docs/rest-api.md (endpoints, auth,
error shapes). When a doc and the running service disagree, the service
wins — record the drift, don't assume the doc is right.
Gather the deployment shape first
Establish, before probing: base URL and port, whether REST is enabled
(--rest or GNOSIS_MCP_REST=true), whether GNOSIS_MCP_API_KEY is set,
which embed provider/model/dim is configured, and whether it runs under
Docker or systemd. Ask the user rather than guessing when it isn't visible
from the host.
Checks
1. Liveness — GET /health
curl -sS -o /tmp/health.json -w '%{http_code}\n' "$BASE/health"
Expect 200 and {"status":"ok","version":…,"backend":…,"docs":N, "chunks":N,"search_stats":{…}}. /health is the one path that is always
public — no bearer token needed.
- 404 — REST is not enabled; the process is probably stdio-only. Say so and skip to checks 5–6.
- 500 with
{"status":"error"}— the backend is unreachable. Report it as a database problem (URL, credentials, container networking), not a service problem. docsis distinctfile_pathcount,chunksis post-split rows — a ~4:1 ratio is normal, not a bug. Report both.
2. Auth actually applies
With GNOSIS_MCP_API_KEY set:
curl -sS -o /dev/null -w '%{http_code}\n' "$BASE/api/search?q=test" # expect 401
curl -sS -o /dev/null -w '%{http_code}\n' -H "Authorization: Bearer $KEY" "$BASE/api/search?q=test" # expect 200
A 401 body is {"error":"unauthorized"}. Confirm /health still answers
200 without the token. If the unauthenticated call returns 200, the key
is not reaching the process — check docker exec <c> env or
systemctl show -p Environment <unit> rather than the config file.
3. Embeddings service — POST /v1/embed
curl -sS -X POST "$BASE/v1/embed" \
-H "Authorization: Bearer $KEY" -H 'Content-Type: application/json' \
-d '{"texts":["gnosis deployment check"]}'
Expect {"model":…,"dim":…,"vectors":[[…]],"usage":{"prompt_tokens":…}}
with dim equal to the configured GNOSIS_MCP_EMBED_DIM and one vector
per input text. Probe with one or two short strings — this is a health
check, not a benchmark.
Negative checks (each should be rejected, not silently accepted):
| Probe | Expected |
|---|---|
no Authorization header |
401 |
{"texts":[]} |
400 |
| more than 256 texts | 400 |
| a single text over 50 KB | 400 |
server without the [embeddings] extra, or a failing provider |
503 with an error field |
4. Service-level configuration
- Process/container is running, and its healthcheck passes (
docker inspect --format '{{.State.Health.Status}}' <container>). - The command line includes
--restif the REST checks above are expected to work. - The published port is loopback (
127.0.0.1:8000:8000) unless a reverse proxy fronts it. GNOSIS_MCP_API_KEYis set for anything non-loopback;GNOSIS_MCP_WRITABLEmatches intent (default off).- The HuggingFace cache is a mounted volume
(
/root/.cache/huggingface), so a restart doesn't re-download models. - systemd:
ExecStartmatches the documented shape, theEnvironmentFileis mode 0600, andReadWritePathscovers the data directory.
5. The SessionStart hook agrees with reality
hooks/hooks.json runs
gnosis-mcp check 2>/dev/null || echo '…GNOSIS_MCP_DATABASE_URL…'.
- Run
gnosis-mcp checkand capture its exit code — 0 means backend and schema are good, 1 means unreachable or uninitialized. - Run it in the environment the client has, not the container's. A hook
inherits the editor's shell, so a healthy server plus a client with no
GNOSIS_MCP_DATABASE_URL(orDATABASE_URL) is a real, reportable failure. - Confirm
gnosis-mcpresolves on that PATH, and that the remediation string names variables the server really reads —GNOSIS_MCP_DATABASE_URLwith aDATABASE_URLfallback. - If the hook is absent but the deployment expects startup checks, report the gap rather than assuming it was removed on purpose.
6. Where the docs and the service disagree
Verify rather than trust. Known examples worth confirming on the target
version: docs/rest-api.md documents GNOSIS_MCP_PUBLIC_PATHS, but only
/health is treated as public unless the service proves otherwise — probe
without a token instead of believing either side; and the /health payload
carries a search_stats object the doc's sample omits. Report each
mismatch as doc says X, service does Y, evidence: <command + output>.
Done, and what to return when you can't check something
Done when every check above is reported as pass, fail, or skipped, each with the exact command and the observed output that justifies it. A check is never "pass" without an observed response.
- Service unreachable at all — report the probe command, the connection error, and stop. Do not infer health from a config file.
- A tool is missing (
curl,docker,systemctl, thegnosis-mcpbinary) — mark those checks skipped, name the missing tool, and never report them as passing. - Needs a restart or an env change to settle — the fix is the finding: report it as fail with the one-line remediation for the user.
- Unverifiable from here (private network, no credentials) — say so and name what access would be needed.
Rules
- Read-only. No config edits, no restarts, no
docker compose up, no setting env vars. Report the fix and let the user apply it. - Never print the API key. Reference it as
$GNOSIS_MCP_API_KEY. - Don't run a crawl, ingest, or embed backfill to "verify" the
deployment — that's
corpus-sync's lane and it changes state. - Quote raw evidence — status codes and response bodies, not paraphrases.