# DeepL v3 Customization Hub — Covered in One DADL

> DeepL just rolled out 13 new REST endpoints — style rules, multilingual glossaries, translation memory, /v3/languages, tag_handling v2. The official MCP server has zero of them today. We covered all of them in a 38 KB DADL. Here is the build log.

Canonical: https://www.toolmesh.io/en/blog/deepl-v3-customization-hub-in-one-yaml-file/

In late May, DeepL turned on the [Customization Hub](https://www.deepl.com/en/customization-hub) — 13 new REST endpoints across style rules, multilingual glossaries, translation memory, the redesigned `/v3/languages` resource, and an opt-in `tag_handling` v2 algorithm. On the morning we merged our DADL for it, the official [`deepl-mcp-server`](https://github.com/DeepLcom/deepl-mcp-server) still exposed nine tools — all of them v2 — and the community alternative [`mcp-deepl`](https://github.com/NimbleBrainInc/mcp-deepl) was in the same shape, last released 2026-05-09. Not because anyone is slow. The unit of work for adding API coverage is fundamentally different on either side of that line, and the new release surfaces the gap clearly. This post is the build log.

## What the new release added

The Customization Hub is the marketing name for an honest API expansion. DeepL now lets API consumers manage **per-language style profiles** (think "Brand voice — DE"), **multilingual glossaries** (one glossary, many `source → target` dictionaries), and **translation memories** (segment-level reuse with a configurable match threshold). `/v2/translate` accepts three new parameters — `style_id`, `custom_instructions`, `translation_memory_id` — any of which silently bumps the model to `quality_optimized`. The new `/v3/languages` endpoint replaces the old `/v2/languages` and exposes per-resource feature flags (formality support, glossary support, style-rules support, voice). Finally, `tag_handling_version: v2` ships a much improved HTML/XML structure preservation algorithm — position-independent translation, better-preserved nesting.

That is a meaningful expansion. None of it is in the official MCP server today.

## The numbers

| | DADL (`deepl.dadl`) | `deepl-mcp-server` (official) |
|---|---|---|
| Tools | **27** | 9 |
| Coverage | text translation, document translation, multilingual v3 glossaries, style rules CRUD, custom instructions CRUD, TM listing, Write/rephrase, `/v3/languages`, usage | translate-text, rephrase-text, translate-document, list-glossaries, get-glossary-info, get-glossary-dictionary-entries, get-source-languages, get-target-languages, get-writing-styles |
| Distribution | 38 KB YAML | Node.js server (TypeScript SDK, build step, runtime to host) |
| Adding a new endpoint | ~30 lines of YAML | Tool definition + request handler + tests + release |
| v3 Customization Hub coverage | full | none today |

The local validation, run from the registry checkout:

```
> cd dadl-registry && npm run validate
✅ deepl.dadl — 27 tools
```

Source on GitHub: [`dadl-registry/deepl.dadl`](https://github.com/DunkelCloud/dadl-registry/blob/main/deepl.dadl). Merged in [PR #34](https://github.com/DunkelCloud/dadl-registry/pull/34). The DADL spec itself: [dadl.ai/spec](https://dadl.ai/spec/dadl-spec-v0.1.md).

## A worked example: style rules end-to-end

The interesting thing about style rules is that they actually take effect — `custom_instructions` carry through into the model output. Here is the round trip:

```js
const style = await toolmesh.deepl_create_style_rule({
  name: "Brand voice — DE",
  language: "de",
  custom_instructions: [
    { label: "Greeting",     prompt: "Begin every translation with 'Sehr geehrte Damen und Herren'." },
    { label: "Product term", prompt: "Render 'ToolMesh' verbatim, never translate." }
  ]
});

const r = await toolmesh.deepl_translate({
  text: ["The deployment of ToolMesh was successful."],
  source_lang: "EN", target_lang: "DE",
  style_id: style.style_id
});
// → "Sehr geehrte Damen und Herren, die Bereitstellung von ToolMesh war erfolgreich."
```

Two calls. No glue code. The first hits `POST /v3/style_rules`; the second references the result by `style_id` in `POST /v2/translate`. The DADL transparently handles:

- the unusual `DeepL-Auth-Key` Authorization scheme (custom prefix, server-side credential injection — the model never sees the key);
- the language-code casing trap (UPPERCASE for `translate`, lowercase for style rules — both correctly typed);
- the silent model switch — passing `style_id`, `custom_instructions`, or `translation_memory_id` flips `model_type` to `quality_optimized`;
- retries on `429` / `529` with `Retry-After`, and terminal classification for `400`/`401`/`403`/`456` (the Free-plan quota-exceeded code is `456`, not `429` — a footgun in hand-coded clients).

Same call from Claude or any other agent. No DeepL-specific code on the client side.

## Maintenance asymmetry

This is the part that does not show up in the tool count but shapes how quickly an integration tracks an upstream API.

**Adding the v3 endpoints to the DADL:**

1. Open `deepl.dadl`.
2. Add the new tool blocks (~30 lines of YAML per endpoint).
3. `npm run validate` — output is `✅ deepl.dadl — 27 tools`.
4. Open a PR. Review the YAML diff. Merge.
5. ToolMesh picks the new tools up on next reload. Users see them.

**Adding the same endpoints to a hand-coded MCP server:**

1. Update the TypeScript SDK to model the new request and response shapes.
2. Add tool definitions and request handlers (one per endpoint).
3. Write or extend tests.
4. Cut a release. Tag. Publish to npm.
5. Tell users to upgrade. Wait for them.
6. Repeat for the Python SDK if you maintain one. Repeat for any downstream forks.

DADL collapses steps 1, 2, 4, 5, and 6 into "edit one YAML file." The PR diff is a reviewable change set, not a software release. We made the general version of this argument [in an earlier post](/en/blog/dadl-the-end-of-mcp-server-boilerplate); the DeepL release is the concrete case study.

The flip side worth naming: **if you need behavior the runtime does not support, the YAML file does not save you.** DADL is declarative — there is no escape hatch for custom orchestration. For DeepL specifically, the document-translation flow (`upload_document → check_document_status → download_document`) is purely sequential REST and fits cleanly. A protocol-level deviation — say, the WebSocket Voice API — would not.

## The context-window argument

The other reason the tool count matters less than it looks: **Code Mode**. Instead of injecting every backend's full tool list into the model's context window, ToolMesh exposes two meta-tools (`list_tools` and `execute_code`). The model discovers what is available on demand and calls flat tool names from inside a sandboxed JavaScript runtime — `toolmesh.deepl_translate`, `toolmesh.deepl_create_style_rule`, not `toolmesh.deepl.translate`.

The token cost is roughly constant: ~1 k tokens of meta-tool description, regardless of whether the registry has one backend with 9 tools or {{registry.apis}} backends with {{registry.tools}}. Tool-count-driven bloat goes away. Adding the v3 Customization Hub took the DADL from 14 to 27 tools and added zero tokens to every Claude conversation that does not actively touch DeepL.

In Code Mode, the JavaScript in the worked example above is not an illustration — it is literally what the model writes to call the tools. That is why it reads like JavaScript rather than like JSON tool-call payloads.

## Honest caveats

The DADL is not a full coverage replacement. Real limits:

- **Voice translation is WebSocket-based.** DeepL's real-time voice translation is a bidirectional streaming protocol. DADL describes REST APIs declaratively; it does not describe streaming protocols. That endpoint is not in our 27-tool count and will not be — it is custom-server territory.
- **The Admin API is out of scope on purpose.** DeepL exposes admin endpoints (org analytics, developer-key management). We deliberately scoped this DADL to user-facing translation surfaces. Admin endpoints have a different threat model and belong in a separate, more privileged backend — not bundled with the everyday `translate` tool that any team member might use.
- **Translation memory mutation is web-UI only.** `/v3/translation_memories` is read-only via the API as of May 2026 — TMs are created and edited in the DeepL web UI. We expose `list_translation_memories`; we cannot expose endpoints that do not exist.
- **Stateful MCP clients are a legitimate use case.** If you drive Claude Desktop, Cursor, or Continue directly and want a local MCP server with no governance layer in between, the official `deepl-mcp-server` is the right shape for that. The DADL-via-ToolMesh approach assumes a runtime that centralizes credentials, authorization, and audit — and that someone is willing to host it. For an individual developer with no governance requirements, that is overhead, not value.
- **Latency-sensitive pipelines.** Every call hops through ToolMesh. For interactive translation at human latencies, this is invisible; for high-throughput batched pipelines, calling the DeepL client library directly is probably faster.

DADL is good at one specific thing — making REST API surface available to agents quickly, with a real control layer underneath. It is not a silver bullet, and it does not try to replace every kind of MCP server.

## What is actually different

The substantive question is not "DADL vs MCP server" — that framing is wrong; ToolMesh runs both, and they coexist in the same registry. The substantive question is: **what does it cost to track an upstream API release?**

For a hand-coded server, it costs an engineering cycle: SDK changes, tool definitions, handlers, tests, a release, an npm publish, user upgrades. That is why community MCP servers tend to lag fast-moving APIs — not for lack of effort, but because the work is linear in software releases, not in lines of YAML.

For a DADL, it costs one PR with a YAML diff. DeepL shipped 13 new endpoints in mid-May. We shipped the updated DADL on May 21 — 14 old tools plus the 13 new ones, validated, merged, live. The work for the new endpoints was a couple of hours, most of it spent reading DeepL's API reference and verifying behavior against a Free key. The runtime did the rest.

That is the asymmetry. Not "everyone should ditch MCP servers." Not "DADL is universally better." Just: when the unit of work to add API coverage is a YAML diff rather than a software release, the integration tracks the upstream faster. That matters when the upstream is shipping a Customization Hub.

---

→ Für die deutsche Geschäfts-Perspektive: [dunkel.cloud/de/blog/deepl-customization-hub-via-dadl](https://www.dunkel.cloud/de/blog/deepl-customization-hub-via-dadl/)
