Skip to content

Commit 201d760

Browse files
committed
docs: enhance API parameter descriptions
Updated descriptions in the Zendesk tools to provide clearer guidance on parameter usage, limits, and expected values, ensuring developers have precise documentation for API interactions.
1 parent eec2657 commit 201d760

27 files changed

Lines changed: 394 additions & 165 deletions

src/ES.FX.Zendesk.MCP.Host/Hosting/McpServerHostingExtensions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ public static McpOptions GetMcpOptions(this IHostApplicationBuilder builder)
6767
/// <returns>The builder, for chaining.</returns>
6868
public static IMcpServerBuilder WithToolsInArea<[DynamicallyAccessedMembers(
6969
DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods)]
70-
TTool>(this IMcpServerBuilder builder, ZendeskToolAreaGate gate)
70+
TTool>(this IMcpServerBuilder builder, ZendeskToolAreaGate gate)
7171
=> gate.Allows<TTool>() ? builder.WithTools<TTool>() : builder;
7272

7373
/// <summary>

src/ES.FX.Zendesk.MCP.Host/Tools/ZendeskArticleTools.cs

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,18 @@ public sealed class ZendeskArticleTools(IZendeskClient zendeskApiClient)
1818
"primary way to find an existing answer to resolve or deflect a ticket. Returns relevance-ranked results " +
1919
"with snippets; call articles_get for the full article body. Read-only.")]
2020
public Task<ZendeskArticleSearchResults> Search(
21-
[Description("The customer's question or keywords to search for.")]
21+
[Description(
22+
"The customer's question or keywords to search for; matches article title, body, and labels. " +
23+
"Wrap a phrase in double quotes for an exact-phrase match (e.g. \"carrot potato\"). Required — " +
24+
"this search cannot run on locale alone.")]
2225
string query,
23-
[Description("Optional locale to scope results, e.g. \"en-us\".")]
26+
[Description("Optional locale to scope results; a valid enabled locale (e.g. \"en-us\"), or \"*\" to search all locales.")]
2427
string? locale = null,
2528
[Description("The 1-based page number (optional).")]
2629
int? page = null,
2730
[Description(
28-
"Results per page (default 25, max 100). The total is in 'count'; a non-null 'next_page' means more pages.")]
31+
"Results per page, an integer (min 1, max 100); default 25. Results are relevance-ranked by default. " +
32+
"The total is in 'count'; a non-null 'next_page' means more pages.")]
2933
int? perPage = 25,
3034
CancellationToken cancellationToken = default)
3135
=> ZendeskToolInvoker.InvokeAsync(() =>
@@ -53,11 +57,13 @@ public Task<ZendeskArticlesResult> List(
5357
string? locale = null,
5458
[Description("When set, lists only the articles in this section (see articles_sections_list).")]
5559
long? sectionId = null,
56-
[Description("The cursor page size (max 100).")]
60+
[Description("The cursor page size; the Help Center API caps at 100 records per page (default 30).")]
5761
int? pageSize = null,
5862
[Description("The cursor from the previous page's meta.after_cursor (optional).")]
5963
string? afterCursor = null,
60-
[Description("Sideloads resolved inline as sibling arrays: \"users\", \"sections\", \"categories\".")]
64+
[Description(
65+
"Sideloads resolved inline as sibling arrays. Allowed values: \"users\" (the author), \"sections\", " +
66+
"\"categories\", and \"translations\" (embedded within the article). Only these four are valid.")]
6167
string[]? include = null,
6268
CancellationToken cancellationToken = default)
6369
=> ZendeskToolInvoker.InvokeAsync(() =>
@@ -78,7 +84,8 @@ public Task<ZendeskHelpCenterSectionsResult> Sections(
7884
[Description("The 1-based page number (optional).")]
7985
int? page = null,
8086
[Description(
81-
"Results per page (default 100, max 100). The total is in 'count'; a non-null 'next_page' means more pages.")]
87+
"Results per page; offset pagination caps at 100 records per page (default 100). The total is in " +
88+
"'count'; a non-null 'next_page' means more pages.")]
8289
int? perPage = 100,
8390
CancellationToken cancellationToken = default)
8491
=> ZendeskToolInvoker.InvokeAsync(() =>
@@ -109,7 +116,8 @@ public Task<ZendeskHelpCenterCategoriesResult> Categories(
109116
[Description("The 1-based page number (optional).")]
110117
int? page = null,
111118
[Description(
112-
"Results per page (default 100, max 100). The total is in 'count'; a non-null 'next_page' means more pages.")]
119+
"Results per page; offset pagination caps at 100 records per page (default 100). The total is in " +
120+
"'count'; a non-null 'next_page' means more pages.")]
113121
int? perPage = 100,
114122
CancellationToken cancellationToken = default)
115123
=> ZendeskToolInvoker.InvokeAsync(() =>

src/ES.FX.Zendesk.MCP.Host/Tools/ZendeskAttachmentTools.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@ public sealed class ZendeskAttachmentTools(IZendeskClient zendeskApiClient)
2525
"('encoding':'base64'). 'truncated':true means the file exceeded the size cap and was cut short. Use to read " +
2626
"a customer's error log, CSV export, or config a screenshot won't convey. Read-only.")]
2727
public Task<ZendeskAttachmentContent> Read(
28-
[Description("The numeric attachment id (from a comment's attachments[].id).")]
28+
[Description(
29+
"The numeric attachment id. It is not directly listable — obtain it from a ticket comment's " +
30+
"attachments[].id (list the ticket's comments first).")]
2931
long id,
3032
CancellationToken cancellationToken)
3133
=> ZendeskToolInvoker.InvokeAsync(() =>

src/ES.FX.Zendesk.MCP.Host/Tools/ZendeskBrandTools.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,12 @@ public sealed class ZendeskBrandTools(IZendeskClient zendeskApiClient)
1414
/// <summary>Lists Zendesk brands.</summary>
1515
[McpServerTool(Name = "brands_list", ReadOnly = true, OpenWorld = true)]
1616
[Description(
17-
"Lists Zendesk brands — decodes the brand_id carried on tickets in multibrand accounts. Cursor " +
18-
"pagination: pass pageSize/afterCursor; the result's meta.has_more/meta.after_cursor drive continuation. " +
19-
"Read-only.")]
17+
"Lists Zendesk brands — decodes the brand_id carried on tickets in multibrand accounts. Requires admin, or " +
18+
"an agent with the assign_tickets_to_any_brand permission, to list all brands; agents without it see only " +
19+
"brands they are members of. Cursor pagination: pass pageSize/afterCursor; the result's " +
20+
"meta.has_more/meta.after_cursor drive continuation. Read-only.")]
2021
public Task<ZendeskBrandsResult> List(
21-
[Description("The cursor page size (optional, max 100).")]
22+
[Description("The cursor page size (optional; Zendesk limits most endpoints to a max of 100, defaulting to 100).")]
2223
int? pageSize = null,
2324
[Description("The cursor from the previous page's meta.after_cursor (omit for the first page).")]
2425
string? afterCursor = null,

src/ES.FX.Zendesk.MCP.Host/Tools/ZendeskGroupTools.cs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,10 @@ public Task<ZendeskGroupsResult> List(
2323
"Results per page (default 100, max 100). The total is in 'count'; a non-null 'next_page' means more pages.")]
2424
int? perPage = 100,
2525
[Description(
26-
"Sideloads to resolve inline as sibling arrays: \"users\" returns each group's members in the same " +
27-
"roundtrip, avoiding per-group groups_memberships_list calls.")]
26+
"Comma-separated sideloads to resolve inline as sibling arrays: \"users\" returns each group's members " +
27+
"in the same roundtrip, avoiding per-group groups_memberships_list calls. Documented values are " +
28+
"\"users\" and \"group_settings\"; there is no closed enum for group sideloads, so unknown values are " +
29+
"silently ignored.")]
2830
string[]? include = null,
2931
CancellationToken cancellationToken = default)
3032
=> ZendeskToolInvoker.InvokeAsync(() =>
@@ -56,7 +58,8 @@ public Task<ZendeskGroupMembershipsResult> Memberships(
5658
"Results per page (default 100, max 100). The total is in 'count'; a non-null 'next_page' means more pages.")]
5759
int? perPage = 100,
5860
[Description(
59-
"Sideloads to resolve ids inline in one call: any of \"users\", \"groups\". Returned as sibling arrays.")]
61+
"Comma-separated sideloads to resolve ids inline in one call; valid values are \"users\" and " +
62+
"\"groups\". Returned as sibling arrays.")]
6063
string[]? include = null,
6164
CancellationToken cancellationToken = default)
6265
=> ZendeskToolInvoker.InvokeAsync(() =>
@@ -82,8 +85,9 @@ public Task<ZendeskGroupsResult> Assignable(
8285
/// <summary>Returns the approximate group count.</summary>
8386
[McpServerTool(Name = "groups_count", ReadOnly = true, OpenWorld = true)]
8487
[Description(
85-
"Returns the number of Zendesk groups. The value is cached and approximate above 100,000 (refreshed roughly " +
86-
"every 24 hours; 'refreshed_at' reports the cache time and may be null while Zendesk recomputes). Read-only.")]
88+
"Returns the number of Zendesk groups. The value is cached and approximate above 100,000: it is refreshed " +
89+
"only every ~24 hours and 'value' is capped at 100,000 until that refresh completes ('refreshed_at' reports " +
90+
"the cache time and may be null while Zendesk recomputes). Read-only.")]
8791
public Task<ZendeskCount> Count(CancellationToken cancellationToken)
8892
=> ZendeskToolInvoker.InvokeAsync(() => zendeskApiClient.Groups.CountAsync(cancellationToken));
8993

