• Townie
    AI
  • Blog
  • Docs
  • Pricing
  • We’re hiring!
Log inSign up
c15r

c15r

ContextualLite

Public
Like
ContextualLite
Home
Code
3
src
5
README.md
H
index.ts
Branches
2
Pull requests
Remixes
History
Environment variables
7
Val Town is a collaborative website to build and scale JavaScript apps.
Deploy APIs, crons, & store data – all from the browser, and deployed in milliseconds.
Sign up now
Code
/
README.md
Code
/
README.md
Search
6/13/2025
Viewing readonly version of main branch: v308
View latest version
README.md

Remote HTTP AWS MCP Server

A remote HTTP Model Context Protocol (MCP) server that provides access to AWS services including DynamoDB and S3. This server now uses the official MCP SDK for JSON-RPC handling and exposes prompts, resources, and tools via both JSON-RPC and legacy HTTP endpoints with bearer token authentication.

Project Structure

The codebase is organized into a clean, modular structure:

├── index.ts                    # Main HTTP entry point
├── src/
│   ├── auth/
│   │   └── auth-manager.ts     # Authentication and namespace management
│   ├── aws/
│   │   └── clients.ts          # AWS client configuration utilities
│   ├── mcp/
│   │   ├── handler.ts          # Main MCP request handler
│   │   └── protocol-handlers.ts # MCP protocol-specific handlers (prompts, resources)
│   ├── storage/
│   │   ├── kv-store.ts         # Namespaced DynamoDB key-value store
│   │   └── files-store.ts      # Namespaced S3 files store
│   └── tools/
│       ├── definitions.ts      # Tool schema definitions
│       └── handlers/
│           ├── index.ts        # Unified tool handlers export
│           ├── kv-tools.ts     # Key-value store tool handlers
│           ├── files-tools.ts  # Files store tool handlers
│           └── code-tools.ts   # Code execution tool handlers
└── README.md

This modular structure provides:

  • Separation of concerns: Each component has a single responsibility
  • Easy testing: Individual components can be tested in isolation
  • Maintainability: Changes to one area don't affect others
  • Extensibility: New tools and handlers can be easily added

Features

JSON-RPC Endpoint (Recommended)

  • POST /mcp: Primary JSON-RPC endpoint using MCP SDK for all operations
  • Supports all MCP operations: prompts, resources, and tools
  • Proper JSON-RPC 2.0 protocol compliance
  • Batch request support

