Files
zeekayandHanzo Dev a386271c80 isolation is a value the org sets, and an empty one is not runc
Every sandbox was created privileged under the daemon's default runtime, and
the setting that would have changed it defaulted to an empty string that
silently meant runc. For a service whose whole premise is running code
somebody else wrote, that is not a boundary.

An org sets its isolation and the create request carries it, so a sandbox
records what it was made with: changing the policy moves new sandboxes and
leaves running ones alone. gvisor is the default. firecracker is delivered
through kata's shim, which is why it is one name rather than two. runc is
refused unless the runner names that org, and an empty list names nobody.

Absent means the default, unknown is a refusal, and a runtime the daemon does
not have is a refusal. Nothing substitutes quietly.

The runner took an organization in a field called UserId with a note beside
it saying so. Deciding who may have runc through a field named after
something else is not reviewable.

Privileged is replaced by dropping everything and granting the eight the
daemon uses. Nothing the sandbox does broke; what stopped working is mount,
mknod, raw sockets, chroot, writing to proc, and seeing the host's disks.
AUDIT_WRITE is among them because without it sudo works and complains every
time.

The creation histogram's lowest bucket was a tenth of a second, so the metric
could not observe the claim the product makes about its own speed. It can
now, and it carries the isolation, so comparing them is a query.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-11 13:47:31 -07:00

123 lines
4.6 KiB
Go

// Copyright 2025 Hanzo Industries Inc.
// SPDX-License-Identifier: AGPL-3.0
package tools
import (
"context"
"fmt"
"strconv"
"strings"
apiclient "github.com/hanzoai/runtime/libs/api-client-go"
apiclient_cli "github.com/hanzoai/runtime/apps/cli/apiclient"
"github.com/mark3labs/mcp-go/mcp"
log "github.com/sirupsen/logrus"
)
type PreviewLinkArgs struct {
Id *string `json:"id,omitempty"`
Port *int32 `json:"port,omitempty"`
CheckServer *bool `json:"checkServer,omitempty"`
Description *string `json:"description,omitempty"`
}
func GetPreviewLinkTool() mcp.Tool {
return mcp.NewTool("preview_link",
mcp.WithDescription("Generate accessible preview URLs for web applications running in the Runtime sandbox. Creates a secure tunnel to expose local ports externally without configuration. Validates if a server is actually running on the specified port and provides diagnostic information for troubleshooting. Supports custom descriptions and metadata for better organization of multiple services."),
mcp.WithNumber("port", mcp.Required(), mcp.Description("Port to expose.")),
mcp.WithString("description", mcp.Required(), mcp.Description("Description of the service.")),
mcp.WithBoolean("checkServer", mcp.Required(), mcp.Description("Check if a server is running on the specified port.")),
mcp.WithString("id", mcp.Required(), mcp.Description("ID of the sandbox to generate the preview link for.")),
)
}
func PreviewLink(ctx context.Context, request mcp.CallToolRequest, args PreviewLinkArgs) (*mcp.CallToolResult, error) {
apiClient, err := apiclient_cli.GetApiClient(nil, runtimeMCPHeaders)
if err != nil {
return nil, err
}
if args.Id == nil || *args.Id == "" {
return &mcp.CallToolResult{IsError: true}, fmt.Errorf("sandbox ID is required")
}
if args.Port == nil {
return &mcp.CallToolResult{IsError: true}, fmt.Errorf("port parameter is required")
}
checkServer := false
if args.CheckServer != nil && *args.CheckServer {
checkServer = *args.CheckServer
}
log.Infof("Generating preview link - port: %d", *args.Port)
// Get the sandbox using sandbox ID
sandbox, _, err := apiClient.SandboxAPI.GetSandbox(ctx, *args.Id).Execute()
if err != nil {
return &mcp.CallToolResult{IsError: true}, fmt.Errorf("failed to get sandbox: %v", err)
}
if sandbox == nil {
return &mcp.CallToolResult{IsError: true}, fmt.Errorf("no sandbox available")
}
// Check if server is running on specified port
if checkServer {
log.Infof("Checking if server is running - port: %d", *args.Port)
checkCmd := fmt.Sprintf("curl -s -o /dev/null -w '%%{http_code}' http://localhost:%d --max-time 2 || echo 'error'", *args.Port)
result, _, err := apiClient.ToolboxAPI.ExecuteCommand(ctx, *args.Id).ExecuteRequest(*apiclient.NewExecuteRequest(checkCmd)).Execute()
if err != nil {
return &mcp.CallToolResult{IsError: true}, fmt.Errorf("error checking server: %v", err)
}
response := strings.TrimSpace(result.Result)
if response == "error" || strings.HasPrefix(response, "0") {
log.Infof("No server detected - port: %d", *args.Port)
// Check what might be using the port
psCmd := fmt.Sprintf("ps aux | grep ':%d' | grep -v grep || echo 'No process found'", *args.Port)
psResult, _, err := apiClient.ToolboxAPI.ExecuteCommand(ctx, *args.Id).ExecuteRequest(*apiclient.NewExecuteRequest(psCmd)).Execute()
if err != nil {
return &mcp.CallToolResult{IsError: true}, fmt.Errorf("error checking processes: %v", err)
}
return &mcp.CallToolResult{IsError: true}, fmt.Errorf("no server detected on port %d. Process info: %s", *args.Port, strings.TrimSpace(psResult.Result))
}
}
var runnerDomain string
if sandbox.RunnerDomain != nil {
runnerDomain = *sandbox.RunnerDomain
}
// Format preview URL
previewURL := fmt.Sprintf("http://%d-%s.%s", *args.Port, *args.Id, runnerDomain)
// Test URL accessibility if requested
var accessible bool
var statusCode string
if checkServer {
checkCmd := fmt.Sprintf("curl -s -o /dev/null -w '%%{http_code}' %s --max-time 3 || echo 'error'", previewURL)
result, _, err := apiClient.ToolboxAPI.ExecuteCommand(ctx, *args.Id).ExecuteRequest(*apiclient.NewExecuteRequest(checkCmd)).Execute()
if err != nil {
log.Errorf("Error checking preview URL: %v", err)
} else {
response := strings.TrimSpace(result.Result)
accessible = response != "error" && !strings.HasPrefix(response, "0")
if _, err := strconv.Atoi(response); err == nil {
statusCode = response
}
}
}
log.Infof("Preview link generated: %s", previewURL)
log.Infof("Accessible: %t", accessible)
log.Infof("Status code: %s", statusCode)
return mcp.NewToolResultText(fmt.Sprintf("Preview link generated: %s", previewURL)), nil
}