runspec-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.
- runspec_mcp-0.1.0/.gitignore +61 -0
- runspec_mcp-0.1.0/CHANGELOG.md +29 -0
- runspec_mcp-0.1.0/PKG-INFO +121 -0
- runspec_mcp-0.1.0/README.md +101 -0
- runspec_mcp-0.1.0/pyproject.toml +77 -0
- runspec_mcp-0.1.0/runspec_mcp/__init__.py +16 -0
- runspec_mcp-0.1.0/runspec_mcp/catalog.py +324 -0
- runspec_mcp-0.1.0/runspec_mcp/cli.py +237 -0
- runspec_mcp-0.1.0/runspec_mcp/config.py +184 -0
- runspec_mcp-0.1.0/runspec_mcp/configmerge.py +327 -0
- runspec_mcp-0.1.0/runspec_mcp/configseed.py +101 -0
- runspec_mcp-0.1.0/runspec_mcp/credentials.py +316 -0
- runspec_mcp-0.1.0/runspec_mcp/executor.py +1084 -0
- runspec_mcp-0.1.0/runspec_mcp/hosts.py +288 -0
- runspec_mcp-0.1.0/runspec_mcp/manifest.py +51 -0
- runspec_mcp-0.1.0/runspec_mcp/plugin/.claude-plugin/marketplace.json +13 -0
- runspec_mcp-0.1.0/runspec_mcp/plugin/.claude-plugin/plugin.json +18 -0
- runspec_mcp-0.1.0/runspec_mcp/plugin/commands/runspec-hosts.md +9 -0
- runspec_mcp-0.1.0/runspec_mcp/plugin/commands/runspec-refresh.md +11 -0
- runspec_mcp-0.1.0/runspec_mcp/plugin/hooks/autonomy_gate.py +155 -0
- runspec_mcp-0.1.0/runspec_mcp/plugin/hooks/hooks.json +15 -0
- runspec_mcp-0.1.0/runspec_mcp/runner.py +113 -0
- runspec_mcp-0.1.0/runspec_mcp/server.py +227 -0
- runspec_mcp-0.1.0/runspec_mcp/ssh_pool.py +675 -0
- runspec_mcp-0.1.0/runspec_mcp/sshkeys.py +136 -0
- runspec_mcp-0.1.0/tests/test_catalog.py +97 -0
- runspec_mcp-0.1.0/tests/test_config.py +71 -0
- runspec_mcp-0.1.0/tests/test_credentials.py +80 -0
- runspec_mcp-0.1.0/tests/test_manifest.py +31 -0
- runspec_mcp-0.1.0/tests/test_parity.py +57 -0
- runspec_mcp-0.1.0/tests/test_server.py +67 -0
- runspec_mcp-0.1.0/tests/test_sshkeys.py +67 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.pyo
|
|
5
|
+
*.pyd
|
|
6
|
+
.Python
|
|
7
|
+
*.egg
|
|
8
|
+
*.egg-info/
|
|
9
|
+
dist/
|
|
10
|
+
build/
|
|
11
|
+
.eggs/
|
|
12
|
+
.venv/
|
|
13
|
+
venv/
|
|
14
|
+
env/
|
|
15
|
+
.env
|
|
16
|
+
pip-wheel-metadata/
|
|
17
|
+
.pytest_cache/
|
|
18
|
+
.mypy_cache/
|
|
19
|
+
.ruff_cache/
|
|
20
|
+
htmlcov/
|
|
21
|
+
.coverage
|
|
22
|
+
coverage.xml
|
|
23
|
+
*.cover
|
|
24
|
+
|
|
25
|
+
# Node
|
|
26
|
+
node_modules/
|
|
27
|
+
dist/
|
|
28
|
+
*.js.map
|
|
29
|
+
.npm
|
|
30
|
+
|
|
31
|
+
# Go
|
|
32
|
+
*.exe
|
|
33
|
+
*.test
|
|
34
|
+
*.out
|
|
35
|
+
vendor/
|
|
36
|
+
|
|
37
|
+
# IDE
|
|
38
|
+
.idea/
|
|
39
|
+
.vscode/
|
|
40
|
+
*.iml
|
|
41
|
+
*.iws
|
|
42
|
+
*.ipr
|
|
43
|
+
.DS_Store
|
|
44
|
+
Thumbs.db
|
|
45
|
+
|
|
46
|
+
# Docs
|
|
47
|
+
site/
|
|
48
|
+
|
|
49
|
+
# Misc
|
|
50
|
+
*.log
|
|
51
|
+
*.tmp
|
|
52
|
+
|
|
53
|
+
# External reference repos (cloned locally, not committed)
|
|
54
|
+
chainlit-docs/
|
|
55
|
+
.chainlit/
|
|
56
|
+
|
|
57
|
+
# Claude Code local config (machine-specific)
|
|
58
|
+
.claude/launch.json
|
|
59
|
+
|
|
60
|
+
# Stray committed test venv (removed from tracking)
|
|
61
|
+
.venv-test/
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to `runspec-mcp` are documented here.
|
|
4
|
+
|
|
5
|
+
## [0.1.0]
|
|
6
|
+
|
|
7
|
+
Initial release. A local MCP **gateway** that connects Claude Code to local and
|
|
8
|
+
remote runspec runnables from one config file.
|
|
9
|
+
|
|
10
|
+
- Aggregating MCP stdio server (`runspec-mcp serve`) over local venvs and remote
|
|
11
|
+
SSH venvs, discovering runnables via `runspec local --format json` and expanding
|
|
12
|
+
them into leaf MCP tools identical to `runspec serve`.
|
|
13
|
+
- **Live discovery**: declares `tools.listChanged` and pushes
|
|
14
|
+
`notifications/tools/list_changed` from a background discovery thread — the tool
|
|
15
|
+
list stays current with no restart or manual refresh.
|
|
16
|
+
- **Credential injection** as name-derived environment variables (reusing the
|
|
17
|
+
runspec-console convention; secrets in the OS keychain, shared service name),
|
|
18
|
+
auto-matched to runnables by their declared arg `env` or by scope globs.
|
|
19
|
+
- One config file (`runspec_mcp.toml`), or reuse of an existing runspec-console
|
|
20
|
+
config directory (`--config-dir`), or a bundled **config seed** package.
|
|
21
|
+
- **Managed SSH keypair**: the gateway generates and uses its own ed25519 key as
|
|
22
|
+
the default SSH identity (no `~/.ssh` setup needed); `runspec-mcp copy-key`
|
|
23
|
+
installs the public key on hosts over a one-time password login, and
|
|
24
|
+
`runspec-mcp key` shows / rotates it. A per-host `identity_file` and the
|
|
25
|
+
ssh-agent / default keys still work.
|
|
26
|
+
- Ships a Claude Code plugin (MCP server entry + autonomy PreToolUse hook, whose
|
|
27
|
+
manifest the gateway keeps fresh + slash commands).
|
|
28
|
+
- Transport/credentials/config layer vendored from runspec-console, kept
|
|
29
|
+
behaviour-identical by parity tests.
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: runspec-mcp
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Connect Claude Code to local and remote runspec runnables as MCP tools, from one config file
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
Requires-Python: >=3.10
|
|
7
|
+
Requires-Dist: cryptography>=41
|
|
8
|
+
Requires-Dist: paramiko>=3.0
|
|
9
|
+
Requires-Dist: runspec>=0.48.0
|
|
10
|
+
Requires-Dist: tomli>=2.0; python_version < '3.11'
|
|
11
|
+
Provides-Extra: credentials
|
|
12
|
+
Requires-Dist: keyring>=24; extra == 'credentials'
|
|
13
|
+
Provides-Extra: dev
|
|
14
|
+
Requires-Dist: keyring>=24; extra == 'dev'
|
|
15
|
+
Requires-Dist: mypy; extra == 'dev'
|
|
16
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
17
|
+
Requires-Dist: ruff==0.15.20; extra == 'dev'
|
|
18
|
+
Requires-Dist: runspec-console; extra == 'dev'
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
|
|
21
|
+
# runspec-mcp
|
|
22
|
+
|
|
23
|
+
Connect **Claude Code** to the runspec runnables installed across your machines —
|
|
24
|
+
local venvs and remote SSH venvs — from **one config file**, with credentials
|
|
25
|
+
injected as environment variables and each runnable's declared `autonomy` carried
|
|
26
|
+
into Claude Code's permission layer.
|
|
27
|
+
|
|
28
|
+
`runspec-mcp` is a small local **MCP gateway**: Claude Code spawns it as a
|
|
29
|
+
single MCP server; it reads your hosts + credential metadata, discovers the
|
|
30
|
+
runnables in every configured venv (`runspec local --format json`, locally and
|
|
31
|
+
over SSH), and presents them all as MCP tools. Discovery is **live** — as hosts
|
|
32
|
+
connect/disconnect or their runnables change, the tool list updates automatically
|
|
33
|
+
(no restart, no manual refresh).
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
pip install "runspec-mcp[credentials]"
|
|
37
|
+
# write runspec_mcp.toml (or point at an existing runspec-console config dir)
|
|
38
|
+
claude --plugin-dir "$(runspec-mcp plugin-path)"
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
**Any MCP client** (Claude Desktop, Cursor, Cline, or Claude Code without the
|
|
42
|
+
plugin) works too — `runspec-mcp serve` is a standard MCP stdio server. Add a
|
|
43
|
+
`mcpServers` entry:
|
|
44
|
+
|
|
45
|
+
```json
|
|
46
|
+
{ "mcpServers": { "runspec-mcp": {
|
|
47
|
+
"command": "runspec-mcp", "args": ["serve"],
|
|
48
|
+
"env": { "RUNSPEC_MCP_CONFIG": "/absolute/path/to/runspec_mcp.toml" } } } }
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
The Claude Code plugin adds one thing over a bare client: the PreToolUse hook that
|
|
52
|
+
auto-approves `autonomous` runnables. Either way, `manual` runnables are refused
|
|
53
|
+
by the gateway and `password` args never reach a tool schema. See
|
|
54
|
+
[`docs/mcp.md`](../../../docs/mcp.md) for per-client details and the config-seed
|
|
55
|
+
("fleet adapter") how-to.
|
|
56
|
+
|
|
57
|
+
## Config (`runspec_mcp.toml`)
|
|
58
|
+
|
|
59
|
+
```toml
|
|
60
|
+
[local]
|
|
61
|
+
venv_globs = ["~/venvs/*"] # local multi-venv discovery
|
|
62
|
+
|
|
63
|
+
[gateway]
|
|
64
|
+
refresh_interval = 30 # background rediscovery cadence (s); 0 = off
|
|
65
|
+
|
|
66
|
+
[[host]]
|
|
67
|
+
name = "prod"
|
|
68
|
+
ssh = "deploy@prod.example.com" # omit ssh → this machine
|
|
69
|
+
runspec_paths = ["/opt/venvs/fleet/bin/runspec"]
|
|
70
|
+
jump = "bastion" # optional ProxyJump (system ssh)
|
|
71
|
+
|
|
72
|
+
[[credential]]
|
|
73
|
+
id = "Windows" # label → WINDOWS_* env vars
|
|
74
|
+
kind = "userpass" # userpass | password | token | ssh-key
|
|
75
|
+
username = "svc-bot"
|
|
76
|
+
# secret stored in the OS keychain: runspec-mcp cred set Windows
|
|
77
|
+
# scope_hosts / scope_runnables optional — else auto-matched by a runnable's arg `env`
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
A runnable that declares it reads `WINDOWS_USERNAME` / `WINDOWS_PASSWORD` (via an
|
|
81
|
+
arg `env`) auto-pulls the `Windows` credential — no scope config needed.
|
|
82
|
+
|
|
83
|
+
Secrets live in the OS keychain (`keyring`), keyed by credential `id` under the
|
|
84
|
+
`runspec-console` service, so they are **shared with the desktop console**. Point
|
|
85
|
+
the gateway at an existing console setup with `--config-dir <dir>`.
|
|
86
|
+
|
|
87
|
+
## SSH keys
|
|
88
|
+
|
|
89
|
+
**No SSH key ever goes in the MCP config** — only path references. The gateway
|
|
90
|
+
manages its **own ed25519 keypair** and uses it as the default SSH identity, so you
|
|
91
|
+
never touch `~/.ssh`; authorise it on your hosts once:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
runspec-mcp key # print the managed public key
|
|
95
|
+
runspec-mcp copy-key --all # install it on every configured host (one password prompt)
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
A per-host `identity_file` path still overrides it, and ssh-agent / `~/.ssh/id_*`
|
|
99
|
+
remain a fallback.
|
|
100
|
+
|
|
101
|
+
## Commands
|
|
102
|
+
|
|
103
|
+
| command | what it does |
|
|
104
|
+
|---|---|
|
|
105
|
+
| `runspec-mcp serve` | the MCP gateway (what the plugin runs) |
|
|
106
|
+
| `runspec-mcp hosts` | list configured hosts + probe connectivity |
|
|
107
|
+
| `runspec-mcp discover [--host H]` | print discovered tools |
|
|
108
|
+
| `runspec-mcp key [--regenerate]` | show / rotate the managed SSH key |
|
|
109
|
+
| `runspec-mcp copy-key [--all] [HOST…]` | install the managed key on host(s) |
|
|
110
|
+
| `runspec-mcp cred set\|list\|rm ID` | manage credential secrets in the keychain |
|
|
111
|
+
| `runspec-mcp seed-status` | show bundled config-seed contributors |
|
|
112
|
+
| `runspec-mcp plugin-path` | print the bundled Claude Code plugin dir |
|
|
113
|
+
| `runspec-mcp check` | validate config + connectivity + manifest |
|
|
114
|
+
|
|
115
|
+
## Autonomy
|
|
116
|
+
|
|
117
|
+
Each runnable's `autonomy` maps onto a Claude Code permission decision via a
|
|
118
|
+
PreToolUse hook the plugin ships (`autonomous → allow`, `confirm`/`supervised →
|
|
119
|
+
ask`, `manual → deny`, unknown → ask). The gateway rewrites the hook's manifest on
|
|
120
|
+
every discovery change, so it is always fresh. The remote side stays authoritative
|
|
121
|
+
(venv denylist, `enforce_run_as`, `password` args omitted from schemas).
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# runspec-mcp
|
|
2
|
+
|
|
3
|
+
Connect **Claude Code** to the runspec runnables installed across your machines —
|
|
4
|
+
local venvs and remote SSH venvs — from **one config file**, with credentials
|
|
5
|
+
injected as environment variables and each runnable's declared `autonomy` carried
|
|
6
|
+
into Claude Code's permission layer.
|
|
7
|
+
|
|
8
|
+
`runspec-mcp` is a small local **MCP gateway**: Claude Code spawns it as a
|
|
9
|
+
single MCP server; it reads your hosts + credential metadata, discovers the
|
|
10
|
+
runnables in every configured venv (`runspec local --format json`, locally and
|
|
11
|
+
over SSH), and presents them all as MCP tools. Discovery is **live** — as hosts
|
|
12
|
+
connect/disconnect or their runnables change, the tool list updates automatically
|
|
13
|
+
(no restart, no manual refresh).
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
pip install "runspec-mcp[credentials]"
|
|
17
|
+
# write runspec_mcp.toml (or point at an existing runspec-console config dir)
|
|
18
|
+
claude --plugin-dir "$(runspec-mcp plugin-path)"
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
**Any MCP client** (Claude Desktop, Cursor, Cline, or Claude Code without the
|
|
22
|
+
plugin) works too — `runspec-mcp serve` is a standard MCP stdio server. Add a
|
|
23
|
+
`mcpServers` entry:
|
|
24
|
+
|
|
25
|
+
```json
|
|
26
|
+
{ "mcpServers": { "runspec-mcp": {
|
|
27
|
+
"command": "runspec-mcp", "args": ["serve"],
|
|
28
|
+
"env": { "RUNSPEC_MCP_CONFIG": "/absolute/path/to/runspec_mcp.toml" } } } }
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
The Claude Code plugin adds one thing over a bare client: the PreToolUse hook that
|
|
32
|
+
auto-approves `autonomous` runnables. Either way, `manual` runnables are refused
|
|
33
|
+
by the gateway and `password` args never reach a tool schema. See
|
|
34
|
+
[`docs/mcp.md`](../../../docs/mcp.md) for per-client details and the config-seed
|
|
35
|
+
("fleet adapter") how-to.
|
|
36
|
+
|
|
37
|
+
## Config (`runspec_mcp.toml`)
|
|
38
|
+
|
|
39
|
+
```toml
|
|
40
|
+
[local]
|
|
41
|
+
venv_globs = ["~/venvs/*"] # local multi-venv discovery
|
|
42
|
+
|
|
43
|
+
[gateway]
|
|
44
|
+
refresh_interval = 30 # background rediscovery cadence (s); 0 = off
|
|
45
|
+
|
|
46
|
+
[[host]]
|
|
47
|
+
name = "prod"
|
|
48
|
+
ssh = "deploy@prod.example.com" # omit ssh → this machine
|
|
49
|
+
runspec_paths = ["/opt/venvs/fleet/bin/runspec"]
|
|
50
|
+
jump = "bastion" # optional ProxyJump (system ssh)
|
|
51
|
+
|
|
52
|
+
[[credential]]
|
|
53
|
+
id = "Windows" # label → WINDOWS_* env vars
|
|
54
|
+
kind = "userpass" # userpass | password | token | ssh-key
|
|
55
|
+
username = "svc-bot"
|
|
56
|
+
# secret stored in the OS keychain: runspec-mcp cred set Windows
|
|
57
|
+
# scope_hosts / scope_runnables optional — else auto-matched by a runnable's arg `env`
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
A runnable that declares it reads `WINDOWS_USERNAME` / `WINDOWS_PASSWORD` (via an
|
|
61
|
+
arg `env`) auto-pulls the `Windows` credential — no scope config needed.
|
|
62
|
+
|
|
63
|
+
Secrets live in the OS keychain (`keyring`), keyed by credential `id` under the
|
|
64
|
+
`runspec-console` service, so they are **shared with the desktop console**. Point
|
|
65
|
+
the gateway at an existing console setup with `--config-dir <dir>`.
|
|
66
|
+
|
|
67
|
+
## SSH keys
|
|
68
|
+
|
|
69
|
+
**No SSH key ever goes in the MCP config** — only path references. The gateway
|
|
70
|
+
manages its **own ed25519 keypair** and uses it as the default SSH identity, so you
|
|
71
|
+
never touch `~/.ssh`; authorise it on your hosts once:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
runspec-mcp key # print the managed public key
|
|
75
|
+
runspec-mcp copy-key --all # install it on every configured host (one password prompt)
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
A per-host `identity_file` path still overrides it, and ssh-agent / `~/.ssh/id_*`
|
|
79
|
+
remain a fallback.
|
|
80
|
+
|
|
81
|
+
## Commands
|
|
82
|
+
|
|
83
|
+
| command | what it does |
|
|
84
|
+
|---|---|
|
|
85
|
+
| `runspec-mcp serve` | the MCP gateway (what the plugin runs) |
|
|
86
|
+
| `runspec-mcp hosts` | list configured hosts + probe connectivity |
|
|
87
|
+
| `runspec-mcp discover [--host H]` | print discovered tools |
|
|
88
|
+
| `runspec-mcp key [--regenerate]` | show / rotate the managed SSH key |
|
|
89
|
+
| `runspec-mcp copy-key [--all] [HOST…]` | install the managed key on host(s) |
|
|
90
|
+
| `runspec-mcp cred set\|list\|rm ID` | manage credential secrets in the keychain |
|
|
91
|
+
| `runspec-mcp seed-status` | show bundled config-seed contributors |
|
|
92
|
+
| `runspec-mcp plugin-path` | print the bundled Claude Code plugin dir |
|
|
93
|
+
| `runspec-mcp check` | validate config + connectivity + manifest |
|
|
94
|
+
|
|
95
|
+
## Autonomy
|
|
96
|
+
|
|
97
|
+
Each runnable's `autonomy` maps onto a Claude Code permission decision via a
|
|
98
|
+
PreToolUse hook the plugin ships (`autonomous → allow`, `confirm`/`supervised →
|
|
99
|
+
ask`, `manual → deny`, unknown → ask). The gateway rewrites the hook's manifest on
|
|
100
|
+
every discovery change, so it is always fresh. The remote side stays authoritative
|
|
101
|
+
(venv denylist, `enforce_run_as`, `password` args omitted from schemas).
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "runspec-mcp"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
requires-python = ">=3.10"
|
|
9
|
+
description = "Connect Claude Code to local and remote runspec runnables as MCP tools, from one config file"
|
|
10
|
+
readme = "README.md"
|
|
11
|
+
license = "MIT"
|
|
12
|
+
dependencies = [
|
|
13
|
+
# 0.48.0 for the `discoverable` boolean + serve leaf globals; the gateway
|
|
14
|
+
# reuses runspec.cli._build_schema and runspec.become.build_become_argv.
|
|
15
|
+
"runspec>=0.48.0",
|
|
16
|
+
# Warm SSH connection pool for remote venvs (mirrors runspec-console).
|
|
17
|
+
"paramiko>=3.0",
|
|
18
|
+
# Managed ed25519 keypair generation (also a transitive paramiko dep).
|
|
19
|
+
"cryptography>=41",
|
|
20
|
+
"tomli>=2.0; python_version < '3.11'",
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
[project.optional-dependencies]
|
|
24
|
+
# Secret storage in the OS keychain. Without it the gateway still runs; only
|
|
25
|
+
# credential injection is disabled (same opt-in split as runspec-console).
|
|
26
|
+
credentials = ["keyring>=24"]
|
|
27
|
+
dev = [
|
|
28
|
+
"ruff==0.15.20",
|
|
29
|
+
"mypy",
|
|
30
|
+
"pytest>=8.0",
|
|
31
|
+
"keyring>=24",
|
|
32
|
+
# Dev-only: the parity tests import the console originals to assert the
|
|
33
|
+
# vendored transport/credential/merge helpers behave identically.
|
|
34
|
+
"runspec-console",
|
|
35
|
+
]
|
|
36
|
+
|
|
37
|
+
[project.scripts]
|
|
38
|
+
runspec-mcp = "runspec_mcp.cli:main"
|
|
39
|
+
|
|
40
|
+
# A corporate seed package can ship a config_seed/ dir under either group; the
|
|
41
|
+
# fleet reads both so one seed configures the console and the plugin alike.
|
|
42
|
+
# [project.entry-points."runspec_mcp.config_seed"]
|
|
43
|
+
# mycorp = "mycorp_fleet"
|
|
44
|
+
|
|
45
|
+
[tool.hatch.build.targets.wheel]
|
|
46
|
+
# The Claude Code plugin under runspec_mcp/plugin/ ships as package data so
|
|
47
|
+
# `runspec-mcp plugin-path` can point Claude Code at it.
|
|
48
|
+
packages = ["runspec_mcp"]
|
|
49
|
+
artifacts = ["runspec_mcp/plugin/**"]
|
|
50
|
+
|
|
51
|
+
[tool.pytest.ini_options]
|
|
52
|
+
testpaths = ["tests"]
|
|
53
|
+
|
|
54
|
+
[tool.mypy]
|
|
55
|
+
python_version = "3.10"
|
|
56
|
+
# Vendored-verbatim modules follow the console's own typing upstream; kept
|
|
57
|
+
# honest by tests/test_parity.py rather than re-checked here.
|
|
58
|
+
exclude = "runspec_mcp/(executor|ssh_pool|configmerge|hosts)\\.py$"
|
|
59
|
+
|
|
60
|
+
[[tool.mypy.overrides]]
|
|
61
|
+
module = ["paramiko.*", "keyring.*", "tomli", "runspec.*", "runspec_console.*"]
|
|
62
|
+
ignore_missing_imports = true
|
|
63
|
+
|
|
64
|
+
[tool.ruff]
|
|
65
|
+
line-length = 200
|
|
66
|
+
target-version = "py310"
|
|
67
|
+
# These modules are vendored verbatim from runspec-console and kept
|
|
68
|
+
# behaviour-identical by tests/test_parity.py — they follow the console's own
|
|
69
|
+
# lint config upstream; restyling them here would create drift, so we don't lint
|
|
70
|
+
# them locally.
|
|
71
|
+
extend-exclude = ["runspec_mcp/executor.py", "runspec_mcp/ssh_pool.py", "runspec_mcp/configmerge.py", "runspec_mcp/hosts.py", "runspec_mcp/plugin"]
|
|
72
|
+
|
|
73
|
+
[tool.ruff.lint]
|
|
74
|
+
select = ["E", "F", "I", "UP", "B", "SIM"]
|
|
75
|
+
# try/except/pass with an explanatory comment (best-effort swallow) reads more
|
|
76
|
+
# clearly than contextlib.suppress here, and matches the vendored modules.
|
|
77
|
+
ignore = ["SIM105"]
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"""
|
|
2
|
+
runspec-mcp — connect Claude Code to local and remote runspec runnables.
|
|
3
|
+
|
|
4
|
+
A single local MCP *gateway* server that reads one config file (hosts + credential
|
|
5
|
+
metadata), discovers the runnables installed in every configured venv (local and
|
|
6
|
+
over SSH), and presents them all to Claude Code as MCP tools — with each
|
|
7
|
+
runnable's declared ``autonomy`` carried into Claude Code's permission layer and
|
|
8
|
+
credentials injected as environment variables the way runspec-console does.
|
|
9
|
+
|
|
10
|
+
The public surface is the ``runspec-mcp`` CLI (see ``cli.py``); the MCP server
|
|
11
|
+
is ``runspec-mcp serve``.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
__version__ = "0.1.0"
|