diff --git a/examples/server-deployment/docker/deploy/caddy/Caddyfile b/examples/server-deployment/docker/deploy/caddy/Caddyfile new file mode 100644 index 0000000..4438936 --- /dev/null +++ b/examples/server-deployment/docker/deploy/caddy/Caddyfile @@ -0,0 +1,51 @@ +{$DOMAIN} { + tls { + issuer acme { + disable_tlsalpn_challenge # force HTTP-01 on port 80 + # ca https://acme-staging-v02.api.letsencrypt.org/directory # optional during testing + } + } + + encode gzip + + @mcp { + path /mcp /mcp/ /mcp/* + } + handle @mcp { + # Ensure trailing slash for /mcp -> /mcp/ + uri path_regexp ^/mcp$ /mcp/ + reverse_proxy http://mcp:8001 { + # SSE/MCP streaming configuration + flush_interval -1 + header_up X-Real-IP {remote_host} + # Disable buffering for SSE + @sse { + header Accept *text/event-stream* + } + } + } + + # Serve favicon and icon files with proper caching + handle /favicon.ico { + root * /srv/site + header Cache-Control "public, max-age=86400, immutable" + header Content-Type "image/x-icon" + file_server + } + handle /favicon.png { + root * /srv/site + header Cache-Control "public, max-age=86400, immutable" + header Content-Type "image/png" + file_server + } + handle /site.webmanifest { + root * /srv/site + header Cache-Control "public, max-age=3600" + header Content-Type "application/manifest+json" + file_server + } + handle { + root * /srv/site + file_server + } +} \ No newline at end of file diff --git a/examples/server-deployment/docker/docker-compose.yml b/examples/server-deployment/docker/docker-compose.yml new file mode 100644 index 0000000..201f845 --- /dev/null +++ b/examples/server-deployment/docker/docker-compose.yml @@ -0,0 +1,56 @@ +networks: + internal: + driver: bridge + +volumes: + caddy_data: + caddy_config: + +services: + mcp: + # Option A: build from this repo's Dockerfile (assumes you are working from the repo's examples/server-deployment/docker directory) + build: + context: ../../../ + dockerfile: Dockerfile + # Option B: if you publish an image, replace with: + # image: ghcr.io/teradata/teradata-mcp-server:latest + container_name: teradata-mcp + env_file: .env + expose: + - "8001" # only visible inside the compose network + command: + - teradata-mcp-server + - --mcp_transport + - streamable-http + - --mcp_host + - 0.0.0.0 + - --mcp_port + - "8001" + healthcheck: + test: ["CMD", "python", "-c", "import socket; s = socket.socket(); s.settimeout(5); s.connect(('127.0.0.1', 8001)); s.close()"] + interval: 15s + timeout: 5s + retries: 10 + start_period: 10s + networks: + - internal + + caddy: + image: caddy:2 + container_name: caddy + depends_on: + mcp: + condition: service_healthy + environment: + # Set this to your DuckDNS (or real) domain, e.g. teradata-mcp.duckdns.org + - DOMAIN=${DOMAIN} + ports: + - "80:80" + - "443:443" + volumes: + - ./deploy/caddy/Caddyfile:/etc/caddy/Caddyfile:ro + - caddy_data:/data # certs / ACME storage + - caddy_config:/config + - ./site:/srv/site:ro # optional favicon/landing page + networks: + - internal \ No newline at end of file diff --git a/examples/server-deployment/docker/site/favicon.ico b/examples/server-deployment/docker/site/favicon.ico new file mode 100644 index 0000000..541b77c Binary files /dev/null and b/examples/server-deployment/docker/site/favicon.ico differ diff --git a/examples/server-deployment/docker/site/favicon.png b/examples/server-deployment/docker/site/favicon.png new file mode 100644 index 0000000..23edea8 Binary files /dev/null and b/examples/server-deployment/docker/site/favicon.png differ diff --git a/examples/server-deployment/docker/site/index.html b/examples/server-deployment/docker/site/index.html new file mode 100644 index 0000000..df2b93d --- /dev/null +++ b/examples/server-deployment/docker/site/index.html @@ -0,0 +1,26 @@ + + +
+Secure endpoint: /mcp/
++ ⚙️ Need to configure your client? See the + + MCP Client Guide + . +
+ + diff --git a/examples/server-deployment/docker/site/site.webmanifest b/examples/server-deployment/docker/site/site.webmanifest new file mode 100644 index 0000000..fbf43c0 --- /dev/null +++ b/examples/server-deployment/docker/site/site.webmanifest @@ -0,0 +1,14 @@ +{ + "name": "Teradata MCP Server", + "short_name": "Teradata MCP", + "icons": [ + { + "src": "/favicon.png", + "sizes": "192x192", + "type": "image/png" + } + ], + "theme_color": "#FF6200", + "background_color": "#ffffff", + "display": "standalone" +} diff --git a/examples/server-deployment/quickstart-docker.md b/examples/server-deployment/quickstart-docker.md new file mode 100644 index 0000000..505879a --- /dev/null +++ b/examples/server-deployment/quickstart-docker.md @@ -0,0 +1,153 @@ +# Quickstart — Docker Compose (MCP + Caddy HTTPS) + +This guide shows how to run the **Teradata MCP server** behind **Caddy** with automatic **HTTPS (Let’s Encrypt)** using **Docker Compose**. It keeps port **8001** private and exposes only **80/443**. + +--- + +## 0) Prerequisites + +- Docker + Docker Compose plugin installed. +- An EC2 instance or host with public IPv4. +- A DNS record pointing to your host (e.g. `teradata-mcp.duckdns.org →