asic-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.
- asic_mcp-0.1.0/.github/ISSUE_TEMPLATE/bug_report.yml +72 -0
- asic_mcp-0.1.0/.github/ISSUE_TEMPLATE/config.yml +11 -0
- asic_mcp-0.1.0/.github/ISSUE_TEMPLATE/feature_request.yml +46 -0
- asic_mcp-0.1.0/.github/PULL_REQUEST_TEMPLATE.md +26 -0
- asic_mcp-0.1.0/.github/dependabot.yml +39 -0
- asic_mcp-0.1.0/.github/workflows/codeql.yml +40 -0
- asic_mcp-0.1.0/.github/workflows/release.yml +57 -0
- asic_mcp-0.1.0/.github/workflows/test.yml +60 -0
- asic_mcp-0.1.0/.gitignore +18 -0
- asic_mcp-0.1.0/CHANGELOG.md +79 -0
- asic_mcp-0.1.0/CODE_OF_CONDUCT.md +33 -0
- asic_mcp-0.1.0/CONTRIBUTING.md +86 -0
- asic_mcp-0.1.0/LICENSE +21 -0
- asic_mcp-0.1.0/PKG-INFO +197 -0
- asic_mcp-0.1.0/README.md +162 -0
- asic_mcp-0.1.0/RESEARCH.md +363 -0
- asic_mcp-0.1.0/SECURITY.md +41 -0
- asic_mcp-0.1.0/examples/claude_desktop_config_all_three.json +33 -0
- asic_mcp-0.1.0/examples/claude_desktop_config_local.json +14 -0
- asic_mcp-0.1.0/examples/demo_prompts.md +104 -0
- asic_mcp-0.1.0/glama.json +4 -0
- asic_mcp-0.1.0/llms.txt +90 -0
- asic_mcp-0.1.0/pyproject.toml +77 -0
- asic_mcp-0.1.0/src/asic_mcp/__init__.py +8 -0
- asic_mcp-0.1.0/src/asic_mcp/cache.py +134 -0
- asic_mcp-0.1.0/src/asic_mcp/catalog.py +57 -0
- asic_mcp-0.1.0/src/asic_mcp/client.py +124 -0
- asic_mcp-0.1.0/src/asic_mcp/curated.py +317 -0
- asic_mcp-0.1.0/src/asic_mcp/data/curated/ASIC_AFS_AUTH_REP.yaml +131 -0
- asic_mcp-0.1.0/src/asic_mcp/data/curated/ASIC_AFS_LICENSEE.yaml +120 -0
- asic_mcp-0.1.0/src/asic_mcp/data/curated/ASIC_BANNED_ORGS.yaml +73 -0
- asic_mcp-0.1.0/src/asic_mcp/data/curated/ASIC_BANNED_PERSONS.yaml +109 -0
- asic_mcp-0.1.0/src/asic_mcp/data/curated/ASIC_CREDIT_LICENSEE.yaml +138 -0
- asic_mcp-0.1.0/src/asic_mcp/data/curated/ASIC_FINANCIAL_ADVISERS.yaml +159 -0
- asic_mcp-0.1.0/src/asic_mcp/data/curated/ASIC_LIQUIDATOR.yaml +128 -0
- asic_mcp-0.1.0/src/asic_mcp/discovery.py +241 -0
- asic_mcp-0.1.0/src/asic_mcp/models.py +105 -0
- asic_mcp-0.1.0/src/asic_mcp/parsing.py +166 -0
- asic_mcp-0.1.0/src/asic_mcp/py.typed +0 -0
- asic_mcp-0.1.0/src/asic_mcp/server.py +564 -0
- asic_mcp-0.1.0/src/asic_mcp/shaping.py +542 -0
- asic_mcp-0.1.0/tests/__init__.py +0 -0
- asic_mcp-0.1.0/tests/conftest.py +71 -0
- asic_mcp-0.1.0/tests/fixtures/asic_afs_auth_rep.csv +51 -0
- asic_mcp-0.1.0/tests/fixtures/asic_afs_licensee.csv +51 -0
- asic_mcp-0.1.0/tests/fixtures/asic_banned_orgs.csv +16 -0
- asic_mcp-0.1.0/tests/fixtures/asic_banned_persons.csv +51 -0
- asic_mcp-0.1.0/tests/fixtures/asic_credit_licensee.csv +51 -0
- asic_mcp-0.1.0/tests/fixtures/asic_financial_advisers.csv +51 -0
- asic_mcp-0.1.0/tests/fixtures/asic_liquidator.csv +51 -0
- asic_mcp-0.1.0/tests/test_cache.py +162 -0
- asic_mcp-0.1.0/tests/test_concurrency.py +112 -0
- asic_mcp-0.1.0/tests/test_curated.py +222 -0
- asic_mcp-0.1.0/tests/test_dataset_specific.py +253 -0
- asic_mcp-0.1.0/tests/test_df_cache.py +192 -0
- asic_mcp-0.1.0/tests/test_discovery.py +298 -0
- asic_mcp-0.1.0/tests/test_edge_inputs.py +316 -0
- asic_mcp-0.1.0/tests/test_live.py +125 -0
- asic_mcp-0.1.0/tests/test_parsing_asic.py +138 -0
- asic_mcp-0.1.0/tests/test_register_shape.py +234 -0
- asic_mcp-0.1.0/tests/test_resilience.py +147 -0
- asic_mcp-0.1.0/tests/test_server_validation.py +107 -0
- asic_mcp-0.1.0/uv.lock +1775 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
name: Bug report
|
|
2
|
+
description: Something works wrong, returns wrong data, or crashes.
|
|
3
|
+
title: "[bug] "
|
|
4
|
+
labels: ["bug"]
|
|
5
|
+
body:
|
|
6
|
+
- type: markdown
|
|
7
|
+
attributes:
|
|
8
|
+
value: |
|
|
9
|
+
Thanks for filing! Please give us enough to reproduce. The fastest path to a fix is a minimal reproducer + the version you're running.
|
|
10
|
+
|
|
11
|
+
- type: input
|
|
12
|
+
id: version
|
|
13
|
+
attributes:
|
|
14
|
+
label: asic-mcp version
|
|
15
|
+
description: Run `python -c "import asic_mcp; print(asic_mcp.__version__)"`
|
|
16
|
+
placeholder: 0.1.1
|
|
17
|
+
validations:
|
|
18
|
+
required: true
|
|
19
|
+
|
|
20
|
+
- type: dropdown
|
|
21
|
+
id: client
|
|
22
|
+
attributes:
|
|
23
|
+
label: MCP client
|
|
24
|
+
options:
|
|
25
|
+
- Claude Desktop
|
|
26
|
+
- Cursor
|
|
27
|
+
- Windsurf
|
|
28
|
+
- Cline
|
|
29
|
+
- Direct Python (no MCP client)
|
|
30
|
+
- Other
|
|
31
|
+
validations:
|
|
32
|
+
required: true
|
|
33
|
+
|
|
34
|
+
- type: textarea
|
|
35
|
+
id: reproducer
|
|
36
|
+
attributes:
|
|
37
|
+
label: Reproducer
|
|
38
|
+
description: |
|
|
39
|
+
The exact tool call(s) that trigger the bug. Either the MCP request payload or the equivalent Python:
|
|
40
|
+
```python
|
|
41
|
+
from asic_mcp import server
|
|
42
|
+
await server.latest("F1.1", series="cash_rate_target")
|
|
43
|
+
```
|
|
44
|
+
render: python
|
|
45
|
+
validations:
|
|
46
|
+
required: true
|
|
47
|
+
|
|
48
|
+
- type: textarea
|
|
49
|
+
id: actual
|
|
50
|
+
attributes:
|
|
51
|
+
label: What actually happened
|
|
52
|
+
description: Error message, wrong value, surprising response shape, etc.
|
|
53
|
+
validations:
|
|
54
|
+
required: true
|
|
55
|
+
|
|
56
|
+
- type: textarea
|
|
57
|
+
id: expected
|
|
58
|
+
attributes:
|
|
59
|
+
label: What you expected
|
|
60
|
+
validations:
|
|
61
|
+
required: true
|
|
62
|
+
|
|
63
|
+
- type: textarea
|
|
64
|
+
id: env
|
|
65
|
+
attributes:
|
|
66
|
+
label: Environment
|
|
67
|
+
description: |
|
|
68
|
+
- Python version (`python --version`)
|
|
69
|
+
- OS (macOS / Linux / Windows + version)
|
|
70
|
+
- How you installed (`uvx asic-mcp`, `uv pip install -e .`, etc.)
|
|
71
|
+
placeholder: |
|
|
72
|
+
Python 3.12.3, macOS 15, installed via uvx
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
blank_issues_enabled: false
|
|
2
|
+
contact_links:
|
|
3
|
+
- name: Question or how-to
|
|
4
|
+
url: https://github.com/Bigred97/asic-mcp/discussions/new?category=q-a
|
|
5
|
+
about: For "how do I" or "is it possible to" — start a Discussion instead of an issue.
|
|
6
|
+
- name: Show & tell — share what you built
|
|
7
|
+
url: https://github.com/Bigred97/asic-mcp/discussions/new?category=show-and-tell
|
|
8
|
+
about: Built something cool with asic-mcp? We'd love to see it.
|
|
9
|
+
- name: Security vulnerability
|
|
10
|
+
url: https://github.com/Bigred97/asic-mcp/security/advisories/new
|
|
11
|
+
about: Use the private security advisory flow — do NOT open a public issue.
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
name: Feature request
|
|
2
|
+
description: Suggest a new tool, F-table, or behaviour.
|
|
3
|
+
title: "[feat] "
|
|
4
|
+
labels: ["enhancement"]
|
|
5
|
+
body:
|
|
6
|
+
- type: markdown
|
|
7
|
+
attributes:
|
|
8
|
+
value: |
|
|
9
|
+
Thanks for the suggestion. Higher chance of merge if you frame it around a real use case ("I want to ask Claude X and currently I have to do Y").
|
|
10
|
+
|
|
11
|
+
- type: textarea
|
|
12
|
+
id: use_case
|
|
13
|
+
attributes:
|
|
14
|
+
label: What are you trying to do?
|
|
15
|
+
placeholder: I want to ask Claude about ATO government bond yields and currently asic-mcp doesn't curate F2.
|
|
16
|
+
validations:
|
|
17
|
+
required: true
|
|
18
|
+
|
|
19
|
+
- type: textarea
|
|
20
|
+
id: proposal
|
|
21
|
+
attributes:
|
|
22
|
+
label: Proposed change
|
|
23
|
+
description: |
|
|
24
|
+
Concrete: which file would change, what would the new tool/curated YAML look like, what does the user-visible API become?
|
|
25
|
+
validations:
|
|
26
|
+
required: true
|
|
27
|
+
|
|
28
|
+
- type: textarea
|
|
29
|
+
id: alternatives
|
|
30
|
+
attributes:
|
|
31
|
+
label: Alternatives considered
|
|
32
|
+
description: e.g. "I could just pass raw ATO series IDs to get_data, but..."
|
|
33
|
+
|
|
34
|
+
- type: dropdown
|
|
35
|
+
id: scope
|
|
36
|
+
attributes:
|
|
37
|
+
label: Scope
|
|
38
|
+
options:
|
|
39
|
+
- Add a curated F-table YAML
|
|
40
|
+
- New MCP tool
|
|
41
|
+
- Change to existing tool's signature
|
|
42
|
+
- Change to default behaviour
|
|
43
|
+
- Documentation
|
|
44
|
+
- Other
|
|
45
|
+
validations:
|
|
46
|
+
required: true
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
## What & why
|
|
2
|
+
|
|
3
|
+
<!-- One paragraph: what does this PR do, and what's the motivating use case or bug? -->
|
|
4
|
+
|
|
5
|
+
## How
|
|
6
|
+
|
|
7
|
+
<!-- Brief: which files changed and why? -->
|
|
8
|
+
|
|
9
|
+
## Tests
|
|
10
|
+
|
|
11
|
+
- [ ] All existing tests still pass (`uv run pytest -m "not live"`)
|
|
12
|
+
- [ ] New behaviour has a test
|
|
13
|
+
- [ ] If this touches the live-API surface, `uv run pytest -m live` is green
|
|
14
|
+
|
|
15
|
+
## Compatibility
|
|
16
|
+
|
|
17
|
+
- [ ] No breaking changes to the public MCP tool signatures
|
|
18
|
+
- [ ] No breaking changes to the `DataResponse` / `TableDetail` JSON shape
|
|
19
|
+
- [ ] CC-BY 4.0 attribution still surfaces in `DataResponse.attribution`
|
|
20
|
+
- [ ] If any of the above is broken, this is justified in the PR body
|
|
21
|
+
|
|
22
|
+
## Other
|
|
23
|
+
|
|
24
|
+
- [ ] CHANGELOG.md updated
|
|
25
|
+
- [ ] README updated if user-visible behaviour changed
|
|
26
|
+
- [ ] No new dependencies (or new dep is justified above)
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
|
|
3
|
+
updates:
|
|
4
|
+
# Python dependencies (pyproject.toml + uv.lock)
|
|
5
|
+
- package-ecosystem: pip
|
|
6
|
+
directory: "/"
|
|
7
|
+
schedule:
|
|
8
|
+
interval: weekly
|
|
9
|
+
day: monday
|
|
10
|
+
time: "10:00"
|
|
11
|
+
timezone: Australia/Sydney
|
|
12
|
+
open-pull-requests-limit: 5
|
|
13
|
+
groups:
|
|
14
|
+
# Group all minor + patch updates into one PR per week.
|
|
15
|
+
python-runtime-minor-patch:
|
|
16
|
+
applies-to: version-updates
|
|
17
|
+
update-types: [minor, patch]
|
|
18
|
+
labels: [dependencies]
|
|
19
|
+
commit-message:
|
|
20
|
+
prefix: deps
|
|
21
|
+
include: scope
|
|
22
|
+
|
|
23
|
+
# GitHub Actions used in workflows
|
|
24
|
+
- package-ecosystem: github-actions
|
|
25
|
+
directory: "/"
|
|
26
|
+
schedule:
|
|
27
|
+
interval: weekly
|
|
28
|
+
day: monday
|
|
29
|
+
time: "10:00"
|
|
30
|
+
timezone: Australia/Sydney
|
|
31
|
+
open-pull-requests-limit: 3
|
|
32
|
+
groups:
|
|
33
|
+
gha-minor-patch:
|
|
34
|
+
applies-to: version-updates
|
|
35
|
+
update-types: [minor, patch]
|
|
36
|
+
labels: [dependencies, github-actions]
|
|
37
|
+
commit-message:
|
|
38
|
+
prefix: ci
|
|
39
|
+
include: scope
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
name: codeql
|
|
2
|
+
|
|
3
|
+
# GitHub's free SAST scanning. Runs on push to main, on PRs, and weekly.
|
|
4
|
+
# Findings appear under the repo's Security tab.
|
|
5
|
+
|
|
6
|
+
on:
|
|
7
|
+
push:
|
|
8
|
+
branches: [main]
|
|
9
|
+
pull_request:
|
|
10
|
+
branches: [main]
|
|
11
|
+
schedule:
|
|
12
|
+
- cron: "47 6 * * 1" # Mondays 06:47 UTC — off-peak, offset 10min from rba-mcp
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
analyze:
|
|
16
|
+
runs-on: ubuntu-latest
|
|
17
|
+
permissions:
|
|
18
|
+
actions: read
|
|
19
|
+
contents: read
|
|
20
|
+
security-events: write
|
|
21
|
+
strategy:
|
|
22
|
+
fail-fast: false
|
|
23
|
+
matrix:
|
|
24
|
+
language: [python]
|
|
25
|
+
steps:
|
|
26
|
+
- uses: actions/checkout@v6
|
|
27
|
+
|
|
28
|
+
- name: Initialise CodeQL
|
|
29
|
+
uses: github/codeql-action/init@v4
|
|
30
|
+
with:
|
|
31
|
+
languages: ${{ matrix.language }}
|
|
32
|
+
queries: security-extended
|
|
33
|
+
|
|
34
|
+
- name: Autobuild
|
|
35
|
+
uses: github/codeql-action/autobuild@v4
|
|
36
|
+
|
|
37
|
+
- name: Analyze
|
|
38
|
+
uses: github/codeql-action/analyze@v4
|
|
39
|
+
with:
|
|
40
|
+
category: "/language:${{ matrix.language }}"
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
name: release
|
|
2
|
+
|
|
3
|
+
# Push a tag like v0.3.0 → wheel is built and published to PyPI via
|
|
4
|
+
# Trusted Publishing (OIDC, no API token in repo secrets). One-time setup:
|
|
5
|
+
# 1. https://pypi.org/manage/account/publishing/
|
|
6
|
+
# 2. Add a "pending publisher":
|
|
7
|
+
# PyPI project = asic-mcp
|
|
8
|
+
# owner = Bigred97
|
|
9
|
+
# repository = asic-mcp
|
|
10
|
+
# workflow = release.yml
|
|
11
|
+
# environment = pypi
|
|
12
|
+
# 3. Create a `pypi` environment in repo Settings → Environments
|
|
13
|
+
# (no secrets needed; the environment scopes the OIDC token).
|
|
14
|
+
# Optionally add a required-reviewers rule so a tag push waits for
|
|
15
|
+
# your manual approval before publishing.
|
|
16
|
+
# Then any `git push origin vX.Y.Z` triggers this job.
|
|
17
|
+
|
|
18
|
+
on:
|
|
19
|
+
push:
|
|
20
|
+
tags:
|
|
21
|
+
- "v*"
|
|
22
|
+
|
|
23
|
+
jobs:
|
|
24
|
+
release:
|
|
25
|
+
runs-on: ubuntu-latest
|
|
26
|
+
environment:
|
|
27
|
+
name: pypi
|
|
28
|
+
url: https://pypi.org/project/asic-mcp/
|
|
29
|
+
permissions:
|
|
30
|
+
id-token: write # required for Trusted Publishing OIDC
|
|
31
|
+
contents: read
|
|
32
|
+
steps:
|
|
33
|
+
- uses: actions/checkout@v6
|
|
34
|
+
|
|
35
|
+
- name: Install uv
|
|
36
|
+
uses: astral-sh/setup-uv@v7
|
|
37
|
+
|
|
38
|
+
- name: Sanity-check the tag matches pyproject.toml
|
|
39
|
+
run: |
|
|
40
|
+
TAG_VERSION="${GITHUB_REF_NAME#v}"
|
|
41
|
+
PYPROJECT_VERSION=$(uv run python -c "import tomllib,sys; print(tomllib.load(open('pyproject.toml','rb'))['project']['version'])")
|
|
42
|
+
if [ "$TAG_VERSION" != "$PYPROJECT_VERSION" ]; then
|
|
43
|
+
echo "::error::Tag $GITHUB_REF_NAME does not match pyproject version $PYPROJECT_VERSION"
|
|
44
|
+
exit 1
|
|
45
|
+
fi
|
|
46
|
+
echo "Releasing version $PYPROJECT_VERSION"
|
|
47
|
+
|
|
48
|
+
- name: Build wheel + sdist
|
|
49
|
+
run: uv build
|
|
50
|
+
|
|
51
|
+
- name: Publish to PyPI (Trusted Publishing)
|
|
52
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
53
|
+
|
|
54
|
+
- uses: actions/upload-artifact@v4
|
|
55
|
+
with:
|
|
56
|
+
name: dist
|
|
57
|
+
path: dist/
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
name: tests
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
lint:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
steps:
|
|
13
|
+
- uses: actions/checkout@v6
|
|
14
|
+
- name: Install uv
|
|
15
|
+
uses: astral-sh/setup-uv@v7
|
|
16
|
+
- name: Run ruff check
|
|
17
|
+
# `uvx` runs ruff in an isolated managed env; avoids PEP 668
|
|
18
|
+
# "externally-managed environment" failure on Ubuntu 23.04+ runners
|
|
19
|
+
# that the previous `uv pip install --system` hit.
|
|
20
|
+
run: uvx "ruff>=0.5" check src/ tests/
|
|
21
|
+
|
|
22
|
+
test:
|
|
23
|
+
runs-on: ubuntu-latest
|
|
24
|
+
needs: lint
|
|
25
|
+
strategy:
|
|
26
|
+
fail-fast: false
|
|
27
|
+
matrix:
|
|
28
|
+
python-version: ["3.11", "3.12", "3.13"]
|
|
29
|
+
steps:
|
|
30
|
+
- uses: actions/checkout@v6
|
|
31
|
+
- name: Install uv
|
|
32
|
+
uses: astral-sh/setup-uv@v7
|
|
33
|
+
with:
|
|
34
|
+
enable-cache: true
|
|
35
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
36
|
+
run: uv python install ${{ matrix.python-version }}
|
|
37
|
+
- name: Sync dependencies
|
|
38
|
+
run: uv sync --extra dev
|
|
39
|
+
- name: Install package
|
|
40
|
+
run: uv pip install -e .
|
|
41
|
+
- name: Run unit tests
|
|
42
|
+
run: uv run pytest -q
|
|
43
|
+
|
|
44
|
+
build:
|
|
45
|
+
runs-on: ubuntu-latest
|
|
46
|
+
needs: test
|
|
47
|
+
steps:
|
|
48
|
+
- uses: actions/checkout@v6
|
|
49
|
+
- name: Install uv
|
|
50
|
+
uses: astral-sh/setup-uv@v7
|
|
51
|
+
- name: Build wheel + sdist
|
|
52
|
+
run: uv build
|
|
53
|
+
- name: Verify wheel installs cleanly
|
|
54
|
+
run: |
|
|
55
|
+
uv run --isolated --with ./dist/*.whl python -c \
|
|
56
|
+
"import asic_mcp.server as s; n = len(s.list_curated()); assert n >= 8, f'expected >=8 curated, got {n}'; print(f'OK ({n} curated datasets)')"
|
|
57
|
+
- uses: actions/upload-artifact@v4
|
|
58
|
+
with:
|
|
59
|
+
name: dist
|
|
60
|
+
path: dist/
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [0.1.0] — 2026-05-13
|
|
9
|
+
|
|
10
|
+
Initial release. ASIC registers via data.gov.au, plain-English access.
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **Seven curated ASIC register datasets**, all served from CKAN-discovered
|
|
15
|
+
resource URLs on data.gov.au under CC BY 3.0 AU:
|
|
16
|
+
- `ASIC_FINANCIAL_ADVISERS` — Financial Advisers Register (~21,000 records, weekly).
|
|
17
|
+
- `ASIC_AFS_LICENSEE` — Australian Financial Services Licensees (~6,500 entities, weekly).
|
|
18
|
+
- `ASIC_AFS_AUTH_REP` — AFS Authorised Representatives (~50 MB CSV, weekly).
|
|
19
|
+
- `ASIC_CREDIT_LICENSEE` — Australian Credit Licensees (NCCP-regulated lenders/brokers, weekly).
|
|
20
|
+
- `ASIC_BANNED_PERSONS` — Banned and Disqualified Persons (weekly).
|
|
21
|
+
- `ASIC_BANNED_ORGS` — Banned and Disqualified Organisations (weekly).
|
|
22
|
+
- `ASIC_LIQUIDATOR` — Registered & Official Liquidators (~700 practitioners, weekly).
|
|
23
|
+
- **Five MCP tools** matching the abs-mcp / rba-mcp / ato-mcp / apra-mcp envelope:
|
|
24
|
+
`search_datasets`, `describe_dataset`, `get_data`, `latest`, `list_curated`.
|
|
25
|
+
- **Trust contract on every `DataResponse`**: `source`, `source_url`,
|
|
26
|
+
`attribution`, `retrieved_at`, `server_version`, `stale`. Attribution is
|
|
27
|
+
the exact CC BY 3.0 AU statement from data.gov.au, naming ASIC as the
|
|
28
|
+
source and pointing at the canonical CC licence URL.
|
|
29
|
+
- **CKAN auto-discovery** — each YAML declares a `discovery:` block
|
|
30
|
+
(`package_id` + `resource_name`); the server resolves the freshest
|
|
31
|
+
resource URL at fetch time. Hard-coded YAML URLs are the safe fallback.
|
|
32
|
+
- **CSV delimiter sniffing** — ASIC labels every file `.csv` on data.gov.au,
|
|
33
|
+
but the actual delimiter is tab for some datasets (Financial Advisers, AFS
|
|
34
|
+
Authorised Representative, Banned Orgs) and comma for others (AFS
|
|
35
|
+
Licensee, Credit Licensee, Banned Persons, Liquidator). `read_csv`
|
|
36
|
+
detects from the first line.
|
|
37
|
+
- **Dimension-only register shaping** — register data has no measure
|
|
38
|
+
columns, so `shape_wide` emits one `Observation` per row carrying every
|
|
39
|
+
dimension on `Observation.dimensions` with `value`/`measure` left `None`.
|
|
40
|
+
- **SQLite byte cache** with per-kind TTLs (24h for register data, 1h for
|
|
41
|
+
CKAN catalogue) and mid-session corruption recovery.
|
|
42
|
+
- **Parsed-DataFrame in-process LRU cache** keyed by (URL, parse-spec,
|
|
43
|
+
body content hash) — warm hits avoid pandas re-parse.
|
|
44
|
+
- **In-flight dedup** — a burst of identical `latest()` calls fans into
|
|
45
|
+
one HTTP request.
|
|
46
|
+
- **State alias maps** on every register that exposes `state` — pass
|
|
47
|
+
`"nsw"`, `"NSW"`, or canonical `"NSW"`; all resolve identically.
|
|
48
|
+
- **Status alias maps** on Credit Licensee, Liquidator, and Financial
|
|
49
|
+
Adviser registers — pass `"approved"` and asic-mcp resolves to ASIC's
|
|
50
|
+
`"APPR"` code.
|
|
51
|
+
- **Polite User-Agent** on every outbound request. data.gov.au's CDN
|
|
52
|
+
blocks the default httpx UA (returns 302 to HTML); asic-mcp identifies
|
|
53
|
+
itself with `asic-mcp/0.1 (+https://github.com/Bigred97/asic-mcp)`.
|
|
54
|
+
|
|
55
|
+
### Tests
|
|
56
|
+
|
|
57
|
+
- **229 unit tests + 9 live tests = 238 total**, zero flake across the
|
|
58
|
+
10× gauntlet.
|
|
59
|
+
- Live tests assert a known-stable AFSL number (234945 — Commonwealth
|
|
60
|
+
Bank of Australia) is present in the live snapshot.
|
|
61
|
+
- Adversarial / fuzz inputs: ~80 parametrised cases probing Unicode, path
|
|
62
|
+
traversal, URL injection, type confusion, huge strings, and emoji on
|
|
63
|
+
every tool parameter.
|
|
64
|
+
- Discovery tests cover happy paths, off-host URL rejection (defense-in-
|
|
65
|
+
depth), no-match raises `DiscoveryError`, malformed CKAN responses,
|
|
66
|
+
and the fallback-to-YAML invariant when the network is down.
|
|
67
|
+
|
|
68
|
+
### Known limitations (deferred to v0.2+)
|
|
69
|
+
|
|
70
|
+
- `ASIC_COMPANIES` (373 MB CSV) and `ASIC_BUSINESS_NAMES` (234 MB CSV)
|
|
71
|
+
are excluded from v0.1 — they need a streaming lookup-by-ACN/ABN tool
|
|
72
|
+
rather than bulk table reads.
|
|
73
|
+
- Enforcement / insolvency statistics (Series 3.1 / 3.2 / 3.3 XLSX on
|
|
74
|
+
asic.gov.au) are not in v0.1 — they live outside data.gov.au and need
|
|
75
|
+
apra-style landing-page scraping.
|
|
76
|
+
- Short-position daily CSVs are not in v0.1 — they have a different
|
|
77
|
+
cadence and shape (one CSV per reporting day).
|
|
78
|
+
- The dimension-only register model gives `Observation.value = None` for
|
|
79
|
+
every row. Agents should read register data from `Observation.dimensions`.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Contributor Covenant Code of Conduct
|
|
2
|
+
|
|
3
|
+
## Our Pledge
|
|
4
|
+
|
|
5
|
+
We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation.
|
|
6
|
+
|
|
7
|
+
We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community.
|
|
8
|
+
|
|
9
|
+
## Our Standards
|
|
10
|
+
|
|
11
|
+
Examples of behaviour that contributes to a positive environment:
|
|
12
|
+
|
|
13
|
+
- Demonstrating empathy and kindness toward other people
|
|
14
|
+
- Being respectful of differing opinions, viewpoints, and experiences
|
|
15
|
+
- Giving and gracefully accepting constructive feedback
|
|
16
|
+
- Accepting responsibility and apologising to those affected by mistakes, and learning from the experience
|
|
17
|
+
- Focusing on what is best for the overall community
|
|
18
|
+
|
|
19
|
+
Examples of unacceptable behaviour:
|
|
20
|
+
|
|
21
|
+
- The use of sexualised language or imagery, and sexual attention or advances of any kind
|
|
22
|
+
- Trolling, insulting or derogatory comments, and personal or political attacks
|
|
23
|
+
- Public or private harassment
|
|
24
|
+
- Publishing others' private information, such as a physical or email address, without their explicit permission
|
|
25
|
+
- Other conduct which could reasonably be considered inappropriate in a professional setting
|
|
26
|
+
|
|
27
|
+
## Enforcement
|
|
28
|
+
|
|
29
|
+
Instances of abusive, harassing, or otherwise unacceptable behaviour may be reported to the project maintainer at hvass97@gmail.com. All complaints will be reviewed and investigated promptly and fairly.
|
|
30
|
+
|
|
31
|
+
## Attribution
|
|
32
|
+
|
|
33
|
+
This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org/), version 2.1.
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# Contributing to asic-mcp
|
|
2
|
+
|
|
3
|
+
Thanks for considering a contribution. This is an indie open-source project — every PR is read.
|
|
4
|
+
|
|
5
|
+
## Quick start
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
git clone https://github.com/Bigred97/asic-mcp.git
|
|
9
|
+
cd asic-mcp
|
|
10
|
+
uv sync --extra dev
|
|
11
|
+
uv pip install -e .
|
|
12
|
+
|
|
13
|
+
# Unit tests (no network)
|
|
14
|
+
uv run pytest
|
|
15
|
+
|
|
16
|
+
# Live integration tests (hits data.gov.au)
|
|
17
|
+
uv run pytest -m live
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## What kind of contribution helps?
|
|
21
|
+
|
|
22
|
+
| Most welcome | Be cautious |
|
|
23
|
+
|---|---|
|
|
24
|
+
| Bug fixes (with a regression test) | Adding new tools to the MCP surface |
|
|
25
|
+
| New curated datasets (one YAML per dataset in `src/asic_mcp/data/curated/`) | Refactors that touch >3 modules |
|
|
26
|
+
| Better error messages with actionable hints | Changes that break the public response shape |
|
|
27
|
+
| Docs / README improvements | Pulling in new dependencies |
|
|
28
|
+
| Performance fixes (with a benchmark) | Changes to the YAML schema |
|
|
29
|
+
|
|
30
|
+
## Adding a curated dataset
|
|
31
|
+
|
|
32
|
+
1. Find the dataset on [data.gov.au](https://data.gov.au/data/organization/australiantaxationoffice). Note the dataset slug (e.g. `taxation-statistics-2022-23`) and the specific resource (e.g. `Individuals - Table 6`).
|
|
33
|
+
2. Fetch the resource metadata via CKAN: `curl https://data.gov.au/data/api/3/action/package_show?id={slug} | jq` and find the resource's `url` field.
|
|
34
|
+
3. Download a copy and inspect headers:
|
|
35
|
+
```python
|
|
36
|
+
import openpyxl
|
|
37
|
+
wb = openpyxl.load_workbook("file.xlsx", read_only=True, data_only=True)
|
|
38
|
+
for sn in wb.sheetnames:
|
|
39
|
+
ws = wb[sn]
|
|
40
|
+
for row in ws.iter_rows(max_row=5, values_only=True):
|
|
41
|
+
print(row)
|
|
42
|
+
```
|
|
43
|
+
Identify the data sheet, the 1-indexed header row, and the canonical column names. Note: ATO column headers often have embedded newlines (`Individuals\nno.`) — `parsing._normalize_header` strips padding around the newline so canonical YAML form is `"Individuals\nno."`.
|
|
44
|
+
4. Hand-write the YAML under `src/asic_mcp/data/curated/{ID}.yaml`. `CORP_TRANSPARENCY.yaml` is the simplest reference (header_row 1, flat tabular); `IND_POSTCODE.yaml` covers the multi-dimension case.
|
|
45
|
+
5. Run the smoke test to confirm column mappings match:
|
|
46
|
+
```bash
|
|
47
|
+
PYTHONPATH=src uv run python -c "
|
|
48
|
+
from pathlib import Path
|
|
49
|
+
from asic_mcp import curated, parsing, shaping
|
|
50
|
+
cd = curated.get('YOUR_ID')
|
|
51
|
+
df = parsing.read_xlsx(Path('/path/to/file.xlsx').read_bytes(), sheet=cd.sheet, header_row=cd.header_row)
|
|
52
|
+
missing = [c.source_column for c in cd.columns.values() if c.source_column not in df.columns]
|
|
53
|
+
print('missing:' if missing else 'all columns match', missing)
|
|
54
|
+
"
|
|
55
|
+
```
|
|
56
|
+
6. Add a test fixture in `tests/fixtures/` and write a test in `tests/test_shaping.py`.
|
|
57
|
+
7. Run `uv run pytest -m live` and confirm green.
|
|
58
|
+
|
|
59
|
+
## PR checklist
|
|
60
|
+
|
|
61
|
+
- [ ] All tests pass (`uv run pytest -m "not live"` minimum; `uv run pytest -m live` if you touched curation or the network path)
|
|
62
|
+
- [ ] New code has tests
|
|
63
|
+
- [ ] No new dependencies (or they're justified in the PR body)
|
|
64
|
+
- [ ] CHANGELOG.md updated under the Unreleased section
|
|
65
|
+
- [ ] If you changed default behaviour, the README "Example queries" still produces the documented values
|
|
66
|
+
- [ ] CC-BY 3.0 AU attribution still surfaces in `DataResponse.attribution`
|
|
67
|
+
|
|
68
|
+
## Style
|
|
69
|
+
|
|
70
|
+
- Python 3.11+, `from __future__ import annotations` at file top
|
|
71
|
+
- Pydantic v2 models — use `Field(default_factory=...)` for mutable defaults
|
|
72
|
+
- Docstrings in module-level summary; functions only when non-obvious
|
|
73
|
+
- No comments restating the code; comments explain *why*
|
|
74
|
+
|
|
75
|
+
## Filing bugs
|
|
76
|
+
|
|
77
|
+
Use the bug-report issue template. Bugs filed via the template get triaged within a week; freeform issues may sit longer.
|
|
78
|
+
|
|
79
|
+
## Discussions vs Issues
|
|
80
|
+
|
|
81
|
+
- **Issue**: bug, feature request, security report
|
|
82
|
+
- **Discussion**: question, idea you're not sure about, sharing how you're using the package
|
|
83
|
+
|
|
84
|
+
## Code of conduct
|
|
85
|
+
|
|
86
|
+
This project follows the [Contributor Covenant](CODE_OF_CONDUCT.md). Be kind.
|
asic_mcp-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
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.
|