Legacy HTTP Endpoints (Deprecated)

  • GET /: Server information and capabilities
  • GET /health: Health check endpoint
  • GET /mcp/prompts: List available prompts (deprecated)
  • POST /mcp/prompts/:name: Get specific prompt content (deprecated)
  • GET /mcp/resources: List S3 resources (deprecated, requires auth)
  • GET /mcp/resources/*: Read specific S3 resource (deprecated, requires auth)
  • GET /mcp/tools: List available tools (deprecated)
  • POST /mcp/tools/:name: Execute specific tool (deprecated, requires auth)

Authentication

  • Uses Bearer token authentication
  • AWS_SECRET_ACCESS_KEY is passed via Authorization: Bearer <secret_key> header
  • Other AWS credentials are configured via environment variables
  • User Isolation: Each bearer token creates an isolated namespace for data storage
    • KV Store operations are automatically namespaced per user
    • Files Store operations are automatically namespaced per user
    • Resources (file listings) are automatically filtered per user namespace
  • Demo Mode: Requests without valid authentication use a shared "demo" namespace with limited capabilities

Prompts

  • analyze-data: Analyze data from DynamoDB and S3 resources
  • data-summary: Generate a summary of available data sources

Resources

  • Files: Access and read files from your personal file store
  • Automatic MIME type detection
  • File metadata (size, last modified, version information)
  • Namespace isolation per user

Tools

Key-Value Store Operations (Namespaced)

  • kv-get: Get a value by key from your personal key-value store
  • kv-put: Store a key-value pair in your personal key-value store
  • kv-delete: Delete a key-value pair from your personal key-value store
  • kv-list: List keys in your personal key-value store with optional prefix filter
  • kv-query: Query key-value pairs by key pattern from your personal key-value store

Files Store Operations (Namespaced)

  • files-get: Get a file by key from your personal file store (supports versioning)
  • files-put: Store a file in your personal file store
  • files-delete: Delete a file from your personal file store (supports version-specific deletion)
  • files-list: List files in your personal file store with optional prefix filter
  • files-list-versions: List all versions of files in your personal file store
  • files-move: Move/rename a file within your personal file store
  • files-copy: Copy a file within your personal file store
  • files-exists: Check if a file exists in your personal file store
  • files-metadata: Get metadata for a file in your personal file store (supports versioning)

Code Execution

  • code-exec: Execute JavaScript/TypeScript code with access to all MCP tools. Code can be provided directly as a string or referenced via files store key

Skill Management

  • register-skill: Register a stored code file as a reusable skill tool with custom input schema
  • unregister-skill: Remove a previously registered skill
  • list-skills: List all registered skills for the current user
  • [user-skills]: Dynamically registered skills appear as individual tools with their own schemas

Code Execution Feature

The code-exec tool allows you to execute JavaScript/TypeScript code with full access to all MCP tools (KV store and Files store operations). This enables powerful automation and data processing workflows.

Skill Management System

The skill management system allows you to register stored code files as reusable tools with custom input schemas. Once registered, skills appear as individual tools in the tools list and can be called like any other MCP tool.

Skill Registration

Use the register-skill tool to register a code file as a skill:

{ "name": "data-analyzer", "description": "Analyzes data from KV store and generates reports", "fileKey": "skills/data-analyzer.js", "inputSchema": { "type": "object", "properties": { "dataKey": { "type": "string", "description": "Key of data to analyze" }, "reportType": { "type": "string", "enum": ["summary", "detailed"], "description": "Type of report to generate" } }, "required": ["dataKey"] } }

Skill Management Tools

  • register-skill: Register a new skill from a files store key
  • unregister-skill: Remove a registered skill
  • list-skills: List all your registered skills

Using Registered Skills

Once registered, skills appear in the tools list and can be called directly:

{ "jsonrpc": "2.0", "method": "tools/call", "params": { "name": "data-analyzer", "arguments": { "dataKey": "user-data-2024", "reportType": "detailed" } }, "id": 1 }

Code Requirements

Your code must define an async execute function that accepts two parameters:

  • input: Object containing input parameters for your script
  • tools: Object containing all available MCP tools as callable functions
async function execute(input, tools) { // Your code logic here const result = await tools["kv-get"]({key: input.key}); return { message: "Processing complete", data: result }; }

Available Tools in Code Context

Within your executed code, you have access to all MCP tools via the tools object:

  • tools["kv-get"](args) - Get from your personal key-value store
  • tools["kv-put"](args) - Put to your personal key-value store
  • tools["kv-delete"](args) - Delete from your personal key-value store
  • tools["kv-list"](args) - List keys in your personal key-value store
  • tools["kv-query"](args) - Query your personal key-value store
  • tools["files-get"](args) - Get file from your personal file store
  • tools["files-put"](args) - Put file to your personal file store
  • tools["files-delete"](args) - Delete file from your personal file store
  • tools["files-list"](args) - List files in your personal file store
  • tools["files-list-versions"](args) - List file versions in your personal file store
  • tools["files-move"](args) - Move file in your personal file store
  • tools["files-copy"](args) - Copy file in your personal file store
  • tools["files-exists"](args) - Check if file exists in your personal file store
  • tools["files-metadata"](args) - Get file metadata from your personal file store

Two Execution Modes

1. Direct Code Execution

Provide the code directly in the request:

{ "code": "async function execute(input, tools) { /* your code */ }", "input": { "param1": "value1" } }

2. Files Store Code Execution

Store your code in your personal file store and reference it by key:

{ "key": "scripts/my-processor.js", "input": { "param1": "value1" } }

