rba-mcp 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. rba_mcp-0.1.0/.github/workflows/test.yml +47 -0
  2. rba_mcp-0.1.0/.gitignore +16 -0
  3. rba_mcp-0.1.0/CHANGELOG.md +15 -0
  4. rba_mcp-0.1.0/LICENSE +28 -0
  5. rba_mcp-0.1.0/PKG-INFO +192 -0
  6. rba_mcp-0.1.0/README.md +161 -0
  7. rba_mcp-0.1.0/glama.json +4 -0
  8. rba_mcp-0.1.0/pyproject.toml +55 -0
  9. rba_mcp-0.1.0/src/rba_mcp/__init__.py +6 -0
  10. rba_mcp-0.1.0/src/rba_mcp/cache.py +95 -0
  11. rba_mcp-0.1.0/src/rba_mcp/client.py +68 -0
  12. rba_mcp-0.1.0/src/rba_mcp/curated.py +153 -0
  13. rba_mcp-0.1.0/src/rba_mcp/data/curated/F11.yaml +56 -0
  14. rba_mcp-0.1.0/src/rba_mcp/data/curated/F11_1.yaml +62 -0
  15. rba_mcp-0.1.0/src/rba_mcp/data/curated/F1_1.yaml +65 -0
  16. rba_mcp-0.1.0/src/rba_mcp/data/curated/F4.yaml +60 -0
  17. rba_mcp-0.1.0/src/rba_mcp/data/curated/F6.yaml +65 -0
  18. rba_mcp-0.1.0/src/rba_mcp/data/tables.yaml +102 -0
  19. rba_mcp-0.1.0/src/rba_mcp/models.py +71 -0
  20. rba_mcp-0.1.0/src/rba_mcp/parsing.py +255 -0
  21. rba_mcp-0.1.0/src/rba_mcp/py.typed +0 -0
  22. rba_mcp-0.1.0/src/rba_mcp/server.py +393 -0
  23. rba_mcp-0.1.0/src/rba_mcp/shaping.py +160 -0
  24. rba_mcp-0.1.0/src/rba_mcp/tables.py +129 -0
  25. rba_mcp-0.1.0/tests/__init__.py +0 -0
  26. rba_mcp-0.1.0/tests/conftest.py +20 -0
  27. rba_mcp-0.1.0/tests/fixtures/f1.1-data.csv +9998 -0
  28. rba_mcp-0.1.0/tests/fixtures/f11-data.csv +425 -0
  29. rba_mcp-0.1.0/tests/fixtures/f11.1-data.csv +2185 -0
  30. rba_mcp-0.1.0/tests/fixtures/f4-data.csv +9998 -0
  31. rba_mcp-0.1.0/tests/fixtures/f6-data.csv +9998 -0
  32. rba_mcp-0.1.0/tests/test_client.py +51 -0
  33. rba_mcp-0.1.0/tests/test_curated.py +99 -0
  34. rba_mcp-0.1.0/tests/test_integration.py +111 -0
  35. rba_mcp-0.1.0/tests/test_mcp_protocol.py +69 -0
  36. rba_mcp-0.1.0/tests/test_parsing.py +137 -0
  37. rba_mcp-0.1.0/tests/test_server_validation.py +96 -0
  38. rba_mcp-0.1.0/tests/test_shaping.py +100 -0
  39. rba_mcp-0.1.0/tests/test_tables.py +62 -0
  40. rba_mcp-0.1.0/uv.lock +1725 -0
