Skip to content

Setup

This guide covers setting up the Authentic8 MCP server in both local (stdio) and remote (HTTP) modes.

Prerequisites

  • Python 3.11 or higher
  • Silo SDK (silo-sdk) installed
  • Valid Authentic8 API tokens

For remote (HTTP) deployment, you'll also need:

  • Docker and Docker Compose
  • Reverse proxy for TLS termination (nginx, Traefik, Caddy)

Installation

Access required

The SDK source is distributed under access control. The release download below resolves only for accounts that have been granted access — if yours has not, it will return "not found" rather than a permission error. Contact your Authentic8 account team to request access.

# Download and extract the latest release
wget https://github.com/salesengr/silo-sdk-python/archive/refs/tags/v0.14.1.zip
unzip v0.14.1.zip
cd silo-sdk-python-0.14.1

# Create virtual environment
python3 -m venv .venv
source .venv/bin/activate  # Windows: .venv\Scripts\activate

# Install with MCP support
pip install -e ".[mcp-server]"

From Git Clone

# Clone the repository
git clone https://github.com/salesengr/silo-sdk-python.git
cd silo-sdk-python

# Create virtual environment
python3 -m venv .venv
source .venv/bin/activate  # Windows: .venv\Scripts\activate

# Install with MCP support
pip install -e ".[mcp-server]"

The [mcp-server] extra includes the MCP SDK, FastAPI, uvicorn, and all required dependencies.

Clone Repository

git clone https://github.com/salesengr/silo-sdk-python.git
cd silo-sdk-python

Build Docker Image

docker build -f Dockerfile.mcp -t a8-mcp-server .

Upgrading from 0.13.x

Version 0.14.0 renamed the Python package from silo_mcp to silo_sdk_mcp, so that it matches the silo-sdk distribution and the silo-sdk-mcp command. There is no compatibility shim. A plain git pull leaves an existing checkout in a broken state until you do two things.

1. Reinstall.

pip install -e ".[mcp-server]"

The silo-sdk-mcp console script and — for editable installs — the generated import finder both record the module path when you install, and neither updates on git pull. Until you reinstall, the console script fails with ModuleNotFoundError: No module named 'silo_mcp'.

python -m silo_sdk_mcp will appear to work before you reinstall

Run from the repository root, it picks the package up from the current directory rather than the installed one. That masks the problem — your MCP client invokes the console script, which is still broken. Reinstall rather than relying on it.

2. Move your credentials file (HTTP transports only).

mv silo_mcp/credentials.yaml silo_sdk_mcp/credentials.yaml
rmdir silo_mcp

credentials.yaml is deliberately untracked, so pulling removes the tracked files around it and leaves your file behind in an orphaned silo_mcp/ directory. Move it before starting Compose, and remove the leftover directory — it holds live API tokens.

A missed move fails confusingly, not loudly

Docker creates a bind mount's host path as an empty directory when it does not exist, rather than refusing to start. The container comes up and then dies trying to parse a directory as YAML.

Also update any MCP client configuration and any logging configuration:

Was Now
python -m silo_mcp python -m silo_sdk_mcp
from silo_mcp… import … from silo_sdk_mcp… import …
/app/silo_mcp/credentials.yaml /app/silo_sdk_mcp/credentials.yaml
Logger name silo_mcp Logger name silo_sdk_mcp

The logger rename is silent — downstream log filtering keyed on the old name simply stops matching, with no error.

Tool names are unchanged: all 73 tools keep their a8_ prefix.

Configuration

Configure Credentials

Create a .env file in the project root with your API tokens:

# Copy the example file
cp .env.example .env

# Edit .env with your actual tokens

Your .env should contain:

A8_ADMIN_TOKEN=your-admin-token-here
A8_SYNC_TOKEN=your-sync-token-here
A8_FILE_TOKEN=your-file-token-here
A8_LOG_TOKEN=your-log-token-here
A8_SCRAPE_TOKEN=your-scrape-token-here
A8_BUCKET_ID=your-bucket-id-here
A8_TOP_ORG=your-org-name-here        # top-level org name used in API calls

