MapleStatsMCP

One Canadian data server to rule them all.

Canadian data lives in dozens of places. MapleStats puts 175 of them behind one connection, so your AI agent can find, fetch and cite the numbers while you focus on what they mean.

One connection

MapleStats puts Canada's scattered agencies and portals behind one connection, in English or French, with the source on every number.

Scripts you can rerun

Most data calls can come back as an R, Python, Stata or Julia script (or an Excel Power Query) that fetches the same numbers straight from the source, so the analysis runs without the agent.

The easiest way: ask your agent One prompt connects MapleStats to the hosted server: nothing to install, no account, no key. The agent reads the setup steps from the repository and does the rest.

Connect the MapleStats MCP server to this agent. Follow the setup steps in https://github.com/dsanchezp18/maplestats-mcp
  1. Copy the prompt.
  2. Paste it into Claude Code, Codex, Cursor or any agent that can run commands on your computer.
  3. Restart the agent when it says so, then ask for data.
  • PyPI version
  • Supported Python versions
  • License: MIT
  • PyPI downloads per month
  • Version on the official MCP Registry
  • Quality and maintenance score on Glama
  • Listed on Smithery
  • Listed on Mcprush
  • Listed on LobeHub
  • Wheels for Raspberry Pi on piwheels
  • Trust score on M8ven
  • Trust index on MCPLookup

3

MCPs for the statisticians, keepers of the weights and the margins,

7

for the demographers, counting who comes to stay,

9

for the financial analysts, doomed to explain the rate…

But MapleStats is the one MCP to rule them all.

Too many places to look, too many interfaces to learn.

MCPs made it easier to connect AI agents to data, and people started building narrow servers for narrow pieces of the Canadian data ecosystem: one for Statistics Canada, another for the Bank of Canada, others for open-data portals. Each can be useful. Together they recreate an old Canadian data problem: too many choices before asking a relatively simple question. I built MapleStats to take the opposite approach: one MCP for Canadian open data.

MapleStats MCP

Centralize the interface, not the data.

The server keeps no dataset of its own, only short-lived caches. It calls each source directly, so every number comes from its publisher.

One discovery layer, many adaptors.

Each agency keeps its own adaptor underneath. The agent sees one search across all of them.

Start from the question, not the portal.

The agent does not need to know whether the answer is a StatCan table, a Valet series, a CMHC dataset or a CKAN resource.

Demos

What you can do with it

Nine questions, from nine kinds of work, each answered with MapleStats tool calls. Here is one of them: a macroeconomist reading the yield curve.

Macroeconomists

What bond markets expect, in one line

The gap between the 10-year and 2-year Government of Canada bond yields, every business day since 2001. When it drops below zero, markets expect rates to fall, usually because they expect the economy to slow. It inverted in 2007, 2019 to 2020 and 2022 to 2024.

