Skip to main content
Glama
andrewjgalea

Planning MCP Server

by andrewjgalea
README.md
# Planning MCP Server v2.0

Model Context Protocol (MCP) server for Australian Planning Property Reports - Cloudflare Workers Edition.

## Features

- šŸŒ **Global Edge Deployment** - Runs on Cloudflare's 300+ edge locations
- ⚔ **High Performance** - Parallel API requests and intelligent caching
- šŸ“Š **Comprehensive Data** - Property details, zones, overlays, electorates, utilities, and land information
- šŸ”’ **Production Ready** - Rate limiting, authentication, structured logging
- šŸ“ˆ **Real-time Progress** - Progress updates during long-running operations
- šŸš€ **HTTP-based MCP** - Works with Claude, ChatGPT, and other AI assistants

## Quick Start

### Prerequisites

- Node.js 18+
- Cloudflare Workers account
- Wrangler CLI (`npm install -g wrangler`)

### Installation

```bash
# Clone the project
cd planning-mcp

# Install dependencies
npm install

# Login to Cloudflare
wrangler login

# Create KV namespace for caching
wrangler kv:namespace create "CACHE"
# Copy the ID and add to wrangler.toml

# Start development server
npm run dev
```

### Configuration

1. Update `wrangler.toml` with your KV namespace ID
2. (Optional) Set API key for authentication:
   ```bash
   wrangler secret put API_KEY
   ```

### Deployment

```bash
# Build the project
npm run build

# Deploy to Cloudflare Workers
npm run deploy
```

## Usage

### MCP Tool: `vic_planning_property_report`

Retrieves comprehensive Victorian planning property reports. (Additional state tools coming soon.)

**Input:**
```json
{
  "address": "1 Spring Street, Melbourne VIC 3000",
  "includePdfBase64": false,
  "includeZoneHtml": false,
  "includeOverlayHtml": false
}
```

**Output:**
```json
{
  "success": true,
  "address": "1 SPRING STREET MELBOURNE VIC 3000",
  "propertyPfi": "12345",
  "propertyDetails": {
    "address": "1 SPRING STREET MELBOURNE VIC 3000",
    "councilName": "Melbourne City Council",
    "landSize": 842,
    "landSizeHectares": 0.0842,
    "standardParcelIdentifier": "1\\PS123456",
    "registeredAboriginalParty": "Bunurong Land Council",
    ...
  },
  "electorates": {
    "federal": "Melbourne",
    "legislativeAssembly": "Melbourne District",
    "legislativeCouncil": "Southern Metropolitan Region"
  },
  "utilities": {
    "powerDistributor": "AusNet Services",
    "gas": "AusNet Services",
    "melbourneWater": "Melbourne Water",
    "melbourneWaterRetailer": "South East Water"
  },
  "zones": [...],
  "overlays": [...]
}
```

### HTTP API

**Health Check:**
```bash
GET /health
```

**MCP Endpoint:**
```bash
POST /mcp
Content-Type: application/json

{
  "jsonrpc": "2.0",
  "id": "1",
  "method": "tools/call",
  "params": {
    "name": "vic_planning_property_report",
    "arguments": {
      "address": "1 Spring Street, Melbourne VIC 3000"
    }
  }
}
```

## Architecture

```
ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
│     Cloudflare Edge Network             │
│  ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”  │
│  │   Worker (HTTP MCP Endpoint)      │  │
│  │   - Hono.js Framework             │  │
│  │   - Rate Limiting                 │  │
│  │   - Authentication                │  │
│  │   - CORS                          │  │
│  ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜  │
│               ↓                          │
│  ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”  │
│  │   Services Layer                  │  │
│  │   - Address Resolution            │  │
│  │   - Property Data Fetching        │  │
│  │   - Progress Reporting            │  │
│  ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜  │
│               ↓                          │
│  ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”  │
│  │   Workers KV (Caching)            │  │
│  │   - 60%+ Cache Hit Rate           │  │
│  │   - 24hr TTL for addresses        │  │
│  ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜  │
ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜
```

## Development

### Project Structure