Warning

Never commit .env to version control. It's gitignored by default.

Test the Server

Verify the server starts and all tools are registered:

silo-sdk-mcp --list-tools

You should see output listing all 73 tools:

Authentic8 MCP Server - 73 tools
==================================================

Browsing Isolation (6 tools)
  a8_create_context
  a8_get_context
  ...

When to Use HTTP Mode

Choose an HTTP transport when:

  • Multiple users need to reach a server they do not run locally
  • You want centralized deployment behind a reverse proxy
  • You need monitoring and logging at the infrastructure level

For individual use, stdio mode is simpler.

Architecture

A server instance serves exactly one set of Authentic8 credentials. Multiple users are supported by running one instance per credential set and letting the proxy route each Bearer token to its own instance:

flowchart TD
    A["<b>Claude Code</b><br/>(User A)"]
    B["<b>Claude Desktop</b><br/>(User B)"]

    P["<b>Reverse Proxy</b><br/>nginx · Traefik · Caddy<br/><i>TLS termination · routes by Bearer token</i>"]

    MA["<b>MCP Server</b> — instance A<br/>Port 8080<br/>━━━━━━━━━━━━━━━━━━━━<br/><b>credentials.yaml</b><br/><code>client-key-A</code> → A8_ADMIN_TOKEN, …"]
    MB["<b>MCP Server</b> — instance B<br/>Port 8081<br/>━━━━━━━━━━━━━━━━━━━━<br/><b>credentials.yaml</b><br/><code>client-key-B</code> → A8_ADMIN_TOKEN, …"]

    A -->|"Bearer: client-key-A"| P
    B -->|"Bearer: client-key-B"| P
    P --> MA
    P --> MB

    style A fill:#e8f4fd,stroke:#1976d2,color:#0d1117
    style B fill:#e8f4fd,stroke:#1976d2,color:#0d1117
    style P fill:#f3e5f5,stroke:#7b1fa2,color:#0d1117
    style MA fill:#fff8e1,stroke:#f57c00,color:#0d1117
    style MB fill:#fff8e1,stroke:#f57c00,color:#0d1117

One Client Per Instance

A credentials file with more than one client will not start

The server refuses to start if credentials.yaml contains more than one entry under clients: — it logs the count and exits with status 1 rather than picking one and silently serving another client's tokens. Give each instance a credentials file holding exactly one client.

Bearer token validation is enforced on every request: a token that does not match that instance's client key is rejected with 401 Unauthorized before any tool runs.

For multiple clients, deploy one server instance per client behind a proxy (e.g., nginx, Traefik) that routes each Bearer token to its own process. See Scaling for the pattern.

Configure Credentials

Create silo_sdk_mcp/credentials.yaml with this instance's client credentials. The template ships inside the installed package, so copy it from there:

cp silo_sdk_mcp/credentials.yaml.example silo_sdk_mcp/credentials.yaml

Edit silo_sdk_mcp/credentials.yaml:

clients:
  "client-key-alice":
    ADMIN_TOKEN: "${ALICE_ADMIN_TOKEN}"
    SYNC_TOKEN: "${ALICE_SYNC_TOKEN}"
    FILE_TOKEN: "${ALICE_FILE_TOKEN}"
    LOG_TOKEN: "${ALICE_LOG_TOKEN}"
    SCRAPE_TOKEN: "${ALICE_SCRAPE_TOKEN}"
    BUCKET_ID: "${ALICE_BUCKET_ID}"
    API_URL: "https://extapi.authentic8.com"

A second client belongs in a second file, served by a second instance — not as a second entry here.

Client keys are arbitrary strings you generate. Clients provide them via Authorization: Bearer <key>.

Environment variables are substituted at runtime using ${VAR} or ${VAR:-default} syntax.

Warning

Never commit credentials.yaml with real tokens. It's gitignored by default.

