diff --git a/cmd/anvilmcp/execute.go b/cmd/anvilmcp/execute.go index 50c9b18..9c5d519 100644 --- a/cmd/anvilmcp/execute.go +++ b/cmd/anvilmcp/execute.go @@ -258,43 +258,11 @@ func executeCode(code, language string, timeout int, sandboxName string, trusted cmd = exec.CommandContext(ctx, landrunPath, args...) cmd.Dir = workDir - case "go": - args := []string{} - - addPaths := func(flag string, paths []string) { - for _, p := range paths { - expanded := sandbox.ExpandPath(p, workDir) - if expanded == "" || strings.Contains(expanded, "{") { - continue - } - if _, err := os.Stat(expanded); err == nil { - args = append(args, flag, expanded) - } - } - } - - addPaths("--ro", cfg.Filesystem.RO) - addPaths("--rox", cfg.Filesystem.ROX) - addPaths("--rw", cfg.Filesystem.RW) - addPaths("--rwx", cfg.Filesystem.RWX) - - if cfg.Network.Unrestricted { - args = append(args, "--unrestricted-network") - } - - for _, env := range cfg.Env { - if os.Getenv(env) != "" || env == "HOME" || env == "USER" || env == "PATH" { - args = append(args, "--env", env) - } - } - - args = append(args, "--", "go", "run", "-") - - cmd = exec.CommandContext(ctx, landrunPath, args...) - cmd.Dir = workDir - cmd.Stdin = strings.NewReader(code) + // Add new language cases here: + // case "python": + // args = append(args, "--", "python3", "-c", code) default: - return "", fmt.Errorf("unsupported language: %s (supported: bash, go)", language) + return "", fmt.Errorf("unsupported language: %s (supported: bash)", language) } // Limit output size (10MB) diff --git a/cmd/anvilmcp/main.go b/cmd/anvilmcp/main.go index efdf3f2..cbfb053 100644 --- a/cmd/anvilmcp/main.go +++ b/cmd/anvilmcp/main.go @@ -133,7 +133,7 @@ func main() { "tool": {Type: "string", Description: "Tool name from agent/tools/ (e.g. 'list_sessions.sh')"}, "args": {Type: "array", Description: "Arguments to pass to tool", Items: &Items{Type: "string"}}, "code": {Type: "string", Description: "Inline code to execute (if tool not specified)"}, - "language": {Type: "string", Description: "Programming language (auto-detected from tool extension)", Enum: []string{"bash", "go"}}, + "language": {Type: "string", Description: "Programming language", Enum: []string{"bash"}}, "timeout": {Type: "integer", Description: "Timeout in seconds (default: 30)"}, "sandbox": {Type: "string", Description: "Sandbox config name (default: default)"}, }, @@ -183,17 +183,8 @@ func handleToolCall(req MCPRequest) { return } code = toolCode - // Auto-detect language from extension - if language == "" { - switch { - case strings.HasSuffix(tool, ".go"): - language = "go" - default: - language = "bash" - } - } // For bash with args, wrap script to receive positional params - if language == "bash" && len(toolArgs) > 0 { + if len(toolArgs) > 0 { // Escape args for bash array var escaped []string for _, arg := range toolArgs { diff --git a/internal/p9/tools.go b/internal/p9/tools.go index b1c2172..45a5e78 100644 --- a/internal/p9/tools.go +++ b/internal/p9/tools.go @@ -94,8 +94,11 @@ func parseFrontMatter(path string) (*ToolMeta, error) { scanner := bufio.NewScanner(f) for scanner.Scan() { line := scanner.Text() + // Handle both shell (#) and Go (//) comments if comment, ok := strings.CutPrefix(line, "#"); ok { line = strings.TrimSpace(comment) + } else if comment, ok := strings.CutPrefix(line, "//"); ok { + line = strings.TrimSpace(comment) } else { break } @@ -114,7 +117,7 @@ func parseFrontMatter(path string) (*ToolMeta, error) { return meta, nil } -// listAllTools scans all tools directories and returns metadata for all .sh files +// listAllTools scans all tools directories and returns metadata for all tool files func (t *ToolsFS) listAllTools() ([]*ToolMeta, error) { seen := make(map[string]bool) var tools []*ToolMeta @@ -126,17 +129,22 @@ func (t *ToolsFS) listAllTools() ([]*ToolMeta, error) { } for _, entry := range entries { - if entry.IsDir() || !strings.HasSuffix(entry.Name(), ".sh") { + name := entry.Name() + if entry.IsDir() { continue } - if seen[entry.Name()] { + // Include .sh and .go files + if !strings.HasSuffix(name, ".sh") && !strings.HasSuffix(name, ".go") { continue } - meta, err := parseFrontMatter(filepath.Join(dir, entry.Name())) + if seen[name] { + continue + } + meta, err := parseFrontMatter(filepath.Join(dir, name)) if err != nil { continue } - seen[entry.Name()] = true + seen[name] = true tools = append(tools, meta) } } @@ -170,15 +178,15 @@ func (t *ToolsFS) List(path string) ([]plan9.Dir, error) { func (t *ToolsFS) Read(path string) ([]byte, error) { parts := strings.Split(strings.TrimPrefix(path, "/"), "/") - // /tools/ - read tool script + // /tools/ - read tool script if len(parts) != 2 || parts[0] != "tools" { return nil, fmt.Errorf("not found") } filename := parts[1] - if !strings.HasSuffix(filename, ".sh") { - return nil, fmt.Errorf("not a shell script") + if !strings.HasSuffix(filename, ".sh") && !strings.HasSuffix(filename, ".go") { + return nil, fmt.Errorf("not a tool file") } // Prevent path traversal