@neoline/hostbridge 0.2.0 → 0.2.2
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/README.md +11 -9
- package/bin/hostbridge.js +2 -0
- package/package.json +1 -1
- package/pyproject.toml +1 -1
- package/src/server_control_mcp/__init__.py +1 -1
- package/src/server_control_mcp/cli.py +13 -2
package/README.md
CHANGED
|
@@ -121,9 +121,10 @@ Recommended agent flow:
|
|
|
121
121
|
|
|
122
122
|
1. Call `hosts_list`.
|
|
123
123
|
2. If the target host exists, call `session_open`.
|
|
124
|
-
3. If
|
|
125
|
-
4.
|
|
126
|
-
5.
|
|
124
|
+
3. If `session_open` times out or fails, run `hostbridge check <host_id>` to verify the recorded login path, then retry or repair setup.
|
|
125
|
+
4. If it does not exist and the user identifies a similar bastion-backed host, run `hostbridge setup <new_id> --from-host <source_id> --menu-selection <ip-or-name> --final-prompt <regex>`.
|
|
126
|
+
5. Call `hosts_list` again, then `session_open(<new_id>)`.
|
|
127
|
+
6. Do not inspect `~/.ssh`, old expect scripts, or shell snapshots unless the user explicitly asks or the setup command lacks required information.
|
|
127
128
|
|
|
128
129
|
### Encrypted login automation
|
|
129
130
|
|
|
@@ -327,11 +328,12 @@ See `SECURITY.md` and `docs/THREAT_MODEL.md` for the trust model and audited eve
|
|
|
327
328
|
1. Call `hosts_list` and choose a configured host id.
|
|
328
329
|
2. If the host is missing, ask for only the missing fields and use `hostbridge setup <host_id>` rather than manually editing config.
|
|
329
330
|
3. Call `session_open` once for the chosen host.
|
|
330
|
-
4.
|
|
331
|
-
5. Use `
|
|
332
|
-
6.
|
|
333
|
-
7.
|
|
334
|
-
8. Call `
|
|
331
|
+
4. Only if `session_open` times out or fails, run `hostbridge check <host_id>` and retry after fixing the login path.
|
|
332
|
+
5. Use `command_run` for quick commands such as `nvidia-smi`, `pwd`, `df -h`, or `tmux ls`.
|
|
333
|
+
6. Use `task_start` for long training jobs, downloads, builds, or scripts.
|
|
334
|
+
7. Poll `task_status` until `state` is `finished`; inspect `exit_code` and `log_tail`.
|
|
335
|
+
8. Call `task_stop` early if a job should be aborted.
|
|
336
|
+
9. Call `session_close` when finished, or `sessions_close_all` to tear down every session.
|
|
335
337
|
|
|
336
338
|
## Security notes
|
|
337
339
|
|
|
@@ -347,4 +349,4 @@ See `CONTRIBUTING.md`. Run tests with `python -m pytest -q`. The full suite shou
|
|
|
347
349
|
|
|
348
350
|
## License
|
|
349
351
|
|
|
350
|
-
MIT. See `LICENSE`.
|
|
352
|
+
MIT. See `LICENSE`.
|
package/bin/hostbridge.js
CHANGED
|
@@ -19,6 +19,8 @@ if (!existsSync(moduleDir)) {
|
|
|
19
19
|
|
|
20
20
|
const env = { ...process.env };
|
|
21
21
|
env.PYTHONPATH = env.PYTHONPATH ? `${bundledSrc}${delimiter}${env.PYTHONPATH}` : bundledSrc;
|
|
22
|
+
env.HOSTBRIDGE_DEFAULT_MCP_COMMAND = env.HOSTBRIDGE_DEFAULT_MCP_COMMAND || 'npx';
|
|
23
|
+
env.HOSTBRIDGE_DEFAULT_MCP_ARGS = env.HOSTBRIDGE_DEFAULT_MCP_ARGS || JSON.stringify(['-y', '@neoline/hostbridge']);
|
|
22
24
|
|
|
23
25
|
const child = spawn(pythonPath, ['-m', 'server_control_mcp', ...process.argv.slice(2)], {
|
|
24
26
|
stdio: 'inherit',
|
package/package.json
CHANGED
package/pyproject.toml
CHANGED
|
@@ -35,7 +35,7 @@ Use HostBridge when the user asks to connect to, inspect, or operate an allowlis
|
|
|
35
35
|
|
|
36
36
|
- First call `hosts_list` to see configured hosts; then use `session_open("<host_id>")`.
|
|
37
37
|
- If the host is missing, ask only for the missing connection details and run `hostbridge setup <host_id>` instead of editing JSON by hand.
|
|
38
|
-
-
|
|
38
|
+
- Do not run `hostbridge check` before every connection; only use `hostbridge check <host_id>` when `session_open` times out or fails.
|
|
39
39
|
- Do not search shell history, SSH config, or old scripts unless the setup flow lacks required information or the user explicitly asks.
|
|
40
40
|
- Keep long-running work in `task_start`/`task_status`; use `session_close` or `sessions_close_all` when done.
|
|
41
41
|
{HOSTBRIDGE_GUIDANCE_END}
|
|
@@ -228,12 +228,23 @@ def _looks_like_shell_script(command: str, args: list[str]) -> bool:
|
|
|
228
228
|
|
|
229
229
|
|
|
230
230
|
def _default_mcp_command_args() -> tuple[str, list[str]]:
|
|
231
|
+
env_command = os.environ.get("HOSTBRIDGE_DEFAULT_MCP_COMMAND")
|
|
232
|
+
if env_command:
|
|
233
|
+
raw_args = os.environ.get("HOSTBRIDGE_DEFAULT_MCP_ARGS", "[]")
|
|
234
|
+
try:
|
|
235
|
+
parsed_args = json.loads(raw_args)
|
|
236
|
+
except json.JSONDecodeError:
|
|
237
|
+
parsed_args = []
|
|
238
|
+
if not isinstance(parsed_args, list) or not all(isinstance(arg, str) for arg in parsed_args):
|
|
239
|
+
parsed_args = []
|
|
240
|
+
return env_command, parsed_args
|
|
241
|
+
|
|
231
242
|
repo_root = Path(__file__).resolve().parents[2]
|
|
232
243
|
run_server = repo_root / "run_server.py"
|
|
233
244
|
if run_server.exists():
|
|
234
245
|
return "python3", [str(run_server)]
|
|
235
246
|
command = Path(sys.argv[0]).name or PUBLIC_NAME
|
|
236
|
-
if command in (LEGACY_PUBLIC_NAME, LEGACY_PACKAGE_NAME):
|
|
247
|
+
if command in (LEGACY_PUBLIC_NAME, LEGACY_PACKAGE_NAME, "__main__.py"):
|
|
237
248
|
command = PUBLIC_NAME
|
|
238
249
|
return command, []
|
|
239
250
|
|