@sonenta/mcp 0.21.2 → 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/README.md +2 -2
- package/package.json +1 -1
- package/python/README.md +2 -2
- package/python/dist/sonenta_mcp-0.22.0-py3-none-any.whl +0 -0
- package/python/pyproject.toml +1 -1
- package/python/verbumia_mcp/__init__.py +1 -1
- package/python/verbumia_mcp/config.py +1 -1
- package/python/verbumia_mcp/tools.py +139 -0
- package/python/dist/sonenta_mcp-0.21.2-py3-none-any.whl +0 -0
package/README.md
CHANGED
|
@@ -18,7 +18,7 @@ runs the bundled `sonenta-mcp` directly.
|
|
|
18
18
|
"env": {
|
|
19
19
|
"SONENTA_API_KEY": "vrb_live_<prefix>.<secret>",
|
|
20
20
|
"SONENTA_PROJECTS": "<project_uuid>",
|
|
21
|
-
"SONENTA_BASE_URL": "https://api.sonenta.
|
|
21
|
+
"SONENTA_BASE_URL": "https://api.sonenta.com"
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
24
|
}
|
|
@@ -64,7 +64,7 @@ Stdio is fully passthrough so the MCP JSON-RPC framing is preserved.
|
|
|
64
64
|
| Var | Required | Default | Notes |
|
|
65
65
|
|----------------------|----------|-----------------------------|--------------------------------------------------------|
|
|
66
66
|
| `SONENTA_API_KEY` | yes | | Bearer ApiKey token. `SONENTA_TOKEN` accepted (back-compat) |
|
|
67
|
-
| `SONENTA_BASE_URL` | no | `https://api.sonenta.
|
|
67
|
+
| `SONENTA_BASE_URL` | no | `https://api.sonenta.com` | Self-host / staging override. `SONENTA_API_BASE` accepted (back-compat) |
|
|
68
68
|
| `SONENTA_PROJECTS` | no | (LLM picks per call) | CSV of project UUIDs. When >1, the LLM MUST pass `project_uuid` per call. |
|
|
69
69
|
| `SONENTA_PROJECT` | no | (legacy) | Singular fallback for v0.10.x users. Ignored when `SONENTA_PROJECTS` is set (warns). |
|
|
70
70
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sonenta/mcp",
|
|
3
|
-
"version": "0.
|
|
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",
|
package/python/README.md
CHANGED
|
@@ -57,7 +57,7 @@ Single-project setup:
|
|
|
57
57
|
"env": {
|
|
58
58
|
"SONENTA_API_KEY": "vrb_live_<prefix>.<secret>",
|
|
59
59
|
"SONENTA_PROJECTS": "<project_uuid>",
|
|
60
|
-
"SONENTA_BASE_URL": "https://api.sonenta.
|
|
60
|
+
"SONENTA_BASE_URL": "https://api.sonenta.com"
|
|
61
61
|
}
|
|
62
62
|
}
|
|
63
63
|
}
|
|
@@ -83,7 +83,7 @@ Restart Claude Desktop. Tools show up in the prompt UI.
|
|
|
83
83
|
| `SONENTA_API_KEY` | yes | | API key from Org Settings → API Keys (`SONENTA_TOKEN` also accepted, back-compat) |
|
|
84
84
|
| `SONENTA_PROJECTS` | no | (LLM passes per call) | CSV of project UUIDs. When >1, the LLM MUST pass `project_uuid` on each tool call. |
|
|
85
85
|
| `SONENTA_PROJECT` | no | (legacy) | Singular fallback for v0.10.x users. Ignored when `SONENTA_PROJECTS` is set (warns). |
|
|
86
|
-
| `SONENTA_BASE_URL` | no | `https://api.sonenta.
|
|
86
|
+
| `SONENTA_BASE_URL` | no | `https://api.sonenta.com` | Override for self-host or staging (`SONENTA_API_BASE` also accepted, back-compat) |
|
|
87
87
|
|
|
88
88
|
> Migrating from `verbumia-mcp`? The legacy `VERBUMIA_API_KEY` / `VERBUMIA_TOKEN`
|
|
89
89
|
> / `VERBUMIA_PROJECTS` / `VERBUMIA_BASE_URL` env vars are still accepted, so
|
|
Binary file
|
package/python/pyproject.toml
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "sonenta-mcp"
|
|
3
|
-
version = "0.
|
|
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"
|
|
@@ -239,6 +239,40 @@ def register(server: Server, client: VerbumiaClient) -> tuple[Any, Any]:
|
|
|
239
239
|
"additionalProperties": False,
|
|
240
240
|
},
|
|
241
241
|
),
|
|
242
|
+
Tool(
|
|
243
|
+
name="distribution_info",
|
|
244
|
+
description=(
|
|
245
|
+
"Get the project's CDN distribution status: the public CDN base "
|
|
246
|
+
"URL + bundle URL template, the production version, which "
|
|
247
|
+
"(language, namespace) bundles are currently published, and any "
|
|
248
|
+
"gaps (bundles not yet published). Use to see what client SDKs "
|
|
249
|
+
"can fetch right now."
|
|
250
|
+
),
|
|
251
|
+
inputSchema={
|
|
252
|
+
"type": "object",
|
|
253
|
+
"properties": {
|
|
254
|
+
"project_uuid": {
|
|
255
|
+
"type": "string",
|
|
256
|
+
"description": "Project UUID. Required when multiple projects are configured (SONENTA_PROJECTS); defaults to the single configured project otherwise.",
|
|
257
|
+
}
|
|
258
|
+
},
|
|
259
|
+
"additionalProperties": False,
|
|
260
|
+
},
|
|
261
|
+
),
|
|
262
|
+
Tool(
|
|
263
|
+
name="sonenta_guide",
|
|
264
|
+
description=(
|
|
265
|
+
"Get the Sonenta usage guide: a concise, up-to-date overview of "
|
|
266
|
+
"how this Sonenta instance works — core concepts, the translation "
|
|
267
|
+
"workflow, how to publish to the CDN, and the available MCP tools. "
|
|
268
|
+
"Takes no arguments. Call this first when unsure how to use Sonenta."
|
|
269
|
+
),
|
|
270
|
+
inputSchema={
|
|
271
|
+
"type": "object",
|
|
272
|
+
"properties": {},
|
|
273
|
+
"additionalProperties": False,
|
|
274
|
+
},
|
|
275
|
+
),
|
|
242
276
|
Tool(
|
|
243
277
|
name="list_keys",
|
|
244
278
|
description=(
|
|
@@ -1501,6 +1535,79 @@ def register(server: Server, client: VerbumiaClient) -> tuple[Any, Any]:
|
|
|
1501
1535
|
"additionalProperties": False,
|
|
1502
1536
|
},
|
|
1503
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
|
+
),
|
|
1504
1611
|
Tool(
|
|
1505
1612
|
name="get_variants",
|
|
1506
1613
|
description=(
|
|
@@ -1814,6 +1921,15 @@ def register(server: Server, client: VerbumiaClient) -> tuple[Any, Any]:
|
|
|
1814
1921
|
project_uuid = _project_uuid(args, client)
|
|
1815
1922
|
data = await client.get(f"/v1/mcp/projects/{project_uuid}")
|
|
1816
1923
|
return _text(data)
|
|
1924
|
+
if name == "distribution_info":
|
|
1925
|
+
project_uuid = _project_uuid(args, client)
|
|
1926
|
+
data = await client.get(
|
|
1927
|
+
f"/v1/mcp/projects/{project_uuid}/distribution"
|
|
1928
|
+
)
|
|
1929
|
+
return _text(data)
|
|
1930
|
+
if name == "sonenta_guide":
|
|
1931
|
+
data = await client.get("/v1/mcp/guide")
|
|
1932
|
+
return _text(data)
|
|
1817
1933
|
if name == "list_keys":
|
|
1818
1934
|
project_uuid = _project_uuid(args, client)
|
|
1819
1935
|
params = {
|
|
@@ -2296,6 +2412,29 @@ def register(server: Server, client: VerbumiaClient) -> tuple[Any, Any]:
|
|
|
2296
2412
|
return _err("slug is required")
|
|
2297
2413
|
await client.delete(f"/v1/mcp/projects/{project_uuid}/surfaces/{slug}")
|
|
2298
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)
|
|
2299
2438
|
if name == "get_variants":
|
|
2300
2439
|
project_uuid = _project_uuid(args, client)
|
|
2301
2440
|
key_uuid = args.get("key_uuid")
|
|
Binary file
|