This approach is ideal for:

  • Reusable scripts and workflows
  • Version control of automation code (files store supports versioning)
  • Sharing scripts across different executions
  • Complex multi-function scripts
  • Personal script libraries isolated per user

Security Considerations

  • Code execution runs in a sandboxed environment
  • No access to global objects or external network calls
  • Only MCP tools are available for external operations
  • All AWS operations use the same authentication as other MCP tools

Setup

Environment Variables

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.

DynamoDB Table Schema

The KV Store requires a DynamoDB table with the following schema:

Table Configuration:

  • Partition Key: pk (String) - Contains the user namespace
  • Sort Key: sk (String) - Contains the user's key
  • Billing Mode: On-demand or Provisioned (your choice)
  • TTL: Optional - Set TTL attribute to ttl if you want automatic expiration

Example AWS CLI command to create the table:

aws dynamodb create-table \ --table-name your-table-name \ --attribute-definitions \ AttributeName=pk,AttributeType=S \ AttributeName=sk,AttributeType=S \ --key-schema \ AttributeName=pk,KeyType=HASH \ AttributeName=sk,KeyType=RANGE \ --billing-mode PAY_PER_REQUEST

Example CloudFormation template:

DynamoDBTable: Type: AWS::DynamoDB::Table Properties: TableName: your-table-name AttributeDefinitions: - AttributeName: pk AttributeType: S - AttributeName: sk AttributeType: S KeySchema: - AttributeName: pk KeyType: HASH - AttributeName: sk KeyType: RANGE BillingMode: PAY_PER_REQUEST TimeToLiveSpecification: AttributeName: ttl Enabled: true

Data Structure: Each item in the table has the following structure:

  • pk (String): User namespace (e.g., "user123", "demo")
  • sk (String): User's key (e.g., "settings", "config-app")
  • data (Any): The actual value stored by the user
  • created (String): ISO timestamp when item was created
  • updated (String): ISO timestamp when item was last updated
  • ttl (Number, Optional): Unix timestamp for automatic expiration

Deployment

  1. Deploy to Val Town as an HTTP val
  2. Set the required environment variables
  3. The server will be available at your Val Town URL

Usage Examples

JSON-RPC Endpoint (Recommended)

All MCP operations should now use the JSON-RPC endpoint at POST /mcp. This provides proper MCP protocol compliance and better error handling.

Authentication

All authenticated requests require the Authorization header:

Authorization: Bearer your-aws-secret-access-key

List Prompts

curl -X POST https://your-val-town-url.web.val.run/mcp \ -H "Content-Type: application/json" \ -d '{ "jsonrpc": "2.0", "method": "prompts/list", "params": {}, "id": 1 }'

Get Prompt Content

curl -X POST https://your-val-town-url.web.val.run/mcp \ -H "Content-Type: application/json" \ -d '{ "jsonrpc": "2.0", "method": "prompts/get", "params": { "name": "analyze-data", "arguments": { "table_key": "user123", "s3_key": "data/analytics.json" } }, "id": 1 }'

List Resources (Files)

curl -X POST https://your-val-town-url.web.val.run/mcp \ -H "Content-Type: application/json" \ -H "Authorization: Bearer your-aws-secret-access-key" \ -d '{ "jsonrpc": "2.0", "method": "resources/list", "params": {}, "id": 1 }'

Read Files Resource

curl -X POST https://your-val-town-url.web.val.run/mcp \ -H "Content-Type: application/json" \ -H "Authorization: Bearer your-aws-secret-access-key" \ -d '{ "jsonrpc": "2.0", "method": "resources/read", "params": { "uri": "files://path/to/file.txt" }, "id": 1 }'

List Tools

curl -X POST https://your-val-town-url.web.val.run/mcp \ -H "Content-Type: application/json" \ -d '{ "jsonrpc": "2.0", "method": "tools/list", "params": {}, "id": 1 }'

Execute Files Operations

