Skip to content

feat: MCP project config, multi-editor install, cache scaling#78

Merged
jamestexas merged 15 commits intomainfrom
feat/mcp-project-config
Mar 11, 2026
Merged

feat: MCP project config, multi-editor install, cache scaling#78
jamestexas merged 15 commits intomainfrom
feat/mcp-project-config

Conversation

@jamestexas
Copy link
Copy Markdown
Contributor

Summary

  • mache init β€” generates .mache.json, .claude/mcp.json, and .claude/CLAUDE.md for per-project MCP setup. Auto-detects project type (Go, Python, SQL) from file extensions.
  • mache init --global β€” registers mache as an MCP server with all detected editors: Claude Code (via CLI), Cursor, Windsurf, VS Code, Zed, Gemini CLI. Only writes config if the editor's directory exists. Preserves existing entries via JSON merge.
  • mache serve zero-arg mode β€” reads .mache.json from CWD, resolves schema via bundled presets (go:embed), serves without explicit args.
  • api.SchemaVersion const β€” replaces magic "v1" string.
  • MemoryStore cache scaling β€” FIFO content cache was hardcoded at 1024 entries. Now scales to 25% of node count, clamped to [1024, 16384]. Fixes a ceiling that would bottleneck large monorepos (100K+ constructs).

New files

