Follow-up fixes from code review of the MCP client skill (10bf9655).
Correctness:
- Force a text answer on loop exhaustion: the final synthesis call now passes no tools (so the model can't request more calls it can't run) and returns a fallback message instead of an empty string.
- Tolerate an empty tools list in every generate_with_tools (openai, anthropic, gemini, xai, ollama, llama_cpp) — required by the above and avoids provider APIs rejecting an empty tools array. the same tool don't collide; drop a shadowed local json import.
Ollama:
- Extract message normalization into _normalize_messages_for_ollama and preserve the tool name as tool_name so models can match results to calls on parallel tool use; guard the request-side json parse.
- Thread the preset's think and num_predict through the tool-calling payload so they're actually honored (previously used chat defaults).
- Add qwen3.5-4b-cpu preset for testing the agent on CPU. Tests (new, no live MCP server / network needed):
- MCPClientManager: namespacing, allowlist, arg validation, result cap.
- Provider message conversion: gemini ($schema strip, content round-trip, thought_signature preservation), anthropic, ollama normalization.
- MCPAgentStep loop incl. the exhaustion/empty-text paths.