@burdenoff/mcp-libs 2026.908.2 → 2026.928.1

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.
@@ -1,5 +1,6 @@
1
1
  import { mcpToolName, errorResult, jsonResult, mcpResourceUri, mcpPromptName } from '../../chunk-BSNL65PZ.js';
2
2
  import { z } from 'zod';
3
+ import { randomBytes, createHash } from 'crypto';
3
4
 
4
5
  // src/modules/planmagnet/operations.ts
5
6
  var PAGE_INFO = `
@@ -132,9 +133,6 @@ var SYNC_RESULT_FIELDS = `
132
133
  syncId success itemsCreated itemsUpdated itemsSkipped errorCount errors
133
134
  durationMs syncedAt
134
135
  `;
135
- var UI_SESSION_FIELDS = `
136
- id userId state metadata workspaceId createdAt updatedAt
137
- `;
138
136
  var GET_PROJECT = `
139
137
  query PlanmagnetProject($id: ID!) {
140
138
  planmagnetProject(id: $id) { ${PROJECT_FIELDS} }
@@ -1074,33 +1072,6 @@ var IMPORT_FROM_EXTERNAL = `
1074
1072
  planmagnetImportFromExternal(input: $input) { ${SYNC_RESULT_FIELDS} }
1075
1073
  }
1076
1074
  `;
1077
- var GET_OR_CREATE_UI_SESSION = `
1078
- query PlanmagnetGetOrCreateUISession($workspaceId: ID!) {
1079
- planmagnetGetOrCreateUISession(workspaceId: $workspaceId) { ${UI_SESSION_FIELDS} }
1080
- }
1081
- `;
1082
- var LIST_UI_SESSIONS = `
1083
- query PlanmagnetUiSessions(
1084
- $workspaceId: ID!
1085
- $filter: PlanmagnetUISessionFilter
1086
- $pagination: PlanmagnetPaginationInput
1087
- ) {
1088
- planmagnetUiSessions(workspaceId: $workspaceId, filter: $filter, pagination: $pagination) {
1089
- items { ${UI_SESSION_FIELDS} }
1090
- ${PAGE_INFO}
1091
- }
1092
- }
1093
- `;
1094
- var UPDATE_UI_SESSION = `
1095
- mutation PlanmagnetUpdateUISession($input: PlanmagnetUISessionViewStateInput!) {
1096
- planmagnetUpdateUISession(input: $input) { ${UI_SESSION_FIELDS} }
1097
- }
1098
- `;
1099
- var DELETE_UI_SESSION = `
1100
- mutation PlanmagnetDeleteUISession($id: ID!) {
1101
- planmagnetDeleteUISession(id: $id)
1102
- }
1103
- `;
1104
1075
  var JsonObject = z.record(z.string(), z.unknown());
1105
1076
  var JsonValue = z.union([JsonObject, z.array(z.unknown())]);
1106
1077
  var paginationInputShape = {
@@ -5766,101 +5737,80 @@ function registerSyncTools(server, ctx, track) {
5766
5737
  }
5767
5738
  );
5768
5739
  }
