- ✅ v1.0 MVP - Phases 1-6 (shipped 2026-04-07)
- 🚧 v1.1 Statistics Canada + Datastore - Phases 7-10 (in progress)
✅ v1.0 MVP (Phases 1-6) - SHIPPED 2026-04-07
Phases 1-6 delivered 7 federal API modules (Bank of Canada, Open Parliament, Recalls, Drug Database, CKAN, Nutrient File, Weather/Climate), BM25 tool discovery, bilingual support, and multi-platform install. 81 tools total.
Milestone Goal: An agent can combine data from any Canadian government source in a single SQL query — turning 7 isolated APIs into one queryable data platform.
- Phase 7: Datastore + SSL - SQLite persistence layer and StatCan SSL strategy resolved (completed 2026-04-07)
- Phase 8: StatCan WDS - All WDS discovery, series, data, and monitoring tools live (completed 2026-04-07)
- Phase 9: SDMX + Composite - Server-side filtered queries and fetch-and-store bridge complete
- Phase 10: Tests + Docs - Integration test coverage and README updated (completed 2026-04-08)
Goal: Agents can persist any data to a local SQLite store and the StatCan SSL strategy is decided before any statcan client code is written Depends on: Nothing (no external API dependency; SSL investigation is empirical) Requirements: DS-01, DS-02, DS-03, DS-04, DS-05, DS-06, DS-07, DS-08, INF-01 Success Criteria (what must be TRUE):
- Agent can create a named table, insert rows, run SELECT queries, list tables, inspect schema, and drop a table — all without blocking the event loop
- Agent-supplied table and column names containing SQL metacharacters are rejected with a structured error before any SQL executes
- StatCan HTTP client uses either truststore-based cert resolution or a scoped verify=False limited strictly to the statcan module — never the shared lifespan client
aiosqliteis listed in pyproject.toml; existinguvx mcp-canadainvocation still works with no new mandatory configuration
Plans: 3/3 plans complete
Plans:
- 07-01-PLAN.md — Datastore module infrastructure: constants, schemas, async SQLite client, identifier validation, --ephemeral flag
- 07-02-PLAN.md — Datastore tools (6 @tool functions) + unit tests + integration tests
- 07-03-PLAN.md — StatCan SSL probe + statcan module stub with _make_statcan_client factory
Goal: Agents can discover, explore, and retrieve Statistics Canada time series data through all WDS REST endpoints with proper caching, rate limiting, and bilingual support Depends on: Phase 7 (SSL strategy decided; datastore available for composite testing in Phase 9) Requirements: SC-01, SC-02, SC-03, SC-04, SC-05, SC-06, SC-07, SC-08, SC-09, SC-13, SC-14, INF-02, INF-03, INF-04, INF-05 Success Criteria (what must be TRUE):
- Agent can search 80,000+ Statistics Canada tables by keyword and receive ranked results (top 20 max)
- Agent can retrieve full dimension metadata for a productId and decode all numeric code fields (frequency, units, scalar factor, status) into human-readable labels
- Agent can fetch the latest N observations for a vector (by vectorId or productId+coordinate), retrieve historical data by date range, and fetch multiple vectors simultaneously
- Agent can list series and cubes that changed on a specific date, enabling change-monitoring workflows
- All StatCan tools respect the 20 req/s rate limit, apply tiered TTL caching (cube list 1hr, metadata 24hr, code sets 7d, observations 1hr), and return bilingual responses
Plans: 3/3 plans complete
Plans:
- 08-01-PLAN.md — Constants, schemas, BM25 search, getCubeMetadata, getCodeSets client functions + tests
- 08-02-PLAN.md — Series info, data retrieval, and change monitoring client functions + tests
- 08-03-PLAN.md — All 11 sc_ tool functions + integration tests through MCP Client
Goal: Agents can apply server-side dimension filters via SDMX for large tables and store multi-series fetches directly to the shared datastore in a single tool call Depends on: Phase 7 (datastore), Phase 8 (WDS tools — productIds and coordinate structures needed to test SDMX filtering) Requirements: SC-10, SC-11, SC-12, SC-15 Success Criteria (what must be TRUE):
- Agent can retrieve the dimension structure (codelists) for any StatCan table via SDMX
- Agent can retrieve server-side filtered observations using SDMX key syntax with date range or lastN support — but not both simultaneously (mutual exclusion enforced)
- Agent can fetch multiple vectors for a date range and have results written to the shared datastore in one tool call, enabling subsequent cross-module SQL queries
Plans: 1/2 plans executed
Plans:
- 09-01-PLAN.md — SDMX client layer: constants, schemas, 3 async client functions (structure/data/vector), unit tests
- 09-02-PLAN.md — SDMX + composite tools (4 @tool functions), unit tests, integration tests through MCP Client
Goal: All new tools are covered by integration tests through the MCP Client layer and the README accurately reflects the expanded tool catalog Depends on: Phase 9 (all tool surfaces must exist before integration sweep) Requirements: INF-06, INF-07, INF-08, INF-09 Success Criteria (what must be TRUE):
- Unit test coverage for all new code is at or above 95% as reported by pytest-cov
- Every new tool has at least one integration test scenario that calls it through the MCP Client layer (not client functions directly) and asserts on response shape
- README tool catalog lists all new statcan and datastore tools with accurate descriptions and updated tool count
- EXAMPLES.md contains at least one end-to-end example showing cross-module SQL queries combining StatCan and another module's data
Plans: 2/2 plans complete
Plans:
- 10-01-PLAN.md — Integration test audit + coverage verification (INF-06, INF-07)
- 10-02-PLAN.md — README updates + EXAMPLES.md cross-module SQL examples (INF-08, INF-09)
Execution Order: 7 → 8 → 9 → 10 (Phase 9 unblocks after both Phase 7 and Phase 8 complete)
| Phase | Milestone | Plans Complete | Status | Completed |
|---|---|---|---|---|
| 7. Datastore + SSL | 3/3 | Complete | 2026-04-07 | - |
| 8. StatCan WDS | 3/3 | Complete | 2026-04-07 | - |
| 9. SDMX + Composite | 1/2 | In Progress | - | |
| 10. Tests + Docs | 2/2 | Complete | 2026-04-08 | - |
Goal: Build a shared XLSX/CSV/XLS parser library, then create an IRCC module that uses it to expose 10 actively-updated immigration datasets (150+ files) as clean ircc_ tools Depends on: Phase 7 (datastore), Phase 10 (docs pattern) Requirements: IRCC-01, IRCC-02, IRCC-03, IRCC-04, IRCC-05, IRCC-06, IRCC-07, IRCC-08, IRCC-09 Success Criteria (what must be TRUE):
- Shared parser can fetch and parse XLSX, CSV, and XLS files from any URL into list[dict] rows
- Agent can query permanent residents by country of citizenship, province, and immigration category
- Agent can query study permits, work permits, Express Entry, asylum claimants, and operational processing data
- IRCC tools handle privacy masking (
--values), bilingual columns, and multi-sheet workbooks - All IRCC tools follow mcp-canada conventions (envelopes, bilingual, BM25 keywords)
- Parsed IRCC data can be stored to the shared datastore for cross-module SQL queries
- Any future module can reuse the shared parser to fetch CKAN dataset resources
Plans: 4/4 plans complete
Plans:
- 11-01-PLAN.md — Shared file parser library (parsers.py) + openpyxl dependency + unit tests
- 11-02-PLAN.md — IRCC module skeleton: dataset registry, client functions, unit tests
- 11-03-PLAN.md — IRCC tool functions, integration tests, README update
- 11-04-PLAN.md — Gap closure: IRCC multi-row merged header parsing (UAT blocker)
Goal: Agents can search Ontario's 2,946 open datasets (data.ontario.ca), browse ministry organizations, get dataset/resource details, and fetch curated population projections data — reusing the proven CKAN client pattern and shared XLSX parser Depends on: Phase 11 (shared parsers) Requirements: ONT-01, ONT-02, ONT-03, ONT-04, ONT-05, ONT-06, ONT-07, ONT-08 Success Criteria (what must be TRUE):
- Agent can search Ontario datasets by keyword and get shaped results with bilingual title/description
- Agent can get full dataset details, resource details, list organizations, and get portal statistics
- Agent can fetch Ontario population projections from the Ministry of Finance XLSX file
- All Ontario tools follow mcp-canada conventions (ontario_ prefix, envelopes, bilingual, BM25 keywords)
- Ontario tools are discoverable via discover_tools and callable via call_tool through MCP Client
- Unit tests at 95%+ coverage; integration tests verify live API through MCP Client layer
Plans: 2/2 plans complete
Plans:
- 12-01-PLAN.md — Ontario module skeleton: constants, schemas, CKAN client layer, population projections parser, unit tests
- 12-02-PLAN.md — Ontario tool functions, unit tests, integration tests, README update
Goal: Agents can search Toronto's open data catalogue (open.toronto.ca), browse city divisions, get dataset/resource details, and use curated tools for TTC transit (GTFS), neighbourhood profiles, 311 service requests, RentSafeTO evaluations, and short-term rentals — with new shared GeoJSON/JSON parsers Depends on: Phase 12 (Ontario CKAN pattern) Requirements: TOR-01, TOR-02, TOR-03, TOR-04, TOR-05, TOR-06, TOR-07, TOR-08, TOR-09, TOR-10, TOR-11, TOR-12 Success Criteria (what must be TRUE):
- Shared parsers handle GeoJSON and JSON in addition to CSV/XLSX/XLS
- Agent can search Toronto datasets and get shaped results with bilingual title/description
- Agent can search TTC stops and routes from parsed GTFS ZIP data
- Agent can query neighbourhood census indicators and compare across neighbourhoods
- Agent can fetch 311 service requests with year/ward/type/status filters
- Agent can query RentSafeTO evaluations and short-term rental registrations
- All Toronto tools follow mcp-canada conventions (toronto_ prefix, envelopes, bilingual, BM25 keywords)
- Unit tests at 95%+ coverage; integration tests verify live API through MCP Client layer
Plans: 2/2 plans complete
Plans:
- 13-01-PLAN.md — Shared GeoJSON/JSON parsers + Toronto module skeleton: constants, schemas, client layer, unit tests
- 13-02-PLAN.md — Toronto tool functions, unit tests, integration tests, README update
Goal: Agents can search 4 verified ArcGIS Hub portals in York Region (York Region regional, Markham, Newmarket, Aurora) and use curated tools for YRT/Viva transit, regional roads, public health, 2021 census demographics, and waste management — reusing a new shared/arcgis_hub.py client that will template future ArcGIS Hub modules. 6 York Region municipalities without public portals return structured NOT_FOUND.
Requirements: YR-01, YR-02, YR-03, YR-04, YR-05, YR-06, YR-07, YR-08, YR-09, YR-10, YR-11, YR-12, YR-13, YR-14
Depends on: Phase 13 (shared parsers with _parse_geojson reused)
Success Criteria (what must be TRUE):
shared/arcgis_hub.pyprovides a reusable ArcGIS Hub Search API + FeatureServer client (search, query, layer metadata, count)- Agent can search each of 4 verified portals (york_region, markham, newmarket, aurora) via 5 discovery tools per prefix (20 total)
- Agent can fetch curated York Region data: YRT/Viva transit stops/routes, regional road network, public health (beach water/hospital/drinking water), 2021 census age/sex/income by Dissemination Area, waste diversion and solid waste sites
- Agent can query curated Markham data: civic addresses and SLRN road network
- Municipalities without public ArcGIS Hub portals (Vaughan, Richmond Hill, King, East Gwillimbury, Georgina, Whitchurch-Stouffville general data) return structured NOT_FOUND via NoPortalError
- Module follows 7-file pattern with prompts.py (4-6 bilingual prompts) and resources.py (6-10 resources covering portal catalog, municipality list, ESRI field naming, census variable reference, ArcGIS query patterns, response templates)
- Unit test coverage ≥95%; integration tests verify live ArcGIS Hub endpoints through MCP Client layer
- README reflects new tool catalog (~27 tools) and ArcGIS Hub as a second portal technology alongside CKAN
Plans: 3/3 plans complete
Plans:
- 14-01-PLAN.md — Shared ArcGIS Hub client + York Region module skeleton (constants, schemas, client, unit tests)
- 14-02-PLAN.md — York Region tool functions (20 discovery × 4 portals + 7 curated) + unit tests
- 14-03-PLAN.md — Prompts, resources, integration tests, README, and REQUIREMENTS.md finalization
Goal: Agents can search the BC Data Catalogue (CKAN + bcgov custom extensions) and query BC Geographic Warehouse geospatial layers via WFS 2.0, with 20 curated bc_ tools (5 discovery + 15 WFS-backed) covering wildfire, forestry, environment, natural resources, health, transportation, and climate. Introduces a reusable shared/ogc.py WFS client (third portal tech alongside CKAN and ArcGIS Hub) plus 6 prompts and 7 resources.
Requirements: BC-01, BC-02, BC-03, BC-04, BC-05, BC-06, BC-07, BC-08, BC-09, BC-10, BC-11, BC-12, BC-13, BC-14, BC-15, BC-16, BC-17, BC-18, BC-19, BC-20, BC-21, BC-22 (backfilled 2026-07-25 from shipped code)
Depends on: Phase 14
Plans: 5/5 plans complete
Plans:
- 15-01-PLAN.md — shared/ogc.py WFS 2.0 client + british_columbia module skeleton + Wave 0 test stubs
- 15-02-PLAN.md — CKAN client functions + 5 discovery tools (bc_search_datasets, bc_get_dataset_details, bc_query_features, bc_list_organizations, bc_list_categories)
- 15-03-PLAN.md — _wfs_fetch caching layer + 15 curated WFS tools (wildfire, forestry, environment, mining, health, transportation, climate)
- 15-04-PLAN.md — 6 prompts + 7 resources + integration tests + README + CLAUDE.md updates
Goal: Agents can search the Données Québec CKAN catalogue (1,593 datasets, 139 orgs, 10 thematic groups) and access curated MSSS health, MTQ transport, environment, demographics, and energy data via 18 quebec_ tools (5 discovery + 13 curated), reusing the post-15-05 _api_get parsed-dict pattern and Phase 15 TestSharedApiGetContract test class from day 1.
Requirements: QC-01, QC-02, QC-03, QC-04, QC-05, QC-06, QC-07, QC-08, QC-09, QC-10, QC-11, QC-12, QC-13, QC-14, QC-15, QC-16, QC-17, QC-18, QC-19 (backfilled 2026-07-25 from shipped code)
Depends on: Phase 15
Plans: 8/8 plans complete + 1 gap-closure plan (18-09)
Plans:
- 16-01-PLAN.md — Quebec module skeleton + Wave 0 test scaffolds
- 16-02-PLAN.md — CKAN client + 5 discovery tools + TestSharedApiGetContract
- 16-03-PLAN.md — Health (MSSS) + Transport (MTQ) curated tools (7)
- 16-04-PLAN.md — Environment/Demographics/Energy tools (6) + prompts + resources + integration + docs
- 16-05-PLAN.md — Gap closure cycle 1 (post-UAT)
- 16-06-PLAN.md — Gap closure cycle 2 (WFS paging, snake_case mapper, Hydro-Québec SECLEVEL=1 SSL)
- 16-07-PLAN.md — Gap closure cycle 3 (bridges int->str coercion, electricity XLSX legend row filter)
- 16-08-PLAN.md — Gap closure cycle 4 (route filter substring match bug)
Goal: Add Alberta's provincial open data surface to mcp-canada via 24 alberta_ tools (5 discovery + 19 curated) covering open.alberta.ca CKAN catalogue (33,269 datasets), GeoDiscover Alberta ArcGIS REST 11.3, WMBappServices wildfire FeatureServers, AHSGIS health FeatureServers, AER (Alberta Energy Regulator) static reports (ST1/ST3/ST39), and 511 Alberta road API. Reuses shared/arcgis_hub.py + shared/parsers.fetch_and_parse — NO new shared utilities. Adds 6 prompts + 7 resources from day 1. Requirements: AB-01, AB-02, AB-03, AB-04, AB-05, AB-06, AB-07, AB-08, AB-09, AB-10, AB-11, AB-12, AB-13, AB-14, AB-15, AB-16, AB-17, AB-18, AB-19, AB-20, AB-21, AB-22, AB-23, AB-24, AB-25, AB-26, AB-27 Depends on: Phase 16 Plans: 9/9 plans complete
Plans:
- 17-01-PLAN.md — Module scaffolding: 7-file pattern + Wave 0 test stubs + _api_get/_511_get helpers + 24 client function stubs
- 17-02-PLAN.md — 5 CKAN discovery tools + TestSharedApiGetContract regression guard
- 17-03-PLAN.md — 4 AER tools (ST1 daily, ST1 archive, ST39 pipelines, ST3 production)
- 17-04-PLAN.md — 4 wildfire tools (active fires, perimeters, fire bans, fire control orders)
- 17-05-PLAN.md — 3 AHS health tools (hospitals, zones, EMS/PCN clinics)
- 17-06-PLAN.md — 3 transport tools (511 road events, winter conditions, cameras)
- 17-07-PLAN.md — 5 environment/agriculture/demographics/parks tools
- 17-08-PLAN.md — 6 prompts + 7 resources (Phase 40 pattern)
- 17-09-PLAN.md — Parametrized envelope/lang tests + integration tests + README/docs/EXAMPLES updates + 95% coverage gate
Goal: Add Manitoba's provincial open data as a new manitoba module via the geoportal.gov.mb.ca ArcGIS Hub (org mMUesHYPkXjaFGfS) — 5 Hub discovery tools + ~15 curated FeatureServer tools across flood/hydrology, agriculture & drought, environment/parks, regional health, and conditional Manitoba 511 transport, with 6 bilingual prompts + 7 resources. ArcGIS Hub pattern (Alberta Phase 17 / York Region Phase 14), NOT CKAN.
Requirements: MB-01, MB-02, MB-03, MB-04, MB-05, MB-06, MB-07, MB-08, MB-09, MB-10, MB-11, MB-12, MB-13, MB-14, MB-15, MB-16, MB-17, MB-18
Depends on: Phase 17
Plans: 9/9 plans complete
Plans:
- 18-01-PLAN.md — Module scaffold (7 files + test scaffolds, stubs, fixtures) + Wave 0 spike (511 key + resolve 3 FeatureServer URLs)
- 18-02-PLAN.md — 5 ArcGIS Hub discovery tools (search, details, query auto-router, organizations, categories)
- 18-03-PLAN.md — 3 flood/hydrology tools (flood alerts, river stations, provincial waterways)
- 18-04-PLAN.md — 4 agriculture/drought tools (drought monitor, ag weather stations, livestock prices, crop regions)
- 18-05-PLAN.md — 5 environment/health/parks tools (parks, surgical wait times, fisheries, forests, health facilities)
- 18-06-PLAN.md — 3 transport tools (511 road events, winter conditions, cameras — conditional, NOT_CONFIGURED fallback)
- 18-07-PLAN.md — 6 bilingual prompts + 7 resources (Phase 40 pattern)
- 18-08-PLAN.md — Parametrized envelope/lang tests + integration tests + README/MODULES/CLAUDE/EXAMPLES sync + 95% coverage gate
- 18-09-PLAN.md — Gap closure: fix 3 ArcGIS-Hub discovery tools (OGC limit/startindex params, omit blank q) + param-regression tests + live integration check [MB-01, MB-04, MB-05]
Goal: Add Saskatchewan's provincial open data as a new saskatchewan module via the geohub.saskatchewan.ca ArcGIS Hub (primary org zcv98lgAl8xQ04cW), the separate WSA org (7MBdlVpjqbfBhQer), and the SPSA wildfire REST server (gis.saskatchewan.ca/egis) — a lean 14 tools (5 Hub discovery + 9 curated) across agriculture (crop yields, grain elevators), energy/mining (potash/uranium/helium/coal), environment (fire bans, historic wildfires, air quality), and water (WSA hydrometric stations, reservoirs), with 6 bilingual prompts + 7 resources. ArcGIS Hub pattern (Manitoba Phase 18 / Alberta Phase 17), NOT CKAN. Wave 0 fixes the shared arcgis_hub.py startindex pagination bug (benefits York/Alberta/Manitoba too). Transport (511 key-gated) and Health (no public SHA FeatureServer) are deferred — no NOT_CONFIGURED stubs.
Requirements: SK-01, SK-02, SK-03, SK-04, SK-05, SK-06, SK-07, SK-08, SK-09, SK-10, SK-11, SK-12, SK-13, SK-14, SK-15
Depends on: Phase 18
Plans: 7/7 plans complete
Plans:
- 19-01-PLAN.md — Wave 0: shared/arcgis_hub.py startindex fix + York/Alberta/Manitoba no-regression check + module scaffold (7 files + test scaffolds, constants for 3 bases, ~14 client stubs) + spike (WSA water-quality layer 19 + Petroleum 400)
- 19-02-PLAN.md — 5 ArcGIS Hub discovery tools (search/details/query auto-router/orgs/categories) with OGC params (limit/startindex, omit blank q) + TestSharedApiGetContract
- 19-03-PLAN.md — Agriculture (crop yields, grain elevators) + Energy/mining (mineral mines dispatch: potash/uranium/helium/coal) — 3 curated tools
- 19-04-PLAN.md — Environment (fire bans via SPSA, historic wildfires, air quality) — 3 curated tools
- 19-05-PLAN.md — Water/WSA (hydrometric stations, reservoirs layer 26) — 2 curated tools
- 19-06-PLAN.md — 6 bilingual prompts + 7 resources (Phase 40 pattern), portal-guide documents multi-org architecture + deferred domains
- 19-07-PLAN.md — Parametrized envelope/lang tests + LIVE field-presence integration (Manitoba lesson) + README/MODULES/CLAUDE/EXAMPLES sync + 95% coverage gate
Goal: Add Nova Scotia provincial open data via data.novascotia.ca (Socrata SODA API) as a new nova_scotia module, establishing a reusable shared/socrata.py client (the 4th portal technology). Ship 5 discovery tools + 12 curated tools (17 total) across fishing/aquaculture, environment/water, lands, air quality, and health + demographics, with 6 bilingual prompts and 7 zero-parameter resources.
Requirements: NS-01…NS-18
Depends on: Phase 19
Plans: 8/8 plans complete
Plans:
- 20-01-PLAN.md — Wave 0: build shared/socrata.py + TestSharedSocrataContract, scaffold nova_scotia module, resolve the 3 dataset-shape spikes (NS-01)
- 20-02-PLAN.md — 5 Socrata catalog discovery tools incl. the categories=-broken workaround (NS-02…NS-06)
- 20-03-PLAN.md — Fishing/aquaculture curated tools: marine + landbased leases, hatchery stocking, production (NS-07…NS-10)
- 20-04-PLAN.md — Environment/water/air curated tools: water quality, boil-water advisories, protected areas, air-quality stations (NS-11, NS-12, NS-15, NS-16)
- 20-05-PLAN.md — Health + demographics curated tools: health facilities (dispatch), vital statistics, chronic disease prevalence (NS-13, NS-14, NS-17)
- 20-06-PLAN.md — 6 bilingual prompts + 7 zero-parameter resources incl. the Socrata/SoQL guide (NS-18)
- 20-07-PLAN.md — Parametrized + LIVE field-presence integration tests, docs sync (Socrata as 4th portal tech), 95% coverage (NS-18)
- 20-08-PLAN.md — Gap closure: per-dataset SoQL for ns_get_health_facilities (hospital + LTC live 400 fix) + real-raw-schema fixtures + de-masked LIVE integration [NS-13]
Goal: Eliminate every masking idiom from the live integration suite, fix the real defects that de-masking exposes, and make the pattern unable to return. Quick task 1 (2026-06-17) removed idiom A from the five provinces it scoped; this phase finishes the modules it never reached (weather, BC, York Region, Alberta), closes the 18 live failures it deferred, and adds an automated guard so a test that cannot fail is caught on commit. Requirements: TEST-01..TEST-05 (backfilled 2026-07-25) Depends on: Phase 20 Plans: 6/6 plans complete
Plans:
- 20.1-01-PLAN.md — Masking guard + PRESERVE marker (worklist for the phase)
- 20.1-02-PLAN.md — De-mask weather (4 files, 32 guards)
- 20.1-03-PLAN.md — De-mask BC; pin WFS-routing tests to stable datasets
- 20.1-04-PLAN.md — De-mask York Region + Alberta
- 20.1-05-PLAN.md — Triage and fix the 18 live failures
- 20.1-06-PLAN.md — PRESERVE audit, structured upstream errors, phase close
Goal: Make every module classify an upstream failure as an upstream failure. shared/http.py:api_get returns response.json() with no decode guard, so an HTTP 200 carrying an HTML error page raises json.JSONDecodeError — a ValueError subclass — which lands in the except ValueError -> INVALID_INPUT arm of statcan, ircc, manitoba, saskatchewan, nova_scotia, british_columbia and datastore. A real outage is reported as caller error, and assert_live_or_transient (which tolerates only UPSTREAM_ERROR / RATE_LIMITED / UPSTREAM_UNAVAILABLE) fails live tests with a misleading code. The guard cannot simply be added at the source: httpx.DecodingError is an HTTPError but not an HTTPStatusError, and 5 of 24 modules (bank_of_canada, ckan, ircc, ontario, recalls) catch only HTTPStatusError — so a naive central fix converts a mislabelled error into an unhandled one, which is strictly worse and is precisely what Phase 20.1 removed. The work is therefore: normalize the handler shape across all 24 modules first, then add one decode guard in api_get. Doing this before Phases 21-39 means ~19 future modules inherit the correct shape instead of enlarging the cleanup.
Requirements: ERR-01..ERR-04
Depends on: Phase 20.1
Plans: 1/1 plans complete
Plans:
- 20.2-01-PLAN.md — Catch-all coverage for every tool + decode guard in api_get
Goal: Finish what Phase 20.2 started. 20.2 added the decode guard to shared/http.py:api_get and stopped there, but three of the four portal technologies decode JSON themselves: ArcGIS Hub and Socrata called response.json() raw, OGC WFS called json.loads(response.content), and the ArcGIS geojson hot path decoded via arcgis_hub._parse_raw_json + parsers._parse_geojson. Because json.JSONDecodeError subclasses ValueError, a malformed body from any of those still reached the except ValueError -> INVALID_INPUT arms in five tools (saskatchewan fire-bans / crop-yields / mineral-mines, manitoba livestock-prices / provincial-waterways) — reproduced before the fix, both probes returned INVALID_INPUT for an upstream outage. Adds decode_json() / decode_json_bytes() to shared/http.py, routes all 14 decode sites through them, and adds a structural test so a raw decode cannot be reintroduced.
Requirements: ERR-05
Depends on: Phase 20.2
Plans: 1/1 plans complete
Plans:
- 20.3-01 — decode_json helpers + route all 14 sites + structural guard
Goal: Remove the defect behind four Codex findings across three PRs. json.JSONDecodeError (PR#2), pydantic.ValidationError (PR#3) and UnicodeDecodeError (PR#4) all subclass ValueError, so each in turn was captured by an except ValueError -> INVALID_INPUT arm and an upstream outage was reported as the caller's mistake. Each was patched by intercepting one more subclass above that arm — a deny-list that cannot be completed, because ValueError is Python's generic bad-value base and any library may add to it. This phase declares blame at the raise site instead (shared/errors.py: InvalidInput / NotFound / UpstreamData) and makes a plain ValueError default to UPSTREAM_ERROR, so an unrecognised subclass is classified safely with no code change. Scope: 31 bare raises classified, 35 handler arms flipped, statcan's 10 message-sniffing arms deleted, and 9 already-misclassified sites corrected. All markers subclass ValueError so unmigrated handlers keep working.
Requirements: ERR-06, ERR-07
Depends on: Phase 20.3
Plans: 1/1 plans complete
Plans:
- 20.4-01 — errors.py markers + classify 31 raises + flip 35 arms + structural guard
Goal: Ship a new_brunswick module exposing NB provincial data as MCP tools — the 8th province in the rollout. 22 tools: 5 federal-CKAN discovery tools (organization:nb, 221 datasets — NB has no provincial CKAN), 2 gnb.socrata.com discovery tools (NB's provincial Socrata portal, 312 datasets, keyless — added by the 21-01 checkpoint, which live-disproved CONTEXT.md's "no provincial catalogue" claim), 3 GeoNB ArcGIS Server discovery tools (the ArcGIS Hub 401s, so the REST directory is enumerated instead), 9 curated geospatial tools across flood/water, Crown land/forestry, parcels/civic address and health/education, and 3 key-gated 511 transport stubs. nb_get_provincial_parks and nb_get_mineral_occurrences were traded to the long tail to hold the 22-tool budget; both stay reachable via nb_query_geonb_layer. Follows the 7-file module pattern; adds two additive bare-ArcGIS-Server enumerator functions to shared/arcgis_hub.py.
Requirements: NB-01..NB-25, ERR-01..ERR-07
Depends on: Phase 20
Plans: 7/7 plans complete
Plans:
Wave 0 (tracer + blocking checkpoint:decision — must resolve before the tool manifest is locked)
- 21-01-PLAN.md — Crown Land tracer end-to-end, gnb.socrata.com discovery-surface checkpoint,
shared/arcgis_hub.pyenumerator + live layer-id spike, full module scaffold
Wave 1 (blocked on Wave 0 completion; 21-02 and 21-03 run in parallel — disjoint files)
- 21-02-PLAN.md — Federal CKAN discovery: 5 tools, bilingual
title_translated/notes_translatedresolution, outgoing-param contract test - 21-03-PLAN.md — 6 prompts + 7 zero-parameter resources (GeoNB catalogue, counties, health/school dispatch, portal guide, query guide, report template)
Wave 2 (blocked on Wave 1 completion)
- 21-04-PLAN.md — GeoNB discovery (3 tools) + flood & water curated (flood hazard, historical floods, wetlands with pre-network guard, contaminated sites)
Wave 3 (blocked on Wave 2 completion)
- 21-05-PLAN.md — Crown land/forestry completion (minerals, parks) + parcels & civic addresses, both guarded over 604K/373K layers
Wave 4 (blocked on Wave 3 completion)
- 21-06-PLAN.md — Health facilities & public schools layer-dispatch tools + 3 NB 511
NOT_CONFIGUREDtransport stubs
Wave 5 (blocked on Wave 4 completion)
- 21-07-PLAN.md — Live MCP-layer integration coverage for all 22 tools, catalogue/README/CLAUDE.md sync, NB-01..NB-25 backfill, COVERAGE.md finalization
Goal: [To be planned] Requirements: TBD Depends on: Phase 21 Plans: 0 plans
Plans:
- TBD (run /gsd:plan-phase 22 to break down)
Goal: [To be planned] Requirements: TBD Depends on: Phase 22 Plans: 0 plans
Plans:
- TBD (run /gsd:plan-phase 23 to break down)
Goal: [To be planned] Requirements: TBD Depends on: Phase 23 Plans: 0 plans
Plans:
- TBD (run /gsd:plan-phase 24 to break down)
Goal: [To be planned] Requirements: TBD Depends on: Phase 24 Plans: 0 plans
Plans:
- TBD (run /gsd:plan-phase 25 to break down)
Goal: [To be planned] Requirements: TBD Depends on: Phase 25 Plans: 0 plans
Plans:
- TBD (run /gsd:plan-phase 26 to break down)
Goal: [To be planned] Requirements: TBD Depends on: Phase 26 Plans: 0 plans
Plans:
- TBD (run /gsd:plan-phase 27 to break down)
Goal: [To be planned] Requirements: TBD Depends on: Phase 27 Plans: 0 plans
Plans:
- TBD (run /gsd:plan-phase 28 to break down)
Goal: [To be planned] Requirements: TBD Depends on: Phase 28 Plans: 0 plans
Plans:
- TBD (run /gsd:plan-phase 29 to break down)
Goal: [To be planned] Requirements: TBD Depends on: Phase 29 Plans: 0 plans
Plans:
- TBD (run /gsd:plan-phase 30 to break down)
Goal: [To be planned] Requirements: TBD Depends on: Phase 30 Plans: 0 plans
Plans:
- TBD (run /gsd:plan-phase 31 to break down)
Goal: [To be planned] Requirements: TBD Depends on: Phase 31 Plans: 0 plans
Plans:
- TBD (run /gsd:plan-phase 32 to break down)
Goal: [To be planned] Requirements: TBD Depends on: Phase 32 Plans: 0 plans
Plans:
- TBD (run /gsd:plan-phase 33 to break down)
Goal: [To be planned] Requirements: TBD Depends on: Phase 33 Plans: 0 plans
Plans:
- TBD (run /gsd:plan-phase 34 to break down)
Goal: [To be planned] Requirements: TBD Depends on: Phase 34 Plans: 0 plans
Plans:
- TBD (run /gsd:plan-phase 35 to break down)
Goal: [To be planned] Requirements: TBD Depends on: Phase 35 Plans: 0 plans
Plans:
- TBD (run /gsd:plan-phase 36 to break down)
Goal: [To be planned] Requirements: TBD Depends on: Phase 36 Plans: 0 plans
Plans:
- TBD (run /gsd:plan-phase 37 to break down)
Goal: [To be planned] Requirements: TBD Depends on: Phase 37 Plans: 0 plans
Plans:
- TBD (run /gsd:plan-phase 38 to break down)
Goal: [To be planned] Requirements: TBD Depends on: Phase 38 Plans: 0 plans
Plans:
- TBD (run /gsd:plan-phase 39 to break down)
Goal: Add MCP prompts (guided workflow templates and quick lookup instructions) and resources (reference catalogs, documentation guides, response templates) to all 12 modules, extending the 5-file module pattern to 7-file with prompts.py and resources.py auto-discovered by FileSystemProvider Depends on: Phase 13 (all modules must exist) Requirements: PR-01, PR-02, PR-03, PR-04, PR-05, PR-06, PR-07, PR-08, PR-09, PR-10, PR-11, PR-12, PR-13, PR-14, PR-15, PR-16, PR-17, PR-18, PR-19, PR-20 Success Criteria (what must be TRUE):
- Every module has prompts.py with 4-6 bilingual @prompt functions (guided workflows + quick lookups) auto-discovered by FileSystemProvider
- Every module has resources.py with 6-10 zero-parameter @resource functions using data://, docs://, template:// URI schemes
- Prompts appear via prompts/list and resources via resources/list natively in MCP clients with no server.py changes
- Integration tests verify discovery of >= 55 prompts and >= 70 resources through MCP Client layer
- README catalogs all prompts and resources; CLAUDE.md documents 7-file module pattern
Plans: 5/5 plans complete
Plans:
- 40-01-PLAN.md — Reference implementation: BoC prompts + resources + _example update + unit tests
- 40-02-PLAN.md — StatCan + Datastore + CKAN prompts/resources + unit tests
- 40-03-PLAN.md — Open Parliament + Recalls + Drug Database + Nutrient File prompts/resources + unit tests
- 40-04-PLAN.md — Weather + IRCC + Ontario + Toronto prompts/resources + unit tests
- 40-05-PLAN.md — Integration tests + README + CLAUDE.md documentation updates