src/ES.FX.Zendesk.MCP.Host/Tools/ZendeskGroupWriteTools.cs

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ public Task<object> Delete(
7474
"directly to the agent assume this group. Returns the created membership. Write operation — honors the " +
7575
"server execution mode: rejected in read-only mode, simulated (no changes made) in dry-run mode.")]
7676
public Task<object> MembershipsCreate(
77-
[Description("The numeric Zendesk user id of the agent.")]
77+
[Description("The numeric Zendesk user id of the agent (must be an agent, not an end user).")]
7878
long userId,
7979
[Description("The numeric Zendesk group id.")]
8080
long groupId,
@@ -97,7 +97,8 @@ public Task<object> MembershipsCreate(
9797
"Returns a job_status — poll job_statuses_get until completed. Write operation — honors the " +
9898
"server execution mode: rejected in read-only mode, simulated (no changes made) in dry-run mode.")]
9999
public Task<object> MembershipsCreateMany(
100-
[Description("The memberships to create (1-100). Each item needs 'user_id' and 'group_id'.")]
100+
[Description(
101+
"The memberships to create (1-100). Each item needs an agent 'user_id' and a 'group_id'.")]
101102
ZendeskGroupMembership[] memberships,
102103
CancellationToken cancellationToken)
103104
=> ZendeskToolInvoker.InvokeWriteAsync(executionMode,
@@ -115,7 +116,8 @@ public Task<object> MembershipsCreateMany(
115116
"tickets in that group. Returns a completion acknowledgement. Write operation — honors the server " +
116117
"execution mode: rejected in read-only mode, simulated (no changes made) in dry-run mode.")]
117118
public Task<object> MembershipsDelete(
118-
[Description("The numeric group membership id.")]
119+
[Description(
120+
"The numeric group membership id (not a user or group id — get it from groups_memberships_list).")]
119121
long membershipId,
120122
CancellationToken cancellationToken)
121123
=> ZendeskToolInvoker.InvokeWriteAsync(executionMode,
@@ -128,11 +130,14 @@ public Task<object> MembershipsDelete(
128130
[McpServerTool(Name = "groups_memberships_delete_many", ReadOnly = false, Destructive = true,
129131
Idempotent = false, OpenWorld = true)]
130132
[Description(
131-
"Removes up to 100 Zendesk group memberships by their MEMBERSHIP ids. Returns a job_status — poll " +
132-
"job_statuses_get until completed. Write operation — honors the server execution mode: rejected " +
133-
"in read-only mode, simulated (no changes made) in dry-run mode.")]
133+
"Removes up to 100 Zendesk group memberships by their MEMBERSHIP ids. Side effect: Zendesk schedules a job " +
134+
"un-assigning the agents' working tickets in those groups. Returns a job_status — poll job_statuses_get " +
135+
"until completed. Write operation — honors the server execution mode: rejected in read-only mode, " +
136+
"simulated (no changes made) in dry-run mode.")]
134137
public Task<object> MembershipsDeleteMany(
135-
[Description("The numeric group membership ids to remove (1-100).")]
138+
[Description(
139+
"The numeric group membership ids to remove (1-100; not user or group ids — get them from " +
140+
"groups_memberships_list).")]
136141
long[] membershipIds,
137142
CancellationToken cancellationToken)
138143
=> ZendeskToolInvoker.InvokeWriteAsync(executionMode,
@@ -151,7 +156,9 @@ public Task<object> MembershipsDeleteMany(
151156
public Task<object> MembershipsMakeDefault(
152157
[Description("The numeric Zendesk user id owning the membership.")]
153158
long userId,
154-
[Description("The numeric group membership id to make default.")]
159+
[Description(
160+
"The numeric group membership id to make default (not a user or group id; must belong to the given " +
161+
"userId).")]
155162
long membershipId,
156163
CancellationToken cancellationToken)
157164
=> ZendeskToolInvoker.InvokeWriteAsync(executionMode,

src/ES.FX.Zendesk.MCP.Host/Tools/ZendeskJobStatusTools.cs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,10 @@ public sealed class ZendeskJobStatusTools(IZendeskClient zendeskApiClient)
1515
/// <summary>Lists recent Zendesk job statuses.</summary>
1616
[McpServerTool(Name = "job_statuses_list", ReadOnly = true, OpenWorld = true)]
1717
[Description(
18-
"Lists recent Zendesk job statuses (the async jobs returned by bulk write tools). Zendesk retains job " +
19-
"status data for roughly one day. Cursor pagination: pass pageSize/afterCursor; the result's " +
20-
"meta.has_more/meta.after_cursor drive continuation. Read-only.")]
18+
"Lists recent Zendesk job statuses (the async jobs returned by bulk write tools), sorted first by " +
19+
"completion date, then by creation date, in descending order. Zendesk retains job status data for roughly " +
20+
"one day. Cursor pagination only: pass pageSize/afterCursor; the result's meta.has_more/meta.after_cursor " +
21+
"drive continuation. Read-only.")]
2122
public Task<ZendeskJobStatusesResult> List(
2223
[Description("The cursor page size (optional, max 100).")]
2324
int? pageSize = null,
@@ -35,7 +36,9 @@ public Task<ZendeskJobStatusesResult> List(
3536
"job_status) until 'status' is 'completed' or 'failed'; 'results' then carries the per-item outcomes. " +
3637
"Job status data is retained for roughly one day. Read-only.")]
3738
public Task<ZendeskJobStatus> Read(
38-
[Description("The job status id (a string, returned by the bulk operation that started the job).")]
39+
[Description(
40+
"The job status id — an opaque string (not numeric), returned by the bulk operation that started the " +
41+
"job.")]
3942
string id,
4043
CancellationToken cancellationToken)
4144
=> ZendeskToolInvoker.InvokeAsync(() => zendeskApiClient.JobStatuses.GetByIdAsync(id, cancellationToken));
@@ -46,7 +49,7 @@ public Task<ZendeskJobStatus> Read(
4649
"Returns up to 100 Zendesk job statuses in one request (more than 100 ids is rejected by design). Use to " +
4750
"poll several bulk jobs at once instead of calling job_statuses_get repeatedly. Read-only.")]
4851
public Task<ZendeskJobStatusesResult> ReadMany(
49-
[Description("The job status ids (strings, at most 100).")]
52+
[Description("The job status ids — opaque strings (not numeric); at most 100.")]
5053
string[] ids,
5154
CancellationToken cancellationToken)
5255
=> ZendeskToolInvoker.InvokeAsync(() => zendeskApiClient.JobStatuses.GetManyAsync(ids, cancellationToken));

