feat(mcp): capture relay tool — MCP door for non-library harnesses (#55)
Adds the `capture` MCP tool: the #55 relay for harnesses that cannot run the use-case in-process (claude.ai Chat/Cowork/Design, Crush, Pi, LLM Council). They reach it through the existing /mcp OAuth connector. - Thin: forwards to the SAME CaptureService as POST /capture; holds no state and retains nothing beyond the I5 audit record. The containment properties accepted in infra security-baseline (I2 ledger) hold by construction. - Per-principal: ServeHTTP re-derives the caller's principal from the Bearer header (the chassis middleware gates but discards it) and stashes it in context; the tool resolves the trust-zone origin from it. A caller-asserted harness/origin in the body is ignored — origin is server-derived, so the I1 confidential refusal still fires for us-nexus callers (claude.ai), and sovereign-allowlisted JWT principals pass. - Registered only when WithCapture is wired (all three sites: tools(), handleCall, package doc); main wires REST + MCP from the same service, resolver, and credentials. Tests: listed-only-when-wired, forwards-via-static-principal, confidential-via-us-nexus-refused, confidential-via-sovereign-allowed, unauthenticated-rejected, caller-cannot-forge-origin. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -38,7 +38,7 @@ func (s *Server) tools() []map[string]any {
|
||||
return b
|
||||
}
|
||||
|
||||
return []map[string]any{
|
||||
tools := []map[string]any{
|
||||
{
|
||||
"name": "brain_query",
|
||||
"description": "BM25 full-text search across brain/knowledge/ and brain/wiki/ markdown files. Optionally scope by wing (topic domain) and hall (memory type).",
|
||||
@@ -171,6 +171,13 @@ func (s *Server) tools() []map[string]any {
|
||||
}),
|
||||
},
|
||||
}
|
||||
// The capture relay tool (#55) is advertised only when wired via
|
||||
// WithCapture — MCP-native harnesses (claude.ai, Crush, Pi, LLM Council)
|
||||
// reach capture through it.
|
||||
if s.capture != nil {
|
||||
tools = append(tools, captureToolDescriptor())
|
||||
}
|
||||
return tools
|
||||
}
|
||||
|
||||
type brainQueryArgs struct {
|
||||
|
||||
Reference in New Issue
Block a user