spice-mcp 0.1.2__py3-none-any.whl → 0.1.4__py3-none-any.whl
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/adapters/dune/__init__.py +4 -2
- spice_mcp/adapters/dune/cache.py +2 -34
- spice_mcp/adapters/dune/client.py +9 -4
- spice_mcp/adapters/dune/extract.py +79 -633
- spice_mcp/adapters/dune/query_wrapper.py +86 -0
- spice_mcp/adapters/dune/user_agent.py +9 -0
- spice_mcp/adapters/spellbook/__init__.py +6 -0
- spice_mcp/adapters/spellbook/explorer.py +313 -0
- spice_mcp/config.py +1 -1
- spice_mcp/core/models.py +0 -8
- spice_mcp/core/ports.py +0 -15
- spice_mcp/mcp/server.py +407 -137
- spice_mcp/mcp/tools/base.py +1 -1
- spice_mcp/mcp/tools/execute_query.py +32 -63
- spice_mcp-0.1.4.dist-info/METADATA +121 -0
- {spice_mcp-0.1.2.dist-info → spice_mcp-0.1.4.dist-info}/RECORD +19 -17
- spice_mcp/mcp/tools/sui_package_overview.py +0 -56
- spice_mcp/service_layer/sui_service.py +0 -131
- spice_mcp-0.1.2.dist-info/METADATA +0 -193
- {spice_mcp-0.1.2.dist-info → spice_mcp-0.1.4.dist-info}/WHEEL +0 -0
- {spice_mcp-0.1.2.dist-info → spice_mcp-0.1.4.dist-info}/entry_points.txt +0 -0
- {spice_mcp-0.1.2.dist-info → spice_mcp-0.1.4.dist-info}/licenses/LICENSE +0 -0
|
@@ -2,9 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
This module provides a thin façade used by the new service layer while
|
|
4
4
|
keeping the battle-tested logic that the original spice client offered.
|
|
5
|
+
|
|
6
|
+
Only synchronous interfaces are exposed.
|
|
5
7
|
"""
|
|
6
8
|
|
|
7
9
|
from . import urls # re-export for callers needing low-level helpers
|
|
8
|
-
from .extract import
|
|
10
|
+
from .extract import query # noqa: F401
|
|
9
11
|
|
|
10
|
-
__all__ = ["query", "
|
|
12
|
+
__all__ = ["query", "urls"]
|
spice_mcp/adapters/dune/cache.py
CHANGED
|
@@ -51,39 +51,7 @@ def load_from_cache(
|
|
|
51
51
|
return None, execution
|
|
52
52
|
|
|
53
53
|
|
|
54
|
-
async
|
|
55
|
-
execute_kwargs: _extract.ExecuteKwargs,
|
|
56
|
-
result_kwargs: _extract.RetrievalKwargs,
|
|
57
|
-
output_kwargs: _extract.OutputKwargs,
|
|
58
|
-
) -> tuple[
|
|
59
|
-
pl.DataFrame | tuple[pl.DataFrame, Execution] | None, Execution | None
|
|
60
|
-
]:
|
|
61
|
-
# get latest execution
|
|
62
|
-
execution = await _extract.async_get_latest_execution(execute_kwargs)
|
|
63
|
-
if execution is None:
|
|
64
|
-
return None, None
|
|
65
|
-
|
|
66
|
-
# build cache path
|
|
67
|
-
cache_path = _build_cache_path(
|
|
68
|
-
execution=execution,
|
|
69
|
-
execute_kwargs=execute_kwargs,
|
|
70
|
-
result_kwargs=result_kwargs,
|
|
71
|
-
cache_dir=output_kwargs['cache_dir'],
|
|
72
|
-
)
|
|
73
|
-
|
|
74
|
-
# load cache result
|
|
75
|
-
if os.path.exists(cache_path):
|
|
76
|
-
import polars as pl
|
|
77
|
-
|
|
78
|
-
if result_kwargs['verbose']:
|
|
79
|
-
print('loading dune query result from cache')
|
|
80
|
-
df = await pl.scan_parquet(cache_path).collect_async()
|
|
81
|
-
if output_kwargs['include_execution']:
|
|
82
|
-
return (df, execution), execution
|
|
83
|
-
else:
|
|
84
|
-
return df, execution
|
|
85
|
-
else:
|
|
86
|
-
return None, execution
|
|
54
|
+
## Removed async cache loader; synchronous load_from_cache should be used exclusively.
|
|
87
55
|
|
|
88
56
|
|
|
89
57
|
def save_to_cache(
|
|
@@ -113,7 +81,7 @@ def save_to_cache(
|
|
|
113
81
|
# save to cache
|
|
114
82
|
tmp_path = (
|
|
115
83
|
cache_path + '_tmp_' + secrets.token_hex(8)
|
|
116
|
-
) # add
|
|
84
|
+
) # add tmp suffix to avoid conflicts during writes
|
|
117
85
|
df.write_parquet(tmp_path)
|
|
118
86
|
shutil.move(tmp_path, cache_path)
|
|
119
87
|
|
|
@@ -24,6 +24,10 @@ from ...polars_utils import collect_preview
|
|
|
24
24
|
from ..http_client import HttpClient, HttpClientConfig
|
|
25
25
|
from . import extract, urls
|
|
26
26
|
|
|
27
|
+
# Use wrapper to avoid FastMCP detecting overloads in extract.query()
|
|
28
|
+
# Note: We still import extract for _determine_input_type and other non-overloaded functions
|
|
29
|
+
from .query_wrapper import execute_query as _execute_dune_query
|
|
30
|
+
|
|
27
31
|
|
|
28
32
|
class DuneAdapter(QueryExecutor, CatalogExplorer):
|
|
29
33
|
"""Thin façade around the vendored extract module."""
|
|
@@ -47,7 +51,7 @@ class DuneAdapter(QueryExecutor, CatalogExplorer):
|
|
|
47
51
|
q_rewritten = _maybe_rewrite_show_sql(q)
|
|
48
52
|
if q_rewritten is not None:
|
|
49
53
|
q = q_rewritten
|
|
50
|
-
result =
|
|
54
|
+
result = _execute_dune_query(
|
|
51
55
|
query_or_execution=q,
|
|
52
56
|
verbose=False,
|
|
53
57
|
refresh=request.refresh,
|
|
@@ -123,9 +127,10 @@ class DuneAdapter(QueryExecutor, CatalogExplorer):
|
|
|
123
127
|
pass
|
|
124
128
|
|
|
125
129
|
url = urls.get_query_results_url(query_id, parameters=params, csv=False)
|
|
130
|
+
from .user_agent import get_user_agent
|
|
126
131
|
headers = {
|
|
127
132
|
"X-Dune-API-Key": self._api_key(),
|
|
128
|
-
"User-Agent":
|
|
133
|
+
"User-Agent": get_user_agent(),
|
|
129
134
|
}
|
|
130
135
|
try:
|
|
131
136
|
resp = self._http.request("GET", url, headers=headers)
|
|
@@ -196,8 +201,8 @@ class DuneAdapter(QueryExecutor, CatalogExplorer):
|
|
|
196
201
|
def _run_sql(self, sql: str, *, limit: int | None = None) -> pl.DataFrame:
|
|
197
202
|
self._ensure_api_key()
|
|
198
203
|
sql_eff = _maybe_rewrite_show_sql(sql) or sql
|
|
199
|
-
df =
|
|
200
|
-
sql_eff,
|
|
204
|
+
df = _execute_dune_query(
|
|
205
|
+
query_or_execution=sql_eff,
|
|
201
206
|
verbose=False,
|
|
202
207
|
performance="medium",
|
|
203
208
|
timeout_seconds=self.config.default_timeout_seconds,
|