@sonenta/mcp 0.21.3 → 0.22.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.21.3",
3
+ "version": "0.22.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.21.3"
3
+ version = "0.22.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.21.3"
3
+ __version__ = "0.22.0"
@@ -1535,6 +1535,79 @@ def register(server: Server, client: VerbumiaClient) -> tuple[Any, Any]:
1535
1535
  "additionalProperties": False,
1536
1536
  },
1537
1537
  ),
1538
+ Tool(
1539
+ name="recommend_surfaces",
1540
+ description=(
1541
+ "Read-only per-key A11Y SURFACE RECOMMENDATIONS (#2): for each key, "
1542
+ "the a11y surfaces implied by its semantic TYPE, derived from the "
1543
+ "backend's authoritative key.type -> treatment mapping "
1544
+ "(A11Y_TREATMENTS_BY_TYPE) — the single source of truth; do NOT "
1545
+ "reimplement the mapping in the client. Returns {project_uuid, "
1546
+ "version_uuid, active_a11y_surfaces[], keys_scanned, keys_with_gaps, "
1547
+ "gaps_by_surface{surface:int}, items:[{key_uuid, key_name, "
1548
+ "namespace_slug, type, base_role (visible_text|alt_text|"
1549
+ "accessible_name), recommended_surfaces:[{surface, active, "
1550
+ "present_in_source}], has_gap}]}. A recommended surface that is "
1551
+ "active && !present_in_source is a config-satisfied GAP to AUTHOR — "
1552
+ "hand the actual text off to sonenta-a11y (set_a11y_variant), this "
1553
+ "tool only tells you WHERE. DEVICE surfaces are not included here. "
1554
+ "Defaults to the production version."
1555
+ ),
1556
+ inputSchema={
1557
+ "type": "object",
1558
+ "properties": {
1559
+ "project_uuid": {
1560
+ "type": "string",
1561
+ "description": "Project UUID. Required when multiple projects are configured (SONENTA_PROJECTS); defaults to the single configured project otherwise.",
1562
+ },
1563
+ "version_id": {
1564
+ "type": "string",
1565
+ "description": "Optional version UUID; defaults to the production version.",
1566
+ },
1567
+ "namespace_id": {
1568
+ "type": "string",
1569
+ "description": "Optional namespace UUID to scope the scan.",
1570
+ },
1571
+ "key_id": {
1572
+ "type": "string",
1573
+ "description": "Optional single key UUID to scope the scan.",
1574
+ },
1575
+ "only_gaps": {
1576
+ "type": "boolean",
1577
+ "description": "When true, return only keys that have a gap (has_gap=true).",
1578
+ },
1579
+ },
1580
+ "additionalProperties": False,
1581
+ },
1582
+ ),
1583
+ Tool(
1584
+ name="surface_coverage",
1585
+ description=(
1586
+ "Read-only COVERAGE BY SURFACE (#3): per active surface, how complete "
1587
+ "it is. Returns {project_uuid, version_uuid, languages[], keys_total, "
1588
+ "surfaces:[{surface, label, kind, meaning, eligible_keys, "
1589
+ "eligible_cells, present_cells, pct, by_language:[{code, eligible, "
1590
+ "present, pct}]}]}. The `meaning` field tells you how to read `pct`: "
1591
+ "'a11y_completeness' for a11y surfaces (eligible = type-relevant keys; "
1592
+ "pct = real fill of NEEDED a11y gaps), 'override_density' for device "
1593
+ "surfaces (un-overridden cells fall back to the base value — that is "
1594
+ "NOT broken, just un-customized). Defaults to the production version."
1595
+ ),
1596
+ inputSchema={
1597
+ "type": "object",
1598
+ "properties": {
1599
+ "project_uuid": {
1600
+ "type": "string",
1601
+ "description": "Project UUID. Required when multiple projects are configured (SONENTA_PROJECTS); defaults to the single configured project otherwise.",
1602
+ },
1603
+ "version_id": {
1604
+ "type": "string",
1605
+ "description": "Optional version UUID; defaults to the production version.",
1606
+ },
1607
+ },
1608
+ "additionalProperties": False,
1609
+ },
1610
+ ),
1538
1611
  Tool(
1539
1612
  name="get_variants",
1540
1613
  description=(
@@ -2339,6 +2412,29 @@ def register(server: Server, client: VerbumiaClient) -> tuple[Any, Any]:
2339
2412
  return _err("slug is required")
2340
2413
  await client.delete(f"/v1/mcp/projects/{project_uuid}/surfaces/{slug}")
2341
2414
  return _text({"deleted": True, "slug": slug})
2415
+ if name == "recommend_surfaces":
2416
+ project_uuid = _project_uuid(args, client)
2417
+ params: dict[str, Any] = {}
2418
+ for opt in ("version_id", "namespace_id", "key_id"):
2419
+ if args.get(opt):
2420
+ params[opt] = args[opt]
2421
+ if args.get("only_gaps"):
2422
+ params["only_gaps"] = "true"
2423
+ data = await client.get(
2424
+ f"/v1/mcp/projects/{project_uuid}/recommend-surfaces",
2425
+ params=params,
2426
+ )
2427
+ return _text(data)
2428
+ if name == "surface_coverage":
2429
+ project_uuid = _project_uuid(args, client)
2430
+ params: dict[str, Any] = {}
2431
+ if args.get("version_id"):
2432
+ params["version_id"] = args["version_id"]
2433
+ data = await client.get(
2434
+ f"/v1/mcp/projects/{project_uuid}/surface-coverage",
2435
+ params=params,
2436
+ )
2437
+ return _text(data)
2342
2438
  if name == "get_variants":
2343
2439
  project_uuid = _project_uuid(args, client)
2344
2440
  key_uuid = args.get("key_uuid")