openwealth-mcp 0.3.5__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.
- openwealth_mcp-0.3.5/.gitattributes +16 -0
- openwealth_mcp-0.3.5/.github/CODEOWNERS +2 -0
- openwealth_mcp-0.3.5/.github/dependabot.yml +18 -0
- openwealth_mcp-0.3.5/.github/workflows/ci.yml +61 -0
- openwealth_mcp-0.3.5/.github/workflows/publish.yml +96 -0
- openwealth_mcp-0.3.5/.github/workflows/release.yml +143 -0
- openwealth_mcp-0.3.5/.github/workflows/tag-release.yml +76 -0
- openwealth_mcp-0.3.5/.gitignore +18 -0
- openwealth_mcp-0.3.5/.pre-commit-config.yaml +19 -0
- openwealth_mcp-0.3.5/CHANGELOG.md +167 -0
- openwealth_mcp-0.3.5/CONTRIBUTING.md +105 -0
- openwealth_mcp-0.3.5/LICENSE +202 -0
- openwealth_mcp-0.3.5/PKG-INFO +368 -0
- openwealth_mcp-0.3.5/README.md +327 -0
- openwealth_mcp-0.3.5/SECURITY.md +42 -0
- openwealth_mcp-0.3.5/docs/local-dev.md +33 -0
- openwealth_mcp-0.3.5/docs/mcp-clients.md +144 -0
- openwealth_mcp-0.3.5/docs/release.md +164 -0
- openwealth_mcp-0.3.5/pyproject.toml +115 -0
- openwealth_mcp-0.3.5/specs/custodyAPI.yaml +1873 -0
- openwealth_mcp-0.3.5/specs/customerAPI.yaml +3526 -0
- openwealth_mcp-0.3.5/specs/tradingAPI.yaml +2215 -0
- openwealth_mcp-0.3.5/src/openwealth_mcp/__init__.py +3 -0
- openwealth_mcp-0.3.5/src/openwealth_mcp/__main__.py +4 -0
- openwealth_mcp-0.3.5/src/openwealth_mcp/_server_base.py +61 -0
- openwealth_mcp-0.3.5/src/openwealth_mcp/app.py +8 -0
- openwealth_mcp-0.3.5/src/openwealth_mcp/client.py +462 -0
- openwealth_mcp-0.3.5/src/openwealth_mcp/config.py +128 -0
- openwealth_mcp-0.3.5/src/openwealth_mcp/custody/__init__.py +3 -0
- openwealth_mcp-0.3.5/src/openwealth_mcp/custody/app.py +28 -0
- openwealth_mcp-0.3.5/src/openwealth_mcp/custody/server.py +78 -0
- openwealth_mcp-0.3.5/src/openwealth_mcp/custody/service.py +186 -0
- openwealth_mcp-0.3.5/src/openwealth_mcp/customer/__init__.py +1 -0
- openwealth_mcp-0.3.5/src/openwealth_mcp/customer/app.py +27 -0
- openwealth_mcp-0.3.5/src/openwealth_mcp/customer/server.py +80 -0
- openwealth_mcp-0.3.5/src/openwealth_mcp/customer/service.py +310 -0
- openwealth_mcp-0.3.5/src/openwealth_mcp/errors.py +94 -0
- openwealth_mcp-0.3.5/src/openwealth_mcp/logging_config.py +112 -0
- openwealth_mcp-0.3.5/src/openwealth_mcp/py.typed +0 -0
- openwealth_mcp-0.3.5/src/openwealth_mcp/resources/__init__.py +4 -0
- openwealth_mcp-0.3.5/src/openwealth_mcp/resources/_spec_path.py +23 -0
- openwealth_mcp-0.3.5/src/openwealth_mcp/resources/custody.py +60 -0
- openwealth_mcp-0.3.5/src/openwealth_mcp/resources/customer.py +83 -0
- openwealth_mcp-0.3.5/src/openwealth_mcp/resources/trading.py +72 -0
- openwealth_mcp-0.3.5/src/openwealth_mcp/server.py +8 -0
- openwealth_mcp-0.3.5/src/openwealth_mcp/service_app.py +74 -0
- openwealth_mcp-0.3.5/src/openwealth_mcp/tools/__init__.py +5 -0
- openwealth_mcp-0.3.5/src/openwealth_mcp/tools/custody.py +305 -0
- openwealth_mcp-0.3.5/src/openwealth_mcp/tools/customer.py +617 -0
- openwealth_mcp-0.3.5/src/openwealth_mcp/tools/trading.py +536 -0
- openwealth_mcp-0.3.5/src/openwealth_mcp/trading/__init__.py +5 -0
- openwealth_mcp-0.3.5/src/openwealth_mcp/trading/app.py +28 -0
- openwealth_mcp-0.3.5/src/openwealth_mcp/trading/server.py +79 -0
- openwealth_mcp-0.3.5/src/openwealth_mcp/trading/service.py +306 -0
- openwealth_mcp-0.3.5/src/openwealth_mcp/validation.py +32 -0
- openwealth_mcp-0.3.5/tests/conftest.py +34 -0
- openwealth_mcp-0.3.5/tests/test_client.py +122 -0
- openwealth_mcp-0.3.5/tests/test_config.py +160 -0
- openwealth_mcp-0.3.5/tests/test_custody_service.py +161 -0
- openwealth_mcp-0.3.5/tests/test_customer_service.py +423 -0
- openwealth_mcp-0.3.5/tests/test_entrypoints.py +205 -0
- openwealth_mcp-0.3.5/tests/test_errors.py +63 -0
- openwealth_mcp-0.3.5/tests/test_logging_config.py +51 -0
- openwealth_mcp-0.3.5/tests/test_resources_and_tools.py +212 -0
- openwealth_mcp-0.3.5/tests/test_settings_docs_sync.py +62 -0
- openwealth_mcp-0.3.5/tests/test_tools_custody.py +90 -0
- openwealth_mcp-0.3.5/tests/test_tools_customer.py +210 -0
- openwealth_mcp-0.3.5/tests/test_tools_trading.py +315 -0
- openwealth_mcp-0.3.5/tests/test_trading_service.py +439 -0
- openwealth_mcp-0.3.5/tests/test_validation.py +33 -0
- openwealth_mcp-0.3.5/uv.lock +2065 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Normalise all text files to LF on commit; check out as LF everywhere.
|
|
2
|
+
* text=auto eol=lf
|
|
3
|
+
|
|
4
|
+
# Explicitly mark binary files so git never mangles them.
|
|
5
|
+
*.png binary
|
|
6
|
+
*.jpg binary
|
|
7
|
+
*.gif binary
|
|
8
|
+
*.ico binary
|
|
9
|
+
*.zip binary
|
|
10
|
+
*.gz binary
|
|
11
|
+
*.whl binary
|
|
12
|
+
*.pyc binary
|
|
13
|
+
|
|
14
|
+
# YAML spec files — keep as LF
|
|
15
|
+
*.yaml text eol=lf
|
|
16
|
+
*.yml text eol=lf
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
updates:
|
|
3
|
+
- package-ecosystem: "pip"
|
|
4
|
+
directory: "/"
|
|
5
|
+
schedule:
|
|
6
|
+
interval: "weekly"
|
|
7
|
+
open-pull-requests-limit: 5
|
|
8
|
+
labels:
|
|
9
|
+
- "dependencies"
|
|
10
|
+
|
|
11
|
+
- package-ecosystem: "github-actions"
|
|
12
|
+
directory: "/"
|
|
13
|
+
schedule:
|
|
14
|
+
interval: "weekly"
|
|
15
|
+
open-pull-requests-limit: 5
|
|
16
|
+
labels:
|
|
17
|
+
- "dependencies"
|
|
18
|
+
- "github-actions"
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [master, main, "feature/**"]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
quality:
|
|
13
|
+
name: Quality (${{ matrix.python-version }})
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
strategy:
|
|
16
|
+
fail-fast: false
|
|
17
|
+
matrix:
|
|
18
|
+
python-version: ["3.11", "3.12", "3.13"]
|
|
19
|
+
|
|
20
|
+
steps:
|
|
21
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
22
|
+
|
|
23
|
+
- name: Install uv
|
|
24
|
+
uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
|
|
25
|
+
with:
|
|
26
|
+
enable-cache: true
|
|
27
|
+
|
|
28
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
29
|
+
run: uv python install ${{ matrix.python-version }}
|
|
30
|
+
|
|
31
|
+
- name: Install dependencies
|
|
32
|
+
run: uv sync --frozen --extra dev
|
|
33
|
+
|
|
34
|
+
- name: Lint (ruff check)
|
|
35
|
+
run: uv run ruff check src tests
|
|
36
|
+
|
|
37
|
+
- name: Format check (ruff format)
|
|
38
|
+
run: uv run ruff format --check src tests
|
|
39
|
+
|
|
40
|
+
- name: Type check (mypy)
|
|
41
|
+
run: uv run mypy
|
|
42
|
+
|
|
43
|
+
- name: Tests (pytest + coverage)
|
|
44
|
+
run: uv run pytest -q
|
|
45
|
+
|
|
46
|
+
audit:
|
|
47
|
+
name: Dependency audit
|
|
48
|
+
runs-on: ubuntu-latest
|
|
49
|
+
steps:
|
|
50
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
51
|
+
|
|
52
|
+
- name: Install uv
|
|
53
|
+
uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
|
|
54
|
+
with:
|
|
55
|
+
enable-cache: true
|
|
56
|
+
|
|
57
|
+
- name: Set up Python
|
|
58
|
+
run: uv python install 3.13
|
|
59
|
+
|
|
60
|
+
- name: Run pip-audit
|
|
61
|
+
run: uv run --with pip-audit pip-audit --requirement <(uv export --no-dev --no-hashes)
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
# Triggered in two ways:
|
|
4
|
+
#
|
|
5
|
+
# 1. workflow_dispatch on a tag ref — called automatically by tag-release.yml
|
|
6
|
+
# after the release PR merges (GITHUB_TOKEN cannot trigger push events,
|
|
7
|
+
# but CAN trigger workflow_dispatch via the REST API).
|
|
8
|
+
#
|
|
9
|
+
# 2. push: tags v* — for manual tag pushes:
|
|
10
|
+
# git tag vX.Y.Z && git push origin vX.Y.Z
|
|
11
|
+
#
|
|
12
|
+
# Pipeline: build → publish-testpypi → publish-pypi
|
|
13
|
+
on:
|
|
14
|
+
workflow_dispatch:
|
|
15
|
+
push:
|
|
16
|
+
tags:
|
|
17
|
+
- "v*"
|
|
18
|
+
|
|
19
|
+
permissions:
|
|
20
|
+
contents: read
|
|
21
|
+
|
|
22
|
+
jobs:
|
|
23
|
+
# ── Job 1: build wheel + sdist ─────────────────────────────────────────────
|
|
24
|
+
build:
|
|
25
|
+
name: Build distribution
|
|
26
|
+
runs-on: ubuntu-latest
|
|
27
|
+
steps:
|
|
28
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
29
|
+
|
|
30
|
+
- name: Install uv
|
|
31
|
+
uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
|
|
32
|
+
with:
|
|
33
|
+
enable-cache: true
|
|
34
|
+
|
|
35
|
+
- name: Set up Python
|
|
36
|
+
run: uv python install 3.13
|
|
37
|
+
|
|
38
|
+
- name: Verify tag matches package version
|
|
39
|
+
run: |
|
|
40
|
+
TAG="${GITHUB_REF_NAME}"
|
|
41
|
+
PKG_VERSION="v$(uv run python -c "import importlib.metadata; print(importlib.metadata.version('openwealth-mcp'))")"
|
|
42
|
+
echo "Tag: $TAG Package version: $PKG_VERSION"
|
|
43
|
+
if [ "$TAG" != "$PKG_VERSION" ]; then
|
|
44
|
+
echo "ERROR: tag $TAG does not match package version $PKG_VERSION"
|
|
45
|
+
exit 1
|
|
46
|
+
fi
|
|
47
|
+
|
|
48
|
+
- name: Build wheel and sdist
|
|
49
|
+
run: uv build
|
|
50
|
+
|
|
51
|
+
- name: Check distributions
|
|
52
|
+
run: uv run --with twine twine check dist/*
|
|
53
|
+
|
|
54
|
+
- name: Upload distributions as artifact
|
|
55
|
+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
56
|
+
with:
|
|
57
|
+
name: dist
|
|
58
|
+
path: dist/
|
|
59
|
+
|
|
60
|
+
# ── Job 2: publish to TestPyPI ─────────────────────────────────────────────
|
|
61
|
+
publish-testpypi:
|
|
62
|
+
name: Publish to TestPyPI
|
|
63
|
+
needs: build
|
|
64
|
+
runs-on: ubuntu-latest
|
|
65
|
+
environment: testpypi
|
|
66
|
+
permissions:
|
|
67
|
+
id-token: write
|
|
68
|
+
steps:
|
|
69
|
+
- name: Download distributions
|
|
70
|
+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
71
|
+
with:
|
|
72
|
+
name: dist
|
|
73
|
+
path: dist/
|
|
74
|
+
|
|
75
|
+
- name: Publish to TestPyPI
|
|
76
|
+
uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2
|
|
77
|
+
with:
|
|
78
|
+
repository-url: https://test.pypi.org/legacy/
|
|
79
|
+
|
|
80
|
+
# ── Job 3: publish to PyPI ──────────────────────────────────────────────────
|
|
81
|
+
publish-pypi:
|
|
82
|
+
name: Publish to PyPI
|
|
83
|
+
needs: publish-testpypi
|
|
84
|
+
runs-on: ubuntu-latest
|
|
85
|
+
environment: pypi
|
|
86
|
+
permissions:
|
|
87
|
+
id-token: write
|
|
88
|
+
steps:
|
|
89
|
+
- name: Download distributions
|
|
90
|
+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
91
|
+
with:
|
|
92
|
+
name: dist
|
|
93
|
+
path: dist/
|
|
94
|
+
|
|
95
|
+
- name: Publish to PyPI
|
|
96
|
+
uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
name: Create Release PR
|
|
2
|
+
|
|
3
|
+
# Bumps the version, updates CHANGELOG.md, and opens a PR against main.
|
|
4
|
+
# No tag is created here — the tag is created automatically by tag-release.yml
|
|
5
|
+
# once this PR is merged into main.
|
|
6
|
+
#
|
|
7
|
+
# Usage:
|
|
8
|
+
# GitHub UI: Actions → "Create Release PR" → Run workflow → choose bump / version
|
|
9
|
+
# CLI: gh workflow run release.yml --field bump=minor
|
|
10
|
+
# gh workflow run release.yml --field version=1.0.0
|
|
11
|
+
on:
|
|
12
|
+
workflow_dispatch:
|
|
13
|
+
inputs:
|
|
14
|
+
bump:
|
|
15
|
+
description: "Version bump type (ignored when 'version' is set)"
|
|
16
|
+
required: false
|
|
17
|
+
default: patch
|
|
18
|
+
type: choice
|
|
19
|
+
options: [patch, minor, major]
|
|
20
|
+
version:
|
|
21
|
+
description: "Exact version to release, e.g. 1.0.0 (overrides 'bump')"
|
|
22
|
+
required: false
|
|
23
|
+
type: string
|
|
24
|
+
|
|
25
|
+
permissions:
|
|
26
|
+
contents: read
|
|
27
|
+
|
|
28
|
+
jobs:
|
|
29
|
+
bump-pr:
|
|
30
|
+
name: Bump version & open PR
|
|
31
|
+
runs-on: ubuntu-latest
|
|
32
|
+
permissions:
|
|
33
|
+
contents: write
|
|
34
|
+
pull-requests: write
|
|
35
|
+
steps:
|
|
36
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
37
|
+
with:
|
|
38
|
+
fetch-depth: 0
|
|
39
|
+
token: ${{ secrets.GITHUB_TOKEN }}
|
|
40
|
+
|
|
41
|
+
- name: Install uv
|
|
42
|
+
uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
|
|
43
|
+
with:
|
|
44
|
+
enable-cache: true
|
|
45
|
+
|
|
46
|
+
- name: Set up Python
|
|
47
|
+
run: uv python install 3.13
|
|
48
|
+
|
|
49
|
+
- name: Install package to read current version
|
|
50
|
+
run: uv sync --frozen
|
|
51
|
+
|
|
52
|
+
- name: Compute new version
|
|
53
|
+
id: bump
|
|
54
|
+
run: |
|
|
55
|
+
# Read current version and strip pre-release suffixes (e.g. "0.3.0b1" → "0.3.0")
|
|
56
|
+
CURRENT=$(uv run python -c "import importlib.metadata; print(importlib.metadata.version('openwealth-mcp'))")
|
|
57
|
+
BASE=$(echo "$CURRENT" | grep -oP '^\d+\.\d+\.\d+')
|
|
58
|
+
MAJOR=$(echo "$BASE" | cut -d. -f1)
|
|
59
|
+
MINOR=$(echo "$BASE" | cut -d. -f2)
|
|
60
|
+
PATCH=$(echo "$BASE" | cut -d. -f3)
|
|
61
|
+
|
|
62
|
+
EXPLICIT="${{ inputs.version }}"
|
|
63
|
+
BUMP_TYPE="${{ inputs.bump }}"
|
|
64
|
+
|
|
65
|
+
if [ -n "$EXPLICIT" ]; then
|
|
66
|
+
NEW_VER="$EXPLICIT"
|
|
67
|
+
elif [ "$BUMP_TYPE" = "major" ]; then
|
|
68
|
+
NEW_VER="$((MAJOR+1)).0.0"
|
|
69
|
+
elif [ "$BUMP_TYPE" = "minor" ]; then
|
|
70
|
+
NEW_VER="${MAJOR}.$((MINOR+1)).0"
|
|
71
|
+
else
|
|
72
|
+
NEW_VER="${MAJOR}.${MINOR}.$((PATCH+1))"
|
|
73
|
+
fi
|
|
74
|
+
|
|
75
|
+
echo "Bumping ${CURRENT} → ${NEW_VER}"
|
|
76
|
+
echo "new_version=${NEW_VER}" >> "$GITHUB_OUTPUT"
|
|
77
|
+
|
|
78
|
+
- name: Create release branch and bump files
|
|
79
|
+
id: branch
|
|
80
|
+
run: |
|
|
81
|
+
NEW_VER="${{ steps.bump.outputs.new_version }}"
|
|
82
|
+
BRANCH="release/v${NEW_VER}"
|
|
83
|
+
echo "name=${BRANCH}" >> "$GITHUB_OUTPUT"
|
|
84
|
+
|
|
85
|
+
git config user.name "github-actions[bot]"
|
|
86
|
+
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
87
|
+
git checkout -b "$BRANCH"
|
|
88
|
+
|
|
89
|
+
# Bump __version__ (single source of truth)
|
|
90
|
+
sed -i "s/__version__ = \".*\"/__version__ = \"${NEW_VER}\"/" \
|
|
91
|
+
src/openwealth_mcp/__init__.py
|
|
92
|
+
|
|
93
|
+
# Promote [Unreleased] → [x.y.z] in CHANGELOG
|
|
94
|
+
TODAY=$(date +%Y-%m-%d)
|
|
95
|
+
sed -i "s/## \[Unreleased\]/## [${NEW_VER}] — ${TODAY}/" CHANGELOG.md
|
|
96
|
+
|
|
97
|
+
# Insert a fresh [Unreleased] section above the new release header
|
|
98
|
+
LINE=$(grep -n "## \[${NEW_VER}\]" CHANGELOG.md | cut -d: -f1)
|
|
99
|
+
sed -i "${LINE}i ## [Unreleased]\n\n---\n" CHANGELOG.md
|
|
100
|
+
|
|
101
|
+
# Update [Unreleased] diff link at the bottom
|
|
102
|
+
PREV_TAG=$(git describe --tags --abbrev=0 HEAD 2>/dev/null || echo "")
|
|
103
|
+
REPO_URL=$(git remote get-url origin | sed 's/\.git$//')
|
|
104
|
+
if [ -n "$PREV_TAG" ] && grep -q "^\[Unreleased\]:" CHANGELOG.md; then
|
|
105
|
+
sed -i "s|^\[Unreleased\]:.*|\[Unreleased\]: ${REPO_URL}/compare/v${NEW_VER}...HEAD|" CHANGELOG.md
|
|
106
|
+
sed -i "/^\[Unreleased\]:/a [${NEW_VER}]: ${REPO_URL}/compare/${PREV_TAG}...v${NEW_VER}" CHANGELOG.md
|
|
107
|
+
fi
|
|
108
|
+
|
|
109
|
+
git add src/openwealth_mcp/__init__.py CHANGELOG.md
|
|
110
|
+
git commit -m "chore: release v${NEW_VER}"
|
|
111
|
+
|
|
112
|
+
git push origin "$BRANCH"
|
|
113
|
+
|
|
114
|
+
- name: Open PR against main
|
|
115
|
+
env:
|
|
116
|
+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
117
|
+
run: |
|
|
118
|
+
NEW_VER="${{ steps.bump.outputs.new_version }}"
|
|
119
|
+
BRANCH="${{ steps.branch.outputs.name }}"
|
|
120
|
+
|
|
121
|
+
PR_URL=$(gh pr create \
|
|
122
|
+
--title "chore: release v${NEW_VER}" \
|
|
123
|
+
--body "## Release v${NEW_VER}
|
|
124
|
+
|
|
125
|
+
Automated version bump — review the diff, then **merge to trigger the publish pipeline**.
|
|
126
|
+
|
|
127
|
+
### What happens after merge
|
|
128
|
+
1. \`tag-release.yml\` detects the \`chore: release v${NEW_VER}\` commit on \`main\`
|
|
129
|
+
2. Creates and pushes tag \`v${NEW_VER}\` pointing to the merge commit
|
|
130
|
+
3. \`publish.yml\` fires on the tag → builds wheel/sdist → publishes to TestPyPI then PyPI
|
|
131
|
+
|
|
132
|
+
### Changes
|
|
133
|
+
- \`src/openwealth_mcp/__init__.py\` — version bumped to \`${NEW_VER}\`
|
|
134
|
+
- \`CHANGELOG.md\` — \`[Unreleased]\` promoted to \`[${NEW_VER}]\`" \
|
|
135
|
+
--base main \
|
|
136
|
+
--head "$BRANCH")
|
|
137
|
+
|
|
138
|
+
echo "PR opened: $PR_URL"
|
|
139
|
+
|
|
140
|
+
# Enable auto-merge so the PR merges automatically once required checks pass.
|
|
141
|
+
# If branch protection requires human review, the PR stays open for manual merge.
|
|
142
|
+
gh pr merge "$PR_URL" --squash --auto || \
|
|
143
|
+
echo "::notice::Auto-merge not available (branch protection requires review). Merge the PR manually."
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
name: Tag Release
|
|
2
|
+
|
|
3
|
+
# Fires on every push to main. When the HEAD commit message starts with
|
|
4
|
+
# "chore: release v", extracts the version and creates the matching tag.
|
|
5
|
+
#
|
|
6
|
+
# This is the bridge between the release PR merge and the publish pipeline:
|
|
7
|
+
#
|
|
8
|
+
# release.yml → PR "chore: release vX.Y.Z" → merge to main
|
|
9
|
+
# │
|
|
10
|
+
# [this workflow]
|
|
11
|
+
# creates tag vX.Y.Z
|
|
12
|
+
# │
|
|
13
|
+
# publish.yml fires
|
|
14
|
+
on:
|
|
15
|
+
push:
|
|
16
|
+
branches: [main]
|
|
17
|
+
|
|
18
|
+
permissions:
|
|
19
|
+
contents: read
|
|
20
|
+
|
|
21
|
+
jobs:
|
|
22
|
+
tag:
|
|
23
|
+
name: Create release tag
|
|
24
|
+
# Only run when the commit is a release bump (chore: release vX.Y.Z)
|
|
25
|
+
if: "startsWith(github.event.head_commit.message, 'chore: release v')"
|
|
26
|
+
runs-on: ubuntu-latest
|
|
27
|
+
permissions:
|
|
28
|
+
contents: write # push tag
|
|
29
|
+
actions: write # gh workflow run (dispatch publish.yml via REST API)
|
|
30
|
+
steps:
|
|
31
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
32
|
+
with:
|
|
33
|
+
token: ${{ secrets.GITHUB_TOKEN }}
|
|
34
|
+
|
|
35
|
+
- name: Extract version from commit message
|
|
36
|
+
id: version
|
|
37
|
+
run: |
|
|
38
|
+
MSG="${{ github.event.head_commit.message }}"
|
|
39
|
+
# Extract "vX.Y.Z" from "chore: release vX.Y.Z" (ignores PR number suffix)
|
|
40
|
+
TAG=$(echo "$MSG" | grep -oP 'v\d+\.\d+\.\d+' | head -1)
|
|
41
|
+
if [ -z "$TAG" ]; then
|
|
42
|
+
echo "ERROR: could not parse version from commit message: $MSG"
|
|
43
|
+
exit 1
|
|
44
|
+
fi
|
|
45
|
+
echo "tag=${TAG}" >> "$GITHUB_OUTPUT"
|
|
46
|
+
echo "Detected release tag: ${TAG}"
|
|
47
|
+
|
|
48
|
+
- name: Check tag does not already exist
|
|
49
|
+
run: |
|
|
50
|
+
TAG="${{ steps.version.outputs.tag }}"
|
|
51
|
+
if git ls-remote --tags origin "$TAG" | grep -q "$TAG"; then
|
|
52
|
+
echo "::warning::Tag ${TAG} already exists — skipping."
|
|
53
|
+
exit 0
|
|
54
|
+
fi
|
|
55
|
+
|
|
56
|
+
- name: Create and push tag
|
|
57
|
+
env:
|
|
58
|
+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
59
|
+
run: |
|
|
60
|
+
TAG="${{ steps.version.outputs.tag }}"
|
|
61
|
+
git config user.name "github-actions[bot]"
|
|
62
|
+
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
63
|
+
git tag "$TAG"
|
|
64
|
+
git push origin "$TAG"
|
|
65
|
+
echo "::notice::Tag ${TAG} pushed."
|
|
66
|
+
|
|
67
|
+
- name: Trigger publish workflow
|
|
68
|
+
# GITHUB_TOKEN cannot trigger push-based workflow runs (security restriction).
|
|
69
|
+
# Using `gh workflow run` (REST API call) bypasses this: API-triggered
|
|
70
|
+
# workflow_dispatch events always fire regardless of who created them.
|
|
71
|
+
env:
|
|
72
|
+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
73
|
+
run: |
|
|
74
|
+
TAG="${{ steps.version.outputs.tag }}"
|
|
75
|
+
gh workflow run publish.yml --ref "$TAG"
|
|
76
|
+
echo "::notice::publish.yml triggered for ${TAG}."
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
repos:
|
|
2
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
3
|
+
rev: v0.9.10
|
|
4
|
+
hooks:
|
|
5
|
+
- id: ruff
|
|
6
|
+
args: [--fix]
|
|
7
|
+
- id: ruff-format
|
|
8
|
+
|
|
9
|
+
- repo: https://github.com/pre-commit/mirrors-mypy
|
|
10
|
+
rev: v1.15.0
|
|
11
|
+
hooks:
|
|
12
|
+
- id: mypy
|
|
13
|
+
additional_dependencies:
|
|
14
|
+
- pydantic>=2
|
|
15
|
+
- pydantic-settings>=2
|
|
16
|
+
- httpx>=0.27
|
|
17
|
+
- types-PyYAML>=6
|
|
18
|
+
args: [--config-file=pyproject.toml]
|
|
19
|
+
pass_filenames: false
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented here.
|
|
4
|
+
|
|
5
|
+
Format: [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
6
|
+
Versioning: [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## [Unreleased]
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## [0.3.5] — 2026-09-04
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## [0.3.4] — 2026-09-04
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## [0.3.3] — 2026-09-03
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## [0.3.2] — 2026-09-03
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## [0.3.1] — 2026-09-03
|
|
31
|
+
|
|
32
|
+
### Added
|
|
33
|
+
|
|
34
|
+
- **`openwealth-customer-mcp`** — new MCP server for the OpenWealth Customer
|
|
35
|
+
Management API v2.0.6 with **26 tools** covering the full customer onboarding
|
|
36
|
+
and lifecycle: customers, persons, contacts, addresses, documents, KYC, and
|
|
37
|
+
prospect pre-checks (GET + POST + PUT + DELETE).
|
|
38
|
+
- **`OPENWEALTH_CUSTOMER_MANAGEMENT_BASE_URL`** — new env variable for the
|
|
39
|
+
Customer Management server base URL.
|
|
40
|
+
- **`specs/customerAPI.yaml`** — vendored OpenAPI YAML for Customer Management
|
|
41
|
+
v2.0.6, served as `openwealth://specs/customer` and
|
|
42
|
+
`openwealth://specs/customer.yaml` MCP resources.
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## [0.3.0] — 2026-09-02
|
|
47
|
+
|
|
48
|
+
### Added
|
|
49
|
+
|
|
50
|
+
- **`OPENWEALTH_CUSTODY_BASE_URL`** and **`OPENWEALTH_TRADING_BASE_URL`** — each
|
|
51
|
+
MCP server now has its own base URL variable. A single `.env` file can hold
|
|
52
|
+
both. The URL for each server is resolved at startup via
|
|
53
|
+
`Settings.base_url_for(service)`, printing a clear error and exiting with
|
|
54
|
+
code 1 if the required variable is unset.
|
|
55
|
+
|
|
56
|
+
### Changed
|
|
57
|
+
|
|
58
|
+
- **BREAKING: `OPENWEALTH_BASE_URL` removed.** Replace it with
|
|
59
|
+
`OPENWEALTH_CUSTODY_BASE_URL` (for the Custody server) and/or
|
|
60
|
+
`OPENWEALTH_TRADING_BASE_URL` (for the Trading server) in your `.env` file
|
|
61
|
+
and MCP client configuration (`claude_desktop_config.json`, `.cursor/mcp.json`).
|
|
62
|
+
- `OpenWealthHttpClient` now requires an explicit `base_url` keyword argument
|
|
63
|
+
(previously read from `settings.base_url`).
|
|
64
|
+
|
|
65
|
+
### Removed
|
|
66
|
+
|
|
67
|
+
- **LLM wiki layer** (`wiki/`, `raw/`, `AGENTS.md`, `.cursor/rules/llm-wiki.mdc`)
|
|
68
|
+
replaced by three plain Markdown pages under `docs/` (`mcp-clients.md`,
|
|
69
|
+
`local-dev.md`, `release.md`). The wiki was an agent-maintained knowledge base
|
|
70
|
+
that added 30 files to the repo with no value for package consumers.
|
|
71
|
+
- **Stale Docker runbook** (`wiki/runbooks/docker-cursor-mcp.md`) which documented
|
|
72
|
+
a `Dockerfile` removed in v0.2.0 and the old package name `openwealth_ai_mcp`.
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## [0.2.0] — 2026-09-02
|
|
77
|
+
|
|
78
|
+
### Added
|
|
79
|
+
|
|
80
|
+
- **Trading MCP server** (`openwealth-trading-mcp`) with 18 tools covering the
|
|
81
|
+
full Order Placement API v3.0.1 lifecycle: customers, accounts, orders,
|
|
82
|
+
executions, states, quotes, and event subscriptions.
|
|
83
|
+
- **`--check` flag** on both server entry points: validates settings and prints
|
|
84
|
+
a one-line status without starting the stdio loop. Useful for deployment
|
|
85
|
+
smoke tests.
|
|
86
|
+
- **`Retry-After` header support** in the HTTP client with ±20% jitter, so
|
|
87
|
+
retries respect server-side rate-limit signals instead of always using
|
|
88
|
+
exponential backoff.
|
|
89
|
+
- **Symmetric input validation** for Trading tools: `validate_id` on list-orders
|
|
90
|
+
filter params, `validate_date` on `settlement_date` in `create_order`, and
|
|
91
|
+
presence checks on every `allocations` entry.
|
|
92
|
+
- **`py.typed` marker** — the package now ships inline type information for
|
|
93
|
+
downstream `mypy --strict` users.
|
|
94
|
+
- **`test_settings_docs_sync`** — asserts that the README config table and
|
|
95
|
+
`Settings` field list are identical, so documentation can no longer silently
|
|
96
|
+
diverge from code.
|
|
97
|
+
- **`test_spec_contract`** — parametrised contract test that verifies every
|
|
98
|
+
`operationId` and path used by `CustodyService` and `TradingService` against
|
|
99
|
+
the vendored OpenAPI specs.
|
|
100
|
+
- **`test_entrypoints`** — smoke tests for `main()` and `--check` on both
|
|
101
|
+
servers, with `server.run` monkeypatched.
|
|
102
|
+
- **CI matrix** across Python 3.11, 3.12, and 3.13 (previously 3.13 only).
|
|
103
|
+
- **`pip-audit` job** in CI for supply-chain scanning.
|
|
104
|
+
- **Dependabot** configuration for pip and GitHub Actions weekly updates.
|
|
105
|
+
- **GitHub Actions pinned by commit SHA** to harden the supply chain.
|
|
106
|
+
- `CONTRIBUTING.md` and `CODE_OF_CONDUCT.md` links.
|
|
107
|
+
|
|
108
|
+
### Changed
|
|
109
|
+
|
|
110
|
+
- **Package renamed** from `openwealth-ai-mcp` / `openwealth_ai_mcp` to
|
|
111
|
+
`openwealth-mcp` / `openwealth_mcp`. This is a **breaking change** for any
|
|
112
|
+
existing import. Console scripts (`openwealth-custody-mcp`,
|
|
113
|
+
`openwealth-trading-mcp`) are unchanged.
|
|
114
|
+
- **Single version source**: `__version__` in `src/openwealth_mcp/__init__.py`
|
|
115
|
+
is the only declaration; `pyproject.toml` reads it dynamically via Hatch.
|
|
116
|
+
Bumping one file bumps both.
|
|
117
|
+
- **License metadata** updated to PEP 639 form (`license = "Apache-2.0"`).
|
|
118
|
+
- **Package metadata** enriched with `authors`, `keywords`, `classifiers`
|
|
119
|
+
(Python 3.11/3.12/3.13, Development Status :: 4 - Beta, Typing :: Typed),
|
|
120
|
+
and `[project.urls]` (Homepage, Repository, Issues, Changelog).
|
|
121
|
+
- **`publish.yml`** tag trigger re-enabled (`push: tags: v*`); version check
|
|
122
|
+
made conditional on tag context so manual dispatch no longer fails.
|
|
123
|
+
- **Coverage gate** raised from 80% to 84% to match the achieved baseline.
|
|
124
|
+
- **`OPENWEALTH_LOG_FILE` description** in README no longer says "Recommended
|
|
125
|
+
with Docker" (Docker support removed).
|
|
126
|
+
|
|
127
|
+
### Removed
|
|
128
|
+
|
|
129
|
+
- **Docker support** (`Dockerfile`, `docker-compose.yml`, `.dockerignore`).
|
|
130
|
+
The servers are distributed as a pip-installable library; Docker was an
|
|
131
|
+
optional deployment target that added maintenance cost without proportional
|
|
132
|
+
value for the current user base.
|
|
133
|
+
- **`openwealth-mcp` console script alias** (was a duplicate of
|
|
134
|
+
`openwealth-custody-mcp` and ambiguous with two servers present).
|
|
135
|
+
- **`IMPROVEMENT-PLAN.md`** from the repository root (absorbed into
|
|
136
|
+
`CHANGELOG.md` and GitHub issues).
|
|
137
|
+
- **Junk files** (`.coverage`, `_customers_dump.json`, `.tmp_*.py`, `logs/`)
|
|
138
|
+
from the working tree; `.gitattributes` added to enforce LF line endings.
|
|
139
|
+
|
|
140
|
+
### Fixed
|
|
141
|
+
|
|
142
|
+
- **`mypy` strict failures** in `tools/trading.py`: `invoke_tool` now takes
|
|
143
|
+
`Awaitable[str]` instead of `Any`, matching the custody implementation.
|
|
144
|
+
- **README config table** was documenting eight env vars that no longer exist
|
|
145
|
+
in `Settings` (`OPENWEALTH_ENV`, `OPENWEALTH_TRANSPORT`, etc.) and had the
|
|
146
|
+
wrong default for `OPENWEALTH_TIMEOUT_SECONDS` (30 vs 120 in code).
|
|
147
|
+
- **Unused dead code** removed: `TypeVar("_T")` in `tools/custody.py`,
|
|
148
|
+
`peek_client()` in both `app.py` files.
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
## [0.1.0] — 2026-08-10
|
|
153
|
+
|
|
154
|
+
Initial release of the Custody MCP server.
|
|
155
|
+
|
|
156
|
+
- 10 read-only GET tools covering Custody Services API v3.2.0.
|
|
157
|
+
- FastMCP over stdio with clean `tools → service → HTTP client` layering.
|
|
158
|
+
- Pydantic-validated settings; structured JSON error envelopes.
|
|
159
|
+
- Vendored OpenAPI spec served as MCP resource.
|
|
160
|
+
|
|
161
|
+
[Unreleased]: https://github.com/OpenWealth/OpenWealth-MCP/compare/v0.3.5...HEAD
|
|
162
|
+
[0.3.5]: https://github.com/OpenWealth/OpenWealth-MCP/compare/v0.3.3...v0.3.5
|
|
163
|
+
[0.3.4]: https://github.com/OpenWealth/OpenWealth-MCP/compare/v0.3.3...v0.3.4
|
|
164
|
+
[0.3.3]: https://github.com/OpenWealth/OpenWealth-MCP/compare/v0.3.2...v0.3.3
|
|
165
|
+
[0.3.0]: https://github.com/synpulse-openwealth/openwealth-mcp/compare/v0.2.0...v0.3.0
|
|
166
|
+
[0.2.0]: https://github.com/synpulse-openwealth/openwealth-mcp/compare/v0.1.0...v0.2.0
|
|
167
|
+
[0.1.0]: https://github.com/synpulse-openwealth/openwealth-mcp/releases/tag/v0.1.0
|