{"_id":"@davidalbertonogueira/redshift-mcp-server","name":"@davidalbertonogueira/redshift-mcp-server","dist-tags":{"latest":"1.0.5"},"versions":{"1.0.5":{"name":"@davidalbertonogueira/redshift-mcp-server","version":"1.0.5","description":"Model Context Protocol server for Amazon Redshift","mcpName":"io.github.davidalbertonogueira/redshift-mcp-server","main":"dist/index.js","type":"module","scripts":{"build":"tsc","start":"node dist/index.js","start:http":"TRANSPORT_MODE=http node dist/index.js","start:http:stateless":"TRANSPORT_MODE=http STATELESS_MODE=true node dist/index.js","dev":"ts-node --esm src/index.ts","dev:http":"TRANSPORT_MODE=http ts-node --esm src/index.ts","dev:http:stateless":"TRANSPORT_MODE=http STATELESS_MODE=true ts-node --esm src/index.ts","test":"echo \"No tests specified\""},"keywords":["mcp","redshift","model-context-protocol","ai","code-generation"],"author":{"name":"Paschal Onuorah"},"license":"MIT","dependencies":{"@modelcontextprotocol/sdk":"^1.8.0","@types/express":"^5.0.3","cors":"^2.8.5","express":"^5.1.0","pg":"^8.11.3"},"devDependencies":{"@types/cors":"^2.8.17","@types/node":"^20.17.30","@types/pg":"^8.10.9","ts-node":"^10.9.2","typescript":"^5.3.3"},"engines":{"node":">=16.0.0"},"gitHead":"6847d62c6bbc2f456d1de0cf840600ae556639f1","_id":"@davidalbertonogueira/redshift-mcp-server@1.0.5","_nodeVersion":"24.11.0","_npmVersion":"11.6.1","dist":{"integrity":"sha512-Wncsgoy8WQOZWeXcTk7IHnXYw4hf0a0Gb90S1qCTPIVKPbI+i6dgM+woP26Jl3C+jQYICnQ0rfHJ/L+NTnpDWQ==","shasum":"57f00aaa667b6ed74e27b7c01c9f59d8f2a3c1c4","tarball":"https://registry.npmjs.org/@davidalbertonogueira/redshift-mcp-server/-/redshift-mcp-server-1.0.5.tgz","fileCount":29,"unpackedSize":130596,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIA1Ez4EYeFBVJBIG9QjBzHUJbBHwe5yg73h5LqNDrqnZAiA0dVc81KEq38uUTJJyp9TxK+EVRjGP44GFF0W+Q7tWhA=="}]},"_npmUser":{"name":"davidalbertonogueira","email":"nogsoftware@outlook.com"},"directories":{},"maintainers":[{"name":"davidalbertonogueira","email":"nogsoftware@outlook.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/redshift-mcp-server_1.0.5_1761762985361_0.627684543490084"},"_hasShrinkwrap":false}},"time":{"created":"2025-10-29T18:36:25.252Z","1.0.5":"2025-10-29T18:36:25.568Z","modified":"2025-10-29T18:36:25.864Z"},"maintainers":[{"name":"davidalbertonogueira","email":"nogsoftware@outlook.com"}],"description":"Model Context Protocol server for Amazon Redshift","keywords":["mcp","redshift","model-context-protocol","ai","code-generation"],"author":{"name":"Paschal Onuorah"},"license":"MIT","readme":"# Redshift MCP Server\n\n**Give AI assistants secure, read-only access to your Amazon Redshift data warehouse.**\n\nThis TypeScript-based [Model Context Protocol (MCP)](https://modelcontextprotocol.io) server enables LLMs to inspect schemas, execute queries, and understand your data warehouse structure.\n\n> 🌟 Based on the [original implementation](https://github.com/paschmaria/redshift-mcp-server) by paschmaria, with production-ready enhancements.\n\n## ✨ Features\n\n- 🔒 **Read-only queries** with automatic transaction safety\n- 🏗️ **Schema introspection** - tables, columns, relationships\n- 📊 **Smart sampling** - optional PII redaction (emails, phones)\n- 📈 **Statistics** - table sizes, row counts, distribution keys\n- 🔍 **Column search** - find columns across all schemas\n- 🚀 **Dual modes** - STDIO (IDEs) + HTTP (web/cloud)\n- 🔐 **Bearer auth** - production-ready security\n- ☸️ **Cloud-native** - stateless mode, health checks, K8s-ready\n- 🐳 **Docker** - single-command deployment\n\n## 🚀 Quick Start\n\n### Local Setup (5 minutes)\n\n```bash\n# 1. Clone and install\ngit clone <repository-url>\ncd redshift-mcp-server\nnpm install\n\n# 2. Build\nnpm run build\n\n# 3. Configure\nexport DATABASE_URL=\"redshift://user:pass@host:5439/db?ssl=true\"\n\n# 4. Run (STDIO mode for IDE)\nnpm start\n\n# OR run HTTP mode for web/cloud\nexport TRANSPORT_MODE=\"http\"\nnpm start\n# Server: http://localhost:3000/mcp or http://localhost:3000/\n```\n\n### Docker (1 minute)\n\n```bash\n# Build\ndocker build -t redshift-mcp:latest .\n\n# Run STDIO (for IDEs)\ndocker run -e DATABASE_URL='redshift://...' -i --rm redshift-mcp:latest\n\n# Run HTTP with auth (for production)\ndocker run \\\n  -e DATABASE_URL='redshift://...' \\\n  -e TRANSPORT_MODE=http \\\n  -e STATELESS_MODE=true \\\n  -e ENABLE_AUTH=true \\\n  -e API_TOKEN=your-secret-token \\\n  -e REDACT_PII=false \\\n  -p 3000:3000 \\\n  redshift-mcp:latest\n```\n\n---\n\n## 📋 Table of Contents\n\n- [Configuration](#-configuration)\n- [Transport Modes](#-transport-modes)\n- [Authentication](#-authentication)\n- [IDE Integration](#-ide-integration)\n- [Dust.tt Integration](#-dusttt-integration)\n- [Kubernetes Deployment](#%EF%B8%8F-kubernetes-deployment)\n- [Available Tools](#-available-tools)\n- [Troubleshooting](#-troubleshooting)\n\n---\n\n## ⚙️ Configuration\n\n### Environment Variables\n\n| Variable | Required | Default | Description |\n|----------|----------|---------|-------------|\n| `DATABASE_URL` | ✅ Yes | - | Redshift connection string |\n| `TRANSPORT_MODE` | No | `stdio` | `stdio` for IDEs, `http` for web/cloud |\n| `PORT` | No | `3000` | HTTP server port |\n| `STATELESS_MODE` | No | `false` | `true` for horizontal scaling |\n| `ENABLE_AUTH` | No | `false` | Enable Bearer token authentication |\n| `API_TOKEN` | No | - | Bearer token (required if `ENABLE_AUTH=true`) |\n| `ALLOWED_ORIGINS` | No | `*` | CORS allowed origins |\n| `ENABLE_RESUMABILITY` | No | `false` | Event resumability (stateful mode only) |\n| `REDACT_PII` | No | `false` | Redact email/phone in output data |\n\n### Database URL Format\n\n```\nredshift://username:password@hostname:port/database?ssl=true&timeout=600\n```\n\n**Example:**\n```bash\nDATABASE_URL=\"redshift://admin:MyPass123@cluster.us-east-1.redshift.amazonaws.com:5439/analytics?ssl=true\"\n```\n\n### Configuration File (`.env`)\n\n```bash\n# Copy example\ncp .env.example .env\n\n# Edit with your values\nDATABASE_URL=\"redshift://...\"\nTRANSPORT_MODE=\"http\"\nSTATELESS_MODE=\"true\"\nENABLE_AUTH=\"true\"\nAPI_TOKEN=\"your-secret-token-here\"\nREDACT_PII=\"false\"\n```\n\n---\n\n## 🔄 Transport Modes\n\nChoose the right transport mode for your use case:\n\n### STDIO Mode (Default)\n\n**Best for:** IDEs, CLI tools, local development\n\n```bash\n# Default mode - no configuration needed\nexport DATABASE_URL=\"redshift://...\"\nnpm start\n```\n\n**Clients:**\n- Cursor IDE\n- Windsurf\n- Claude Desktop\n- Custom CLI tools\n\n**How it works:** Communicates via standard input/output streams\n\n### HTTP Mode\n\n**Best for:** Web apps, Dust.tt, Kubernetes, remote integrations\n\n```bash\n# Enable HTTP transport\nexport DATABASE_URL=\"redshift://...\"\nexport TRANSPORT_MODE=\"http\"\nnpm start\n```\n\n**Endpoints:**\n- `POST/GET/DELETE /mcp` - MCP protocol endpoint\n- `POST/GET/DELETE /` - Root path (alias for `/mcp`)\n- `GET /health` - Health check with metrics\n- `GET /ready` - Readiness probe\n\n**Stateful vs Stateless:**\n\n| Mode | Best For | Sessions | Scaling | Set With |\n|------|----------|----------|---------|----------|\n| **Stateful** | IDE clients, MCP Inspector | ✅ Session-based | Needs sticky sessions | `STATELESS_MODE=false` (default) |\n| **Stateless** | Dust.tt, K8s, APIs | ❌ No sessions | ✅ Horizontal scaling | `STATELESS_MODE=true` |\n\n**Production recommendation:** Use `STATELESS_MODE=true` for cloud deployments\n\n---\n\n## 🔐 Authentication\n\n### Bearer Token Auth (Production)\n\nEnable authentication for production deployments (required for Dust.tt, recommended for K8s):\n\n```bash\nexport TRANSPORT_MODE=\"http\"\nexport ENABLE_AUTH=\"true\"\nexport API_TOKEN=\"your-super-secret-token-here\"\nnpm start\n```\n\n**How it works:**\n1. Clients send requests with `Authorization: Bearer <token>` header\n2. Server validates token against `API_TOKEN`\n3. Invalid/missing tokens receive `401 Unauthorized`\n\n**Security features:**\n- OPTIONS requests (CORS preflight) don't require auth\n- Health/ready endpoints don't require auth\n- OAuth discovery endpoints return 404 (tells clients OAuth is not available)\n\n**Testing authentication:**\n\n```bash\n# Without token - should fail\ncurl -X POST http://localhost:3000/mcp \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"jsonrpc\":\"2.0\",\"id\":1}'\n# Returns: 401 Unauthorized\n\n# With token - should work\ncurl -X POST http://localhost:3000/mcp \\\n  -H \"Authorization: Bearer your-super-secret-token-here\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"jsonrpc\":\"2.0\",\"method\":\"initialize\",\"params\":{\"protocolVersion\":\"2024-11-05\",\"capabilities\":{},\"clientInfo\":{\"name\":\"test\",\"version\":\"1.0\"}},\"id\":1}'\n# Returns: 200 OK with server capabilities\n```\n\n**Best practices:**\n- Generate strong tokens: `openssl rand -hex 32`\n- Store tokens in secrets (K8s Secrets, env vars, vault)\n- Rotate tokens regularly (every 90 days)\n- Use HTTPS in production (ngrok, load balancer, ingress)\n\n---\n\n## 💻 IDE Integration\n\n### Cursor / Windsurf / Claude Desktop\n\n**Add to your MCP config file:**\n- Cursor: `.cursor/mcp.json`\n- Windsurf: `mcp_config.json`\n- Claude Desktop: `claude_desktop_config.json`\n\n#### Option 1: Node.js (Recommended)\n\n```json\n{\n  \"mcpServers\": {\n    \"redshift\": {\n      \"command\": \"node\",\n      \"args\": [\"/absolute/path/to/redshift-mcp-server/dist/index.js\"],\n      \"env\": {\n        \"DATABASE_URL\": \"redshift://user:pass@host:5439/db?ssl=true\",\n        \"REDACT_PII\": \"false\"\n      }\n    }\n  }\n}\n```\n\n⚠️ **Important:** Use absolute paths, not relative paths!\n\n#### Option 2: Docker\n\n```json\n{\n  \"mcpServers\": {\n    \"redshift\": {\n      \"command\": \"docker\",\n      \"args\": [\n        \"run\", \"-i\", \"--rm\",\n        \"-e\", \"DATABASE_URL\",\n        \"-e\", \"REDACT_PII\",\n        \"redshift-mcp:latest\"\n      ],\n      \"env\": {\n        \"DATABASE_URL\": \"redshift://user:pass@host:5439/db?ssl=true\",\n        \"REDACT_PII\": \"false\"\n      }\n    }\n  }\n}\n```\n\n**After configuration:**\n1. Restart your IDE\n2. Tools appear automatically in MCP settings\n3. Ask AI: \"What tables are in my database?\"\n\n---\n\n## 🌐 MCP Inspector (Testing Tool)\n\nAnthropic's [MCP Inspector](https://github.com/modelcontextprotocol/inspector) is a web-based tool for testing MCP servers.\n\n**Setup:**\n\n```bash\n# 1. Start server with auth (optional)\nexport DATABASE_URL=\"redshift://...\"\nexport TRANSPORT_MODE=\"http\"\nexport STATELESS_MODE=\"true\"\nexport ENABLE_AUTH=\"true\"\nexport API_TOKEN=\"test-token-123\"\nnpm start\n```\n\n**2. Open MCP Inspector and connect:**\n- **Transport:** Streamable HTTP\n- **Connection:** Direct\n- **URL:** `http://localhost:3000/mcp` or `http://localhost:3000/`\n- **Authentication:** Custom Header (if enabled)\n  - Header: `Authorization`\n  - Value: `Bearer test-token-123`\n\n**3. Test tools:**\n- List tools\n- Execute `query` tool\n- Check resources\n\n---\n\n## ☁️ Dust.tt Integration\n\n[Dust.tt](https://dust.tt) supports remote MCP servers. Here's how to connect:\n\n### Step 1: Expose Your Server\n\n**Option A: ngrok (Quick testing)**\n\n```bash\n# Start server with auth\nexport DATABASE_URL=\"redshift://...\"\nexport TRANSPORT_MODE=\"http\"\nexport STATELESS_MODE=\"true\"\nexport ENABLE_AUTH=\"true\"\nexport API_TOKEN=\"your-secret-token\"\nnpm start\n\n# In another terminal, expose\nngrok http 3000\n# You'll get: https://abc123.ngrok.io\n```\n\n**Option B: Kubernetes (Production)**\n\nSee [Kubernetes Deployment](#%EF%B8%8F-kubernetes-deployment) section below.\n\n### Step 2: Configure in Dust.tt\n\n1. Go to Dust.tt → **Connections** → **Add MCP Server**\n2. Fill in:\n   - **Server Name:** Redshift Data Warehouse\n   - **URL:** `https://your-ngrok-url.ngrok.io/mcp` or `https://your-domain.com/mcp`\n   - **Authentication:** Bearer Token\n   - **Token:** `your-secret-token` (same as `API_TOKEN`)\n3. Click **Save**\n\n✅ **Success!** Dust.tt agents can now query your Redshift data.\n\n**Troubleshooting:**\n- ❌ \"404 Not Found\" → Use `/mcp` suffix or root `/` path\n- ❌ \"401 Unauthorized\" → Check token matches `API_TOKEN` exactly\n- ❌ \"OAuth error\" → Select \"Bearer Token\" auth (not \"Automatic\")\n\n### Step 3: Test in Dust.tt\n\nAsk your Dust.tt agent:\n- \"What tables are in my Redshift database?\"\n- \"Show me the schema of the users table\"\n- \"How many rows are in the orders table?\"\n\n**Learn more:** [Dust.tt MCP Guide](https://blog.dust.tt/give-dust-agents-access-to-your-internal-systems-with-custom-mcp-servers/)\n\n---\n\n\n## ☸️ Kubernetes Deployment\n\n**Production-ready K8s deployment with horizontal scaling:**\n\n**Complete manifest:**\n\n```yaml\napiVersion: v1\nkind: Secret\nmetadata:\n  name: redshift-mcp-secrets\ntype: Opaque\nstringData:\n  database-url: \"redshift://user:pass@host:5439/db?ssl=true\"\n  api-token: \"your-super-secret-token\"\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: redshift-mcp-server\nspec:\n  replicas: 3  # Horizontal scaling with stateless mode\n  selector:\n    matchLabels:\n      app: redshift-mcp-server\n  template:\n    metadata:\n      labels:\n        app: redshift-mcp-server\n    spec:\n      containers:\n      - name: server\n        image: your-registry/redshift-mcp:latest\n        ports:\n        - containerPort: 3000\n        env:\n        - name: TRANSPORT_MODE\n          value: \"http\"\n        - name: STATELESS_MODE\n          value: \"true\"  # Enable for horizontal scaling\n        - name: ENABLE_AUTH\n          value: \"true\"\n        - name: API_TOKEN\n          valueFrom:\n            secretKeyRef:\n              name: redshift-mcp-secrets\n              key: api-token\n        - name: DATABASE_URL\n          valueFrom:\n            secretKeyRef:\n              name: redshift-mcp-secrets\n              key: database-url\n        - name: ALLOWED_ORIGINS\n          value: \"https://dust.tt\"\n        - name: REDACT_PII\n          value: \"false\"\n        livenessProbe:\n          httpGet:\n            path: /health\n            port: 3000\n          initialDelaySeconds: 10\n          periodSeconds: 30\n        readinessProbe:\n          httpGet:\n            path: /ready\n            port: 3000\n          initialDelaySeconds: 5\n          periodSeconds: 10\n        resources:\n          requests:\n            memory: \"256Mi\"\n            cpu: \"100m\"\n          limits:\n            memory: \"512Mi\"\n            cpu: \"500m\"\n---\napiVersion: v1\nkind: Service\nmetadata:\n  name: redshift-mcp-service\nspec:\n  selector:\n    app: redshift-mcp-server\n  ports:\n  - protocol: TCP\n    port: 80\n    targetPort: 3000\n  type: ClusterIP\n---\napiVersion: networking.k8s.io/v1\nkind: Ingress\nmetadata:\n  name: redshift-mcp-ingress\n  annotations:\n    cert-manager.io/cluster-issuer: \"letsencrypt-prod\"\n    nginx.ingress.kubernetes.io/ssl-redirect: \"true\"\nspec:\n  tls:\n  - hosts:\n    - mcp.your-company.com\n    secretName: mcp-tls\n  rules:\n  - host: mcp.your-company.com\n    http:\n      paths:\n      - path: /\n        pathType: Prefix\n        backend:\n          service:\n            name: redshift-mcp-service\n            port:\n              number: 80\n```\n\n**Key configuration points:**\n\n| Feature | Configuration | Why |\n|---------|---------------|-----|\n| **Horizontal Scaling** | `STATELESS_MODE=true`, `replicas: 3` | No sticky sessions needed |\n| **Security** | `ENABLE_AUTH=true`, token in Secret | Protect your data |\n| **Health Checks** | `/health` and `/ready` endpoints | Auto-restart unhealthy pods |\n| **TLS** | Ingress with cert-manager | HTTPS required for production |\n| **Resources** | Adjust based on query load | Start with 256Mi RAM, 100m CPU |\n\n---\n\n## 🛠️ Available Tools\n\nThe MCP server exposes these tools to AI assistants:\n\n### 1. `query` - Execute SQL\n\n**Execute read-only SQL queries** with automatic transaction safety.\n\n```json\n// Input\n{\n  \"sql\": \"SELECT table_name FROM information_schema.tables LIMIT 10\"\n}\n\n// Output\n[\n  {\"table_name\": \"users\"},\n  {\"table_name\": \"orders\"},\n  ...\n]\n```\n\n**Features:**\n- Automatic `BEGIN TRANSACTION READ ONLY`\n- Safe for production use\n- Returns results as JSON array\n\n**Example prompts:**\n- \"Show me all tables in the public schema\"\n- \"What are the top 10 customers by revenue?\"\n- \"Count rows in the orders table\"\n\n### 2. `describe_table` - Table Schema\n\n**Get comprehensive table information** including columns, data types, and Redshift-specific attributes.\n\n```json\n// Input\n{\n  \"schema\": \"public\",\n  \"table\": \"users\"\n}\n\n// Output\n{\n  \"schema\": \"public\",\n  \"table\": \"users\",\n  \"columns\": [\n    {\n      \"column_name\": \"id\",\n      \"data_type\": \"integer\",\n      \"is_nullable\": \"NO\",\n      \"is_distkey\": true,\n      \"is_sortkey\": true\n    },\n    ...\n  ]\n}\n```\n\n**Includes:**\n- Column names and data types\n- Nullability\n- Distribution keys (DISTKEY)\n- Sort keys (SORTKEY)\n- Defaults and constraints\n\n**Example prompts:**\n- \"Describe the structure of the users table\"\n- \"What columns are in the orders table?\"\n- \"Show me the schema for public.payments\"\n\n### 3. `find_column` - Search Columns\n\n**Find tables containing columns** matching a search pattern.\n\n```json\n// Input\n{\n  \"pattern\": \"email\"\n}\n\n// Output\n[\n  {\n    \"table_schema\": \"public\",\n    \"table_name\": \"users\",\n    \"column_name\": \"email\",\n    \"data_type\": \"varchar\"\n  },\n  {\n    \"table_schema\": \"public\",\n    \"table_name\": \"contacts\",\n    \"column_name\": \"contact_email\",\n    \"data_type\": \"varchar\"\n  }\n]\n```\n\n**Use cases:**\n- Find all tables with customer IDs\n- Locate PII fields across schemas\n- Discover relationships between tables\n\n**Example prompts:**\n- \"Find all columns containing 'customer'\"\n- \"Which tables have an 'updated_at' column?\"\n- \"Search for columns with 'amount' in the name\"\n\n### Resources (Contextual Information)\n\nThese are auto-discovered and provided to AI assistants:\n\n| Resource | URI Pattern | Description |\n|----------|-------------|-------------|\n| **Schema Lists** | `redshift://host/schema/{schema}` | All tables in a schema |\n| **Table Schemas** | `redshift://host/{schema}/{table}/schema` | Column definitions, keys |\n| **Sample Data** | `redshift://host/{schema}/{table}/sample` | 5 sample rows (unredacted by default) |\n| **Statistics** | `redshift://host/{schema}/{table}/statistics` | Size, rows, distribution |\n\n**PII Redaction:** Email and phone fields can be redacted in sample data by setting `REDACT_PII=true` (disabled by default).\n\n---\n\n## 🔧 Troubleshooting\n\n### Common Issues\n\n#### ❌ Connection Fails\n\n**Symptoms:** `ENOTFOUND`, `ECONNREFUSED`, or timeout errors\n\n**Solutions:**\n1. **Check DATABASE_URL format**:\n   ```bash\n   redshift://username:password@cluster.region.redshift.amazonaws.com:5439/database?ssl=true\n   ```\n2. **Verify network access:** Security groups, VPC settings, public access\n3. **Test with psql:** `psql \"$DATABASE_URL\"`\n\n#### ❌ Authentication 401 Unauthorized\n\n**Solutions:**\n1. Verify token matches: `API_TOKEN=\"abc123\"` → `Authorization: Bearer abc123`\n2. Select \"Bearer Token\" in Dust.tt (not \"Automatic\")\n3. Check request headers in logs\n\n#### ❌ MCP Inspector Won't Connect\n\n**Solutions:**\n1. Enable stateless mode: `STATELESS_MODE=\"true\"`\n2. Use correct URL: `http://localhost:3000/mcp` or `http://localhost:3000/`\n3. Add auth header if enabled: `Authorization: Bearer your-token`\n\n#### ❌ Dust.tt 404 Not Found\n\n**Solutions:**\n1. Use full path: `https://your-ngrok-url.ngrok.io/mcp`\n2. Check ngrok logs for actual requests\n3. Verify auth token is correct\n\n#### ❌ IDE Tools Not Showing\n\n**Solutions:**\n1. Use absolute paths in config\n2. Verify build: `npm run build && ls -la dist/index.js`\n3. Restart IDE after config changes\n\n### Debug Commands\n\n```bash\n# Health check\ncurl http://localhost:3000/health\n\n# Test with auth\ncurl -H \"Authorization: Bearer token\" http://localhost:3000/mcp\n\n# Test DB connection\npsql \"$DATABASE_URL\" -c \"SELECT 1;\"\n```\n\n---\n\n## 🏗️ Architecture\n\n```\nsrc/\n├── core/\n│   └── redshift-tools.ts     # Pure DB logic (transport-agnostic)\n├── mcp/\n│   └── server.ts             # MCP protocol handler\n├── transports/\n│   ├── stdio.ts              # STDIO transport\n│   └── streamable-http.ts    # HTTP/SSE transport\n├── middleware/\n│   └── auth.ts               # Bearer token authentication\n└── index.ts                  # Application entry point\n```\n\n**Key principles:**\n- 🧩 **Core logic** is transport-agnostic (reusable)\n- 🔌 **Transports** are pluggable (STDIO, HTTP, WebSocket)\n- 🔒 **Middleware** is modular (auth, CORS, logging)\n- ⚙️ **Config** is environment-driven (12-factor)\n\n**See [ARCHITECTURE.md](./ARCHITECTURE.md) for details.**\n\n---\n\n## 📚 Resources\n\n- [MCP Specification](https://modelcontextprotocol.io)\n- [MCP TypeScript SDK](https://github.com/modelcontextprotocol/typescript-sdk)\n- [Dust.tt MCP Guide](https://blog.dust.tt/give-dust-agents-access-to-your-internal-systems-with-custom-mcp-servers/)\n- [Original Implementation](https://github.com/paschmaria/redshift-mcp-server)\n\n---\n\n## 🔐 Security\n\n**Built-in protections:**\n- 🔒 **Read-only transactions** - All queries in `BEGIN TRANSACTION READ ONLY`\n- 😷 **PII redaction** - Optional email/phone redaction in samples\n- 🔐 **Bearer auth** - Token-based access control\n- 🔒 **SSL/TLS** - Encrypted database connections\n\n**Best practices:**\n1. Use dedicated **read-only Redshift user**\n2. Limit **permissions** to necessary schemas/tables\n3. Enable **auth for production**: `ENABLE_AUTH=true`\n4. Use **strong tokens**: `openssl rand -hex 32`\n5. **Rotate credentials** every 90 days\n6. Deploy in **private network** when possible\n7. **Monitor query logs** for suspicious activity\n\n---\n\n## 📝 License & Credits\n\n**Based on:** [paschmaria/redshift-mcp-server](https://github.com/paschmaria/redshift-mcp-server)\n\n**Enhancements:**\n- ✅ Streamable HTTP + stateless mode\n- ✅ Bearer token authentication\n- ✅ Kubernetes-ready deployment\n- ✅ Root path (`/`) + OAuth discovery\n- ✅ Clean architecture with separation of concerns\n\n**HTTP Transport Inspiration:**\nThe HTTP/SSE transport implementation took inspiration from:\n- [mcp-streamable-http](https://github.com/invariantlabs-ai/mcp-streamable-http)\n- [mcp-streamable-http-typescript-server](https://github.com/ferrants/mcp-streamable-http-typescript-server)\n- [http-oauth-mcp-server](https://github.com/NapthaAI/http-oauth-mcp-server)\n\n**Stack:** TypeScript 5.3+ | Node.js 16+ | MCP SDK 1.8.0 | Express.js\n\n---\n\n**🚀 Questions? Issues? PRs welcome!**\n","readmeFilename":"README.md","_rev":"1-ee345db64515840e8b149ed6780fc201"}