Set Environment Variables

Create a .env.http file for the HTTP transport's environment variables:

# Alice's credentials — this instance's client
ALICE_ADMIN_TOKEN=actual-token-here
ALICE_SYNC_TOKEN=actual-token-here
ALICE_FILE_TOKEN=actual-token-here
ALICE_LOG_TOKEN=actual-token-here
ALICE_SCRAPE_TOKEN=actual-token-here
ALICE_BUCKET_ID=actual-bucket-id

Note

Add .env.http to .gitignore if using a custom name.

How Credentials Flow into the Container

The container has no .env file

The Docker image does not include your .env.http or any credential file — they are gitignored and never copied into the build context.

Credentials reach the container in two steps:

  1. credentials.yaml is volume-mounted into the container (read-only). It maps each client Bearer token to a set of ${VAR} references.
  2. The actual token values are injected as environment variables via --env-file or env_file: in Docker Compose. The MCP server resolves ${VAR} references in credentials.yaml against the container's environment at startup.

Without both steps, the server starts but ${VAR} placeholders remain unresolved and API calls will fail with authentication errors.

Local File Access

a8_upload_file and a8_download_file are the only tools that touch the host filesystem, and they are confined to the directories named by MCP_FILE_ROOT. This applies to every transport.

# A single root
export MCP_FILE_ROOT=/srv/silo-mcp/files

# Or a PATH-style list — a read directory and a write directory
export MCP_FILE_ROOT=/srv/silo-mcp/inbox:/srv/silo-mcp/outbox

The list separator is the platform's PATH separator: : on macOS and Linux, ; on Windows.

$env:MCP_FILE_ROOT = "C:\silo-mcp\inbox;C:\silo-mcp\outbox"
Behavior Detail
Default A silo_sdk_mcp_files directory under the system temporary directory, created on demand
Missing directory Created at startup of the first file operation; a path that exists but is not a directory is an error
Relative paths Anchored to the first root, not to the server's working directory
Symlinks Resolved before the check, so a link inside a root cannot point outside one
Violation The tool returns an error naming the permitted roots; nothing is read or written

This is a security boundary, not a convenience default

An upload reads a local file and sends its contents to the storage API, and the path is chosen by a model that routinely reads untrusted web content — the very content this SDK exists to fetch. Text on a fetched page can talk a model into naming a path the operator never intended. Point MCP_FILE_ROOT at the narrowest directory your workflow actually needs, and do not set it to a home directory, a repository root, or /.

Upgrading from 0.13.x

Earlier releases placed no restriction on these paths. If a workflow moves files through a specific directory, set MCP_FILE_ROOT to it before upgrading, or those calls will start failing.

Client Configuration

Claude Desktop

Pattern 1: CLI Entry Point (Recommended)

After installing with pip install -e ".[mcp-server]", the silo-sdk-mcp command is available directly in the virtual environment. The SDK loads .env automatically via python-dotenv, so no wrapper script is needed.

Ensure .env exists:

cp .env.example .env
# Edit .env with your actual API tokens

macOS/Linux:

Add to ~/Library/Application Support/Claude/claude_desktop_config.json:

{
  "mcpServers": {
    "silo-sdk-mcp": {
      "command": "/absolute/path/to/silo-sdk-python/.venv/bin/silo-sdk-mcp",
      "args": [],
      "cwd": "/absolute/path/to/silo-sdk-python"
    }
  }
}

Windows:

Add to %APPDATA%\Claude\claude_desktop_config.json:

{
  "mcpServers": {
    "silo-sdk-mcp": {
      "command": "C:\\absolute\\path\\to\\silo-sdk-python\\.venv\\Scripts\\silo-sdk-mcp.exe",
      "args": [],
      "cwd": "C:\\absolute\\path\\to\\silo-sdk-python"
    }
  }
}

Tip

Use absolute paths for the command and cwd fields. Relative paths and environment variables like $HOME or ~ don't expand reliably in posix_spawn.

