Skip to content

An MCP server for querying Modern.gov powered sites.

Notifications You must be signed in to change notification settings

jadu/modgov-mcp-server

Repository files navigation

Modgov MCP Server

A comprehensive Model Context Protocol (MCP) server that provides access to modgov council APIs for retrieving councillor information, committee details, meeting schedules, election results, and parish council data across UK local councils.

Table of Contents

Quick Start

Prerequisites

  • Node.js (version 18+)
  • Docker & Docker Compose (for production deployment)

Build & Run

  1. Clone and Build:

    git clone <repository-url>
    cd modgov-mcp-server
    npm install
    npm run build
  2. Run with STDIO transport:

    node dist/index.js
  3. Run with HTTP transport:

    MCP_TRANSPORT=http node dist/index.js
    # Server available at: http://localhost:3003/mcp
  4. Test with MCP Inspector:

    npx @modelcontextprotocol/inspector node dist/index.js

Docker Deployment

For production deployment, use Docker:

# Build and run
make build && make up

# Server available at: http://localhost:3003/mcp
# Health check: http://localhost:3003/health

Features

  • 100% Success Rate: 9/9 endpoints fully functional with automatic server bug workarounds
  • Complete API Coverage: All major ModGov endpoints (councillors, committees, meetings, elections, etc.)
  • Multi-site support: Tested across 3 UK council sites (Lichfield, Kirklees, Liverpool)
  • Server Bug Handling: Automatic workarounds for WSDL vs actual server discrepancies
  • Flexible querying: Multiple ways to access council data (by ward, committee, date, etc.)
  • Rate limiting: Built-in rate limiting (1 request/second per domain) to prevent API abuse
  • Error handling: Robust error handling with meaningful error messages
  • Council lookup: Smart fuzzy matching to find councils by name or region

🚨 Critical Server Bug Workarounds

Major discrepancies exist between official WSDL documentation and actual ModGov server implementations. This MCP server automatically handles these issues:

Parameter Requirements Mismatch

Many parameters marked as "optional" in WSDL are actually required by servers:

Endpoint WSDL Shows Optional Actually Required
GetMeetings sFromDate, sToDate βœ… REQUIRED
GetAllMeetingsByDate lCommitteeId, bIsAscendingDateOrder βœ… REQUIRED
GetCalendarEvents bGlobalCalendar, lUserId βœ… REQUIRED
GetWebCastMeetings lCommitteeId, sFromDate, sToDate βœ… REQUIRED
GetElectionResults lElectionId βœ… REQUIRED
GetMpOrMepsAndWards bIsMPs βœ… REQUIRED

Automatic Workarounds Applied

The MCP server transparently applies these fixes:

  • Missing dates: Defaults to current year range (YYYY-01-01 to YYYY-12-31)
  • Missing committee IDs: Defaults to Cabinet (138)
  • Missing boolean flags: Provides sensible defaults (true for global calendar, etc.)
  • Missing user IDs: Defaults to 0 for public access

Testing Results

Council Working Endpoints Success Rate
Lichfield DC 9/9 100%
Kirklees 9/9 100%
Liverpool 9/9 100%

All tested sites exhibit identical server bugs and all are handled automatically.

πŸ§ͺ Testing

Test Structure

tests/
β”œβ”€β”€ integration/        # End-to-end integration tests
β”œβ”€β”€ debugging/         # Debug and investigation scripts
β”œβ”€β”€ utils/            # Utility test scripts
└── README.md         # Test documentation

Running Tests

Unit Tests (in Docker)

# Run Jest unit tests in Docker container
make test

# Or use Docker Compose directly
docker-compose run --rm modgov-mcp-server npm test

Integration Tests (in Docker)

# Test all 9 endpoints end-to-end in Docker
docker-compose run --rm modgov-mcp-server npm run test:integration

Debug Tests (in Docker)

# Investigate endpoint compatibility across sites
docker-compose run --rm modgov-mcp-server npm run test:debug

# Verify parameter handling
docker-compose run --rm modgov-mcp-server npm run test:params

