Skip to main content
Glama
README.md
# BYOB MCP Server πŸš€

**Bring Your Own Binary**: A dynamic MCP server built on Cloudflare Workers, Containers, and D1.

Enables AI agents to discover and invoke containerized tools registered at runtimeβ€”no redeployment needed.

## Quick Start

```bash
# Install dependencies
npm install

# Start local dev server
npm run dev

# In another terminal, test the API
bash test-api.sh

# Deploy to production
npm run deploy
```

## What This Is

A proof-of-concept demonstrating:

- βœ… **Dynamic Tool Registry** - Tools stored in D1, queried by MCP server
- βœ… **Containerized Execution** - Each tool runs in isolated Cloudflare Container
- βœ… **MCP Protocol** - AI agents discover tools via Model Context Protocol
- βœ… **HTTP Registration API** - Register new tools without redeploying
- βœ… **Scale-to-Zero** - Containers only run when tools are invoked

## Architecture

```
AI Agent (Claude) ──[MCP]──> Cloudflare Worker ──[HTTP]──> Universal Container
                                    β”‚                         (ToolRunner)
                                    └──[SQL]──> D1 Registry
                                                              Supports:
                                                              β€’ Echo
                                                              β€’ Uppercase
                                                              β€’ JQ
                                                              β€’ Git Clone
```

## Pre-Built Demo Tools

All four tools run in a single universal container:

1. **echo_message** - Echoes back any JSON input
2. **why_are_we_yelling** - Converts text to UPPERCASE
3. **query_json** - Processes JSON with jq filters
4. **summarize_repo_readme** - Clones a GitHub repo and summarizes its README

## API Endpoints

### GET /
Health check and server info

### GET /api/tools
List all registered tools

### POST /api/register-tool
Register a new tool
```json
{
  "name": "my_tool",
  "description": "What this tool does",
  "containerClass": "echo",
  "schema": {
    "type": "object",
    "properties": {
      "input": {"type": "string"}
    }
  }
}
```

### POST /mcp
MCP protocol endpoint (connect your AI agent here)

## Example: Register a Tool

```bash
curl -X POST http://localhost:8787/api/register-tool \
  -H "Content-Type: application/json" \
  -d '{
    "name": "whisper",
    "description": "Echoes message in lowercase",
    "containerClass": "toolrunner",
    "schema": {
      "type": "object",
      "properties": {
        "message": {"type": "string"}
      },
      "required": ["message"]
    }
  }'
```

## Connect to Claude Desktop

Edit your Claude Desktop config:

**macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`

```json
{
  "mcpServers": {
    "byob-server": {
      "url": "http://localhost:8787/mcp"
    }
  }
}
```

Restart Claude Desktop, then ask:
- "What tools do you have available?"
- "Can you echo the message 'Hello BYOB!'?"
- "Use why_are_we_yelling with text: hello world"
- "Summarize the README from https://github.com/fiberplane/mcp-lite"

## Documentation

- **[PROJECT_SUMMARY.md](./PROJECT_SUMMARY.md)** - High-level overview
- **[HACKATHON.md](./HACKATHON.md)** - Full architecture and setup guide
- **[DEMO.md](./DEMO.md)** - Step-by-step demo script
- **[CLAUDE.md](./CLAUDE.md)** - Development instructions (for AI assistants)

## Project Structure

```
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ index.ts          # Main Worker + MCP server
β”‚   β”œβ”€β”€ containers.ts     # Container class definitions
β”‚   └── types.ts          # TypeScript interfaces
β”œβ”€β”€ containers/
β”‚   β”œβ”€β”€ Dockerfile        # Universal container image
β”‚   β”œβ”€β”€ server.js         # Multi-tool HTTP server
β”‚   └── README.md         # Container documentation
β”œβ”€β”€ migrations/
β”‚   β”œβ”€β”€ 0001_initial_schema.sql
β”‚   └── 0002_seed_example_tools.sql
└── wrangler.jsonc        # Cloudflare configuration
```

## Adding New Tools

Since all tools use the same universal container, adding new tools is simple:

### Option 1: Via API (No redeployment needed)
```bash
curl -X POST http://localhost:8787/api/register-tool \
  -H "Content-Type: application/json" \
  -d '{"name":"my_tool", "description":"...", ...}'
```

### Option 2: Extend the Container
To add new operation types:
1. Edit `containers/server.js` to handle new input patterns
2. Add new tool definitions to `migrations/0002_seed_example_tools.sql`
3. Redeploy

The single container approach keeps things simple for demos while still demonstrating the BYOB architecture.

## Technology Stack

- **Runtime:** Cloudflare Workers (V8 Isolates)
- **MCP:** mcp-lite (not @modelcontextprotocol/sdk)
- **Web Framework:** Hono
- **Database:** Cloudflare D1 (SQLite)
- **Containers:** Cloudflare Containers (Durable Objects)
- **Schema:** Zod + JSON Schema

## Deployment

### Local Development
```bash
npm run dev
# Server runs on http://localhost:8787
```

### Production Deployment

1. Run migrations on remote database:
```bash
npx wrangler d1 execute byob-tools-registry --remote \
  --file=./migrations/0001_initial_schema.sql
npx wrangler d1 execute byob-tools-registry --remote \
  --file=./migrations/0002_seed_example_tools.sql
```

2. Deploy Worker and Containers:
```bash
npm run deploy
```

**Note:** First deployment takes 2-5 minutes to build Docker images.

3. Update Claude Desktop config with your production URL:
```json
{
  "mcpServers": {
    "byob-server": {
      "url": "https://byob-mcp-server.YOUR_ACCOUNT.workers.dev/mcp"
    }
  }
}
```

## Testing

```bash
# Automated API tests
bash test-api.sh

# Manual health check
curl http://localhost:8787/

# List tools
curl http://localhost:8787/api/tools | jq

# Test MCP protocol
curl -X POST http://localhost:8787/mcp \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'
```

## Key Features

### Dynamic Discovery
Tools registered in D1 appear immediately to all connected AI agentsβ€”no redeployment required.

### Secure Isolation
Each container runs in an isolated sandbox with resource limits and ephemeral storage.

### Serverless Scale
Containers scale to zero when idle. Pay only for actual tool invocations.

### Standard Interface
All containers expose `POST /execute` endpoint accepting/returning JSON.

## Limitations

**Container classes must be defined at deploy time** in `wrangler.jsonc`. True runtime BYOB would require automatic Worker rebuild/redeploy when new containers are registered.

**Workaround:** Multiple logical tools can share the same container class, allowing significant flexibility without redeployment.

## Resources

- [Cloudflare Containers Docs](https://developers.cloudflare.com/containers/)
- [Model Context Protocol](https://modelcontextprotocol.io/)
- [mcp-lite GitHub](https://github.com/fiberplane/mcp-lite)
- [Containers Examples](https://github.com/cloudflare/containers-demos)

## License

MIT - Built for hackathon demonstration

## Contributing

This is a hackathon prototype. For questions or suggestions, open an issue!

---

**Built with** ☁️ Cloudflare Workers | 🐳 Containers | πŸ—„οΈ D1 | πŸ€– MCP