Remove path restrictions for node, bash, python commands; add MCP.md and reference in README

This commit is contained in:
Cheikh Seck committed 2026-03-17 15:34:29 +00:00
1 parent bb494274ad
commit 953723dbc7
3 files changed
+164 -77

No files matched your search

+161
View File
@@ -0,0 +1,161 @@
# MCP Integration Guide
GoDex supports integrating with external MCP (Model Context Protocol) servers to extend its capabilities. This document explains how to configure external MCP servers.
## Configuration
External MCP servers are configured in your `config.yaml` file under the `mcp` section.
### MCPServer Structure
Each MCP server is defined with the following properties:
| Field | Type | Description |
|-------|------|-------------|
| `name` | string | A friendly name for the server |
| `command` | string | The command to run the MCP server executable |
| `args` | []string | Optional command-line arguments |
| `env` | []string | Optional environment variables |
| `transport` | string | Transport type (e.g., `stdio`, `sse`) |
| `allowed_paths` | []string | Paths the server is allowed to access |
### Example Configuration
```yaml
mcp:
servers:
# Example: A custom filesystem server
filesystem:
command: "npx"
args: ["-y", "@modelcontextprotocol/server-filesystem", "/Users/myuser/docs"]
transport: "stdio"
allowed_paths:
- "/Users/myuser/docs"
- "/Users/myuser/shared"
# Example: A GitHub MCP server
github:
command: "npx"
args: ["-y", "@modelcontextprotocol/server-github"]
transport: "stdio"
env:
- "GITHUB_PERSONAL_ACCESS_TOKEN=$GITHUB_TOKEN"
```
## Built-in MCP Servers
GoDex includes several built-in MCP tools:
### Bash
Execute shell commands on your system.
```yaml
mcp:
servers:
bash:
command: "godex"
args: ["mcp", "bash"]
```
### Filesystem
Perform file operations (read, write, list, delete, search).
```yaml
mcp:
servers:
filesystem:
command: "godex"
args: ["mcp", "filesystem"]
allowed_paths:
- "/home/user/projects"
```
### Webscraper
Fetch URLs and extract content from web pages.
```yaml
mcp:
servers:
webscraper:
command: "godex"
args: ["mcp", "webscraper"]
```
## Using MCP Servers in Conversations
Once configured, you can use MCP servers in your conversations with GoDex. The AI agent will automatically discover and use available tools from your configured MCP servers.
For example:
```
User: Can you read the contents of /home/user/projects/README.md?
GoDex: (uses filesystem MCP server to read the file)
# Contents of README.md
...
```
## Environment Variables
You can reference environment variables in your MCP server configuration using `$VAR_NAME` syntax:
```yaml
mcp:
servers:
myserver:
command: "my-mcp-server"
env:
- "API_KEY=$MY_API_KEY"
- "DATABASE_URL=$DB_URL"
```
Make sure these environment variables are set before starting GoDex.
## Transport Types
### stdio
The default transport type. Communicates with the MCP server via standard input/output.
```yaml
transport: "stdio"
```
### SSE (Server-Sent Events)
For HTTP-based MCP servers.
```yaml
transport: "sse"
url: "http://localhost:8080/sse"
```
## Security
- Only use MCP servers from trusted sources
- Review the `allowed_paths` configuration to restrict filesystem access
- Be cautious when passing sensitive data via environment variables
- MCP servers run with the same permissions as the GoDex process
## Troubleshooting
### Server fails to start
- Verify the command path is correct
- Check that required dependencies are installed
- Review the server logs for error messages
### Tools not available
- Ensure the MCP server started successfully
- Check that the server configuration is valid YAML
- Verify the transport type matches the server's requirements
### Permission denied errors
- Check that the paths in `allowed_paths` exist
- Verify file/directory permissions
- Ensure the MCP server process has necessary access rights
+2
View File
@@ -141,6 +141,8 @@ GoDex includes built-in MCP servers:
| `bash` | Run shell commands, Python, Node.js |
| `webscraper` | Fetch URLs with JavaScript rendering, search HTML, extract links |
For detailed MCP configuration including external servers, see [MCP.md](MCP.md).
#### Adding Allowed Paths
By default, MCP servers only allow access to the current working directory. Add more allowed paths:
+1 -77
View File
@@ -107,18 +107,9 @@ func (s *BashServer) isPathAllowed(path string) bool {
}
var (
cdRegex = regexp.MustCompile(`(?i)^cd\s+(\S+)`)
pythonPathOp = regexp.MustCompile(`(?i)(?:os\.chdir|os\.mkdir|os\.makedirs|os\.rmdir|os\.remove|os\.rename|shutil\.move|shutil\.copy|open)\s*\(\s*['"]`)
nodePathOp = regexp.MustCompile(`(?i)(?:process\.chdir|fs\.(?:mkdir|rmdir|unlink|rename|writeFile|readFile)|fs\.promises\.(?:mkdir|rmdir|unlink|rename|writeFile|readFile))\s*\(\s*['"]`)
cdRegex = regexp.MustCompile(`(?i)^cd\s+(\S+)`)
)
var pathCommands = []string{
"cat", "ls", "rm", "rmdir", "mv", "cp", "touch", "chmod", "chown", "chgrp",
"head", "tail", "less", "more", "grep", "rg", "find", "stat", "file",
"mkdir", "tar", "zip", "unzip", "gzip", "gunzip", "xz", "diff", "cmp",
"du", "df", "ln", "readlink", "realpath", "which", "whereis",
}
func (s *BashServer) isCommandAllowed(command string) bool {
trimmed := strings.TrimSpace(command)
@@ -132,65 +123,6 @@ func (s *BashServer) isCommandAllowed(command string) bool {
}
}
for _, cmd := range pathCommands {
re := regexp.MustCompile(fmt.Sprintf(`(?i)^%s\s+(\S+)`, cmd))
match := re.FindStringSubmatch(trimmed)
if len(match) > 1 {
targetPath := match[1]
targetPath = strings.ReplaceAll(targetPath, "~", os.Getenv("HOME"))
targetPath = filepath.Clean(targetPath)
if !s.isPathAllowed(targetPath) {
return false
}
}
reWithFlags := regexp.MustCompile(fmt.Sprintf(`(?i)^%s\s+-[a-zA-Z]+\s+(\S+)`, cmd))
match = reWithFlags.FindStringSubmatch(trimmed)
if len(match) > 1 {
targetPath := match[1]
targetPath = strings.ReplaceAll(targetPath, "~", os.Getenv("HOME"))
targetPath = filepath.Clean(targetPath)
if !s.isPathAllowed(targetPath) {
return false
}
}
}
return true
}
func (s *BashServer) isPythonCodeAllowed(code string) bool {
indices := pythonPathOp.FindAllStringIndex(code, -1)
for _, loc := range indices {
quote := code[loc[1]]
endIdx := loc[1] + 1
for endIdx < len(code) && code[endIdx] != quote {
endIdx++
}
path := code[loc[1]+1 : endIdx]
path = strings.ReplaceAll(path, "~", os.Getenv("HOME"))
path = filepath.Clean(path)
if !s.isPathAllowed(path) {
return false
}
}
return true
}
func (s *BashServer) isNodeCodeAllowed(code string) bool {
indices := nodePathOp.FindAllStringIndex(code, -1)
for _, loc := range indices {
quote := code[loc[1]]
endIdx := loc[1] + 1
for endIdx < len(code) && code[endIdx] != quote {
endIdx++
}
path := code[loc[1]+1 : endIdx]
path = strings.ReplaceAll(path, "~", os.Getenv("HOME"))
path = filepath.Clean(path)
if !s.isPathAllowed(path) {
return false
}
}
return true
}
@@ -360,10 +292,6 @@ func (s *BashServer) runPython(ctx context.Context, args map[string]interface{})
return "", fmt.Errorf("code is required")
}
if !s.isPythonCodeAllowed(code) {
return "", fmt.Errorf("code not allowed: must operate within allowed paths: %s", strings.Join(s.allowedPaths, ", "))
}
timeout := 30
if t, ok := args["timeout"].(float64); ok {
timeout = int(t)
@@ -388,10 +316,6 @@ func (s *BashServer) runNode(ctx context.Context, args map[string]interface{}) (
return "", fmt.Errorf("code is required")
}
if !s.isNodeCodeAllowed(code) {
return "", fmt.Errorf("code not allowed: must operate within allowed paths: %s", strings.Join(s.allowedPaths, ", "))
}
timeout := 30
if t, ok := args["timeout"].(float64); ok {
timeout = int(t)