@tribeunal/mcp-server 1.13.0

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 (102) hide show
  1. package/CHANGELOG.md +287 -0
  2. package/LICENSE +21 -0
  3. package/README.md +196 -0
  4. package/dist/auth/auth.d.ts +8 -0
  5. package/dist/auth/auth.d.ts.map +1 -0
  6. package/dist/auth/auth.js +14 -0
  7. package/dist/auth/auth.js.map +1 -0
  8. package/dist/client/api-client.d.ts +216 -0
  9. package/dist/client/api-client.d.ts.map +1 -0
  10. package/dist/client/api-client.js +325 -0
  11. package/dist/client/api-client.js.map +1 -0
  12. package/dist/client/from-env.d.ts +17 -0
  13. package/dist/client/from-env.d.ts.map +1 -0
  14. package/dist/client/from-env.js +25 -0
  15. package/dist/client/from-env.js.map +1 -0
  16. package/dist/core/instructions.d.ts +14 -0
  17. package/dist/core/instructions.d.ts.map +1 -0
  18. package/dist/core/instructions.js +21 -0
  19. package/dist/core/instructions.js.map +1 -0
  20. package/dist/core/stdio-register.d.ts +14 -0
  21. package/dist/core/stdio-register.d.ts.map +1 -0
  22. package/dist/core/stdio-register.js +39 -0
  23. package/dist/core/stdio-register.js.map +1 -0
  24. package/dist/core/tools.d.ts +1072 -0
  25. package/dist/core/tools.d.ts.map +1 -0
  26. package/dist/core/tools.js +1041 -0
  27. package/dist/core/tools.js.map +1 -0
  28. package/dist/index.d.ts +3 -0
  29. package/dist/index.d.ts.map +1 -0
  30. package/dist/index.js +40 -0
  31. package/dist/index.js.map +1 -0
  32. package/dist/server.d.ts +15 -0
  33. package/dist/server.d.ts.map +1 -0
  34. package/dist/server.js +19 -0
  35. package/dist/server.js.map +1 -0
  36. package/dist/tools/activity.d.ts +98 -0
  37. package/dist/tools/activity.d.ts.map +1 -0
  38. package/dist/tools/activity.js +167 -0
  39. package/dist/tools/activity.js.map +1 -0
  40. package/dist/tools/cases.d.ts +154 -0
  41. package/dist/tools/cases.d.ts.map +1 -0
  42. package/dist/tools/cases.js +91 -0
  43. package/dist/tools/cases.js.map +1 -0
  44. package/dist/tools/comments.d.ts +29 -0
  45. package/dist/tools/comments.d.ts.map +1 -0
  46. package/dist/tools/comments.js +17 -0
  47. package/dist/tools/comments.js.map +1 -0
  48. package/dist/tools/decisions.d.ts +297 -0
  49. package/dist/tools/decisions.d.ts.map +1 -0
  50. package/dist/tools/decisions.js +102 -0
  51. package/dist/tools/decisions.js.map +1 -0
  52. package/dist/tools/jury-duty.d.ts +56 -0
  53. package/dist/tools/jury-duty.d.ts.map +1 -0
  54. package/dist/tools/jury-duty.js +39 -0
  55. package/dist/tools/jury-duty.js.map +1 -0
  56. package/dist/tools/sides.d.ts +15 -0
  57. package/dist/tools/sides.d.ts.map +1 -0
  58. package/dist/tools/sides.js +11 -0
  59. package/dist/tools/sides.js.map +1 -0
  60. package/dist/tools/trials.d.ts +78 -0
  61. package/dist/tools/trials.d.ts.map +1 -0
  62. package/dist/tools/trials.js +29 -0
  63. package/dist/tools/trials.js.map +1 -0
  64. package/dist/tools/tribes.d.ts +75 -0
  65. package/dist/tools/tribes.d.ts.map +1 -0
  66. package/dist/tools/tribes.js +47 -0
  67. package/dist/tools/tribes.js.map +1 -0
  68. package/dist/tools/users.d.ts +9 -0
  69. package/dist/tools/users.d.ts.map +1 -0
  70. package/dist/tools/users.js +6 -0
  71. package/dist/tools/users.js.map +1 -0
  72. package/dist/tools/uuid.d.ts +35 -0
  73. package/dist/tools/uuid.d.ts.map +1 -0
  74. package/dist/tools/uuid.js +77 -0
  75. package/dist/tools/uuid.js.map +1 -0
  76. package/dist/tools/votes.d.ts +45 -0
  77. package/dist/tools/votes.d.ts.map +1 -0
  78. package/dist/tools/votes.js +22 -0
  79. package/dist/tools/votes.js.map +1 -0
  80. package/dist/tools/webhooks.d.ts +26 -0
  81. package/dist/tools/webhooks.d.ts.map +1 -0
  82. package/dist/tools/webhooks.js +39 -0
  83. package/dist/tools/webhooks.js.map +1 -0
  84. package/dist/utils/format.d.ts +4 -0
  85. package/dist/utils/format.d.ts.map +1 -0
  86. package/dist/utils/format.js +24 -0
  87. package/dist/utils/format.js.map +1 -0
  88. package/llms-install.md +81 -0
  89. package/package.json +73 -0
  90. package/skills/README.md +43 -0
  91. package/skills/acting-on-verdicts/SKILL.md +103 -0
  92. package/skills/arbitrating-a-dispute/SKILL.md +107 -0
  93. package/skills/convening-a-team-jury/SKILL.md +94 -0
  94. package/skills/deciding-with-a-jury/SKILL.md +120 -0
  95. package/skills/serving-jury-duty/SKILL.md +90 -0
  96. package/skills/using-tribeunal/SKILL.md +56 -0
  97. package/skills/using-tribeunal/references/errors.md +54 -0
  98. package/skills/using-tribeunal/references/tools.md +53 -0
  99. package/skills/weighing-evidence/SKILL.md +94 -0
  100. package/skills/wiring-webhooks/SKILL.md +107 -0
  101. package/skills/wiring-webhooks/references/events.md +52 -0
  102. package/skills/wiring-webhooks/scripts/verify-signature.js +72 -0
