143 lines
4.7 KiB
Python
143 lines
4.7 KiB
Python
"""Руки: какие MCP есть у сетапа и кому из агентов какая рука выдана.
|
||
|
||
Секреты MCP - только через env подпроцесса, никогда argv: процесс модели
|
||
видит `ps` всего контейнера. Рука, чей env не задан, просто не появляется.
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
import os
|
||
from pathlib import Path
|
||
|
||
from beaver_gateway.agents.base import ExposedMcp
|
||
from beaver_gateway.mcp.types import McpServer, McpServerT
|
||
|
||
from beaver_agent.hands.calendars import calendars
|
||
from beaver_agent.hands.homeassistant import HomeAssistant
|
||
from beaver_agent.hands.komodo import Komodo
|
||
from beaver_agent.hands.vibegram import Vibegram
|
||
from beaver_agent.vault import TZ
|
||
|
||
env = os.environ.get
|
||
|
||
obsidian = McpServer.stdio(
|
||
name="obsidian-fs",
|
||
command=["bunx", "-y", "@modelcontextprotocol/server-filesystem", "/vault"],
|
||
lenient=True,
|
||
)
|
||
"""Файловые тулзы для тех, у кого нет своих (Raycast); у Claude vault смонтирован."""
|
||
|
||
firefly = (
|
||
McpServer.stdio(
|
||
name="firefly",
|
||
command=["bunx", "-y", "@firefly-iii-mcp/local", "--preset", "default"],
|
||
env={
|
||
"FIREFLY_III_PAT": os.environ["FIREFLY_PAT"],
|
||
"FIREFLY_III_BASE_URL": os.environ["FIREFLY_BASE_URL"],
|
||
},
|
||
lenient=True,
|
||
)
|
||
if env("FIREFLY_PAT")
|
||
else None
|
||
)
|
||
firefly_exposed = (ExposedMcp(name="firefly", deny=("delete_*",)),) if firefly else ()
|
||
|
||
telegram = (
|
||
McpServer.http(name="telegram", url=os.environ["BEAVERGRAM_MCP"])
|
||
if env("BEAVERGRAM_MCP")
|
||
else None
|
||
)
|
||
"""beavergram: история чатов Бобра в Telegram."""
|
||
|
||
calendar_servers = calendars(env("CALENDAR_MCPS", ""))
|
||
calendar_exposed = tuple(ExposedMcp(name=m.name) for m in calendar_servers)
|
||
|
||
KOMODO = (
|
||
Komodo(
|
||
url=os.environ["KOMODO_URL"],
|
||
key=os.environ["KOMODO_KEY"],
|
||
secret=os.environ["KOMODO_SECRET"],
|
||
)
|
||
if env("KOMODO_URL")
|
||
else None
|
||
)
|
||
"""Флот: перечислимые действия, ключ остаётся в gateway."""
|
||
komodo = McpServer.python_tool(name="komodo", tools=[KOMODO.komodo]) if KOMODO else None
|
||
komodo_exposed = (ExposedMcp(name="komodo"),) if KOMODO else ()
|
||
|
||
HA = (
|
||
HomeAssistant(url=os.environ["HA_URL"], token=os.environ["HA_TOKEN"])
|
||
if env("HA_URL") and env("HA_TOKEN")
|
||
else None
|
||
)
|
||
"""Дом: HA живёт на хосте, из контейнера - host.docker.internal."""
|
||
ha = McpServer.python_tool(name="ha", tools=[HA.ha]) if HA else None
|
||
ha_exposed = (ExposedMcp(name="ha"),) if HA else ()
|
||
|
||
VIBEGRAM_REPO = Path("/vibegram") / env("VIBEGRAM_REPO", "org/room").split("/")[-1]
|
||
VIBEGRAM = (
|
||
Vibegram(
|
||
hub=os.environ["VIBEGRAM_HUB"],
|
||
token=os.environ["VIBEGRAM_TOKEN"],
|
||
nick=os.environ["VIBEGRAM_NICK"],
|
||
repo=VIBEGRAM_REPO if VIBEGRAM_REPO.exists() else None,
|
||
tz=TZ,
|
||
)
|
||
if env("VIBEGRAM_TOKEN") and env("VIBEGRAM_HUB") and env("VIBEGRAM_NICK")
|
||
else None
|
||
)
|
||
"""Комната агентов: диспетчер сидит в ней сам; клон репы комнаты - том `vibegram`."""
|
||
vibegram = (
|
||
McpServer.python_tool(name="vibegram", tools=[VIBEGRAM.vibegram])
|
||
if VIBEGRAM
|
||
else None
|
||
)
|
||
vibegram_exposed = (ExposedMcp(name="vibegram"),) if VIBEGRAM else ()
|
||
|
||
t3code = (
|
||
McpServer.http(name="t3code", url=env("T3CODE_MCP", "http://t3code-mcp:8000/mcp"))
|
||
if "t3" in env("COMPOSE_PROFILES", "").split(",")
|
||
else None
|
||
)
|
||
"""t3code-mcp - сосед по compose (профиль t3); машины и allowlist в его t3code.toml."""
|
||
t3code_exposed = (ExposedMcp(name="t3code"),) if t3code else ()
|
||
|
||
msos = (
|
||
McpServer.http(name="msos", url=os.environ["MSOS_MCP"]) if env("MSOS_MCP") else None
|
||
)
|
||
"""Таскер рабочих проектов (скилл `задачи`)."""
|
||
msos_exposed = (ExposedMcp(name="msos"),) if msos else ()
|
||
|
||
mcps: list[McpServerT] = [
|
||
m
|
||
for m in (
|
||
obsidian,
|
||
firefly,
|
||
telegram,
|
||
*calendar_servers,
|
||
komodo,
|
||
ha,
|
||
vibegram,
|
||
t3code,
|
||
msos,
|
||
)
|
||
if m is not None
|
||
]
|
||
|
||
CLAUDE = (
|
||
*firefly_exposed,
|
||
ExposedMcp(name="telegram"),
|
||
*calendar_exposed,
|
||
*komodo_exposed,
|
||
*ha_exposed,
|
||
)
|
||
"""Руки любого Claude-агента: firefly без delete, телега, календари, флот, дом."""
|
||
DISPATCHER = (*CLAUDE, *t3code_exposed, *vibegram_exposed, *msos_exposed)
|
||
"""Диспетчер ещё ходит в код, в комнату агентов и в таскер; глубоким это не даётся."""
|
||
RAYCAST = (
|
||
ExposedMcp(name="obsidian-fs"),
|
||
*firefly_exposed,
|
||
ExposedMcp(name="telegram"),
|
||
*calendar_exposed,
|
||
)
|