Sage ships a shared MCP (Model Context Protocol) server implementation to support:
- False-positive reporting from the local audit log (
~/.sage/audit.jsonl) to Sage Proxy (POST /v2/fp-report). - (Optional) Allowlist management tools, when the host platform can provide “recent user approval” signals.
This document explains:
- What the shared MCP server is (
@gendigital/sage-mcp) - Which clients are supported
- How Sage registers the MCP server on supported clients
Sage’s MCP server is implemented once in @gendigital/sage-mcp and then bundled into each platform distribution that needs a runnable MCP server process.
flowchart TD
auditLog[~/.sage/audit.jsonl]
core[@gendigital/sage-core]
mcp[@gendigital/sage-mcp]
host[HostClient(CLI/IDE)]
sageProxy[SageProxy(/v2/fp-report)]
core --> auditLog
mcp --> core
host -->|stdio JSON-RPC| mcp
mcp -->|"POST /v2/fp-report"| sageProxy
mcp -->|"read + filter by conversation_id"| auditLog
packages/core(@gendigital/sage-core)- Detection engine, config, allowlist, and audit log writer.
- Audit entries now include:
entry_id(UUID)conversation_id(used for report scoping)agent_runtime(best-effort source platform identifier)signals(best-effort structured signal metadata for reporting)
packages/mcp(@gendigital/sage-mcp)- Shared MCP server implementation (stdio transport) + tool registration.
- Reads the audit log via
@gendigital/sage-coreand sends reports via HTTPPOST /v2/fp-report. - Platform bundles (runnable scripts)
- Claude Code:
packages/claude-code/dist/mcp-server.cjs - Cursor/VS Code VSIX:
packages/extension/dist/mcp-server.cjs
- Claude Code:
- Uses the plugin manifest
.claude-plugin/plugin.jsonto registermcpServers.sage. - Sage bundles the MCP server into
packages/claude-code/dist/mcp-server.cjs.
- Sage registers the
sageMCP server via Cursor’s MCP API. - Cursor handles enable/disable automatically based on whether Sage protection is enabled.
Sage’s VS Code extension manages Claude-style settings (in ~/.claude/settings.json or workspace .claude/settings.json) for hooks.
For MCP, Sage registers an MCP server definition provider so that the server shows up in VS Code’s MCP UI.
- VS Code requires a manual start. Use the command palette:
MCP: List Server→sage→Start server.
Lists recent audit entries from ~/.sage/audit.jsonl, optionally filtered by conversation_id. This is intended to help users pick entry_ids for reporting.
Reports audit entries as false positives to Sage Proxy (POST /v2/fp-report).
- Scoping: filters to entries matching
conversation_id.- If
conversation_idis not provided, Sage will infer it from the most recentruntime_verdictentry in the audit log.
- If
- User input: the tool requires:
description: a short description of what is wrongreasoning: why it’s a false positive
- Payload: one report per audit entry, shaped like the Sage FP Submit Structure (see
sage_fp_handling_implementation.mdin this branch for the full schema).
The sage_report_false_positive tool is always available (it cannot be disabled via configuration).
Environment overrides:
SAGE_FALSE_POSITIVE_TIMEOUT_SECONDSSAGE_AGENT_RUNTIME_VERSION(used when the caller does not provide an explicit agent runtime version)
- On startup (and when protection is manually re-enabled), Sage registers the
sageMCP server viavscode.cursor.mcp.registerServer(...). - When protection is disabled until restart, Sage unregisters it via
vscode.cursor.mcp.unregisterServer("sage"). The server is re-registered on the next startup.
- VS Code does not currently expose an API to programmatically enable/disable (start/stop) an MCP server.
- Sage registers a server definition provider (via
contributes.mcpServerDefinitionProviders+vscode.lm.registerMcpServerDefinitionProvider(...)) so the server appears in the MCP UI. - The user must start the server manually using:
MCP: List Server→sage→Start server.
- No copy/paste across connectors: protocol + tool logic lives in
@gendigital/sage-mcp; connectors only provide a thin runnable entrypoint and (optionally) an allowlist approval adapter. - Conversation id quality is host-dependent: Sage records the best available conversation/session identifier from each host and stores it as
conversation_idin the audit log.