host-execution-mcp 1.0.1 → 2.0.0
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.
- package/CHANGELOG.md +37 -0
- package/README.md +13 -11
- package/SECURITY.md +3 -3
- package/dist/access/index.d.ts +21 -10
- package/dist/access/index.js +55 -27
- package/dist/access/index.js.map +1 -1
- package/dist/access/paradi-auth.d.ts +3 -3
- package/dist/access/paradi-auth.js +4 -4
- package/dist/access/paradi-auth.js.map +1 -1
- package/dist/access/paradi-transport.d.ts +1 -1
- package/dist/access/paradi-transport.js +3 -3
- package/dist/access/paradi-transport.js.map +1 -1
- package/dist/access/paradi-username.d.ts +1 -1
- package/dist/access/paradi-username.js +2 -2
- package/dist/access/paradi-username.js.map +1 -1
- package/dist/access/session-pool.d.ts +5 -0
- package/dist/access/session-pool.js +7 -0
- package/dist/access/session-pool.js.map +1 -1
- package/dist/access/ssh-transport.d.ts +1 -1
- package/dist/access/ssh-transport.js +3 -2
- package/dist/access/ssh-transport.js.map +1 -1
- package/dist/config-yaml.d.ts +54 -0
- package/dist/config-yaml.js +172 -0
- package/dist/config-yaml.js.map +1 -0
- package/dist/config.d.ts +45 -1
- package/dist/config.js +126 -22
- package/dist/config.js.map +1 -1
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/instructions.d.ts +4 -1
- package/dist/instructions.js +73 -51
- package/dist/instructions.js.map +1 -1
- package/dist/kubectl/runner.d.ts +7 -8
- package/dist/kubectl/runner.js +18 -21
- package/dist/kubectl/runner.js.map +1 -1
- package/dist/link-runtime.d.ts +39 -0
- package/dist/link-runtime.js +134 -0
- package/dist/link-runtime.js.map +1 -0
- package/dist/server.d.ts +2 -1
- package/dist/server.js +10 -12
- package/dist/server.js.map +1 -1
- package/dist/sources/guides.d.ts +34 -0
- package/dist/sources/guides.js +50 -0
- package/dist/sources/guides.js.map +1 -0
- package/dist/sources/index.d.ts +5 -0
- package/dist/sources/index.js +22 -0
- package/dist/sources/index.js.map +1 -0
- package/dist/sources/yaml-template.d.ts +31 -0
- package/dist/sources/yaml-template.js +35 -0
- package/dist/sources/yaml-template.js.map +1 -0
- package/dist/ssh/access-client.d.ts +6 -2
- package/dist/ssh/access-client.js +58 -27
- package/dist/ssh/access-client.js.map +1 -1
- package/dist/ssh/access-errors.js +1 -1
- package/dist/ssh/access-errors.js.map +1 -1
- package/dist/ssh/access-sftp.js +3 -3
- package/dist/ssh/access-sftp.js.map +1 -1
- package/dist/tools/copy-job-schemas.d.ts +96 -581
- package/dist/tools/copy-job-schemas.js +9 -9
- package/dist/tools/copy-job-schemas.js.map +1 -1
- package/dist/tools/register.d.ts +2 -10
- package/dist/tools/register.js +174 -331
- package/dist/tools/register.js.map +1 -1
- package/dist/tools/remote-schemas.d.ts +156 -708
- package/dist/tools/remote-schemas.js +99 -103
- package/dist/tools/remote-schemas.js.map +1 -1
- package/dist/utils/copy-executor.d.ts +3 -1
- package/dist/utils/copy-executor.js +39 -25
- package/dist/utils/copy-executor.js.map +1 -1
- package/dist/utils/copy-transfer.d.ts +2 -0
- package/dist/utils/copy-transfer.js.map +1 -1
- package/dist/utils/remote-executor.d.ts +3 -4
- package/dist/utils/remote-executor.js +8 -18
- package/dist/utils/remote-executor.js.map +1 -1
- package/dist/utils/remote-target.js +1 -1
- package/dist/utils/remote-target.js.map +1 -1
- package/docs/AGENT_GUIDE.md +31 -103
- package/docs/CONFIGURATION.md +30 -9
- package/docs/GUIDE.md +186 -0
- package/docs/PARADI_ACCESS_PLAN.md +6 -6
- package/docs/TODO.md +4 -11
- package/docs/USER_GUIDE.zh-CN.md +26 -173
- package/docs/host-execution.yaml +92 -0
- package/package.json +3 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remote-executor.js","sourceRoot":"","sources":["../../src/utils/remote-executor.ts"],"names":[],"mappings":"AAKA
|
|
1
|
+
{"version":3,"file":"remote-executor.js","sourceRoot":"","sources":["../../src/utils/remote-executor.ts"],"names":[],"mappings":"AAKA;;GAEG;AACH,MAAM,OAAO,cAAc;IAEN;IACA;IACA;IAHnB,YACmB,MAAqB,EACrB,OAAsB,EACtB,MAAiB;QAFjB,WAAM,GAAN,MAAM,CAAe;QACrB,YAAO,GAAP,OAAO,CAAe;QACtB,WAAM,GAAN,MAAM,CAAW;IACjC,CAAC;IAEJ,KAAK,CAAC,WAAW,CAAC,MAAuB,EAAE,OAAe,EAAE,SAAkB;QAC5E,MAAM,OAAO,GAAG,SAAS,IAAI,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC;QAC1D,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAC9B,OAAO,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,OAAO,EAAE;gBACpC,UAAU,EAAE,MAAM,CAAC,UAAU;gBAC7B,SAAS,EAAE,OAAO;aACnB,CAAC,CAAC;QACL,CAAC;QACD,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CACtB,MAAM,CAAC,SAAS,EAChB,MAAM,CAAC,GAAG,EACV,OAAO,EACP,MAAM,CAAC,SAAS,EAChB,OAAO,EACP,MAAM,CAAC,UAAU,CAClB,CAAC;IACJ,CAAC;CACF"}
|
|
@@ -11,7 +11,7 @@ export function resolveRemotePassword(password, defaultPassword) {
|
|
|
11
11
|
export function resolveRemoteUser(user, defaultUser) {
|
|
12
12
|
const resolved = user?.trim() || defaultUser?.trim();
|
|
13
13
|
if (!resolved) {
|
|
14
|
-
throw new Error('
|
|
14
|
+
throw new Error('Second-hop / Paradi host tools require "user" or TARGET_USER. Do not assume root.');
|
|
15
15
|
}
|
|
16
16
|
return resolved;
|
|
17
17
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remote-target.js","sourceRoot":"","sources":["../../src/utils/remote-target.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,qBAAqB,CACnC,QAA4B,EAC5B,eAAmC;IAEnC,6EAA6E;IAC7E,IAAI,QAAQ,KAAK,SAAS,IAAI,QAAQ,KAAK,EAAE,EAAE,CAAC;QAC9C,OAAO,QAAQ,CAAC;IAClB,CAAC;IACD,IAAI,eAAe,KAAK,SAAS,IAAI,eAAe,KAAK,EAAE,EAAE,CAAC;QAC5D,OAAO,eAAe,CAAC;IACzB,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,iBAAiB,CAC/B,IAAwB,EACxB,WAA+B;IAE/B,MAAM,QAAQ,GAAG,IAAI,EAAE,IAAI,EAAE,IAAI,WAAW,EAAE,IAAI,EAAE,CAAC;IACrD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CACb,
|
|
1
|
+
{"version":3,"file":"remote-target.js","sourceRoot":"","sources":["../../src/utils/remote-target.ts"],"names":[],"mappings":"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"}
|
package/docs/AGENT_GUIDE.md
CHANGED
|
@@ -1,110 +1,45 @@
|
|
|
1
1
|
# Agent Guide — host-execution-mcp
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Operational cookbook. User-facing usage and config are in [GUIDE.md](./GUIDE.md) (MCP Resource `host-execution://guides/user`).
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
**GUIDE.md is the capability the user wants this MCP to provide.** If a tool error, missing path, timeout, or implementation gap means that capability is not met, tell the user promptly — do not hide it or invent a workaround that pretends the tool worked.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Handshake `instructions` stay short. Once per conversation, `listResources` and read `host-execution://guides/user`, `host-execution://guides/agent`, and `host-execution://guides/yaml` (before creating or appending a roster link). Reuse for the session. Do not look for repo file paths.
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|-------------|-----------------|----------------------------------------|
|
|
11
|
-
| `ssh` (default) | ACCESS host | ACCESS OS |
|
|
12
|
-
| `paradi-gateway` | TARGET host | TARGET OS (not the gateway) |
|
|
9
|
+
## Tool returns
|
|
13
10
|
|
|
14
|
-
|
|
11
|
+
On **success** (`exitCode===0`), remote stdout and stderr are merged into `stdout`; `stderr` is empty.
|
|
15
12
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
**On this MCP path**, there is no laptop SSH to pods or cluster nodes.
|
|
19
|
-
|
|
20
|
-
### Shape A — ACCESS_KIND=ssh
|
|
21
|
-
|
|
22
|
-
```
|
|
23
|
-
┌─────────────┐ Hop 1 (automatic) ┌──────────┐ Hop 2 (tools) ┌────────────┐
|
|
24
|
-
│ MCP Client │ ─── SSH (ssh2) ──────► │ ACCESS │ ── kubectl exec ────► │ Pod │
|
|
25
|
-
│ + MCP Server│ │ landing │ ── ssh/sshpass ─────► │ Host/node │
|
|
26
|
-
└─────────────┘ │ │ ── shell / docker ──► │ ACCESS OS │
|
|
27
|
-
└──────────┘ └────────────┘
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
`TARGET_*` (optional) = **default derive selector only** — not a second Context at init. `ssh_exec` = derive + shell.
|
|
31
|
-
|
|
32
|
-
### Shape B — ACCESS_KIND=paradi-gateway
|
|
33
|
-
|
|
34
|
-
```
|
|
35
|
-
┌─────────────┐ Hop 1 ┌──────────┐
|
|
36
|
-
│ MCP Client │ ── SSH (encoded user) ►│ Gateway │──► landing Context = TARGET
|
|
37
|
-
└─────────────┘ ACCESS_USER/TARGET_HOST/TARGET_USER
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
Runtime tools run on **TARGET**. Disabled: `context_derive`, `remote_*` / `remote_copy_*` with `target=context`. Use `shell_exec` / `target=landing` / `docker_*` (omit contextKey). SFTP is `degraded` — avoid parallel hammering; prefer smaller copies / `remote_copy_start`.
|
|
41
|
-
|
|
42
|
-
| Hop | Who initiates | What |
|
|
43
|
-
|-----|---------------|------|
|
|
44
|
-
| **Hop 1** | MCP server on user's machine | SSH to `ACCESS_HOST` (always; not exposed as a tool) |
|
|
45
|
-
| **Hop 2** | Landing Context | `shell_exec`, `k8s_*`, `ssh_exec` (ssh only), `docker_*`, `remote_*` |
|
|
46
|
-
|
|
47
|
-
**Common misconception:** `ssh_exec` is **NOT** "local laptop SSH to remote host". It means **ACCESS SSHs to the target** (`ACCESS_KIND=ssh` only).
|
|
48
|
-
|
|
49
|
-
## Capability boundary
|
|
13
|
+
On **command failure** (`exitCode≠0`, `success=false`, no thrown exception): merged remote output is still in **`stdout`**. Only tool/connection exceptions (e.g. `ACCESS_UNAVAILABLE`) put the message in `stderr`.
|
|
50
14
|
|
|
51
|
-
|
|
15
|
+
Always check both `success` / `exitCode` and `stdout`.
|
|
52
16
|
|
|
17
|
+
- Host Docker engine → `docker_*`. Kubernetes container → `k8s_exec` / `k8s_logs`.
|
|
53
18
|
- `docker_*` auto-probes `capabilities.docker` (unknown ≠ true).
|
|
54
|
-
- `k8s_*` does
|
|
55
|
-
|
|
56
|
-
## Three Runtime paths (ssh)
|
|
57
|
-
|
|
58
|
-
| Path | Tool(s) | Action |
|
|
59
|
-
|------|---------|--------|
|
|
60
|
-
| **Landing shell** | `shell_exec`, `remote_*` target=landing | Run on ACCESS (or TARGET under Paradi) |
|
|
61
|
-
| **Pod** | `k8s_exec`, `k8s_logs`, `remote_*` target=pod | kubectl exec / logs |
|
|
62
|
-
| **Derived host** | `context_derive` → `ssh_exec`, `remote_*` target=context | ssh/sshpass — **ssh kind only** |
|
|
63
|
-
|
|
64
|
-
### Decision matrix
|
|
65
|
-
|
|
66
|
-
| User intent | Tool (ssh) | Tool (paradi) |
|
|
67
|
-
|-------------|------------|---------------|
|
|
68
|
-
| List/find pods | `k8s_list_pods` | same |
|
|
69
|
-
| Run script in container | `k8s_exec` | same |
|
|
70
|
-
| Read file in container | `remote_read_file` target=pod | same |
|
|
71
|
-
| Host OS shell on landing | `shell_exec` | `shell_exec` (TARGET) |
|
|
72
|
-
| Host OS after jump | `context_derive` + `ssh_exec` / target=context | **disabled** — already on TARGET |
|
|
73
|
-
| Docker on landing | `docker_*` | `docker_*` (no host) |
|
|
74
|
-
| Docker on worker | `docker_*` + contextKey | **disabled** under Paradi |
|
|
75
|
-
| Copy short | `remote_copy_file` | same; no `target=context` under Paradi |
|
|
76
|
-
| Copy large | `remote_copy_start` | same; SFTP degraded |
|
|
19
|
+
- `k8s_*` does not gate on `capabilities.kubectl` — failures surface as exitCode; use `context_probe` for presence.
|
|
77
20
|
|
|
78
|
-
##
|
|
79
|
-
|
|
80
|
-
| Tool | Reaches | Auth / notes |
|
|
81
|
-
|------|---------|----------------|
|
|
82
|
-
| `shell_exec` | Landing OS shell | ACCESS_* (Paradi: TARGET via gateway); optional contextKey |
|
|
83
|
-
| `k8s_exec` | Inside pod container | Landing kubeconfig |
|
|
84
|
-
| `ssh_exec` | Host OS (derive + shell) | ACCESS→host / TARGET_*; unavailable under Paradi |
|
|
85
|
-
| `docker_ps` / `docker_exec` / `docker_logs` | Docker on landing or derived Context | SessionPool; contextKey; auto-probes docker; unknown ≠ true |
|
|
86
|
-
| `context_probe` | Same Context | Returns docker/kubectl tri-state |
|
|
87
|
-
|
|
88
|
-
**Derived-host defaults (`TARGET_USER` / `TARGET_PASSWORD`):** optional under ssh. When both set, omit `user`/`password`. Password-only: omit password, still pass user. See one-line status in server instructions. Under Paradi, derive guidance is replaced by a “landing=TARGET / derive unsupported” note.
|
|
89
|
-
|
|
90
|
-
**Docker vs k8s:** container on host Docker engine → `docker_*`; container in Kubernetes → `k8s_exec` / `k8s_logs`.
|
|
91
|
-
|
|
92
|
-
## Handshake behavior
|
|
21
|
+
## First remote calls
|
|
93
22
|
|
|
94
23
|
1. Connectivity unknown / first remote ops: `access_check` (ACCESS SSH probe ≤10s; ephemeral; not kubectl)
|
|
95
24
|
2. Kubernetes ops only: then `shell_exec({"command":"kubectl cluster-info --request-timeout=5s"})`
|
|
96
25
|
|
|
97
|
-
If `access_check.reachable=false`: stop
|
|
26
|
+
If `access_check.reachable=false`: stop **this YAML link**; read JSON `message`/`hints` (VPN / `ACCESS_HOST`). Other `description` values may still work. If other tools return `code=ACCESS_UNAVAILABLE` for the same link: stop that link; Chinese hints are usually in `stderr`.
|
|
98
27
|
|
|
99
|
-
Always obtain from user or context: namespace, container name for multi-container pods.
|
|
28
|
+
Always obtain from user or context: namespace, container name for multi-container pods. Omit `host` to stay on the link landing. Pass `host` to hop-2 from ACCESS (or to select a Paradi TARGET). For hop-2 SSH: only ask user/password when the selected link has no `TARGET_*`. Passwords already in the YAML roster: do not ask again or put them in tool arguments.
|
|
100
29
|
|
|
101
|
-
##
|
|
30
|
+
## YAML roster
|
|
102
31
|
|
|
103
|
-
|
|
32
|
+
The roster is a file, not a tool: `~/.agents/host-execution.yaml` (Windows `%USERPROFILE%\.agents\host-execution.yaml`). There is no `list_links` / `config_write`.
|
|
104
33
|
|
|
105
|
-
|
|
34
|
+
Before creating or appending a link, read `host-execution://guides/yaml`. Copy one commented block, uncomment it, set a unique `description`. Do not invent field names.
|
|
106
35
|
|
|
107
|
-
|
|
36
|
+
- Same link = user+IP on ACCESS and on TARGET. `root@10.0.0.5` and `mccxadmin@10.0.0.5` are two links — do not merge them into one `TARGET_HOSTS`.
|
|
37
|
+
- New user+IP in this conversation → append to the roster unless the user says not to. Same ACCESS + same `TARGET_USER` + an extra IP → append that IP to that link's `TARGET_HOSTS`.
|
|
38
|
+
- `description` is a scenario label, not a frozen key. If it is misleading for how you are using the link (e.g. 「本机直连」 for a remote Xiaomo OpenClaw host), rewrite it in the YAML now — keep ACCESS/TARGET fields, make the label unique and scenario-accurate — then pass the **new** exact string. Do not keep a wrong label just because tool calls require exact match.
|
|
39
|
+
- Keep using the current link while the conversation still points at it. Many links: pass the exact `description`. Do not fuzzy-match. The server does not remember "last link".
|
|
40
|
+
- Laptop-direct hosts are each their own ACCESS landing — do not dump them into another link's `TARGET_HOSTS`. `TARGET_HOSTS` is only hop-2 from that ACCESS (same `TARGET_USER` and password).
|
|
41
|
+
- 0 links: tell the user to write a link from the yaml Resource. 1 link: `description` may be omitted. Many links without exact `description`: fail; list the descriptions.
|
|
42
|
+
- If a tool cannot meet GUIDE, tell the user.
|
|
108
43
|
|
|
109
44
|
## Shell / I/O pitfalls
|
|
110
45
|
|
|
@@ -116,21 +51,13 @@ Always check both `success` / `exitCode` and `stdout`.
|
|
|
116
51
|
| DOCKER_CONFIG | If permission denied: `export DOCKER_CONFIG=$HOME/dockertmp && mkdir -p "$DOCKER_CONFIG"`. |
|
|
117
52
|
| Registry SOP | Host with egress; `docker login` once; quoted Registry API probe. Never bare `&` in URLs. |
|
|
118
53
|
|
|
119
|
-
##
|
|
120
|
-
|
|
121
|
-
| Prompt | Purpose |
|
|
122
|
-
|--------|---------|
|
|
123
|
-
| `tool-selection` | Pick the right tool for a scenario |
|
|
124
|
-
| `remote-debug-workflow` | list → read/tail → ps workflow |
|
|
125
|
-
|
|
126
|
-
## Error handling
|
|
54
|
+
## Errors
|
|
127
55
|
|
|
128
56
|
| Situation | Action |
|
|
129
57
|
|-----------|--------|
|
|
130
58
|
| `truncatedByLines: true` | Increase `maxLines`, use `offset`, or use `remote_copy_file` |
|
|
131
59
|
| `truncatedByChars: true` | Raise `MAX_OUTPUT_CHARS` or use `remote_copy_file` |
|
|
132
|
-
| `
|
|
133
|
-
| `ssh_exec` Permission denied | Add password or use `k8s_exec` for pods |
|
|
60
|
+
| hop-2 `host` Permission denied | Pass password (or use keys on ACCESS); for pods use `k8s_exec` |
|
|
134
61
|
| Command `success=false` / exit≠0 | Read **stdout** |
|
|
135
62
|
| Empty stdout + exit 0 (docker) | Normal for non-TTY |
|
|
136
63
|
| `k8s_logs` empty | Use `remote_read_file` mode=tail for file logs |
|
|
@@ -142,7 +69,7 @@ For multi-GB landing↔local (or pod→local last hop):
|
|
|
142
69
|
|
|
143
70
|
```json
|
|
144
71
|
{
|
|
145
|
-
"source": { "target": "
|
|
72
|
+
"source": { "target": "remote", "path": "/tmp/big.pt" },
|
|
146
73
|
"dest": { "target": "local", "path": "C:/data/big.pt" },
|
|
147
74
|
"skipIfComplete": true,
|
|
148
75
|
"totalTimeoutMs": 3600000,
|
|
@@ -154,8 +81,9 @@ For multi-GB landing↔local (or pod→local last hop):
|
|
|
154
81
|
- `skipIfComplete`: skip gate follows `verify`
|
|
155
82
|
- Result includes `transferId`; async jobs expose `remote_copy_status`
|
|
156
83
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
|
160
|
-
|
|
161
|
-
|
|
|
84
|
+
## MCP prompts
|
|
85
|
+
|
|
86
|
+
| Prompt | Purpose |
|
|
87
|
+
|--------|---------|
|
|
88
|
+
| `tool-selection` | Pick the right tool for a scenario |
|
|
89
|
+
| `remote-debug-workflow` | list → read/tail → ps workflow |
|
package/docs/CONFIGURATION.md
CHANGED
|
@@ -1,12 +1,21 @@
|
|
|
1
1
|
# Configuration
|
|
2
2
|
|
|
3
|
+
## YAML roster (preferred when you have more than one link)
|
|
4
|
+
|
|
5
|
+
Fixed path: `~/.agents/host-execution.yaml` (Windows `%USERPROFILE%\.agents\host-execution.yaml`). No path env.
|
|
6
|
+
|
|
7
|
+
- One link = the same GUIDE §2 fields as a `mcp.json` `env` block, plus a unique `description`.
|
|
8
|
+
- At least one real link → YAML only. Empty `links: []` + `ACCESS_*` env → JSON below.
|
|
9
|
+
- Commented examples live in MCP Resource `host-execution://guides/yaml`. The user file is seeded with a short header only; existing files are never overwritten.
|
|
10
|
+
- Process-level `DEFAULT_TIMEOUT_MS` / `MAX_OUTPUT_CHARS` / copy job root stay in env, not per link.
|
|
11
|
+
|
|
3
12
|
## Access shapes (user mental model)
|
|
4
13
|
|
|
5
14
|
| Shape | Env | Meaning |
|
|
6
15
|
|-------|-----|---------|
|
|
7
16
|
| Single host | `ACCESS_*` only | Land on ACCESS; shell / kubectl / docker there |
|
|
8
|
-
| Bastion → target | `ACCESS_*` + `TARGET_*` | Land on ACCESS; `
|
|
9
|
-
| Paradi gateway | `ACCESS_KIND=paradi-gateway` + `
|
|
17
|
+
| Bastion → target | `ACCESS_*` + `TARGET_*` | Land on ACCESS; `TARGET_USER`/`TARGET_PASSWORD` are derive auth; `TARGET_HOSTS` is a known hop-2 list (one host = default; many = pass `host`) |
|
|
18
|
+
| Paradi gateway | `ACCESS_KIND=paradi-gateway` + `TARGET_HOSTS` + `TARGET_USER` | SSH to gateway with encoded identity; landing = selected TARGET (one concrete = omit `host`; many = pass `host`) |
|
|
10
19
|
|
|
11
20
|
Runtime (shell / docker / kubectl) is **not** configured in mcp.json — Agent chooses from Context capabilities.
|
|
12
21
|
|
|
@@ -26,8 +35,8 @@ Runtime (shell / docker / kubectl) is **not** configured in mcp.json — Agent c
|
|
|
26
35
|
| `ACCESS_PRIVATE_KEY_PATH` | — | Explicit private key path |
|
|
27
36
|
| `ACCESS_PASSWORD` | — | Password auth (dev only); also used to build Paradi compound password when that mode wins |
|
|
28
37
|
| `ACCESS_PARADI_AUTH` | `auto` | Paradi only: `auto` \| `slash` \| `compound`. Default `auto` tries slash then compound on AUTH_FAILED and **pins** the winner for this MCP process |
|
|
29
|
-
| `
|
|
30
|
-
| `TARGET_USER` | — | **Required if `
|
|
38
|
+
| `TARGET_HOSTS` | — | One host or comma-separated list (IP or hostname). **One entry** = default landing (`ssh` hop-2 / Paradi landing). 0 or many = pass `host`. CIDR/glob rejected. Not a JSON array string |
|
|
39
|
+
| `TARGET_USER` | — | **Required if `TARGET_HOSTS` set** (no fallback to `ACCESS_USER`) |
|
|
31
40
|
| `TARGET_PASSWORD` | — | Default derive password (sshpass); ignored for Paradi auth |
|
|
32
41
|
| `DEFAULT_TIMEOUT_MS` | `60000` | Default command timeout |
|
|
33
42
|
| `MAX_OUTPUT_CHARS` | `65536` | Max tool output size |
|
|
@@ -50,6 +59,8 @@ Runtime (shell / docker / kubectl) is **not** configured in mcp.json — Agent c
|
|
|
50
59
|
Do **not** set: `BASTION_HOST`, `BASTION_USER`, `BASTION_PORT`, `BASTION_PASSWORD`, `BASTION_PRIVATE_KEY_PATH`, `REMOTE_SSH_USER`, `REMOTE_SSH_PASSWORD`.
|
|
51
60
|
If present, `loadConfig` throws with rename hints (`BASTION_HOST` → `ACCESS_HOST`, etc.).
|
|
52
61
|
|
|
62
|
+
`TARGET_HOST` is also removed: use `TARGET_HOSTS`.
|
|
63
|
+
|
|
53
64
|
## SSH authentication (ACCESS)
|
|
54
65
|
|
|
55
66
|
Configure **one or more** methods; the server passes all of them to the SSH client, which tries each until one succeeds:
|
|
@@ -96,7 +107,17 @@ The server uses **stdio transport**. See [clients/](clients/).
|
|
|
96
107
|
"ACCESS_HOST": "10.121.120.7",
|
|
97
108
|
"ACCESS_USER": "mccxadmin",
|
|
98
109
|
"ACCESS_PASSWORD": "<secret>",
|
|
99
|
-
"
|
|
110
|
+
"TARGET_HOSTS": "10.121.35.68",
|
|
111
|
+
"TARGET_USER": "mccuseradmin",
|
|
112
|
+
"TARGET_PASSWORD": "<secret>"
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Same credentials, several known hop-2 hosts (no single default — Agent passes `host` from user context):
|
|
117
|
+
|
|
118
|
+
```json
|
|
119
|
+
{
|
|
120
|
+
"TARGET_HOSTS": "10.121.35.74,10.121.33.2",
|
|
100
121
|
"TARGET_USER": "mccuseradmin",
|
|
101
122
|
"TARGET_PASSWORD": "<secret>"
|
|
102
123
|
}
|
|
@@ -110,7 +131,7 @@ The server uses **stdio transport**. See [clients/](clients/).
|
|
|
110
131
|
"ACCESS_HOST": "10.121.61.3",
|
|
111
132
|
"ACCESS_USER": "bastion-login",
|
|
112
133
|
"ACCESS_PASSWORD": "<secret>",
|
|
113
|
-
"
|
|
134
|
+
"TARGET_HOSTS": "10.121.35.68",
|
|
114
135
|
"TARGET_USER": "mccuseradmin"
|
|
115
136
|
}
|
|
116
137
|
```
|
|
@@ -119,8 +140,8 @@ Customers only set gateway + target. Do **not** put a three-part SSH username or
|
|
|
119
140
|
|
|
120
141
|
Default `ACCESS_PARADI_AUTH=auto` (may omit):
|
|
121
142
|
|
|
122
|
-
1. Try **slash** username `ACCESS_USER
|
|
123
|
-
2. On AUTH_FAILED only, try **compound** username `ACCESS_USER` + `ACCESS_PASSWORD
|
|
143
|
+
1. Try **slash** username `ACCESS_USER/<landing-ip>/TARGET_USER` + `ACCESS_PASSWORD`
|
|
144
|
+
2. On AUTH_FAILED only, try **compound** username `ACCESS_USER` + `ACCESS_PASSWORD@##@<landing-ip>:SSH:22:TARGET_USER`
|
|
124
145
|
3. Pin the winner for this MCP process (restart MCP to clear / re-probe)
|
|
125
146
|
|
|
126
147
|
Ops may force `ACCESS_PARADI_AUTH=auto|slash|compound` (customers usually keep **`auto`**). One table:
|
|
@@ -133,6 +154,6 @@ Ops may force `ACCESS_PARADI_AUTH=auto|slash|compound` (customers usually keep *
|
|
|
133
154
|
|
|
134
155
|
Do not put slash usernames or `@##@` strings in mcp.json — the server encodes them.
|
|
135
156
|
|
|
136
|
-
Landing
|
|
157
|
+
Landing is a TARGET OS. One `TARGET_HOSTS` entry: omit `host`. Many entries: pass `host` on `shell_exec` / `docker_*` / `remote_*`.
|
|
137
158
|
|
|
138
159
|
See [PARADI_ACCESS_PLAN.md](PARADI_ACCESS_PLAN.md) for the full Access / Runtime model.
|
package/docs/GUIDE.md
ADDED
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
# host-execution
|
|
2
|
+
|
|
3
|
+
**使用场景**:经 ACCESS(SSH 跳板或帕拉迪网关)在远端执行 shell / docker / `kubectl`、读文件 / 拷贝。
|
|
4
|
+
|
|
5
|
+
Agent 把本文当作**用户期望这个 MCP 提供的能力**。配好之后用户会按下面的说法下指令。
|
|
6
|
+
|
|
7
|
+
如设计到 k8s 环境配置,建议配套 [k8s-multi-node-deploy](../../../skill/env/k8s-multi-node-deploy/) skill。
|
|
8
|
+
|
|
9
|
+
> 包名已由 `bastion-k8s-mcp` 升级为 `host-execution-mcp`。
|
|
10
|
+
|
|
11
|
+
## 1. 安装 Node.js
|
|
12
|
+
|
|
13
|
+
需要 **Node.js >= 18**([nodejs.org](https://nodejs.org) LTS):
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
node -v
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## 2. 配置:先选 ACCESS_KIND
|
|
20
|
+
|
|
21
|
+
配置文件:`~/.cursor/mcp.json`(或 Cursor → Settings → MCP → Edit Config)。
|
|
22
|
+
|
|
23
|
+
先问自己一句:**本机能不能用普通** `ssh user@ip` **直接登到要用的那台机器(或跳板)?** 答案决定 `ACCESS_KIND`。
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
| `ACCESS_KIND` | 你的实际情况 | 一句话 |
|
|
27
|
+
| ---------------- | ----------------------------------------------------------- | ------ |
|
|
28
|
+
| `ssh`(默认) | 本机(通常开 VPN)能**正常 SSH** 到入口机 / 目标机,连上就是 bash,没有「选资产 / 选账号」菜单 | 普通 SSH |
|
|
29
|
+
| `paradi-gateway` | **不能**对目标机直接 `ssh`;只能先连帕拉迪网关,再在网关里交互选资产、选登录账号 | 网关菜单穿透 |
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
两种写法**同一套字段**(下面 §2.1 / §2.2),不要混用、不要合并。
|
|
33
|
+
|
|
34
|
+
**YAML 名册(可改)**:`~/.agents/host-execution.yaml`(Windows:`%USERPROFILE%\.agents\host-execution.yaml`)。mcp.json 极简,不必摊一整表 `ACCESS_*`。完整注释模板见 MCP Resource `host-execution://guides/yaml`,不要在本文或对话里发明字段。
|
|
35
|
+
|
|
36
|
+
- 一条链路 = 下面一份 JSON env;每条必须有唯一 `description`,写清场景(谁、干什么、哪台),不要只写「本机直连 + IP」
|
|
37
|
+
- 是否同一条看 **user+IP**,不是只看 IP(`root@10.0.0.5` 与 `mccxadmin@10.0.0.5` 是两条,不要写进同一条 `TARGET_HOSTS`)
|
|
38
|
+
- 对话里出现新的 user+IP → 默认写入名册;仅当同一 ACCESS 且同一 `TARGET_USER`、只是多了一个目标 IP → 往该条 `TARGET_HOSTS` 追加。用户说这次不要记 → 不写
|
|
39
|
+
- `description` 和真实用途不符 → 当场改名册里的标签,之后按新名精确选用;精确匹配不是「旧名不可改」
|
|
40
|
+
- 本轮对话一直指向某一条 → 一直用那条。多条时工具带**精确** `description`。省略 `host` = 在该条入口机上执行;要再 SSH 到另一台,传 `host`(从入口机可达的 IP)
|
|
41
|
+
- 名册至少一条真实链路 → 只认 YAML。仅有空名册(`links: []`)且 env 有 `ACCESS_*` → 仍用下面的 JSON
|
|
42
|
+
|
|
43
|
+
**JSON / env(启动时写死)**:把 §2.1 / §2.2 写进 `mcp.json` 的 `env`。改配置要重启 MCP。
|
|
44
|
+
|
|
45
|
+
`ssh` **长什么样:** 本机 `ssh user@入口IP`,输密码后直接进 shell → 配 §2.1。
|
|
46
|
+
|
|
47
|
+
`paradi-gateway` **长什么样:** 本机只能先 `ssh 网关账号@网关IP`,连上后出现资产/账号列表要手选数字 → MCP 替你省掉这份交互(§2.2)。示意:
|
|
48
|
+
|
|
49
|
+

|
|
50
|
+
|
|
51
|
+
### 2.1 `ACCESS_KIND=ssh`:本机能正常 SSH
|
|
52
|
+
|
|
53
|
+
先确认本机经 VPN 能 `ssh` 到入口机,再配:
|
|
54
|
+
|
|
55
|
+
```json
|
|
56
|
+
{
|
|
57
|
+
"mcpServers": {
|
|
58
|
+
"host-execution": {
|
|
59
|
+
"command": "npx",
|
|
60
|
+
"args": ["-y", "host-execution-mcp@latest"],
|
|
61
|
+
"env": {
|
|
62
|
+
"ACCESS_KIND": "ssh", # 可省
|
|
63
|
+
"ACCESS_HOST": "<入口机 IP>",
|
|
64
|
+
"ACCESS_USER": "<入口机用户>",
|
|
65
|
+
"ACCESS_PASSWORD": "<入口机密码>",
|
|
66
|
+
"ACCESS_PORT": "22", # 可省
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
`ACCESS_HOST` + `ACCESS_USER` = 本机能 SSH 直连的入口机。也可用 `ACCESS_PRIVATE_KEY_PATH` 代替密码。
|
|
74
|
+
|
|
75
|
+
可选:
|
|
76
|
+
|
|
77
|
+
- 如果目标机器是K8s 集群控制节点,希望限制操作范围:
|
|
78
|
+
|
|
79
|
+
```json
|
|
80
|
+
# 以his-test 为例
|
|
81
|
+
"ALLOWED_NAMESPACES": "his-test"
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
- 常从跳板再 SSH 到某台目标机时,加默认第二跳:
|
|
85
|
+
|
|
86
|
+
```json
|
|
87
|
+
"TARGET_HOSTS": "<目标机 IP>",
|
|
88
|
+
"TARGET_USER": "<目标机用户>",
|
|
89
|
+
"TARGET_PASSWORD": "<目标机密码>"
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
- 如果从跳板再 SSH 的机器不止一个,同时用户名,密码相同,可把已知 IP 写进同一项:
|
|
93
|
+
|
|
94
|
+
```json
|
|
95
|
+
"TARGET_HOSTS": "<目标机 IP>,<目标机 IP>",
|
|
96
|
+
"TARGET_USER": "<目标机用户>",
|
|
97
|
+
"TARGET_PASSWORD": "<目标机密码>"
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
`TARGET_HOSTS` 可省,只留账号,每次对话里说 IP:
|
|
101
|
+
|
|
102
|
+
```json
|
|
103
|
+
"TARGET_USER": "<目标机用户>",
|
|
104
|
+
"TARGET_PASSWORD": "<目标机密码>"
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
旧键 `TARGET_HOST` 已去掉,请改用 `TARGET_HOSTS`。
|
|
108
|
+
|
|
109
|
+
### 2.2 `ACCESS_KIND=paradi-gateway`:经帕拉迪网关
|
|
110
|
+
|
|
111
|
+
本机无法对业务机普通 SSH。只配**网关账号** + **目标机 IP / 系统用户**;**不要**手写三段用户名或 `@##@` 密码串(MCP 内部编码)。默认 `ACCESS_PARADI_AUTH=auto`。
|
|
112
|
+
|
|
113
|
+
```json
|
|
114
|
+
{
|
|
115
|
+
"mcpServers": {
|
|
116
|
+
"host-execution-paradi": {
|
|
117
|
+
"command": "npx",
|
|
118
|
+
"args": ["-y", "host-execution-mcp@latest"],
|
|
119
|
+
"env": {
|
|
120
|
+
"ACCESS_KIND": "paradi-gateway",
|
|
121
|
+
"ACCESS_HOST": "<网关 IP>",
|
|
122
|
+
"ACCESS_PORT": "22",
|
|
123
|
+
"ACCESS_USER": "<网关用户>",
|
|
124
|
+
"ACCESS_PASSWORD": "<网关密码>",
|
|
125
|
+
"ACCESS_PARADI_AUTH": "auto",
|
|
126
|
+
"TARGET_HOSTS": "<目标机 IP>",
|
|
127
|
+
"TARGET_USER": "<目标机系统用户>"
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
| `ACCESS_PARADI_AUTH` | 行为 | 何时用 |
|
|
136
|
+
| -------------------- | ---------------------------------------- | ----------- |
|
|
137
|
+
| **auto**(默认) | 先 slash,AUTH_FAILED 再 compound;成功后进程内钉死 | 不确定网关能力时 |
|
|
138
|
+
| **slash** | 用户名 `USER/HOST/OSUSER`,密码=网关密码 | 网关按三段用户名选资产 |
|
|
139
|
+
| **compound** | 用户名 `USER`,密码 `密码@##@HOST:SSH:22:OSUSER` | 网关已开程序穿透 |
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
保存后重启 MCP。验证:
|
|
143
|
+
|
|
144
|
+
> 用 host-execution 跑 `access_check`;若要做 K8s,再让 Agent 执行 `kubectl cluster-info --request-timeout=5s`
|
|
145
|
+
|
|
146
|
+
`ACCESS_UNAVAILABLE` → 先查 VPN / 这条链路的 `ACCESS_HOST`,不要反复锤**这一条**。名册里别的 `description` 仍可试。
|
|
147
|
+
|
|
148
|
+
本地改源码时:
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
cd packages/mcp/host-execution
|
|
152
|
+
npm install && npm run build
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
## 3. 怎么用
|
|
156
|
+
|
|
157
|
+
对 Agent **用自然语言**说清:**命名空间、负载/Pod 名、文件路径**;破坏性操作加「只读,不要改」。
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
| 你想做的事 | 告诉 Agent |
|
|
161
|
+
| ----- | ------------------------------------------------------- |
|
|
162
|
+
| 找 Pod | 命名空间 + Deployment/负载名 |
|
|
163
|
+
| 看日志 | Pod 名 + 日志**文件路径**(训练日志多在挂载盘,不是 stdout) |
|
|
164
|
+
| 拷到本地 | 远程路径 + 本地目录 |
|
|
165
|
+
| 排查故障 | 日志 / dmesg / core 路径 + 「只读分析」 |
|
|
166
|
+
| 上目标机 | 目标 IP + 用户(已有 `TARGET_*` 时可省略 `user`/`password`);Agent 在 `shell_exec` 等工具上传 `host` |
|
|
167
|
+
| 帕拉迪落点 | 一条 TARGET 时省略 `host`;多条时传 `host` 选落地机 |
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
输出被截断时,让 Agent 用 `grep` / `tail` 缩小范围。
|
|
171
|
+
|
|
172
|
+
常用工具:`access_check`、`shell_exec`、`context_probe`、`k8s_*`、`docker_*`、`remote_*` / `remote_copy_*`。
|
|
173
|
+
|
|
174
|
+
## 常见问题
|
|
175
|
+
|
|
176
|
+
- **MCP 起不来**:查 `node -v`、入口机地址账号、本机能否 `ssh user@ACCESS_HOST`;确认已改成 `ACCESS_`*(旧* `BASTION_` 会被拒绝)。仅有空 YAML 名册时进程仍应能起来,工具会提示按 `host-execution://guides/yaml` 追加链路
|
|
177
|
+
- **k8s_logs 为空**:日志在文件里,让 Agent 读挂载路径,不要只用 container stdout
|
|
178
|
+
- **帕拉迪连不上**:确认网关开了程序穿透(或 slash 可用);可强制 `ACCESS_PARADI_AUTH=compound` / `slash`;`access_check` 成功后会带 `paradiAuth`
|
|
179
|
+
|
|
180
|
+
## 更多文档
|
|
181
|
+
|
|
182
|
+
- YAML 名册模板(MCP Resource):`host-execution://guides/yaml`
|
|
183
|
+
- 工程说明:[README.md](../README.md)
|
|
184
|
+
- Codex / 迁移 / 场景示例:[USER_GUIDE.zh-CN.md](./USER_GUIDE.zh-CN.md)
|
|
185
|
+
- Agent 操作说明:[AGENT_GUIDE.md](./AGENT_GUIDE.md)
|
|
186
|
+
- Skill 侧示例:[skill/env/k8s-multi-node-deploy/mcp/](../../../skill/env/k8s-multi-node-deploy/mcp/)
|
|
@@ -112,7 +112,7 @@ Client ──SSH──► Context0(ACCESS) ── Runtime
|
|
|
112
112
|
"ACCESS_HOST": "10.121.120.7",
|
|
113
113
|
"ACCESS_USER": "mccxadmin",
|
|
114
114
|
"ACCESS_PASSWORD": "<secret>",
|
|
115
|
-
"
|
|
115
|
+
"TARGET_HOSTS": "10.121.35.68",
|
|
116
116
|
"TARGET_USER": "mccuseradmin",
|
|
117
117
|
"TARGET_PASSWORD": "<secret>"
|
|
118
118
|
}
|
|
@@ -135,7 +135,7 @@ Client ──SSH──► Context0(ACCESS) ── Runtime
|
|
|
135
135
|
"ACCESS_HOST": "10.121.61.3",
|
|
136
136
|
"ACCESS_USER": "zhangyimingzgc",
|
|
137
137
|
"ACCESS_PASSWORD": "<secret>",
|
|
138
|
-
"
|
|
138
|
+
"TARGET_HOSTS": "10.121.35.68",
|
|
139
139
|
"TARGET_USER": "mccuseradmin"
|
|
140
140
|
}
|
|
141
141
|
```
|
|
@@ -145,7 +145,7 @@ ParadiTransport.createContext() → Context0(endpoint=T, transport=paradi-gatewa
|
|
|
145
145
|
Client ──SSH(身份编码目标)──► T ── Runtime (Runtime 无帕拉迪分支)
|
|
146
146
|
```
|
|
147
147
|
|
|
148
|
-
实现细节(用户不配):`sshUsername = ACCESS_USER
|
|
148
|
+
实现细节(用户不配):`sshUsername = ACCESS_USER/<landing-ip>/TARGET_USER`。一般不配 `TARGET_PASSWORD`。
|
|
149
149
|
|
|
150
150
|
---
|
|
151
151
|
|
|
@@ -159,8 +159,8 @@ Access **不含** `ALLOWED_NAMESPACES`。另层例如 `ACCESS_POLICY`。Phase 1
|
|
|
159
159
|
|
|
160
160
|
| KIND | 规则 |
|
|
161
161
|
|------|------|
|
|
162
|
-
| `ssh`(默认) | ACCESS 必填;TARGET 可选;**若存在 `
|
|
163
|
-
| `paradi-gateway` | ACCESS +
|
|
162
|
+
| `ssh`(默认) | ACCESS 必填;TARGET 可选;**若存在 `TARGET_HOSTS` → `TARGET_USER` 必填**(禁止 fallback 到 `ACCESS_USER`) |
|
|
163
|
+
| `paradi-gateway` | ACCESS + 恰好一条具体 `TARGET_HOSTS` + TARGET_USER 必填;忽略 TARGET_PASSWORD 默认认证 |
|
|
164
164
|
|
|
165
165
|
`ACCESS_KIND` 仅:`ssh` | `paradi-gateway`。
|
|
166
166
|
|
|
@@ -224,7 +224,7 @@ ssh_exec(host?, command) ≡
|
|
|
224
224
|
|
|
225
225
|
- [x] `HostExecutionContext`(无 session)+ `SessionPool`(按 key)
|
|
226
226
|
- [x] `SshTransport.createContext` → 仅 Context0(ACCESS);capabilities 初值 `exec` + docker/kubectl=`unknown`
|
|
227
|
-
- [x] loadConfig + TARGET 作 default derive;有
|
|
227
|
+
- [x] loadConfig + TARGET 作 default derive;有 TARGET_HOSTS 则 TARGET_USER 必填;字段名 `TARGET_PASSWORD`
|
|
228
228
|
- [x] 入口 shell;**ssh_exec = derive+shell**;k8s_* 仍经 ACCESS(bastion)执行
|
|
229
229
|
- [x] CONFIGURATION / AGENT_GUIDE / USER_GUIDE / clients → ACCESS_*(legacy BASTION_* 薄别名)
|
|
230
230
|
- [x] 版本 3.1.0
|
package/docs/TODO.md
CHANGED
|
@@ -4,26 +4,19 @@ As of **5.0.0**. Items below are intentional or deferred; do not treat as regres
|
|
|
4
4
|
|
|
5
5
|
## Done in 5.0 cleanup (this branch)
|
|
6
6
|
|
|
7
|
-
- [x]
|
|
8
|
-
- [x] Copy assert rejects Paradi `host`
|
|
7
|
+
- [x] `target=context` / `contextKey` allowed on both ssh and Paradi (removed allowContext switch)
|
|
8
|
+
- [x] Copy assert rejects Paradi `host` (context = selected landing)
|
|
9
9
|
- [x] Agent-facing tool descriptions: drop Hop1/Hop2 jargon; docs aligned to ACCESS/Context naming
|
|
10
10
|
|
|
11
11
|
## 5.1 backlog
|
|
12
12
|
|
|
13
13
|
### 1. Remote endpoint API — remove `target=context` pollution (ssh)
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
// TODO(remote-endpoint-union): Split agent-facing copy/read endpoints:
|
|
17
|
-
// { target: landing|pod|local, path, ... } vs { contextKey, path }
|
|
18
|
-
// Keep materialize internal; stop overloading target=context on the same union.
|
|
19
|
-
```
|
|
15
|
+
- [x] Agent-facing: `description` + optional `host`; copy `target=local|remote|pod`; read/ps use path + optional namespace/pod. `contextKey` stays internal.
|
|
20
16
|
|
|
21
17
|
### 2. KubectlRunner → SessionPool, then optional `k8s_*(contextKey)`
|
|
22
18
|
|
|
23
|
-
|
|
24
|
-
// TODO(kubectl-session-pool): Route kubectl through SessionPool (same as shell/docker).
|
|
25
|
-
// Then optionally expose k8s_*(contextKey?) for derived-host kubeconfig — doc honesty first in 5.0.
|
|
26
|
-
```
|
|
19
|
+
- [x] Route kubectl through AccessRuntime / SessionPool; `k8s_*(contextKey?)` same selection as `shell_exec`.
|
|
27
20
|
|
|
28
21
|
### 3. SessionPool TTL / LRU
|
|
29
22
|
|