pocketsmith-mcp 1.0.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.
- pocketsmith_mcp-1.0.0/.env.example +18 -0
- pocketsmith_mcp-1.0.0/.gitignore +178 -0
- pocketsmith_mcp-1.0.0/LICENSE +21 -0
- pocketsmith_mcp-1.0.0/PKG-INFO +365 -0
- pocketsmith_mcp-1.0.0/README.md +334 -0
- pocketsmith_mcp-1.0.0/logs/.gitkeep +1 -0
- pocketsmith_mcp-1.0.0/pyproject.toml +84 -0
- pocketsmith_mcp-1.0.0/src/pocketsmith_mcp/__init__.py +8 -0
- pocketsmith_mcp-1.0.0/src/pocketsmith_mcp/__main__.py +19 -0
- pocketsmith_mcp-1.0.0/src/pocketsmith_mcp/client/__init__.py +14 -0
- pocketsmith_mcp-1.0.0/src/pocketsmith_mcp/client/api_client.py +269 -0
- pocketsmith_mcp-1.0.0/src/pocketsmith_mcp/client/circuit_breaker.py +179 -0
- pocketsmith_mcp-1.0.0/src/pocketsmith_mcp/client/rate_limiter.py +106 -0
- pocketsmith_mcp-1.0.0/src/pocketsmith_mcp/client/retry.py +106 -0
- pocketsmith_mcp-1.0.0/src/pocketsmith_mcp/config.py +110 -0
- pocketsmith_mcp-1.0.0/src/pocketsmith_mcp/errors.py +87 -0
- pocketsmith_mcp-1.0.0/src/pocketsmith_mcp/logger.py +69 -0
- pocketsmith_mcp-1.0.0/src/pocketsmith_mcp/models/__init__.py +24 -0
- pocketsmith_mcp-1.0.0/src/pocketsmith_mcp/models/account.py +177 -0
- pocketsmith_mcp-1.0.0/src/pocketsmith_mcp/models/attachment.py +81 -0
- pocketsmith_mcp-1.0.0/src/pocketsmith_mcp/models/category.py +90 -0
- pocketsmith_mcp-1.0.0/src/pocketsmith_mcp/models/common.py +65 -0
- pocketsmith_mcp-1.0.0/src/pocketsmith_mcp/models/event.py +81 -0
- pocketsmith_mcp-1.0.0/src/pocketsmith_mcp/models/institution.py +31 -0
- pocketsmith_mcp-1.0.0/src/pocketsmith_mcp/models/transaction.py +94 -0
- pocketsmith_mcp-1.0.0/src/pocketsmith_mcp/models/user.py +73 -0
- pocketsmith_mcp-1.0.0/src/pocketsmith_mcp/server.py +69 -0
- pocketsmith_mcp-1.0.0/src/pocketsmith_mcp/tools/__init__.py +40 -0
- pocketsmith_mcp-1.0.0/src/pocketsmith_mcp/tools/accounts.py +122 -0
- pocketsmith_mcp-1.0.0/src/pocketsmith_mcp/tools/attachments.py +149 -0
- pocketsmith_mcp-1.0.0/src/pocketsmith_mcp/tools/budgeting.py +169 -0
- pocketsmith_mcp-1.0.0/src/pocketsmith_mcp/tools/categories.py +183 -0
- pocketsmith_mcp-1.0.0/src/pocketsmith_mcp/tools/events.py +195 -0
- pocketsmith_mcp-1.0.0/src/pocketsmith_mcp/tools/institutions.py +143 -0
- pocketsmith_mcp-1.0.0/src/pocketsmith_mcp/tools/labels.py +56 -0
- pocketsmith_mcp-1.0.0/src/pocketsmith_mcp/tools/transaction_accounts.py +117 -0
- pocketsmith_mcp-1.0.0/src/pocketsmith_mcp/tools/transactions.py +241 -0
- pocketsmith_mcp-1.0.0/src/pocketsmith_mcp/tools/users.py +101 -0
- pocketsmith_mcp-1.0.0/src/pocketsmith_mcp/tools/utilities.py +52 -0
- pocketsmith_mcp-1.0.0/tests/__init__.py +1 -0
- pocketsmith_mcp-1.0.0/tests/conftest.py +207 -0
- pocketsmith_mcp-1.0.0/tests/integration/__init__.py +1 -0
- pocketsmith_mcp-1.0.0/tests/integration/test_server.py +181 -0
- pocketsmith_mcp-1.0.0/tests/integration/test_tools.py +126 -0
- pocketsmith_mcp-1.0.0/tests/unit/__init__.py +1 -0
- pocketsmith_mcp-1.0.0/tests/unit/test_api_client.py +225 -0
- pocketsmith_mcp-1.0.0/tests/unit/test_circuit_breaker.py +171 -0
- pocketsmith_mcp-1.0.0/tests/unit/test_rate_limiter.py +135 -0
- pocketsmith_mcp-1.0.0/tests/unit/test_retry.py +148 -0
- pocketsmith_mcp-1.0.0/tests/unit/tools/__init__.py +1 -0
- pocketsmith_mcp-1.0.0/tests/unit/tools/test_accounts.py +123 -0
- pocketsmith_mcp-1.0.0/tests/unit/tools/test_attachments.py +161 -0
- pocketsmith_mcp-1.0.0/tests/unit/tools/test_budgeting.py +135 -0
- pocketsmith_mcp-1.0.0/tests/unit/tools/test_categories.py +161 -0
- pocketsmith_mcp-1.0.0/tests/unit/tools/test_events.py +190 -0
- pocketsmith_mcp-1.0.0/tests/unit/tools/test_institutions.py +145 -0
- pocketsmith_mcp-1.0.0/tests/unit/tools/test_labels.py +111 -0
- pocketsmith_mcp-1.0.0/tests/unit/tools/test_transaction_accounts.py +144 -0
- pocketsmith_mcp-1.0.0/tests/unit/tools/test_transactions.py +252 -0
- pocketsmith_mcp-1.0.0/tests/unit/tools/test_users.py +169 -0
- pocketsmith_mcp-1.0.0/tests/unit/tools/test_utilities.py +102 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# PocketSmith MCP Server Configuration
|
|
2
|
+
# Copy this file to .env and fill in your API key
|
|
3
|
+
|
|
4
|
+
# Required: Your PocketSmith API key
|
|
5
|
+
# Get your API key from: https://my.pocketsmith.com/settings/security
|
|
6
|
+
POCKETSMITH_API_KEY=your_api_key_here
|
|
7
|
+
|
|
8
|
+
# Optional: Debug mode (set to true for verbose logging)
|
|
9
|
+
DEBUG=false
|
|
10
|
+
|
|
11
|
+
# Optional: API timeout in seconds (default: 30)
|
|
12
|
+
API_TIMEOUT=30
|
|
13
|
+
|
|
14
|
+
# Optional: Maximum retry attempts (default: 3)
|
|
15
|
+
MAX_RETRIES=3
|
|
16
|
+
|
|
17
|
+
# Optional: Rate limit per minute (default: 60)
|
|
18
|
+
RATE_LIMIT_PER_MINUTE=60
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.so
|
|
8
|
+
|
|
9
|
+
# Distribution / packaging
|
|
10
|
+
.Python
|
|
11
|
+
build/
|
|
12
|
+
develop-eggs/
|
|
13
|
+
dist/
|
|
14
|
+
downloads/
|
|
15
|
+
eggs/
|
|
16
|
+
.eggs/
|
|
17
|
+
lib/
|
|
18
|
+
lib64/
|
|
19
|
+
parts/
|
|
20
|
+
sdist/
|
|
21
|
+
var/
|
|
22
|
+
wheels/
|
|
23
|
+
share/python-wheels/
|
|
24
|
+
*.egg-info/
|
|
25
|
+
.installed.cfg
|
|
26
|
+
*.egg
|
|
27
|
+
MANIFEST
|
|
28
|
+
|
|
29
|
+
# PyInstaller
|
|
30
|
+
*.manifest
|
|
31
|
+
*.spec
|
|
32
|
+
|
|
33
|
+
# Installer logs
|
|
34
|
+
pip-log.txt
|
|
35
|
+
pip-delete-this-directory.txt
|
|
36
|
+
|
|
37
|
+
# Unit test / coverage reports
|
|
38
|
+
htmlcov/
|
|
39
|
+
.tox/
|
|
40
|
+
.nox/
|
|
41
|
+
.coverage
|
|
42
|
+
.coverage.*
|
|
43
|
+
.cache
|
|
44
|
+
nosetests.xml
|
|
45
|
+
coverage.xml
|
|
46
|
+
*.cover
|
|
47
|
+
*.py,cover
|
|
48
|
+
.hypothesis/
|
|
49
|
+
.pytest_cache/
|
|
50
|
+
cover/
|
|
51
|
+
|
|
52
|
+
# Translations
|
|
53
|
+
*.mo
|
|
54
|
+
*.pot
|
|
55
|
+
|
|
56
|
+
# Django stuff:
|
|
57
|
+
*.log
|
|
58
|
+
local_settings.py
|
|
59
|
+
db.sqlite3
|
|
60
|
+
db.sqlite3-journal
|
|
61
|
+
|
|
62
|
+
# Flask stuff:
|
|
63
|
+
instance/
|
|
64
|
+
.webassets-cache
|
|
65
|
+
|
|
66
|
+
# Scrapy stuff:
|
|
67
|
+
.scrapy
|
|
68
|
+
|
|
69
|
+
# Sphinx documentation
|
|
70
|
+
docs/_build/
|
|
71
|
+
|
|
72
|
+
# PyBuilder
|
|
73
|
+
.pybuilder/
|
|
74
|
+
target/
|
|
75
|
+
|
|
76
|
+
# Jupyter Notebook
|
|
77
|
+
.ipynb_checkpoints
|
|
78
|
+
|
|
79
|
+
# IPython
|
|
80
|
+
profile_default/
|
|
81
|
+
ipython_config.py
|
|
82
|
+
|
|
83
|
+
# pyenv
|
|
84
|
+
.python-version
|
|
85
|
+
|
|
86
|
+
# pipenv
|
|
87
|
+
Pipfile.lock
|
|
88
|
+
|
|
89
|
+
# UV
|
|
90
|
+
uv.lock
|
|
91
|
+
|
|
92
|
+
# PEP 582
|
|
93
|
+
__pypackages__/
|
|
94
|
+
|
|
95
|
+
# Celery stuff
|
|
96
|
+
celerybeat-schedule
|
|
97
|
+
celerybeat.pid
|
|
98
|
+
|
|
99
|
+
# SageMath parsed files
|
|
100
|
+
*.sage.py
|
|
101
|
+
|
|
102
|
+
# Environments
|
|
103
|
+
.env
|
|
104
|
+
.venv
|
|
105
|
+
env/
|
|
106
|
+
venv/
|
|
107
|
+
ENV/
|
|
108
|
+
env.bak/
|
|
109
|
+
venv.bak/
|
|
110
|
+
|
|
111
|
+
# Spyder project settings
|
|
112
|
+
.spyderproject
|
|
113
|
+
.spyproject
|
|
114
|
+
|
|
115
|
+
# Rope project settings
|
|
116
|
+
.ropeproject
|
|
117
|
+
|
|
118
|
+
# mkdocs documentation
|
|
119
|
+
/site
|
|
120
|
+
|
|
121
|
+
# mypy
|
|
122
|
+
.mypy_cache/
|
|
123
|
+
.dmypy.json
|
|
124
|
+
dmypy.json
|
|
125
|
+
|
|
126
|
+
# ruff
|
|
127
|
+
.ruff_cache/
|
|
128
|
+
|
|
129
|
+
# Pyre type checker
|
|
130
|
+
.pyre/
|
|
131
|
+
|
|
132
|
+
# pytype static type analyzer
|
|
133
|
+
.pytype/
|
|
134
|
+
|
|
135
|
+
# Cython debug symbols
|
|
136
|
+
cython_debug/
|
|
137
|
+
|
|
138
|
+
# IDE
|
|
139
|
+
.idea/
|
|
140
|
+
.vscode/
|
|
141
|
+
*.swp
|
|
142
|
+
*.swo
|
|
143
|
+
*~
|
|
144
|
+
|
|
145
|
+
# OS
|
|
146
|
+
.DS_Store
|
|
147
|
+
Thumbs.db
|
|
148
|
+
|
|
149
|
+
# Project specific
|
|
150
|
+
!logs/.gitkeep
|
|
151
|
+
|
|
152
|
+
# Secrets
|
|
153
|
+
*.pem
|
|
154
|
+
*.key
|
|
155
|
+
credentials.json
|
|
156
|
+
|
|
157
|
+
# AI Assistant Artifacts
|
|
158
|
+
.gemini/
|
|
159
|
+
.claude/
|
|
160
|
+
.cursorrules
|
|
161
|
+
.cursor/
|
|
162
|
+
.aider*
|
|
163
|
+
.continue/
|
|
164
|
+
.codeium/
|
|
165
|
+
.tabnine/
|
|
166
|
+
.copilot/
|
|
167
|
+
.ai/
|
|
168
|
+
AGENTS.md
|
|
169
|
+
CLAUDE.md
|
|
170
|
+
.mcp.json
|
|
171
|
+
|
|
172
|
+
# Logs
|
|
173
|
+
logs/
|
|
174
|
+
*.log
|
|
175
|
+
|
|
176
|
+
# Development
|
|
177
|
+
dev/
|
|
178
|
+
PRPs
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 AJ Anderson
|
|
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.
|
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pocketsmith-mcp
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Production-ready MCP server for PocketSmith personal finance API
|
|
5
|
+
Author-email: AJ Anderson <ajanderson1@gmail.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Keywords: ai,api,claude,finance,mcp,pocketsmith
|
|
9
|
+
Classifier: Development Status :: 4 - Beta
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Requires-Python: >=3.10
|
|
17
|
+
Requires-Dist: httpx>=0.27.0
|
|
18
|
+
Requires-Dist: mcp>=1.0.0
|
|
19
|
+
Requires-Dist: pydantic>=2.0.0
|
|
20
|
+
Requires-Dist: python-dotenv>=1.0.0
|
|
21
|
+
Provides-Extra: dev
|
|
22
|
+
Requires-Dist: black>=24.0.0; extra == 'dev'
|
|
23
|
+
Requires-Dist: mypy>=1.8.0; extra == 'dev'
|
|
24
|
+
Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
|
|
25
|
+
Requires-Dist: pytest-cov>=4.0.0; extra == 'dev'
|
|
26
|
+
Requires-Dist: pytest-httpx>=0.30.0; extra == 'dev'
|
|
27
|
+
Requires-Dist: pytest>=8.0.0; extra == 'dev'
|
|
28
|
+
Requires-Dist: respx>=0.21.0; extra == 'dev'
|
|
29
|
+
Requires-Dist: ruff>=0.3.0; extra == 'dev'
|
|
30
|
+
Description-Content-Type: text/markdown
|
|
31
|
+
|
|
32
|
+
<p align="center">
|
|
33
|
+
<h1 align="center">PocketSmith MCP Server</h1>
|
|
34
|
+
<p align="center">
|
|
35
|
+
<strong>A production-ready MCP server for the PocketSmith personal finance API</strong>
|
|
36
|
+
</p>
|
|
37
|
+
</p>
|
|
38
|
+
|
|
39
|
+
<p align="center">
|
|
40
|
+
<a href="https://www.python.org/downloads/"><img src="https://img.shields.io/badge/python-3.10%2B-blue.svg" alt="Python 3.10+"></a>
|
|
41
|
+
<a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/license-MIT-green.svg" alt="License: MIT"></a>
|
|
42
|
+
<a href="https://pypi.org/project/pocketsmith-mcp/"><img src="https://img.shields.io/pypi/v/pocketsmith-mcp.svg" alt="PyPI"></a>
|
|
43
|
+
<a href="https://github.com/your-repo/pocketsmith-mcp/actions"><img src="https://img.shields.io/github/actions/workflow/status/your-repo/pocketsmith-mcp/test.yml?label=tests" alt="Tests"></a>
|
|
44
|
+
<a href="https://codecov.io/gh/your-repo/pocketsmith-mcp"><img src="https://img.shields.io/codecov/c/github/your-repo/pocketsmith-mcp" alt="Coverage"></a>
|
|
45
|
+
</p>
|
|
46
|
+
|
|
47
|
+
<p align="center">
|
|
48
|
+
<a href="#features">Features</a> •
|
|
49
|
+
<a href="#quick-start">Quick Start</a> •
|
|
50
|
+
<a href="#available-tools">Tools</a> •
|
|
51
|
+
<a href="#testing">Testing</a> •
|
|
52
|
+
<a href="#development">Development</a>
|
|
53
|
+
</p>
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## Features
|
|
58
|
+
|
|
59
|
+
- **43 MCP Tools** - Complete coverage of PocketSmith API v2 endpoints
|
|
60
|
+
- **Production Ready** - Rate limiting, retry with exponential backoff, circuit breaker
|
|
61
|
+
- **Universal Compatibility** - Works with Claude Desktop, Cursor, and any MCP-compatible client
|
|
62
|
+
- **Type Safe** - Pydantic models for all API entities
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Quick Start
|
|
67
|
+
|
|
68
|
+
### Installation
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
# Run directly with uvx (recommended)
|
|
72
|
+
uvx pocketsmith-mcp
|
|
73
|
+
|
|
74
|
+
# Or install with pip
|
|
75
|
+
pip install pocketsmith-mcp
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Configuration
|
|
79
|
+
|
|
80
|
+
1. **Get your API key** from [PocketSmith Settings](https://my.pocketsmith.com/settings/api)
|
|
81
|
+
|
|
82
|
+
2. **Set your environment variable:**
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
export POCKETSMITH_API_KEY=your_api_key_here
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
3. **Run the server:**
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
uvx pocketsmith-mcp
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## Claude Desktop Integration
|
|
97
|
+
|
|
98
|
+
Add to your Claude Desktop config:
|
|
99
|
+
|
|
100
|
+
**macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
101
|
+
**Windows:** `%APPDATA%\Claude\claude_desktop_config.json`
|
|
102
|
+
|
|
103
|
+
```json
|
|
104
|
+
{
|
|
105
|
+
"mcpServers": {
|
|
106
|
+
"pocketsmith": {
|
|
107
|
+
"command": "uvx",
|
|
108
|
+
"args": ["pocketsmith-mcp"],
|
|
109
|
+
"env": {
|
|
110
|
+
"POCKETSMITH_API_KEY": "your_api_key_here"
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## Available Tools
|
|
120
|
+
|
|
121
|
+
<details>
|
|
122
|
+
<summary><strong>User Management</strong></summary>
|
|
123
|
+
|
|
124
|
+
| Tool | Description |
|
|
125
|
+
|------|-------------|
|
|
126
|
+
| `get_current_user` | Get authenticated user info |
|
|
127
|
+
| `get_user` | Get user by ID |
|
|
128
|
+
| `update_user` | Update user settings |
|
|
129
|
+
|
|
130
|
+
</details>
|
|
131
|
+
|
|
132
|
+
<details>
|
|
133
|
+
<summary><strong>Account Management</strong></summary>
|
|
134
|
+
|
|
135
|
+
| Tool | Description |
|
|
136
|
+
|------|-------------|
|
|
137
|
+
| `list_accounts` | List all accounts |
|
|
138
|
+
| `get_account` | Get account details |
|
|
139
|
+
| `update_account` | Update account |
|
|
140
|
+
| `delete_account` | Delete account |
|
|
141
|
+
|
|
142
|
+
</details>
|
|
143
|
+
|
|
144
|
+
<details>
|
|
145
|
+
<summary><strong>Transaction Accounts</strong></summary>
|
|
146
|
+
|
|
147
|
+
| Tool | Description |
|
|
148
|
+
|------|-------------|
|
|
149
|
+
| `list_transaction_accounts` | List transaction accounts |
|
|
150
|
+
| `get_transaction_account` | Get transaction account details |
|
|
151
|
+
| `update_transaction_account` | Update transaction account |
|
|
152
|
+
|
|
153
|
+
</details>
|
|
154
|
+
|
|
155
|
+
<details>
|
|
156
|
+
<summary><strong>Transactions</strong></summary>
|
|
157
|
+
|
|
158
|
+
| Tool | Description |
|
|
159
|
+
|------|-------------|
|
|
160
|
+
| `list_transactions` | List transactions with filters |
|
|
161
|
+
| `get_transaction` | Get transaction details |
|
|
162
|
+
| `create_transaction` | Create new transaction |
|
|
163
|
+
| `update_transaction` | Update transaction |
|
|
164
|
+
| `delete_transaction` | Delete transaction |
|
|
165
|
+
|
|
166
|
+
</details>
|
|
167
|
+
|
|
168
|
+
<details>
|
|
169
|
+
<summary><strong>Categories</strong></summary>
|
|
170
|
+
|
|
171
|
+
| Tool | Description |
|
|
172
|
+
|------|-------------|
|
|
173
|
+
| `list_categories` | List all categories |
|
|
174
|
+
| `get_category` | Get category details |
|
|
175
|
+
| `create_category` | Create new category |
|
|
176
|
+
| `update_category` | Update category |
|
|
177
|
+
| `delete_category` | Delete category |
|
|
178
|
+
|
|
179
|
+
</details>
|
|
180
|
+
|
|
181
|
+
<details>
|
|
182
|
+
<summary><strong>Budgeting</strong></summary>
|
|
183
|
+
|
|
184
|
+
| Tool | Description |
|
|
185
|
+
|------|-------------|
|
|
186
|
+
| `get_budget` | Get budget data |
|
|
187
|
+
| `get_budget_summary` | Get budget summary |
|
|
188
|
+
| `get_trend_analysis` | Get spending trends |
|
|
189
|
+
| `clear_forecast_cache` | Clear forecast cache |
|
|
190
|
+
|
|
191
|
+
</details>
|
|
192
|
+
|
|
193
|
+
<details>
|
|
194
|
+
<summary><strong>Institutions</strong></summary>
|
|
195
|
+
|
|
196
|
+
| Tool | Description |
|
|
197
|
+
|------|-------------|
|
|
198
|
+
| `list_institutions` | List financial institutions |
|
|
199
|
+
| `get_institution` | Get institution details |
|
|
200
|
+
| `create_institution` | Create institution |
|
|
201
|
+
| `update_institution` | Update institution |
|
|
202
|
+
| `delete_institution` | Delete institution |
|
|
203
|
+
|
|
204
|
+
</details>
|
|
205
|
+
|
|
206
|
+
<details>
|
|
207
|
+
<summary><strong>Events (Budget Calendar)</strong></summary>
|
|
208
|
+
|
|
209
|
+
| Tool | Description |
|
|
210
|
+
|------|-------------|
|
|
211
|
+
| `list_events` | List budget events |
|
|
212
|
+
| `get_event` | Get event details |
|
|
213
|
+
| `create_event` | Create budget event |
|
|
214
|
+
| `update_event` | Update event |
|
|
215
|
+
| `delete_event` | Delete event |
|
|
216
|
+
|
|
217
|
+
</details>
|
|
218
|
+
|
|
219
|
+
<details>
|
|
220
|
+
<summary><strong>Attachments</strong></summary>
|
|
221
|
+
|
|
222
|
+
| Tool | Description |
|
|
223
|
+
|------|-------------|
|
|
224
|
+
| `list_attachments` | List attachments |
|
|
225
|
+
| `get_attachment` | Get attachment details |
|
|
226
|
+
| `create_attachment` | Upload attachment |
|
|
227
|
+
| `update_attachment` | Update attachment |
|
|
228
|
+
| `delete_attachment` | Delete attachment |
|
|
229
|
+
|
|
230
|
+
</details>
|
|
231
|
+
|
|
232
|
+
<details>
|
|
233
|
+
<summary><strong>Labels & Searches</strong></summary>
|
|
234
|
+
|
|
235
|
+
| Tool | Description |
|
|
236
|
+
|------|-------------|
|
|
237
|
+
| `list_labels` | List all labels |
|
|
238
|
+
| `list_saved_searches` | List saved searches |
|
|
239
|
+
|
|
240
|
+
</details>
|
|
241
|
+
|
|
242
|
+
<details>
|
|
243
|
+
<summary><strong>Utilities</strong></summary>
|
|
244
|
+
|
|
245
|
+
| Tool | Description |
|
|
246
|
+
|------|-------------|
|
|
247
|
+
| `list_currencies` | List supported currencies |
|
|
248
|
+
| `list_time_zones` | List supported time zones |
|
|
249
|
+
|
|
250
|
+
</details>
|
|
251
|
+
|
|
252
|
+
---
|
|
253
|
+
|
|
254
|
+
## Testing
|
|
255
|
+
|
|
256
|
+
### Running Tests
|
|
257
|
+
|
|
258
|
+
```bash
|
|
259
|
+
# Run all tests
|
|
260
|
+
uv run pytest
|
|
261
|
+
|
|
262
|
+
# Run with coverage report
|
|
263
|
+
uv run pytest --cov=src/pocketsmith_mcp --cov-report=term-missing
|
|
264
|
+
|
|
265
|
+
# Run specific test file
|
|
266
|
+
uv run pytest tests/unit/tools/test_transactions.py
|
|
267
|
+
|
|
268
|
+
# Run tests by marker
|
|
269
|
+
uv run pytest -m unit # Unit tests only
|
|
270
|
+
uv run pytest -m integration # Integration tests only
|
|
271
|
+
uv run pytest -m e2e # End-to-end tests (requires API key)
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
### Test Structure
|
|
275
|
+
|
|
276
|
+
```
|
|
277
|
+
tests/
|
|
278
|
+
├── unit/ # Fast, isolated tests with mocked API
|
|
279
|
+
│ ├── test_api_client.py
|
|
280
|
+
│ ├── test_rate_limiter.py
|
|
281
|
+
│ ├── test_circuit_breaker.py
|
|
282
|
+
│ └── tools/ # Tool-specific unit tests
|
|
283
|
+
├── integration/ # Tests with mocked HTTP responses
|
|
284
|
+
│ ├── test_server.py
|
|
285
|
+
│ └── test_tools.py
|
|
286
|
+
└── conftest.py # Shared fixtures
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
### Coverage
|
|
290
|
+
|
|
291
|
+
The project maintains a **70% coverage threshold**. Coverage reports are generated automatically:
|
|
292
|
+
|
|
293
|
+
```bash
|
|
294
|
+
uv run pytest --cov=src/pocketsmith_mcp --cov-report=html
|
|
295
|
+
open htmlcov/index.html
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
---
|
|
299
|
+
|
|
300
|
+
## Development
|
|
301
|
+
|
|
302
|
+
### Setup
|
|
303
|
+
|
|
304
|
+
```bash
|
|
305
|
+
# Clone the repository
|
|
306
|
+
git clone https://github.com/your-repo/pocketsmith-mcp.git
|
|
307
|
+
cd pocketsmith-mcp
|
|
308
|
+
|
|
309
|
+
# Install dependencies (including dev)
|
|
310
|
+
uv sync --dev
|
|
311
|
+
|
|
312
|
+
# Copy environment template
|
|
313
|
+
cp .env.example .env
|
|
314
|
+
# Edit .env and add your API key
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
### Architecture
|
|
318
|
+
|
|
319
|
+
```
|
|
320
|
+
pocketsmith-mcp/
|
|
321
|
+
├── src/pocketsmith_mcp/
|
|
322
|
+
│ ├── __main__.py # Entry point
|
|
323
|
+
│ ├── server.py # FastMCP server setup
|
|
324
|
+
│ ├── config.py # Environment configuration
|
|
325
|
+
│ ├── client/ # API client with resilience patterns
|
|
326
|
+
│ │ ├── api_client.py # HTTP client wrapper
|
|
327
|
+
│ │ ├── rate_limiter.py # Token bucket algorithm
|
|
328
|
+
│ │ ├── circuit_breaker.py # Fault tolerance
|
|
329
|
+
│ │ └── retry.py # Exponential backoff
|
|
330
|
+
│ ├── models/ # Pydantic data models
|
|
331
|
+
│ └── tools/ # MCP tool implementations
|
|
332
|
+
└── tests/ # Unit and integration tests
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
### API Resilience
|
|
336
|
+
|
|
337
|
+
The client includes production-grade resilience:
|
|
338
|
+
|
|
339
|
+
- **Rate Limiting** - Token bucket algorithm (60 req/min default)
|
|
340
|
+
- **Retry Logic** - Exponential backoff with jitter for transient failures
|
|
341
|
+
- **Circuit Breaker** - Prevents cascade failures during outages
|
|
342
|
+
|
|
343
|
+
---
|
|
344
|
+
|
|
345
|
+
## Environment Variables
|
|
346
|
+
|
|
347
|
+
| Variable | Required | Default | Description |
|
|
348
|
+
|----------|----------|---------|-------------|
|
|
349
|
+
| `POCKETSMITH_API_KEY` | Yes | - | Your PocketSmith API key |
|
|
350
|
+
| `DEBUG` | No | `false` | Enable debug logging |
|
|
351
|
+
| `API_TIMEOUT` | No | `30` | Request timeout (seconds) |
|
|
352
|
+
| `MAX_RETRIES` | No | `3` | Retry attempts for failed requests |
|
|
353
|
+
| `RATE_LIMIT_PER_MINUTE` | No | `60` | API rate limit |
|
|
354
|
+
|
|
355
|
+
---
|
|
356
|
+
|
|
357
|
+
## License
|
|
358
|
+
|
|
359
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
360
|
+
|
|
361
|
+
---
|
|
362
|
+
|
|
363
|
+
<p align="center">
|
|
364
|
+
Made with Python and FastMCP
|
|
365
|
+
</p>
|