@burdenoff/mcp-libs 2026.1028.1 → 2026.1030.2

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.
@@ -142,10 +142,6 @@ var LOCATION_ENTRY_FIELDS = `
142
142
  id latitude longitude accuracy address startTime endTime duration geofenceId
143
143
  projectId userId workspaceId createdAt updatedAt
144
144
  `;
145
- var CHANNEL_FIELDS = `
146
- id name type status syncInterval lastSync settings workspaceId
147
- createdAt updatedAt
148
- `;
149
145
  var CLIENT_PORTAL_FIELDS = `
150
146
  id clientName description contactEmail contactPhone logoUrl isActive
151
147
  permissions settings workspaceId createdAt updatedAt
@@ -154,12 +150,6 @@ var EMAIL_ENTRY_FIELDS = `
154
150
  id subject sender recipients threadId category isImportant duration
155
151
  responseTime date userId workspaceId createdAt updatedAt
156
152
  `;
157
- var CONFIG_FIELDS = `
158
- id key value scope scopeId description isSecret workspaceId createdAt updatedAt
159
- `;
160
- var UI_SESSION_FIELDS = `
161
- id activeView preferences state userId workspaceId createdAt updatedAt
162
- `;
163
153
  var GET_TIME_ENTRY = `
164
154
  query TimecampusGetTimeEntry($id: ID!) {
165
155
  timeEntry(id: $id) { ${TIME_ENTRY_FIELDS} }
@@ -956,51 +946,6 @@ var DELETE_LOCATION_ENTRY = `
956
946
  deleteLocationEntry(id: $id) { ${LOCATION_ENTRY_FIELDS} }
957
947
  }
958
948
  `;
959
- var GET_CHANNEL = `
960
- query TimecampusGetChannel($id: ID!) {
961
- channelConfig(id: $id) { ${CHANNEL_FIELDS} }
962
- }
963
- `;
964
- var LIST_CHANNELS = `
965
- query TimecampusListChannels($limit: Int, $offset: Int) {
966
- channelConfigs(limit: $limit, offset: $offset) { ${CHANNEL_FIELDS} }
967
- }
968
- `;
969
- var ACTIVE_CHANNELS = `
970
- query TimecampusActiveChannels {
971
- activeChannels { ${CHANNEL_FIELDS} }
972
- }
973
- `;
974
- var CHANNEL_STATUSES = `
975
- query TimecampusChannelStatuses {
976
- channelStatuses { channelId name type status isHealthy lastSync }
977
- }
978
- `;
979
- var CREATE_CHANNEL = `
980
- mutation TimecampusCreateChannel($input: CreateChannelConfigInput!) {
981
- createChannelConfig(input: $input) { ${CHANNEL_FIELDS} }
982
- }
983
- `;
984
- var UPDATE_CHANNEL = `
985
- mutation TimecampusUpdateChannel($id: ID!, $input: UpdateChannelConfigInput!) {
986
- updateChannelConfig(id: $id, input: $input) { ${CHANNEL_FIELDS} }
987
- }
988
- `;
989
- var DELETE_CHANNEL = `
990
- mutation TimecampusDeleteChannel($id: ID!) {
991
- deleteChannelConfig(id: $id) { ${CHANNEL_FIELDS} }
992
- }
993
- `;
994
- var SYNC_CHANNEL = `
995
- mutation TimecampusSyncChannel($id: ID!) {
996
- syncChannel(id: $id) { ${CHANNEL_FIELDS} }
997
- }
998
- `;
999
- var TOGGLE_CHANNEL = `
1000
- mutation TimecampusToggleChannel($id: ID!, $status: ChannelStatus!) {
1001
- toggleChannel(id: $id, status: $status) { ${CHANNEL_FIELDS} }
1002
- }
1003
- `;
1004
949
  var GET_CLIENT_PORTAL = `
1005
950
  query TimecampusGetClientPortal($id: ID!) {
1006
951
  clientPortalConfig(id: $id) { ${CLIENT_PORTAL_FIELDS} }
@@ -1091,76 +1036,9 @@ var DELETE_EMAIL_ENTRY = `
1091
1036
  deleteEmailTimeEntry(id: $id) { ${EMAIL_ENTRY_FIELDS} }
1092
1037
  }
