Files
ai-harness/docs/09-integrations.md
T
darman 420f00494f M0: scaffold Cargo workspace, core types, event bus, permission engine, storage actor
Sets up the Cargo workspace (harness-core, harness-tools, harness-providers, harness-mcp, harness-lsp, harness-app, harness-tui) and the ten architecture docs under docs/. harness-core gets its foundational types (session/message/part/model ids), an in-process event bus, a table-driven permission evaluate function, and a SQLite-backed storage actor with schema and roundtrip coverage. Every crate compiles empty and a bin stub prints its version.
2026-07-10 16:19:27 +02:00

2.9 KiB

09 — Integrations: MCP, LSP, Commands & Skills

MCP client (harness-mcp)

  • For each configured server (config.mcp): rmcp client over TokioChildProcess transport — spawn, initialize, list_tools.
  • Each MCP tool wraps into McpTool: Tool named {server}_{tool} (sanitized to [a-zA-Z0-9_-], 64-char cap). parameters() passes the server's JSON Schema through untouched. executecall_tool; text content items concatenated, images noted and saved to the session data dir.
  • Permissions: key mcp, pattern {server}_{tool}; bundled default rule { permission: "mcp", pattern: "*", action: "ask" }.
  • Failure handling: a server that fails to start is marked failed with a ServerNotice — other tools unaffected; restart attempted on next use after a crash.
  • Out of scope for v1: MCP resources, prompts, sampling; non-stdio transports (HTTP/SSE later).

LSP diagnostics (harness-lsp)

Implements a seam trait defined in core, so harness-tools never links this crate:

// in harness-core
pub trait DiagnosticsSource: Send + Sync {
    async fn touch(&self, path: &Path);                            // spawn-if-needed + didOpen/didChange
    async fn diagnostics(&self, path: &Path, wait: Duration) -> Vec<Diagnostic>;
}
  • LspPool: extension → server config. Built-ins (spawned only if the binary exists on PATH, all config-overridable): rust-analyzer (.rs), typescript-language-server (.ts/.tsx/.js), gopls (.go), pyright/basedpyright (.py).
  • Client = hand-rolled JSON-RPC over child stdio (Content-Length framing, ~150 lines: request map id → oneshot, notification broadcast) using lsp-types for the payloads. Only ~6 methods needed: initialize, initialized, didOpen, didChange, publishDiagnostics, optionally textDocument/diagnostic.
  • Edit/write tools call touch(path) then diagnostics(path, 1500ms) — wait for the first publishDiagnostics after the change version, or time out. Error-severity items are appended to the tool output: LSP errors detected in this file, please fix:\n{file}: L{line}: {message}; the full set goes into part metadata for the TUI.
  • All failures are silent to the model (log only) — diagnostics are best-effort.

Commands & skills

  • Commands (command/*.md, see 06-config.md): a pure input-layer concern — /name args expands the template into the user message, optionally switching agent/model for that run.
  • Skills (skill/<name>/SKILL.md): the system prompt lists name + description of each available skill; the model loads a skill's body on demand with the built-in skill tool. Per-agent skill filtering via the agent's tools/permission config.

Child-process hygiene

MCP servers, LSP servers, and bash all spawn children. A single ChildRegistry tracks them; process-group kills + Drop guards ensure cleanup on exit or panic (flagged risk: zombie children).