Test Results

  • βœ… 100% Success Rate: 9/9 endpoints working
  • βœ… Server Bug Workarounds: All WSDL discrepancies handled automatically
  • βœ… Cross-Site Compatibility: Tested across 3 council sites

πŸ“š Documentation

OpenAPI/Swagger Specification

  • File: modgov-openapi-spec.yaml
  • Status: βœ… Complete and Authoritative
  • Coverage: All 9 supported endpoints with real-world examples
  • Features:
    • Server bug workarounds clearly documented
    • Request/response examples
    • Parameter validation rules
    • Cross-site compatibility notes

Developer Resources

  • Robustness Report: MCP_ROBUSTNESS_REPORT.md - Testing and performance details
  • Test Documentation: tests/README.md - Complete test suite guide
  • Implementation Notes: Server bug workarounds and best practices (see sections above)

Installation

Native Node.js (Recommended for Development)

# Clone and install
git clone <repository-url>
cd modgov-mcp-server
npm install
npm run build

# Run with STDIO transport (default)
node dist/index.js

# Run with HTTP transport
MCP_TRANSPORT=http node dist/index.js

Docker (Recommended for Production)

# Using Makefile (recommended)
make build && make up

# Or using Docker Compose directly
docker-compose up --build

Available Make Commands:

  • make build - Build production image
  • make up - Start production container
  • make test - Run tests in container
  • make logs - View container logs
  • make clean - Remove containers and images
  • make shell - Open shell in container for debugging

MCP Transport Options

The Modgov MCP Server supports both STDIO and HTTP transports:

STDIO Transport (Default)

Perfect for development and MCP client integration:

# Start with STDIO transport
node dist/index.js

# Test with MCP Inspector
npx @modelcontextprotocol/inspector node dist/index.js

STDIO transport characteristics:

  • Default transport mode
  • Interactive stdin/stdout communication
  • Perfect for MCP clients (Claude Desktop, Cursor, etc.)
  • Terminates after client disconnects

HTTP Transport (Streamable)

Ideal for web services and API integration:

# Start with HTTP transport
MCP_TRANSPORT=http node dist/index.js

# Or with custom port
MCP_TRANSPORT=http MCP_PORT=3005 node dist/index.js

HTTP transport endpoints:

  • MCP Protocol: http://localhost:3003/mcp
  • Health Check: http://localhost:3003/health

HTTP transport characteristics:

  • Runs as persistent web server
  • RESTful MCP protocol over HTTP
  • Supports streaming responses
  • Built-in health monitoring

MCP Inspector

Test your server with the official MCP Inspector:

# For STDIO transport (default)
npx @modelcontextprotocol/inspector node dist/index.js

# For HTTP transport
npx @modelcontextprotocol/inspector http://localhost:3003/mcp

The inspector provides:

  • βœ… Interactive tool testing
  • βœ… Protocol validation
  • βœ… Request/response debugging
  • βœ… Schema verification

Usage

Docker (Production)

Production with HTTP Transport

# Build and run production container
make build && make up

# Or using Docker Compose directly
docker-compose up --build modgov-mcp-server

The server automatically starts in HTTP mode on port 3003 when the container starts.

HTTP API Endpoints

The MCP server runs in Docker and exposes these endpoints on port 3003:

MCP Protocol Endpoint

POST http://localhost:3003/mcp
Content-Type: application/json

# Example request
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "get_councillors",
    "arguments": {
      "site_url": "https://democracy.lichfielddc.gov.uk/mgWebService.asmx?WSDL"
    }
  }
}

Health Check Endpoint

GET http://localhost:3003/health

# Response
{
  "status": "healthy",
  "timestamp": "2025-01-11T10:20:30.000Z",
  "server": "modgov-mcp-server",
  "version": "1.0.0",
  "transport": "streamable-http"
}

Docker Logging

The MCP server includes comprehensive logging for all tool calls when running in Docker:

# View real-time logs
docker logs modgov-mcp-server --follow

# View recent logs
docker logs modgov-mcp-server --tail 20

Example Log Output:

