Configuration
The Sarek MCP server is a thin, stateless proxy. You can run it yourself, in your
own infrastructure, and point it at the Sarek API. It validates input, forwards
the agent’s Authorization header to Sarek unchanged, masks internal errors, and
reshapes responses into the three tools. It holds no state between requests.
Environment variables
| Variable | Default | Description |
|---|---|---|
SAREK_URL | http://localhost:3000 | Base URL of the Sarek API the server proxies to. |
PORT | 3001 | Port the MCP server listens on. The transport is served at /mcp. |
CORS_ORIGIN | unset (CORS off) | Allowed CORS origin. When unset, CORS is disabled. |
Running with Docker
Set SAREK_URL to wherever your Sarek API is reachable and expose port 3001:
mcp:
build: ./mcp
ports:
- "3001:3001"
environment:
- SAREK_URL=https://api.sarek.technology
depends_on:
- core-serviceAuthentication
Agents authenticate with a Bearer API key in the Authorization header, the same
key the Sarek SDKs use:
Authorization: Bearer YOUR_API_KEYThe server forwards this header to Sarek unchanged and does not validate it
itself. Sarek owns authentication, so an invalid or missing key surfaces as an
UNAUTHORIZED error from the tool call.
Security
- CORS off by default. It is enabled only when
CORS_ORIGINis set, which suits backend-to-backend agents. - Standard security headers are applied to every response.
- 100kb body limit, matching the Sarek API. The tools only ever carry hashes and proofs, so this is generous headroom.
- Header forwarding is restricted. Only
Authorizationandx-request-idare passed upstream; nothing else is forwarded blindly. - Strict schema validation on every tool rejects unknown fields and malformed input before any upstream call.
- Error masking. Internal details never reach the agent. Full errors are
logged internally as structured JSON, with secrets such as the
Authorizationheader redacted.
Error handling
When a tool call fails, the result is returned with isError set and a generic,
agent-safe message. Internal specifics (upstream URLs, stack traces) are never
included. Calls to Sarek time out after 15 seconds.
| Category | Message |
|---|---|
TIMEOUT | The Sarek service did not respond in time. Please try again. |
BAD_REQUEST | The Sarek service rejected the request as invalid. |
UNAUTHORIZED | Authentication failed. Check the API key in the Authorization header. |
FORBIDDEN | Access denied for this operation. |
NOT_FOUND | The requested resource was not found. |
CONFLICT | The resource already exists. |
RATE_LIMITED | Rate limit exceeded. Please wait before retrying. |
UPSTREAM | The Sarek service encountered an internal error. Please try again later. |
UNREACHABLE | Could not reach the Sarek service. |
Validation errors raised before any upstream call carry their own actionable
message instead, such as the hint to hash data locally for sarek_stamp.
Health check
GET /health reports the server’s status and whether the Sarek API is reachable.
It returns 200 when reachable and 503 when not:
{
"status": "ok",
"server": "sarek-mcp-server",
"version": "0.1.0",
"core": "reachable"
}Graceful shutdown
On SIGTERM or SIGINT the server stops accepting new connections and waits for
in-flight calls to drain (around 10 seconds, matching the stamp budget) before
exiting. A stamp in progress at restart is allowed to finish.
Verification
Proofs returned by these tools are independently verifiable, with or without the
MCP server. See Verification for the layered checks and how
to verify a .ldgp proof from the SDK or the CLI.