The yield curve: 10-year minus 2-year Government of Canada benchmark bond yields, monthly average of daily values, with inverted months shaded−200 bp−100 bp0 bp100 bp200 bp300 bpInverted200520102015202020252001-01-01: 41 bp2001-02-01: 50 bp2001-03-01: 63 bp2001-04-01: 82 bp2001-05-01: 98 bp2001-06-01: 92 bp2001-07-01: 98 bp2001-08-01: 107 bp2001-09-01: 163 bp2001-10-01: 187 bp2001-11-01: 207 bp2001-12-01: 213 bp2002-01-01: 225 bp2002-02-01: 207 bp2002-03-01: 161 bp2002-04-01: 139 bp2002-05-01: 144 bp2002-06-01: 141 bp2002-07-01: 171 bp2002-08-01: 183 bp2002-09-01: 150 bp2002-10-01: 165 bp2002-11-01: 176 bp2002-12-01: 170 bp2003-01-01: 166 bp2003-02-01: 153 bp2003-03-01: 132 bp2003-04-01: 131 bp2003-05-01: 124 bp2003-06-01: 131 bp2003-07-01: 170 bp2003-08-01: 188 bp2003-09-01: 172 bp2003-10-01: 169 bp2003-11-01: 161 bp2003-12-01: 165 bp2004-01-01: 183 bp2004-02-01: 199 bp2004-03-01: 195 bp2004-04-01: 188 bp2004-05-01: 181 bp2004-06-01: 163 bp2004-07-01: 160 bp2004-08-01: 165 bp2004-09-01: 147 bp2004-10-01: 133 bp2004-11-01: 126 bp2004-12-01: 138 bp2005-01-01: 131 bp2005-02-01: 129 bp2005-03-01: 122 bp2005-04-01: 109 bp2005-05-01: 103 bp2005-06-01: 98 bp2005-07-01: 88 bp2005-08-01: 81 bp2005-09-01: 74 bp2005-10-01: 59 bp2005-11-01: 40 bp2005-12-01: 23 bp2006-01-01: 24 bp2006-02-01: 22 bp2006-03-01: 26 bp2006-04-01: 32 bp2006-05-01: 29 bp2006-06-01: 17 bp2006-07-01: 21 bp2006-08-01: 16 bp2006-09-01: 12 bp2006-10-01: 9 bp2006-11-01: 6 bp2006-12-01: 6 bp2007-01-01: 7 bp2007-02-01: 4 bp2007-03-01: 10 bp2007-04-01: 7 bp2007-05-01: −3 bp2007-06-01: −5 bp2007-07-01: −5 bp2007-08-01: 8 bp2007-09-01: 15 bp2007-10-01: 16 bp2007-11-01: 32 bp2007-12-01: 27 bp2008-01-01: 54 bp2008-02-01: 77 bp2008-03-01: 93 bp2008-04-01: 84 bp2008-05-01: 75 bp2008-06-01: 58 bp2008-07-01: 62 bp2008-08-01: 80 bp2008-09-01: 82 bp2008-10-01: 145 bp2008-11-01: 171 bp2008-12-01: 157 bp2009-01-01: 167 bp2009-02-01: 175 bp2009-03-01: 186 bp2009-04-01: 189 bp2009-05-01: 208 bp2009-06-01: 217 bp2009-07-01: 218 bp2009-08-01: 213 bp2009-09-01: 211 bp2009-10-01: 196 bp2009-11-01: 209 bp2009-12-01: 213 bp2010-01-01: 221 bp2010-02-01: 210 bp2010-03-01: 192 bp2010-04-01: 177 bp2010-05-01: 165 bp2010-06-01: 163 bp2010-07-01: 162 bp2010-08-01: 160 bp2010-09-01: 147 bp2010-10-01: 139 bp2010-11-01: 145 bp2010-12-01: 154 bp2011-01-01: 153 bp2011-02-01: 158 bp2011-03-01: 152 bp2011-04-01: 152 bp2011-05-01: 151 bp2011-06-01: 152 bp2011-07-01: 145 bp2011-08-01: 146 bp2011-09-01: 128 bp2011-10-01: 129 bp2011-11-01: 119 bp2011-12-01: 110 bp2012-01-01: 100 bp2012-02-01: 96 bp2012-03-01: 91 bp2012-04-01: 77 bp2012-05-01: 71 bp2012-06-01: 74 bp2012-07-01: 66 bp2012-08-01: 67 bp2012-09-01: 69 bp2012-10-01: 71 bp2012-11-01: 65 bp2012-12-01: 67 bp2013-01-01: 76 bp2013-02-01: 86 bp2013-03-01: 88 bp2013-04-01: 79 bp2013-05-01: 89 bp2013-06-01: 110 bp2013-07-01: 129 bp2013-08-01: 143 bp2013-09-01: 145 bp2013-10-01: 136 bp2013-11-01: 145 bp2013-12-01: 157 bp2014-01-01: 150 bp2014-02-01: 142 bp2014-03-01: 141 bp2014-04-01: 138 bp2014-05-01: 126 bp2014-06-01: 121 bp2014-07-01: 110 bp2014-08-01: 98 bp2014-09-01: 104 bp2014-10-01: 99 bp2014-11-01: 100 bp2014-12-01: 84 bp2015-01-01: 77 bp2015-02-01: 94 bp2015-03-01: 89 bp2015-04-01: 83 bp2015-05-01: 107 bp2015-06-01: 117 bp2015-07-01: 113 bp2015-08-01: 99 bp2015-09-01: 100 bp2015-10-01: 93 bp2015-11-01: 101 bp2015-12-01: 92 bp2016-01-01: 87 bp2016-02-01: 70 bp2016-03-01: 72 bp2016-04-01: 73 bp2016-05-01: 75 bp2016-06-01: 64 bp2016-07-01: 51 bp2016-08-01: 49 bp2016-09-01: 53 bp2016-10-01: 60 bp2016-11-01: 81 bp2016-12-01: 96 bp2017-01-01: 95 bp2017-02-01: 94 bp2017-03-01: 93 bp2017-04-01: 79 bp2017-05-01: 82 bp2017-06-01: 64 bp2017-07-01: 69 bp2017-08-01: 64 bp2017-09-01: 52 bp2017-10-01: 55 bp2017-11-01: 48 bp2017-12-01: 34 bp2018-01-01: 42 bp2018-02-01: 51 bp2018-03-01: 39 bp2018-04-01: 39 bp2018-05-01: 41 bp2018-06-01: 34 bp2018-07-01: 22 bp2018-08-01: 19 bp2018-09-01: 21 bp2018-10-01: 20 bp2018-11-01: 14 bp2018-12-01: 8 bp2019-01-01: 8 bp2019-02-01: 12 bp2019-03-01: 10 bp2019-04-01: 14 bp2019-05-01: 8 bp2019-06-01: 5 bp2019-07-01: 0 bp2019-08-01: −16 bp2019-09-01: −18 bp2019-10-01: −13 bp2019-11-01: −7 bp2019-12-01: −6 bp2020-01-01: −9 bp2020-02-01: −12 bp2020-03-01: 20 bp2020-04-01: 29 bp2020-05-01: 26 bp2020-06-01: 26 bp2020-07-01: 24 bp2020-08-01: 28 bp2020-09-01: 30 bp2020-10-01: 36 bp2020-11-01: 42 bp2020-12-01: 49 bp2021-01-01: 64 bp2021-02-01: 89 bp2021-03-01: 124 bp2021-04-01: 124 bp2021-05-01: 121 bp2021-06-01: 105 bp2021-07-01: 79 bp2021-08-01: 74 bp2021-09-01: 82 bp2021-10-01: 82 bp2021-11-01: 69 bp2021-12-01: 47 bp2022-01-01: 58 bp2022-02-01: 44 bp2022-03-01: 29 bp2022-04-01: 24 bp2022-05-01: 27 bp2022-06-01: 16 bp2022-07-01: −13 bp2022-08-01: −50 bp2022-09-01: −58 bp2022-10-01: −63 bp2022-11-01: −79 bp2022-12-01: −87 bp2023-01-01: −80 bp2023-02-01: −88 bp2023-03-01: −83 bp2023-04-01: −81 bp2023-05-01: −88 bp2023-06-01: −119 bp2023-07-01: −123 bp2023-08-01: −105 bp2023-09-01: −97 bp2023-10-01: −72 bp2023-11-01: −71 bp2023-12-01: −78 bp2024-01-01: −66 bp2024-02-01: −68 bp2024-03-01: −69 bp2024-04-01: −56 bp2024-05-01: −58 bp2024-06-01: −55 bp2024-07-01: −37 bp2024-08-01: −21 bp2024-09-01: −4 bp2024-10-01: 11 bp2024-11-01: 10 bp2024-12-01: 17 bp2025-01-01: 36 bp2025-02-01: 37 bp2025-03-01: 47 bp2025-04-01: 58 bp2025-05-01: 63 bp2025-06-01: 66 bp2025-07-01: 72 bp2025-08-01: 73 bp2025-09-01: 72 bp2025-10-01: 71 bp2025-11-01: 73 bp2025-12-01: 81 bp2026-01-01: 84 bp2026-02-01: 80 bp2026-03-01: 68 bp2026-04-01: 65 bp2026-05-01: 61 bp2026-06-01: 63 bp2026-07-01: 71 bp2026-08-01: 72 bp2026-09-01: 62 bp62 bpThe yield curve: 10-year minus 2-year Government of Canada benchmark bond yields, monthly average of daily values, with inverted months shaded−200 bp−100 bp0 bp100 bp200 bp300 bpInverted200520102015202020252001-01-01: 41 bp2001-02-01: 50 bp2001-03-01: 63 bp2001-04-01: 82 bp2001-05-01: 98 bp2001-06-01: 92 bp2001-07-01: 98 bp2001-08-01: 107 bp2001-09-01: 163 bp2001-10-01: 187 bp2001-11-01: 207 bp2001-12-01: 213 bp2002-01-01: 225 bp2002-02-01: 207 bp2002-03-01: 161 bp2002-04-01: 139 bp2002-05-01: 144 bp2002-06-01: 141 bp2002-07-01: 171 bp2002-08-01: 183 bp2002-09-01: 150 bp2002-10-01: 165 bp2002-11-01: 176 bp2002-12-01: 170 bp2003-01-01: 166 bp2003-02-01: 153 bp2003-03-01: 132 bp2003-04-01: 131 bp2003-05-01: 124 bp2003-06-01: 131 bp2003-07-01: 170 bp2003-08-01: 188 bp2003-09-01: 172 bp2003-10-01: 169 bp2003-11-01: 161 bp2003-12-01: 165 bp2004-01-01: 183 bp2004-02-01: 199 bp2004-03-01: 195 bp2004-04-01: 188 bp2004-05-01: 181 bp2004-06-01: 163 bp2004-07-01: 160 bp2004-08-01: 165 bp2004-09-01: 147 bp2004-10-01: 133 bp2004-11-01: 126 bp2004-12-01: 138 bp2005-01-01: 131 bp2005-02-01: 129 bp2005-03-01: 122 bp2005-04-01: 109 bp2005-05-01: 103 bp2005-06-01: 98 bp2005-07-01: 88 bp2005-08-01: 81 bp2005-09-01: 74 bp2005-10-01: 59 bp2005-11-01: 40 bp2005-12-01: 23 bp2006-01-01: 24 bp2006-02-01: 22 bp2006-03-01: 26 bp2006-04-01: 32 bp2006-05-01: 29 bp2006-06-01: 17 bp2006-07-01: 21 bp2006-08-01: 16 bp2006-09-01: 12 bp2006-10-01: 9 bp2006-11-01: 6 bp2006-12-01: 6 bp2007-01-01: 7 bp2007-02-01: 4 bp2007-03-01: 10 bp2007-04-01: 7 bp2007-05-01: −3 bp2007-06-01: −5 bp2007-07-01: −5 bp2007-08-01: 8 bp2007-09-01: 15 bp2007-10-01: 16 bp2007-11-01: 32 bp2007-12-01: 27 bp2008-01-01: 54 bp2008-02-01: 77 bp2008-03-01: 93 bp2008-04-01: 84 bp2008-05-01: 75 bp2008-06-01: 58 bp2008-07-01: 62 bp2008-08-01: 80 bp2008-09-01: 82 bp2008-10-01: 145 bp2008-11-01: 171 bp2008-12-01: 157 bp2009-01-01: 167 bp2009-02-01: 175 bp2009-03-01: 186 bp2009-04-01: 189 bp2009-05-01: 208 bp2009-06-01: 217 bp2009-07-01: 218 bp2009-08-01: 213 bp2009-09-01: 211 bp2009-10-01: 196 bp2009-11-01: 209 bp2009-12-01: 213 bp2010-01-01: 221 bp2010-02-01: 210 bp2010-03-01: 192 bp2010-04-01: 177 bp2010-05-01: 165 bp2010-06-01: 163 bp2010-07-01: 162 bp2010-08-01: 160 bp2010-09-01: 147 bp2010-10-01: 139 bp2010-11-01: 145 bp2010-12-01: 154 bp2011-01-01: 153 bp2011-02-01: 158 bp2011-03-01: 152 bp2011-04-01: 152 bp2011-05-01: 151 bp2011-06-01: 152 bp2011-07-01: 145 bp2011-08-01: 146 bp2011-09-01: 128 bp2011-10-01: 129 bp2011-11-01: 119 bp2011-12-01: 110 bp2012-01-01: 100 bp2012-02-01: 96 bp2012-03-01: 91 bp2012-04-01: 77 bp2012-05-01: 71 bp2012-06-01: 74 bp2012-07-01: 66 bp2012-08-01: 67 bp2012-09-01: 69 bp2012-10-01: 71 bp2012-11-01: 65 bp2012-12-01: 67 bp2013-01-01: 76 bp2013-02-01: 86 bp2013-03-01: 88 bp2013-04-01: 79 bp2013-05-01: 89 bp2013-06-01: 110 bp2013-07-01: 129 bp2013-08-01: 143 bp2013-09-01: 145 bp2013-10-01: 136 bp2013-11-01: 145 bp2013-12-01: 157 bp2014-01-01: 150 bp2014-02-01: 142 bp2014-03-01: 141 bp2014-04-01: 138 bp2014-05-01: 126 bp2014-06-01: 121 bp2014-07-01: 110 bp2014-08-01: 98 bp2014-09-01: 104 bp2014-10-01: 99 bp2014-11-01: 100 bp2014-12-01: 84 bp2015-01-01: 77 bp2015-02-01: 94 bp2015-03-01: 89 bp2015-04-01: 83 bp2015-05-01: 107 bp2015-06-01: 117 bp2015-07-01: 113 bp2015-08-01: 99 bp2015-09-01: 100 bp2015-10-01: 93 bp2015-11-01: 101 bp2015-12-01: 92 bp2016-01-01: 87 bp2016-02-01: 70 bp2016-03-01: 72 bp2016-04-01: 73 bp2016-05-01: 75 bp2016-06-01: 64 bp2016-07-01: 51 bp2016-08-01: 49 bp2016-09-01: 53 bp2016-10-01: 60 bp2016-11-01: 81 bp2016-12-01: 96 bp2017-01-01: 95 bp2017-02-01: 94 bp2017-03-01: 93 bp2017-04-01: 79 bp2017-05-01: 82 bp2017-06-01: 64 bp2017-07-01: 69 bp2017-08-01: 64 bp2017-09-01: 52 bp2017-10-01: 55 bp2017-11-01: 48 bp2017-12-01: 34 bp2018-01-01: 42 bp2018-02-01: 51 bp2018-03-01: 39 bp2018-04-01: 39 bp2018-05-01: 41 bp2018-06-01: 34 bp2018-07-01: 22 bp2018-08-01: 19 bp2018-09-01: 21 bp2018-10-01: 20 bp2018-11-01: 14 bp2018-12-01: 8 bp2019-01-01: 8 bp2019-02-01: 12 bp2019-03-01: 10 bp2019-04-01: 14 bp2019-05-01: 8 bp2019-06-01: 5 bp2019-07-01: 0 bp2019-08-01: −16 bp2019-09-01: −18 bp2019-10-01: −13 bp2019-11-01: −7 bp2019-12-01: −6 bp2020-01-01: −9 bp2020-02-01: −12 bp2020-03-01: 20 bp2020-04-01: 29 bp2020-05-01: 26 bp2020-06-01: 26 bp2020-07-01: 24 bp2020-08-01: 28 bp2020-09-01: 30 bp2020-10-01: 36 bp2020-11-01: 42 bp2020-12-01: 49 bp2021-01-01: 64 bp2021-02-01: 89 bp2021-03-01: 124 bp2021-04-01: 124 bp2021-05-01: 121 bp2021-06-01: 105 bp2021-07-01: 79 bp2021-08-01: 74 bp2021-09-01: 82 bp2021-10-01: 82 bp2021-11-01: 69 bp2021-12-01: 47 bp2022-01-01: 58 bp2022-02-01: 44 bp2022-03-01: 29 bp2022-04-01: 24 bp2022-05-01: 27 bp2022-06-01: 16 bp2022-07-01: −13 bp2022-08-01: −50 bp2022-09-01: −58 bp2022-10-01: −63 bp2022-11-01: −79 bp2022-12-01: −87 bp2023-01-01: −80 bp2023-02-01: −88 bp2023-03-01: −83 bp2023-04-01: −81 bp2023-05-01: −88 bp2023-06-01: −119 bp2023-07-01: −123 bp2023-08-01: −105 bp2023-09-01: −97 bp2023-10-01: −72 bp2023-11-01: −71 bp2023-12-01: −78 bp2024-01-01: −66 bp2024-02-01: −68 bp2024-03-01: −69 bp2024-04-01: −56 bp2024-05-01: −58 bp2024-06-01: −55 bp2024-07-01: −37 bp2024-08-01: −21 bp2024-09-01: −4 bp2024-10-01: 11 bp2024-11-01: 10 bp2024-12-01: 17 bp2025-01-01: 36 bp2025-02-01: 37 bp2025-03-01: 47 bp2025-04-01: 58 bp2025-05-01: 63 bp2025-06-01: 66 bp2025-07-01: 72 bp2025-08-01: 73 bp2025-09-01: 72 bp2025-10-01: 71 bp2025-11-01: 73 bp2025-12-01: 81 bp2026-01-01: 84 bp2026-02-01: 80 bp2026-03-01: 68 bp2026-04-01: 65 bp2026-05-01: 61 bp2026-06-01: 63 bp2026-07-01: 71 bp2026-08-01: 72 bp2026-09-01: 62 bp62 bp
Show the data
The 10-year minus 2-year yield gap by year: the average, lowest and highest of that year's monthly averages
YearAverageLowest monthHighest month
2001117 bp41 bp213 bp
2002169 bp139 bp225 bp
2003155 bp124 bp188 bp
2004165 bp126 bp199 bp
200588 bp23 bp131 bp
200618 bp6 bp32 bp
20079 bp−5 bp32 bp
200895 bp54 bp171 bp
2009200 bp167 bp218 bp
2010169 bp139 bp221 bp
2011141 bp110 bp158 bp
201276 bp65 bp100 bp
2013115 bp76 bp157 bp
2014118 bp84 bp150 bp
201597 bp77 bp117 bp
201669 bp49 bp96 bp
201769 bp34 bp95 bp
201829 bp8 bp51 bp
20190 bp−18 bp14 bp
202024 bp−12 bp49 bp
202188 bp47 bp124 bp
2022−13 bp−87 bp58 bp
2023−91 bp−123 bp−71 bp
2024−33 bp−69 bp17 bp
202563 bp36 bp81 bp
202670 bp61 bp84 bp
Source: Bank of Canada, Canadian bond yields, queried 27 September 2026