# Store a file in your personal file store curl -X POST https://your-val-town-url.web.val.run/mcp \ -H "Content-Type: application/json" \ -H "Authorization: Bearer your-aws-secret-access-key" \ -d '{ "jsonrpc": "2.0", "method": "tools/call", "params": { "name": "files-put", "arguments": { "key": "documents/my-file.txt", "content": "Hello, World!", "contentType": "text/plain" } }, "id": 1 }' # Get a file from your personal file store curl -X POST https://your-val-town-url.web.val.run/mcp \ -H "Content-Type: application/json" \ -H "Authorization: Bearer your-aws-secret-access-key" \ -d '{ "jsonrpc": "2.0", "method": "tools/call", "params": { "name": "files-get", "arguments": { "key": "documents/my-file.txt" } }, "id": 1 }' # List files in your personal file store curl -X POST https://your-val-town-url.web.val.run/mcp \ -H "Content-Type: application/json" \ -H "Authorization: Bearer your-aws-secret-access-key" \ -d '{ "jsonrpc": "2.0", "method": "tools/call", "params": { "name": "files-list", "arguments": { "prefix": "documents/" } }, "id": 1 }' # List all versions of a file curl -X POST https://your-val-town-url.web.val.run/mcp \ -H "Content-Type: application/json" \ -H "Authorization: Bearer your-aws-secret-access-key" \ -d '{ "jsonrpc": "2.0", "method": "tools/call", "params": { "name": "files-list-versions", "arguments": { "key": "documents/my-file.txt" } }, "id": 1 }' # Get a specific version of a file curl -X POST https://your-val-town-url.web.val.run/mcp \ -H "Content-Type: application/json" \ -H "Authorization: Bearer your-aws-secret-access-key" \ -d '{ "jsonrpc": "2.0", "method": "tools/call", "params": { "name": "files-get", "arguments": { "key": "documents/my-file.txt", "versionId": "specific-version-id" } }, "id": 1 }' # Copy a file within your personal file store curl -X POST https://your-val-town-url.web.val.run/mcp \ -H "Content-Type: application/json" \ -H "Authorization: Bearer your-aws-secret-access-key" \ -d '{ "jsonrpc": "2.0", "method": "tools/call", "params": { "name": "files-copy", "arguments": { "sourceKey": "documents/my-file.txt", "destinationKey": "backup/my-file-backup.txt" } }, "id": 1 }' # Check if a file exists curl -X POST https://your-val-town-url.web.val.run/mcp \ -H "Content-Type: application/json" \ -H "Authorization: Bearer your-aws-secret-access-key" \ -d '{ "jsonrpc": "2.0", "method": "tools/call", "params": { "name": "files-exists", "arguments": { "key": "documents/my-file.txt" } }, "id": 1 }' # Get file metadata curl -X POST https://your-val-town-url.web.val.run/mcp \ -H "Content-Type: application/json" \ -H "Authorization: Bearer your-aws-secret-access-key" \ -d '{ "jsonrpc": "2.0", "method": "tools/call", "params": { "name": "files-metadata", "arguments": { "key": "documents/my-file.txt" } }, "id": 1 }' # Delete a file curl -X POST https://your-val-town-url.web.val.run/mcp \ -H "Content-Type: application/json" \ -H "Authorization: Bearer your-aws-secret-access-key" \ -d '{ "jsonrpc": "2.0", "method": "tools/call", "params": { "name": "files-delete", "arguments": { "key": "documents/my-file.txt" } }, "id": 1 }'

Execute KV Store Operations

