spice-mcp 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of spice-mcp might be problematic. Click here for more details.
- spice_mcp-0.1.0/.factory/droids/agentic-documentation-systems-droid.md +16 -0
- spice_mcp-0.1.0/.factory/droids/development-workflow-optimization-droid.md +16 -0
- spice_mcp-0.1.0/.factory/droids/production-python-development-droid.md +18 -0
- spice_mcp-0.1.0/.factory/droids/temp-smoke-droid.md +8 -0
- spice_mcp-0.1.0/.github/workflows/ci.yml +144 -0
- spice_mcp-0.1.0/.gitignore +17 -0
- spice_mcp-0.1.0/.python-version +1 -0
- spice_mcp-0.1.0/CONTRIBUTING.md +27 -0
- spice_mcp-0.1.0/LICENSE +21 -0
- spice_mcp-0.1.0/PKG-INFO +133 -0
- spice_mcp-0.1.0/README.md +112 -0
- spice_mcp-0.1.0/bin/bat +18 -0
- spice_mcp-0.1.0/bin/fd +18 -0
- spice_mcp-0.1.0/debug_api.py +97 -0
- spice_mcp-0.1.0/docs/architecture.md +76 -0
- spice_mcp-0.1.0/docs/codex_cli.md +76 -0
- spice_mcp-0.1.0/docs/codex_cli_tools.md +63 -0
- spice_mcp-0.1.0/docs/commands.md +41 -0
- spice_mcp-0.1.0/docs/config.md +23 -0
- spice_mcp-0.1.0/docs/development.md +43 -0
- spice_mcp-0.1.0/docs/discovery.md +31 -0
- spice_mcp-0.1.0/docs/dune_api.md +34 -0
- spice_mcp-0.1.0/docs/index.md +14 -0
- spice_mcp-0.1.0/docs/installation.md +21 -0
- spice_mcp-0.1.0/docs/tools.md +101 -0
- spice_mcp-0.1.0/pyproject.toml +108 -0
- spice_mcp-0.1.0/pytest.ini +11 -0
- spice_mcp-0.1.0/scripts/codex_tools_doctor.sh +104 -0
- spice_mcp-0.1.0/src/spice_mcp/__init__.py +2 -0
- spice_mcp-0.1.0/src/spice_mcp/adapters/__init__.py +0 -0
- spice_mcp-0.1.0/src/spice_mcp/adapters/dune/__init__.py +10 -0
- spice_mcp-0.1.0/src/spice_mcp/adapters/dune/admin.py +94 -0
- spice_mcp-0.1.0/src/spice_mcp/adapters/dune/cache.py +185 -0
- spice_mcp-0.1.0/src/spice_mcp/adapters/dune/client.py +255 -0
- spice_mcp-0.1.0/src/spice_mcp/adapters/dune/extract.py +1461 -0
- spice_mcp-0.1.0/src/spice_mcp/adapters/dune/helpers.py +11 -0
- spice_mcp-0.1.0/src/spice_mcp/adapters/dune/transport.py +70 -0
- spice_mcp-0.1.0/src/spice_mcp/adapters/dune/types.py +52 -0
- spice_mcp-0.1.0/src/spice_mcp/adapters/dune/typing_utils.py +10 -0
- spice_mcp-0.1.0/src/spice_mcp/adapters/dune/urls.py +126 -0
- spice_mcp-0.1.0/src/spice_mcp/adapters/http_client.py +156 -0
- spice_mcp-0.1.0/src/spice_mcp/config.py +81 -0
- spice_mcp-0.1.0/src/spice_mcp/core/__init__.py +0 -0
- spice_mcp-0.1.0/src/spice_mcp/core/errors.py +101 -0
- spice_mcp-0.1.0/src/spice_mcp/core/models.py +88 -0
- spice_mcp-0.1.0/src/spice_mcp/core/ports.py +69 -0
- spice_mcp-0.1.0/src/spice_mcp/logging/query_history.py +131 -0
- spice_mcp-0.1.0/src/spice_mcp/mcp/__init__.py +1 -0
- spice_mcp-0.1.0/src/spice_mcp/mcp/server.py +546 -0
- spice_mcp-0.1.0/src/spice_mcp/mcp/tools/__init__.py +1 -0
- spice_mcp-0.1.0/src/spice_mcp/mcp/tools/base.py +41 -0
- spice_mcp-0.1.0/src/spice_mcp/mcp/tools/execute_query.py +425 -0
- spice_mcp-0.1.0/src/spice_mcp/mcp/tools/sui_package_overview.py +56 -0
- spice_mcp-0.1.0/src/spice_mcp/observability/__init__.py +0 -0
- spice_mcp-0.1.0/src/spice_mcp/observability/logging.py +18 -0
- spice_mcp-0.1.0/src/spice_mcp/polars_utils.py +15 -0
- spice_mcp-0.1.0/src/spice_mcp/py.typed +1 -0
- spice_mcp-0.1.0/src/spice_mcp/service_layer/__init__.py +0 -0
- spice_mcp-0.1.0/src/spice_mcp/service_layer/discovery_service.py +20 -0
- spice_mcp-0.1.0/src/spice_mcp/service_layer/query_admin_service.py +26 -0
- spice_mcp-0.1.0/src/spice_mcp/service_layer/query_service.py +118 -0
- spice_mcp-0.1.0/src/spice_mcp/service_layer/sui_service.py +131 -0
- spice_mcp-0.1.0/tests/cassettes/.gitkeep +1 -0
- spice_mcp-0.1.0/tests/config/environments.yaml +91 -0
- spice_mcp-0.1.0/tests/config/test_queries.yaml +259 -0
- spice_mcp-0.1.0/tests/conftest.py +13 -0
- spice_mcp-0.1.0/tests/fastmcp/test_resources_and_validation.py +49 -0
- spice_mcp-0.1.0/tests/fastmcp/test_server_fastmcp.py +122 -0
- spice_mcp-0.1.0/tests/fastmcp/test_server_mcp_extras.py +41 -0
- spice_mcp-0.1.0/tests/http_stubbed/test_age.py +28 -0
- spice_mcp-0.1.0/tests/http_stubbed/test_errors.py +75 -0
- spice_mcp-0.1.0/tests/http_stubbed/test_pagination.py +57 -0
- spice_mcp-0.1.0/tests/live/test_live_basic.py +18 -0
- spice_mcp-0.1.0/tests/live/test_live_sui.py +18 -0
- spice_mcp-0.1.0/tests/mcp/conftest.py +117 -0
- spice_mcp-0.1.0/tests/mcp/test_resources.py +53 -0
- spice_mcp-0.1.0/tests/mcp/test_tool_contracts.py +58 -0
- spice_mcp-0.1.0/tests/offline/test_cache.py +132 -0
- spice_mcp-0.1.0/tests/offline/test_discovery.py +79 -0
- spice_mcp-0.1.0/tests/offline/test_dune_adapter.py +115 -0
- spice_mcp-0.1.0/tests/offline/test_parsing.py +46 -0
- spice_mcp-0.1.0/tests/offline/test_query_history.py +54 -0
- spice_mcp-0.1.0/tests/offline/test_show_rewrite.py +24 -0
- spice_mcp-0.1.0/tests/offline/test_timeout.py +42 -0
- spice_mcp-0.1.0/tests/offline/test_urls.py +49 -0
- spice_mcp-0.1.0/tests/scripts/comprehensive_test_runner.py +164 -0
- spice_mcp-0.1.0/tests/scripts/run_tests.py +25 -0
- spice_mcp-0.1.0/tests/scripts/test_api_health.py +424 -0
- spice_mcp-0.1.0/tests/scripts/test_cache_functionality.py +197 -0
- spice_mcp-0.1.0/tests/scripts/test_data_types.py +727 -0
- spice_mcp-0.1.0/tests/scripts/test_dune_connectivity.py +93 -0
- spice_mcp-0.1.0/tests/scripts/test_dune_query_execution.py +170 -0
- spice_mcp-0.1.0/tests/scripts/test_error_handling.py +200 -0
- spice_mcp-0.1.0/tests/scripts/test_mcp_simulation.py +1167 -0
- spice_mcp-0.1.0/tests/scripts/test_mcp_tools.py +134 -0
- spice_mcp-0.1.0/tests/scripts/test_performance.py +654 -0
- spice_mcp-0.1.0/tests/scripts/test_query_lifecycle.py +534 -0
- spice_mcp-0.1.0/tests/scripts/test_resilience.py +945 -0
- spice_mcp-0.1.0/tests/scripts/test_resource_management.py +376 -0
- spice_mcp-0.1.0/tests/style/test_polars_lazy.py +53 -0
- spice_mcp-0.1.0/tests/support/api_client.py +231 -0
- spice_mcp-0.1.0/tests/support/helpers.py +350 -0
- spice_mcp-0.1.0/tests/support/query_factory.py +195 -0
- spice_mcp-0.1.0/tests/support/test_data.py +224 -0
- spice_mcp-0.1.0/tests/tools/test_additional_mcp_tools.py +82 -0
- spice_mcp-0.1.0/tests/tools/test_execute_query_tool.py +130 -0
- spice_mcp-0.1.0/tests/tools/test_health_tool.py +21 -0
- spice_mcp-0.1.0/tests/tools/test_query_service.py +55 -0
- spice_mcp-0.1.0/tests/tools/test_schemas.py +36 -0
- spice_mcp-0.1.0/uv.lock +1502 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: agentic-documentation-systems-droid
|
|
3
|
+
description: Documentation reviewer focused on agent-ready knowledge systems.
|
|
4
|
+
model: inherit
|
|
5
|
+
tools: ["Read", "LS", "Grep", "Glob"]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
You are a documentation specialist. Analyze README and docs with read-only tools and propose minimal, focused updates.
|
|
9
|
+
Keep suggestions path-specific and concise; do not write full docs unless asked.
|
|
10
|
+
|
|
11
|
+
Output:
|
|
12
|
+
Summary: <one line>
|
|
13
|
+
Findings:
|
|
14
|
+
- <path>: <gap/issue>
|
|
15
|
+
Suggestions:
|
|
16
|
+
- <small change>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: development-workflow-optimization-droid
|
|
3
|
+
description: Reviews engineering workflows and automation practices.
|
|
4
|
+
model: inherit
|
|
5
|
+
tools: ["Read", "LS", "Grep", "Glob"]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
You are a workflow strategist. Inspect CI/workflows and repo automation using read-only tools.
|
|
9
|
+
Respond with a concise, path-referenced assessment and concrete changes to apply.
|
|
10
|
+
|
|
11
|
+
Output:
|
|
12
|
+
Summary: <one line>
|
|
13
|
+
Observations:
|
|
14
|
+
- <path>: <issue/opportunity>
|
|
15
|
+
Recommendations:
|
|
16
|
+
- <change>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: production-python-development-droid
|
|
3
|
+
description: Python reviewer focused on maintainability, testing, and ergonomics.
|
|
4
|
+
model: inherit
|
|
5
|
+
tools: ["Read", "LS", "Grep", "Glob"]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
You are a senior Python engineer. Do research-only analysis using the allowed tools.
|
|
9
|
+
Requirements:
|
|
10
|
+
- Keep outputs concise; cite concrete file paths for all findings.
|
|
11
|
+
- No edits or shell commands; summarize config/state and recommend minimal diffs.
|
|
12
|
+
|
|
13
|
+
Respond with:
|
|
14
|
+
Summary: <one line>
|
|
15
|
+
Findings:
|
|
16
|
+
- <path>: <note>
|
|
17
|
+
Recommendations:
|
|
18
|
+
- <action>
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
pull_request:
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
lint:
|
|
12
|
+
name: ruff (Python ${{ matrix.python-version }})
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
timeout-minutes: 15
|
|
15
|
+
strategy:
|
|
16
|
+
fail-fast: false
|
|
17
|
+
matrix:
|
|
18
|
+
python-version: ["3.13"]
|
|
19
|
+
|
|
20
|
+
steps:
|
|
21
|
+
- name: Check out
|
|
22
|
+
uses: actions/checkout@v4
|
|
23
|
+
|
|
24
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
25
|
+
uses: actions/setup-python@v5
|
|
26
|
+
with:
|
|
27
|
+
python-version: ${{ matrix.python-version }}
|
|
28
|
+
|
|
29
|
+
- name: Cache uv
|
|
30
|
+
uses: actions/cache@v4
|
|
31
|
+
with:
|
|
32
|
+
path: ~/.cache/uv
|
|
33
|
+
key: ${{ runner.os }}-uv-${{ matrix.python-version }}-${{ hashFiles('uv.lock') }}
|
|
34
|
+
restore-keys: |
|
|
35
|
+
${{ runner.os }}-uv-${{ matrix.python-version }}-
|
|
36
|
+
|
|
37
|
+
- name: Cache ruff cache
|
|
38
|
+
uses: actions/cache@v4
|
|
39
|
+
with:
|
|
40
|
+
path: .ruff_cache
|
|
41
|
+
key: ${{ runner.os }}-ruff-${{ matrix.python-version }}-${{ hashFiles('pyproject.toml') }}
|
|
42
|
+
restore-keys: |
|
|
43
|
+
${{ runner.os }}-ruff-${{ matrix.python-version }}-
|
|
44
|
+
|
|
45
|
+
- name: Install uv
|
|
46
|
+
uses: astral-sh/setup-uv@v5
|
|
47
|
+
|
|
48
|
+
- name: Install dependencies (uv)
|
|
49
|
+
run: |
|
|
50
|
+
uv --version
|
|
51
|
+
uv sync --frozen --dev
|
|
52
|
+
|
|
53
|
+
- name: Ruff lint
|
|
54
|
+
run: uv run ruff check --output-format=github --color always .
|
|
55
|
+
|
|
56
|
+
typecheck:
|
|
57
|
+
name: mypy (Python ${{ matrix.python-version }})
|
|
58
|
+
runs-on: ubuntu-latest
|
|
59
|
+
timeout-minutes: 20
|
|
60
|
+
strategy:
|
|
61
|
+
fail-fast: false
|
|
62
|
+
matrix:
|
|
63
|
+
python-version: ["3.13"]
|
|
64
|
+
|
|
65
|
+
steps:
|
|
66
|
+
- name: Check out
|
|
67
|
+
uses: actions/checkout@v4
|
|
68
|
+
|
|
69
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
70
|
+
uses: actions/setup-python@v5
|
|
71
|
+
with:
|
|
72
|
+
python-version: ${{ matrix.python-version }}
|
|
73
|
+
|
|
74
|
+
- name: Cache uv
|
|
75
|
+
uses: actions/cache@v4
|
|
76
|
+
with:
|
|
77
|
+
path: ~/.cache/uv
|
|
78
|
+
key: ${{ runner.os }}-uv-${{ matrix.python-version }}-${{ hashFiles('uv.lock') }}
|
|
79
|
+
restore-keys: |
|
|
80
|
+
${{ runner.os }}-uv-${{ matrix.python-version }}-
|
|
81
|
+
|
|
82
|
+
- name: Cache mypy cache
|
|
83
|
+
uses: actions/cache@v4
|
|
84
|
+
with:
|
|
85
|
+
path: .mypy_cache
|
|
86
|
+
key: ${{ runner.os }}-mypy-${{ matrix.python-version }}-${{ hashFiles('pyproject.toml') }}
|
|
87
|
+
restore-keys: |
|
|
88
|
+
${{ runner.os }}-mypy-${{ matrix.python-version }}-
|
|
89
|
+
|
|
90
|
+
- name: Install uv
|
|
91
|
+
uses: astral-sh/setup-uv@v5
|
|
92
|
+
|
|
93
|
+
- name: Install dependencies (uv)
|
|
94
|
+
run: |
|
|
95
|
+
uv --version
|
|
96
|
+
uv sync --frozen --dev
|
|
97
|
+
|
|
98
|
+
- name: mypy
|
|
99
|
+
env:
|
|
100
|
+
MYPY_CACHE_DIR: .mypy_cache
|
|
101
|
+
run: uv run mypy --pretty --color-output --show-error-codes .
|
|
102
|
+
|
|
103
|
+
test:
|
|
104
|
+
name: pytest (Python ${{ matrix.python-version }})
|
|
105
|
+
runs-on: ubuntu-latest
|
|
106
|
+
timeout-minutes: 30
|
|
107
|
+
strategy:
|
|
108
|
+
fail-fast: false
|
|
109
|
+
matrix:
|
|
110
|
+
python-version: ["3.13"]
|
|
111
|
+
|
|
112
|
+
steps:
|
|
113
|
+
- name: Check out
|
|
114
|
+
uses: actions/checkout@v4
|
|
115
|
+
|
|
116
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
117
|
+
uses: actions/setup-python@v5
|
|
118
|
+
with:
|
|
119
|
+
python-version: ${{ matrix.python-version }}
|
|
120
|
+
|
|
121
|
+
- name: Cache uv
|
|
122
|
+
uses: actions/cache@v4
|
|
123
|
+
with:
|
|
124
|
+
path: ~/.cache/uv
|
|
125
|
+
key: ${{ runner.os }}-uv-${{ matrix.python-version }}-${{ hashFiles('uv.lock') }}
|
|
126
|
+
restore-keys: |
|
|
127
|
+
${{ runner.os }}-uv-${{ matrix.python-version }}-
|
|
128
|
+
|
|
129
|
+
- name: Install uv
|
|
130
|
+
uses: astral-sh/setup-uv@v5
|
|
131
|
+
|
|
132
|
+
- name: Install dependencies (uv)
|
|
133
|
+
run: |
|
|
134
|
+
uv --version
|
|
135
|
+
uv sync --frozen --dev
|
|
136
|
+
|
|
137
|
+
- name: Run tests (skip live) with coverage
|
|
138
|
+
env:
|
|
139
|
+
PYTHONUNBUFFERED: "1"
|
|
140
|
+
SPICE_MCP_SKIP_DOTENV: "1"
|
|
141
|
+
run: |
|
|
142
|
+
uv run pytest -m "not live" -ra --color=yes \
|
|
143
|
+
--durations=10 \
|
|
144
|
+
--cov=src/spice_mcp --cov-report=term-missing:skip-covered --cov-report=xml
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.13.1
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
## Contributing to spice-mcp
|
|
2
|
+
|
|
3
|
+
Thanks for your interest in contributing! This is a lightweight guide to get you productive quickly.
|
|
4
|
+
|
|
5
|
+
### Setup
|
|
6
|
+
- Python 3.13+
|
|
7
|
+
- Install dependencies:
|
|
8
|
+
- Using uv: `uv sync`
|
|
9
|
+
- Or pip: `pip install -e . && pip install -r <(python - <<'PY'\nimport tomllib,sys;print('\n'.join(tomllib.load(open('pyproject.toml','rb'))['tool']['rye']['dev-dependencies']))\nPY\n)`
|
|
10
|
+
|
|
11
|
+
### Running the server
|
|
12
|
+
- `python -m spice_mcp.mcp.server --env PYTHONPATH=$(pwd)/src`
|
|
13
|
+
- Or `spice-mcp` if installed as a console script
|
|
14
|
+
|
|
15
|
+
### Tests
|
|
16
|
+
- Tiered runner: `python tests/scripts/comprehensive_test_runner.py [-t 1 -t 3] [--stop] [--junit out.xml]`
|
|
17
|
+
- Pytest quick run (offline): `uv run pytest -q -m "not live"`
|
|
18
|
+
- Live tests: `export SPICE_TEST_LIVE=1 DUNE_API_KEY=...` then run as above
|
|
19
|
+
|
|
20
|
+
### Linting / Type checks
|
|
21
|
+
- Ruff: `uv run ruff check . && uv run ruff format .`
|
|
22
|
+
- MyPy (optional relaxed config): `uv run mypy`
|
|
23
|
+
|
|
24
|
+
### Pull requests
|
|
25
|
+
- Keep changes focused, add/adjust tests when possible
|
|
26
|
+
- Ensure no secrets are committed (`.env` is ignored and required for keys)
|
|
27
|
+
- Follow existing code style and patterns; avoid gratuitous new deps
|
spice_mcp-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Spice MCP contributors
|
|
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.
|
spice_mcp-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: spice-mcp
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: MCP server for Dune Analytics data access
|
|
5
|
+
Author-email: Evan-Kim2028 <ekcopersonal@gmail.com>
|
|
6
|
+
License-File: LICENSE
|
|
7
|
+
Classifier: Operating System :: OS Independent
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
11
|
+
Classifier: Typing :: Typed
|
|
12
|
+
Requires-Python: >=3.13
|
|
13
|
+
Requires-Dist: aiohttp>=3.9.5
|
|
14
|
+
Requires-Dist: fastmcp>=0.3.0
|
|
15
|
+
Requires-Dist: mcp>=0.9.0
|
|
16
|
+
Requires-Dist: polars>=1.35.1
|
|
17
|
+
Requires-Dist: requests>=2.31.0
|
|
18
|
+
Requires-Dist: rich-argparse>=1.5.2
|
|
19
|
+
Requires-Dist: rich>=13.3.3
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
|
|
22
|
+
# spice-mcp
|
|
23
|
+
|
|
24
|
+
spice-mcp is an MCP server for Dune Analytics. It wraps a curated subset of the original Spice client inside a clean architecture (`core` models/ports ā `adapters.dune` ā service layer ā FastMCP tools) and adds agent-friendly workflows for discovery and Sui package exploration. Results are Polars-first in Python and compact, token-efficient in MCP responses.
|
|
25
|
+
|
|
26
|
+
Requirements: Python 3.13+
|
|
27
|
+
|
|
28
|
+
This project uses FastMCP for typed, decorator-registered tools and resources.
|
|
29
|
+
|
|
30
|
+
Highlights
|
|
31
|
+
- Polars LazyFrame-first pipeline: results stay lazy until explicitly materialized
|
|
32
|
+
- Ports/adapters layering for maintainable integrations (`docs/architecture.md`)
|
|
33
|
+
- Discovery utilities (find schemas/tables, describe columns)
|
|
34
|
+
- Sui package workflows (events/transactions/objects) with safe defaults
|
|
35
|
+
- JSONL query history + SQL artifacts (SHA-256) for reproducibility
|
|
36
|
+
- Rich MCP surface: query info/run, discovery, health, Sui, and Dune admin (create/update/fork)
|
|
37
|
+
|
|
38
|
+
Quick Start
|
|
39
|
+
- Export `DUNE_API_KEY` in your shell (the server can also load a local `.env`; set `SPICE_MCP_SKIP_DOTENV=1` to skip during tests).
|
|
40
|
+
- Install dependencies (`uv sync` or `pip install -e .`).
|
|
41
|
+
- Start the FastMCP stdio server:
|
|
42
|
+
- `python -m spice_mcp.mcp.server --env PYTHONPATH=$(pwd)/src`
|
|
43
|
+
- or install the console script via `uv tool install .` and run `spice-mcp`.
|
|
44
|
+
|
|
45
|
+
## MCP Tools and Features
|
|
46
|
+
|
|
47
|
+
All tools expose typed parameters, titles, and tags; failures return a consistent error envelope.
|
|
48
|
+
|
|
49
|
+
- `dune_query_info` (Query Info, tags: dune, query)
|
|
50
|
+
- Fetch saved-query metadata by ID/URL (name, parameters, tags, SQL, version).
|
|
51
|
+
|
|
52
|
+
- `dune_query` (Run Dune Query, tags: dune, query)
|
|
53
|
+
- Execute by ID/URL/raw SQL with parameters. Supports `refresh`, `max_age`, `limit/offset`, `sample_count`, `sort_by`, `columns`, and `format` = `preview|raw|metadata|poll`; accepts `timeout_seconds`.
|
|
54
|
+
|
|
55
|
+
- `dune_health_check` (Health Check, tag: health)
|
|
56
|
+
- Checks API key presence, query-history path, logging enabled; best-effort template check when configured.
|
|
57
|
+
|
|
58
|
+
- `dune_find_tables` (Find Tables, tags: dune, schema)
|
|
59
|
+
- Search schemas by keyword and/or list tables in a schema (`limit`).
|
|
60
|
+
|
|
61
|
+
- `dune_describe_table` (Describe Table, tags: dune, schema)
|
|
62
|
+
- Column metadata for `schema.table` (Dune types + Polars inferred dtypes when available).
|
|
63
|
+
|
|
64
|
+
- `sui_package_overview` (Sui Package Overview, tag: sui)
|
|
65
|
+
- Compact Sui activity overview for `packages[]` with `hours` (default 72) and `timeout_seconds`.
|
|
66
|
+
|
|
67
|
+
- Dune Admin tools (tags: dune, admin)
|
|
68
|
+
- `dune_query_create(name, query_sql, description?, tags?, parameters?)`
|
|
69
|
+
- `dune_query_update(query_id, name?, query_sql?, description?, tags?, parameters?)`
|
|
70
|
+
- `dune_query_fork(source_query_id, name?)`
|
|
71
|
+
|
|
72
|
+
### Resources
|
|
73
|
+
- `spice:history/tail/{n}` ā tail last N lines of query history (1..1000)
|
|
74
|
+
- `spice:artifact/{sha}` ā fetch stored SQL by 64-hex SHA-256
|
|
75
|
+
- `spice:sui/events_preview/{hours}/{limit}/{packages}` ā Sui events preview (JSON)
|
|
76
|
+
- `spice:sui/package_overview/{hours}/{timeout_seconds}/{packages}` ā Sui overview (JSON)
|
|
77
|
+
|
|
78
|
+
## Resources
|
|
79
|
+
|
|
80
|
+
- `spice:history/tail/{n}`
|
|
81
|
+
- Last `n` lines from the query-history JSONL, clamped to [1, 1000]
|
|
82
|
+
|
|
83
|
+
- `spice:artifact/{sha}`
|
|
84
|
+
- Returns stored SQL for the SHA-256 (validated as 64 lowercase hex)
|
|
85
|
+
|
|
86
|
+
Tests
|
|
87
|
+
- Offline/unit tests (no network) live under `tests/offline/` and `tests/http_stubbed/`.
|
|
88
|
+
- Live tests under `tests/live/` are skipped by default; enable with `SPICE_TEST_LIVE=1` and a valid `DUNE_API_KEY`.
|
|
89
|
+
- Comprehensive scripted runner (tiered):
|
|
90
|
+
- Run all tiers: `python tests/scripts/comprehensive_test_runner.py`
|
|
91
|
+
- Select tiers: `python tests/scripts/comprehensive_test_runner.py -t 1 -t 3`
|
|
92
|
+
- Stop on first failure: `python tests/scripts/comprehensive_test_runner.py --stop`
|
|
93
|
+
- Optional JUnit export: `python tests/scripts/comprehensive_test_runner.py --junit tests/scripts/report.xml`
|
|
94
|
+
- Pytest directly (offline/default): `uv run pytest -q -m "not live" --cov=src/spice_mcp --cov-report=term-missing`
|
|
95
|
+
|
|
96
|
+
Core Tools (with parameters)
|
|
97
|
+
- `dune_query`
|
|
98
|
+
- Use: Preview/query results by ID, URL, or raw SQL (Polars preview + Dune metadata/pagination).
|
|
99
|
+
- Params: `query` (string), `parameters?` (object), `performance?` ('medium'|'large'), `limit?` (int), `offset?` (int), `sort_by?` (string), `columns?` (string[]), `sample_count?` (int), `refresh?` (bool), `max_age?` (number), `timeout_seconds?` (number), `format?` ('preview'|'raw'|'metadata').
|
|
100
|
+
- Output: `type`, `rowcount`, `columns`, `data_preview`, `execution_id`, `duration_ms`, `metadata?`, `next_uri?`, `next_offset?`.
|
|
101
|
+
- `dune_find_tables`
|
|
102
|
+
- Use: Search schemas by keyword and/or list tables for a schema.
|
|
103
|
+
- Params: `keyword?` (string), `schema?` (string), `limit?` (int)
|
|
104
|
+
- Output: `schemas?` (string[]), `tables?` (string[])
|
|
105
|
+
- `dune_describe_table`
|
|
106
|
+
- Use: Column descriptions for `schema.table` via SHOW + fallback to 1-row sample inference.
|
|
107
|
+
- Params: `schema` (string), `table` (string)
|
|
108
|
+
- Output: `columns` ([{ name, dune_type?, polars_dtype?, extra?, comment? }])
|
|
109
|
+
- `sui_package_overview`
|
|
110
|
+
- Use: Small-window overview for Sui packages (events/transactions/objects) with timeout handling.
|
|
111
|
+
- Params: `packages` (string[]), `hours?` (int, default 72), `timeout_seconds?` (number, default 30)
|
|
112
|
+
- Output: best-effort counts and previews; may include `*_timeout`/`*_error`
|
|
113
|
+
- `dune_health_check`
|
|
114
|
+
- Use: Verify API key presence and logging paths
|
|
115
|
+
- Output: `api_key_present`, `query_history_path`, `logging_enabled`, `status`
|
|
116
|
+
|
|
117
|
+
Docs
|
|
118
|
+
- See `docs/index.md` for full documentation:
|
|
119
|
+
- Dune API structure and capabilities: `docs/dune_api.md`
|
|
120
|
+
- Discovery patterns and examples: `docs/discovery.md`
|
|
121
|
+
- Sui package workflows: `docs/sui_packages.md`
|
|
122
|
+
- Tool reference and schemas: `docs/tools.md`
|
|
123
|
+
- Codex CLI + tooling integration: `docs/codex_cli.md`, `docs/codex_cli_tools.md`
|
|
124
|
+
- Architecture overview: `docs/architecture.md`
|
|
125
|
+
- Installation and configuration: `docs/installation.md`, `docs/config.md`
|
|
126
|
+
- Development and linting: `docs/development.md`
|
|
127
|
+
|
|
128
|
+
Notes
|
|
129
|
+
- Legacy Spice code now lives under `src/spice_mcp/adapters/dune` (extract, cache, urls, types).
|
|
130
|
+
- Ports and models live in `src/spice_mcp/core`; services consume ports and are exercised by FastMCP tools.
|
|
131
|
+
- Query history and SQL artefacts are always-on (see `src/spice_mcp/logging/query_history.py`).
|
|
132
|
+
- To bypass dot-env loading during tests/CI, export `SPICE_MCP_SKIP_DOTENV=1`.
|
|
133
|
+
- LazyFrames everywhere: eager `.collect()` or `pl.DataFrame` usage outside dedicated helpers is blocked by `tests/style/test_polars_lazy.py`; materialization helpers live in `src/spice_mcp/polars_utils.py`.
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# spice-mcp
|
|
2
|
+
|
|
3
|
+
spice-mcp is an MCP server for Dune Analytics. It wraps a curated subset of the original Spice client inside a clean architecture (`core` models/ports ā `adapters.dune` ā service layer ā FastMCP tools) and adds agent-friendly workflows for discovery and Sui package exploration. Results are Polars-first in Python and compact, token-efficient in MCP responses.
|
|
4
|
+
|
|
5
|
+
Requirements: Python 3.13+
|
|
6
|
+
|
|
7
|
+
This project uses FastMCP for typed, decorator-registered tools and resources.
|
|
8
|
+
|
|
9
|
+
Highlights
|
|
10
|
+
- Polars LazyFrame-first pipeline: results stay lazy until explicitly materialized
|
|
11
|
+
- Ports/adapters layering for maintainable integrations (`docs/architecture.md`)
|
|
12
|
+
- Discovery utilities (find schemas/tables, describe columns)
|
|
13
|
+
- Sui package workflows (events/transactions/objects) with safe defaults
|
|
14
|
+
- JSONL query history + SQL artifacts (SHA-256) for reproducibility
|
|
15
|
+
- Rich MCP surface: query info/run, discovery, health, Sui, and Dune admin (create/update/fork)
|
|
16
|
+
|
|
17
|
+
Quick Start
|
|
18
|
+
- Export `DUNE_API_KEY` in your shell (the server can also load a local `.env`; set `SPICE_MCP_SKIP_DOTENV=1` to skip during tests).
|
|
19
|
+
- Install dependencies (`uv sync` or `pip install -e .`).
|
|
20
|
+
- Start the FastMCP stdio server:
|
|
21
|
+
- `python -m spice_mcp.mcp.server --env PYTHONPATH=$(pwd)/src`
|
|
22
|
+
- or install the console script via `uv tool install .` and run `spice-mcp`.
|
|
23
|
+
|
|
24
|
+
## MCP Tools and Features
|
|
25
|
+
|
|
26
|
+
All tools expose typed parameters, titles, and tags; failures return a consistent error envelope.
|
|
27
|
+
|
|
28
|
+
- `dune_query_info` (Query Info, tags: dune, query)
|
|
29
|
+
- Fetch saved-query metadata by ID/URL (name, parameters, tags, SQL, version).
|
|
30
|
+
|
|
31
|
+
- `dune_query` (Run Dune Query, tags: dune, query)
|
|
32
|
+
- Execute by ID/URL/raw SQL with parameters. Supports `refresh`, `max_age`, `limit/offset`, `sample_count`, `sort_by`, `columns`, and `format` = `preview|raw|metadata|poll`; accepts `timeout_seconds`.
|
|
33
|
+
|
|
34
|
+
- `dune_health_check` (Health Check, tag: health)
|
|
35
|
+
- Checks API key presence, query-history path, logging enabled; best-effort template check when configured.
|
|
36
|
+
|
|
37
|
+
- `dune_find_tables` (Find Tables, tags: dune, schema)
|
|
38
|
+
- Search schemas by keyword and/or list tables in a schema (`limit`).
|
|
39
|
+
|
|
40
|
+
- `dune_describe_table` (Describe Table, tags: dune, schema)
|
|
41
|
+
- Column metadata for `schema.table` (Dune types + Polars inferred dtypes when available).
|
|
42
|
+
|
|
43
|
+
- `sui_package_overview` (Sui Package Overview, tag: sui)
|
|
44
|
+
- Compact Sui activity overview for `packages[]` with `hours` (default 72) and `timeout_seconds`.
|
|
45
|
+
|
|
46
|
+
- Dune Admin tools (tags: dune, admin)
|
|
47
|
+
- `dune_query_create(name, query_sql, description?, tags?, parameters?)`
|
|
48
|
+
- `dune_query_update(query_id, name?, query_sql?, description?, tags?, parameters?)`
|
|
49
|
+
- `dune_query_fork(source_query_id, name?)`
|
|
50
|
+
|
|
51
|
+
### Resources
|
|
52
|
+
- `spice:history/tail/{n}` ā tail last N lines of query history (1..1000)
|
|
53
|
+
- `spice:artifact/{sha}` ā fetch stored SQL by 64-hex SHA-256
|
|
54
|
+
- `spice:sui/events_preview/{hours}/{limit}/{packages}` ā Sui events preview (JSON)
|
|
55
|
+
- `spice:sui/package_overview/{hours}/{timeout_seconds}/{packages}` ā Sui overview (JSON)
|
|
56
|
+
|
|
57
|
+
## Resources
|
|
58
|
+
|
|
59
|
+
- `spice:history/tail/{n}`
|
|
60
|
+
- Last `n` lines from the query-history JSONL, clamped to [1, 1000]
|
|
61
|
+
|
|
62
|
+
- `spice:artifact/{sha}`
|
|
63
|
+
- Returns stored SQL for the SHA-256 (validated as 64 lowercase hex)
|
|
64
|
+
|
|
65
|
+
Tests
|
|
66
|
+
- Offline/unit tests (no network) live under `tests/offline/` and `tests/http_stubbed/`.
|
|
67
|
+
- Live tests under `tests/live/` are skipped by default; enable with `SPICE_TEST_LIVE=1` and a valid `DUNE_API_KEY`.
|
|
68
|
+
- Comprehensive scripted runner (tiered):
|
|
69
|
+
- Run all tiers: `python tests/scripts/comprehensive_test_runner.py`
|
|
70
|
+
- Select tiers: `python tests/scripts/comprehensive_test_runner.py -t 1 -t 3`
|
|
71
|
+
- Stop on first failure: `python tests/scripts/comprehensive_test_runner.py --stop`
|
|
72
|
+
- Optional JUnit export: `python tests/scripts/comprehensive_test_runner.py --junit tests/scripts/report.xml`
|
|
73
|
+
- Pytest directly (offline/default): `uv run pytest -q -m "not live" --cov=src/spice_mcp --cov-report=term-missing`
|
|
74
|
+
|
|
75
|
+
Core Tools (with parameters)
|
|
76
|
+
- `dune_query`
|
|
77
|
+
- Use: Preview/query results by ID, URL, or raw SQL (Polars preview + Dune metadata/pagination).
|
|
78
|
+
- Params: `query` (string), `parameters?` (object), `performance?` ('medium'|'large'), `limit?` (int), `offset?` (int), `sort_by?` (string), `columns?` (string[]), `sample_count?` (int), `refresh?` (bool), `max_age?` (number), `timeout_seconds?` (number), `format?` ('preview'|'raw'|'metadata').
|
|
79
|
+
- Output: `type`, `rowcount`, `columns`, `data_preview`, `execution_id`, `duration_ms`, `metadata?`, `next_uri?`, `next_offset?`.
|
|
80
|
+
- `dune_find_tables`
|
|
81
|
+
- Use: Search schemas by keyword and/or list tables for a schema.
|
|
82
|
+
- Params: `keyword?` (string), `schema?` (string), `limit?` (int)
|
|
83
|
+
- Output: `schemas?` (string[]), `tables?` (string[])
|
|
84
|
+
- `dune_describe_table`
|
|
85
|
+
- Use: Column descriptions for `schema.table` via SHOW + fallback to 1-row sample inference.
|
|
86
|
+
- Params: `schema` (string), `table` (string)
|
|
87
|
+
- Output: `columns` ([{ name, dune_type?, polars_dtype?, extra?, comment? }])
|
|
88
|
+
- `sui_package_overview`
|
|
89
|
+
- Use: Small-window overview for Sui packages (events/transactions/objects) with timeout handling.
|
|
90
|
+
- Params: `packages` (string[]), `hours?` (int, default 72), `timeout_seconds?` (number, default 30)
|
|
91
|
+
- Output: best-effort counts and previews; may include `*_timeout`/`*_error`
|
|
92
|
+
- `dune_health_check`
|
|
93
|
+
- Use: Verify API key presence and logging paths
|
|
94
|
+
- Output: `api_key_present`, `query_history_path`, `logging_enabled`, `status`
|
|
95
|
+
|
|
96
|
+
Docs
|
|
97
|
+
- See `docs/index.md` for full documentation:
|
|
98
|
+
- Dune API structure and capabilities: `docs/dune_api.md`
|
|
99
|
+
- Discovery patterns and examples: `docs/discovery.md`
|
|
100
|
+
- Sui package workflows: `docs/sui_packages.md`
|
|
101
|
+
- Tool reference and schemas: `docs/tools.md`
|
|
102
|
+
- Codex CLI + tooling integration: `docs/codex_cli.md`, `docs/codex_cli_tools.md`
|
|
103
|
+
- Architecture overview: `docs/architecture.md`
|
|
104
|
+
- Installation and configuration: `docs/installation.md`, `docs/config.md`
|
|
105
|
+
- Development and linting: `docs/development.md`
|
|
106
|
+
|
|
107
|
+
Notes
|
|
108
|
+
- Legacy Spice code now lives under `src/spice_mcp/adapters/dune` (extract, cache, urls, types).
|
|
109
|
+
- Ports and models live in `src/spice_mcp/core`; services consume ports and are exercised by FastMCP tools.
|
|
110
|
+
- Query history and SQL artefacts are always-on (see `src/spice_mcp/logging/query_history.py`).
|
|
111
|
+
- To bypass dot-env loading during tests/CI, export `SPICE_MCP_SKIP_DOTENV=1`.
|
|
112
|
+
- LazyFrames everywhere: eager `.collect()` or `pl.DataFrame` usage outside dedicated helpers is blocked by `tests/style/test_polars_lazy.py`; materialization helpers live in `src/spice_mcp/polars_utils.py`.
|
spice_mcp-0.1.0/bin/bat
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Wrapper to provide a consistent `bat` command across distros.
|
|
3
|
+
# On Debian/Ubuntu the binary may be `batcat`.
|
|
4
|
+
set -euo pipefail
|
|
5
|
+
|
|
6
|
+
if command -v bat >/dev/null 2>&1; then
|
|
7
|
+
exec bat "$@"
|
|
8
|
+
elif command -v batcat >/dev/null 2>&1; then
|
|
9
|
+
exec batcat "$@"
|
|
10
|
+
else
|
|
11
|
+
echo "bat (or batcat) is not installed. Suggested installs:" >&2
|
|
12
|
+
echo " macOS: brew install bat" >&2
|
|
13
|
+
echo " Ubuntu: sudo apt install bat && sudo update-alternatives --set bat \$(command -v batcat) || echo 'Use batcat instead'" >&2
|
|
14
|
+
echo " Arch: sudo pacman -S bat" >&2
|
|
15
|
+
echo " Fedora: sudo dnf install bat" >&2
|
|
16
|
+
exit 127
|
|
17
|
+
fi
|
|
18
|
+
|
spice_mcp-0.1.0/bin/fd
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Wrapper to provide a consistent `fd` command across distros.
|
|
3
|
+
# On Debian/Ubuntu the binary may be `fdfind`.
|
|
4
|
+
set -euo pipefail
|
|
5
|
+
|
|
6
|
+
if command -v fd >/dev/null 2>&1; then
|
|
7
|
+
exec fd "$@"
|
|
8
|
+
elif command -v fdfind >/dev/null 2>&1; then
|
|
9
|
+
exec fdfind "$@"
|
|
10
|
+
else
|
|
11
|
+
echo "fd (or fdfind) is not installed. Suggested installs:" >&2
|
|
12
|
+
echo " macOS: brew install fd" >&2
|
|
13
|
+
echo " Ubuntu: sudo apt install fd-find && sudo ln -s \$(command -v fdfind) /usr/local/bin/fd" >&2
|
|
14
|
+
echo " Arch: sudo pacman -S fd" >&2
|
|
15
|
+
echo " Fedora: sudo dnf install fd-find" >&2
|
|
16
|
+
exit 127
|
|
17
|
+
fi
|
|
18
|
+
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Debug script to figure out what's happening with the Dune API calls.
|
|
4
|
+
"""
|
|
5
|
+
import os
|
|
6
|
+
import sys
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
# Add src to path
|
|
10
|
+
src_path = Path('src')
|
|
11
|
+
sys.path.insert(0, str(src_path))
|
|
12
|
+
|
|
13
|
+
from spice_mcp.adapters.dune import urls, transport
|
|
14
|
+
|
|
15
|
+
def test_dune_connection():
|
|
16
|
+
"""Test API connectivity directly."""
|
|
17
|
+
print("š§ Debugging Dune API connection...")
|
|
18
|
+
|
|
19
|
+
api_key = os.getenv("DUNE_API_KEY")
|
|
20
|
+
print(f"API key: {api_key[:8] if api_key else 'None'}...")
|
|
21
|
+
|
|
22
|
+
try:
|
|
23
|
+
# Test1: Check headers
|
|
24
|
+
headers = urls.get_headers(api_key=api_key)
|
|
25
|
+
print(f"Headers: {headers}")
|
|
26
|
+
|
|
27
|
+
# Test2: Simple URL construction
|
|
28
|
+
url = urls.get_query_execute_url("SELECT 1 as test")
|
|
29
|
+
print(f"URL for raw SQL: {url}")
|
|
30
|
+
|
|
31
|
+
# Test3: Try a direct API call
|
|
32
|
+
print("\nš” Testing direct API call...")
|
|
33
|
+
test_url = urls.url_templates['query_create']
|
|
34
|
+
print(f"Test URL: {test_url}")
|
|
35
|
+
|
|
36
|
+
response = transport.post(
|
|
37
|
+
test_url,
|
|
38
|
+
headers=headers,
|
|
39
|
+
json={
|
|
40
|
+
"query_sql": "SELECT 1 as test_col",
|
|
41
|
+
"name": "debug_test",
|
|
42
|
+
"dataset": "preview",
|
|
43
|
+
"is_private": True
|
|
44
|
+
},
|
|
45
|
+
timeout=10.0
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
print(f"Response status: {response.status_code}")
|
|
49
|
+
print(f"Response: {response.text[:200]}...")
|
|
50
|
+
|
|
51
|
+
if response.status_code == 200:
|
|
52
|
+
data = response.json()
|
|
53
|
+
query_id = data.get('query_id')
|
|
54
|
+
print(f"ā Created query with ID: {query_id}")
|
|
55
|
+
|
|
56
|
+
# Now try to execute it
|
|
57
|
+
execute_url = urls.get_query_execute_url(query_id)
|
|
58
|
+
execute_response = transport.post(
|
|
59
|
+
execute_url,
|
|
60
|
+
headers=headers,
|
|
61
|
+
json={
|
|
62
|
+
"performance": "medium",
|
|
63
|
+
"query_parameters": {}
|
|
64
|
+
},
|
|
65
|
+
timeout=10.0
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
print(f"Execute response status: {execute_response.status_code}")
|
|
69
|
+
print(f"Execute response: {execute_response.text[:200]}...")
|
|
70
|
+
|
|
71
|
+
if execute_response.status_code == 200:
|
|
72
|
+
exec_data = execute_response.json()
|
|
73
|
+
execution_id = exec_data.get('execution_id')
|
|
74
|
+
print(f"ā Created execution with ID: {execution_id}")
|
|
75
|
+
return True
|
|
76
|
+
|
|
77
|
+
return False
|
|
78
|
+
|
|
79
|
+
except Exception as e:
|
|
80
|
+
print(f"ā Error: {e}")
|
|
81
|
+
import traceback
|
|
82
|
+
traceback.print_exc()
|
|
83
|
+
return False
|
|
84
|
+
|
|
85
|
+
if __name__ == "__main__":
|
|
86
|
+
# Load env
|
|
87
|
+
env_file = Path('.env')
|
|
88
|
+
if env_file.exists():
|
|
89
|
+
with open(env_file) as f:
|
|
90
|
+
for line in f:
|
|
91
|
+
line = line.strip()
|
|
92
|
+
if line and not line.startswith("#") and "=" in line:
|
|
93
|
+
key, value = line.split("=", 1)
|
|
94
|
+
os.environ[key] = value
|
|
95
|
+
|
|
96
|
+
success = test_dune_connection()
|
|
97
|
+
sys.exit(0 if success else 1)
|