πŸ› οΈ  Tool called: get_councillors_by_ward
πŸ“ Parameters: site_url=https://democracy.lichfielddc.gov.uk/mgWebService.asmx
βœ… Tool completed: get_councillors_by_ward (1280ms)

πŸ› οΈ  Tool called: get_committees
πŸ“ Parameters: site_url=https://democracy.lichfielddc.gov.uk/mgWebService.asmx
βœ… Tool completed: get_committees (320ms)

Each tool call logs:

  • πŸ”§ Tool initiation with emoji and tool name
  • πŸ“ Parameters passed to the tool
  • βœ… Completion with execution time in milliseconds

The MCP server runs at http://localhost:3003/mcp and supports the full MCP protocol for testing all registered tools.

Port Conflict Solutions: If you encounter port conflicts:

# Stop all containers
make down

# Or manually kill processes on ports 3003, 6274, 6277
lsof -ti:3003,6274,6277 | xargs kill -9 2>/dev/null || true

Stopping the Server:

# Stop the Docker container
make down

# Or use Docker Compose directly
docker-compose down

Troubleshooting:

  • Check container logs: make logs
  • Verify container is running: docker ps
  • Test health endpoint: curl http://localhost:3003/health

Available Tools

The MCP server exposes 18 tools for querying modgov council APIs and finding councils:

βœ… Councillor Information (No Workarounds Needed)

  • get_councillors_by_ward - Get all councillors organized by ward with photos and political affiliations
  • get_councillors_by_ward_id - Get councillors for a specific ward ID
  • get_councillors_by_postcode - Get councillors for a specific postcode
  • get_councillor_details - Get comprehensive councillor profiles including surgery times and contact details

βœ… Governance & Committees (Automatic Workarounds Applied)

  • get_committees - Get all committees (Cabinet, Council, Planning, etc.)
  • get_meetings - Get meetings with automatic date range defaults βš™οΈ
  • get_meeting - Get details for a specific meeting by ID
  • get_all_meetings_by_date - Get meetings for specific date with committee defaults βš™οΈ

βœ… Events & Calendar (Automatic Workarounds Applied)

  • get_calendar_events - Get calendar events with automatic parameter handling βš™οΈ

βœ… Local Government Structure (No Workarounds Needed)

  • get_parish_councils - Get parish councils and their information

βœ… Elections & Democracy (Automatic Workarounds Applied)

  • get_election_results - Get election results with required election ID βš™οΈ

βœ… Digital Services (Automatic Workarounds Applied)

  • get_webcast_meetings - Get webcast meetings with date and committee defaults βš™οΈ
  • get_mp_or_meps_and_wards - Get MP/MEP information with boolean flag handling βš™οΈ
  • get_mp_or_mep_and_wards_by_postcode - Get MP/MEP info for specific postcode βš™οΈ

βœ… Council Discovery & Management

  • find_council - Find a council by name using fuzzy matching
  • search_councils - Search councils with confidence thresholds
  • get_council_by_region - Get all councils in a specific region
  • get_server_diagnostics - Get server diagnostic information

βš™οΈ Automatic server bug workarounds applied | βœ… All tools tested and working

Tool Usage Examples

All tools require a site_url parameter pointing to the council's modgov API endpoint.

Councillor Information

Get all councillors by ward:

{
  "site_url": "https://democracy.lichfielddc.gov.uk/mgWebService.asmx?WSDL"
}

Get councillors for a specific ward:

{
  "site_url": "https://democracy.lichfielddc.gov.uk/mgWebService.asmx?WSDL",
  "ward_id": 1
}

Get councillors by postcode:

{
  "site_url": "https://democracy.lichfielddc.gov.uk/mgWebService.asmx?WSDL",
  "postcode": "WS14 9AB"
}

Governance & Committees

Get all committees:

{
  "site_url": "https://democracy.lichfielddc.gov.uk/mgWebService.asmx?WSDL"
}

Get meetings for a specific committee:

{
  "site_url": "https://democracy.lichfielddc.gov.uk/mgWebService.asmx?WSDL",
  "committee_id": 1
}

Get a specific meeting by ID:

{
  "site_url": "https://democracy.lichfielddc.gov.uk/mgWebService.asmx?WSDL",
  "meeting_id": 123
}

Local Government Structure

Get parish councils:

{
  "site_url": "https://democracy.lichfielddc.gov.uk/mgWebService.asmx?WSDL"
}

## Response Format

The tool returns JSON data with the following structure:

```json
{
  "site_url": "https://democracy.lichfielddc.gov.uk/mgWebService.asmx?WSDL",
  "total_wards": 25,
  "total_councillors": 47,
  "wards": [
    {
      "ward_name": "Alrewas and Fradley",
      "councillor_count": "3",
      "councillors": [
        {
          "id": "570",
          "name": "Councillor Sonia Claverley",
          "party": "The Conservative Party",
          "group": "Conservative Group",
          "district": "Lichfield District Council",
          "representing": "Lichfield District Council",
          "photos": {
            "small": "https://democracy.lichfielddc.gov.uk/UserData/0/7/5/Info00000570/smallpic.jpg",
            "large": "https://democracy.lichfielddc.gov.uk/UserData/0/7/5/Info00000570/bigpic.jpg"
          },
          "additional_info": "...",
          "key_posts": "..."
        }
      ]
    }
  ]
}

Rate Limiting

The server implements rate limiting of 1 request per second per domain to prevent abuse and respect API limits.

Error Handling

The server provides comprehensive error handling:

  • Network errors: Connection timeouts, DNS resolution failures
  • API errors: Invalid responses, malformed XML
  • Rate limiting: Automatic retry with exponential backoff
  • Validation errors: Invalid parameters, missing required fields

Development

Development Environment

All development happens within Docker containers:

# Start development environment with live code mounting
make dev

# This mounts your source code and provides hot reloading

Running Tests

Unit Tests (in Docker)

# Run Jest unit tests in development container
make test

# Or run tests in watch mode for development
docker-compose --profile dev exec modgov-mcp-dev npm run test:watch

Integration Tests (in Docker)

Test the full MCP server functionality with real API calls:

# Start development environment (Terminal 1)
make dev

# Run integration tests (Terminal 2)
docker-compose --profile dev exec modgov-mcp-dev npm run test:mcp

The integration tests include:

  • Health endpoint validation
  • MCP protocol compliance
  • Tool discovery and execution
  • Council data retrieval and validation

See TEST_README.md for detailed testing documentation.

Building

The build process happens automatically in the Docker container:

# Manual build in container
docker-compose --profile dev exec modgov-mcp-dev npm run build

Stopping Development Environment

# Stop development containers
make down

This stops all development containers and cleans up resources.

Docker Configuration

Production Container

The production container is optimized for deployment:

docker build -t modgov-mcp-server .
docker run -p 3003:3003 modgov-mcp-server

Features:

  • Multi-stage build for minimal image size
  • Non-root user for security
  • Health checks
  • Only production dependencies
  • Always runs on port 3003 with HTTP transport

Testing Docker Setup

Verify your Docker container works:

# Build and test
make build
make up

# Check health endpoint
curl http://localhost:3003/health

Expected health response:

{
  "status": "healthy",
  "timestamp": "2025-01-11T10:20:30.000Z",
  "server": "modgov-mcp-server",
  "version": "1.0.0",
  "transport": "streamable-http"
}

MCP Server Behavior

Important: The MCP server runs continuously in HTTP mode inside the Docker container. This is different from stdio mode where servers exit after each request.

  • The server stays running and listens on port 3003
  • Each MCP request is handled over HTTP
  • The container will show as running (not exited)
  • Use make logs to monitor the server output

Architecture

The server consists of three main components:

  1. ModgovClient: Handles HTTP requests to modgov APIs, XML parsing, and rate limiting
  2. ModgovServer: MCP server implementation with tool registration and request handling
  3. Type Definitions: TypeScript interfaces for API responses and data structures

Supported Council Sites

The server works with any modgov-enabled council website. Our database includes 44 verified councils across all UK regions.

Complete Council Database

Council Region Type URL
Bath and North East Somerset Council South West Unitary Authority https://democracy.bathnes.gov.uk/
Brentwood Borough Council East of England Borough Council https://brentwood.moderngov.co.uk/
Brighton & Hove City Council South East City Council https://democracy.brighton-hove.gov.uk/
Bristol City Council South West City Council https://democracy.bristol.gov.uk/
Buckinghamshire Council East of England Unitary Authority https://buckinghamshire.moderngov.co.uk/
Cambridge City Council East of England City Council https://democracy.cambridge.gov.uk/
Cardiff Council Wales Unitary Authority https://cardiff.moderngov.co.uk/
Chichester District Council South East District Council https://chichester.moderngov.co.uk/
City of Lincoln Council East Midlands City Council https://lincoln.moderngov.co.uk/
City of Wolverhampton Council West Midlands Metropolitan Borough https://wolverhampton.moderngov.co.uk/
City of York Council Yorkshire and Humber City Council https://democracy.york.gov.uk/
Coventry City Council West Midlands City Council https://edemocracy.coventry.gov.uk/
East Hampshire District Council South East District Council https://easthants.moderngov.co.uk/
Greater London Authority (GLA) London Combined Authority https://gla.moderngov.co.uk/
Hastings Borough Council South East Borough Council https://hastings.moderngov.co.uk/
Leeds City Council Yorkshire and Humber City Council https://democracy.leeds.gov.uk/
Leicestershire County Council East Midlands County Council https://democracy.leics.gov.uk/
Lichfield District Council West Midlands District Council https://lichfield.moderngov.co.uk/
Liverpool City Council North West City Council https://councillors.liverpool.gov.uk/
London Borough of Barnet London London Borough https://barnet.moderngov.co.uk/
London Borough of Brent London London Borough https://democracy.brent.gov.uk/
London Borough of Camden London London Borough https://camden.moderngov.co.uk/
London Borough of Croydon London London Borough https://croydon.moderngov.co.uk/
London Borough of Haringey London London Borough https://www.minutes.haringey.gov.uk/
London Borough of Harrow London London Borough https://moderngov.harrow.gov.uk/
London Borough of Havering London London Borough https://democracy.havering.gov.uk/
London Borough of Hounslow London London Borough https://democraticservices.hounslow.gov.uk/
London Borough of Islington London London Borough https://islington.moderngov.co.uk/
London Borough of Southwark London London Borough https://moderngov.southwark.gov.uk/
London Borough of Sutton London London Borough https://moderngov.sutton.gov.uk/
London Borough of Tower Hamlets London London Borough https://democracy.towerhamlets.gov.uk/
Medway Council South East Unitary Authority https://democracy.medway.gov.uk/
Newcastle City Council North East City Council https://democracy.newcastle.gov.uk/
Portsmouth City Council South East City Council https://democracy.portsmouth.gov.uk/
Royal Borough of Kingston upon Thames London Royal Borough https://kingston.moderngov.co.uk/
Sheffield City Council Yorkshire and Humber City Council https://democracy.sheffield.gov.uk/
South Cambridgeshire District Council East of England District Council https://scambs.moderngov.co.uk/
Three Rivers District Council East of England District Council https://moderngov.threerivers.gov.uk/
Vale of White Horse District Council South East District Council https://democratic.whitehorsedc.gov.uk/
Warwickshire County Council West Midlands County Council https://warwickshire.moderngov.co.uk/
Watford Borough Council East of England Borough Council https://watford.moderngov.co.uk/
West of England Combined Authority South West Combined Authority https://westofengland-ca.moderngov.co.uk/
Wirral Council North West Metropolitan Borough https://wirral.moderngov.co.uk/
Worcestershire County Council West Midlands County Council https://worcestershire.moderngov.co.uk/

Coverage Statistics

  • Total Councils: 44
  • Regions Covered: 11 (all UK regions)
  • Council Types: 10 different authority types
  • Tested Sites: 3 (Lichfield, Kirklees, Liverpool - 100% success rate)

Verified Working Examples

Council URL Committee IDs Notes
Lichfield District Council https://democracy.lichfielddc.gov.uk/mgWebService.asmx?WSDL Cabinet: 138, Council: 136, Planning: 135 Primary test site
Kirklees Council http://democracy.kirklees.gov.uk/mgWebService.asmx?WSDL Same pattern Identical behavior
Liverpool City Council https://democracy.liverpool.gov.uk/mgWebService.asmx?WSDL Same pattern Identical behavior
London Borough of Sutton https://moderngov.sutton.gov.uk/mgWebService.asmx Full endpoint documentation Comprehensive API testing

Special Features

  • London Borough of Sutton: Includes detailed endpoint documentation with parameter specifications, response formats, and working examples
  • Council Discovery: Built-in fuzzy matching to find councils by name (find_council)
  • Regional Search: Find all councils in a specific region (get_council_by_region)
  • Confidence Scoring: Search with configurable confidence thresholds (search_councils)

Council Discovery

Use the built-in council finder tools:

# Find a specific council
curl -X POST http://localhost:3003/mcp \
  -H "Content-Type: application/json" \
  -d '{"method": "tools/call", "params": {"name": "find_council", "arguments": {"council_name": "Leeds"}}}'

# Search councils by region
curl -X POST http://localhost:3003/mcp \
  -H "Content-Type: application/json" \
  -d '{"method": "tools/call", "params": {"name": "get_council_by_region", "arguments": {"region": "West Midlands"}}}'

API Discovery

To discover available operations for a specific council site, you can inspect the WSDL:

curl "https://democracy.lichfielddc.gov.uk/mgWebService.asmx?WSDL" | grep -i "council"

Examples

See the examples/ directory for complete configuration examples:

  • Cursor: examples/cursor-mcp.json
  • Claude Desktop: examples/claude-desktop-config.json
  • VS Code: examples/vscode-mcp.json
  • Docker Production: examples/docker-compose.production.yml
  • Nginx Configuration: examples/nginx.conf
  • Test Client: examples/test-mcp-client.js
  • Postman Collection: examples/postman-collection.json
  • Environment Config: examples/env-example.txt

Quick Test

Test your setup with the provided script:

./examples/test-setup.sh

Configuration Notes

The MCP server supports both native Node.js execution and Docker deployment. Choose the configuration that matches your deployment method.

MCP Client Configuration

Choose the configuration that matches your transport preference:

βœ… HTTP Transport (Recommended for production):

{
  "mcpServers": {
    "modgov-council": {
      "url": "http://localhost:3003/mcp",
      "headers": {
        "Content-Type": "application/json",
        "Accept": "application/json, text/event-stream"
      }
    }
  }
}

βœ… STDIO Transport (Recommended for development):

{
  "mcpServers": {
    "modgov-council": {
      "command": "node",
      "args": ["dist/index.js"],
      "cwd": "/path/to/modgov-mcp-server"
    }
  }
}

Server Requirements:

For HTTP Transport:

  • Start the server: MCP_TRANSPORT=http node dist/index.js
  • Or with Docker: make build && make up
  • Server available at: http://localhost:3003/mcp
  • Health check: curl http://localhost:3003/health

For STDIO Transport:

  • Build the project: npm run build
  • Client will spawn: node dist/index.js
  • No persistent server required

🎯 Best Practices

  1. Always use the MCP server - It handles all server bugs automatically
  2. Don't rely on WSDL alone - Test actual server behavior
  3. Handle 500 errors gracefully - May indicate server bugs, not client errors
  4. Use sensible defaults - The MCP provides them automatically
  5. Test across multiple sites - Behavior is consistent but verify
  6. Use council discovery tools - Find councils by name or region easily

πŸ”§ Error Handling Examples

// The MCP server handles these automatically, but for direct API usage:
try {
  const result = await modgovClient.getMeetings(siteUrl, 138);
} catch (error) {
  if (error.message.includes('Missing parameter')) {
    // This indicates a server bug, not client error
    console.log('Server implementation bug detected - use MCP server instead');
  }
}

Contributing

  1. Follow TDD principles - write tests first
  2. Ensure all tests pass before committing
  3. Add new features with comprehensive test coverage
  4. Update documentation for any API changes

License

MIT

About

An MCP server for querying Modern.gov powered sites.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published