diff --git a/.env.oauth.example b/.env.oauth.example new file mode 100644 index 0000000..b8909a6 --- /dev/null +++ b/.env.oauth.example @@ -0,0 +1,28 @@ +# OAuth staging environment — copy to .env.oauth and fill in values +# Launch: docker compose -f docker-compose.oauth.yaml --env-file .env.oauth up -d + +# --- WorkOS AuthKit --- +AWARENESS_OAUTH_ISSUER=https://your-app.authkit.app +AWARENESS_OAUTH_AUDIENCE= +# AWARENESS_OAUTH_JWKS_URI= # defaults to /.well-known/jwks.json + +# --- JWT (for self-signed tokens via mcp-awareness-token CLI) --- +AWARENESS_JWT_SECRET= +# Generate with: mcp-awareness-secret + +# --- Postgres --- +POSTGRES_PASSWORD= + +# --- Cloudflare tunnel --- +CLOUDFLARED_STAGING_CONFIG=~/.cloudflared/staging-config.yml +CLOUDFLARED_STAGING_CREDS=~/.cloudflared/.json + +# --- Secret path (optional, for WAF) --- +# AWARENESS_MOUNT_PATH=/your-secret-path + +# --- Default owner (for stdio/unauthenticated, usually not needed with auth) --- +# AWARENESS_DEFAULT_OWNER= + +# --- Embeddings (optional) --- +# AWARENESS_EMBEDDING_PROVIDER=ollama +# Launch with: docker compose -f docker-compose.oauth.yaml --env-file .env.oauth --profile embeddings up -d diff --git a/.gitignore b/.gitignore index d04c2fd..3401615 100644 --- a/.gitignore +++ b/.gitignore @@ -146,6 +146,7 @@ celerybeat.pid # Environments .env +.env.oauth .envrc .venv env/ diff --git a/CHANGELOG.md b/CHANGELOG.md index 785862a..dc77b39 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added +- **OAuth staging compose**: `docker-compose.oauth.yaml` for isolated OAuth/WorkOS AuthKit testing with separate Postgres, Cloudflare tunnel, and optional Ollama — runs on port 8421 alongside production +- **OAuth env template**: `.env.oauth.example` with all required/optional variables for staging deployment + ### Fixed - **JSON content rejected by Pydantic validation**: `remember` and `update_entry` now accept `dict` and `list` content in addition to `str` — fixes `string_type` validation error when MCP transport auto-parses JSON strings before they reach the handler (#130) diff --git a/docker-compose.oauth.yaml b/docker-compose.oauth.yaml new file mode 100644 index 0000000..efde00c --- /dev/null +++ b/docker-compose.oauth.yaml @@ -0,0 +1,138 @@ +# OAuth staging deployment — isolated stack for testing WorkOS AuthKit +# Uses separate containers, volumes, and ports from production. +# +# Setup: +# 1. Create a Cloudflare named tunnel for staging: +# cloudflared tunnel create awareness-staging +# 2. Add DNS route: +# cloudflared tunnel route dns awareness-staging staging.mcpawareness.com +# 3. Create config at ~/.cloudflared/staging-config.yml: +# tunnel: +# credentials-file: /etc/cloudflared/credentials.json +# ingress: +# - hostname: staging.mcpawareness.com +# service: http://awareness-oauth:8421 +# - service: http_status:404 +# 4. Copy .env.oauth.example to .env.oauth and fill in WorkOS values +# 5. Launch: docker compose -f docker-compose.oauth.yaml --env-file .env.oauth up -d +# +# Tear down: docker compose -f docker-compose.oauth.yaml down -v +name: mcp-awareness-oauth + +services: + awareness-oauth: + build: . + container_name: awareness-oauth + restart: unless-stopped + ports: + - "127.0.0.1:8421:8421" + environment: + - AWARENESS_HOST=0.0.0.0 + - AWARENESS_PORT=8421 + - AWARENESS_TRANSPORT=streamable-http + - AWARENESS_DATABASE_URL=postgresql://awareness:${POSTGRES_PASSWORD:-awareness-oauth}@postgres-oauth:5432/awareness + - AWARENESS_MOUNT_PATH=${AWARENESS_MOUNT_PATH:-} + - AWARENESS_AUTH_REQUIRED=true + - AWARENESS_JWT_SECRET=${AWARENESS_JWT_SECRET:-} + - AWARENESS_JWT_ALGORITHM=${AWARENESS_JWT_ALGORITHM:-HS256} + - AWARENESS_OAUTH_ISSUER=${AWARENESS_OAUTH_ISSUER:?Set AWARENESS_OAUTH_ISSUER to your WorkOS AuthKit domain} + - AWARENESS_OAUTH_AUDIENCE=${AWARENESS_OAUTH_AUDIENCE:-} + - AWARENESS_OAUTH_JWKS_URI=${AWARENESS_OAUTH_JWKS_URI:-} + - AWARENESS_OAUTH_USER_CLAIM=${AWARENESS_OAUTH_USER_CLAIM:-sub} + - AWARENESS_OAUTH_AUTO_PROVISION=true + - AWARENESS_PUBLIC_URL=${AWARENESS_PUBLIC_URL:-https://staging.mcpawareness.com} + - AWARENESS_DEFAULT_OWNER=${AWARENESS_DEFAULT_OWNER:-} + - AWARENESS_EMBEDDING_PROVIDER=${AWARENESS_EMBEDDING_PROVIDER:-} + - AWARENESS_EMBEDDING_MODEL=${AWARENESS_EMBEDDING_MODEL:-nomic-embed-text} + - AWARENESS_OLLAMA_URL=${AWARENESS_OLLAMA_URL:-http://ollama-oauth:11434} + depends_on: + postgres-oauth: + condition: service_healthy + deploy: + resources: + limits: + cpus: '0.1' + memory: 64M + healthcheck: + test: ["CMD", "python", "-c", "import socket; s = socket.create_connection(('localhost', 8421), timeout=2); s.close()"] + interval: 10s + timeout: 10s + retries: 3 + start_period: 15s + + tunnel-oauth: + image: cloudflare/cloudflared:latest + container_name: awareness-tunnel-oauth + restart: unless-stopped + command: tunnel --no-autoupdate run + volumes: + - ${CLOUDFLARED_STAGING_CONFIG:-~/.cloudflared/staging-config.yml}:/etc/cloudflared/config.yml:ro + - ${CLOUDFLARED_STAGING_CREDS:?Set CLOUDFLARED_STAGING_CREDS to your staging tunnel credentials file}:/etc/cloudflared/credentials.json:ro + depends_on: + awareness-oauth: + condition: service_healthy + deploy: + resources: + limits: + cpus: '0.05' + memory: 64M + + postgres-oauth: + image: pgvector/pgvector:pg17 + container_name: awareness-postgres-oauth + restart: unless-stopped + environment: + POSTGRES_DB: awareness + POSTGRES_USER: awareness + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-awareness-oauth} + volumes: + - ${AWARENESS_OAUTH_PG_DATA:-~/awareness-oauth-pg}:/var/lib/postgresql/data + command: + - postgres + - -c + - wal_level=logical + - -c + - max_replication_slots=4 + - -c + - shared_preload_libraries=pg_stat_statements + deploy: + resources: + limits: + cpus: '0.5' + memory: 256M + healthcheck: + test: ["CMD-SHELL", "pg_isready -U awareness"] + interval: 10s + timeout: 5s + retries: 5 + start_period: 10s + + # Ollama for staging — separate volume from production to avoid concurrent access + ollama-oauth: + image: ollama/ollama:latest + container_name: awareness-ollama-oauth + restart: unless-stopped + entrypoint: ["/bin/sh", "-c"] + command: + - | + ollama serve & + until ollama list > /dev/null 2>&1; do sleep 1; done + ollama pull ${AWARENESS_EMBEDDING_MODEL:-nomic-embed-text} + wait + environment: + - AWARENESS_EMBEDDING_MODEL=${AWARENESS_EMBEDDING_MODEL:-nomic-embed-text} + volumes: + - ${AWARENESS_OLLAMA_DATA:-~/awareness-ollama-oauth}:/root/.ollama + deploy: + resources: + limits: + cpus: '1.0' + memory: 2G + healthcheck: + test: ["CMD-SHELL", "ollama list | grep -q ${AWARENESS_EMBEDDING_MODEL:-nomic-embed-text}"] + interval: 30s + timeout: 10s + retries: 10 + start_period: 60s + profiles: + - embeddings