The other eight

Sources

Where the data comes from

Federal agencies answer most national questions; provincial agencies and open-data catalogues add the local detail. Every result comes straight from its publisher.

42
federal and national sources
133
provincial, territorial and city sources
12/13
provinces and territories with local data
175
sources, one connection

Statistics Canada, in depth Every table, series and microdata file an agent can reach, and the hard parts MapleStats handles for you.

How it works

From a question to a cited number

A connected agent sees three tools: plan_query, search_tools and call_tool. The other 357 stay out of its context until a search finds them. Every output below is real. The server produced the plan, the search and the scripts when this page was built; the data call was recorded on 27 September 2026.

  1. 01

    Planplan_query

    The planner reads the question and lists the agencies to ask, in order, with the caveats on combining them. Places it recognizes add their local portals.

    plan_queryRun when this page was built

    Question

    How have rents and interest rates moved in Calgary since 2020?

    Plan

    Housing: starts, rents, prices, mortgages

    1. cmhc_list_categoriesCMHC starts, completions, rents and vacancy: category_level_1 and _2
    2. cmhc_get_table_optionscolumn_field and row_field options for that category and geography
    3. cmhc_get_table_datathe table: category_level_1, category_level_2, column_field and row_field (row_field='TIMESERIES' for a series), geography_type and geography_id
    4. cmhc_dt_list_tablesCMHC's published Excel tables: category='rental-market' or 'household-characteristics'
    5. wds_search_cubesStatCan New Housing Price Index, building permits
    6. boc_search_seriesBank of Canada mortgage and policy rates
    7. crea_get_hpi_linksCREA MLS® Home Price Index (resale prices): download link, attribution and terms only; no values, since CREA's terms forbid publishing them
    8. statcan_census_profile_get_datacensus shelter cost and tenure: level, geography_codes (DGUIDs from statcan_census_profile_search_geography) and characteristic_codes

    Caveat CMHC reports by census metropolitan area and centre; StatCan price indexes are by CMA too, but the two define some areas differently, so name the geography each figure uses.

    Interest rates, exchange rates and markets

    1. boc_search_seriesfind the Valet series (e.g. FXUSDCAD, V39079)
    2. boc_get_observationspull the series for the period

    Calgary (city)

    1. socrata_search_datasetssearch with portal='calgary'
  2. 02

    Findsearch_tools

    Search ranks the catalogue against a plain-language query and returns the top 5. French works because every tool carries French keywords. The panel runs the server's own index in your browser, so type your own query.

  3. 03

    Fetchcall_tool

    The agent calls the tool by name. The result is a typed object, and its provenance block, marked here, gives the exact upstream URL and the time of the query.

    call_toolRecorded 27 September 2026

    Prompt

    What is the Bank of Canada's overnight rate?

    Result

    Target for the overnight rate (business daily) V39079
    DateValue
    24 September 20262.25
    23 September 20262.25
    22 September 20262.25

    Provenance

    Queried
    27 September 2026, 17:00 UTC
    Result type
    boc.ObservationsResult
    Show the full response as JSON
    {
      "series": {
        "V39079": {"name": "V39079", "label": "Target for the overnight rate (business daily)", "description": "Also called the policy interest rate, the average rate that the Bank of Canada wants to see in the market for overnight money market financing. (V39079)"}
      },
      "observations": [
        {"ref_date": "2026-09-24", "values": {"V39079": 2.25}},
        {"ref_date": "2026-09-23", "values": {"V39079": 2.25}},
        {"ref_date": "2026-09-22", "values": {"V39079": 2.25}}
      ],
      "provenance": {
        "source": "boc",
        "url": "https://www.bankofcanada.ca/valet/observations/V39079/json",
        "queried_at": "2026-09-27T17:00:48.227537Z",
        "as_of": null,
        "freshness": null,
        "coverage": null,
        "limits": null,
        "cached": false,
        "schema_name": "boc.ObservationsResult",
        "reproduce": "For R, Python, Stata and Julia scripts that fetch and clean this data, call reproduce_code with this tool's name and arguments."
      }}
  4. 04

    Reproducereproduce_code

    The same call becomes an R, Python, Stata or Julia script, or an Excel Power Query, that downloads, checks and cleans the data, so the analysis does not depend on the agent.

    reproduce_codeRun when this page was built

    Prompt

    Write me a script that fetches this, so I can rerun it myself.

    R

    # ============================================================
    # Bank of Canada Valet: V39079
    # Purpose: Fetch the data behind MapleStats MCP's boc_get_observations
    #          (exact: Valet request rebuilt from the tool's arguments)
    # Inputs:  https://www.bankofcanada.ca/valet/observations/V39079/json?recent=3
    # Outputs: data/raw/valet_observations.json; the prepared table as `data`
    # ============================================================
    
    # 0. Setup ----
    
    library(dplyr)
    library(httr2)
    library(janitor)
    library(jsonlite)
    library(lubridate)
    library(readr)
    library(stringr)
    library(tibble)
    library(tidyr)
    
    dir.create("data/raw", recursive = TRUE, showWarnings = FALSE)
    
    # 1. Read inputs ----
    
    response <- request("https://www.bankofcanada.ca/valet/observations/V39079/json?recent=3") |>
      req_perform()
    
    writeLines(resp_body_string(response), "data/raw/valet_observations.json")
    
    payload <- fromJSON("data/raw/valet_observations.json", flatten = TRUE)
    data <- as_tibble(payload[["observations"]])
    
    # 2. Check inputs ----
    
    stopifnot("https://www.bankofcanada.ca/valet/observations/V39079/json?recent=3 returned no rows" = nrow(data) > 0)
    
    # 3. Prepare data ----
    
    data <- data |>
      clean_names()
    
    # Valet nests each series as <series>.v; make one row per date and series.
    
    data <- data |>
      pivot_longer(-d, names_to = "series", values_to = "value") |>
      mutate(
        series = str_remove(series, "_v$") |> str_to_upper(),
        value = as.numeric(value),
        date = ymd(d)
      ) |>
      select(date, series, value)
    
    # Standard cleaning: trimmed text, empty strings as missing, and numbers
    # stored as text converted to numbers.
    
    data <- data |>
      mutate(across(where(is.character), \(x) na_if(str_trim(x), ""))) |>
      type_convert()

    Python

    # ============================================================
    # Bank of Canada Valet: V39079
    # Purpose: Fetch the data behind MapleStats MCP's boc_get_observations
    #          (exact: Valet request rebuilt from the tool's arguments)
    # Inputs:  https://www.bankofcanada.ca/valet/observations/V39079/json?recent=3
    # Outputs: data/raw/valet_observations.json; the prepared table as `data`
    # ============================================================
    
    # %% 0. Setup
    
    import json
    import re
    import unicodedata
    from pathlib import Path
    
    import httpx
    import polars as pl
    
    RAW_DIR = Path("data/raw")
    RAW_DIR.mkdir(parents=True, exist_ok=True)
    raw_path = RAW_DIR / "valet_observations.json"
    
    # %% 1. Read inputs
    
    with httpx.Client(
        http2=True,
        follow_redirects=True,
        timeout=300,
        headers={"User-Agent": "Mozilla/5.0 (compatible; research script)"},
    ) as client:
        response = client.get('https://www.bankofcanada.ca/valet/observations/V39079/json?recent=3')
    response.raise_for_status()
    raw_path.write_bytes(response.content)
    
    payload = json.loads(raw_path.read_text(encoding="utf-8"))
    records = payload['observations']
    data = pl.json_normalize(records, strict=False)
    
    # %% 2. Check inputs
    
    assert data.height > 0, "https://www.bankofcanada.ca/valet/observations/V39079/json?recent=3 returned no rows"
    
    # %% 3. Prepare data
    
    # Valet nests each series as <series>.v; make one row per date and series.
    
    data = data.unpivot(index="d", variable_name="series", value_name="value")
    data = data.with_columns(
        pl.col("d").str.to_date().alias("date"),
        pl.col("series").str.replace(r"\.v$", ""),
        pl.col("value").cast(pl.Float64, strict=False),
    ).select("date", "series", "value")
    
    # Standard cleaning: snake_case names without accents (PÉRIODE -> periode,
    # referenceNumber -> reference_number, as janitor does in R), trimmed text,
    # empty strings as missing. Names that clean alike are numbered as janitor
    # numbers them (Indicator, indicator -> indicator, indicator_2).
    
    clean_names = [
        re.sub(
            r"[^0-9a-z]+",
            "_",
            re.sub(
                r"([a-z0-9])([A-Z])",
                r"\1_\2",
                unicodedata.normalize("NFKD", column).encode("ascii", "ignore").decode(),
            ).lower(),
        ).strip("_")
        for column in data.columns
    ]
    while len(set(clean_names)) < len(clean_names):
        name_counts = {}
        numbered = []
        for name in clean_names:
            name_counts[name] = name_counts.get(name, 0) + 1
            count = name_counts[name]
            numbered.append(name if count == 1 else f"{name}_{count}")
        clean_names = numbered
    data = data.rename(dict(zip(data.columns, clean_names)))
    data = data.with_columns(pl.col(pl.Utf8).str.strip_chars().replace("", None))

    Stata

    * ============================================================
    * Bank of Canada Valet: V39079
    * Purpose: Fetch the data behind MapleStats MCP's boc_get_observations
    *          (exact: Valet request rebuilt from the tool's arguments)
    * Inputs:  https://www.bankofcanada.ca/valet/observations/V39079/json?recent=3
    * Outputs: data/raw/valet_observations.json; the prepared table as `data`
    * ============================================================
    
    version 18
    clear all
    set more off
    
    * 0. Setup
    
    capture mkdir "logs"
    capture log close
    log using "logs/boc_get_observations.log", replace
    capture mkdir "data"
    capture mkdir "data/raw"
    
    * 1. Read inputs
    
    * Stata reads no JSON or HTML and truncates long column names, so its
    * built-in Python (Stata 16+) fetches, filters and writes a CSV. Point
    * Stata at a Python with these packages first: python set exec <path>.
    
    python:
    import json
    from pathlib import Path
    import httpx
    import polars as pl
    RAW_DIR = Path("data/raw")
    RAW_DIR.mkdir(parents=True, exist_ok=True)
    raw_path = RAW_DIR / "valet_observations.json"
    with httpx.Client(http2=True, follow_redirects=True, timeout=300, headers={"User-Agent": "Mozilla/5.0 (compatible; research script)"}) as client: response = client.get('https://www.bankofcanada.ca/valet/observations/V39079/json?recent=3')
    response.raise_for_status()
    raw_path.write_bytes(response.content)
    payload = json.loads(raw_path.read_text(encoding="utf-8"))
    records = payload['observations']
    data = pl.json_normalize(records, strict=False)
    nested = [name for name, dtype in data.schema.items() if dtype.is_nested()]
    data = data.with_columns(pl.col(name).map_elements(lambda value: json.dumps(value.to_list() if isinstance(value, pl.Series) else value, default=str), return_dtype=pl.Utf8) for name in nested)
    data.write_csv(RAW_DIR / "valet_observations_prepared.csv")
    end
    
    import delimited "data/raw/valet_observations_prepared.csv", clear varnames(1) encoding("utf-8")
    
    * 2. Check inputs
    
    assert _N > 0
    
    * 3. Prepare data
    
    * One column per series (<series>_v), one row per date.
    
    generate date = date(d, "YMD")
    format date %td
    drop d
    
    * Standard cleaning: lower-case names, trimmed text, and numbers stored as
    * text converted (destring leaves genuinely non-numeric text alone).
    * rename *, lower stops at a clash (Indicator next to indicator), so names
    * that lower-case alike are numbered as janitor numbers them (indicator,
    * indicator_2), then renamed in one group rename, which allows swaps.
    
    local names
    foreach var of varlist _all {
        local names `names' `=strlower("`var'")'
    }
    local dups : list dups names
    while "`dups'" != "" {
        local numbered
        local before
        foreach name of local names {
            local count 1
            foreach earlier of local before {
                if "`earlier'" == "`name'" local ++count
            }
            local before `before' `name'
            if `count' > 1 {
                local name = substr("`name'", 1, 32 - strlen("_`count'")) + "_`count'"
            }
            local numbered `numbered' `name'
        }
        local names `numbered'
        local dups : list dups names
    }
    local old_names
    local new_names
    local i 0
    foreach var of varlist _all {
        local ++i
        local name : word `i' of `names'
        if "`name'" != "`var'" {
            local old_names `old_names' `var'
            local new_names `new_names' `name'
        }
    }
    if "`old_names'" != "" {
        rename (`old_names') (`new_names')
    }
    quietly ds, has(type string)
    local text_vars `r(varlist)'
    foreach var of local text_vars {
        replace `var' = strtrim(`var')
    }
    destring, replace
    
    log close

    Julia

    # ============================================================
    # Bank of Canada Valet: V39079
    # Purpose: Fetch the data behind MapleStats MCP's boc_get_observations
    #          (exact: Valet request rebuilt from the tool's arguments)
    # Inputs:  https://www.bankofcanada.ca/valet/observations/V39079/json?recent=3
    # Outputs: data/raw/valet_observations.json; the prepared table as `data`
    # ============================================================
    
    # 0. Setup
    
    using DataFrames
    using Downloads
    using JSON3
    using Tables
    using TidierData
    
    mkpath("data/raw")
    
    # 1. Read inputs
    
    Downloads.download("https://www.bankofcanada.ca/valet/observations/V39079/json?recent=3", "data/raw/valet_observations.json")
    payload = JSON3.read(read("data/raw/valet_observations.json", String))
    records = payload["observations"]
    data = DataFrame(Tables.dictrowtable(records))
    
    # 2. Check inputs
    
    @assert nrow(data) > 0 "https://www.bankofcanada.ca/valet/observations/V39079/json?recent=3 returned no rows"
    
    # 3. Prepare data
    
    # Standard cleaning: snake_case names, trimmed text, empty strings as missing.
    
    data = @chain data begin
        @clean_names
    end
    data = mapcols(
        col -> eltype(col) <: Union{Missing, AbstractString} ?
            [ismissing(x) || isempty(strip(x)) ? missing : strip(x) for x in col] : col,
        data,
    )

