@codazen/harmonica-mcp 0.25.0 → 0.25.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.
Files changed (2) hide show
  1. package/dist/index.js +26 -8
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -25154,11 +25154,14 @@ function registerSnapshotTools(server, ctx, client) {
25154
25154
  "",
25155
25155
  ...versionNote,
25156
25156
  ` Beats: ${snapshot.beats.length}`,
25157
+ ` Beat Versions: ${snapshot.beatVersions?.length ?? 0}`,
25157
25158
  ` Proposals: ${snapshot.proposals.length}`,
25158
25159
  ` Notes: ${snapshot.notes.length}`,
25159
25160
  ` Tasks: ${snapshot.tasks.length}`,
25160
25161
  ` Submissions: ${snapshot.submissions.length}`,
25161
25162
  ` PromptLogs: ${snapshot.promptLogs.length}`,
25163
+ ` Drops: ${snapshot.drops?.length ?? 0}`,
25164
+ ` Deliverables: ${snapshot.deliverables?.length ?? 0}`,
25162
25165
  "",
25163
25166
  "Use import_project_snapshot with this file path to import into another environment."
25164
25167
  ];
@@ -25169,9 +25172,12 @@ function registerSnapshotTools(server, ctx, client) {
25169
25172
  "import_project_snapshot",
25170
25173
  "Import a project snapshot into the current environment. Accepts an S3 presigned URL (https:// only), a file path, or inline JSON. Blocked in production by default.",
25171
25174
  {
25172
- snapshot: external_exports.string().describe("S3 presigned URL (https://...), file path, or inline JSON string")
25175
+ snapshot: external_exports.string().describe("S3 presigned URL (https://...), file path, or inline JSON string"),
25176
+ targetTeamspaceId: external_exports.string().min(1).optional().describe(
25177
+ "Remap all teamspace references (Drops, Deliverables, Project record) to this teamspace ID in the target environment. Required when the source and target environments use different teamspace UUIDs. When omitted and the snapshot contains Drops or Deliverables, a warning is included in the import summary."
25178
+ )
25173
25179
  },
25174
- async ({ snapshot: snapshotInput }) => {
25180
+ async ({ snapshot: snapshotInput, targetTeamspaceId }) => {
25175
25181
  const isProduction = process.env.NODE_ENV === "production";
25176
25182
  const importAllowed = process.env.ALLOW_PROJECT_IMPORT === "true";
25177
25183
  if (isProduction && !importAllowed) {
@@ -25184,13 +25190,13 @@ function registerSnapshotTools(server, ctx, client) {
25184
25190
  };
25185
25191
  }
25186
25192
  const trimmed = snapshotInput.trim();
25187
- const importOptions = { targetOrgId: ctx.orgId, targetUserId: ctx.user.userId };
25193
+ const importOptions = { targetOrgId: ctx.orgId, targetUserId: ctx.user.userId, targetTeamspaceId };
25188
25194
  if (trimmed.startsWith("https://")) {
25189
25195
  if (isPrivateHost(trimmed)) {
25190
25196
  throw new Error("Snapshot URL must point to a public host \u2014 private, link-local, and loopback addresses are not permitted.");
25191
25197
  }
25192
25198
  const result2 = await client.importProjectSnapshotFromUrl(trimmed, importOptions);
25193
- return { content: [{ type: "text", text: formatImportSummary(result2) }] };
25199
+ return { content: [{ type: "text", text: formatImportSummary(result2, targetTeamspaceId) }] };
25194
25200
  }
25195
25201
  if (trimmed.startsWith("http://")) {
25196
25202
  throw new Error("Snapshot URL must use https:// \u2014 http:// is not permitted.");
@@ -25205,7 +25211,7 @@ function registerSnapshotTools(server, ctx, client) {
25205
25211
  assertSnapshotShape(parsed, "");
25206
25212
  const normalized = normalizeSnapshot(parsed);
25207
25213
  const result = await client.importProjectSnapshot(normalized, importOptions);
25208
- return { content: [{ type: "text", text: formatImportSummary(result) }] };
25214
+ return { content: [{ type: "text", text: formatImportSummary(result, targetTeamspaceId) }] };
25209
25215
  }
25210
25216
  );
25211
25217
  }
@@ -25248,7 +25254,7 @@ async function resolveSnapshotInput(input) {
25248
25254
  }
25249
25255
  return trimmed;
25250
25256
  }
25251
- function formatImportSummary(result) {
25257
+ function formatImportSummary(result, targetTeamspaceId) {
25252
25258
  const lines = [
25253
25259
  `Imported project: ${result.projectId}`,
25254
25260
  ` Beats: ${result.counts.beats}`,
@@ -25259,12 +25265,24 @@ function formatImportSummary(result) {
25259
25265
  ` Notes: ${result.counts.notes}`,
25260
25266
  ` Tasks: ${result.counts.tasks}`,
25261
25267
  ` Submissions: ${result.counts.submissions}`,
25262
- ` PromptLogs: ${result.counts.promptLogs}`
25268
+ ` PromptLogs: ${result.counts.promptLogs}`,
25269
+ ` Beat Versions: ${result.counts.beatVersions ?? 0}`,
25270
+ ` Drops: ${result.counts.drops ?? 0}`,
25271
+ ` Deliverables: ${result.counts.deliverables ?? 0}`
25263
25272
  ];
25264
25273
  if (result.errors.length > 0) {
25265
25274
  lines.push("", `Errors (${result.errors.length}):`);
25266
25275
  result.errors.forEach((e) => lines.push(` - ${e}`));
25267
25276
  }
25277
+ const hasTeamspaceData = result.projectTeamspaceId !== void 0 || (result.counts.drops ?? 0) + (result.counts.deliverables ?? 0) > 0;
25278
+ if (!targetTeamspaceId && hasTeamspaceData) {
25279
+ lines.push(
25280
+ "",
25281
+ "Warning: snapshot contains teamspace-scoped data but targetTeamspaceId was not provided.",
25282
+ "The project record and any Drops or Deliverables were imported with their original teamspaceId and may not appear under the correct teamspace in this environment.",
25283
+ "Re-run with targetTeamspaceId set to the target teamspace UUID to remap them."
25284
+ );
25285
+ }
25268
25286
  return lines.join("\n");
25269
25287
  }
25270
25288
  function isPrivateHost(url) {
@@ -27038,7 +27056,7 @@ function loadConfig() {
27038
27056
  };
27039
27057
  }
27040
27058
  async function main() {
27041
- console.error(`[harmonica-mcp] v${"0.25.0"} starting\u2026`);
27059
+ console.error(`[harmonica-mcp] v${"0.25.2"} starting\u2026`);
27042
27060
  const config2 = loadConfig();
27043
27061
  const client = createHttpClient({
27044
27062
  apiBaseUrl: config2.apiBaseUrl,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codazen/harmonica-mcp",
3
- "version": "0.25.0",
3
+ "version": "0.25.2",
4
4
  "description": "MCP server for Harmonica — connect Claude to your Harmonica projects",
5
5
  "license": "MIT",
6
6
  "bin": {