```
planning-mcp/
ā”œā”€ā”€ src/
│   ā”œā”€ā”€ index.ts              # Main entry point
│   ā”œā”€ā”€ types/                # TypeScript types
│   ā”œā”€ā”€ services/             # Business logic
│   ā”œā”€ā”€ middleware/           # HTTP middleware
│   ā”œā”€ā”€ handlers/             # MCP handlers
│   ā”œā”€ā”€ lib/                  # Utilities
│   └── schemas/              # Validation schemas
ā”œā”€ā”€ test/                     # Tests
ā”œā”€ā”€ wrangler.toml            # Cloudflare config
ā”œā”€ā”€ tsconfig.json            # TypeScript config
└── package.json             # Dependencies
```

### Testing

```bash
# Run tests
npm test

# Run tests with coverage
npm run test:coverage

# Type check
npm run type-check
```

## Environment Variables

Configure in `wrangler.toml`:

| Variable | Description | Default |
|----------|-------------|---------|
| `RATE_LIMIT_PER_MINUTE` | Rate limit per IP | 100 |
| `CACHE_TTL_HOURS` | Cache TTL in hours | 24 |
| `ENABLE_ANALYTICS` | Enable analytics | true |
| `ALLOWED_ORIGINS` | CORS origins | * |

Secrets (use `wrangler secret put`):

| Secret | Description | Required |
|--------|-------------|----------|
| `API_KEY` | Bearer token for auth | No |

## Performance

- **Latency:** <5s P50, <8s P95
- **Cache Hit Rate:** >60% after warmup
- **Throughput:** 1000+ req/sec with auto-scaling
- **Cold Start:** <100ms
- **Memory:** <128MB per request

## Security

- āœ… Input validation with Zod
- āœ… Rate limiting (100 req/min per IP)
- āœ… Optional API key authentication
- āœ… CORS configuration
- āœ… No secrets in logs

## Monitoring

### Structured Logging

All requests are logged in JSON format with correlation IDs:

```json
{
  "timestamp": "2024-01-30T10:00:00.000Z",
  "level": "info",
  "message": "Tool call started",
  "requestId": "550e8400-e29b-41d4-a716-446655440000",
  "tool": "vic_planning_property_report",
  "metadata": {
    "address": "1 Spring St"
  }
}
```

### Analytics

Enable Cloudflare Analytics Engine for:
- Request counts and latency
- Cache hit/miss rates
- Error tracking
- API performance metrics

## Deployment Options

### Option 1: Cloudflare Workers (Recommended)

- 300+ edge locations
- $5/month base + usage
- Lowest latency globally

### Option 2: Vercel Edge Functions

See [Vercel deployment guide](./docs/vercel-deployment.md) for migration instructions.

### Option 3: Oracle Server

Traditional Node.js deployment - see [v1.0 branch](./tree/v1.0).

## Troubleshooting

### Common Issues

**KV Namespace not found:**
```bash
# Create namespace and update wrangler.toml
wrangler kv:namespace create "CACHE"
```

**Rate limit errors:**
```bash
# Increase limit in wrangler.toml
RATE_LIMIT_PER_MINUTE = "200"
```

**Authentication failures:**
```bash
# Check API key is set
wrangler secret list
wrangler secret put API_KEY
```

## Contributing

1. Fork the repository
2. Create a feature branch
3. Make your changes
4. Add tests
5. Submit a pull request

## License

MIT

## Support

- Documentation: [PRD](./docs/PRD.md)
- Issues: [GitHub Issues](https://github.com/andrewjgalea/planning-mcp/issues)
- Discussions: [GitHub Discussions](https://github.com/andrewjgalea/planning-mcp/discussions)

## Changelog

### v2.0.0 (2024-01-30)

- ✨ Rewritten for Cloudflare Workers
- ✨ HTTP-based MCP protocol
- ✨ Enhanced property data with land size
- ✨ Real-time progress updates
- ✨ Parallel API requests
- ✨ Intelligent caching with Workers KV
- ✨ Complete field coverage (15+ fields)
- šŸ”’ Production-ready security
- šŸ“Š Structured logging and metrics

### v1.0.0

- Initial Node.js stdio implementation

---

Built with ā¤ļø for Australian planning research