Semantic router for MCP ecosystems - Discover and execute tools across multiple MCP servers without context bloat
OmniMCP exhibits mixed definition quality with several structural issues. Tool naming follows verb_noun conventions adequately (semantic_router, search_tools, execute_tool, etc.), but descriptions vary widely in depth and utility. The `semantic_router` tool is a meta-gateway combining 9+ operations into a single overloaded parameter, violating the single-responsibility principle. Parameter descriptions are present for most tools but often generic. Schemas are visible but several tools lack critical validation constraints. Error handling is basic (try/except wrapped in TextContent responses) without actionable recovery guidance. No tool annotations (readOnlyHint, destructiveHint) despite clear risk classifications provided in the evaluation context.
Run tools on active servers with optional background execution support
Retrieve offloaded content (large text chunks, images, audio) by reference ID. Supports chunked content retrieval.
View detailed server capabilities, limitations, and tool count
Get complete tool schema and description before execution. Includes warnings for blocked tools.
Show currently active server sessions ready for tool execution
See all tools available on a specific server with pagination support
semantic_router violates single-responsibility principle: combines 9 distinct operations (search_tools, get_server_info, list_server_tools, get_tool_details, manage_server, list_running_servers, execute_tool, poll_task_result, get_content) into one tool via operation enum. This forces LLM reasoning overhead and splits what should be separate composable tools. The 23-parameter input schema is a code smell for poor separation of concerns.
Output schemas are not documented. Tools return ToolResult(content=[TextContent(...)]) but the actual structure of the content, field names, types, pagination formats, is not specified. LLMs cannot plan downstream calls or extract structured data without knowing what fields to expect.
Inferred effective spec: <=2025-11-25.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | C | 61 | <=2025-11-25 | v2 |
| 2026-03-09 | C | 64 | - | v1 |
Start or shutdown MCP server sessions
Check status and retrieve results of background tasks
Discover tools/servers using natural language queries with semantic ranking. Supports query enhancement with LLM and filtering by server names and scope.
Universal gateway to the Pulsar MCP ecosystem. Execute any MCP operation through a single unified interface. Supports search_tools, get_server_info, list_server_tools, get_tool_details, manage_server, list_running_servers, execute_tool, poll_task_result, and get_content operations.
Error handling returns raw exception strings wrapped in TextContent (e.g., 'Execution failed: {str(e)}' in execute_tool.py). No actionable recovery guidance. Errors should categorize as retryable/user-fixable/fatal and offer next-step hints (e.g., 'Server not running. Try manage_server("server_name", "start") first').
Tool annotations missing. execute_tool, manage_server, and other destructive/non-idempotent operations lack readOnlyHint, destructiveHint, or idempotentHint in schema. This prevents LLM frameworks from applying appropriate safety guardrails.
Parameter descriptions lack validation constraints. E.g., 'limit' parameter in search_tools has no bounds (min/max). 'timeout' in execute_tool defaults to 60s but no constraint range specified. LLMs pass absurd values (limit=999999, timeout=0.001) without explicit min/max constraints.
list_server_tools and search_tools accept 'limit' and 'offset' but output schema is undocumented. LLM cannot verify if total_count is returned or construct next-cursor for pagination. Pagination pattern incomplete.
Tool descriptions lack 'WHEN to use' context. E.g., list_running_servers description is 'Show currently active server sessions ready for tool execution' but doesn't explain: call this after manage_server('start'), or use this to check availability before execute_tool. Agents must infer dependencies.
execute_tool accepts 'arguments' as a free-form dict but no schema for the expected structure. LLM must blindly pass arguments matching the target tool's schema, but if arguments are malformed, the error is cryptic. Validate arguments early and return field-level error guidance.
manage_server accepts 'action' enum with only two values (start, shutdown). No validation error shown if LLM passes 'restart' or 'status'. Constraint is defined but error message if violated is not documented.