Examples: workspace mode (local + github-clone-tracker)¶
kglite-mcp-server --workspace <dir> runs the server with a workspace
backing it. Two flavours, picked by the manifest’s workspace.kind
field:
workspace.kind: local— a fixed local source directory, watch mode for auto-rebuild on file changes,set_root_dir(path)to swap between sibling subdirectories without restarting. Best for code-review against a checked-out project tree.No
workspace:block (default github-clone-tracker) — the agent callsrepo_management('org/repo')to clone repos into the workspace; the injected codingest builder produces a code graph for each; queries flow against the active one. Best for exploring open-source codebases on demand.
Both share the same source tools (read_source / grep /
list_source), the same read_code_source qualified-name lookup,
and the same trust gates for extensions.
Copy-pasteable starting points ship in the repo’s examples/:
Local code-review →
examples/local_code_review_mcp.yamlGitHub-clone tracker →
examples/open_source_workspace_mcp.yaml
After copying one, run kglite-mcp-server --selftest --mcp-config <your.yaml>
to confirm it stands up correctly (see the guide’s
Verify your setup).
Variant 1 — workspace.kind: local + watch¶
Bind a local source directory as the active source root for source
tools (read_source / grep / list_source), build a code
graph over it, and auto-rebuild on file changes. The agent can swap
between sibling project directories with set_root_dir(path)
without restarting the server.
Manifest¶
# code_review_mcp.yaml — under /Volumes/EksternalHome/Koding/
name: Code Review
instructions: |
Code review against any project under Koding/. The active root
starts at the directory below; swap with set_root_dir(path).
workspace:
kind: local
root: /Volumes/EksternalHome/Koding # the sandbox boundary
watch: true # auto-rebuild on file changes
What gets registered¶
tools/list returns:
- cypher_query
- graph_overview
- read_code_source
- ping
- read_source / grep / list_source
- repo_management # local-mode also gets this for rebuild dispatch
- set_root_dir # local-mode only
- github_issues / github_api # if GITHUB_TOKEN is in env
The flow¶
Boot: the server canonicalises
/Volumes/.../Koding/and binds it as the active root.read_source/grep/list_sourcesandbox to it.The watcher starts on the root with a 500 ms debounce.
First agent action:
cypher_queryagainst the auto-built code graph (modules, functions, calls, imports).Agent narrows interest to a specific file → calls
read_source.Agent decides to switch to a different project under Koding/:
set_root_dir("/Volumes/EksternalHome/Koding/Rust/KGLite"). The active root atomically swaps; source tools rebind; the watch handle moves to the new root.On any file change inside the new root, the watcher fires (after the 500 ms debounce window), the code graph rebuilds on a background thread, and the new graph atomically swaps in. Queries against the previous graph keep working until the swap.
Sandbox boundary¶
workspace.root is the manifest-declared root. The sandbox check on
set_root_dir(path) validates against this immutable boundary, not
the current active root. After set_root_dir(/.../Rust/KGLite),
a subsequent set_root_dir(/.../MCP servers) works because both
paths are under workspace.root:
{"name":"set_root_dir","arguments":{"path":"/Volumes/EksternalHome/Koding/Rust/KGLite"}}
→ "Active root set to /Volumes/EksternalHome/Koding/Rust/KGLite." ✓
{"name":"set_root_dir","arguments":{"path":"/Volumes/EksternalHome/Koding/MCP servers"}}
→ "Active root set to /Volumes/EksternalHome/Koding/MCP servers." ✓ (sibling swap, no restart)
{"name":"set_root_dir","arguments":{"path":"/tmp"}}
→ "Error: path '/tmp' escapes the workspace root." ✓ (outside the sandbox)
repo_management in local mode¶
In local-workspace mode repo_management does not accept a repo
name (there’s nothing to clone). It accepts:
{"update": true} — re-fingerprint + rebuild
{"update": true, "force_rebuild": true} — rebuild regardless of fingerprint
force_rebuild: true bypasses the SHA gating that’s otherwise on
top of the post-activate hook — useful after upgrading kglite
itself or after a builder change.
github_issues integration¶
If the project under the active root has a .git/config with a
GitHub remote, github_issues auto-resolves the repo_name
argument from the active root’s git config. Agents can call
{"name": "github_issues", "arguments": {"limit": 5, "state": "all"}}
without supplying repo_name; the active workspace repo is used as
the fallback. The token still has to be in env / walked-up .env.
Performance notes¶
Code-tree rebuild is incremental for small files (a single-file edit is fast). Whole-tree rebuilds on large projects (>100k LoC) can take a few seconds — the debounce + background thread keep the agent unblocked during the rebuild.
Atomic swap means agents never see a half-built graph. Queries against the in-flight graph complete; the next query after the swap sees the new graph.
The
.mcp-workspace/directory insideworkspace.rootstores inventory + last-built SHA. Safe to delete — the next boot re-seeds it.
Variant 2 — github-clone-tracker (no workspace: block)¶
Run the server with --workspace <dir> (no workspace.kind: local
in the manifest) and the agent gets repo_management for cloning,
plus the standard source tools against the active clone. A copy-
paste-ready manifest lives at
examples/open_source_workspace_mcp.yaml.
Deployment¶
mkdir /path/to/my-workspace/
cp examples/open_source_workspace_mcp.yaml /path/to/my-workspace/workspace_mcp.yaml
kglite-mcp-server --workspace /path/to/my-workspace/
The filename inside the workspace dir MUST be workspace_mcp.yaml —
that’s the name the CLI auto-detects when given --workspace <dir>.
What the manifest enables¶
Looking at the example file inline:
name: Open Source Explorer
env_file: ../.env # walks up to find GITHUB_TOKEN for github_*
builtins:
temp_cleanup: on_overview
extensions:
csv_http_server: true # FORMAT CSV → localhost URL (CORS-enabled)
instructions: |
Code intelligence for open-source GitHub repositories ...
FIRST STEP: call repo_management('org/repo') to clone + build ...
overview_prefix: |
## Two read paths
... (sticky context shown on bare graph_overview())
tools:
- bundled: repo_management
description: | # per-tool guidance lives with the tool
Manage cloned repositories. FIRST STEP before any other tool.
Common invocations: ... (full text in the file)
- bundled: cypher_query
description: |
Run a Cypher query against the active repo's knowledge graph.
Append `FORMAT CSV` for a CSV-exported result over localhost ...
- bundled: read_source
description: |
Read a file slice from the active repo. Prefer
read_code_source for graph-indexed symbols ...
- bundled: grep
description: |
.gitignore-aware regex search across the active repo's source.
Reach for cypher first for symbol lookups ...
Key choices:
env_file: ../.env— manifest paths are manifest-relative, so this walks up one level from the workspace dir to find the.env. LoadsGITHUB_TOKENforgithub_issues+github_api. Without a token those tools don’t register at boot.builtins.temp_cleanup: on_overview— wipes the temp/ dir on every baregraph_overview()call. Withcsv_http_serverenabled, everyFORMAT CSVexport writes a file to temp/; without cleanup they accumulate.extensions.csv_http_server: true— enables the localhost listener soFORMAT CSVexports return URLs the agent can fetch (instead of inlining the CSV body, which blows out for large results). Loopback-only, CORS-enabled.instructions:— server-wide first-message orientation. Kept short: the project pitch + the FIRST STEP framing. The detailed per-tool guidance lives on the tools themselves (seetools[].bundled:overrides below). Splitting reduces the one-time-read context the agent has to retain through a long session.overview_prefix:— sticky context prepended to baregraph_overview()output. Skipped for focused drill-downs (graph_overview(types=...)etc.) so it doesn’t bloat every response. Good place for the “two-read-paths” mental model.tools[].bundled:overrides (kglite 0.9.27 / mcp-methods 0.3.31+) — replace the agent-facingdescription:for specific bundled tools. The example overrides four:repo_management— its description carries the “FIRST STEP + five common invocations” guidance that used to live in the globalinstructions:blob. Now it ridestools/listnext to the tool’s schema, so the agent sees the guidance every time it considers which tool to call.cypher_query— description teaches theFORMAT CSV→ localhost URL pattern.read_source— disambiguates againstread_code_source(prefer the latter for symbols the graph already indexed) and pinsfile_pathsemantics to the active repo’s clone path.grep— frames the regex-search workhorse against cypher (cypher first for symbols; grep for plain text). Same principle as the other three: per-tool guidance attached to the tool, not buried in a session-wide blob.
Override
descriptionworks on any of the 12 bundled tools (cypher_query,graph_overview,ping,read_code_source,save_graph,read_source,grep,list_source,repo_management,set_root_dir,github_issues,github_api). Addinghidden: truedrops a tool fromtools/listAND rejects calls — useful for narrowing the agent surface when a bundled tool doesn’t fit your deployment. Unknown tool names fail at boot with the full valid catalogue listed in the error message.
What gets registered¶
For --workspace <dir> mode (no workspace.kind: local):
- cypher_query
- graph_overview
- read_code_source
- ping
- repo_management # github clone tracker
- read_source / grep / list_source # against the active repo
- github_issues / github_api # if GITHUB_TOKEN was loaded
Note: set_root_dir is only in the workspace.kind: local
variant above. repo_management is only in github-workspace
mode. The two modes are mutually exclusive.
Lifecycle¶
First call:
repo_management('pydata/xarray')does a shallowgit clone --depth 1, the injected builder produces the code graph, graph is active for subsequent queries.Subsequent calls:
repo_management('pydata/xarray')again short-circuits to “already cloned, activated.”repo_management(update=True)doesgit fetch --depth 1 origin+ reset to remote; graph rebuilds only if the SHA moved (gated bylast_built_sha).Idle sweep: repos untouched for
--stale-after-days(default 7) get tombstoned ininventory.json. The active repo is exempt. Sweep happens on the nextrepo_managementcall.Force rebuild:
repo_management(update=True, force_rebuild=True)bypasses the SHA gate — useful after a kglite upgrade.