From 2df8f7874784caf753ec81d7e3d28da16c6a64c8 Mon Sep 17 00:00:00 2001 From: lekss361 Date: Sat, 30 May 2026 11:05:24 +0300 Subject: [PATCH] chore(bots): per-window MCP isolation via --strict-mcp-config MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Каждое bot-окно грузит ТОЛЬКО нужные роли серверы (не все 7+ в каждом окне). Выигрыш: не спавнить heavy-серверы зря (docker postgres в frontend/qa), right-size eager-набор, чистый tool-surface на роль. (Контекст tool-search и так бережёт — deferred ≈ бесплатно; это про процессы + eager + ясность.) - .claude/mcp/{analyst,backend,frontend,reviewer,qa}.json — self-contained per-role конфиги. Секреты НЕ инлайнятся: ${OBSIDIAN_API_KEY}/${GENDESIGN_DB_URI}/ ${GLITCHTIP_TOKEN} через env-подстановку (.mcp.json env expansion, подтв. в доках). Матрица: forgejo+obsidian+context7 eager везде; pg-gendesign eager у backend/reviewer, deferred у analyst; UI (playwright/a11y/lighthouse/shadcn) только frontend/qa; fetch+ glitchtip у backend; glitchtip у qa. - start-bot.ps1: извлекает MCP-секреты из ~/.claude.json (единый источник) → export → запускает `claude --strict-mcp-config --mcp-config .claude/mcp/.json`. Main/интерактивное окно (без start-bot.ps1) по-прежнему видит полный .mcp.json+user. --- .claude/mcp/analyst.json | 22 ++++++++++++++++++++++ .claude/mcp/backend.json | 29 +++++++++++++++++++++++++++++ .claude/mcp/frontend.json | 20 ++++++++++++++++++++ .claude/mcp/qa.json | 23 +++++++++++++++++++++++ .claude/mcp/reviewer.json | 23 +++++++++++++++++++++++ scripts/start-bot.ps1 | 22 ++++++++++++++++++++-- 6 files changed, 137 insertions(+), 2 deletions(-) create mode 100644 .claude/mcp/analyst.json create mode 100644 .claude/mcp/backend.json create mode 100644 .claude/mcp/frontend.json create mode 100644 .claude/mcp/qa.json create mode 100644 .claude/mcp/reviewer.json diff --git a/.claude/mcp/analyst.json b/.claude/mcp/analyst.json new file mode 100644 index 00000000..2a69c267 --- /dev/null +++ b/.claude/mcp/analyst.json @@ -0,0 +1,22 @@ +{ + "mcpServers": { + "obsidian": { + "command": "uvx", + "args": ["mcp-obsidian"], + "env": { "OBSIDIAN_API_KEY": "${OBSIDIAN_API_KEY}", "OBSIDIAN_HOST": "127.0.0.1", "OBSIDIAN_PORT": "27124" }, + "alwaysLoad": true + }, + "forgejo": { + "command": "C:/Users/user/tools/bin/forgejo-mcp.exe", + "args": ["-t", "stdio", "-url", "https://git.gendsgn.ru", "-debug=false"], + "alwaysLoad": true + }, + "context7": { "type": "http", "url": "https://mcp.context7.com/mcp", "alwaysLoad": true }, + "postgres-gendesign": { + "type": "stdio", + "command": "docker", + "args": ["run", "-i", "--rm", "-e", "DATABASE_URI", "crystaldba/postgres-mcp", "--access-mode=unrestricted"], + "env": { "DATABASE_URI": "${GENDESIGN_DB_URI}" } + } + } +} diff --git a/.claude/mcp/backend.json b/.claude/mcp/backend.json new file mode 100644 index 00000000..45257d93 --- /dev/null +++ b/.claude/mcp/backend.json @@ -0,0 +1,29 @@ +{ + "mcpServers": { + "obsidian": { + "command": "uvx", + "args": ["mcp-obsidian"], + "env": { "OBSIDIAN_API_KEY": "${OBSIDIAN_API_KEY}", "OBSIDIAN_HOST": "127.0.0.1", "OBSIDIAN_PORT": "27124" }, + "alwaysLoad": true + }, + "forgejo": { + "command": "C:/Users/user/tools/bin/forgejo-mcp.exe", + "args": ["-t", "stdio", "-url", "https://git.gendsgn.ru", "-debug=false"], + "alwaysLoad": true + }, + "context7": { "type": "http", "url": "https://mcp.context7.com/mcp", "alwaysLoad": true }, + "postgres-gendesign": { + "type": "stdio", + "command": "docker", + "args": ["run", "-i", "--rm", "-e", "DATABASE_URI", "crystaldba/postgres-mcp", "--access-mode=unrestricted"], + "env": { "DATABASE_URI": "${GENDESIGN_DB_URI}" }, + "alwaysLoad": true + }, + "fetch": { "command": "uvx", "args": ["mcp-server-fetch"] }, + "glitchtip": { + "command": "npx", + "args": ["-y", "mcp-glitchtip"], + "env": { "GLITCHTIP_TOKEN": "${GLITCHTIP_TOKEN}", "GLITCHTIP_ORGANIZATION": "gendesign", "GLITCHTIP_BASE_URL": "https://errors.gendsgn.ru" } + } + } +} diff --git a/.claude/mcp/frontend.json b/.claude/mcp/frontend.json new file mode 100644 index 00000000..e0e3ecdf --- /dev/null +++ b/.claude/mcp/frontend.json @@ -0,0 +1,20 @@ +{ + "mcpServers": { + "obsidian": { + "command": "uvx", + "args": ["mcp-obsidian"], + "env": { "OBSIDIAN_API_KEY": "${OBSIDIAN_API_KEY}", "OBSIDIAN_HOST": "127.0.0.1", "OBSIDIAN_PORT": "27124" }, + "alwaysLoad": true + }, + "forgejo": { + "command": "C:/Users/user/tools/bin/forgejo-mcp.exe", + "args": ["-t", "stdio", "-url", "https://git.gendsgn.ru", "-debug=false"], + "alwaysLoad": true + }, + "context7": { "type": "http", "url": "https://mcp.context7.com/mcp", "alwaysLoad": true }, + "playwright": { "command": "npx", "args": ["-y", "@playwright/mcp@latest", "--cdp-endpoint=http://localhost:9222"] }, + "a11y": { "command": "npx", "args": ["-y", "a11y-mcp"] }, + "lighthouse": { "command": "npx", "args": ["-y", "-p", "@danielsogl/lighthouse-mcp", "lighthouse-mcp-server"] }, + "shadcn": { "command": "npx", "args": ["shadcn@latest", "mcp"] } + } +} diff --git a/.claude/mcp/qa.json b/.claude/mcp/qa.json new file mode 100644 index 00000000..662d965b --- /dev/null +++ b/.claude/mcp/qa.json @@ -0,0 +1,23 @@ +{ + "mcpServers": { + "obsidian": { + "command": "uvx", + "args": ["mcp-obsidian"], + "env": { "OBSIDIAN_API_KEY": "${OBSIDIAN_API_KEY}", "OBSIDIAN_HOST": "127.0.0.1", "OBSIDIAN_PORT": "27124" }, + "alwaysLoad": true + }, + "forgejo": { + "command": "C:/Users/user/tools/bin/forgejo-mcp.exe", + "args": ["-t", "stdio", "-url", "https://git.gendsgn.ru", "-debug=false"], + "alwaysLoad": true + }, + "playwright": { "command": "npx", "args": ["-y", "@playwright/mcp@latest", "--cdp-endpoint=http://localhost:9222"], "alwaysLoad": true }, + "a11y": { "command": "npx", "args": ["-y", "a11y-mcp"] }, + "lighthouse": { "command": "npx", "args": ["-y", "-p", "@danielsogl/lighthouse-mcp", "lighthouse-mcp-server"] }, + "glitchtip": { + "command": "npx", + "args": ["-y", "mcp-glitchtip"], + "env": { "GLITCHTIP_TOKEN": "${GLITCHTIP_TOKEN}", "GLITCHTIP_ORGANIZATION": "gendesign", "GLITCHTIP_BASE_URL": "https://errors.gendsgn.ru" } + } + } +} diff --git a/.claude/mcp/reviewer.json b/.claude/mcp/reviewer.json new file mode 100644 index 00000000..674357cc --- /dev/null +++ b/.claude/mcp/reviewer.json @@ -0,0 +1,23 @@ +{ + "mcpServers": { + "obsidian": { + "command": "uvx", + "args": ["mcp-obsidian"], + "env": { "OBSIDIAN_API_KEY": "${OBSIDIAN_API_KEY}", "OBSIDIAN_HOST": "127.0.0.1", "OBSIDIAN_PORT": "27124" }, + "alwaysLoad": true + }, + "forgejo": { + "command": "C:/Users/user/tools/bin/forgejo-mcp.exe", + "args": ["-t", "stdio", "-url", "https://git.gendsgn.ru", "-debug=false"], + "alwaysLoad": true + }, + "context7": { "type": "http", "url": "https://mcp.context7.com/mcp", "alwaysLoad": true }, + "postgres-gendesign": { + "type": "stdio", + "command": "docker", + "args": ["run", "-i", "--rm", "-e", "DATABASE_URI", "crystaldba/postgres-mcp", "--access-mode=unrestricted"], + "env": { "DATABASE_URI": "${GENDESIGN_DB_URI}" }, + "alwaysLoad": true + } + } +} diff --git a/scripts/start-bot.ps1 b/scripts/start-bot.ps1 index f3a69711..a7947fdd 100644 --- a/scripts/start-bot.ps1 +++ b/scripts/start-bot.ps1 @@ -49,9 +49,27 @@ if ($me -ne $bot) { return } +# MCP-секреты для per-role конфига (.claude/mcp/.json через ${VAR}-подстановку). +# Единый источник — существующий ~/.claude.json; в role-файлах секретов НЕТ. +$claudeJson = Join-Path $env:USERPROFILE ".claude.json" +if (Test-Path $claudeJson) { + $ms = (Get-Content $claudeJson -Raw | ConvertFrom-Json).mcpServers + if ($ms.obsidian) { $env:OBSIDIAN_API_KEY = $ms.obsidian.env.OBSIDIAN_API_KEY } + if ($ms.'postgres-gendesign') { $env:GENDESIGN_DB_URI = $ms.'postgres-gendesign'.env.DATABASE_URI } + if ($ms.glitchtip) { $env:GLITCHTIP_TOKEN = $ms.glitchtip.env.GLITCHTIP_TOKEN } +} +# fallback: obsidian-ключ может жить в project .mcp.json +if (-not $env:OBSIDIAN_API_KEY -and (Test-Path "$PSScriptRoot\..\.mcp.json")) { + $env:OBSIDIAN_API_KEY = (Get-Content "$PSScriptRoot\..\.mcp.json" -Raw | ConvertFrom-Json).mcpServers.obsidian.env.OBSIDIAN_API_KEY +} + +$mcpConfig = (Resolve-Path "$PSScriptRoot\..\.claude\mcp\$Role.json").Path + Write-Host "OK bot=$bot" -ForegroundColor Green -Write-Host "OK forgejo MCP token set (FORGEJO_ACCESS_TOKEN) + git identity + forgejo-bot remote" -ForegroundColor Green +Write-Host "OK identity + tokens + forgejo-bot remote" -ForegroundColor Green +Write-Host "OK per-role MCP (--strict-mcp-config): $mcpConfig" -ForegroundColor Green Write-Host "" Write-Host "В окне Claude (Opus 4.8 для reviewer): /work-as-$Role -> затем /loop" -ForegroundColor Cyan -claude +# --strict-mcp-config: грузим ТОЛЬКО серверы этой роли (игнорируем .mcp.json + ~/.claude.json) +claude --strict-mcp-config --mcp-config "$mcpConfig" -- 2.45.3