MCP server provides 4 tools for architectural decision tracking with reasonable structure but significant gaps in parameter validation, error messaging, and output documentation. All tools have descriptions and visible input schemas with type definitions, placing them above the median community server. However, parameter descriptions lack actionable constraints, output schemas are not formally documented, error responses do not guide recovery, and there are no tool annotations or security considerations evident. The implementation is functional but lacks polish needed for production confidence.
Tools (4)
query-decisionsread onlysource verified67/100
Search prior decisions by keyword, technology, or domain
record-decisionwritesource verified75/100
Register a technical decision with problem, solution, alternatives, and technologies
record-outcomewritesource verified72/100
Close the loop with actual results and accuracy score
Output schemas not documented in tool definitions. Callers cannot know what fields to expect from tool responses (e.g., record-decision returns decision_id, prediction_ids, status, but this is inferred from code, not explicit in schema). LLMs cannot plan downstream operations without knowing response structure.
Parameter descriptions lack actionable constraints. 'predicted_value' is described as 'The predicted value or outcome (e.g., '< 100ms', '$50k/month', '99.99% uptime')' but the description includes examples, which LLMs tend to reuse literally, rather than formal constraints. 'accuracy_score' accepts 0-100 but no guidance on what scores mean until you read the function body (>=90 SUCCESS).
Error responses do not guide recovery. record_prediction returns {'error': f'decision_id not found: {decision_id}'} but does not suggest that the LLM should call query-decisions to find valid decision IDs. Without recovery guidance, agents hit dead ends.
Recommendations
Document explicit output schemas for all tools. Add 'returns' sections to tool descriptions or include a returnSchema field in the MCP tool definition. Example for record-decision: 'Returns: {decision_id (string), prediction_ids (array of strings), status (string)}'. This enables LLMs to plan downstream operations.
Replace example values in parameter descriptions with formal constraints. Change 'predicted_value: The predicted value or outcome (e.g., \'< 100ms\', \'$50k/month\', \'99.99% uptime\')' to 'predicted_value: A measurable outcome as a string. No format constraint; examples for reference: \'< 100ms\' (latency), \'$50k/month\' (cost), \'99.99% uptime\' (reliability). LLM should select format matching prediction_type.'
Enhance error messages with recovery guidance. When record_prediction returns error for missing decision_id, include: 'error': 'decision_id not found: DEC-2024-0042. Call query-decisions() to list valid decision IDs, or create a new decision with record-decision().'
Add tool annotations to all tool definitions. Mark query-decisions with readOnlyHint=true. Mark record-decision, record-prediction, record-outcome with destructiveHint=true. If record-decision and record-prediction are idempotent (same decision+prediction always produces the same ID), add idempotentHint=true.
Document pagination in query-decisions. Update tool description to state: 'Limits results to max_results (default 5, max 100). If more matches exist, results are sorted by timestamp descending. Call again with higher max_results to paginate.' Add a note in return schema: 'result_count (integer), number of results returned; total_matches (integer), total decisions matching query; if total_matches > result_count, paginate.'
No tool annotations (readOnlyHint, destructiveHint, idempotentHint). query-decisions should be marked read-only; record-decision/record-prediction/record-outcome are destructive (append to log). Without annotations, agents cannot reason about safety, retry logic, or side effects.
query-decisions lacks pagination and limit enforcement. Parameters accept max_results (default 5) but no documentation of total results, no cursor/offset, and no statement in tool description that results are capped. If query matches thousands of decisions, the response could explode the context window.
Parameter 'predictions' in record-decision is an array of objects with nested schema, but the nested object structure (with 'prediction_type' and 'predicted_value' keys) is not described in parameter documentation. Only visible by reading the function code.
No validation or error handling for invalid enum values. If an LLM passes prediction_type='INVALID' instead of one of the 7 enum options, the code silently accepts it and stores the invalid value. Should return 'Invalid prediction_type. Must be one of: LATENCY, COST, SCALABILITY, DATA_QUALITY, RELIABILITY, MAINTAINABILITY, BUSINESS_IMPACT'.
File system path exposure. LOG_PATH defaults to ~/.local/share/mcp-decisions/decisions_log.json and can be overridden via MCP_DECISIONS_LOG_PATH environment variable. No sanitization against path traversal. An agent or user setting MCP_DECISIONS_LOG_PATH=../../../etc/passwd could write outside the intended directory.
record-decisionrecord-predictionrecord-outcome
Validate enum parameters at tool entry. Before storing, check that prediction_type is in [LATENCY, COST, SCALABILITY, DATA_QUALITY, RELIABILITY, MAINTAINABILITY, BUSINESS_IMPACT] and status is in [ACTIVE, SUPERSEDED, DEPRECATED]. Return clear error: 'Invalid prediction_type: \'INVALID\'. Allowed values: LATENCY, COST, SCALABILITY, DATA_QUALITY, RELIABILITY, MAINTAINABILITY, BUSINESS_IMPACT.'
Sanitize file paths. Validate that LOG_PATH resolves within an allowed directory tree (e.g., ~/.local/share/mcp-decisions/). Use os.path.abspath() and confirm it starts with an expected prefix. Reject paths with '..' components.
Document nested schema for 'predictions' parameter in record-decision. Add to parameter description: 'predictions: Optional array of prediction objects. Each object must have: {prediction_type (enum: LATENCY|COST|SCALABILITY|DATA_QUALITY|RELIABILITY|MAINTAINABILITY|BUSINESS_IMPACT), predicted_value (string)}. Example: [{prediction_type: \'LATENCY\', predicted_value: \'< 50ms\'}]'.
Add idempotency keys or deduplication logic. If record-decision is called twice with identical problem/chosen_solution/technologies, it currently creates two separate decision records with different IDs. Consider adding a 'decision_ref' or checksum to detect duplicates, or document the expected behavior for agents.
Return matched decision count in query-decisions response. Change response format to include 'total_matches' and 'results' fields so agents know if they need to paginate. Example: {total_matches: 42, result_count: 5, results: [...]}.