@@ -0,0 +1,47 @@
1
+ name: tests
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ubuntu-latest
12
+ strategy:
13
+ fail-fast: false
14
+ matrix:
15
+ python-version: ["3.11", "3.12", "3.13"]
16
+ steps:
17
+ - uses: actions/checkout@v4
18
+ - name: Install uv
19
+ uses: astral-sh/setup-uv@v3
20
+ with:
21
+ enable-cache: true
22
+ - name: Set up Python ${{ matrix.python-version }}
23
+ run: uv python install ${{ matrix.python-version }}
24
+ - name: Sync dependencies
25
+ run: uv sync --extra dev
26
+ - name: Install package
27
+ run: uv pip install -e .
28
+ - name: Run unit tests
29
+ run: uv run pytest -q
30
+
31
+ build:
32
+ runs-on: ubuntu-latest
33
+ needs: test
34
+ steps:
35
+ - uses: actions/checkout@v4
36
+ - name: Install uv
37
+ uses: astral-sh/setup-uv@v3
38
+ - name: Build wheel + sdist
39
+ run: uv build
40
+ - name: Verify wheel installs cleanly
41
+ run: |
42
+ uv run --isolated --with ./dist/*.whl python -c \
43
+ "import rba_mcp.server as s; n = len(s.list_curated()); assert n >= 5, f'expected >=5 curated, got {n}'; print(f'OK ({n} curated tables)')"
44
+ - uses: actions/upload-artifact@v4
45
+ with:
46
+ name: dist
47
+ path: dist/
@@ -0,0 +1,16 @@
1
+ __pycache__/
2
+ *.pyc
3
+ *.pyo
4
+ *.egg-info/
5
+ .eggs/
6
+ build/
7
+ dist/
8
+ .venv/
9
+ .pytest_cache/
10
+ .ruff_cache/
11
+ .mypy_cache/
12
+ .coverage
13
+ htmlcov/
14
+ *.swp
15
+ .DS_Store
16
+ .env
@@ -0,0 +1,15 @@
1
+ # Changelog
2
+
3
+ ## 0.1.0 (2026-05-11)
4
+
5
+ Initial release. MCP server for RBA F-tables; companion to `abs-mcp`.
6
+
7
+ - 5 MCP tools: `search_tables`, `describe_table`, `get_data`, `latest`, `list_curated`
8
+ - 5 curated F-tables with plain-English series mappings: **F1.1** (money market — cash rate), **F4** (deposit rates), **F6** (housing lending rates), **F11** (FX monthly history), **F11.1** (FX daily current)
9
+ - 14 non-curated F-tables accessible via raw RBA series IDs
10
+ - Label-driven CSV header parser (resilient to RBA adding new metadata rows)
11
+ - SQLite-backed cache (6h data TTL, 15min latest TTL)
12
+ - Unit attribution per series (Per cent per annum / USD per AUD / Index / etc.)
13
+ - CC-BY 4.0 attribution surfaced in every response
14
+ - Input validation guards (URL-injection-safe)
15
+ - 76 unit tests + 21 live integration tests
rba_mcp-0.1.0/LICENSE ADDED
@@ -0,0 +1,28 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Harry Vass
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
23
+ ---
24
+
25
+ Note on RBA data: this software fetches statistical tables published by the
26
+ Reserve Bank of Australia. RBA data is licensed under Creative Commons
27
+ Attribution 4.0 International (CC BY 4.0) — see https://www.rba.gov.au/copyright/.
28
+ End-users redistributing data fetched via this server must credit the RBA.
rba_mcp-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,192 @@
1
+ Metadata-Version: 2.4
2
+ Name: rba-mcp
3
+ Version: 0.1.0
4
+ Summary: MCP server for the Reserve Bank of Australia statistical tables (F-tables). Plain-English access to interest rates, FX rates, deposit/lending rates.
5
+ Project-URL: Homepage, https://github.com/Bigred97/rba-mcp
6
+ Project-URL: Issues, https://github.com/Bigred97/rba-mcp/issues
7
+ Author: Harry Vass
8
+ License: MIT
9
+ License-File: LICENSE
10
+ Keywords: australia,claude,fastmcp,fx,interest-rates,mcp,rba
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Programming Language :: Python :: 3.13
17
+ Classifier: Topic :: Scientific/Engineering :: Information Analysis
18
+ Requires-Python: >=3.11
19
+ Requires-Dist: aiosqlite>=0.20
20
+ Requires-Dist: fastmcp<4,>=2.0
21
+ Requires-Dist: httpx>=0.27
22
+ Requires-Dist: pandas<3,>=2.2
23
+ Requires-Dist: pydantic>=2.7
24
+ Requires-Dist: pyyaml>=6.0
25
+ Requires-Dist: rapidfuzz>=3.9
26
+ Provides-Extra: dev
27
+ Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
28
+ Requires-Dist: pytest>=8; extra == 'dev'
29
+ Requires-Dist: respx>=0.21; extra == 'dev'
30
+ Description-Content-Type: text/markdown
31
+
32
+ # rba-mcp
33
+
34
+ [![tests](https://github.com/Bigred97/rba-mcp/actions/workflows/test.yml/badge.svg)](https://github.com/Bigred97/rba-mcp/actions/workflows/test.yml)
35
+ [![PyPI](https://img.shields.io/pypi/v/rba-mcp.svg)](https://pypi.org/project/rba-mcp/)
36
+ [![Python](https://img.shields.io/pypi/pyversions/rba-mcp.svg)](https://pypi.org/project/rba-mcp/)
37
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
38
+
39
+ **Ask Claude about Australian interest rates, exchange rates, and lending rates and get real, current numbers** — not "I don't have access to that data." This MCP server gives Claude (and other MCP clients like Cursor) live access to the [Reserve Bank of Australia's statistical tables](https://www.rba.gov.au/statistics/tables/), with curated mappings for the most-asked indicators.
40
+
41
+ Companion to [abs-mcp](https://github.com/Bigred97/abs-mcp) — together they cover the most-asked Australian economic data.
42
+
43
+ ## What you can ask
44
+
45
+ Once installed, your LLM can answer questions like:
46
+
47
+ | Question | Real response |
48
+ |---|---|
49
+ | What's the current RBA cash rate? | RBA Cash Rate Target, latest month |
50
+ | What's AUD/USD today? | Latest daily exchange rate |
51
+ | Show me AUD vs major currencies in 2024 | Multi-series query with monthly observations |
52
+ | What's the average mortgage rate? | Owner-occupier variable, outstanding loans |
53
+ | What rate are 12-month term deposits at? | Latest from F4 |
54
+ | What's the trade-weighted index trend? | TWI series back to 1983 |
55
+
56
+ Every answer comes with the period, units (Per cent per annum, USD per AUD, etc.), and a link back to the RBA source.
57
+
58
+ ## Install
59
+
60
+ ```bash
61
+ # After publish:
62
+ uvx rba-mcp
63
+
64
+ # Local dev:
65
+ uv pip install -e .
66
+ ```
67
+
68
+ ### Claude Desktop
69
+
70
+ Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:
71
+
72
+ ```json
73
+ {
74
+ "mcpServers": {
75
+ "rba": {
76
+ "command": "uvx",
77
+ "args": ["rba-mcp"]
78
+ }
79
+ }
80
+ }
81
+ ```
82
+
83
+ If you also have `abs-mcp` installed, both servers run side-by-side. Claude disambiguates with the server prefix (`rba:get_data` vs `abs:get_data`).
84
+
85
+ For local dev (pre-PyPI):
86
+
87
+ ```json
88
+ {
89
+ "mcpServers": {
90
+ "rba": {
91
+ "command": "uv",
92
+ "args": ["run", "--directory", "/absolute/path/to/rba-mcp", "rba-mcp"]
93
+ }
94
+ }
95
+ }
96
+ ```
97
+
98
+ ### Cursor
99
+
100
+ Add to `~/.cursor/mcp.json` (or workspace `.cursor/mcp.json`):
101
+
102
+ ```json
103
+ {
104
+ "mcpServers": {
105
+ "rba": {
106
+ "command": "uvx",
107
+ "args": ["rba-mcp"]
108
+ }
109
+ }
110
+ }
111
+ ```
112
+
113
+ ## Tools
114
+
115
+ | Tool | What it does |
116
+ |---|---|
117
+ | `search_tables(query, limit=10)` | Fuzzy-search RBA F-tables by name or topic. |
118
+ | `describe_table(table_id)` | Plain-English series listing for one F-table. |
119
+ | `get_data(table_id, series, start_date, end_date, format)` | Query data. `series=None` returns all curated series; format = records / series / csv. |
120
+ | `latest(table_id, series)` | Most-recent observation for the requested series. |
121
+ | `list_curated()` | The 5 F-table IDs with hand-curated plain-English support. |
122
+
123
+ ## Curated F-tables
124
+
125
+ For these five, `series` accepts plain-English keys (e.g. `"aud_usd"` instead of `"FXRUSD"`):
126
+
127
+ - **F1.1** — Money Market — Monthly: cash rate target, cash rate, bank bills, OIS rates, treasury notes
128
+ - **F4** — Retail Deposit & Investment Rates: transaction accounts, savings, term deposits, cash management trusts
129
+ - **F6** — Housing Lending Rates: owner-occupier vs investor, variable vs fixed, outstanding vs new loans
130
+ - **F11** — Exchange Rates — Monthly History (1983+): AUD/USD, AUD/EUR, AUD/GBP, AUD/JPY, AUD/CNY, AUD/NZD, TWI
131
+ - **F11.1** — Exchange Rates — Daily (2023+): same series, daily resolution
132
+
133
+ Any other F-table works too — pass raw RBA series IDs (e.g. `"FXRUSD"`) instead of curated keys.
134
+
135
+ ## Worked examples
136
+
137
+ **"What's the current RBA cash rate?"**
138
+
139
+ ```
140
+ latest(table_id="F1.1", series="cash_rate_target")
141
+ ```
142
+
143
+ **"AUD to USD over the last year"**
144
+
145
+ ```
146
+ get_data(table_id="F11.1", series="aud_usd", start_date="2024")
147
+ ```
148
+
149
+ **"Compare AUD against USD, EUR and GBP since 2020"**
150
+
151
+ ```
152
+ get_data(
153
+ table_id="F11",
154
+ series=["aud_usd", "aud_eur", "aud_gbp"],
155
+ start_date="2020"
156
+ )
157
+ ```
158
+
159
+ ## Period formats
160
+
161
+ RBA series use ISO-style date formats. Pass `start_date` / `end_date` as:
162
+
163
+ | Format | Example | Use for |
164
+ |---|---|---|
165
+ | `YYYY` | `"2024"` | Year start |
166
+ | `YYYY-MM` | `"2024-03"` | Month start |
167
+ | `YYYY-MM-DD` | `"2024-03-15"` | Specific day (daily tables only) |
168
+
169
+ ## Development
170
+
171
+ ```bash
172
+ git clone https://github.com/Bigred97/rba-mcp.git
173
+ cd rba-mcp
174
+ uv sync --extra dev
175
+ uv pip install -e .
176
+
177
+ # Unit tests (no network)
178
+ uv run pytest
179
+
180
+ # Live integration tests (hits RBA CDN)
181
+ uv run pytest -m live
182
+ ```
183
+
184
+ The SQLite cache lives at `~/.rba-mcp/cache.db`. Data refreshes every 6h, latest 15min. Delete to force a refresh.
185
+
186
+ ## Data attribution
187
+
188
+ RBA data is licensed under [Creative Commons Attribution 4.0 International (CC BY 4.0)](https://www.rba.gov.au/copyright/). Every `DataResponse` from this server includes an `attribution` field with the required notice. If you redistribute responses, credit the RBA.
189
+
190
+ ## License
191
+
192
+ MIT — Harry Vass, 2026.
@@ -0,0 +1,161 @@
1
+ # rba-mcp
2
+
3
+ [![tests](https://github.com/Bigred97/rba-mcp/actions/workflows/test.yml/badge.svg)](https://github.com/Bigred97/rba-mcp/actions/workflows/test.yml)
4
+ [![PyPI](https://img.shields.io/pypi/v/rba-mcp.svg)](https://pypi.org/project/rba-mcp/)
5
+ [![Python](https://img.shields.io/pypi/pyversions/rba-mcp.svg)](https://pypi.org/project/rba-mcp/)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
7
+
8
+ **Ask Claude about Australian interest rates, exchange rates, and lending rates and get real, current numbers** — not "I don't have access to that data." This MCP server gives Claude (and other MCP clients like Cursor) live access to the [Reserve Bank of Australia's statistical tables](https://www.rba.gov.au/statistics/tables/), with curated mappings for the most-asked indicators.
9
+
10
+ Companion to [abs-mcp](https://github.com/Bigred97/abs-mcp) — together they cover the most-asked Australian economic data.
11
+
12
+ ## What you can ask
13
+
14
+ Once installed, your LLM can answer questions like:
15
+
16
+ | Question | Real response |
17
+ |---|---|
18
+ | What's the current RBA cash rate? | RBA Cash Rate Target, latest month |
19
+ | What's AUD/USD today? | Latest daily exchange rate |
20
+ | Show me AUD vs major currencies in 2024 | Multi-series query with monthly observations |
21
+ | What's the average mortgage rate? | Owner-occupier variable, outstanding loans |
22
+ | What rate are 12-month term deposits at? | Latest from F4 |
23
+ | What's the trade-weighted index trend? | TWI series back to 1983 |
24
+
25
+ Every answer comes with the period, units (Per cent per annum, USD per AUD, etc.), and a link back to the RBA source.
26
+
27
+ ## Install
28
+
29
+ ```bash
30
+ # After publish:
31
+ uvx rba-mcp
32
+
33
+ # Local dev:
34
+ uv pip install -e .
35
+ ```
36
+
37
+ ### Claude Desktop
38
+
39
+ Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:
40
+
41
+ ```json
42
+ {
43
+ "mcpServers": {
44
+ "rba": {
45
+ "command": "uvx",
46
+ "args": ["rba-mcp"]
47
+ }
48
+ }
49
+ }
50
+ ```
51
+
52
+ If you also have `abs-mcp` installed, both servers run side-by-side. Claude disambiguates with the server prefix (`rba:get_data` vs `abs:get_data`).
53
+
54
+ For local dev (pre-PyPI):
55
+
56
+ ```json
57
+ {
58
+ "mcpServers": {
59
+ "rba": {
60
+ "command": "uv",
61
+ "args": ["run", "--directory", "/absolute/path/to/rba-mcp", "rba-mcp"]
62
+ }
63
+ }
64
+ }
65
+ ```
66
+
67
+ ### Cursor
68
+
69
+ Add to `~/.cursor/mcp.json` (or workspace `.cursor/mcp.json`):
70
+
71
+ ```json
72
+ {
73
+ "mcpServers": {
74
+ "rba": {
75
+ "command": "uvx",
76
+ "args": ["rba-mcp"]
77
+ }
78
+ }
79
+ }
80
+ ```
81
+
82
+ ## Tools
83
+
84
+ | Tool | What it does |
85
+ |---|---|
86
+ | `search_tables(query, limit=10)` | Fuzzy-search RBA F-tables by name or topic. |
87
+ | `describe_table(table_id)` | Plain-English series listing for one F-table. |
88
+ | `get_data(table_id, series, start_date, end_date, format)` | Query data. `series=None` returns all curated series; format = records / series / csv. |
89
+ | `latest(table_id, series)` | Most-recent observation for the requested series. |
90
+ | `list_curated()` | The 5 F-table IDs with hand-curated plain-English support. |
91
+
92
+ ## Curated F-tables
93
+
94
+ For these five, `series` accepts plain-English keys (e.g. `"aud_usd"` instead of `"FXRUSD"`):
95
+
96
+ - **F1.1** — Money Market — Monthly: cash rate target, cash rate, bank bills, OIS rates, treasury notes
97
+ - **F4** — Retail Deposit & Investment Rates: transaction accounts, savings, term deposits, cash management trusts
98
+ - **F6** — Housing Lending Rates: owner-occupier vs investor, variable vs fixed, outstanding vs new loans
99
+ - **F11** — Exchange Rates — Monthly History (1983+): AUD/USD, AUD/EUR, AUD/GBP, AUD/JPY, AUD/CNY, AUD/NZD, TWI
100
+ - **F11.1** — Exchange Rates — Daily (2023+): same series, daily resolution
101
+
102
+ Any other F-table works too — pass raw RBA series IDs (e.g. `"FXRUSD"`) instead of curated keys.
103
+
104
+ ## Worked examples
105
+
106
+ **"What's the current RBA cash rate?"**
107
+
108
+ ```
109
+ latest(table_id="F1.1", series="cash_rate_target")
110
+ ```
111
+
112
+ **"AUD to USD over the last year"**
113
+
114
+ ```
115
+ get_data(table_id="F11.1", series="aud_usd", start_date="2024")
116
+ ```
117
+
118
+ **"Compare AUD against USD, EUR and GBP since 2020"**
119
+
120
+ ```
121
+ get_data(
122
+ table_id="F11",
123
+ series=["aud_usd", "aud_eur", "aud_gbp"],
124
+ start_date="2020"
125
+ )
126
+ ```
127
+
128
+ ## Period formats
129
+
130
+ RBA series use ISO-style date formats. Pass `start_date` / `end_date` as:
131
+
132
+ | Format | Example | Use for |
133
+ |---|---|---|
134
+ | `YYYY` | `"2024"` | Year start |
135
+ | `YYYY-MM` | `"2024-03"` | Month start |
136
+ | `YYYY-MM-DD` | `"2024-03-15"` | Specific day (daily tables only) |
137
+
138
+ ## Development
139
+
140
+ ```bash
141
+ git clone https://github.com/Bigred97/rba-mcp.git
142
+ cd rba-mcp
143
+ uv sync --extra dev
144
+ uv pip install -e .
145
+
146
+ # Unit tests (no network)
147
+ uv run pytest
148
+
149
+ # Live integration tests (hits RBA CDN)
150
+ uv run pytest -m live
151
+ ```
152
+
153
+ The SQLite cache lives at `~/.rba-mcp/cache.db`. Data refreshes every 6h, latest 15min. Delete to force a refresh.
154
+
155
+ ## Data attribution
156
+
157
+ RBA data is licensed under [Creative Commons Attribution 4.0 International (CC BY 4.0)](https://www.rba.gov.au/copyright/). Every `DataResponse` from this server includes an `attribution` field with the required notice. If you redistribute responses, credit the RBA.
158
+
159
+ ## License
160
+
161
+ MIT — Harry Vass, 2026.
@@ -0,0 +1,4 @@
1
+ {
2
+ "$schema": "https://glama.ai/mcp/schemas/server.json",
3
+ "maintainers": ["Bigred97"]
4
+ }
@@ -0,0 +1,55 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "rba-mcp"
7
+ version = "0.1.0"
8
+ description = "MCP server for the Reserve Bank of Australia statistical tables (F-tables). Plain-English access to interest rates, FX rates, deposit/lending rates."
9
+ readme = "README.md"
10
+ requires-python = ">=3.11"
11
+ license = { text = "MIT" }
12
+ authors = [{ name = "Harry Vass" }]
13
+ keywords = ["mcp", "rba", "australia", "interest-rates", "fx", "claude", "fastmcp"]
14
+ classifiers = [
15
+ "Development Status :: 4 - Beta",
16
+ "Intended Audience :: Developers",
17
+ "License :: OSI Approved :: MIT License",
18
+ "Programming Language :: Python :: 3.11",
19
+ "Programming Language :: Python :: 3.12",
20
+ "Programming Language :: Python :: 3.13",
21
+ "Topic :: Scientific/Engineering :: Information Analysis",
22
+ ]
23
+ dependencies = [
24
+ "fastmcp>=2.0,<4",
25
+ "httpx>=0.27",
26
+ "pydantic>=2.7",
27
+ "rapidfuzz>=3.9",
28
+ "pandas>=2.2,<3",
29
+ "aiosqlite>=0.20",
30
+ "PyYAML>=6.0",
31
+ ]
32
+
33
+ [project.optional-dependencies]
34
+ dev = [
35
+ "pytest>=8",
36
+ "pytest-asyncio>=0.23",
37
+ "respx>=0.21",
38
+ ]
39
+
40
+ [project.scripts]
41
+ rba-mcp = "rba_mcp.server:main"
42
+
43
+ [project.urls]
44
+ Homepage = "https://github.com/Bigred97/rba-mcp"
45
+ Issues = "https://github.com/Bigred97/rba-mcp/issues"
46
+
47
+ [tool.hatch.build.targets.wheel]
48
+ packages = ["src/rba_mcp"]
49
+
50
+ [tool.pytest.ini_options]
51
+ asyncio_mode = "auto"
52
+ markers = ["live: hits the real RBA CDN"]
53
+ addopts = "-m 'not live'"
54
+ testpaths = ["tests"]
55
+ pythonpath = ["src"]
@@ -0,0 +1,6 @@
1
+ from importlib.metadata import PackageNotFoundError, version as _version
2
+
3
+ try:
4
+ __version__ = _version("rba-mcp")
5
+ except PackageNotFoundError: # editable install before metadata is generated
6
+ __version__ = "0.0.0+unknown"
@@ -0,0 +1,95 @@
1
+ """SQLite-backed HTTP cache with per-read TTL.
2
+
3
+ Single table; the same row can satisfy different TTL windows because TTL is
4
+ evaluated at read time. The `kind` column lets us run targeted invalidation
5
+ later without renaming.
6
+
7
+ Ported from abs-mcp 0.2.8 — only differences:
8
+ - DEFAULT_DB_PATH points at ~/.rba-mcp/
9
+ - CacheKind enum reduced to {"data", "latest"} (no SDMX catalogue/datastructure)
10
+ - Default TTLs tuned for RBA's daily-CDN refresh cadence
11
+ """
12
+ from __future__ import annotations
13
+
14
+ import asyncio
15
+ import time
16
+ from datetime import timedelta
17
+ from pathlib import Path
18
+ from typing import Literal
19
+
20
+ import aiosqlite
21
+
22
+ CacheKind = Literal["data", "latest"]
23
+
24
+ DEFAULT_DB_PATH = Path.home() / ".rba-mcp" / "cache.db"
25
+
26
+ TTL: dict[CacheKind, timedelta] = {
27
+ "data": timedelta(hours=6), # RBA refreshes mid-morning Sydney for daily tables
28
+ "latest": timedelta(minutes=15), # post-publication freshness window
29
+ }
30
+
31
+ _SCHEMA = """
32
+ CREATE TABLE IF NOT EXISTS http_cache (
33
+ cache_key TEXT PRIMARY KEY,
34
+ payload BLOB NOT NULL,
35
+ cached_at REAL NOT NULL,
36
+ kind TEXT NOT NULL
37
+ );
38
+ CREATE INDEX IF NOT EXISTS idx_kind_cached_at ON http_cache(kind, cached_at);
39
+ """
40
+
41
+
42
+ class Cache:
43
+ def __init__(self, db_path: Path = DEFAULT_DB_PATH) -> None:
44
+ self.db_path = db_path
45
+ self.db_path.parent.mkdir(parents=True, exist_ok=True)
46
+ self._initialized = False
47
+ self._init_lock = asyncio.Lock()
48
+
49
+ async def _ensure_init(self) -> None:
50
+ if self._initialized:
51
+ return
52
+ async with self._init_lock:
53
+ if self._initialized:
54
+ return
55
+ async with aiosqlite.connect(self.db_path) as conn:
56
+ await conn.execute("PRAGMA journal_mode=WAL")
57
+ await conn.executescript(_SCHEMA)
58
+ await conn.commit()
59
+ self._initialized = True
60
+
61
+ async def get(self, key: str, ttl: timedelta) -> bytes | None:
62
+ await self._ensure_init()
63
+ cutoff = time.time() - ttl.total_seconds()
64
+ async with aiosqlite.connect(self.db_path) as conn:
65
+ async with conn.execute(
66
+ "SELECT payload FROM http_cache WHERE cache_key = ? AND cached_at >= ?",
67
+ (key, cutoff),
68
+ ) as cur:
69
+ row = await cur.fetchone()
70
+ return row[0] if row else None
71
+
72
+ async def set(self, key: str, value: bytes, kind: CacheKind) -> None:
73
+ await self._ensure_init()
74
+ async with aiosqlite.connect(self.db_path) as conn:
75
+ await conn.execute(
76
+ """
77
+ INSERT INTO http_cache (cache_key, payload, cached_at, kind)
78
+ VALUES (?, ?, ?, ?)
79
+ ON CONFLICT(cache_key) DO UPDATE SET
80
+ payload = excluded.payload,
81
+ cached_at = excluded.cached_at,
82
+ kind = excluded.kind
83
+ """,
84
+ (key, value, time.time(), kind),
85
+ )
86
+ await conn.commit()
87
+
88
+ async def clear(self, kind: CacheKind | None = None) -> None:
89
+ await self._ensure_init()
90
+ async with aiosqlite.connect(self.db_path) as conn:
91
+ if kind:
92
+ await conn.execute("DELETE FROM http_cache WHERE kind = ?", (kind,))
93
+ else:
94
+ await conn.execute("DELETE FROM http_cache")
95
+ await conn.commit()