Connect

Add it to your client

Your client starts the server with uv when it needs it. There is nothing to host and no port to open.

Full setup, hosting and troubleshooting

Claude Code

Run this once in a terminal. --scope user makes the server available in every project; leave it out to add it to the current project only.

Terminal
claude mcp add --scope user maplestats -- uvx maplestats-mcp

Claude Desktop

In Claude Desktop, open Settings, then Developer, then Edit Config. Add the server to the file that opens, save it and restart Claude.

claude_desktop_config.json
{
  "mcpServers": {
    "maplestats": {
      "command": "uvx",
      "args": ["maplestats-mcp"]
    }
  }
}

The file lives at ~/Library/Application Support/Claude/claude_desktop_config.json on macOS and %APPDATA%\Claude\claude_desktop_config.json on Windows.

Cursor

The link opens Cursor with the entry filled in. To add it by hand, put it in ~/.cursor/mcp.json for every project, or in .cursor/mcp.json for one project.

~/.cursor/mcp.json
{
  "mcpServers": {
    "maplestats": {
      "command": "uvx",
      "args": ["maplestats-mcp"]
    }
  }
}

VS Code

To add it by hand, note that VS Code uses a servers key, not mcpServers. Put this in .vscode/mcp.json in a workspace, or run MCP: Open User Configuration from the Command Palette to add it for every workspace.

