Static source inference · medium confidence · detected: Logging
Deprecated protocol patterns detected
Summary
This server has significant definition quality gaps. Tools are registered with fastmcp @mcp.tool() decorator, visible in source code, so tool definitions are explicit (not inferred). However, most tools lack proper parameter descriptions, error handling guidance, and output schema documentation. Three tools (update_stats, insert_stats, delete_stats) accept raw JSON strings as parameters, creating injection vectors and poor UX. Calys tools have minimal descriptions (under 50 chars). Error responses are generic ('Failure', error objects) without recovery guidance. No tool has a documented return schema. The server operates as READ_ONLY for calys tools (fitness data) and WRITE/DESTRUCTIVE for stats tools, but this risk distinction is not surfaced in descriptions or error handling.
Tools (7)
calys_exercisesread onlysource verified43/100
Read unique list of all exercises.
calys_historyread onlysource verified47/100
Read exercise results by owner with date and reps.
calys_prsread onlysource verified47/100
Read max score by exercise and owner for a date range.
Three tools (update_stats, insert_stats, delete_stats) accept raw JSON strings as parameters with no schema validation. This creates SQL/JSON injection vectors and forces LLMs to construct JSON without guidance, leading to malformed payloads.
Delete_stats is a DESTRUCTIVE operation but lacks a dry-run mode, confirmation step, or explicit warning in the description. Agents can accidentally delete records without recovery path.
All tools return unstructured responses (plain strings or generic error dicts) without documented schemas. LLMs cannot plan downstream calls or extract structured results.
Replace raw JSON string parameters (filter_json, update_json, payload) with structured objects. Define schemas for MongoDB filter/update objects and stats payload. Example: instead of 'payload: str', use 'payload: list[StatsRecord]' with StatsRecord = {owner: str, key: str, value: str, category: str, description: str, created_at: datetime}.
Expand all tool descriptions to 50-200 characters. Example: 'calys_prs' → 'Get the maximum score achieved for each exercise by owner during a date range. Use this to find personal records or compare top performers. Returns exercise, owner, and score.'
Add format constraints to date parameters. Document: 'ISO 8601 format (YYYY-MM-DD). Dates are inclusive. Timezone is UTC.'
Convert enum parameters from description text to JSON Schema enums. Example: weaviate_reindex.collection should declare enum: ['PatternFile', 'ObsidianFile'].
Document return schemas for all tools. Example: calys_prs returns [{exercise: str, owner: str, score: int}]. weaviate_reindex returns {status: 'OK'|'Failure', message: str, records_indexed: int (if status=='OK')}.
Add a dry-run mode or confirmation step to delete_stats. Example: add optional 'confirm: bool' parameter that defaults to false; if false, return 'Would delete X records matching filter. Set confirm=true to proceed.'
Improve error messages with recovery guidance. Example: instead of 'Failure', return '{"error": "Collection unknown", "hint": "Try one of: PatternFile, ObsidianFile"}'. For malformed JSON errors, return the specific JSON parse error and an example of valid format.
Spec posture evidence
Inferred effective spec: 2026-07-28+.
Relies on Logging (deprecated) - log to stderr or use OpenTelemetry
Error responses are generic ('Failure', error dict with 'error' key, or no guidance). LLMs cannot determine if errors are retryable, user-fixable, or fatal, and have no recovery path.
Tool descriptions are below the 50-200 character baseline (most under 50 chars). Calys tools especially lack context on when to use each variant or what data they expose.
Parameter 'collection' in weaviate_reindex should be an enum (PatternFile, ObsidianFile) but is a free-form string. LLMs can hallucinate invalid values.
Calys tools accept date parameters as strings with no format guidance. Example: start_date, end_date. No documentation of expected format (YYYY-MM-DD? ISO 8601? timezone?), boundary behavior (inclusive? exclusive?), or validation.
No output schema documented for any tool. LLMs cannot know what fields to expect in responses, forcing them to infer structure from examples or code (which they cannot see).
Add a 'limit' parameter (default 20) to calys_prs and calys_history to enforce result limits and enable pagination with offset/cursor. Document: 'Results are ordered by score (desc) for prs, workout_date (desc) for history. Maximum 100 results per call.'
Document which tools are READ_ONLY vs WRITE/DESTRUCTIVE in descriptions. Example: 'calys_prs: Read-only. Retrieves but does not modify fitness data.' 'delete_stats: Destructive. Permanently deletes records from the database.'
Add parameter descriptions where missing. Example: calys_prs 'exercise' parameter → 'Filter by exercise name (case-insensitive). Leave blank to include all exercises. Returns distinct values from calys_exercises.'
Implement input validation and return clear error messages. Example: if date parsing fails, return '{"error": "Invalid date format", "expected": "YYYY-MM-DD", "got": "invalid_date_string"}'.
For multi-record operations (insert_stats), return per-record success/failure. Example: '[{"record_index": 0, "status": "ok", "inserted_id": "..."}, {"record_index": 1, "status": "error", "reason": "duplicate_key"}]' instead of a blanket 'OK' or 'Failure'.