-
Notifications
You must be signed in to change notification settings - Fork 1
Feature/ssh mcp #133
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: trunk
Are you sure you want to change the base?
Feature/ssh mcp #133
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -971,6 +971,51 @@ function run_wpcom_site_wp_cli_command( string $site_id_or_url, string $wp_cli_c | |
| ); | ||
| } | ||
|
|
||
| /** | ||
| * Runs an arbitrary, non-interactive shell command on the specified WordPress.com Atomic site over SSH and returns the captured output. | ||
| * | ||
| * Unlike run_wpcom_site_wp_cli_command(), the command is not prefixed with `wp` and is executed verbatim. SSH is only available on | ||
| * Atomic sites. This is a high-risk operation: callers are responsible for guarding/approving the command (e.g. the MCP layer | ||
| * requires human approval). | ||
| * | ||
| * @param string $site_id_or_url The ID or URL of the site to run the command on. | ||
| * @param string $ssh_command The raw shell command to run. | ||
| * | ||
| * @return string|null The captured command output, or null if the site could not be resolved, is not Atomic, or the SSH connection failed. | ||
| */ | ||
| function run_wpcom_site_ssh_command( string $site_id_or_url, string $ssh_command ): ?string { | ||
| // Accept a full URL, a bare domain, or a numeric ID. Normalize URLs to a host, mirroring get_site_input(). | ||
| if ( str_contains( $site_id_or_url, 'http' ) ) { | ||
| $host = parse_url( $site_id_or_url, PHP_URL_HOST ); | ||
| $site_id_or_url = empty( $host ) ? $site_id_or_url : $host; | ||
| } | ||
|
|
||
| $site = get_wpcom_site( $site_id_or_url ); | ||
| if ( is_null( $site ) || empty( $site->is_wpcom_atomic ) ) { | ||
| return null; | ||
| } | ||
|
|
||
| $ssh = WPCOM_Connection_Helper::get_ssh_connection( $site->ID ); // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase | ||
| if ( is_null( $ssh ) ) { | ||
| return null; | ||
| } | ||
|
|
||
| $output = ''; | ||
| try { | ||
| $ssh->setTimeout( 0 ); // Disable timeout in case the command takes a long time. | ||
| $ssh->exec( | ||
| $ssh_command, | ||
| static function ( string $str ) use ( &$output ): void { | ||
| $output .= $str; | ||
| } | ||
|
Comment on lines
+1005
to
+1010
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🌐 Web query:
💡 Result: In phpseclib3, setting Citations:
Bound SSH runtime and output size to avoid hanging MCP requests. Line 1005 disables timeouts ( Suggested hardening sketch- $ssh->setTimeout( 0 ); // Disable timeout in case the command takes a long time.
+ $timeout_seconds = (int) ( getenv( 'TEAM51_MCP_SSH_TIMEOUT_SECONDS' ) ?: 300 );
+ $max_output_bytes = (int) ( getenv( 'TEAM51_MCP_SSH_MAX_OUTPUT_BYTES' ) ?: 262144 );
+ $captured_bytes = 0;
+ $truncated = false;
+ $ssh->setTimeout( $timeout_seconds );
$ssh->exec(
$ssh_command,
- static function ( string $str ) use ( &$output ): void {
- $output .= $str;
+ static function ( string $str ) use ( &$output, &$captured_bytes, &$truncated, $max_output_bytes ): void {
+ if ( $captured_bytes >= $max_output_bytes ) {
+ $truncated = true;
+ return;
+ }
+ $remaining = $max_output_bytes - $captured_bytes;
+ $chunk = substr( $str, 0, $remaining );
+ $output .= $chunk;
+ $captured_bytes += strlen( $chunk );
}
);
+ if ( $truncated ) {
+ $output .= "\n[output truncated]";
+ }🤖 Prompt for AI Agents |
||
| ); | ||
| } finally { | ||
| $ssh->disconnect(); | ||
| } | ||
|
|
||
| return $output; | ||
| } | ||
|
|
||
| // endregion | ||
|
|
||
| // region CONSOLE | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Align exclusion claim with the actual MCP tool surface.
Line 123 says other high-risk operations are excluded from MCP, but
mcp/Team51McpTools.phpstill exposes legacy high-risk tools (e.g., site creation and deployment-related operations). Please reword this to avoid a false security posture.🤖 Prompt for AI Agents