.vscode/mcp.json
{
  "servers": {
    "maplestats": {
      "type": "stdio",
      "command": "uvx",
      "args": ["maplestats-mcp"]
    }
  }
}

Codex CLI

Add it from the terminal, or write the same entry into ~/.codex/config.toml yourself.

Terminal
codex mcp add maplestats -- uvx maplestats-mcp
~/.codex/config.toml
[mcp_servers.maplestats]
command = "uvx"
args = ["maplestats-mcp"]

Gemini CLI

Add it from the terminal (-s user for every project), or write the entry into ~/.gemini/settings.json next to any settings already there.

Terminal
gemini mcp add -s user maplestats uvx maplestats-mcp
~/.gemini/settings.json
{
  "mcpServers": {
    "maplestats": {
      "command": "uvx",
      "args": ["maplestats-mcp"]
    }
  }
}

Other clients

Most MCP clients accept this mcpServers entry. If you installed the command with uv tool install or pip, use "command": "maplestats-mcp" and drop args.

JSON
{
  "mcpServers": {
    "maplestats": {
      "command": "uvx",
      "args": ["maplestats-mcp"]
    }
  }
}

Every source. One server.

The square: 42 federal publishers around the outside, the provinces and cities with local sources inside, and 358 tools as segments by subjectBank of Canada · Borealis · Canada Gazette · CBSA · CDC · CER · CFIA · CGC · CIHI · CMHC · Competition Bureau · CRA · CREA · DFO tides · Earthquakes Canada · ECCC · ECCC Data Catalogue · Elections Canada · Elections Canada; Borealis and Harvard Dataverse (historical) · FCAC · Finance Canada · GC InfoBase · Health Canada · House of Commons · IRCC · ISED · National Forestry Database · NRCan burned areas · NRCan energy use · NRCan minerals · NRCan places · NRCan wildfires · PBO · PHAC Health Infobase · PMPRB · PMRA · Recalls · Represent · Senate · StatCan · Transport Canada · World Bank WDI · Bank of Canada · Borealis · Canada Gazette · CBSA · CDC · CER · CFIA · CGC · CIHI · CMHC · Competition Bureau · CRA · CREA · DFO tides · Earthquakes Canada · ECCC · ECCC Data Catalogue · Elections Canada · Elections Canada; Borealis and Harvard Dataverse (historical) · FCAC · Finance Canada · GC InfoBase · Health Canada · House of Commons · IRCC · ISED · National Forestry Database · NRCan burned areas · NRCan energy use · NRCan minerals · NRCan places · NRCan wildfires · PBO · PHAC Health Infobase · PMPRB · PMRA · Recalls · Represent · Senate · StatCan · Transport Canada · World Bank WDI · British Columbia · Abbotsford · Burnaby OpenData · Coquitlam · Delta · Kamloops · Kelowna · Maple Ridge · Penticton · Port Moody · Prince George · Saanich · Surrey · Transit schedules · Vancouver · Victoria · White Rock · Alberta · Airdrie · Calgary · Canmore · Cochrane · Edmonton · Grande Prairie · Lethbridge · Medicine Hat · Okotoks · Parkland · Red Deer · St. Albert · Strathcona · Sturgeon · Transit schedules · Saskatchewan · Regina · Saskatoon · Transit schedules · Manitoba · Transit schedules · Winnipeg · Ontario · Aurora · Barrie · Brampton · Burlington · Cambridge · Central Lake Ontario Conservation Authority · Conservation Halton · Credit Valley Conservation · Data Kingston · Durham · Greater Sudbury · Guelph · Hamilton Conservation Authority · Kitchener · London · Markham · Milton · Mississauga · Newmarket · Niagara · Oakville · Orangeville · Oshawa · Ottawa · Peel · Peterborough · Pickering · Quinte Conservation Authority · Sarnia · St Catharines · Thunder Bay · Toronto · Transit schedules · Waterloo · Whitby · Windsor · York · Quebec · Montreal · Transit schedules · New Brunswick · Fredericton · Moncton · Saint John · Transit schedules · Nova Scotia · Halifax · Transit schedules · Prince Edward Island · Transit schedules · Newfoundland and Labrador · Transit schedules · Yukon · Transit schedules · Northwest Territories · Transit schedules · Yellowknife · British Columbia · Abbotsford · Burnaby OpenData · Coquitlam · Delta · Kamloops · Kelowna · Maple Ridge · Penticton · Port Moody · Prince George · Saanich · Surrey · Transit schedules · Vancouver · Victoria · White Rock · Alberta · Airdrie · Calgary · Canmore · Cochrane · Edmonton · Grande Prairie · Lethbridge · Medicine Hat · Okotoks · Parkland · Red Deer · St. Albert · Strathcona · Sturgeon · Transit schedules · Saskatchewan · Regina · Saskatoon · Transit schedules · Manitoba · Transit schedules · Winnipeg · Ontario · Aurora · Barrie · Brampton · Burlington · Cambridge · Central Lake Ontario Conservation Authority · Conservation Halton · Credit Valley Conservation · Data Kingston · Durham · Greater Sudbury · Guelph · Hamilton Conservation Authority · Kitchener · London · Markham · Milton · Mississauga · Newmarket · Niagara · Oakville · Orangeville · Oshawa · Ottawa · Peel · Peterborough · Pickering · Quinte Conservation Authority · Sarnia · St Catharines · Thunder Bay · Toronto · Transit schedules · Waterloo · Whitby · Windsor · York · Quebec · Montreal · Transit schedules · New Brunswick · Fredericton · Moncton · Saint John · Transit schedules · Nova Scotia · Halifax · Transit schedules · Prince Edward Island · Transit schedules · Newfoundland and Labrador · Transit schedules · Yukon · Transit schedules · Northwest Territories · Transit schedules · Yellowknife · Provinces and cities: open-data catalogues, provincial, municipal (117)Statistics: statistics and census (92)Land and energy: agriculture and food, environment and hazards, energy and mining, geography, transport and safety (55)People: health, housing, immigration (40)Money and business: money, prices and public finance, business, IP and competition (30)Parliament: parliament, law and elections (21)Provinces and cities 117Statistics 92Land and energy 55People 403021175sources,one connection
Show the data
The 358 tools by subject (the segments); MapleStats' own tools are counted only in the total
SubjectTools
Provinces and cities: open-data catalogues, provincial, municipal117
Statistics: statistics and census92
Land and energy: agriculture and food, environment and hazards, energy and mining, geography, transport and safety55
People: health, housing, immigration40
Money and business: money, prices and public finance, business, IP and competition30
Parliament: parliament, law and elections21