Implement zero-friction authentication persistence with MCP user scope
Major breakthrough solving the authentication chicken-and-egg problem: Key Changes: - Copy ~/.claude.json and ~/.claude/ during Docker build for baked-in auth - Add -s user flag to claude mcp add-json for persistent MCP servers - Simplify rebuild logic to prevent unnecessary rebuilds - Update documentation with rebuild instructions Technical Details: - Authentication files placed before USER switch in Dockerfile - MCP configuration now persists across all sessions - Rebuild only occurs when image doesn't exist - Clean separation of build vs runtime concerns Result: Users authenticate once on host, then zero login prompts forever. SMS notifications ready immediately on container start.
This commit is contained in:
parent
d9bf0f4b53
commit
7cd765b756
@ -1,7 +1,7 @@
|
|||||||
# Copy this file to .env and fill in your credentials
|
# Copy this file to .env and fill in your credentials
|
||||||
# The .env file will be baked into the Docker image during build
|
# The .env file will be baked into the Docker image during build
|
||||||
|
|
||||||
# Required for Claude Code
|
# Required for Claude Code if not using via subscription.
|
||||||
ANTHROPIC_API_KEY=your_anthropic_api_key_here
|
ANTHROPIC_API_KEY=your_anthropic_api_key_here
|
||||||
|
|
||||||
# Optional: Twilio credentials for SMS notifications
|
# Optional: Twilio credentials for SMS notifications
|
||||||
|
5
.gitignore
vendored
5
.gitignore
vendored
@ -26,5 +26,10 @@ data/
|
|||||||
*.tmp
|
*.tmp
|
||||||
*.temp
|
*.temp
|
||||||
~*
|
~*
|
||||||
|
|
||||||
|
# Claude authentication files (copied during build)
|
||||||
|
.claude.json
|
||||||
|
.claude/
|
||||||
|
|
||||||
# Environment file with credentials
|
# Environment file with credentials
|
||||||
.env
|
.env
|
||||||
|
18
Dockerfile
18
Dockerfile
@ -39,17 +39,30 @@ RUN chmod +x /app/startup.sh
|
|||||||
# This enables one-time setup - no need for .env in project directories
|
# This enables one-time setup - no need for .env in project directories
|
||||||
COPY .env /app/.env
|
COPY .env /app/.env
|
||||||
|
|
||||||
# Set proper ownership
|
# Copy Claude authentication files from host
|
||||||
|
# Note: These must exist - host must have authenticated Claude Code first
|
||||||
|
COPY .claude.json /tmp/.claude.json
|
||||||
|
COPY .claude /tmp/.claude
|
||||||
|
|
||||||
|
# Move auth files to proper location before switching user
|
||||||
|
RUN cp /tmp/.claude.json /home/claude-user/.claude.json && \
|
||||||
|
cp -r /tmp/.claude/* /home/claude-user/.claude/ && \
|
||||||
|
rm -rf /tmp/.claude*
|
||||||
|
|
||||||
|
# Set proper ownership for everything
|
||||||
RUN chown -R claude-user:claude-user /app /home/claude-user
|
RUN chown -R claude-user:claude-user /app /home/claude-user
|
||||||
|
|
||||||
# Switch to non-root user
|
# Switch to non-root user
|
||||||
USER claude-user
|
USER claude-user
|
||||||
|
|
||||||
|
# Set HOME immediately after switching user
|
||||||
|
ENV HOME=/home/claude-user
|
||||||
|
|
||||||
# Configure MCP server during build if Twilio credentials are provided
|
# Configure MCP server during build if Twilio credentials are provided
|
||||||
RUN bash -c 'source /app/.env && \
|
RUN bash -c 'source /app/.env && \
|
||||||
if [ -n "$TWILIO_ACCOUNT_SID" ] && [ -n "$TWILIO_AUTH_TOKEN" ]; then \
|
if [ -n "$TWILIO_ACCOUNT_SID" ] && [ -n "$TWILIO_AUTH_TOKEN" ]; then \
|
||||||
echo "Configuring Twilio MCP server..." && \
|
echo "Configuring Twilio MCP server..." && \
|
||||||
/usr/local/bin/claude mcp add-json twilio \
|
/usr/local/bin/claude mcp add-json twilio -s user \
|
||||||
"{\"command\":\"npx\",\"args\":[\"-y\",\"@yiyang.1i/sms-mcp-server\"],\"env\":{\"ACCOUNT_SID\":\"$TWILIO_ACCOUNT_SID\",\"AUTH_TOKEN\":\"$TWILIO_AUTH_TOKEN\",\"FROM_NUMBER\":\"$TWILIO_FROM_NUMBER\"}}"; \
|
"{\"command\":\"npx\",\"args\":[\"-y\",\"@yiyang.1i/sms-mcp-server\"],\"env\":{\"ACCOUNT_SID\":\"$TWILIO_ACCOUNT_SID\",\"AUTH_TOKEN\":\"$TWILIO_AUTH_TOKEN\",\"FROM_NUMBER\":\"$TWILIO_FROM_NUMBER\"}}"; \
|
||||||
else \
|
else \
|
||||||
echo "No Twilio credentials found, skipping MCP configuration"; \
|
echo "No Twilio credentials found, skipping MCP configuration"; \
|
||||||
@ -60,7 +73,6 @@ WORKDIR /workspace
|
|||||||
|
|
||||||
# Environment variables will be passed from host
|
# Environment variables will be passed from host
|
||||||
ENV NODE_ENV=production
|
ENV NODE_ENV=production
|
||||||
ENV HOME=/home/claude-user
|
|
||||||
|
|
||||||
# Start both MCP server and Claude Code
|
# Start both MCP server and Claude Code
|
||||||
ENTRYPOINT ["/app/startup.sh"]
|
ENTRYPOINT ["/app/startup.sh"]
|
26
README.md
26
README.md
@ -10,6 +10,15 @@ A Docker container setup for running Claude Code with full autonomous permission
|
|||||||
- Auto-configures Claude settings for seamless operation
|
- Auto-configures Claude settings for seamless operation
|
||||||
- Simple one-command setup and usage
|
- Simple one-command setup and usage
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
**Important**: Before building the Docker image, you must authenticate Claude Code on your host system:
|
||||||
|
1. Install Claude Code: `npm install -g @anthropic-ai/claude-code`
|
||||||
|
2. Run `claude` and complete the authentication flow
|
||||||
|
3. Verify authentication files exist: `ls ~/.claude.json ~/.claude/`
|
||||||
|
|
||||||
|
The Docker build will copy your authentication from these locations.
|
||||||
|
|
||||||
## Quick Start
|
## Quick Start
|
||||||
|
|
||||||
1. **Clone the repository:**
|
1. **Clone the repository:**
|
||||||
@ -157,6 +166,23 @@ Each project gets:
|
|||||||
- `.claude/CLAUDE.md` - Instructions for Claude behavior
|
- `.claude/CLAUDE.md` - Instructions for Claude behavior
|
||||||
- `scratchpad.md` - Project context file
|
- `scratchpad.md` - Project context file
|
||||||
|
|
||||||
|
### Rebuilding the Image
|
||||||
|
|
||||||
|
The Docker image is built only once when you first run `claude-docker`. To force a rebuild:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Remove the existing image
|
||||||
|
docker rmi claude-docker:latest
|
||||||
|
|
||||||
|
# Next run of claude-docker will rebuild
|
||||||
|
claude-docker
|
||||||
|
```
|
||||||
|
|
||||||
|
Rebuild when you:
|
||||||
|
- Update your .env file with new credentials
|
||||||
|
- Update the Claude Docker repository
|
||||||
|
- Want to refresh the authentication files
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
- Docker installed and running
|
- Docker installed and running
|
||||||
|
199
scratchpad.md
199
scratchpad.md
@ -1,171 +1,64 @@
|
|||||||
# Claude Docker Project Scratchpad
|
# Claude Docker Project Scratchpad
|
||||||
|
|
||||||
## Project Overview
|
## Project Overview
|
||||||
Building a Docker container that runs Claude Code with full autonomous permissions and Twilio SMS notifications upon task completion.
|
Docker container for Claude Code with full autonomous permissions, authentication persistence, and Twilio SMS notifications.
|
||||||
|
|
||||||
## What Was Done ✅
|
## ✅ COMPLETED PHASES
|
||||||
**Phase 1 - Complete MVP:**
|
|
||||||
- GitHub repository created: https://github.com/VishalJ99/claude-docker
|
### Phase 1 - MVP (Complete)
|
||||||
- Docker setup with Claude Code + Twilio MCP integration
|
- Docker setup with Claude Code + Twilio MCP integration
|
||||||
- Wrapper script (`claude-docker.sh`) for easy invocation
|
- Wrapper script for easy invocation
|
||||||
- Auto .claude directory setup with MCP configuration
|
- Auto .claude directory setup
|
||||||
- Installation script for zshrc alias
|
|
||||||
- SMS notifications via Twilio MCP server
|
|
||||||
- Full autonomous permissions with --dangerously-skip-permissions
|
- Full autonomous permissions with --dangerously-skip-permissions
|
||||||
- Context persistence via scratchpad.md files
|
- Context persistence via scratchpad.md files
|
||||||
- Complete documentation and examples
|
|
||||||
- **✅ WORKING** - All startup issues resolved, Docker container launches Claude Code successfully
|
|
||||||
|
|
||||||
## Next Steps 🎯
|
### Phase 2 - Authentication Persistence (Complete)
|
||||||
**Phase 2 - Security & Persistence Enhancements:**
|
- **SOLVED**: Authentication files copied during Docker build
|
||||||
|
- **SOLVED**: MCP servers persist with user scope
|
||||||
|
- **SOLVED**: No unnecessary rebuilds
|
||||||
|
- **RESULT**: Zero-friction experience - no login prompts, SMS ready instantly
|
||||||
|
|
||||||
### 1. Authentication Persistence (HIGH Priority) - ✅ COMPLETED
|
## 🎯 CURRENT FOCUS
|
||||||
**Problem:** Need to re-login to Claude Code every time container starts
|
**Phase 3 - Smart SMS Notifications:**
|
||||||
|
|
||||||
**Research Findings:**
|
### Next Task: Prompt Engineering for SMS Notifications
|
||||||
- Claude Code stores auth tokens in `~/.claude/.credentials.json`
|
**Goal:** Configure Claude to automatically send completion SMS to `$TWILIO_TO_NUMBER`
|
||||||
- Known issues: #1222 (persistent auth warnings), #1676 (logout after restart)
|
|
||||||
- The devcontainer mounts `/home/node/.claude` for config persistence
|
|
||||||
- But auth tokens are NOT persisted properly even in devcontainer
|
|
||||||
|
|
||||||
**Implementation Completed:**
|
**Implementation Plan:**
|
||||||
1. **Created persistent directory structure:**
|
1. Update CLAUDE.md template with SMS notification instructions
|
||||||
- Host: `~/.claude-docker/claude-home`
|
2. Add completion detection logic
|
||||||
- Container: `/home/claude-user/.claude`
|
3. Integrate with existing Twilio MCP server
|
||||||
- Mounted with read/write permissions
|
4. Test notification flow
|
||||||
|
|
||||||
2. **Updated Docker setup:**
|
## 📚 KEY INSIGHTS FROM AUTHENTICATION JOURNEY
|
||||||
- Created non-root user `claude-user` for better security
|
|
||||||
- Set proper ownership and permissions
|
|
||||||
- Added volume mount for Claude home directory
|
|
||||||
|
|
||||||
3. **Enhanced startup script:**
|
### Critical Discovery: ~/.claude.json + MCP Scope
|
||||||
- Checks for existing `.credentials.json` on startup
|
- Claude Code requires BOTH `~/.claude.json` (user profile) AND `~/.claude/.credentials.json` (tokens)
|
||||||
- Notifies user if auth exists or login needed
|
- MCP servers default to "local" scope (project-specific) - need "user" scope for persistence
|
||||||
- Credentials persist across container restarts
|
- Authentication can be baked into Docker image during build
|
||||||
|
- Simple rebuild logic (only if image missing) prevents unnecessary rebuilds
|
||||||
|
|
||||||
**Result:** Users now login once and authentication persists forever!
|
### Technical Implementation
|
||||||
|
- Copy auth files during Docker build, not runtime mounting
|
||||||
|
- Use `-s user` flag for MCP persistence across sessions
|
||||||
|
- Files placed at correct locations before user switch in Dockerfile
|
||||||
|
|
||||||
### 2. Network Security (High Priority) - PLANNED
|
## 🔮 FUTURE ENHANCEMENTS
|
||||||
**Implementation based on devcontainer's init-firewall.sh:**
|
- Network security with firewall (iptables + ipset)
|
||||||
|
- Shell history persistence between sessions
|
||||||
**Key Components:**
|
|
||||||
1. **Firewall Script Features:**
|
|
||||||
- Uses iptables with default DROP policy
|
|
||||||
- ipset for managing allowed IP ranges
|
|
||||||
- Dynamic IP resolution for allowed domains
|
|
||||||
- Verification of connectivity post-setup
|
|
||||||
|
|
||||||
2. **Allowed Domains Configuration:**
|
|
||||||
```yaml
|
|
||||||
allowed_domains:
|
|
||||||
- api.anthropic.com # Claude API
|
|
||||||
- api.twilio.com # SMS notifications
|
|
||||||
- github.com # Git operations
|
|
||||||
- raw.githubusercontent.com
|
|
||||||
- registry.npmjs.org # Package management
|
|
||||||
- pypi.org # Python packages
|
|
||||||
|
|
||||||
blocked_paths: # File system restrictions
|
|
||||||
- /etc
|
|
||||||
- /root
|
|
||||||
- ~/.ssh
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **User-Friendly Setup:**
|
|
||||||
- Simple YAML config file for rules
|
|
||||||
- Easy enable/disable of firewall
|
|
||||||
- Logging of blocked attempts
|
|
||||||
- Graceful degradation if firewall fails
|
|
||||||
|
|
||||||
### 3. Shell History Persistence (Medium Priority)
|
|
||||||
- Add persistent bash/zsh history between container sessions
|
|
||||||
- Mount history file to host directory
|
|
||||||
- Implement history management similar to Claude dev container
|
|
||||||
- Ensure commands persist across sessions
|
|
||||||
|
|
||||||
### 4. Additional Persistence Features (Medium Priority)
|
|
||||||
- Persistent npm cache for faster startups
|
|
||||||
- Git configuration persistence
|
- Git configuration persistence
|
||||||
- Custom shell aliases and environment
|
|
||||||
|
|
||||||
## Direction & Vision
|
## 📋 DECISIONS LOG
|
||||||
**Security-First Autonomous Environment:**
|
- MCP integration using user scope for persistence
|
||||||
- Maintain full Claude autonomy within projects
|
- Authentication files baked into Docker image at build time
|
||||||
- Add network security layer to prevent unauthorized access
|
- Single container approach (no Docker Compose)
|
||||||
- Enhance user experience with persistent shell history
|
- Simplified rebuild logic (only when image missing)
|
||||||
- Keep container lightweight and fast
|
- SMS via `@yiyang.1i/sms-mcp-server` with Auth Token
|
||||||
- Ensure easy setup and maintenance
|
|
||||||
|
|
||||||
## Decisions Log
|
## 🔗 QUICK REFERENCES
|
||||||
- Using MCP (Model Context Protocol) for Twilio integration instead of direct API
|
- **Install:** `./scripts/install.sh`
|
||||||
- Single container approach (no Docker Compose needed)
|
- **Usage:** `claude-docker` (from any project directory)
|
||||||
- API keys via .env file
|
- **Config:** `~/.claude-docker/.env`
|
||||||
- Context persistence via scratchpad.md files
|
- **Force rebuild:** `docker rmi claude-docker:latest`
|
||||||
- Simplified settings.json to only include MCP config (no redundant allowedTools)
|
- **SMS command:** `twilio__send_text`
|
||||||
- **NEW:** Adding firewall for network security
|
- **Repository:** https://github.com/VishalJ99/claude-docker
|
||||||
- **NEW:** Adding shell history persistence like Claude dev container
|
|
||||||
- **NEW (2024-12-06):** Focus on auth persistence first before firewall implementation
|
|
||||||
- **COMPLETED (2024-12-06):** Auth persistence via mounted ~/.claude directory
|
|
||||||
|
|
||||||
## Notes & Context
|
|
||||||
- Repository: https://github.com/VishalJ99/claude-docker
|
|
||||||
- Using --dangerously-skip-permissions flag for full autonomy
|
|
||||||
- Twilio MCP server runs via Claude's MCP config (not as separate process)
|
|
||||||
- Uses @twilio-alpha/mcp package with API Key/Secret authentication
|
|
||||||
- Container auto-removes on exit for clean state
|
|
||||||
- Project directory mounted at /workspace
|
|
||||||
- Need to research Claude dev container's init-firewall.sh implementation
|
|
||||||
- Need to research their history persistence mechanism
|
|
||||||
- **Fixed startup issues:**
|
|
||||||
- Changed executable from `claude-code` to `claude` in startup.sh
|
|
||||||
- Fixed .env parsing to handle comments properly using `set -a`/`source`
|
|
||||||
- Added explicit PATH for npm global binaries
|
|
||||||
- Maintained separation: `claude-docker` (host) vs `claude` (container)
|
|
||||||
- **Current working state:** Container launches successfully, authentication required each session
|
|
||||||
- **Auth Persistence Research (2024-12-06):**
|
|
||||||
- Claude Code has known issues with auth persistence
|
|
||||||
- Tokens stored in temp locations that get cleared
|
|
||||||
- Need to find exact token storage location and persist it
|
|
||||||
|
|
||||||
## MCP Integration Update (2024-12-17)
|
|
||||||
|
|
||||||
### ✅ COMPLETED: Simplified Twilio MCP Integration
|
|
||||||
|
|
||||||
**What Changed:**
|
|
||||||
1. **Switched MCP Server:** From `@twilio-alpha/mcp` (API Key/Secret) to `@yiyang.1i/sms-mcp-server` (Auth Token)
|
|
||||||
2. **Simplified Configuration:** MCP setup now happens during Docker build instead of runtime
|
|
||||||
3. **Removed Complexity:** No more mcp-config.json or environment variable substitution
|
|
||||||
|
|
||||||
**Implementation Details:**
|
|
||||||
1. **Updated .env.example:**
|
|
||||||
- Removed: `TWILIO_API_KEY` and `TWILIO_API_SECRET`
|
|
||||||
- Added: `TWILIO_AUTH_TOKEN`
|
|
||||||
- Kept: `TWILIO_ACCOUNT_SID`, `TWILIO_FROM_NUMBER`, `TWILIO_TO_NUMBER`
|
|
||||||
|
|
||||||
2. **Updated Dockerfile:**
|
|
||||||
- Removed global installation of `@twilio-alpha/mcp`
|
|
||||||
- Added MCP configuration during build using `claude mcp add-json` command
|
|
||||||
- MCP server is configured if Twilio credentials are present in .env
|
|
||||||
|
|
||||||
3. **Simplified startup.sh:**
|
|
||||||
- Removed all MCP configuration logic
|
|
||||||
- Just loads environment variables and starts Claude
|
|
||||||
- Shows Twilio status on startup
|
|
||||||
|
|
||||||
4. **Removed Files:**
|
|
||||||
- `config/mcp-config.json` (no longer needed)
|
|
||||||
- `config/` directory (now empty)
|
|
||||||
|
|
||||||
**Result:**
|
|
||||||
- MCP configuration is baked into the Docker image at build time
|
|
||||||
- No runtime configuration needed
|
|
||||||
- Simpler, more reliable setup
|
|
||||||
- SMS capability available via `twilio__send_text` command
|
|
||||||
|
|
||||||
## Quick References
|
|
||||||
- Install: `./scripts/install.sh`
|
|
||||||
- Usage: `claude-docker` (from any project directory)
|
|
||||||
- Config: `~/.claude-docker/.env`
|
|
||||||
- Repo: https://github.com/VishalJ99/claude-docker
|
|
||||||
- Claude dev container: https://github.com/anthropics/claude-code/tree/main/.devcontainer
|
|
@ -38,28 +38,24 @@ fi
|
|||||||
NEED_REBUILD=false
|
NEED_REBUILD=false
|
||||||
|
|
||||||
if ! docker images | grep -q "claude-docker"; then
|
if ! docker images | grep -q "claude-docker"; then
|
||||||
echo "Building Claude Docker image with your user permissions..."
|
echo "Building Claude Docker image for first time..."
|
||||||
NEED_REBUILD=true
|
NEED_REBUILD=true
|
||||||
elif ! docker image inspect claude-docker:latest | grep -q "USER_UID.*$(id -u)" 2>/dev/null; then
|
|
||||||
echo "Rebuilding Claude Docker image to match your user permissions..."
|
|
||||||
NEED_REBUILD=true
|
|
||||||
elif [ -f "$ENV_FILE" ]; then
|
|
||||||
# Check if .env is newer than the Docker image
|
|
||||||
IMAGE_CREATED=$(docker inspect -f '{{.Created}}' claude-docker:latest 2>/dev/null)
|
|
||||||
if [ -n "$IMAGE_CREATED" ]; then
|
|
||||||
IMAGE_TIMESTAMP=$(date -d "$IMAGE_CREATED" +%s 2>/dev/null || date -j -f "%Y-%m-%dT%H:%M:%S" "${IMAGE_CREATED%%.*}" +%s 2>/dev/null)
|
|
||||||
ENV_TIMESTAMP=$(stat -c %Y "$ENV_FILE" 2>/dev/null || stat -f %m "$ENV_FILE" 2>/dev/null)
|
|
||||||
|
|
||||||
if [ -n "$IMAGE_TIMESTAMP" ] && [ -n "$ENV_TIMESTAMP" ] && [ "$ENV_TIMESTAMP" -gt "$IMAGE_TIMESTAMP" ]; then
|
|
||||||
echo "⚠️ .env file has been updated since last build"
|
|
||||||
echo " Rebuilding to include new credentials..."
|
|
||||||
NEED_REBUILD=true
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$NEED_REBUILD" = true ]; then
|
if [ "$NEED_REBUILD" = true ]; then
|
||||||
|
# Copy authentication files to build context
|
||||||
|
if [ -f "$HOME/.claude.json" ]; then
|
||||||
|
cp "$HOME/.claude.json" "$PROJECT_ROOT/.claude.json"
|
||||||
|
fi
|
||||||
|
if [ -d "$HOME/.claude" ]; then
|
||||||
|
cp -r "$HOME/.claude" "$PROJECT_ROOT/.claude"
|
||||||
|
fi
|
||||||
|
|
||||||
docker build --build-arg USER_UID=$(id -u) --build-arg USER_GID=$(id -g) -t claude-docker:latest "$PROJECT_ROOT"
|
docker build --build-arg USER_UID=$(id -u) --build-arg USER_GID=$(id -g) -t claude-docker:latest "$PROJECT_ROOT"
|
||||||
|
|
||||||
|
# Clean up copied auth files
|
||||||
|
rm -f "$PROJECT_ROOT/.claude.json"
|
||||||
|
rm -rf "$PROJECT_ROOT/.claude"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Ensure the claude-home directory exists
|
# Ensure the claude-home directory exists
|
||||||
|
@ -1,59 +0,0 @@
|
|||||||
#!/usr/bin/env node
|
|
||||||
|
|
||||||
// Test script to verify Twilio SMS functionality
|
|
||||||
const accountSid = process.env.TWILIO_ACCOUNT_SID;
|
|
||||||
const authToken = process.env.TWILIO_AUTH_TOKEN;
|
|
||||||
const fromNumber = process.env.TWILIO_FROM_NUMBER;
|
|
||||||
const toNumber = process.env.TWILIO_TO_NUMBER;
|
|
||||||
|
|
||||||
console.log('Twilio Test Configuration:');
|
|
||||||
console.log(`Account SID: ${accountSid?.substring(0, 10)}...`);
|
|
||||||
console.log(`Auth Token: ${authToken ? '***' + authToken.substring(authToken.length - 4) : 'Not set'}`);
|
|
||||||
console.log(`From: ${fromNumber}`);
|
|
||||||
console.log(`To: ${toNumber}`);
|
|
||||||
|
|
||||||
// Using Twilio REST API directly
|
|
||||||
const https = require('https');
|
|
||||||
|
|
||||||
const auth = Buffer.from(`${accountSid}:${authToken}`).toString('base64');
|
|
||||||
const data = new URLSearchParams({
|
|
||||||
To: toNumber,
|
|
||||||
From: fromNumber,
|
|
||||||
Body: 'MCP is working! This is a test message from Claude Docker.'
|
|
||||||
});
|
|
||||||
|
|
||||||
const options = {
|
|
||||||
hostname: 'api.twilio.com',
|
|
||||||
port: 443,
|
|
||||||
path: `/2010-04-01/Accounts/${accountSid}/Messages.json`,
|
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
'Authorization': `Basic ${auth}`,
|
|
||||||
'Content-Type': 'application/x-www-form-urlencoded',
|
|
||||||
'Content-Length': data.toString().length
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const req = https.request(options, (res) => {
|
|
||||||
let body = '';
|
|
||||||
res.on('data', (chunk) => body += chunk);
|
|
||||||
res.on('end', () => {
|
|
||||||
if (res.statusCode === 201) {
|
|
||||||
console.log('\n✅ SMS sent successfully!');
|
|
||||||
const response = JSON.parse(body);
|
|
||||||
console.log(`Message SID: ${response.sid}`);
|
|
||||||
console.log(`Status: ${response.status}`);
|
|
||||||
} else {
|
|
||||||
console.error('\n❌ Failed to send SMS');
|
|
||||||
console.error(`Status: ${res.statusCode}`);
|
|
||||||
console.error(`Response: ${body}`);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
req.on('error', (e) => {
|
|
||||||
console.error(`Problem with request: ${e.message}`);
|
|
||||||
});
|
|
||||||
|
|
||||||
req.write(data.toString());
|
|
||||||
req.end();
|
|
Loading…
Reference in New Issue
Block a user