diff --git a/docs/api.md b/docs/api.md index 5cf05d4..95c9ddd 100644 --- a/docs/api.md +++ b/docs/api.md @@ -149,7 +149,7 @@ "id": "secretary", "name": "Personal Secretary", "description": "General-purpose assistant", - "enabled_tools": ["todo", "mcp_navi-web_search", "filesystem", "..."], + "enabled_tools": ["todo", "mcp:navi-web:web_search", "filesystem", "..."], "llm_backend": "ollama", "model": ["gemma4:31b-cloud", "gemma4:26b-a4b-it-q4_K_M"], "temperature": 0.65, @@ -172,7 +172,7 @@ ```json [ { - "name": "mcp_navi-web_search", + "name": "mcp:navi-web:web_search", "description": "Search the web using DuckDuckGo.", "parameters": {"type": "object", "properties": {...}, "required": [...]} }, @@ -334,7 +334,7 @@ "tool_calls": [ { "id": "abc123", - "name": "mcp_navi-web_search", + "name": "mcp:navi-web:web_search", "arguments": { "query": "..." } } ] @@ -343,7 +343,7 @@ "role": "tool", "content": "tool result", "tool_call_id": "abc123", - "name": "mcp_navi-web_search" + "name": "mcp:navi-web:web_search" } ] } @@ -657,7 +657,7 @@ ```json { "type": "tool_started", - "tool": "mcp_navi-web_search", + "tool": "mcp:navi-web:web_search", "args": { "query": "weather in moscow" }, "is_subagent": false } @@ -671,7 +671,7 @@ ```json { "type": "tool_call", - "tool": "mcp_navi-web_search", + "tool": "mcp:navi-web:web_search", "args": { "query": "weather in moscow" }, "result": "Today +12°C, cloudy.", "success": true, diff --git a/docs/profiles.md b/docs/profiles.md index dae70b9..11e7edf 100644 --- a/docs/profiles.md +++ b/docs/profiles.md @@ -131,7 +131,7 @@ "model": ["gemma4:31b-cloud", "gemma4:26b-a4b-it-q4_K_M"], "temperature": 0.5, "max_iterations": 20, - "enabled_tools": ["todo", "scratchpad", "mcp_navi-web_search", "filesystem"], + "enabled_tools": ["todo", "scratchpad", "mcp:navi-web:web_search", "filesystem"], "subagent_tools": ["todo", "filesystem", "terminal"], "planning_enabled": true, "planning_mandatory": false, diff --git a/docs/tools.md b/docs/tools.md index 32fd056..bcdd147 100644 --- a/docs/tools.md +++ b/docs/tools.md @@ -10,10 +10,10 @@ | Tool | Name | Description | |---|---|---| -| `WebSearchTool` | `mcp_navi-web_search` | DuckDuckGo search | -| `WebViewTool` | `mcp_navi-web_view` | Fetch and render a URL | +| `WebSearchTool` | `mcp:navi-web:web_search` | DuckDuckGo search | +| `WebViewTool` | `mcp:navi-web:web_view` | Fetch and render a URL | | `FilesystemTool` | `filesystem` | Read/write/list local files (path restrictions via config) | -| `HttpRequestTool` | `mcp_navi-web_request` | Generic HTTP client (GET/POST/etc.) | +| `HttpRequestTool` | `mcp:navi-web:http_request` | Generic HTTP client (GET/POST/etc.) | | `CodeExecTool` | `code_exec` | Execute Python in a subprocess sandbox | | `TerminalTool` | `terminal` | Run shell commands (command allowlist via config) | | `SshExecTool` | `ssh_exec` | SSH into remote hosts; connection pool keyed by session ID | @@ -30,9 +30,12 @@ | `ListProfilesTool` | `list_profiles` | List all available profiles | | `ShareFileTool` | `share_file` | Copy an existing local file into session files and return a download link | | `ContentPublishTool` | `content_publish` | Register an existing session file for inline viewing in chat | -| `Model3DTool` | `model_3d` | Compile an OpenSCAD script into a binary STL file | -| `ScadLintTool` | `scad_lint` | Lightweight OpenSCAD source linting before STL compilation | -| `Render3DTool` | `render_3d` | Render preview PNG images from an STL file (up to 3 views) | +| `McpTool` (navi-3d) | `mcp:navi-3d:compile_scad` | Compile an OpenSCAD script into a binary STL file | +| `McpTool` (navi-3d) | `mcp:navi-3d:lint_scad` | Lightweight OpenSCAD source linting before STL compilation | +| `McpTool` (navi-3d) | `mcp:navi-3d:render_stl` | Render preview PNG images from an STL file (up to 3 views) | +| `McpTool` (navi-web) | `mcp:navi-web:web_search` | Web search (SearXNG primary, DDG fallback, Brave tertiary) | +| `McpTool` (navi-web) | `mcp:navi-web:web_view` | Open a URL in a headless browser and return clean readable text | +| `McpTool` (navi-web) | `mcp:navi-web:http_request` | Raw HTTP request (GET/POST/PUT/PATCH/DELETE) | | `DeleteToolTool` | `delete_tool` | Delete a user tool file | | `TestToolTool` | `test_tool` | Run a user tool and verify its output | | `McpStatusTool` | `mcp_status` | Check connectivity and list tools for configured MCP servers | diff --git a/docs/visual.html b/docs/visual.html index b3b2f24..57c3e40 100644 --- a/docs/visual.html +++ b/docs/visual.html @@ -872,10 +872,10 @@
- - + + - + @@ -1091,8 +1091,8 @@
stream_start
tool_started spawn_agent is_subagent=false
turn_thinking is_subagent=true
-
tool_started web_search is_subagent=true
-
tool_call web_search is_subagent=true
+
tool_started mcp:navi-web:web_search is_subagent=true
+
tool_call mcp:navi-web:web_search is_subagent=true
tool_started filesystem is_subagent=true
tool_call filesystem is_subagent=true
tool_call spawn_agent is_subagent=false
diff --git a/manuals/lint_scad.md b/manuals/lint_scad.md new file mode 100644 index 0000000..85404bf --- /dev/null +++ b/manuals/lint_scad.md @@ -0,0 +1,84 @@ +# mcp:navi-3d:lint_scad + +## Что делает + +Проверяет OpenSCAD-скрипт на типичные ошибки, которые часто допускают LLM при генерации кода: незакрытые скобки, отсутствующие точки с запятой, неправильные аргументы примитивов, устаревший синтаксис и т.д. + +## Предпосылки + +1. **Файл `.scad` уже должен существовать.** Напишите его заранее через `filesystem write`. + +## Формат вызова + +```python +mcp:navi-3d:lint_scad( + session_id="...", + source_path="bracket.scad" +) +``` + +## Параметры + +| Параметр | Обязательно | Описание | +|---|---|---| +| `session_id` | Да | UUID текущей сессии Navi. Файлы разрешаются внутри `session_files//`. | +| `source_path` | Да | Путь к существующему `.scad`-файлу (внутри сессии или абсолютный) | + +## Workflow + +### 1. Написать OpenSCAD-скрипт + +``` +filesystem write session_files/sess-abc/bracket.scad ' +difference() { + cube([40, 20, 5], center=true); + translate([15, 0, 0]) cylinder(h=6, d=4, center=true); +} +' +``` + +### 2. Запустить линтинг + +``` +mcp:navi-3d:lint_scad( + session_id="sess-abc", + source_path="bracket.scad" +) +``` + +### 3. Исправить ошибки + +Если линт нашёл проблемы — исправьте `.scad` через `filesystem edit` и запустите линт повторно. + +### 4. Компилировать + +После чистого линта: + +``` +mcp:navi-3d:compile_scad( + session_id="sess-abc", + source_path="bracket.scad", + output_path="bracket.stl" +) +``` + +## Что возвращает + +При успехе (ошибок нет): +``` +Lint passed: no issues found. +``` + +При ошибках: +``` +Lint errors (3): + line 7: missing semicolon after cylinder() + line 12: unexpected token '}' + line 15: unknown parameter 'radiu' in cylinder (did you mean 'r' or 'd'?) +``` + +## Важные правила + +1. **Всегда линт перед компиляцией** — это быстрее, чем ловить `openscad_compile_error`. +2. **Всегда передавайте `session_id`** — без него инструмент не знает, в какой директории искать файлы. +3. **Линт не проверяет логику** — только синтаксис и типичные LLM-ошибки. Физическую корректность проверяйте через превью. diff --git a/manuals/model_3d.md b/manuals/model_3d.md index 7ccfa71..3e86221 100644 --- a/manuals/model_3d.md +++ b/manuals/model_3d.md @@ -1,4 +1,4 @@ -# model_3d +# mcp:navi-3d:compile_scad ## Что делает @@ -14,9 +14,10 @@ ## Формат вызова ```python -model_3d( - scad_path="session_files/{session_id}/handle.scad", - output_path="session_files/{session_id}/handle.stl" +mcp:navi-3d:compile_scad( + session_id="...", + source_path="handle.scad", + output_path="handle.stl" ) ``` @@ -24,7 +25,8 @@ | Параметр | Обязательно | Описание | |---|---|---| -| `scad_path` | Да | Путь к существующему `.scad`-файлу | +| `session_id` | Да | UUID текущей сессии Navi. Файлы разрешаются внутри `session_files//`. | +| `source_path` | Да | Путь к существующему `.scad`-файлу (внутри сессии или абсолютный) | | `output_path` | Да | Путь, куда записать сгенерированный `.stl`. Родительские директории создаются автоматически. | ## Workflow @@ -41,16 +43,26 @@ ' ``` -### 2. Скомпилировать в STL +### 2. Проверить линтингом (рекомендуется) ``` -model_3d( - scad_path="session_files/sess-abc/bracket.scad", - output_path="session_files/sess-abc/bracket.stl" +mcp:navi-3d:lint_scad( + session_id="sess-abc", + source_path="bracket.scad" ) ``` -### 3. Показать пользователю +### 3. Скомпилировать в STL + +``` +mcp:navi-3d:compile_scad( + session_id="sess-abc", + source_path="bracket.scad", + output_path="bracket.stl" +) +``` + +### 4. Показать пользователю ``` content_publish(filename="bracket.stl", title="Bracket") @@ -70,9 +82,11 @@ - `scad_not_found` — исходный файл не найден - `openscad_compile_error` — ошибка компиляции (невалидный CSG, деление на ноль и т.д.) - `no_output` — OpenSCAD завершился без ошибок, но файл не создался +- `wrong_session_dir` — файл находится вне разрешённой сессии ## Важные правила 1. **Всегда binary STL** — нет параметра ASCII/binary, всегда используется `--export-format binstl`. -2. **Скрипт должен существовать до вызова** — `model_3d` не пишет `.scad`, только компилирует. -3. **Ошибки OpenSCAD** читаемы: строка, символ, тип ошибки — всё в stderr. +2. **Скрипт должен существовать до вызова** — `compile_scad` не пишет `.scad`, только компилирует. +3. **Всегда передавайте `session_id`** — без него инструмент не знает, в какой директории искать файлы. +4. **Ошибки OpenSCAD** читаемы: строка, символ, тип ошибки — всё в stderr. diff --git a/manuals/render_3d.md b/manuals/render_3d.md index fea1d75..2f05ac0 100644 --- a/manuals/render_3d.md +++ b/manuals/render_3d.md @@ -1,4 +1,4 @@ -# render_3d +# mcp:navi-3d:render_stl ## Что делает @@ -8,14 +8,15 @@ ## Предпосылки -1. **STL-файл уже должен существовать.** Сгенерируйте его через `model_3d` заранее. +1. **STL-файл уже должен существовать.** Сгенерируйте его через `mcp:navi-3d:compile_scad` заранее. 2. **OpenSCAD должен быть установлен.** ## Формат вызова ```python -render_3d( - source="session_files/{session_id}/bracket.stl", +mcp:navi-3d:render_stl( + session_id="...", + source_path="bracket.stl", views=["iso", "front", "top"] ) ``` @@ -24,7 +25,8 @@ | Параметр | Обязательно | Описание | |---|---|---| -| `source` | Да | Путь к существующему `.stl`-файлу | +| `session_id` | Да | UUID текущей сессии Navi. Файлы разрешаются внутри `session_files//`. | +| `source_path` | Да | Путь к существующему `.stl`-файлу (внутри сессии или абсолютный) | | `views` | Нет | Список ракурсов (макс. 3). Доступные: `front`, `back`, `top`, `bottom`, `left`, `right`, `iso`. По умолчанию `["iso"]`. | ## Доступные ракурсы @@ -44,14 +46,19 @@ ### 1. Сгенерировать STL ``` -model_3d(scad_path="...", output_path="...") +mcp:navi-3d:compile_scad( + session_id="sess-abc", + source_path="bracket.scad", + output_path="bracket.stl" +) ``` ### 2. Отрендерить ракурсы ``` -render_3d( - source="session_files/sess-abc/bracket.stl", +mcp:navi-3d:render_stl( + session_id="sess-abc", + source_path="bracket.stl", views=["iso", "front", "top"] ) ``` @@ -63,7 +70,7 @@ - `bracket.front.png` - `bracket.top.png` -Обычно эти PNG нужны Нави для внутренней проверки геометрии перед публикацией STL. Откройте их через `image_view` и проверьте форму, пропорции, печатную ориентацию и очевидные проблемы печати. +Обычно эти PNG нужны Нави для внутренней проверки геометрии перед публикацией STL. Откройте их через `image_view` и проверьте форму, пропорции и физическую корректность. Не публикуйте PNG пользователю, если пользователь явно не попросил preview-картинки. @@ -97,3 +104,4 @@ 3. **PNG сохраняются рядом с STL** — в той же директории, с суффиксом ракурса. 4. **Всегда preview mode** — быстрый рендер, не полный CSG. 5. **Не склеивает в сетку** — каждый ракурс — отдельный файл. PNG обычно нужны для внутренней проверки; публикуйте их только по явной просьбе пользователя. +6. **Всегда передавайте `session_id`** — без него инструмент не знает, в какой директории искать файлы. diff --git a/manuals/spawn_agent.md b/manuals/spawn_agent.md index a16cb4d..a444927 100644 --- a/manuals/spawn_agent.md +++ b/manuals/spawn_agent.md @@ -35,9 +35,9 @@ | Profile | Sub-agent tools | |---------|----------------| -| `secretary` | scratchpad, reflect, web_search, web_view, http_request, filesystem, code_exec, image_view, memory, share_file, weather | -| `server_admin` | scratchpad, reflect, web_search, http_request, filesystem, code_exec, terminal, ssh_exec, image_view, share_file | -| `developer` | scratchpad, reflect, web_search, web_view, http_request, filesystem, code_exec, terminal, image_view, reload_tools, test_tool, share_file | +| `secretary` | scratchpad, reflect, mcp:navi-web:web_search, mcp:navi-web:web_view, mcp:navi-web:http_request, filesystem, code_exec, image_view, memory, share_file, weather | +| `server_admin` | scratchpad, reflect, mcp:navi-web:web_search, mcp:navi-web:http_request, filesystem, code_exec, terminal, ssh_exec, image_view, share_file | +| `developer` | scratchpad, reflect, mcp:navi-web:web_search, mcp:navi-web:web_view, mcp:navi-web:http_request, filesystem, code_exec, terminal, image_view, reload_tools, test_tool, share_file | `spawn_agent` is always excluded — recursion is impossible. diff --git a/mcp-servers/navi-web/app/mcp_server.py b/mcp-servers/navi-web/app/mcp_server.py index 74aefe0..4f910bb 100644 --- a/mcp-servers/navi-web/app/mcp_server.py +++ b/mcp-servers/navi-web/app/mcp_server.py @@ -42,7 +42,7 @@ return Settings() -@mcp.tool(name="search") +@mcp.tool(name="web_search") async def search_tool( query: Annotated[str, Field(description="Search query.")], max_results: Annotated[int, Field(description="Number of results (default 5).")] = 5, @@ -52,7 +52,7 @@ return _json(result) -@mcp.tool(name="view") +@mcp.tool(name="web_view") async def view_tool( url: Annotated[str, Field(description="Full URL to open (must start with http:// or https://).")], screenshot: Annotated[bool, Field(description="Also capture a screenshot.")] = False, @@ -68,7 +68,7 @@ return _json(result) -@mcp.tool(name="request") +@mcp.tool(name="http_request") async def request_tool( method: Annotated[str, Field(description="HTTP method: GET, POST, PUT, PATCH, DELETE.")], url: Annotated[str, Field(description="Full URL to request.")], diff --git a/mcp_servers.json b/mcp_servers.json index 17f8a1a..854d3cb 100644 --- a/mcp_servers.json +++ b/mcp_servers.json @@ -58,13 +58,13 @@ }, "groups": { "search": [ - "search" + "web_search" ], "browse": [ - "view" + "web_view" ], "request": [ - "request" + "http_request" ] }, "instructions": "Navi Web MCP server provides web search, browsing, and raw HTTP tools.\n\nUse it when the task involves:\n- searching the web for current info, docs, or real-time data;\n- opening a URL in a browser to read human-readable content;\n- making REST API calls, webhooks, or raw HTTP requests.\n\nWorkflow:\n1. search — find relevant pages or facts.\n2. view — open promising URLs to read full content.\n3. request — call APIs or services requiring headers/auth.\n\nAll three tools are stateless and work with public URLs.\nNo session_id or filesystem paths are required.\n\nABSOLUTE RULE — NEVER bypass MCP tools:\nYou MUST NOT use filesystem, terminal, code_exec, or any direct file access to read or write web content. Use only the MCP tools listed above." diff --git a/navi/api/deps.py b/navi/api/deps.py index 57ca137..6685ff2 100644 --- a/navi/api/deps.py +++ b/navi/api/deps.py @@ -108,7 +108,7 @@ """Discover tools from all connected MCP servers and register them as external.""" # clear previous external MCP tools for name in list(registry._external_names): - if name.startswith("mcp_"): + if name.startswith("mcp:"): registry.unregister_external(name) tools = await manager.get_all_tools() diff --git a/navi/api/routes/agents.py b/navi/api/routes/agents.py index 1846e25..1de481a 100644 --- a/navi/api/routes/agents.py +++ b/navi/api/routes/agents.py @@ -53,14 +53,14 @@ names: list[str] = [] for server_name, groups in profile.mcp_servers.items(): if "*" in groups: - prefix = f"mcp_{server_name}_" + prefix = f"mcp:{server_name}:" for tool in tool_registry.all(): if tool.name.startswith(prefix) and tool.name not in names: names.append(tool.name) else: for group_name in groups: for tool_name in mcp_manager.resolve_group(server_name, group_name): - full_name = f"mcp_{server_name}_{tool_name}" + full_name = f"mcp:{server_name}:{tool_name}" if full_name not in names: names.append(full_name) return names diff --git a/navi/core/tool_executor.py b/navi/core/tool_executor.py index 3ecd938..33a51c9 100644 --- a/navi/core/tool_executor.py +++ b/navi/core/tool_executor.py @@ -24,7 +24,7 @@ bare_matches = [ (candidate_name, candidate) for candidate_name, candidate in tool_map.items() - if candidate_name.startswith("mcp_") and candidate_name.endswith(f"_{name}") + if candidate_name.startswith("mcp:") and candidate_name.endswith(f":{name}") ] if len(bare_matches) == 1: return bare_matches[0] @@ -33,7 +33,7 @@ normalized_matches = [ (candidate_name, candidate) for candidate_name, candidate in tool_map.items() - if candidate_name.startswith("mcp_") and candidate_name.replace("-", "_") == normalized + if candidate_name.startswith("mcp:") and candidate_name.replace("-", "_") == normalized ] if len(normalized_matches) == 1: return normalized_matches[0] diff --git a/navi/mcp/tools.py b/navi/mcp/tools.py index b938894..72aa371 100644 --- a/navi/mcp/tools.py +++ b/navi/mcp/tools.py @@ -27,7 +27,7 @@ self.description = description self.parameters = parameters self._manager = manager - self.name = f"mcp_{server_name}_{tool_name}" + self.name = f"mcp:{server_name}:{tool_name}" async def execute(self, params: dict[str, Any]) -> ToolResult: try: diff --git a/navi/profiles/developer/config.json b/navi/profiles/developer/config.json index 7347827..f4d707a 100644 --- a/navi/profiles/developer/config.json +++ b/navi/profiles/developer/config.json @@ -6,7 +6,7 @@ "full_description": { "specialization": "Full-stack software development: writing code in any language, debugging, running tests, working with files and project structure, git, APIs, scripting. Works on the user's own projects, not Navi's internals.", "when_to_use": "When the user wants to build something — a game, a script, an app, a web service, anything. For writing Navi tools specifically, use tool_developer instead.", - "key_tools": "filesystem, code_exec, terminal, mcp_navi-web_search, mcp_navi-web_view, spawn_agent" + "key_tools": "filesystem, code_exec, terminal, mcp:navi-web:web_search, mcp:navi-web:web_view, spawn_agent" }, "llm_backend": "ollama", "model": [ @@ -66,8 +66,8 @@ "mcp_servers": { "navi-web": [ "search", - "view", - "request" + "web_view", + "http_request" ] } } \ No newline at end of file diff --git a/navi/profiles/discuss/config.json b/navi/profiles/discuss/config.json index f08bc5f..b2c1f2b 100644 --- a/navi/profiles/discuss/config.json +++ b/navi/profiles/discuss/config.json @@ -30,8 +30,8 @@ ], "navi-web": [ "search", - "view", - "request" + "web_view", + "http_request" ] }, "subagent_tools": [], diff --git a/navi/profiles/discuss/system_prompt.txt b/navi/profiles/discuss/system_prompt.txt index 3f5ddfa..53f3bd9 100644 --- a/navi/profiles/discuss/system_prompt.txt +++ b/navi/profiles/discuss/system_prompt.txt @@ -18,7 +18,7 @@ ## Tools -Use `mcp_navi-web_search` + `mcp_navi-web_view` when a factual grounding would strengthen the discussion — not for every question, only when currency or precision matters. +Use `mcp:navi-web:web_search` + `mcp:navi-web:web_view` when a factual grounding would strengthen the discussion — not for every question, only when currency or precision matters. Use project `docs/` when discussing an active project. Prefer `docs/index.md` as the map, then query specific docs rather than rereading broad source trees. diff --git a/navi/profiles/modeler_3d/config.json b/navi/profiles/modeler_3d/config.json index 408ec4b..4ee27ea 100644 --- a/navi/profiles/modeler_3d/config.json +++ b/navi/profiles/modeler_3d/config.json @@ -6,7 +6,7 @@ "full_description": { "specialization": "Physically coherent 3D geometry and STL generation. Generates STL files from OpenSCAD through dedicated 3D tools, and validates with OpenSCAD compilation plus preview render inspection.", "when_to_use": "When the user needs a physical object modeled as 3D geometry: replacement parts, mechanical assemblies, decorative items, functional prototypes, jigs, fixtures, or custom enclosures.", - "key_tools": "spawn_agent, filesystem, mcp_navi-3d_lint_scad, mcp_navi-3d_compile_scad, mcp_navi-3d_render_stl, image_view, content_publish" + "key_tools": "spawn_agent, filesystem, mcp:navi-3d:lint_scad, mcp:navi-3d:compile_scad, mcp:navi-3d:render_stl, image_view, content_publish" }, "llm_backend": "ollama", "model": [ @@ -59,8 +59,8 @@ ], "navi-web": [ "search", - "view", - "request" + "web_view", + "http_request" ] }, "top_k": 30, diff --git a/navi/profiles/modeler_3d/subagent_system_prompt.txt b/navi/profiles/modeler_3d/subagent_system_prompt.txt index af8b329..3c1fd75 100644 --- a/navi/profiles/modeler_3d/subagent_system_prompt.txt +++ b/navi/profiles/modeler_3d/subagent_system_prompt.txt @@ -6,7 +6,7 @@ 1. Read the briefing and parent session context. 2. Identify the exact missing facts requested by the parent agent. -3. Use `mcp_navi-web_search`, `mcp_navi-web_view`, `filesystem`, and `image_view` as needed to gather evidence. +3. Use `mcp:navi-web:web_search`, `mcp:navi-web:web_view`, `filesystem`, and `image_view` as needed to gather evidence. 4. Prefer primary sources, product pages, datasheets, manuals, dimensions in local files, or images provided by the user. 5. Return only the facts found, source paths/URLs, confidence, and unresolved gaps. diff --git a/navi/profiles/modeler_3d/system_prompt.txt b/navi/profiles/modeler_3d/system_prompt.txt index d9e56c2..c4e7659 100644 --- a/navi/profiles/modeler_3d/system_prompt.txt +++ b/navi/profiles/modeler_3d/system_prompt.txt @@ -27,9 +27,9 @@ All MCP 3D tools require the exact Navi `session_id` so files are resolved inside `session_files//`. Pass the current session ID from context. 1. **`filesystem write`** — write the OpenSCAD script (`.scad`) to the session directory. -2. **`mcp_navi-3d_lint_scad`** — check the `.scad` source for common LLM mistakes before compiling. -3. **`mcp_navi-3d_compile_scad`** — compile the `.scad` into a binary `.stl`. -4. **`mcp_navi-3d_render_stl`** — generate PNG previews from several angles for your own inspection. +2. **`mcp:navi-3d:lint_scad`** — check the `.scad` source for common LLM mistakes before compiling. +3. **`mcp:navi-3d:compile_scad`** — compile the `.scad` into a binary `.stl`. +4. **`mcp:navi-3d:render_stl`** — generate PNG previews from several angles for your own inspection. 5. **`image_view`** — inspect each PNG so YOU can verify geometry. PNG previews are for Navi, not for the user. 6. **`content_publish`** — publish the final STL after internal checks pass. Include `source_filename` when a real `.scad` source exists in the same session directory. @@ -142,8 +142,8 @@ When the next step requires a tool, call the tool in the same assistant turn. Do not end a message with an announcement such as "I will now compile", "I am moving to publication", or "Next I will publish" unless you also make the required tool call in that same turn. - If the STL is ready to publish, call `content_publish` immediately instead of saying you are going to publish it. -- If the SCAD is ready to compile, call `mcp_navi-3d_compile_scad` immediately instead of saying you are going to compile it. -- If the SCAD was just written or edited, call `mcp_navi-3d_lint_scad` immediately before `mcp_navi-3d_compile_scad`. +- If the SCAD is ready to compile, call `mcp:navi-3d:compile_scad` immediately instead of saying you are going to compile it. +- If the SCAD was just written or edited, call `mcp:navi-3d:lint_scad` immediately before `mcp:navi-3d:compile_scad`. - If previews are ready to inspect, call `image_view` immediately instead of saying you are going to inspect them. - Only send a text-only progress message when you are blocked, need a user decision, or are reporting a completed tool result. @@ -154,7 +154,7 @@ - Never type, shorten, or reconstruct session IDs from memory. - Use the exact `Session files directory` from system context or from tool output. - Keep the `.scad`, compiled `.stl`, and preview PNGs in that same current session directory. -- Prefer simple filenames with `mcp_navi-3d_compile_scad` when possible; the tool resolves them inside the current session directory. +- Prefer simple filenames with `mcp:navi-3d:compile_scad` when possible; the tool resolves them inside the current session directory. - Choose the final basename before compiling, for example `wind_turbine_blades_100mm.scad` and `wind_turbine_blades_100mm.stl`. Avoid renaming after compilation unless necessary. - If `content_publish` returns `not_found`, read the exact directory named in its error, list that directory, then copy/move or recreate the file there before retrying. Do not keep listing or editing another `session_files/` directory. @@ -165,12 +165,12 @@ 3. **Plan physical geometry** — use `scratchpad` to store `design_plan` with scale, modules, axis convention, physical orientation, tolerances, weak points, and preview checks. 4. **Run parameter sanity check** — for functional, mechanical, or parametric fit parts, use `scratchpad` to store `parameter_sanity_check` before writing `.scad`. 5. **Write OpenSCAD yourself** — create or edit the `.scad` source with `filesystem write` or `filesystem edit`. The file must be clean, parameterized, in the session directory, and include the source comments contract. -6. **Lint OpenSCAD** — call `scad_lint(path="...scad")` after the file exists. Fix every error before compiling. Treat warnings as reasons to inspect and revise when they affect geometry or source cleanliness. +6. **Lint OpenSCAD** — call `mcp:navi-3d:lint_scad(session_id="...", source_path="...scad")` after the file exists. Fix every error before compiling. Treat warnings as reasons to inspect and revise when they affect geometry or source cleanliness. 7. **Research missing facts when useful** — if exact dimensions, reference images, or local documents are needed, call `spawn_agent` with a narrow research brief. Use the returned facts to update `technical_spec` or `design_plan`; do not ask the subagent to design, write, review, compile, render, or publish the model. -8. **Compile STL** — call `model_3d(scad_path=..., output_path=...)`. -9. **Handle compile result** — proceed only if `mcp_navi-3d_compile_scad` returns success. If it returns `openscad_compile_error`, `no_output`, `scad_not_found`, `wrong_session_dir`, or another error, fix the cause and compile again. -10. **Render previews** — call `render_3d(source="...stl", views=["iso","front","top"])` or other relevant views. -11. **Inspect every preview** — call `image_view` on every PNG path returned by `mcp_navi-3d_render_stl`. Do not publish PNG previews unless the user explicitly asks for preview images. +8. **Compile STL** — call `mcp:navi-3d:compile_scad(session_id="...", source_path="...scad", output_path="...stl")`. +9. **Handle compile result** — proceed only if `mcp:navi-3d:compile_scad` returns success. If it returns `openscad_compile_error`, `no_output`, `scad_not_found`, `wrong_session_dir`, or another error, fix the cause and compile again. +10. **Render previews** — call `mcp:navi-3d:render_stl(session_id="...", source_path="...stl", views=["iso","front","top"])` or other relevant views. +11. **Inspect every preview** — call `image_view` on every PNG path returned by `mcp:navi-3d:render_stl`. Do not publish PNG previews unless the user explicitly asks for preview images. 12. **Run preview checklist** — compare all inspected previews against `technical_spec` and `design_plan`. Record the checklist result in `scratchpad` section `preview_check`. 13. **Revise before publishing** — if lint, compilation output, researched facts, or preview inspection reveals a substantial issue, edit the `.scad`, lint again, recompile, re-render, and inspect again. 14. **Publish final STL** — after the model passes the geometry gate, call `content_publish(filename="...stl", content_type="stl", source_filename="...scad")`. This step is mandatory for a successful task. @@ -206,10 +206,10 @@ - Functional, mechanical, and parametric fit parts have a `scratchpad` `parameter_sanity_check` confirming interface dimensions and formulas are internally consistent. - The final `.stl` and `.scad` source are in the current session files directory, not another `session_files/` directory. - The STL compiled successfully. -- Every preview image returned by `mcp_navi-3d_render_stl` was inspected with `image_view`; inspecting only `iso` is not enough. +- Every preview image returned by `mcp:navi-3d:render_stl` was inspected with `image_view`; inspecting only `iso` is not enough. - `scratchpad` section `preview_check` exists and says `Revision required: no`, or records the revision that was made after a failed check. -- OpenSCAD warnings/errors from `mcp_navi-3d_compile_scad` or `mcp_navi-3d_render_stl` were handled instead of ignored. -- `mcp_navi-3d_lint_scad` was run on the final `.scad`, and all lint errors were fixed before compilation. +- OpenSCAD warnings/errors from `mcp:navi-3d:compile_scad` or `mcp:navi-3d:render_stl` were handled instead of ignored. +- `mcp:navi-3d:lint_scad` was run on the final `.scad`, and all lint errors were fixed before compilation. - Any subagent use was limited to gathering missing factual information from web pages, local files, or images. The main agent made all modeling decisions. - For functional fit parts, exact compatibility dimensions are either verified, provided by the user, or the artifact is explicitly labeled as a parametric template that requires user measurements. diff --git a/navi/profiles/secretary/config.json b/navi/profiles/secretary/config.json index 94b397b..876d6ab 100644 --- a/navi/profiles/secretary/config.json +++ b/navi/profiles/secretary/config.json @@ -6,7 +6,7 @@ "full_description": { "specialization": "General-purpose personal assistant. Web research, document writing, data analysis, email correspondence, planning, calculations, and any everyday task that doesn't require direct server access or tool development.", "when_to_use": "Default profile for most requests. If you're unsure which profile to use, this one is correct. Switch away only when the task clearly requires server/infrastructure access (server_admin) or modifying Navi's own tools (developer).", - "key_tools": "mcp_navi-web_search, mcp_navi-web_view, filesystem, code_exec, gmail, todo, scratchpad, spawn_agent, memory" + "key_tools": "mcp:navi-web:web_search, mcp:navi-web:web_view, filesystem, code_exec, gmail, todo, scratchpad, spawn_agent, memory" }, "llm_backend": "ollama", "model": [ @@ -65,8 +65,8 @@ "mcp_servers": { "navi-web": [ "search", - "view", - "request" + "web_view", + "http_request" ] } } \ No newline at end of file diff --git a/navi/profiles/secretary/system_prompt.txt b/navi/profiles/secretary/system_prompt.txt index 4409b97..488dc14 100644 --- a/navi/profiles/secretary/system_prompt.txt +++ b/navi/profiles/secretary/system_prompt.txt @@ -69,11 +69,11 @@ --- ## Tool priorities -1. mcp_navi-web_search — first choice for current info, facts, documentation. +1. mcp:navi-web:web_search — first choice for current info, facts, documentation. 2. code_exec — calculations, data processing, text parsing, format conversion. -3. mcp_navi-web_view — view a specific page in full. +3. mcp:navi-web:web_view — view a specific page in full. 4. filesystem — read/write local documents, notes, data files. -5. mcp_navi-web_request — external APIs, webhooks, content not suited for search. +5. mcp:navi-web:http_request — external APIs, webhooks, content not suited for search. 6. image_view — whenever an image path or URL is mentioned. ## Output style diff --git a/navi/profiles/server_admin/config.json b/navi/profiles/server_admin/config.json index 4a404cc..b164207 100644 --- a/navi/profiles/server_admin/config.json +++ b/navi/profiles/server_admin/config.json @@ -6,7 +6,7 @@ "full_description": { "specialization": "Remote server operations via SSH, system diagnostics, service management, log analysis, network troubleshooting, process monitoring, and infrastructure automation.", "when_to_use": "When the task involves SSH access to servers, running system commands, managing Linux services, analyzing logs, monitoring resources, or any hands-on infrastructure work.", - "key_tools": "ssh_exec, terminal, filesystem, code_exec, mcp_navi-web_search, spawn_agent, memory" + "key_tools": "ssh_exec, terminal, filesystem, code_exec, mcp:navi-web:web_search, spawn_agent, memory" }, "llm_backend": "ollama", "model": [ @@ -64,8 +64,8 @@ ], "navi-web": [ "search", - "view", - "request" + "web_view", + "http_request" ] }, "planning_mandatory": false, diff --git a/navi/profiles/server_admin/system_prompt.txt b/navi/profiles/server_admin/system_prompt.txt index 08ad591..419d8dd 100644 --- a/navi/profiles/server_admin/system_prompt.txt +++ b/navi/profiles/server_admin/system_prompt.txt @@ -46,7 +46,7 @@ 6. **Synthesise** — after all agents report back, write your conclusions and next steps. ### Plan → execution binding -- **TOOL** — direct local call (terminal, filesystem, mcp_navi-web_request for health checks). +- **TOOL** — direct local call (terminal, filesystem, mcp:navi-web:http_request for health checks). - **AGENT** — call `spawn_agent` for THIS STEP ONLY. One AGENT step = one spawn_agent call. If your plan has steps 1, 2, 3 all marked AGENT — you make three separate spawn_agent calls. Never bundle multiple steps into one call. Never pass your full plan to a single subagent. @@ -80,8 +80,8 @@ 1. ssh_exec — direct single-command checks on known hosts when spawning is overkill. 2. terminal — local machine operations. 3. filesystem — local config files, scripts. -4. mcp_navi-web_request — health check endpoints, REST APIs. -5. mcp_navi-web_search — error lookups, documentation. +4. mcp:navi-web:http_request — health check endpoints, REST APIs. +5. mcp:navi-web:web_search — error lookups, documentation. ## Execution environment `terminal`, `filesystem`, and `code_exec` run on the LOCAL machine (where Navi's server is running) — NOT on any remote host. diff --git a/navi/tools/reload_tools.py b/navi/tools/reload_tools.py index 63792f3..a7a4edf 100644 --- a/navi/tools/reload_tools.py +++ b/navi/tools/reload_tools.py @@ -61,7 +61,7 @@ await self._mcp_manager.reload_all() from navi.api.deps import register_mcp_tools await register_mcp_tools(self._registry, self._mcp_manager) - mcp_tools = [t.name for t in self._registry.all() if t.name.startswith("mcp_")] + mcp_tools = [t.name for t in self._registry.all() if t.name.startswith("mcp:")] lines.append(f"MCP tools ({len(mcp_tools)}): {', '.join(mcp_tools) or 'none'}") except Exception as exc: has_errors = True diff --git a/tests/unit/core/test_tool_executor.py b/tests/unit/core/test_tool_executor.py index 8dcc719..aa5e180 100644 --- a/tests/unit/core/test_tool_executor.py +++ b/tests/unit/core/test_tool_executor.py @@ -9,7 +9,7 @@ class TestToolExecutorMcpAliases: async def test_executes_bare_mcp_tool_alias(self): registry = ToolRegistry() - tool = FakeTool("mcp_gnexus-book_search_docs") + tool = FakeTool("mcp:gnexus-book:search_docs") registry.register(tool, builtin=True) executor = ToolExecutor(registry) @@ -19,20 +19,20 @@ ) assert images == [] - assert messages[0].name == "mcp_gnexus-book_search_docs" - assert messages[0].content == "executed mcp_gnexus-book_search_docs" + assert messages[0].name == "mcp:gnexus-book:search_docs" + assert messages[0].content == "executed mcp:gnexus-book:search_docs" async def test_executes_mcp_tool_alias_with_underscore_server_name(self): registry = ToolRegistry() - tool = FakeTool("mcp_gnexus-book_search_docs") + tool = FakeTool("mcp:gnexus-book:search_docs") registry.register(tool, builtin=True) executor = ToolExecutor(registry) messages, images = await executor._execute_tool_calls( - [ToolCallRequest(id="1", name="mcp_gnexus_book_search_docs", arguments={"query": "git"})], + [ToolCallRequest(id="1", name="mcp:gnexus_book:search_docs", arguments={"query": "git"})], [tool], ) assert images == [] - assert messages[0].name == "mcp_gnexus-book_search_docs" - assert messages[0].content == "executed mcp_gnexus-book_search_docs" + assert messages[0].name == "mcp:gnexus-book:search_docs" + assert messages[0].content == "executed mcp:gnexus-book:search_docs" diff --git a/tests/unit/test_mcp.py b/tests/unit/test_mcp.py index 86f6530..f6b7424 100644 --- a/tests/unit/test_mcp.py +++ b/tests/unit/test_mcp.py @@ -105,7 +105,7 @@ parameters={"type": "object", "properties": {}}, manager=mock_manager, ) - assert tool.name == "mcp_gnexus-book_search_docs" + assert tool.name == "mcp:gnexus-book:search_docs" async def test_execute_success(self): mock_manager = AsyncMock(spec=McpManager)
NameClassDescription
web_searchWebSearchToolDuckDuckGo web search
web_viewWebViewToolFetch and render a URL as text
mcp:navi-web:web_searchMcpToolWeb search (SearXNG primary, DDG fallback, Brave tertiary)
mcp:navi-web:web_viewMcpToolOpen a URL in a headless browser and return clean text
filesystemFilesystemToolRead/write/list local files (path allowlist via config)
http_requestHttpRequestToolGeneric HTTP client — GET/POST/PUT/etc.
mcp:navi-web:http_requestMcpToolRaw HTTP request — GET/POST/PUT/PATCH/DELETE
code_execCodeExecToolExecute Python in a subprocess sandbox
terminalTerminalToolRun shell commands (command allowlist via config)
ssh_execSshExecToolSSH into remote hosts; connection pool keyed by session ID