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

c15r

ContextualLite

Public
Like
ContextualLite
Home
Code
4
src
6
README.md
SKILL_EXECUTION_FIX.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
7/5/2025
Viewing readonly version of main branch: v497
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
│   │       └── openai-tools.ts # OpenAI API tool handlers
│   └── valtown/
│       └── client.ts           # Val Town API client (for admin features)
└── 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

HTTP Endpoints

  • GET /: Server information and capabilities
  • GET /health: Health check endpoint

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
  • Admin Mode: When the bearer token matches the AWS_SECRET_ACCESS_KEY environment variable, the system enters "admin mode" with access to:
    • All regular user tools and operations within the user's own namespace
    • Special admin tools for managing system-wide skills
    • Enhanced administration features
    • Important: Admin mode preserves the original user's namespace instead of switching to a separate "admin" namespace, ensuring consistent data access across modes

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

Admin Tools (Admin Mode Only)

  • admin-promote-skill: Promote an existing user skill to system-wide availability (admin only). If userNamespace is not provided, promotes from the current user's namespace.
  • admin-demote-skill: Remove system-wide availability of a promoted skill (admin only)
  • admin-list-promoted-skills: List all skills that have been promoted to system-wide availability (admin only)
  • admin-update-promoted-skill: Update a promoted skill with the latest version from its original user (admin only)
  • admin-read-val-file: Read a source code file from the project using Val Town API (admin only)
  • admin-write-val-file: Write/update a source code file in the project using Val Town API (admin only)
  • admin-list-val-files: List all files in the project directory structure using Val Town API (admin only)
  • admin-project-info: Get project information and structure overview using Val Town API (admin only)

OpenAI API Tools

  • openai-chat-completion: Create chat completions using OpenAI's API via Val Town's built-in OpenAI integration (supports GPT-4, GPT-3.5, and other models)

OpenAI Integration

The server includes OpenAI chat completion functionality using Val Town's built-in OpenAI integration. This provides seamless access to OpenAI's models without requiring additional API key configuration.

Example Usage

# Simple chat completion 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": "openai-chat-completion", "arguments": { "messages": [ {"role": "user", "content": "Say hello in a creative way"} ], "model": "gpt-4o-mini", "max_tokens": 30 } }, "id": 1 }' # Chat with system prompt 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": "openai-chat-completion", "arguments": { "messages": [ {"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": "Explain quantum computing in simple terms."} ], "model": "gpt-4o-mini", "max_tokens": 500, "temperature": 0.7 } }, "id": 1 }'

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. The system supports both user-specific skills and system-wide skills managed by administrators.

Promotion-Based System Skills

The system uses a promotion-based approach for system skills, which simplifies management and ensures consistency:

  1. User Skills First: Users create and test skills in their personal namespace using register-skill
  2. Promote to System: Admins can promote proven user skills to system-wide availability using admin-promote-skill
  3. File Isolation: When promoting, the skill file is copied to the system folder (system/skills/skillName.js) to ensure complete isolation from the original user's namespace
  4. Automatic Sync: Promoted skills maintain a link to their original user skill for easy updates via admin-update-promoted-skill
  5. No Namespace Confusion: System skills execute using files from the system folder, eliminating namespace-related execution issues

Benefits of Promotion-Based Approach:

  • ✅ No Duplication: Promote existing user skills directly without re-entering metadata
  • ✅ Consistency: System skills are always based on actual tested user skills
  • ✅ Simplicity: Single source of truth for skill definitions
  • ✅ Maintenance: Easy to update promoted skills from their source
  • ✅ Audit Trail: Clear tracking of who created and promoted each skill
  • ✅ Isolation: Complete file isolation prevents namespace-related execution failures

Skill Types

User Skills

  • Scope: Personal to each user
  • Registration: Use register-skill tool
  • Override: User skills can override system skills with the same name
  • Namespace: Stored with user-specific namespace isolation

System Skills (Admin Only)

  • Scope: Available to all users
  • Registration: Use admin-promote-skill tool to promote existing user skills
  • Management: Only administrators can promote, demote, or update system skills
  • Priority: User skills take precedence over system skills with the same name
  • Promotion: Promoted skills maintain a link to their original user for easy updates

System Folder

The system includes a "system" folder that provides:

  • Read access for all users to view system resources
  • Write access for administrators in admin mode only
  • Shared storage for system-wide files and resources

System files are stored with the system/ prefix and are accessible to all users but can only be modified by administrators.

Skill Resolution Priority

When a skill is called, the system resolves it in this order:

  1. User Skills: Check if the user has registered a skill with that name
  2. System Skills: Fall back to system-wide skills if no user skill exists
  3. Error: Return "skill not found" if neither exists

Admin Skill Management (Admin Mode Only)

Administrators can promote user skills to system-wide availability using the promotion-based approach:

Promotion Workflow Example:

{ "userNamespace": "user123", "skillName": "data-analyzer", "description": "Analyzes data from KV store and generates reports (promoted from user123)" }

Admin Promotion Tools

  • admin-promote-skill: Promote an existing user skill to system-wide availability
  • admin-demote-skill: Remove system-wide availability of a promoted skill
  • admin-list-promoted-skills: List all promoted skills with source information
  • admin-update-promoted-skill: Update promoted skills from their original source

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
  • tools["openai-chat-completion"](args) - Create OpenAI chat completions

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.

OpenAI Integration: OpenAI functionality uses Val Town's built-in OpenAI integration, which automatically handles API key management. No additional environment variables are required for OpenAI tools.

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 Admin Skill Promotion Operations

# Promote a skill from your own namespace (userNamespace inferred from auth context) 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": "admin-promote-skill", "arguments": { "skillName": "data-analyzer" } }, "id": 1 }' # Promote a skill from a specific user namespace 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": "admin-promote-skill", "arguments": { "userNamespace": "user123", "skillName": "data-analyzer" } }, "id": 1 }' # List all promoted 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": "admin-list-promoted-skills", "arguments": {} }, "id": 1 }' # Update a promoted skill with latest version from original user 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": "admin-update-promoted-skill", "arguments": { "skillName": "data-analyzer" } }, "id": 1 }' # Demote a skill from system-wide availability 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": "admin-demote-skill", "arguments": { "skillName": "data-analyzer" } }, "id": 1 }' # List all system skills (both promoted and directly registered) 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": "admin-list-system-skills", "arguments": {} }, "id": 1 }'

Execute Admin File Operations

# Read a project source file using Val Town API (admin only) 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": "admin-read-val-file", "arguments": { "path": "src/auth/auth-manager.ts" } }, "id": 1 }' # Write/update a project source file using Val Town API (admin only) 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": "admin-write-val-file", "arguments": { "path": "src/config/new-config.ts", "content": "export const config = { version: \"1.0.0\" };" } }, "id": 1 }' # List project files recursively using Val Town API (admin only) 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": "admin-list-val-files", "arguments": { "path": "/src", "recursive": true } }, "id": 1 }' # Get comprehensive project information using Val Town API (admin only) 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": "admin-project-info", "arguments": {} }, "id": 1 }'

Execute Code Operations

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

HTTP Endpoints

Server Information

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

Health Check

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

Response:

{ "status": "healthy", "timestamp": "2024-01-01T00:00:00.000Z" }

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.

HTTP Errors

HTTP 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.)
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.