Add built-in MCP server (dexter mcp) - #84
Open
shanehull wants to merge 1 commit into
Open
Conversation
Expose the index to AI agents over the Model Context Protocol, modeled on gopls mcp. Nine tools, addressed by module/function name rather than file positions because Elixir modules are not tied to files: - dexter_workspace, dexter_search, dexter_definition, dexter_references, dexter_module_api, dexter_file_outline, dexter_implementations, dexter_call_hierarchy, dexter_reindex Transports: stdio (dexter mcp), streamable HTTP (dexter mcp --listen), and attached mode on a running LSP session (dexter lsp --mcp-listen) sharing open buffers and caches. dexter mcp --instructions prints an agent-facing usage guide. Reuses the LSP server internals: reindexing via the extracted Server.ReindexWorkspace (backgroundReindex body, now also callable blocking), reference collection via Server.CollectReferences, and doc extraction via the tokenizer. No index schema or parser changes. Uses the official github.com/modelcontextprotocol/go-sdk.
This was referenced Aug 20, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
First of two stacked PRs; the follow-up, #85, is based on this branch and adds
dexter_rename_symbol.What
A built-in MCP server, modeled on gopls mcp, so AI agents can navigate Elixir codebases through dexter's index instead of grep:
Nine tools, deliberately coarse and agent-oriented rather than 1:1 LSP methods, and addressed by module/function name rather than file+position (Elixir modules are not tied to files, which makes name-based addressing the natural fit for agents):
dexter_workspacedexter_searchdexter_definition@doc/@specand source snippet; follows defdelegate chainsdexter_referencesdexter_module_apidexter_file_outlinedexter_implementationsdexter_call_hierarchydexter_reindexTransports: stdio (
dexter mcp), streamable HTTP (--listen), and attached mode on a running LSP (dexter lsp --mcp-listen=ADDR) sharing the live session's open buffers and caches.dexter mcp --instructionsprints an agent-facing guide covering Elixir-specific behavior (modules vs files, defdelegate following, use-chain injection, behaviours vs protocols).Uses the official
github.com/modelcontextprotocol/go-sdk(v1.6.1, stable), the same SDK gopls uses. Tool input schemas are inferred from Go param structs.Why a built-in MCP server rather than an LSP bridge?
Agent frontends can already drive
dexter lspthrough a generic LSP bridge (Claude Code's LSP tool, for example), so the real question is what built-in tools add over bridging.A bridge inherits LSP's request shapes. Apart from workspace symbol search, every operation is position-based: the agent must find the file, locate the exact line and column, make the call, then open each returned location. Every step is a round trip, and a wrong position silently returns nothing. A bridge also cannot expose anything the protocol does not define.
Built-in tools have neither limit:
dexter_definition {module: MyApp.Accounts, function: fetch_user}answers directly.dexter_module_apisummarizes a whole module in one call; references include source lines, so no second pass.Editors keep the LSP; both share the same index.
Review guide
Everything is new leaf code except small, mechanical touches to existing files:
internal/mcp/(new): one file per tool, gopls-style. Tools call the store's existing name-based queries and the exported LSP surface below.internal/lsp/api.go(new):Serve(now takes a constructed*Server, so the same instance can back both LSP and MCP),CollectReferences(the References handler's collection logic, name-based), and stdlib accessors.cmd/main.go: adds themcpcommand and--mcp-listen; extractscmdLSP's open-with-recovery loop intoopenStoreForServerso both servers share it.init/reindex/lookup/referencesare untouched.internal/lsp/server.go:backgroundReindex's body becamereindexWorkspacewith a blocking exportedReindexWorkspace(git diff -wshows the move; the body is unchanged),Servemoved toapi.gowith the*Serverparameter, andreadFileText/getFileLine/watchGitHeadare exported by rename.internal/store: two additive read-only queries (Stats,ListModuleCallbacks).No index schema or parser changes, so
IndexVersionstays at 12.Testing
go test ./...,-race, andgolangci-lintall green.