Minimal MCP server in Go that exposes a local filesystem directory through HTTP JSON-RPC, with strict path confinement and optional file filtering.
list_files,read_file, andsearch_filesMCP tools- Path traversal protection (
..and absolute paths are rejected) - Optional dotfile and regex-based exclusion
--excludealias for regex-based exclusion (combined with--exclude-regexwhen both are set)- Bearer-token authentication
- Optional TLS support
- Optional Tailscale
serveintegration - Foreground-first with live terminal dashboard (TUI)
go build ./...The default workflow is designed for local use:
go run .This starts the MCP endpoint in the foreground, serves the current directory (.), chooses an available local port automatically, auto-generates a token if needed, keeps a live dashboard until shutdown, and on macOS enables Apple sandboxing by default (restricting file access to the target root while inheriting Apple’s baseline runtime allowances).
You can always pass an explicit listen address if you want to pin it:
go run . /absolute/path/to/expose 127.0.0.1:8080You can disable sandbox mode (for debugging or unsupported environments) with:
go run . /absolute/path/to/expose --sandbox=falseOr provide your own sandbox profile:
go run . /absolute/path/to/expose --sandbox-profile /path/to/profile.sbYou can also pass explicit flags if preferred:
go run . \
--root /absolute/path/to/expose \
--listen 127.0.0.1:8080 \
--token "<long-random-secret>"To exclude paths with one or two regex expressions:
go run . /absolute/path/to/expose --exclude='\\.(log|tmp)$'
go run . /absolute/path/to/expose --exclude='\\.git' --exclude-regex='node_modules'The two patterns are combined with OR when both are provided.
If you want old-school output only:
go run . /absolute/path/to/expose --no-tuiTailscale exposure is disabled by default and can be enabled explicitly:
--tailscale-expose configures mapping with:
- endpoint path:
/mcp - remote URL:
https://<tailscale-hostname>/mcp
You can override defaults:
go run . /absolute/path/to/expose \
--tailscale-path /mcp \
--tailscale-port 443 \
--tailscale-hostname my-machine.ts.netTo disable tailscale exposure:
go run . /absolute/path/to/expose --no-tailscaleLOCALFILES_MCP_ROOT(alternative to--root)LOCALFILES_MCP_TOKEN(alternative to--token)
POST /mcp accepts JSON-RPC requests.
Supported methods:
initializetools/listtools/call- Tool
list_files:path(string, default.)recursive(bool, defaultfalse)glob(string, optional) — filter results by glob pattern (e.g.*.go,**/*.test.js). Implies recursive when set.
- Tool
read_file:path(string, required)max_bytes(int, default from--max-file-bytes)offset(int, optional) — 1-based starting line number for partial readslimit(int, optional) — maximum number of lines to return
- Tool
search_files:path(string, default.) — directory to search withinquery(string, required) — text to search forcase_sensitive(bool, defaultfalse)max_matches(int, default100)max_bytes_per_file(int, optional) — skip files larger than this
- Tool
-
Open the ChatGPT app.
-
Add a Custom MCP server with endpoint:
- Remote URL:
https://<your-tailnet-hostname>/mcp - Header:
Authorization: Bearer <token>
- Remote URL:
-
Use tools
list_files,read_file, andsearch_files.
The token displayed at startup in the dashboard is generated if you don't provide one.
The process calls tailscale serve with your configured values and removes that mapping when the process exits or if it crashes.
Current command pattern:
tailscale serve --https=<tailscale-port> --set-path <tailscale-path>=http://<listen><tailscale-path>- teardown:
tailscale serve --https=<tailscale-port> --set-path <tailscale-path>=offand falls back totailscale serve resetif needed
By default, the binary runs a Wireshark-inspired terminal dashboard with:
- pinned top bar: endpoint, uptime, live/paused status, request counters
- pinned bottom bar: keybinding hints or filter input
- color-coded scrollable request table (green 2xx, red errors, yellow 401)
- detail inspector pane with expandable request params and metadata
- setup instructions shown until the first request arrives
Keyboard shortcuts:
j/kor arrows: move selectiong/G: jump to top/bottomctrl-d/ctrl-u: half-page scrollenter: expand/collapse inspector detailsspace: pause/resume live stream/: filter (tool:read_file,status:200,-status:401, free text)c: clear event logq: quit
Disable the dashboard with --no-tui if you need plain logs.
go test ./...