Add wave three specs: stdio MCP, web search, repo tabs

Three independent specs for the next siGit Code wave: the stdio MCP transport that unlocks the published server ecosystem, web search routed through sigit.si as a signed-in cloud feature with a provider adapter, and Issues and Pull requests tabs in the terminal for repos hosted on sigit.si, consuming the MCP repo workflow tools. The repo tab spec stacks on the unmerged TUI tabs branch and rebases once that merges, per the stacking rule.

Seto Elkahfi committed Jul 5, 2026 at 08:59 UTC e0797e716b2efd631bbc107ba80a72dd5a5b09d9
1 file changed +137
docs/product/sigit-code-wave-three.md
+137
new file mode 100644 index 0000000..acccb42 --- /dev/null +++ b/docs/product/sigit-code-wave-three.md @@ -0,0 +1,137 @@ +# siGit Code wave three: stdio MCP, web search, and the repo tabs + +Status: draft v1 (2026-07-05). Owner: product/eng. Audience: internal (private repo). +Scope: the third feature wave for **siGit Code**, following +[sigit-code-parity-roadmap.md](sigit-code-parity-roadmap.md) (wave one, shipped +in v1.3.2) and [sigit-code-copilot-cli-parity.md](sigit-code-copilot-cli-parity.md) +(wave two, in review). One ecosystem unlock, one core capability with a product +hook, one differentiator. The three are independent and run in parallel; spec 3 +stacks on the unmerged TUI tabs branch and rebases once that merges. + +--- + +## 1. Spec: stdio MCP transport + +**Branch:** `feature/mcp-stdio-transport` (sigit) · **Touches:** `src/mcp.rs` + +### Problem + +Nearly every published MCP server (filesystem, Playwright, Postgres, GitHub's +own) is stdio-first. siGit Code speaks only Streamable HTTP, so users cannot +plug in most of the MCP ecosystem. Claude Code and Copilot CLI both support +stdio. + +### Design + +- `mcp.toml` server entries gain the stdio shape: `command` (required), + `args = [...]`, `[server.env]`, all mutually exclusive with `url`. Existing + HTTP entries keep working unchanged. +- A stdio server is spawned at discovery (`mcp::init`): child process with + piped stdin/stdout, stderr inherited to the log. JSON-RPC frames are + newline-delimited per the MCP stdio transport spec. The same + `initialize`/`tools/list` handshake and `tools/call` forwarding as HTTP; + the transport is an enum behind the existing server cache. +- Lifecycle: the child lives for the sigit process; a dead child fails calls + with a clear in-band error and is not restarted mid-session (restart on + `/reload`). Discovery timeout applies to the handshake like HTTP. All + children are killed on exit. +- Same namespacing (`mcp__<server>__<tool>`), same output caps, same `/mcp` + listing (show the command instead of the URL). +- Cross-platform: plain std/tokio process handling, no cfg(unix). + +### Acceptance + +- A `[[server]]` entry with `command = "npx"`, `args = ["-y", "@modelcontextprotocol/server-everything"]` + (or a local stub) discovers tools and serves calls end to end. +- Unit/integration tests use a tiny scripted stdio MCP server (a shell or + Rust stub speaking the handshake) rather than a real npm package; CI stays + hermetic. A dead-child call returns the in-band error. + +--- + +## 2. Spec: web search through sigit.si + +**Branch:** `feature/mcp-web-search` (sigit-si) · **Touches:** the MCP server, a new search proxy service + +### Problem + +The agent can fetch a page (`read_website`) but cannot find one. Both +competitors ship search. Routing it through sigit.si instead of baking a +provider key into the client makes search a signed-in cloud feature, keeps one +place to swap providers, and adds a concrete reason to `sigit login`. + +### Design + +- New MCP tool on the official server: `web_search {query, count?}` returning + a compact JSON list of `{title, url, snippet}` (count default 5, max 10). +- Behind it, a `WebSearchService` with a provider adapter. First provider: + Brave Search API (`SEARCH_PROVIDER=brave`, `BRAVE_SEARCH_API_KEY`), chosen + for its simple REST shape; the adapter boundary keeps Bing/SearXNG swappable. + Unconfigured provider returns an in-band ToolError telling the operator what + to set, never a 500. +- Rate limit per user (reuse the existing rate-limit pattern if one exists; + otherwise a simple per-user counter, e.g. 60 searches/hour) so a runaway + agent cannot burn the provider quota. +- Auth and result envelope follow the existing MCP tools exactly. Update + `.agents/specs/mcp-server.md`. +- Client side: nothing structural (MCP plumbing exists). Read-only + classification of official-server tools ships with spec 3. + +### Acceptance + +- Request specs: happy path (provider stubbed with WebMock or the repo's + HTTP-stubbing convention), unconfigured provider, rate limit, param + validation. No live provider calls in CI. + +--- + +## 3. Spec: Issues and Pull requests in the terminal + +**Branch:** `feature/tui-repo-tabs` (sigit, stacked on `feature/tui-tabs`) · +**Touches:** `src/chat.rs`, `src/permissions.rs`, `src/main.rs` (prompt) + +### Problem + +Copilot CLI shows Issues and Pull requests tabs when run inside a GitHub repo. +sigit.si is our own git host, the MCP repo workflow tools exist server-side +(sigit-si #3), and siGit Code should be the best terminal client sigit.si has. + +### Design + +- When the session cwd's `origin` remote points at the sigit.si host (parse + `git remote get-url origin`, compare against the `SIGIT_API_URL` host, + default sigit.si), the TUI adds a **Repo** tab after History: two sections, + Issues and Pull requests, fetched through the official MCP server + (`mcp__sigit__list_issues` / `mcp__sigit__list_pull_requests`, repo derived + from the remote's `owner/name`). Up/Down selects, Enter opens the detail + (`get_issue` / `get_pull_request`) in a scrollable view, `r` refreshes, + section toggle on `i`/`p` (or Left/Right). +- Fetches run as spawned tasks feeding the render loop (the Cloud tab + pattern); the tab degrades gracefully when signed out, MCP is off, or the + remote is not sigit.si (tab hidden entirely in that last case). +- Permission classification: the official server's read-only tools + (`list_*`, `get_*`, `search_code`, `get_file_contents`, `web_search`) are + classified read-only in `permissions.rs` so browsing never prompts; + everything else `mcp__sigit__*` stays mutating. Match on the official + server's namespace prefix plus tool-name prefix, not a hardcoded full list, + so new server-side read tools inherit it. +- Prompt guidance in `main.rs`: issue and PR workflows on sigit.si repos go + through the `mcp__sigit__*` tools; reference them by exact name. +- Stacking: branch from `feature/tui-tabs`. After sigit #25 merges, rebase + onto `development` before opening the PR so it shows only its own commits + (the repo's stacking rule). + +### Acceptance + +- In a repo cloned from sigit.si while signed in, the Repo tab lists real + issues and PRs and opens details; signed out it shows the sign-in hint. +- Unit tests for the remote-URL parsing (ssh and https forms, non-sigit hosts) + and the read-only classification; TUI flows verified under tmux against a + scripted MCP server. + +--- + +## 4. After this wave + +Hooks, a `/context` usage display, memory recall over `remember`, then the two +big strategic items: sandboxing (Cloud Agent trust) and checkpointing/rewind.