Restart Claude Desktop after editing the config file.

Pattern 2: Direct Python

This pattern invokes Python directly. It requires passing tokens via the env section.

Warning

Environment variable expansion in the env section is client-dependent and may not work reliably in all MCP clients. Use Pattern 1 instead.

{
  "mcpServers": {
    "silo-sdk-mcp": {
      "command": "/absolute/path/to/silo-sdk-python/.venv/bin/python",
      "args": ["-m", "silo_sdk_mcp", "--transport", "stdio"],
      "cwd": "/absolute/path/to/silo-sdk-python",
      "env": {
        "A8_ADMIN_TOKEN": "your-actual-token-here",
        "A8_SYNC_TOKEN": "your-actual-token-here",
        "A8_FILE_TOKEN": "your-actual-token-here",
        "A8_LOG_TOKEN": "your-actual-token-here",
        "A8_SCRAPE_TOKEN": "your-actual-token-here",
        "A8_BUCKET_ID": "your-actual-bucket-id-here"
      }
    }
  }
}

Pattern 3: Docker stdio

Run the MCP server in a Docker container. Claude spawns the container as a subprocess and communicates via stdin/stdout, identical to the non-Docker patterns.

Build the Docker image first:

cd /path/to/silo-sdk-python
docker build -f Dockerfile.mcp -t a8-mcp-server .

How the container gets credentials

The Docker image does not include your .env file — it is gitignored and never copied into the build context. The container reads config/default.json (which contains ${A8_ADMIN_TOKEN} placeholders) and resolves them from the process environment. You must supply real token values via one of the three methods below.

Method A: --env-file (recommended)

Pass your .env file directly to Docker. Docker reads it as plain KEY=value pairs and injects them as environment variables into the container:

{
  "mcpServers": {
    "silo-sdk-mcp": {
      "command": "docker",
      "args": [
        "run", "--rm", "-i",
        "--env-file", "/absolute/path/to/silo-sdk-python/.env",
        "a8-mcp-server"
      ]
    }
  }
}

Note

Docker's --env-file reads plain KEY=value pairs only — it does not expand shell variables like ${OTHER_VAR} within the file. If your .env contains any variable references, use Method C (volume mount) instead.

Method B: Explicit -e flags

Inline each token directly in the args list. Useful when tokens come from a secrets manager or CI environment rather than a file:

{
  "mcpServers": {
    "silo-sdk-mcp": {
      "command": "docker",
      "args": [
        "run", "--rm", "-i",
        "-e", "A8_ADMIN_TOKEN=your-admin-token",
        "-e", "A8_SYNC_TOKEN=your-sync-token",
        "-e", "A8_FILE_TOKEN=your-file-token",
        "-e", "A8_LOG_TOKEN=your-log-token",
        "-e", "A8_SCRAPE_TOKEN=your-scrape-token",
        "-e", "A8_BUCKET_ID=your-bucket-id",
        "-e", "A8_TOP_ORG=your-org-name",
        "a8-mcp-server"
      ]
    }
  }
}

Method C: Volume-mount the .env file

Mount your .env into the container at /app/.env. The SDK's config loader uses python-dotenv to load this file at startup, which does support variable interpolation:

{
  "mcpServers": {
    "silo-sdk-mcp": {
      "command": "docker",
      "args": [
        "run", "--rm", "-i",
        "-v", "/absolute/path/to/silo-sdk-python/.env:/app/.env:ro",
        "a8-mcp-server"
      ]
    }
  }
}

This is the closest equivalent to running the server natively with a .env file and is recommended if your .env uses variable references.

Claude Code

Project-scoped (single project)

Create .mcp.json in the project root:

{
  "mcpServers": {
    "silo-sdk-mcp": {
      "command": "/absolute/path/to/silo-sdk-python/scripts/.internal/mcp_with_env.sh",
      "args": []
    }
  }
}

A template is provided at .mcp.json.example. Copy and update paths:

