okama-mcp 0.2.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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Sergey Kikevich
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,276 @@
1
+ Metadata-Version: 2.4
2
+ Name: okama-mcp
3
+ Version: 0.2.0
4
+ Summary: MCP (Model Context Protocol) server exposing the okama investment portfolio toolkit to AI assistants
5
+ License: MIT
6
+ License-File: LICENSE
7
+ Keywords: mcp,okama,investments,portfolio,finance,llm
8
+ Author: Sergey Kikevich
9
+ Author-email: sergey@rostsber.ru
10
+ Requires-Python: >=3.11,<4.0.0
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Financial and Insurance Industry
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Programming Language :: Python :: 3.14
19
+ Classifier: Topic :: Office/Business :: Financial :: Investment
20
+ Requires-Dist: fastmcp (>=2.7)
21
+ Requires-Dist: okama (>=2.1.0)
22
+ Requires-Dist: pydantic (>=2.0)
23
+ Project-URL: Homepage, https://mcp.okama.io
24
+ Project-URL: Repository, https://github.com/mbk-dev/okama-mcp
25
+ Description-Content-Type: text/markdown
26
+
27
+ # okama-mcp
28
+
29
+ MCP (Model Context Protocol) server that exposes the [okama](https://github.com/mbk-dev/okama)
30
+ investment portfolio toolkit to AI assistants — Claude Desktop, Claude Code, Cursor, and any
31
+ other MCP-compatible client.
32
+
33
+ With okama-mcp installed, you can ask an AI things like:
34
+
35
+ > *"Backtest a portfolio of 30% gold and 70% real estate over the last 15 years."*
36
+ >
37
+ > *"Run a Monte Carlo retirement forecast on that portfolio, withdrawing $1,000/month
38
+ > indexed to inflation, over 25 years."*
39
+ >
40
+ > *"What's the tangency portfolio of SPY, BND, and GLD with a 3% risk-free rate?"*
41
+
42
+ …and the AI uses the MCP tools to call okama directly — no Python code needed.
43
+
44
+ Built on [FastMCP](https://github.com/jlowin/fastmcp). Single codebase, two transports:
45
+ `stdio` (for local clients) and `streamable-http` (for self-hosting).
46
+ okama-mcp is free and open source — no hosted service, no registration; you run it
47
+ yourself, locally or on your own server.
48
+
49
+ ## Install
50
+
51
+ Requires Python ≥ 3.11 (same floor as okama itself).
52
+
53
+ ```bash
54
+ git clone https://github.com/mbk-dev/okama-mcp
55
+ cd okama-mcp
56
+ poetry install
57
+ ```
58
+
59
+ ## Run
60
+
61
+ ```bash
62
+ # stdio — for Claude Desktop, Claude Code, Cursor (local IPC)
63
+ poetry run okama-mcp stdio
64
+
65
+ # streamable HTTP — for self-hosting on your own server
66
+ poetry run okama-mcp http --host 127.0.0.1 --port 8765
67
+ ```
68
+
69
+ ## Connect a client
70
+
71
+ ### Claude Desktop
72
+
73
+ Edit `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or
74
+ `%APPDATA%\Claude\claude_desktop_config.json` (Windows):
75
+
76
+ ```json
77
+ {
78
+ "mcpServers": {
79
+ "okama": {
80
+ "command": "poetry",
81
+ "args": ["run", "okama-mcp", "stdio"],
82
+ "cwd": "/absolute/path/to/okama-mcp"
83
+ }
84
+ }
85
+ }
86
+ ```
87
+
88
+ Restart Claude Desktop; the server appears in the tools menu.
89
+
90
+ ### Claude Code
91
+
92
+ From the project root — registers the server for this project only (`claude` must be
93
+ launched from this directory to see it):
94
+
95
+ ```bash
96
+ claude mcp add okama poetry run okama-mcp stdio
97
+ ```
98
+
99
+ To make the server available in **every** project (user scope), register the absolute
100
+ path of the venv binary — `poetry run` would not work outside the project directory:
101
+
102
+ ```bash
103
+ claude mcp add --scope user okama -- "$(poetry env info -p)/bin/okama-mcp" stdio
104
+ ```
105
+
106
+ Or commit a `.claude/mcp.json` so the whole team picks it up:
107
+
108
+ ```json
109
+ {
110
+ "mcpServers": {
111
+ "okama": {
112
+ "command": "poetry",
113
+ "args": ["run", "okama-mcp", "stdio"]
114
+ }
115
+ }
116
+ }
117
+ ```
118
+
119
+ ### Cursor
120
+
121
+ Open *Settings → MCP*, click *Add new MCP Server*, and use:
122
+
123
+ - Name: `okama`
124
+ - Type: `stdio`
125
+ - Command: `poetry run okama-mcp stdio`
126
+ - Working dir: this project's root
127
+
128
+ ### Self-hosting (streamable HTTP)
129
+
130
+ Run okama-mcp on your own server and share it across your MCP clients:
131
+
132
+ ```bash
133
+ poetry run okama-mcp http --host 127.0.0.1 --port 8765 --path /mcp
134
+ ```
135
+
136
+ Then point your MCP client at `http://<your-server>:8765/mcp`. For a production
137
+ setup put nginx + TLS in front; ready-made examples live in `deploy/`:
138
+
139
+ - `deploy/systemd/okama-mcp.service` — systemd unit (hardened, runs as a dedicated user)
140
+ - `deploy/nginx/self-hosted.conf` — nginx vhost: TLS, SSE-friendly proxying of `/mcp`
141
+
142
+ The server is open by design — free to run, no registration. If your instance must
143
+ not be public, restrict access at the nginx level (allow-list, VPN, or HTTP basic auth).
144
+
145
+ ## Tool catalog
146
+
147
+ All tools are **stateless** — pass the full portfolio specification with every call.
148
+ The server caches expensive okama objects (`Portfolio`, `EfficientFrontier`) by content
149
+ hash, so repeated calls on the same spec are fast.
150
+
151
+ ### Search & metadata
152
+
153
+ | Tool | Purpose |
154
+ |---|---|
155
+ | `search_assets(query, namespace?)` | Free-text search across all okama symbols by name / ticker / ISIN. |
156
+ | `list_namespaces(kind="all"\|"assets"\|"macro")` | Show the available okama namespaces. |
157
+ | `get_asset_info(symbol)` | Metadata for one symbol — name, country, currency, type, date range. |
158
+
159
+ ### Single asset & comparisons
160
+
161
+ | Tool | Purpose |
162
+ |---|---|
163
+ | `get_asset_history(symbol, kind, first_date?, last_date?)` | Time series for one asset. `kind` ∈ {`close_monthly`, `close_daily`, `adj_close`, `ror`, `dividends`}. |
164
+ | `compare_assets(symbols, ccy, first_date?, last_date?, inflation)` | Side-by-side statistics (`describe()` table: CAGR, risk, drawdowns by period). |
165
+ | `get_correlations(symbols, ccy, ...)` | Correlation matrix of monthly returns. |
166
+
167
+ ### Portfolio backtest
168
+
169
+ | Tool | Purpose |
170
+ |---|---|
171
+ | `analyze_portfolio(portfolio)` | Headline metrics + full `describe()` for a `PortfolioSpec`. |
172
+ | `get_portfolio_drawdowns(portfolio)` | Drawdown time series + max drawdown / recovery period. |
173
+ | `get_portfolio_var_cvar(portfolio, time_frame=12, level=1)` | Historical Value at Risk and CVaR. |
174
+ | `get_portfolio_wealth_index(portfolio, full=False)` | Wealth-index series (cumulative growth of 1000). |
175
+
176
+ ### Monte Carlo DCF
177
+
178
+ | Tool | Purpose |
179
+ |---|---|
180
+ | `monte_carlo_forecast(portfolio, mc, cashflow)` | Forward simulation with one of five cash-flow strategies (`indexation`, `percentage`, `time_series`, `vanguard`, `cut_if_drawdown`). Returns percentile wealth bands, terminal-wealth stats, and survival metrics. |
181
+
182
+ ### Efficient Frontier
183
+
184
+ | Tool | Purpose |
185
+ |---|---|
186
+ | `build_efficient_frontier(frontier)` | Full EF point table (Risk / Mean return / CAGR + per-asset weights). |
187
+ | `get_tangency_portfolio(frontier, rf_return, rate_of_return)` | Max-Sharpe portfolio on the EF. |
188
+ | `get_min_variance_portfolio(frontier)` | Global Minimum Variance portfolio. |
189
+
190
+ ### Macro
191
+
192
+ | Tool | Purpose |
193
+ |---|---|
194
+ | `get_inflation(currency, first_date?, last_date?, include_cumulative?)` | Inflation series for a currency (`USD`, `EUR`, `RUB`, …). |
195
+ | `get_central_bank_rate(country, first_date?, last_date?)` | Central-bank policy rate (`US`, `ECB`, `RUS`, …). |
196
+
197
+ ## Spec shapes
198
+
199
+ The complex tools take typed dicts validated by pydantic. The full schemas live in
200
+ `src/okama_mcp/schemas.py`; here are the headline shapes:
201
+
202
+ ```jsonc
203
+ // PortfolioSpec
204
+ {
205
+ "assets": ["GLD.US", "VNQ.US"],
206
+ "weights": [0.3, 0.7], // optional, must sum to 1.0
207
+ "ccy": "USD",
208
+ "first_date": "2010-01",
209
+ "last_date": "2024-12",
210
+ "rebalancing_period": "year", // month | quarter | half-year | year | none
211
+ "inflation": true
212
+ }
213
+
214
+ // MCSpec
215
+ {
216
+ "distribution": "norm", // norm | lognorm | t
217
+ "period_years": 25,
218
+ "scenarios": 500, // ≤ 5000
219
+ "percentiles": [5, 50, 95],
220
+ "random_seed": 42 // optional, for reproducibility
221
+ }
222
+
223
+ // CashflowSpec — discriminated by `type`
224
+ { "type": "indexation", "initial_investment": 1000000, "frequency": "month", "amount": -1000, "indexation": "inflation" }
225
+ { "type": "percentage", "initial_investment": 1000000, "frequency": "year", "percentage": -0.04 }
226
+ { "type": "time_series", "initial_investment": 100000, "events": { "2030-06": -50000 } }
227
+ { "type": "vanguard", "initial_investment": 1000000, "percentage": -0.04, "floor_ceiling": [-0.025, 0.05], "indexation": "inflation" }
228
+ { "type": "cut_if_drawdown", "initial_investment": 1000000, "frequency": "year", "amount": -60000, "indexation": "inflation",
229
+ "crash_threshold_reduction": [[0.2, 0.4], [0.5, 1.0]] }
230
+
231
+ // FrontierSpec
232
+ {
233
+ "assets": ["SPY.US", "BND.US", "GLD.US"],
234
+ "ccy": "USD",
235
+ "bounds": [[0.0, 0.7], [0.1, 1.0], [0.0, 0.3]], // optional
236
+ "n_points": 20,
237
+ "rebalancing_period": "year",
238
+ "inflation": false
239
+ }
240
+ ```
241
+
242
+ ## Development
243
+
244
+ The project follows TDD (see `AGENTS.md`). After every code change run:
245
+
246
+ ```bash
247
+ poetry run pytest -q
248
+ poetry run ruff check .
249
+ ```
250
+
251
+ To run the live-API integration test (hits `api.okama.io`):
252
+
253
+ ```bash
254
+ poetry run pytest -m integration
255
+ ```
256
+
257
+ ## Project layout
258
+
259
+ ```
260
+ src/okama_mcp/
261
+ ├── server.py # FastMCP instance + registration entry point
262
+ ├── transport.py # CLI: `okama-mcp stdio | http`
263
+ ├── schemas.py # PortfolioSpec, MCSpec, CashflowSpec, FrontierSpec
264
+ ├── cache.py # TTL+LRU cache keyed by sha256 of canonical spec
265
+ ├── serialization.py # pandas → JSON-safe with smart truncation
266
+ ├── errors.py # Translate okama exceptions to actionable MCP errors
267
+ └── tools/
268
+ ├── search.py, asset.py, asset_list.py
269
+ ├── portfolio.py, monte_carlo.py
270
+ ├── frontier.py, macro.py
271
+ ```
272
+
273
+ ## License
274
+
275
+ Same as okama itself: MIT.
276
+
@@ -0,0 +1,249 @@
1
+ # okama-mcp
2
+
3
+ MCP (Model Context Protocol) server that exposes the [okama](https://github.com/mbk-dev/okama)
4
+ investment portfolio toolkit to AI assistants — Claude Desktop, Claude Code, Cursor, and any
5
+ other MCP-compatible client.
6
+
7
+ With okama-mcp installed, you can ask an AI things like:
8
+
9
+ > *"Backtest a portfolio of 30% gold and 70% real estate over the last 15 years."*
10
+ >
11
+ > *"Run a Monte Carlo retirement forecast on that portfolio, withdrawing $1,000/month
12
+ > indexed to inflation, over 25 years."*
13
+ >
14
+ > *"What's the tangency portfolio of SPY, BND, and GLD with a 3% risk-free rate?"*
15
+
16
+ …and the AI uses the MCP tools to call okama directly — no Python code needed.
17
+
18
+ Built on [FastMCP](https://github.com/jlowin/fastmcp). Single codebase, two transports:
19
+ `stdio` (for local clients) and `streamable-http` (for self-hosting).
20
+ okama-mcp is free and open source — no hosted service, no registration; you run it
21
+ yourself, locally or on your own server.
22
+
23
+ ## Install
24
+
25
+ Requires Python ≥ 3.11 (same floor as okama itself).
26
+
27
+ ```bash
28
+ git clone https://github.com/mbk-dev/okama-mcp
29
+ cd okama-mcp
30
+ poetry install
31
+ ```
32
+
33
+ ## Run
34
+
35
+ ```bash
36
+ # stdio — for Claude Desktop, Claude Code, Cursor (local IPC)
37
+ poetry run okama-mcp stdio
38
+
39
+ # streamable HTTP — for self-hosting on your own server
40
+ poetry run okama-mcp http --host 127.0.0.1 --port 8765
41
+ ```
42
+
43
+ ## Connect a client
44
+
45
+ ### Claude Desktop
46
+
47
+ Edit `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or
48
+ `%APPDATA%\Claude\claude_desktop_config.json` (Windows):
49
+
50
+ ```json
51
+ {
52
+ "mcpServers": {
53
+ "okama": {
54
+ "command": "poetry",
55
+ "args": ["run", "okama-mcp", "stdio"],
56
+ "cwd": "/absolute/path/to/okama-mcp"
57
+ }
58
+ }
59
+ }
60
+ ```
61
+
62
+ Restart Claude Desktop; the server appears in the tools menu.
63
+
64
+ ### Claude Code
65
+
66
+ From the project root — registers the server for this project only (`claude` must be
67
+ launched from this directory to see it):
68
+
69
+ ```bash
70
+ claude mcp add okama poetry run okama-mcp stdio
71
+ ```
72
+
73
+ To make the server available in **every** project (user scope), register the absolute
74
+ path of the venv binary — `poetry run` would not work outside the project directory:
75
+
76
+ ```bash
77
+ claude mcp add --scope user okama -- "$(poetry env info -p)/bin/okama-mcp" stdio
78
+ ```
79
+
80
+ Or commit a `.claude/mcp.json` so the whole team picks it up:
81
+
82
+ ```json
83
+ {
84
+ "mcpServers": {
85
+ "okama": {
86
+ "command": "poetry",
87
+ "args": ["run", "okama-mcp", "stdio"]
88
+ }
89
+ }
90
+ }
91
+ ```
92
+
93
+ ### Cursor
94
+
95
+ Open *Settings → MCP*, click *Add new MCP Server*, and use:
96
+
97
+ - Name: `okama`
98
+ - Type: `stdio`
99
+ - Command: `poetry run okama-mcp stdio`
100
+ - Working dir: this project's root
101
+
102
+ ### Self-hosting (streamable HTTP)
103
+
104
+ Run okama-mcp on your own server and share it across your MCP clients:
105
+
106
+ ```bash
107
+ poetry run okama-mcp http --host 127.0.0.1 --port 8765 --path /mcp
108
+ ```
109
+
110
+ Then point your MCP client at `http://<your-server>:8765/mcp`. For a production
111
+ setup put nginx + TLS in front; ready-made examples live in `deploy/`:
112
+
113
+ - `deploy/systemd/okama-mcp.service` — systemd unit (hardened, runs as a dedicated user)
114
+ - `deploy/nginx/self-hosted.conf` — nginx vhost: TLS, SSE-friendly proxying of `/mcp`
115
+
116
+ The server is open by design — free to run, no registration. If your instance must
117
+ not be public, restrict access at the nginx level (allow-list, VPN, or HTTP basic auth).
118
+
119
+ ## Tool catalog
120
+
121
+ All tools are **stateless** — pass the full portfolio specification with every call.
122
+ The server caches expensive okama objects (`Portfolio`, `EfficientFrontier`) by content
123
+ hash, so repeated calls on the same spec are fast.
124
+
125
+ ### Search & metadata
126
+
127
+ | Tool | Purpose |
128
+ |---|---|
129
+ | `search_assets(query, namespace?)` | Free-text search across all okama symbols by name / ticker / ISIN. |
130
+ | `list_namespaces(kind="all"\|"assets"\|"macro")` | Show the available okama namespaces. |
131
+ | `get_asset_info(symbol)` | Metadata for one symbol — name, country, currency, type, date range. |
132
+
133
+ ### Single asset & comparisons
134
+
135
+ | Tool | Purpose |
136
+ |---|---|
137
+ | `get_asset_history(symbol, kind, first_date?, last_date?)` | Time series for one asset. `kind` ∈ {`close_monthly`, `close_daily`, `adj_close`, `ror`, `dividends`}. |
138
+ | `compare_assets(symbols, ccy, first_date?, last_date?, inflation)` | Side-by-side statistics (`describe()` table: CAGR, risk, drawdowns by period). |
139
+ | `get_correlations(symbols, ccy, ...)` | Correlation matrix of monthly returns. |
140
+
141
+ ### Portfolio backtest
142
+
143
+ | Tool | Purpose |
144
+ |---|---|
145
+ | `analyze_portfolio(portfolio)` | Headline metrics + full `describe()` for a `PortfolioSpec`. |
146
+ | `get_portfolio_drawdowns(portfolio)` | Drawdown time series + max drawdown / recovery period. |
147
+ | `get_portfolio_var_cvar(portfolio, time_frame=12, level=1)` | Historical Value at Risk and CVaR. |
148
+ | `get_portfolio_wealth_index(portfolio, full=False)` | Wealth-index series (cumulative growth of 1000). |
149
+
150
+ ### Monte Carlo DCF
151
+
152
+ | Tool | Purpose |
153
+ |---|---|
154
+ | `monte_carlo_forecast(portfolio, mc, cashflow)` | Forward simulation with one of five cash-flow strategies (`indexation`, `percentage`, `time_series`, `vanguard`, `cut_if_drawdown`). Returns percentile wealth bands, terminal-wealth stats, and survival metrics. |
155
+
156
+ ### Efficient Frontier
157
+
158
+ | Tool | Purpose |
159
+ |---|---|
160
+ | `build_efficient_frontier(frontier)` | Full EF point table (Risk / Mean return / CAGR + per-asset weights). |
161
+ | `get_tangency_portfolio(frontier, rf_return, rate_of_return)` | Max-Sharpe portfolio on the EF. |
162
+ | `get_min_variance_portfolio(frontier)` | Global Minimum Variance portfolio. |
163
+
164
+ ### Macro
165
+
166
+ | Tool | Purpose |
167
+ |---|---|
168
+ | `get_inflation(currency, first_date?, last_date?, include_cumulative?)` | Inflation series for a currency (`USD`, `EUR`, `RUB`, …). |
169
+ | `get_central_bank_rate(country, first_date?, last_date?)` | Central-bank policy rate (`US`, `ECB`, `RUS`, …). |
170
+
171
+ ## Spec shapes
172
+
173
+ The complex tools take typed dicts validated by pydantic. The full schemas live in
174
+ `src/okama_mcp/schemas.py`; here are the headline shapes:
175
+
176
+ ```jsonc
177
+ // PortfolioSpec
178
+ {
179
+ "assets": ["GLD.US", "VNQ.US"],
180
+ "weights": [0.3, 0.7], // optional, must sum to 1.0
181
+ "ccy": "USD",
182
+ "first_date": "2010-01",
183
+ "last_date": "2024-12",
184
+ "rebalancing_period": "year", // month | quarter | half-year | year | none
185
+ "inflation": true
186
+ }
187
+
188
+ // MCSpec
189
+ {
190
+ "distribution": "norm", // norm | lognorm | t
191
+ "period_years": 25,
192
+ "scenarios": 500, // ≤ 5000
193
+ "percentiles": [5, 50, 95],
194
+ "random_seed": 42 // optional, for reproducibility
195
+ }
196
+
197
+ // CashflowSpec — discriminated by `type`
198
+ { "type": "indexation", "initial_investment": 1000000, "frequency": "month", "amount": -1000, "indexation": "inflation" }
199
+ { "type": "percentage", "initial_investment": 1000000, "frequency": "year", "percentage": -0.04 }
200
+ { "type": "time_series", "initial_investment": 100000, "events": { "2030-06": -50000 } }
201
+ { "type": "vanguard", "initial_investment": 1000000, "percentage": -0.04, "floor_ceiling": [-0.025, 0.05], "indexation": "inflation" }
202
+ { "type": "cut_if_drawdown", "initial_investment": 1000000, "frequency": "year", "amount": -60000, "indexation": "inflation",
203
+ "crash_threshold_reduction": [[0.2, 0.4], [0.5, 1.0]] }
204
+
205
+ // FrontierSpec
206
+ {
207
+ "assets": ["SPY.US", "BND.US", "GLD.US"],
208
+ "ccy": "USD",
209
+ "bounds": [[0.0, 0.7], [0.1, 1.0], [0.0, 0.3]], // optional
210
+ "n_points": 20,
211
+ "rebalancing_period": "year",
212
+ "inflation": false
213
+ }
214
+ ```
215
+
216
+ ## Development
217
+
218
+ The project follows TDD (see `AGENTS.md`). After every code change run:
219
+
220
+ ```bash
221
+ poetry run pytest -q
222
+ poetry run ruff check .
223
+ ```
224
+
225
+ To run the live-API integration test (hits `api.okama.io`):
226
+
227
+ ```bash
228
+ poetry run pytest -m integration
229
+ ```
230
+
231
+ ## Project layout
232
+
233
+ ```
234
+ src/okama_mcp/
235
+ ├── server.py # FastMCP instance + registration entry point
236
+ ├── transport.py # CLI: `okama-mcp stdio | http`
237
+ ├── schemas.py # PortfolioSpec, MCSpec, CashflowSpec, FrontierSpec
238
+ ├── cache.py # TTL+LRU cache keyed by sha256 of canonical spec
239
+ ├── serialization.py # pandas → JSON-safe with smart truncation
240
+ ├── errors.py # Translate okama exceptions to actionable MCP errors
241
+ └── tools/
242
+ ├── search.py, asset.py, asset_list.py
243
+ ├── portfolio.py, monte_carlo.py
244
+ ├── frontier.py, macro.py
245
+ ```
246
+
247
+ ## License
248
+
249
+ Same as okama itself: MIT.
@@ -0,0 +1,62 @@
1
+ [tool.poetry]
2
+ name = "okama-mcp"
3
+ version = "0.2.0"
4
+ description = "MCP (Model Context Protocol) server exposing the okama investment portfolio toolkit to AI assistants"
5
+ authors = ["Sergey Kikevich <sergey@rostsber.ru>"]
6
+ readme = "README.md"
7
+ license = "MIT"
8
+ homepage = "https://mcp.okama.io"
9
+ repository = "https://github.com/mbk-dev/okama-mcp"
10
+ keywords = ["mcp", "okama", "investments", "portfolio", "finance", "llm"]
11
+ classifiers = [
12
+ "Development Status :: 4 - Beta",
13
+ "Intended Audience :: Financial and Insurance Industry",
14
+ "Topic :: Office/Business :: Financial :: Investment",
15
+ ]
16
+ packages = [{ include = "okama_mcp", from = "src" }]
17
+
18
+ [tool.poetry.dependencies]
19
+ python = ">=3.11,<4.0.0"
20
+ okama = ">=2.1.0"
21
+ fastmcp = ">=2.7"
22
+ pydantic = ">=2.0"
23
+
24
+ [tool.poetry.group.test]
25
+ optional = false
26
+
27
+ [tool.poetry.group.test.dependencies]
28
+ pytest = "*"
29
+ pytest-asyncio = "*"
30
+
31
+ [tool.poetry.group.dev]
32
+ optional = false
33
+
34
+ [tool.poetry.group.dev.dependencies]
35
+ ruff = "*"
36
+
37
+ [tool.poetry.scripts]
38
+ okama-mcp = "okama_mcp.transport:main"
39
+
40
+ [build-system]
41
+ requires = ["poetry-core>=1.0.0"]
42
+ build-backend = "poetry.core.masonry.api"
43
+
44
+ [tool.ruff]
45
+ line-length = 120
46
+ extend-exclude = [".ipynb_checkpoints", "env", ".env"]
47
+ target-version = "py311"
48
+
49
+ [tool.ruff.lint]
50
+ select = ["C", "E", "F", "W", "B", "UP"]
51
+ ignore = ["E203", "E501"]
52
+
53
+ [tool.ruff.lint.per-file-ignores]
54
+ "__init__.py" = ["F401"]
55
+
56
+ [tool.pytest.ini_options]
57
+ testpaths = ["tests"]
58
+ asyncio_mode = "auto"
59
+ markers = [
60
+ "integration: live test that hits api.okama.io (slow, network-dependent)",
61
+ ]
62
+ addopts = "-m 'not integration'"
@@ -0,0 +1,10 @@
1
+ """okama-mcp: an MCP server wrapping the okama investment toolkit.
2
+
3
+ Exposes a FastMCP server through both stdio and streamable-http transports so AI
4
+ assistants can run portfolio backtests, Monte Carlo forecasts, efficient-frontier
5
+ optimisation and macro queries via tool calls.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ __version__ = "0.1.0"
@@ -0,0 +1,10 @@
1
+ """Allow `python -m okama_mcp <command>` execution."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import sys
6
+
7
+ from okama_mcp.transport import main
8
+
9
+ if __name__ == "__main__":
10
+ sys.exit(main())