MCP Server for Ninsaúde Clinic API — 74 tools
The server demonstrates good foundational structure with 15 well-organized tools covering patient, appointment, survey, and financial management. All tools have explicit registrations with descriptions and Zod-based input schemas. However, there are consistent gaps in description quality, missing output schema documentation, and inadequate error handling guidance. Parameter descriptions are present but often terse. The schema definitions are solid (using Zod with type safety), but the semantic completeness for agent planning is moderate. Average tool description length is ~80 characters (below the 194-char baseline for A+ tools), and no output schemas are documented despite tools returning complex objects. Security is appropriate (no credentials exposed as parameters), and naming follows verb_noun conventions well.
Cancel an appointment by ID (sets status to 5=Cancelled)
Create a new appointment
Create a new patient in Ninsaúde Clinic
Create a new revenue/income entry
Create a new research survey
Delete a survey by ID
Get details of a specific patient by ID
No output schema documentation. All tools return wrapped JSON via ok() helper, but downstream agents cannot see what fields to expect, forcing them to guess response structure and complicating chaining between tools. Example: get_patient returns unspecified structure; agents cannot predict whether id, nome, cpf fields exist, breaking multi-tool workflows.
Tool descriptions are terse (average ~60 chars) and lack guidance on WHEN to call the tool vs. similar alternatives. Example: 'Get details of a specific patient by ID' does not explain whether to use list_patients + filter vs. get_patient, or how it differs from create_patient. LLM may not select the right tool.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | C | 63 | 2026-07-28+ | v2 |
| 2026-03-09 | F | 0 | - | v1 |
Get survey details by ID
List appointments (agendamentos) with filters
List patients from Ninsaúde Clinic with optional filters
List income/revenue entries with optional date filters
List research/satisfaction surveys
Update/reschedule an appointment
Update an existing patient record
Update an existing survey
Parameter descriptions are generic or missing context on valid values. Example: 'Active: 0=Inactive, 1=Active' repeated across tools is self-documenting but inconsistent, sometimes it says '0=Inactive, 1=Active', sometimes implied. Use enum constraints (e.g., z.enum(['0', '1'])) with descriptions to be machine-parseable and unambiguous.
No explicit error handling or recovery guidance in tool descriptions. Tools may fail (e.g., invalid patient ID, conflict on create, API timeout), but descriptions do not explain what errors are possible or how to recover. Example: create_patient could fail if CPF is duplicate, but no guidance on how to check for existing patients first.
Destructive operations (delete_survey) lack dry-run or confirmation support. An agent invoking delete_survey with incorrect ID will permanently delete survey data with no undo. Pattern: confirmation-request should be implemented.
List tools do not document pagination limits or defaults. list_patients, list_appointments, list_surveys, list_receitas all accept 'limit' and 'offset' but descriptions do not specify: (1) default limit if omitted, (2) max limit to prevent excessive API load, (3) whether results include total_count or next_cursor for chaining. This complicates agent planning.
Tool names use both English and Portuguese inconsistently. 'list_appointments' vs 'create_agendamento', 'list_receitas' (Portuguese) vs 'cancel_agendamento' (Portuguese). LLM may be confused by mixed nomenclature. Recommend standardizing to English throughout for clarity.
Response filtering and token efficiency not addressed. No indication that verbose API fields (e.g., audit metadata, internal references) are stripped before returning to LLM. If Ninsaúde API returns 50+ fields per record, returning all of them bloats context. Should document what fields are returned and why.