1093
1038
  `;
1094
- var GET_CONFIG = `
1095
- query TimecampusGetConfig($id: ID!) {
1096
- timeCampusConfiguration(id: $id) { ${CONFIG_FIELDS} }
1097
- }
1098
- `;
1099
- var GET_CONFIG_BY_KEY = `
1100
- query TimecampusGetConfigByKey($key: String!, $scope: TimeCampusConfigScope, $scopeId: String) {
1101
- timeCampusConfigurationByKey(key: $key, scope: $scope, scopeId: $scopeId) { ${CONFIG_FIELDS} }
1102
- }
1103
- `;
1104
- var CONFIG_VALUE = `
1105
- query TimecampusConfigValue($key: String!, $scope: TimeCampusConfigScope, $scopeId: String) {
1106
- timeCampusConfigurationValue(key: $key, scope: $scope, scopeId: $scopeId)
1107
- }
1108
- `;
1109
- var LIST_CONFIGS = `
1110
- query TimecampusListConfigs($scope: TimeCampusConfigScope, $scopeId: String, $limit: Int, $offset: Int) {
1111
- timeCampusConfigurations(scope: $scope, scopeId: $scopeId, limit: $limit, offset: $offset) {
1112
- ${CONFIG_FIELDS}
1113
- }
1114
- }
1115
- `;
1116
- var SET_CONFIG = `
1117
- mutation TimecampusSetConfig($input: SetTimeCampusConfigurationInput!) {
1118
- setTimeCampusConfiguration(input: $input) { ${CONFIG_FIELDS} }
1119
- }
1120
- `;
1121
- var BULK_SET_CONFIGS = `
1122
- mutation TimecampusBulkSetConfigs($inputs: [SetTimeCampusConfigurationInput!]!) {
1123
- bulkSetTimeCampusConfigurations(inputs: $inputs) { ${CONFIG_FIELDS} }
1124
- }
1125
- `;
1126
- var UPDATE_CONFIG = `
1127
- mutation TimecampusUpdateConfig($id: ID!, $input: UpdateTimeCampusConfigurationInput!) {
1128
- updateTimeCampusConfiguration(id: $id, input: $input) { ${CONFIG_FIELDS} }
1129
- }
1130
- `;
1131
- var DELETE_CONFIG = `
1132
- mutation TimecampusDeleteConfig($id: ID!) {
1133
- deleteTimeCampusConfiguration(id: $id) { ${CONFIG_FIELDS} }
1134
- }
1135
- `;
1136
- var GET_UI_SESSION = `
1137
- query TimecampusGetUISession {
1138
- timeCampusUISession { ${UI_SESSION_FIELDS} }
1139
- }
1140
- `;
1141
- var UI_SESSION_BY_USER = `
1142
- query TimecampusUISessionByUser($userId: ID!) {
1143
- timeCampusUISessionByUser(userId: $userId) { ${UI_SESSION_FIELDS} }
1144
- }
1145
- `;
1146
- var SAVE_UI_SESSION = `
1147
- mutation TimecampusSaveUISession($input: SaveTimeCampusUISessionInput!) {
1148
- saveTimeCampusUISession(input: $input) { ${UI_SESSION_FIELDS} }
1149
- }
1150
- `;
1151
- var UPDATE_UI_SESSION = `
1152
- mutation TimecampusUpdateUISession($id: ID!, $input: UpdateTimeCampusUISessionInput!) {
1153
- updateTimeCampusUISession(id: $id, input: $input) { ${UI_SESSION_FIELDS} }
1154
- }
1155
- `;
1156
- var CLEAR_UI_SESSION = `
1157
- mutation TimecampusClearUISession {
1158
- clearTimeCampusUISession
1159
- }
1160
- `;
1161
1039
  var ApprovalStatusEnum = zod.z.enum(["PENDING", "APPROVED", "REJECTED", "REVISION_REQUESTED"]).describe("Lifecycle status of a time-approval request");
1162
- var ChannelStatusEnum = zod.z.enum(["ACTIVE", "INACTIVE", "SETUP"]).describe("Operational status of a tracking channel");
1163
- var ChannelTypeEnum = zod.z.enum(["API", "BROWSER", "CALENDAR", "CLI", "CUSTOM", "DESKTOP", "IDE", "MOBILE"]).describe("Source type of a tracking channel");
1040
+ zod.z.enum(["ACTIVE", "INACTIVE", "SETUP"]).describe("Operational status of a tracking channel");
1041
+ zod.z.enum(["API", "BROWSER", "CALENDAR", "CLI", "CUSTOM", "DESKTOP", "IDE", "MOBILE"]).describe("Source type of a tracking channel");
1164
1042
  var ExpenseStatusEnum = zod.z.enum(["PENDING", "APPROVED", "REJECTED", "REIMBURSED"]).describe("Status of an expense entry");
1165
1043
  var ExpenseOrderByFieldEnum = zod.z.enum(["amount", "category", "createdAt", "date", "status", "updatedAt"]).describe("Sortable field for expense listings");
1166
1044
  var GeofenceTriggerEnum = zod.z.enum(["ENTER", "EXIT", "BOTH"]).describe("Which boundary crossings a geofence reacts to");
@@ -1173,7 +1051,7 @@ var MeetingOrderByFieldEnum = zod.z.enum(["cost", "createdAt", "duration", "endT
1173
1051
  var PomodoroSessionTypeEnum = zod.z.enum(["FOCUS", "SHORT_BREAK", "LONG_BREAK"]).describe("Type of a pomodoro session");
1174
1052
  var PomodoroGoalTypeEnum = zod.z.enum(["DAILY", "WEEKLY", "MONTHLY"]).describe("Cadence of a pomodoro goal");
1175
1053
  var PomodoroSessionOrderByFieldEnum = zod.z.enum(["createdAt", "duration", "endTime", "startTime", "updatedAt"]).describe("Sortable field for pomodoro-session listings");
1176
- var ConfigScopeEnum = zod.z.enum(["GLOBAL", "WORKSPACE", "PROJECT", "USER"]).describe("Scope at which a configuration value applies");
1054
+ zod.z.enum(["GLOBAL", "WORKSPACE", "PROJECT", "USER"]).describe("Scope at which a configuration value applies");
1177
1055
  var OrderDirectionEnum = zod.z.enum(["ASC", "DESC"]).describe("Sort direction (uppercase) for OrderDirection-typed list args");
1178
1056
  var SortDirectionEnum = zod.z.enum(["asc", "desc"]).describe("Sort direction (lowercase) for TimeCampusSortDirection-typed list args");
1179
1057
  var TaskOrderFieldEnum = zod.z.enum(["CREATED_AT", "DUE_DATE", "ORDER", "PRIORITY", "STATUS", "TITLE"]).describe("Sortable field for task listings");
@@ -1533,6 +1411,7 @@ function registerTimeEntryTools(server, ctx, track) {
1533
1411
  track(mcpToolName(ctx.productName, "timers_running")),
1534
1412
  {
1535
1413
  title: "List Running Timers",
1414
+ annotations: { readOnlyHint: true },
1536
1415
  description: "List all currently-running timers with their elapsed seconds.",
1537
1416
  inputSchema: {}
1538
1417
  },
@@ -2221,6 +2100,7 @@ function registerMeetingTools(server, ctx, track) {
2221
2100
  track(mcpToolName(ctx.productName, "meetings_upcoming")),
2222
2101
  {
2223
2102
  title: "Upcoming Meetings",
2103
+ annotations: { readOnlyHint: true },
2224
2104
  description: "List upcoming meetings in a workspace.",
2225
2105
  inputSchema: {
2226
2106
  workspaceId: zod.z.string().describe("Workspace ID"),
@@ -2607,6 +2487,7 @@ function registerPomodoroTools(server, ctx, track) {
2607
2487
  track(mcpToolName(ctx.productName, "pomodoro_active_session")),
2608
2488
  {
2609
2489
  title: "Active Pomodoro Session",
2490
+ annotations: { readOnlyHint: true },
2610
2491
  description: "Fetch the currently-active pomodoro session in a workspace, if any.",
2611
2492
  inputSchema: { workspaceId: zod.z.string().describe("Workspace ID") }
2612
2493
  },
@@ -2626,6 +2507,7 @@ function registerPomodoroTools(server, ctx, track) {
2626
2507
  track(mcpToolName(ctx.productName, "pomodoro_session")),
2627
2508
  {
2628
2509
  title: "Get Pomodoro Session",
2510
+ annotations: { readOnlyHint: true },
2629
2511
  description: "Fetch a single pomodoro session by ID. Requires workspaceId.",
2630
2512
  inputSchema: {
2631
2513
  id: zod.z.string().describe("Pomodoro session ID"),
@@ -2649,6 +2531,7 @@ function registerPomodoroTools(server, ctx, track) {
2649
2531
  track(mcpToolName(ctx.productName, "pomodoro_sessions")),
2650
2532
  {
2651
2533
  title: "List Pomodoro Sessions",
2534
+ annotations: { readOnlyHint: true },
2652
2535
  description: "List pomodoro sessions in a workspace with optional filters, pagination and ordering.",
2653
2536
  inputSchema: {
2654
2537
  workspaceId: zod.z.string().describe("Workspace ID"),
@@ -2738,6 +2621,7 @@ function registerPomodoroTools(server, ctx, track) {
2738
2621
  track(mcpToolName(ctx.productName, "pomodoro_goals")),
2739
2622
  {
2740
2623
  title: "List Pomodoro Goals",
2624
+ annotations: { readOnlyHint: true },
2741
2625
  description: "List pomodoro goals in a workspace.",
2742
2626
  inputSchema: { workspaceId: zod.z.string().describe("Workspace ID") }
2743
2627
  },
@@ -2757,6 +2641,7 @@ function registerPomodoroTools(server, ctx, track) {
2757
2641
  track(mcpToolName(ctx.productName, "pomodoro_settings")),
2758
2642
  {
2759
2643
  title: "Get Pomodoro Settings",
2644
+ annotations: { readOnlyHint: true },
2760
2645
  description: "Fetch the pomodoro settings for a workspace.",
2761
2646
  inputSchema: { workspaceId: zod.z.string().describe("Workspace ID") }
2762
2647
  },
@@ -3116,6 +3001,7 @@ function registerExpenseTools(server, ctx, track) {
3116
3001
  track(mcpToolName(ctx.productName, "expenses_categories")),
3117
3002
  {
3118
3003
  title: "Expense Categories",
3004
+ annotations: { readOnlyHint: true },
3119
3005
  description: "List the distinct expense categories used in a workspace.",
3120
3006
  inputSchema: { workspaceId: zod.z.string().describe("Workspace ID") }
3121
3007
  },
@@ -3435,6 +3321,7 @@ function registerApprovalTools(server, ctx, track) {
3435
3321
  track(mcpToolName(ctx.productName, "approvals_mine")),
3436
3322
  {
3437
3323
  title: "My Approval Requests",
3324
+ annotations: { readOnlyHint: true },
3438
3325
  description: "List the calling user\u2019s own approval requests, optionally filtered by status.",
3439
3326
  inputSchema: { status: ApprovalStatusEnum.optional().describe("Filter by status") }
3440
3327
  },
@@ -3454,6 +3341,7 @@ function registerApprovalTools(server, ctx, track) {
3454
3341
  track(mcpToolName(ctx.productName, "approvals_pending")),
3455
3342
  {
3456
3343
  title: "Pending Approvals",
3344
+ annotations: { readOnlyHint: true },
3457
3345
  description: "List approval requests pending the calling reviewer\u2019s decision.",
3458
3346
  inputSchema: {}
3459
3347
  },
@@ -3792,6 +3680,7 @@ function registerResourcingTools(server, ctx, track) {
3792
3680
  track(mcpToolName(ctx.productName, "resource_allocations_user")),
3793
3681
  {
3794
3682
  title: "User Allocations",
3683
+ annotations: { readOnlyHint: true },
3795
3684
  description: "List a user\u2019s resource allocations over an optional date range.",
3796
3685
  inputSchema: {
3797
3686
  userId: zod.z.string().describe("User ID"),
@@ -3815,6 +3704,7 @@ function registerResourcingTools(server, ctx, track) {
3815
3704
  track(mcpToolName(ctx.productName, "resource_capacity_overview")),
3816
3705
  {
3817
3706
  title: "Capacity Overview",
3707
+ annotations: { readOnlyHint: true },
3818
3708
  description: "Capacity vs allocation overview across a required date range.",
3819
3709
  inputSchema: {
3820
3710
  startDate: zod.z.string().describe("ISO range start"),
@@ -4040,6 +3930,7 @@ function registerFocusTools(server, ctx, track) {
4040
3930
  track(mcpToolName(ctx.productName, "focus_summary")),
4041
3931
  {
4042
3932
  title: "Focus Score Summary",
3933
+ annotations: { readOnlyHint: true },
4043
3934
  description: "Summary of focus scores (average/high/low, trend, top factor) over a range.",
4044
3935
  inputSchema: {
4045
3936
  startDate: zod.z.string().optional().describe("ISO range start"),
@@ -4063,6 +3954,7 @@ function registerFocusTools(server, ctx, track) {
4063
3954
  track(mcpToolName(ctx.productName, "focus_trend")),
4064
3955
  {
4065
3956
  title: "Focus Score Trend",
3957
+ annotations: { readOnlyHint: true },
4066
3958
  description: "Daily focus-score trend over the last N days.",
4067
3959
  inputSchema: {
4068
3960
  days: zod.z.number().int().optional().describe("Number of days (default 30)"),
@@ -4085,6 +3977,7 @@ function registerFocusTools(server, ctx, track) {
4085
3977
  track(mcpToolName(ctx.productName, "focus_today")),
4086
3978
  {
4087
3979
  title: "Today Focus Score",
3980
+ annotations: { readOnlyHint: true },
4088
3981
  description: "Fetch today\u2019s focus score for the calling user, if recorded.",
4089
3982
  inputSchema: {}
4090
3983
  },
@@ -4306,6 +4199,7 @@ function registerWorkPatternTools(server, ctx, track) {
4306
4199
  track(mcpToolName(ctx.productName, "workpatterns_summary")),
4307
4200
  {
4308
4201
  title: "Work Pattern Summary",
4202
+ annotations: { readOnlyHint: true },
4309
4203
  description: "Summary of work patterns (avg focus/meeting hours, productivity, best/worst day, insights) over a range.",
4310
4204
  inputSchema: {
4311
4205
  startDate: zod.z.string().optional().describe("ISO range start"),
@@ -4329,6 +4223,7 @@ function registerWorkPatternTools(server, ctx, track) {
4329
4223
  track(mcpToolName(ctx.productName, "workpatterns_today")),
4330
4224
  {
4331
4225
  title: "Today Work Pattern",
4226
+ annotations: { readOnlyHint: true },
4332
4227
  description: "Fetch today\u2019s work pattern for the calling user, if recorded.",
4333
4228
  inputSchema: {}
4334
4229
  },
@@ -4525,6 +4420,7 @@ function registerAppUsageTools(server, ctx, track) {
4525
4420
  track(mcpToolName(ctx.productName, "appusage_summary")),
4526
4421
  {
4527
4422
  title: "Application Usage Summary",
4423
+ annotations: { readOnlyHint: true },
4528
4424
  description: "Summary of application usage (productive/neutral/distracting time, ratio, top apps) over a range.",
4529
4425
  inputSchema: {
4530
4426
  startDate: zod.z.string().optional().describe("ISO range start"),
@@ -4551,6 +4447,7 @@ function registerAppUsageTools(server, ctx, track) {
4551
4447
  track(mcpToolName(ctx.productName, "appusage_top")),
4552
4448
  {
4553
4449
  title: "Top Applications",
4450
+ annotations: { readOnlyHint: true },
4554
4451
  description: "List the most-used applications over an optional date range.",
4555
4452
  inputSchema: {
4556
4453
  startDate: zod.z.string().optional().describe("ISO range start"),
@@ -4992,6 +4889,7 @@ function registerLocationTools(server, ctx, track) {
4992
4889
  track(mcpToolName(ctx.productName, "locations_active")),
4993
4890
  {
4994
4891
  title: "Active Location Entry",
4892
+ annotations: { readOnlyHint: true },
4995
4893
  description: "Fetch the currently-open (no end time) location entry for the calling user.",
4996
4894
  inputSchema: {}
4997
4895
  },
@@ -5199,221 +5097,6 @@ function registerLocationTools(server, ctx, track) {
5199
5097
  }
5200
5098
  );
5201
5099
  }
5202
- function registerChannelTools(server, ctx, track) {
5203
- server.registerTool(
5204
- track(mcpToolName(ctx.productName, "commchannels_get")),
5205
- {
5206
- title: "Get Channel Config",
5207
- description: "Fetch a single tracking-channel config by ID.",
5208
- inputSchema: { id: zod.z.string().describe("Channel config ID") }
5209
- },
5210
- async ({ id }) => {
5211
- try {
5212
- const data = await ctx.gql.workspace.request(GET_CHANNEL, { id });
5213
- if (!data.channelConfig) return errorResult(`Channel config ${id} not found`);
5214
- return jsonResult(data.channelConfig);
5215
- } catch (error) {
5216
- ctx.logger.error("timecampus commchannels_get failed", { error: String(error) });
5217
- return errorResult(
5218
- `Failed to get channel config: ${error instanceof Error ? error.message : String(error)}`
5219
- );
5220
- }
5221
- }
5222
- );
5223
- server.registerTool(
5224
- track(mcpToolName(ctx.productName, "commchannels_list")),
5225
- {
5226
- title: "List Channel Configs",
5227
- description: "List tracking-channel configs with pagination.",
5228
- inputSchema: {
5229
- limit: zod.z.number().int().optional().describe("Page size (default 50)"),
5230
- offset: zod.z.number().int().optional().describe("Pagination offset (default 0)")
5231
- }
5232
- },
5233
- async ({ limit, offset }) => {
5234
- try {
5235
- const data = await ctx.gql.workspace.request(LIST_CHANNELS, { limit: limit ?? 50, offset: offset ?? 0 });
5236
- return jsonResult(data.channelConfigs);
5237
- } catch (error) {
5238
- ctx.logger.error("timecampus commchannels_list failed", { error: String(error) });
5239
- return errorResult(
5240
- `Failed to list channel configs: ${error instanceof Error ? error.message : String(error)}`
5241
- );
5242
- }
5243
- }
5244
- );
5245
- server.registerTool(
5246
- track(mcpToolName(ctx.productName, "commchannels_active")),
5247
- {
5248
- title: "Active Channels",
5249
- description: "List the currently-active tracking channels.",
5250
- inputSchema: {}
5251
- },
5252
- async () => {
5253
- try {
5254
- const data = await ctx.gql.workspace.request(ACTIVE_CHANNELS, {});
5255
- return jsonResult(data.activeChannels);
5256
- } catch (error) {
5257
- ctx.logger.error("timecampus commchannels_active failed", { error: String(error) });
5258
- return errorResult(
5259
- `Failed to list active channels: ${error instanceof Error ? error.message : String(error)}`
5260
- );
5261
- }
5262
- }
5263
- );
5264
- server.registerTool(
5265
- track(mcpToolName(ctx.productName, "commchannels_statuses")),
5266
- {
5267
- title: "Channel Statuses",
5268
- description: "Health/status snapshot of every tracking channel.",
5269
- inputSchema: {}
5270
- },
5271
- async () => {
5272
- try {
5273
- const data = await ctx.gql.workspace.request(CHANNEL_STATUSES, {});
5274
- return jsonResult(data.channelStatuses);
5275
- } catch (error) {
5276
- ctx.logger.error("timecampus commchannels_statuses failed", { error: String(error) });
5277
- return errorResult(
5278
- `Failed to get channel statuses: ${error instanceof Error ? error.message : String(error)}`
5279
- );
5280
- }
5281
- }
5282
- );
5283
- server.registerTool(
5284
- track(mcpToolName(ctx.productName, "commchannels_create")),
5285
- {
5286
- title: "Create Channel Config",
5287
- description: "Create a tracking channel. `name` and `type` are required.",
5288
- inputSchema: {
5289
- name: zod.z.string().min(1).describe("Channel name"),
5290
- type: ChannelTypeEnum.describe("Channel source type"),
5291
- status: ChannelStatusEnum.optional().describe("Initial status (default SETUP)"),
5292
- syncInterval: zod.z.number().int().optional().describe("Sync interval (seconds)"),
5293
- settings: JsonObject.optional().describe("Channel settings JSON"),
5294
- context: JsonObject.optional().describe("Context JSON")
5295
- }
5296
- },
5297
- async ({ name, type, status, syncInterval, settings, context }) => {
5298
- try {
5299
- const input = { name, type };
5300
- if (status !== void 0) input.status = status;
5301
- if (syncInterval !== void 0) input.syncInterval = syncInterval;
5302
- if (settings !== void 0) input.settings = settings;
5303
- if (context !== void 0) input.context = context;
5304
- const data = await ctx.gql.workspace.request(CREATE_CHANNEL, { input });
5305
- return jsonResult(data.createChannelConfig);
5306
- } catch (error) {
5307
- ctx.logger.error("timecampus commchannels_create failed", { error: String(error) });
5308
- return errorResult(
5309
- `Failed to create channel config: ${error instanceof Error ? error.message : String(error)}`
5310
- );
5311
- }
5312
- }
5313
- );
5314
- server.registerTool(
5315
- track(mcpToolName(ctx.productName, "commchannels_update")),
5316
- {
5317
- title: "Update Channel Config",
5318
- description: "Update a tracking channel. At least one mutable field must be provided.",
5319
- inputSchema: {
5320
- id: zod.z.string().describe("Channel config ID"),
5321
- name: zod.z.string().optional().describe("Updated name"),
5322
- type: ChannelTypeEnum.optional().describe("Updated type"),
5323
- status: ChannelStatusEnum.optional().describe("Updated status"),
5324
- syncInterval: zod.z.number().int().optional().describe("Updated sync interval (seconds)"),
5325
- settings: JsonObject.optional().describe("Updated settings JSON")
5326
- }
5327
- },
5328
- async ({ id, name, type, status, syncInterval, settings }) => {
5329
- try {
5330
- const input = {};
5331
- if (name !== void 0) input.name = name;
5332
- if (type !== void 0) input.type = type;
5333
- if (status !== void 0) input.status = status;
5334
- if (syncInterval !== void 0) input.syncInterval = syncInterval;
5335
- if (settings !== void 0) input.settings = settings;
5336
- if (Object.keys(input).length === 0) {
5337
- return errorResult("No updates specified \u2014 provide at least one mutable field");
5338
- }
5339
- const data = await ctx.gql.workspace.request(UPDATE_CHANNEL, { id, input });
5340
- return jsonResult(data.updateChannelConfig);
5341
- } catch (error) {
5342
- ctx.logger.error("timecampus commchannels_update failed", { error: String(error) });
5343
- return errorResult(
5344
- `Failed to update channel config: ${error instanceof Error ? error.message : String(error)}`
5345
- );
5346
- }
5347
- }
5348
- );
5349
- server.registerTool(
5350
- track(mcpToolName(ctx.productName, "commchannels_delete")),
5351
- {
5352
- title: "Delete Channel Config",
5353
- description: "Delete a tracking channel by ID.",
5354
- inputSchema: { id: zod.z.string().describe("Channel config ID") }
5355
- },
5356
- async ({ id }) => {
5357
- try {
5358
- const data = await ctx.gql.workspace.request(DELETE_CHANNEL, { id });
5359
- return jsonResult(data.deleteChannelConfig);
5360
- } catch (error) {
5361
- ctx.logger.error("timecampus commchannels_delete failed", { error: String(error) });
5362
- return errorResult(
5363
- `Failed to delete channel config: ${error instanceof Error ? error.message : String(error)}`
5364
- );
5365
- }
5366
- }
5367
- );
5368
- server.registerTool(
5369
- track(mcpToolName(ctx.productName, "commchannels_sync")),
5370
- {
5371
- title: "Sync Channel",
5372
- description: "Trigger a sync for a tracking channel.",
5373
- inputSchema: { id: zod.z.string().describe("Channel config ID") },
5374
- annotations: { destructiveHint: true }
5375
- },
5376
- async ({ id }) => {
5377
- try {
5378
- const data = await ctx.gql.workspace.request(
5379
- SYNC_CHANNEL,
5380
- { id }
5381
- );
5382
- return jsonResult(data.syncChannel);
5383
- } catch (error) {
5384
- ctx.logger.error("timecampus commchannels_sync failed", { error: String(error) });
5385
- return errorResult(
5386
- `Failed to sync channel: ${error instanceof Error ? error.message : String(error)}`
5387
- );
5388
- }
5389
- }
5390
- );
5391
- server.registerTool(
5392
- track(mcpToolName(ctx.productName, "commchannels_toggle")),
5393
- {
5394
- title: "Toggle Channel",
5395
- description: "Set a tracking channel\u2019s status (ACTIVE / INACTIVE / SETUP).",
5396
- inputSchema: {
5397
- id: zod.z.string().describe("Channel config ID"),
5398
- status: ChannelStatusEnum.describe("New status")
5399
- }
5400
- },
5401
- async ({ id, status }) => {
5402
- try {
5403
- const data = await ctx.gql.workspace.request(
5404
- TOGGLE_CHANNEL,
5405
- { id, status }
5406
- );
5407
- return jsonResult(data.toggleChannel);
5408
- } catch (error) {
5409
- ctx.logger.error("timecampus commchannels_toggle failed", { error: String(error) });
5410
- return errorResult(
5411
- `Failed to toggle channel: ${error instanceof Error ? error.message : String(error)}`
5412
- );
5413
- }
5414
- }
5415
- );
5416
- }
5417
5100
  function registerClientPortalTools(server, ctx, track) {
5418
5101
  server.registerTool(
5419
5102
  track(mcpToolName(ctx.productName, "client_portals_get")),
@@ -5866,338 +5549,6 @@ function registerEmailTools(server, ctx, track) {
5866
5549
  }
5867
5550
  );
5868
5551
  }
5869
- function registerConfigTools(server, ctx, track) {
5870
- server.registerTool(
5871
- track(mcpToolName(ctx.productName, "config_get")),
5872
- {
5873
- title: "Get Configuration",
5874
- description: "Fetch a single configuration entry by ID.",
5875
- inputSchema: { id: zod.z.string().describe("Configuration ID") }
5876
- },
5877
- async ({ id }) => {
5878
- try {
5879
- const data = await ctx.gql.workspace.request(GET_CONFIG, { id });
5880
- if (!data.timeCampusConfiguration) return errorResult(`Configuration ${id} not found`);
5881
- return jsonResult(data.timeCampusConfiguration);
5882
- } catch (error) {
5883
- ctx.logger.error("timecampus config_get failed", { error: String(error) });
5884
- return errorResult(
5885
- `Failed to get configuration: ${error instanceof Error ? error.message : String(error)}`
5886
- );
5887
- }
5888
- }
5889
- );
5890
- server.registerTool(
5891
- track(mcpToolName(ctx.productName, "config_get_by_key")),
5892
- {
5893
- title: "Get Configuration By Key",
5894
- description: "Fetch a configuration entry by key (optionally scoped).",
5895
- inputSchema: {
5896
- key: zod.z.string().describe("Configuration key"),
5897
- scope: ConfigScopeEnum.optional().describe("Scope (GLOBAL/WORKSPACE/PROJECT/USER)"),
5898
- scopeId: zod.z.string().optional().describe("Scope ID (e.g. projectId/userId)")
5899
- }
5900
- },
5901
- async ({ key, scope, scopeId }) => {
5902
- try {
5903
- const data = await ctx.gql.workspace.request(GET_CONFIG_BY_KEY, { key, scope, scopeId });
5904
- return jsonResult(data.timeCampusConfigurationByKey);
5905
- } catch (error) {
5906
- ctx.logger.error("timecampus config_get_by_key failed", { error: String(error) });
5907
- return errorResult(
5908
- `Failed to get configuration by key: ${error instanceof Error ? error.message : String(error)}`
5909
- );
5910
- }
5911
- }
5912
- );
5913
- server.registerTool(
5914
- track(mcpToolName(ctx.productName, "config_value")),
5915
- {
5916
- title: "Get Configuration Value",
5917
- description: "Fetch just the JSON value of a configuration key (optionally scoped).",
5918
- inputSchema: {
5919
- key: zod.z.string().describe("Configuration key"),
5920
- scope: ConfigScopeEnum.optional().describe("Scope"),
5921
- scopeId: zod.z.string().optional().describe("Scope ID")
5922
- }
5923
- },
5924
- async ({ key, scope, scopeId }) => {
5925
- try {
5926
- const data = await ctx.gql.workspace.request(
5927
- CONFIG_VALUE,
5928
- { key, scope, scopeId }
5929
- );
5930
- return jsonResult({ value: data.timeCampusConfigurationValue });
5931
- } catch (error) {
5932
- ctx.logger.error("timecampus config_value failed", { error: String(error) });
5933
- return errorResult(
5934
- `Failed to get configuration value: ${error instanceof Error ? error.message : String(error)}`
5935
- );
5936
- }
5937
- }
5938
- );
5939
- server.registerTool(
5940
- track(mcpToolName(ctx.productName, "config_list")),
5941
- {
5942
- title: "List Configurations",
5943
- description: "List configuration entries with optional scope filter and pagination.",
5944
- inputSchema: {
5945
- scope: ConfigScopeEnum.optional().describe("Scope filter"),
5946
- scopeId: zod.z.string().optional().describe("Scope ID filter"),
5947
- limit: zod.z.number().int().optional().describe("Page size (default 50)"),
5948
- offset: zod.z.number().int().optional().describe("Pagination offset (default 0)")
5949
- }
5950
- },
5951
- async ({ scope, scopeId, limit, offset }) => {
5952
- try {
5953
- const data = await ctx.gql.workspace.request(LIST_CONFIGS, { scope, scopeId, limit: limit ?? 50, offset: offset ?? 0 });
5954
- return jsonResult(data.timeCampusConfigurations);
5955
- } catch (error) {
5956
- ctx.logger.error("timecampus config_list failed", { error: String(error) });
5957
- return errorResult(
5958
- `Failed to list configurations: ${error instanceof Error ? error.message : String(error)}`
5959
- );
5960
- }
5961
- }
5962
- );
5963
- server.registerTool(
5964
- track(mcpToolName(ctx.productName, "config_set")),
5965
- {
5966
- title: "Set Configuration",
5967
- description: "Set (upsert) a configuration key. `key` and `value` are required.",
5968
- inputSchema: {
5969
- key: zod.z.string().min(1).describe("Configuration key"),
5970
- value: JsonObject.describe("Configuration value JSON"),
5971
- scope: ConfigScopeEnum.optional().describe("Scope (default WORKSPACE)"),
5972
- scopeId: zod.z.string().optional().describe("Scope ID"),
5973
- description: zod.z.string().optional().describe("Description"),
5974
- isSecret: zod.z.boolean().optional().describe("Whether the value is secret (default false)"),
5975
- context: JsonObject.optional().describe("Context JSON")
5976
- }
5977
- },
5978
- async ({ key, value, scope, scopeId, description, isSecret, context }) => {
5979
- try {
5980
- const input = { key, value };
5981
- if (scope !== void 0) input.scope = scope;
5982
- if (scopeId !== void 0) input.scopeId = scopeId;
5983
- if (description !== void 0) input.description = description;
5984
- if (isSecret !== void 0) input.isSecret = isSecret;
5985
- if (context !== void 0) input.context = context;
5986
- const data = await ctx.gql.workspace.request(SET_CONFIG, { input });
5987
- return jsonResult(data.setTimeCampusConfiguration);
5988
- } catch (error) {
5989
- ctx.logger.error("timecampus config_set failed", { error: String(error) });
5990
- return errorResult(
5991
- `Failed to set configuration: ${error instanceof Error ? error.message : String(error)}`
5992
- );
5993
- }
5994
- }
5995
- );
5996
- server.registerTool(
5997
- track(mcpToolName(ctx.productName, "config_bulk_set")),
5998
- {
5999
- title: "Bulk Set Configurations",
6000
- description: "Set (upsert) multiple configuration keys in one call.",
6001
- inputSchema: {
6002
- inputs: zod.z.array(
6003
- zod.z.object({
6004
- key: zod.z.string().describe("Configuration key"),
6005
- value: JsonObject.describe("Value JSON"),
6006
- scope: ConfigScopeEnum.optional(),
6007
- scopeId: zod.z.string().optional(),
6008
- description: zod.z.string().optional(),
6009
- isSecret: zod.z.boolean().optional()
6010
- })
6011
- ).min(1).describe("Configuration entries to set")
6012
- },
6013
- annotations: { destructiveHint: true }
6014
- },
6015
- async ({ inputs }) => {
6016
- try {
6017
- const data = await ctx.gql.workspace.request(BULK_SET_CONFIGS, { inputs });
6018
- return jsonResult(data.bulkSetTimeCampusConfigurations);
6019
- } catch (error) {
6020
- ctx.logger.error("timecampus config_bulk_set failed", { error: String(error) });
6021
- return errorResult(
6022
- `Failed to bulk-set configurations: ${error instanceof Error ? error.message : String(error)}`
6023
- );
6024
- }
6025
- }
6026
- );
6027
- server.registerTool(
6028
- track(mcpToolName(ctx.productName, "config_update")),
6029
- {
6030
- title: "Update Configuration",
6031
- description: "Update a configuration entry. At least one mutable field must be provided.",
6032
- inputSchema: {
6033
- id: zod.z.string().describe("Configuration ID"),
6034
- value: JsonObject.optional().describe("Updated value JSON"),
6035
- description: zod.z.string().optional().describe("Updated description"),
6036
- isSecret: zod.z.boolean().optional().describe("Updated secret flag"),
6037
- context: JsonObject.optional().describe("Updated context JSON")
6038
- }
6039
- },
6040
- async ({ id, value, description, isSecret, context }) => {
6041
- try {
6042
- const input = {};
6043
- if (value !== void 0) input.value = value;
6044
- if (description !== void 0) input.description = description;
6045
- if (isSecret !== void 0) input.isSecret = isSecret;
6046
- if (context !== void 0) input.context = context;
6047
- if (Object.keys(input).length === 0) {
6048
- return errorResult("No updates specified \u2014 provide at least one mutable field");
6049
- }
6050
- const data = await ctx.gql.workspace.request(UPDATE_CONFIG, { id, input });
6051
- return jsonResult(data.updateTimeCampusConfiguration);
6052
- } catch (error) {
6053
- ctx.logger.error("timecampus config_update failed", { error: String(error) });
6054
- return errorResult(
6055
- `Failed to update configuration: ${error instanceof Error ? error.message : String(error)}`
6056
- );
6057
- }
6058
- }
6059
- );
6060
- server.registerTool(
6061
- track(mcpToolName(ctx.productName, "config_delete")),
6062
- {
6063
- title: "Delete Configuration",
6064
- description: "Delete a configuration entry by ID.",
6065
- inputSchema: { id: zod.z.string().describe("Configuration ID") }
6066
- },
6067
- async ({ id }) => {
6068
- try {
6069
- const data = await ctx.gql.workspace.request(DELETE_CONFIG, { id });
6070
- return jsonResult(data.deleteTimeCampusConfiguration);
6071
- } catch (error) {
6072
- ctx.logger.error("timecampus config_delete failed", { error: String(error) });
6073
- return errorResult(
6074
- `Failed to delete configuration: ${error instanceof Error ? error.message : String(error)}`
6075
- );
6076
- }
6077
- }
6078
- );
6079
- server.registerTool(
6080
- track(mcpToolName(ctx.productName, "ui_session_get")),
6081
- {
6082
- title: "Get UI Session",
6083
- description: "Fetch the calling user\u2019s saved UI session (view, preferences, state).",
6084
- inputSchema: {}
6085
- },
6086
- async () => {
6087
- try {
6088
- const data = await ctx.gql.workspace.request(GET_UI_SESSION, {});
6089
- return jsonResult(data.timeCampusUISession);
6090
- } catch (error) {
6091
- ctx.logger.error("timecampus ui_session_get failed", { error: String(error) });
6092
- return errorResult(
6093
- `Failed to get UI session: ${error instanceof Error ? error.message : String(error)}`
6094
- );
6095
- }
6096
- }
6097
- );
6098
- server.registerTool(
6099
- track(mcpToolName(ctx.productName, "ui_session_by_user")),
6100
- {
6101
- title: "Get UI Session By User",
6102
- description: "Fetch a specific user\u2019s saved UI session.",
6103
- inputSchema: { userId: zod.z.string().describe("User ID") }
6104
- },
6105
- async ({ userId }) => {
6106
- try {
6107
- const data = await ctx.gql.workspace.request(UI_SESSION_BY_USER, { userId });
6108
- return jsonResult(data.timeCampusUISessionByUser);
6109
- } catch (error) {
6110
- ctx.logger.error("timecampus ui_session_by_user failed", { error: String(error) });
6111
- return errorResult(
6112
- `Failed to get UI session by user: ${error instanceof Error ? error.message : String(error)}`
6113
- );
6114
- }
6115
- }
6116
- );
6117
- server.registerTool(
6118
- track(mcpToolName(ctx.productName, "ui_session_save")),
6119
- {
6120
- title: "Save UI Session",
6121
- description: "Save (upsert) the calling user\u2019s UI session.",
6122
- inputSchema: {
6123
- activeView: zod.z.string().optional().describe("Active view"),
6124
- preferences: JsonObject.optional().describe("Preferences JSON"),
6125
- state: JsonObject.optional().describe("State JSON"),
6126
- context: JsonObject.optional().describe("Context JSON")
6127
- }
6128
- },
6129
- async ({ activeView, preferences, state, context }) => {
6130
- try {
6131
- const input = {};
6132
- if (activeView !== void 0) input.activeView = activeView;
6133
- if (preferences !== void 0) input.preferences = preferences;
6134
- if (state !== void 0) input.state = state;
6135
- if (context !== void 0) input.context = context;
6136
- const data = await ctx.gql.workspace.request(SAVE_UI_SESSION, { input });
6137
- return jsonResult(data.saveTimeCampusUISession);
6138
- } catch (error) {
6139
- ctx.logger.error("timecampus ui_session_save failed", { error: String(error) });
6140
- return errorResult(
6141
- `Failed to save UI session: ${error instanceof Error ? error.message : String(error)}`
6142
- );
6143
- }
6144
- }
6145
- );
6146
- server.registerTool(
6147
- track(mcpToolName(ctx.productName, "ui_session_update")),
6148
- {
6149
- title: "Update UI Session",
6150
- description: "Update a UI session by ID. At least one mutable field must be provided.",
6151
- inputSchema: {
6152
- id: zod.z.string().describe("UI session ID"),
6153
- activeView: zod.z.string().optional().describe("Updated active view"),
6154
- preferences: JsonObject.optional().describe("Updated preferences JSON"),
6155
- state: JsonObject.optional().describe("Updated state JSON")
6156
- }
6157
- },
6158
- async ({ id, activeView, preferences, state }) => {
6159
- try {
6160
- const input = {};
6161
- if (activeView !== void 0) input.activeView = activeView;
6162
- if (preferences !== void 0) input.preferences = preferences;
6163
- if (state !== void 0) input.state = state;
6164
- if (Object.keys(input).length === 0) {
6165
- return errorResult("No updates specified \u2014 provide at least one mutable field");
6166
- }
6167
- const data = await ctx.gql.workspace.request(UPDATE_UI_SESSION, { id, input });
6168
- return jsonResult(data.updateTimeCampusUISession);
6169
- } catch (error) {
6170
- ctx.logger.error("timecampus ui_session_update failed", { error: String(error) });
6171
- return errorResult(
6172
- `Failed to update UI session: ${error instanceof Error ? error.message : String(error)}`
6173
- );
6174
- }
6175
- }
6176
- );
6177
- server.registerTool(
6178
- track(mcpToolName(ctx.productName, "ui_session_clear")),
6179
- {
6180
- title: "Clear UI Session",
6181
- description: "Clear the calling user\u2019s saved UI session.",
6182
- inputSchema: {},
6183
- annotations: { destructiveHint: true }
6184
- },
6185
- async () => {
6186
- try {
6187
- const data = await ctx.gql.workspace.request(
6188
- CLEAR_UI_SESSION,
6189
- {}
6190
- );
6191
- return jsonResult({ cleared: data.clearTimeCampusUISession });
6192
- } catch (error) {
6193
- ctx.logger.error("timecampus ui_session_clear failed", { error: String(error) });
6194
- return errorResult(
6195
- `Failed to clear UI session: ${error instanceof Error ? error.message : String(error)}`
6196
- );
6197
- }
6198
- }
6199
- );
6200
- }
6201
5552
 
6202
5553
  // src/modules/timecampus/resources.ts
6203
5554
  function registerTimecampusResources(server, ctx, track) {
@@ -6229,15 +5580,24 @@ Time tracking, productivity analytics & resource planning for workspaces.
6229
5580
  - ResourcePlan + ResourceAllocation \u2014 capacity planning
6230
5581
  - FocusScore / WorkPattern / ApplicationUsage \u2014 productivity analytics
6231
5582
  - Geofence (+ GeofenceEvent) / LocationEntry \u2014 location-based tracking
6232
- - ChannelConfig \u2014 capture channels (CLI/IDE/Browser/Mobile/\u2026)
6233
5583
  - ClientPortalConfig \u2014 external client portals
6234
5584
  - EmailTimeEntry \u2014 email-time tracking
6235
- - TimeCampusConfiguration / TimeCampusUISession \u2014 config + UI state
6236
5585
 
6237
5586
  ## Workspace scoping
6238
- Most fields scope via the gateway headers (no explicit workspaceId). The
6239
- meeting, expense and pomodoro fields take an EXPLICIT workspaceId argument
6240
- (create-inputs carry it inside the input) \u2014 match the tool's required args.
5587
+ Every field is scoped to the workspace in the gateway headers. The meeting,
5588
+ expense and pomodoro fields still take a workspaceId argument because the
5589
+ schema requires it, but the service always uses the header workspace, so the
5590
+ argument can never reach another workspace. Pass the current workspace id.
5591
+
5592
+ ## Privacy boundary
5593
+ Personal analytics (focus scores, work patterns, application usage, location,
5594
+ email time) are self-scoped: a userId naming another member is ignored and the
5595
+ caller's own data is returned. Only service and super-admin actors may read
5596
+ another member's personal data.
5597
+
5598
+ ## Destructive tools
5599
+ Tools annotated destructiveHint (deletes, approve/reject, archive, activate,
5600
+ withdraw) do nothing unless the call passes confirm: true. Ask the user first.
6241
5601
 
6242
5602
  ## Pagination
6243
5603
  { limit, offset }. Many list queries return a *ListResponse object
@@ -6246,7 +5606,7 @@ meeting, expense and pomodoro fields take an EXPLICIT workspaceId argument
6246
5606
  ## Tool groups
6247
5607
  timeentries/timers, projects, tasks, meetings, pomodoro, expenses, approvals,
6248
5608
  resource_plans/resource_allocations, focus, workpatterns, appusage,
6249
- geofences/locations, channels, client_portals, email_entries, config/ui_session.
5609
+ geofences/locations, client_portals, email_entries.
6250
5610
  The subgraph exposes no @public health field (only federation _empty), so there
6251
5611
  is intentionally no health tool.
6252
5612
  `;
@@ -6487,10 +5847,8 @@ var timecampusModule = {
6487
5847
  registerWorkPatternTools(server, ctx, trackTool);
6488
5848
  registerAppUsageTools(server, ctx, trackTool);
6489
5849
  registerLocationTools(server, ctx, trackTool);
6490
- registerChannelTools(server, ctx, trackTool);
6491
5850
  registerClientPortalTools(server, ctx, trackTool);
6492
5851
  registerEmailTools(server, ctx, trackTool);
6493
- registerConfigTools(server, ctx, trackTool);
6494
5852
  registerTimecampusResources(server, ctx, trackResource);
6495
5853
  registerTimecampusPrompts(server, ctx, trackPrompt);
6496
5854
  return { tools, resources, prompts };