File Purpose
cmd/config.go Project config types, schema resolution, editor detection/registration, CLAUDE.md generation
cmd/config_test.go 29 tests covering config, schema, detection, registration, merge semantics
cmd/init.go mache init command (project + global modes)
cmd/init_test.go 8 tests covering init flows
cmd/schemas.go go:embed bundled preset schemas + PresetNames()
cmd/schemas/*.json 6 preset schemas (go, python, sql, cli, mcp, mcp-registry)

Editor registration details

Editor Config path Server key Notes
Claude Code via claude mcp add --scope user β€” CLI-based
Cursor ~/.cursor/mcp.json mcpServers
Windsurf ~/.codeium/windsurf/mcp_config.json mcpServers
VS Code platform-specific mcp.json servers entry needs "type":"stdio"
Zed ~/.config/zed/settings.json context_servers entry needs "source":"custom"
Gemini CLI ~/.gemini/settings.json mcpServers

Test plan

  • All existing tests pass (task test)
  • New config/init tests pass (37 tests)
  • Cache scaling test validates floor/ceiling/proportional behavior
  • Lint clean (task lint β€” 0 issues)
  • Build succeeds (task build)
  • Manual: mache init in a Go project creates correct .mache.json + .claude/mcp.json + .claude/CLAUDE.md
  • Manual: mache init --global registers with installed editors
  • Manual: mache serve (zero args) works in a project with .mache.json

Add convention-based project configuration so mache can be installed
as an MCP server once and automatically know what to serve per-project.

- `mache init` auto-detects project type, generates .mache.json and
  .claude/mcp.json
- `mache serve` (zero args) reads .mache.json from CWD
- Bundled preset schemas (go, python, sql, cli, mcp, mcp-registry)
  via go:embed
- Schema resolution: preset name, relative path, or absolute path
- .claude/mcp.json merge preserves existing MCP server entries
- Add api.SchemaVersion const for "v1"
- `mache init` now generates .claude/CLAUDE.md describing mache MCP
  tools, workflow, and schema preset β€” Claude Code reads this
  automatically
- `mache init --global` installs mache MCP server to ~/.claude/mcp.json
  for user-wide availability across all Claude Code sessions
- CLAUDE.md appends to existing content, skips if mache section exists
Registers mache as an MCP server with all detected editors:
- Claude Code (via CLI: claude mcp add --scope user)
- Cursor (~/.cursor/mcp.json)
- Windsurf (~/.codeium/windsurf/mcp_config.json)
- VS Code (platform-specific mcp.json)
- Zed (~/.config/zed/settings.json, context_servers key)
- Gemini CLI (~/.gemini/settings.json)

Each editor has its own config format (mcpServers vs servers vs
context_servers) and entry shape. Registration only writes if the
editor's config directory exists (i.e. editor is installed).
Existing config entries are preserved via JSON merge.
The FIFO content cache was hardcoded at 1024 entries, which becomes a
bottleneck for large monorepos (100K+ constructs). Cache now scales to
25% of node count with floor=1024 and ceiling=16384.

SQLiteGraph/WritableGraph keep their 2048 ceiling since they resolve
content on-demand from SQLite (cache is just for hot files).
1. writeClaudeMCPConfig now uses map[string]any as root type to
   preserve unknown top-level keys during JSON round-trip.

2. PresetNames() actually sorts the output (sort.Strings).

3. registerClaudeCodeCLI extracted into mockable var to prevent
   real `claude mcp add` side effects in tests.

4. detectProjectType checks sentinel files (go.mod, pyproject.toml,
   requirements.txt, setup.py, Cargo.toml) before extension counting,
   so projects with code in subdirectories are detected correctly.

5. runServe logs a warning when Sources[1:] are silently ignored.

6. registerEditorMCP returns (ok, warning) β€” shared config files
   (Zed, Gemini CLI) that fail JSON parse return a warning about
   JSONC comments instead of silently skipping. SharedConfig flag
   replaces name-based checks.

7. resolveSchema and resolveDataSource enforce path containment
   for relative paths to prevent traversal from untrusted .mache.json.
   Absolute paths bypass the check (explicit user intent).

8. init tests refactored to use execInit(w, cmd, initOpts{...})
   instead of mutating package-level flag vars. Safe for t.Parallel().
…tie-breaking)

1. leyline defsMap: changed from map[string]string to map[string][]string
   to handle tokens defined by multiple constructs (e.g. Init in different packages)
2. deleteFileNodes: clean stale refs and defs maps when nodes are removed,
   preventing phantom callers/callees after live re-ingestion
3. detectProjectType: deterministic alphabetical tie-breaking when two
   languages have equal file counts
Add plugin/ directory for distribution as a Claude Code plugin:
- .claude-plugin/plugin.json manifest
- .mcp.json auto-starts mache serve as MCP server
- agents/mache-explorer.md (MCP-tools-first exploration agent)
- skills/mache-explore/SKILL.md (FUSE mount fallback)

Add hybrid auto-detect to mache serve (no .mache.json required):
- detectProjectLanguages() walks repo to find ALL languages
- Languages with presets (go, python, sql) use embedded schemas
- Remaining languages (ts, js, tf, hcl, yaml, rs) get FCA inference
- Single-language projects skip namespace wrapping
- Multi-language produces unified topology with language namespaces

This enables the plugin to auto-configure for any codebase:
Go-only projects use the hand-tuned preset, monorepos get hybrid
preset+inference, and .mache.json remains the explicit override.
Address agent feedback from MCP testing:
- find_definition: exposes defs map (symbol β†’ construct dir) as MCP tool
  with exact match, case-insensitive fallback, and fuzzy suggestions
- get_overview: aggregate first-contact orientation tool returning
  top-level dirs, node counts, ref/def token stats
- get_communities summary mode: new summary=true param returns compact
  output (community sizes + top 5 members) instead of full member lists
  that blew up at 103K chars on real codebases

Adds DefsMap() to both MemoryStore and SQLiteGraph, gated behind
defsMapProvider interface (mirrors existing refsMapProvider pattern).
Updates mache-explorer agent docs with new tools and workflows.
The MCP server was failing health checks because schema auto-detection,
tree-sitter parsing, FCA inference, and graph building all happened
before the server started listening on stdio.

Introduces lazyGraph wrapper that implements Graph + all provider
interfaces (refsQuerier, refsMapProvider, defsMapProvider). The MCP
server now starts immediately and responds to initialize/tools/list
without delay. Graph construction is deferred to the first actual
tool call via sync.Once.
…al dirs

- list_directory: surface callers/ and callees/ virtual dirs on construct nodes
- search: add optional 'type' param to filter by construct type in path
- read_file: add 'paths' param for batch reads (JSON array), reduces round-trips
- task install: build + codesign + copy to ~/.local/bin (fixes macOS SIGKILL)
- search: add 'role' param β€” 'definition' searches defs map, 'reference'
  (default) searches mache_refs. Lets agents distinguish where a symbol
  is declared vs where it's used.
- find_callees: return structured hints when empty (unexported methods,
  wrong path type) instead of bare [].
- mache-explorer agent: document batch read_file, role/type filters,
  find_definition as primary lookup tool.
…ummaries

Dogfooding the MCP self-hosting revealed three issues:

1. search with role=definition returned duplicate results when the same
   construct path was indexed under multiple token variants (e.g.
   "GetCallers" and "graph.MemoryStore.GetCallers"). Dedup by path.

2. list_directory on large packages (e.g. go/graph/functions with 120+
   entries) was dominated by Test*/Benchmark* noise. Add exclude_tests
   boolean param to filter them out.