src/ES.FX.Zendesk.MCP.Host/Tools/ZendeskMacroTools.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ public Task<ZendeskMacrosResult> List(
2121
[Description("The 1-based page number (optional).")]
2222
int? page = null,
2323
[Description(
24-
"Results per page (default 25, max 100). The total is in 'count'; a non-null 'next_page' means more pages.")]
24+
"Results per page (default 25, max 100 — Zendesk clamps higher values to 100). The total is in 'count'; " +
25+
"a non-null 'next_page' means more pages.")]
2526
int? perPage = 25,
2627
CancellationToken cancellationToken = default)
2728
=> ZendeskToolInvoker.InvokeAsync(() => zendeskApiClient.Macros.ListAsync(page, perPage, cancellationToken));
@@ -35,7 +36,8 @@ public Task<ZendeskMacrosResult> ListActive(
3536
[Description("The 1-based page number (optional).")]
3637
int? page = null,
3738
[Description(
38-
"Results per page (default 25, max 100). The total is in 'count'; a non-null 'next_page' means more pages.")]
39+
"Results per page (default 25, max 100 — Zendesk clamps higher values to 100). The total is in 'count'; " +
40+
"a non-null 'next_page' means more pages.")]
3941
int? perPage = 25,
4042
CancellationToken cancellationToken = default)
4143
=> ZendeskToolInvoker.InvokeAsync(() =>

0 commit comments

Comments
 (0)