spice-mcp 0.1.0__tar.gz → 0.1.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.
Potentially problematic release.
This version of spice-mcp might be problematic. Click here for more details.
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/.gitignore +6 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/PKG-INFO +75 -15
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/README.md +74 -14
- spice_mcp-0.1.2/debug_mcp_tool.py +147 -0
- spice_mcp-0.1.2/debug_template_query.py +147 -0
- spice_mcp-0.1.2/issue_diagnostics.py +76 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/pyproject.toml +18 -1
- spice_mcp-0.1.2/scripts/bridgez/make_circle_comparison.py +114 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/src/spice_mcp/adapters/dune/extract.py +12 -7
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/src/spice_mcp/adapters/dune/typing_utils.py +10 -1
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/src/spice_mcp/mcp/server.py +1 -20
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/src/spice_mcp/mcp/tools/execute_query.py +23 -1
- spice_mcp-0.1.2/test_semaphore_fix.py +101 -0
- spice_mcp-0.1.2/test_sync_fix.py +55 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/tests/fastmcp/test_server_fastmcp.py +2 -3
- spice_mcp-0.1.2/tests/mcp/test_tool_contracts.py +55 -0
- spice_mcp-0.1.2/tests/offline/test_typing_utils.py +62 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/uv.lock +409 -3
- spice_mcp-0.1.0/.factory/droids/agentic-documentation-systems-droid.md +0 -16
- spice_mcp-0.1.0/.factory/droids/development-workflow-optimization-droid.md +0 -16
- spice_mcp-0.1.0/.factory/droids/production-python-development-droid.md +0 -18
- spice_mcp-0.1.0/.factory/droids/temp-smoke-droid.md +0 -8
- spice_mcp-0.1.0/.github/workflows/ci.yml +0 -144
- spice_mcp-0.1.0/bin/bat +0 -18
- spice_mcp-0.1.0/bin/fd +0 -18
- spice_mcp-0.1.0/debug_api.py +0 -97
- spice_mcp-0.1.0/tests/mcp/test_tool_contracts.py +0 -58
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/.python-version +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/CONTRIBUTING.md +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/LICENSE +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/docs/architecture.md +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/docs/codex_cli.md +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/docs/codex_cli_tools.md +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/docs/commands.md +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/docs/config.md +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/docs/development.md +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/docs/discovery.md +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/docs/dune_api.md +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/docs/index.md +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/docs/installation.md +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/docs/tools.md +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/pytest.ini +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/scripts/codex_tools_doctor.sh +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/src/spice_mcp/__init__.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/src/spice_mcp/adapters/__init__.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/src/spice_mcp/adapters/dune/__init__.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/src/spice_mcp/adapters/dune/admin.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/src/spice_mcp/adapters/dune/cache.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/src/spice_mcp/adapters/dune/client.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/src/spice_mcp/adapters/dune/helpers.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/src/spice_mcp/adapters/dune/transport.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/src/spice_mcp/adapters/dune/types.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/src/spice_mcp/adapters/dune/urls.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/src/spice_mcp/adapters/http_client.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/src/spice_mcp/config.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/src/spice_mcp/core/__init__.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/src/spice_mcp/core/errors.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/src/spice_mcp/core/models.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/src/spice_mcp/core/ports.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/src/spice_mcp/logging/query_history.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/src/spice_mcp/mcp/__init__.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/src/spice_mcp/mcp/tools/__init__.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/src/spice_mcp/mcp/tools/base.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/src/spice_mcp/mcp/tools/sui_package_overview.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/src/spice_mcp/observability/__init__.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/src/spice_mcp/observability/logging.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/src/spice_mcp/polars_utils.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/src/spice_mcp/py.typed +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/src/spice_mcp/service_layer/__init__.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/src/spice_mcp/service_layer/discovery_service.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/src/spice_mcp/service_layer/query_admin_service.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/src/spice_mcp/service_layer/query_service.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/src/spice_mcp/service_layer/sui_service.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/tests/cassettes/.gitkeep +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/tests/config/environments.yaml +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/tests/config/test_queries.yaml +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/tests/conftest.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/tests/fastmcp/test_resources_and_validation.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/tests/fastmcp/test_server_mcp_extras.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/tests/http_stubbed/test_age.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/tests/http_stubbed/test_errors.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/tests/http_stubbed/test_pagination.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/tests/live/test_live_basic.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/tests/live/test_live_sui.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/tests/mcp/conftest.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/tests/mcp/test_resources.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/tests/offline/test_cache.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/tests/offline/test_discovery.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/tests/offline/test_dune_adapter.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/tests/offline/test_parsing.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/tests/offline/test_query_history.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/tests/offline/test_show_rewrite.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/tests/offline/test_timeout.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/tests/offline/test_urls.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/tests/scripts/comprehensive_test_runner.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/tests/scripts/run_tests.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/tests/scripts/test_api_health.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/tests/scripts/test_cache_functionality.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/tests/scripts/test_data_types.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/tests/scripts/test_dune_connectivity.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/tests/scripts/test_dune_query_execution.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/tests/scripts/test_error_handling.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/tests/scripts/test_mcp_simulation.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/tests/scripts/test_mcp_tools.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/tests/scripts/test_performance.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/tests/scripts/test_query_lifecycle.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/tests/scripts/test_resilience.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/tests/scripts/test_resource_management.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/tests/style/test_polars_lazy.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/tests/support/api_client.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/tests/support/helpers.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/tests/support/query_factory.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/tests/support/test_data.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/tests/tools/test_additional_mcp_tools.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/tests/tools/test_execute_query_tool.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/tests/tools/test_health_tool.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/tests/tools/test_query_service.py +0 -0
- {spice_mcp-0.1.0 → spice_mcp-0.1.2}/tests/tools/test_schemas.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: spice-mcp
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.2
|
|
4
4
|
Summary: MCP server for Dune Analytics data access
|
|
5
5
|
Author-email: Evan-Kim2028 <ekcopersonal@gmail.com>
|
|
6
6
|
License-File: LICENSE
|
|
@@ -21,27 +21,87 @@ Description-Content-Type: text/markdown
|
|
|
21
21
|
|
|
22
22
|
# spice-mcp
|
|
23
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.
|
|
24
|
+
spice-mcp is an MCP server for [Dune](https://dune.com/) 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
25
|
|
|
26
26
|
Requirements: Python 3.13+
|
|
27
27
|
|
|
28
28
|
This project uses FastMCP for typed, decorator-registered tools and resources.
|
|
29
29
|
|
|
30
|
-
Highlights
|
|
30
|
+
## Highlights
|
|
31
31
|
- Polars LazyFrame-first pipeline: results stay lazy until explicitly materialized
|
|
32
|
-
- Ports/adapters layering for maintainable integrations (
|
|
32
|
+
- Ports/adapters layering for maintainable integrations ([docs/architecture.md](docs/architecture.md))
|
|
33
33
|
- Discovery utilities (find schemas/tables, describe columns)
|
|
34
34
|
- Sui package workflows (events/transactions/objects) with safe defaults
|
|
35
35
|
- JSONL query history + SQL artifacts (SHA-256) for reproducibility
|
|
36
36
|
- Rich MCP surface: query info/run, discovery, health, Sui, and Dune admin (create/update/fork)
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
## What is Dune?
|
|
39
|
+
[Dune](https://dune.com/) is a crypto data platform providing curated blockchain datasets and a public API to run and fetch query results. See the [Dune Docs](https://dune.com/docs) and [Dune API](https://dune.com/docs/api/) for full details.
|
|
40
|
+
|
|
41
|
+
## Quick Start
|
|
39
42
|
- 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
43
|
- Install dependencies (`uv sync` or `pip install -e .`).
|
|
41
44
|
- Start the FastMCP stdio server:
|
|
42
45
|
- `python -m spice_mcp.mcp.server --env PYTHONPATH=$(pwd)/src`
|
|
43
46
|
- or install the console script via `uv tool install .` and run `spice-mcp`.
|
|
44
47
|
|
|
48
|
+
## Cursor IDE Setup
|
|
49
|
+
|
|
50
|
+
To use spice-mcp with Cursor IDE:
|
|
51
|
+
|
|
52
|
+
1. **Install the MCP Server**:
|
|
53
|
+
```bash
|
|
54
|
+
# Install dependencies and package
|
|
55
|
+
uv sync
|
|
56
|
+
pip install -e .
|
|
57
|
+
|
|
58
|
+
# Or install via uv tool (creates console script)
|
|
59
|
+
uv tool install .
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
2. **Configure Cursor**:
|
|
63
|
+
- Open Cursor Settings → MCP Servers
|
|
64
|
+
- Add new MCP server configuration:
|
|
65
|
+
```json
|
|
66
|
+
{
|
|
67
|
+
"name": "spice-mcp",
|
|
68
|
+
"command": "spice-mcp",
|
|
69
|
+
"env": {
|
|
70
|
+
"DUNE_API_KEY": "your-dune-api-key-here"
|
|
71
|
+
},
|
|
72
|
+
"disabled": false
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
Alternatively, if you prefer running from source:
|
|
76
|
+
```json
|
|
77
|
+
{
|
|
78
|
+
"name": "spice-mcp",
|
|
79
|
+
"command": "python",
|
|
80
|
+
"args": ["-m", "spice_mcp.mcp.server"],
|
|
81
|
+
"env": {
|
|
82
|
+
"PYTHONPATH": "/path/to/your/spice-mcp/src",
|
|
83
|
+
"DUNE_API_KEY": "your-dune-api-key-here"
|
|
84
|
+
},
|
|
85
|
+
"disabled": false
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
3. **Restart Cursor** to load the MCP server
|
|
90
|
+
|
|
91
|
+
4. **Verify Connection**:
|
|
92
|
+
- Open Cursor and use the command palette (Cmd/Ctrl + Shift + P)
|
|
93
|
+
- Search for "MCP" or "spice" commands
|
|
94
|
+
- Test with `dune_health_check` to verify the connection
|
|
95
|
+
|
|
96
|
+
5. **Available Tools in Cursor**:
|
|
97
|
+
- `dune_query`: Run Dune queries by ID, URL, or raw SQL
|
|
98
|
+
- `dune_find_tables`: Search schemas and list tables
|
|
99
|
+
- `dune_describe_table`: Get column metadata
|
|
100
|
+
- `sui_package_overview`: Analyze Sui packages
|
|
101
|
+
- `dune_health_check`: Verify API connection
|
|
102
|
+
|
|
103
|
+
**Tip**: Create a `.env` file in your project root with `DUNE_API_KEY=your-key-here` for easier configuration.
|
|
104
|
+
|
|
45
105
|
## MCP Tools and Features
|
|
46
106
|
|
|
47
107
|
All tools expose typed parameters, titles, and tags; failures return a consistent error envelope.
|
|
@@ -114,16 +174,16 @@ Core Tools (with parameters)
|
|
|
114
174
|
- Use: Verify API key presence and logging paths
|
|
115
175
|
- Output: `api_key_present`, `query_history_path`, `logging_enabled`, `status`
|
|
116
176
|
|
|
117
|
-
Docs
|
|
118
|
-
- See
|
|
119
|
-
- Dune API structure and capabilities:
|
|
120
|
-
- Discovery patterns and examples:
|
|
121
|
-
- Sui package workflows:
|
|
122
|
-
- Tool reference and schemas:
|
|
123
|
-
- Codex CLI + tooling integration:
|
|
124
|
-
- Architecture overview:
|
|
125
|
-
- Installation and configuration:
|
|
126
|
-
- Development and linting:
|
|
177
|
+
## Docs
|
|
178
|
+
- See [docs/index.md](docs/index.md) for full documentation:
|
|
179
|
+
- Dune API structure and capabilities: [docs/dune_api.md](docs/dune_api.md)
|
|
180
|
+
- Discovery patterns and examples: [docs/discovery.md](docs/discovery.md)
|
|
181
|
+
- Sui package workflows: [docs/sui_packages.md](docs/sui_packages.md)
|
|
182
|
+
- Tool reference and schemas: [docs/tools.md](docs/tools.md)
|
|
183
|
+
- Codex CLI + tooling integration: [docs/codex_cli.md](docs/codex_cli.md), [docs/codex_cli_tools.md](docs/codex_cli_tools.md)
|
|
184
|
+
- Architecture overview: [docs/architecture.md](docs/architecture.md)
|
|
185
|
+
- Installation and configuration: [docs/installation.md](docs/installation.md), [docs/config.md](docs/config.md)
|
|
186
|
+
- Development and linting: [docs/development.md](docs/development.md)
|
|
127
187
|
|
|
128
188
|
Notes
|
|
129
189
|
- Legacy Spice code now lives under `src/spice_mcp/adapters/dune` (extract, cache, urls, types).
|
|
@@ -1,26 +1,86 @@
|
|
|
1
1
|
# spice-mcp
|
|
2
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.
|
|
3
|
+
spice-mcp is an MCP server for [Dune](https://dune.com/) 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
4
|
|
|
5
5
|
Requirements: Python 3.13+
|
|
6
6
|
|
|
7
7
|
This project uses FastMCP for typed, decorator-registered tools and resources.
|
|
8
8
|
|
|
9
|
-
Highlights
|
|
9
|
+
## Highlights
|
|
10
10
|
- Polars LazyFrame-first pipeline: results stay lazy until explicitly materialized
|
|
11
|
-
- Ports/adapters layering for maintainable integrations (
|
|
11
|
+
- Ports/adapters layering for maintainable integrations ([docs/architecture.md](docs/architecture.md))
|
|
12
12
|
- Discovery utilities (find schemas/tables, describe columns)
|
|
13
13
|
- Sui package workflows (events/transactions/objects) with safe defaults
|
|
14
14
|
- JSONL query history + SQL artifacts (SHA-256) for reproducibility
|
|
15
15
|
- Rich MCP surface: query info/run, discovery, health, Sui, and Dune admin (create/update/fork)
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
## What is Dune?
|
|
18
|
+
[Dune](https://dune.com/) is a crypto data platform providing curated blockchain datasets and a public API to run and fetch query results. See the [Dune Docs](https://dune.com/docs) and [Dune API](https://dune.com/docs/api/) for full details.
|
|
19
|
+
|
|
20
|
+
## Quick Start
|
|
18
21
|
- 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
22
|
- Install dependencies (`uv sync` or `pip install -e .`).
|
|
20
23
|
- Start the FastMCP stdio server:
|
|
21
24
|
- `python -m spice_mcp.mcp.server --env PYTHONPATH=$(pwd)/src`
|
|
22
25
|
- or install the console script via `uv tool install .` and run `spice-mcp`.
|
|
23
26
|
|
|
27
|
+
## Cursor IDE Setup
|
|
28
|
+
|
|
29
|
+
To use spice-mcp with Cursor IDE:
|
|
30
|
+
|
|
31
|
+
1. **Install the MCP Server**:
|
|
32
|
+
```bash
|
|
33
|
+
# Install dependencies and package
|
|
34
|
+
uv sync
|
|
35
|
+
pip install -e .
|
|
36
|
+
|
|
37
|
+
# Or install via uv tool (creates console script)
|
|
38
|
+
uv tool install .
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
2. **Configure Cursor**:
|
|
42
|
+
- Open Cursor Settings → MCP Servers
|
|
43
|
+
- Add new MCP server configuration:
|
|
44
|
+
```json
|
|
45
|
+
{
|
|
46
|
+
"name": "spice-mcp",
|
|
47
|
+
"command": "spice-mcp",
|
|
48
|
+
"env": {
|
|
49
|
+
"DUNE_API_KEY": "your-dune-api-key-here"
|
|
50
|
+
},
|
|
51
|
+
"disabled": false
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
Alternatively, if you prefer running from source:
|
|
55
|
+
```json
|
|
56
|
+
{
|
|
57
|
+
"name": "spice-mcp",
|
|
58
|
+
"command": "python",
|
|
59
|
+
"args": ["-m", "spice_mcp.mcp.server"],
|
|
60
|
+
"env": {
|
|
61
|
+
"PYTHONPATH": "/path/to/your/spice-mcp/src",
|
|
62
|
+
"DUNE_API_KEY": "your-dune-api-key-here"
|
|
63
|
+
},
|
|
64
|
+
"disabled": false
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
3. **Restart Cursor** to load the MCP server
|
|
69
|
+
|
|
70
|
+
4. **Verify Connection**:
|
|
71
|
+
- Open Cursor and use the command palette (Cmd/Ctrl + Shift + P)
|
|
72
|
+
- Search for "MCP" or "spice" commands
|
|
73
|
+
- Test with `dune_health_check` to verify the connection
|
|
74
|
+
|
|
75
|
+
5. **Available Tools in Cursor**:
|
|
76
|
+
- `dune_query`: Run Dune queries by ID, URL, or raw SQL
|
|
77
|
+
- `dune_find_tables`: Search schemas and list tables
|
|
78
|
+
- `dune_describe_table`: Get column metadata
|
|
79
|
+
- `sui_package_overview`: Analyze Sui packages
|
|
80
|
+
- `dune_health_check`: Verify API connection
|
|
81
|
+
|
|
82
|
+
**Tip**: Create a `.env` file in your project root with `DUNE_API_KEY=your-key-here` for easier configuration.
|
|
83
|
+
|
|
24
84
|
## MCP Tools and Features
|
|
25
85
|
|
|
26
86
|
All tools expose typed parameters, titles, and tags; failures return a consistent error envelope.
|
|
@@ -93,16 +153,16 @@ Core Tools (with parameters)
|
|
|
93
153
|
- Use: Verify API key presence and logging paths
|
|
94
154
|
- Output: `api_key_present`, `query_history_path`, `logging_enabled`, `status`
|
|
95
155
|
|
|
96
|
-
Docs
|
|
97
|
-
- See
|
|
98
|
-
- Dune API structure and capabilities:
|
|
99
|
-
- Discovery patterns and examples:
|
|
100
|
-
- Sui package workflows:
|
|
101
|
-
- Tool reference and schemas:
|
|
102
|
-
- Codex CLI + tooling integration:
|
|
103
|
-
- Architecture overview:
|
|
104
|
-
- Installation and configuration:
|
|
105
|
-
- Development and linting:
|
|
156
|
+
## Docs
|
|
157
|
+
- See [docs/index.md](docs/index.md) for full documentation:
|
|
158
|
+
- Dune API structure and capabilities: [docs/dune_api.md](docs/dune_api.md)
|
|
159
|
+
- Discovery patterns and examples: [docs/discovery.md](docs/discovery.md)
|
|
160
|
+
- Sui package workflows: [docs/sui_packages.md](docs/sui_packages.md)
|
|
161
|
+
- Tool reference and schemas: [docs/tools.md](docs/tools.md)
|
|
162
|
+
- Codex CLI + tooling integration: [docs/codex_cli.md](docs/codex_cli.md), [docs/codex_cli_tools.md](docs/codex_cli_tools.md)
|
|
163
|
+
- Architecture overview: [docs/architecture.md](docs/architecture.md)
|
|
164
|
+
- Installation and configuration: [docs/installation.md](docs/installation.md), [docs/config.md](docs/config.md)
|
|
165
|
+
- Development and linting: [docs/development.md](docs/development.md)
|
|
106
166
|
|
|
107
167
|
Notes
|
|
108
168
|
- Legacy Spice code now lives under `src/spice_mcp/adapters/dune` (extract, cache, urls, types).
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Debug script to test the MCP tool layer directly.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import os
|
|
7
|
+
import sys
|
|
8
|
+
import json
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
|
|
11
|
+
# Add src to path
|
|
12
|
+
sys.path.insert(0, '/Users/evandekim/Documents/spice_mcp/src')
|
|
13
|
+
|
|
14
|
+
from spice_mcp.config import Config
|
|
15
|
+
from spice_mcp.logging.query_history import QueryHistory
|
|
16
|
+
from spice_mcp.mcp.tools.execute_query import ExecuteQueryTool
|
|
17
|
+
from spice_mcp.service_layer.query_service import QueryService
|
|
18
|
+
from spice_mcp.adapters.dune.client import DuneAdapter
|
|
19
|
+
|
|
20
|
+
def test_mcp_tool_directly():
|
|
21
|
+
"""Test the MCP tool directly"""
|
|
22
|
+
|
|
23
|
+
# Ensure API key is available
|
|
24
|
+
api_key = os.getenv('DUNE_API_KEY')
|
|
25
|
+
if not api_key:
|
|
26
|
+
print("❌ DUNE_API_KEY not set")
|
|
27
|
+
return False
|
|
28
|
+
|
|
29
|
+
print("🔍 Testing MCP tool directly...")
|
|
30
|
+
|
|
31
|
+
try:
|
|
32
|
+
# Setup the components
|
|
33
|
+
from spice_mcp.config import DuneConfig, CacheConfig, HttpClientConfig
|
|
34
|
+
config = Config(
|
|
35
|
+
dune=DuneConfig(api_key=api_key),
|
|
36
|
+
cache=CacheConfig(),
|
|
37
|
+
http=HttpClientConfig()
|
|
38
|
+
)
|
|
39
|
+
adapter = DuneAdapter(config)
|
|
40
|
+
query_service = QueryService(adapter)
|
|
41
|
+
query_history = QueryHistory(Path("/tmp/query_history.jsonl"), Path("/tmp/sql_artifacts"))
|
|
42
|
+
|
|
43
|
+
# Create the tool
|
|
44
|
+
tool = ExecuteQueryTool(config, query_service, query_history)
|
|
45
|
+
|
|
46
|
+
# Test simple raw SQL
|
|
47
|
+
print("\n📝 Testing MCP tool with 'SELECT 1 as test'")
|
|
48
|
+
|
|
49
|
+
# This should work via the MCP tool interface
|
|
50
|
+
import asyncio
|
|
51
|
+
result = asyncio.run(tool.execute(
|
|
52
|
+
query="SELECT 1 as test",
|
|
53
|
+
refresh=True,
|
|
54
|
+
format="preview"
|
|
55
|
+
))
|
|
56
|
+
|
|
57
|
+
print(f"✅ Tool result type: {type(result)}")
|
|
58
|
+
print(f"✅ Tool result keys: {list(result.keys()) if isinstance(result, dict) else 'not dict'}")
|
|
59
|
+
|
|
60
|
+
if isinstance(result, dict):
|
|
61
|
+
print(f"✅ Response type: {result.get('type')}")
|
|
62
|
+
print(f"✅ Row count: {result.get('rowcount')}")
|
|
63
|
+
print(f"✅ Execution ID: {result.get('execution_id')}")
|
|
64
|
+
if 'error' in result:
|
|
65
|
+
print(f"❌ Error: {result['error']}")
|
|
66
|
+
return False
|
|
67
|
+
else:
|
|
68
|
+
print("✅ Success! MCP tool executed raw SQL correctly")
|
|
69
|
+
|
|
70
|
+
except Exception as e:
|
|
71
|
+
print(f"❌ MCP tool test failed: {e}")
|
|
72
|
+
print(f" Error type: {type(e)}")
|
|
73
|
+
import traceback
|
|
74
|
+
traceback.print_exc()
|
|
75
|
+
return False
|
|
76
|
+
|
|
77
|
+
return True
|
|
78
|
+
|
|
79
|
+
def test_service_layer_directly():
|
|
80
|
+
"""Test the service layer directly"""
|
|
81
|
+
|
|
82
|
+
# Ensure API key is available
|
|
83
|
+
api_key = os.getenv('DUNE_API_KEY')
|
|
84
|
+
if not api_key:
|
|
85
|
+
print("❌ DUNE_API_KEY not set")
|
|
86
|
+
return False
|
|
87
|
+
|
|
88
|
+
print("🔍 Testing service layer directly...")
|
|
89
|
+
|
|
90
|
+
try:
|
|
91
|
+
# Setup the components
|
|
92
|
+
from spice_mcp.config import DuneConfig, CacheConfig, HttpClientConfig
|
|
93
|
+
config = Config(
|
|
94
|
+
dune=DuneConfig(api_key=api_key),
|
|
95
|
+
cache=CacheConfig(),
|
|
96
|
+
http=HttpClientConfig()
|
|
97
|
+
)
|
|
98
|
+
adapter = DuneAdapter(config)
|
|
99
|
+
query_service = QueryService(adapter)
|
|
100
|
+
|
|
101
|
+
# Test service layer directly
|
|
102
|
+
print("\n📝 Testing service layer with 'SELECT 1 as test'")
|
|
103
|
+
|
|
104
|
+
result = query_service.execute(
|
|
105
|
+
query="SELECT 1 as test",
|
|
106
|
+
refresh=True,
|
|
107
|
+
include_execution=True
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
print(f"✅ Service result type: {type(result)}")
|
|
111
|
+
print(f"✅ Service result keys: {list(result.keys()) if isinstance(result, dict) else 'not dict'}")
|
|
112
|
+
|
|
113
|
+
if isinstance(result, dict):
|
|
114
|
+
print(f"✅ Row count: {result.get('rowcount')}")
|
|
115
|
+
print(f"✅ Execution: {result.get('execution')}")
|
|
116
|
+
if 'execution' in result and result['execution'].get('execution_id'):
|
|
117
|
+
print("✅ Service layer executed successfully!")
|
|
118
|
+
return True
|
|
119
|
+
else:
|
|
120
|
+
print("❌ Service layer failed - no execution ID")
|
|
121
|
+
return False
|
|
122
|
+
|
|
123
|
+
except Exception as e:
|
|
124
|
+
print(f"❌ Service layer test failed: {e}")
|
|
125
|
+
import traceback
|
|
126
|
+
traceback.print_exc()
|
|
127
|
+
return False
|
|
128
|
+
|
|
129
|
+
return False
|
|
130
|
+
|
|
131
|
+
if __name__ == "__main__":
|
|
132
|
+
print("🐛 Debugging spice-mcp MCP tool layer...")
|
|
133
|
+
|
|
134
|
+
success = True
|
|
135
|
+
|
|
136
|
+
# Test 1: Service layer
|
|
137
|
+
success &= test_service_layer_directly()
|
|
138
|
+
|
|
139
|
+
# Test 2: MCP tool
|
|
140
|
+
success &= test_mcp_tool_directly()
|
|
141
|
+
|
|
142
|
+
if success:
|
|
143
|
+
print("\n✅ All tests passed!")
|
|
144
|
+
sys.exit(0)
|
|
145
|
+
else:
|
|
146
|
+
print("\n❌ Some tests failed!")
|
|
147
|
+
sys.exit(1)
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Debug script to test template query 4060379 execution directly.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import os
|
|
7
|
+
import sys
|
|
8
|
+
import json
|
|
9
|
+
|
|
10
|
+
# Add src to path
|
|
11
|
+
sys.path.insert(0, '/Users/evandekim/Documents/spice_mcp/src')
|
|
12
|
+
|
|
13
|
+
from spice_mcp.adapters.dune import extract, urls
|
|
14
|
+
|
|
15
|
+
def test_template_query_directly():
|
|
16
|
+
"""Test the template query directly via extract.query()"""
|
|
17
|
+
|
|
18
|
+
# Ensure API key is available
|
|
19
|
+
api_key = os.getenv('DUNE_API_KEY')
|
|
20
|
+
if not api_key:
|
|
21
|
+
print("❌ DUNE_API_KEY not set")
|
|
22
|
+
return False
|
|
23
|
+
|
|
24
|
+
template_id = int(os.getenv("SPICE_RAW_SQL_QUERY_ID", "4060379"))
|
|
25
|
+
print(f"🔍 Testing template query {template_id} directly...")
|
|
26
|
+
|
|
27
|
+
try:
|
|
28
|
+
# Test 1: Execute simple raw SQL
|
|
29
|
+
print("\n📝 Test 1: Simple SELECT 1")
|
|
30
|
+
result = extract.query(
|
|
31
|
+
query_or_execution="SELECT 1 as test",
|
|
32
|
+
verbose=True,
|
|
33
|
+
refresh=True,
|
|
34
|
+
poll=True,
|
|
35
|
+
api_key=api_key,
|
|
36
|
+
timeout_seconds=30
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
print(f"✅ Result type: {type(result)}")
|
|
40
|
+
if hasattr(result, 'shape'):
|
|
41
|
+
print(f"✅ Result shape: {result.shape}")
|
|
42
|
+
print(f"✅ Result columns: {list(result.columns) if hasattr(result, 'columns') else 'N/A'}")
|
|
43
|
+
|
|
44
|
+
except Exception as e:
|
|
45
|
+
print(f"❌ Test 1 failed: {e}")
|
|
46
|
+
print(f" Error type: {type(e)}")
|
|
47
|
+
return False
|
|
48
|
+
|
|
49
|
+
try:
|
|
50
|
+
# Test 2: Test with parameters explicitly
|
|
51
|
+
print("\n📝 Test 2: Raw SQL with explicit parameters")
|
|
52
|
+
result = extract.query(
|
|
53
|
+
query_or_execution="SELECT 1 as test",
|
|
54
|
+
verbose=True,
|
|
55
|
+
refresh=True,
|
|
56
|
+
poll=True,
|
|
57
|
+
api_key=api_key,
|
|
58
|
+
parameters={'query': 'SELECT 1 as test'},
|
|
59
|
+
timeout_seconds=30
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
print(f"✅ Result type: {type(result)}")
|
|
63
|
+
if hasattr(result, 'shape'):
|
|
64
|
+
print(f"✅ Result shape: {result.shape}")
|
|
65
|
+
|
|
66
|
+
except Exception as e:
|
|
67
|
+
print(f"❌ Test 2 failed: {e}")
|
|
68
|
+
return False
|
|
69
|
+
|
|
70
|
+
return True
|
|
71
|
+
|
|
72
|
+
def test_determine_input_type():
|
|
73
|
+
"""Test the determine_input_type function"""
|
|
74
|
+
print("\n🔍 Testing determine_input_type...")
|
|
75
|
+
|
|
76
|
+
query_id, execution, parameters = extract.determine_input_type("SELECT 1 as test")
|
|
77
|
+
|
|
78
|
+
print(f"✅ Query ID: {query_id}")
|
|
79
|
+
print(f"✅ Execution: {execution}")
|
|
80
|
+
print(f"✅ Parameters: {parameters}")
|
|
81
|
+
|
|
82
|
+
return True
|
|
83
|
+
|
|
84
|
+
def test_template_query_api_check():
|
|
85
|
+
"""Check if the template query actually exists and is accessible"""
|
|
86
|
+
template_id = int(os.getenv("SPICE_RAW_SQL_QUERY_ID", "4060379"))
|
|
87
|
+
api_key = os.getenv('DUNE_API_KEY')
|
|
88
|
+
|
|
89
|
+
if not api_key:
|
|
90
|
+
print("❌ DUNE_API_KEY not set")
|
|
91
|
+
return False
|
|
92
|
+
|
|
93
|
+
print(f"\n🔍 Checking template query {template_id} metadata...")
|
|
94
|
+
|
|
95
|
+
try:
|
|
96
|
+
# Check if the query exists by trying to get its info
|
|
97
|
+
url = urls.get_query_execute_url(template_id)
|
|
98
|
+
headers = {'X-Dune-API-Key': api_key, 'User-Agent': extract.get_user_agent()}
|
|
99
|
+
|
|
100
|
+
print(f"🌐 Query execute URL: {url}")
|
|
101
|
+
|
|
102
|
+
# Try to execute with empty parameters first
|
|
103
|
+
import requests
|
|
104
|
+
|
|
105
|
+
response = requests.post(
|
|
106
|
+
url,
|
|
107
|
+
headers=headers,
|
|
108
|
+
json={'query_parameters': {}, 'performance': 'medium'},
|
|
109
|
+
timeout=30
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
print(f"📊 Status code: {response.status_code}")
|
|
113
|
+
|
|
114
|
+
if response.status_code == 200:
|
|
115
|
+
result = response.json()
|
|
116
|
+
print(f"✅ Execution result: {json.dumps(result, indent=2)}")
|
|
117
|
+
else:
|
|
118
|
+
print(f"❌ API Response: {response.text}")
|
|
119
|
+
return False
|
|
120
|
+
|
|
121
|
+
except Exception as e:
|
|
122
|
+
print(f"❌ Template query check failed: {e}")
|
|
123
|
+
return False
|
|
124
|
+
|
|
125
|
+
return True
|
|
126
|
+
|
|
127
|
+
if __name__ == "__main__":
|
|
128
|
+
print("🐛 Debugging spice-mcp raw SQL execution issues...")
|
|
129
|
+
|
|
130
|
+
success = True
|
|
131
|
+
|
|
132
|
+
# Test 1: Determine input type
|
|
133
|
+
success &= test_determine_input_type()
|
|
134
|
+
|
|
135
|
+
# Test 2: Check template query API
|
|
136
|
+
success &= test_template_query_api_check()
|
|
137
|
+
|
|
138
|
+
# Test 3: Direct execution
|
|
139
|
+
print(f"\n🚀 About to test raw SQL execution...")
|
|
140
|
+
success &= test_template_query_directly()
|
|
141
|
+
|
|
142
|
+
if success:
|
|
143
|
+
print("\n✅ All tests passed!")
|
|
144
|
+
sys.exit(0)
|
|
145
|
+
else:
|
|
146
|
+
print("\n❌ Some tests failed!")
|
|
147
|
+
sys.exit(1)
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# Raw SQL Execution Issue Analysis
|
|
2
|
+
|
|
3
|
+
## ✅ GOOD NEWS: Core Code is Working Correctly!
|
|
4
|
+
|
|
5
|
+
After extensive debugging, I've determined that the core spice-mcp code is **working perfectly**. Both the Dune adapter layer and MCP tool layer successfully execute raw SQL queries when properly configured.
|
|
6
|
+
|
|
7
|
+
## 🐛 Root Cause: Environmental/Configuration Issue
|
|
8
|
+
|
|
9
|
+
The issue reported in #6 is **not in the code itself** but rather in how users are running the MCP server. The symptoms suggest:
|
|
10
|
+
|
|
11
|
+
1. **Environment variable issue**: `SPICE_RAW_SQL_QUERY_ID` may not be set in the MCP server context
|
|
12
|
+
2. **MCP server setup issue**: The FastMCP server may not be properly configured
|
|
13
|
+
3. **Path/import issues**: The MCP server may be running in a different environment
|
|
14
|
+
|
|
15
|
+
## 🔧 Proposed Solutions
|
|
16
|
+
|
|
17
|
+
### Option 1: Hard-code fallback (Recommended)
|
|
18
|
+
Make the template ID resolution more robust by providing a fallback:
|
|
19
|
+
|
|
20
|
+
```python
|
|
21
|
+
def resolve_raw_sql_template_id() -> int:
|
|
22
|
+
"""Return a stable template ID used for executing raw SQL text."""
|
|
23
|
+
# Try environment variable first, fallback to hardcoded value
|
|
24
|
+
env_value = os.getenv("SPICE_RAW_SQL_QUERY_ID")
|
|
25
|
+
if env_value and env_value.strip():
|
|
26
|
+
try:
|
|
27
|
+
return int(env_value.strip())
|
|
28
|
+
except ValueError:
|
|
29
|
+
pass
|
|
30
|
+
# Fallback to known working template ID
|
|
31
|
+
return 4060379
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Option 2: Enhanced Diagnostics
|
|
35
|
+
Add better error reporting in the MCP tool to help users debug their setup:
|
|
36
|
+
|
|
37
|
+
```python
|
|
38
|
+
# Add environment variable check at tool startup
|
|
39
|
+
if not os.getenv("SPICE_RAW_SQL_QUERY_ID"):
|
|
40
|
+
print("Warning: SPICE_RAW_SQL_QUERY_ID not set, using default template ID")
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Option 3: Verify Tool
|
|
44
|
+
Create a verification tool that tests the raw SQL path:
|
|
45
|
+
|
|
46
|
+
```python
|
|
47
|
+
def verify_raw_sql_config(self) -> dict:
|
|
48
|
+
"""Verify that raw SQL configuration is working."""
|
|
49
|
+
try:
|
|
50
|
+
template_id = resolve_raw_sql_template_id()
|
|
51
|
+
return {
|
|
52
|
+
"status": "ok",
|
|
53
|
+
"template_id": template_id,
|
|
54
|
+
"env_var_set": bool(os.getenv("SPICE_RAW_SQL_QUERY_ID"))
|
|
55
|
+
}
|
|
56
|
+
except Exception as e:
|
|
57
|
+
return {"status": "error", "error": str(e)}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## 🎯 User Action Required
|
|
61
|
+
|
|
62
|
+
For users experiencing this issue:
|
|
63
|
+
|
|
64
|
+
1. **Set environment variable properly in MCP server context**
|
|
65
|
+
2. **Verify MCP server startup logs** for any authentication or import errors
|
|
66
|
+
3. **Use the enhanced diagnostics** (once implemented)
|
|
67
|
+
|
|
68
|
+
## 📋 Test Results Summary
|
|
69
|
+
|
|
70
|
+
- ✅ Template ID resolution: Working
|
|
71
|
+
- ✅ Dune adapter raw SQL: Working
|
|
72
|
+
- ✅ MCP tool raw SQL: Working
|
|
73
|
+
- ✅ Service layer: Working
|
|
74
|
+
- ❌ User environment: Needs investigation
|
|
75
|
+
|
|
76
|
+
The fix in 0.1.1 addressed the core issue. The remaining problem is likely user environment specific.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "spice-mcp"
|
|
3
|
-
version = "0.1.
|
|
3
|
+
version = "0.1.2"
|
|
4
4
|
description = "MCP server for Dune Analytics data access"
|
|
5
5
|
authors = [
|
|
6
6
|
{ name = "Evan-Kim2028", email = "ekcopersonal@gmail.com" }
|
|
@@ -36,6 +36,23 @@ managed = true
|
|
|
36
36
|
dev-dependencies = [
|
|
37
37
|
"pytest>=8.0.0",
|
|
38
38
|
"pytest-asyncio>=0.23.0",
|
|
39
|
+
"pytest-cov>=5.0.0",
|
|
40
|
+
"freezegun>=1.4.0",
|
|
41
|
+
"jsonschema>=4.21.1",
|
|
42
|
+
"responses>=0.25.0",
|
|
43
|
+
"aioresponses>=0.7.6",
|
|
44
|
+
"vcrpy>=6.0.1",
|
|
45
|
+
"hypothesis>=6.100.0",
|
|
46
|
+
"ruff>=0.6.9",
|
|
47
|
+
"mypy>=1.11.2",
|
|
48
|
+
]
|
|
49
|
+
|
|
50
|
+
# uv dependency groups for CI and local dev
|
|
51
|
+
[dependency-groups]
|
|
52
|
+
dev = [
|
|
53
|
+
"pytest>=8.0.0",
|
|
54
|
+
"pytest-asyncio>=0.23.0",
|
|
55
|
+
"pytest-cov>=5.0.0",
|
|
39
56
|
"freezegun>=1.4.0",
|
|
40
57
|
"jsonschema>=4.21.1",
|
|
41
58
|
"responses>=0.25.0",
|