# s3-mcp-server

MCP server for AWS S3 (and S3-compatible) object storage. Provides tools to list, read, upload, delete, and copy objects — designed for website hosting maintenance and page management.

## Features

- **Default read-only** — write/delete tools are disabled unless `ALLOW_WRITE=true` is set
- **S3-compatible** — works with AWS S3, MinIO, Cloudflare R2, Backblaze B2, and other S3-compatible services via `AWS_ENDPOINT_URL`
- **Default bucket** — configure once via `S3_BUCKET`, or pass `bucket` per tool call

## Tools

### Read-only (always available)

| Tool | Description |
|------|-------------|
| `s3_list_buckets` | List all accessible buckets |
| `s3_list_objects` | List objects with prefix filter, delimiter, and cursor pagination |
| `s3_head_object` | Get object metadata (size, content-type, ETag) without downloading |
| `s3_get_object` | Download object content (text files as UTF-8, binary as base64) |
| `s3_get_object_url` | Return the direct S3 access URL for an object |
| `s3_get_object_cdn_url` | Return the CDN URL for an object (requires `CDN_DOMAIN`) |

### Write (requires `ALLOW_WRITE=true`)

| Tool | Description |
|------|-------------|
| `s3_put_object` | Upload or overwrite an object; auto-detects content-type from extension |
| `s3_upload_file` | Upload a local file as binary (supports images, fonts, PDFs, etc.) |
| `s3_delete_object` | Delete a single object |
| `s3_delete_objects` | Batch delete up to 1000 objects in one request |
| `s3_copy_object` | Copy an object within or between buckets (rename, duplicate) |

## Configuration

All sensitive configuration is provided via environment variables in the MCP client config — never hard-coded.

| Variable | Required | Default | Description |
|----------|----------|---------|-------------|
| `AWS_ACCESS_KEY_ID` | **Yes** | — | AWS access key ID |
| `AWS_SECRET_ACCESS_KEY` | **Yes** | — | AWS secret access key |
| `AWS_REGION` | No | `us-east-1` | AWS region |
| `AWS_ENDPOINT_URL` | No | — | Custom endpoint for S3-compatible services |
| `S3_BUCKET` | No | — | Default bucket (tools accept `bucket` param as override) |
| `ALLOW_WRITE` | No | `false` | Set to `"true"` to enable write/delete tools |
| `CDN_DOMAIN` | No | — | CDN domain for `s3_get_object_cdn_url` (e.g. `cdn.example.com`) |

## Usage

### Install and build

```bash
npm install
npm run build
```

### Claude Desktop config (`claude_desktop_config.json`)

**Read-only mode (default):**

```json
{
  "mcpServers": {
    "s3": {
      "command": "node",
      "args": ["/path/to/s3-mcp-server/dist/index.js"],
      "env": {
        "AWS_ACCESS_KEY_ID": "AKIAIOSFODNN7EXAMPLE",
        "AWS_SECRET_ACCESS_KEY": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
        "AWS_REGION": "us-east-1",
        "S3_BUCKET": "my-website-bucket"
      }
    }
  }
}
```

**Read-write mode:**

```json
{
  "mcpServers": {
    "s3": {
      "command": "node",
      "args": ["/path/to/s3-mcp-server/dist/index.js"],
      "env": {
        "AWS_ACCESS_KEY_ID": "AKIAIOSFODNN7EXAMPLE",
        "AWS_SECRET_ACCESS_KEY": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
        "AWS_REGION": "us-east-1",
        "S3_BUCKET": "my-website-bucket",
        "ALLOW_WRITE": "true",
        "CDN_DOMAIN": "cdn.example.com"
      }
    }
  }
}
```

**S3-compatible service (e.g. Cloudflare R2):**

```json
{
  "mcpServers": {
    "s3": {
      "command": "node",
      "args": ["/path/to/s3-mcp-server/dist/index.js"],
      "env": {
        "AWS_ACCESS_KEY_ID": "<R2 Access Key ID>",
        "AWS_SECRET_ACCESS_KEY": "<R2 Secret Access Key>",
        "AWS_REGION": "auto",
        "AWS_ENDPOINT_URL": "https://<account-id>.r2.cloudflarestorage.com",
        "S3_BUCKET": "my-site",
        "ALLOW_WRITE": "true"
      }
    }
  }
}
```

## Development

```bash
npm run dev    # watch mode with tsx
npm run build  # compile to dist/
npm start      # run compiled server
```

## Security notes

- IAM credentials are read from environment variables injected by the MCP client — they are never stored in code or config files checked into version control
- Write tools (`s3_put_object`, `s3_delete_object`, `s3_delete_objects`, `s3_copy_object`) are only registered when `ALLOW_WRITE=true`; they are completely absent from the tool list in read-only mode
- For production use, scope the IAM policy to the minimum required permissions (`s3:GetObject`, `s3:ListBucket`, plus `s3:PutObject`, `s3:DeleteObject` only when write is needed)
