MCP In SecondBrain¶
SecondBrain treats MCP as a governed capability plane rather than a loose collection of server-specific adapters.
The current implementation is aligned to the MCP 2025-11-25 protocol revision.
Purpose¶
- discover approved MCP capabilities
- enforce policy and approval before execution
- compile trusted resources into local context when appropriate
- expose operator tooling for health, scoring, and debugging
Main Commands¶
sb mcp servers
sb mcp discover <server_name>
sb mcp call <server_name> <capability_name>
sb mcp read-resource <server_name> <resource_uri>
sb mcp compile-resource <server_name> <resource_uri>
sb mcp doctor
sb mcp approvals
sb mcp score
sb mcp exposure
sb mcp report
sb mcp marketplace
Use sb mcp --help and subcommand help for the exact live flags and arguments.
Runtime Model¶
The MCP layer in SecondBrain is responsible for:
- loading approved server config
- connecting through the supported transports
- speaking the real MCP initialize / initialized / request lifecycle
- discovering tools, resources, and prompts
- normalizing upstream metadata into stable internal contracts
- enforcing trust and policy before execution
- tracing and scoring MCP usage
Key implementation area:
brain/mcp/brain/serve/routers/mcp.pyfor the local MCP server endpoint
How It Fits Into The System¶
MCP is not the whole tool runtime. It is one governed source of capabilities alongside local tools, integrations, and domain-specific runtime features.
Practical split:
sb mcpis the operator and diagnostics surfacebrain/mcp/is the protocol core plus governed backend- chat/tool exposure layers decide when MCP capabilities are visible to an agent
Local MCP Endpoint¶
sb serve now exposes a real MCP Streamable HTTP endpoint at /mcp.
Initialization is now strict about protocol pinning: clients must request the supported MCP version 2025-11-25, or the server rejects initialize rather than silently coercing the version.
Current server capabilities:
initializenotifications/initializedpinglogging/setLevelcompletion/completeprompts/listprompts/getresources/listresources/readresources/templates/listtools/listtools/call
The initial built-in local context surfaces are:
- tool:
search_local_context - prompt:
summarize_local_context - resources:
secondbrain://context/help,secondbrain://context/status - resource template:
secondbrain://context/search{?query,limit}
The local server also supports completion/complete for prompt and resource-template arguments such as query and limit.
Claude Code Stdio Server¶
SecondBrain also exposes a local stdio MCP server for Claude Code and other project-scoped MCP clients:
The repository-level Claude Code config at .claude/settings.json registers it
as the secondbrain MCP server. It exposes first-class local tools:
sb_asksb_ingestsb_packsb_open_loopssb_decision_extractsb_grounded_answersb_recallsb_meeting_extract
Use sb_ingest only when the user intends to add content to SecondBrain. The
remaining tools are read-oriented retrieval, extraction, or synthesis surfaces.
Streamable HTTP Events¶
The local /mcp endpoint now also supports GET with text/event-stream after initialization.
Current behavior:
- emits an initial primer SSE event for new streams
- keeps the SSE connection open for live notifications
- emits keepalive comments while the stream is idle
- buffers server-to-client MCP notifications per session
- replays buffered notifications after
Last-Event-ID - currently uses
notifications/messagefor session readiness and logging-level updates
The Streamable HTTP client transport now maintains a durable initialized session with a background SSE pump, tracking the latest Last-Event-ID and responding to nested server requests over the same session instead of re-opening a one-shot replay stream around every request.
The stdio client transport now also keeps a real initialized MCP subprocess session alive across operations on the same transport instance, with a background reader handling notifications and nested server requests.
Stdio Command Safety¶
Stdio MCP servers are process launches, so SecondBrain validates configured commands before a subprocess is started:
commandmust be a single executable token; put all arguments inargs- list-valued
commandconfig is rejected; model or user supplied command arrays cannot be split into executable + args at runtime - shell-shaped commands such as
bash,zsh,sh,pwsh, andosascriptare blocked - shell metacharacters such as pipes, redirects, command substitution, and
newlines are rejected in
command - enabled stdio servers require a reviewed command allowlist, either in
control_plane.mcp_stdio_allowed_commandsor the server-specificstdio_allowed_commands - enabled stdio servers also require signed manifest metadata, a non-disabled sandbox profile, and explicit per-client consent
Example:
control_plane:
mcp_stdio_allowed_commands:
- uvx
- .venv/bin/python
mcp_servers:
- name: example
transport: stdio
command: uvx
args:
- example-mcp-server
stdio_allowed_commands:
- uvx
manifest_digest: sha256:<64-hex-digest>
manifest_signature: <review-system-signature>
sandbox_profile: restricted
client_consent: approved
enabled: true
Leave mcp_stdio_allowed_commands empty only when every enabled stdio server
has its own stdio_allowed_commands entry. An enabled stdio server with no
reviewed allowlist is blocked before launch.
Stdio subprocesses are launched with a minimal environment, closed file descriptors, a new process session, and the configured sandbox working directory when one is supplied. This is intentionally stricter than the default MCP ecosystem behavior because stdio is code execution.
sb mcp servers reports blocked stdio launches in the Reason column, and
per-server discovery stays scoped so one blocked server does not prevent other
configured MCP servers from being inspected.
SecondBrain now also advertises and handles optional client-side MCP capabilities for nested server requests:
roots/listreturns the configuredallowed_file_rootssampling/createMessageroutes through the configured provider/model stackelicitation/createsupports both form and URL flows with explicit operator consent
Handled nested requests work the same way across stdio and Streamable HTTP transports, so upstream MCP servers can rely on the same client capability surface regardless of transport.
When an upstream server returns URLElicitationRequiredError (-32042), the client now processes the required URL elicitations, waits for notifications/elicitation/complete, and retries the original request automatically when possible.
Cancellation is now wired in both directions:
- the local
/mcpserver honorsnotifications/cancelledfor in-flight requests and returns JSON-RPC-32800 - outbound stdio and Streamable HTTP transports send
notifications/cancelledfor timed-out or explicitly cancelled in-flight requests
Operational Guidance¶
- start with
sb mcp serversandsb mcp discover - use
sb mcp doctorwhen a configured server is not reachable or not behaving as expected - use
sb mcp approvals,score,exposure, andreportwhen debugging why a capability was or was not surfaced - prefer
compile-resourceonly for sources you trust to become durable local context
Related Docs¶
- ../../guides/integrations.md
- ../../explanation/architecture.md
brain/mcp/README.md