Class: SmartBrain::Server::McpServer
- Inherits:
-
Object
- Object
- SmartBrain::Server::McpServer
- Defined in:
- lib/smart_brain/server/mcp_server.rb
Overview
Model Context Protocol server over stdio (newline-delimited JSON-RPC 2.0).
No external MCP gem dependency: implements the subset clients actually use (initialize / notifications/initialized / tools/list / tools/call) so that Claude Code, Cursor, etc. can drive SmartBrain as a native tool.
Constant Summary collapse
- PROTOCOL_VERSION =
'2024-11-05'- INSTRUCTIONS =
<<~TXT.strip SmartBrain memory runtime. Available tools: - commit_turn: persist a turn (messages + structured events) and extract durable memory. - compose_context: assemble the minimal sufficient context (summary + recent + evidence) for a user message. - search_memory: full-text recall over the session's persistent memory. - knowledge_distill / knowledge_gate / knowledge_promote / knowledge_demote: the Stage-1 knowledge lifecycle (evidence → candidate → promoted → demoted). Distill reusable rules at tier dao_ren or qi; promote only after enough supporting evidence; demote with a reason_type (contradicted|obsolete|superseded). - kg_add / kg_query / kg_invalidate: knowledge-graph triples (subject-predicate-object) with temporal validity. Run fact_check before asserting entity relations to catch name/contradiction/stale issues. - fact_check: offline, zero-LLM contradiction scan (SimilarNameConflict / RelationContradiction / StaleFact) of a text against the session's entities + KG. - brief / wake_up: deterministic citation-first cognitive snapshot and L0/L1 resume payload. - status: backend, metrics, counts. Always pass a stable session_id per conversation. Prefer compose_context before answering, and commit_turn after each assistant reply. TXT
- SCOPE_PROPERTIES =
{ domain_id: { type: 'string' }, scope_context: { type: 'object' } }.freeze
- TOOLS =
[ { name: 'commit_turn', description: 'Persist a conversation turn and extract structured memory items (decisions, tasks, goals, entities, preferences).', inputSchema: { type: 'object', properties: SCOPE_PROPERTIES.merge( session_id: { type: 'string' }, turn_events: { type: 'object', description: 'messages: [{role, content}], plus optional tasks/decisions/goals/entities/preferences/refs arrays.' } ), required: %w[session_id turn_events] } }, { name: 'compose_context', description: 'Retrieve evidence and assemble a context package for the latest user message.', inputSchema: { type: 'object', properties: SCOPE_PROPERTIES.merge( session_id: { type: 'string' }, user_message: { type: 'string' }, agent_state: { type: 'object' } ), required: %w[session_id user_message] } }, { name: 'search_memory', description: 'Full-text search the session\'s persistent memory; returns ranked evidence.', inputSchema: { type: 'object', properties: SCOPE_PROPERTIES.merge( session_id: { type: 'string' }, query: { type: 'string' }, limit: { type: 'integer' } ), required: %w[session_id query] } }, { name: 'status', description: 'SmartBrain diagnostics: storage backend, P95, memory/resource ratio, counts.', inputSchema: { type: 'object', properties: {}, additionalProperties: false } }, { name: 'knowledge_distill', description: 'Distill a candidate knowledge item (tier dao_ren or qi) from supporting evidence refs.', inputSchema: { type: 'object', properties: SCOPE_PROPERTIES.merge( session_id: { type: 'string' }, statement: { type: 'string' }, content: { type: 'string' }, tier: { type: 'string', enum: %w[dao_ren qi] }, supporting_refs: { type: 'array', items: { type: 'string' } }, domain: { type: 'string' }, field: { type: 'string' }, reviewer: { type: 'string' } ), required: %w[session_id statement tier] } }, { name: 'knowledge_gate', description: 'Read-only check: is a candidate knowledge item ready for promotion?', inputSchema: { type: 'object', properties: SCOPE_PROPERTIES.merge(memory_item_id: { type: 'string' }, session_id: { type: 'string' }), required: %w[memory_item_id] } }, { name: 'knowledge_promote', description: 'Gate-enforced promotion of a candidate knowledge item to promoted.', inputSchema: { type: 'object', properties: SCOPE_PROPERTIES.merge( session_id: { type: 'string' }, memory_item_id: { type: 'string' }, verification_refs: { type: 'array', items: { type: 'string' } }, reason: { type: 'string' }, reviewer: { type: 'string' }, force: { type: 'boolean' } ), required: %w[memory_item_id verification_refs reason] } }, { name: 'knowledge_demote', description: 'Evidence-backed demotion of a knowledge item (reason_type: contradicted|obsolete|superseded).', inputSchema: { type: 'object', properties: SCOPE_PROPERTIES.merge( session_id: { type: 'string' }, memory_item_id: { type: 'string' }, evidence_refs: { type: 'array', items: { type: 'string' } }, reason: { type: 'string' }, reason_type: { type: 'string', enum: %w[contradicted obsolete superseded] } ), required: %w[memory_item_id evidence_refs reason reason_type] } }, { name: 'knowledge_promote_to_scope', description: 'Copy a verified memory item into a writable target scope while preserving provenance.', inputSchema: { type: 'object', properties: SCOPE_PROPERTIES.merge( session_id: { type: 'string' }, memory_item_id: { type: 'string' }, target_scope: { type: 'object' }, verification_refs: { type: 'array', items: { type: 'string' } }, reason: { type: 'string' }, reviewer: { type: 'string' } ), required: %w[domain_id session_id scope_context memory_item_id target_scope verification_refs reason] } }, { name: 'knowledge_retract', description: 'Retract a memory item with evidence and an audit event.', inputSchema: { type: 'object', properties: SCOPE_PROPERTIES.merge( session_id: { type: 'string' }, memory_item_id: { type: 'string' }, evidence_refs: { type: 'array', items: { type: 'string' } }, reason: { type: 'string' }, reviewer: { type: 'string' } ), required: %w[memory_item_id evidence_refs reason] } }, { name: 'knowledge_lineage', description: 'Return cross-scope promotion lineage for a memory item.', inputSchema: { type: 'object', properties: SCOPE_PROPERTIES.merge(session_id: { type: 'string' }, memory_item_id: { type: 'string' }), required: %w[memory_item_id] } }, { name: 'kg_add', description: 'Add a knowledge-graph triple (subject-predicate-object) with temporal validity.', inputSchema: { type: 'object', properties: SCOPE_PROPERTIES.merge( session_id: { type: 'string' }, subject: { type: 'string' }, predicate: { type: 'string' }, object: { type: 'string' }, confidence: { type: 'number' }, scope_ref: { type: 'object' } ), required: %w[session_id subject predicate object] } }, { name: 'kg_query', description: 'Query KG triples (any of subject/predicate/object; include_invalid to see invalidated).', inputSchema: { type: 'object', properties: SCOPE_PROPERTIES.merge( session_id: { type: 'string' }, subject: { type: 'string' }, predicate: { type: 'string' }, object: { type: 'string' }, include_invalid: { type: 'boolean' } ), required: %w[session_id] } }, { name: 'kg_invalidate', description: 'Invalidate a KG triple (sets valid_to=now, status=invalidated).', inputSchema: { type: 'object', properties: SCOPE_PROPERTIES.merge( edge_id: { type: 'string' }, reason: { type: 'string' }, session_id: { type: 'string' } ), required: %w[edge_id] } }, { name: 'kg_timeline', description: 'Return the temporal history of KG edges for a subject across readable scopes.', inputSchema: { type: 'object', properties: SCOPE_PROPERTIES.merge(session_id: { type: 'string' }, subject: { type: 'string' }), required: %w[session_id subject] } }, { name: 'kg_stats', description: 'Return KG active and invalidated counts across readable scopes.', inputSchema: { type: 'object', properties: SCOPE_PROPERTIES.merge(session_id: { type: 'string' }), required: %w[session_id] } }, { name: 'fact_check', description: 'Offline zero-LLM contradiction scan of text vs session entities + KG (SimilarName/Relation/StaleFact).', inputSchema: { type: 'object', properties: SCOPE_PROPERTIES.merge(session_id: { type: 'string' }, text: { type: 'string' }), required: %w[session_id text] } }, { name: 'brief', description: 'Deterministic citation-first cognitive snapshot (summary/key_facts/evidence/entities/unresolved/uncertainty/next_actions).', inputSchema: { type: 'object', properties: SCOPE_PROPERTIES.merge(session_id: { type: 'string' }, query: { type: 'string' }), required: %w[session_id] } }, { name: 'wake_up', description: 'Minimal L0/L1 importance-ordered resume payload for a session.', inputSchema: { type: 'object', properties: SCOPE_PROPERTIES.merge(session_id: { type: 'string' }), required: %w[session_id] } } ].freeze
Instance Attribute Summary collapse
-
#service ⇒ Object
readonly
Returns the value of attribute service.
Instance Method Summary collapse
-
#initialize(service:, in_io: $stdin, out_io: $stdout, err_io: $stderr) ⇒ McpServer
constructor
A new instance of McpServer.
- #run ⇒ Object
Constructor Details
#initialize(service:, in_io: $stdin, out_io: $stdout, err_io: $stderr) ⇒ McpServer
Returns a new instance of McpServer.
246 247 248 249 250 251 |
# File 'lib/smart_brain/server/mcp_server.rb', line 246 def initialize(service:, in_io: $stdin, out_io: $stdout, err_io: $stderr) @service = service @in = in_io @out = out_io @err = err_io end |
Instance Attribute Details
#service ⇒ Object (readonly)
Returns the value of attribute service.
244 245 246 |
# File 'lib/smart_brain/server/mcp_server.rb', line 244 def service @service end |
Instance Method Details
#run ⇒ Object
253 254 255 256 257 258 259 260 261 262 263 264 265 266 |
# File 'lib/smart_brain/server/mcp_server.rb', line 253 def run @out.sync = true @in.each_line do |raw| line = raw.to_s.strip next if line.empty? request = JSON.parse(line) handle(request) rescue JSON::ParserError => e log("ignoring malformed line: #{e.}") rescue StandardError => e log("handler error: #{e.class}: #{e.}") end end |