Static source inference · medium confidence · evidence: Apps extension
Current-spec patterns detected
Summary
simply-mcp demonstrates foundational MCP tool infrastructure with TypeScript type safety, but exhibits pervasive definition quality issues. Tool naming follows conventions (verb_noun pattern) and input schemas are generally present with JSON Schema structure, but lack of parameter constraints (enums, ranges) and missing output documentation significantly undermines LLM usability. The framework itself is well-engineered (createTool, createSkill, createResource abstractions), but tool definitions feel more like example fixtures than production-ready agents. Average per-tool score: 52 across 26 tools, dragged down by missing descriptions, minimal parameter constraints, and zero output schema documentation.
Tools (26)
add_toolread only50/100
Add two numbers together
analyze_patternsread onlysource verified72/100
Analyze code for patterns and anti-patterns
analyze_toolread only50/100
Analyze data using external Python script
batch_process_toolread only50/100
Process multiple items
calculate_toolread only50/100
Perform a calculation
check_securityread onlysource verified73/100
Check code for security vulnerabilities
checksum_toolread only50/100
Compute SHA-256 of provided text and return the digest as raw bytes
Missing output schema documentation across all 26 tools. No tool documents what fields the LLM should expect in the response, forcing LLMs to guess at return structure and preventing proper chaining of tool calls.
Tool 'ping' (examples/oversized-description.ts) has no description.
ping
Recommendations
Add documented output schemas for every tool. Include a 'Returns' section in each tool definition (or via JSON Schema definition) specifying field names, types, and what they represent. Example: 'Returns {status: string, deployed_version: string, timestamp: ISO8601, service_name: string}'.
Expand tool descriptions from 1 sentence to 2-3 sentences following the pattern: WHAT (what does it do), WHEN (when should I call it), WHAT HAPPENS (what does it return, are there side effects?). Target 50 - 200 characters per description. Example for deploy_service: 'Deploy a named service to a target environment. Use this after validating the service is ready in staging. Returns the deployed version number, environment, and deployment timestamp. This is a write operation, use with caution.'
Add enum constraints to all parameters with a known set of valid values. For calculate_tool, change operation from string to enum: {type: 'string', enum: ['add', 'subtract', 'multiply', 'divide']}. For analyze_tool, keep algorithm enum explicit. For weather tools, severity constraint is already present in check_security; apply similar rigor across the board.
Document every parameter with explicit constraints. For numeric parameters (x in double_tool, n in torch_predict_tool), add minValue and maxValue. For string parameters (key in lookup_tool), describe valid format: 'Key to look up (alphanumeric, 1-64 chars, case-sensitive). Example: user_12345'.
Implement error recovery guidance in all tool descriptions. For lookup_tool: 'Look up data by key. If key not found, check the available keys via list_keys(). Returns the data value or an error message identifying why the lookup failed.' For delete_user_tool: 'Delete a user account permanently. This is irreversible, consider archiving instead if user history must be preserved. Requires explicit user_id match.'
Spec posture evidence
Inferred effective spec: 2026-07-28+.
Current-spec patterns present: tool annotations
Score history
Overall score trend
First recorded score · v2 rubric
47/100
Scored
Grade
Overall
Spec posture
Rubric
2026-09-23
F
47
2026-07-28+
v2
73/100
Deploy a named service to an env.
double_toolread only50/100
Double a number using Python
double_typescript_toolread only50/100
Double a number using TypeScript
execute_codewriteauth50/100
Execute arbitrary code (requires elevated scope)
get_forecast_toolread only50/100
Get weather forecast
get_weather_toolread only50/100
Get weather for a location
greet_toolread only50/100
Greet a user
greet_toolread only50/100
Greet someone by name
lookup_toolread only50/100
Look up data by key
ml_predict_toolread only50/100
Run ML prediction (requires numpy/sklearn)
pingread only37/100
ping_toolread onlysource verified53/100
Health check endpoint
release_notesread onlysource verified72/100
Draft a release-notes blurb from a PR number.
send_email_toolwrite50/100
Send an email to a user
statistics_toolread only50/100
Calculate basic statistics for a list of numbers
torch_predict_toolread only50/100
Run a torch tensor op (pool mode — first call cold, rest warm)
void_paymentirreversiblesource verified68/100
Void a customer payment using the tier-specific approval code.
Many parameters lack enum constraints where applicable (e.g., 'operation' in calculate_tool accepts 'add|subtract|multiply|divide' but is string; 'units' in get_weather_tool accepts 'celsius|fahrenheit' and IS enum, inconsistency). Free-form strings invite hallucinated values.
Parameter descriptions are inconsistent in specificity. 'Look up data by key' (lookup_tool) does not explain format, range, or valid key structure. Compare to 'Number to double' (double_tool), both need richer context about constraints and expected input format.
Destructive tools (delete_user_tool, void_payment, execute_code) lack confirmation/dry-run capability and have no guidance on recovery. Tool descriptions do not warn that these are irreversible or suggest undo steps.
Tool 'who_am_i' has minimal description ('Show current user info from JWT claims') and no parameter documentation about which claims are returned or how to use the response. LLMs cannot determine when this is the right tool to call.
Error handling guidance is absent or minimal across all tools. No tool documents what errors might occur (e.g., 'User not found'), how to recover, or what to do next. Void_payment handler includes validation logic but does not expose these errors through schema or description.
Duplicate tool name 'greet_tool' appears in examples/complete.ts and examples/minimal.ts, creating ambiguity. LLMs cannot disambiguate which greet_tool to call when both are registered.
Tools that return lists (batch_process_tool, analyze_patterns) do not document pagination, limits, or result count. No indication of whether 50, 500, or unlimited items can be returned.
Tools: 'ping_tool' (20 chars: 'Health check endpoint'), 'lookup_tool' (18 chars: 'Look up data by key'), 'torch_predict_tool' (43 chars but vague: 'Run a torch tensor op (pool mode, first call cold, rest warm)'), 'who_am_i' (43 chars: 'Show current user info from JWT claims').
ping_toollookup_toolwho_am_i
Add a dry-run or confirmation mode for destructive tools (delete_user_tool, void_payment, execute_code). Example: add a boolean 'confirm_destructive' parameter, defaulting to false. When false, return 'Would delete user U12345. Set confirm_destructive=true to proceed.' This prevents accidental irreversible actions.
Rename or alias the duplicate 'greet_tool' in examples/minimal.ts to 'greet_user_minimal' or remove it. Single canonical tools per function reduce LLM decision fatigue.
Document pagination and result limits. For batch_process_tool, add a description: 'Process multiple items (max 100 per call). Returns success/failure per item. If batch > 100, paginate via offset parameter.' For statistics_tool, add: 'Analyze 1 - 10,000 numbers. Returns count, sum, min, max, mean as a single result object (no pagination required).'
For tools that accept natural identifiers (usernames, emails), expand descriptions to show acceptance of both. Example for who_am_i: 'Retrieve current user info from JWT claims. Returns user_id, email, display_name, roles, and scope. Use before executing privileged operations to verify permissions.'
Audit all parameter descriptions for vagueness. Replace 'Items to process' (batch_process_tool) with 'Array of items to process (1 - 100 per call). Each item is a string identifier (max 256 chars). Returns per-item success/failure status.' This enables the LLM to understand constraints and error handling.
Add scope declarations to security-sensitive tools. Example for execute_code: 'Requires elevated scope. Executes arbitrary code with the server's runtime permissions. Logs all calls for audit. Use only for trusted LLM agents.' For send_email_tool: 'Requires write:email scope. Sends an email immediately, no undo available after send. Verify recipient before calling.'
For tools returning structured data (get_weather_tool, get_forecast_tool), document the exact schema. Example: 'Returns {location: string, temperature: number, unit: string, description: string, wind_speed: number, humidity: number, last_updated: ISO8601_timestamp}'.