@sonenta/mcp 0.30.0 → 0.32.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sonenta/mcp",
3
- "version": "0.30.0",
3
+ "version": "0.32.0",
4
4
  "description": "MCP server for Sonenta translation management \u2014 wires Claude Desktop and other MCP clients into your project's keys, missing-key feed, and translation drafts.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://sonenta.com",
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "sonenta-mcp"
3
- version = "0.30.0"
3
+ version = "0.32.0"
4
4
  description = "Model Context Protocol server for Sonenta — list projects, missing keys, propose translations from Claude Desktop and other MCP clients."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.12,<3.14"
@@ -1,3 +1,3 @@
1
1
  """Sonenta MCP server (MIT)."""
2
2
 
3
- __version__ = "0.30.0"
3
+ __version__ = "0.32.0"
@@ -89,23 +89,33 @@ from .client import VerbumiaApiError, VerbumiaClient
89
89
  # visible text. `surfaceKinds` in the variants matrix tags each as a11y.
90
90
  A11Y_SURFACES = ("aria_label", "alt_text", "screen_reader", "plain_language")
91
91
 
92
- # RS1 (task 1367): audit trail of code edits an agent made while resolving a
93
- # duplicate group — passed on set_source_duplicate_merge_plan / set_duplicate_status,
94
- # persisted + surfaced in resolved_duplicates[]. Supplying it overwrites; omitting
95
- # preserves the prior value.
92
+ # RS1 (1367) + FM1 (1390) + FF1 (1397): audit trail of t() repoints an agent made
93
+ # while resolving a duplicate group — accepted on ALL FOUR resolution paths
94
+ # (set_source_duplicate_merge_plan, set_duplicate_status, apply_new_key_cluster,
95
+ # mark_cluster_applied), persisted + surfaced in resolved_duplicates[]. UNION-MERGE
96
+ # (accumulate + dedup by normalized entry). FF1 split key_name into found_key +
97
+ # replacement_key (key_name kept, deprecated).
96
98
  _FILES_MODIFIED_SCHEMA = {
97
99
  "type": "array",
98
100
  "description": (
99
- "Optional audit trail of the code edits you made (e.g. t() repoints) while "
100
- "resolving this group: each {path (required), line?, key_name?}. Supplying it "
101
- "overwrites the stored record; omit to preserve the prior value."
101
+ "Optional audit trail of the t() repoints you made while resolving this group: "
102
+ "each {path (required), line?, found_key, replacement_key, occurrences?}. "
103
+ "`found_key` = the key string that WAS in the code at this spot (the old, "
104
+ "redundant one); `replacement_key` = the canonical you repointed it to (an "
105
+ "existing survivor, OR the new_key from apply_new_key_cluster). Accepted on "
106
+ "every resolution path and MERGED (union + dedup by the full normalized entry) "
107
+ "— record edits at whatever step you make them and they accumulate; omit to "
108
+ "preserve the existing list. Always pass the STRUCTURED field, never just a note."
102
109
  ),
103
110
  "items": {
104
111
  "type": "object",
105
112
  "properties": {
106
113
  "path": {"type": "string", "description": "Repo-relative file path that was edited."},
107
114
  "line": {"type": "integer", "description": "Optional 1-based line number of the edit."},
108
- "key_name": {"type": "string", "description": "Optional key (namespace::name or name) the edit concerns."},
115
+ "found_key": {"type": "string", "description": "The OLD key found in the code at this spot (the redundant one being repointed away)."},
116
+ "replacement_key": {"type": "string", "description": "The CANONICAL key you repointed to (an existing survivor, or the created new_key)."},
117
+ "occurrences": {"type": "integer", "description": "Optional count of how many usages you replaced here."},
118
+ "key_name": {"type": "string", "description": "DEPRECATED (pre-FF1 single field) — prefer found_key + replacement_key."},
109
119
  },
110
120
  "required": ["path"],
111
121
  "additionalProperties": False,
@@ -2291,6 +2301,7 @@ def register(server: Server, client: VerbumiaClient) -> tuple[Any, Any]:
2291
2301
  "type": "boolean",
2292
2302
  "description": "True to mark applied (default), false to un-mark.",
2293
2303
  },
2304
+ "files_modified": _FILES_MODIFIED_SCHEMA,
2294
2305
  },
2295
2306
  "required": ["source_value", "canonical_key_uuid"],
2296
2307
  "additionalProperties": False,
@@ -2308,8 +2319,8 @@ def register(server: Server, client: VerbumiaClient) -> tuple[Any, Any]:
2308
2319
  "the name must be free). Returns {new_key_uuid, name, namespace, "
2309
2320
  "copied_from_key_uuid, copied_languages, trashed_key_uuids}. YOUR job "
2310
2321
  "after this is the CODE only: repoint every t() usage of the trashed "
2311
- "keys onto new_key_uuid, then record it via set_source_duplicate_merge_"
2312
- "plan / set_duplicate_status files_modified. You do NOT create_key or "
2322
+ "keys onto new_key_uuid, and record those edits in `files_modified` "
2323
+ "(accepted right here, union-merged). You do NOT create_key or "
2313
2324
  "delete_keys_bulk yourself — the backend owns that. Author the "
2314
2325
  "new_key cluster in the merge plan first (on the dev's acceptance)."
2315
2326
  ),
@@ -2333,6 +2344,7 @@ def register(server: Server, client: VerbumiaClient) -> tuple[Any, Any]:
2333
2344
  },
2334
2345
  "required": ["name", "namespace"],
2335
2346
  },
2347
+ "files_modified": _FILES_MODIFIED_SCHEMA,
2336
2348
  },
2337
2349
  "required": ["source_value", "new_key"],
2338
2350
  "additionalProperties": False,
@@ -3088,6 +3100,8 @@ def register(server: Server, client: VerbumiaClient) -> tuple[Any, Any]:
3088
3100
  }
3089
3101
  if "applied" in args:
3090
3102
  body["applied"] = bool(args["applied"])
3103
+ if args.get("files_modified"):
3104
+ body["files_modified"] = args["files_modified"]
3091
3105
  data = await client.put(
3092
3106
  f"/v1/mcp/projects/{project_uuid}/source-duplicates/cluster-applied",
3093
3107
  json=body,
@@ -3100,9 +3114,12 @@ def register(server: Server, client: VerbumiaClient) -> tuple[Any, Any]:
3100
3114
  return _err("source_value and new_key {name, namespace} are required")
3101
3115
  if not new_key.get("name") or not new_key.get("namespace"):
3102
3116
  return _err("new_key requires name and namespace")
3117
+ body = {"source_value": args["source_value"], "new_key": new_key}
3118
+ if args.get("files_modified"):
3119
+ body["files_modified"] = args["files_modified"]
3103
3120
  data = await client.post(
3104
3121
  f"/v1/mcp/projects/{project_uuid}/source-duplicates/apply-cluster",
3105
- json={"source_value": args["source_value"], "new_key": new_key},
3122
+ json=body,
3106
3123
  )
3107
3124
  return _text(data)
3108
3125
  return _err(f"unknown tool: {name}")