@akms/mcp-ssh 0.0.3 → 0.1.1

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/lib/index.d.cts CHANGED
@@ -28,6 +28,18 @@ interface SshPolicy {
28
28
  /** Remote path prefixes the file tools may touch. Empty means unrestricted. */
29
29
  allowedPaths: string[];
30
30
  }
31
+ /** Intermediate host the target is reached through, as OpenSSH's `ProxyJump` / `-J`. */
32
+ interface SshJumpProfile {
33
+ host: string;
34
+ port: number;
35
+ username: string;
36
+ /** Expanded absolute path to a private key file. */
37
+ privateKeyPath?: string;
38
+ passphrase?: string;
39
+ password?: string;
40
+ /** Expected jump host key, `SHA256:…`; a mismatch aborts the connection. */
41
+ hostKeyFingerprint?: string;
42
+ }
31
43
  /** The registered host: where to connect, how to authenticate, what is permitted. */
32
44
  interface SshHostProfile {
33
45
  /** Alias shown to the model, from `SSH_NAME`; defaults to the hostname. */
@@ -47,6 +59,14 @@ interface SshHostProfile {
47
59
  hostKeyFingerprint?: string;
48
60
  /** Directory every session starts in; falls back to the login shell's default. */
49
61
  defaultCwd?: string;
62
+ /**
63
+ * Command whose stdin/stdout carry the SSH stream instead of a TCP socket — OpenSSH's
64
+ * `ProxyCommand`. It carries the first hop: the jump host when one is set, else the
65
+ * target. `%h` / `%p` / `%r` expand to that hop's host, port and user.
66
+ */
67
+ proxyCommand?: string;
68
+ /** Jump host the target is reached through via a forwarded TCP channel. */
69
+ jump?: SshJumpProfile;
50
70
  policy: SshPolicy;
51
71
  }
52
72
  /** Credential-free view of the profile, safe to hand back to the model. */
@@ -57,6 +77,13 @@ interface SshHostSummary {
57
77
  username: string;
58
78
  description?: string;
59
79
  authMethod: "privateKey" | "password" | "agent";
80
+ /** True when a proxy command carries the first hop; the command itself is withheld. */
81
+ viaProxyCommand: boolean;
82
+ jump?: {
83
+ host: string;
84
+ port: number;
85
+ username: string;
86
+ };
60
87
  readonly: boolean;
61
88
  allowSudo: boolean;
62
89
  allowedPaths: string[];
@@ -135,17 +162,23 @@ declare class SshConnection {
135
162
  /** Set when the peer closed a previously established connection. */
136
163
  private droppedAfterReady;
137
164
  private observedFingerprint;
165
+ private observedJumpFingerprint;
138
166
  constructor(profile: SshHostProfile);
139
167
  get isConnected(): boolean;
140
168
  /** Host key the server presented, once a handshake has been attempted. */
141
169
  get hostKeyFingerprint(): string | null;
170
+ /** Host key the jump host presented; null without a jump host or before its handshake. */
171
+ get jumpHostKeyFingerprint(): string | null;
142
172
  /** True when a connection was established and then lost, so shell state is gone. */
143
173
  get wasDropped(): boolean;
144
174
  /**
145
175
  * Opens the connection, or joins the in-flight attempt when one is already running.
146
176
  *
177
+ * With a proxy command or a jump host the carrier is opened first and handed to ssh2
178
+ * as the socket; it is torn down with the target connection, whichever side closes.
179
+ *
147
180
  * @throws {Error} If the connection was closed, authentication fails, the host is
148
- * unreachable, or the handshake times out.
181
+ * unreachable, the handshake times out, or the carrier cannot be opened.
149
182
  */
150
183
  connect(): Promise<void>;
151
184
  /**
@@ -344,10 +377,14 @@ declare function createSshMcpServer(): SshMcpServerInstance;
344
377
  * 2) Resolve the policy over the built-in permissive stance; each variable is opt-in restriction
345
378
  * 3) Assemble the connection fields
346
379
  * 4) Expand the private key path and check it exists
380
+ * 5) Route: proxy command and / or jump host
347
381
  *
348
- * @throws {Error} If `SSH_HOST` is set without `SSH_USER`, or a typed value is malformed.
382
+ * @param env - Where the `SSH_*` variables are read from. Defaults to the process
383
+ * environment; the `config` command passes the entry it is about to write.
384
+ * @throws {Error} If `SSH_HOST` is set without `SSH_USER`, a `SSH_JUMP_*` variable is set
385
+ * without `SSH_JUMP_HOST`, or a typed value is malformed.
349
386
  */
350
- declare function loadHostProfile(): SshHostProfile | null;
387
+ declare function loadHostProfile(env?: NodeJS.ProcessEnv): SshHostProfile | null;
351
388
  /** Strips every secret so the profile can be described back to the model. */
352
389
  declare function toHostSummary(profile: SshHostProfile): SshHostSummary;
353
390
 
@@ -495,7 +532,7 @@ declare const $logger: Logger;
495
532
  /** Env var overriding the stderr log level ("debug" | "info" | "warn" | "error" | "silent"). */
496
533
  declare const LOG_LEVEL_ENV = "SSH_MCP_LOG_LEVEL";
497
534
  declare const SERVER_NAME = "akms-mcp-ssh";
498
- declare const SERVER_VERSION = "0.0.3";
535
+ declare const SERVER_VERSION = "0.1.1";
499
536
 
500
537
  /**
501
538
  * Environment variables that define the host, one MCP server entry per host.
@@ -520,6 +557,22 @@ declare const SINGLE_HOST_ENV: {
520
557
  readonly DESCRIPTION: "SSH_DESCRIPTION";
521
558
  /** Directory new sessions start in. */
522
559
  readonly CWD: "SSH_CWD";
560
+ /**
561
+ * Command whose stdin/stdout carry the SSH stream, like OpenSSH's `ProxyCommand`.
562
+ * `%h` / `%p` / `%r` expand to the first hop's host, port and user.
563
+ */
564
+ readonly PROXY_COMMAND: "SSH_PROXY_COMMAND";
565
+ /** Presence of this variable routes the connection through a jump host. */
566
+ readonly JUMP_HOST: "SSH_JUMP_HOST";
567
+ readonly JUMP_PORT: "SSH_JUMP_PORT";
568
+ /** Defaults to `SSH_USER`. */
569
+ readonly JUMP_USER: "SSH_JUMP_USER";
570
+ /** Path to the jump host's private key file; defaults to `SSH_KEY`. */
571
+ readonly JUMP_KEY: "SSH_JUMP_KEY";
572
+ readonly JUMP_PASSPHRASE: "SSH_JUMP_PASSPHRASE";
573
+ readonly JUMP_PASSWORD: "SSH_JUMP_PASSWORD";
574
+ /** Pinned jump host key, `SHA256:…`. */
575
+ readonly JUMP_HOST_KEY: "SSH_JUMP_HOST_KEY";
523
576
  readonly READONLY: "SSH_READONLY";
524
577
  readonly ALLOW_SUDO: "SSH_ALLOW_SUDO";
525
578
  /** Comma-separated binary names. */
@@ -534,4 +587,4 @@ declare const SINGLE_HOST_ENV: {
534
587
  readonly MAX_READ_FILE_BYTES: "SSH_MAX_READ_BYTES";
535
588
  };
536
589
 
537
- export { $logger, GuardRejectionError, type GuardVerdict, LOG_LEVEL_ENV, type LogLevel, type Logger, type RemoteDirectoryListing, type RemoteFileContent, type RemotePathAccess, SERVER_NAME, SERVER_VERSION, SINGLE_HOST_ENV, type SegmentAnalysis, SshConnection, type SshExecOptions, type SshExecResult, type SshHostProfile, type SshHostSummary, type SshMcpServerInstance, type SshPolicy, type SshRemoteEntry, SshSession, type SshSessionInfo, SshSessionManager, type ToolContext, analyzeSegment, canonicalizeCommand, createSshMcpServer, downloadFile, extractSubstitutions, inspectCommand, inspectLocalPath, inspectRemotePath, inspectWorkingDirectory, listRemoteDirectory, loadHostProfile, normalizeCommandText, readRemoteFile, registerAllTools, splitCommandSegments, stripQuotedText, toHostSummary, uploadFile, writeRemoteFile };
590
+ export { $logger, GuardRejectionError, type GuardVerdict, LOG_LEVEL_ENV, type LogLevel, type Logger, type RemoteDirectoryListing, type RemoteFileContent, type RemotePathAccess, SERVER_NAME, SERVER_VERSION, SINGLE_HOST_ENV, type SegmentAnalysis, SshConnection, type SshExecOptions, type SshExecResult, type SshHostProfile, type SshHostSummary, type SshJumpProfile, type SshMcpServerInstance, type SshPolicy, type SshRemoteEntry, SshSession, type SshSessionInfo, SshSessionManager, type ToolContext, analyzeSegment, canonicalizeCommand, createSshMcpServer, downloadFile, extractSubstitutions, inspectCommand, inspectLocalPath, inspectRemotePath, inspectWorkingDirectory, listRemoteDirectory, loadHostProfile, normalizeCommandText, readRemoteFile, registerAllTools, splitCommandSegments, stripQuotedText, toHostSummary, uploadFile, writeRemoteFile };
package/lib/index.d.ts CHANGED
@@ -28,6 +28,18 @@ interface SshPolicy {
28
28
  /** Remote path prefixes the file tools may touch. Empty means unrestricted. */
29
29
  allowedPaths: string[];
30
30
  }
31
+ /** Intermediate host the target is reached through, as OpenSSH's `ProxyJump` / `-J`. */
32
+ interface SshJumpProfile {
33
+ host: string;
34
+ port: number;
35
+ username: string;
36
+ /** Expanded absolute path to a private key file. */
37
+ privateKeyPath?: string;
38
+ passphrase?: string;
39
+ password?: string;
40
+ /** Expected jump host key, `SHA256:…`; a mismatch aborts the connection. */
41
+ hostKeyFingerprint?: string;
42
+ }
31
43
  /** The registered host: where to connect, how to authenticate, what is permitted. */
32
44
  interface SshHostProfile {
33
45
  /** Alias shown to the model, from `SSH_NAME`; defaults to the hostname. */
@@ -47,6 +59,14 @@ interface SshHostProfile {
47
59
  hostKeyFingerprint?: string;
48
60
  /** Directory every session starts in; falls back to the login shell's default. */
49
61
  defaultCwd?: string;
62
+ /**
63
+ * Command whose stdin/stdout carry the SSH stream instead of a TCP socket — OpenSSH's
64
+ * `ProxyCommand`. It carries the first hop: the jump host when one is set, else the
65
+ * target. `%h` / `%p` / `%r` expand to that hop's host, port and user.
66
+ */
67
+ proxyCommand?: string;
68
+ /** Jump host the target is reached through via a forwarded TCP channel. */
69
+ jump?: SshJumpProfile;
50
70
  policy: SshPolicy;
51
71
  }
52
72
  /** Credential-free view of the profile, safe to hand back to the model. */
@@ -57,6 +77,13 @@ interface SshHostSummary {
57
77
  username: string;
58
78
  description?: string;
59
79
  authMethod: "privateKey" | "password" | "agent";
80
+ /** True when a proxy command carries the first hop; the command itself is withheld. */
81
+ viaProxyCommand: boolean;
82
+ jump?: {
83
+ host: string;
84
+ port: number;
85
+ username: string;
86
+ };
60
87
  readonly: boolean;
61
88
  allowSudo: boolean;
62
89
  allowedPaths: string[];
@@ -135,17 +162,23 @@ declare class SshConnection {
135
162
  /** Set when the peer closed a previously established connection. */
136
163
  private droppedAfterReady;
137
164
  private observedFingerprint;
165
+ private observedJumpFingerprint;
138
166
  constructor(profile: SshHostProfile);
139
167
  get isConnected(): boolean;
140
168
  /** Host key the server presented, once a handshake has been attempted. */
141
169
  get hostKeyFingerprint(): string | null;
170
+ /** Host key the jump host presented; null without a jump host or before its handshake. */
171
+ get jumpHostKeyFingerprint(): string | null;
142
172
  /** True when a connection was established and then lost, so shell state is gone. */
143
173
  get wasDropped(): boolean;
144
174
  /**
145
175
  * Opens the connection, or joins the in-flight attempt when one is already running.
146
176
  *
177
+ * With a proxy command or a jump host the carrier is opened first and handed to ssh2
178
+ * as the socket; it is torn down with the target connection, whichever side closes.
179
+ *
147
180
  * @throws {Error} If the connection was closed, authentication fails, the host is
148
- * unreachable, or the handshake times out.
181
+ * unreachable, the handshake times out, or the carrier cannot be opened.
149
182
  */
150
183
  connect(): Promise<void>;
151
184
  /**
@@ -344,10 +377,14 @@ declare function createSshMcpServer(): SshMcpServerInstance;
344
377
  * 2) Resolve the policy over the built-in permissive stance; each variable is opt-in restriction
345
378
  * 3) Assemble the connection fields
346
379
  * 4) Expand the private key path and check it exists
380
+ * 5) Route: proxy command and / or jump host
347
381
  *
348
- * @throws {Error} If `SSH_HOST` is set without `SSH_USER`, or a typed value is malformed.
382
+ * @param env - Where the `SSH_*` variables are read from. Defaults to the process
383
+ * environment; the `config` command passes the entry it is about to write.
384
+ * @throws {Error} If `SSH_HOST` is set without `SSH_USER`, a `SSH_JUMP_*` variable is set
385
+ * without `SSH_JUMP_HOST`, or a typed value is malformed.
349
386
  */
350
- declare function loadHostProfile(): SshHostProfile | null;
387
+ declare function loadHostProfile(env?: NodeJS.ProcessEnv): SshHostProfile | null;
351
388
  /** Strips every secret so the profile can be described back to the model. */
352
389
  declare function toHostSummary(profile: SshHostProfile): SshHostSummary;
353
390
 
@@ -495,7 +532,7 @@ declare const $logger: Logger;
495
532
  /** Env var overriding the stderr log level ("debug" | "info" | "warn" | "error" | "silent"). */
496
533
  declare const LOG_LEVEL_ENV = "SSH_MCP_LOG_LEVEL";
497
534
  declare const SERVER_NAME = "akms-mcp-ssh";
498
- declare const SERVER_VERSION = "0.0.3";
535
+ declare const SERVER_VERSION = "0.1.1";
499
536
 
500
537
  /**
501
538
  * Environment variables that define the host, one MCP server entry per host.
@@ -520,6 +557,22 @@ declare const SINGLE_HOST_ENV: {
520
557
  readonly DESCRIPTION: "SSH_DESCRIPTION";
521
558
  /** Directory new sessions start in. */
522
559
  readonly CWD: "SSH_CWD";
560
+ /**
561
+ * Command whose stdin/stdout carry the SSH stream, like OpenSSH's `ProxyCommand`.
562
+ * `%h` / `%p` / `%r` expand to the first hop's host, port and user.
563
+ */
564
+ readonly PROXY_COMMAND: "SSH_PROXY_COMMAND";
565
+ /** Presence of this variable routes the connection through a jump host. */
566
+ readonly JUMP_HOST: "SSH_JUMP_HOST";
567
+ readonly JUMP_PORT: "SSH_JUMP_PORT";
568
+ /** Defaults to `SSH_USER`. */
569
+ readonly JUMP_USER: "SSH_JUMP_USER";
570
+ /** Path to the jump host's private key file; defaults to `SSH_KEY`. */
571
+ readonly JUMP_KEY: "SSH_JUMP_KEY";
572
+ readonly JUMP_PASSPHRASE: "SSH_JUMP_PASSPHRASE";
573
+ readonly JUMP_PASSWORD: "SSH_JUMP_PASSWORD";
574
+ /** Pinned jump host key, `SHA256:…`. */
575
+ readonly JUMP_HOST_KEY: "SSH_JUMP_HOST_KEY";
523
576
  readonly READONLY: "SSH_READONLY";
524
577
  readonly ALLOW_SUDO: "SSH_ALLOW_SUDO";
525
578
  /** Comma-separated binary names. */
@@ -534,4 +587,4 @@ declare const SINGLE_HOST_ENV: {
534
587
  readonly MAX_READ_FILE_BYTES: "SSH_MAX_READ_BYTES";
535
588
  };
536
589
 
537
- export { $logger, GuardRejectionError, type GuardVerdict, LOG_LEVEL_ENV, type LogLevel, type Logger, type RemoteDirectoryListing, type RemoteFileContent, type RemotePathAccess, SERVER_NAME, SERVER_VERSION, SINGLE_HOST_ENV, type SegmentAnalysis, SshConnection, type SshExecOptions, type SshExecResult, type SshHostProfile, type SshHostSummary, type SshMcpServerInstance, type SshPolicy, type SshRemoteEntry, SshSession, type SshSessionInfo, SshSessionManager, type ToolContext, analyzeSegment, canonicalizeCommand, createSshMcpServer, downloadFile, extractSubstitutions, inspectCommand, inspectLocalPath, inspectRemotePath, inspectWorkingDirectory, listRemoteDirectory, loadHostProfile, normalizeCommandText, readRemoteFile, registerAllTools, splitCommandSegments, stripQuotedText, toHostSummary, uploadFile, writeRemoteFile };
590
+ export { $logger, GuardRejectionError, type GuardVerdict, LOG_LEVEL_ENV, type LogLevel, type Logger, type RemoteDirectoryListing, type RemoteFileContent, type RemotePathAccess, SERVER_NAME, SERVER_VERSION, SINGLE_HOST_ENV, type SegmentAnalysis, SshConnection, type SshExecOptions, type SshExecResult, type SshHostProfile, type SshHostSummary, type SshJumpProfile, type SshMcpServerInstance, type SshPolicy, type SshRemoteEntry, SshSession, type SshSessionInfo, SshSessionManager, type ToolContext, analyzeSegment, canonicalizeCommand, createSshMcpServer, downloadFile, extractSubstitutions, inspectCommand, inspectLocalPath, inspectRemotePath, inspectWorkingDirectory, listRemoteDirectory, loadHostProfile, normalizeCommandText, readRemoteFile, registerAllTools, splitCommandSegments, stripQuotedText, toHostSummary, uploadFile, writeRemoteFile };