Skip to main content
Glama

Sandbox MCP

MIT License
78
  • Linux
  • Apple
config.go6.23 kB
package config import ( "encoding/json" "fmt" "os" "path/filepath" "strconv" "strings" "time" ) // SandboxHints stores hints provided to the MCP client type SandboxHints struct { IsReadOnlyRaw *bool `json:"isReadOnly,omitempty"` IsDestructiveRaw *bool `json:"isDestructive,omitempty"` IsIdempotentRaw *bool `json:"isIdempotent,omitempty"` IsExternalInteractionRaw *bool `json:"isExternalInteraction,omitempty"` } // IsReadOnly returns true if the sandbox is meant to be read-only // If the raw value is not set, check the mount and security configurations func (h *SandboxHints) IsReadOnly(mountReadOnly bool, securityReadOnly bool) bool { // If the raw value is set to either true or false, return that if h.IsReadOnlyRaw != nil { return *h.IsReadOnlyRaw } // If the raw value is not set, check the mount and security configurations return mountReadOnly || securityReadOnly } // IsDestructive returns true if the sandbox is meant to be destructive // Defaults to false func (h *SandboxHints) IsDestructive() bool { if h.IsDestructiveRaw != nil { return *h.IsDestructiveRaw } return false } // IsIdempotent returns true if the sandbox is meant to be idempotent // Defaults to true func (h *SandboxHints) IsIdempotent() bool { if h.IsIdempotentRaw != nil { return *h.IsIdempotentRaw } return true } // IsExternalInteraction returns true if the sandbox is meant to interact with external systems // Defaults to the network configuration under security func (h *SandboxHints) IsExternalInteraction(securityNetwork string) bool { if h.IsExternalInteractionRaw != nil { return *h.IsExternalInteractionRaw } // If the raw value is not set, check the network configuration return securityNetwork != "none" } // SandboxFile represents a file parameter type SandboxFile struct { Name string `json:"name"` Description string `json:"description"` } // ParamName returns a safe parameter name for a file (replaces '.' with '_') func (f *SandboxFile) ParamName() string { return strings.ReplaceAll(f.Name, ".", "_") } // SandboxParameters represents the parameters configuration type SandboxParameters struct { AdditionalFiles bool `json:"additionalFiles"` Files []SandboxFile `json:"files,omitempty"` } // SandboxSecurity represents the security configuration type SandboxSecurity struct { ReadOnly bool `json:"readOnly"` CapDrop []string `json:"capDrop"` SecurityOpt []string `json:"securityOpt"` Network string `json:"network"` } // SandboxResources represents the resource limits type SandboxResources struct { CPU int `json:"cpu"` Memory int64 `json:"memory"` Processes int64 `json:"processes"` Files int64 `json:"files"` } // SandboxMount represents the mount configuration type SandboxMount struct { WorkDir string `json:"workdir"` TmpDirPrefix string `json:"tmpdirPrefix"` ScriptPermsRaw string `json:"scriptPerms"` ReadOnly bool `json:"readOnly"` } // ScriptPerms returns the script permissions as os.FileMode func (m *SandboxMount) ScriptPerms() os.FileMode { mode, err := parseFileMode(m.ScriptPermsRaw) if err != nil { return 0755 } return mode } // SandboxConfig represents the complete configuration for a sandbox environment type SandboxConfig struct { // Basic configuration Id string `json:"id"` NameRaw string `json:"name"` Description string `json:"description"` Hints SandboxHints `json:"hints,omitempty"` Version string `json:"version"` Image string `json:"image"` User string `json:"user"` Entrypoint string `json:"entrypoint"` TimeoutRaw int `json:"timeout"` Before []string `json:"before"` Command []string `json:"command"` Parameters SandboxParameters `json:"parameters"` Security SandboxSecurity `json:"security"` Resources SandboxResources `json:"resources"` Mount SandboxMount `json:"mount"` } // Name returns the name if set, otherwise falls back to Id func (c *SandboxConfig) Name() string { if c.NameRaw != "" { return c.NameRaw } return c.Id } // ParamEntrypoint returns the entrypoint file name with proper formatting func (c *SandboxConfig) ParamEntrypoint() string { return strings.ReplaceAll(c.Entrypoint, ".", "_") } // Timeout returns the timeout as a time.Duration func (c *SandboxConfig) Timeout() time.Duration { return time.Duration(c.TimeoutRaw) * time.Second } // RunCommand returns the initial command to run in the sandbox func (c *SandboxConfig) RunCommand() []string { if len(c.Before) > 0 { return c.Before } return c.Command } // ExecCommand returns the command to execute in a running sandbox func (c *SandboxConfig) ExecCommand() []string { if len(c.Before) > 0 { return c.Command } return nil } // Tty returns true if the sandbox should be run with a TTY func (c *SandboxConfig) Tty() bool { return len(c.Before) > 0 } // parseFileMode converts a string like "0755" into os.FileMode func parseFileMode(mode string) (os.FileMode, error) { // Parse as base-8 (octal) parsed, err := strconv.ParseUint(mode, 8, 32) if err != nil { return 0, fmt.Errorf("invalid file mode %q: %w", mode, err) } return os.FileMode(parsed), nil } // LoadSandboxConfigs loads all sandbox configurations from the sandboxes directory func LoadSandboxConfigs(sandboxDir string) (map[string]*SandboxConfig, error) { configs := make(map[string]*SandboxConfig) entries, err := os.ReadDir(sandboxDir) if err != nil { return nil, fmt.Errorf("failed to read sandbox directory: %v", err) } for _, entry := range entries { if !entry.IsDir() { continue } configPath := filepath.Join(sandboxDir, entry.Name(), "config.json") configData, err := os.ReadFile(configPath) if err != nil { return nil, fmt.Errorf("failed to read config file %s: %v", configPath, err) } var config SandboxConfig if err := json.Unmarshal(configData, &config); err != nil { return nil, fmt.Errorf("failed to parse config file %s: %v", configPath, err) } configs[config.Id] = &config } return configs, nil }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/pottekkat/sandbox-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server