cp .mcp.json.example .mcp.json
# Edit .mcp.json with the absolute path to mcp_with_env.sh

Note

.mcp.json is gitignored and project-local. Each developer maintains their own.

Global CLI (available in all projects)

The Claude Code CLI manages MCP servers via claude mcp add, not via mcpServers in settings.json (that field is for Claude Desktop only). To make silo-sdk-mcp available across all projects:

claude mcp add silo-sdk-mcp --scope user -- \
  /absolute/path/to/silo-sdk-python/scripts/.internal/mcp_with_env.sh

Why the wrapper script — not the binary directly

The silo-sdk-mcp binary requires the project root as its working directory to locate config/default.json. The claude mcp add command does not persist a cwd setting, so calling the binary directly fails at startup. The wrapper script scripts/.internal/mcp_with_env.sh resolves the project root from its own location and loads .env before launching the server — no cwd needed from the client.

Verify the server is connected:

claude mcp list
# silo-sdk-mcp: /path/to/mcp_with_env.sh - ✓ Connected

Note

The user-scope entry is stored in ~/.claude.json and applies to every Claude Code session regardless of project directory. To disable for a specific machine, run claude mcp remove silo-sdk-mcp --scope user.

Start the Server

With Docker Compose

The provided docker-compose.mcp.yml defines an mcp-http service. Add env_file: to inject the token values that credentials.yaml references:

services:
  mcp-http:
    build:
      context: .
      dockerfile: Dockerfile.mcp
    volumes:
      # Step 1: mount the credentials map (client keys → ${VAR} references)
      - ./silo_sdk_mcp/credentials.yaml:/app/silo_sdk_mcp/credentials.yaml:ro
    ports:
      # Bind loopback explicitly. A bare "8080:8080" binds 0.0.0.0 and
      # exposes the server to the whole network.
      - "127.0.0.1:8080:8080"
    env_file:
      # Step 2: inject the actual token values that credentials.yaml references
      - .env.http
    environment:
      # Required whenever the container's published port is not loopback:
      # without it the server turns DNS-rebinding protection off and only
      # logs a warning. List the host:port your client actually sends.
      - MCP_ALLOWED_HOSTS=127.0.0.1:8080,localhost:8080
    command: >
      silo-sdk-mcp --transport streamable-http
      --host 0.0.0.0 --port 8080
      --credentials /app/silo_sdk_mcp/credentials.yaml

sse is the legacy transport

--transport sse is still accepted and serves at /sse rather than /mcp. It stays available for older clients, but Streamable HTTP supersedes it and is what the shipped Compose file uses. New deployments should use streamable-http.

The mount path must match the package path

The container's default credentials path sits next to the installed package, at /app/silo_sdk_mcp/credentials.yaml. Mount the file there — mounting it at /app/credentials.yaml leaves the default pointing at a file that does not exist.

Start the server:

docker compose -f docker-compose.mcp.yml up -d mcp-http

View logs:

docker compose -f docker-compose.mcp.yml logs -f mcp-http

Stop the server:

docker compose -f docker-compose.mcp.yml down

Manual Docker Run

Without Docker Compose — both steps in one command:

docker run -d \
  --name silo-sdk-mcp-http \
  -p 127.0.0.1:8080:8080 \
  -v $(pwd)/silo_sdk_mcp/credentials.yaml:/app/silo_sdk_mcp/credentials.yaml:ro \
  --env-file .env.http \
  -e MCP_ALLOWED_HOSTS=127.0.0.1:8080,localhost:8080 \
  a8-mcp-server \
  silo-sdk-mcp --transport streamable-http \
    --host 0.0.0.0 --port 8080 \
    --credentials /app/silo_sdk_mcp/credentials.yaml

The -v flag mounts the credential map; --env-file injects the token values it references.

Reverse Proxy Configuration

The endpoint path depends on the transport: streamable-http serves at /mcp, the legacy sse transport at /sse. The server speaks plain HTTP and has no TLS options of its own, so for anything beyond loopback put it behind a reverse proxy that terminates TLS.