3. get_communities summary top_members included "/source" suffix on every
   entry β€” pure noise for the consumer. Strip it.

Also fixes TestFindCallees_EmptyWithoutExtractor which expected "[]" but
the handler now returns structured JSON with hints.
- read_file now returns SourceOrigin (file, start_byte, end_byte) so
  consumers know exactly where each construct lives in the real filesystem
- write_file wires the full splice pipeline: validate (tree-sitter) β†’
  format (gofumpt/hclwrite) β†’ atomic splice β†’ shift origins β†’ update graph
- writeBacker interface + lazyGraph delegation for write-back capability
- JSON struct tags on SourceOrigin for clean serialization
@jamestexas jamestexas merged commit 683086a into main Mar 11, 2026
13 checks passed
@jamestexas jamestexas deleted the feat/mcp-project-config branch March 11, 2026 23:56
jamestexas added a commit that referenced this pull request Mar 12, 2026
- README: update feature matrix, tool table, and landscape for 9 MCP
  tools (find_definition, get_overview, write_file added in PR #78)
- ARCHITECTURE: update MCP server description and key file reference
- PRIOR_ART: add codebase-memory-mcp (DeusData) detailed comparison β€”
  inspiration source for communities, overview, and definition tools
jamestexas added a commit that referenced this pull request Mar 12, 2026
- README: update feature matrix, tool table, and landscape for 9 MCP
  tools (find_definition, get_overview, write_file added in PR #78)
- ARCHITECTURE: update MCP server description and key file reference
- PRIOR_ART: add codebase-memory-mcp (DeusData) detailed comparison β€”
  inspiration source for communities, overview, and definition tools
jamestexas added a commit that referenced this pull request Mar 12, 2026
#80)

* docs: update MCP tool count to 9, add codebase-memory-mcp to PRIOR_ART

- README: update feature matrix, tool table, and landscape for 9 MCP
  tools (find_definition, get_overview, write_file added in PR #78)
- ARCHITECTURE: update MCP server description and key file reference
- PRIOR_ART: add codebase-memory-mcp (DeusData) detailed comparison β€”
  inspiration source for communities, overview, and definition tools

* feat: consume leyline LSP tables for hover, diagnostics, and MCP tools

Materializer (`materializeVirtuals`):
- New `materializeLSP()` reads `_lsp_hover` and `_lsp` tables produced
  by `leyline lsp` and creates `{construct}/hover` and
  `{construct}/diagnostics` file nodes in the db.
- `extractCallerDir` updated to recognize `hover` and `diagnostics` as
  leaf names.

MCP server (`registerMCPTools`):
- `get_type_info` tool: queries `_lsp_hover` for type signatures and
  documentation. Agents can ask "what type does X return?" without
  parsing source.
- `get_diagnostics` tool: queries `_lsp` for LSP diagnostics (errors,
  warnings). Agents can ask "what's wrong?" without running a linter.

Both tools gracefully degrade β€” if no LSP tables exist, they return a
helpful error pointing to `leyline lsp`.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore: add TODO for schema-driven LSP file materialization

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant