Refactor agent to read tracker data via remote MCP server#118
Open
matthelm wants to merge 2 commits intoBuildCanada:mainfrom
Open
Refactor agent to read tracker data via remote MCP server#118matthelm wants to merge 2 commits intoBuildCanada:mainfrom
matthelm wants to merge 2 commits intoBuildCanada:mainfrom
Conversation
The Build Canada tracker already makes government accountability data publicly available through a REST API. This PR adds a Model Context Protocol (MCP) server so AI assistants can query that data directly. Anyone using Claude Desktop, Claude Code, Cursor, or any MCP client can connect with a single URL: https://www.buildcanada.com/mcp ## MCP server Uses the official `mcp` Ruby SDK with stateless Streamable HTTP transport. Thirteen read-only tools, no auth required: - list_policy_areas — discover valid policy area slugs - list_commitments / get_commitment — search and inspect commitments - list_promises / get_promise — platform promises with progress scores - list_bills / get_bill — parliamentary bills with stage tracking - list_departments / get_department — departments with ministers - list_ministers — cabinet officials by portfolio - list_activity — chronological feed of government activity - get_commitment_summary — status overview by policy area - get_commitment_progress — time-series for trend analysis Each tool dispatches internally to the existing REST endpoints via Rack — zero duplicated query or serialization logic. The entire MCP surface is a single controller with a declarative config array. Adding a new tool is ~8 lines. No existing files are modified — this is purely additive (new controller, new policy_areas endpoint, routes, and tests). ## Testing locally 1. Start Rails: `bin/rails server -p 3099` 2. Verify: `curl -X POST http://localhost:3099/mcp -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}'` 3. To test with Claude Desktop, expose via ngrok: ngrok http 3099 4. In Claude Desktop: Settings > Connectors > Add custom connector, then enter the ngrok URL with /mcp appended. You may need to allow the ngrok host in Rails: # config/initializers/allow_tunnel.rb (do not commit) Rails.application.config.hosts.clear 5. Run tests: `bin/rails test test/controllers/mcp_controller_test.rb`
The evaluation agent previously read commitments, bills, and other tracker data via ~300 lines of raw SQL in db_read.py. It now connects to the remote MCP server (POST /mcp) for those reads, removing the duplicated query logic. The agent uses two MCP servers: - "tracker" (remote) — read-only tools served by the Rails app - "agent" (local) — entry processing and government page fetching The CLI scan-all command now reads via the REST API with correct stale-first ordering (sort=last_assessed_at, direction=asc). ## REST API enhancements (to support agent and MCP tools) - GET /commitments: stale_days filter, criteria_count/matches_count in response, last_assessed_at in listing, NULLS FIRST ordering - GET /commitments/:id: evidence matches (linked bills/entries) - GET /bills: parliament_number and government_bills filters - GET /bills/:id: Jbuilder view with linked_commitments - GET /policy_areas: new endpoint (id, name, slug, description) ## New MCP tools (added to the controller from PR 1) - list_policy_areas — discover valid policy area slugs - Updated list_commitments with stale_days, criteria_count, matches_count - Updated list_bills with parliament_number and government_bills filters - Updated get_commitment with evidence matches - Updated get_bill with linked_commitments Depends on: feat/mcp-server (the MCP endpoint must be deployed first)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Refactors the evaluation agent to read tracker data through the remote MCP server (from #117) instead of direct Postgres queries, removing ~300 lines of raw SQL. Also enriches the REST API and MCP tools to support the agent's needs.
Agent changes
The agent previously maintained its own SQL queries for reading commitments, bills, sources, and parliament data (
db_read.py— 277 lines). It now connects to two MCP servers:POST /mcpThe CLI
scan-allcommand now reads via the REST API with correct stale-first ordering.REST API enhancements
Additive changes to existing endpoints to support both the agent and MCP tools:
GET /commitments—stale_daysfilter,criteria_count/matches_count/last_assessed_atin response,NULLS FIRSTordering forlast_assessed_atsortGET /commitments/:id— evidence matches (linked bills/entries with relevance scores)GET /bills—parliament_numberandgovernment_billsfiltersGET /bills/:id— Jbuilder view withlinked_commitmentsGET /policy_areas— new lightweight endpointNew/updated MCP tools
list_policy_areas— discover valid policy area slugs for filteringlist_commitments— gainsstale_daysparam, response includescriteria_countandmatches_countget_commitment— response includes evidence matcheslist_bills— gainsparliament_numberandgovernment_billsparamsget_bill— response includeslinked_commitments