LLM Routing Service - Routes requests to different LLM providers based on configuration. An MCP server that provides tool execution, script execution, resource management, and prompt handling via Scriptling.
LLMRouter exposes 3 tools with significant quality gaps. Tool naming follows verb_noun convention (execute_tool, tool_search, execute_script), which is a positive baseline. However, descriptions are present but generic, and critically, NO input schemas are visible in the provided source code. The execute_script tool accepts arbitrary code with minimal validation guidance. Parameter descriptions exist but lack detail about constraints, formats, and error recovery. The server appears to conflate server-registered tools with external tool routing, creating conceptual confusion. Error handling is not evident from the provided code. Overall, the definitions lack the rigor expected for production MCP servers.
Execute Scriptling code and return the result. Scriptling is a Python 3-like scripting language. KEY SYNTAX RULES: Use True/False (capitalized), None for null. Use elif (not else if). 4-space indentation for blocks. No nested classes, no multiple inheritance, no generators/yield. HTTP & JSON: HTTP response is an object: response.status_code, response.body, response.headers. Use json.loads(str) and json.dumps(obj) for JSON. Use msgpack.packb(obj) and msgpack.unpackb(bytes) for MessagePack binary serialization. Use requests.get(url, options), requests.post(url, body, options) for HTTP. Default HTTP timeout is 5 seconds. HTTP options dict: {"timeout": 10, "headers": {"Authorization": "Bearer token"}}. COMMON PATTERNS: Dict iteration: for item in items(dict): key=item[0], value=item[1]. List append: append(list, item) modifies in-place. Use join() for string building in loops: result = "".join(parts). Error handling: try/except/finally, raise "message" or raise ValueError("msg"). RETURNING RESULTS: print() output is captured and returned automatically. For structured data: import scriptling.mcp.tool; tool.return_object(data). For text: tool.return_string(text). Use help(topic) for built-in help: help("builtins"), help("json"), help("requests").
Execute a tool via the MCP server. This is a server-registered tool that executes named tools through the MCP interface.
Search for available tools. This is a server-registered tool that allows searching through available MCP tools.
NO visible input schemas for any of the 3 tools. The source excerpt shows parameter descriptions ('name', 'arguments', 'code') but NO formal JSON Schema definitions (type, required, format, constraints).
execute_script tool accepts arbitrary code execution ('Scriptling code') with minimal validation or sandbox description. Description includes extensive syntax rules (True/False, 4-space indentation, HTTP/JSON/msgpack patterns) but does NOT explain: what happens on syntax error? What are resource limits? Is there a timeout? Can it access the filesystem? This is a WRITE/IRREVERSIBLE tool that requires clear error guidance and safety boundaries.
execute_tool description is circular and vague: 'Execute a tool via the MCP server. This is a server-registered tool that executes named tools through the MCP interface.' It does NOT explain: which tools can be executed? How does it differ from calling tools directly? When should an LLM use this vs. tool_search? Does it return the raw tool result or transform it?
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | F | 47 | 2026-07-28+ | v2 |
| 2026-03-09 | F | 33 | - | v1 |
tool_search description is minimal (48 chars): 'Search for available tools. This is a server-registered tool that allows searching through available MCP tools.' It lacks: what search criteria does it accept (name, keyword, capability)? What fields does it return? What happens if no tools match?
execute_tool parameter 'arguments' is optional with type 'object' but NO constraints on its structure. What happens if invalid JSON is passed? Should the LLM validate it first? Does the tool return which argument was invalid?
No output schemas documented. What does execute_tool return? A raw tool result? What fields? What does tool_search return, a list of tool objects? With what properties (name, description, inputSchema)? Without documented return types, LLMs cannot plan downstream usage or extract relevant data.
No error handling or recovery guidance visible. What error categories does execute_tool emit? If a tool name is not found, what message is returned? Can the LLM retry? Should it call tool_search first? No actionable error messages detected.
execute_script tool is marked IRREVERSIBLE but provides NO confirmation/dry-run pattern. If code calls DELETE or sends requests, there is no undo path. The description does not warn about consequences or suggest when to request user confirmation.