Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion skills/mcp_tools.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ The daslang MCP server (`utils/mcp/main.das`) exposes compiler diagnostics, prog

**Configuration.** Configure `.mcp.json` with `"command"` pointing at the daslang binary (`bin/daslang` on Windows MSVC, `build/daslang` on Linux/macOS, `bin/daslang` for the installed SDK), `"args": ["utils/mcp/main.das"]`. See `utils/mcp/README.md` for details and Claude Code permissions.

**Fresh checkouts / worktrees.** `.mcp.json`, `sgconfig.yml`, `bin/`, and the tree-sitter grammar lib are all gitignored, so a new `git worktree add` (or clone) has no daslang MCP at all. Bootstrap it with `daslang utils/mcp/setup.das -- --root <worktree>` - it builds a worktree-local binary (+ grammar), copies the platform `sgconfig.yml`, and merges a `daslang` entry into `.mcp.json` (adds no new secrets; existing servers, including any secret env blocks, are preserved as-is). `--no-build` skips the build. Restart the session to pick it up.
**Fresh checkouts / worktrees.** `.mcp.json`, `sgconfig.yml`, `bin/`, and the tree-sitter grammar lib are all gitignored, so a new `git worktree add` (or clone) has no daslang MCP at all. Bootstrap it with `daslang utils/mcp/setup.das -- --root <worktree>` - it configures `build/` on the cmake generator of the tree running the setup (platform default when that tree has no `build/CMakeCache.txt`), builds a worktree-local binary (+ grammar), copies the platform `sgconfig.yml`, and merges a `daslang` entry into `.mcp.json` (adds no new secrets; existing servers, including any secret env blocks, are preserved as-is). `--no-build` skips the build. Restart the session to pick it up.

**`"defer_loading": false` (repo-only).** The repo's `.mcp.json` sets this on the `daslang` server entry so tool schemas load at session start instead of being deferred (deferred = caller has to `ToolSearch select:<tool>` before each first call). When the harness honors the flag, this removes the per-call ToolSearch friction. When it doesn't, the flag is harmless and tools fall back to the deferred path; CLAUDE.md's "MCP-first search" rule documents that workflow.

Expand Down
26 changes: 24 additions & 2 deletions utils/mcp/setup.das
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ options gen2

require daslib/clargs
require daslib/fio
require daslib/strings_boost
require strings
require jobque

// daslang MCP worktree bootstrap.
//
Expand Down Expand Up @@ -72,11 +75,30 @@ def shell_unsafe(s : string) : bool {
// flag only takes effect on the INITIAL configure — a build/ that already has a
// CMakeCache keeps its cached OPENSSL_ROOT_DIR (wipe build/ to change it). This
// tool targets fresh worktrees, so that's the common case.
//! The cmake generator of the tree running this setup (`build/CMakeCache.txt` under
//! `get_das_root()`), or "" when that tree has no configured build. A worktree configured
//! with the platform default lands on Unix Makefiles, whose `cmake --build --parallel`
//! is unbounded `make -j`; matching the source tree keeps a bootstrapped worktree on the
//! generator the box already builds with.
def source_tree_generator : string {
let cache = path_join(get_das_root(), path_join("build", "CMakeCache.txt"))
if (!fexist(cache)) return ""
let key = "CMAKE_GENERATOR:INTERNAL="
for (line in fread(cache) |> split("\n")) {
if (starts_with(line, key)) return strip(slice(line, length(key), length(line)))
}
return ""
}

def build_worktree(root, openssl_dir : string) : bool {
let build_dir = path_join(root, "build")
if (!fexist(path_join(build_dir, "CMakeCache.txt"))) {
print("Configuring CMake in {build_dir} ...\n")
var cfg_cmd = "cmake -S \"{root}\" -B \"{build_dir}\" -DCMAKE_BUILD_TYPE=Release"
let gen = source_tree_generator()
if (!empty(gen) && !shell_unsafe(gen)) {
cfg_cmd += " -G \"{gen}\""
}
print("Configuring CMake in {build_dir} (generator: {empty(gen) ? "platform default" : gen}) ...\n")
Comment thread
borisbat marked this conversation as resolved.
if (!empty(openssl_dir)) {
cfg_cmd += " -DOPENSSL_ROOT_DIR=\"{to_generic_path(openssl_dir)}\""
}
Expand All @@ -87,7 +109,7 @@ def build_worktree(root, openssl_dir : string) : bool {
}
}
print("Building daslang (this can take a while) ...\n")
let rc = run_visible("cmake --build \"{build_dir}\" --target daslang --config Release")
let rc = run_visible("cmake --build \"{build_dir}\" --target daslang --config Release --parallel {get_total_hw_threads()}")
if (rc != 0) {
print("ERROR: building daslang failed (exit {rc})\n")
return false
Expand Down
Loading