Set MCP_ALLOWED_HOSTS to the public name

Behind a proxy the server sees the Host header the client sent — mcp.yourcompany.com, not localhost. If that name is not in MCP_ALLOWED_HOSTS, DNS-rebinding protection rejects every request. Set MCP_ALLOWED_HOSTS=mcp.yourcompany.com:443 (or whatever your clients send) alongside the proxy config below.

nginx Example:

server {
    listen 443 ssl http2;
    server_name mcp.yourcompany.com;

    ssl_certificate /etc/ssl/certs/mcp.yourcompany.com.crt;
    ssl_certificate_key /etc/ssl/private/mcp.yourcompany.com.key;

    location /mcp {
        proxy_pass http://localhost:8080/mcp;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        # Streaming responses: don't let the proxy buffer them
        proxy_set_header Connection '';
        proxy_buffering off;
        proxy_cache off;
        chunked_transfer_encoding off;
    }
}

Traefik Example:

http:
  routers:
    mcp-http:
      rule: "Host(`mcp.yourcompany.com`) && Path(`/mcp`)"
      service: mcp-http-service
      tls:
        certResolver: letsencrypt

  services:
    mcp-http-service:
      loadBalancer:
        servers:
          - url: "http://localhost:8080"

Client Configuration

Clients connect to the server's /mcp endpoint with their Bearer token. A client still on the legacy sse transport connects to /sse instead.

Claude Desktop:

Add to ~/Library/Application Support/Claude/claude_desktop_config.json:

{
  "mcpServers": {
    "silo-sdk-mcp": {
      "url": "https://mcp.yourcompany.com/mcp",
      "headers": {
        "Authorization": "Bearer client-key-alice"
      }
    }
  }
}

Claude Code:

Add to project .mcp.json:

{
  "mcpServers": {
    "silo-sdk-mcp": {
      "url": "https://mcp.yourcompany.com/mcp",
      "headers": {
        "Authorization": "Bearer client-key-alice"
      }
    }
  }
}

Cursor / Other Clients:

Most MCP clients support Streamable HTTP with a similar config structure. Clients that only speak the legacy SSE transport work too — point them at /sse and start the server with --transport sse. Consult the client's MCP documentation.

Security Considerations

Authentication:

  • Bearer tokens act as API keys. Generate long, random strings (e.g., openssl rand -hex 32)
  • Rotate tokens periodically and when team members leave
  • Use HTTPS for all client-server communication (never plain HTTP in production)

Credential Isolation:

  • Invalid Bearer tokens result in 401 Unauthorized
  • Note: An instance serves exactly one client's API credentials, and refuses to start if given a credentials file listing more than one. Isolating clients from each other means one instance per client. See One Client Per Instance above.

Network Security:

  • Deploy behind a reverse proxy with TLS termination
  • Use a firewall to restrict access to port 8080 (only reverse proxy should reach it)
  • Enable rate limiting at the reverse proxy layer to prevent abuse
  • Consider IP allowlisting if clients connect from known networks

Monitoring:

  • Log all requests with client identifiers (but redact sensitive data)
  • Monitor for failed auth attempts—may indicate credential compromise
  • Set up alerts for unusual API usage patterns

Health Checks

The MCP server doesn't expose a dedicated health endpoint. Monitor with Docker health checks:

services:
  mcp-http:
    healthcheck:
      test: ["CMD", "python", "-c", "import socket; s = socket.socket(); s.connect(('localhost', 8080)); s.close()"]
      interval: 30s
      timeout: 5s
      retries: 3

Or use a simple TCP check from your monitoring system.

Scaling

For high-traffic deployments:

  • Horizontal scaling: Run multiple MCP server containers behind a load balancer
  • Sticky sessions: Not required—each request is independent
  • Shared credentials: Use a secrets manager (AWS Secrets Manager, HashiCorp Vault) instead of credentials.yaml

Verify Connection

After configuring your client:

  1. Restart the application (Claude Desktop, Claude Code, etc.)
  2. Check the MCP connection status (usually shown in settings or status bar)
  3. Test by asking Claude: "List users in [your org name] organization"

If the MCP server is connected, you'll see all tools loaded. If there's an error, check:

  • Client debug logs (e.g., ~/.claude/debug/*.txt for Claude Desktop/Code)
  • Verify .env exists and contains all required tokens (stdio mode)
  • Ensure absolute paths in config (no $HOME, ~, or relative paths)
  • Verify the silo-sdk-mcp binary exists in the venv: ls .venv/bin/silo-sdk-mcp (stdio mode)
  • Review server logs for authentication errors (HTTP mode)

Troubleshooting

ModuleNotFoundError: No module named 'silo_mcp'

Symptom: silo-sdk-mcp exits immediately with ModuleNotFoundError: No module named 'silo_mcp', usually right after upgrading.

Cause: The package was renamed to silo_sdk_mcp in 0.14.0, but the console script and the editable-install import finder still point at the old path. Both are generated at install time and do not update on git pull.

Fix: Reinstall — see Upgrading from 0.13.x.

pip install -e ".[mcp-server]"

MCP Server Fails to Start (stdio mode)

Symptom: Connection error in Claude Desktop/Code

Check:

# Verify Python path is correct
/absolute/path/to/silo-sdk-python/.venv/bin/python --version

# Test server manually
cd /path/to/silo-sdk-python
source .venv/bin/activate
silo-sdk-mcp --list-tools

Client Connection Refused (HTTP mode)

Symptom: Clients cannot connect to the server endpoint (/mcp, or /sse on the legacy transport)

Check:

  • Server is running: docker ps | grep silo-sdk-mcp-http
  • Port 8080 is accessible: curl http://localhost:8080/mcp
  • Reverse proxy configuration is correct
  • Firewall allows traffic to reverse proxy

CryptError or API Authentication Failures

Symptom: CryptError: Invalid data or 401 Unauthorized

Cause: Environment variables not loaded correctly (stdio) or ${VAR} references in credentials.yaml were not resolved (HTTP)

Fix (stdio): Use Pattern 1 (CLI entry point) instead of Pattern 2

Fix (HTTP):

  • Confirm --env-file .env.http (manual run) or env_file: .env.http (Compose) is present
  • Check that variable names in .env.http match exactly what silo_sdk_mcp/credentials.yaml references (e.g., ALICE_ADMIN_TOKEN in .env.http must match ${ALICE_ADMIN_TOKEN} in the YAML)
  • Ensure ${VAR} syntax is used in the YAML — not $VAR or {VAR}
  • Review server startup logs for credential loading warnings:
    docker compose -f docker-compose.mcp.yml logs mcp-http | grep -i credential
    

401 Unauthorized (HTTP mode)

Symptom: Client gets 401 Unauthorized when connecting

Cause: Bearer token not found in credentials.yaml or missing Authorization header

Fix:

  • Verify client Bearer token matches a key in credentials.yaml
  • Check client config has Authorization: Bearer <token> header
  • Review server logs for authentication errors

Server Crashes (HTTP mode)

Symptom: Container exits immediately after start

Check logs:

docker compose -f docker-compose.mcp.yml logs mcp-http

Common causes:

  • credentials.yaml file not found or invalid YAML syntax
  • Missing required environment variables
  • Port 8080 already in use
  • credentials.yaml still at the pre-0.14.0 path. If the log shows a YAML error that looks like it is reading a directory, the bind mount's host path is missing and Docker created an empty directory in its place. Check with ls -la silo_sdk_mcp/credentials.yaml — if that is a directory rather than a file, see Upgrading from 0.13.x.

Tools Not Appearing (stdio mode)

Symptom: Claude doesn't see the Authentic8 tools

Check:

  • MCP server config file location (it varies by OS)
  • Config file syntax (valid JSON, no trailing commas)
  • Restart client application after editing config

Next Steps