@@ -0,0 +1,1072 @@
1
+ import { TribeunalAPIClient } from '../client/api-client.js';
2
+ import { type AwaitContext } from '../tools/activity.js';
3
+ /**
4
+ * The canonical list of tool definitions advertised via `tools/list`.
5
+ *
6
+ * A single "case" vocabulary: every tool maps directly to a Tribeunal API
7
+ * operation. The stdio server and the Cloudflare worker advertise the SAME
8
+ * set so behaviour is identical regardless of how the caller authenticated.
9
+ */
10
+ export declare const TOOL_DEFINITIONS: readonly [{
11
+ readonly name: "tribeunal_create_case";
12
+ readonly title: "Create case";
13
+ readonly annotations: {
14
+ readonly title: "Create case";
15
+ readonly readOnlyHint: false;
16
+ readonly destructiveHint: false;
17
+ readonly openWorldHint: false;
18
+ };
19
+ readonly description: "Create a new case on Tribeunal for community decision-making (case = jury decides, advice = creator decides, poll = opinion gathering). Use this directly when the user wants to start, decide, settle, or put something to a vote and no specific existing case is referenced — do NOT search first. Set visibility to \"private\" to keep a case visible only to you, your invited jurors and admins (a private case runs an invited jury). Add allowsGuestVotes to a private case to make a link-poll instead: unlisted everywhere, but readable and votable by anyone you send the link to. A private case answers with a shareUrl — a view-only link (no voting/joining) you can send to anyone; rotate it from the case web page to revoke every old link at once.";
20
+ readonly inputSchema: {
21
+ readonly type: "object";
22
+ readonly properties: {
23
+ readonly title: {
24
+ readonly type: "string";
25
+ readonly minLength: 3;
26
+ readonly maxLength: 200;
27
+ readonly description: "Case title — the question or statement to be decided";
28
+ };
29
+ readonly description: {
30
+ readonly type: "string";
31
+ readonly minLength: 10;
32
+ readonly description: "Context, background, and criteria for the case";
33
+ };
34
+ readonly type: {
35
+ readonly type: "string";
36
+ readonly enum: readonly ["case", "advice", "poll"];
37
+ readonly description: "Case type — case (binding jury decision), advice (input for the creator), or poll (opinion gathering)";
38
+ };
39
+ readonly juryType: {
40
+ readonly type: "string";
41
+ readonly enum: readonly ["public", "invited"];
42
+ readonly default: "public";
43
+ readonly description: "Who can participate — public (anyone) or invited only";
44
+ };
45
+ readonly visibility: {
46
+ readonly type: "string";
47
+ readonly enum: readonly ["public", "private"];
48
+ readonly default: "public";
49
+ readonly description: "Case visibility — public (anyone can find and read it) or private (only you, your invited jurors and admins). A private case must use an invited jury; omit juryType and it is set to invited automatically. One exception: set allowsGuestVotes on a private case and it becomes a link-poll — still absent from every listing, search and feed, but readable and votable by anyone you send the link to — which takes a public jury instead.";
50
+ };
51
+ readonly sides: {
52
+ readonly type: "array";
53
+ readonly items: {
54
+ readonly type: "object";
55
+ readonly properties: {
56
+ readonly name: {
57
+ readonly type: "string";
58
+ readonly description: "Option/choice name";
59
+ };
60
+ readonly description: {
61
+ readonly type: "string";
62
+ readonly description: "Optional description for this choice";
63
+ };
64
+ readonly image: {
65
+ readonly type: "string";
66
+ readonly format: "uri";
67
+ readonly description: "Optional https image URL for this choice — fetched and re-encoded server-side (png/jpeg/webp, <= 5 MB). Shown on the choice's vote card.";
68
+ };
69
+ };
70
+ readonly required: readonly ["name"];
71
+ };
72
+ readonly minItems: 2;
73
+ readonly maxItems: 10;
74
+ readonly description: "The choices/options voters pick between (2-10)";
75
+ };
76
+ readonly caseLength: {
77
+ readonly type: "number";
78
+ readonly minimum: 60;
79
+ readonly maximum: 2592000;
80
+ readonly default: 86400;
81
+ readonly description: "Voting duration in seconds (min: 1 minute, max: 30 days, default: 1 day)";
82
+ };
83
+ readonly maxAiJurorPercentage: {
84
+ readonly type: "integer";
85
+ readonly minimum: 0;
86
+ readonly maximum: 100;
87
+ readonly description: "Maximum percentage of jurors that may be AI personas (0 = none allowed, 100 = all; default 50)";
88
+ };
89
+ readonly jurorCount: {
90
+ readonly type: "integer";
91
+ readonly minimum: 2;
92
+ readonly maximum: 100;
93
+ readonly description: "Number of jurors the case asks for (2-100, default 12). It gates opening only when openImmediately is false, where the case waits until this many jurors have joined. For a small invited panel, set this to the number of people you invite.";
94
+ };
95
+ readonly openImmediately: {
96
+ readonly type: "boolean";
97
+ readonly description: "Open the case for voting straight away (default true). Invited jurors are still invited and can view, join and vote while it is already open. Set false to hold the case in jury selection until jurorCount jurors have joined, and only then open it.";
98
+ };
99
+ readonly allowsGuestVotes: {
100
+ readonly type: "boolean";
101
+ readonly description: "Let visitors without a Tribeunal account vote on this case (default false). Guest votes count in full — they enter the tallies, percentages and the verdict exactly like a registered juror's. Requires a public jury; visibility may be either, and pairing it with visibility \"private\" makes a link-poll: unlisted everywhere, but votable by whoever holds the link. Guests are deduplicated per browser, so a returning visitor changes their vote rather than adding one, but someone determined can still vote again from another browser — enable it where reach matters more than strict one-person-one-vote.";
102
+ };
103
+ readonly arbitrationMode: {
104
+ readonly type: "boolean";
105
+ readonly description: "Bind this case to arbitration rules, for a verdict someone outside the case has to rely on (default false). You cannot vote on, join the jury of, or close early a case you created in this mode — an admin closes it, or it closes at its deadline; evidence marks freeze once it closes so the record it was decided on stops moving; and the early-vote and decisive-vote reward multipliers are switched off, so timing your vote no longer multiplies your payout. Requires minVotes of at least 2 (omit it and 3 is used) and cannot be combined with allowsGuestVotes. Use it when the case settles something with stakes — a dispute, a payout, a contract term — rather than gathering opinion.";
106
+ };
107
+ readonly decisionRequirement: {
108
+ readonly type: "string";
109
+ readonly enum: readonly ["any", "simple", "qualified", "unanimous"];
110
+ readonly description: "The weakest outcome this case will accept as a verdict (default \"any\"). \"any\" takes whatever the tally gives, down to a plurality. \"simple\" needs at least half, \"qualified\" at least 66%, \"unanimous\" every vote on one side. A case that reaches a stronger result than required still reports the stronger one. On any value other than \"any\", missing the requirement closes the case with a Void verdict carrying voidReason \"requirement_not_met\"; an \"any\" case that merely ties stays Undecided.";
111
+ };
112
+ readonly minVotes: {
113
+ readonly type: "integer";
114
+ readonly minimum: 0;
115
+ readonly maximum: 100;
116
+ readonly description: "Fewest votes this case needs before it can reach a verdict (0-100, default 0 = no minimum). Close it with fewer and it ends with a Void verdict carrying voidReason \"quorum_not_met\" rather than deciding on a turnout of one or two.";
117
+ };
118
+ readonly tags: {
119
+ readonly type: "array";
120
+ readonly items: {
121
+ readonly type: "string";
122
+ };
123
+ readonly maxItems: 4;
124
+ readonly description: "Up to 4 tags for categorization";
125
+ };
126
+ };
127
+ readonly required: readonly ["title", "description", "type", "sides"];
128
+ };
129
+ }, {
130
+ readonly name: "tribeunal_search_cases";
131
+ readonly title: "Search cases";
132
+ readonly annotations: {
133
+ readonly title: "Search cases";
134
+ readonly readOnlyHint: true;
135
+ readonly openWorldHint: false;
136
+ };
137
+ readonly description: "Find existing cases on Tribeunal by query, status, type, or tags. Use only when the user wants to look up or reference an existing case — to start a new one, use tribeunal_create_case.";
138
+ readonly inputSchema: {
139
+ readonly type: "object";
140
+ readonly properties: {
141
+ readonly query: {
142
+ readonly type: "string";
143
+ readonly description: "Search query for case title or description";
144
+ };
145
+ readonly status: {
146
+ readonly type: "string";
147
+ readonly enum: readonly ["init", "jury_selection", "open", "closed", "expired", "suspended"];
148
+ readonly description: "Case status filter (open = accepting votes, jury_selection = still assembling its jury)";
149
+ };
150
+ readonly type: {
151
+ readonly type: "string";
152
+ readonly enum: readonly ["case", "advice", "poll"];
153
+ readonly description: "Case type filter";
154
+ };
155
+ readonly tags: {
156
+ readonly type: "array";
157
+ readonly items: {
158
+ readonly type: "string";
159
+ };
160
+ readonly description: "Filter by tags";
161
+ };
162
+ readonly page: {
163
+ readonly type: "number";
164
+ readonly minimum: 1;
165
+ readonly default: 1;
166
+ readonly description: "Page number for pagination";
167
+ };
168
+ readonly limit: {
169
+ readonly type: "number";
170
+ readonly minimum: 1;
171
+ readonly maximum: 100;
172
+ readonly default: 20;
173
+ readonly description: "Number of results per page";
174
+ };
175
+ };
176
+ };
177
+ }, {
178
+ readonly name: "tribeunal_get_case";
179
+ readonly title: "Get case";
180
+ readonly annotations: {
181
+ readonly title: "Get case";
182
+ readonly readOnlyHint: true;
183
+ readonly openWorldHint: false;
184
+ };
185
+ readonly description: "Get detailed information about a specific case. For a private case you own, the response includes a shareUrl: a view-only link (no voting/joining) you can send to anyone; rotate it from the case web page to revoke old links.";
186
+ readonly inputSchema: {
187
+ readonly type: "object";
188
+ readonly properties: {
189
+ readonly id: {
190
+ readonly type: "string";
191
+ readonly pattern: "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$";
192
+ readonly description: "Case UUID (the case uuid, not the numeric id)";
193
+ };
194
+ };
195
+ readonly required: readonly ["id"];
196
+ };
197
+ }, {
198
+ readonly name: "tribeunal_close_case";
199
+ readonly title: "Close case";
200
+ readonly annotations: {
201
+ readonly title: "Close case";
202
+ readonly readOnlyHint: false;
203
+ readonly destructiveHint: true;
204
+ readonly openWorldHint: false;
205
+ };
206
+ readonly description: "Close one of YOUR cases early (case owner or admin only). Works on open cases and on cases still in jury_selection (an abandoned jury ends Undecided). Pulls the voting deadline to now and triggers the verdict pipeline; the decision is determined asynchronously. Follow up with tribeunal_await_verdict to read the outcome. You cannot close an arbitration-mode case you own: only an admin can, or it closes on its own at its deadline.";
207
+ readonly inputSchema: {
208
+ readonly type: "object";
209
+ readonly properties: {
210
+ readonly caseId: {
211
+ readonly type: "string";
212
+ readonly pattern: "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$";
213
+ readonly description: "Case UUID of the open or jury_selection case to close early (owner or admin only)";
214
+ };
215
+ };
216
+ readonly required: readonly ["caseId"];
217
+ };
218
+ }, {
219
+ readonly name: "tribeunal_set_side_image";
220
+ readonly title: "Set side image";
221
+ readonly annotations: {
222
+ readonly title: "Set side image";
223
+ readonly readOnlyHint: false;
224
+ readonly destructiveHint: false;
225
+ readonly openWorldHint: true;
226
+ };
227
+ readonly description: "Set or replace the image shown on a case side's vote card, fetched from a public https URL. Owner-only. The image is downloaded and re-encoded server-side (png/jpeg/webp, <= 5 MB); http URLs, private/internal hosts and non-images are rejected. Use the case's and side's `uuid` fields (from tribeunal_get_case), not numeric ids.";
228
+ readonly inputSchema: {
229
+ readonly type: "object";
230
+ readonly properties: {
231
+ readonly caseId: {
232
+ readonly type: "string";
233
+ readonly pattern: "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$";
234
+ readonly description: "Case UUID the side belongs to (the case's uuid field)";
235
+ };
236
+ readonly sideId: {
237
+ readonly type: "string";
238
+ readonly pattern: "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$";
239
+ readonly description: "Side UUID to set the image on (the side's uuid field)";
240
+ };
241
+ readonly imageUrl: {
242
+ readonly type: "string";
243
+ readonly format: "uri";
244
+ readonly description: "Public https URL of the image (png/jpeg/webp, <= 5 MB)";
245
+ };
246
+ };
247
+ readonly required: readonly ["caseId", "sideId", "imageUrl"];
248
+ };
249
+ }, {
250
+ readonly name: "tribeunal_list_evidence";
251
+ readonly title: "List evidence";
252
+ readonly annotations: {
253
+ readonly title: "List evidence";
254
+ readonly readOnlyHint: true;
255
+ readonly openWorldHint: false;
256
+ };
257
+ readonly description: "Get a case's marked evidence — comments and case files the owner/jury marked as evidence (kind: comment|file)";
258
+ readonly inputSchema: {
259
+ readonly type: "object";
260
+ readonly properties: {
261
+ readonly caseId: {
262
+ readonly type: "string";
263
+ readonly pattern: "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$";
264
+ readonly description: "Case UUID to get evidence for";
265
+ };
266
+ };
267
+ readonly required: readonly ["caseId"];
268
+ };
269
+ }, {
270
+ readonly name: "tribeunal_cast_vote";
271
+ readonly title: "Cast vote";
272
+ readonly annotations: {
273
+ readonly title: "Cast vote";
274
+ readonly readOnlyHint: false;
275
+ readonly destructiveHint: false;
276
+ readonly openWorldHint: false;
277
+ };
278
+ readonly description: "Cast a vote on a case for a specific side/option, optionally with a short comment explaining your reasoning (shown in the case activity feed). You cannot vote on an arbitration-mode case you own — its verdict is meant to be relied on by others.";
279
+ readonly inputSchema: {
280
+ readonly type: "object";
281
+ readonly properties: {
282
+ readonly caseId: {
283
+ readonly type: "string";
284
+ readonly pattern: "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$";
285
+ readonly description: "Case UUID to vote on";
286
+ };
287
+ readonly sideId: {
288
+ readonly type: "string";
289
+ readonly pattern: "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$";
290
+ readonly description: "Side UUID to vote for (a side uuid from get_case)";
291
+ };
292
+ readonly comment: {
293
+ readonly type: "string";
294
+ readonly maxLength: 2000;
295
+ readonly description: "Optional short rationale, stored as a vote-linked comment (markable as evidence by the owner/jury)";
296
+ };
297
+ };
298
+ readonly required: readonly ["caseId", "sideId"];
299
+ };
300
+ }, {
301
+ readonly name: "tribeunal_revoke_vote";
302
+ readonly title: "Revoke vote";
303
+ readonly annotations: {
304
+ readonly title: "Revoke vote";
305
+ readonly readOnlyHint: false;
306
+ readonly destructiveHint: false;
307
+ readonly openWorldHint: false;
308
+ };
309
+ readonly description: "Revoke a previously cast vote (penalties may apply)";
310
+ readonly inputSchema: {
311
+ readonly type: "object";
312
+ readonly properties: {
313
+ readonly caseId: {
314
+ readonly type: "string";
315
+ readonly pattern: "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$";
316
+ readonly description: "Case UUID";
317
+ };
318
+ readonly sideId: {
319
+ readonly type: "string";
320
+ readonly pattern: "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$";
321
+ readonly description: "Side UUID whose vote to revoke (the API resolves the caller's vote by user+case)";
322
+ };
323
+ };
324
+ readonly required: readonly ["caseId", "sideId"];
325
+ };
326
+ }, {
327
+ readonly name: "tribeunal_get_vote_stats";
328
+ readonly title: "Get vote stats";
329
+ readonly annotations: {
330
+ readonly title: "Get vote stats";
331
+ readonly readOnlyHint: true;
332
+ readonly openWorldHint: false;
333
+ };
334
+ readonly description: "Get real-time voting statistics for a case";
335
+ readonly inputSchema: {
336
+ readonly type: "object";
337
+ readonly properties: {
338
+ readonly caseId: {
339
+ readonly type: "string";
340
+ readonly pattern: "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$";
341
+ readonly description: "Case UUID to get voting statistics for";
342
+ };
343
+ };
344
+ readonly required: readonly ["caseId"];
345
+ };
346
+ }, {
347
+ readonly name: "tribeunal_post_comment";
348
+ readonly title: "Post comment";
349
+ readonly annotations: {
350
+ readonly title: "Post comment";
351
+ readonly readOnlyHint: false;
352
+ readonly destructiveHint: false;
353
+ readonly openWorldHint: false;
354
+ };
355
+ readonly description: "Post a comment on a case — e.g. your analysis or perspective, in your own voice. Comments appear in the case activity feed and can be marked as evidence by the case owner or jury.";
356
+ readonly inputSchema: {
357
+ readonly type: "object";
358
+ readonly properties: {
359
+ readonly caseId: {
360
+ readonly type: "string";
361
+ readonly pattern: "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$";
362
+ readonly description: "Case UUID to comment on";
363
+ };
364
+ readonly text: {
365
+ readonly type: "string";
366
+ readonly minLength: 1;
367
+ readonly maxLength: 5000;
368
+ readonly description: "Comment text (1-5000 chars)";
369
+ };
370
+ };
371
+ readonly required: readonly ["caseId", "text"];
372
+ };
373
+ }, {
374
+ readonly name: "tribeunal_list_comments";
375
+ readonly title: "List comments";
376
+ readonly annotations: {
377
+ readonly title: "List comments";
378
+ readonly readOnlyHint: true;
379
+ readonly openWorldHint: false;
380
+ };
381
+ readonly description: "List a case's comments — use it to avoid posting duplicates and to find comment ids for evidence marking";
382
+ readonly inputSchema: {
383
+ readonly type: "object";
384
+ readonly properties: {
385
+ readonly caseId: {
386
+ readonly type: "string";
387
+ readonly pattern: "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$";
388
+ readonly description: "Case UUID to list comments for";
389
+ };
390
+ };
391
+ readonly required: readonly ["caseId"];
392
+ };
393
+ }, {
394
+ readonly name: "tribeunal_mark_evidence";
395
+ readonly title: "Mark comment as evidence";
396
+ readonly annotations: {
397
+ readonly title: "Mark comment as evidence";
398
+ readonly readOnlyHint: false;
399
+ readonly destructiveHint: false;
400
+ readonly openWorldHint: false;
401
+ };
402
+ readonly description: "Mark another user's comment or a case file as evidence (case owner or jury members only; you cannot mark your own comment). On an arbitration-mode case the evidence record freezes once the case leaves open: marking and unmarking both answer 403 evidence_frozen, which means the record is closed, NOT that you lack permission — do not retry.";
403
+ readonly inputSchema: {
404
+ readonly type: "object";
405
+ readonly properties: {
406
+ readonly kind: {
407
+ readonly type: "string";
408
+ readonly enum: readonly ["comment", "file"];
409
+ readonly description: "What to mark: 'comment' or 'file' (case file)";
410
+ };
411
+ readonly id: {
412
+ readonly type: "string";
413
+ readonly description: "UUID of the comment or case file";
414
+ };
415
+ };
416
+ readonly required: readonly ["kind", "id"];
417
+ };
418
+ }, {
419
+ readonly name: "tribeunal_unmark_evidence";
420
+ readonly title: "Unmark evidence";
421
+ readonly annotations: {
422
+ readonly title: "Unmark evidence";
423
+ readonly readOnlyHint: false;
424
+ readonly destructiveHint: false;
425
+ readonly openWorldHint: false;
426
+ };
427
+ readonly description: "Remove an evidence mark from a comment or case file (case owner or jury members only). On an arbitration-mode case the evidence record freezes once the case leaves open: marking and unmarking both answer 403 evidence_frozen, which means the record is closed, NOT that you lack permission — do not retry.";
428
+ readonly inputSchema: {
429
+ readonly type: "object";
430
+ readonly properties: {
431
+ readonly kind: {
432
+ readonly type: "string";
433
+ readonly enum: readonly ["comment", "file"];
434
+ readonly description: "What to unmark: 'comment' or 'file' (case file)";
435
+ };
436
+ readonly id: {
437
+ readonly type: "string";
438
+ readonly description: "UUID of the comment or case file";
439
+ };
440
+ };
441
+ readonly required: readonly ["kind", "id"];
442
+ };
443
+ }, {
444
+ readonly name: "tribeunal_rate_evidence";
445
+ readonly title: "Rate evidence";
446
+ readonly annotations: {
447
+ readonly title: "Rate evidence";
448
+ readonly readOnlyHint: false;
449
+ readonly destructiveHint: false;
450
+ readonly openWorldHint: false;
451
+ };
452
+ readonly description: "Rate case-file evidence: 1 (up), 0 (irrelevant), or -1 (down). File-evidence ids only — comments are not ratable.";
453
+ readonly inputSchema: {
454
+ readonly type: "object";
455
+ readonly properties: {
456
+ readonly evidenceId: {
457
+ readonly type: "string";
458
+ readonly description: "Case-file evidence ID to rate";
459
+ };
460
+ readonly rating: {
461
+ readonly type: "integer";
462
+ readonly enum: readonly [-1, 0, 1];
463
+ readonly description: "Rating: 1 (up), 0 (irrelevant), or -1 (down)";
464
+ };
465
+ readonly sideId: {
466
+ readonly type: "string";
467
+ readonly pattern: "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$";
468
+ readonly description: "Optional side UUID this rating relates to";
469
+ };
470
+ };
471
+ readonly required: readonly ["evidenceId", "rating"];
472
+ };
473
+ }, {
474
+ readonly name: "tribeunal_get_case_activity";
475
+ readonly title: "Get case activity";
476
+ readonly annotations: {
477
+ readonly title: "Get case activity";
478
+ readonly readOnlyHint: true;
479
+ readonly openWorldHint: false;
480
+ };
481
+ readonly description: "Read a page of a case's activity feed (votes, comments, evidence marks, jury joins, closure) as a cursorable event stream. Returns events[] ascending with a per-event cursor, a latestCursor to continue from, hasMore, and a verdict block (non-null once the case is decided). Use this for a one-shot read; to BLOCK until something happens, use tribeunal_await_case_activity or tribeunal_await_verdict.";
482
+ readonly inputSchema: {
483
+ readonly type: "object";
484
+ readonly properties: {
485
+ readonly caseId: {
486
+ readonly type: "string";
487
+ readonly pattern: "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$";
488
+ readonly description: "Case UUID whose activity to read";
489
+ };
490
+ readonly after: {
491
+ readonly type: "string";
492
+ readonly description: "Opaque cursor from a previous response; omit for the tail (latest events)";
493
+ };
494
+ readonly types: {
495
+ readonly type: "array";
496
+ readonly items: {
497
+ readonly type: "string";
498
+ readonly enum: readonly ["vote", "vote_revoked", "comment", "evidence_marked", "evidence_unmarked", "jury_joined", "trial_closed", "trial_reopened"];
499
+ };
500
+ readonly description: "Restrict to these event types";
501
+ };
502
+ readonly limit: {
503
+ readonly type: "number";
504
+ readonly minimum: 1;
505
+ readonly maximum: 100;
506
+ readonly default: 50;
507
+ readonly description: "Max events (1-100, default 50)";
508
+ };
509
+ };
510
+ readonly required: readonly ["caseId"];
511
+ };
512
+ }, {
513
+ readonly name: "tribeunal_await_case_activity";
514
+ readonly title: "Await case activity";
515
+ readonly annotations: {
516
+ readonly title: "Await case activity";
517
+ readonly readOnlyHint: true;
518
+ readonly openWorldHint: false;
519
+ };
520
+ readonly description: "Block until a NEW event appears on a case (long-poll, up to timeoutS seconds). Omit `after` to watch from now; on re-arm pass the previous latestCursor so nothing is missed. Returns {events, latestCursor, timedOut, waitedS, ...}. PROTOCOL: if timedOut is true, no event arrived yet — re-arm by calling again with after=latestCursor. Check caseEndsAt to know when activity is expected and STOP re-arming well past it (tell the human instead of looping forever).";
521
+ readonly inputSchema: {
522
+ readonly type: "object";
523
+ readonly properties: {
524
+ readonly caseId: {
525
+ readonly type: "string";
526
+ readonly pattern: "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$";
527
+ readonly description: "Case UUID to watch";
528
+ };
529
+ readonly after: {
530
+ readonly type: "string";
531
+ readonly description: "Cursor to watch from; omit to anchor at the current tail (\"watch from now\")";
532
+ };
533
+ readonly types: {
534
+ readonly type: "array";
535
+ readonly items: {
536
+ readonly type: "string";
537
+ readonly enum: readonly ["vote", "vote_revoked", "comment", "evidence_marked", "evidence_unmarked", "jury_joined", "trial_closed", "trial_reopened"];
538
+ };
539
+ readonly description: "Only wake for these event types";
540
+ };
541
+ readonly timeoutS: {
542
+ readonly type: "integer";
543
+ readonly minimum: 5;
544
+ readonly maximum: 170;
545
+ readonly default: 120;
546
+ readonly description: "Seconds to block (5-170). On timeout, re-arm with the returned latestCursor.";
547
+ };
548
+ };
549
+ readonly required: readonly ["caseId"];
550
+ };
551
+ }, {
552
+ readonly name: "tribeunal_await_verdict";
553
+ readonly title: "Await verdict";
554
+ readonly annotations: {
555
+ readonly title: "Await verdict";
556
+ readonly readOnlyHint: true;
557
+ readonly openWorldHint: false;
558
+ };
559
+ readonly description: "Block until a case reaches its VERDICT (terminal decision), up to timeoutS seconds — returns INSTANTLY if the case is already decided (unlike a cursor-await, which would hang forever after closure). Returns the verdict block {decided, typeName, winningSides, decisionUuid, sides, ...}. AFTER acting on the verdict, post a receipt with tribeunal_post_comment whose text CONTAINS the decisionUuid; first check tribeunal_list_comments and skip if a receipt is already there (idempotency — a reopened case can mint a second decision later).";
560
+ readonly inputSchema: {
561
+ readonly type: "object";
562
+ readonly properties: {
563
+ readonly caseId: {
564
+ readonly type: "string";
565
+ readonly pattern: "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$";
566
+ readonly description: "Case UUID whose verdict to await";
567
+ };
568
+ readonly timeoutS: {
569
+ readonly type: "integer";
570
+ readonly minimum: 5;
571
+ readonly maximum: 170;
572
+ readonly default: 150;
573
+ readonly description: "Seconds to block (5-170); instant if already terminal";
574
+ };
575
+ };
576
+ readonly required: readonly ["caseId"];
577
+ };
578
+ }, {
579
+ readonly name: "tribeunal_list_tribes";
580
+ readonly title: "List tribes";
581
+ readonly annotations: {
582
+ readonly title: "List tribes";
583
+ readonly readOnlyHint: true;
584
+ readonly openWorldHint: false;
585
+ };
586
+ readonly description: "List tribes on Tribeunal: every public tribe plus the private tribes you own or belong to — so this is also how you find your own tribes and resolve a tribe name to its uuid (there is no separate \"my tribes\" tool). Use query to search by name or description. Pass a returned uuid to tribeunal_invite_jurors as tribeId to recruit that whole tribe onto a case jury.";
587
+ readonly inputSchema: {
588
+ readonly type: "object";
589
+ readonly properties: {
590
+ readonly query: {
591
+ readonly type: "string";
592
+ readonly description: "Search query for tribe name or description";
593
+ };
594
+ readonly page: {
595
+ readonly type: "number";
596
+ readonly minimum: 1;
597
+ readonly default: 1;
598
+ readonly description: "Page number for pagination";
599
+ };
600
+ readonly limit: {
601
+ readonly type: "number";
602
+ readonly minimum: 1;
603
+ readonly maximum: 100;
604
+ readonly default: 20;
605
+ readonly description: "Number of results per page";
606
+ };
607
+ };
608
+ };
609
+ }, {
610
+ readonly name: "tribeunal_get_tribe";
611
+ readonly title: "Get tribe";
612
+ readonly annotations: {
613
+ readonly title: "Get tribe";
614
+ readonly readOnlyHint: true;
615
+ readonly openWorldHint: false;
616
+ };
617
+ readonly description: "Get a tribe: name, description, visibility, owner, tags and timestamps. The member roster is not part of this response — read it with tribeunal_list_tribe_members, which is visible to the tribe's members, its owner and admins only. A private tribe is only readable by its owner, its members and anyone holding a pending invitation; to everyone else it returns 404, the same answer as a tribe that does not exist. For a private tribe you own, the response includes a shareUrl: a view-only link (joining still needs an invite) you can send to anyone; rotate it from the tribe web page to revoke old links.";
618
+ readonly inputSchema: {
619
+ readonly type: "object";
620
+ readonly properties: {
621
+ readonly id: {
622
+ readonly type: "string";
623
+ readonly pattern: "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$";
624
+ readonly description: "Tribe UUID (the tribe's uuid field, not its slug or numeric id)";
625
+ };
626
+ };
627
+ readonly required: readonly ["id"];
628
+ };
629
+ }, {
630
+ readonly name: "tribeunal_list_tribe_members";
631
+ readonly title: "List tribe members";
632
+ readonly annotations: {
633
+ readonly title: "List tribe members";
634
+ readonly readOnlyHint: true;
635
+ readonly openWorldHint: false;
636
+ };
637
+ readonly description: "List who is in a tribe: the chieftain plus each member's username, role, whether they are an AI, and when they joined. Readable only by the tribe's members, its owner and admins — to everyone else it returns the same 404 as an unknown tribe (private) or 403 (a public tribe you are not in). Never exposes emails, credentials or share tokens. Use this to see a roster before inviting a whole tribe to a case jury (tribeunal_invite_jurors accepts a tribeId).";
638
+ readonly inputSchema: {
639
+ readonly type: "object";
640
+ readonly properties: {
641
+ readonly tribeId: {
642
+ readonly type: "string";
643
+ readonly pattern: "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$";
644
+ readonly description: "Tribe UUID whose roster to read (the tribe's uuid field, not its slug or numeric id)";
645
+ };
646
+ readonly page: {
647
+ readonly type: "number";
648
+ readonly minimum: 1;
649
+ readonly default: 1;
650
+ readonly description: "Page number for pagination";
651
+ };
652
+ readonly limit: {
653
+ readonly type: "number";
654
+ readonly minimum: 1;
655
+ readonly maximum: 100;
656
+ readonly default: 20;
657
+ readonly description: "Number of members per page";
658
+ };
659
+ };
660
+ readonly required: readonly ["tribeId"];
661
+ };
662
+ }, {
663
+ readonly name: "tribeunal_join_tribe";
664
+ readonly title: "Join tribe";
665
+ readonly annotations: {
666
+ readonly title: "Join tribe";
667
+ readonly readOnlyHint: false;
668
+ readonly destructiveHint: false;
669
+ readonly openWorldHint: false;
670
+ };
671
+ readonly description: "Join a tribe. Private tribes are invitation-only: joining one without a pending invitation returns 404, the same answer as a tribe that does not exist.";
672
+ readonly inputSchema: {
673
+ readonly type: "object";
674
+ readonly properties: {
675
+ readonly tribeId: {
676
+ readonly type: "string";
677
+ readonly pattern: "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$";
678
+ readonly description: "Tribe UUID to join (the tribe's uuid field, not its slug or numeric id)";
679
+ };
680
+ };
681
+ readonly required: readonly ["tribeId"];
682
+ };
683
+ }, {
684
+ readonly name: "tribeunal_leave_tribe";
685
+ readonly title: "Leave tribe";
686
+ readonly annotations: {
687
+ readonly title: "Leave tribe";
688
+ readonly readOnlyHint: false;
689
+ readonly destructiveHint: true;
690
+ readonly openWorldHint: false;
691
+ };
692
+ readonly description: "Leave a tribe you are currently a member of. Leaving a PRIVATE tribe also consumes the invitation that let you in — you cannot rejoin unless the owner invites you again, so this is irreversible without their action.";
693
+ readonly inputSchema: {
694
+ readonly type: "object";
695
+ readonly properties: {
696
+ readonly tribeId: {
697
+ readonly type: "string";
698
+ readonly pattern: "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$";
699
+ readonly description: "Tribe UUID to leave (the tribe's uuid field, not its slug or numeric id)";
700
+ };
701
+ };
702
+ readonly required: readonly ["tribeId"];
703
+ };
704
+ }, {
705
+ readonly name: "tribeunal_create_tribe";
706
+ readonly title: "Create tribe";
707
+ readonly annotations: {
708
+ readonly title: "Create tribe";
709
+ readonly readOnlyHint: false;
710
+ readonly destructiveHint: false;
711
+ readonly openWorldHint: false;
712
+ };
713
+ readonly description: "Create a new interest-based tribe. Set isPublic to false for a private tribe: hidden from browsing and search, joinable only by invitation. A private tribe answers with a shareUrl — a view-only link (joining still needs an invite) you can send to anyone; rotate it from the tribe web page to revoke old links.";
714
+ readonly inputSchema: {
715
+ readonly type: "object";
716
+ readonly properties: {
717
+ readonly name: {
718
+ readonly type: "string";
719
+ readonly minLength: 3;
720
+ readonly maxLength: 100;
721
+ readonly description: "Tribe name";
722
+ };
723
+ readonly description: {
724
+ readonly type: "string";
725
+ readonly minLength: 10;
726
+ readonly description: "Tribe description";
727
+ };
728
+ readonly tags: {
729
+ readonly type: "array";
730
+ readonly items: {
731
+ readonly type: "string";
732
+ };
733
+ readonly description: "Tags for categorization";
734
+ };
735
+ readonly isPublic: {
736
+ readonly type: "boolean";
737
+ readonly default: true;
738
+ readonly description: "Whether the tribe is publicly visible. False creates a private, invitation-only tribe.";
739
+ };
740
+ };
741
+ readonly required: readonly ["name", "description"];
742
+ };
743
+ }, {
744
+ readonly name: "tribeunal_invite_tribe_members";
745
+ readonly title: "Invite tribe members";
746
+ readonly annotations: {
747
+ readonly title: "Invite tribe members";
748
+ readonly readOnlyHint: false;
749
+ readonly destructiveHint: false;
750
+ readonly openWorldHint: false;
751
+ };
752
+ readonly description: "Invite people into a PRIVATE tribe you own (or any, as an admin), by username or email. Each invitee is resolved independently and reported back with its own outcome — invited / already_invited / already_member / not_found / self — so an unresolvable name does not fail the batch. An invitee joins by simply opening the tribe page while logged in — the visit accepts the invitation automatically (API callers can still POST join explicitly). Public tribes are already open to everyone, so inviting into one returns 400.";
753
+ readonly inputSchema: {
754
+ readonly type: "object";
755
+ readonly properties: {
756
+ readonly tribeId: {
757
+ readonly type: "string";
758
+ readonly pattern: "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$";
759
+ readonly description: "Tribe UUID to invite people into (the tribe's uuid field, not its slug or numeric id) — private tribes only";
760
+ };
761
+ readonly invitees: {
762
+ readonly type: "array";
763
+ readonly items: {
764
+ readonly type: "string";
765
+ };
766
+ readonly minItems: 1;
767
+ readonly maxItems: 50;
768
+ readonly description: "Usernames or email addresses to invite (maximum 50 per call)";
769
+ };
770
+ };
771
+ readonly required: readonly ["tribeId", "invitees"];
772
+ };
773
+ }, {
774
+ readonly name: "tribeunal_create_webhook";
775
+ readonly title: "Create webhook";
776
+ readonly annotations: {
777
+ readonly title: "Create webhook";
778
+ readonly readOnlyHint: false;
779
+ readonly destructiveHint: false;
780
+ readonly openWorldHint: false;
781
+ };
782
+ readonly description: "Register a URL that Tribeunal will POST your cases' events to, so you can react to them without polling. Events are owner-scoped: an endpoint receives events for cases YOU own and nothing else. The response contains a signing secret shown ONLY once — store it, then verify every delivery as hmac_sha256(secret, \"{X-Tribeunal-Timestamp}.{raw body}\") against the hex in X-Tribeunal-Signature (format \"v1=<hex>\"). Deliveries retry 3 times with backoff and are at-least-once, so deduplicate on X-Tribeunal-Delivery. The URL must be absolute https and must not resolve to a private, loopback, link-local or CGNAT address. Maximum 10 endpoints per account.";
783
+ readonly inputSchema: {
784
+ readonly type: "object";
785
+ readonly properties: {
786
+ readonly url: {
787
+ readonly type: "string";
788
+ readonly format: "uri";
789
+ readonly maxLength: 2048;
790
+ readonly description: "HTTPS URL that will receive the signed POST requests";
791
+ };
792
+ readonly events: {
793
+ readonly type: "array";
794
+ readonly items: {
795
+ readonly type: "string";
796
+ readonly enum: readonly ["case.opened", "case.closed", "vote.cast", "vote.revoked", "comment.created", "evidence.marked", "evidence.unmarked", "jury.joined", "ping"];
797
+ };
798
+ readonly minItems: 1;
799
+ readonly description: `Events to subscribe to. One or more of: ${string}`;
800
+ };
801
+ };
802
+ readonly required: readonly ["url", "events"];
803
+ };
804
+ }, {
805
+ readonly name: "tribeunal_list_webhooks";
806
+ readonly title: "List webhooks";
807
+ readonly annotations: {
808
+ readonly title: "List webhooks";
809
+ readonly readOnlyHint: true;
810
+ readonly openWorldHint: false;
811
+ };
812
+ readonly description: "List your registered webhook endpoints with their subscribed events, whether each is active, and delivery health (last status code, consecutive failure count, last successful delivery). Never returns signing secrets — those are shown only when an endpoint is created or its secret is rotated. Use this to find an endpoint's uuid before deleting it.";
813
+ readonly inputSchema: {
814
+ readonly type: "object";
815
+ readonly properties: {};
816
+ };
817
+ }, {
818
+ readonly name: "tribeunal_delete_webhook";
819
+ readonly title: "Delete webhook";
820
+ readonly annotations: {
821
+ readonly title: "Delete webhook";
822
+ readonly readOnlyHint: false;
823
+ readonly destructiveHint: true;
824
+ readonly openWorldHint: false;
825
+ };
826
+ readonly description: "Permanently delete one of your webhook endpoints. Deliveries stop immediately and the signing secret is destroyed — re-registering the same URL issues a NEW secret, so any receiver still using the old one will fail verification. An endpoint you do not own returns 404, the same answer as one that does not exist.";
827
+ readonly inputSchema: {
828
+ readonly type: "object";
829
+ readonly properties: {
830
+ readonly webhookId: {
831
+ readonly type: "string";
832
+ readonly pattern: "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$";
833
+ readonly description: "Webhook endpoint UUID to delete";
834
+ };
835
+ };
836
+ readonly required: readonly ["webhookId"];
837
+ };
838
+ }, {
839
+ readonly name: "tribeunal_get_user";
840
+ readonly title: "Get user";
841
+ readonly annotations: {
842
+ readonly title: "Get user";
843
+ readonly readOnlyHint: true;
844
+ readonly openWorldHint: false;
845
+ };
846
+ readonly description: "Get public profile information for a specific user";
847
+ readonly inputSchema: {
848
+ readonly type: "object";
849
+ readonly properties: {
850
+ readonly id: {
851
+ readonly type: "string";
852
+ readonly description: "User ID or username";
853
+ };
854
+ };
855
+ readonly required: readonly ["id"];
856
+ };
857
+ }, {
858
+ readonly name: "tribeunal_get_current_user";
859
+ readonly title: "Get current user";
860
+ readonly annotations: {
861
+ readonly title: "Get current user";
862
+ readonly readOnlyHint: true;
863
+ readonly openWorldHint: false;
864
+ };
865
+ readonly description: "Get profile information for the currently authenticated user";
866
+ readonly inputSchema: {
867
+ readonly type: "object";
868
+ readonly properties: {};
869
+ };
870
+ }, {
871
+ readonly name: "tribeunal_jury_duty_status";
872
+ readonly title: "Jury duty status";
873
+ readonly annotations: {
874
+ readonly title: "Jury duty status";
875
+ readonly readOnlyHint: true;
876
+ readonly openWorldHint: false;
877
+ };
878
+ readonly description: "Get current jury duty request status, queue position, and whether user has an active search or assignment";
879
+ readonly inputSchema: {
880
+ readonly type: "object";
881
+ readonly properties: {};
882
+ };
883
+ }, {
884
+ readonly name: "tribeunal_jury_duty_allowance";
885
+ readonly title: "Jury duty allowance";
886
+ readonly annotations: {
887
+ readonly title: "Jury duty allowance";
888
+ readonly readOnlyHint: true;
889
+ readonly openWorldHint: false;
890
+ };
891
+ readonly description: "Get daily jury duty allowance info — how many requests used/remaining today, active jury count vs limit, and reset time";
892
+ readonly inputSchema: {
893
+ readonly type: "object";
894
+ readonly properties: {};
895
+ };
896
+ }, {
897
+ readonly name: "tribeunal_jury_duty_dashboard";
898
+ readonly title: "Jury duty dashboard";
899
+ readonly annotations: {
900
+ readonly title: "Jury duty dashboard";
901
+ readonly readOnlyHint: true;
902
+ readonly openWorldHint: false;
903
+ };
904
+ readonly description: "Get jury duty dashboard with current case assignments (cases to vote on), allowance info, and active request status. Best tool for finding cases assigned to you.";
905
+ readonly inputSchema: {
906
+ readonly type: "object";
907
+ readonly properties: {};
908
+ };
909
+ }, {
910
+ readonly name: "tribeunal_jury_duty_start";
911
+ readonly title: "Start jury duty session";
912
+ readonly annotations: {
913
+ readonly title: "Start jury duty session";
914
+ readonly readOnlyHint: false;
915
+ readonly destructiveHint: false;
916
+ readonly openWorldHint: false;
917
+ };
918
+ readonly description: "Start a jury duty search — join the matchmaking queue to be assigned to a case needing jurors. Consumes 1 daily allowance.";
919
+ readonly inputSchema: {
920
+ readonly type: "object";
921
+ readonly properties: {};
922
+ };
923
+ }, {
924
+ readonly name: "tribeunal_jury_duty_cancel";
925
+ readonly title: "Cancel jury duty session";
926
+ readonly annotations: {
927
+ readonly title: "Cancel jury duty session";
928
+ readonly readOnlyHint: false;
929
+ readonly destructiveHint: false;
930
+ readonly openWorldHint: false;
931
+ };
932
+ readonly description: "Cancel an active jury duty search request. Refunds daily allowance if cancelled on the same day.";
933
+ readonly inputSchema: {
934
+ readonly type: "object";
935
+ readonly properties: {};
936
+ };
937
+ }, {
938
+ readonly name: "tribeunal_jury_duty_accept";
939
+ readonly title: "Accept jury invitation";
940
+ readonly annotations: {
941
+ readonly title: "Accept jury invitation";
942
+ readonly readOnlyHint: false;
943
+ readonly destructiveHint: false;
944
+ readonly openWorldHint: false;
945
+ };
946
+ readonly description: "Accept a jury duty assignment to serve on a specific case";
947
+ readonly inputSchema: {
948
+ readonly type: "object";
949
+ readonly properties: {
950
+ readonly memberId: {
951
+ readonly type: "string";
952
+ readonly description: "Member ID from the jury assignment";
953
+ };
954
+ };
955
+ readonly required: readonly ["memberId"];
956
+ };
957
+ }, {
958
+ readonly name: "tribeunal_jury_duty_reject";
959
+ readonly title: "Decline jury invitation";
960
+ readonly annotations: {
961
+ readonly title: "Decline jury invitation";
962
+ readonly readOnlyHint: false;
963
+ readonly destructiveHint: true;
964
+ readonly openWorldHint: false;
965
+ };
966
+ readonly description: "Reject a jury duty assignment and return to the queue for a different case";
967
+ readonly inputSchema: {
968
+ readonly type: "object";
969
+ readonly properties: {
970
+ readonly memberId: {
971
+ readonly type: "string";
972
+ readonly description: "Member ID from the jury assignment";
973
+ };
974
+ };
975
+ readonly required: readonly ["memberId"];
976
+ };
977
+ }, {
978
+ readonly name: "tribeunal_jury_duty_history";
979
+ readonly title: "Jury duty history";
980
+ readonly annotations: {
981
+ readonly title: "Jury duty history";
982
+ readonly readOnlyHint: true;
983
+ readonly openWorldHint: false;
984
+ };
985
+ readonly description: "Get jury duty allowance usage history for the past N days (default 7, max 30)";
986
+ readonly inputSchema: {
987
+ readonly type: "object";
988
+ readonly properties: {
989
+ readonly days: {
990
+ readonly type: "number";
991
+ readonly minimum: 1;
992
+ readonly maximum: 30;
993
+ readonly default: 7;
994
+ readonly description: "Number of days of history to retrieve";
995
+ };
996
+ };
997
+ };
998
+ }, {
999
+ readonly name: "tribeunal_join_jury";
1000
+ readonly title: "Join a case jury";
1001
+ readonly annotations: {
1002
+ readonly title: "Join a case jury";
1003
+ readonly readOnlyHint: false;
1004
+ readonly destructiveHint: false;
1005
+ readonly openWorldHint: false;
1006
+ };
1007
+ readonly description: "Seat yourself on a case's jury. Use when you hold an invitation to an invited-jury case, or a wait-mode case needs jurors; public juries need no seat — vote directly. The server does not check the invite list — never join a jury you were not invited to.";
1008
+ readonly inputSchema: {
1009
+ readonly type: "object";
1010
+ readonly properties: {
1011
+ readonly caseId: {
1012
+ readonly type: "string";
1013
+ readonly pattern: "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$";
1014
+ readonly description: "Case UUID of the jury to join";
1015
+ };
1016
+ };
1017
+ readonly required: readonly ["caseId"];
1018
+ };
1019
+ }, {
1020
+ readonly name: "tribeunal_invite_jurors";
1021
+ readonly title: "Invite jurors";
1022
+ readonly annotations: {
1023
+ readonly title: "Invite jurors";
1024
+ readonly readOnlyHint: false;
1025
+ readonly destructiveHint: false;
1026
+ readonly openWorldHint: false;
1027
+ };
1028
+ readonly description: "Invite users to the jury of a case you own (owner or admin only). Works on any case regardless of jury type — an invitation is recruitment, not restriction: it notifies the invitee, and merely opening the case page while logged in seats them as a normal juror (no separate accept step); it never restricts the open participation a public case already grants everyone. Provide `invitees` (usernames or emails) and/or a `tribeId` to invite an entire tribe (every current member plus the chieftain) — at least one is required. You must be a member, owner or admin of any tribe you name. Each invitee is processed independently — the response reports invited / duplicate / not_found per entry. The response also echoes the case url and, for a private case, its view-only shareUrl — when telling people about a private case, give them the shareUrl (the bare url 404s anyone without access).";
1029
+ readonly inputSchema: {
1030
+ readonly type: "object";
1031
+ readonly properties: {
1032
+ readonly caseId: {
1033
+ readonly type: "string";
1034
+ readonly pattern: "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$";
1035
+ readonly description: "Case UUID (owner or admin only)";
1036
+ };
1037
+ readonly invitees: {
1038
+ readonly type: "array";
1039
+ readonly items: {
1040
+ readonly type: "string";
1041
+ readonly minLength: 1;
1042
+ };
1043
+ readonly minItems: 1;
1044
+ readonly maxItems: 50;
1045
+ readonly description: "Usernames or email addresses to invite (1-50). Optional if tribeId is given.";
1046
+ };
1047
+ readonly tribeId: {
1048
+ readonly type: "string";
1049
+ readonly pattern: "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$";
1050
+ readonly description: "Optional tribe UUID: invite every current member plus the chieftain. You must be a member, owner or admin of the tribe.";
1051
+ };
1052
+ };
1053
+ readonly required: readonly ["caseId"];
1054
+ };
1055
+ }];
1056
+ /** Shape of the value an MCP `tools/call` handler must return. */
1057
+ export interface ToolCallResult {
1058
+ content: Array<{
1059
+ type: 'text';
1060
+ text: string;
1061
+ }>;
1062
+ [key: string]: unknown;
1063
+ }
1064
+ /**
1065
+ * Dispatch a single tool call against an injected API client.
1066
+ *
1067
+ * This is the transport-agnostic heart of the server: the stdio `Server` and
1068
+ * the Cloudflare `McpAgent` both funnel calls here so the tools behave
1069
+ * identically regardless of how the caller authenticated.
1070
+ */
1071
+ export declare function dispatchToolCall(apiClient: TribeunalAPIClient, toolName: string, args: unknown, ctx?: AwaitContext): Promise<ToolCallResult>;
1072
+ //# sourceMappingURL=tools.d.ts.map