MCP Server for the Clint CRM platform. Manage the full sales pipeline via API including contacts, deals, tags, groups, organizations, origins, users, and account configuration.
Clint MCP demonstrates solid fundamentals: all 19 tools have clear verb-noun naming (list_*, get_*, create_*, update_*, delete_*), descriptions range 50 - 200 chars (within baseline), and input schemas are present with typed parameters. Tool annotations (destructiveHint) are correctly applied to delete/remove operations. However, several parameter descriptions lack specificity (e.g., 'fields' object lacks structure guidance), output schemas are not documented, and error handling is minimal. Pagination is implemented but not consistently described. No evidence of idempotency guarantees or recovery guidance in error messages.
Add tags to a single contact. Use list_contacts first to find the contact ID. Use list_tags to find tags IDs or names.
Creates a contact. fields: custom fields as a JSON object (e.g. {"field_key": "value"}). Call list_fields first to discover available field keys.
Create a new deal in the CRM. origin_id is required — use list_origins to find valid origin IDs. fields: custom fields as a JSON object (e.g. {"field_key": "value"}). Call list_fields first to discover available field keys.
WARNING: This is a destructive action, ask user permission to execute. Deletes a contact by its ID. Use list_contacts first to find the contact ID.
Get full details of a single contact by UUID. Use list_contacts first to find the contact ID.
Custom fields parameter ('fields': object) lacks structure documentation. LLMs cannot infer valid field keys or value types without calling list_fields first. Descriptions should state: 'Custom fields as JSON object. Call list_fields to discover available field_key names and expected value types.'
Output schemas are not documented. Tool descriptions do not specify what fields are returned (e.g., does get_contact return 'created_at', 'tags', 'custom_fields'?). LLMs cannot plan downstream tool calls without knowing available response fields.
Error handling in client.py (src/client.py) provides generic ToolError messages without recovery guidance. E.g., '404 Resource not found' does not suggest 'Try list_contacts() to find the correct UUID.' Errors should guide the LLM's next action.
Inferred effective spec: <=2025-11-25.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 63 | <=2025-11-25 | v2 |
Retrieve a single deal by ID. Use list_deals to find the deal ID.
Retrieve a single group by ID. Use list_groups to find the group ID.
Retrieve details of a single organization by ID.
Retrieve a single origin by ID. Use list_origins to find the origin ID.
List all contacts from the CRM. Optionally filter by name, email, phone (without country code), tag_names, or origin_id (use list_origins to find valid origin IDs). Returns up to 1000 per call. Use offset to paginate (e.g., offset=1000 for next batch).
Retrieve a list of deals. Optionally filter by date ranges (ISO 8601), user_email, phone, email, tag_names (comma-separated), status (OPEN, WON, LOST), or stage_id. Defaults to status=OPEN if not specified. Returns up to 1000 per call. Use offset to paginate (e.g., offset=1000 for next batch).
Get all custom fields available in the account. Use this to discover field names before creating or updating contacts and deals.
Retrieve a list of all groups. Returns up to 1000 per call. Use offset to paginate (e.g., offset=1000 for next batch).
Retrieve a list of origins filtered by group. group_id is required — use list_groups to find valid group IDs. Returns up to 1000 per call. Use offset to paginate (e.g., offset=1000 for next batch).
WARNING: This is a destructive action, ask user permission to execute. Remove a deal permanently by ID. Use list_deals or get_deal to find the deal ID.
WARNING: This is a destructive action, ask user permission to execute. Remove a tag from a single contact. Use list_contacts first to find the contact ID. Use list_tags to find tag names.
Update contact by its ID. Use list_contacts first to find the contact ID. fields: custom fields as a JSON object (e.g. {"field_key": "value"}). Call list_fields first to discover available field keys.
Update an existing deal. Use list_deals or get_deal to find the deal ID. Status options: OPEN, WON, LOST. fields: custom fields as a JSON object (e.g. {"field_key": "value"}). Call list_fields first to discover available field keys.
Update an existing organization. Use get_organization first to check current data. custom_fields: custom fields as a JSON object (e.g. {"field_key": "value"}).
Pagination limit (1000 items) is not enforced in tool descriptions. Returning 1000 contacts in a single call risks context window exhaustion. Descriptions should state: 'Returns up to 1000 items per call. Use offset to paginate.' and recommend smaller defaults (e.g., 'Typically returns 20 - 50 items; use offset for more.').
Destructive operations (delete_contact, remove_deal, remove_tags) lack confirmation or dry-run support. Tool descriptions warn 'ask user permission' but no mechanism enforces this. Consider adding a 'confirm' parameter or separate 'preview_delete' tool.