stackql-mcp-server 0.10.500__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.
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"""
|
|
2
|
+
stackql-mcp-server - uvx/pip-able launcher for the StackQL MCP server.
|
|
3
|
+
|
|
4
|
+
On first run, downloads the platform's signed .mcpb bundle from the GitHub
|
|
5
|
+
release pinned in platforms.json, verifies its sha256, extracts the stackql
|
|
6
|
+
binary into ~/.stackql/mcp-server-bin/<version>/ (a cache shared with the
|
|
7
|
+
@stackql/mcp-server npm wrapper), then runs it as an MCP stdio server.
|
|
8
|
+
|
|
9
|
+
Extra arguments are passed through to stackql after the standard MCP args:
|
|
10
|
+
|
|
11
|
+
uvx stackql-mcp-server --auth='{"github":{"type":"null_auth"}}'
|
|
12
|
+
|
|
13
|
+
Env overrides:
|
|
14
|
+
STACKQL_MCP_BIN path to an existing stackql binary (skips download)
|
|
15
|
+
STACKQL_MCP_BUNDLE path to a local .mcpb to extract from (CI/testing;
|
|
16
|
+
skips download and sha verification)
|
|
17
|
+
|
|
18
|
+
All diagnostics go to stderr - stdout belongs to the MCP protocol.
|
|
19
|
+
Stdlib only, no dependencies.
|
|
20
|
+
"""
|
|
21
|
+
from __future__ import annotations
|
|
22
|
+
|
|
23
|
+
import hashlib
|
|
24
|
+
import json
|
|
25
|
+
import os
|
|
26
|
+
import platform as _platform
|
|
27
|
+
import subprocess
|
|
28
|
+
import sys
|
|
29
|
+
import urllib.request
|
|
30
|
+
import zipfile
|
|
31
|
+
from importlib.resources import files
|
|
32
|
+
from io import BytesIO
|
|
33
|
+
from pathlib import Path
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def _log(msg: str) -> None:
|
|
37
|
+
print(f"stackql-mcp: {msg}", file=sys.stderr, flush=True)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def _platform_key() -> str | None:
|
|
41
|
+
machine = _platform.machine().lower()
|
|
42
|
+
if sys.platform.startswith("linux"):
|
|
43
|
+
if machine in ("x86_64", "amd64"):
|
|
44
|
+
return "linux-x64"
|
|
45
|
+
if machine in ("arm64", "aarch64"):
|
|
46
|
+
return "linux-arm64"
|
|
47
|
+
return None
|
|
48
|
+
if sys.platform == "win32":
|
|
49
|
+
return "windows-x64" if machine in ("x86_64", "amd64") else None
|
|
50
|
+
if sys.platform == "darwin":
|
|
51
|
+
return "darwin-universal" # universal binary covers x64 + arm64
|
|
52
|
+
return None
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def _load_manifest() -> dict:
|
|
56
|
+
return json.loads(files(__package__).joinpath("platforms.json").read_text())
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def _download(url: str) -> bytes:
|
|
60
|
+
req = urllib.request.Request(url, headers={"User-Agent": "stackql-mcp-server"})
|
|
61
|
+
with urllib.request.urlopen(req) as resp: # follows redirects
|
|
62
|
+
return resp.read()
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def _extract_binary(bundle: bytes, entry_name: str, dest: Path) -> None:
|
|
66
|
+
with zipfile.ZipFile(BytesIO(bundle)) as zf:
|
|
67
|
+
data = zf.read(entry_name)
|
|
68
|
+
dest.parent.mkdir(parents=True, exist_ok=True)
|
|
69
|
+
# write-then-rename so a concurrent first run cannot see a half-written binary
|
|
70
|
+
tmp = dest.with_name(f"{dest.name}.tmp-{os.getpid()}")
|
|
71
|
+
tmp.write_bytes(data)
|
|
72
|
+
tmp.chmod(0o755)
|
|
73
|
+
tmp.replace(dest)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def _ensure_binary() -> str:
|
|
77
|
+
override = os.environ.get("STACKQL_MCP_BIN")
|
|
78
|
+
if override:
|
|
79
|
+
return override
|
|
80
|
+
|
|
81
|
+
key = _platform_key()
|
|
82
|
+
if key is None:
|
|
83
|
+
_log(f"unsupported platform: {sys.platform}/{_platform.machine()}")
|
|
84
|
+
raise SystemExit(1)
|
|
85
|
+
|
|
86
|
+
manifest = _load_manifest()
|
|
87
|
+
info = manifest["platforms"][key]
|
|
88
|
+
bin_name = "stackql.exe" if key == "windows-x64" else "stackql"
|
|
89
|
+
bin_path = (
|
|
90
|
+
Path.home() / ".stackql" / "mcp-server-bin" / manifest["version"] / key / bin_name
|
|
91
|
+
)
|
|
92
|
+
if bin_path.exists():
|
|
93
|
+
return str(bin_path)
|
|
94
|
+
|
|
95
|
+
local_bundle = os.environ.get("STACKQL_MCP_BUNDLE")
|
|
96
|
+
if local_bundle:
|
|
97
|
+
bundle = Path(local_bundle).read_bytes()
|
|
98
|
+
else:
|
|
99
|
+
url = f"{manifest['baseUrl']}/{info['bundle']}"
|
|
100
|
+
_log(f"downloading {info['bundle']} (first run only) ...")
|
|
101
|
+
bundle = _download(url)
|
|
102
|
+
digest = hashlib.sha256(bundle).hexdigest()
|
|
103
|
+
if digest != info["sha256"]:
|
|
104
|
+
_log(f"sha256 mismatch for {info['bundle']}")
|
|
105
|
+
_log(f" expected {info['sha256']}")
|
|
106
|
+
_log(f" got {digest}")
|
|
107
|
+
raise SystemExit(1)
|
|
108
|
+
_extract_binary(bundle, f"server/{bin_name}", bin_path)
|
|
109
|
+
_log(f"installed {bin_path}")
|
|
110
|
+
return str(bin_path)
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def main() -> None:
|
|
114
|
+
bin_path = _ensure_binary()
|
|
115
|
+
# approot and the audit sink must not depend on the cwd: MCP clients may
|
|
116
|
+
# launch this with cwd '/' (read-only on macOS). Later duplicate flags
|
|
117
|
+
# win, so user-passed overrides still take effect.
|
|
118
|
+
args = [
|
|
119
|
+
bin_path,
|
|
120
|
+
"mcp",
|
|
121
|
+
"--mcp.server.type=stdio",
|
|
122
|
+
"--approot", str(Path.home() / ".stackql"),
|
|
123
|
+
"--mcp.config", json.dumps({"server": {"audit": {"disabled": True}}}),
|
|
124
|
+
*sys.argv[1:],
|
|
125
|
+
]
|
|
126
|
+
if os.name != "nt":
|
|
127
|
+
os.execv(bin_path, args) # replace this process; signals flow naturally
|
|
128
|
+
raise SystemExit(subprocess.call(args))
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "0.10.500",
|
|
3
|
+
"baseUrl": "https://github.com/stackql/stackql/releases/download/v0.10.500",
|
|
4
|
+
"platforms": {
|
|
5
|
+
"linux-x64": { "bundle": "stackql-mcp-linux-x64.mcpb", "sha256": "6615737747156b1a8413a976afb23af2e7eec29ebc98a6f0a0f65d1b153c44be" },
|
|
6
|
+
"linux-arm64": { "bundle": "stackql-mcp-linux-arm64.mcpb", "sha256": "594bedbabc3096dc3563c907724e845ce0b61a67de4b3fed4158b40c0363786c" },
|
|
7
|
+
"windows-x64": { "bundle": "stackql-mcp-windows-x64.mcpb", "sha256": "d2ce895e88f9c6b557df07073158629808f56d75598f3a701164d65506b791b0" },
|
|
8
|
+
"darwin-universal": { "bundle": "stackql-mcp-darwin-universal.mcpb", "sha256": "4eed70af5cfa67295ae0b42fa3a6dca71ac9acabd0d67914fd96ad1247a9b4cc" }
|
|
9
|
+
}
|
|
10
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: stackql-mcp-server
|
|
3
|
+
Version: 0.10.500
|
|
4
|
+
Summary: StackQL MCP server - SQL-native query and provisioning engine for cloud infrastructure, served over MCP. Downloads the signed stackql binary on first run.
|
|
5
|
+
Project-URL: Homepage, https://stackql.io
|
|
6
|
+
Project-URL: Documentation, https://stackql.io/docs
|
|
7
|
+
Project-URL: Source, https://github.com/stackql/stackql
|
|
8
|
+
Author-email: StackQL Studios <info@stackql.io>
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
Keywords: cloud,devops,infrastructure,mcp,model-context-protocol,multicloud,sql,stackql
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Operating System :: OS Independent
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Topic :: Database
|
|
15
|
+
Classifier: Topic :: System :: Systems Administration
|
|
16
|
+
Requires-Python: >=3.9
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
|
|
19
|
+
# stackql-mcp-server
|
|
20
|
+
|
|
21
|
+
mcp-name: io.github.stackql/stackql-mcp
|
|
22
|
+
|
|
23
|
+
uvx/pip-able launcher for the [StackQL](https://stackql.io) MCP server - a
|
|
24
|
+
SQL-native query and provisioning engine for cloud and SaaS infrastructure
|
|
25
|
+
(AWS, Azure, Google, GitHub, Databricks, and 40+ other providers), served over
|
|
26
|
+
the Model Context Protocol.
|
|
27
|
+
|
|
28
|
+
On first run, the launcher downloads the signed `stackql` binary for your
|
|
29
|
+
platform from the matching GitHub release (sha256-verified against pins baked
|
|
30
|
+
into this package), caches it under `~/.stackql/mcp-server-bin/`, and starts
|
|
31
|
+
it as an MCP stdio server. Subsequent runs start instantly from the cache.
|
|
32
|
+
Pure stdlib - no dependencies.
|
|
33
|
+
|
|
34
|
+
## Usage
|
|
35
|
+
|
|
36
|
+
With any MCP client that supports stdio servers:
|
|
37
|
+
|
|
38
|
+
```json
|
|
39
|
+
{
|
|
40
|
+
"mcpServers": {
|
|
41
|
+
"stackql": {
|
|
42
|
+
"command": "uvx",
|
|
43
|
+
"args": ["stackql-mcp-server"]
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Provider credentials are passed through with stackql's standard `--auth` flag:
|
|
50
|
+
|
|
51
|
+
```json
|
|
52
|
+
{
|
|
53
|
+
"mcpServers": {
|
|
54
|
+
"stackql": {
|
|
55
|
+
"command": "uvx",
|
|
56
|
+
"args": [
|
|
57
|
+
"stackql-mcp-server",
|
|
58
|
+
"--auth={\"github\":{\"type\":\"null_auth\"}}"
|
|
59
|
+
]
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Or install it: `pip install stackql-mcp-server`, then use `stackql-mcp` as the
|
|
66
|
+
command. Any extra arguments are passed to `stackql` after the standard MCP
|
|
67
|
+
server arguments. The launcher sets `--approot` to `~/.stackql` and disables
|
|
68
|
+
the audit file sink by default; pass your own `--approot` or `--mcp.config`
|
|
69
|
+
to override (later flags win).
|
|
70
|
+
|
|
71
|
+
## Environment overrides
|
|
72
|
+
|
|
73
|
+
- `STACKQL_MCP_BIN` - path to an existing `stackql` binary; skips the download.
|
|
74
|
+
- `STACKQL_MCP_BUNDLE` - path to a local `.mcpb` bundle to extract the binary
|
|
75
|
+
from (testing; skips download and sha verification).
|
|
76
|
+
|
|
77
|
+
## Other installation vectors
|
|
78
|
+
|
|
79
|
+
- Claude Desktop one-click bundles (`.mcpb`):
|
|
80
|
+
https://github.com/stackql/stackql/releases/latest
|
|
81
|
+
- npm: `npx -y @stackql/mcp-server`
|
|
82
|
+
- Docker: `docker run -i --rm stackql/stackql-mcp`
|
|
83
|
+
- Native installers and package managers: https://stackql.io/docs/installing-stackql
|
|
84
|
+
|
|
85
|
+
## Links
|
|
86
|
+
|
|
87
|
+
- Docs: https://stackql.io/docs
|
|
88
|
+
- MCP Registry: `io.github.stackql/stackql-mcp`
|
|
89
|
+
- Source: https://github.com/stackql/stackql
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
stackql_mcp_server/__init__.py,sha256=mKwdLeQdsoM1vRZmX2sgn3BDvKpbawZCIr0xj-seKiw,4362
|
|
2
|
+
stackql_mcp_server/platforms.json,sha256=HwwZqLRXEBExQztMTZY93ruSmY_nsqPlpwkUtgikLCw,706
|
|
3
|
+
stackql_mcp_server-0.10.500.dist-info/METADATA,sha256=TwJbOUdI2eUyHDu-OmpkI3nE-_pYA011VF3q36TNnl0,2959
|
|
4
|
+
stackql_mcp_server-0.10.500.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
|
|
5
|
+
stackql_mcp_server-0.10.500.dist-info/entry_points.txt,sha256=31my4mwZ6PY1MtGAhpH4pgkXlyIr3wE0Nk3FLB22DZo,101
|
|
6
|
+
stackql_mcp_server-0.10.500.dist-info/RECORD,,
|