@nimara-app/mcp 0.4.0 → 0.6.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.
package/README.md CHANGED
@@ -50,6 +50,7 @@ remove existing data, as opposed to only adding.
50
50
  | `remove_item_from_milestone` | **Write ⚠** | Remove a work item's association with a milestone (idempotent — a no-op if it wasn't associated).. |
51
51
  | `remove_label_from_work_item` | **Write ⚠** | Remove a label from a work item (idempotent — a no-op if it wasn't attached).. |
52
52
  | `search_work_items` | Read | Find work items in a project by title — the cheap way to check whether something is already tracked. |
53
+ | `watch_work_item` | Write | Put the token owner on (or off) an item's watch list: they are told when it changes status, gets a comment or reviewer, is archived or moved. |
53
54
  | `update_document` | **Write ⚠** | Update an existing document's markdown content and/or title. |
54
55
  | `update_work_item` | **Write ⚠** | Update an existing work item: title, description, status, priority, parent, or review flags. |
55
56
 
package/dist/index.js CHANGED
@@ -9,7 +9,7 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
9
9
  // package.json
10
10
  var package_default = {
11
11
  name: "@nimara-app/mcp",
12
- version: "0.4.0",
12
+ version: "0.6.0",
13
13
  private: false,
14
14
  mcpName: "io.github.langskip-studios/nimara",
15
15
  description: "Nimara MCP server \u2014 AI tool integration for Claude, Codex, and others",
@@ -72,15 +72,10 @@ Titles are plain language a teammate understands at a glance: what is wrong or w
72
72
 
73
73
  A status must be one of the project's \`statuses\` from list_projects, spelled exactly; never invent one. Labels come from list_labels; do not invent those either.
74
74
 
75
- When you pick up an item: update_work_item { status: <in-progress status>, agentWorking: true }. That lights its row for 15 minutes; any write or read of the item renews it, and on a long stretch with no Nimara calls, heartbeat_work_item every few minutes keeps it lit. Post a comment at real milestones. If you stop early, agentWorking: false. Moving to the last status clears it.
75
+ When you pick up an item: update_work_item { status: <in-progress status>, agentWorking: true, model: <the model you run as> }. That lights its row for 15 minutes and lets the app say whose agent, and which, is on it; any write or read of the item renews it, and on a long stretch with no Nimara calls, heartbeat_work_item every few minutes keeps it lit. Post a comment at real milestones. If you stop early, agentWorking: false. Moving to the last status clears it.
76
76
 
77
77
  Mention a person in a comment as [@Name](user:<userId>) and they are notified. Append agent research to a description under the exact heading "## Research (auto)", never editing the human text above it. When you open a PR, put the displayId in its title.`;
78
78
 
79
- // ../convex/convex/_generated/api.js
80
- import { anyApi, componentsGeneric } from "convex/server";
81
- var api = anyApi;
82
- var components = componentsGeneric();
83
-
84
79
  // src/convex.ts
85
80
  import { ConvexHttpClient } from "convex/browser";
86
81
  var cachedClient = null;
@@ -104,6 +99,20 @@ function getToken() {
104
99
  }
105
100
  return token;
106
101
  }
102
+ var clientInfo;
103
+ function setClientInfo(info) {
104
+ clientInfo = info;
105
+ }
106
+ function agentArg(model) {
107
+ if (!clientInfo) return model ? { client: "unknown", model } : void 0;
108
+ const client = clientInfo.version ? `${clientInfo.name} ${clientInfo.version}` : clientInfo.name;
109
+ return model ? { client, model } : { client };
110
+ }
111
+
112
+ // ../convex/convex/_generated/api.js
113
+ import { anyApi, componentsGeneric } from "convex/server";
114
+ var api = anyApi;
115
+ var components = componentsGeneric();
107
116
 
108
117
  // src/tools/list-orgs.ts
109
118
  function registerListOrgs(server) {
@@ -507,7 +516,8 @@ function registerUpdateWorkItem(server) {
507
516
  ),
508
517
  agentWorking: z9.boolean().optional().describe(
509
518
  "Set true when you start working on this item: the app lights its row so the person can see it is in flight. It is a 15-minute lease renewed by any later MCP write on the item (updates, comments), by reading it (get_work_items, list_work_item_comments), or by heartbeat_work_item \u2014 call that every few minutes on a long task with no other Nimara calls, or the row goes quiet while you are still at it. Set false when you stop without finishing; moving the item to the last status clears it for you."
510
- )
519
+ ),
520
+ model: z9.string().optional().describe("With agentWorking: the model you are running as, e.g. claude-opus-5, so the app can say which agent is on this. Your harness is reported automatically.")
511
521
  },
512
522
  annotations: {
513
523
  readOnlyHint: false,
@@ -516,10 +526,11 @@ function registerUpdateWorkItem(server) {
516
526
  openWorldHint: false
517
527
  }
518
528
  },
519
- async (args) => {
529
+ async ({ model, ...args }) => {
520
530
  const result = await getConvexClient().action(api.mcp.updateWorkItem, {
521
531
  token: getToken(),
522
- ...args
532
+ ...args,
533
+ agent: agentArg(model)
523
534
  });
524
535
  return {
525
536
  content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
@@ -799,7 +810,8 @@ function registerHeartbeatWorkItem(server) {
799
810
  {
800
811
  description: 'Say you are still working on an item. Renews (or starts) its 15-minute "agent working" lease and does nothing else: no comment, no activity event, no change to the item. The app lights the row while the lease is live, so on a long task call this every few minutes or every handful of tool calls \u2014 otherwise the row goes quiet while you are still at it. Reads of the item (get_work_items, list_work_item_comments) also renew a live lease, and any update or comment does; this is for the stretches where you do none of those. Cheap and idempotent.',
801
812
  inputSchema: {
802
- workItemId: z18.string().describe("workItemId of the item you are working on")
813
+ workItemId: z18.string().describe("workItemId of the item you are working on"),
814
+ model: z18.string().optional().describe("The model you are running as, e.g. claude-opus-5 or gpt-5, so the app can say which agent is on this. Your harness is reported automatically.")
803
815
  },
804
816
  annotations: {
805
817
  readOnlyHint: false,
@@ -808,10 +820,11 @@ function registerHeartbeatWorkItem(server) {
808
820
  openWorldHint: false
809
821
  }
810
822
  },
811
- async ({ workItemId }) => {
823
+ async ({ workItemId, model }) => {
812
824
  const result = await getConvexClient().action(api.mcp.heartbeatWorkItem, {
813
825
  token: getToken(),
814
- workItemId
826
+ workItemId,
827
+ agent: agentArg(model)
815
828
  });
816
829
  return {
817
830
  content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
@@ -820,18 +833,49 @@ function registerHeartbeatWorkItem(server) {
820
833
  );
821
834
  }
822
835
 
823
- // src/tools/add-work-item-image.ts
836
+ // src/tools/watch-work-item.ts
824
837
  import { z as z19 } from "zod";
838
+ function registerWatchWorkItem(server) {
839
+ server.registerTool(
840
+ "watch_work_item",
841
+ {
842
+ description: "Put the token owner on (or take them off) an item's watch list. A watcher is notified when the item changes status, gets a comment, gets a reviewer, is archived or moved \u2014 not on title or description edits. The item's assignee and reviewer already hear about it. Use this when you start work the person will want to follow, or when they ask to keep an eye on something.",
843
+ inputSchema: {
844
+ workItemId: z19.string().describe("workItemId of the item"),
845
+ watching: z19.boolean().default(true).describe("true to watch, false to stop")
846
+ },
847
+ annotations: {
848
+ readOnlyHint: false,
849
+ destructiveHint: false,
850
+ idempotentHint: true,
851
+ openWorldHint: false
852
+ }
853
+ },
854
+ async ({ workItemId, watching }) => {
855
+ const result = await getConvexClient().action(api.mcp.watchWorkItem, {
856
+ token: getToken(),
857
+ workItemId,
858
+ watching
859
+ });
860
+ return {
861
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
862
+ };
863
+ }
864
+ );
865
+ }
866
+
867
+ // src/tools/add-work-item-image.ts
868
+ import { z as z20 } from "zod";
825
869
  function registerAddWorkItemImage(server) {
826
870
  server.registerTool(
827
871
  "add_work_item_image",
828
872
  {
829
873
  description: "Attach an externally hosted image URL to a work item. Use this when an MCP client has a screenshot, mockup, or generated image URL to preserve with the task.",
830
874
  inputSchema: {
831
- workItemId: z19.string().describe("workItemId from list_work_items"),
832
- imageUrl: z19.string().url().describe("Public or otherwise fetchable http(s) image URL"),
833
- filename: z19.string().optional().describe("Optional display filename"),
834
- altText: z19.string().optional().describe("Optional description/caption for the image")
875
+ workItemId: z20.string().describe("workItemId from list_work_items"),
876
+ imageUrl: z20.string().url().describe("Public or otherwise fetchable http(s) image URL"),
877
+ filename: z20.string().optional().describe("Optional display filename"),
878
+ altText: z20.string().optional().describe("Optional description/caption for the image")
835
879
  },
836
880
  annotations: {
837
881
  readOnlyHint: false,
@@ -853,14 +897,14 @@ function registerAddWorkItemImage(server) {
853
897
  }
854
898
 
855
899
  // src/tools/list-work-item-images.ts
856
- import { z as z20 } from "zod";
900
+ import { z as z21 } from "zod";
857
901
  function registerListWorkItemImages(server) {
858
902
  server.registerTool(
859
903
  "list_work_item_images",
860
904
  {
861
905
  description: "List image attachments for a work item, including uploaded images and externally attached MCP images. Call list_work_items first to find the workItemId.",
862
906
  inputSchema: {
863
- workItemId: z20.string().describe("workItemId from list_work_items")
907
+ workItemId: z21.string().describe("workItemId from list_work_items")
864
908
  },
865
909
  annotations: {
866
910
  readOnlyHint: true,
@@ -883,18 +927,18 @@ function registerListWorkItemImages(server) {
883
927
  }
884
928
 
885
929
  // src/tools/add-work-item-comment.ts
886
- import { z as z21 } from "zod";
930
+ import { z as z22 } from "zod";
887
931
  function registerAddWorkItemComment(server) {
888
932
  server.registerTool(
889
933
  "add_work_item_comment",
890
934
  {
891
935
  description: "Add a timestamped comment to a work item. Use this to record notes, updates, or an 'AI touched' entry instead of editing the description. Comments are stamped with the current time automatically and never overwrite each other.",
892
936
  inputSchema: {
893
- workItemId: z21.string().describe("workItemId from list_work_items"),
894
- body: z21.string().min(1).describe(
937
+ workItemId: z22.string().describe("workItemId from list_work_items"),
938
+ body: z22.string().min(1).describe(
895
939
  "Comment text (markdown supported). To pull a person into the thread, mention them as [@Name](user:<userId>) \u2014 they are notified and the app renders it as a chip. userIds come from an item's assigneeId/reviewerId; there is no member lookup tool yet, so only mention ids you have seen."
896
940
  ),
897
- source: z21.enum(["user", "ai"]).optional().describe('Who authored it; defaults to "ai" for MCP callers')
941
+ source: z22.enum(["user", "ai"]).optional().describe('Who authored it; defaults to "ai" for MCP callers')
898
942
  },
899
943
  annotations: {
900
944
  readOnlyHint: false,
@@ -908,7 +952,8 @@ function registerAddWorkItemComment(server) {
908
952
  api.mcp.addWorkItemComment,
909
953
  {
910
954
  token: getToken(),
911
- ...args
955
+ ...args,
956
+ agent: agentArg()
912
957
  }
913
958
  );
914
959
  return {
@@ -919,14 +964,14 @@ function registerAddWorkItemComment(server) {
919
964
  }
920
965
 
921
966
  // src/tools/list-work-item-comments.ts
922
- import { z as z22 } from "zod";
967
+ import { z as z23 } from "zod";
923
968
  function registerListWorkItemComments(server) {
924
969
  server.registerTool(
925
970
  "list_work_item_comments",
926
971
  {
927
972
  description: "List the timestamped comments on a work item, oldest first. Use this to check whether the item was already touched/commented before adding a new comment.",
928
973
  inputSchema: {
929
- workItemId: z22.string().describe("workItemId from list_work_items")
974
+ workItemId: z23.string().describe("workItemId from list_work_items")
930
975
  },
931
976
  annotations: {
932
977
  readOnlyHint: true,
@@ -949,14 +994,14 @@ function registerListWorkItemComments(server) {
949
994
  }
950
995
 
951
996
  // src/tools/list-validations.ts
952
- import { z as z23 } from "zod";
997
+ import { z as z24 } from "zod";
953
998
  function registerListValidations(server) {
954
999
  server.registerTool(
955
1000
  "list_validations",
956
1001
  {
957
1002
  description: "List a project's validation graph: core systems and validation/test tasks with their DERIVED state (passing, failing, stale, unvalidated). A task is 'stale' when a system it covers changed since it was last validated, or an upstream dependency is no longer passing. Call list_projects first to find the projectId.",
958
1003
  inputSchema: {
959
- projectId: z23.string().describe("projectId from list_projects")
1004
+ projectId: z24.string().describe("projectId from list_projects")
960
1005
  },
961
1006
  annotations: {
962
1007
  readOnlyHint: true,
@@ -977,15 +1022,15 @@ function registerListValidations(server) {
977
1022
  }
978
1023
 
979
1024
  // src/tools/record-validation.ts
980
- import { z as z24 } from "zod";
1025
+ import { z as z25 } from "zod";
981
1026
  function registerRecordValidation(server) {
982
1027
  server.registerTool(
983
1028
  "record_validation",
984
1029
  {
985
1030
  description: "Check off a validation task by recording a pass or fail. Stamps the task as validated 'now', clearing any stale flag until a covered system changes or an upstream dependency moves again. Get validationTaskId from list_validations.",
986
1031
  inputSchema: {
987
- validationTaskId: z24.string().describe("validationTaskId from list_validations"),
988
- result: z24.enum(["pass", "fail"]).describe("Outcome of running the test")
1032
+ validationTaskId: z25.string().describe("validationTaskId from list_validations"),
1033
+ result: z25.enum(["pass", "fail"]).describe("Outcome of running the test")
989
1034
  },
990
1035
  annotations: {
991
1036
  readOnlyHint: false,
@@ -1009,14 +1054,14 @@ function registerRecordValidation(server) {
1009
1054
  }
1010
1055
 
1011
1056
  // src/tools/mark-system-changed.ts
1012
- import { z as z25 } from "zod";
1057
+ import { z as z26 } from "zod";
1013
1058
  function registerMarkSystemChanged(server) {
1014
1059
  server.registerTool(
1015
1060
  "mark_system_changed",
1016
1061
  {
1017
1062
  description: "Mark a core system as changed. This is the single action that invalidates testing: every validation task that covers this system (and everything transitively depending on those tasks) immediately becomes 'stale' and needs revalidation. Get systemId from list_validations.",
1018
1063
  inputSchema: {
1019
- systemId: z25.string().describe("systemId from list_validations")
1064
+ systemId: z26.string().describe("systemId from list_validations")
1020
1065
  },
1021
1066
  annotations: {
1022
1067
  readOnlyHint: false,
@@ -1039,16 +1084,16 @@ function registerMarkSystemChanged(server) {
1039
1084
  }
1040
1085
 
1041
1086
  // src/tools/create-system.ts
1042
- import { z as z26 } from "zod";
1087
+ import { z as z27 } from "zod";
1043
1088
  function registerCreateSystem(server) {
1044
1089
  server.registerTool(
1045
1090
  "create_system",
1046
1091
  {
1047
1092
  description: "Create a core system in a project \u2014 a subsystem (e.g. Auth, Payments, Sync) whose change should invalidate the validation tasks that cover it. Returns the new systemId.",
1048
1093
  inputSchema: {
1049
- projectId: z26.string().describe("projectId from list_projects"),
1050
- name: z26.string().min(1).describe("Short system name, e.g. 'Auth'"),
1051
- description: z26.string().optional().describe("Optional details")
1094
+ projectId: z27.string().describe("projectId from list_projects"),
1095
+ name: z27.string().min(1).describe("Short system name, e.g. 'Auth'"),
1096
+ description: z27.string().optional().describe("Optional details")
1052
1097
  },
1053
1098
  annotations: {
1054
1099
  readOnlyHint: false,
@@ -1071,20 +1116,20 @@ function registerCreateSystem(server) {
1071
1116
  }
1072
1117
 
1073
1118
  // src/tools/create-validation-task.ts
1074
- import { z as z27 } from "zod";
1119
+ import { z as z28 } from "zod";
1075
1120
  function registerCreateValidationTask(server) {
1076
1121
  server.registerTool(
1077
1122
  "create_validation_task",
1078
1123
  {
1079
1124
  description: "Create a validation/test task in a project. After creating it, use add_system_to_task to declare which systems it exercises (so it goes stale when they change) and add_validation_dependency to order it after other tasks. Returns the new validationTaskId.",
1080
1125
  inputSchema: {
1081
- projectId: z27.string().describe("projectId from list_projects"),
1082
- title: z27.string().min(1).describe("What this test validates"),
1083
- description: z27.string().optional().describe("Optional steps / details"),
1084
- kind: z27.enum(["auto", "manual"]).optional().describe(
1126
+ projectId: z28.string().describe("projectId from list_projects"),
1127
+ title: z28.string().min(1).describe("What this test validates"),
1128
+ description: z28.string().optional().describe("Optional steps / details"),
1129
+ kind: z28.enum(["auto", "manual"]).optional().describe(
1085
1130
  "'auto' if runnable by a test runner, 'manual' if a human checks it. Defaults to manual."
1086
1131
  ),
1087
- workItemId: z27.string().optional().describe(
1132
+ workItemId: z28.string().optional().describe(
1088
1133
  "Optional workItemId to link this test to a feature for traceability"
1089
1134
  )
1090
1135
  },
@@ -1109,15 +1154,15 @@ function registerCreateValidationTask(server) {
1109
1154
  }
1110
1155
 
1111
1156
  // src/tools/add-system-to-task.ts
1112
- import { z as z28 } from "zod";
1157
+ import { z as z29 } from "zod";
1113
1158
  function registerAddSystemToTask(server) {
1114
1159
  server.registerTool(
1115
1160
  "add_system_to_task",
1116
1161
  {
1117
1162
  description: "Declare that a validation task COVERS (exercises) a system. Once linked, the task becomes 'stale' whenever that system is marked changed. Idempotent. Both IDs come from list_validations and must be in the same project.",
1118
1163
  inputSchema: {
1119
- validationTaskId: z28.string().describe("validationTaskId from list_validations"),
1120
- systemId: z28.string().describe("systemId from list_validations")
1164
+ validationTaskId: z29.string().describe("validationTaskId from list_validations"),
1165
+ systemId: z29.string().describe("systemId from list_validations")
1121
1166
  },
1122
1167
  annotations: {
1123
1168
  readOnlyHint: false,
@@ -1141,15 +1186,15 @@ function registerAddSystemToTask(server) {
1141
1186
  }
1142
1187
 
1143
1188
  // src/tools/add-validation-dependency.ts
1144
- import { z as z29 } from "zod";
1189
+ import { z as z30 } from "zod";
1145
1190
  function registerAddValidationDependency(server) {
1146
1191
  server.registerTool(
1147
1192
  "add_validation_dependency",
1148
1193
  {
1149
1194
  description: "Make one validation task depend on another (validationTaskId depends on dependsOnTaskId). The dependent goes 'stale' whenever the upstream task is not passing or gets revalidated. Cycles and self-dependencies are rejected. Idempotent. Both IDs come from list_validations and must be in the same project.",
1150
1195
  inputSchema: {
1151
- validationTaskId: z29.string().describe("The dependent (downstream) task"),
1152
- dependsOnTaskId: z29.string().describe("The dependency (upstream) task it relies on")
1196
+ validationTaskId: z30.string().describe("The dependent (downstream) task"),
1197
+ dependsOnTaskId: z30.string().describe("The dependency (upstream) task it relies on")
1153
1198
  },
1154
1199
  annotations: {
1155
1200
  readOnlyHint: false,
@@ -1173,14 +1218,14 @@ function registerAddValidationDependency(server) {
1173
1218
  }
1174
1219
 
1175
1220
  // src/tools/list-labels.ts
1176
- import { z as z30 } from "zod";
1221
+ import { z as z31 } from "zod";
1177
1222
  function registerListLabels(server) {
1178
1223
  server.registerTool(
1179
1224
  "list_labels",
1180
1225
  {
1181
1226
  description: "List all labels defined in a project. Returns each label's id, name, and color. Use the labelId with add_label_to_work_item / remove_label_from_work_item.",
1182
1227
  inputSchema: {
1183
- projectId: z30.string().describe("projectId from list_projects")
1228
+ projectId: z31.string().describe("projectId from list_projects")
1184
1229
  },
1185
1230
  annotations: {
1186
1231
  readOnlyHint: true,
@@ -1200,16 +1245,16 @@ function registerListLabels(server) {
1200
1245
  }
1201
1246
 
1202
1247
  // src/tools/create-label.ts
1203
- import { z as z31 } from "zod";
1248
+ import { z as z32 } from "zod";
1204
1249
  function registerCreateLabel(server) {
1205
1250
  server.registerTool(
1206
1251
  "create_label",
1207
1252
  {
1208
1253
  description: "Apply-or-seed a label. Returns the existing label if the name is already taken (idempotent), and otherwise creates it ONLY if the name is one of the curated ones. Any other new name is REFUSED \u2014 the reply carries `refused: true`, the reason, and `available`, the project's existing labels. Agents apply labels; they do not invent them, because a near-duplicate of an existing label splits the vocabulary silently. Prefer list_labels first. Colors are ignored for curated names so the vocabulary looks the same in every project.",
1209
1254
  inputSchema: {
1210
- projectId: z31.string().describe("projectId from list_projects"),
1211
- name: z31.string().min(1).describe("Label name, unique within the project"),
1212
- color: z31.string().regex(/^#[0-9a-fA-F]{6}$/).optional().describe("Hex color like #2563eb. Defaults to a neutral slate.")
1255
+ projectId: z32.string().describe("projectId from list_projects"),
1256
+ name: z32.string().min(1).describe("Label name, unique within the project"),
1257
+ color: z32.string().regex(/^#[0-9a-fA-F]{6}$/).optional().describe("Hex color like #2563eb. Defaults to a neutral slate.")
1213
1258
  },
1214
1259
  annotations: {
1215
1260
  readOnlyHint: false,
@@ -1231,15 +1276,15 @@ function registerCreateLabel(server) {
1231
1276
  }
1232
1277
 
1233
1278
  // src/tools/add-label-to-work-item.ts
1234
- import { z as z32 } from "zod";
1279
+ import { z as z33 } from "zod";
1235
1280
  function registerAddLabelToWorkItem(server) {
1236
1281
  server.registerTool(
1237
1282
  "add_label_to_work_item",
1238
1283
  {
1239
1284
  description: "Attach a label to a work item (idempotent). The label and work item must be in the same project. Get labelIds from list_labels / create_label.",
1240
1285
  inputSchema: {
1241
- workItemId: z32.string().describe("workItemId from list_work_items"),
1242
- labelId: z32.string().describe("labelId from list_labels or create_label")
1286
+ workItemId: z33.string().describe("workItemId from list_work_items"),
1287
+ labelId: z33.string().describe("labelId from list_labels or create_label")
1243
1288
  },
1244
1289
  annotations: {
1245
1290
  readOnlyHint: false,
@@ -1262,15 +1307,15 @@ function registerAddLabelToWorkItem(server) {
1262
1307
  }
1263
1308
 
1264
1309
  // src/tools/remove-label-from-work-item.ts
1265
- import { z as z33 } from "zod";
1310
+ import { z as z34 } from "zod";
1266
1311
  function registerRemoveLabelFromWorkItem(server) {
1267
1312
  server.registerTool(
1268
1313
  "remove_label_from_work_item",
1269
1314
  {
1270
1315
  description: "Remove a label from a work item (idempotent \u2014 a no-op if it wasn't attached).",
1271
1316
  inputSchema: {
1272
- workItemId: z33.string().describe("workItemId from list_work_items"),
1273
- labelId: z33.string().describe("labelId from list_labels")
1317
+ workItemId: z34.string().describe("workItemId from list_work_items"),
1318
+ labelId: z34.string().describe("labelId from list_labels")
1274
1319
  },
1275
1320
  annotations: {
1276
1321
  readOnlyHint: false,
@@ -1293,14 +1338,14 @@ function registerRemoveLabelFromWorkItem(server) {
1293
1338
  }
1294
1339
 
1295
1340
  // src/tools/list-milestones.ts
1296
- import { z as z34 } from "zod";
1341
+ import { z as z35 } from "zod";
1297
1342
  function registerListMilestones(server) {
1298
1343
  server.registerTool(
1299
1344
  "list_milestones",
1300
1345
  {
1301
1346
  description: "List all milestones in a project. Returns each milestone's id, name, description, dueDate (unix ms), and status. Use the milestoneId with add_item_to_milestone / remove_item_from_milestone.",
1302
1347
  inputSchema: {
1303
- projectId: z34.string().describe("projectId from list_projects")
1348
+ projectId: z35.string().describe("projectId from list_projects")
1304
1349
  },
1305
1350
  annotations: {
1306
1351
  readOnlyHint: true,
@@ -1320,17 +1365,17 @@ function registerListMilestones(server) {
1320
1365
  }
1321
1366
 
1322
1367
  // src/tools/create-milestone.ts
1323
- import { z as z35 } from "zod";
1368
+ import { z as z36 } from "zod";
1324
1369
  function registerCreateMilestone(server) {
1325
1370
  server.registerTool(
1326
1371
  "create_milestone",
1327
1372
  {
1328
1373
  description: "Create a milestone in a project. Returns the milestoneId. Good for grouping work into phases (e.g. 'Phase 1 \u2014 Web', 'Phase 2 \u2014 Native').",
1329
1374
  inputSchema: {
1330
- projectId: z35.string().describe("projectId from list_projects"),
1331
- name: z35.string().min(1).describe("Milestone name"),
1332
- description: z35.string().optional().describe("Optional markdown description"),
1333
- dueDate: z35.number().optional().describe("Optional due date as a unix timestamp in milliseconds")
1375
+ projectId: z36.string().describe("projectId from list_projects"),
1376
+ name: z36.string().min(1).describe("Milestone name"),
1377
+ description: z36.string().optional().describe("Optional markdown description"),
1378
+ dueDate: z36.number().optional().describe("Optional due date as a unix timestamp in milliseconds")
1334
1379
  },
1335
1380
  annotations: {
1336
1381
  readOnlyHint: false,
@@ -1352,15 +1397,15 @@ function registerCreateMilestone(server) {
1352
1397
  }
1353
1398
 
1354
1399
  // src/tools/add-item-to-milestone.ts
1355
- import { z as z36 } from "zod";
1400
+ import { z as z37 } from "zod";
1356
1401
  function registerAddItemToMilestone(server) {
1357
1402
  server.registerTool(
1358
1403
  "add_item_to_milestone",
1359
1404
  {
1360
1405
  description: "Associate a work item with a milestone (idempotent). Both must be in the same project.",
1361
1406
  inputSchema: {
1362
- milestoneId: z36.string().describe("milestoneId from list_milestones or create_milestone"),
1363
- workItemId: z36.string().describe("workItemId from list_work_items")
1407
+ milestoneId: z37.string().describe("milestoneId from list_milestones or create_milestone"),
1408
+ workItemId: z37.string().describe("workItemId from list_work_items")
1364
1409
  },
1365
1410
  annotations: {
1366
1411
  readOnlyHint: false,
@@ -1386,15 +1431,15 @@ function registerAddItemToMilestone(server) {
1386
1431
  }
1387
1432
 
1388
1433
  // src/tools/remove-item-from-milestone.ts
1389
- import { z as z37 } from "zod";
1434
+ import { z as z38 } from "zod";
1390
1435
  function registerRemoveItemFromMilestone(server) {
1391
1436
  server.registerTool(
1392
1437
  "remove_item_from_milestone",
1393
1438
  {
1394
1439
  description: "Remove a work item's association with a milestone (idempotent \u2014 a no-op if it wasn't associated).",
1395
1440
  inputSchema: {
1396
- milestoneId: z37.string().describe("milestoneId from list_milestones"),
1397
- workItemId: z37.string().describe("workItemId from list_work_items")
1441
+ milestoneId: z38.string().describe("milestoneId from list_milestones"),
1442
+ workItemId: z38.string().describe("workItemId from list_work_items")
1398
1443
  },
1399
1444
  annotations: {
1400
1445
  readOnlyHint: false,
@@ -1429,6 +1474,7 @@ function createServer() {
1429
1474
  // Sent at connect time, before any tool is read (NIM-T189).
1430
1475
  { instructions: INSTRUCTIONS }
1431
1476
  );
1477
+ server.server.oninitialized = () => setClientInfo(server.server.getClientVersion());
1432
1478
  registerListOrgs(server);
1433
1479
  registerListProjects(server);
1434
1480
  registerListWorkItems(server);
@@ -1448,6 +1494,7 @@ function createServer() {
1448
1494
  registerListScratchNotes(server);
1449
1495
  registerResolveScratchNote(server);
1450
1496
  registerHeartbeatWorkItem(server);
1497
+ registerWatchWorkItem(server);
1451
1498
  registerAddWorkItemImage(server);
1452
1499
  registerListWorkItemImages(server);
1453
1500
  registerAddWorkItemComment(server);
package/dist/index.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/index.ts", "../src/server.ts", "../package.json", "../src/instructions.ts", "../../convex/convex/_generated/api.js", "../src/convex.ts", "../src/tools/list-orgs.ts", "../src/tools/list-projects.ts", "../src/tools/list-work-items.ts", "../src/tools/get-work-items.ts", "../src/tools/search-work-items.ts", "../src/tools/list-ai-review-queue.ts", "../src/tools/get-active-block.ts", "../src/tools/create-work-item.ts", "../src/tools/titleGuidance.ts", "../src/tools/statusGuidance.ts", "../../convex/convex/lib/descriptionLimits.ts", "../src/tools/descriptionGuidance.ts", "../src/tools/create-project.ts", "../src/tools/update-work-item.ts", "../src/tools/researchFormat.ts", "../src/tools/move-work-item.ts", "../src/tools/create-document.ts", "../src/tools/update-document.ts", "../src/tools/list-documents.ts", "../src/tools/create-project-link.ts", "../src/tools/list-project-links.ts", "../src/tools/list-scratch-notes.ts", "../src/tools/resolve-scratch-note.ts", "../src/tools/heartbeat-work-item.ts", "../src/tools/add-work-item-image.ts", "../src/tools/list-work-item-images.ts", "../src/tools/add-work-item-comment.ts", "../src/tools/list-work-item-comments.ts", "../src/tools/list-validations.ts", "../src/tools/record-validation.ts", "../src/tools/mark-system-changed.ts", "../src/tools/create-system.ts", "../src/tools/create-validation-task.ts", "../src/tools/add-system-to-task.ts", "../src/tools/add-validation-dependency.ts", "../src/tools/list-labels.ts", "../src/tools/create-label.ts", "../src/tools/add-label-to-work-item.ts", "../src/tools/remove-label-from-work-item.ts", "../src/tools/list-milestones.ts", "../src/tools/create-milestone.ts", "../src/tools/add-item-to-milestone.ts", "../src/tools/remove-item-from-milestone.ts"],
4
- "sourcesContent": ["#!/usr/bin/env node\n// MCP stdio transport reserves stdout for JSON-RPC frames. Any library that\n// writes to stdout (e.g. the Convex client's `[CONVEX A(uth)]` info logs)\n// corrupts the stream. Redirect console.* to stderr before anything else loads.\nfor (const m of [\"log\", \"info\", \"warn\", \"debug\"] as const) {\n console[m] = (...args: unknown[]) => console.error(...args);\n}\n\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { createServer } from \"./server.js\";\n\nasync function main() {\n const server = createServer();\n const transport = new StdioServerTransport();\n await server.connect(transport);\n // Server runs until stdin closes; nothing else to do here.\n}\n\nmain().catch((err) => {\n console.error(\"nimara-mcp: fatal error\", err);\n process.exit(1);\n});\n", "import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport pkg from \"../package.json\" with { type: \"json\" };\nimport { INSTRUCTIONS } from \"./instructions.js\";\nimport { registerListOrgs } from \"./tools/list-orgs.js\";\nimport { registerListProjects } from \"./tools/list-projects.js\";\nimport { registerListWorkItems } from \"./tools/list-work-items.js\";\nimport { registerGetWorkItems } from \"./tools/get-work-items.js\";\nimport { registerSearchWorkItems } from \"./tools/search-work-items.js\";\nimport { registerListAiReviewQueue } from \"./tools/list-ai-review-queue.js\";\nimport { registerGetActiveBlock } from \"./tools/get-active-block.js\";\nimport { registerCreateWorkItem } from \"./tools/create-work-item.js\";\nimport { registerCreateProject } from \"./tools/create-project.js\";\nimport { registerUpdateWorkItem } from \"./tools/update-work-item.js\";\nimport { registerMoveWorkItem } from \"./tools/move-work-item.js\";\nimport { registerCreateDocument } from \"./tools/create-document.js\";\nimport { registerUpdateDocument } from \"./tools/update-document.js\";\nimport { registerListDocuments } from \"./tools/list-documents.js\";\nimport { registerCreateProjectLink } from \"./tools/create-project-link.js\";\nimport { registerListProjectLinks } from \"./tools/list-project-links.js\";\nimport { registerListScratchNotes } from \"./tools/list-scratch-notes.js\";\nimport { registerResolveScratchNote } from \"./tools/resolve-scratch-note.js\";\nimport { registerHeartbeatWorkItem } from \"./tools/heartbeat-work-item.js\";\nimport { registerAddWorkItemImage } from \"./tools/add-work-item-image.js\";\nimport { registerListWorkItemImages } from \"./tools/list-work-item-images.js\";\nimport { registerAddWorkItemComment } from \"./tools/add-work-item-comment.js\";\nimport { registerListWorkItemComments } from \"./tools/list-work-item-comments.js\";\nimport { registerListValidations } from \"./tools/list-validations.js\";\nimport { registerRecordValidation } from \"./tools/record-validation.js\";\nimport { registerMarkSystemChanged } from \"./tools/mark-system-changed.js\";\nimport { registerCreateSystem } from \"./tools/create-system.js\";\nimport { registerCreateValidationTask } from \"./tools/create-validation-task.js\";\nimport { registerAddSystemToTask } from \"./tools/add-system-to-task.js\";\nimport { registerAddValidationDependency } from \"./tools/add-validation-dependency.js\";\nimport { registerListLabels } from \"./tools/list-labels.js\";\nimport { registerCreateLabel } from \"./tools/create-label.js\";\nimport { registerAddLabelToWorkItem } from \"./tools/add-label-to-work-item.js\";\nimport { registerRemoveLabelFromWorkItem } from \"./tools/remove-label-from-work-item.js\";\nimport { registerListMilestones } from \"./tools/list-milestones.js\";\nimport { registerCreateMilestone } from \"./tools/create-milestone.js\";\nimport { registerAddItemToMilestone } from \"./tools/add-item-to-milestone.js\";\nimport { registerRemoveItemFromMilestone } from \"./tools/remove-item-from-milestone.js\";\n\nexport function createServer(): McpServer {\n const server = new McpServer(\n {\n name: \"nimara\",\n version: pkg.version,\n },\n // Sent at connect time, before any tool is read (NIM-T189).\n { instructions: INSTRUCTIONS },\n );\n\n registerListOrgs(server);\n registerListProjects(server);\n registerListWorkItems(server);\n registerGetWorkItems(server);\n registerSearchWorkItems(server);\n registerListAiReviewQueue(server);\n registerGetActiveBlock(server);\n registerCreateProject(server);\n registerCreateWorkItem(server);\n registerUpdateWorkItem(server);\n registerMoveWorkItem(server);\n registerCreateDocument(server);\n registerUpdateDocument(server);\n registerListDocuments(server);\n registerCreateProjectLink(server);\n registerListProjectLinks(server);\n registerListScratchNotes(server);\n registerResolveScratchNote(server);\n registerHeartbeatWorkItem(server);\n registerAddWorkItemImage(server);\n registerListWorkItemImages(server);\n registerAddWorkItemComment(server);\n registerListWorkItemComments(server);\n\n // Validation / test-dependency framework\n registerListValidations(server);\n registerRecordValidation(server);\n registerMarkSystemChanged(server);\n registerCreateSystem(server);\n registerCreateValidationTask(server);\n registerAddSystemToTask(server);\n registerAddValidationDependency(server);\n\n // Labels & milestones\n registerListLabels(server);\n registerCreateLabel(server);\n registerAddLabelToWorkItem(server);\n registerRemoveLabelFromWorkItem(server);\n registerListMilestones(server);\n registerCreateMilestone(server);\n registerAddItemToMilestone(server);\n registerRemoveItemFromMilestone(server);\n\n return server;\n}\n", "{\n \"name\": \"@nimara-app/mcp\",\n \"version\": \"0.4.0\",\n \"private\": false,\n \"mcpName\": \"io.github.langskip-studios/nimara\",\n \"description\": \"Nimara MCP server \u2014 AI tool integration for Claude, Codex, and others\",\n \"license\": \"MIT\",\n \"type\": \"module\",\n \"main\": \"dist/index.js\",\n \"bin\": {\n \"nimara-mcp\": \"dist/index.js\"\n },\n \"files\": [\n \"dist\",\n \"README.md\"\n ],\n \"keywords\": [\n \"mcp\",\n \"model-context-protocol\",\n \"nimara\",\n \"claude\",\n \"ai\",\n \"convex\"\n ],\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/Langskip-Studios/Nimara.git\",\n \"directory\": \"packages/mcp\"\n },\n \"homepage\": \"https://github.com/Langskip-Studios/Nimara/tree/master/packages/mcp#readme\",\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"scripts\": {\n \"build\": \"node build.mjs\",\n \"dev\": \"node build.mjs\",\n \"start\": \"node dist/index.js\",\n \"typecheck\": \"tsc --noEmit\",\n \"prepublishOnly\": \"npm run typecheck && npm run build\"\n },\n \"dependencies\": {\n \"@modelcontextprotocol/sdk\": \"^1.0.0\",\n \"convex\": \"^1.18.0\",\n \"zod\": \"^3.23.0\"\n },\n \"devDependencies\": {\n \"@nimara/convex\": \"workspace:*\",\n \"@types/node\": \"^20.0.0\",\n \"esbuild\": \"^0.23.0\",\n \"typescript\": \"^5.0.0\"\n },\n \"engines\": {\n \"node\": \">=20\"\n }\n}\n", "/**\n * What every MCP client is told at connect time, before any tool is read.\n *\n * The rules that span tools \u2014 titles, statuses, the lease, mentions \u2014 each\n * live in one tool's parameter description, so a model that never loads that\n * tool never hears them. This is the map; the tool descriptions stay the\n * detailed reference. Kept short on purpose: it sits in the model's context\n * for the whole session.\n */\nexport const INSTRUCTIONS = `Nimara is the team's work tracker. Work items have a type (epic > feature > task > subtask), a status from the project's own workflow, and a displayId like NIM-T42 that people read and type.\n\nStart with list_orgs \u2192 list_projects \u2192 get_active_block (the committed work; position 0 is next) and list_ai_review_queue (what a person has asked an agent to do; read \\`answer\\` first). Use get_work_items / search_work_items for items you already know of; list_work_items only to survey.\n\nTitles are plain language a teammate understands at a glance: what is wrong or what changes for a person, not the file, function or mechanism. No em dashes, no \"Area: thing, thing\" shapes. Descriptions carry the why, acceptance criteria and file paths; a spec, design or long report goes in a document (create_document) linked from the item.\n\nA status must be one of the project's \\`statuses\\` from list_projects, spelled exactly; never invent one. Labels come from list_labels; do not invent those either.\n\nWhen you pick up an item: update_work_item { status: <in-progress status>, agentWorking: true }. That lights its row for 15 minutes; any write or read of the item renews it, and on a long stretch with no Nimara calls, heartbeat_work_item every few minutes keeps it lit. Post a comment at real milestones. If you stop early, agentWorking: false. Moving to the last status clears it.\n\nMention a person in a comment as [@Name](user:<userId>) and they are notified. Append agent research to a description under the exact heading \"## Research (auto)\", never editing the human text above it. When you open a PR, put the displayId in its title.`;\n", "/* eslint-disable */\n/**\n * Generated `api` utility.\n *\n * THIS CODE IS AUTOMATICALLY GENERATED.\n *\n * To regenerate, run `npx convex dev`.\n * @module\n */\n\nimport { anyApi, componentsGeneric } from \"convex/server\";\n\n/**\n * A utility for referencing Convex functions in your app's API.\n *\n * Usage:\n * ```js\n * const myFunctionReference = api.myModule.myFunction;\n * ```\n */\nexport const api = anyApi;\nexport const internal = anyApi;\nexport const components = componentsGeneric();\n", "import { ConvexHttpClient } from \"convex/browser\";\n\nlet cachedClient: ConvexHttpClient | null = null;\n\nexport function getConvexClient(): ConvexHttpClient {\n if (cachedClient) return cachedClient;\n\n const url = process.env.NIMARA_CONVEX_URL;\n if (!url) {\n throw new Error(\n \"NIMARA_CONVEX_URL is not set. Add it to your MCP client config (e.g. Claude Desktop's mcpServers env block).\"\n );\n }\n\n cachedClient = new ConvexHttpClient(url);\n return cachedClient;\n}\n\nexport function getToken(): string {\n const token = process.env.NIMARA_TOKEN;\n if (!token) {\n throw new Error(\n \"NIMARA_TOKEN is not set. Generate a personal access token from Nimara \u2192 Settings \u2192 Personal Access Tokens, then add it to your MCP client config.\"\n );\n }\n return token;\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerListOrgs(server: McpServer): void {\n server.registerTool(\n \"list_orgs\",\n {\n description:\n \"List all organizations (and the personal workspace) the authenticated user belongs to. Use this first to discover org IDs needed by other tools.\",\n inputSchema: {},\n annotations: {\n readOnlyHint: true,\n openWorldHint: false,\n },\n },\n\n async () => {\n const client = getConvexClient();\n const orgs = await client.action(api.mcp.listOrgs, { token: getToken() });\n return {\n content: [{ type: \"text\", text: JSON.stringify(orgs, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerListProjects(server: McpServer): void {\n server.registerTool(\n \"list_projects\",\n {\n description:\n \"List projects in a given organization. Call list_orgs first to find \" +\n \"the orgId. Each project includes `statuses` \u2014 its workflow in board \" +\n \"order. Read that before setting a status on any item: those names are \" +\n \"the only accepted values, and anything else is rejected.\",\n inputSchema: { orgId: z.string().describe(\"orgId from list_orgs\") },\n annotations: {\n readOnlyHint: true,\n openWorldHint: false,\n },\n },\n\n async ({ orgId }) => {\n const client = getConvexClient();\n const projects = await client.action(api.mcp.listProjects, {\n token: getToken(),\n orgId,\n });\n return {\n content: [{ type: \"text\", text: JSON.stringify(projects, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerListWorkItems(server: McpServer): void {\n server.registerTool(\n \"list_work_items\",\n {\n // The description is the only place a model learns paging exists, so it\n // states the shape of the response and what to do when hasMore is true.\n description:\n \"List non-archived work items in a project, oldest-created first. Returns \" +\n \"{ items, nextCursor, hasMore }. Long descriptions are previewed \u2014 an \" +\n \"item with descriptionTruncated: true has more text, readable via \" +\n \"fullDescriptions. When hasMore is true, call again with cursor set to \" +\n \"nextCursor to get the next page \u2014 the FIRST page is the OLDEST items, so \" +\n \"recently created ones are on the LAST page and you have not seen the \" +\n \"project until hasMore is false. Narrow with status/type/parentId/\" +\n \"needsReview rather than paging and filtering yourself. If you already \" +\n \"know which items you want, use get_work_items instead \u2014 it takes \" +\n \"displayIds like NIM-T75 and costs a fraction of a list. \" +\n \"Call list_projects first for the projectId.\",\n inputSchema: {\n projectId: z.string().describe(\"projectId from list_projects\"),\n status: z\n .union([z.string(), z.array(z.string())])\n .optional()\n .describe(\n \"Only items in these statuses. Names come from the project's \" +\n \"statusOrder (e.g. 'In Progress'). One name or a list.\",\n ),\n type: z\n .union([\n z.enum([\"epic\", \"feature\", \"task\", \"subtask\"]),\n z.array(z.enum([\"epic\", \"feature\", \"task\", \"subtask\"])),\n ])\n .optional()\n .describe(\"Only items of these types. One type or a list.\"),\n parentId: z\n .string()\n .optional()\n .describe(\n \"Only direct children of this workItemId. One level, not the whole subtree.\",\n ),\n needsReview: z\n .boolean()\n .optional()\n .describe(\n \"true returns only items flagged needsReview; false only unflagged ones. \" +\n \"Omit for both.\",\n ),\n limit: z\n .number()\n .int()\n .min(1)\n .max(200)\n .optional()\n .describe(\"Items per page (default 50, max 200).\"),\n cursor: z\n .number()\n .optional()\n .describe(\n \"nextCursor from the previous page. Omit for the first page.\",\n ),\n fullDescriptions: z\n .boolean()\n .optional()\n .describe(\n \"Return descriptions in full instead of previewed. Costly on large \" +\n \"projects \u2014 prefer paging, or read one item at a time.\",\n ),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: false,\n },\n },\n async ({\n projectId,\n limit,\n cursor,\n fullDescriptions,\n status,\n type,\n parentId,\n needsReview,\n }) => {\n const page = await getConvexClient().action(api.mcp.listWorkItems, {\n token: getToken(),\n projectId,\n limit,\n cursor,\n fullDescriptions,\n // Accepting a bare string as well as a list is what keeps a model from\n // failing validation on the overwhelmingly common single-value case.\n status:\n status === undefined\n ? undefined\n : Array.isArray(status)\n ? status\n : [status],\n type:\n type === undefined ? undefined : Array.isArray(type) ? type : [type],\n parentId,\n needsReview,\n });\n return {\n content: [{ type: \"text\", text: JSON.stringify(page, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerGetWorkItems(server: McpServer): void {\n server.registerTool(\n \"get_work_items\",\n {\n // Written to be chosen *over* list_work_items whenever the caller already\n // knows which items it wants \u2014 that is the whole point of the tool, and\n // the description is the only place a model learns it.\n description:\n \"Read specific work items by id \u2014 the cheap way to re-read items you \" +\n \"already know about. Prefer this over list_work_items whenever you have \" +\n \"a displayId (e.g. NIM-T75) or a workItemId: listing a project returns \" +\n \"every item and its description, which is orders of magnitude more data. \" +\n \"Accepts up to 50 ids per call and always returns descriptions in full. \" +\n \"Returns { items, notFound }; ids in notFound either do not exist or are \" +\n \"not readable by this token. displayIds require projectId (they are \" +\n \"unique per project, not globally); workItemIds do not.\",\n inputSchema: {\n displayIds: z\n .array(z.string())\n .optional()\n .describe(\n \"Human-facing ids like ['NIM-T75', 'NIM-F27']. Case-insensitive. \" +\n \"Requires projectId.\",\n ),\n workItemIds: z\n .array(z.string())\n .optional()\n .describe(\n \"Raw workItemIds, as returned by create_work_item or list_work_items.\",\n ),\n projectId: z\n .string()\n .optional()\n .describe(\n \"projectId from list_projects. Required only when passing displayIds.\",\n ),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: false,\n },\n },\n async ({ displayIds, workItemIds, projectId }) => {\n const result = await getConvexClient().action(api.mcp.getWorkItems, {\n token: getToken(),\n displayIds,\n workItemIds,\n projectId,\n });\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerSearchWorkItems(server: McpServer): void {\n server.registerTool(\n \"search_work_items\",\n {\n // The point of this description is to stop a model reaching for\n // list_work_items when it is looking for something by name. Listing a\n // project to find one item is the expensive mistake this tool exists to\n // prevent.\n description:\n \"Find work items in a project by title. Use this to answer 'does an \" +\n \"item for X already exist?' \u2014 listing the whole project and filtering \" +\n \"yourself is far more expensive and, because the first page is the \" +\n \"OLDEST items, easy to get wrong. Matches TITLES only, not \" +\n \"descriptions. Returns { items, query } with descriptions previewed; \" +\n \"once you know which item you want, get_work_items returns it in full. \" +\n \"Capped at 25 results \u2014 narrow the query rather than paging. \" +\n \"Call list_projects first for the projectId.\",\n inputSchema: {\n projectId: z.string().describe(\"projectId from list_projects\"),\n q: z\n .string()\n .min(1)\n .describe(\n \"Words to match against item titles, e.g. 'mobile modal' or \" +\n \"'shortcut'. Matching is full-text, so word order does not matter.\",\n ),\n limit: z\n .number()\n .int()\n .min(1)\n .max(25)\n .optional()\n .describe(\"Maximum results (default and maximum 25).\"),\n },\n annotations: { readOnlyHint: true },\n },\n async ({ projectId, q, limit }) => {\n const result = await getConvexClient().action(api.mcp.searchWorkItems, {\n token: getToken(),\n projectId,\n q,\n limit,\n });\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerListAiReviewQueue(server: McpServer): void {\n server.registerTool(\n \"list_ai_review_queue\",\n {\n description:\n \"List work items in a project that a human has flagged for AI review \" +\n \"(aiReviewRequested). Descriptions come back in full here, since \" +\n \"enrichment needs the whole text. Each item also carries recentComments \" +\n \"(the last few, oldest first) and, when a person has written one, \" +\n \"`answer`: the newest human comment. READ `answer` FIRST. When you \" +\n \"flagged an item with a question and it is back in this queue, `answer` \" +\n \"is the person's reply to that question; act on it rather than asking \" +\n \"again. Returns { items, nextCursor, hasMore } \u2014 when hasMore is true, \" +\n \"call again with cursor set to nextCursor. Process each item, then clear \" +\n \"its flag by calling update_work_item with aiReviewRequested: false. \" +\n \"Call list_projects first to find the projectId.\",\n inputSchema: {\n projectId: z.string().describe(\"projectId from list_projects\"),\n limit: z\n .number()\n .int()\n .min(1)\n .max(200)\n .optional()\n .describe(\"Items per page (default 50, max 200).\"),\n cursor: z\n .number()\n .optional()\n .describe(\n \"nextCursor from the previous page. Omit for the first page.\",\n ),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: false,\n },\n },\n async ({ projectId, limit, cursor }) => {\n const page = await getConvexClient().action(api.mcp.listAiReviewQueue, {\n token: getToken(),\n projectId,\n limit,\n cursor,\n });\n return {\n content: [{ type: \"text\", text: JSON.stringify(page, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerGetActiveBlock(server: McpServer): void {\n server.registerTool(\n \"get_active_block\",\n {\n description:\n \"The project's ACTIVE BLOCK: the small, ordered set of work a person has \" +\n \"committed to right now. Call this BEFORE list_work_items when deciding what \" +\n \"to work on \u2014 position 0 is the next thing to do, and the wider backlog is \" +\n \"not on the table until the block is empty. Each item carries a lane: \" +\n \"'person' means a human owes it (flagged for review, or parked in a Review \" +\n \"status) and you should not touch it; 'agent' means a human asked an agent \" +\n \"to act on it, so it is yours first, and it carries recentComments and \" +\n \"`answer` (the newest human comment: read it before anything else); \" +\n \"'open' is uncommitted-to-anyone work in \" +\n \"priority order; 'done' is finished. Returns null when the project has no \" +\n \"active block, in which case fall back to list_work_items. Descriptions are \" +\n \"previewed; use get_work_items for the full text of an item you pick up. \" +\n \"Call list_projects first for the projectId.\",\n inputSchema: {\n projectId: z.string().describe(\"projectId from list_projects\"),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: false,\n },\n },\n async ({ projectId }) => {\n const block = await getConvexClient().action(api.mcp.getActiveBlock, {\n token: getToken(),\n projectId,\n });\n return {\n content: [{ type: \"text\", text: JSON.stringify(block, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\nimport { TITLE_GUIDANCE } from \"./titleGuidance.js\";\nimport { STATUS_GUIDANCE } from \"./statusGuidance.js\";\nimport { DESCRIPTION_GUIDANCE, DESCRIPTION_MAX } from \"./descriptionGuidance.js\";\n\nexport function registerCreateWorkItem(server: McpServer): void {\n server.registerTool(\n \"create_work_item\",\n {\n description:\n \"Create a new work item in a project. Hierarchy rules: epics live at the root; features go under epics; tasks go under epics or features (or root); subtasks must go under a task. Returns the new workItemId and its display ID (e.g. NIM-42).\",\n inputSchema: {\n projectId: z.string().describe(\"projectId from list_projects\"),\n type: z\n .enum([\"epic\", \"feature\", \"task\", \"subtask\"])\n .describe(\"Item type \u2014 drives hierarchy validation\"),\n title: z.string().min(1).describe(TITLE_GUIDANCE),\n description: z.string().max(DESCRIPTION_MAX).optional().describe(DESCRIPTION_GUIDANCE),\n parentId: z\n .string()\n .optional()\n .describe(\n \"workItemId of the parent. Required for subtask, optional otherwise.\",\n ),\n status: z\n .string()\n .optional()\n .describe(\n STATUS_GUIDANCE,\n ),\n priority: z\n .enum([\"p0\", \"p1\", \"p2\", \"p3\"])\n .optional()\n .describe(\"p0 highest, p3 lowest. Defaults to p2.\"),\n },\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: false,\n },\n },\n\n async (args) => {\n const client = getConvexClient();\n const result = await client.action(api.mcp.createWorkItem, {\n token: getToken(),\n ...args,\n });\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n },\n );\n}\n", "/**\n * What a work-item title should read like, stated once.\n *\n * This exists because \"Short, descriptive title\" \u2014 the previous guidance on\n * `create_work_item` \u2014 is satisfied by \"Fix hasChildren computation in\n * list.tsx\". That is short and it does describe something, and it is unreadable\n * to anyone who has not just been in that file. Titles are what a board shows;\n * a board full of symbol names cannot be scanned.\n *\n * The em-dash and verbosity rules come from NIM-T117, which Jordan filed\n * before this and which asked for exactly that: \"Remove the em dash and\n * other verbose title that make it hard to read.\"\n *\n * Shared by `create_work_item` and `update_work_item` so the rule cannot hold\n * on one path and not the other \u2014 retitling is the same act as titling, and\n * `update_work_item` previously carried no guidance at all.\n */\nexport const TITLE_GUIDANCE =\n \"A title a teammate can understand at a glance, without opening the item or \" +\n \"knowing the codebase. Say what is wrong or what changes FOR A PERSON, in \" +\n \"plain words \u2014 not the mechanism, the file, or the symbol. \" +\n 'Good: \"Sorted list shows an expand arrow that does nothing\". ' +\n 'Bad: \"Fix hasChildren computation in list.tsx\". ' +\n 'Good: \"Long titles wrap to three lines and are hard to read\". ' +\n 'Bad: \"Adjust COLUMNS.title min-width constant\". ' +\n \"Prefer ordinary words over internal abbreviations, and only name a file, \" +\n \"function or identifier when it genuinely is the clearest way to say it \" +\n \"(a tool or endpoint the user calls by name, for instance). No ticket \" +\n \"prefixes or status markers \u2014 the board renders those already. Root cause, \" +\n \"file paths, and reproduction steps belong in the description, which has \" +\n \"room for them. \" +\n \"Keep it to one plain clause. Do NOT use an em dash, and do not use the \" +\n '\"Area: thing, other thing\" shape \u2014 both are ways of stapling a second ' +\n \"title on and they are what makes these hard to read. \" +\n 'Bad: \"Gantt: tighten row density, match app typography, stop the chart ' +\n 'falling short of its container\". ' +\n 'Good: \"Gantt chart looks nothing like the rest of the app\". ' +\n \"If the title needs a comma-spliced list to be accurate, that is a sign the \" +\n \"item is really several items, not a sign it needs a longer title.\";\n", "/**\n * How to choose a status, stated once.\n *\n * The rule the tools already stated \u2014 \"a status name from the project's\n * statusOrder\" \u2014 referred to data no tool returned. An agent could not read a\n * project's workflow, so it guessed a plausible-sounding name, and the guess\n * was frequently \"In Review\" on boards whose workflow only ever had \"Review\".\n * `list_projects` now returns `statuses`, which is what makes this instruction\n * followable rather than aspirational.\n *\n * The second half matters as much as the first. A status is POSITIONAL \u2014 it is\n * the board column \u2014 so inventing one is not a labelling choice, it reshapes\n * the board and every status chart that aggregates across projects. Anything\n * that describes an item without saying where it sits in the flow is a label:\n * `list_labels`, `create_label` and `add_label_to_work_item` exist for exactly\n * that, and cost nothing to add. This is NIM-T49's decision, held to.\n *\n * Shared by `create_work_item` and `update_work_item`. `update_work_item.status`\n * previously carried no guidance at all, which is the path most likely to move\n * an item to an invented status.\n */\nexport const STATUS_GUIDANCE =\n \"Must be one of the names in the project's `statuses`, returned by \" +\n \"list_projects. Read it rather than guessing \u2014 a status is the board \" +\n \"column, so a name the workflow does not have is rejected, and before that \" +\n \"check existed such items rendered in the first column while claiming \" +\n \"otherwise. Match the existing name exactly, including its wording: if the \" +\n \"workflow says \\\"Review\\\", do not write \\\"In Review\\\". \" +\n \"Do NOT invent a status to capture something about an item. Statuses are \" +\n \"shared across the whole project and aggregated on the dashboard, so each \" +\n \"new one is a permanent extra band there. Anything that describes an item \" +\n \"rather than locating it in the flow belongs in a LABEL \u2014 see create_label \" +\n \"and add_label_to_work_item. Defaults to the first status when omitted.\";\n", "/**\n * The two sizes a work item description is measured against. Kept free of\n * Convex imports so the web app and the MCP package can share the numbers.\n *\n * PREVIEW is what the row carries so lists never join the body\n * (lib/workItemBody.ts). MAX is a sanity cap, not a product decision: no\n * task written by hand comes near it, but an agent pasting a log or a whole\n * research report into a description would \u2014 and that belongs in a document.\n * Descriptions averaged 14 KB when the cap was chosen; 32 KB is roughly\n * 5,000 words, eight pages.\n */\nexport const DESCRIPTION_PREVIEW_CHARS = 500;\nexport const DESCRIPTION_MAX_CHARS = 32_000;\n\n/** Where a description's length stands, for an error or a counter. */\nexport const DESCRIPTION_TOO_LONG =\n `A description can be at most ${DESCRIPTION_MAX_CHARS.toLocaleString(\"en-US\")} characters. ` +\n \"Put specs, research and long reports in a document and link it to the item.\";\n", "import { DESCRIPTION_MAX_CHARS } from \"@nimara/convex/convex/lib/descriptionLimits.js\";\n\n/**\n * What a description is for, and how big it may be, stated once and shared\n * by `create_work_item` and `update_work_item` the way TITLE_GUIDANCE is.\n *\n * The cap is enforced server-side in writeDescription; the zod max here\n * only means an agent hears about it before the round-trip. The guidance is\n * the real lever: descriptions averaged 14 KB because agents used them as\n * the place to put everything, and the row split (lib/workItemBody.ts) made\n * that cheap but not right \u2014 a document is what other items can link to.\n */\nexport const DESCRIPTION_MAX = DESCRIPTION_MAX_CHARS;\n\nexport const DESCRIPTION_GUIDANCE =\n \"Markdown. The what and the why: the problem, acceptance criteria, \" +\n \"reproduction steps, file paths, root cause. Keep it to what someone \" +\n \"picking the item up needs. A spec, a design, research, or a long report \" +\n \"goes in a document (create_document) linked from here, not inline. \" +\n `At most ${DESCRIPTION_MAX_CHARS.toLocaleString(\"en-US\")} characters.`;\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerCreateProject(server: McpServer): void {\n server.registerTool(\n \"create_project\",\n {\n description:\n \"Create a new project in an org. Prefix must be unique within the org and is uppercased (e.g. 'NIM' yields work items NIM-1, NIM-2\u2026). Caller becomes the project admin. Returns the new projectId.\",\n inputSchema: {\n orgId: z.string().describe(\"orgId from list_orgs\"),\n name: z.string().min(1).describe(\"Project name\"),\n prefix: z\n .string()\n .min(1)\n .max(8)\n .describe(\n \"Short uppercase prefix for work item IDs (e.g. 'NIM'). Unique per org.\",\n ),\n description: z\n .string()\n .optional()\n .describe(\"Optional markdown description\"),\n isPrivate: z\n .boolean()\n .optional()\n .describe(\n \"If true, only explicitly added members see it. Defaults to false.\",\n ),\n workflowTemplate: z\n .enum([\"default\", \"simple\", \"kanban\", \"bug\"])\n .optional()\n .describe(\n \"Status workflow. Defaults to 'default' (Backlog/Todo/In Progress/Review/Done).\",\n ),\n },\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: false,\n },\n },\n\n async (args) => {\n const client = getConvexClient();\n const result = await client.action(api.mcp.createProject, {\n token: getToken(),\n ...args,\n });\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\nimport { TITLE_GUIDANCE } from \"./titleGuidance.js\";\nimport { STATUS_GUIDANCE } from \"./statusGuidance.js\";\nimport { DESCRIPTION_GUIDANCE, DESCRIPTION_MAX } from \"./descriptionGuidance.js\";\nimport { RESEARCH_FORMAT } from \"./researchFormat.js\";\n\nexport function registerUpdateWorkItem(server: McpServer): void {\n server.registerTool(\n \"update_work_item\",\n {\n description:\n \"Update an existing work item: title, description, status, priority, parent, or review flags. Any update also stamps the item as AI-touched.\",\n inputSchema: {\n workItemId: z.string().describe(\"workItemId from list_work_items\"),\n title: z.string().min(1).optional().describe(TITLE_GUIDANCE),\n description: z\n .string()\n .max(DESCRIPTION_MAX)\n .optional()\n .describe(\n \"Full markdown body, replacing what is there. \" +\n DESCRIPTION_GUIDANCE +\n \" \" +\n RESEARCH_FORMAT,\n ),\n status: z.string().optional().describe(STATUS_GUIDANCE),\n priority: z.enum([\"p0\", \"p1\", \"p2\", \"p3\"]).optional(),\n parentId: z\n .string()\n .nullable()\n .optional()\n .describe(\"New parent workItemId, null to move to root.\"),\n needsReview: z\n .boolean()\n .optional()\n .describe(\n \"Flag the item for manual human review \u2014 set true when your enrichment was thin or uncertain.\",\n ),\n reviewReason: z\n .string()\n .optional()\n .describe(\n \"Short reason the item needs manual review (shown to the human).\",\n ),\n aiReviewRequested: z\n .boolean()\n .optional()\n .describe(\n \"The human\u2192AI review flag. Set false to clear it after you have reviewed/enriched an item from list_ai_review_queue.\",\n ),\n agentWorking: z\n .boolean()\n .optional()\n .describe(\n \"Set true when you start working on this item: the app lights its row so the person can see it is in flight. It is a 15-minute lease renewed by any later MCP write on the item (updates, comments), by reading it (get_work_items, list_work_item_comments), or by heartbeat_work_item \u2014 call that every few minutes on a long task with no other Nimara calls, or the row goes quiet while you are still at it. Set false when you stop without finishing; moving the item to the last status clears it for you.\",\n ),\n },\n annotations: {\n readOnlyHint: false,\n destructiveHint: true,\n idempotentHint: true,\n openWorldHint: false,\n },\n },\n\n async (args) => {\n const result = await getConvexClient().action(api.mcp.updateWorkItem, {\n token: getToken(),\n ...args,\n });\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n },\n );\n}\n", "/**\n * The shape of the automated research block an enrichment agent appends to a\n * work item's description.\n *\n * Two reasons this is stated here rather than left to each agent's own taste.\n *\n * The web app parses this block out of the description and renders it in its\n * own tab on the item (NIM-T125). The anchor heading is therefore a contract,\n * not a style choice: change its wording and the tab stops appearing, with the\n * text still sitting in the description and nothing failing loudly.\n *\n * And the existing blocks are decorated with emoji section markers \u2014 \uD83D\uDD0E, \uD83D\uDD17,\n * \uD83E\uDDED, \uD83C\uDF9A. They read as noise in a panel that is already labelled \"Research\",\n * they carry no information the heading does not, and they are the first thing\n * Jordan asked to remove. The parser accepts the old emoji heading so the 20\n * items already enriched keep working; nothing new should write one.\n *\n * Deliberately NOT permitted: raw HTML. The app renders this with\n * `react-markdown` and no `rehype-raw`, so HTML is stripped rather than shown \u2014\n * and turning that on would render agent-authored markup whose inputs include\n * untrusted work-item text. Mermaid fences cover the diagram case without\n * opening that door.\n */\nexport const RESEARCH_FORMAT = `When appending automated research to a description, use EXACTLY this format, \\\nafter the human-written text:\n\n---\n## Research (auto)\n\n### Findings\n- One bullet per verified fact, each naming what you checked.\n\n### Dependencies\n- Items this blocks or is blocked by, by displayId. Omit the section if none.\n\n### Duplicates\n- Existing items covering the same work, by displayId. Omit if none.\n\n### Suggested priority\nOne line. Say \"No change\" when it is already right.\n\nRules:\n- The \"## Research (auto)\" heading is EXACT and is what the app keys on to show \\\nthis in its own tab. Do not reword it, renumber its level, or translate it.\n- NO EMOJI anywhere in the block, in headings or in bullets. Older items carry \\\nemoji headings; do not copy them.\n- Omit a section rather than writing \"None found\" in it. An empty section is \\\nnoise the reader still has to read.\n- Never edit or delete the human-written text above the rule. Append only.\n- Markdown only. GFM tables are supported and are the right choice for \\\ncomparisons. Raw HTML is NOT rendered by the app and must not be used.\n- For a workflow, sequence or state machine, use a \\\\\\`\\\\\\`\\\\\\`mermaid fenced block. \\\nThat is the supported way to draw one.\n- Say what you verified and how. \"Confirmed X still returns Y (file:line)\" is \\\nworth more than a conclusion with no trail.`;\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerMoveWorkItem(server: McpServer): void {\n server.registerTool(\n \"move_work_item\",\n {\n // Everything a model needs to predict the damage has to be stated here \u2014\n // the description is the only channel it has. The consequences that are\n // NOT obvious from the name are the ones worth the tokens: the display ID\n // changes, and labels/milestones do not survive.\n description:\n \"Move a work item to a different project, taking its whole subtree \" +\n \"with it \u2014 children and grandchildren move too, and the hierarchy is \" +\n \"preserved. Both projects must be in the same organization, and you \" +\n \"need write access to both. \" +\n \"Not reversible by calling this again: the item is renumbered in the \" +\n \"destination, so NIM-T44 might become SKA-T18 and the old ID stops \" +\n \"resolving. Labels and milestone assignments are dropped, because both \" +\n \"belong to the project being left; a status the destination doesn't \" +\n \"define falls back to its first status. The response reports every \" +\n \"old \u2192 new ID plus everything that was dropped or remapped. \" +\n \"Comments, images, attached documents, PR links and history all follow \" +\n \"the item. Call list_projects first for the target projectId.\",\n inputSchema: {\n workItemId: z\n .string()\n .describe(\"workItemId from list_work_items \u2014 the item to move.\"),\n targetProjectId: z\n .string()\n .describe(\n \"projectId from list_projects \u2014 the destination. Must be in the \" +\n \"same org as the item's current project.\",\n ),\n },\n annotations: {\n readOnlyHint: false,\n // Renumbering display IDs and deleting label/milestone links are\n // overwrites, not additions \u2014 this belongs with the tools a client\n // should prompt on rather than auto-approve.\n destructiveHint: true,\n // Calling it twice does not land in the same place: the second call\n // either errors as already-there or moves the item on again.\n idempotentHint: false,\n openWorldHint: false,\n },\n },\n async ({ workItemId, targetProjectId }) => {\n const result = await getConvexClient().action(\n api.mcp.moveWorkItemToProject,\n { token: getToken(), workItemId, targetProjectId },\n );\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerCreateDocument(server: McpServer): void {\n server.registerTool(\n \"create_document\",\n {\n description:\n \"Create a markdown project document. Use type 'prd' for project docs or 'fd' for feature/work-item documents.\",\n inputSchema: {\n projectId: z.string().describe(\"projectId from list_projects\"),\n title: z.string().min(1),\n type: z\n .enum([\"prd\", \"fd\"])\n .describe(\n \"Document type. 'fd' is stored as the app's feature document type.\",\n ),\n workItemId: z\n .string()\n .optional()\n .describe(\"Required for fd documents; omitted for prd.\"),\n content: z\n .string()\n .optional()\n .describe(\"Optional initial markdown content.\"),\n },\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: false,\n },\n },\n\n async (args) => {\n const result = await getConvexClient().action(api.mcp.createDocument, {\n token: getToken(),\n ...args,\n });\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerUpdateDocument(server: McpServer): void {\n server.registerTool(\n \"update_document\",\n {\n description:\n \"Update an existing document's markdown content and/or title. Use this to fill in or revise a document created earlier (e.g. backfill content into an empty doc). documentId comes from list_documents. Provided content fully replaces the existing content.\",\n inputSchema: {\n documentId: z.string().describe(\"documentId from list_documents\"),\n content: z\n .string()\n .optional()\n .describe(\n \"New markdown content. Replaces the document's existing content.\",\n ),\n title: z.string().min(1).optional().describe(\"New title (optional).\"),\n },\n annotations: {\n readOnlyHint: false,\n destructiveHint: true,\n idempotentHint: true,\n openWorldHint: false,\n },\n },\n\n async (args) => {\n const result = await getConvexClient().action(api.mcp.updateDocument, {\n token: getToken(),\n ...args,\n });\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerListDocuments(server: McpServer): void {\n server.registerTool(\n \"list_documents\",\n {\n description:\n \"List PRD/FD markdown documents for a project, optionally filtered to one work item.\",\n inputSchema: {\n projectId: z.string().describe(\"projectId from list_projects\"),\n workItemId: z\n .string()\n .optional()\n .describe(\"Optional workItemId to list linked FD documents.\"),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: false,\n },\n },\n\n async (args) => {\n const result = await getConvexClient().action(api.mcp.listDocuments, {\n token: getToken(),\n ...args,\n });\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nconst projectLinkCategory = z.enum([\n \"api\",\n \"dashboard\",\n \"documentation\",\n \"repository\",\n \"service\",\n \"other\",\n]);\n\nexport function registerCreateProjectLink(server: McpServer): void {\n server.registerTool(\n \"create_project_link\",\n {\n description:\n \"Save a link on a project for resources like APIs, dashboards, documentation, repositories, or services.\",\n inputSchema: {\n projectId: z.string().describe(\"projectId from list_projects\"),\n title: z.string().min(1).max(120),\n url: z.string().url().describe(\"http(s) URL to save\"),\n description: z.string().max(500).optional(),\n category: projectLinkCategory.optional().describe(\"Defaults to other.\"),\n },\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: false,\n },\n },\n\n async (args) => {\n const result = await getConvexClient().action(api.mcp.createProjectLink, {\n token: getToken(),\n ...args,\n });\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerListProjectLinks(server: McpServer): void {\n server.registerTool(\n \"list_project_links\",\n {\n description:\n \"List saved links for a project, such as APIs, dashboards, docs, repositories, and services.\",\n inputSchema: {\n projectId: z.string().describe(\"projectId from list_projects\"),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: false,\n },\n },\n\n async ({ projectId }) => {\n const result = await getConvexClient().action(api.mcp.listProjectLinks, {\n token: getToken(),\n projectId,\n });\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerListScratchNotes(server: McpServer): void {\n server.registerTool(\n \"list_scratch_notes\",\n {\n description:\n \"The token owner's OPEN scratch notes: thoughts and ideas they captured \" +\n \"in the app with the `s` shortcut before deciding what to do with them. \" +\n \"Returns the notes that belong with this project (tagged with it, or \" +\n \"tagged with nothing), oldest first, each with noteId, body, projectId \" +\n \"and createdAt. These are raw: a note may be one line or a paragraph, \" +\n \"may describe one task or three, and may not be a task at all. Read \" +\n \"each, decide what it should become (usually one or more work items \" +\n \"via create_work_item, sometimes a comment on an existing item, \" +\n \"sometimes nothing), do that, then call resolve_scratch_note with the \" +\n \"noteId and the workItemId it became so the person sees where their \" +\n \"note went. Ask in a comment rather than guess when a note is too \" +\n \"thin to act on. Call list_projects first for the projectId.\",\n inputSchema: {\n projectId: z.string().describe(\"projectId from list_projects\"),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: false,\n },\n },\n async ({ projectId }) => {\n const notes = await getConvexClient().action(api.mcp.listScratchNotes, {\n token: getToken(),\n projectId,\n });\n return {\n content: [{ type: \"text\", text: JSON.stringify(notes, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerResolveScratchNote(server: McpServer): void {\n server.registerTool(\n \"resolve_scratch_note\",\n {\n description:\n \"Mark a scratch note as used, recording the work item it became. Call \" +\n \"this after acting on a note from list_scratch_notes: pass the noteId \" +\n \"and the workItemId you created or updated from it (omit workItemId \" +\n \"only when the note needed no item). The note leaves the person's open \" +\n \"list and shows where it went. Only the token owner's own notes.\",\n inputSchema: {\n noteId: z.string().describe(\"noteId from list_scratch_notes\"),\n workItemId: z\n .string()\n .optional()\n .describe(\"The workItemId the note became, from create_work_item or list_work_items.\"),\n },\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: false,\n },\n },\n async ({ noteId, workItemId }) => {\n const result = await getConvexClient().action(api.mcp.resolveScratchNote, {\n token: getToken(),\n noteId,\n workItemId,\n });\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerHeartbeatWorkItem(server: McpServer): void {\n server.registerTool(\n \"heartbeat_work_item\",\n {\n description:\n \"Say you are still working on an item. Renews (or starts) its 15-minute \" +\n \"\\\"agent working\\\" lease and does nothing else: no comment, no activity \" +\n \"event, no change to the item. The app lights the row while the lease is \" +\n \"live, so on a long task call this every few minutes or every handful of \" +\n \"tool calls \u2014 otherwise the row goes quiet while you are still at it. \" +\n \"Reads of the item (get_work_items, list_work_item_comments) also renew a \" +\n \"live lease, and any update or comment does; this is for the stretches \" +\n \"where you do none of those. Cheap and idempotent.\",\n inputSchema: {\n workItemId: z.string().describe(\"workItemId of the item you are working on\"),\n },\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: false,\n },\n },\n async ({ workItemId }) => {\n const result = await getConvexClient().action(api.mcp.heartbeatWorkItem, {\n token: getToken(),\n workItemId,\n });\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerAddWorkItemImage(server: McpServer): void {\n server.registerTool(\n \"add_work_item_image\",\n {\n description:\n \"Attach an externally hosted image URL to a work item. Use this when an MCP client has a screenshot, mockup, or generated image URL to preserve with the task.\",\n inputSchema: {\n workItemId: z.string().describe(\"workItemId from list_work_items\"),\n imageUrl: z\n .string()\n .url()\n .describe(\"Public or otherwise fetchable http(s) image URL\"),\n filename: z.string().optional().describe(\"Optional display filename\"),\n altText: z\n .string()\n .optional()\n .describe(\"Optional description/caption for the image\"),\n },\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: false,\n },\n },\n\n async (args) => {\n const result = await getConvexClient().action(api.mcp.addWorkItemImage, {\n token: getToken(),\n ...args,\n });\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerListWorkItemImages(server: McpServer): void {\n server.registerTool(\n \"list_work_item_images\",\n {\n description:\n \"List image attachments for a work item, including uploaded images and externally attached MCP images. Call list_work_items first to find the workItemId.\",\n inputSchema: {\n workItemId: z.string().describe(\"workItemId from list_work_items\"),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: false,\n },\n },\n\n async ({ workItemId }) => {\n const result = await getConvexClient().action(\n api.mcp.listWorkItemImages,\n {\n token: getToken(),\n workItemId,\n },\n );\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerAddWorkItemComment(server: McpServer): void {\n server.registerTool(\n \"add_work_item_comment\",\n {\n description:\n \"Add a timestamped comment to a work item. Use this to record notes, updates, \" +\n \"or an 'AI touched' entry instead of editing the description. Comments are \" +\n \"stamped with the current time automatically and never overwrite each other.\",\n inputSchema: {\n workItemId: z.string().describe(\"workItemId from list_work_items\"),\n body: z\n .string()\n .min(1)\n .describe(\n \"Comment text (markdown supported). To pull a person into the thread, mention them as [@Name](user:<userId>) \u2014 they are notified and the app renders it as a chip. userIds come from an item's assigneeId/reviewerId; there is no member lookup tool yet, so only mention ids you have seen.\",\n ),\n source: z\n .enum([\"user\", \"ai\"])\n .optional()\n .describe('Who authored it; defaults to \"ai\" for MCP callers'),\n },\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: false,\n },\n },\n\n async (args) => {\n const result = await getConvexClient().action(\n api.mcp.addWorkItemComment,\n {\n token: getToken(),\n ...args,\n },\n );\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerListWorkItemComments(server: McpServer): void {\n server.registerTool(\n \"list_work_item_comments\",\n {\n description:\n \"List the timestamped comments on a work item, oldest first. Use this to check \" +\n \"whether the item was already touched/commented before adding a new comment.\",\n inputSchema: {\n workItemId: z.string().describe(\"workItemId from list_work_items\"),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: false,\n },\n },\n\n async (args) => {\n const result = await getConvexClient().action(\n api.mcp.listWorkItemComments,\n {\n token: getToken(),\n ...args,\n },\n );\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerListValidations(server: McpServer): void {\n server.registerTool(\n \"list_validations\",\n {\n description:\n \"List a project's validation graph: core systems and validation/test tasks with their DERIVED state (passing, failing, stale, unvalidated). A task is 'stale' when a system it covers changed since it was last validated, or an upstream dependency is no longer passing. Call list_projects first to find the projectId.\",\n inputSchema: {\n projectId: z.string().describe(\"projectId from list_projects\"),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: false,\n },\n },\n\n async ({ projectId }) => {\n const client = getConvexClient();\n const graph = await client.action(api.mcp.listValidations, {\n token: getToken(),\n projectId,\n });\n return {\n content: [{ type: \"text\", text: JSON.stringify(graph, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerRecordValidation(server: McpServer): void {\n server.registerTool(\n \"record_validation\",\n {\n description:\n \"Check off a validation task by recording a pass or fail. Stamps the task as validated 'now', clearing any stale flag until a covered system changes or an upstream dependency moves again. Get validationTaskId from list_validations.\",\n inputSchema: {\n validationTaskId: z\n .string()\n .describe(\"validationTaskId from list_validations\"),\n result: z\n .enum([\"pass\", \"fail\"])\n .describe(\"Outcome of running the test\"),\n },\n annotations: {\n readOnlyHint: false,\n destructiveHint: true,\n idempotentHint: true,\n openWorldHint: false,\n },\n },\n\n async ({ validationTaskId, result }) => {\n const client = getConvexClient();\n const res = await client.action(api.mcp.recordValidation, {\n token: getToken(),\n validationTaskId,\n result,\n });\n return {\n content: [{ type: \"text\", text: JSON.stringify(res, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerMarkSystemChanged(server: McpServer): void {\n server.registerTool(\n \"mark_system_changed\",\n {\n description:\n \"Mark a core system as changed. This is the single action that invalidates testing: every validation task that covers this system (and everything transitively depending on those tasks) immediately becomes 'stale' and needs revalidation. Get systemId from list_validations.\",\n inputSchema: {\n systemId: z.string().describe(\"systemId from list_validations\"),\n },\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: false,\n },\n },\n\n async ({ systemId }) => {\n const client = getConvexClient();\n const res = await client.action(api.mcp.markSystemChanged, {\n token: getToken(),\n systemId,\n });\n return {\n content: [{ type: \"text\", text: JSON.stringify(res, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerCreateSystem(server: McpServer): void {\n server.registerTool(\n \"create_system\",\n {\n description:\n \"Create a core system in a project \u2014 a subsystem (e.g. Auth, Payments, Sync) whose change should invalidate the validation tasks that cover it. Returns the new systemId.\",\n inputSchema: {\n projectId: z.string().describe(\"projectId from list_projects\"),\n name: z.string().min(1).describe(\"Short system name, e.g. 'Auth'\"),\n description: z.string().optional().describe(\"Optional details\"),\n },\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: false,\n },\n },\n\n async (args) => {\n const client = getConvexClient();\n const res = await client.action(api.mcp.createSystem, {\n token: getToken(),\n ...args,\n });\n return {\n content: [{ type: \"text\", text: JSON.stringify(res, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerCreateValidationTask(server: McpServer): void {\n server.registerTool(\n \"create_validation_task\",\n {\n description:\n \"Create a validation/test task in a project. After creating it, use add_system_to_task to declare which systems it exercises (so it goes stale when they change) and add_validation_dependency to order it after other tasks. Returns the new validationTaskId.\",\n inputSchema: {\n projectId: z.string().describe(\"projectId from list_projects\"),\n title: z.string().min(1).describe(\"What this test validates\"),\n description: z.string().optional().describe(\"Optional steps / details\"),\n kind: z\n .enum([\"auto\", \"manual\"])\n .optional()\n .describe(\n \"'auto' if runnable by a test runner, 'manual' if a human checks it. Defaults to manual.\",\n ),\n workItemId: z\n .string()\n .optional()\n .describe(\n \"Optional workItemId to link this test to a feature for traceability\",\n ),\n },\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: false,\n },\n },\n\n async (args) => {\n const client = getConvexClient();\n const res = await client.action(api.mcp.createValidationTask, {\n token: getToken(),\n ...args,\n });\n return {\n content: [{ type: \"text\", text: JSON.stringify(res, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerAddSystemToTask(server: McpServer): void {\n server.registerTool(\n \"add_system_to_task\",\n {\n description:\n \"Declare that a validation task COVERS (exercises) a system. Once linked, the task becomes 'stale' whenever that system is marked changed. Idempotent. Both IDs come from list_validations and must be in the same project.\",\n inputSchema: {\n validationTaskId: z\n .string()\n .describe(\"validationTaskId from list_validations\"),\n systemId: z.string().describe(\"systemId from list_validations\"),\n },\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: false,\n },\n },\n\n async ({ validationTaskId, systemId }) => {\n const client = getConvexClient();\n const res = await client.action(api.mcp.addSystemToTask, {\n token: getToken(),\n validationTaskId,\n systemId,\n });\n return {\n content: [{ type: \"text\", text: JSON.stringify(res, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerAddValidationDependency(server: McpServer): void {\n server.registerTool(\n \"add_validation_dependency\",\n {\n description:\n \"Make one validation task depend on another (validationTaskId depends on dependsOnTaskId). The dependent goes 'stale' whenever the upstream task is not passing or gets revalidated. Cycles and self-dependencies are rejected. Idempotent. Both IDs come from list_validations and must be in the same project.\",\n inputSchema: {\n validationTaskId: z\n .string()\n .describe(\"The dependent (downstream) task\"),\n dependsOnTaskId: z\n .string()\n .describe(\"The dependency (upstream) task it relies on\"),\n },\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: false,\n },\n },\n\n async ({ validationTaskId, dependsOnTaskId }) => {\n const client = getConvexClient();\n const res = await client.action(api.mcp.addValidationDependency, {\n token: getToken(),\n validationTaskId,\n dependsOnTaskId,\n });\n return {\n content: [{ type: \"text\", text: JSON.stringify(res, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerListLabels(server: McpServer): void {\n server.registerTool(\n \"list_labels\",\n {\n description:\n \"List all labels defined in a project. Returns each label's id, name, and color. Use the labelId with add_label_to_work_item / remove_label_from_work_item.\",\n inputSchema: {\n projectId: z.string().describe(\"projectId from list_projects\"),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: false,\n },\n },\n\n async (args) => {\n const result = await getConvexClient().action(api.mcp.listLabels, {\n token: getToken(),\n ...args,\n });\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerCreateLabel(server: McpServer): void {\n server.registerTool(\n \"create_label\",\n {\n description:\n \"Apply-or-seed a label. Returns the existing label if the name is \" +\n \"already taken (idempotent), and otherwise creates it ONLY if the name \" +\n \"is one of the curated ones. Any other new name is REFUSED \u2014 the reply \" +\n \"carries `refused: true`, the reason, and `available`, the project's \" +\n \"existing labels. Agents apply labels; they do not invent them, because \" +\n \"a near-duplicate of an existing label splits the vocabulary silently. \" +\n \"Prefer list_labels first. Colors are ignored for curated names so the \" +\n \"vocabulary looks the same in every project.\",\n inputSchema: {\n projectId: z.string().describe(\"projectId from list_projects\"),\n name: z\n .string()\n .min(1)\n .describe(\"Label name, unique within the project\"),\n color: z\n .string()\n .regex(/^#[0-9a-fA-F]{6}$/)\n .optional()\n .describe(\"Hex color like #2563eb. Defaults to a neutral slate.\"),\n },\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: false,\n },\n },\n\n async (args) => {\n const result = await getConvexClient().action(api.mcp.createLabel, {\n token: getToken(),\n ...args,\n });\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerAddLabelToWorkItem(server: McpServer): void {\n server.registerTool(\n \"add_label_to_work_item\",\n {\n description:\n \"Attach a label to a work item (idempotent). The label and work item must be in the same project. Get labelIds from list_labels / create_label.\",\n inputSchema: {\n workItemId: z.string().describe(\"workItemId from list_work_items\"),\n labelId: z\n .string()\n .describe(\"labelId from list_labels or create_label\"),\n },\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: false,\n },\n },\n\n async (args) => {\n const result = await getConvexClient().action(api.mcp.setWorkItemLabel, {\n token: getToken(),\n ...args,\n attached: true,\n });\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerRemoveLabelFromWorkItem(server: McpServer): void {\n server.registerTool(\n \"remove_label_from_work_item\",\n {\n description:\n \"Remove a label from a work item (idempotent \u2014 a no-op if it wasn't attached).\",\n inputSchema: {\n workItemId: z.string().describe(\"workItemId from list_work_items\"),\n labelId: z.string().describe(\"labelId from list_labels\"),\n },\n annotations: {\n readOnlyHint: false,\n destructiveHint: true,\n idempotentHint: true,\n openWorldHint: false,\n },\n },\n\n async (args) => {\n const result = await getConvexClient().action(api.mcp.setWorkItemLabel, {\n token: getToken(),\n ...args,\n attached: false,\n });\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerListMilestones(server: McpServer): void {\n server.registerTool(\n \"list_milestones\",\n {\n description:\n \"List all milestones in a project. Returns each milestone's id, name, description, dueDate (unix ms), and status. Use the milestoneId with add_item_to_milestone / remove_item_from_milestone.\",\n inputSchema: {\n projectId: z.string().describe(\"projectId from list_projects\"),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: false,\n },\n },\n\n async (args) => {\n const result = await getConvexClient().action(api.mcp.listMilestones, {\n token: getToken(),\n ...args,\n });\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerCreateMilestone(server: McpServer): void {\n server.registerTool(\n \"create_milestone\",\n {\n description:\n \"Create a milestone in a project. Returns the milestoneId. Good for grouping work into phases (e.g. 'Phase 1 \u2014 Web', 'Phase 2 \u2014 Native').\",\n inputSchema: {\n projectId: z.string().describe(\"projectId from list_projects\"),\n name: z.string().min(1).describe(\"Milestone name\"),\n description: z\n .string()\n .optional()\n .describe(\"Optional markdown description\"),\n dueDate: z\n .number()\n .optional()\n .describe(\"Optional due date as a unix timestamp in milliseconds\"),\n },\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: false,\n },\n },\n\n async (args) => {\n const result = await getConvexClient().action(api.mcp.createMilestone, {\n token: getToken(),\n ...args,\n });\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerAddItemToMilestone(server: McpServer): void {\n server.registerTool(\n \"add_item_to_milestone\",\n {\n description:\n \"Associate a work item with a milestone (idempotent). Both must be in the same project.\",\n inputSchema: {\n milestoneId: z\n .string()\n .describe(\"milestoneId from list_milestones or create_milestone\"),\n workItemId: z.string().describe(\"workItemId from list_work_items\"),\n },\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: false,\n },\n },\n\n async (args) => {\n const result = await getConvexClient().action(\n api.mcp.setWorkItemMilestone,\n {\n token: getToken(),\n ...args,\n attached: true,\n },\n );\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerRemoveItemFromMilestone(server: McpServer): void {\n server.registerTool(\n \"remove_item_from_milestone\",\n {\n description:\n \"Remove a work item's association with a milestone (idempotent \u2014 a no-op if it wasn't associated).\",\n inputSchema: {\n milestoneId: z.string().describe(\"milestoneId from list_milestones\"),\n workItemId: z.string().describe(\"workItemId from list_work_items\"),\n },\n annotations: {\n readOnlyHint: false,\n destructiveHint: true,\n idempotentHint: true,\n openWorldHint: false,\n },\n },\n\n async (args) => {\n const result = await getConvexClient().action(\n api.mcp.setWorkItemMilestone,\n {\n token: getToken(),\n ...args,\n attached: false,\n },\n );\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n },\n );\n}\n"],
5
- "mappings": "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",
6
- "names": ["z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z"]
3
+ "sources": ["../src/index.ts", "../src/server.ts", "../package.json", "../src/instructions.ts", "../src/convex.ts", "../../convex/convex/_generated/api.js", "../src/tools/list-orgs.ts", "../src/tools/list-projects.ts", "../src/tools/list-work-items.ts", "../src/tools/get-work-items.ts", "../src/tools/search-work-items.ts", "../src/tools/list-ai-review-queue.ts", "../src/tools/get-active-block.ts", "../src/tools/create-work-item.ts", "../src/tools/titleGuidance.ts", "../src/tools/statusGuidance.ts", "../../convex/convex/lib/descriptionLimits.ts", "../src/tools/descriptionGuidance.ts", "../src/tools/create-project.ts", "../src/tools/update-work-item.ts", "../src/tools/researchFormat.ts", "../src/tools/move-work-item.ts", "../src/tools/create-document.ts", "../src/tools/update-document.ts", "../src/tools/list-documents.ts", "../src/tools/create-project-link.ts", "../src/tools/list-project-links.ts", "../src/tools/list-scratch-notes.ts", "../src/tools/resolve-scratch-note.ts", "../src/tools/heartbeat-work-item.ts", "../src/tools/watch-work-item.ts", "../src/tools/add-work-item-image.ts", "../src/tools/list-work-item-images.ts", "../src/tools/add-work-item-comment.ts", "../src/tools/list-work-item-comments.ts", "../src/tools/list-validations.ts", "../src/tools/record-validation.ts", "../src/tools/mark-system-changed.ts", "../src/tools/create-system.ts", "../src/tools/create-validation-task.ts", "../src/tools/add-system-to-task.ts", "../src/tools/add-validation-dependency.ts", "../src/tools/list-labels.ts", "../src/tools/create-label.ts", "../src/tools/add-label-to-work-item.ts", "../src/tools/remove-label-from-work-item.ts", "../src/tools/list-milestones.ts", "../src/tools/create-milestone.ts", "../src/tools/add-item-to-milestone.ts", "../src/tools/remove-item-from-milestone.ts"],
4
+ "sourcesContent": ["#!/usr/bin/env node\n// MCP stdio transport reserves stdout for JSON-RPC frames. Any library that\n// writes to stdout (e.g. the Convex client's `[CONVEX A(uth)]` info logs)\n// corrupts the stream. Redirect console.* to stderr before anything else loads.\nfor (const m of [\"log\", \"info\", \"warn\", \"debug\"] as const) {\n console[m] = (...args: unknown[]) => console.error(...args);\n}\n\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { createServer } from \"./server.js\";\n\nasync function main() {\n const server = createServer();\n const transport = new StdioServerTransport();\n await server.connect(transport);\n // Server runs until stdin closes; nothing else to do here.\n}\n\nmain().catch((err) => {\n console.error(\"nimara-mcp: fatal error\", err);\n process.exit(1);\n});\n", "import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport pkg from \"../package.json\" with { type: \"json\" };\nimport { INSTRUCTIONS } from \"./instructions.js\";\nimport { setClientInfo } from \"./convex.js\";\nimport { registerListOrgs } from \"./tools/list-orgs.js\";\nimport { registerListProjects } from \"./tools/list-projects.js\";\nimport { registerListWorkItems } from \"./tools/list-work-items.js\";\nimport { registerGetWorkItems } from \"./tools/get-work-items.js\";\nimport { registerSearchWorkItems } from \"./tools/search-work-items.js\";\nimport { registerListAiReviewQueue } from \"./tools/list-ai-review-queue.js\";\nimport { registerGetActiveBlock } from \"./tools/get-active-block.js\";\nimport { registerCreateWorkItem } from \"./tools/create-work-item.js\";\nimport { registerCreateProject } from \"./tools/create-project.js\";\nimport { registerUpdateWorkItem } from \"./tools/update-work-item.js\";\nimport { registerMoveWorkItem } from \"./tools/move-work-item.js\";\nimport { registerCreateDocument } from \"./tools/create-document.js\";\nimport { registerUpdateDocument } from \"./tools/update-document.js\";\nimport { registerListDocuments } from \"./tools/list-documents.js\";\nimport { registerCreateProjectLink } from \"./tools/create-project-link.js\";\nimport { registerListProjectLinks } from \"./tools/list-project-links.js\";\nimport { registerListScratchNotes } from \"./tools/list-scratch-notes.js\";\nimport { registerResolveScratchNote } from \"./tools/resolve-scratch-note.js\";\nimport { registerHeartbeatWorkItem } from \"./tools/heartbeat-work-item.js\";\nimport { registerWatchWorkItem } from \"./tools/watch-work-item.js\";\nimport { registerAddWorkItemImage } from \"./tools/add-work-item-image.js\";\nimport { registerListWorkItemImages } from \"./tools/list-work-item-images.js\";\nimport { registerAddWorkItemComment } from \"./tools/add-work-item-comment.js\";\nimport { registerListWorkItemComments } from \"./tools/list-work-item-comments.js\";\nimport { registerListValidations } from \"./tools/list-validations.js\";\nimport { registerRecordValidation } from \"./tools/record-validation.js\";\nimport { registerMarkSystemChanged } from \"./tools/mark-system-changed.js\";\nimport { registerCreateSystem } from \"./tools/create-system.js\";\nimport { registerCreateValidationTask } from \"./tools/create-validation-task.js\";\nimport { registerAddSystemToTask } from \"./tools/add-system-to-task.js\";\nimport { registerAddValidationDependency } from \"./tools/add-validation-dependency.js\";\nimport { registerListLabels } from \"./tools/list-labels.js\";\nimport { registerCreateLabel } from \"./tools/create-label.js\";\nimport { registerAddLabelToWorkItem } from \"./tools/add-label-to-work-item.js\";\nimport { registerRemoveLabelFromWorkItem } from \"./tools/remove-label-from-work-item.js\";\nimport { registerListMilestones } from \"./tools/list-milestones.js\";\nimport { registerCreateMilestone } from \"./tools/create-milestone.js\";\nimport { registerAddItemToMilestone } from \"./tools/add-item-to-milestone.js\";\nimport { registerRemoveItemFromMilestone } from \"./tools/remove-item-from-milestone.js\";\n\nexport function createServer(): McpServer {\n const server = new McpServer(\n {\n name: \"nimara\",\n version: pkg.version,\n },\n // Sent at connect time, before any tool is read (NIM-T189).\n { instructions: INSTRUCTIONS },\n );\n // The client's name arrives with initialize; keep it for every later write.\n server.server.oninitialized = () => setClientInfo(server.server.getClientVersion());\n\n registerListOrgs(server);\n registerListProjects(server);\n registerListWorkItems(server);\n registerGetWorkItems(server);\n registerSearchWorkItems(server);\n registerListAiReviewQueue(server);\n registerGetActiveBlock(server);\n registerCreateProject(server);\n registerCreateWorkItem(server);\n registerUpdateWorkItem(server);\n registerMoveWorkItem(server);\n registerCreateDocument(server);\n registerUpdateDocument(server);\n registerListDocuments(server);\n registerCreateProjectLink(server);\n registerListProjectLinks(server);\n registerListScratchNotes(server);\n registerResolveScratchNote(server);\n registerHeartbeatWorkItem(server);\n registerWatchWorkItem(server);\n registerAddWorkItemImage(server);\n registerListWorkItemImages(server);\n registerAddWorkItemComment(server);\n registerListWorkItemComments(server);\n\n // Validation / test-dependency framework\n registerListValidations(server);\n registerRecordValidation(server);\n registerMarkSystemChanged(server);\n registerCreateSystem(server);\n registerCreateValidationTask(server);\n registerAddSystemToTask(server);\n registerAddValidationDependency(server);\n\n // Labels & milestones\n registerListLabels(server);\n registerCreateLabel(server);\n registerAddLabelToWorkItem(server);\n registerRemoveLabelFromWorkItem(server);\n registerListMilestones(server);\n registerCreateMilestone(server);\n registerAddItemToMilestone(server);\n registerRemoveItemFromMilestone(server);\n\n return server;\n}\n", "{\n \"name\": \"@nimara-app/mcp\",\n \"version\": \"0.6.0\",\n \"private\": false,\n \"mcpName\": \"io.github.langskip-studios/nimara\",\n \"description\": \"Nimara MCP server \u2014 AI tool integration for Claude, Codex, and others\",\n \"license\": \"MIT\",\n \"type\": \"module\",\n \"main\": \"dist/index.js\",\n \"bin\": {\n \"nimara-mcp\": \"dist/index.js\"\n },\n \"files\": [\n \"dist\",\n \"README.md\"\n ],\n \"keywords\": [\n \"mcp\",\n \"model-context-protocol\",\n \"nimara\",\n \"claude\",\n \"ai\",\n \"convex\"\n ],\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/Langskip-Studios/Nimara.git\",\n \"directory\": \"packages/mcp\"\n },\n \"homepage\": \"https://github.com/Langskip-Studios/Nimara/tree/master/packages/mcp#readme\",\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"scripts\": {\n \"build\": \"node build.mjs\",\n \"dev\": \"node build.mjs\",\n \"start\": \"node dist/index.js\",\n \"typecheck\": \"tsc --noEmit\",\n \"prepublishOnly\": \"npm run typecheck && npm run build\"\n },\n \"dependencies\": {\n \"@modelcontextprotocol/sdk\": \"^1.0.0\",\n \"convex\": \"^1.18.0\",\n \"zod\": \"^3.23.0\"\n },\n \"devDependencies\": {\n \"@nimara/convex\": \"workspace:*\",\n \"@types/node\": \"^20.0.0\",\n \"esbuild\": \"^0.23.0\",\n \"typescript\": \"^5.0.0\"\n },\n \"engines\": {\n \"node\": \">=20\"\n }\n}\n", "/**\n * What every MCP client is told at connect time, before any tool is read.\n *\n * The rules that span tools \u2014 titles, statuses, the lease, mentions \u2014 each\n * live in one tool's parameter description, so a model that never loads that\n * tool never hears them. This is the map; the tool descriptions stay the\n * detailed reference. Kept short on purpose: it sits in the model's context\n * for the whole session.\n */\nexport const INSTRUCTIONS = `Nimara is the team's work tracker. Work items have a type (epic > feature > task > subtask), a status from the project's own workflow, and a displayId like NIM-T42 that people read and type.\n\nStart with list_orgs \u2192 list_projects \u2192 get_active_block (the committed work; position 0 is next) and list_ai_review_queue (what a person has asked an agent to do; read \\`answer\\` first). Use get_work_items / search_work_items for items you already know of; list_work_items only to survey.\n\nTitles are plain language a teammate understands at a glance: what is wrong or what changes for a person, not the file, function or mechanism. No em dashes, no \"Area: thing, thing\" shapes. Descriptions carry the why, acceptance criteria and file paths; a spec, design or long report goes in a document (create_document) linked from the item.\n\nA status must be one of the project's \\`statuses\\` from list_projects, spelled exactly; never invent one. Labels come from list_labels; do not invent those either.\n\nWhen you pick up an item: update_work_item { status: <in-progress status>, agentWorking: true, model: <the model you run as> }. That lights its row for 15 minutes and lets the app say whose agent, and which, is on it; any write or read of the item renews it, and on a long stretch with no Nimara calls, heartbeat_work_item every few minutes keeps it lit. Post a comment at real milestones. If you stop early, agentWorking: false. Moving to the last status clears it.\n\nMention a person in a comment as [@Name](user:<userId>) and they are notified. Append agent research to a description under the exact heading \"## Research (auto)\", never editing the human text above it. When you open a PR, put the displayId in its title.`;\n", "import { ConvexHttpClient } from \"convex/browser\";\n\nlet cachedClient: ConvexHttpClient | null = null;\n\nexport function getConvexClient(): ConvexHttpClient {\n if (cachedClient) return cachedClient;\n\n const url = process.env.NIMARA_CONVEX_URL;\n if (!url) {\n throw new Error(\n \"NIMARA_CONVEX_URL is not set. Add it to your MCP client config (e.g. Claude Desktop's mcpServers env block).\"\n );\n }\n\n cachedClient = new ConvexHttpClient(url);\n return cachedClient;\n}\n\nexport function getToken(): string {\n const token = process.env.NIMARA_TOKEN;\n if (!token) {\n throw new Error(\n \"NIMARA_TOKEN is not set. Generate a personal access token from Nimara \u2192 Settings \u2192 Personal Access Tokens, then add it to your MCP client config.\"\n );\n }\n return token;\n}\n\n/**\n * Who this server is talking to. Every MCP client names itself in the\n * `initialize` request (claude-code, codex, pi, \u2026); the server keeps it so\n * writes can say which agent made them, and the app can show \"Jordan's\n * Claude Code agent is working on this\" (NIM-F43). The model is not in the\n * protocol: an agent may pass it on the tools that take `model`.\n */\nlet clientInfo: { name: string; version?: string } | undefined;\n\nexport function setClientInfo(info: { name: string; version?: string } | undefined): void {\n clientInfo = info;\n}\n\n/** The `agent` argument for a Convex write, or undefined before initialize. */\nexport function agentArg(model?: string): { client: string; model?: string } | undefined {\n if (!clientInfo) return model ? { client: \"unknown\", model } : undefined;\n const client = clientInfo.version ? `${clientInfo.name} ${clientInfo.version}` : clientInfo.name;\n return model ? { client, model } : { client };\n}\n", "/* eslint-disable */\n/**\n * Generated `api` utility.\n *\n * THIS CODE IS AUTOMATICALLY GENERATED.\n *\n * To regenerate, run `npx convex dev`.\n * @module\n */\n\nimport { anyApi, componentsGeneric } from \"convex/server\";\n\n/**\n * A utility for referencing Convex functions in your app's API.\n *\n * Usage:\n * ```js\n * const myFunctionReference = api.myModule.myFunction;\n * ```\n */\nexport const api = anyApi;\nexport const internal = anyApi;\nexport const components = componentsGeneric();\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerListOrgs(server: McpServer): void {\n server.registerTool(\n \"list_orgs\",\n {\n description:\n \"List all organizations (and the personal workspace) the authenticated user belongs to. Use this first to discover org IDs needed by other tools.\",\n inputSchema: {},\n annotations: {\n readOnlyHint: true,\n openWorldHint: false,\n },\n },\n\n async () => {\n const client = getConvexClient();\n const orgs = await client.action(api.mcp.listOrgs, { token: getToken() });\n return {\n content: [{ type: \"text\", text: JSON.stringify(orgs, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerListProjects(server: McpServer): void {\n server.registerTool(\n \"list_projects\",\n {\n description:\n \"List projects in a given organization. Call list_orgs first to find \" +\n \"the orgId. Each project includes `statuses` \u2014 its workflow in board \" +\n \"order. Read that before setting a status on any item: those names are \" +\n \"the only accepted values, and anything else is rejected.\",\n inputSchema: { orgId: z.string().describe(\"orgId from list_orgs\") },\n annotations: {\n readOnlyHint: true,\n openWorldHint: false,\n },\n },\n\n async ({ orgId }) => {\n const client = getConvexClient();\n const projects = await client.action(api.mcp.listProjects, {\n token: getToken(),\n orgId,\n });\n return {\n content: [{ type: \"text\", text: JSON.stringify(projects, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerListWorkItems(server: McpServer): void {\n server.registerTool(\n \"list_work_items\",\n {\n // The description is the only place a model learns paging exists, so it\n // states the shape of the response and what to do when hasMore is true.\n description:\n \"List non-archived work items in a project, oldest-created first. Returns \" +\n \"{ items, nextCursor, hasMore }. Long descriptions are previewed \u2014 an \" +\n \"item with descriptionTruncated: true has more text, readable via \" +\n \"fullDescriptions. When hasMore is true, call again with cursor set to \" +\n \"nextCursor to get the next page \u2014 the FIRST page is the OLDEST items, so \" +\n \"recently created ones are on the LAST page and you have not seen the \" +\n \"project until hasMore is false. Narrow with status/type/parentId/\" +\n \"needsReview rather than paging and filtering yourself. If you already \" +\n \"know which items you want, use get_work_items instead \u2014 it takes \" +\n \"displayIds like NIM-T75 and costs a fraction of a list. \" +\n \"Call list_projects first for the projectId.\",\n inputSchema: {\n projectId: z.string().describe(\"projectId from list_projects\"),\n status: z\n .union([z.string(), z.array(z.string())])\n .optional()\n .describe(\n \"Only items in these statuses. Names come from the project's \" +\n \"statusOrder (e.g. 'In Progress'). One name or a list.\",\n ),\n type: z\n .union([\n z.enum([\"epic\", \"feature\", \"task\", \"subtask\"]),\n z.array(z.enum([\"epic\", \"feature\", \"task\", \"subtask\"])),\n ])\n .optional()\n .describe(\"Only items of these types. One type or a list.\"),\n parentId: z\n .string()\n .optional()\n .describe(\n \"Only direct children of this workItemId. One level, not the whole subtree.\",\n ),\n needsReview: z\n .boolean()\n .optional()\n .describe(\n \"true returns only items flagged needsReview; false only unflagged ones. \" +\n \"Omit for both.\",\n ),\n limit: z\n .number()\n .int()\n .min(1)\n .max(200)\n .optional()\n .describe(\"Items per page (default 50, max 200).\"),\n cursor: z\n .number()\n .optional()\n .describe(\n \"nextCursor from the previous page. Omit for the first page.\",\n ),\n fullDescriptions: z\n .boolean()\n .optional()\n .describe(\n \"Return descriptions in full instead of previewed. Costly on large \" +\n \"projects \u2014 prefer paging, or read one item at a time.\",\n ),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: false,\n },\n },\n async ({\n projectId,\n limit,\n cursor,\n fullDescriptions,\n status,\n type,\n parentId,\n needsReview,\n }) => {\n const page = await getConvexClient().action(api.mcp.listWorkItems, {\n token: getToken(),\n projectId,\n limit,\n cursor,\n fullDescriptions,\n // Accepting a bare string as well as a list is what keeps a model from\n // failing validation on the overwhelmingly common single-value case.\n status:\n status === undefined\n ? undefined\n : Array.isArray(status)\n ? status\n : [status],\n type:\n type === undefined ? undefined : Array.isArray(type) ? type : [type],\n parentId,\n needsReview,\n });\n return {\n content: [{ type: \"text\", text: JSON.stringify(page, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerGetWorkItems(server: McpServer): void {\n server.registerTool(\n \"get_work_items\",\n {\n // Written to be chosen *over* list_work_items whenever the caller already\n // knows which items it wants \u2014 that is the whole point of the tool, and\n // the description is the only place a model learns it.\n description:\n \"Read specific work items by id \u2014 the cheap way to re-read items you \" +\n \"already know about. Prefer this over list_work_items whenever you have \" +\n \"a displayId (e.g. NIM-T75) or a workItemId: listing a project returns \" +\n \"every item and its description, which is orders of magnitude more data. \" +\n \"Accepts up to 50 ids per call and always returns descriptions in full. \" +\n \"Returns { items, notFound }; ids in notFound either do not exist or are \" +\n \"not readable by this token. displayIds require projectId (they are \" +\n \"unique per project, not globally); workItemIds do not.\",\n inputSchema: {\n displayIds: z\n .array(z.string())\n .optional()\n .describe(\n \"Human-facing ids like ['NIM-T75', 'NIM-F27']. Case-insensitive. \" +\n \"Requires projectId.\",\n ),\n workItemIds: z\n .array(z.string())\n .optional()\n .describe(\n \"Raw workItemIds, as returned by create_work_item or list_work_items.\",\n ),\n projectId: z\n .string()\n .optional()\n .describe(\n \"projectId from list_projects. Required only when passing displayIds.\",\n ),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: false,\n },\n },\n async ({ displayIds, workItemIds, projectId }) => {\n const result = await getConvexClient().action(api.mcp.getWorkItems, {\n token: getToken(),\n displayIds,\n workItemIds,\n projectId,\n });\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerSearchWorkItems(server: McpServer): void {\n server.registerTool(\n \"search_work_items\",\n {\n // The point of this description is to stop a model reaching for\n // list_work_items when it is looking for something by name. Listing a\n // project to find one item is the expensive mistake this tool exists to\n // prevent.\n description:\n \"Find work items in a project by title. Use this to answer 'does an \" +\n \"item for X already exist?' \u2014 listing the whole project and filtering \" +\n \"yourself is far more expensive and, because the first page is the \" +\n \"OLDEST items, easy to get wrong. Matches TITLES only, not \" +\n \"descriptions. Returns { items, query } with descriptions previewed; \" +\n \"once you know which item you want, get_work_items returns it in full. \" +\n \"Capped at 25 results \u2014 narrow the query rather than paging. \" +\n \"Call list_projects first for the projectId.\",\n inputSchema: {\n projectId: z.string().describe(\"projectId from list_projects\"),\n q: z\n .string()\n .min(1)\n .describe(\n \"Words to match against item titles, e.g. 'mobile modal' or \" +\n \"'shortcut'. Matching is full-text, so word order does not matter.\",\n ),\n limit: z\n .number()\n .int()\n .min(1)\n .max(25)\n .optional()\n .describe(\"Maximum results (default and maximum 25).\"),\n },\n annotations: { readOnlyHint: true },\n },\n async ({ projectId, q, limit }) => {\n const result = await getConvexClient().action(api.mcp.searchWorkItems, {\n token: getToken(),\n projectId,\n q,\n limit,\n });\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerListAiReviewQueue(server: McpServer): void {\n server.registerTool(\n \"list_ai_review_queue\",\n {\n description:\n \"List work items in a project that a human has flagged for AI review \" +\n \"(aiReviewRequested). Descriptions come back in full here, since \" +\n \"enrichment needs the whole text. Each item also carries recentComments \" +\n \"(the last few, oldest first) and, when a person has written one, \" +\n \"`answer`: the newest human comment. READ `answer` FIRST. When you \" +\n \"flagged an item with a question and it is back in this queue, `answer` \" +\n \"is the person's reply to that question; act on it rather than asking \" +\n \"again. Returns { items, nextCursor, hasMore } \u2014 when hasMore is true, \" +\n \"call again with cursor set to nextCursor. Process each item, then clear \" +\n \"its flag by calling update_work_item with aiReviewRequested: false. \" +\n \"Call list_projects first to find the projectId.\",\n inputSchema: {\n projectId: z.string().describe(\"projectId from list_projects\"),\n limit: z\n .number()\n .int()\n .min(1)\n .max(200)\n .optional()\n .describe(\"Items per page (default 50, max 200).\"),\n cursor: z\n .number()\n .optional()\n .describe(\n \"nextCursor from the previous page. Omit for the first page.\",\n ),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: false,\n },\n },\n async ({ projectId, limit, cursor }) => {\n const page = await getConvexClient().action(api.mcp.listAiReviewQueue, {\n token: getToken(),\n projectId,\n limit,\n cursor,\n });\n return {\n content: [{ type: \"text\", text: JSON.stringify(page, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerGetActiveBlock(server: McpServer): void {\n server.registerTool(\n \"get_active_block\",\n {\n description:\n \"The project's ACTIVE BLOCK: the small, ordered set of work a person has \" +\n \"committed to right now. Call this BEFORE list_work_items when deciding what \" +\n \"to work on \u2014 position 0 is the next thing to do, and the wider backlog is \" +\n \"not on the table until the block is empty. Each item carries a lane: \" +\n \"'person' means a human owes it (flagged for review, or parked in a Review \" +\n \"status) and you should not touch it; 'agent' means a human asked an agent \" +\n \"to act on it, so it is yours first, and it carries recentComments and \" +\n \"`answer` (the newest human comment: read it before anything else); \" +\n \"'open' is uncommitted-to-anyone work in \" +\n \"priority order; 'done' is finished. Returns null when the project has no \" +\n \"active block, in which case fall back to list_work_items. Descriptions are \" +\n \"previewed; use get_work_items for the full text of an item you pick up. \" +\n \"Call list_projects first for the projectId.\",\n inputSchema: {\n projectId: z.string().describe(\"projectId from list_projects\"),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: false,\n },\n },\n async ({ projectId }) => {\n const block = await getConvexClient().action(api.mcp.getActiveBlock, {\n token: getToken(),\n projectId,\n });\n return {\n content: [{ type: \"text\", text: JSON.stringify(block, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\nimport { TITLE_GUIDANCE } from \"./titleGuidance.js\";\nimport { STATUS_GUIDANCE } from \"./statusGuidance.js\";\nimport { DESCRIPTION_GUIDANCE, DESCRIPTION_MAX } from \"./descriptionGuidance.js\";\n\nexport function registerCreateWorkItem(server: McpServer): void {\n server.registerTool(\n \"create_work_item\",\n {\n description:\n \"Create a new work item in a project. Hierarchy rules: epics live at the root; features go under epics; tasks go under epics or features (or root); subtasks must go under a task. Returns the new workItemId and its display ID (e.g. NIM-42).\",\n inputSchema: {\n projectId: z.string().describe(\"projectId from list_projects\"),\n type: z\n .enum([\"epic\", \"feature\", \"task\", \"subtask\"])\n .describe(\"Item type \u2014 drives hierarchy validation\"),\n title: z.string().min(1).describe(TITLE_GUIDANCE),\n description: z.string().max(DESCRIPTION_MAX).optional().describe(DESCRIPTION_GUIDANCE),\n parentId: z\n .string()\n .optional()\n .describe(\n \"workItemId of the parent. Required for subtask, optional otherwise.\",\n ),\n status: z\n .string()\n .optional()\n .describe(\n STATUS_GUIDANCE,\n ),\n priority: z\n .enum([\"p0\", \"p1\", \"p2\", \"p3\"])\n .optional()\n .describe(\"p0 highest, p3 lowest. Defaults to p2.\"),\n },\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: false,\n },\n },\n\n async (args) => {\n const client = getConvexClient();\n const result = await client.action(api.mcp.createWorkItem, {\n token: getToken(),\n ...args,\n });\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n },\n );\n}\n", "/**\n * What a work-item title should read like, stated once.\n *\n * This exists because \"Short, descriptive title\" \u2014 the previous guidance on\n * `create_work_item` \u2014 is satisfied by \"Fix hasChildren computation in\n * list.tsx\". That is short and it does describe something, and it is unreadable\n * to anyone who has not just been in that file. Titles are what a board shows;\n * a board full of symbol names cannot be scanned.\n *\n * The em-dash and verbosity rules come from NIM-T117, which Jordan filed\n * before this and which asked for exactly that: \"Remove the em dash and\n * other verbose title that make it hard to read.\"\n *\n * Shared by `create_work_item` and `update_work_item` so the rule cannot hold\n * on one path and not the other \u2014 retitling is the same act as titling, and\n * `update_work_item` previously carried no guidance at all.\n */\nexport const TITLE_GUIDANCE =\n \"A title a teammate can understand at a glance, without opening the item or \" +\n \"knowing the codebase. Say what is wrong or what changes FOR A PERSON, in \" +\n \"plain words \u2014 not the mechanism, the file, or the symbol. \" +\n 'Good: \"Sorted list shows an expand arrow that does nothing\". ' +\n 'Bad: \"Fix hasChildren computation in list.tsx\". ' +\n 'Good: \"Long titles wrap to three lines and are hard to read\". ' +\n 'Bad: \"Adjust COLUMNS.title min-width constant\". ' +\n \"Prefer ordinary words over internal abbreviations, and only name a file, \" +\n \"function or identifier when it genuinely is the clearest way to say it \" +\n \"(a tool or endpoint the user calls by name, for instance). No ticket \" +\n \"prefixes or status markers \u2014 the board renders those already. Root cause, \" +\n \"file paths, and reproduction steps belong in the description, which has \" +\n \"room for them. \" +\n \"Keep it to one plain clause. Do NOT use an em dash, and do not use the \" +\n '\"Area: thing, other thing\" shape \u2014 both are ways of stapling a second ' +\n \"title on and they are what makes these hard to read. \" +\n 'Bad: \"Gantt: tighten row density, match app typography, stop the chart ' +\n 'falling short of its container\". ' +\n 'Good: \"Gantt chart looks nothing like the rest of the app\". ' +\n \"If the title needs a comma-spliced list to be accurate, that is a sign the \" +\n \"item is really several items, not a sign it needs a longer title.\";\n", "/**\n * How to choose a status, stated once.\n *\n * The rule the tools already stated \u2014 \"a status name from the project's\n * statusOrder\" \u2014 referred to data no tool returned. An agent could not read a\n * project's workflow, so it guessed a plausible-sounding name, and the guess\n * was frequently \"In Review\" on boards whose workflow only ever had \"Review\".\n * `list_projects` now returns `statuses`, which is what makes this instruction\n * followable rather than aspirational.\n *\n * The second half matters as much as the first. A status is POSITIONAL \u2014 it is\n * the board column \u2014 so inventing one is not a labelling choice, it reshapes\n * the board and every status chart that aggregates across projects. Anything\n * that describes an item without saying where it sits in the flow is a label:\n * `list_labels`, `create_label` and `add_label_to_work_item` exist for exactly\n * that, and cost nothing to add. This is NIM-T49's decision, held to.\n *\n * Shared by `create_work_item` and `update_work_item`. `update_work_item.status`\n * previously carried no guidance at all, which is the path most likely to move\n * an item to an invented status.\n */\nexport const STATUS_GUIDANCE =\n \"Must be one of the names in the project's `statuses`, returned by \" +\n \"list_projects. Read it rather than guessing \u2014 a status is the board \" +\n \"column, so a name the workflow does not have is rejected, and before that \" +\n \"check existed such items rendered in the first column while claiming \" +\n \"otherwise. Match the existing name exactly, including its wording: if the \" +\n \"workflow says \\\"Review\\\", do not write \\\"In Review\\\". \" +\n \"Do NOT invent a status to capture something about an item. Statuses are \" +\n \"shared across the whole project and aggregated on the dashboard, so each \" +\n \"new one is a permanent extra band there. Anything that describes an item \" +\n \"rather than locating it in the flow belongs in a LABEL \u2014 see create_label \" +\n \"and add_label_to_work_item. Defaults to the first status when omitted.\";\n", "/**\n * The two sizes a work item description is measured against. Kept free of\n * Convex imports so the web app and the MCP package can share the numbers.\n *\n * PREVIEW is what the row carries so lists never join the body\n * (lib/workItemBody.ts). MAX is a sanity cap, not a product decision: no\n * task written by hand comes near it, but an agent pasting a log or a whole\n * research report into a description would \u2014 and that belongs in a document.\n * Descriptions averaged 14 KB when the cap was chosen; 32 KB is roughly\n * 5,000 words, eight pages.\n */\nexport const DESCRIPTION_PREVIEW_CHARS = 500;\nexport const DESCRIPTION_MAX_CHARS = 32_000;\n\n/** Where a description's length stands, for an error or a counter. */\nexport const DESCRIPTION_TOO_LONG =\n `A description can be at most ${DESCRIPTION_MAX_CHARS.toLocaleString(\"en-US\")} characters. ` +\n \"Put specs, research and long reports in a document and link it to the item.\";\n", "import { DESCRIPTION_MAX_CHARS } from \"@nimara/convex/convex/lib/descriptionLimits.js\";\n\n/**\n * What a description is for, and how big it may be, stated once and shared\n * by `create_work_item` and `update_work_item` the way TITLE_GUIDANCE is.\n *\n * The cap is enforced server-side in writeDescription; the zod max here\n * only means an agent hears about it before the round-trip. The guidance is\n * the real lever: descriptions averaged 14 KB because agents used them as\n * the place to put everything, and the row split (lib/workItemBody.ts) made\n * that cheap but not right \u2014 a document is what other items can link to.\n */\nexport const DESCRIPTION_MAX = DESCRIPTION_MAX_CHARS;\n\nexport const DESCRIPTION_GUIDANCE =\n \"Markdown. The what and the why: the problem, acceptance criteria, \" +\n \"reproduction steps, file paths, root cause. Keep it to what someone \" +\n \"picking the item up needs. A spec, a design, research, or a long report \" +\n \"goes in a document (create_document) linked from here, not inline. \" +\n `At most ${DESCRIPTION_MAX_CHARS.toLocaleString(\"en-US\")} characters.`;\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerCreateProject(server: McpServer): void {\n server.registerTool(\n \"create_project\",\n {\n description:\n \"Create a new project in an org. Prefix must be unique within the org and is uppercased (e.g. 'NIM' yields work items NIM-1, NIM-2\u2026). Caller becomes the project admin. Returns the new projectId.\",\n inputSchema: {\n orgId: z.string().describe(\"orgId from list_orgs\"),\n name: z.string().min(1).describe(\"Project name\"),\n prefix: z\n .string()\n .min(1)\n .max(8)\n .describe(\n \"Short uppercase prefix for work item IDs (e.g. 'NIM'). Unique per org.\",\n ),\n description: z\n .string()\n .optional()\n .describe(\"Optional markdown description\"),\n isPrivate: z\n .boolean()\n .optional()\n .describe(\n \"If true, only explicitly added members see it. Defaults to false.\",\n ),\n workflowTemplate: z\n .enum([\"default\", \"simple\", \"kanban\", \"bug\"])\n .optional()\n .describe(\n \"Status workflow. Defaults to 'default' (Backlog/Todo/In Progress/Review/Done).\",\n ),\n },\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: false,\n },\n },\n\n async (args) => {\n const client = getConvexClient();\n const result = await client.action(api.mcp.createProject, {\n token: getToken(),\n ...args,\n });\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { agentArg, getConvexClient, getToken } from \"../convex.js\";\nimport { TITLE_GUIDANCE } from \"./titleGuidance.js\";\nimport { STATUS_GUIDANCE } from \"./statusGuidance.js\";\nimport { DESCRIPTION_GUIDANCE, DESCRIPTION_MAX } from \"./descriptionGuidance.js\";\nimport { RESEARCH_FORMAT } from \"./researchFormat.js\";\n\nexport function registerUpdateWorkItem(server: McpServer): void {\n server.registerTool(\n \"update_work_item\",\n {\n description:\n \"Update an existing work item: title, description, status, priority, parent, or review flags. Any update also stamps the item as AI-touched.\",\n inputSchema: {\n workItemId: z.string().describe(\"workItemId from list_work_items\"),\n title: z.string().min(1).optional().describe(TITLE_GUIDANCE),\n description: z\n .string()\n .max(DESCRIPTION_MAX)\n .optional()\n .describe(\n \"Full markdown body, replacing what is there. \" +\n DESCRIPTION_GUIDANCE +\n \" \" +\n RESEARCH_FORMAT,\n ),\n status: z.string().optional().describe(STATUS_GUIDANCE),\n priority: z.enum([\"p0\", \"p1\", \"p2\", \"p3\"]).optional(),\n parentId: z\n .string()\n .nullable()\n .optional()\n .describe(\"New parent workItemId, null to move to root.\"),\n needsReview: z\n .boolean()\n .optional()\n .describe(\n \"Flag the item for manual human review \u2014 set true when your enrichment was thin or uncertain.\",\n ),\n reviewReason: z\n .string()\n .optional()\n .describe(\n \"Short reason the item needs manual review (shown to the human).\",\n ),\n aiReviewRequested: z\n .boolean()\n .optional()\n .describe(\n \"The human\u2192AI review flag. Set false to clear it after you have reviewed/enriched an item from list_ai_review_queue.\",\n ),\n agentWorking: z\n .boolean()\n .optional()\n .describe(\n \"Set true when you start working on this item: the app lights its row so the person can see it is in flight. It is a 15-minute lease renewed by any later MCP write on the item (updates, comments), by reading it (get_work_items, list_work_item_comments), or by heartbeat_work_item \u2014 call that every few minutes on a long task with no other Nimara calls, or the row goes quiet while you are still at it. Set false when you stop without finishing; moving the item to the last status clears it for you.\",\n ),\n model: z\n .string()\n .optional()\n .describe(\"With agentWorking: the model you are running as, e.g. claude-opus-5, so the app can say which agent is on this. Your harness is reported automatically.\"),\n },\n annotations: {\n readOnlyHint: false,\n destructiveHint: true,\n idempotentHint: true,\n openWorldHint: false,\n },\n },\n\n async ({ model, ...args }) => {\n const result = await getConvexClient().action(api.mcp.updateWorkItem, {\n token: getToken(),\n ...args,\n agent: agentArg(model),\n });\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n },\n );\n}\n", "/**\n * The shape of the automated research block an enrichment agent appends to a\n * work item's description.\n *\n * Two reasons this is stated here rather than left to each agent's own taste.\n *\n * The web app parses this block out of the description and renders it in its\n * own tab on the item (NIM-T125). The anchor heading is therefore a contract,\n * not a style choice: change its wording and the tab stops appearing, with the\n * text still sitting in the description and nothing failing loudly.\n *\n * And the existing blocks are decorated with emoji section markers \u2014 \uD83D\uDD0E, \uD83D\uDD17,\n * \uD83E\uDDED, \uD83C\uDF9A. They read as noise in a panel that is already labelled \"Research\",\n * they carry no information the heading does not, and they are the first thing\n * Jordan asked to remove. The parser accepts the old emoji heading so the 20\n * items already enriched keep working; nothing new should write one.\n *\n * Deliberately NOT permitted: raw HTML. The app renders this with\n * `react-markdown` and no `rehype-raw`, so HTML is stripped rather than shown \u2014\n * and turning that on would render agent-authored markup whose inputs include\n * untrusted work-item text. Mermaid fences cover the diagram case without\n * opening that door.\n */\nexport const RESEARCH_FORMAT = `When appending automated research to a description, use EXACTLY this format, \\\nafter the human-written text:\n\n---\n## Research (auto)\n\n### Findings\n- One bullet per verified fact, each naming what you checked.\n\n### Dependencies\n- Items this blocks or is blocked by, by displayId. Omit the section if none.\n\n### Duplicates\n- Existing items covering the same work, by displayId. Omit if none.\n\n### Suggested priority\nOne line. Say \"No change\" when it is already right.\n\nRules:\n- The \"## Research (auto)\" heading is EXACT and is what the app keys on to show \\\nthis in its own tab. Do not reword it, renumber its level, or translate it.\n- NO EMOJI anywhere in the block, in headings or in bullets. Older items carry \\\nemoji headings; do not copy them.\n- Omit a section rather than writing \"None found\" in it. An empty section is \\\nnoise the reader still has to read.\n- Never edit or delete the human-written text above the rule. Append only.\n- Markdown only. GFM tables are supported and are the right choice for \\\ncomparisons. Raw HTML is NOT rendered by the app and must not be used.\n- For a workflow, sequence or state machine, use a \\\\\\`\\\\\\`\\\\\\`mermaid fenced block. \\\nThat is the supported way to draw one.\n- Say what you verified and how. \"Confirmed X still returns Y (file:line)\" is \\\nworth more than a conclusion with no trail.`;\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerMoveWorkItem(server: McpServer): void {\n server.registerTool(\n \"move_work_item\",\n {\n // Everything a model needs to predict the damage has to be stated here \u2014\n // the description is the only channel it has. The consequences that are\n // NOT obvious from the name are the ones worth the tokens: the display ID\n // changes, and labels/milestones do not survive.\n description:\n \"Move a work item to a different project, taking its whole subtree \" +\n \"with it \u2014 children and grandchildren move too, and the hierarchy is \" +\n \"preserved. Both projects must be in the same organization, and you \" +\n \"need write access to both. \" +\n \"Not reversible by calling this again: the item is renumbered in the \" +\n \"destination, so NIM-T44 might become SKA-T18 and the old ID stops \" +\n \"resolving. Labels and milestone assignments are dropped, because both \" +\n \"belong to the project being left; a status the destination doesn't \" +\n \"define falls back to its first status. The response reports every \" +\n \"old \u2192 new ID plus everything that was dropped or remapped. \" +\n \"Comments, images, attached documents, PR links and history all follow \" +\n \"the item. Call list_projects first for the target projectId.\",\n inputSchema: {\n workItemId: z\n .string()\n .describe(\"workItemId from list_work_items \u2014 the item to move.\"),\n targetProjectId: z\n .string()\n .describe(\n \"projectId from list_projects \u2014 the destination. Must be in the \" +\n \"same org as the item's current project.\",\n ),\n },\n annotations: {\n readOnlyHint: false,\n // Renumbering display IDs and deleting label/milestone links are\n // overwrites, not additions \u2014 this belongs with the tools a client\n // should prompt on rather than auto-approve.\n destructiveHint: true,\n // Calling it twice does not land in the same place: the second call\n // either errors as already-there or moves the item on again.\n idempotentHint: false,\n openWorldHint: false,\n },\n },\n async ({ workItemId, targetProjectId }) => {\n const result = await getConvexClient().action(\n api.mcp.moveWorkItemToProject,\n { token: getToken(), workItemId, targetProjectId },\n );\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerCreateDocument(server: McpServer): void {\n server.registerTool(\n \"create_document\",\n {\n description:\n \"Create a markdown project document. Use type 'prd' for project docs or 'fd' for feature/work-item documents.\",\n inputSchema: {\n projectId: z.string().describe(\"projectId from list_projects\"),\n title: z.string().min(1),\n type: z\n .enum([\"prd\", \"fd\"])\n .describe(\n \"Document type. 'fd' is stored as the app's feature document type.\",\n ),\n workItemId: z\n .string()\n .optional()\n .describe(\"Required for fd documents; omitted for prd.\"),\n content: z\n .string()\n .optional()\n .describe(\"Optional initial markdown content.\"),\n },\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: false,\n },\n },\n\n async (args) => {\n const result = await getConvexClient().action(api.mcp.createDocument, {\n token: getToken(),\n ...args,\n });\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerUpdateDocument(server: McpServer): void {\n server.registerTool(\n \"update_document\",\n {\n description:\n \"Update an existing document's markdown content and/or title. Use this to fill in or revise a document created earlier (e.g. backfill content into an empty doc). documentId comes from list_documents. Provided content fully replaces the existing content.\",\n inputSchema: {\n documentId: z.string().describe(\"documentId from list_documents\"),\n content: z\n .string()\n .optional()\n .describe(\n \"New markdown content. Replaces the document's existing content.\",\n ),\n title: z.string().min(1).optional().describe(\"New title (optional).\"),\n },\n annotations: {\n readOnlyHint: false,\n destructiveHint: true,\n idempotentHint: true,\n openWorldHint: false,\n },\n },\n\n async (args) => {\n const result = await getConvexClient().action(api.mcp.updateDocument, {\n token: getToken(),\n ...args,\n });\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerListDocuments(server: McpServer): void {\n server.registerTool(\n \"list_documents\",\n {\n description:\n \"List PRD/FD markdown documents for a project, optionally filtered to one work item.\",\n inputSchema: {\n projectId: z.string().describe(\"projectId from list_projects\"),\n workItemId: z\n .string()\n .optional()\n .describe(\"Optional workItemId to list linked FD documents.\"),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: false,\n },\n },\n\n async (args) => {\n const result = await getConvexClient().action(api.mcp.listDocuments, {\n token: getToken(),\n ...args,\n });\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nconst projectLinkCategory = z.enum([\n \"api\",\n \"dashboard\",\n \"documentation\",\n \"repository\",\n \"service\",\n \"other\",\n]);\n\nexport function registerCreateProjectLink(server: McpServer): void {\n server.registerTool(\n \"create_project_link\",\n {\n description:\n \"Save a link on a project for resources like APIs, dashboards, documentation, repositories, or services.\",\n inputSchema: {\n projectId: z.string().describe(\"projectId from list_projects\"),\n title: z.string().min(1).max(120),\n url: z.string().url().describe(\"http(s) URL to save\"),\n description: z.string().max(500).optional(),\n category: projectLinkCategory.optional().describe(\"Defaults to other.\"),\n },\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: false,\n },\n },\n\n async (args) => {\n const result = await getConvexClient().action(api.mcp.createProjectLink, {\n token: getToken(),\n ...args,\n });\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerListProjectLinks(server: McpServer): void {\n server.registerTool(\n \"list_project_links\",\n {\n description:\n \"List saved links for a project, such as APIs, dashboards, docs, repositories, and services.\",\n inputSchema: {\n projectId: z.string().describe(\"projectId from list_projects\"),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: false,\n },\n },\n\n async ({ projectId }) => {\n const result = await getConvexClient().action(api.mcp.listProjectLinks, {\n token: getToken(),\n projectId,\n });\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerListScratchNotes(server: McpServer): void {\n server.registerTool(\n \"list_scratch_notes\",\n {\n description:\n \"The token owner's OPEN scratch notes: thoughts and ideas they captured \" +\n \"in the app with the `s` shortcut before deciding what to do with them. \" +\n \"Returns the notes that belong with this project (tagged with it, or \" +\n \"tagged with nothing), oldest first, each with noteId, body, projectId \" +\n \"and createdAt. These are raw: a note may be one line or a paragraph, \" +\n \"may describe one task or three, and may not be a task at all. Read \" +\n \"each, decide what it should become (usually one or more work items \" +\n \"via create_work_item, sometimes a comment on an existing item, \" +\n \"sometimes nothing), do that, then call resolve_scratch_note with the \" +\n \"noteId and the workItemId it became so the person sees where their \" +\n \"note went. Ask in a comment rather than guess when a note is too \" +\n \"thin to act on. Call list_projects first for the projectId.\",\n inputSchema: {\n projectId: z.string().describe(\"projectId from list_projects\"),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: false,\n },\n },\n async ({ projectId }) => {\n const notes = await getConvexClient().action(api.mcp.listScratchNotes, {\n token: getToken(),\n projectId,\n });\n return {\n content: [{ type: \"text\", text: JSON.stringify(notes, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerResolveScratchNote(server: McpServer): void {\n server.registerTool(\n \"resolve_scratch_note\",\n {\n description:\n \"Mark a scratch note as used, recording the work item it became. Call \" +\n \"this after acting on a note from list_scratch_notes: pass the noteId \" +\n \"and the workItemId you created or updated from it (omit workItemId \" +\n \"only when the note needed no item). The note leaves the person's open \" +\n \"list and shows where it went. Only the token owner's own notes.\",\n inputSchema: {\n noteId: z.string().describe(\"noteId from list_scratch_notes\"),\n workItemId: z\n .string()\n .optional()\n .describe(\"The workItemId the note became, from create_work_item or list_work_items.\"),\n },\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: false,\n },\n },\n async ({ noteId, workItemId }) => {\n const result = await getConvexClient().action(api.mcp.resolveScratchNote, {\n token: getToken(),\n noteId,\n workItemId,\n });\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { agentArg, getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerHeartbeatWorkItem(server: McpServer): void {\n server.registerTool(\n \"heartbeat_work_item\",\n {\n description:\n \"Say you are still working on an item. Renews (or starts) its 15-minute \" +\n \"\\\"agent working\\\" lease and does nothing else: no comment, no activity \" +\n \"event, no change to the item. The app lights the row while the lease is \" +\n \"live, so on a long task call this every few minutes or every handful of \" +\n \"tool calls \u2014 otherwise the row goes quiet while you are still at it. \" +\n \"Reads of the item (get_work_items, list_work_item_comments) also renew a \" +\n \"live lease, and any update or comment does; this is for the stretches \" +\n \"where you do none of those. Cheap and idempotent.\",\n inputSchema: {\n workItemId: z.string().describe(\"workItemId of the item you are working on\"),\n model: z\n .string()\n .optional()\n .describe(\"The model you are running as, e.g. claude-opus-5 or gpt-5, so the app can say which agent is on this. Your harness is reported automatically.\"),\n },\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: false,\n },\n },\n async ({ workItemId, model }) => {\n const result = await getConvexClient().action(api.mcp.heartbeatWorkItem, {\n token: getToken(),\n workItemId,\n agent: agentArg(model),\n });\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerWatchWorkItem(server: McpServer): void {\n server.registerTool(\n \"watch_work_item\",\n {\n description:\n \"Put the token owner on (or take them off) an item's watch list. A watcher \" +\n \"is notified when the item changes status, gets a comment, gets a reviewer, \" +\n \"is archived or moved \u2014 not on title or description edits. The item's \" +\n \"assignee and reviewer already hear about it. Use this when you start work \" +\n \"the person will want to follow, or when they ask to keep an eye on something.\",\n inputSchema: {\n workItemId: z.string().describe(\"workItemId of the item\"),\n watching: z.boolean().default(true).describe(\"true to watch, false to stop\"),\n },\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: false,\n },\n },\n async ({ workItemId, watching }) => {\n const result = await getConvexClient().action(api.mcp.watchWorkItem, {\n token: getToken(),\n workItemId,\n watching,\n });\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerAddWorkItemImage(server: McpServer): void {\n server.registerTool(\n \"add_work_item_image\",\n {\n description:\n \"Attach an externally hosted image URL to a work item. Use this when an MCP client has a screenshot, mockup, or generated image URL to preserve with the task.\",\n inputSchema: {\n workItemId: z.string().describe(\"workItemId from list_work_items\"),\n imageUrl: z\n .string()\n .url()\n .describe(\"Public or otherwise fetchable http(s) image URL\"),\n filename: z.string().optional().describe(\"Optional display filename\"),\n altText: z\n .string()\n .optional()\n .describe(\"Optional description/caption for the image\"),\n },\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: false,\n },\n },\n\n async (args) => {\n const result = await getConvexClient().action(api.mcp.addWorkItemImage, {\n token: getToken(),\n ...args,\n });\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerListWorkItemImages(server: McpServer): void {\n server.registerTool(\n \"list_work_item_images\",\n {\n description:\n \"List image attachments for a work item, including uploaded images and externally attached MCP images. Call list_work_items first to find the workItemId.\",\n inputSchema: {\n workItemId: z.string().describe(\"workItemId from list_work_items\"),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: false,\n },\n },\n\n async ({ workItemId }) => {\n const result = await getConvexClient().action(\n api.mcp.listWorkItemImages,\n {\n token: getToken(),\n workItemId,\n },\n );\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { agentArg, getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerAddWorkItemComment(server: McpServer): void {\n server.registerTool(\n \"add_work_item_comment\",\n {\n description:\n \"Add a timestamped comment to a work item. Use this to record notes, updates, \" +\n \"or an 'AI touched' entry instead of editing the description. Comments are \" +\n \"stamped with the current time automatically and never overwrite each other.\",\n inputSchema: {\n workItemId: z.string().describe(\"workItemId from list_work_items\"),\n body: z\n .string()\n .min(1)\n .describe(\n \"Comment text (markdown supported). To pull a person into the thread, mention them as [@Name](user:<userId>) \u2014 they are notified and the app renders it as a chip. userIds come from an item's assigneeId/reviewerId; there is no member lookup tool yet, so only mention ids you have seen.\",\n ),\n source: z\n .enum([\"user\", \"ai\"])\n .optional()\n .describe('Who authored it; defaults to \"ai\" for MCP callers'),\n },\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: false,\n },\n },\n\n async (args) => {\n const result = await getConvexClient().action(\n api.mcp.addWorkItemComment,\n {\n token: getToken(),\n ...args,\n agent: agentArg(),\n },\n );\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerListWorkItemComments(server: McpServer): void {\n server.registerTool(\n \"list_work_item_comments\",\n {\n description:\n \"List the timestamped comments on a work item, oldest first. Use this to check \" +\n \"whether the item was already touched/commented before adding a new comment.\",\n inputSchema: {\n workItemId: z.string().describe(\"workItemId from list_work_items\"),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: false,\n },\n },\n\n async (args) => {\n const result = await getConvexClient().action(\n api.mcp.listWorkItemComments,\n {\n token: getToken(),\n ...args,\n },\n );\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerListValidations(server: McpServer): void {\n server.registerTool(\n \"list_validations\",\n {\n description:\n \"List a project's validation graph: core systems and validation/test tasks with their DERIVED state (passing, failing, stale, unvalidated). A task is 'stale' when a system it covers changed since it was last validated, or an upstream dependency is no longer passing. Call list_projects first to find the projectId.\",\n inputSchema: {\n projectId: z.string().describe(\"projectId from list_projects\"),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: false,\n },\n },\n\n async ({ projectId }) => {\n const client = getConvexClient();\n const graph = await client.action(api.mcp.listValidations, {\n token: getToken(),\n projectId,\n });\n return {\n content: [{ type: \"text\", text: JSON.stringify(graph, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerRecordValidation(server: McpServer): void {\n server.registerTool(\n \"record_validation\",\n {\n description:\n \"Check off a validation task by recording a pass or fail. Stamps the task as validated 'now', clearing any stale flag until a covered system changes or an upstream dependency moves again. Get validationTaskId from list_validations.\",\n inputSchema: {\n validationTaskId: z\n .string()\n .describe(\"validationTaskId from list_validations\"),\n result: z\n .enum([\"pass\", \"fail\"])\n .describe(\"Outcome of running the test\"),\n },\n annotations: {\n readOnlyHint: false,\n destructiveHint: true,\n idempotentHint: true,\n openWorldHint: false,\n },\n },\n\n async ({ validationTaskId, result }) => {\n const client = getConvexClient();\n const res = await client.action(api.mcp.recordValidation, {\n token: getToken(),\n validationTaskId,\n result,\n });\n return {\n content: [{ type: \"text\", text: JSON.stringify(res, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerMarkSystemChanged(server: McpServer): void {\n server.registerTool(\n \"mark_system_changed\",\n {\n description:\n \"Mark a core system as changed. This is the single action that invalidates testing: every validation task that covers this system (and everything transitively depending on those tasks) immediately becomes 'stale' and needs revalidation. Get systemId from list_validations.\",\n inputSchema: {\n systemId: z.string().describe(\"systemId from list_validations\"),\n },\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: false,\n },\n },\n\n async ({ systemId }) => {\n const client = getConvexClient();\n const res = await client.action(api.mcp.markSystemChanged, {\n token: getToken(),\n systemId,\n });\n return {\n content: [{ type: \"text\", text: JSON.stringify(res, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerCreateSystem(server: McpServer): void {\n server.registerTool(\n \"create_system\",\n {\n description:\n \"Create a core system in a project \u2014 a subsystem (e.g. Auth, Payments, Sync) whose change should invalidate the validation tasks that cover it. Returns the new systemId.\",\n inputSchema: {\n projectId: z.string().describe(\"projectId from list_projects\"),\n name: z.string().min(1).describe(\"Short system name, e.g. 'Auth'\"),\n description: z.string().optional().describe(\"Optional details\"),\n },\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: false,\n },\n },\n\n async (args) => {\n const client = getConvexClient();\n const res = await client.action(api.mcp.createSystem, {\n token: getToken(),\n ...args,\n });\n return {\n content: [{ type: \"text\", text: JSON.stringify(res, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerCreateValidationTask(server: McpServer): void {\n server.registerTool(\n \"create_validation_task\",\n {\n description:\n \"Create a validation/test task in a project. After creating it, use add_system_to_task to declare which systems it exercises (so it goes stale when they change) and add_validation_dependency to order it after other tasks. Returns the new validationTaskId.\",\n inputSchema: {\n projectId: z.string().describe(\"projectId from list_projects\"),\n title: z.string().min(1).describe(\"What this test validates\"),\n description: z.string().optional().describe(\"Optional steps / details\"),\n kind: z\n .enum([\"auto\", \"manual\"])\n .optional()\n .describe(\n \"'auto' if runnable by a test runner, 'manual' if a human checks it. Defaults to manual.\",\n ),\n workItemId: z\n .string()\n .optional()\n .describe(\n \"Optional workItemId to link this test to a feature for traceability\",\n ),\n },\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: false,\n },\n },\n\n async (args) => {\n const client = getConvexClient();\n const res = await client.action(api.mcp.createValidationTask, {\n token: getToken(),\n ...args,\n });\n return {\n content: [{ type: \"text\", text: JSON.stringify(res, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerAddSystemToTask(server: McpServer): void {\n server.registerTool(\n \"add_system_to_task\",\n {\n description:\n \"Declare that a validation task COVERS (exercises) a system. Once linked, the task becomes 'stale' whenever that system is marked changed. Idempotent. Both IDs come from list_validations and must be in the same project.\",\n inputSchema: {\n validationTaskId: z\n .string()\n .describe(\"validationTaskId from list_validations\"),\n systemId: z.string().describe(\"systemId from list_validations\"),\n },\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: false,\n },\n },\n\n async ({ validationTaskId, systemId }) => {\n const client = getConvexClient();\n const res = await client.action(api.mcp.addSystemToTask, {\n token: getToken(),\n validationTaskId,\n systemId,\n });\n return {\n content: [{ type: \"text\", text: JSON.stringify(res, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerAddValidationDependency(server: McpServer): void {\n server.registerTool(\n \"add_validation_dependency\",\n {\n description:\n \"Make one validation task depend on another (validationTaskId depends on dependsOnTaskId). The dependent goes 'stale' whenever the upstream task is not passing or gets revalidated. Cycles and self-dependencies are rejected. Idempotent. Both IDs come from list_validations and must be in the same project.\",\n inputSchema: {\n validationTaskId: z\n .string()\n .describe(\"The dependent (downstream) task\"),\n dependsOnTaskId: z\n .string()\n .describe(\"The dependency (upstream) task it relies on\"),\n },\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: false,\n },\n },\n\n async ({ validationTaskId, dependsOnTaskId }) => {\n const client = getConvexClient();\n const res = await client.action(api.mcp.addValidationDependency, {\n token: getToken(),\n validationTaskId,\n dependsOnTaskId,\n });\n return {\n content: [{ type: \"text\", text: JSON.stringify(res, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerListLabels(server: McpServer): void {\n server.registerTool(\n \"list_labels\",\n {\n description:\n \"List all labels defined in a project. Returns each label's id, name, and color. Use the labelId with add_label_to_work_item / remove_label_from_work_item.\",\n inputSchema: {\n projectId: z.string().describe(\"projectId from list_projects\"),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: false,\n },\n },\n\n async (args) => {\n const result = await getConvexClient().action(api.mcp.listLabels, {\n token: getToken(),\n ...args,\n });\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerCreateLabel(server: McpServer): void {\n server.registerTool(\n \"create_label\",\n {\n description:\n \"Apply-or-seed a label. Returns the existing label if the name is \" +\n \"already taken (idempotent), and otherwise creates it ONLY if the name \" +\n \"is one of the curated ones. Any other new name is REFUSED \u2014 the reply \" +\n \"carries `refused: true`, the reason, and `available`, the project's \" +\n \"existing labels. Agents apply labels; they do not invent them, because \" +\n \"a near-duplicate of an existing label splits the vocabulary silently. \" +\n \"Prefer list_labels first. Colors are ignored for curated names so the \" +\n \"vocabulary looks the same in every project.\",\n inputSchema: {\n projectId: z.string().describe(\"projectId from list_projects\"),\n name: z\n .string()\n .min(1)\n .describe(\"Label name, unique within the project\"),\n color: z\n .string()\n .regex(/^#[0-9a-fA-F]{6}$/)\n .optional()\n .describe(\"Hex color like #2563eb. Defaults to a neutral slate.\"),\n },\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: false,\n },\n },\n\n async (args) => {\n const result = await getConvexClient().action(api.mcp.createLabel, {\n token: getToken(),\n ...args,\n });\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerAddLabelToWorkItem(server: McpServer): void {\n server.registerTool(\n \"add_label_to_work_item\",\n {\n description:\n \"Attach a label to a work item (idempotent). The label and work item must be in the same project. Get labelIds from list_labels / create_label.\",\n inputSchema: {\n workItemId: z.string().describe(\"workItemId from list_work_items\"),\n labelId: z\n .string()\n .describe(\"labelId from list_labels or create_label\"),\n },\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: false,\n },\n },\n\n async (args) => {\n const result = await getConvexClient().action(api.mcp.setWorkItemLabel, {\n token: getToken(),\n ...args,\n attached: true,\n });\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerRemoveLabelFromWorkItem(server: McpServer): void {\n server.registerTool(\n \"remove_label_from_work_item\",\n {\n description:\n \"Remove a label from a work item (idempotent \u2014 a no-op if it wasn't attached).\",\n inputSchema: {\n workItemId: z.string().describe(\"workItemId from list_work_items\"),\n labelId: z.string().describe(\"labelId from list_labels\"),\n },\n annotations: {\n readOnlyHint: false,\n destructiveHint: true,\n idempotentHint: true,\n openWorldHint: false,\n },\n },\n\n async (args) => {\n const result = await getConvexClient().action(api.mcp.setWorkItemLabel, {\n token: getToken(),\n ...args,\n attached: false,\n });\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerListMilestones(server: McpServer): void {\n server.registerTool(\n \"list_milestones\",\n {\n description:\n \"List all milestones in a project. Returns each milestone's id, name, description, dueDate (unix ms), and status. Use the milestoneId with add_item_to_milestone / remove_item_from_milestone.\",\n inputSchema: {\n projectId: z.string().describe(\"projectId from list_projects\"),\n },\n annotations: {\n readOnlyHint: true,\n openWorldHint: false,\n },\n },\n\n async (args) => {\n const result = await getConvexClient().action(api.mcp.listMilestones, {\n token: getToken(),\n ...args,\n });\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerCreateMilestone(server: McpServer): void {\n server.registerTool(\n \"create_milestone\",\n {\n description:\n \"Create a milestone in a project. Returns the milestoneId. Good for grouping work into phases (e.g. 'Phase 1 \u2014 Web', 'Phase 2 \u2014 Native').\",\n inputSchema: {\n projectId: z.string().describe(\"projectId from list_projects\"),\n name: z.string().min(1).describe(\"Milestone name\"),\n description: z\n .string()\n .optional()\n .describe(\"Optional markdown description\"),\n dueDate: z\n .number()\n .optional()\n .describe(\"Optional due date as a unix timestamp in milliseconds\"),\n },\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: false,\n },\n },\n\n async (args) => {\n const result = await getConvexClient().action(api.mcp.createMilestone, {\n token: getToken(),\n ...args,\n });\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerAddItemToMilestone(server: McpServer): void {\n server.registerTool(\n \"add_item_to_milestone\",\n {\n description:\n \"Associate a work item with a milestone (idempotent). Both must be in the same project.\",\n inputSchema: {\n milestoneId: z\n .string()\n .describe(\"milestoneId from list_milestones or create_milestone\"),\n workItemId: z.string().describe(\"workItemId from list_work_items\"),\n },\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: false,\n },\n },\n\n async (args) => {\n const result = await getConvexClient().action(\n api.mcp.setWorkItemMilestone,\n {\n token: getToken(),\n ...args,\n attached: true,\n },\n );\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n },\n );\n}\n", "import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { api } from \"@nimara/convex/convex/_generated/api.js\";\nimport { getConvexClient, getToken } from \"../convex.js\";\n\nexport function registerRemoveItemFromMilestone(server: McpServer): void {\n server.registerTool(\n \"remove_item_from_milestone\",\n {\n description:\n \"Remove a work item's association with a milestone (idempotent \u2014 a no-op if it wasn't associated).\",\n inputSchema: {\n milestoneId: z.string().describe(\"milestoneId from list_milestones\"),\n workItemId: z.string().describe(\"workItemId from list_work_items\"),\n },\n annotations: {\n readOnlyHint: false,\n destructiveHint: true,\n idempotentHint: true,\n openWorldHint: false,\n },\n },\n\n async (args) => {\n const result = await getConvexClient().action(\n api.mcp.setWorkItemMilestone,\n {\n token: getToken(),\n ...args,\n attached: false,\n },\n );\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n },\n );\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z", "z"]
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nimara-app/mcp",
3
- "version": "0.4.0",
3
+ "version": "0.6.0",
4
4
  "private": false,
5
5
  "mcpName": "io.github.langskip-studios/nimara",
6
6
  "description": "Nimara MCP server — AI tool integration for Claude, Codex, and others",