# Store a key-value pair in your personal store curl -X POST https://your-val-town-url.web.val.run/mcp \ -H "Content-Type: application/json" \ -H "Authorization: Bearer your-aws-secret-access-key" \ -d '{ "jsonrpc": "2.0", "method": "tools/call", "params": { "name": "kv-put", "arguments": { "key": "user-settings", "value": {"theme": "dark", "language": "en"}, "ttl": 3600 } }, "id": 1 }' # Get a value from your personal store curl -X POST https://your-val-town-url.web.val.run/mcp \ -H "Content-Type: application/json" \ -H "Authorization: Bearer your-aws-secret-access-key" \ -d '{ "jsonrpc": "2.0", "method": "tools/call", "params": { "name": "kv-get", "arguments": { "key": "user-settings" } }, "id": 1 }' # List keys in your personal store curl -X POST https://your-val-town-url.web.val.run/mcp \ -H "Content-Type: application/json" \ -H "Authorization: Bearer your-aws-secret-access-key" \ -d '{ "jsonrpc": "2.0", "method": "tools/call", "params": { "name": "kv-list", "arguments": { "prefix": "user-" } }, "id": 1 }' # Query key-value pairs by pattern curl -X POST https://your-val-town-url.web.val.run/mcp \ -H "Content-Type: application/json" \ -H "Authorization: Bearer your-aws-secret-access-key" \ -d '{ "jsonrpc": "2.0", "method": "tools/call", "params": { "name": "kv-query", "arguments": { "keyPattern": "config*" } }, "id": 1 }'

Execute Skill Management Operations

# Register a skill curl -X POST https://your-val-town-url.web.val.run/mcp \ -H "Content-Type: application/json" \ -H "Authorization: Bearer your-aws-secret-access-key" \ -d '{ "jsonrpc": "2.0", "method": "tools/call", "params": { "name": "register-skill", "arguments": { "name": "data-analyzer", "description": "Analyzes data from KV store and generates reports", "fileKey": "skills/data-analyzer.js", "inputSchema": { "type": "object", "properties": { "dataKey": { "type": "string", "description": "Key of data to analyze" }, "reportType": { "type": "string", "enum": ["summary", "detailed"], "description": "Type of report to generate" } }, "required": ["dataKey"] } } }, "id": 1 }' # List registered skills curl -X POST https://your-val-town-url.web.val.run/mcp \ -H "Content-Type: application/json" \ -H "Authorization: Bearer your-aws-secret-access-key" \ -d '{ "jsonrpc": "2.0", "method": "tools/call", "params": { "name": "list-skills", "arguments": {} }, "id": 1 }' # Execute a registered skill curl -X POST https://your-val-town-url.web.val.run/mcp \ -H "Content-Type: application/json" \ -H "Authorization: Bearer your-aws-secret-access-key" \ -d '{ "jsonrpc": "2.0", "method": "tools/call", "params": { "name": "data-analyzer", "arguments": { "dataKey": "user-data-2024", "reportType": "detailed" } }, "id": 1 }' # Unregister a skill curl -X POST https://your-val-town-url.web.val.run/mcp \ -H "Content-Type: application/json" \ -H "Authorization: Bearer your-aws-secret-access-key" \ -d '{ "jsonrpc": "2.0", "method": "tools/call", "params": { "name": "unregister-skill", "arguments": { "name": "data-analyzer" } }, "id": 1 }'
# Execute code directly (inline) curl -X POST https://your-val-town-url.web.val.run/mcp \ -H "Content-Type: application/json" \ -H "Authorization: Bearer your-aws-secret-access-key" \ -d '{ "jsonrpc": "2.0", "method": "tools/call", "params": { "name": "code-exec", "arguments": { "code": "async function execute(input, tools) { const result = await tools[\"kv-get\"]({key: input.key}); return {message: \"Data retrieved\", data: result}; }", "input": { "key": "user-settings" } } }, "id": 1 }' # Execute code from files store curl -X POST https://your-val-town-url.web.val.run/mcp \ -H "Content-Type: application/json" \ -H "Authorization: Bearer your-aws-secret-access-key" \ -d '{ "jsonrpc": "2.0", "method": "tools/call", "params": { "name": "code-exec", "arguments": { "key": "scripts/data-processor.js", "input": { "operation": "analyze" } } }, "id": 1 }'

Batch Requests

You can send multiple JSON-RPC requests in a single HTTP request:

curl -X POST https://your-val-town-url.web.val.run/mcp \ -H "Content-Type: application/json" \ -H "Authorization: Bearer your-aws-secret-access-key" \ -d '[ { "jsonrpc": "2.0", "method": "prompts/list", "params": {}, "id": 1 }, { "jsonrpc": "2.0", "method": "tools/list", "params": {}, "id": 2 }, { "jsonrpc": "2.0", "method": "resources/list", "params": {}, "id": 3 } ]'

