gopher-bridge
AI coding agents are bad at navigating large Go codebases without help from gopls. gopher-bridge is an MCP server that gives them gopls: go-to-definition, find-references, hover, diagnostics, implementations, and call hierarchy. It works with Claude Code, Copilot, Cursor, or any MCP client.
On etcd (~238K LOC), gopher-bridge averaged 285ms per tool call compared to 1,043ms for mcp-language-server. On istio (~540K LOC), IDE was fastest at 437ms, gb was second at 805ms, and mls was third at 1,356ms. See the full results for all five codebases. gopher-bridge is smaller (~6.8K lines vs ~24.5K), read-only, and has two direct dependencies. It only supports Go. If you need Rust, Python, or TypeScript, use mcp-language-server.
Install
go install github.com/iandvt/gopher-bridge@latest
Prerequisites: Go 1.26+ and gopls v0.21+ (go install golang.org/x/tools/gopls@latest).
Configuration
Add to .mcp.json in your project root (Claude Code):
{
"mcpServers": {
"gopher-bridge": {
"command": "gopher-bridge",
"args": ["--workspace", "."]
}
}
}
Claude Desktop, VS Code / Copilot, and replacing mcp-language-server
Claude Desktop (claude_desktop_config.json)
{
"mcpServers": {
"gopher-bridge": {
"command": "gopher-bridge",
"args": ["--workspace", "/path/to/your/go/project"]
}
}
}
VS Code / GitHub Copilot (settings.json)
{
"mcp": {
"servers": {
"gopher-bridge": {
"command": "gopher-bridge",
"args": ["--workspace", "${workspaceFolder}"]
}
}
}
}
Replacing mcp-language-server
If you currently use mcp-language-server with gopls, replace:
{
"command": "mcp-language-server",
"args": ["--workspace", "/path/to/project", "--lsp", "gopls"]
}
With:
{
"command": "gopher-bridge",
"args": ["--workspace", "/path/to/project"]
}
No --lsp flag is needed. gopher-bridge is hardcoded to gopls.
| Tool |
Input |
Description |
definition |
symbolName |
Look up a Go symbol's definition. Returns source code extracted via go/parser. |
references |
symbolName |
Find all references to a Go symbol. Returns file locations with context lines. |
hover |
filePath, line, column |
Get type info and documentation at a position. |
diagnostics |
filePath |
Get compiler errors and warnings for a file. |
implementation |
filePath, line, column |
Find implementations of an interface or abstract method. |
incoming_calls |
filePath, line, column |
Find all functions and methods that call the function at a position. |
outgoing_calls |
filePath, line, column |
Find all functions and methods called by the function at a position. |
All tools are read-only.
How It Works
gopher-bridge sits between two stdio-based JSON-RPC protocols. The AI agent talks MCP on one side, gopls talks LSP on the other. gopher-bridge translates between them and manages the gopls subprocess lifecycle: open files, stale file detection, diagnostics caching, graceful shutdown.
Unlike gopls directly (where most queries need a file path and position), gopher-bridge lets agents look up symbols by name. definition "http.Handler" works without knowing which file it lives in. Source extraction uses go/parser to return full declarations, not just type signatures.
Architecture diagrams and feature comparison
flowchart TD
A[AI Assistant<br>Claude, Copilot, etc.] -->|MCP JSON-RPC over stdio| B[gopher-bridge]
B -->|LSP JSON-RPC over stdio pipes| C[gopls subprocess]
C -->|Semantic analysis| D[Your Go codebase]
sequenceDiagram
participant AI as AI Assistant
participant GB as gopher-bridge
participant GP as gopls
AI->>GB: MCP tool call (e.g. definition "http.Handler")
GB->>GB: Acquire semaphore (max 20 concurrent)
GB->>GP: workspace/symbol query
GP-->>GB: Symbol locations
GB->>GB: EnsureFile (re-read from disk if stale)
GB->>GP: textDocument/definition
GP-->>GB: Source location
GB->>GB: go/parser AST extraction (cap 200 lines)
GB-->>AI: Formatted source code + location
Lifecycle
stateDiagram-v2
[*] --> Startup: gopher-bridge --workspace /path
Startup --> ParseFlags: --workspace, --log-level, etc.
ParseFlags --> CheckGopls: exec.LookPath + version >= v0.21
CheckGopls --> InitGopls: Spawn gopls, LSP initialize/initialized
InitGopls --> Ready: MCP server.Run (stdio)
Ready --> Ready: Tool calls (definition, references, hover, diagnostics, implementation, incoming_calls, outgoing_calls)
Ready --> Shutdown: Client disconnect / SIGINT / SIGTERM / PPID change
Shutdown --> CloseFiles: didClose (fire-and-forget)
CloseFiles --> LSPShutdown: shutdown request
LSPShutdown --> LSPExit: exit notification
LSPExit --> Kill: SIGKILL if gopls hangs
Kill --> [*]: Exit code 0/1/2/3
LSPExit --> [*]: Exit code 0
Feature Comparison
| Capability |
Claude Code built-in LSP |
gopher-bridge |
mcp-language-server |
| Position-based navigation |
✅ |
✅ |
✅ |
| Symbol-name lookups |
❌ |
✅ |
✅ |
| goToImplementation |
✅ |
✅ |
❌ |
| Call hierarchy |
✅ |
✅ |
❌ |
Source extraction via go/parser |
❌ |
✅ |
❌ |
| Multi-language support |
✅ |
❌ |
✅ |
| Works outside Claude Code |
❌ |
✅ |
✅ |
| Works in subagent mode |
❌* |
✅ |
✅ |
* Claude Code's LSP tool is a deferred tool not available to subagents (as of v2.1.69). See .docs/DESIGN.md for details.
Development
make build # Build binary
make install # Install to $GOPATH/bin
make test # Run unit tests with race detector
make test-integration # Integration tests (requires gopls)
make test-all # Unit + integration tests
make coverage # Generate coverage report
make check # vet + lint + tests
make deps # Tidy modules + verify gopls
make clean # Remove build artifacts
CLI flags
All configuration is via CLI flags.
| Flag |
Type |
Default |
Valid Range |
Description |
--workspace |
string |
(required) |
- |
Path to Go project workspace |
--log-level |
string |
info |
debug, info, warn, error |
Log level. Logs go to stderr as JSON. |
--max-concurrent |
int |
20 |
1-100 |
Max concurrent tool calls |
--tool-timeout |
duration |
30s |
5s-5m |
Timeout per tool call |
--diag-poll-timeout |
duration |
3s |
1s-60s |
Max wait for diagnostics |
--context-lines |
int |
3 |
0-20 |
Context lines around references |
--max-extract-lines |
int |
200 |
50-1000 |
Max source lines in definition output |
--max-file-size |
int64 |
5242880 (5MB) |
1MB-50MB |
Max file size for parsing (bytes) |
--init-timeout |
duration |
60s |
10s-5m |
gopls initialize timeout |
--gopls-staticcheck |
bool |
false |
- |
Enable gopls staticcheck analysis |
--gopls-hints |
bool |
false |
- |
Enable gopls hint analyzers |
License
MIT