5769
- function registerUiSessionTools(server, ctx, track) {
5770
- server.registerTool(
5771
- track(mcpToolName(ctx.productName, "ui_sessions_list")),
5772
- {
5773
- title: "List UI Sessions",
5774
- description: "List persisted UI sessions for the current user in a workspace.",
5775
- inputSchema: {
5776
- workspaceId: z.string().describe("Workspace ID (required)"),
5777
- userId: z.string().optional().describe("Filter by user actor ID"),
5778
- ...paginationInputShape
5779
- }
5780
- },
5781
- async ({ workspaceId, userId, first, after }) => {
5782
- try {
5783
- const filter = {};
5784
- if (userId !== void 0) filter.userId = userId;
5785
- const data = await ctx.gql.workspace.request(LIST_UI_SESSIONS, {
5786
- workspaceId,
5787
- filter: Object.keys(filter).length > 0 ? filter : void 0,
5788
- pagination: buildPagination(first, after)
5789
- });
5790
- return jsonResult(data.planmagnetUiSessions);
5791
- } catch (error) {
5792
- ctx.logger.error("planmagnet ui_sessions_list failed", { error: String(error) });
5793
- return errorResult(
5794
- `Failed to list UI sessions: ${error instanceof Error ? error.message : String(error)}`
5795
- );
5796
- }
5797
- }
5798
- );
5799
- server.registerTool(
5800
- track(mcpToolName(ctx.productName, "ui_sessions_get_or_create")),
5801
- {
5802
- title: "Get or Create UI Session",
5803
- description: "Get (or lazily create) the UI session for the current user in a workspace.",
5804
- inputSchema: { workspaceId: z.string().describe("Workspace ID (required)") }
5805
- },
5806
- async ({ workspaceId }) => {
5807
- try {
5808
- const data = await ctx.gql.workspace.request(GET_OR_CREATE_UI_SESSION, { workspaceId });
5809
- return jsonResult(data.planmagnetGetOrCreateUISession);
5810
- } catch (error) {
5811
- ctx.logger.error("planmagnet ui_sessions_get_or_create failed", { error: String(error) });
5812
- return errorResult(
5813
- `Failed to get/create UI session: ${error instanceof Error ? error.message : String(error)}`
5814
- );
5815
- }
5816
- }
5817
- );
5818
- server.registerTool(
5819
- track(mcpToolName(ctx.productName, "ui_sessions_update")),
5820
- {
5821
- title: "Update UI Session",
5822
- description: "Update the current user\u2019s UI-session view state.",
5823
- inputSchema: {
5824
- viewState: JsonValue.describe("Persisted view state JSON (filters, columns, sort, \u2026)"),
5825
- metadata: JsonObject.optional().describe("Arbitrary metadata JSON")
5826
- }
5827
- },
5828
- async ({ viewState, metadata }) => {
5829
- try {
5830
- const input = { viewState };
5831
- if (metadata !== void 0) input.metadata = metadata;
5832
- const data = await ctx.gql.workspace.request(UPDATE_UI_SESSION, { input });
5833
- return jsonResult(data.planmagnetUpdateUISession);
5834
- } catch (error) {
5835
- ctx.logger.error("planmagnet ui_sessions_update failed", { error: String(error) });
5836
- return errorResult(
5837
- `Failed to update UI session: ${error instanceof Error ? error.message : String(error)}`
5838
- );
5839
- }
5840
- }
5841
- );
5842
- server.registerTool(
5843
- track(mcpToolName(ctx.productName, "ui_sessions_delete")),
5844
- {
5845
- title: "Delete UI Session",
5846
- description: "Delete a UI session by ID.",
5847
- inputSchema: { id: z.string().describe("UI session ID") }
5848
- },
5849
- async ({ id }) => {
5850
- try {
5851
- const data = await ctx.gql.workspace.request(
5852
- DELETE_UI_SESSION,
5853
- { id }
5854
- );
5855
- return jsonResult({ id, deleted: data.planmagnetDeleteUISession });
5856
- } catch (error) {
5857
- ctx.logger.error("planmagnet ui_sessions_delete failed", { error: String(error) });
5858
- return errorResult(
5859
- `Failed to delete UI session: ${error instanceof Error ? error.message : String(error)}`
5860
- );
5740
+ var DESTRUCTIVE_TOOL = /_(delete|remove|unlink)(_|$)/;
5741
+ var SALT = randomBytes(16).toString("hex");
5742
+ function canonical(value) {
5743
+ if (Array.isArray(value)) return `[${value.map(canonical).join(",")}]`;
5744
+ if (value && typeof value === "object") {
5745
+ const entries = Object.entries(value).filter(([, v]) => v !== void 0).sort(([a], [b]) => a.localeCompare(b));
5746
+ return `{${entries.map(([k, v]) => `${JSON.stringify(k)}:${canonical(v)}`).join(",")}}`;
5747
+ }
5748
+ return JSON.stringify(value);
5749
+ }
5750
+ function confirmTokenFor(tool, args) {
5751
+ return createHash("sha256").update(`${SALT}|${tool}|${canonical(args)}`).digest("hex").slice(0, 16);
5752
+ }
5753
+ function gateDestructiveTools(server) {
5754
+ const register = server.registerTool.bind(server);
5755
+ const gated = (name, config, handler) => {
5756
+ if (!DESTRUCTIVE_TOOL.test(name)) return register(name, config, handler);
5757
+ const declared = config;
5758
+ if (declared.inputSchema instanceof z.ZodType) {
5759
+ throw new Error(`${name}: destructive tools must declare inputSchema as a raw zod shape`);
5760
+ }
5761
+ const annotations = { ...declared.annotations, destructiveHint: true, readOnlyHint: false };
5762
+ const inputSchema = {
5763
+ ...declared.inputSchema ?? {},
5764
+ confirmToken: z.string().optional().describe(
5765
+ "Leave empty to preview (nothing changes). To act, pass the confirmToken from the preview of these exact arguments."
5766
+ )
5767
+ };
5768
+ 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();
5769
+ return register(
5770
+ name,
5771
+ // Cast: the SDK's config type is generic over the schema; the gate adds one optional field, a sentence and
5772
+ // the destructive annotations.
5773
+ {
5774
+ ...config,
5775
+ description,
5776
+ inputSchema,
5777
+ annotations
5778
+ },
5779
+ (args, extra) => {
5780
+ const { confirmToken, ...rest } = args;
5781
+ const token = confirmTokenFor(name, rest);
5782
+ if (confirmToken !== token) {
5783
+ return {
5784
+ content: [
5785
+ {
5786
+ type: "text",
5787
+ text: JSON.stringify(
5788
+ {
5789
+ dryRun: true,
5790
+ tool: name,
5791
+ arguments: rest,
5792
+ wouldDo: declared.description ?? name,
5793
+ confirmToken: token,
5794
+ 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."
5795
+ },
5796
+ null,
5797
+ 2
5798
+ )
5799
+ }
5800
+ ]
5801
+ };
5802
+ }
5803
+ return handler(rest, extra);
5861
5804
  }
5805
+ );
5806
+ };
5807
+ return new Proxy(server, {
5808
+ get(target, prop, receiver) {
5809
+ if (prop === "registerTool") return gated;
5810
+ const value = Reflect.get(target, prop, receiver);
5811
+ return typeof value === "function" ? value.bind(target) : value;
5862
5812
  }
5863
- );
5813
+ });
5864
5814
  }
5865
5815
 
5866
5816
  // src/modules/planmagnet/resources.ts
@@ -5902,7 +5852,6 @@ Portfolio > Program > Project > (Work Items, Sprints, Boards, Milestones, \u2026
5902
5852
  - CustomFieldDefinition (+CustomFieldValue) \u2014 extensible fields
5903
5853
  - ProjectTemplate \u2014 reusable blueprints
5904
5854
  - ExternalSync (+ExternalMapping) \u2014 integrations (Jira, GitHub, Linear, \u2026)
5905
- - PlanmagnetUISession \u2014 persisted per-user view state
5906
5855
 
5907
5856
  ## Key enums
5908
5857
  - WorkItemType: BUG, EPIC, STORY, SUB_TASK, TASK
@@ -6080,24 +6029,24 @@ var planmagnetModule = {
6080
6029
  prompts.push(n);
6081
6030
  return n;
6082
6031
  };
6083
- registerProjectTools(server, ctx, trackTool);
6084
- registerWorkItemTools(server, ctx, trackTool);
6085
- registerSprintTools(server, ctx, trackTool);
6086
- registerBoardTools(server, ctx, trackTool);
6087
- registerMilestoneTools(server, ctx, trackTool);
6088
- registerDependencyTools(server, ctx, trackTool);
6089
- registerBudgetTools(server, ctx, trackTool);
6090
- registerRiskTools(server, ctx, trackTool);
6091
- registerReleaseTools(server, ctx, trackTool);
6092
- registerQualityGateTools(server, ctx, trackTool);
6093
- registerRoadmapTools(server, ctx, trackTool);
6094
- registerTimeTrackingTools(server, ctx, trackTool);
6095
- registerAutomationTools(server, ctx, trackTool);
6096
- registerFeatureTools(server, ctx, trackTool);
6097
- registerCustomFieldTools(server, ctx, trackTool);
6098
- registerTemplateTools(server, ctx, trackTool);
6099
- registerSyncTools(server, ctx, trackTool);
6100
- registerUiSessionTools(server, ctx, trackTool);
6032
+ const toolServer = gateDestructiveTools(server);
6033
+ registerProjectTools(toolServer, ctx, trackTool);
6034
+ registerWorkItemTools(toolServer, ctx, trackTool);
6035
+ registerSprintTools(toolServer, ctx, trackTool);
6036
+ registerBoardTools(toolServer, ctx, trackTool);
6037
+ registerMilestoneTools(toolServer, ctx, trackTool);
6038
+ registerDependencyTools(toolServer, ctx, trackTool);
6039
+ registerBudgetTools(toolServer, ctx, trackTool);
6040
+ registerRiskTools(toolServer, ctx, trackTool);
6041
+ registerReleaseTools(toolServer, ctx, trackTool);
6042
+ registerQualityGateTools(toolServer, ctx, trackTool);
6043
+ registerRoadmapTools(toolServer, ctx, trackTool);
6044
+ registerTimeTrackingTools(toolServer, ctx, trackTool);
6045
+ registerAutomationTools(toolServer, ctx, trackTool);
6046
+ registerFeatureTools(toolServer, ctx, trackTool);
6047
+ registerCustomFieldTools(toolServer, ctx, trackTool);
6048
+ registerTemplateTools(toolServer, ctx, trackTool);
6049
+ registerSyncTools(toolServer, ctx, trackTool);
6101
6050
  registerPlanmagnetResources(server, ctx, trackResource);
6102
6051
  registerPlanmagnetPrompts(server, ctx, trackPrompt);
6103
6052
  return { tools, resources, prompts };