@burdenoff/mcp-libs 2026.908.2 → 2026.928.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.
@@ -5,6 +5,7 @@ require('graphql-request');
5
5
  require('cross-fetch');
6
6
  require('@modelcontextprotocol/sdk/server/mcp.js');
7
7
  require('@modelcontextprotocol/sdk/types.js');
8
+ var crypto = require('crypto');
8
9
 
9
10
  // src/modules/planmagnet/tools/projects.ts
10
11
 
@@ -193,9 +194,6 @@ var SYNC_RESULT_FIELDS = `
193
194
  syncId success itemsCreated itemsUpdated itemsSkipped errorCount errors
194
195
  durationMs syncedAt
195
196
  `;
196
- var UI_SESSION_FIELDS = `
197
- id userId state metadata workspaceId createdAt updatedAt
198
- `;
199
197
  var GET_PROJECT = `
200
198
  query PlanmagnetProject($id: ID!) {
201
199
  planmagnetProject(id: $id) { ${PROJECT_FIELDS} }
@@ -1135,33 +1133,6 @@ var IMPORT_FROM_EXTERNAL = `
1135
1133
  planmagnetImportFromExternal(input: $input) { ${SYNC_RESULT_FIELDS} }
1136
1134
  }
1137
1135
  `;
1138
- var GET_OR_CREATE_UI_SESSION = `
1139
- query PlanmagnetGetOrCreateUISession($workspaceId: ID!) {
1140
- planmagnetGetOrCreateUISession(workspaceId: $workspaceId) { ${UI_SESSION_FIELDS} }
1141
- }
1142
- `;
1143
- var LIST_UI_SESSIONS = `
1144
- query PlanmagnetUiSessions(
1145
- $workspaceId: ID!
1146
- $filter: PlanmagnetUISessionFilter
1147
- $pagination: PlanmagnetPaginationInput
1148
- ) {
1149
- planmagnetUiSessions(workspaceId: $workspaceId, filter: $filter, pagination: $pagination) {
1150
- items { ${UI_SESSION_FIELDS} }
1151
- ${PAGE_INFO}
1152
- }
1153
- }
1154
- `;
1155
- var UPDATE_UI_SESSION = `
1156
- mutation PlanmagnetUpdateUISession($input: PlanmagnetUISessionViewStateInput!) {
1157
- planmagnetUpdateUISession(input: $input) { ${UI_SESSION_FIELDS} }
1158
- }
1159
- `;
1160
- var DELETE_UI_SESSION = `
1161
- mutation PlanmagnetDeleteUISession($id: ID!) {
1162
- planmagnetDeleteUISession(id: $id)
1163
- }
1164
- `;
1165
1136
  var JsonObject = zod.z.record(zod.z.string(), zod.z.unknown());
1166
1137
  var JsonValue = zod.z.union([JsonObject, zod.z.array(zod.z.unknown())]);
1167
1138
  var paginationInputShape = {
@@ -5827,101 +5798,80 @@ function registerSyncTools(server, ctx, track) {
5827
5798
  }
5828
5799
  );
5829
5800
  }
5830
- function registerUiSessionTools(server, ctx, track) {
5831
- server.registerTool(
5832
- track(mcpToolName(ctx.productName, "ui_sessions_list")),
5833
- {
5834
- title: "List UI Sessions",
5835
- description: "List persisted UI sessions for the current user in a workspace.",
5836
- inputSchema: {
5837
- workspaceId: zod.z.string().describe("Workspace ID (required)"),
5838
- userId: zod.z.string().optional().describe("Filter by user actor ID"),
5839
- ...paginationInputShape
5840
- }
5841
- },
5842
- async ({ workspaceId, userId, first, after }) => {
5843
- try {
5844
- const filter = {};
5845
- if (userId !== void 0) filter.userId = userId;
5846
- const data = await ctx.gql.workspace.request(LIST_UI_SESSIONS, {
5847
- workspaceId,
5848
- filter: Object.keys(filter).length > 0 ? filter : void 0,
5849
- pagination: buildPagination(first, after)
5850
- });
5851
- return jsonResult(data.planmagnetUiSessions);
5852
- } catch (error) {
5853
- ctx.logger.error("planmagnet ui_sessions_list failed", { error: String(error) });
5854
- return errorResult(
5855
- `Failed to list UI sessions: ${error instanceof Error ? error.message : String(error)}`
5856
- );
5857
- }
5858
- }
5859
- );
5860
- server.registerTool(
5861
- track(mcpToolName(ctx.productName, "ui_sessions_get_or_create")),
5862
- {
5863
- title: "Get or Create UI Session",
5864
- description: "Get (or lazily create) the UI session for the current user in a workspace.",
5865
- inputSchema: { workspaceId: zod.z.string().describe("Workspace ID (required)") }
5866
- },
5867
- async ({ workspaceId }) => {
5868
- try {
5869
- const data = await ctx.gql.workspace.request(GET_OR_CREATE_UI_SESSION, { workspaceId });
5870
- return jsonResult(data.planmagnetGetOrCreateUISession);
5871
- } catch (error) {
5872
- ctx.logger.error("planmagnet ui_sessions_get_or_create failed", { error: String(error) });
5873
- return errorResult(
5874
- `Failed to get/create UI session: ${error instanceof Error ? error.message : String(error)}`
5875
- );
5876
- }
5877
- }
5878
- );
5879
- server.registerTool(
5880
- track(mcpToolName(ctx.productName, "ui_sessions_update")),
5881
- {
5882
- title: "Update UI Session",
5883
- description: "Update the current user\u2019s UI-session view state.",
5884
- inputSchema: {
5885
- viewState: JsonValue.describe("Persisted view state JSON (filters, columns, sort, \u2026)"),
5886
- metadata: JsonObject.optional().describe("Arbitrary metadata JSON")
5887
- }
5888
- },
5889
- async ({ viewState, metadata }) => {
5890
- try {
5891
- const input = { viewState };
5892
- if (metadata !== void 0) input.metadata = metadata;
5893
- const data = await ctx.gql.workspace.request(UPDATE_UI_SESSION, { input });
5894
- return jsonResult(data.planmagnetUpdateUISession);
5895
- } catch (error) {
5896
- ctx.logger.error("planmagnet ui_sessions_update failed", { error: String(error) });
5897
- return errorResult(
5898
- `Failed to update UI session: ${error instanceof Error ? error.message : String(error)}`
5899
- );
5900
- }
5901
- }
5902
- );
5903
- server.registerTool(
5904
- track(mcpToolName(ctx.productName, "ui_sessions_delete")),
5905
- {
5906
- title: "Delete UI Session",
5907
- description: "Delete a UI session by ID.",
5908
- inputSchema: { id: zod.z.string().describe("UI session ID") }
5909
- },
5910
- async ({ id }) => {
5911
- try {
5912
- const data = await ctx.gql.workspace.request(
5913
- DELETE_UI_SESSION,
5914
- { id }
5915
- );
5916
- return jsonResult({ id, deleted: data.planmagnetDeleteUISession });
5917
- } catch (error) {
5918
- ctx.logger.error("planmagnet ui_sessions_delete failed", { error: String(error) });
5919
- return errorResult(
5920
- `Failed to delete UI session: ${error instanceof Error ? error.message : String(error)}`
5921
- );
5801
+ var DESTRUCTIVE_TOOL = /_(delete|remove|unlink)(_|$)/;
5802
+ var SALT = crypto.randomBytes(16).toString("hex");
5803
+ function canonical(value) {
5804
+ if (Array.isArray(value)) return `[${value.map(canonical).join(",")}]`;
5805
+ if (value && typeof value === "object") {
5806
+ const entries = Object.entries(value).filter(([, v]) => v !== void 0).sort(([a], [b]) => a.localeCompare(b));
5807
+ return `{${entries.map(([k, v]) => `${JSON.stringify(k)}:${canonical(v)}`).join(",")}}`;
5808
+ }
5809
+ return JSON.stringify(value);
5810
+ }
5811
+ function confirmTokenFor(tool, args) {
5812
+ return crypto.createHash("sha256").update(`${SALT}|${tool}|${canonical(args)}`).digest("hex").slice(0, 16);
5813
+ }
5814
+ function gateDestructiveTools(server) {
5815
+ const register = server.registerTool.bind(server);
5816
+ const gated = (name, config, handler) => {
5817
+ if (!DESTRUCTIVE_TOOL.test(name)) return register(name, config, handler);
5818
+ const declared = config;
5819
+ if (declared.inputSchema instanceof zod.z.ZodType) {
5820
+ throw new Error(`${name}: destructive tools must declare inputSchema as a raw zod shape`);
5821
+ }
5822
+ const annotations = { ...declared.annotations, destructiveHint: true, readOnlyHint: false };
5823
+ const inputSchema = {
5824
+ ...declared.inputSchema ?? {},
5825
+ confirmToken: zod.z.string().optional().describe(
5826
+ "Leave empty to preview (nothing changes). To act, pass the confirmToken from the preview of these exact arguments."
5827
+ )
5828
+ };
5829
+ const description = `${declared.description ?? ""} DESTRUCTIVE: the first call only previews and returns a confirmToken; call again with the same arguments and that token to proceed.`.trim();
5830
+ return register(
5831
+ name,
5832
+ // Cast: the SDK's config type is generic over the schema; the gate adds one optional field, a sentence and
5833
+ // the destructive annotations.
5834
+ {
5835
+ ...config,
5836
+ description,
5837
+ inputSchema,
5838
+ annotations
5839
+ },
5840
+ (args, extra) => {
5841
+ const { confirmToken, ...rest } = args;
5842
+ const token = confirmTokenFor(name, rest);
5843
+ if (confirmToken !== token) {
5844
+ return {
5845
+ content: [
5846
+ {
5847
+ type: "text",
5848
+ text: JSON.stringify(
5849
+ {
5850
+ dryRun: true,
5851
+ tool: name,
5852
+ arguments: rest,
5853
+ wouldDo: declared.description ?? name,
5854
+ confirmToken: token,
5855
+ note: confirmToken === void 0 ? "Nothing was changed. To proceed, call this tool again with the same arguments and this confirmToken." : "Nothing was changed: the confirmToken does not match these arguments. Review this preview and confirm with the new token."
5856
+ },
5857
+ null,
5858
+ 2
5859
+ )
5860
+ }
5861
+ ]
5862
+ };
5863
+ }
5864
+ return handler(rest, extra);
5922
5865
  }
5866
+ );
5867
+ };
5868
+ return new Proxy(server, {
5869
+ get(target, prop, receiver) {
5870
+ if (prop === "registerTool") return gated;
5871
+ const value = Reflect.get(target, prop, receiver);
5872
+ return typeof value === "function" ? value.bind(target) : value;
5923
5873
  }
5924
- );
5874
+ });
5925
5875
  }
5926
5876
 
5927
5877
  // src/modules/planmagnet/resources.ts
@@ -5963,7 +5913,6 @@ Portfolio > Program > Project > (Work Items, Sprints, Boards, Milestones, \u2026
5963
5913
  - CustomFieldDefinition (+CustomFieldValue) \u2014 extensible fields
5964
5914
  - ProjectTemplate \u2014 reusable blueprints
5965
5915
  - ExternalSync (+ExternalMapping) \u2014 integrations (Jira, GitHub, Linear, \u2026)
5966
- - PlanmagnetUISession \u2014 persisted per-user view state
5967
5916
 
5968
5917
  ## Key enums
5969
5918
  - WorkItemType: BUG, EPIC, STORY, SUB_TASK, TASK
@@ -6141,24 +6090,24 @@ var planmagnetModule = {
6141
6090
  prompts.push(n);
6142
6091
  return n;
6143
6092
  };
6144
- registerProjectTools(server, ctx, trackTool);
6145
- registerWorkItemTools(server, ctx, trackTool);
6146
- registerSprintTools(server, ctx, trackTool);
6147
- registerBoardTools(server, ctx, trackTool);
6148
- registerMilestoneTools(server, ctx, trackTool);
6149
- registerDependencyTools(server, ctx, trackTool);
6150
- registerBudgetTools(server, ctx, trackTool);
6151
- registerRiskTools(server, ctx, trackTool);
6152
- registerReleaseTools(server, ctx, trackTool);
6153
- registerQualityGateTools(server, ctx, trackTool);
6154
- registerRoadmapTools(server, ctx, trackTool);
6155
- registerTimeTrackingTools(server, ctx, trackTool);
6156
- registerAutomationTools(server, ctx, trackTool);
6157
- registerFeatureTools(server, ctx, trackTool);
6158
- registerCustomFieldTools(server, ctx, trackTool);
6159
- registerTemplateTools(server, ctx, trackTool);
6160
- registerSyncTools(server, ctx, trackTool);
6161
- registerUiSessionTools(server, ctx, trackTool);
6093
+ const toolServer = gateDestructiveTools(server);
6094
+ registerProjectTools(toolServer, ctx, trackTool);
6095
+ registerWorkItemTools(toolServer, ctx, trackTool);
6096
+ registerSprintTools(toolServer, ctx, trackTool);
6097
+ registerBoardTools(toolServer, ctx, trackTool);
6098
+ registerMilestoneTools(toolServer, ctx, trackTool);
6099
+ registerDependencyTools(toolServer, ctx, trackTool);
6100
+ registerBudgetTools(toolServer, ctx, trackTool);
6101
+ registerRiskTools(toolServer, ctx, trackTool);
6102
+ registerReleaseTools(toolServer, ctx, trackTool);
6103
+ registerQualityGateTools(toolServer, ctx, trackTool);
6104
+ registerRoadmapTools(toolServer, ctx, trackTool);
6105
+ registerTimeTrackingTools(toolServer, ctx, trackTool);
6106
+ registerAutomationTools(toolServer, ctx, trackTool);
6107
+ registerFeatureTools(toolServer, ctx, trackTool);
6108
+ registerCustomFieldTools(toolServer, ctx, trackTool);
6109
+ registerTemplateTools(toolServer, ctx, trackTool);
6110
+ registerSyncTools(toolServer, ctx, trackTool);
6162
6111
  registerPlanmagnetResources(server, ctx, trackResource);
6163
6112
  registerPlanmagnetPrompts(server, ctx, trackPrompt);
6164
6113
  return { tools, resources, prompts };