Skip to content

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.py for 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 mcp is the operator and diagnostics surface
  • brain/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:

  • initialize
  • notifications/initialized
  • ping
  • logging/setLevel
  • completion/complete
  • prompts/list
  • prompts/get
  • resources/list
  • resources/read
  • resources/templates/list
  • tools/list
  • tools/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:

.venv/bin/python -m brain.mcp.server

The repository-level Claude Code config at .claude/settings.json registers it as the secondbrain MCP server. It exposes first-class local tools:

  • sb_ask
  • sb_ingest
  • sb_pack
  • sb_open_loops
  • sb_decision_extract
  • sb_grounded_answer
  • sb_recall
  • sb_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/message for 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:

  • command must be a single executable token; put all arguments in args
  • list-valued command config 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, and osascript are 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_commands or the server-specific stdio_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/list returns the configured allowed_file_roots
  • sampling/createMessage routes through the configured provider/model stack
  • elicitation/create supports 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 /mcp server honors notifications/cancelled for in-flight requests and returns JSON-RPC -32800
  • outbound stdio and Streamable HTTP transports send notifications/cancelled for timed-out or explicitly cancelled in-flight requests

Operational Guidance

  • start with sb mcp servers and sb mcp discover
  • use sb mcp doctor when a configured server is not reachable or not behaving as expected
  • use sb mcp approvals, score, exposure, and report when debugging why a capability was or was not surfaced
  • prefer compile-resource only for sources you trust to become durable local context