kaiten-cli 0.3.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. kaiten_cli/__init__.py +5 -0
  2. kaiten_cli/__main__.py +9 -0
  3. kaiten_cli/agent_gateway.py +577 -0
  4. kaiten_cli/app.py +1636 -0
  5. kaiten_cli/completion.py +570 -0
  6. kaiten_cli/discovery.py +39 -0
  7. kaiten_cli/errors.py +79 -0
  8. kaiten_cli/i18n.py +92 -0
  9. kaiten_cli/locales/ru.json +2967 -0
  10. kaiten_cli/localized_click.py +160 -0
  11. kaiten_cli/models.py +202 -0
  12. kaiten_cli/profiles.py +316 -0
  13. kaiten_cli/registry/__init__.py +260 -0
  14. kaiten_cli/registry/addons.py +392 -0
  15. kaiten_cli/registry/audit_and_analytics.py +451 -0
  16. kaiten_cli/registry/automation_schema.py +44 -0
  17. kaiten_cli/registry/automation_schemas.json +7417 -0
  18. kaiten_cli/registry/automations.py +342 -0
  19. kaiten_cli/registry/base.py +62 -0
  20. kaiten_cli/registry/blockers.py +320 -0
  21. kaiten_cli/registry/boards.py +520 -0
  22. kaiten_cli/registry/card_relations.py +376 -0
  23. kaiten_cli/registry/card_types.py +363 -0
  24. kaiten_cli/registry/cards.py +1329 -0
  25. kaiten_cli/registry/charts.py +539 -0
  26. kaiten_cli/registry/checklists.py +600 -0
  27. kaiten_cli/registry/columns.py +558 -0
  28. kaiten_cli/registry/comments.py +224 -0
  29. kaiten_cli/registry/custom_directories.py +980 -0
  30. kaiten_cli/registry/custom_properties.py +1460 -0
  31. kaiten_cli/registry/dashboards.py +564 -0
  32. kaiten_cli/registry/documents.py +761 -0
  33. kaiten_cli/registry/external_links.py +128 -0
  34. kaiten_cli/registry/files.py +738 -0
  35. kaiten_cli/registry/github_addon.py +613 -0
  36. kaiten_cli/registry/iterations.py +397 -0
  37. kaiten_cli/registry/lanes.py +205 -0
  38. kaiten_cli/registry/live_contracts.py +361 -0
  39. kaiten_cli/registry/members.py +336 -0
  40. kaiten_cli/registry/module_docs.py +108 -0
  41. kaiten_cli/registry/projects.py +369 -0
  42. kaiten_cli/registry/query.py +129 -0
  43. kaiten_cli/registry/restrictions.py +249 -0
  44. kaiten_cli/registry/roles_and_groups.py +1102 -0
  45. kaiten_cli/registry/scim.py +263 -0
  46. kaiten_cli/registry/service_desk.py +1270 -0
  47. kaiten_cli/registry/snapshot.py +187 -0
  48. kaiten_cli/registry/spaces.py +272 -0
  49. kaiten_cli/registry/subscribers.py +168 -0
  50. kaiten_cli/registry/tags.py +193 -0
  51. kaiten_cli/registry/time_logs.py +353 -0
  52. kaiten_cli/registry/tree.py +352 -0
  53. kaiten_cli/registry/utilities.py +287 -0
  54. kaiten_cli/registry/webhooks.py +265 -0
  55. kaiten_cli/runtime/__init__.py +1 -0
  56. kaiten_cli/runtime/automation_validation.py +115 -0
  57. kaiten_cli/runtime/behaviors.py +787 -0
  58. kaiten_cli/runtime/cache.py +733 -0
  59. kaiten_cli/runtime/client.py +387 -0
  60. kaiten_cli/runtime/endpoints.py +59 -0
  61. kaiten_cli/runtime/executor.py +269 -0
  62. kaiten_cli/runtime/fs_security.py +168 -0
  63. kaiten_cli/runtime/input.py +310 -0
  64. kaiten_cli/runtime/output.py +59 -0
  65. kaiten_cli/runtime/public_validation.py +35 -0
  66. kaiten_cli/runtime/snapshot_build.py +527 -0
  67. kaiten_cli/runtime/snapshot_common.py +363 -0
  68. kaiten_cli/runtime/snapshot_query.py +306 -0
  69. kaiten_cli/runtime/snapshot_store.py +1192 -0
  70. kaiten_cli/runtime/snapshots.py +62 -0
  71. kaiten_cli/runtime/sqlite_errors.py +23 -0
  72. kaiten_cli/runtime/support/__init__.py +1 -0
  73. kaiten_cli/runtime/support/addons.py +953 -0
  74. kaiten_cli/runtime/support/audit.py +70 -0
  75. kaiten_cli/runtime/support/batch.py +234 -0
  76. kaiten_cli/runtime/support/card_move_url.py +213 -0
  77. kaiten_cli/runtime/support/cards.py +174 -0
  78. kaiten_cli/runtime/support/checklists.py +21 -0
  79. kaiten_cli/runtime/support/company_users.py +117 -0
  80. kaiten_cli/runtime/support/dashboards.py +35 -0
  81. kaiten_cli/runtime/support/documents.py +175 -0
  82. kaiten_cli/runtime/support/files.py +561 -0
  83. kaiten_cli/runtime/support/markdown_export.py +525 -0
  84. kaiten_cli/runtime/support/pagination.py +167 -0
  85. kaiten_cli/runtime/support/projects.py +66 -0
  86. kaiten_cli/runtime/support/relations.py +86 -0
  87. kaiten_cli/runtime/support/restrictions.py +62 -0
  88. kaiten_cli/runtime/support/spaces.py +20 -0
  89. kaiten_cli/runtime/support/time_logs.py +61 -0
  90. kaiten_cli/runtime/support/tree.py +140 -0
  91. kaiten_cli/runtime/support/tree_sharing.py +447 -0
  92. kaiten_cli/runtime/trace.py +500 -0
  93. kaiten_cli/runtime/transforms.py +128 -0
  94. kaiten_cli/schema_docs.py +22 -0
  95. kaiten_cli/update_check.py +519 -0
  96. kaiten_cli-0.3.3.dist-info/METADATA +1110 -0
  97. kaiten_cli-0.3.3.dist-info/RECORD +99 -0
  98. kaiten_cli-0.3.3.dist-info/WHEEL +4 -0
  99. kaiten_cli-0.3.3.dist-info/entry_points.txt +3 -0
