Static source inference · medium confidence · evidence: stateless requests
Current-spec patterns detected
Summary
ConnectWise Manage MCP exhibits a consistent but moderately incomplete tool definition pattern. All 30 tools have basic descriptions and input schemas with type declarations. However, descriptions are uniformly terse (8 - 50 characters), falling well below the production baseline of 194 chars. Parameter descriptions are minimal or absent. Output schemas are not documented anywhere in the source. No tool annotations (readOnlyHint/destructiveHint/idempotentHint) are present despite having WRITE tools. Error handling guidance is absent from tool descriptions. Tool naming follows verb-noun convention adequately (get_*, list_*, create_*, update_*, add_*), which is good. However, parameter documentation is sparse: most parameters lack descriptions explaining their purpose, constraints, or acceptable values. The schema structures are present but underdeveloped, no enums, ranges, or format constraints visible. This server is competent but falls short of production-grade tooling.
All 30 tool descriptions are critically short (8 - 50 characters vs. production baseline of 194). Descriptions do not explain WHEN to use the tool, what it returns, or its dependencies. Example: 'cw_create_ticket' reads 'Create a new ticket in ConnectWise Manage' (41 chars) but omits required fields, return format, or next steps.
Expand all 30 tool descriptions from current 8 - 50 chars to 120 - 300 chars, following pattern: 'WHAT: [action]. WHEN: [use case]. RETURNS: [key fields]. NEXT: [common follow-up tools].' Example: 'cw_create_ticket' → 'Create a new ticket in ConnectWise Manage. Requires company_id (look up with cw_list_companies if unknown) and summary (string, 1-255 chars). Returns ticket_id for use in cw_add_ticket_note and cw_create_time_entry. Ticket starts in Open status.'
Add descriptions to all parameters. For 'filter' params, document OData syntax or link to ConnectWise API docs; for 'company_id', clarify it is a system integer ID, not a name; for 'pageSize', add range (e.g., 1-100). Example: 'company_id (integer): The unique ConnectWise Company ID (e.g., 42). Look up with cw_list_companies if you only have the company name.'
Document output schemas for all 30 tools. Create a reference table or inline JSON showing: GET tools return single object or array, fields included (id, name, status, created_date), and field types. Example for cw_get_ticket: 'Returns {id: integer, summary: string, company_id: integer, status: string, created_date: ISO8601, notes: array of note objects}.' This enables LLM composition.
Add tool annotations to source code registration. Mark all READ_ONLY tools with readOnlyHint=true; mark WRITE tools with destructiveHint=true and idempotentHint=false. Clarify which WRITE operations are retryable (e.g., cw_update_ticket is idempotent if it uses a PUT with full payload; cw_create_ticket is not).
Spec posture evidence
Inferred effective spec: 2026-07-28+.
Relies on Dynamic Client Registration (deprecated) - use Client ID Metadata Documents (CIMD)
Score history
Overall score trend
First recorded score · v2 rubric
54/100
Scored
Grade
Overall
Spec posture
Rubric
2026-09-23
D
54
2026-07-28+
v2
cw_get_contactread onlyauth50/100
Get a contact by ID from ConnectWise Manage
cw_get_memberread onlyauth50/100
Get a member by ID from ConnectWise Manage
cw_get_opportunityread onlyauth50/100
Get an opportunity by ID from ConnectWise Manage
cw_get_projectread onlyauth50/100
Get a project by ID from ConnectWise Manage
cw_get_serviceread onlyauth50/100
Get a service item by ID from ConnectWise Manage
cw_get_ticketread onlyauth50/100
Get a ticket by ID from ConnectWise Manage
cw_get_time_entryread onlyauth50/100
Get a time entry by ID from ConnectWise Manage
cw_health_checkread onlyauth50/100
Health check endpoint for ConnectWise Manage connectivity
cw_list_activitiesread onlyauth50/100
List activities from ConnectWise Manage
cw_list_agreementsread onlyauth50/100
List agreements from ConnectWise Manage
cw_list_catalog_itemsread onlyauth50/100
List catalog items from ConnectWise Manage
cw_list_companiesread onlyauth50/100
List companies from ConnectWise Manage
cw_list_configurationsread onlyauth50/100
List configurations from ConnectWise Manage
cw_list_contactsread onlyauth50/100
List contacts from ConnectWise Manage
cw_list_membersread onlyauth50/100
List members from ConnectWise Manage
cw_list_opportunitiesread onlyauth50/100
List opportunities from ConnectWise Manage
cw_list_projectsread onlyauth50/100
List projects from ConnectWise Manage
cw_list_servicesread onlyauth50/100
List service items from ConnectWise Manage
cw_list_ticketsread onlyauth50/100
List tickets from ConnectWise Manage with optional filtering
No parameter descriptions provided for most parameters. Example: 'cw_create_ticket' has parameters 'summary' and 'company_id' but the input schema shows only type and description attributes. No guidance on whether these are required, acceptable ranges, or dependent relationships. LLMs cannot infer if 'company_id' is a system ID or a display name.
No output schemas documented for any tool. Production tools document what fields are returned (e.g., ticket object structure, count, pagination info). Without documented output schemas, LLMs cannot compose downstream tool chains, e.g., 'cw_get_ticket' returns data but what fields? Does it include ticket_id for use in 'cw_add_ticket_note'?
WRITE tools (cw_create_ticket, cw_update_ticket, cw_add_ticket_note, cw_create_time_entry) lack destructiveHint/idempotentHint annotations and do not include confirmation/dry-run guidance in descriptions. Agents cannot distinguish safe-to-retry operations from irreversible ones, risking duplicate records or silent failures.
Error handling descriptions are absent. Tools do not specify what errors are retryable, what requires user intervention, or what recovery steps exist. Example: 'cw_create_ticket' does not document: What if company_id is invalid? Call cw_list_companies first? Or fail outright?
List tools (cw_list_*) accept a 'filter' parameter (OData expression) but provide no enum, validation rules, or format guidance. LLMs will hallucinate filter syntax. Additionally, no pagination info: are results limited? How does the LLM fetch the next page if results exceed a threshold?
cw_list_tickets and cw_list_time_entries accept 'pageSize' parameter but no 'page' or 'offset' is documented. Unclear how pagination is managed, is it 1-indexed? 0-indexed? Are results cursor-based or offset-based? No limit is stated, risking runaway queries.
No tool annotations present. Tools do not declare readOnlyHint, destructiveHint, or idempotentHint, metadata now expected per MCP spec 2026-07-28. Agents cannot quickly identify safe reads vs. risky writes without parsing descriptions.
All 30 tools
Add error recovery guidance to WRITE tools. Example for cw_create_ticket: 'If company_id is invalid, response will include 'Unknown company.' Call cw_list_companies with a partial name filter to find the correct ID, then retry. If summary exceeds 255 chars, truncate and retry.'
Clarify pagination for all list_* tools. Add to descriptions: 'Results are limited to 50 per page by default. Provide page (1-indexed, optional) and pageSize (1-100, default 50). Response includes total count and next_page_available flag.' Add explicit 'page' and 'limit' parameters if currently absent.
Add enums or pattern constraints to 'filter' parameters. If OData is the syntax, provide an example and link docs. Better: add a 'search' parameter (string) as an alternative to 'filter' for simpler LLM usage. Example: 'search: "CompanyName contains 'Acme'" (simpler than raw OData filter expressions).'
Add a 'description_only' or 'summary' parameter to GET tools to reduce token overhead. Large objects (full ticket details) waste tokens; agents often need only key fields (id, status, summary). Example: 'cw_get_ticket with summary_only=true returns {id, summary, status, created_date} instead of full 50-field object.'
Create a helper/discovery tool or documentation page listing OData filter examples for each resource type. Reduce LLM hallucination by providing templates: 'To filter tickets by status: filter="Status eq 'Open'" or filter="DateCreated gt 2024-01-01".'
Add relationship hints to tool descriptions. Example: 'cw_get_ticket always returns company_id; use that in cw_get_company to fetch customer details. Time entries require ticket_id from cw_get_ticket or cw_create_ticket.' This guides multi-step planning.