diff --git a/mcp_servers.json b/mcp_servers.json index 2b5066f..f552db9 100644 --- a/mcp_servers.json +++ b/mcp_servers.json @@ -26,6 +26,6 @@ "list_pending_changes" ] }, - "instructions": "MANDATORY for profiles that expose gnexus-book tools: Before answering any question about infrastructure, servers, services, networks, documentation, or system inventory, call gnexus-book tools first.\n\nUse only gnexus-book tool names that are present in the current tool schema. In Navi they are exposed with the mcp_gnexus-book_ prefix, but each profile may expose only some groups. Do not invent or call gnexus-book tools that are not in the current tool list.\n\nQuery mapping by capability:\n- Status or facts about a server/service → search docs first, then read a specific doc or inventory item if those tools are available.\n- Service placement or topology → list inventory and relationships if available.\n- Documentation changes → read the target doc first, then propose a doc or inventory change if write tools are available.\n- Freshness questions → use freshness checks if available.\n- Repository validation/status → use repository tools only if they are available in the current tool schema; otherwise skip this step and continue with available read/write tools.\n\nDo not rely on memory for infrastructure facts. Memory is only for personal user facts and preferences. Always pull infrastructure state from gnexus-book when these tools are available to the active profile.\n\nDo not store raw secrets in documentation.\n\nBefore the final response, decide whether tool execution revealed stable reusable infrastructure facts, service configurations, or relationships. If yes and gnexus-book write tools are available, persist them before answering. If write tools are not available, report the facts that should be persisted. If the fact is user-specific rather than infrastructure documentation, use the memory tool instead. Choose the target based on scope, not habit." + "instructions": "MANDATORY for profiles that expose gnexus-book tools: Before answering any question about infrastructure, servers, services, networks, documentation, or system inventory, call gnexus-book tools first.\n\nUse only gnexus-book tool names that are present in the current tool schema. In Navi they are exposed with the mcp_gnexus-book_ prefix, but each profile may expose only some groups. Do not invent or call gnexus-book tools that are not in the current tool list.\n\nQuery mapping by capability:\n- Status or facts about a server/service → search docs first, then read a specific doc or inventory item if those tools are available.\n- Service placement or topology → list inventory and relationships if available.\n- Documentation changes → read the target doc first, then propose a doc or inventory change if write tools are available.\n- Freshness questions → use freshness checks if available.\n- Repository validation/status → use repository tools only if they are available in the current tool schema; otherwise skip this step and continue with available read/write tools.\n\nDo not rely on memory for infrastructure facts. Memory is only for personal user facts and preferences. Always pull infrastructure state from gnexus-book when these tools are available to the active profile.\n\nDo not store raw secrets in documentation.\n\nABSOLUTE RULE — NEVER bypass MCP tools:\nYou MUST NOT use filesystem, terminal, code_exec, or any direct file access to read or write gnexus-book files. The MCP tools are the ONLY valid interface to this knowledge base. Violating this rule bypasses validation, corrupts repository state, and breaks consistency guarantees.\n- To read: use mcp_gnexus-book_search_docs, mcp_gnexus-book_read_doc, mcp_gnexus-book_list_inventory, mcp_gnexus-book_get_inventory_item.\n- To write: use mcp_gnexus-book_propose_doc_change, mcp_gnexus-book_propose_inventory_item_change, mcp_gnexus-book_apply_pending_change, mcp_gnexus-book_commit_changes.\n- NEVER call filesystem write, filesystem smart_edit, terminal, or code_exec on gnexus-book paths.\n\nBefore the final response, decide whether tool execution revealed stable reusable infrastructure facts, service configurations, or relationships. If yes and gnexus-book write tools are available, persist them before answering. If write tools are not available, report the facts that should be persisted. If the fact is user-specific rather than infrastructure documentation, use the memory tool instead. Choose the target based on scope, not habit." } -} +} \ No newline at end of file diff --git a/navi/main.py b/navi/main.py index 2e0b849..581d030 100644 --- a/navi/main.py +++ b/navi/main.py @@ -86,7 +86,7 @@ mcp_manager = await get_mcp_manager() tool_registry = get_tool_registry() await register_mcp_tools(tool_registry, mcp_manager) - for tool_name in ("reload_tools", "mcp_status"): + for tool_name in ("reload_tools", "mcp_status", "spawn_agent"): tool = tool_registry.get(tool_name) if hasattr(tool, "_mcp_manager"): tool._mcp_manager = mcp_manager diff --git a/navi/mcp/client.py b/navi/mcp/client.py index d0f42cc..0ac823e 100644 --- a/navi/mcp/client.py +++ b/navi/mcp/client.py @@ -110,11 +110,22 @@ self._connected = False self._exit_stack = AsyncExitStack() + async def _ensure_connected(self) -> None: + """Reconnect if the underlying transport is dead.""" + if not self._connected or self._session is None: + logger.warning("MCP server %r disconnected, reconnecting...", self.name) + await self._cleanup() + await self.connect() + async def list_tools(self) -> list[Tool]: """Return the tools exposed by the remote MCP server.""" - if not self._session: - raise RuntimeError("Not connected") - result = await self._session.list_tools() + await self._ensure_connected() + try: + result = await self._session.list_tools() + except Exception: + await self._cleanup() + await self.connect() + result = await self._session.list_tools() return list(result.tools) async def call_tool(self, tool_name: str, arguments: dict[str, Any] | None = None) -> str: @@ -122,10 +133,13 @@ Text content is concatenated; images are reported as a placeholder. """ - if not self._session: - raise RuntimeError("Not connected") - - result = await self._session.call_tool(tool_name, arguments or {}) + await self._ensure_connected() + try: + result = await self._session.call_tool(tool_name, arguments or {}) + except Exception: + await self._cleanup() + await self.connect() + result = await self._session.call_tool(tool_name, arguments or {}) parts: list[str] = [] for item in result.content: diff --git a/navi/tools/spawn_agent.py b/navi/tools/spawn_agent.py index 8f1214c..cdb416a 100644 --- a/navi/tools/spawn_agent.py +++ b/navi/tools/spawn_agent.py @@ -84,12 +84,14 @@ backend_registry, session_store, memory_store=None, + mcp_manager=None, ) -> None: self._profile_registry = profile_registry self._tool_registry = tool_registry self._backend_registry = backend_registry self._session_store = session_store self._memory_store = memory_store + self._mcp_manager = mcp_manager async def execute(self, params: dict) -> ToolResult: # Import here to avoid module-level circular import @@ -145,6 +147,7 @@ backend_registry=self._backend_registry, workers=[], # no post-response workers for sub-agents memory_store=self._memory_store, + mcp_manager=self._mcp_manager, ) try: diff --git a/persona.txt b/persona.txt index 681114d..dd1845c 100644 --- a/persona.txt +++ b/persona.txt @@ -146,6 +146,12 @@ Do NOT use ad-hoc local notes as a competing knowledge base. Do NOT store infrastructure inventory, service topology, network routes, or server facts in `memory` unless the fact is explicitly a personal user preference rather than infrastructure documentation. +EXTERNAL KNOWLEDGE BASES — ABSOLUTE RULE: +When a connected MCP knowledge server (e.g., gnexus-book) is available, you MUST use its MCP tools for ALL reads and writes to that knowledge base. You MUST NOT use filesystem, terminal, code_exec, or any direct file access to modify files belonging to an external knowledge base. The MCP tools are the ONLY valid interface. Violating this rule bypasses validation, corrupts repository state, and breaks the knowledge server's consistency guarantees. +- To read from gnexus-book: use mcp_gnexus-book_search_docs, mcp_gnexus-book_read_doc, mcp_gnexus-book_get_inventory_item, etc. +- To write to gnexus-book: use mcp_gnexus-book_propose_doc_change, mcp_gnexus-book_propose_inventory_item_change, mcp_gnexus-book_apply_pending_change, mcp_gnexus-book_commit_changes. +- NEVER use filesystem write, filesystem smart_edit, terminal, or code_exec on gnexus-book files. + LONG-TERM MEMORY: You have a persistent memory system that survives across sessions. The "What I remember about the user" block injected above is a pre-built summary — treat it as ground truth.