@@ -0,0 +1,1102 @@
1
+ """Roles, groups, and space-user tool specs."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from kaiten_cli.models import ExampleSpec, OperationSpec, ResponsePolicy, RuntimeBehavior
6
+ from kaiten_cli.registry.base import make_tool
7
+ from kaiten_cli.runtime.public_validation import validate_public_request
8
+ from kaiten_cli.runtime.behaviors import company_members_section_request, payload_body_request
9
+ from kaiten_cli.runtime.support.company_users import (
10
+ COMPANY_USERS_DEFAULT_MAX_PAGES,
11
+ COMPANY_USERS_MAX_PAGE_SIZE,
12
+ execute_company_users_list_all,
13
+ validate_company_users_list_all,
14
+ )
15
+
16
+
17
+ COMPANY_USERS_DEFAULT_LIMIT = 100
18
+
19
+
20
+ TOOLS = (
21
+ make_tool(
22
+ canonical_name="space-users.list",
23
+ mcp_alias="kaiten_list_space_users",
24
+ description="List one page of users in a Kaiten space.",
25
+ input_schema={
26
+ "type": "object",
27
+ "properties": {
28
+ "space_id": {"type": "integer", "description": "Space ID"},
29
+ "limit": {
30
+ "type": "integer",
31
+ "minimum": 1,
32
+ "maximum": 100,
33
+ "description": "Max results (default 50, max 100)",
34
+ },
35
+ "offset": {"type": "integer", "minimum": 0, "description": "Pagination offset"},
36
+ "compact": {
37
+ "type": "boolean",
38
+ "description": "Return compact response without heavy fields.",
39
+ },
40
+ "include_inherited_access": {
41
+ "type": "boolean",
42
+ "description": "The result includes users with inherited access",
43
+ },
44
+ "inactive": {
45
+ "type": "boolean",
46
+ "description": "The result includes only inactive in company members",
47
+ },
48
+ },
49
+ "required": ["space_id"],
50
+ },
51
+ operation=OperationSpec(
52
+ method="GET",
53
+ path_template="/spaces/{space_id}/users",
54
+ path_fields=("space_id",),
55
+ query_fields=("limit", "offset", "include_inherited_access", "inactive"),
56
+ ),
57
+ response_policy=ResponsePolicy(
58
+ compact_supported=True, default_limit=50, result_kind="list"
59
+ ),
60
+ examples=(
61
+ ExampleSpec(
62
+ command="kaiten --json space-users list --space-id 1 --compact",
63
+ description="List space users.",
64
+ ),
65
+ ),
66
+ usage_notes=(
67
+ "This direct command returns one page; increase offset to read subsequent pages.",
68
+ ),
69
+ ),
70
+ make_tool(
71
+ canonical_name="space-users.get",
72
+ mcp_alias="kaiten_get_space_user",
73
+ description="Get a user in a Kaiten space.",
74
+ input_schema={
75
+ "type": "object",
76
+ "properties": {
77
+ "space_id": {"type": "integer", "description": "Space ID"},
78
+ "user_id": {"type": "integer", "description": "User ID"},
79
+ "compact": {
80
+ "type": "boolean",
81
+ "description": "Return compact response without heavy fields.",
82
+ },
83
+ },
84
+ "required": ["space_id", "user_id"],
85
+ },
86
+ operation=OperationSpec(
87
+ method="GET",
88
+ path_template="/spaces/{space_id}/users/{user_id}",
89
+ path_fields=("space_id", "user_id"),
90
+ ),
91
+ response_policy=ResponsePolicy(compact_supported=True, result_kind="entity"),
92
+ examples=(
93
+ ExampleSpec(
94
+ command="kaiten --json space-users get --space-id 1 --user-id 7 --compact",
95
+ description="Get a space user.",
96
+ ),
97
+ ),
98
+ ),
99
+ make_tool(
100
+ canonical_name="space-users.add",
101
+ mcp_alias="kaiten_add_space_user",
102
+ description="Add a user to a Kaiten space.",
103
+ input_schema={
104
+ "type": "object",
105
+ "properties": {
106
+ "space_id": {"type": "integer", "description": "Space ID"},
107
+ "user_id": {"type": "integer", "description": "User ID to add"},
108
+ "role_id": {"type": "string", "description": "Role ID (UUID) to assign"},
109
+ "email": {"type": "string", "description": "User email address"},
110
+ "guest": {
111
+ "type": "boolean",
112
+ "description": "Set true to invite the user as a guest",
113
+ },
114
+ "operator_comment": {"type": "string", "description": "Operator's comment"},
115
+ "send_email": {"type": "boolean", "description": "Whether to send email or not"},
116
+ },
117
+ "required": ["space_id"],
118
+ },
119
+ operation=OperationSpec(
120
+ method="POST",
121
+ path_template="/spaces/{space_id}/users",
122
+ path_fields=("space_id",),
123
+ body_fields=("user_id", "role_id", "email", "guest", "operator_comment", "send_email"),
124
+ ),
125
+ runtime_behavior=RuntimeBehavior(payload_validator=validate_public_request),
126
+ examples=(
127
+ ExampleSpec(
128
+ command="kaiten --json space-users add --space-id 1 --user-id 7",
129
+ description="Add a user to a space.",
130
+ ),
131
+ ),
132
+ ),
133
+ make_tool(
134
+ canonical_name="space-users.update",
135
+ mcp_alias="kaiten_update_space_user",
136
+ description="Update a user's role in a Kaiten space.",
137
+ input_schema={
138
+ "type": "object",
139
+ "properties": {
140
+ "space_id": {"type": "integer", "description": "Space ID"},
141
+ "user_id": {"type": "integer", "description": "User ID to update"},
142
+ "role_id": {"type": "string", "description": "New role ID (UUID)"},
143
+ "notifications_enabled": {
144
+ "type": "boolean",
145
+ "description": "Enabled or disable notifications for space events",
146
+ },
147
+ "space_group_id": {
148
+ "description": "Space group id",
149
+ "type": ["number", "null"],
150
+ "x-documentation-alternatives": [{"type": "number"}, {"type": "null"}],
151
+ },
152
+ "settings": {"type": "object", "description": "Space user settings"},
153
+ },
154
+ "required": ["space_id", "user_id"],
155
+ },
156
+ operation=OperationSpec(
157
+ method="PATCH",
158
+ path_template="/spaces/{space_id}/users/{user_id}",
159
+ path_fields=("space_id", "user_id"),
160
+ body_fields=("role_id", "notifications_enabled", "space_group_id", "settings"),
161
+ ),
162
+ examples=(
163
+ ExampleSpec(
164
+ command="kaiten --json space-users update --space-id 1 --user-id 7 --role-id 9",
165
+ description="Update a space user role.",
166
+ ),
167
+ ),
168
+ ),
169
+ make_tool(
170
+ canonical_name="space-users.remove",
171
+ mcp_alias="kaiten_remove_space_user",
172
+ description="Remove a user from a Kaiten space.",
173
+ input_schema={
174
+ "type": "object",
175
+ "properties": {
176
+ "space_id": {"type": "integer", "description": "Space ID"},
177
+ "user_id": {"type": "integer", "description": "User ID to remove"},
178
+ },
179
+ "required": ["space_id", "user_id"],
180
+ },
181
+ operation=OperationSpec(
182
+ method="DELETE",
183
+ path_template="/spaces/{space_id}/users/{user_id}",
184
+ path_fields=("space_id", "user_id"),
185
+ ),
186
+ examples=(
187
+ ExampleSpec(
188
+ command="kaiten --json space-users remove --space-id 1 --user-id 7",
189
+ description="Remove a user from a space.",
190
+ ),
191
+ ),
192
+ ),
193
+ make_tool(
194
+ canonical_name="company-users.list",
195
+ mcp_alias="kaiten_list_company_users",
196
+ description=(
197
+ "List company users from the administrative Members section. "
198
+ "Defaults to for_members_section=true with paginated limit/offset."
199
+ ),
200
+ input_schema={
201
+ "type": "object",
202
+ "properties": {
203
+ "for_members_section": {
204
+ "type": "boolean",
205
+ "description": "Use the administrative Members section response shape (default true).",
206
+ },
207
+ "query": {"type": "string", "description": "Search by email or full name."},
208
+ "limit": {
209
+ "type": "integer",
210
+ "minimum": 1,
211
+ "maximum": 100,
212
+ "description": "Maximum number of users to return (default 100).",
213
+ },
214
+ "offset": {
215
+ "type": "integer",
216
+ "minimum": 0,
217
+ "description": "Number of users to skip (default 0).",
218
+ },
219
+ "only_records_count": {
220
+ "type": "boolean",
221
+ "description": "Return only the filtered user count.",
222
+ },
223
+ "access_type_permissions": {
224
+ "type": "string",
225
+ "enum": ["member", "guest", "denied"],
226
+ "description": "Filter by Kaiten access type.",
227
+ },
228
+ "sd_access_type": {
229
+ "type": "string",
230
+ "enum": ["any", "has_access", "has_no_access"],
231
+ "description": "Filter by Service Desk access.",
232
+ },
233
+ "take_licence": {
234
+ "type": "string",
235
+ "enum": ["any", "yes", "no"],
236
+ "description": "Filter by users who take a paid license.",
237
+ },
238
+ "temporarily_inactive_status": {
239
+ "type": "string",
240
+ "enum": ["all_users", "only_temporarily_inactive_users", "only_active_users"],
241
+ "description": "Filter by temporary deactivation status.",
242
+ },
243
+ "group_ids": {"type": "array", "description": "JSON array of company group IDs."},
244
+ "permissions": {
245
+ "type": "array",
246
+ "description": "JSON array of company permission criteria.",
247
+ },
248
+ "compact": {
249
+ "type": "boolean",
250
+ "description": "Return compact response without heavy fields.",
251
+ },
252
+ "fields": {
253
+ "type": "string",
254
+ "description": "Comma-separated field names to return per user.",
255
+ },
256
+ "invitesOnly": {"type": "boolean", "description": "Filter to return only invites"},
257
+ "withTransferAccessStatus": {
258
+ "type": "boolean",
259
+ "description": "Data about the user rights transfer process is added",
260
+ },
261
+ "owner_only": {
262
+ "type": "boolean",
263
+ "description": "When this flag is enabled the company owner is returned",
264
+ },
265
+ "only_paid": {
266
+ "type": "boolean",
267
+ "description": "Only users with paid access are returned",
268
+ },
269
+ "only_virtual": {
270
+ "type": "boolean",
271
+ "description": "Only virtual users are returned and result of the request is displayed page by page (See limit and offset params).",
272
+ },
273
+ },
274
+ },
275
+ operation=OperationSpec(
276
+ method="GET",
277
+ path_template="/company/users",
278
+ query_fields=(
279
+ "for_members_section",
280
+ "query",
281
+ "limit",
282
+ "offset",
283
+ "only_records_count",
284
+ "access_type_permissions",
285
+ "sd_access_type",
286
+ "take_licence",
287
+ "temporarily_inactive_status",
288
+ "group_ids",
289
+ "permissions",
290
+ "invitesOnly",
291
+ "withTransferAccessStatus",
292
+ "owner_only",
293
+ "only_paid",
294
+ "only_virtual",
295
+ ),
296
+ ),
297
+ response_policy=ResponsePolicy(
298
+ compact_supported=True,
299
+ fields_supported=True,
300
+ default_limit=COMPANY_USERS_DEFAULT_LIMIT,
301
+ result_kind="list",
302
+ ),
303
+ runtime_behavior=RuntimeBehavior(request_shaper=company_members_section_request),
304
+ examples=(
305
+ ExampleSpec(
306
+ command="kaiten --json company-users list --limit 100 --offset 0 --compact",
307
+ description="List administrative company members.",
308
+ ),
309
+ ExampleSpec(
310
+ command=(
311
+ "kaiten --json company-users list --only-records-count "
312
+ "--temporarily-inactive-status all_users"
313
+ ),
314
+ description="Count company members including temporarily inactive users.",
315
+ ),
316
+ ),
317
+ usage_notes=(
318
+ "Use this command for paginated administrative member exports. "
319
+ "`users.list` is a generic users endpoint and may not be reliable for full member paging.",
320
+ ),
321
+ ),
322
+ make_tool(
323
+ canonical_name="company-users.list-all",
324
+ mcp_alias="kaiten_list_all_company_users",
325
+ description=(
326
+ "List all administrative company users with bounded pagination and no silent truncation."
327
+ ),
328
+ input_schema={
329
+ "type": "object",
330
+ "properties": {
331
+ "for_members_section": {
332
+ "type": "boolean",
333
+ "description": "Use the administrative Members response shape (default true).",
334
+ },
335
+ "query": {"type": "string", "description": "Search by email or full name."},
336
+ "page_size": {
337
+ "type": "integer",
338
+ "minimum": 1,
339
+ "maximum": 100,
340
+ "description": "Users per request (1..100, default 100).",
341
+ },
342
+ "max_pages": {
343
+ "type": "integer",
344
+ "minimum": 1,
345
+ "maximum": 1000,
346
+ "description": (
347
+ "Safety cap for requests; a full final page causes an error instead of truncation "
348
+ f"(default {COMPANY_USERS_DEFAULT_MAX_PAGES})."
349
+ ),
350
+ },
351
+ "access_type_permissions": {
352
+ "type": "string",
353
+ "enum": ["member", "guest", "denied"],
354
+ "description": "Filter by Kaiten access type.",
355
+ },
356
+ "sd_access_type": {
357
+ "type": "string",
358
+ "enum": ["any", "has_access", "has_no_access"],
359
+ "description": "Filter by Service Desk access.",
360
+ },
361
+ "take_licence": {
362
+ "type": "string",
363
+ "enum": ["any", "yes", "no"],
364
+ "description": "Filter by paid-license usage.",
365
+ },
366
+ "temporarily_inactive_status": {
367
+ "type": "string",
368
+ "enum": [
369
+ "all_users",
370
+ "only_temporarily_inactive_users",
371
+ "only_active_users",
372
+ ],
373
+ "description": "Filter by temporary deactivation status.",
374
+ },
375
+ "group_ids": {"type": "array", "description": "JSON array of group IDs."},
376
+ "permissions": {
377
+ "type": "array",
378
+ "description": "JSON array of company permission criteria.",
379
+ },
380
+ "compact": {
381
+ "type": "boolean",
382
+ "description": "Return compact output without heavy fields.",
383
+ },
384
+ "fields": {
385
+ "type": "string",
386
+ "description": "Comma-separated field names to return per user.",
387
+ },
388
+ },
389
+ },
390
+ operation=OperationSpec(
391
+ method="GET",
392
+ path_template="/company/users",
393
+ query_fields=(
394
+ "for_members_section",
395
+ "query",
396
+ "access_type_permissions",
397
+ "sd_access_type",
398
+ "take_licence",
399
+ "temporarily_inactive_status",
400
+ "group_ids",
401
+ "permissions",
402
+ ),
403
+ ),
404
+ response_policy=ResponsePolicy(
405
+ compact_supported=True,
406
+ fields_supported=True,
407
+ heavy=True,
408
+ result_kind="list",
409
+ ),
410
+ runtime_behavior=RuntimeBehavior(
411
+ execution_mode="aggregated",
412
+ custom_executor=execute_company_users_list_all,
413
+ payload_validator=validate_company_users_list_all,
414
+ ),
415
+ examples=(
416
+ ExampleSpec(
417
+ command="kaiten --json company-users list-all --page-size 100 --max-pages 100 --fields id,uid,email,full_name --compact",
418
+ description="Read every company user within an explicit safety cap.",
419
+ ),
420
+ ),
421
+ usage_notes=(
422
+ f"Uses at most {COMPANY_USERS_MAX_PAGE_SIZE} users per request for forward compatibility.",
423
+ "Legacy endpoints that ignore pagination are accepted when the first page is oversized or the second page is identical; duplicate users are not appended.",
424
+ "If max_pages is reached on a full page, the command fails instead of returning a partial list.",
425
+ ),
426
+ ),
427
+ make_tool(
428
+ canonical_name="company-users.update",
429
+ mcp_alias="kaiten_update_company_user",
430
+ description="Update a company user.",
431
+ input_schema={
432
+ "type": "object",
433
+ "properties": {
434
+ "user_id": {"type": "integer", "description": "User ID"},
435
+ "full_name": {"type": "string", "description": "Full name"},
436
+ "email": {"type": "string", "description": "Email"},
437
+ "payload": {
438
+ "type": "object",
439
+ "description": "Extra JSON body fields from the Kaiten API docs.",
440
+ },
441
+ "apps_permissions": {
442
+ "type": "integer",
443
+ "description": "User access.\n 0 - no access,\n 1 - full access to Kaiten, access to service desk denied.\n 2 - guest access to Kaiten, access to service desk denied.\n 4 - access only to service desk.\n 5 - full access to Kaiten and service desk.\n 6 - guest access to Kaiten, access to service desk",
444
+ },
445
+ "temporarily_inactive": {
446
+ "type": "boolean",
447
+ "description": "Temporarily inactive: user is still in company, but can't sign in and doesn't need a license",
448
+ },
449
+ },
450
+ "required": ["user_id"],
451
+ },
452
+ operation=OperationSpec(
453
+ method="PATCH",
454
+ path_template="/company/users/{user_id}",
455
+ path_fields=("user_id",),
456
+ body_fields=(
457
+ "full_name",
458
+ "email",
459
+ "payload",
460
+ "apps_permissions",
461
+ "temporarily_inactive",
462
+ ),
463
+ ),
464
+ runtime_behavior=RuntimeBehavior(request_shaper=payload_body_request),
465
+ examples=(
466
+ ExampleSpec(
467
+ command='kaiten --json company-users update --user-id 7 --full-name "Alice Smith"',
468
+ description="Update a company user.",
469
+ ),
470
+ ),
471
+ ),
472
+ make_tool(
473
+ canonical_name="company-users.remove-virtual",
474
+ mcp_alias="kaiten_remove_virtual_company_user",
475
+ description="Remove a virtual company user.",
476
+ input_schema={
477
+ "type": "object",
478
+ "properties": {"user_id": {"type": "integer", "description": "Virtual user ID"}},
479
+ "required": ["user_id"],
480
+ },
481
+ operation=OperationSpec(
482
+ method="DELETE", path_template="/company/users/{user_id}", path_fields=("user_id",)
483
+ ),
484
+ examples=(
485
+ ExampleSpec(
486
+ command="kaiten --json company-users remove-virtual --user-id 7",
487
+ description="Remove a virtual company user.",
488
+ ),
489
+ ),
490
+ ),
491
+ make_tool(
492
+ canonical_name="user-roles.list",
493
+ mcp_alias="kaiten_list_user_roles",
494
+ description="List user roles.",
495
+ input_schema={
496
+ "type": "object",
497
+ "properties": {
498
+ "query": {"type": "string", "description": "Search query"},
499
+ "limit": {"type": "integer", "description": "Max results"},
500
+ "offset": {"type": "integer", "description": "Pagination offset"},
501
+ },
502
+ },
503
+ operation=OperationSpec(
504
+ method="GET", path_template="/user-roles", query_fields=("query", "limit", "offset")
505
+ ),
506
+ response_policy=ResponsePolicy(default_limit=50, result_kind="list"),
507
+ examples=(
508
+ ExampleSpec(command="kaiten --json user-roles list", description="List user roles."),
509
+ ),
510
+ ),
511
+ make_tool(
512
+ canonical_name="user-roles.get",
513
+ mcp_alias="kaiten_get_user_role",
514
+ description="Get a user role.",
515
+ input_schema={
516
+ "type": "object",
517
+ "properties": {"role_id": {"type": "integer", "description": "User role ID"}},
518
+ "required": ["role_id"],
519
+ },
520
+ operation=OperationSpec(
521
+ method="GET", path_template="/user-roles/{role_id}", path_fields=("role_id",)
522
+ ),
523
+ examples=(
524
+ ExampleSpec(
525
+ command="kaiten --json user-roles get --role-id 1", description="Get a user role."
526
+ ),
527
+ ),
528
+ ),
529
+ make_tool(
530
+ canonical_name="user-roles.create",
531
+ mcp_alias="kaiten_create_user_role",
532
+ description="Create a user role.",
533
+ input_schema={
534
+ "type": "object",
535
+ "properties": {
536
+ "name": {"type": "string", "description": "Role name"},
537
+ "permissions": {"type": "object", "description": "Role permissions JSON."},
538
+ "payload": {
539
+ "type": "object",
540
+ "description": "Extra JSON body fields from the Kaiten API docs.",
541
+ },
542
+ },
543
+ "required": ["name"],
544
+ },
545
+ operation=OperationSpec(
546
+ method="POST",
547
+ path_template="/user-roles",
548
+ body_fields=("name", "permissions", "payload"),
549
+ ),
550
+ runtime_behavior=RuntimeBehavior(request_shaper=payload_body_request),
551
+ examples=(
552
+ ExampleSpec(
553
+ command='kaiten --json user-roles create --name "Manager"',
554
+ description="Create a user role.",
555
+ ),
556
+ ),
557
+ ),
558
+ make_tool(
559
+ canonical_name="user-roles.update",
560
+ mcp_alias="kaiten_update_user_role",
561
+ description="Update a user role.",
562
+ input_schema={
563
+ "type": "object",
564
+ "properties": {
565
+ "role_id": {"type": "integer", "description": "User role ID"},
566
+ "name": {"type": "string", "description": "Role name"},
567
+ "permissions": {"type": "object", "description": "Role permissions JSON."},
568
+ "payload": {
569
+ "type": "object",
570
+ "description": "Extra JSON body fields from the Kaiten API docs.",
571
+ },
572
+ },
573
+ "required": ["role_id"],
574
+ },
575
+ operation=OperationSpec(
576
+ method="PATCH",
577
+ path_template="/user-roles/{role_id}",
578
+ path_fields=("role_id",),
579
+ body_fields=("name", "permissions", "payload"),
580
+ ),
581
+ runtime_behavior=RuntimeBehavior(request_shaper=payload_body_request),
582
+ examples=(
583
+ ExampleSpec(
584
+ command='kaiten --json user-roles update --role-id 1 --name "Manager"',
585
+ description="Update a user role.",
586
+ ),
587
+ ),
588
+ ),
589
+ make_tool(
590
+ canonical_name="user-roles.delete",
591
+ mcp_alias="kaiten_delete_user_role",
592
+ description="Delete a user role.",
593
+ input_schema={
594
+ "type": "object",
595
+ "properties": {
596
+ "role_id": {"type": "integer", "description": "User role ID"},
597
+ "replace_role_id": {"type": "integer", "description": "Role id to replace deleted"},
598
+ },
599
+ "required": ["role_id"],
600
+ },
601
+ operation=OperationSpec(
602
+ method="DELETE",
603
+ path_template="/user-roles/{role_id}",
604
+ path_fields=("role_id",),
605
+ body_fields=("replace_role_id",),
606
+ ),
607
+ examples=(
608
+ ExampleSpec(
609
+ command="kaiten --json user-roles delete --role-id 1",
610
+ description="Delete a user role.",
611
+ ),
612
+ ),
613
+ ),
614
+ make_tool(
615
+ canonical_name="company-groups.list",
616
+ mcp_alias="kaiten_list_company_groups",
617
+ description="List company groups in Kaiten.",
618
+ input_schema={
619
+ "type": "object",
620
+ "properties": {
621
+ "query": {"type": "string", "description": "Search query"},
622
+ "limit": {"type": "integer", "description": "Max results to return"},
623
+ "offset": {"type": "integer", "description": "Offset for pagination"},
624
+ "with_tree_entities": {
625
+ "type": "boolean",
626
+ "description": "Add tree entities for each group",
627
+ },
628
+ "with_users_count": {
629
+ "type": "boolean",
630
+ "description": "Add users count for each group",
631
+ },
632
+ "with_sync_group_attribute": {
633
+ "type": "boolean",
634
+ "description": "Add sync attribute for each group",
635
+ },
636
+ "condition": {"description": "1 - active, 2 - inactive", "type": "string"},
637
+ },
638
+ },
639
+ operation=OperationSpec(
640
+ method="GET",
641
+ path_template="/company/groups",
642
+ query_fields=(
643
+ "query",
644
+ "limit",
645
+ "offset",
646
+ "with_tree_entities",
647
+ "with_users_count",
648
+ "with_sync_group_attribute",
649
+ "condition",
650
+ ),
651
+ ),
652
+ response_policy=ResponsePolicy(default_limit=50, result_kind="list"),
653
+ examples=(
654
+ ExampleSpec(
655
+ command='kaiten --json company-groups list --query "Engineering"',
656
+ description="List company groups.",
657
+ ),
658
+ ),
659
+ ),
660
+ make_tool(
661
+ canonical_name="company-groups.create",
662
+ mcp_alias="kaiten_create_company_group",
663
+ description="Create a new company group in Kaiten.",
664
+ input_schema={
665
+ "type": "object",
666
+ "properties": {
667
+ "name": {"type": "string", "description": "Group name"},
668
+ "permissions": {"type": "integer", "description": "Group permissions"},
669
+ "add_to_cards_and_spaces_enabled": {
670
+ "type": "boolean",
671
+ "description": "Should add cards and spaces",
672
+ },
673
+ },
674
+ "required": ["name"],
675
+ },
676
+ operation=OperationSpec(
677
+ method="POST",
678
+ path_template="/company/groups",
679
+ body_fields=("name", "permissions", "add_to_cards_and_spaces_enabled"),
680
+ ),
681
+ examples=(
682
+ ExampleSpec(
683
+ command='kaiten --json company-groups create --name "Engineering"',
684
+ description="Create a company group.",
685
+ ),
686
+ ),
687
+ ),
688
+ make_tool(
689
+ canonical_name="company-groups.get",
690
+ mcp_alias="kaiten_get_company_group",
691
+ description="Get a company group by UID.",
692
+ input_schema={
693
+ "type": "object",
694
+ "properties": {"group_uid": {"type": "string", "description": "Group UID"}},
695
+ "required": ["group_uid"],
696
+ },
697
+ operation=OperationSpec(
698
+ method="GET", path_template="/company/groups/{group_uid}", path_fields=("group_uid",)
699
+ ),
700
+ examples=(
701
+ ExampleSpec(
702
+ command="kaiten --json company-groups get --group-uid grp-1",
703
+ description="Get a company group.",
704
+ ),
705
+ ),
706
+ ),
707
+ make_tool(
708
+ canonical_name="company-groups.update",
709
+ mcp_alias="kaiten_update_company_group",
710
+ description="Update a company group in Kaiten.",
711
+ input_schema={
712
+ "type": "object",
713
+ "properties": {
714
+ "group_uid": {"type": "string", "description": "Group UID"},
715
+ "name": {"type": "string", "description": "New group name"},
716
+ "permissions": {"type": "integer", "description": "Group permissions(bit mask)"},
717
+ "add_to_cards_and_spaces_enabled": {
718
+ "type": "boolean",
719
+ "description": "Ability to add all users of the group to cards, placed in group spaces. Ability to filter logs by group in «Timesheets»",
720
+ },
721
+ },
722
+ "required": ["group_uid"],
723
+ },
724
+ operation=OperationSpec(
725
+ method="PATCH",
726
+ path_template="/company/groups/{group_uid}",
727
+ path_fields=("group_uid",),
728
+ body_fields=("name", "permissions", "add_to_cards_and_spaces_enabled"),
729
+ ),
730
+ examples=(
731
+ ExampleSpec(
732
+ command='kaiten --json company-groups update --group-uid grp-1 --name "Docs"',
733
+ description="Update a company group.",
734
+ ),
735
+ ),
736
+ ),
737
+ make_tool(
738
+ canonical_name="company-groups.delete",
739
+ mcp_alias="kaiten_delete_company_group",
740
+ description="Delete a company group in Kaiten.",
741
+ input_schema={
742
+ "type": "object",
743
+ "properties": {"group_uid": {"type": "string", "description": "Group UID"}},
744
+ "required": ["group_uid"],
745
+ },
746
+ operation=OperationSpec(
747
+ method="DELETE", path_template="/company/groups/{group_uid}", path_fields=("group_uid",)
748
+ ),
749
+ examples=(
750
+ ExampleSpec(
751
+ command="kaiten --json company-groups delete --group-uid grp-1",
752
+ description="Delete a company group.",
753
+ ),
754
+ ),
755
+ ),
756
+ make_tool(
757
+ canonical_name="group-users.list",
758
+ mcp_alias="kaiten_list_group_users",
759
+ description="List one page of users in a company group.",
760
+ input_schema={
761
+ "type": "object",
762
+ "properties": {
763
+ "group_uid": {"type": "string", "description": "Group UID"},
764
+ "limit": {
765
+ "type": "integer",
766
+ "minimum": 1,
767
+ "maximum": 100,
768
+ "description": "Max results (default 50, max 100)",
769
+ },
770
+ "offset": {"type": "integer", "minimum": 0, "description": "Pagination offset"},
771
+ "compact": {
772
+ "type": "boolean",
773
+ "description": "Return compact response without heavy fields.",
774
+ },
775
+ },
776
+ "required": ["group_uid"],
777
+ },
778
+ operation=OperationSpec(
779
+ method="GET",
780
+ path_template="/groups/{group_uid}/users",
781
+ path_fields=("group_uid",),
782
+ query_fields=("limit", "offset"),
783
+ ),
784
+ response_policy=ResponsePolicy(
785
+ compact_supported=True, default_limit=50, result_kind="list"
786
+ ),
787
+ examples=(
788
+ ExampleSpec(
789
+ command="kaiten --json group-users list --group-uid grp-1 --compact",
790
+ description="List group users.",
791
+ ),
792
+ ),
793
+ usage_notes=(
794
+ "This direct command returns one page; increase offset to read subsequent pages.",
795
+ ),
796
+ ),
797
+ make_tool(
798
+ canonical_name="group-users.add",
799
+ mcp_alias="kaiten_add_group_user",
800
+ description="Add a user to a company group.",
801
+ input_schema={
802
+ "type": "object",
803
+ "properties": {
804
+ "group_uid": {"type": "string", "description": "Group UID"},
805
+ "user_id": {"type": "integer", "description": "User ID to add"},
806
+ "request_id": {
807
+ "type": "string",
808
+ "description": "Request id if addition to the group is answer for access request",
809
+ },
810
+ "operator_comment": {
811
+ "minLength": 1,
812
+ "maxLength": 1024,
813
+ "description": "Operator's comment if addition to the group is answer for access request",
814
+ "type": ["string", "null"],
815
+ "x-documentation-alternatives": [
816
+ {
817
+ "type": "string",
818
+ "minLength": 1,
819
+ "maxLength": 1024,
820
+ "description": "Operator's comment if addition to the group is answer for access request",
821
+ },
822
+ {"type": "null"},
823
+ ],
824
+ },
825
+ },
826
+ "required": ["group_uid", "user_id"],
827
+ },
828
+ operation=OperationSpec(
829
+ method="POST",
830
+ path_template="/groups/{group_uid}/users",
831
+ path_fields=("group_uid",),
832
+ body_fields=("user_id", "request_id", "operator_comment"),
833
+ ),
834
+ examples=(
835
+ ExampleSpec(
836
+ command="kaiten --json group-users add --group-uid grp-1 --user-id 7",
837
+ description="Add a user to a group.",
838
+ ),
839
+ ),
840
+ ),
841
+ make_tool(
842
+ canonical_name="group-users.remove",
843
+ mcp_alias="kaiten_remove_group_user",
844
+ description="Remove a user from a company group.",
845
+ input_schema={
846
+ "type": "object",
847
+ "properties": {
848
+ "group_uid": {"type": "string", "description": "Group UID"},
849
+ "user_id": {"type": "integer", "description": "User ID to remove"},
850
+ },
851
+ "required": ["group_uid", "user_id"],
852
+ },
853
+ operation=OperationSpec(
854
+ method="DELETE",
855
+ path_template="/groups/{group_uid}/users/{user_id}",
856
+ path_fields=("group_uid", "user_id"),
857
+ ),
858
+ examples=(
859
+ ExampleSpec(
860
+ command="kaiten --json group-users remove --group-uid grp-1 --user-id 7",
861
+ description="Remove a user from a group.",
862
+ ),
863
+ ),
864
+ ),
865
+ make_tool(
866
+ canonical_name="group-admins.list",
867
+ mcp_alias="kaiten_list_group_admins",
868
+ description="List admins of a company group.",
869
+ input_schema={
870
+ "type": "object",
871
+ "properties": {
872
+ "group_uid": {"type": "string", "description": "Group UID"},
873
+ "compact": {
874
+ "type": "boolean",
875
+ "description": "Return compact response without heavy fields.",
876
+ },
877
+ },
878
+ "required": ["group_uid"],
879
+ },
880
+ operation=OperationSpec(
881
+ method="GET", path_template="/groups/{group_uid}/admins", path_fields=("group_uid",)
882
+ ),
883
+ response_policy=ResponsePolicy(compact_supported=True, result_kind="list"),
884
+ examples=(
885
+ ExampleSpec(
886
+ command="kaiten --json group-admins list --group-uid grp-1 --compact",
887
+ description="List group admins.",
888
+ ),
889
+ ),
890
+ ),
891
+ make_tool(
892
+ canonical_name="group-admins.add",
893
+ mcp_alias="kaiten_add_group_admin",
894
+ description="Add an admin to a company group.",
895
+ input_schema={
896
+ "type": "object",
897
+ "properties": {
898
+ "group_uid": {"type": "string", "description": "Group UID"},
899
+ "user_id": {"type": "integer", "description": "User ID to add as admin"},
900
+ },
901
+ "required": ["group_uid", "user_id"],
902
+ },
903
+ operation=OperationSpec(
904
+ method="POST",
905
+ path_template="/groups/{group_uid}/admins",
906
+ path_fields=("group_uid",),
907
+ body_fields=("user_id",),
908
+ ),
909
+ examples=(
910
+ ExampleSpec(
911
+ command="kaiten --json group-admins add --group-uid grp-1 --user-id 7",
912
+ description="Add a group admin.",
913
+ ),
914
+ ),
915
+ ),
916
+ make_tool(
917
+ canonical_name="group-admins.remove",
918
+ mcp_alias="kaiten_remove_group_admin",
919
+ description="Remove an admin from a company group.",
920
+ input_schema={
921
+ "type": "object",
922
+ "properties": {
923
+ "group_uid": {"type": "string", "description": "Group UID"},
924
+ "user_id": {"type": "integer", "description": "User ID to remove"},
925
+ },
926
+ "required": ["group_uid", "user_id"],
927
+ },
928
+ operation=OperationSpec(
929
+ method="DELETE",
930
+ path_template="/groups/{group_uid}/admins/{user_id}",
931
+ path_fields=("group_uid", "user_id"),
932
+ ),
933
+ examples=(
934
+ ExampleSpec(
935
+ command="kaiten --json group-admins remove --group-uid grp-1 --user-id 7",
936
+ description="Remove a group admin.",
937
+ ),
938
+ ),
939
+ ),
940
+ make_tool(
941
+ canonical_name="group-entities.list",
942
+ mcp_alias="kaiten_list_group_entities",
943
+ description="List tree entities attached to a company group.",
944
+ input_schema={
945
+ "type": "object",
946
+ "properties": {"group_uid": {"type": "string", "description": "Group UID"}},
947
+ "required": ["group_uid"],
948
+ },
949
+ operation=OperationSpec(
950
+ method="GET",
951
+ path_template="/company/groups/{group_uid}/entities",
952
+ path_fields=("group_uid",),
953
+ ),
954
+ response_policy=ResponsePolicy(result_kind="list"),
955
+ examples=(
956
+ ExampleSpec(
957
+ command="kaiten --json group-entities list --group-uid grp-1",
958
+ description="List group entities.",
959
+ ),
960
+ ),
961
+ ),
962
+ make_tool(
963
+ canonical_name="group-entities.add",
964
+ mcp_alias="kaiten_add_group_entity",
965
+ description="Attach a tree entity to a company group.",
966
+ input_schema={
967
+ "type": "object",
968
+ "properties": {
969
+ "group_uid": {"type": "string", "description": "Group UID"},
970
+ "entity_uid": {
971
+ "type": "string",
972
+ "description": "Tree entity UID",
973
+ "format": "uuid",
974
+ },
975
+ "role_ids": {
976
+ "type": "array",
977
+ "description": "Tree entity role IDs.",
978
+ "items": {"type": "string", "format": "uuid"},
979
+ },
980
+ "payload": {
981
+ "type": "object",
982
+ "description": "Extra JSON body fields from the Kaiten API docs.",
983
+ },
984
+ },
985
+ "required": ["group_uid", "entity_uid", "role_ids"],
986
+ },
987
+ operation=OperationSpec(
988
+ method="POST",
989
+ path_template="/company/groups/{group_uid}/entities",
990
+ path_fields=("group_uid",),
991
+ body_fields=("entity_uid", "role_ids", "payload"),
992
+ ),
993
+ runtime_behavior=RuntimeBehavior(request_shaper=payload_body_request),
994
+ examples=(
995
+ ExampleSpec(
996
+ command="kaiten --json group-entities add --group-uid grp-1 --entity-uid entity-1 --role-ids '[\"role-1\"]'",
997
+ description="Attach a group entity.",
998
+ ),
999
+ ),
1000
+ ),
1001
+ make_tool(
1002
+ canonical_name="group-entities.update",
1003
+ mcp_alias="kaiten_update_group_entity",
1004
+ description="Update a tree entity attached to a company group.",
1005
+ input_schema={
1006
+ "type": "object",
1007
+ "properties": {
1008
+ "group_uid": {"type": "string", "description": "Group UID"},
1009
+ "entity_uid": {"type": "string", "description": "Tree entity UID"},
1010
+ "role_ids": {
1011
+ "type": "array",
1012
+ "description": "Tree entity role IDs.",
1013
+ "items": {"type": "string", "format": "uuid"},
1014
+ },
1015
+ "payload": {
1016
+ "type": "object",
1017
+ "description": "Extra JSON body fields from the Kaiten API docs.",
1018
+ },
1019
+ },
1020
+ "required": ["group_uid", "entity_uid"],
1021
+ },
1022
+ operation=OperationSpec(
1023
+ method="PATCH",
1024
+ path_template="/company/groups/{group_uid}/entities/{entity_uid}",
1025
+ path_fields=("group_uid", "entity_uid"),
1026
+ body_fields=("role_ids", "payload"),
1027
+ ),
1028
+ runtime_behavior=RuntimeBehavior(request_shaper=payload_body_request),
1029
+ examples=(
1030
+ ExampleSpec(
1031
+ command="kaiten --json group-entities update --group-uid grp-1 --entity-uid entity-1 --role-ids '[\"role-1\"]'",
1032
+ description="Update a group entity.",
1033
+ ),
1034
+ ),
1035
+ ),
1036
+ make_tool(
1037
+ canonical_name="group-entities.remove",
1038
+ mcp_alias="kaiten_remove_group_entity",
1039
+ description="Remove a tree entity from a company group.",
1040
+ input_schema={
1041
+ "type": "object",
1042
+ "properties": {
1043
+ "group_uid": {"type": "string", "description": "Group UID"},
1044
+ "entity_uid": {"type": "string", "description": "Tree entity UID"},
1045
+ },
1046
+ "required": ["group_uid", "entity_uid"],
1047
+ },
1048
+ operation=OperationSpec(
1049
+ method="DELETE",
1050
+ path_template="/company/groups/{group_uid}/entities/{entity_uid}",
1051
+ path_fields=("group_uid", "entity_uid"),
1052
+ ),
1053
+ examples=(
1054
+ ExampleSpec(
1055
+ command="kaiten --json group-entities remove --group-uid grp-1 --entity-uid entity-1",
1056
+ description="Remove a group entity.",
1057
+ ),
1058
+ ),
1059
+ ),
1060
+ make_tool(
1061
+ canonical_name="roles.list",
1062
+ mcp_alias="kaiten_list_roles",
1063
+ description="List available roles in Kaiten.",
1064
+ input_schema={
1065
+ "type": "object",
1066
+ "properties": {
1067
+ "query": {"type": "string", "description": "Search query"},
1068
+ "limit": {"type": "integer", "description": "Max results to return"},
1069
+ "offset": {"type": "integer", "description": "Offset for pagination"},
1070
+ },
1071
+ },
1072
+ operation=OperationSpec(
1073
+ method="GET",
1074
+ path_template="/tree-entity-roles",
1075
+ query_fields=("query", "limit", "offset"),
1076
+ ),
1077
+ response_policy=ResponsePolicy(default_limit=50, result_kind="list"),
1078
+ examples=(
1079
+ ExampleSpec(
1080
+ command='kaiten --json roles list --query "admin"', description="List roles."
1081
+ ),
1082
+ ),
1083
+ ),
1084
+ make_tool(
1085
+ canonical_name="roles.get",
1086
+ mcp_alias="kaiten_get_role",
1087
+ description="Get a role by ID.",
1088
+ input_schema={
1089
+ "type": "object",
1090
+ "properties": {"role_id": {"type": "string", "description": "Role ID (UUID)"}},
1091
+ "required": ["role_id"],
1092
+ },
1093
+ operation=OperationSpec(
1094
+ method="GET", path_template="/tree-entity-roles/{role_id}", path_fields=("role_id",)
1095
+ ),
1096
+ examples=(
1097
+ ExampleSpec(
1098
+ command="kaiten --json roles get --role-id role-1", description="Get a role."
1099
+ ),
1100
+ ),
1101
+ ),
1102
+ )