(t *testing.T)
| 296 | } |
| 297 | |
| 298 | func TestBuildMCPToolsSection(t *testing.T) { |
| 299 | tools := []models.ToolDefinition{ |
| 300 | {Function: models.ToolFunctionDef{Name: "mcp_read_file", Description: "[MCP:fs] read"}}, |
| 301 | {Function: models.ToolFunctionDef{Name: "mcp_list_dir", Description: "[MCP:fs] list"}}, |
| 302 | } |
| 303 | coder := buildMCPToolsSection(tools, true) |
| 304 | agent := buildMCPToolsSection(tools, false) |
| 305 | |
| 306 | for _, s := range []string{coder, agent} { |
| 307 | if !strings.Contains(s, "MCP Tools (external):") { |
| 308 | t.Errorf("missing header in section:\n%s", s) |
| 309 | } |
| 310 | if !strings.Contains(s, "mcp_read_file") || !strings.Contains(s, "mcp_list_dir") { |
| 311 | t.Errorf("missing tool entry in section:\n%s", s) |
| 312 | } |
| 313 | // The section must route schema discovery through @tools describe — |
| 314 | // never blind invocation (a schemaless call to a no-required-params |
| 315 | // tool EXECUTES it as a side effect of "discovery"). |
| 316 | if !strings.Contains(s, `name=\"@tools\"`) && !strings.Contains(s, `name="@tools"`) { |
| 317 | t.Errorf("section must teach @tools describe for MCP schemas:\n%s", s) |
| 318 | } |
| 319 | } |
| 320 | // Coder mode must reference @coder fallback; agent mode must not. |
| 321 | if !strings.Contains(coder, "@coder") { |
| 322 | t.Errorf("coder section missing @coder fallback hint:\n%s", coder) |
| 323 | } |
| 324 | if strings.Contains(agent, "@coder") { |
| 325 | t.Errorf("agent section should not reference @coder:\n%s", agent) |
| 326 | } |
| 327 | } |
| 328 | |
| 329 | func TestBuildMCPEmptyNote(t *testing.T) { |
| 330 | if got := buildMCPEmptyNote(nil); got != "" { |
nothing calls this directly
no test coverage detected