Legacy HTTP Endpoints (Deprecated)

The following endpoints are maintained for backward compatibility but are deprecated. Use the JSON-RPC endpoint instead.

Server Information

curl https://your-val-town-url.web.val.run/

List Prompts

curl https://your-val-town-url.web.val.run/mcp/prompts

Get Prompt Content

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"}'

List Resources (S3 Objects)

curl https://your-val-town-url.web.val.run/mcp/resources \ -H "Authorization: Bearer your-aws-secret-access-key"

Read S3 Resource

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"

List Tools

curl https://your-val-town-url.web.val.run/mcp/tools

Execute DynamoDB Operations

# 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"}}'

Execute S3 Operations

# 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"}'

Execute Code

# Execute code directly (inline) curl -X POST https://your-val-town-url.web.val.run/mcp/tools/code-exec \ -H "Authorization: Bearer your-aws-secret-access-key" \ -H "Content-Type: application/json" \ -d '{ "code": "async function execute(input, tools) { const result = await tools[\"dynamodb-get\"]({key: {id: input.userId}}); return {message: \"User data retrieved\", data: result}; }", "input": { "userId": "user123" } }' # Execute code from S3 object curl -X POST https://your-val-town-url.web.val.run/mcp/tools/code-exec \ -H "Authorization: Bearer your-aws-secret-access-key" \ -H "Content-Type: application/json" \ -d '{ "key": "scripts/data-processor.js", "input": { "userId": "user123", "operation": "analyze" } }'

MCP Client Integration

To integrate with MCP clients like Claude Desktop, you can create a client that makes JSON-RPC requests to the /mcp endpoint. 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}" } } } }

JSON-RPC Response Format

Success Response

{ "jsonrpc": "2.0", "result": { "content": [ { "type": "text", "text": "Response content here" } ] }, "id": 1 }

Error Response

{ "jsonrpc": "2.0", "error": { "code": -32603, "message": "Error message description" }, "id": 1 }

JSON-RPC Error Codes

  • -32700: Parse error (Invalid JSON)
  • -32600: Invalid Request
  • -32601: Method not found
  • -32602: Invalid params
  • -32603: Internal error
  • -32001: Authentication error (custom)

Security Considerations

  • 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

Required AWS Permissions

S3 Permissions

{ "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/*" ] } ] }

DynamoDB Permissions

{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "dynamodb:GetItem", "dynamodb:PutItem", "dynamodb:DeleteItem", "dynamodb:Query" ], "Resource": "arn:aws:dynamodb:region:account:table/your-table-name" } ] }

Note: The KV Store uses DynamoDB Query operations with a composite key structure (partition key + sort key) for efficient namespace isolation and prefix matching. Scan operations are not required.

Error Handling

The server includes comprehensive error handling for:

  • Missing or invalid Authorization headers
  • AWS service errors
  • Invalid parameters
  • Network connectivity issues
  • JSON-RPC protocol errors

JSON-RPC Errors

All JSON-RPC errors follow the standard format with appropriate error codes.

Legacy HTTP Errors

Legacy endpoints return errors with HTTP status codes:

  • 401: Authentication errors
  • 400: Bad request (invalid parameters)
  • 404: Resource or tool not found
  • 500: Server errors (AWS service errors, etc.)

Legacy API Response Format (Deprecated)

Success Response

{ "content": [ { "type": "text", "text": "Response content here" } ] }

Error Response

{ "error": "Error message description" }

Health Check

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" }
FeaturesVersion controlCode intelligenceCLI
Use cases
TeamsAI agentsSlackGTM
ExploreDocsShowcaseTemplatesNewestTrendingAPI examplesNPM packages
PricingNewsletterBlogAboutCareers
We’re hiring!
Brandhi@val.townStatus
X (Twitter)
Discord community
GitHub discussions
YouTube channel
Bluesky
Terms of usePrivacy policyAbuse contact
© 2025 Val Town, Inc.