alloc-context 0.2.1__tar.gz → 0.2.2__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.
- {alloc_context-0.2.1 → alloc_context-0.2.2}/PKG-INFO +2 -2
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloc_context.egg-info/PKG-INFO +2 -2
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloc_context.egg-info/SOURCES.txt +2 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/__init__.py +1 -1
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/mcp/bazaar.py +88 -172
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/mcp/server.py +23 -0
- alloc_context-0.2.2/alloccontext/mcp/tool_catalog.py +311 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/pyproject.toml +2 -2
- {alloc_context-0.2.1 → alloc_context-0.2.2}/tests/test_mcp_bazaar.py +6 -0
- alloc_context-0.2.2/tests/test_tool_catalog.py +65 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/LICENSE +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/README.md +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloc_context.egg-info/dependency_links.txt +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloc_context.egg-info/entry_points.txt +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloc_context.egg-info/requires.txt +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloc_context.egg-info/top_level.txt +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/__main__.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/config.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/constants.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/horizon.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/ingest/__init__.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/ingest/alt_quote_registry.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/ingest/alt_quote_store.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/ingest/alt_quotes.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/ingest/asset_registry.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/ingest/cf_benchmarks.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/ingest/cf_history.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/ingest/coinbase_client.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/ingest/coinbase_portfolio.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/ingest/coingecko.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/ingest/coinmarketcap.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/ingest/env_keys.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/ingest/etf_flows.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/ingest/exchange/__init__.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/ingest/exchange/coinbase_adapter.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/ingest/exchange/kraken_adapter.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/ingest/exchange/live.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/ingest/exchange/portfolio.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/ingest/exchange/registry.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/ingest/exchange/types.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/ingest/exchange_http.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/ingest/fear_greed.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/ingest/fred.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/ingest/http_errors.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/ingest/kalshi.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/ingest/kalshi_api.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/ingest/kalshi_client.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/ingest/kalshi_files.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/ingest/kalshi_state.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/ingest/kraken_client.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/ingest/kraken_portfolio.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/ingest/macro_calendar.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/ingest/macro_normalize.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/ingest/market_snapshots.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/ingest/outcome.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/ingest/parse_helpers.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/ingest/portfolio_holdings.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/ingest/quote_resolver.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/ingest/runner.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/mcp/__init__.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/mcp/assets.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/mcp/bridge.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/mcp/bridge_portfolio.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/mcp/contracts.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/mcp/glama.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/mcp/handlers.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/mcp/http.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/mcp/instructions.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/mcp/payer.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/mcp/payment_middleware.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/mcp/setup.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/mcp/staleness.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/mcp/tool_fields.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/mcp/upstream.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/mcp/validation.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/mcp/x402_bazaar_dynamic.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/mcp/x402_config.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/mcp/x402_pricing.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/mcp/x402_stables.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/rollup/__init__.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/rollup/allocation_analysis.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/rollup/band.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/rollup/breadth.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/rollup/cf_math.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/rollup/cluster.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/rollup/cluster_config.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/rollup/comparison.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/rollup/context.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/rollup/delta.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/rollup/etf.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/rollup/fear_greed.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/rollup/macro.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/rollup/portfolio.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/rollup/portfolio_payload.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/rollup/rebalance.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/rollup/regime.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/rollup/sentiment.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/rollup/snapshots.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/rollup/tape.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/status_report.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/store/__init__.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/store/db.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/store/jsonutil.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/store/meta.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/store/retention.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/store/status.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/timeutil.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/user_config.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/x402_production_check.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/alloccontext/x402_smoke_redact.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/setup.cfg +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/tests/test_backup_sqlite.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/tests/test_bridge.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/tests/test_bridge_portfolio.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/tests/test_bump_version.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/tests/test_coinbase_portfolio.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/tests/test_config_cli.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/tests/test_context_bundle_schema.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/tests/test_context_snapshots.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/tests/test_db_schema.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/tests/test_deploy.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/tests/test_dev_stack.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/tests/test_etf.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/tests/test_exchanges_config.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/tests/test_fear_greed.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/tests/test_fred.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/tests/test_glama_well_known.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/tests/test_holdings_scoped_delta_regime.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/tests/test_holdings_scoped_market.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/tests/test_horizon.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/tests/test_ingest_outcome.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/tests/test_ingest_runner.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/tests/test_ingest_store_integration.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/tests/test_kalshi_api.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/tests/test_kraken_portfolio.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/tests/test_live_ingest_handlers.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/tests/test_macro.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/tests/test_market_breadth.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/tests/test_mcp_assets_regime.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/tests/test_mcp_contracts.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/tests/test_mcp_data_staleness.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/tests/test_mcp_handlers.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/tests/test_mcp_health.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/tests/test_mcp_http_lifecycle.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/tests/test_mcp_live_portfolio.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/tests/test_mcp_server.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/tests/test_mcp_validation.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/tests/test_mcp_x402.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/tests/test_mcp_x402_http.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/tests/test_mcp_x402_pricing.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/tests/test_mcp_x402_stables.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/tests/test_payer.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/tests/test_portfolio_holdings.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/tests/test_quote_resolver.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/tests/test_rebalance.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/tests/test_rollup.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/tests/test_script_runtime.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/tests/test_security_hardening.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/tests/test_server_json.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/tests/test_setup.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/tests/test_snapshots_and_delta.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/tests/test_status_report.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/tests/test_user_config.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/tests/test_workflows.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/tests/test_x402_bazaar_dynamic.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/tests/test_x402_production_check.py +0 -0
- {alloc_context-0.2.1 → alloc_context-0.2.2}/tests/test_x402_smoke_redact.py +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: alloc-context
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: Portfolio-aware crypto context for agents — holdings, market, optional allocation analysis
|
|
5
5
|
License: Elastic-2.0
|
|
6
|
-
Project-URL: Homepage, https://
|
|
6
|
+
Project-URL: Homepage, https://mcp.alloc-context.com/llms.txt
|
|
7
7
|
Project-URL: Documentation, https://github.com/negillett/alloc-context/blob/main/docs/agent-integration.md
|
|
8
8
|
Project-URL: Repository, https://github.com/negillett/alloc-context
|
|
9
9
|
Project-URL: Issues, https://github.com/negillett/alloc-context/issues
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: alloc-context
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: Portfolio-aware crypto context for agents — holdings, market, optional allocation analysis
|
|
5
5
|
License: Elastic-2.0
|
|
6
|
-
Project-URL: Homepage, https://
|
|
6
|
+
Project-URL: Homepage, https://mcp.alloc-context.com/llms.txt
|
|
7
7
|
Project-URL: Documentation, https://github.com/negillett/alloc-context/blob/main/docs/agent-integration.md
|
|
8
8
|
Project-URL: Repository, https://github.com/negillett/alloc-context
|
|
9
9
|
Project-URL: Issues, https://github.com/negillett/alloc-context/issues
|
|
@@ -71,6 +71,7 @@ alloccontext/mcp/payment_middleware.py
|
|
|
71
71
|
alloccontext/mcp/server.py
|
|
72
72
|
alloccontext/mcp/setup.py
|
|
73
73
|
alloccontext/mcp/staleness.py
|
|
74
|
+
alloccontext/mcp/tool_catalog.py
|
|
74
75
|
alloccontext/mcp/tool_fields.py
|
|
75
76
|
alloccontext/mcp/upstream.py
|
|
76
77
|
alloccontext/mcp/validation.py
|
|
@@ -156,6 +157,7 @@ tests/test_server_json.py
|
|
|
156
157
|
tests/test_setup.py
|
|
157
158
|
tests/test_snapshots_and_delta.py
|
|
158
159
|
tests/test_status_report.py
|
|
160
|
+
tests/test_tool_catalog.py
|
|
159
161
|
tests/test_user_config.py
|
|
160
162
|
tests/test_workflows.py
|
|
161
163
|
tests/test_x402_bazaar_dynamic.py
|
|
@@ -10,6 +10,24 @@ from x402.extensions.bazaar import (
|
|
|
10
10
|
declare_mcp_discovery_extension,
|
|
11
11
|
)
|
|
12
12
|
|
|
13
|
+
from alloccontext.mcp.tool_catalog import (
|
|
14
|
+
ASSET_FILTER_SCHEMA,
|
|
15
|
+
AS_OF_SCHEMA,
|
|
16
|
+
BAND_SCHEMA,
|
|
17
|
+
CURRENT_AS_OF_SCHEMA,
|
|
18
|
+
FRESHNESS_SCHEMA,
|
|
19
|
+
MATCH_SCHEMA,
|
|
20
|
+
MCP_SERVER_PROMPTS,
|
|
21
|
+
MCP_SERVER_RESOURCES,
|
|
22
|
+
OPTIONAL_TARGET_PCT_SCHEMA,
|
|
23
|
+
PRIOR_AS_OF_SCHEMA,
|
|
24
|
+
SCENARIOS_SCHEMA,
|
|
25
|
+
SCOPE_SCHEMA,
|
|
26
|
+
TARGET_PCT_SCHEMA,
|
|
27
|
+
allocation_pct_schema,
|
|
28
|
+
server_card_tool_entry,
|
|
29
|
+
)
|
|
30
|
+
|
|
13
31
|
SERVICE_NAME = "AllocContext"
|
|
14
32
|
OFFICIAL_HOSTED_MCP_URL = "https://mcp.alloc-context.com/mcp"
|
|
15
33
|
USE_DOCS_PATH = "docs/USE.md"
|
|
@@ -98,54 +116,22 @@ LISTING_DESCRIPTION = (
|
|
|
98
116
|
f"MCP at {OFFICIAL_HOSTED_MCP_URL} — see {USE_DOCS_PATH}."
|
|
99
117
|
)
|
|
100
118
|
|
|
101
|
-
_ASSET_FILTER_SCHEMA = {
|
|
102
|
-
"type": "array",
|
|
103
|
-
"items": {"type": "string", "enum": ["BTC", "ETH", "CASH"]},
|
|
104
|
-
"description": "Subset market and ETF fields (default BTC and ETH).",
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
_TARGET_PCT_SCHEMA = {
|
|
108
|
-
"type": "object",
|
|
109
|
-
"description": "Target weights keyed by BTC, ETH, CASH.",
|
|
110
|
-
"properties": {
|
|
111
|
-
"BTC": {"type": "number"},
|
|
112
|
-
"ETH": {"type": "number"},
|
|
113
|
-
"CASH": {"type": "number"},
|
|
114
|
-
},
|
|
115
|
-
"required": ["BTC", "ETH", "CASH"],
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
_BAND_SCHEMA = {
|
|
119
|
-
"type": "number",
|
|
120
|
-
"description": "Drift band width (for example 0.15 = 15%).",
|
|
121
|
-
}
|
|
122
|
-
|
|
123
119
|
_MCP_TOOLS: tuple[dict[str, Any], ...] = (
|
|
124
120
|
{
|
|
125
121
|
"tool_name": "get_market_context",
|
|
126
122
|
"description": (
|
|
127
|
-
"
|
|
128
|
-
"sentiment, macro
|
|
129
|
-
"
|
|
130
|
-
"
|
|
123
|
+
"Return read-only fused market backdrop for crypto portfolio context: "
|
|
124
|
+
"sentiment (Fear & Greed, Kalshi), macro events, FRED indicators, ETF "
|
|
125
|
+
"flows, and market breadth — no portfolio holdings. Use "
|
|
126
|
+
"get_context_bundle when you also need holdings, delta, or regime. "
|
|
127
|
+
"freshness=cached reads the ingest DB; freshness=live runs ingest first."
|
|
131
128
|
),
|
|
132
129
|
"input_schema": {
|
|
133
130
|
"type": "object",
|
|
134
131
|
"properties": {
|
|
135
|
-
"scope":
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
"description": "Rollup horizon for macro and context bundle.",
|
|
139
|
-
},
|
|
140
|
-
"freshness": {
|
|
141
|
-
"type": "string",
|
|
142
|
-
"enum": ["cached", "live"],
|
|
143
|
-
"description": (
|
|
144
|
-
"cached reads the ingest DB; live runs ingest first "
|
|
145
|
-
"(requires ingest API keys on the host)."
|
|
146
|
-
),
|
|
147
|
-
},
|
|
148
|
-
"assets": _ASSET_FILTER_SCHEMA,
|
|
132
|
+
"scope": SCOPE_SCHEMA,
|
|
133
|
+
"freshness": FRESHNESS_SCHEMA,
|
|
134
|
+
"assets": ASSET_FILTER_SCHEMA,
|
|
149
135
|
},
|
|
150
136
|
},
|
|
151
137
|
"example": {"scope": "daily", "freshness": "cached", "assets": ["BTC", "ETH"]},
|
|
@@ -163,25 +149,20 @@ _MCP_TOOLS: tuple[dict[str, Any], ...] = (
|
|
|
163
149
|
{
|
|
164
150
|
"tool_name": "get_context_bundle",
|
|
165
151
|
"description": (
|
|
166
|
-
"
|
|
167
|
-
"market, sentiment, macro, regime hints, and delta vs the prior "
|
|
168
|
-
"
|
|
169
|
-
"
|
|
152
|
+
"Return the full read-only ContextBundle JSON: portfolio holdings, "
|
|
153
|
+
"market, sentiment, macro, regime hints, and delta vs the prior saved "
|
|
154
|
+
"snapshot. Use get_market_context for market-only; use get_context_at "
|
|
155
|
+
"for a historical snapshot. Optional target_pct and band attach "
|
|
156
|
+
"allocation_analysis drift math."
|
|
170
157
|
),
|
|
171
158
|
"input_schema": {
|
|
172
159
|
"type": "object",
|
|
173
160
|
"properties": {
|
|
174
|
-
"scope":
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
"
|
|
179
|
-
"type": "string",
|
|
180
|
-
"enum": ["cached", "live"],
|
|
181
|
-
},
|
|
182
|
-
"assets": _ASSET_FILTER_SCHEMA,
|
|
183
|
-
"target_pct": _TARGET_PCT_SCHEMA,
|
|
184
|
-
"band": _BAND_SCHEMA,
|
|
161
|
+
"scope": SCOPE_SCHEMA,
|
|
162
|
+
"freshness": FRESHNESS_SCHEMA,
|
|
163
|
+
"assets": ASSET_FILTER_SCHEMA,
|
|
164
|
+
"target_pct": TARGET_PCT_SCHEMA,
|
|
165
|
+
"band": BAND_SCHEMA,
|
|
185
166
|
},
|
|
186
167
|
},
|
|
187
168
|
"example": {
|
|
@@ -211,45 +192,28 @@ _MCP_TOOLS: tuple[dict[str, Any], ...] = (
|
|
|
211
192
|
{
|
|
212
193
|
"tool_name": "get_rebalance_plan",
|
|
213
194
|
"description": (
|
|
214
|
-
"Compute USD deltas and exchange
|
|
215
|
-
"BTC/ETH/CASH
|
|
216
|
-
"
|
|
195
|
+
"Compute read-only USD deltas and suggested exchange move lines to "
|
|
196
|
+
"reach a BTC/ETH/CASH target split. Pure math — no exchange API calls. "
|
|
197
|
+
"Requires allocation_pct, target_pct, and nav_usd. Use get_portfolio_state "
|
|
198
|
+
"or get_context_bundle when you need live weights first."
|
|
217
199
|
),
|
|
218
200
|
"input_schema": {
|
|
219
201
|
"type": "object",
|
|
220
202
|
"properties": {
|
|
221
|
-
"allocation_pct":
|
|
222
|
-
|
|
223
|
-
"description": "Current weights keyed by BTC, ETH, CASH.",
|
|
224
|
-
"properties": {
|
|
225
|
-
"BTC": {"type": "number"},
|
|
226
|
-
"ETH": {"type": "number"},
|
|
227
|
-
"CASH": {"type": "number"},
|
|
228
|
-
},
|
|
229
|
-
"required": ["BTC", "ETH", "CASH"],
|
|
230
|
-
},
|
|
231
|
-
"target_pct": {
|
|
232
|
-
"type": "object",
|
|
233
|
-
"description": "Target weights keyed by BTC, ETH, CASH.",
|
|
234
|
-
"properties": {
|
|
235
|
-
"BTC": {"type": "number"},
|
|
236
|
-
"ETH": {"type": "number"},
|
|
237
|
-
"CASH": {"type": "number"},
|
|
238
|
-
},
|
|
239
|
-
"required": ["BTC", "ETH", "CASH"],
|
|
240
|
-
},
|
|
203
|
+
"allocation_pct": allocation_pct_schema(role="Current"),
|
|
204
|
+
"target_pct": allocation_pct_schema(role="Target"),
|
|
241
205
|
"nav_usd": {
|
|
242
206
|
"type": "number",
|
|
243
|
-
"description": "Portfolio
|
|
207
|
+
"description": "Portfolio net asset value in USD.",
|
|
244
208
|
},
|
|
245
209
|
"exchange": {
|
|
246
210
|
"type": "string",
|
|
247
211
|
"enum": ["kraken", "coinbase"],
|
|
248
212
|
"description": (
|
|
249
|
-
"
|
|
213
|
+
"Spot exchange for move wording: kraken (default) or coinbase."
|
|
250
214
|
),
|
|
251
215
|
},
|
|
252
|
-
"band":
|
|
216
|
+
"band": BAND_SCHEMA,
|
|
253
217
|
},
|
|
254
218
|
"required": ["allocation_pct", "target_pct", "nav_usd"],
|
|
255
219
|
},
|
|
@@ -272,10 +236,10 @@ _MCP_TOOLS: tuple[dict[str, Any], ...] = (
|
|
|
272
236
|
{
|
|
273
237
|
"tool_name": "get_portfolio_state",
|
|
274
238
|
"description": (
|
|
275
|
-
"
|
|
276
|
-
"
|
|
277
|
-
"
|
|
278
|
-
"
|
|
239
|
+
"Fetch live read-only portfolio NAV, holdings[], and band weights from "
|
|
240
|
+
"Kraken or Coinbase credentials passed in this call (never stored). "
|
|
241
|
+
"Requires exchange, api_key, and api_secret. Returns available=false "
|
|
242
|
+
"with reason on invalid credentials — no side effects."
|
|
279
243
|
),
|
|
280
244
|
"input_schema": {
|
|
281
245
|
"type": "object",
|
|
@@ -283,11 +247,13 @@ _MCP_TOOLS: tuple[dict[str, Any], ...] = (
|
|
|
283
247
|
"exchange": {
|
|
284
248
|
"type": "string",
|
|
285
249
|
"enum": ["kraken", "coinbase"],
|
|
286
|
-
"description": "Spot exchange to query.",
|
|
250
|
+
"description": "Spot exchange to query: kraken or coinbase.",
|
|
287
251
|
},
|
|
288
252
|
"api_key": {
|
|
289
253
|
"type": "string",
|
|
290
|
-
"description":
|
|
254
|
+
"description": (
|
|
255
|
+
"Read-only exchange API key (Coinbase CDP key name)."
|
|
256
|
+
),
|
|
291
257
|
},
|
|
292
258
|
"api_secret": {
|
|
293
259
|
"type": "string",
|
|
@@ -295,19 +261,8 @@ _MCP_TOOLS: tuple[dict[str, Any], ...] = (
|
|
|
295
261
|
"Read-only API secret (Kraken base64 secret or Coinbase EC PEM)."
|
|
296
262
|
),
|
|
297
263
|
},
|
|
298
|
-
"target_pct":
|
|
299
|
-
|
|
300
|
-
"description": "Optional target weights for allocation_analysis.",
|
|
301
|
-
"properties": {
|
|
302
|
-
"BTC": {"type": "number"},
|
|
303
|
-
"ETH": {"type": "number"},
|
|
304
|
-
"CASH": {"type": "number"},
|
|
305
|
-
},
|
|
306
|
-
},
|
|
307
|
-
"band": {
|
|
308
|
-
"type": "number",
|
|
309
|
-
"description": "Drift band width when target_pct is supplied (e.g. 0.15).",
|
|
310
|
-
},
|
|
264
|
+
"target_pct": OPTIONAL_TARGET_PCT_SCHEMA,
|
|
265
|
+
"band": BAND_SCHEMA,
|
|
311
266
|
},
|
|
312
267
|
"required": ["exchange", "api_key", "api_secret"],
|
|
313
268
|
},
|
|
@@ -330,34 +285,19 @@ _MCP_TOOLS: tuple[dict[str, Any], ...] = (
|
|
|
330
285
|
{
|
|
331
286
|
"tool_name": "check_allocation_band",
|
|
332
287
|
"description": (
|
|
333
|
-
"Check
|
|
334
|
-
"vs
|
|
335
|
-
"
|
|
288
|
+
"Check read-only drift: are BTC/ETH/CASH band weights outside the drift "
|
|
289
|
+
"band vs target_pct? Returns rebalance_hint (within_band, "
|
|
290
|
+
"consider_rebalance, etc.). Single scenario — use check_allocation_bands "
|
|
291
|
+
"for multiple targets. Use get_rebalance_plan when you need USD move lines."
|
|
336
292
|
),
|
|
337
293
|
"input_schema": {
|
|
338
294
|
"type": "object",
|
|
339
295
|
"properties": {
|
|
340
|
-
"allocation_pct":
|
|
341
|
-
|
|
342
|
-
"properties": {
|
|
343
|
-
"BTC": {"type": "number"},
|
|
344
|
-
"ETH": {"type": "number"},
|
|
345
|
-
"CASH": {"type": "number"},
|
|
346
|
-
},
|
|
347
|
-
"required": ["BTC", "ETH", "CASH"],
|
|
348
|
-
},
|
|
349
|
-
"target_pct": {
|
|
350
|
-
"type": "object",
|
|
351
|
-
"properties": {
|
|
352
|
-
"BTC": {"type": "number"},
|
|
353
|
-
"ETH": {"type": "number"},
|
|
354
|
-
"CASH": {"type": "number"},
|
|
355
|
-
},
|
|
356
|
-
"required": ["BTC", "ETH", "CASH"],
|
|
357
|
-
},
|
|
296
|
+
"allocation_pct": allocation_pct_schema(role="Current"),
|
|
297
|
+
"target_pct": allocation_pct_schema(role="Target"),
|
|
358
298
|
"band": {
|
|
359
299
|
"type": "number",
|
|
360
|
-
"description": "Drift band width (default 0.15 = 15%).",
|
|
300
|
+
"description": "Drift band width as a fraction (default 0.15 = 15%).",
|
|
361
301
|
},
|
|
362
302
|
},
|
|
363
303
|
"required": ["allocation_pct", "target_pct"],
|
|
@@ -378,16 +318,20 @@ _MCP_TOOLS: tuple[dict[str, Any], ...] = (
|
|
|
378
318
|
{
|
|
379
319
|
"tool_name": "get_context_at",
|
|
380
320
|
"description": (
|
|
381
|
-
"Load a
|
|
382
|
-
"
|
|
321
|
+
"Load a read-only ContextBundle snapshot from ingest history at a point "
|
|
322
|
+
"in time. Use get_context_bundle for the latest snapshot; use "
|
|
323
|
+
"get_context_delta to compare two timestamps. Returns unavailable when "
|
|
324
|
+
"no snapshot matches as_of and match."
|
|
383
325
|
),
|
|
384
326
|
"input_schema": {
|
|
385
327
|
"type": "object",
|
|
386
328
|
"properties": {
|
|
387
|
-
"as_of":
|
|
388
|
-
"scope":
|
|
389
|
-
"match":
|
|
390
|
-
"assets":
|
|
329
|
+
"as_of": AS_OF_SCHEMA,
|
|
330
|
+
"scope": SCOPE_SCHEMA,
|
|
331
|
+
"match": MATCH_SCHEMA,
|
|
332
|
+
"assets": ASSET_FILTER_SCHEMA,
|
|
333
|
+
"target_pct": TARGET_PCT_SCHEMA,
|
|
334
|
+
"band": BAND_SCHEMA,
|
|
391
335
|
},
|
|
392
336
|
"required": ["as_of"],
|
|
393
337
|
},
|
|
@@ -406,15 +350,18 @@ _MCP_TOOLS: tuple[dict[str, Any], ...] = (
|
|
|
406
350
|
{
|
|
407
351
|
"tool_name": "get_context_delta",
|
|
408
352
|
"description": (
|
|
409
|
-
"Compare two ContextBundle snapshots and return notable_shifts
|
|
353
|
+
"Compare two read-only ContextBundle snapshots and return notable_shifts "
|
|
354
|
+
"between them. Requires prior_as_of; omit current_as_of to diff against "
|
|
355
|
+
"the latest live bundle. Use get_context_at to load one snapshot without "
|
|
356
|
+
"diffing."
|
|
410
357
|
),
|
|
411
358
|
"input_schema": {
|
|
412
359
|
"type": "object",
|
|
413
360
|
"properties": {
|
|
414
|
-
"prior_as_of":
|
|
415
|
-
"scope":
|
|
416
|
-
"current_as_of":
|
|
417
|
-
"assets":
|
|
361
|
+
"prior_as_of": PRIOR_AS_OF_SCHEMA,
|
|
362
|
+
"scope": SCOPE_SCHEMA,
|
|
363
|
+
"current_as_of": CURRENT_AS_OF_SCHEMA,
|
|
364
|
+
"assets": ASSET_FILTER_SCHEMA,
|
|
418
365
|
},
|
|
419
366
|
"required": ["prior_as_of"],
|
|
420
367
|
},
|
|
@@ -431,39 +378,15 @@ _MCP_TOOLS: tuple[dict[str, Any], ...] = (
|
|
|
431
378
|
{
|
|
432
379
|
"tool_name": "check_allocation_bands",
|
|
433
380
|
"description": (
|
|
434
|
-
"Evaluate allocation drift against multiple
|
|
381
|
+
"Evaluate read-only allocation drift against multiple target_pct/band "
|
|
382
|
+
"scenarios in one call. Each scenario requires target_pct; optional name "
|
|
383
|
+
"and band (default 0.15). Use check_allocation_band for a single target."
|
|
435
384
|
),
|
|
436
385
|
"input_schema": {
|
|
437
386
|
"type": "object",
|
|
438
387
|
"properties": {
|
|
439
|
-
"allocation_pct":
|
|
440
|
-
|
|
441
|
-
"properties": {
|
|
442
|
-
"BTC": {"type": "number"},
|
|
443
|
-
"ETH": {"type": "number"},
|
|
444
|
-
"CASH": {"type": "number"},
|
|
445
|
-
},
|
|
446
|
-
"required": ["BTC", "ETH", "CASH"],
|
|
447
|
-
},
|
|
448
|
-
"scenarios": {
|
|
449
|
-
"type": "array",
|
|
450
|
-
"items": {
|
|
451
|
-
"type": "object",
|
|
452
|
-
"properties": {
|
|
453
|
-
"name": {"type": "string"},
|
|
454
|
-
"target_pct": {
|
|
455
|
-
"type": "object",
|
|
456
|
-
"properties": {
|
|
457
|
-
"BTC": {"type": "number"},
|
|
458
|
-
"ETH": {"type": "number"},
|
|
459
|
-
"CASH": {"type": "number"},
|
|
460
|
-
},
|
|
461
|
-
},
|
|
462
|
-
"band": {"type": "number"},
|
|
463
|
-
},
|
|
464
|
-
"required": ["target_pct"],
|
|
465
|
-
},
|
|
466
|
-
},
|
|
388
|
+
"allocation_pct": allocation_pct_schema(role="Current"),
|
|
389
|
+
"scenarios": SCENARIOS_SCHEMA,
|
|
467
390
|
},
|
|
468
391
|
"required": ["allocation_pct", "scenarios"],
|
|
469
392
|
},
|
|
@@ -715,14 +638,7 @@ def build_mcp_server_card(*, version: str) -> dict[str, Any]:
|
|
|
715
638
|
"see /.well-known/x402.json for pricing."
|
|
716
639
|
),
|
|
717
640
|
},
|
|
718
|
-
"tools": [
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
"description": spec["description"],
|
|
722
|
-
"inputSchema": spec["input_schema"],
|
|
723
|
-
}
|
|
724
|
-
for spec in _MCP_TOOLS
|
|
725
|
-
],
|
|
726
|
-
"resources": [],
|
|
727
|
-
"prompts": [],
|
|
641
|
+
"tools": [server_card_tool_entry(spec) for spec in _MCP_TOOLS],
|
|
642
|
+
"resources": list(MCP_SERVER_RESOURCES),
|
|
643
|
+
"prompts": list(MCP_SERVER_PROMPTS),
|
|
728
644
|
}
|
|
@@ -6,6 +6,7 @@ from typing import Any
|
|
|
6
6
|
from alloccontext.config import load_config
|
|
7
7
|
from alloccontext.mcp import handlers
|
|
8
8
|
from alloccontext.mcp.instructions import PRODUCT_INSTRUCTIONS, REBALANCE_HINT_GUIDE
|
|
9
|
+
from alloccontext.mcp.tool_catalog import tool_annotations, tool_title
|
|
9
10
|
from alloccontext.mcp.tool_fields import (
|
|
10
11
|
AllocationPct,
|
|
11
12
|
ApiKey,
|
|
@@ -72,6 +73,12 @@ def _require_mcp():
|
|
|
72
73
|
return FastMCP
|
|
73
74
|
|
|
74
75
|
|
|
76
|
+
def _tool_hints(tool_name: str):
|
|
77
|
+
from mcp.types import ToolAnnotations
|
|
78
|
+
|
|
79
|
+
return ToolAnnotations(**tool_annotations(tool_name))
|
|
80
|
+
|
|
81
|
+
|
|
75
82
|
def create_server(
|
|
76
83
|
*,
|
|
77
84
|
config_path: str | None = None,
|
|
@@ -97,6 +104,8 @@ def create_server(
|
|
|
97
104
|
|
|
98
105
|
@mcp.tool(
|
|
99
106
|
name="get_context_bundle",
|
|
107
|
+
title=tool_title("get_context_bundle"),
|
|
108
|
+
annotations=_tool_hints("get_context_bundle"),
|
|
100
109
|
description=(
|
|
101
110
|
"Return the full read-only ContextBundle JSON: portfolio holdings, "
|
|
102
111
|
"market, sentiment, macro, regime hints, and delta vs the prior saved "
|
|
@@ -133,6 +142,8 @@ def create_server(
|
|
|
133
142
|
|
|
134
143
|
@mcp.tool(
|
|
135
144
|
name="get_market_context",
|
|
145
|
+
title=tool_title("get_market_context"),
|
|
146
|
+
annotations=_tool_hints("get_market_context"),
|
|
136
147
|
description=(
|
|
137
148
|
"Return read-only fused market backdrop: sentiment (Fear & Greed, "
|
|
138
149
|
"Kalshi), macro events, FRED indicators, ETF flows, and market breadth "
|
|
@@ -163,6 +174,8 @@ def create_server(
|
|
|
163
174
|
|
|
164
175
|
@mcp.tool(
|
|
165
176
|
name="get_rebalance_plan",
|
|
177
|
+
title=tool_title("get_rebalance_plan"),
|
|
178
|
+
annotations=_tool_hints("get_rebalance_plan"),
|
|
166
179
|
description=(
|
|
167
180
|
"Compute read-only USD deltas and suggested exchange move lines to "
|
|
168
181
|
"reach a BTC/ETH/CASH target split. Pure math — no exchange API calls. "
|
|
@@ -192,6 +205,8 @@ def create_server(
|
|
|
192
205
|
|
|
193
206
|
@mcp.tool(
|
|
194
207
|
name="get_portfolio_state",
|
|
208
|
+
title=tool_title("get_portfolio_state"),
|
|
209
|
+
annotations=_tool_hints("get_portfolio_state"),
|
|
195
210
|
description=(
|
|
196
211
|
"Fetch live read-only portfolio NAV, holdings[], and band weights from "
|
|
197
212
|
"Kraken or Coinbase credentials passed in this call (never stored). "
|
|
@@ -221,6 +236,8 @@ def create_server(
|
|
|
221
236
|
|
|
222
237
|
@mcp.tool(
|
|
223
238
|
name="check_allocation_band",
|
|
239
|
+
title=tool_title("check_allocation_band"),
|
|
240
|
+
annotations=_tool_hints("check_allocation_band"),
|
|
224
241
|
description=(
|
|
225
242
|
"Read-only drift check: are BTC/ETH/CASH band weights outside the "
|
|
226
243
|
"drift band vs target_pct? Returns rebalance_hint (within_band, "
|
|
@@ -241,6 +258,8 @@ def create_server(
|
|
|
241
258
|
|
|
242
259
|
@mcp.tool(
|
|
243
260
|
name="get_context_at",
|
|
261
|
+
title=tool_title("get_context_at"),
|
|
262
|
+
annotations=_tool_hints("get_context_at"),
|
|
244
263
|
description=(
|
|
245
264
|
"Load a read-only ContextBundle snapshot from ingest history at a "
|
|
246
265
|
"point in time. Use get_context_bundle for the latest snapshot; use "
|
|
@@ -277,6 +296,8 @@ def create_server(
|
|
|
277
296
|
|
|
278
297
|
@mcp.tool(
|
|
279
298
|
name="get_context_delta",
|
|
299
|
+
title=tool_title("get_context_delta"),
|
|
300
|
+
annotations=_tool_hints("get_context_delta"),
|
|
280
301
|
description=(
|
|
281
302
|
"Compare two read-only ContextBundle snapshots and return "
|
|
282
303
|
"notable_shifts between them. Requires prior_as_of; omit current_as_of "
|
|
@@ -307,6 +328,8 @@ def create_server(
|
|
|
307
328
|
|
|
308
329
|
@mcp.tool(
|
|
309
330
|
name="check_allocation_bands",
|
|
331
|
+
title=tool_title("check_allocation_bands"),
|
|
332
|
+
annotations=_tool_hints("check_allocation_bands"),
|
|
310
333
|
description=(
|
|
311
334
|
"Read-only batch drift check: evaluate allocation_pct against multiple "
|
|
312
335
|
"target_pct/band scenarios in one call. Each scenario requires "
|