A remote HTTP Model Context Protocol (MCP) server that provides access to AWS services including DynamoDB and S3. This server exposes prompts, resources, and tools via HTTP endpoints with bearer token authentication.
- GET /: Server information and capabilities
- GET /health: Health check endpoint
- GET /mcp/prompts: List available prompts
- POST /mcp/prompts/:name: Get specific prompt content
- GET /mcp/resources: List S3 resources (requires auth)
- GET /mcp/resources/*: Read specific S3 resource (requires auth)
- GET /mcp/tools: List available tools
- POST /mcp/tools/:name: Execute specific tool (requires auth)
- Uses Bearer token authentication
- AWS_SECRET_ACCESS_KEY is passed via
Authorization: Bearer <secret_key>
header - Other AWS credentials are configured via environment variables
- analyze-data: Analyze data from DynamoDB and S3 resources
- data-summary: Generate a summary of available data sources
- S3 Objects: Access and read objects from your S3 bucket
- Automatic MIME type detection
- Object metadata (size, last modified)
- dynamodb-get: Get an item by key
- dynamodb-put: Store an item
- dynamodb-delete: Delete an item by key
- dynamodb-query: Query items with conditions
- s3-get: Download object content
- s3-put: Upload object content
- s3-delete: Delete an object
- s3-move: Move/rename an object
Set the following environment variables on your Val Town:
AWS_REGION=us-east-1 AWS_ACCESS_KEY_ID=your-access-key-id S3_BUCKET=your-bucket-name DYNAMODB_TABLE=your-table-name MCP_SERVER_NAME=aws-mcp-server MCP_SERVER_VERSION=1.0.0
Note: AWS_SECRET_ACCESS_KEY
is NOT set as an environment variable. Instead, it's passed via the Authorization header for security.
- Deploy to Val Town as an HTTP val
- Set the required environment variables
- The server will be available at your Val Town URL
All authenticated endpoints require the Authorization header:
Authorization: Bearer your-aws-secret-access-key
curl https://your-val-town-url.web.val.run/
curl https://your-val-town-url.web.val.run/mcp/prompts
curl -X POST https://your-val-town-url.web.val.run/mcp/prompts/analyze-data \ -H "Content-Type: application/json" \ -d '{"table_key": "user123", "s3_key": "data/analytics.json"}'
curl https://your-val-town-url.web.val.run/mcp/resources \ -H "Authorization: Bearer your-aws-secret-access-key"
curl "https://your-val-town-url.web.val.run/mcp/resources/s3://your-bucket/path/to/file.txt" \ -H "Authorization: Bearer your-aws-secret-access-key"
curl https://your-val-town-url.web.val.run/mcp/tools
# Get an item curl -X POST https://your-val-town-url.web.val.run/mcp/tools/dynamodb-get \ -H "Authorization: Bearer your-aws-secret-access-key" \ -H "Content-Type: application/json" \ -d '{"key": {"id": "user123"}}' # Put an item curl -X POST https://your-val-town-url.web.val.run/mcp/tools/dynamodb-put \ -H "Authorization: Bearer your-aws-secret-access-key" \ -H "Content-Type: application/json" \ -d '{"item": {"id": "user123", "name": "John Doe", "email": "john@example.com"}}' # Query items curl -X POST https://your-val-town-url.web.val.run/mcp/tools/dynamodb-query \ -H "Authorization: Bearer your-aws-secret-access-key" \ -H "Content-Type: application/json" \ -d '{"keyConditionExpression": "id = :id", "expressionAttributeValues": {":id": "user123"}}' # Delete an item curl -X POST https://your-val-town-url.web.val.run/mcp/tools/dynamodb-delete \ -H "Authorization: Bearer your-aws-secret-access-key" \ -H "Content-Type: application/json" \ -d '{"key": {"id": "user123"}}'
# Get object content curl -X POST https://your-val-town-url.web.val.run/mcp/tools/s3-get \ -H "Authorization: Bearer your-aws-secret-access-key" \ -H "Content-Type: application/json" \ -d '{"key": "documents/report.txt"}' # Upload content curl -X POST https://your-val-town-url.web.val.run/mcp/tools/s3-put \ -H "Authorization: Bearer your-aws-secret-access-key" \ -H "Content-Type: application/json" \ -d '{"key": "documents/new-file.txt", "content": "Hello, World!", "contentType": "text/plain"}' # Move/rename object curl -X POST https://your-val-town-url.web.val.run/mcp/tools/s3-move \ -H "Authorization: Bearer your-aws-secret-access-key" \ -H "Content-Type: application/json" \ -d '{"sourceKey": "old-location/file.txt", "destinationKey": "new-location/file.txt"}' # Delete object curl -X POST https://your-val-town-url.web.val.run/mcp/tools/s3-delete \ -H "Authorization: Bearer your-aws-secret-access-key" \ -H "Content-Type: application/json" \ -d '{"key": "documents/old-file.txt"}'
To integrate with MCP clients like Claude Desktop, you can create a client that makes HTTP requests to these endpoints. Here's an example configuration:
{ "mcpServers": { "aws-http-mcp-server": { "command": "node", "args": ["mcp-http-client.js"], "env": { "MCP_SERVER_URL": "https://your-val-town-url.web.val.run", "AWS_SECRET_ACCESS_KEY": "${AWS_SECRET_ACCESS_KEY}" } } } }
- Bearer Token Authentication: AWS_SECRET_ACCESS_KEY is passed via Authorization header, not stored in environment variables
- HTTPS Only: Always use HTTPS in production to protect the bearer token
- IAM Permissions: Use IAM roles with minimal required permissions
- Token Rotation: Regularly rotate your AWS secret access keys
- Rate Limiting: Consider implementing rate limiting for production use
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:GetObject", "s3:PutObject", "s3:DeleteObject", "s3:ListBucket" ], "Resource": [ "arn:aws:s3:::your-bucket-name", "arn:aws:s3:::your-bucket-name/*" ] } ] }
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "dynamodb:GetItem", "dynamodb:PutItem", "dynamodb:DeleteItem", "dynamodb:Query", "dynamodb:Scan" ], "Resource": "arn:aws:dynamodb:region:account:table/your-table-name" } ] }
The server includes comprehensive error handling for:
- Missing or invalid Authorization headers
- AWS service errors
- Invalid parameters
- Network connectivity issues
All errors are properly formatted and returned as JSON with appropriate HTTP status codes:
401
: Authentication errors400
: Bad request (invalid parameters)404
: Resource or tool not found500
: Server errors (AWS service errors, etc.)
{ "content": [ { "type": "text", "text": "Response content here" } ] }
{ "error": "Error message description" }
The server provides a health check endpoint:
curl https://your-val-town-url.web.val.run/health
Response:
{ "status": "healthy", "timestamp": "2024-01-01T00:00:00.000Z" }