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
new
+137
@@ -0,0 +1,137 @@
1
+# siGit Code wave three: stdio MCP, web search, and the repo tabs
2
+
3
+Status: draft v1 (2026-07-05). Owner: product/eng. Audience: internal (private repo).
4
+Scope: the third feature wave for **siGit Code**, following
5
+[sigit-code-parity-roadmap.md](sigit-code-parity-roadmap.md) (wave one, shipped
6
+in v1.3.2) and [sigit-code-copilot-cli-parity.md](sigit-code-copilot-cli-parity.md)
7
+(wave two, in review). One ecosystem unlock, one core capability with a product
8
+hook, one differentiator. The three are independent and run in parallel; spec 3
9
+stacks on the unmerged TUI tabs branch and rebases once that merges.
10
+
11
+---
12
+
13
+## 1. Spec: stdio MCP transport
14
+
15
+**Branch:** `feature/mcp-stdio-transport` (sigit) · **Touches:** `src/mcp.rs`
16
+
17
+### Problem
18
+
19
+Nearly every published MCP server (filesystem, Playwright, Postgres, GitHub's
20
+own) is stdio-first. siGit Code speaks only Streamable HTTP, so users cannot
21
+plug in most of the MCP ecosystem. Claude Code and Copilot CLI both support
22
+stdio.
23
+
24
+### Design
25
+
26
+- `mcp.toml` server entries gain the stdio shape: `command` (required),
27
+ `args = [...]`, `[server.env]`, all mutually exclusive with `url`. Existing
28
+ HTTP entries keep working unchanged.
29
+- A stdio server is spawned at discovery (`mcp::init`): child process with
30
+ piped stdin/stdout, stderr inherited to the log. JSON-RPC frames are
31
+ newline-delimited per the MCP stdio transport spec. The same
32
+ `initialize`/`tools/list` handshake and `tools/call` forwarding as HTTP;
33
+ the transport is an enum behind the existing server cache.
34
+- Lifecycle: the child lives for the sigit process; a dead child fails calls
35
+ with a clear in-band error and is not restarted mid-session (restart on
36
+ `/reload`). Discovery timeout applies to the handshake like HTTP. All
37
+ children are killed on exit.
38
+- Same namespacing (`mcp__<server>__<tool>`), same output caps, same `/mcp`
39
+ listing (show the command instead of the URL).
40
+- Cross-platform: plain std/tokio process handling, no cfg(unix).
41
+
42
+### Acceptance
43
+
44
+- A `[[server]]` entry with `command = "npx"`, `args = ["-y", "@modelcontextprotocol/server-everything"]`
45
+ (or a local stub) discovers tools and serves calls end to end.
46
+- Unit/integration tests use a tiny scripted stdio MCP server (a shell or
47
+ Rust stub speaking the handshake) rather than a real npm package; CI stays
48
+ hermetic. A dead-child call returns the in-band error.
49
+
50
+---
51
+
52
+## 2. Spec: web search through sigit.si
53
+
54
+**Branch:** `feature/mcp-web-search` (sigit-si) · **Touches:** the MCP server, a new search proxy service
55
+
56
+### Problem
57
+
58
+The agent can fetch a page (`read_website`) but cannot find one. Both
59
+competitors ship search. Routing it through sigit.si instead of baking a
60
+provider key into the client makes search a signed-in cloud feature, keeps one
61
+place to swap providers, and adds a concrete reason to `sigit login`.
62
+
63
+### Design
64
+
65
+- New MCP tool on the official server: `web_search {query, count?}` returning
66
+ a compact JSON list of `{title, url, snippet}` (count default 5, max 10).
67
+- Behind it, a `WebSearchService` with a provider adapter. First provider:
68
+ Brave Search API (`SEARCH_PROVIDER=brave`, `BRAVE_SEARCH_API_KEY`), chosen
69
+ for its simple REST shape; the adapter boundary keeps Bing/SearXNG swappable.
70
+ Unconfigured provider returns an in-band ToolError telling the operator what
71
+ to set, never a 500.
72
+- Rate limit per user (reuse the existing rate-limit pattern if one exists;
73
+ otherwise a simple per-user counter, e.g. 60 searches/hour) so a runaway
74
+ agent cannot burn the provider quota.
75
+- Auth and result envelope follow the existing MCP tools exactly. Update
76
+ `.agents/specs/mcp-server.md`.
77
+- Client side: nothing structural (MCP plumbing exists). Read-only
78
+ classification of official-server tools ships with spec 3.
79
+
80
+### Acceptance
81
+
82
+- Request specs: happy path (provider stubbed with WebMock or the repo's
83
+ HTTP-stubbing convention), unconfigured provider, rate limit, param
84
+ validation. No live provider calls in CI.
85
+
86
+---
87
+
88
+## 3. Spec: Issues and Pull requests in the terminal
89
+
90
+**Branch:** `feature/tui-repo-tabs` (sigit, stacked on `feature/tui-tabs`) ·
91
+**Touches:** `src/chat.rs`, `src/permissions.rs`, `src/main.rs` (prompt)
92
+
93
+### Problem
94
+
95
+Copilot CLI shows Issues and Pull requests tabs when run inside a GitHub repo.
96
+sigit.si is our own git host, the MCP repo workflow tools exist server-side
97
+(sigit-si #3), and siGit Code should be the best terminal client sigit.si has.
98
+
99
+### Design
100
+
101
+- When the session cwd's `origin` remote points at the sigit.si host (parse
102
+ `git remote get-url origin`, compare against the `SIGIT_API_URL` host,
103
+ default sigit.si), the TUI adds a **Repo** tab after History: two sections,
104
+ Issues and Pull requests, fetched through the official MCP server
105
+ (`mcp__sigit__list_issues` / `mcp__sigit__list_pull_requests`, repo derived
106
+ from the remote's `owner/name`). Up/Down selects, Enter opens the detail
107
+ (`get_issue` / `get_pull_request`) in a scrollable view, `r` refreshes,
108
+ section toggle on `i`/`p` (or Left/Right).
109
+- Fetches run as spawned tasks feeding the render loop (the Cloud tab
110
+ pattern); the tab degrades gracefully when signed out, MCP is off, or the
111
+ remote is not sigit.si (tab hidden entirely in that last case).
112
+- Permission classification: the official server's read-only tools
113
+ (`list_*`, `get_*`, `search_code`, `get_file_contents`, `web_search`) are
114
+ classified read-only in `permissions.rs` so browsing never prompts;
115
+ everything else `mcp__sigit__*` stays mutating. Match on the official
116
+ server's namespace prefix plus tool-name prefix, not a hardcoded full list,
117
+ so new server-side read tools inherit it.
118
+- Prompt guidance in `main.rs`: issue and PR workflows on sigit.si repos go
119
+ through the `mcp__sigit__*` tools; reference them by exact name.
120
+- Stacking: branch from `feature/tui-tabs`. After sigit #25 merges, rebase
121
+ onto `development` before opening the PR so it shows only its own commits
122
+ (the repo's stacking rule).
123
+
124
+### Acceptance
125
+
126
+- In a repo cloned from sigit.si while signed in, the Repo tab lists real
127
+ issues and PRs and opens details; signed out it shows the sign-in hint.
128
+- Unit tests for the remote-URL parsing (ssh and https forms, non-sigit hosts)
129
+ and the read-only classification; TUI flows verified under tmux against a
130
+ scripted MCP server.
131
+
132
+---
133
+
134
+## 4. After this wave
135
+
136
+Hooks, a `/context` usage display, memory recall over `remember`, then the two
137
+big strategic items: sandboxing (Cloud Agent trust) and checkpointing/rewind.