From 9475358393e47d4bf361286c7f3f4a9834e77b28 Mon Sep 17 00:00:00 2001 From: joelwp Date: Fri, 8 May 2026 11:11:16 -0600 Subject: [PATCH] feat: GBRAIN_EXPOSED_TOOLS env var for MCP tool filtering Allow MCP consumers to control which tools are exposed via a comma-separated GBRAIN_EXPOSED_TOOLS environment variable. When set, only the listed operations are registered with the MCP server. When unset, all operations are exposed (backward-compatible default). If the filter matches zero operations, falls back to exposing all tools with a stderr warning. This lets chatbot integrations (OpenClaw, Claude Desktop, etc.) reduce prompt size and LLM latency by exposing only the tools the agent needs for conversation, while keeping the full 51-tool set available for CLI, dream cycles, and background jobs. Example: GBRAIN_EXPOSED_TOOLS=get_page,put_page,search,query,list_pages Co-Authored-By: Claude Opus 4.6 (1M context) --- src/mcp/server.ts | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/mcp/server.ts b/src/mcp/server.ts index be0ae8ab3..59ed967c7 100644 --- a/src/mcp/server.ts +++ b/src/mcp/server.ts @@ -13,11 +13,29 @@ export async function startMcpServer(engine: BrainEngine) { { capabilities: { tools: {} } }, ); + // Optional tool filtering via GBRAIN_EXPOSED_TOOLS env var. + // Comma-separated list of operation names to expose (e.g. "get_page,put_page,search"). + // When unset, all operations are exposed (backward-compatible default). + const exposedToolsEnv = process.env.GBRAIN_EXPOSED_TOOLS; + const allowedOps = exposedToolsEnv + ? (() => { + const allowed = new Set(exposedToolsEnv.split(',').map(s => s.trim()).filter(Boolean)); + const filtered = operations.filter(op => allowed.has(op.name)); + if (filtered.length > 0) { + process.stderr.write(`[mcp] GBRAIN_EXPOSED_TOOLS: exposing ${filtered.length} of ${operations.length} tools\n`); + } else { + process.stderr.write(`[mcp] GBRAIN_EXPOSED_TOOLS set but matched 0 operations — exposing all ${operations.length}\n`); + return operations; + } + return filtered; + })() + : operations; + // Generate tool definitions from operations. Extracted to buildToolDefs so // the subagent tool registry (v0.15+) can call the same mapper against a // filtered OPERATIONS subset instead of duplicating this shape. server.setRequestHandler(ListToolsRequestSchema, async () => ({ - tools: buildToolDefs(operations), + tools: buildToolDefs(allowedOps), })); // Dispatch tool calls via shared dispatch.ts (parity with HTTP transport).