# DADL Registry — Full Corpus > Generated from 31 backend DADL files and the canonical spec. > Source: https://www.dadl.ai/ · Index: https://www.dadl.ai/llms.txt --- # DADL Specification # DADL — Dunkel API Description Language **Specification Draft v0.1** A **declarative YAML format** for describing REST APIs as [ToolMesh](https://toolmesh.io) backends. Write a `.dadl` file — ToolMesh handles the rest. | | | |---|---| | Version | 0.1.0-draft | | Date | 2026-03-26 | | Author | Dunkel Cloud GmbH | | License | [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/) | --- ## 1 Overview **DADL** (Dunkel API Description Language) is a declarative YAML format that describes REST APIs for consumption by **ToolMesh** — a secure execution layer between AI agents and enterprise infrastructure. Instead of building a dedicated MCP server for each REST API, you write a `.dadl` file. ToolMesh reads it, generates TypeScript interfaces, and exposes the API via **Code Mode** — two tools (`search` + `execute`) that give any AI agent access to the entire API in roughly 1,000 tokens. ``` # Without DADL Claude → ToolMesh → custom Go/TS MCP Server → REST API # With DADL Claude → ToolMesh → REST API (via declarative .dadl file) ``` > **Code Mode only.** DADL backends are always exposed via Code Mode. The LLM writes JavaScript against auto-generated TypeScript interfaces. No tool-per-endpoint explosion — regardless of API size. --- ## 2 Design Principles **Describe the API, not the agent behavior.** DADL declares what endpoints exist and how to authenticate. ToolMesh decides how to present them to the LLM (always Code Mode). Temporal handles durability. OpenFGA handles authorization. - **YAML-native** — every `.dadl` file is valid YAML. Existing editors, linters, and parsers work out of the box. - **Code Mode only** — no tool-grouping syntax, no scope-exposure mechanics. The LLM writes code against TypeScript interfaces. - **OpenAPI-compatible** — optional `openapi_source` field uses an existing OpenAPI spec for schemas. DADL adds only what OpenAPI lacks: credential injection, pagination strategy, response transformation. - **No templating** — no variables, no conditionals, no loops. DADL is declarative, not generative. - **No workflow syntax** — multi-step orchestration happens in Code Mode (the LLM writes sequential code) and Temporal (durability, retry, audit). --- ## 3 File Structure A DADL file has the extension `.dadl` and is a YAML document with the following top-level fields: | Field | Type | Required | Description | |---|---|---|---| | `spec` | string | yes | URL of the DADL specification this file conforms to. Currently `"https://dadl.ai/spec/dadl-spec-v0.1.md"` | | `credits` | array of strings | no | Free-form list of contributors, maintainers, and sponsors. Each entry is a plain string — conventions emerge from usage (e.g. `"Jane Doe (@janedoe)"`, `"Acme Corp — sponsor"`). | | `source_name` | string | no | Name of the source API being described (e.g. `"GitHub REST API"`) | | `source_url` | string | no | URL to the original API specification or documentation | | `date` | string | no | Creation or last-modified date of this file (`YYYY-MM-DD`) | | `backend` | object | yes | The backend definition | | `includes` | array | no | Reusable fragments to merge in | | `_*` | any | no | Underscore-prefixed keys are ignored by ToolMesh (used for YAML anchors) | ```yaml # minimal.dadl spec: "https://dadl.ai/spec/dadl-spec-v0.1.md" credits: # optional - "Jane Doe (@janedoe)" - "Acme Corp — verifies against production" source_name: "Example REST API" # optional source_url: https://docs.example.com/api # optional date: "2026-03-26" # optional backend: name: my-api type: rest version: "1.0" base_url: https://api.example.com/v1 description: "My REST API" auth: type: bearer credential: vault/my-api-token tools: list_items: method: GET path: /items access: read description: "List all items" ``` --- ## 4 Backend Object | Field | Type | Required | Description | |---|---|---|---| | `name` | string | yes | Unique backend identifier (slug format: lowercase, hyphens) | | `type` | string | yes | Always `rest` for DADL backends | | `version` | string | no | Semantic version of this DADL file (e.g. `"1.0"`, `"1.2.1"`). Used by ToolMesh to detect available upgrades from the registry. See Section 4.5. | | `base_url` | string | yes | Base URL for all API requests | | `description` | string | yes | Human-readable description (used in Code Mode prompt) | | `openapi_source` | string | no | Path or URL to OpenAPI 3.x spec. When provided, schemas and parameters are derived from it. | | `arazzo_source` | string | no | Path or URL to Arazzo workflow file. Used as documentation context for Code Mode, not executed. | | `auth` | object | yes | Authentication configuration | | `defaults` | object | no | Default headers, pagination, error, and response config for all tools. Supports `headers` (map of default HTTP headers), `pagination`, `errors`, and `response`. | | `types` | object | no | Type definitions (JSON Schema subset). Only needed without `openapi_source`. | | `tools` | object | yes | Map of tool definitions | | `examples` | array | no | Code examples for multi-step workflows (few-shot prompts for the LLM). See Section 4.4. | | `coverage` | object | no | API coverage metadata. Helps LLMs understand scope and users assess fitness. | | `hints` | object | no | Per-tool domain knowledge for LLM consumers (structured key-value). Injected into tool descriptions at load time. Subject to security scanning. | | `setup` | object | no | Human-readable setup instructions. Describes how to obtain credentials, configure backends.yaml, and required permissions. Powers `toolmesh setup ` CLI. | ### 4.1 Coverage Object Optional metadata describing how much of the target API this DADL file covers. Useful for discovery, community contributions, and LLM decision-making. | Field | Type | Required | Description | |---|---|---|---| | `endpoints` | integer | no | Number of tools defined in this DADL file | | `total_endpoints` | integer | no | Estimated total number of REST endpoints in the target API | | `percentage` | integer | no | Approximate coverage percentage (0–100) | | `focus` | string | no | Comma-separated list of covered API areas (e.g. "repos, issues, PRs, search") | | `missing` | string | no | Notable uncovered API areas (e.g. "webhooks, teams, code scanning") | | `last_reviewed` | string | no | ISO 8601 date when coverage was last verified (e.g. "2026-03-26") | ### 4.2 Hints Object Structured domain knowledge that is injected into tool descriptions at load time. Helps LLMs use tools correctly without trial and error. Hints are per-tool and use key-value pairs rather than free text to reduce prompt injection surface. **Security:** Hint values are subject to automated security scanning. DADL files from untrusted sources (community registries) are scanned for imperative instructions, URLs, shell commands, and authority claims. Suspicious content is rejected or flagged. | Field | Type | Required | Description | |---|---|---|---| | `` | object | no | Map of hint key-value pairs for a specific tool | ```yaml # Example: coverage and hints backend: name: github coverage: endpoints: 24 total_endpoints: 900 percentage: 3 focus: "repos, issues, PRs, commits, search, releases, actions" missing: "git primitives, projects v2, teams, webhooks, code scanning" last_reviewed: "2026-03-26" hints: list_project_tasks: position_type: float64 requires: "call list_views first to get view_id" kanban_note: "kanban views return buckets with nested tasks, not a flat list" ``` ### 4.3 Setup Object Human-readable instructions for setting up this DADL backend. Intended for operators, not LLMs. Powers the `toolmesh setup ` CLI command that guides users through credential creation and configuration. | Field | Type | Required | Description | |---|---|---|---| | `credential_steps` | array of string | no | Step-by-step instructions to obtain the required credential (API key, PAT, etc.) | | `env_var` | string | no | Name of the environment variable to set in `.env` | | `backends_yaml` | string | no | Example `backends.yaml` entry (multiline YAML string) | | `required_scopes` | array of string | no | API scopes or permissions needed for full functionality | | `optional_scopes` | array of string | no | Additional scopes for extended features (read-only alternatives, etc.) | | `docs_url` | string | no | Link to the API provider's credential/authentication documentation | | `notes` | string | no | Additional setup notes (e.g. self-hosted URL patterns, regional endpoints) | ```yaml # Example: setup setup: credential_steps: - "Navigate to GitLab → Settings → Access Tokens" - "Create a token with scope: api (full access) or read_api (read-only)" - "Copy the token (starts with glpat-)" env_var: CREDENTIAL_GITLAB_TOKEN backends_yaml: | - name: gitlab transport: rest dadl: /app/dadl/gitlab.dadl url: "https://your-gitlab.example.com/api/v4" required_scopes: - api optional_scopes: - read_api docs_url: "https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html" notes: "For self-hosted GitLab, replace the URL with your instance. The token prefix glpat- is for personal access tokens." ``` ### 4.4 Examples Array Code examples that serve as few-shot prompts for the LLM in Code Mode. Each example demonstrates a multi-step workflow using `api.*` calls, helping the LLM understand common patterns for this backend. | Field | Type | Required | Description | |-------|------|----------|-------------| | `name` | string | yes | Short name for the example (e.g. `"Customer onboarding"`) | | `description` | string | yes | What the example demonstrates | | `code` | string | yes | JavaScript/TypeScript code using `api.*` calls. Same sandbox as composite tools. | ```yaml # examples examples: - name: "Customer onboarding" description: "Create a customer and retrieve their details" code: | const customer = await api.create_customer({ email: "jane@example.com", name: "Jane Doe" }); const details = await api.get_customer({ id: customer.id }); return details; ``` ### 4.5 Version Optional semantic version string for the DADL file. Enables ToolMesh to detect when a newer version is available in the registry. ```yaml backend: name: github version: "1.2" # ... ``` **Format:** Any string that follows [Semantic Versioning](https://semver.org/) conventions. Both `"1.2"` (major.minor) and `"1.2.1"` (major.minor.patch) are valid. **Semantics:** | Change | Version bump | Example | |--------|-------------|---------| | New tools added | Minor | `1.1` → `1.2` | | Bug fix in transform/pagination | Patch | `1.2.0` → `1.2.1` | | Tool renamed or removed, breaking param change | Major | `1.2` → `2.0` | **Registry integration:** The DADL registry (`dadl.ai`) publishes a manifest with the latest version and checksum for each DADL file. ToolMesh compares the local `version` against the manifest at startup and logs a notice when an upgrade is available. No automatic updates — the operator decides when to upgrade. **When `version` is omitted:** ToolMesh skips the upgrade check for this backend. This is expected for private/local DADL files that are not published to the registry. --- ## 5 Authentication DADL supports five authentication patterns. Credentials are referenced by logical name and resolved at runtime by ToolMesh's three-tier Credential Store (Embedded → Infisical → Vault/OpenBao). **The LLM never sees credentials.** ### 5.1 Bearer Token ```yaml # auth — bearer auth: type: bearer credential: vault/stripe-secret-key inject_into: header # default header_name: Authorization # default prefix: "Bearer " # default ``` ### 5.2 Basic Authentication ```yaml # auth — basic auth: type: basic username_credential: vault/bitdefender-api-key password_credential: vault/bitdefender-password # optional, default: "" ``` ToolMesh builds the `Authorization: Basic base64(username:password)` header automatically. If `password_credential` is omitted, an empty password is used — this is common for APIs that use an API key as the username (e.g. Bitdefender GravityZone, many JSON-RPC APIs). ### 5.3 OAuth 2.0 Client Credentials ```yaml # auth — oauth2 auth: type: oauth2 flow: client_credentials token_url: https://api.example.com/oauth/token client_id_credential: vault/example-client-id client_secret_credential: vault/example-client-secret scopes: ["read", "write"] token_cache_key: example-api-token refresh_before_expiry: 60s ``` ### 5.4 Session-based (Login → Token → Use) ```yaml # auth — session auth: type: session login: method: POST path: /auth/login body: username_credential: vault/example-username password_credential: vault/example-password extract: token: "$.data.access_token" csrf: "$.data.csrf_token" inject: - header: Authorization value: "Bearer {{token}}" - header: X-CSRF-Token value: "{{csrf}}" refresh: trigger: status_code_401 action: re_login ``` ### 5.5 API Key ```yaml # auth — api_key auth: type: api_key credential: vault/my-api-key inject_into: header # header | query header_name: X-API-Key ``` --- ## 6 Tools Each tool maps to one REST API endpoint. In Code Mode, tools become methods on the auto-generated TypeScript interface that the LLM writes code against. | Field | Type | Required | Description | |---|---|---|---| | `method` | string | yes | HTTP method: GET, POST, PUT, PATCH, DELETE | | `path` | string | yes | URL path (may contain `{param}` placeholders) | | `description` | string | yes | Used as JSDoc comment in TypeScript interface | | `access` | string | no | Access classification for authorization and policy mapping. See Section 6.5. | | `params` | object | no | Parameter definitions (path, query, header, body). See Section 6.1. | | `content_type` | string | no | Request content type. Default: `application/json`. Use `multipart/form-data` for file uploads. | | `max_body_size` | string | no | Max upload size, e.g. `50MB` | | `depends_on` | array | no | Informational: other tools that should be called first. Becomes JSDoc hint. | | `response` | object | no | Response transformation config (overrides `defaults.response`) | | `pagination` | string\|object | no | `none` to disable, or object to override default pagination | | `errors` | object | no | Error mapping (overrides `defaults.errors`) | ### 6.1 Parameter Definition All parameters — path, query, and **body** — are defined under the `params` key using `in:` to specify their location. There is no separate `body:` keyword in DADL. ```yaml # params — path, query, and body parameters in one place params: id: type: string in: path required: true limit: type: integer in: query default: 10 description: "Max items to return" name: type: string in: body required: true description: "Resource name" tags: type: array in: body description: "List of tags" metadata: type: object in: body description: "Arbitrary key-value metadata" ``` > **Important:** Do NOT use a separate `body:` block with `type: object` / `properties` / `required` (OpenAPI-style). ToolMesh only exposes parameters defined via `params` with `in: body` as tool inputs. A standalone `body:` block will be silently ignored and the tool will appear with zero parameters. Supported `in:` values: | Value | Sent as | |-------|---------| | `path` | URL path segment (`/items/{id}`) | | `query` | URL query parameter (`?limit=10`) | | `header` | HTTP request header (e.g. `X-Custom-Header: value`) | | `body` | JSON body field (for `application/json`) or form field (for `application/x-www-form-urlencoded`) | ### 6.2 File Handling Files in DADL are always referenced by **URL** — never as inline data or local file paths. This keeps tool calls lightweight (only a URL string in the context, not megabytes of Base64) and works with any storage backend (S3, MinIO, NextCloud, ToolMesh's built-in file broker). #### 6.2.1 File Input (`type: file_url`) When a tool accepts a file, the parameter type is `file_url`. The caller provides a URL, and ToolMesh fetches the file and builds the appropriate request (e.g. multipart/form-data upload) to the backend API. Supported URL schemes: - `https://s3.amazonaws.com/bucket/file.pdf` — S3 / MinIO / any HTTP(S) URL - `https://toolmesh-host/files/f-abc123` — ToolMesh file broker (uploaded via `POST /files/upload`) - `file:///path/on/host` — local filesystem (only for same-host deployments) ```yaml # file upload tool — URL-based convert_pdf: method: POST path: /api/v1/convert description: "Convert a PDF to Markdown" content_type: multipart/form-data max_body_size: 100MB params: file: { type: file_url, in: body, required: true } title: { type: string, in: body } ``` #### 6.2.2 File Output (`response.type: file_url`) When a backend returns binary data (PDFs, images, exports), ToolMesh stores the response in its file broker and returns a download URL to the caller. The URL has a configurable TTL and can be shared across sessions. ```yaml # binary response → file URL export_report: method: GET path: /reports/{id}/export description: "Export report as PDF" params: id: { type: string, in: path, required: true } response: type: file_url ttl: 24h ``` #### 6.2.3 ToolMesh File Broker ToolMesh provides a built-in file broker for uploading and downloading files outside the MCP channel. Files are stored temporarily with a TTL and referenced by ID. This avoids Base64 overhead in tool calls and enables session-independent file handling. | Endpoint | Method | Description | |---|---|---| | `/files/upload` | POST | Upload a file (multipart). Returns `{"file_id": "f-...", "url": "...", "expires": "..."}` | | `/files/{file_id}` | GET | Download a file by ID | | `/files/{file_id}` | DELETE | Delete a file before TTL expires | ### 6.3 Binary Download & Streaming ```yaml # binary & streaming responses download_report: method: GET path: /reports/{id}/pdf description: "Download report as PDF" response: binary: true content_type: application/pdf event_stream: method: GET path: /events description: "Stream real-time events" response: streaming: true stream_handling: collect # collect | skip max_duration: 30s max_items: 100 ``` ### 6.4 Access Classification The optional `access` field classifies each tool by its risk level. This metadata enables policy files and authorization layers (OpenFGA) to group tools into roles without hard-coding tool names. **DADL defines access per tool. Policy files define roles from access levels. OpenFGA assigns roles to users.** This three-layer separation keeps DADL portable while enabling fine-grained authorization at deployment time. ```yaml # access classification tools: list_repos: method: GET path: /repos access: read description: "List repositories" create_repo: method: POST path: /user/repos access: write description: "Create a repository" update_branch_protection: method: PUT path: /repos/{owner}/{repo}/branches/{branch}/protection access: admin description: "Update branch protection rules" delete_repo: method: DELETE path: /repos/{owner}/{repo} access: dangerous description: "Delete a repository" ``` #### Well-Known Values The following values are well-known and understood by ToolMesh's built-in policy engine: | Value | Typical Use | HTTP Methods | |-------|-------------|--------------| | `read` | Read-only operations, listing, searching | GET, HEAD | | `write` | Create or update resources | POST, PUT, PATCH | | `admin` | Privileged operations (permissions, settings, configuration) | Any | | `dangerous` | Destructive or irreversible operations | DELETE, but also POST/PUT that are irreversible | #### Custom Values The `access` field is **not restricted** to the well-known values above. DADL authors can use domain-specific values that make sense for their API: ```yaml # custom access values tools: list_invoices: access: billing export_user_data: access: pii trigger_deploy: access: ops send_notification: access: messaging ``` Custom values are passed through to policy files and OpenFGA unchanged. ToolMesh does not validate or reject unknown access values — they are treated as opaque strings. #### Defaults When `access` is omitted, ToolMesh does **not** infer a default. Tools without an `access` field are unrestricted by access-based policies (they can still be restricted by explicit per-tool OpenFGA rules). This is intentional: inferring `read` from `GET` would be wrong for endpoints like `POST /search` or `GET /admin/reset-cache`. > **Best practice:** Always set `access` explicitly. It costs one line per tool and makes the DADL file self-documenting for authorization purposes. --- ## 7 Pagination Pagination config is adapted from the [Airbyte Low-Code CDK](https://docs.airbyte.com), battle-tested across 400+ connectors. Set it in `defaults.pagination` to apply to all list endpoints, or override per tool. | Strategy | Description | |---|---| | `cursor` | Cursor-based (Stripe, Slack). Uses a token from the response to fetch the next page. | | `offset` | Offset-based. Increments an offset parameter. | | `page` | Page number-based. Increments a page parameter. | | `link_header` | RFC 8288 Link header (GitHub). Follows the `next` relation. | ```yaml # pagination — cursor example pagination: strategy: cursor request: cursor_param: after limit_param: per_page limit_default: 50 response: next_cursor: "$.meta.next_cursor" has_more: "$.meta.has_more" behavior: auto # auto | expose max_pages: 10 # safety limit ``` When `behavior` is `auto`, ToolMesh fetches all pages transparently. When `expose`, the LLM controls pagination via the cursor parameter in Code Mode. --- ## 8 Error Mapping ```yaml # defaults.errors errors: format: json message_path: "$.error.message" code_path: "$.error.code" retry_on: [429, 502, 503, 504] retry_strategy: max_retries: 3 backoff: exponential initial_delay: 1s terminal: [400, 401, 403, 404, 409] rate_limit: header: X-RateLimit-Remaining retry_after_header: Retry-After ``` ### 8.1 Rate Limit Behavior When `rate_limit` is configured, ToolMesh performs **proactive throttling** — it inspects rate-limit headers on every response and acts before the API rejects requests. **Request flow:** 1. Before each request, ToolMesh checks the cached value of `rate_limit.header` (e.g. `X-RateLimit-Remaining`). 2. If the remaining count is **0**, ToolMesh **pauses** the request and waits until the reset time. 3. The wait duration is determined by (in order of precedence): - The `retry_after_header` response header (e.g. `Retry-After: 30`) — seconds or HTTP date. - The `X-RateLimit-Reset` header if present — Unix timestamp. - Fallback: exponential backoff starting at `retry_strategy.initial_delay`. 4. After waiting, ToolMesh retries the request. This counts toward `retry_strategy.max_retries`. 5. If a `429` response arrives despite proactive throttling (race condition, shared quota), it is handled by `retry_on` with the same backoff strategy. **When `rate_limit` is not configured:** ToolMesh relies solely on `retry_on` — a `429` response triggers reactive retries with the configured backoff strategy. No proactive throttling occurs. | Field | Type | Description | |-------|------|-------------| | `header` | string | Response header containing remaining request quota (e.g. `X-RateLimit-Remaining`) | | `retry_after_header` | string | Response header indicating when to retry (e.g. `Retry-After`). Supports seconds and HTTP date formats. | --- ## 9 Response Transformation Most APIs wrap results in container objects. Response transformation extracts the relevant data before it reaches the LLM, reducing token consumption. This is **critical for IoT and status APIs** that return large payloads with system internals (RAM, firmware, WiFi details) that are irrelevant for the LLM. ### 9.1 Defaults-Level Response Config ```yaml # defaults.response — applies to all tools unless overridden response: result_path: "$.data" # JSONPath to the actual result metadata_path: "$.meta" # extracted separately (for pagination, not sent to LLM) transform: | # optional jq filter .data | map({id, name, status}) max_items: 100 allow_jq_override: true # LLM can pass ad-hoc jq filters ``` ### 9.2 Tool-Level Response Override Individual tools can override `defaults.response` to apply custom transformations. This is especially useful when a single API returns large, deeply nested payloads that should be flattened or filtered before reaching the LLM context. ```yaml # tool-level response override — reduces a 60KB IoT status payload to ~2KB get_all_device_status: method: POST path: /device/all_status description: "Get status of all devices" response: result_path: "$.data.devices_status" transform: | to_entries | map({ id: .key, name: (.value._dev_info.name // .key), online: (.value._dev_info.online // false), relay_on: [.value.relays // [] | .[] | select(.ison)] | length > 0, switch_on: (.value."switch:0".output // false), power_w: (.value."switch:0".apower // 0) }) ``` | Field | Type | Description | |-------|------|-------------| | `result_path` | string | JSONPath to extract before `transform` runs. Applied first. | | `metadata_path` | string | JSONPath to pagination/meta info (not sent to LLM). | | `transform` | string | jq filter applied after `result_path` extraction. Use to flatten, rename, or filter fields. | | `max_items` | integer | Truncate arrays to this length (prevents context overflow). | | `allow_jq_override` | boolean | When `true`, the LLM can pass ad-hoc jq filters at call time. | > **Best practice:** Always add `response.transform` to status/list endpoints that return more than ~5KB per item. LLM context is expensive — strip firmware versions, MAC addresses, WiFi RSSI, uptime counters, and other system internals unless they are the primary purpose of the tool. --- ## 10 Types *(optional)* When `openapi_source` is provided, types are derived from the OpenAPI spec. Without it, you can define types inline using a JSON Schema subset. These are used to generate TypeScript interfaces for Code Mode. ```yaml # types — inline definitions types: Customer: type: object properties: id: { type: string } email: { type: string } name: { type: string } metadata: type: object additionalProperties: { type: string } required: [id] ``` **Supported JSON Schema keywords** (for TypeScript generation): `type`, `properties`, `items`, `required`, `$ref`, `enum`, `description`, `additionalProperties`, `oneOf`, `anyOf`, `allOf`. Validation keywords (`minLength`, `pattern`, `minimum`, etc.) are accepted but not used for TypeScript generation. This allows copy-paste from OpenAPI schemas without modification. --- ## 11 Includes & Composability DADL supports two levels of reuse: standard YAML anchors (intra-file) and DADL includes (cross-file). There is no templating, no inheritance, no conditionals. ### 11.1 YAML Anchors (intra-file) ```yaml # YAML anchors — native DRY # Underscore-prefixed keys are ignored by ToolMesh _defaults: pagination: &default-pagination strategy: cursor request: limit_param: limit limit_default: 50 behavior: auto max_pages: 20 backend: defaults: pagination: <<: *default-pagination request: cursor_param: starting_after ``` ### 11.2 Cross-file Includes ```yaml # includes includes: - path: common/oauth2-client-credentials.dadl.yaml merge_into: backend.auth overrides: token_url: https://api.stripe.com/oauth/token client_id_credential: vault/stripe-client-id - path: common/standard-rest-errors.dadl.yaml merge_into: backend.defaults.errors ``` Include fragments are files with `_fragment: true` at the top level. Merge semantics: deep merge, overrides win. Arrays are replaced, not appended. Includes are flat — no nested includes (max 1 level). --- ## 12 Composite Tools Composite tools are server-side TypeScript functions that combine multiple primitive tools into a single, higher-level operation. They solve problems that `response.transform` (jq) cannot: cross-endpoint joins, multi-step workflows, and business logic that requires branching or loops. ### 12.1 When to Use Composites | Problem | Solution | |---------|----------| | Single endpoint has too much data | `response.transform` (jq) | | Join data from two endpoints (e.g. names + status) | **Composite tool** | | Multi-step workflow (create → configure → verify) | **Composite tool** | | Conditional logic (if device is X, call Y) | **Composite tool** | ### 12.2 Definition Composites are defined under the `composites` key at the same level as `tools`. They appear as regular tools in the TypeScript interface — callers cannot distinguish them from primitive tools. ```yaml composites: get_named_status: description: "Get all device status with human-readable names and on/off state" params: only_on: type: boolean default: false description: "If true, return only devices that are currently on" timeout: 30s code: | const devices = await api.list_devices(); const nameMap = Object.fromEntries(devices.map(d => [d.id, d.name])); const status = await api.get_all_device_status({ show_info: true }); const result = status.map(d => ({ ...d, name: nameMap[d.id] || d.id })); if (params.only_on) { return result.filter(d => d.relay_on || d.light_on || d.switch_on); } return result; ``` ### 12.3 Composite Tool Fields | Field | Type | Required | Description | |-------|------|----------|-------------| | `description` | string | yes | Used as JSDoc comment in TypeScript interface | | `params` | object | no | Input parameters (same syntax as tool params, but `in:` is not used) | | `code` | string | yes | TypeScript/JavaScript function body. Has access to `api.*` (all tools in this backend) and `params` (input parameters). | | `timeout` | string | no | Max execution time (default: `30s`). Killed after timeout. | | `depends_on` | array | no | Informational: primitive tools called internally. | ### 12.4 Sandbox & Security Composite code runs in a **restricted sandbox** with the following constraints: | Allowed | Forbidden | |---------|-----------| | `api.*` calls (tools in the same backend) | `fetch()`, `XMLHttpRequest`, any network I/O | | `params` (input parameters) | `require()`, `import`, dynamic module loading | | Pure JS: `map`, `filter`, `reduce`, `JSON.*`, `Math.*`, `Date.*` | `fs`, `process`, `child_process`, `os` | | `console.log` (captured to audit log) | `eval()`, `Function()`, `globalThis` mutation | | `await` (for `api.*` calls) | Accessing other backends or services | | String/Array/Object manipulation | `setTimeout`, `setInterval` (use `timeout` field instead) | **Additional runtime constraints:** - **Timeout:** Hard-killed after the configured timeout (default 30s, max 120s). - **Call depth:** Composites can only call primitive tools, not other composites. Max 50 `api.*` calls per execution. - **No side-channel:** Composites cannot construct URLs or make HTTP calls outside of `api.*`. All network access is mediated by ToolMesh. - **Audit:** Every `api.*` call within a composite is logged individually in the audit trail with the composite's name as parent context. > **Security note:** When DADL files contain composites, ToolMesh sets `contains_code: true` in the backend metadata. Deployment pipelines should flag DADL files with composites for automated static analysis (AST scanning for forbidden globals, network calls, eval patterns). Manual review is not scalable — automated scanning at CI/CD time is the primary gate. See the ToolMesh Security Guide for reference AST rules. ### 12.5 Best Practices - Keep composites **short** (< 30 lines). If it is longer, the logic probably belongs in a dedicated microservice. - Use composites for **read-only** joins and aggregations. Avoid composites that write to multiple endpoints — use Temporal workflows for durable multi-step mutations. - Always set a **`description`** that explains what the composite does, not how. The LLM sees this in the TypeScript interface. - Prefer `response.transform` (jq) when a single endpoint is involved. Composites are for multi-endpoint orchestration. --- ## 13 Full Example ```yaml # stripe.dadl spec: "https://dadl.ai/spec/dadl-spec-v0.1.md" backend: name: stripe type: rest version: "1.0" base_url: https://api.stripe.com/v1 description: "Stripe payment processing API" openapi_source: https://raw.githubusercontent.com/stripe/openapi/master/openapi/spec3.yaml auth: type: bearer credential: vault/stripe-secret-key defaults: headers: Content-Type: application/x-www-form-urlencoded pagination: strategy: cursor request: cursor_param: starting_after limit_param: limit limit_default: 100 response: next_cursor: "$.data[-1].id" has_more: "$.has_more" behavior: expose max_pages: 10 errors: format: json message_path: "$.error.message" code_path: "$.error.type" retry_on: [429, 502, 503] response: result_path: "$.data" allow_jq_override: true tools: list_customers: method: GET path: /customers access: read description: "List all customers" params: email: { type: string, in: query, required: false } limit: { type: integer, in: query, default: 10 } get_customer: method: GET path: /customers/{id} access: read description: "Retrieve a single customer by ID" params: id: { type: string, in: path, required: true } response: result_path: "$" pagination: none create_customer: method: POST path: /customers access: write description: "Create a new customer" params: email: { type: string, in: body, required: true } name: { type: string, in: body } metadata: { type: object, in: body } response: result_path: "$" pagination: none examples: - name: "Customer onboarding" description: "Create a customer and retrieve their details" code: | const customer = await api.create_customer({ email: "jane@example.com", name: "Jane Doe" }); const details = await api.get_customer({ id: customer.id }); return details; ``` --- ## 14 ToolMesh Integration DADL files are consumed by **ToolMesh** and integrated into its six-pillar architecture: | Pillar | DADL Integration | |---|---| | **Code Mode** | TypeScript interfaces are auto-generated from DADL tools and types. The LLM writes code against `api.*` methods. | | **Temporal** | Each `execute()` call runs as a Temporal Activity — retry, timeout, and full audit trail. | | **OpenFGA** | Per-tool authorization. The `access` field on each tool enables role-based policy mapping (e.g. `read` → reader role). Policies can further restrict by user, plan, or caller origin. | | **MCP Aggregation** | DADL backends mix seamlessly with native MCP backends in the same ToolMesh instance. | | **Credential Store** | `credential: vault/xxx` references are resolved through the three-tier store (Embedded → Infisical → Vault/OpenBao). | | **Output Gate** | Responses pass through goja-based policies (PII redaction, rate limiting, caller-dependent filtering). | --- *DADL is created and maintained by [Dunkel Cloud GmbH](https://dunkel.cloud)* [ToolMesh](https://toolmesh.io) · [GitHub](https://github.com/DunkelCloud) · This specification is licensed under [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/). ToolMesh source code is licensed under Apache 2.0. --- # Backend DADLs # Alertmanager MCP Server — 12 tools via DADL The Alertmanager DADL turns Alertmanager's API into an MCP server that Claude, GPT or any MCP-compatible agent can consume directly. One YAML file declares all 12 tools — silence, alert, health, receiver, status, group, and more — and ToolMesh serves them at runtime. No Python boilerplate, no per-endpoint code, no separate MCP server process. Below: the endpoint coverage matrix, a two-block ToolMesh setup, the full tool reference grouped by Alertmanager feature area. **Source:** [Prometheus Alertmanager API v2](https://prometheus.io/docs/alerting/latest/clients/) **Updated:** 2026-04-13 **Tags:** monitoring, alerting, crud, user-management, notifications, deployment, logging, auth:basic ## Which Alertmanager endpoints are covered? **100%** (14 of ~14 endpoints). **Focus:** alerts (list, create/update, groups), silences (CRUD), receivers (list), status, health/ready/reload **Missing:** metrics and pprof debug endpoints (not useful for API consumers) *Last reviewed: 2026-04-13* ## How do you configure the Alertmanager DADL? 1. Alertmanager has no built-in auth by default. If --web.config.file is configured with basic_auth_users: 2. 1. Open the web.config.yml used by your Alertmanager instance 3. 2. Find or add your username under basic_auth_users 4. 3. Generate a bcrypt hash of your password: htpasswd -nBC 10 '' | tr -d ':\n' 5. 4. Add the username: bcrypt_hash pair to basic_auth_users 6. 5. Reload Alertmanager config (POST /-/reload or send SIGHUP) 7. If no auth is configured, leave credentials empty or use a reverse proxy for auth **Environment variable:** `ALERTMANAGER_URL` [Authentication docs](https://prometheus.io/docs/alerting/latest/https/) *Default port is 9093. Set ALERTMANAGER_URL to http(s)://host:9093. For HA setups, point to any cluster member or a load balancer.* ## How do you install the Alertmanager MCP server with ToolMesh? Add to your `backends.yaml`: ```yaml alertmanager.dadl ``` Set the credential: ``` ALERTMANAGER_URL=your-token-here ``` ## What 12 tools does the Alertmanager DADL expose? - **GET** `get_status` — Get Alertmanager status including version, config, uptime, and cluster state - **GET** `get_health` — Health check — returns 200 if Alertmanager is running (liveness probe) - **GET** `get_ready` — Readiness check — returns 200 when Alertmanager is ready to serve traffic - **GET** `list_alerts` — List alerts with optional filters by state, receiver, and label matchers - **POST** `post_alerts` — Create new alerts or update existing ones. Alerts are matched by label fingerprint. Set endsAt to resolve. - **GET** `list_alert_groups` — Get alerts grouped by the routing tree configuration - **GET** `list_silences` — List all silences, optionally filtered by label matchers - **GET** `get_silence` — Get a single silence by its ID - **POST** `post_silence` — Create a new silence or update an existing one. Include id to update, omit to create. - **DELETE** `delete_silence` — Expire (delete) a silence by its ID. This immediately stops the silence from suppressing alerts. - **GET** `list_receivers` — List all configured notification receiver names - **POST** `reload_config` — Trigger a configuration reload (equivalent to sending SIGHUP to the process) ## Which DADLs are related to Alertmanager? - [Checkmk](https://www.dadl.ai/d/checkmk/) — Checkmk REST API (version 1.0, Checkmk 2.4) -- live host and service status via Livestatus queries, downtimes, acknowledgements and comments, the Event Console (list, acknowledge, change state and archive events) and BI (packs, rules, aggregations and live aggregation state), plus the full Setup side: hosts, clusters, folders, service discovery, rules and rulesets, host/service/contact groups, users, roles, passwords, time periods, host tags, notification rules, site connections and change activation. - [Mikrotik](https://www.dadl.ai/d/mikrotik/) — MikroTik RouterOS REST API -- manage interfaces, IP addresses, routing, firewall, DHCP, DNS, PPP, queues, wireless, system configuration, users, certificates, files, logs, and diagnostics on RouterOS v7.1+ devices - [Billomat](https://www.dadl.ai/d/billomat/) — Billomat REST API — German cloud invoicing & accounting: invoices, estimates, credit notes, recurring invoices, delivery notes, order confirmations, dunning reminders, clients, contacts, articles, payments, expenses, taxes - [BookStack](https://www.dadl.ai/d/bookstack/) — BookStack wiki and documentation platform REST API -- shelves, books, chapters, pages (HTML/Markdown content), attachments, image gallery, comments, cross-entity search, exports (HTML/Markdown/PDF/ZIP), ZIP imports, users, roles, content permissions, recycle bin, audit log and tags. Hierarchy: shelves > books > chapters > pages. - [Graylog](https://www.dadl.ai/d/graylog/) — Graylog REST API -- log search (Views/Search + legacy universal), streams, pipelines, inputs, alerts, events, dashboards, users, roles, sidecars, index management, and cluster administration. Targets Graylog 6.x. - [Hacker News](https://www.dadl.ai/d/hackernews/) — Hacker News API — read-only access to stories, comments, polls, jobs, users, and live feeds from news.ycombinator.com --- **Canonical URL:** https://www.dadl.ai/d/alertmanager/ **Raw DADL:** https://github.com/DunkelCloud/dadl-registry/blob/main/alertmanager.dadl --- # Algolia HN Search MCP Server — 4 tools via DADL The Algolia HN Search DADL turns Algolia HN Search's API into an MCP server that Claude, GPT or any MCP-compatible agent can consume directly. One YAML file declares all 4 tools — item, user, full-text — and ToolMesh serves them at runtime. No Python boilerplate, no per-endpoint code, no separate MCP server process. Below: the endpoint coverage matrix, a two-block ToolMesh setup, the full tool reference grouped by Algolia HN Search feature area. **Source:** [Algolia HN Search API](https://hn.algolia.com/api) **Updated:** 2026-04-04 **Tags:** search, crud, analytics, documentation, real-time, user-management, auth:apikey ## Which Algolia HN Search endpoints are covered? **100%** (4 of ~4 endpoints). **Focus:** full-text search (relevance and date), item retrieval with comment trees, user profiles **Missing:** none — full coverage of the Algolia HN Search API *Last reviewed: 2026-04-04* ## How do you configure the Algolia HN Search DADL? 1. No credentials required — the Algolia HN Search API is fully public 2. No signup or API key needed [Authentication docs](https://hn.algolia.com/api) *Completely public API — no authentication, no API keys. Two search endpoints: /search (relevance) and /search_by_date (chronological). Use tags and numericFilters for precise filtering. The /items endpoint returns full nested comment trees, unlike the Firebase API. * ## How do you install the Algolia HN Search MCP server with ToolMesh? Add to your `backends.yaml`: ```yaml - name: algolia-hn-search transport: rest dadl: algolia-hn-search.dadl url: "https://hn.algolia.com/api/v1" ``` Set the credential: ``` CREDENTIAL_ALGOLIA_HN_SEARCH_TOKEN=your-token-here ``` ## What 4 tools does the Algolia HN Search DADL expose? - **GET** `search` — Full-text search ranked by relevance (points, num_comments). Best for finding popular/relevant content. Returns hits with: objectID, title, url, author, points, num_comments, created_at, created_at_i, story_text, comment_text, _tags, _highlightResult. Also returns nbHits, page, nbPages, hitsPerPage at the top level. - **GET** `search_by_date` — Full-text search ranked by date (newest first). Same parameters and response format as search, but results are sorted chronologically. Best for finding recent content or monitoring new submissions. Identical response fields to the search endpoint. - **GET** `get_item` — Get an item by ID with its full nested comment tree. Unlike the Firebase API, this returns the complete children array with recursively nested comments already resolved. Each child has: id, created_at, author, text, points, children. The parent item also includes title, url, points, num_comments. - **GET** `get_user` — Get a user profile by username. Returns: username, about (HTML bio), karma, created_at, avg, and other profile metadata. Username is case-sensitive. ## What composite workflows does the Algolia HN Search DADL provide? - **FN** `search_stories` — Search for stories only, returning a clean list with title, url, author, points, num_comments, and created_at. Convenience wrapper around search with tags=story. - **FN** `search_recent_comments` — Search for recent comments matching a query, sorted by date (newest first). Returns comment text, author, story title, and timestamps. - **FN** `get_front_page` — Get current HN front page stories with full details, sorted by relevance. Equivalent to browsing the HN homepage. - **FN** `search_distilled` — LLM-optimized search that strips all Algolia metadata cruft before returning results. Implements the _clean_hit() pattern from hn-pulse: raw Algolia hits are ~2 KB each due to _highlightResult, _snippetResult, _rankingInfo, _tags, and other index-internal fields. This composite reduces each hit to ~200 bytes — only data an LLM actually needs. Supports both relevance (sort=relevance) and recency (sort=date) ranking, and all content types via the tags parameter. Designed as the primary search primitive for LangGraph-style ReAct agents that combine this Algolia backend with the Firebase HN backend (hackernews.dadl) for live enrichment. - **FN** `get_user_activity` — Get a user's recent stories and comments. Fetches the user profile and their most recent submissions of each type. ## Which DADLs are related to Algolia HN Search? - [Graylog](https://www.dadl.ai/d/graylog/) — Graylog REST API -- log search (Views/Search + legacy universal), streams, pipelines, inputs, alerts, events, dashboards, users, roles, sidecars, index management, and cluster administration. Targets Graylog 6.x. - [Mastodon](https://www.dadl.ai/d/mastodon/) — Mastodon REST API — statuses, timelines, accounts, notifications, search, media, lists, polls, conversations, trends, filters, and instance info. Base URL must be set to the target Mastodon instance (e.g. https://mastodon.social). - [Umami](https://www.dadl.ai/d/umami/) — Umami open-source web analytics — privacy-friendly alternative to Google Analytics - [BookStack](https://www.dadl.ai/d/bookstack/) — BookStack wiki and documentation platform REST API -- shelves, books, chapters, pages (HTML/Markdown content), attachments, image gallery, comments, cross-entity search, exports (HTML/Markdown/PDF/ZIP), ZIP imports, users, roles, content permissions, recycle bin, audit log and tags. Hierarchy: shelves > books > chapters > pages. - [Checkmk](https://www.dadl.ai/d/checkmk/) — Checkmk REST API (version 1.0, Checkmk 2.4) -- live host and service status via Livestatus queries, downtimes, acknowledgements and comments, the Event Console (list, acknowledge, change state and archive events) and BI (packs, rules, aggregations and live aggregation state), plus the full Setup side: hosts, clusters, folders, service discovery, rules and rulesets, host/service/contact groups, users, roles, passwords, time periods, host tags, notification rules, site connections and change activation. - [DokuWiki](https://www.dadl.ai/d/dokuwiki/) — DokuWiki JSON-RPC API — wiki pages, media files, search, ACL management, and user administration --- **Canonical URL:** https://www.dadl.ai/d/algolia-hn-search/ **Raw DADL:** https://github.com/DunkelCloud/dadl-registry/blob/main/algolia-hn-search.dadl --- # Billomat MCP Server — 145 tools via DADL The Billomat DADL turns Billomat's API into an MCP server that Claude, GPT or any MCP-compatible agent can consume directly. One YAML file declares all 145 tools — invoice, offer, credit, confirmation, delivery, recurring, and more — and ToolMesh serves them at runtime. No Python boilerplate, no per-endpoint code, no separate MCP server process. Below: the endpoint coverage matrix, a two-block ToolMesh setup, the full tool reference grouped by Billomat feature area. **Source:** [Billomat REST API](https://www.billomat.com/en/api/) **Updated:** 2026-07-20 **Tags:** cloud, e-commerce, crud, user-management, file-management, notifications, logging, automation, auth:apikey ## Which Billomat endpoints are covered? **58%** (145 of ~250 endpoints). **Focus:** Billomat invoicing: invoices (items, payments, comments, tags), offers (estimates, quotes), credit notes, recurring invoices, clients (contacts), articles, taxes, units, suppliers, incoming invoices. **Missing:** article property values, client/supplier property values, inbox documents, activity feed, webhooks, templates CRUD (read-only here), settings write beyond read, letters, digital signature upload, postal mail (Pixelletter), encashment *Last reviewed: 2026-07-20* ## How do you configure the Billomat DADL? 1. Log in to your Billomat account at https://{billomatID}.billomat.net 2. Open Settings > Employees (Einstellungen > Mitarbeiter) and select your user 3. Enable API access for the user — a personal API key is generated 4. Store it as CREDENTIAL_BILLOMAT_API_KEY in .env (sent as the X-BillomatApiKey header) 5. Note your billomatID (the subdomain in your Billomat URL) — it forms the base URL **Environment variable:** `CREDENTIAL_BILLOMAT_API_KEY` [Authentication docs](https://www.billomat.com/en/api/basics/authentication/) *One credential is needed: CREDENTIAL_BILLOMAT_API_KEY (a person-bound API key from Settings > Employees). Replace YOUR_BILLOMAT_ID in the backends.yaml url with your account subdomain. Billomat has no OAuth scopes — the API key grants the issuing user's permissions, so restrict that user to limit API access. Optional: registering an App (Settings > Administration > Apps) yields an App-ID/App-Secret sent as separate X-AppId / X-AppSecret headers that only raise the rate limit (300 → plan quota per 15 min); adding those two credential-backed headers would need a small ToolMesh auth extension. A free developer account is available from api@billomat.com. * ## How do you install the Billomat MCP server with ToolMesh? Add to your `backends.yaml`: ```yaml - name: billomat transport: rest dadl: billomat.dadl url: "https://YOUR_BILLOMAT_ID.billomat.net/api" ``` Set the credential: ``` CREDENTIAL_BILLOMAT_API_KEY=your-token-here ``` ## What 145 tools does the Billomat DADL expose? - **GET** `list_clients` — List clients (customers). Filter with name, client_number, email, country_code, note, tags, invoice_id, creditor_identifier. Returns an array of client objects (values are strings). - **GET** `get_client` — Retrieve a single client by numeric ID - **POST** `create_client` — Create a client. Wrap fields under the `client` key. - **PUT** `update_client` — Update a client. Wrap changed fields under the `client` key (same fields as create_client). - **DELETE** `delete_client` — Permanently delete a client. Fails if the client still has documents. - **GET** `list_contacts` — List contacts for one client. client_id is REQUIRED — contacts are always scoped to a single client. Returns an array of contact objects. - **GET** `get_contact` — Retrieve a single contact by ID - **POST** `create_contact` — Create a contact for a client. Empty fields inherit the client's value. - **PUT** `update_contact` — Update a contact (same fields as create_contact). - **DELETE** `delete_contact` — Delete a contact - **GET** `list_articles` — List catalog articles (products/services). Filter with article_number, title, description, currency_code, unit_id, supplier_id. Returns an array. - **GET** `get_article` — Retrieve a single article by ID - **POST** `create_article` — Create a catalog article. - **PUT** `update_article` — Update an article (same fields as create_article). - **DELETE** `delete_article` — Delete an article from the catalog - **GET** `list_invoices` — List invoices. Filters: client_id, contact_id, invoice_number, status (DRAFT/OPEN/OVERDUE/PAID/CANCELED — comma-separated OR), payment_type, from, to (YYYY-MM-DD), label, intro, note, tags, article_id. group_by (client/status/day/week/month/year) returns aggregated sums instead. Returns an array of invoice objects (all values are strings). - **GET** `get_invoice` — Retrieve a single invoice by ID (includes combined taxes and totals) - **POST** `create_invoice` — Create an invoice (always DRAFT). Line items may be embedded. Call complete_invoice afterwards to assign a number and render the PDF. - **PUT** `update_invoice` — Update an invoice. Only DRAFT invoices can be edited. Items are managed via invoice-items, not here. - **DELETE** `delete_invoice` — Delete an invoice with all its documents (PDFs), items and comments. Irreversible. - **PUT** `complete_invoice` — Complete a DRAFT invoice: assigns the final invoice number, renders the PDF and moves the status to OPEN (or OVERDUE/PAID). Optional template_id. - **POST** `email_invoice` — Send the invoice to the client by e-mail. SIDE EFFECT: sends a real e-mail. recipients must contain at least one of to/cc/bcc. - **PUT** `cancel_invoice` — Cancel a completed invoice (status -> CANCELED) - **PUT** `uncancel_invoice` — Undo the cancellation of an invoice - **GET** `get_invoice_pdf` — Get the invoice PDF metadata and content. Returns { base64file, filename, mimetype, filesize } — decode base64file to obtain the PDF bytes. - **GET** `list_invoice_items` — List line items of an invoice. invoice_id is required. Returns an array ordered by position. - **GET** `get_invoice_item` — Retrieve a single invoice line item by ID - **POST** `create_invoice_item` — Add a line item to an existing invoice (DRAFT only). - **PUT** `update_invoice_item` — Update an invoice line item (same fields as create_invoice_item, without invoice_id). - **DELETE** `delete_invoice_item` — Delete an invoice line item - **GET** `list_invoice_payments` — List payments booked against invoices. Filters: invoice_id, from, to, type (payment type, comma-OR), user_id. Returns an array. - **GET** `get_invoice_payment` — Retrieve a single invoice payment by ID - **POST** `create_invoice_payment` — Book a payment for an invoice (invoice must be OPEN or OVERDUE). Set mark_invoice_as_paid to also flip the invoice to PAID. - **DELETE** `delete_invoice_payment` — Delete an invoice payment - **GET** `list_invoice_comments` — List comments/activity-log entries of an invoice. invoice_id required. Returns an array. - **POST** `create_invoice_comment` — Add a comment to an invoice's activity log. - **DELETE** `delete_invoice_comment` — Delete an invoice comment - **GET** `list_invoice_tags` — List tags of an invoice. invoice_id required. Returns an array. - **POST** `create_invoice_tag` — Attach a tag to an invoice. - **DELETE** `delete_invoice_tag` — Remove a tag from an invoice - **GET** `list_recurrings` — List recurring invoice templates. Filters: client_id, contact_id, name, payment_type, cycle. Returns an array of recurring objects. - **GET** `get_recurring` — Retrieve a single recurring invoice template by ID - **POST** `create_recurring` — Create a recurring invoice template that auto-generates invoices on a cycle. - **PUT** `update_recurring` — Update a recurring invoice template (same fields as create_recurring). - **DELETE** `delete_recurring` — Delete a recurring invoice template - **GET** `list_recurring_items` — List line items of a recurring template. recurring_id required. Returns an array. - **GET** `get_recurring_item` — Retrieve a single recurring line item by ID - **POST** `create_recurring_item` — Add a line item to a recurring template. - **PUT** `update_recurring_item` — Update a recurring line item (same fields as create_recurring_item, without recurring_id). - **DELETE** `delete_recurring_item` — Delete a recurring line item - **GET** `list_offers` — List estimates (offers/quotes). Filters: client_id, contact_id, offer_number, status (DRAFT/OPEN/WON/LOST/CANCELED/CLEARED — comma-OR), from, to, label, intro, note, tags, article_id. Returns an array. - **GET** `get_offer` — Retrieve a single estimate by ID - **POST** `create_offer` — Create an estimate/offer (always DRAFT). Complete it to assign a number and render the PDF. - **PUT** `update_offer` — Update an estimate (DRAFT only; same fields as create_offer). - **DELETE** `delete_offer` — Delete an estimate with all items and comments - **PUT** `complete_offer` — Complete a DRAFT estimate: assigns the number, renders the PDF, moves status to OPEN. Optional template_id. - **POST** `email_offer` — Send the estimate to the client by e-mail. SIDE EFFECT: sends a real e-mail. - **PUT** `cancel_offer` — Cancel an estimate (status -> CANCELED) - **PUT** `uncancel_offer` — Undo the cancellation of an estimate - **GET** `get_offer_pdf` — Get the estimate PDF: { base64file, filename, mimetype, filesize } — decode base64file. - **GET** `list_offer_items` — List line items of an estimate. offer_id required. Returns an array. - **GET** `get_offer_item` — Retrieve a single estimate line item by ID - **POST** `create_offer_item` — Add a line item to an estimate. - **PUT** `update_offer_item` — Update an estimate line item (same fields as create_offer_item, without offer_id). - **DELETE** `delete_offer_item` — Delete an estimate line item - **GET** `list_confirmations` — List order confirmations. Filters: client_id, contact_id, confirmation_number, status (DRAFT/OPEN/CANCELED/CLEARED), from, to, label, intro, note, tags, article_id. Returns an array. - **GET** `get_confirmation` — Retrieve a single order confirmation by ID - **POST** `create_confirmation` — Create an order confirmation (always DRAFT). - **PUT** `update_confirmation` — Update an order confirmation (DRAFT only; same fields as create_confirmation). - **DELETE** `delete_confirmation` — Delete an order confirmation with all items and comments - **PUT** `complete_confirmation` — Complete a DRAFT confirmation: assigns the number, renders the PDF, moves status to OPEN. - **POST** `email_confirmation` — Send the order confirmation by e-mail. SIDE EFFECT: sends a real e-mail. - **PUT** `cancel_confirmation` — Cancel an order confirmation (status -> CANCELED) - **GET** `get_confirmation_pdf` — Get the confirmation PDF: { base64file, filename, mimetype, filesize } — decode base64file. - **GET** `list_confirmation_items` — List line items of an order confirmation. confirmation_id required. Returns an array. - **GET** `get_confirmation_item` — Retrieve a single confirmation line item by ID - **POST** `create_confirmation_item` — Add a line item to an order confirmation. - **PUT** `update_confirmation_item` — Update a confirmation line item (same fields as create_confirmation_item, without confirmation_id). - **DELETE** `delete_confirmation_item` — Delete a confirmation line item - **GET** `list_credit_notes` — List credit notes. Filters: client_id, contact_id, credit_note_number, status (DRAFT/OPEN/PAID/CANCELED), from, to, label, intro, note, tags, article_id, invoice_id. Returns an array. - **GET** `get_credit_note` — Retrieve a single credit note by ID - **POST** `create_credit_note` — Create a credit note (always DRAFT). Optionally reference a source invoice via invoice_id. - **PUT** `update_credit_note` — Update a credit note (DRAFT only; same fields as create_credit_note). - **DELETE** `delete_credit_note` — Delete a credit note with all items and comments - **PUT** `complete_credit_note` — Complete a DRAFT credit note: assigns the number, renders the PDF, moves status to OPEN. - **POST** `email_credit_note` — Send the credit note by e-mail. SIDE EFFECT: sends a real e-mail. - **GET** `get_credit_note_pdf` — Get the credit note PDF: { base64file, filename, mimetype, filesize } — decode base64file. - **GET** `list_credit_note_items` — List line items of a credit note. credit_note_id required. Returns an array. - **GET** `get_credit_note_item` — Retrieve a single credit note line item by ID - **POST** `create_credit_note_item` — Add a line item to a credit note. - **PUT** `update_credit_note_item` — Update a credit note line item (same fields as create_credit_note_item, without credit_note_id). - **DELETE** `delete_credit_note_item` — Delete a credit note line item - **GET** `list_delivery_notes` — List delivery notes. Filters: client_id, contact_id, delivery_note_number, status (DRAFT/OPEN/CANCELED), from, to, label, intro, note, tags, article_id, invoice_id. Returns an array. - **GET** `get_delivery_note` — Retrieve a single delivery note by ID - **POST** `create_delivery_note` — Create a delivery note (always DRAFT). Often created from an invoice via invoice_id. - **PUT** `update_delivery_note` — Update a delivery note (DRAFT only; same fields as create_delivery_note). - **DELETE** `delete_delivery_note` — Delete a delivery note with all items and comments - **PUT** `complete_delivery_note` — Complete a DRAFT delivery note: assigns the number, renders the PDF, moves status to OPEN. - **POST** `email_delivery_note` — Send the delivery note by e-mail. SIDE EFFECT: sends a real e-mail. - **GET** `get_delivery_note_pdf` — Get the delivery note PDF: { base64file, filename, mimetype, filesize } — decode base64file. - **GET** `list_delivery_note_items` — List line items of a delivery note. delivery_note_id required. Returns an array. - **GET** `get_delivery_note_item` — Retrieve a single delivery note line item by ID - **POST** `create_delivery_note_item` — Add a line item to a delivery note. - **PUT** `update_delivery_note_item` — Update a delivery note line item (same fields as create_delivery_note_item, without delivery_note_id). - **DELETE** `delete_delivery_note_item` — Delete a delivery note line item - **GET** `list_reminders` — List dunning reminders for overdue invoices. Filters: client_id, contact_id, invoice_id, invoice_number, status (DRAFT/OPEN/CANCELED), from, to, label, intro, note. Returns an array. - **GET** `get_reminder` — Retrieve a single dunning reminder by ID - **POST** `create_reminder` — Create a dunning reminder for an overdue invoice (always DRAFT). The reminder level escalates automatically based on prior reminders. - **PUT** `update_reminder` — Update a dunning reminder (DRAFT only; same fields as create_reminder). - **DELETE** `delete_reminder` — Delete a dunning reminder - **PUT** `complete_reminder` — Complete a DRAFT reminder: assigns the number, renders the PDF, moves status to OPEN. - **POST** `email_reminder` — Send the dunning reminder by e-mail. SIDE EFFECT: sends a real e-mail. - **GET** `get_reminder_pdf` — Get the reminder PDF: { base64file, filename, mimetype, filesize } — decode base64file. - **GET** `list_suppliers` — List suppliers. Filters: name, supplier_number, email, country_code, note, tags. Returns an array. - **GET** `get_supplier` — Retrieve a single supplier by ID - **POST** `create_supplier` — Create a supplier (vendor for incoming invoices). - **PUT** `update_supplier` — Update a supplier (same fields as create_supplier). - **DELETE** `delete_supplier` — Delete a supplier - **GET** `list_incomings` — List incoming invoices (expenses / supplier bills). Filters: supplier_id, number, status (paid/unpaid/overdue), from, to, tags. Returns an array. - **GET** `get_incoming` — Retrieve a single incoming invoice by ID - **POST** `create_incoming` — Record an incoming invoice (expense) from a supplier. - **PUT** `update_incoming` — Update an incoming invoice (same fields as create_incoming). - **DELETE** `delete_incoming` — Delete an incoming invoice - **GET** `list_incoming_payments` — List payments made against incoming invoices. Filter with incoming_id. Returns an array. - **POST** `create_incoming_payment` — Book a payment against an incoming invoice. - **DELETE** `delete_incoming_payment` — Delete an incoming payment - **GET** `list_taxes` — List configured tax rates. Returns an array of tax objects (name, rate, is_default). - **GET** `get_tax` — Retrieve a single tax rate by ID - **POST** `create_tax` — Create a tax rate. - **PUT** `update_tax` — Update a tax rate (same fields as create_tax). - **DELETE** `delete_tax` — Delete a tax rate - **GET** `list_units` — List units of measure (e.g. hour, piece). Returns an array of unit objects. - **GET** `get_unit` — Retrieve a single unit by ID - **POST** `create_unit` — Create a unit of measure. - **PUT** `update_unit` — Rename a unit of measure. - **DELETE** `delete_unit` — Delete a unit of measure - **GET** `list_templates` — List document (PDF) templates. Filter with type (INVOICE, OFFER, ...). Returns an array. - **GET** `get_template` — Retrieve a single document template by ID - **GET** `list_email_templates` — List e-mail templates used by the email_* actions. Returns an array. - **GET** `get_email_template` — Retrieve a single e-mail template by ID - **GET** `get_settings` — Retrieve the account settings (default number ranges, texts, due days, currency, tax defaults, etc.). - **GET** `list_users` — List employees/users of the account. Returns an array of user objects. - **GET** `get_user` — Retrieve a single user by ID - **GET** `list_countries` — List countries with their tax/currency configuration. Returns an array. - **GET** `list_currencies` — List configured currencies. Returns an array. ## Which DADLs are related to Billomat? - [Xen Orchestra](https://www.dadl.ai/d/xen-orchestra/) — Xen Orchestra REST API (XO 6.4+, current through 6.9) -- complete coverage: VMs (incl. PATCH update + snapshot revert), VM controllers, hosts (incl. full power/lifecycle actions + maintenance mode + PIF rescan), pools (incl. add_host, rolling reboot/update with interrupted-update recovery + finalize), storage (SR create/delete, VDI incl. PATCH update + vhd/raw/qcow2 export, VBD), networks (VIF incl. PATCH update + PIF/PBD), VM/VDI snapshots, VM templates, hardware (PCI/PGPU/SM), tasks, backups (archives incl. live mount of backup disks, jobs/logs, repositories incl. health + benchmark + space reclaim), schedules, messages, alarms, events (SSE incl. non-XAPI collections), RBAC v2 (users/groups/acl-roles/acl-privileges incl. assignment introspection), proxies, servers, dashboards, SDN traffic rules (add/delete/update), IPMI sensor inventory (plugin), audit records (plugin), health check - [BookStack](https://www.dadl.ai/d/bookstack/) — BookStack wiki and documentation platform REST API -- shelves, books, chapters, pages (HTML/Markdown content), attachments, image gallery, comments, cross-entity search, exports (HTML/Markdown/PDF/ZIP), ZIP imports, users, roles, content permissions, recycle bin, audit log and tags. Hierarchy: shelves > books > chapters > pages. - [Mempool](https://www.dadl.ai/d/mempool/) — mempool.space — Bitcoin block explorer, mempool visualizer, fee estimator, Lightning Network explorer, and transaction accelerator - [NetBox](https://www.dadl.ai/d/netbox/) — NetBox DCIM/IPAM API -- full v4 coverage: sites, racks, devices, modules, interfaces, cables, power, IPAM (prefixes, IPs, VLANs, VRFs, route-targets, VLAN translation), virtualization, circuits (including virtual circuits), tenants, contacts, VPN (IKE/IPSec/L2VPN), wireless, extras (webhooks, event-rules, scripts, config-templates, bookmarks, notifications), users/permissions/tokens, and core data sources & jobs - [Soniox](https://www.dadl.ai/d/soniox/) — Soniox Speech AI — async speech-to-text for recorded audio (60+ languages, speaker diarization, language identification, speech translation), text-to-speech synthesis with voice cloning, audio file management, model discovery, temporary API keys for untrusted clients, and per-request usage, cost and concurrency reporting. - [Stripe](https://www.dadl.ai/d/stripe/) — Stripe REST API — payment processing, billing, subscriptions, invoices, products, and financial infrastructure --- **Canonical URL:** https://www.dadl.ai/d/billomat/ **Raw DADL:** https://github.com/DunkelCloud/dadl-registry/blob/main/billomat.dadl --- # BookStack MCP Server — 69 tools via DADL The BookStack DADL turns BookStack's API into an MCP server that Claude, GPT or any MCP-compatible agent can consume directly. One YAML file declares all 69 tools — book, chapter, image, page, role, attachment, and more — and ToolMesh serves them at runtime. No Python boilerplate, no per-endpoint code, no separate MCP server process. Below: the endpoint coverage matrix, a two-block ToolMesh setup, the full tool reference grouped by BookStack feature area, required credential scopes. **Source:** [BookStack REST API](https://demo.bookstackapp.com/api/docs) **Updated:** 2026-06-12 **Tags:** wiki, crud, user-management, file-management, notifications, logging, version-control, documentation, auth:apikey ## Which BookStack endpoints are covered? **98%** (69 of ~77 endpoints). **Focus:** BookStack full API: books (CRUD, exports), pages (CRUD, HTML, markdown, exports), chapters (CRUD, exports), shelves (CRUD, book assignment), attachments (links, uploads), images (gallery, drawio, file data), comments (threads, replies, archiving), search (cross-entity), users (CRUD, invites), roles (permissions, MFA), recycle-bin (restore, purge), content-permissions (role overrides, fallback), audit-log, tags, ZIP imports. **Missing:** Cover-image upload on book/shelf create/update and file replacement on attachment/image update (multipart facets of covered endpoints); the _method=PUT form workaround. All 77 documented endpoints are otherwise reachable -- the 15 export endpoints are collapsed into 6 parameterized tools. *Last reviewed: 2026-06-12* ## How do you configure the BookStack DADL? 1. Log in to your BookStack instance as the user the API should act as (its roles define what the API can see and do) 2. Ensure one of the user's roles grants the 'Access System API' permission: Settings > Roles > (role) > System Permissions 3. Open the user's profile (avatar top-right > 'Edit Profile') and scroll to the 'API Tokens' section 4. Click 'Create Token', enter a name and expiry date, then Save -- the Token ID and Token Secret are shown 5. Join both values with a colon to form the credential: ':' -- store this single string as bookstack_token **Environment variable:** `CREDENTIAL_BOOKSTACK_TOKEN` [Authentication docs](https://demo.bookstackapp.com/api/docs) *The backends.yaml url MUST include the /api suffix. The header sent is "Authorization: Token :" -- the credential value is the colon-joined pair, ToolMesh prepends the "Token " prefix. Content visibility mirrors the token user's roles exactly; for read-mostly agents prefer a dedicated low-privilege user. Default rate limit is 180 requests/min per user (env API_REQUESTS_PER_MIN). * ## How do you install the BookStack MCP server with ToolMesh? Add to your `backends.yaml`: ```yaml - name: bookstack transport: rest dadl: bookstack.dadl url: "https://wiki.example.com/api" ``` Set the credential: ``` CREDENTIAL_BOOKSTACK_TOKEN=your-token-here ``` ## What 69 tools does the BookStack DADL expose? - **GET** `search_content` — Search across all content types (shelves, books, chapters, pages) using the same query syntax as the BookStack UI search bar. Returns {data, total}; each result has a 'type' property (bookshelf, book, chapter, page), tags, parent references (book/chapter), and a 'preview_html' object with highlighted name/content snippets. Uses its own page/count paging -- sort and filter params are NOT supported here. - **GET** `list_shelves` — List all shelves visible to the API user. Returns id, name, slug, description, created_at, updated_at, created_by, updated_by, owned_by per shelf in {data, total}. - **GET** `get_shelf` — Get a single shelf with tags, cover image info, description_html and the visible books on it (id, name, slug each). - **POST** `create_shelf` — Create a new shelf. Optionally assign books by ID -- they appear on the shelf in the order given. Provide description (plain text) or description_html, not both. - **PUT** `update_shelf` — Update a shelf. Providing 'books' REPLACES the entire book assignment with the given list -- fetch current books via get_shelf first when only adding/removing one. - **DELETE** `delete_shelf` — Delete a shelf (sent to the recycle bin; books on it are NOT deleted). Returns 204. - **GET** `list_books` — List all books visible to the API user. Returns id, name, slug, description, created_at, updated_at, created_by, updated_by, owned_by plus cover image info per book in {data, total}. - **GET** `get_book` — Get a single book with tags, cover, description_html, shelves it is on, and a 'contents' tree listing its direct chapters and pages in display order -- each entry has a 'type' (chapter/page); chapters nest their pages. Use this to navigate a book's structure before reading pages. - **POST** `create_book` — Create a new book. Provide description (plain text) or description_html. Cover-image upload requires multipart and is not supported here. - **PUT** `update_book` — Update a book's details. Same writable fields as create_book. - **DELETE** `delete_book` — Delete a book including its chapters and pages (sent to the recycle bin). Returns 204. - **GET** `export_book` — Export a whole book (all chapters and pages compiled) as text. The result is the raw exported content -- HTML document, Markdown, or plain text. For PDF/ZIP use export_book_file. - **GET** `export_book_file` — Export a whole book as a binary file -- 'pdf' or 'zip' (portable BookStack ZIP). Returns a download URL via the ToolMesh file broker. - **GET** `list_chapters` — List all chapters visible to the API user. Returns id, book_id, name, slug, description, priority, created_at, updated_at, created_by, updated_by, owned_by per chapter in {data, total}. - **GET** `get_chapter` — Get a single chapter with tags, description_html, book_slug and its visible pages (listing-level fields each). - **POST** `create_chapter` — Create a new chapter inside a book. - **PUT** `update_chapter` — Update a chapter. Passing a different book_id MOVES the chapter (and its pages) into that book -- requires delete permission on the chapter. - **DELETE** `delete_chapter` — Delete a chapter including its pages (sent to the recycle bin). Returns 204. - **GET** `export_chapter` — Export a chapter (all its pages compiled) as text -- HTML document, Markdown, or plain text. For PDF/ZIP use export_chapter_file. - **GET** `export_chapter_file` — Export a chapter as a binary file -- 'pdf' or 'zip' (portable BookStack ZIP). Returns a download URL via the ToolMesh file broker. - **GET** `list_pages` — List all pages visible to the API user. Returns id, book_id, chapter_id (0 when directly in a book), name, slug, priority, draft, template, created_at, updated_at, created_by, updated_by, owned_by per page in {data, total}. Content is NOT included -- call get_page for that. - **GET** `get_page` — Get a single page with full content: 'html' (rendered output, includes resolved), 'raw_html' (stored source -- use as editing basis), 'markdown' (only if last saved with the Markdown editor), tags, and a 'comments' object with 'active' and 'archived' comment trees. - **POST** `create_page` — Create a new page. Exactly ONE of book_id (page directly in book) or chapter_id (page inside chapter) is required, and exactly ONE of html or markdown content. Keep HTML to a single-block depth of plain elements for editor compatibility; base64 data-URI images are extracted into the image gallery automatically. - **PUT** `update_page` — Update a page's details or content. Passing book_id or chapter_id MOVES the page to that parent (requires delete permission on the page). When updating content, base your edit on 'raw_html' from get_page and send it via 'html' -- the rendered 'html' field has include-tags resolved and round-trips badly. - **DELETE** `delete_page` — Delete a page (sent to the recycle bin). Returns 204. - **GET** `export_page` — Export a single page as text -- HTML document, Markdown, or plain text. For PDF/ZIP use export_page_file. Note: get_page already returns html/markdown content; exports add standalone document wrapping. - **GET** `export_page_file` — Export a single page as a binary file -- 'pdf' or 'zip' (portable BookStack ZIP). Returns a download URL via the ToolMesh file broker. - **GET** `list_attachments` — List attachments visible to the API user. Returns id, name, extension, uploaded_to (page ID), external (true = link attachment, false = file upload), order, created_at, updated_at, created_by, updated_by in {data, total}. - **GET** `get_attachment` — Get details and content of an attachment. 'content' holds the link URL for external attachments, or the FULL base64-encoded file data for uploads -- which can be very large; strip it with a jq override when you only need metadata. 'links' provides ready-made HTML and Markdown embed snippets. - **POST** `create_attachment` — Attach an external LINK to a page. For uploading a file as attachment use upload_attachment instead. - **POST** `upload_attachment` — Upload a FILE as attachment to a page (multipart request). The file is fetched from the given URL by ToolMesh and uploaded to BookStack. - **PUT** `update_attachment` — Update an attachment's name, target link, or move it to another page. Replacing an uploaded FILE requires a multipart PUT which is not modeled -- delete and re-create via upload_attachment instead. - **DELETE** `delete_attachment` — Permanently delete an attachment (no recycle bin). Returns 204. - **GET** `list_images` — List images in the system (page gallery images and drawio diagrams). Returns id, name, url, path, type (gallery|drawio), uploaded_to (page ID), created_by, updated_by, created_at, updated_at in {data, total}. Visibility requires access to the page each image was uploaded to. - **GET** `get_image` — Get details of a single image: url, 'thumbs' (scaled variants) and 'content' with ready-made HTML/Markdown embed snippets as BookStack would insert them. Image file data is NOT included -- use get_image_data or the 'url' property. - **POST** `create_image` — Upload a new image to the gallery of a page (multipart request). Use type 'gallery' for normal page images; 'drawio' ONLY for PNG files with embedded diagrams.net data. If name is omitted the filename is used. - **PUT** `update_image` — Update an image's name. Replacing the image FILE requires a multipart PUT which is not modeled -- upload a new image instead. - **DELETE** `delete_image` — Permanently delete an image and its thumbnails (no recycle bin). Usage is NOT checked -- pages referencing the image will show broken references. Returns 204. - **GET** `get_image_data` — Download the raw image file data for an image ID. Returns a download URL via the ToolMesh file broker instead of JSON. - **GET** `get_image_data_by_url` — Download raw image file data identified by its public BookStack image URL (as found in page content src attributes) instead of an ID. Returns a download URL via the ToolMesh file broker. - **GET** `list_comments` — List comments visible to the API user. Returns id, commentable_id (page ID), commentable_type, parent_id, local_id, content_ref, created_by, updated_by, created_at, updated_at in {data, total}. Comment HTML is NOT included -- use get_comment. For a page's full comment tree prefer get_page (comments property). - **GET** `get_comment` — Get a single comment (with safe HTML content) plus its direct replies. Note: 'local_id' is page-scoped; 'parent_id' of replies refers to the parent's local_id, not the global id. - **POST** `create_comment` — Create a comment on a page. To reply to an existing comment set reply_to to the parent comment's LOCAL_ID (page-scoped), not its global id. - **PUT** `update_comment` — Update a comment's content and/or archive state. Only provide 'archived' when actively changing it; only top-level comments (non-replies) can be archived/unarchived. - **DELETE** `delete_comment` — Permanently delete a comment (no recycle bin). Returns 204. - **GET** `list_users` — List all users. Requires 'Manage users' permission. Returns id, name, slug, email, external_auth_id, created_at, updated_at, last_activity_at plus profile/avatar URLs in {data, total}. - **GET** `get_user` — Get a single user including their assigned roles (id + display_name). Requires 'Manage users' permission. - **POST** `create_user` — Create a new user. Requires 'Manage users' permission. Either set a password or send_invite=true so the user sets their own via email. - **PUT** `update_user` — Update a user. Requires 'Manage users' permission. 'roles' replaces the full role assignment. - **DELETE** `delete_user` — Permanently delete a user. Requires 'Manage users' permission. Pass migrate_ownership_id to transfer ownership of their content to another user first. Returns 204. - **GET** `list_roles` — List all roles. Requires 'Manage roles' permission. Returns display_name, description, mfa_enforced, external_auth_id, timestamps plus permissions_count and users_count in {data, total}. - **GET** `get_role` — Get a single role including its granted permission name strings and a high-level list of assigned users. Requires 'Manage roles' permission. - **POST** `create_role` — Create a new role. Permissions are given as an array of permission name strings (e.g. 'access-api', 'page-create-all', 'book-view-own') -- inspect an existing role via get_role for the full vocabulary. - **PUT** `update_role` — Update a role. CAUTION: 'permissions' replaces ALL granted permissions and an empty array clears them -- fetch current permissions via get_role and send the modified full set. - **DELETE** `delete_role` — Permanently delete a role (users keep their other roles). Requires 'Manage roles' permission. Returns 204. - **GET** `list_recycle_bin` — List items in the recycle bin. Requires permission to manage both system settings and permissions. Each entry has a deletion id (use for restore/purge), deleted_by, deletable_type (page/chapter/book/ bookshelf), deletable_id and a 'deletable' object with child counts (books/chapters) or parent info (chapters/pages). - **PUT** `restore_recycle_bin_item` — Restore a deletion from the recycle bin, including all child content. Takes the DELETION id from list_recycle_bin, not the content's own ID. Returns {restore_count}. - **DELETE** `purge_recycle_bin_item` — PERMANENTLY destroy a deletion from the recycle bin including all child content -- this cannot be undone. Takes the DELETION id from list_recycle_bin. Returns {delete_count}. - **GET** `get_content_permissions` — Read the content-level permission OVERRIDES for one item: owner, role_permissions (per-role view/create/update/delete flags) and fallback_permissions ('inheriting': true means no override; its flag values are null then). Shows only overrides on this item -- not evaluated/inherited permissions. - **PUT** `update_content_permissions` — Update content-level permission overrides for one item. OMIT owner_id / role_permissions / fallback_permissions entirely to leave that category unchanged. CAUTION: an empty role_permissions array CLEARS all configured role overrides -- read existing permissions first and send the merged result. - **GET** `list_audit_log` — List audit log events. Requires permission to manage both users and system settings. Returns id, type (e.g. page_create, auth_login, permissions_update), detail, user_id (plus user object), loggable_id, loggable_type, ip, created_at in {data, total}. - **GET** `list_tag_names` — List distinct tag NAMES used across visible content, with usage totals: name, values (count of distinct values), usages, page_count, chapter_count, book_count, shelf_count. Only 'name' is filterable. Requires BookStack >= v26.05 -- older instances return a 404 HTML page. - **GET** `list_tag_values` — List the distinct VALUES set for one tag name across visible content, with usage totals per value. Only 'value' is filterable. Requires BookStack >= v26.05 -- older instances return a 404 HTML page. - **GET** `list_imports` — List pending ZIP imports visible to the user. Requires 'Import content' permission. Returns id, name, size, type (book/chapter/page), created_by, created_at, updated_at in {data, total}. - **POST** `create_import` — Upload and validate a BookStack portable ZIP file (from export_*_file zip exports) as a pending import. Does NOT import yet -- call run_import afterwards. Requires 'Import content' permission. - **GET** `get_import` — Read a pending ZIP import including a 'details' property with metadata about the ZIP content (structure varies by import type). - **POST** `run_import` — Execute a pending ZIP import. parent_type + parent_id are REQUIRED when the import's type is 'chapter' or 'page' (check via get_import); book imports need no parent. Returns the imported item on success. - **DELETE** `delete_import` — Delete a pending ZIP import (the staged upload, not imported content). Returns 204. - **GET** `get_system_info` — Read instance details: version, instance_id, app_name, app_logo (may be null), base_url. Useful for verifying connectivity and version-gated features. ## Which DADLs are related to BookStack? - [Billomat](https://www.dadl.ai/d/billomat/) — Billomat REST API — German cloud invoicing & accounting: invoices, estimates, credit notes, recurring invoices, delivery notes, order confirmations, dunning reminders, clients, contacts, articles, payments, expenses, taxes - [NetBox](https://www.dadl.ai/d/netbox/) — NetBox DCIM/IPAM API -- full v4 coverage: sites, racks, devices, modules, interfaces, cables, power, IPAM (prefixes, IPs, VLANs, VRFs, route-targets, VLAN translation), virtualization, circuits (including virtual circuits), tenants, contacts, VPN (IKE/IPSec/L2VPN), wireless, extras (webhooks, event-rules, scripts, config-templates, bookmarks, notifications), users/permissions/tokens, and core data sources & jobs - [Alertmanager](https://www.dadl.ai/d/alertmanager/) — Prometheus Alertmanager API v2 -- alerts, silences, receivers, alert groups, status, and operational health - [Checkmk](https://www.dadl.ai/d/checkmk/) — Checkmk REST API (version 1.0, Checkmk 2.4) -- live host and service status via Livestatus queries, downtimes, acknowledgements and comments, the Event Console (list, acknowledge, change state and archive events) and BI (packs, rules, aggregations and live aggregation state), plus the full Setup side: hosts, clusters, folders, service discovery, rules and rulesets, host/service/contact groups, users, roles, passwords, time periods, host tags, notification rules, site connections and change activation. - [DokuWiki](https://www.dadl.ai/d/dokuwiki/) — DokuWiki JSON-RPC API — wiki pages, media files, search, ACL management, and user administration - [Hacker News](https://www.dadl.ai/d/hackernews/) — Hacker News API — read-only access to stories, comments, polls, jobs, users, and live feeds from news.ycombinator.com --- **Canonical URL:** https://www.dadl.ai/d/bookstack/ **Raw DADL:** https://github.com/DunkelCloud/dadl-registry/blob/main/bookstack.dadl --- # Checkmk MCP Server — 146 tools via DADL The Checkmk DADL turns Checkmk's API into an MCP server that Claude, GPT or any MCP-compatible agent can consume directly. One YAML file declares all 146 tools — host, service, downtime, folder, rule, user, and more — and ToolMesh serves them at runtime. No Python boilerplate, no per-endpoint code, no separate MCP server process. Below: the endpoint coverage matrix, a two-block ToolMesh setup, the full tool reference grouped by Checkmk feature area, required credential scopes. **Source:** [Checkmk REST API](https://docs.checkmk.com/latest/en/rest_api.html) **Updated:** 2026-08-14 **Tags:** monitoring, crud, user-management, logging, notifications, deployment, real-time, auth:bearer ## Which Checkmk endpoints are covered? **63%** (146 of ~230 endpoints). **Focus:** Checkmk 2.4 REST API v1: host status and service status via Livestatus queries, downtimes for hosts and host groups, downtimes for services and service groups, downtime modification and deletion, acknowledgements, comments, event console (current events, acknowledge, change state, archive), BI (packs, rules, aggregations, live aggregation state), host configuration, host clusters, host bulk operations, folders with attribute inheritance, folder moves, service discovery, service phase updates, rules, rulesets, rule ordering, activation of pending changes, host groups, service groups, contact groups, roles and user accounts, passwords, time periods, host tags, aux tags, notification rules, site connections, agent download, metrics, audit log, background jobs, parent scan. **Missing:** HW/SW inventory trees, agent registration, event console HISTORY (its two endpoints exist only under the separate 'unstable' API version, unreachable below /api/1.0), the GET twin of the BI aggregation_state action (needs array query parameters), LDAP connections, broker connections, quick setup wizards, configuration entities (notification parameters), DCD (dynamic host configuration), licensing, certificate management, custom host attributes, autocomplete helpers, graph timerange and icon endpoints, agent baking and signature keys (CEE), bulk update/delete for the three group types, deprecated GET variants of the status collections. NOT a gap: Checkmk's global settings have no REST endpoint in any 2.x version (see domain notes). *Last reviewed: 2026-08-14* ## How do you configure the Checkmk DADL? 1. 1. Log into the Checkmk GUI of the site you want to automate 2. 2. Go to Setup > Users > Add user 3. 3. Set 'Username' to e.g. 'automation' and enable 'Automation secret for machine accounts' 4. 4. Click the dice icon to generate a secret, or paste your own, and copy it 5. 5. Assign roles: 'Monitoring user' for read-only, 'Administrator' for Setup writes 6. 6. Save the user, then click 'Activate on selected sites' -- a new user is a pending change 7. 7. Set CREDENTIAL_CHECKMK_AUTOMATION_SECRET to the string ' ' -- the 8. username, ONE space, then the secret (e.g. 'automation ABCdef123...'). The Checkmk 9. bearer token consists of both values; a bare secret results in HTTP 401. 10. 8. Point the backends.yaml url at the SITE, not the server: https:////check_mk/api/1.0 11. 9. Verify with the get_version tool -- it needs no parameters and no permissions. **Environment variable:** `CREDENTIAL_CHECKMK_AUTOMATION_SECRET` [Authentication docs](https://docs.checkmk.com/latest/en/rest_api.html) *The interactive, always-up-to-date API reference lives inside every Checkmk site under Help > REST API documentation (and the raw spec under //check_mk/api/1.0/openapi-swagger-ui/). Self-hosted: the url MUST contain the site name -- the shape is :////check_mk/api/1.0. Getting this wrong is the most common setup failure and it looks confusing: EVERY tool then returns the same HTTP 404 carrying an Apache HTML error page instead of Checkmk JSON. Diagnose it by requesting /version by hand -- the correct site answers with JSON ({"title": "Unauthorized"} when unauthenticated), a wrong path answers with Apache's HTML. If you do not know the site name, `omd sites` on the server lists it. An automation user must be activated once (step 6) before the API accepts it. For a read-only integration, give the user the 'Monitoring user' role only: every Setup tool in this backend then fails with HTTP 403 instead of silently changing configuration. * ## How do you install the Checkmk MCP server with ToolMesh? Add to your `backends.yaml`: ```yaml - name: checkmk transport: rest dadl: checkmk.dadl url: "https://monitoring.example.com/prod/check_mk/api/1.0" ``` Set the credential: ``` CREDENTIAL_CHECKMK_AUTOMATION_SECRET=your-token-here ``` ## What 146 tools does the Checkmk DADL expose? - **POST** `list_hosts_status` — Live status of monitored hosts, filtered with a Livestatus query. POST is used only to carry the query payload -- this is a read-only call. Returns one entry per host with exactly the columns requested. Example query for all non-UP hosts: {"op": "!=", "left": "state", "right": "0"}. Useful columns: name, address, alias, state (0=UP, 1=DOWN, 2=UNREACHABLE), state_type, acknowledged, scheduled_downtime_depth, last_check, last_state_change, plugin_output, num_services_crit, num_services_warn, tag_names, groups. Without a query this returns EVERY host -- always filter on large sites. Requires Checkmk 2.4+ (on 2.3 and older this URL only exists as GET). - **GET** `get_host_status` — Live status of ONE monitored host. Returns name, alias and address by default. Because ToolMesh cannot send repeated query parameters, only a single extra column can be selected here -- for a full column set call list_hosts_status with {"op": "=", "left": "name", "right": ""} instead. Answers HTTP 404 when the host is not monitored (a host that exists in Setup but was never activated is NOT monitored). - **POST** `list_services_status` — Live status of monitored services across all hosts, filtered with a Livestatus query. Read-only despite POST. The single most useful monitoring call: unacknowledged problems are {"op": "and", "expr": [{"op": "!=", "left": "state", "right": "0"}, {"op": "=", "left": "acknowledged", "right": "0"}, {"op": "=", "left": "scheduled_downtime_depth", "right": "0"}]}. Useful columns: host_name, description, state (0=OK, 1=WARN, 2=CRIT, 3=UNKNOWN), state_type, acknowledged, scheduled_downtime_depth, plugin_output, last_check, last_state_change, current_attempt, max_check_attempts, perf_data, host_state. Unfiltered this returns every service of every host -- easily tens of thousands of rows. Requires Checkmk 2.4+. - **POST** `list_host_services` — Live status of all monitored services of ONE host. Read-only despite POST. Same column and query semantics as list_services_status, but scoped to the host in the path -- the cheapest way to answer "what is wrong on host X". Requires Checkmk 2.4+. - **GET** `get_service_status` — Live status of ONE service on ONE host. Returns host_name, description, state, state_type and last_check by default -- a sensible set without further parameters. The service is addressed by its display name ("Filesystem /", "CPU utilization", "Check_MK"), which is what the `description` column contains. HTTP 404 when host or service is not monitored. - **GET** `list_downtimes` — All scheduled downtimes, host and service. Each entry carries the downtime id (as `id`), host_name, author, comment, start_time, end_time, is_service and recurring. The id is what delete_downtime(delete_type "by_id") and modify_downtime need. Note the `query` parameter is a JSON STRING here (GET), not an object. - **GET** `get_downtime` — Show a single downtime by its numeric id. site_id is required in distributed setups to locate the downtime. - **POST** `create_downtime_host` — Schedule a downtime for hosts. `downtime_type` selects how the targets are addressed: "host" (single host_name), "hostgroup" (all hosts of hostgroup_name) or "host_by_query" (all hosts matching query). start_time/end_time are ISO 8601 with timezone. A FIXED downtime (duration 0, the default) simply spans start..end. With duration > 0 the downtime is FLEXIBLE: it lasts `duration` SECONDS starting at the first problem inside the window. `recur` makes it repeat: fixed (default, no repeat), hour, day, week, second_week, fourth_week, weekday_start, weekday_end, day_of_month. Takes effect immediately, no activation needed. Returns 204 with no body on success. - **POST** `create_downtime_service` — Schedule a downtime for services. `downtime_type` selects the addressing: "service" (host_name plus service_descriptions), "servicegroup" (all services of servicegroup_name) or "service_by_query" (all services matching query). Same time, duration and recur semantics as create_downtime_host. To silence a whole host INCLUDING its services, schedule a host downtime and additionally a service downtime by query on that host -- a host downtime alone does not suppress service notifications. - **PUT** `modify_downtime` — Change end time and/or comment of existing downtimes. Select the downtimes exactly like delete_downtime does, via `modify_type`: by_id, params (host_name plus optional service_descriptions), query, hostgroup or servicegroup. `end_time` is an object: {"modify_type": "absolute", "value": "2026-08-12T22:00:00Z"} or {"modify_type": "relative", "value": 30} where value is a non-zero number of MINUTES added to (or, if negative, subtracted from) the current end time. - **POST** `delete_downtime` — Remove scheduled downtimes -- POST, not DELETE. `delete_type` selects the targets: "by_id" (downtime_id plus site_id), "params" (host_name, optionally narrowed by service_descriptions -- without them ALL downtimes of that host go away), "query" (Livestatus filter on the downtimes table), "hostgroup" or "servicegroup". Returns 204 with no body. Deleting a non-existent downtime is not an error. - **POST** `create_acknowledgement_host` — Acknowledge host problems, which stops notifications until the host recovers. `acknowledge_type`: "host" (host_name), "hostgroup" (hostgroup_name) or "host_by_query" (query on the hosts table). `sticky` keeps the acknowledgement until the host is UP again (not just until it improves), `notify` informs the contacts, `persistent` keeps the comment after recovery. Effective immediately. Returns 204. There is NO endpoint to remove an acknowledgement in this API version. - **POST** `create_acknowledgement_service` — Acknowledge service problems. `acknowledge_type`: "service" (host_name plus service_description -- exactly one service), "servicegroup" (servicegroup_name) or "service_by_query" (query on the services table; the way to acknowledge many services at once). Same sticky/notify/persistent semantics as create_acknowledgement_host. Effective immediately, returns 204, and cannot be undone via the API. - **GET** `list_comments` — List monitoring comments. The collection in the path selects the scope: "host" for host comments, "service" for service comments, "all" for both. Acknowledgements and downtimes also show up here, because Checkmk stores their text as comments. `query` is a JSON STRING (GET), filtering the Livestatus comments table. - **GET** `get_comment` — Show a single monitoring comment by its numeric id. site_id is required to locate the comment. - **POST** `create_comment_host` — Add a comment to hosts. `comment_type` is "host" (single host_name) or "host_by_query" (all hosts matching query). Non-persistent comments vanish when the monitoring core restarts; set persistent true to keep them. Comments do not suppress notifications -- use create_acknowledgement_host or a downtime for that. - **POST** `create_comment_service` — Add a comment to services. `comment_type` is "service" (host_name plus service_description) or "service_by_query" (all services matching query). Same persistence semantics as create_comment_host. - **POST** `delete_comments` — Delete monitoring comments -- POST, not DELETE. `delete_type`: "by_id" (comment_id plus site_id), "query" (Livestatus filter) or "params" (host_name, optionally narrowed by service_descriptions). Deleting the comment of an acknowledgement removes the acknowledgement -- this is the only indirect way to un-acknowledge a problem via the API. - **GET** `list_events` — Current (non-archived) Event Console events -- syslog, SNMP-trap and logfile events, a category of its own next to host/service states. Each entry has plain, un-prefixed fields: id (event id as string), site_id, host, application, text, state (STRING critical | warning | ok | unknown), phase (open|ack), count, first/last (ISO 8601), priority, facility, rule_id, service_level, comment, contact, ipaddress. Only inside `query` do the Livestatus column names apply -- event_-prefixed, as a JSON STRING here (GET), e.g. '{"op": "=", "left": "event_host", "right": "srv1"}'. - **GET** `get_event` — Show ONE current Event Console event by its numeric id. Unlike most single-object GETs of this API, `site_id` is REQUIRED -- EC events are only addressable per site. HTTP 404 when the event does not exist on that site (or was already archived). - **POST** `acknowledge_event` — Acknowledge ONE Event Console event -- or reopen it with phase "open". Optionally updates the event's comment and contact fields in the same call. Returns 204 with no body; 404 when the event id does not exist on that site. - **POST** `acknowledge_events` — Acknowledge (or reopen) MANY Event Console events at once. `filter_type` selects the targets: "query" (Livestatus filter OBJECT on eventconsoleevents), "params" (a `filters` object with at least one of state/host/application -- phase is NOT accepted here) or "all" (every event, optionally scoped by site_id). When acknowledging, only open events are touched. Returns 204 with NO count of affected events -- verify with list_events. - **POST** `change_event_state` — Set the state of ONE Event Console event. `new_state` is a STRING NAME (ok, warning, critical, unknown) although responses report event_state as an integer. Returns 204; 404 when the event does not exist on that site. - **POST** `change_event_states` — Set the state of MANY Event Console events at once. `filter_type` "query" takes a Livestatus filter OBJECT, "params" a `filters` object with at least one of state/host/application/phase. Returns 204 without an affected count. - **POST** `archive_events` — Archive Event Console events -- the EC "delete": the events leave the active list PERMANENTLY (no un-archive; their history stays visible in the GUI only). `filter_type` "by_id" needs event_id (an INTEGER in this body, unlike the string path params) plus site_id, "query" takes a Livestatus filter OBJECT, "params" a `filters` object with at least one of state/host/application/phase. Returns 204 without an affected count. - **GET** `list_hosts` — All hosts configured in Setup, with their folder and attributes. This is the CONFIGURATION view -- a host listed here is not necessarily monitored yet (it becomes monitored after activate_changes). For live state use list_hosts_status. Set effective_attributes to see the attributes inherited from the folder tree as well. Returns every host of the site; there is no paging. - **GET** `get_host` — Setup configuration of a single host: its folder, its explicitly set attributes and, on request, the effective attributes inherited from the folder tree. Cluster hosts additionally carry cluster_nodes. HTTP 404 if the host does not exist in Setup. - **POST** `create_host` — Create a host in Setup. `folder` uses tilde notation ("~" for the root folder, "~datacenter~racks" for a nested one). `attributes` holds the host attributes, most commonly {"ipaddress": "10.0.0.5", "site": "prod", "tag_agent": "cmk-agent", "tag_address_family": "ip-v4-only", "alias": "...", "labels": {"env": "prod"}, "parents": ["gateway"]}. The host is created but NOT monitored until you run service discovery and activate_changes -- see the add_host_monitored composite for the full flow. - **POST** `create_host_cluster` — Create a CLUSTER host -- a virtual host whose services are provided jointly by its nodes (e.g. a failover pair). Identical to create_host plus the mandatory `nodes` list, which must contain host names that already exist in Setup. - **PUT** `update_host` — Change the attributes of a host in Setup. Pick exactly ONE strategy: `attributes` REPLACES the whole attribute set (everything not listed is lost), `update_attributes` merges the given keys into the existing ones (the usual choice), `remove_attributes` deletes the listed attribute names. Requires If-Match; "*" is sent by default -- pass the ETag from get_host for real optimistic locking. - **PUT** `update_host_nodes` — Replace the node list of a CLUSTER host. The given list is authoritative -- nodes not included are detached from the cluster. Fails with HTTP 400 on a non-cluster host. - **PUT** `rename_host` — Rename a host, carrying over its historic data, downtimes and comments. This starts a BACKGROUND JOB and requires that there are NO pending changes (activate first, otherwise HTTP 409) and that the monitoring core is stopped for the rename window. Poll wait_host_rename_completion afterwards. - **GET** `wait_host_rename_completion` — Poll the currently running host-rename background job. HTTP 204 = finished, HTTP 302 = still running (call again), HTTP 404 = no rename job exists. Empty body in all cases. - **POST** `move_host` — Move a host to another folder. The host then inherits the attributes of the new folder, which can change how it is monitored (site, agent type, check intervals). Explicitly set host attributes are kept. - **DELETE** `delete_host` — Delete a host from Setup, including its services and its historic data reference. Returns 204. The host keeps being monitored until the next activate_changes. - **POST** `create_hosts_bulk` — Create many hosts in one request. `entries` is a list of create_host bodies: [{"host_name": "h1", "folder": "~linux", "attributes": {"ipaddress": "10.0.0.1"}}, ...]. Far cheaper than a loop for onboarding whole racks. The response contains the created hosts; entries that fail validation abort the request. - **PUT** `update_hosts_bulk` — Update many hosts in one request. `entries` is a list of {"host_name": "h1", "update_attributes": {...}} objects; `attributes` and `remove_attributes` work per entry exactly as in update_host. No If-Match is required for the bulk variant. - **POST** `delete_hosts_bulk` — Delete many hosts in one request -- POST, not DELETE. `entries` is a plain list of host names. Returns 204. Irreversible once activated. - **GET** `list_folders` — List folders of the Setup tree. By default only the direct children of the root folder are returned -- set recursive true for the whole tree, or point `parent` at a sub-folder. Each entry carries its path, title and attributes. Folder attributes are inherited by every host below, which makes folders the primary place to configure sites, agent types and check intervals. - **GET** `get_folder` — Show one folder with its title, path and attributes. `folder` uses tilde notation ("~" is the root folder, "~linux~web" a nested one) or the folder's 32-character hex id. Slashes do not work in the URL, not even percent-encoded. - **POST** `create_folder` — Create a folder. `name` is the directory name used in the path, `title` the label shown in the GUI, `parent` the containing folder in tilde notation ("~" for top level). `attributes` are inherited by all hosts and sub-folders below, e.g. {"site": "prod", "tag_agent": "cmk-agent", "snmp_community": "public"}. - **PUT** `update_folder` — Change title and/or attributes of a folder. Same three mutually exclusive strategies as update_host: `attributes` replaces everything, `update_attributes` merges, `remove_attributes` deletes named keys. Changing folder attributes silently reconfigures every host below. - **DELETE** `delete_folder` — Delete a folder. delete_mode "recursive" (the DEFAULT) removes the folder with all sub-folders and all hosts inside it -- pass "abort_on_nonempty" to refuse unless the folder is empty. Returns 204. - **POST** `move_folder` — Move a folder (with everything inside it) under a different parent. All hosts below inherit the attributes of the new parent chain. - **PUT** `update_folders_bulk` — Update several folders in one request. `entries` is a list of {"folder": "~linux~web", "title": ..., "update_attributes": {...}} objects, with the same attribute strategies as update_folder. No If-Match needed. - **GET** `list_folder_hosts` — List the hosts stored directly in one folder (not recursive). Cheaper and clearer than get_folder with show_hosts, and it returns full host_config objects including attributes. - **GET** `list_pending_changes` — All configuration changes that are staged but not yet activated. Each entry is a FLAT object {id, user_id, action_name, text, time} -- no extensions wrapper; `time` is an ISO 8601 string here (unlike the audit log, which returns epoch integers). An empty result means the running configuration matches Setup. Call this before activate_changes to see what you are about to publish, and above all to spot FOREIGN changes: any entry whose user_id is not your API user makes activate_changes fail unless force_foreign_changes is set. Note the `text` field is HTML-escaped by Checkmk (' for apostrophes). - **POST** `activate_changes` — Publish all pending Setup changes to the monitoring core -- nothing configured via the host_config/folder_config/rule/... tools takes effect before this runs. `sites` restricts the activation to certain sites (default: all sites with pending changes). `force_foreign_changes` is required when another user has staged changes as well. Without it Checkmk answers **HTTP 401** "There are changes from other users and foreign changes are not allowed in this API call" -- that reads like an auth failure and is mapped to `unauthorized`, but the credential is fine; check list_pending_changes for entries with a foreign user_id. Other status codes: 200 = accepted, 303 = started and still running, 422 = nothing to activate, 423 = another activation is already running, 409 = a site failed. The response carries {id, is_running, changes, sites, time_started} -- `id` feeds wait_activation_completion. Requires If-Match; "*" is sent by default -- pass the ETag from list_pending_changes to be sure that nothing changed in between. - **GET** `wait_activation_completion` — Block until an activation run finishes. HTTP 204 = completed, HTTP 302 = still running (call again), HTTP 404 = unknown activation id. Empty body. Use get_activation_run afterwards to see whether every site succeeded. - **GET** `get_activation_run` — Status of one activation run: {id, is_running, changes, sites, status_per_site, time_started, title}. Completion is `is_running: false` -- there is NO top-level "status" field. The outcome sits in `status_per_site`, an ARRAY of {site, state, phase, status_text, status_details, start_time, end_time} where state is "success"/"error" and phase reaches "done". ALWAYS check state per site: a finished run does not mean every site succeeded, and in a distributed setup one remote site can fail while the local one reports done. - **GET** `list_activation_runs` — All activation runs currently in progress. Non-empty means a subsequent activate_changes would fail with HTTP 423 (locked) -- check this first when automating. - **POST** `start_service_discovery` — Run a service discovery on one host as a background job. `mode` decides what happens to the result: "fix_all" (default -- add all undecided services and remove all vanished ones, the usual choice after creating a host), "new" (only add newly found services), "remove" (only drop vanished ones), "refresh" (re-scan and refresh labels/parameters), "only_host_labels", "only_service_labels", "tabula_rasa" (throw everything away and rediscover from scratch). The result is a pending Setup change -- run activate_changes afterwards. On 2.5 this returns the discovery RESULT directly ({id, title, check_table, host_labels, vanished_labels, changed_labels}) rather than a job handle, and a fast scan can finish before a job record exists -- wait_service_discovery_completion then answers HTTP 404, which means "already done", not "failed". Treat that 404 as success and read get_service_discovery. - **GET** `wait_service_discovery_completion` — Block until the discovery job of a host finishes. HTTP 204 = done, HTTP 302 = still running (call again), HTTP 404 = no discovery job for that host. Empty body. - **GET** `get_service_discovery_run` — Status and log output of the last service discovery job of a host -- use it to find out WHY a discovery produced nothing (unreachable agent, SNMP timeout, wrong credentials). - **GET** `get_service_discovery` — The discovery result of a host: every service the agent offers, grouped by phase -- "monitored" (active), "undecided" (found but not added), "vanished" (configured but no longer reported), "ignored" (disabled by rule). This is the read side that tells you what update_service_phase can act on. Shape: `check_table` is an OBJECT keyed by "-", each value being {value: "", extensions: {check_plugin_name, service_item, service_name, host_name, ...}} -- the phase sits in `value`, the display name in extensions.service_name. An empty check_table means the agent returned nothing (ping-only host, unreachable agent, wrong credentials) -- check get_service_discovery_run for the log. - **PUT** `update_service_phase` — Move a single discovered service into another phase -- the API equivalent of clicking one service in the discovery view. `target_phase` is usually "monitored" (accept an undecided service), "undecided" or "ignored" (disable it). `check_type` is the check plugin name (e.g. "df", "cpu_utilization") and `service_item` the item within that plugin (e.g. "/boot"), both as shown by get_service_discovery. Creates a pending change. - **POST** `start_discovery_bulk` — Run service discovery on MANY hosts as one background job -- the right tool after a bulk host import. `options` selects what to apply, e.g. {"monitor_undecided_services": true, "remove_vanished_services": true, "update_service_labels": false, "update_service_parameters": false, "update_host_labels": true} (all default to false). `do_full_scan` forces a fresh agent contact instead of using cached data, `bulk_size` is the number of hosts per worker batch, and `ignore_errors` keeps going when single hosts fail. Track it with get_background_job. - **GET** `list_rulesets` — Search the available rulesets -- the ~1700 configuration knobs of Checkmk (thresholds, check parameters, notification settings, agent options). The ruleset name (e.g. "checkgroup_parameters:filesystem", "host_groups", "active_checks:http") is what list_rules and create_rule expect. TRAP: `used` defaults to TRUE on the server, so without it you only see rulesets that ALREADY have rules -- on a fresh site that is a handful, and `fulltext`/`name` searches come back empty even for rulesets that plainly exist (verified on 2.5.0p11: no filter = 15 hits, used=false = 1674). To search the CATALOGUE, always pass used=false. That response is large (~400 KB), so combine it with `fulltext` or `group`. - **GET** `get_ruleset` — Show one ruleset with its title, help text, item form and the number of rules it holds. Read this before writing rules into it -- it tells you what the value structure has to look like. - **GET** `list_rules` — All rules of ONE ruleset, in evaluation order (the first matching rule wins). Each rule carries its id, folder, properties (description, comment, disabled), value_raw and conditions. `ruleset_name` is mandatory -- there is no "all rules of the site" call. - **GET** `get_rule` — Show one rule by its id, including value_raw and its conditions. - **POST** `create_rule` — Create a rule in a ruleset. `value_raw` is the rule value as a PYTHON REPRESENTATION STRING, not JSON -- e.g. "{'levels': (80.0, 90.0)}" for filesystem levels. Copy the exact shape from an existing rule via list_rules. `conditions` limits where the rule applies, e.g. {"host_name": {"match_on": ["web01"], "operator": "one_of"}, "host_tags": [{"key": "agent", "operator": "is", "value": "cmk-agent"}]}. `properties` holds {"description": "...", "comment": "...", "disabled": false}. New rules are inserted at the TOP of the folder's rule list; use move_rule to reposition. - **PUT** `update_rule` — Replace value, properties and conditions of an existing rule. The ruleset and folder of a rule cannot be changed here -- use move_rule for the folder, or delete and recreate. - **POST** `move_rule` — Change the evaluation position of a rule, which decides precedence. `position`: "top_of_folder" / "bottom_of_folder" (needs `folder`), "before_specific_rule" / "after_specific_rule" (needs the other rule's id in `rule_id`). - **DELETE** `delete_rule` — Delete a rule. Returns 204. Takes effect after activate_changes. - **GET** `list_host_groups` — All host groups with name and alias. Host groups are used as downtime/acknowledgement targets and as notification conditions. - **GET** `get_host_group` — Show one host group -- returns its name and alias. HTTP 404 if it does not exist, which is the cheapest existence check before referencing the group in a downtime or a rule. - **POST** `create_host_group` — Create a host group. `name` is the internal id used everywhere in the API, `alias` the label shown in the GUI. Assigning hosts to the group is done with a rule in the "host_groups" ruleset, not here. - **PUT** `update_host_group` — Change the alias of a host group. The name itself cannot be changed -- delete and recreate instead. - **DELETE** `delete_host_group` — Delete a host group. Fails while rules still reference it. Returns 204. - **POST** `create_host_groups_bulk` — Create several host groups in one request. `entries` is a list of {name, alias} objects. - **GET** `list_service_groups` — All service groups with name and alias. Used as downtime/acknowledgement targets and in notification rules. - **GET** `get_service_group` — Show one service group -- returns its name and alias. HTTP 404 if it does not exist, which is the cheapest existence check before using it as a downtime or acknowledgement target. - **POST** `create_service_group` — Create a service group. Membership is assigned via a rule in the 'service_groups' ruleset, not here. - **PUT** `update_service_group` — Change the alias of a service group. The name itself is immutable -- delete and recreate to rename it. - **DELETE** `delete_service_group` — Delete a service group. Fails while rules in the 'service_groups' ruleset still assign services to it. Returns 204 and takes effect after activate_changes. - **POST** `create_service_groups_bulk` — Create several service groups in one request. `entries` is a list of {name, alias} objects. - **GET** `list_contact_groups` — All contact groups. Contact groups are Checkmk's authorization unit: a user sees exactly the hosts and services whose contact groups they belong to, and notifications are routed by them. - **GET** `get_contact_group` — Show one contact group -- returns its name, alias and inventory path restrictions. It does NOT list the members: users carry their contact groups, hosts get them from an attribute or a rule. - **POST** `create_contact_group` — Create a contact group. Users are added to it via create_user/update_user (contactgroups), hosts via the 'host_contactgroups' ruleset or the host attribute 'contactgroups'. - **PUT** `update_contact_group` — Change alias and inventory path restrictions of a contact group. - **DELETE** `delete_contact_group` — Delete a contact group. Fails while users or rules still reference it. Returns 204. - **POST** `create_contact_groups_bulk` — Create several contact groups in one request. `entries` is a list of {name, alias} objects. - **GET** `list_users` — All configured users with their roles, contact groups and contact options. Passwords and secrets are never returned. - **GET** `get_user` — Show one user: full name, roles, contact groups, contact options and interface settings. Passwords and automation secrets are never returned -- there is no way to read a secret back out of Checkmk, only to set a new one via update_user. - **POST** `create_user` — Create a user. `auth_option` decides the login type: {"auth_type": "password", "password": "..."} for humans (they are forced to change it), or {"auth_type": "automation", "secret": "..."} for machine accounts used with this very API. `roles` is a list of role ids (["user"], ["admin"], ["guest"] or custom ones), `contactgroups` decides which hosts/services the user sees and is notified about, and `contact_options` holds {"email": "...", "fallback_contact": false}. A new user only works after activate_changes. - **PUT** `update_user` — Change a user. All fields are optional -- only what you pass is modified. Sending `auth_option` with a new password or secret rotates the credential (this is how you rotate the automation secret this backend itself uses). Roles and contactgroups are REPLACED, not merged. - **DELETE** `delete_user` — Delete a user. Returns 204. Takes effect after activate_changes. - **GET** `list_user_roles` — All user roles, built-in (admin, user, guest, agent_registration) and custom clones, with their permission sets. - **GET** `get_user_role` — Show one role with its alias, base role and permission overrides. - **POST** `create_user_role` — Clone an existing role -- roles are always derived, never created from nothing. `role_id` is the role to copy (admin, user, guest, agent_registration), `new_role_id` and `new_alias` name the clone. Adjust its permissions afterwards with update_user_role. - **PUT** `update_user_role` — Change a role: rename it (new_role_id/new_alias), re-base it (new_basedon, only for custom roles) or override single permissions. `new_permissions` is a map of permission name to "yes"/"no"/"default", e.g. {"general.server_side_requests": "no"}. - **DELETE** `delete_user_role` — Delete a custom user role. Built-in roles cannot be deleted. Returns 204. - **GET** `list_passwords` — All entries of the password store -- the shared secrets that rules reference by id instead of embedding them (SNMP communities, API tokens for active checks, agent credentials). The password VALUES are never returned, only the metadata. - **GET** `get_password` — Show one password store entry (metadata only, no secret). - **POST** `create_password` — Store a shared secret. `ident` is the id that rules reference. `owned_by` is the contact group owning the entry ("admin" or a contact group name), `editable_by` the group allowed to change it. Storing a secret here is much better than putting it into a rule value. - **PUT** `update_password` — Change a password store entry, including rotating the secret itself via `password`. - **DELETE** `delete_password` — Delete a password store entry. Rules referencing it break. Returns 204. - **GET** `list_time_periods` — All time periods. Time periods define when checks run and when notifications are sent (e.g. "workhours", "24X7"). Note the domain type is singular: time_period. - **GET** `get_time_period` — Show one time period with its active ranges, exceptions and exclusions. - **POST** `create_time_period` — Create a time period. `active_time_ranges` is a list of {"day": "monday"|...|"all", "time_ranges": [{"start": "08:00", "end": "17:00"}]}. `exceptions` overrides single dates: [{"date": "2026-12-24", "time_ranges": [{"start": "08:00", "end": "12:00"}]}]. `exclude` lists other time period names to subtract. - **PUT** `update_time_period` — Change a time period. Fields left out stay as they are; `active_time_ranges` is replaced as a whole when given. - **DELETE** `delete_time_period` — Delete a time period. Fails while rules or users still reference it. Returns 204. - **GET** `list_host_tag_groups` — All host tag groups. Host tags are Checkmk's classification mechanism: every host carries one tag per group (e.g. criticality: prod/test), and rules use them as conditions. - **GET** `get_host_tag_group` — Show one host tag group with its possible tags. - **POST** `create_host_tag_group` — Create a host tag group. `tags` is the list of choices: [{"id": "prod", "title": "Production", "aux_tags": []}, {"id": "test", "title": "Test"}]. A tag with id null becomes the "no choice" option. Hosts then set the attribute "tag_" to one of these ids. - **PUT** `update_host_tag_group` — Change a host tag group. `tags` replaces the whole choice list -- removing a tag that hosts still use fails unless `repair` is true, which then reassigns those hosts. - **DELETE** `delete_host_tag_group` — Delete a host tag group. Fails when hosts or rules still use it unless `repair` is set. Returns 204. - **GET** `list_aux_tags` — All auxiliary tags. Aux tags are attached to host tags and add a second, orthogonal dimension for rule conditions (e.g. tag 'snmp-v2' implies aux tag 'snmp'). - **GET** `get_aux_tag` — Show one auxiliary tag with its title, topic and help text. HTTP 404 if the id does not exist. - **POST** `create_aux_tag` — Create an auxiliary tag that host tags can reference in their aux_tags list. - **PUT** `update_aux_tag` — Change title, topic or help of an auxiliary tag. The id is immutable. - **POST** `delete_aux_tag` — Delete an auxiliary tag -- POST on the delete action, NOT the DELETE method. Fails while host tag groups still reference it. - **GET** `list_notification_rules` — All notification rules in evaluation order. Notification rules decide who is informed about which problem through which channel; they are evaluated top to bottom and all matching rules contribute unless one cancels the others. - **GET** `get_notification_rule` — Show one notification rule with its full rule_config. - **POST** `create_notification_rule` — Create a notification rule. Everything lives in the single nested `rule_config` object: {"rule_properties": {"description": "...", "comment": "", "documentation_url": "", "do_not_notify": {"state": "disabled"}, "allow_users_to_deactivate": {"state": "enabled"}}, "notification_method": {"notify_plugin": {"option": "create_notification_with_the_following_parameters", "plugin_params": {"plugin_name": "mail"}}}, "contact_selection": {...}, "conditions": {...}}. The structure is deep and version-specific -- read an existing rule with get_notification_rule first and modify a copy rather than writing one from scratch. - **PUT** `update_notification_rule` — Replace the configuration of a notification rule. `rule_config` must be complete -- this is not a merge. - **POST** `delete_notification_rule` — Delete a notification rule -- POST on the delete action, NOT the DELETE method. Returns 204. - **GET** `list_site_connections` — All configured site connections of this distributed monitoring setup, including their status host and socket configuration. - **GET** `get_site_connection` — Show one site connection: its basic settings, the Livestatus status connection (socket, proxy, timeouts, status host) and the configuration connection used for replication. - **POST** `create_site_connection` — Add a remote site to the distributed setup. Everything sits in the nested `site_config` object: {"basic_settings": {"site_id": "remote1", "alias": "Remote 1", "customer": "..."}, "status_connection": {"connection": {"socket_type": "tcp", "host": "10.0.0.9", "port": 6557, "encrypted": true, "verify": true}, "proxy": {"use_livestatus_daemon": "direct"}, "connect_timeout": 2, "status_host": {"status_host_set": "disabled"}, ...}, "configuration_connection": {"enable_replication": true, "url_of_remote_site": "https://10.0.0.9/remote1/check_mk/", ...}}. After creating the connection you still have to call login_site_connection. - **PUT** `update_site_connection` — Replace the configuration of an existing site connection. `site_config` must be complete. - **POST** `login_site_connection` — Log into a remote site to establish the configuration replication. Needs the credentials of an ADMIN user ON THE REMOTE SITE; Checkmk exchanges them for a permanent automation secret and does not store the password. Required once after create_site_connection. - **POST** `logout_site_connection` — Drop the replication credentials of a remote site. The connection stays configured but can no longer replicate. - **POST** `delete_site_connection` — Remove a site connection -- POST on the delete action, NOT the DELETE method. Log out first. - **GET** `get_version` — Version and edition of the site: {"site", "group", "rest_api": {"revision"}, "versions": {"checkmk", "python", "apache", ...}, "edition"}. Needs no parameters and almost no permissions -- the ideal connectivity and credential smoke test, and the way to find out which edition you are talking to before using edition-specific features. Edition strings: "community" (the former Raw/cre, renamed in 2.5), "enterprise"/"cee", "cloud"/"cce", "managed"/"cme". A 404 with an Apache error page instead of JSON means the configured URL misses the site segment -- see setup.notes. - **GET** `list_audit_log` — Audit log entries of ONE day -- `date` is required and expects YYYY-MM-DD. Every Setup change is recorded here with user, time, object and the diff text. Filter further by object_type (e.g. "Host", "Folder", "Rule"), object_id, user_id or a regular expression on the text. - **POST** `archive_audit_log` — Move all current audit log entries into the archive, clearing the active log. Irreversible via the API. Returns 204. - **GET** `get_background_job` — State of any background job by id: whether it is active or finished, its state and its log output. Use it for the jobs that have no dedicated wait tool, above all bulk discovery and parent scan. The job id is part of the response of the tool that started the job. - **POST** `get_metric` — Read the RRD time series behind a service graph. Read-only despite POST. `type` is "single_metric" (plus metric_id, e.g. "cmk_time_agent") or "predefined_graph" (plus graph_id, e.g. "cmk_cpu_time_by_phase"); both ids become visible in the GUI after enabling "Show internal IDs" in the service view's display options. `time_range` takes ISO 8601 start/end, `reduce` how a segment is condensed (average, min, max). The answer is {"time_range": {"start", "end"}, "step": , "metrics": [{"title", "color", "line_type", "data_points": [...]}]} -- data_points is a bare value array spaced `step` seconds apart, with nulls for gaps. Passing `site` is strongly recommended in distributed setups. - **GET** `download_agent` — Download one of the vanilla agent packages shipped with Checkmk. `os_type` is linux_rpm, linux_deb or windows_msi. These are the UNBAKED generic agents -- individually baked agents with per-host configuration are an Enterprise feature and are not available here. The binary is stored in the ToolMesh file broker and returned as a time-limited download URL, not as inline data. This endpoint serves ONLY application/octet-stream, so it overrides the backend-wide `Accept: application/json` via its own Accept parameter -- without that override Checkmk answers HTTP 406 (verified on 2.5.0p11). - **POST** `start_parent_scan` — Start a parent scan background job: Checkmk traceroutes to the given hosts and derives their network parents, which makes the monitoring suppress notifications for hosts that are merely UNREACHABLE behind a broken router. `gateway_hosts` decides what happens to gateways that are not yet monitored ({"state": "monitor_in_folder"|"do_not_monitor", "folder": "~", "alias": ...}), `performance` tunes the probing ({"responses_timeout", "hop_probes", "max_gateway_distance", "ping_probes"}) and `configuration` holds {"force_explicit_parents": true}. Track it with get_background_job. - **GET** `list_bi_packs` — All BI packs as {id, title} entries. A pack is the container object: it owns BI rules and BI aggregations and carries the contact-group permissions. Fresh sites ship one pack with id "default". Call get_bi_pack to see which rules and aggregations a pack contains. - **GET** `get_bi_pack` — One BI pack: title, contact_groups and public flag, plus the ids of the rules and aggregations it contains (this tool extracts them from the members links into plain `rules` and `aggregations` arrays). - **POST** `create_bi_pack` — Create a BI pack. ALL THREE body fields are required. Needs the wato.bi_admin permission on top of wato.edit + wato.bi_rules. Fails when the pack_id already exists. Live immediately -- BI configuration does not go through activate_changes. - **PUT** `update_bi_pack` — Replace title, contact_groups and public of an existing BI pack -- all three fields are required (full replace, no merge). The rules and aggregations inside the pack are preserved. Needs wato.bi_admin. - **DELETE** `delete_bi_pack` — Delete a BI pack. Refuses (HTTP 404 with a "contains N rules" detail) while the pack still contains RULES -- delete those first; contained aggregations do not block and are deleted with the pack. Needs wato.bi_admin. Returns 204. - **GET** `get_bi_rule` — One BI rule as plain JSON: {pack_id, id, nodes, params, node_visualization, properties, aggregation_function, computation_options}. This exact shape is what create_bi_rule and update_bi_rule expect as body -- read a rule, adapt it, write it back. - **POST** `create_bi_rule` — Create a BI rule inside a pack. The body is the FULL rule schema -- easiest is to get_bi_rule an existing rule and adapt it. `id` in the body must equal the rule_id in the path. `nodes` lists the child nodes, each {search: {...}, action: {...}} with action.type one of state_of_host, state_of_service, state_of_remaining_services or call_a_rule. `aggregation_function` decides how child states combine (type worst | best | count_ok). Fails when the rule_id already exists. Live immediately, no activation. - **PUT** `update_bi_rule` — Update an existing BI rule -- FULL REPLACE with the same body shape as create_bi_rule (get_bi_rule first, modify, write back). Fails when the rule_id does not exist. Live immediately. - **DELETE** `delete_bi_rule` — Delete a BI rule. HTTP 409 when the rule is still referenced by another rule or by an aggregation -- remove those references first. Returns 204. Live immediately. - **GET** `get_bi_aggregation` — One BI aggregation as plain JSON: {pack_id, id, comment, customer, groups, node, aggregation_visualization, computation_options}. This exact shape is what create_bi_aggregation and update_bi_aggregation expect as body. - **POST** `create_bi_aggregation` — Create a BI aggregation: the tree root that instantiates a rule (node.action.type "call_a_rule") for a set of hosts found by node.search. Mirror an existing aggregation from get_bi_aggregation. `groups.names` decides under which BI group headings the tree appears. computation_options: {disabled, use_hard_states, escalate_downtimes_as_warn}. Fails when the aggregation_id already exists. Live immediately, no activation. - **PUT** `update_bi_aggregation` — Update an existing BI aggregation -- FULL REPLACE with the same body shape as create_bi_aggregation. Fails when the aggregation_id does not exist. Live immediately. - **DELETE** `delete_bi_aggregation` — Delete a BI aggregation. Returns 204. Live immediately, no activation. - **POST** `get_bi_aggregation_states` — LIVE state of BI aggregations, computed on the fly from current host/service states. Read-only despite POST (the GET twin needs array query parameters, which this backend cannot send). Returns {aggregations: {: {state, output, hosts, acknowledged, in_downtime, in_service_period, infos}}, missing_sites, missing_aggr}. The dict is keyed by aggregation TITLE (properties.title), not id, and BI states are INTEGERS: 0=OK, 1=WARN, 2=CRIT, 3=UNKNOWN, -1=pending. Computing every aggregation can be expensive -- filter on big installations. An empty aggregations object means no aggregation matched, none is configured, or the matching aggregations are DISABLED -- fresh sites ship default_aggregation with computation_options.disabled=true, so a brand-new site returns {} here until an aggregation is enabled. ## What composite workflows does the Checkmk DADL provide? - **FN** `get_problems` — The "what is broken right now" call. Returns {hosts, services, summary} with all hosts that are not UP and all services that are not OK, by default hiding everything that is already acknowledged or in a scheduled downtime. Set include_handled true to see those as well, or limit the scope to a single host with host_name. This is one round trip instead of two hand-written Livestatus queries and is the right entry point for any triage question. - **FN** `apply_pending_changes` — Activate all pending Setup changes and wait until the activation has really finished -- activate_changes alone only STARTS the job. Returns {activated, activation_id, changes, state, sites}. Answers {activated: false, reason: "no_pending_changes"} when there is nothing to do, so it is safe to call unconditionally at the end of a configuration session. Set force_foreign true when other users have staged changes as well, otherwise Checkmk refuses to activate them. - **FN** `add_host_monitored` — Create a host and take it all the way to "actually monitored": create_host, then a service discovery in fix_all mode, then activation of the pending changes. Returns {host, folder, discovered, activated, services}. This is the complete onboarding flow -- doing only create_host leaves a host that exists in Setup but is never checked. Set activate false to stage the change and activate later together with other work. ## Which DADLs are related to Checkmk? - [Alertmanager](https://www.dadl.ai/d/alertmanager/) — Prometheus Alertmanager API v2 -- alerts, silences, receivers, alert groups, status, and operational health - [Graylog](https://www.dadl.ai/d/graylog/) — Graylog REST API -- log search (Views/Search + legacy universal), streams, pipelines, inputs, alerts, events, dashboards, users, roles, sidecars, index management, and cluster administration. Targets Graylog 6.x. - [Hacker News](https://www.dadl.ai/d/hackernews/) — Hacker News API — read-only access to stories, comments, polls, jobs, users, and live feeds from news.ycombinator.com - [Mempool](https://www.dadl.ai/d/mempool/) — mempool.space — Bitcoin block explorer, mempool visualizer, fee estimator, Lightning Network explorer, and transaction accelerator - [Mikrotik](https://www.dadl.ai/d/mikrotik/) — MikroTik RouterOS REST API -- manage interfaces, IP addresses, routing, firewall, DHCP, DNS, PPP, queues, wireless, system configuration, users, certificates, files, logs, and diagnostics on RouterOS v7.1+ devices - [PeeringDB](https://www.dadl.ai/d/peeringdb/) — PeeringDB v2 API -- the public peering database of networks (ASNs), Internet Exchanges, and colocation facilities: full CRUD over net, ix, fac, org, carrier, campus, point-of-contact records, and the netixlan/netfac/ixfac/carrierfac/ixlan/ixpfx relationships that map who peers where --- **Canonical URL:** https://www.dadl.ai/d/checkmk/ **Raw DADL:** https://github.com/DunkelCloud/dadl-registry/blob/main/checkmk.dadl --- # Cloudflare MCP Server — 284 tools via DADL The Cloudflare DADL turns Cloudflare's API into an MCP server that Claude, GPT or any MCP-compatible agent can consume directly. One YAML file declares all 284 tools — email, page, zone, worker, account, secondary, and more — and ToolMesh serves them at runtime. No Python boilerplate, no per-endpoint code, no separate MCP server process. Below: the endpoint coverage matrix, a two-block ToolMesh setup, the full tool reference grouped by Cloudflare feature area, required credential scopes. **Source:** [Cloudflare REST API v4](https://developers.cloudflare.com/api/) **Updated:** 2026-10-10 **Tags:** cloud, dns, storage, security, crud, search, authentication, deployment, auth:bearer ## Which Cloudflare endpoints are covered? **19%** (284 of ~1500 endpoints). **Focus:** zones, DNS records, DNSSEC, DNS settings, secondary DNS incoming/outgoing/peers/TSIGs/ACLs, DNS Firewall clusters, Registrar domains/search/pricing/registration, Pages projects/deployments/domains, Workers scripts/routes/secrets/cron/deployments/tails, KV namespaces/keys, R2 buckets/lifecycle/CORS/domains, D1 databases/queries, SSL/TLS certificates/custom hostnames, cache purge/settings, load balancers/pools/monitors, firewall rules/rulesets/rate limits, page rules, Access apps/policies/groups, accounts/members/roles, Email Routing settings/DNS/rules/catch-all/destination addresses, Email Sending send/raw MIME/sending subdomains/DNS status/suppressions/reputation/limits, Email Auth DMARC reports/SPF inspection **Missing:** Argo, Spectrum, Stream, Images (transformations), Email Security (Area 1), Email Routing wrangler plan endpoint, Radar email statistics, Waiting Room, Web3, Turnstile, Queues, Hyperdrive, Vectorize, AI Gateway, Durable Objects, Zone Lockdown, IP Access Rules, User-Agent Blocking, Logpush, Notifications, Audit Logs *Last reviewed: 2026-10-10* ## How do you configure the Cloudflare DADL? 1. Log in to Cloudflare dashboard at https://dash.cloudflare.com 2. Go to My Profile (top right) → API Tokens 3. Click 'Create Token' 4. Use a template (e.g. 'Edit zone DNS') or create a custom token with specific permissions 5. Copy the token immediately -- it is shown only once **Environment variable:** `CREDENTIAL_CLOUDFLARE_API_TOKEN` [Authentication docs](https://developers.cloudflare.com/fundamentals/api/get-started/create-token/) *API Tokens (scoped) are preferred over the Global API Key. Tokens can be restricted to specific zones and permissions. The Global API Key (X-Auth-Email + X-Auth-Key headers) grants full account access and is only needed for the rare endpoints that reject tokens. Registrar: the registrar/domains endpoints DO work with a scoped API Token, but only if it carries the 'Account > Registrar > Domains' permission (Read for list/get, Edit for update) -- without it Cloudflare returns HTTP 403 (code 10000). Verified working against the live API with a scoped token plus that permission; the Global API Key is not required. The Registrar API beta tools (search_registrar_domains, check_registrar_domains, register_registrar_domain) additionally require the token's Registrar permission at Edit/write level AND a billing profile + default registrant contact configured on the account. Email: routing settings, DNS, rules and catch-all need the zone permission 'Email Routing Rules' (Read/Edit); destination addresses need the account permission 'Email Routing Addresses' (Read/Edit); DMARC/SPF tools need 'DMARC Management' (Read/Edit); Email Sending (send, sending subdomains, suppressions, reputation, limits) needs the account permission 'Email Sending' (Read/Edit) plus a sending subdomain whose DNS status is ready. Verified 2026-09-27 against the live API: routing settings/DNS/rules/catch-all, destination addresses, DMARC status/config, SPF inspection, sending limits, sending-subdomain preview and the suppression CRUD work with a scoped token carrying those permissions; the account-wide rules list still returned 403 with per-zone rule permissions, and reputation returns 404 until Email Sending is activated.* ## How do you install the Cloudflare MCP server with ToolMesh? Add to your `backends.yaml`: ```yaml - name: cloudflare transport: rest dadl: cloudflare.dadl ``` Set the credential: ``` CREDENTIAL_CLOUDFLARE_API_TOKEN=your-token-here ``` ## What 284 tools does the Cloudflare DADL expose? - **GET** `list_accounts` — List all accounts you have access to. The returned id is the account_id that every account-scoped tool requires (Pages, Workers, KV, R2, D1, Access, Email Sending) -- call this first when you do not know it; most users see exactly one account. - **GET** `get_account` — Get account details - **PUT** `update_account` — Update account settings - **GET** `list_account_members` — List all account members - **GET** `get_account_member` — Get account member details - **POST** `add_account_member` — Add a member to an account - **PUT** `update_account_member` — Update account member roles - **DELETE** `remove_account_member` — Remove a member from an account - **GET** `list_account_roles` — List all available roles for an account - **GET** `get_account_role` — Get role details and permissions - **GET** `verify_token` — Verify the API token used for this request: returns its id and status (active/expired/disabled) plus validity window. Confirms auth works; does NOT list the token's own permissions (use GET /user/tokens/{id} for that). - **GET** `list_token_permission_groups` — List the catalog of grantable API token permission groups (id, name, scopes). Use to find the exact group ID to attach when creating a token via the API -- e.g. filter name=Registrar to locate the registrar read vs write groups. Returns the global catalog, NOT the current token's permissions. Needs the token permission User > API Tokens (Read); without it Cloudflare answers HTTP 403 code 9109. - **GET** `list_zones` — List, search, sort, and filter zones. Returns zone_id needed for all zone-scoped endpoints. - **GET** `get_zone` — Get zone details - **POST** `create_zone` — Create a new zone (add a domain to Cloudflare) - **PATCH** `update_zone` — Edit zone properties (paused, type, vanity nameservers) - **DELETE** `delete_zone` — Delete a zone and all associated settings. Irreversible. - **PUT** `check_zone_activation` — Trigger activation check for a PENDING zone. Rate limited (5min paygo/enterprise, 1hr free). - **GET** `list_zone_settings` — Get all zone settings - **GET** `get_zone_setting` — Get a single zone setting by ID - **PATCH** `update_zone_setting` — Update a single zone setting - **GET** `get_zone_hold` — Get zone hold status and metadata - **POST** `create_zone_hold` — Enforce a zone hold (block zone creation with this hostname) - **DELETE** `delete_zone_hold` — Remove zone hold (permanently or temporarily) - **GET** `list_zone_plans` — List available plans the zone can subscribe to - **GET** `get_zone_subscription` — Get zone subscription details - **POST** `create_zone_subscription` — Create zone subscription (plan/add-on) - **GET** `list_registrar_domains` — List all domains managed by Cloudflare Registrar in this account. Returns name, status, expiry, current registrar, and lock/auto-renew/privacy flags. Does not include zones that are merely using Cloudflare DNS. - **GET** `get_registrar_domain` — Get details for a single Cloudflare Registrar domain (status, expiry, contacts, nameservers, lock/auto-renew/privacy). Response is trimmed to key fields; pass a jq filter to override if you need the raw WHOIS object. - **PUT** `update_registrar_domain` — Update an existing Cloudflare Registrar domain. Only auto_renew, privacy (WHOIS redaction), and locked (registrar transfer lock) are editable here; nameservers are managed on the zone. To register a NEW domain use register_registrar_domain instead. - **GET** `search_registrar_domains` — Search for registrable domain suggestions by keyword/phrase (Registrar API beta). Returns candidate domains across TLDs WITH availability and pricing (registration_cost/renewal_cost), same per-domain shape as check_registrar_domains. - **POST** `check_registrar_domains` — Check availability AND pricing for up to 20 domains at once (Registrar API beta). For each domain returns registrable, tier, reason (when not registrable), and pricing (currency, registration_cost, renewal_cost) at Cloudflare's at-cost wholesale rate. - **POST** `register_registrar_domain` — Register a NEW domain via Cloudflare Registrar (Registrar API beta). PLACES A PAID ORDER charged to the account billing profile, using the account's default registrant contact. Run check_registrar_domains first to confirm availability and price. Irreversible billing action. - **GET** `list_dns_records` — List, search, sort, and filter DNS records for a zone - **GET** `get_dns_record` — Get a single DNS record - **POST** `create_dns_record` — Create a new DNS record - **PATCH** `update_dns_record` — Update (partial) a DNS record - **PUT** `overwrite_dns_record` — Overwrite (full replace) a DNS record - **DELETE** `delete_dns_record` — Delete a DNS record - **POST** `batch_dns_records` — Batch create/update/delete DNS records atomically in one transaction - **POST** `import_dns_records` — Import DNS records from a BIND config file - **GET** `export_dns_records` — Export DNS records as BIND zone file - **POST** `scan_dns_records` — Scan for common DNS records and auto-add them - **GET** `get_dnssec` — Get DNSSEC status and configuration - **PATCH** `update_dnssec` — Enable or disable DNSSEC - **DELETE** `delete_dnssec` — Delete DNSSEC records - **GET** `get_zone_dns_settings` — Get DNS settings for a zone - **PATCH** `update_zone_dns_settings` — Update DNS settings for a zone - **GET** `get_account_dns_settings` — Get DNS settings for an account - **PATCH** `update_account_dns_settings` — Update DNS settings for an account - **GET** `get_dns_analytics` — Get summarized aggregate DNS metrics over a time period - **GET** `get_dns_analytics_by_time` — Get aggregate DNS metrics grouped by time interval - **GET** `get_secondary_dns_incoming` — Get the incoming (secondary) zone transfer configuration. Cloudflare pulls this zone from your external primary. - **POST** `create_secondary_dns_incoming` — Create the incoming (secondary) zone transfer config so Cloudflare pulls the zone from your primary. peers references account-scoped peer tags. - **PUT** `update_secondary_dns_incoming` — Update the incoming (secondary) zone transfer configuration - **DELETE** `delete_secondary_dns_incoming` — Delete the incoming (secondary) zone transfer configuration - **POST** `force_axfr_secondary_dns` — Force an immediate AXFR (full zone transfer) from the primary for a secondary zone - **GET** `get_secondary_dns_outgoing` — Get the outgoing (primary) zone transfer configuration. Cloudflare serves this zone as primary and notifies external secondaries. - **POST** `create_secondary_dns_outgoing` — Create the outgoing (primary) zone transfer config so external secondaries can pull this zone from Cloudflare. peers references account-scoped peer tags. - **PUT** `update_secondary_dns_outgoing` — Update the outgoing (primary) zone transfer configuration - **DELETE** `delete_secondary_dns_outgoing` — Delete the outgoing (primary) zone transfer configuration - **POST** `enable_secondary_dns_outgoing` — Enable outgoing zone transfers (resume notifying external secondaries) - **POST** `disable_secondary_dns_outgoing` — Disable outgoing zone transfers (stop notifying external secondaries) - **POST** `force_notify_secondary_dns_outgoing` — Send a DNS NOTIFY to all external secondaries to prompt an immediate pull - **GET** `get_secondary_dns_outgoing_status` — Get the enabled/disabled status of outgoing zone transfers - **GET** `list_dns_peers` — List all secondary DNS peers (nameservers) for an account. Peer tags are referenced from zone incoming/outgoing configs. - **GET** `get_dns_peer` — Get a single secondary DNS peer - **POST** `create_dns_peer` — Create a secondary DNS peer (a primary/secondary nameserver Cloudflare transfers with) - **PUT** `update_dns_peer` — Update a secondary DNS peer - **DELETE** `delete_dns_peer` — Delete a secondary DNS peer - **GET** `list_dns_tsigs` — List all secondary DNS TSIG keys for an account - **GET** `get_dns_tsig` — Get a single secondary DNS TSIG key - **POST** `create_dns_tsig` — Create a TSIG key for authenticated zone transfers - **PUT** `update_dns_tsig` — Update a secondary DNS TSIG key - **DELETE** `delete_dns_tsig` — Delete a secondary DNS TSIG key - **GET** `list_dns_acls` — List all secondary DNS ACLs (IP-range allowlists) for an account - **GET** `get_dns_acl` — Get a single secondary DNS ACL - **POST** `create_dns_acl` — Create a secondary DNS ACL restricting which peer IP ranges may transfer - **PUT** `update_dns_acl` — Update a secondary DNS ACL - **DELETE** `delete_dns_acl` — Delete a secondary DNS ACL - **GET** `list_dns_firewall_clusters` — List all DNS Firewall clusters (account-scoped recursive resolvers). Distinct from authoritative zone DNS and from zone firewall rules. - **GET** `get_dns_firewall_cluster` — Get a DNS Firewall cluster's configuration, including the anycast dns_firewall_ips to point clients at - **POST** `create_dns_firewall_cluster` — Create a DNS Firewall cluster. upstream_ips are your origin resolvers; the response returns anycast IPs to use as your nameservers. - **PATCH** `update_dns_firewall_cluster` — Update a DNS Firewall cluster's configuration (rate limits, cache TTLs, upstreams, mitigation) - **DELETE** `delete_dns_firewall_cluster` — Delete a DNS Firewall cluster - **GET** `list_pages_projects` — List all Cloudflare Pages projects. Requires account_id -- the Cloudflare account ID from list_accounts (field id), not a zone_id. - **GET** `get_pages_project` — Get a Pages project by name. Requires account_id -- the Cloudflare account ID from list_accounts (field id), not a zone_id. - **POST** `create_pages_project` — Create a new Pages project. Requires account_id -- the Cloudflare account ID from list_accounts (field id), not a zone_id. - **PATCH** `update_pages_project` — Update Pages project attributes. Requires account_id -- the Cloudflare account ID from list_accounts (field id), not a zone_id. - **DELETE** `delete_pages_project` — Delete a Pages project and all deployments. Irreversible. Requires account_id -- the Cloudflare account ID from list_accounts (field id), not a zone_id. - **POST** `purge_pages_build_cache` — Purge all cached build artifacts for a Pages project. Requires account_id -- the Cloudflare account ID from list_accounts (field id), not a zone_id. - **GET** `list_pages_deployments` — List all deployments for a Pages project. Requires account_id -- the Cloudflare account ID from list_accounts (field id), not a zone_id. - **GET** `get_pages_deployment` — Get a specific deployment. Requires account_id -- the Cloudflare account ID from list_accounts (field id), not a zone_id. - **POST** `create_pages_deployment` — Create a new deployment (direct upload via multipart or trigger Git build). Requires account_id -- the Cloudflare account ID from list_accounts (field id), not a zone_id. - **DELETE** `delete_pages_deployment` — Delete a deployment. Requires account_id -- the Cloudflare account ID from list_accounts (field id), not a zone_id. - **POST** `retry_pages_deployment` — Retry a failed deployment. Requires account_id -- the Cloudflare account ID from list_accounts (field id), not a zone_id. - **POST** `rollback_pages_deployment` — Rollback production to a previous deployment. Requires account_id -- the Cloudflare account ID from list_accounts (field id), not a zone_id. - **GET** `get_pages_deployment_logs` — Get build/deployment logs for a specific deployment. Requires account_id -- the Cloudflare account ID from list_accounts (field id), not a zone_id. - **GET** `list_pages_domains` — List all custom domains for a Pages project. Requires account_id -- the Cloudflare account ID from list_accounts (field id), not a zone_id. - **GET** `get_pages_domain` — Get a specific Pages domain. Requires account_id -- the Cloudflare account ID from list_accounts (field id), not a zone_id. - **POST** `add_pages_domain` — Add a custom domain to a Pages project. Requires account_id -- the Cloudflare account ID from list_accounts (field id), not a zone_id. - **PATCH** `retry_pages_domain_validation` — Retry domain validation for a Pages custom domain. Requires account_id -- the Cloudflare account ID from list_accounts (field id), not a zone_id. - **DELETE** `delete_pages_domain` — Remove a custom domain from a Pages project. Requires account_id -- the Cloudflare account ID from list_accounts (field id), not a zone_id. - **GET** `list_worker_scripts` — List all uploaded Worker scripts - **GET** `get_worker_script` — Fetch raw Worker script content - **PUT** `upload_worker_script` — Upload or update a Worker script (multipart: module content + metadata with bindings) - **DELETE** `delete_worker_script` — Delete a Worker script - **GET** `get_worker_script_content` — Fetch Worker script content only (without metadata) - **PUT** `update_worker_script_content` — Update Worker script content without changing settings/bindings - **GET** `list_worker_routes` — List all Worker routes for a zone - **GET** `get_worker_route` — Get a specific Worker route - **POST** `create_worker_route` — Create a Worker route (map URL pattern to a Worker script) - **PUT** `update_worker_route` — Update a Worker route - **DELETE** `delete_worker_route` — Delete a Worker route - **GET** `list_worker_cron_triggers` — List cron triggers for a Worker - **PUT** `update_worker_cron_triggers` — Set cron triggers for a Worker (replaces all existing triggers) - **GET** `list_worker_secrets` — List secrets bound to a Worker (names only, values not returned) - **PUT** `put_worker_secret` — Add or update a secret binding for a Worker - **DELETE** `delete_worker_secret` — Remove a secret binding from a Worker - **GET** `list_worker_deployments` — List deployments for a Worker (latest first) - **POST** `create_worker_deployment` — Create a Worker deployment (percentage-based rollout) - **GET** `list_worker_tails` — List active tails (live log streams) for a Worker - **POST** `create_worker_tail` — Start a tail to receive live logs and exceptions from a Worker - **DELETE** `delete_worker_tail` — Delete a Worker tail - **GET** `get_worker_subdomain` — Check workers.dev subdomain status for a Worker - **POST** `set_worker_subdomain` — Enable or disable workers.dev subdomain for a Worker - **GET** `list_kv_namespaces` — List all Workers KV namespaces - **GET** `get_kv_namespace` — Get a KV namespace - **POST** `create_kv_namespace` — Create a KV namespace - **PUT** `rename_kv_namespace` — Rename a KV namespace - **DELETE** `delete_kv_namespace` — Delete a KV namespace and all its keys - **GET** `list_kv_keys` — List keys in a KV namespace - **GET** `kv_read_value` — Read a value from KV by key name - **PUT** `kv_write_value` — Write a key-value pair to KV. Eventually consistent (up to 60s propagation). - **DELETE** `kv_delete_value` — Delete a key from KV - **GET** `kv_get_metadata` — Get metadata for a KV key - **PUT** `kv_bulk_write` — Write multiple key-value pairs to KV in one request - **POST** `kv_bulk_delete` — Delete multiple keys from KV in one request - **POST** `kv_bulk_read` — Read multiple keys from KV in one request (up to 100) - **GET** `list_r2_buckets` — List all R2 buckets - **GET** `get_r2_bucket` — Get R2 bucket properties - **POST** `create_r2_bucket` — Create an R2 bucket - **DELETE** `delete_r2_bucket` — Delete an R2 bucket (must be empty) - **GET** `get_r2_lifecycle` — Get R2 bucket lifecycle rules - **PUT** `set_r2_lifecycle` — Set R2 bucket lifecycle rules - **GET** `get_r2_cors` — Get R2 bucket CORS policy - **PUT** `set_r2_cors` — Set R2 bucket CORS policy - **DELETE** `delete_r2_cors` — Delete R2 bucket CORS policy - **GET** `list_r2_custom_domains` — List custom domains for an R2 bucket - **POST** `add_r2_custom_domain` — Add a custom domain to an R2 bucket - **DELETE** `delete_r2_custom_domain` — Remove a custom domain from an R2 bucket - **GET** `get_r2_managed_domain` — Get r2.dev public domain status - **PUT** `set_r2_managed_domain` — Enable or disable r2.dev public access - **GET** `list_d1_databases` — List all D1 databases - **GET** `get_d1_database` — Get D1 database details - **POST** `create_d1_database` — Create a D1 database - **DELETE** `delete_d1_database` — Delete a D1 database - **POST** `d1_query` — Execute SQL query on D1 (results as objects) - **POST** `d1_raw_query` — Execute SQL query on D1 (results as arrays, more compact) - **POST** `d1_export` — Export D1 database as SQL dump - **POST** `d1_import` — Import SQL into a D1 database - **GET** `d1_time_travel_bookmark` — Get current or historical D1 database bookmark (point-in-time) - **POST** `d1_time_travel_restore` — Restore D1 database to a point in time. Overwrites current state. - **GET** `list_custom_certificates` — List all custom SSL certificates for a zone - **GET** `get_custom_certificate` — Get custom certificate details - **POST** `upload_custom_certificate` — Upload a new custom SSL certificate - **PATCH** `update_custom_certificate` — Update a custom SSL certificate or private key - **DELETE** `delete_custom_certificate` — Remove a custom SSL certificate - **PUT** `prioritize_certificates` — Set priority order for custom certificates - **GET** `list_certificate_packs` — List all certificate packs for a zone - **GET** `get_certificate_pack` — Get a specific certificate pack - **POST** `order_certificate_pack` — Order an advanced certificate pack - **DELETE** `delete_certificate_pack` — Delete a certificate pack - **GET** `list_custom_hostnames` — List all custom hostnames for a zone - **GET** `get_custom_hostname` — Get custom hostname details including SSL status and verification - **POST** `create_custom_hostname` — Create a custom hostname and request SSL certificate - **PATCH** `update_custom_hostname` — Update custom hostname SSL config or trigger DCV - **DELETE** `delete_custom_hostname` — Delete a custom hostname and revoke its SSL certificates - **GET** `get_ssl_recommendation` — Get SSL/TLS mode recommendation for a zone - **GET** `get_ssl_verification` — Get SSL verification info and DCV status - **GET** `get_universal_ssl_settings` — Get Universal SSL settings for a zone - **PATCH** `update_universal_ssl_settings` — Update Universal SSL settings (enable/disable) - **POST** `purge_cache` — Purge cached content. Use purge_everything for full purge, or files/tags/hosts/prefixes for selective. - **GET** `get_cache_reserve` — Get Cache Reserve status - **PATCH** `update_cache_reserve` — Enable or disable Cache Reserve - **GET** `get_tiered_cache` — Get Smart Tiered Cache setting - **PATCH** `update_tiered_cache` — Enable or disable Smart Tiered Cache - **GET** `list_load_balancers` — List all load balancers for a zone - **GET** `get_load_balancer` — Get load balancer details - **POST** `create_load_balancer` — Create a load balancer - **PUT** `update_load_balancer` — Update a load balancer - **DELETE** `delete_load_balancer` — Delete a load balancer - **GET** `list_lb_pools` — List all load balancer pools - **GET** `get_lb_pool` — Get load balancer pool details - **POST** `create_lb_pool` — Create a load balancer pool - **PUT** `update_lb_pool` — Update a load balancer pool - **DELETE** `delete_lb_pool` — Delete a load balancer pool - **GET** `get_lb_pool_health` — Get pool health status - **GET** `list_lb_monitors` — List all load balancer monitors - **GET** `get_lb_monitor` — Get load balancer monitor details - **POST** `create_lb_monitor` — Create a load balancer health monitor - **PUT** `update_lb_monitor` — Update a load balancer monitor - **DELETE** `delete_lb_monitor` — Delete a load balancer monitor - **GET** `list_firewall_rules` — List firewall rules for a zone - **GET** `get_firewall_rule` — Get a specific firewall rule - **POST** `create_firewall_rules` — Create one or more firewall rules - **PUT** `update_firewall_rule` — Update a firewall rule - **DELETE** `delete_firewall_rule` — Delete a firewall rule - **GET** `list_account_rulesets` — List all account-level rulesets - **GET** `list_zone_rulesets` — List all zone-level rulesets - **GET** `get_zone_ruleset` — Get a specific zone ruleset - **POST** `create_zone_ruleset` — Create a zone ruleset - **PUT** `update_zone_ruleset` — Update/deploy a zone ruleset (replaces all rules) - **DELETE** `delete_zone_ruleset` — Delete a zone ruleset - **GET** `get_zone_ruleset_phase` — Get the entry point ruleset for a phase (e.g. http_ratelimit, http_request_firewall_custom) - **PUT** `update_zone_ruleset_phase` — Update the entry point ruleset for a phase - **GET** `list_page_rules` — List all page rules for a zone - **GET** `get_page_rule` — Get a specific page rule - **POST** `create_page_rule` — Create a page rule - **PUT** `update_page_rule` — Replace a page rule entirely - **DELETE** `delete_page_rule` — Delete a page rule - **GET** `list_access_apps` — List all Cloudflare Access applications - **GET** `get_access_app` — Get Access application details - **POST** `create_access_app` — Create an Access application - **PUT** `update_access_app` — Update an Access application - **DELETE** `delete_access_app` — Delete an Access application - **GET** `list_access_policies` — List all reusable Access policies - **GET** `get_access_policy` — Get a reusable Access policy - **POST** `create_access_policy` — Create a reusable Access policy - **PUT** `update_access_policy` — Update a reusable Access policy - **DELETE** `delete_access_policy` — Delete a reusable Access policy - **GET** `list_access_app_policies` — List policies for a specific Access application - **GET** `get_access_app_policy` — Get a specific policy for an Access application - **POST** `create_access_app_policy` — Create a policy for a specific Access application - **PUT** `update_access_app_policy` — Update a policy for an Access application - **DELETE** `delete_access_app_policy` — Delete a policy for an Access application - **GET** `list_access_groups` — List all Access groups - **GET** `get_access_group` — Get Access group details - **POST** `create_access_group` — Create an Access group - **PUT** `update_access_group` — Update an Access group - **DELETE** `delete_access_group` — Delete an Access group - **GET** `get_email_routing_settings` — Get the Email Routing state of a zone: enabled, status (ready | unconfigured | misconfigured | misconfigured/locked | unlocked), support_subaddress (plus-addressing), skip_wizard, created/modified. Call this first -- routing rules only take effect while status is 'ready'. - **PATCH** `update_email_routing_settings` — Update Email Routing zone settings: support_subaddress (honor plus-addressing like user+tag@zone when matching rules) and skip_wizard. Omitted fields keep their value. Cannot switch routing on or off -- use enable_email_routing / disable_email_routing for that. - **GET** `get_email_routing_dns_records` — Show the DNS records Email Routing needs on this zone -- MX route1/2/3.mx.cloudflare.net, an SPF TXT record at the apex and the DKIM TXT record cf2024-1._domainkey -- each as {type, name, content, priority, ttl}. Works for zones where routing is not enabled yet (shows what enable_email_routing would create and lock). - **POST** `enable_email_routing` — Enable Email Routing on a zone: Cloudflare adds AND LOCKS the required MX records and the SPF TXT record at the zone apex. Existing foreign MX records must be removed first, otherwise the zone ends up with status 'misconfigured'. Returns the settings object -- check that status == 'ready'. - **DELETE** `disable_email_routing` — Disable Email Routing on a zone and REMOVE the MX/SPF records it added. Incoming mail to the zone stops being routed immediately; routing rules and destination addresses are kept but become inactive. - **PATCH** `unlock_email_routing_dns` — Unlock the MX records that Email Routing locked so they can be edited with the DNS tools (status becomes 'unlocked'). Editing them can break routing; run enable_email_routing again to restore and re-lock the records. - **GET** `list_email_routing_rules` — List the custom-address routing rules of a zone: id, name, enabled, priority, matchers [{type: literal | all, field: to, value}], actions [{type: forward | drop | worker, value: [target]}], source (api | wrangler). The catch-all rule is included as well (matchers [{type: all}], priority 2147483647) -- manage it via get/update_email_routing_catch_all, not via update_email_routing_rule. - **GET** `get_email_routing_rule` — Get one routing rule by id (matchers, actions, enabled, priority, source). - **POST** `create_email_routing_rule` — Create a routing rule for a custom address of the zone. matchers: [{type: 'literal', field: 'to', value: 'alias@yourzone.tld'}]. actions: [{type: 'forward', value: ['dest@example.net']}] forwards to exactly ONE destination address that is already VERIFIED in the account (create_email_destination_address + link click), [{type: 'drop'}] discards the mail, [{type: 'worker', value: ['script-name']}] hands it to an Email Worker. Lower priority number wins when several rules match. Requires Email Routing to be enabled on the zone. - **PUT** `update_email_routing_rule` — Replace a routing rule (PUT = full replace: matchers AND actions are required again, omitted name/enabled/priority fall back to their defaults). Use it to change the forward target, disable a rule, or re-prioritize. Forward actions need exactly one verified destination address. - **DELETE** `delete_email_routing_rule` — Delete a routing rule. Mail to that custom address is no longer matched and falls through to the catch-all rule (which drops by default). - **GET** `get_email_routing_catch_all` — Get the zone's catch-all rule -- what happens to mail for addresses no custom rule matches: enabled, actions [{type: forward | drop | worker, value}], matchers [{type: all}]. - **PUT** `update_email_routing_catch_all` — Set the zone's catch-all rule: enable or disable it and choose the action -- forward all unmatched mail to one verified destination address ([{type: 'forward', value: ['dest@example.net']}]), drop it ([{type: 'drop'}]), or route it to an Email Worker ([{type: 'worker', value: ['script-name']}]). matchers must be [{type: 'all'}]. PUT = full replace. - **GET** `list_email_destination_addresses` — List the Email Routing destination addresses of the account (the mailboxes forward rules may deliver to): id, email, verified (timestamp, or null while the recipient has not clicked the verification link), created, modified. Without the verified filter ALL addresses are returned (verified and pending); verified=true or verified=false narrows the list. account_id is required; get it via list_accounts. - **GET** `get_email_destination_address` — Get one destination address by id, including its verified timestamp (null = not yet verified). - **POST** `create_email_destination_address` — Register a destination address for forwarding. Cloudflare immediately emails a verification link to that address; until the recipient clicks it, verified stays null and routing rules that forward to it are rejected. Returns the address object (id, email, verified: null). - **PATCH** `update_email_destination_address` — Change a destination address status. With a regular API token this can only reset a verified address to 'unverified' (forcing re-verification); setting 'verified' requires Cloudflare admin privileges and is rejected otherwise. - **DELETE** `delete_email_destination_address` — Delete a destination address. Routing rules that forward to it stop working -- update or delete those rules first. Cloudflare refuses to delete an address that was created only moments ago (HTTP 429 code 2032 'created too recently') -- wait a few minutes and retry. - **GET** `list_email_routing_rules_across_zones` — List the routing rules of ALL zones in the account in one call; each rule carries zone {name, tag} in addition to id, name, enabled, priority, matchers, actions. Use it to audit which custom addresses forward where without iterating zones. Permission caveat: a token whose Email Routing Rules permission is granted per zone gets HTTP 403 (code 10000) here even though the per-zone list_email_routing_rules works -- fall back to iterating zones in that case. - **POST** `send_email` — Send an outbound email through Cloudflare Email Sending. from must be an address on an ENABLED sending subdomain of the account (create_email_sending_subdomain, DNS status 'ready'); recipients can be any external addresses. Every address value is either a plain string 'user@example.com' or {address, name}; to/cc/bcc take arrays of those and at least one of the three is required. Provide subject and at least one of text/html. Returns {message_id, delivered[], queued[], permanent_bounces[], suppressed_recipients[]}. Each send counts against the daily quota (get_email_sending_limits). - **POST** `send_email_raw` — Send a pre-built RFC 5322 MIME message (headers + body, optionally multipart) through Email Sending. from and recipients form the SMTP envelope and must be plain addresses; the message's From header must still use an enabled sending subdomain. Prefer send_email unless you need full control over the MIME structure. Returns {message_id, delivered[], queued[], permanent_bounces[], suppressed_recipients[]}. - **GET** `get_email_sending_limits` — Get the account's Email Sending quota and current usage: {quota: {value, unit: day | hour}, usage: {sent, over_quota, resets_at}}. quota and usage are null while no quota is resolved yet (Email Sending not activated). Check before bulk sends. - **GET** `get_email_sending_reputation` — Get the account's Email Sending reputation: status (healthy | warning | at_risk | suspended), status_since, evaluated_at, grace_started_at, and the active_policy thresholds (complaint, customer_bounce and spam_rejection rates with warning_at/at_risk_at/minimum_denominator, suspension_after_hours). While suspended, sends are rejected. Accounts that have not activated Email Sending get HTTP 404 (code 10001 'Unable to authenticate request') from this endpoint even with the right permission -- check get_email_sending_limits (quota null) first. - **GET** `get_email_sending_message` — Fetch the raw RFC 5322 MIME of a message sent via Email Sending, by the message_id returned from send_email / send_email_raw. The body is message/rfc822 (not JSON), so ToolMesh returns a file-broker download URL. Only available for subdomains with preview_enabled=true (activity-log preview). - **GET** `list_email_sending_suppressions` — List active Email Sending suppressions (addresses that will NOT be delivered to): id, email, reason (manual | complaint | hard_bounce | soft_bounce | policy), scope ({type: 'account'} or {type: 'sending_domain', value}), expires_at (null = permanent), read_only, note. Sending-domain suppressions come first, then account-wide ones. CURSOR pagination unlike the rest of the API: the result is {suppressions: [...], next_cursor}; pass next_cursor as cursor to fetch the next page (page/per_page paging does not apply). - **GET** `get_email_sending_suppression` — Get one Email Sending suppression by id (email, reason, scope, expires_at, read_only, note). - **POST** `create_email_sending_suppression` — Suppress an address so Email Sending never delivers to it -- for every sending domain of the account by default, or for one sending domain via scope {type: 'sending_domain', value: 'mail.example.com'}. Creating an already active suppression returns its existing id. Scope is immutable afterwards (delete and recreate to change it). Returns {id, scope}. - **POST** `bulk_create_email_sending_suppressions` — Import up to 1,000 Email Sending suppressions in one request. items: [{email, expires_at?, note?, scope?}] with the same semantics as create_email_sending_suppression; duplicates (same email + scope) are deduplicated. Returns counts (total, processed, deduplicated, invalid, skipped, errors) and per-item results {index, email, status: processed | invalid | error | skipped, id?, error?} in request order. - **PATCH** `update_email_sending_suppression` — Update the expiry or note of a suppression. Send expires_at as null to make it permanent, note as '' to clear it; omitted fields stay unchanged. Scope cannot be changed (400 scope_immutable) and read_only suppressions (reason policy) cannot be edited. - **DELETE** `delete_email_sending_suppression` — Delete a suppression so the address can receive Email Sending mail again. - **GET** `list_email_sending_subdomains` — List the sending-enabled (sub)domains of a zone: tag (this is the subdomain_id for the other subdomain tools), name, enabled, dkim_selector, return_path_domain, preview_enabled, drop_suppressed_recipients. A zone has none until create_email_sending_subdomain is called. - **GET** `get_email_sending_subdomain` — Get one sending subdomain by id (the tag field of list_email_sending_subdomains). - **POST** `create_email_sending_subdomain` — Enable Email Sending on a domain of the zone, e.g. 'mail.example.com' or the apex 'example.com' ('*.example.com' wildcards need the wildcard entitlement). Cloudflare creates and locks the DKIM, SPF, DMARC and return-path DNS records and returns the subdomain (tag = subdomain_id). Run preview_email_sending_subdomain first to detect conflicts with existing MX/SPF/DMARC records, then confirm readiness with get_email_sending_subdomain_dns_status. Also re-enables a previously deleted subdomain. - **POST** `preview_email_sending_subdomain` — Dry run for create_email_sending_subdomain: returns the DNS records Cloudflare would create for the name plus errors[] with codes such as mx.missing, mx.foreign, spf.multiple, dkim.conflict, dmarc.incompatible, sending_subdomain.conflict (each with the existing/missing/multiple records involved). Nothing is created or modified. - **PATCH** `update_email_sending_subdomain` — Update a sending subdomain (at least one field required): preview_enabled lets sent messages be previewed in the activity log (needed for get_email_sending_message); drop_suppressed_recipients=true makes send_email drop suppressed recipients and deliver to the rest instead of failing the whole request. - **DELETE** `delete_email_sending_subdomain` — Disable sending on the subdomain and remove its sending DNS records (DKIM/SPF/DMARC/return-path). Email Routing on the same name is unaffected. Sends with a from address on this subdomain fail afterwards. - **GET** `get_email_sending_subdomain_dns` — Return the DNS records a sending subdomain is expected to have (desired state as {type, name, content, priority, ttl}) -- no live comparison; use get_email_sending_subdomain_dns_status for that. - **GET** `get_email_sending_subdomain_dns_status` — Live DNS health of a sending subdomain: status (ready | unconfigured | unlocked | misconfigured), the desired records, and errors[] (mx.missing, mx.foreign, spf.missing, spf.foreign, spf.multiple, dkim.missing, dkim.conflict, dmarc.missing, dmarc.multiple, dmarc.incompatible, domainkey.delegated, sending_subdomain.conflict). Call this before fix_email_sending_subdomain_dns. - **POST** `fix_email_sending_subdomain_dns` — Idempotently repair a sending subdomain's DNS: re-creates missing sending records and re-applies the lock on unlocked ones. Refuses with HTTP 409 while foreign MX, multiple SPF, multiple DMARC or multiple DKIM records exist at the relevant names -- clean those up with the DNS tools first. Returns the same shape as get_email_sending_subdomain_dns_status. - **GET** `get_email_sending_subdomain_complaints` — Number of spam complaints matched to a sending subdomain in the half-open window [start_at, end_at), at most seven days long. Returns {complaints}. - **GET** `get_dmarc_reports_status` — Get the zone's DMARC Management state: enabled (Cloudflare collects DMARC aggregate reports through its RUA address), rua_prefix, status (missing-dmarc-report | multiple-dmarc-reports | missing-dmarc-rua | cname-on-dmarc-record | unauthorized-reporting-domain; the field is absent when DMARC is configured correctly), approved_sources (sending sources seen in reports, with resolved IPs) and records -- the zone's live SPF, DKIM, DMARC and BIMI TXT/CNAME records grouped by type. A good first call for any email-deliverability audit of a zone. - **PATCH** `configure_dmarc_reports` — Enable or disable Cloudflare DMARC report collection for the zone (at least one of enabled/skip_wizard required). enabled=true ensures the zone's DMARC TXT record carries Cloudflare's rua= reporting address (creating it if needed) so aggregate reports flow into DMARC Management. Returns the same shape as get_dmarc_reports_status. - **GET** `inspect_spf_record` — Parse one SPF TXT record of the zone into a component tree: every mechanism (A, MX, IP4, IP6, INCLUDE, REDIRECT, EXISTS, PTR, ALL) with its qualifier result, nested includes resolved recursively, lookup_count per component and total_lookups (RFC 7208 allows 10), plus errors[] (lookup_failed, spf_not_found, invalid_spf, invalid_domain, loop_detected, invalid_mechanism, ...). id is the DNS record id of the SPF TXT record -- find it with list_dns_records(type='TXT'). ## Which DADLs are related to Cloudflare? - [Linode](https://www.dadl.ai/d/linode/) — Linode (Akamai) cloud infrastructure API -- compute instances, volumes, DNS, networking, Kubernetes, databases, object storage, and account management - [Tailscale](https://www.dadl.ai/d/tailscale/) — Tailscale API -- devices, users, auth keys, DNS, ACL/policy, webhooks, contacts, posture integrations, log streaming, and tailnet settings - [DokuWiki](https://www.dadl.ai/d/dokuwiki/) — DokuWiki JSON-RPC API — wiki pages, media files, search, ACL management, and user administration - [ELITEDOMAINS](https://www.dadl.ai/d/elitedomains/) — ELITEDOMAINS domain registrar API -- register/transfer/manage .de and gTLD domains, redirector & inline DNS, AuthInfo/AuthInfo2 transfer codes, RGP catcher backorders, contact handles, and marketplace offers (Sedo, sale pages) - [GitLab](https://www.dadl.ai/d/gitlab/) — GitLab REST API v4 — projects, issues, merge requests, pipelines, CI/CD, and code search - [Hetzner Cloud](https://www.dadl.ai/d/hetzner-cloud/) — Hetzner Cloud API -- servers, volumes, networks, load balancers, firewalls, floating IPs, primary IPs, images, SSH keys, placement groups, certificates, and infrastructure metadata --- **Canonical URL:** https://www.dadl.ai/d/cloudflare/ **Raw DADL:** https://github.com/DunkelCloud/dadl-registry/blob/main/cloudflare.dadl --- # DeepL MCP Server — 27 tools via DADL The DeepL DADL turns DeepL's API into an MCP server that Claude, GPT or any MCP-compatible agent can consume directly. One YAML file declares all 27 tools — glossary, style, document, text, custom, translation, and more — and ToolMesh serves them at runtime. No Python boilerplate, no per-endpoint code, no separate MCP server process. Below: the endpoint coverage matrix, a two-block ToolMesh setup, the full tool reference grouped by DeepL feature area. **Source:** [DeepL REST API (v2 + v3)](https://developers.deepl.com/api-reference) **Updated:** 2026-05-21 **Tags:** translation, crud, file-management, metrics, auth:bearer ## Which DeepL endpoints are covered? **71%** (27 of ~38 endpoints). **Focus:** text translation (with style_id / translation_memory_id / custom_instructions / tag_handling v2), document translation, multilingual v3 glossaries, style rules (CRUD + custom instructions + configured rules), translation memory listing, text improvement (Write/rephrase), v3 languages and usage **Missing:** admin API (org analytics, developer key management), voice translation (WebSocket, not REST), language detection beta endpoint, translation memory mutation (TM create/edit are web-UI only as of 2026-05) *Last reviewed: 2026-05-21* ## How do you configure the DeepL DADL? 1. Sign up for a DeepL API plan at https://www.deepl.com/pro-api 2. Choose API Free (500k chars/month) or API Pro (pay-per-use, unlocks style rules + TM + multilingual glossaries) 3. Open Account → API Keys 4. Create a new Authentication Key and copy it 5. Free keys end with ':fx' and require api-free.deepl.com — Pro keys use api.deepl.com 6. Store the key in your credential store under the name 'deepl_auth_key' **Environment variable:** `CREDENTIAL_DEEPL_AUTH_KEY` [Authentication docs](https://developers.deepl.com/docs/getting-started/auth) *The legacy auth_key query parameter was deprecated in Nov 2025 — all auth must use the Authorization header with "DeepL-Auth-Key" scheme. Style rules, translation memory and multilingual glossaries are Pro-only. Rate limits are not publicly documented; 429 and 529 include Retry-After. Free plan returns 456 (not 429) when the monthly character quota is exhausted. * ## How do you install the DeepL MCP server with ToolMesh? Add to your `backends.yaml`: ```yaml - name: deepl transport: rest dadl: deepl.dadl url: "https://api.deepl.com" # Free plan: https://api-free.deepl.com ``` Set the credential: ``` CREDENTIAL_DEEPL_AUTH_KEY=your-token-here ``` ## What 27 tools does the DeepL DADL expose? - **POST** `translate` — Translate text into a target language. Up to 50 texts per request, max 128 KiB body. Auto-detects source language when source_lang is omitted. Setting style_id, custom_instructions or translation_memory_id implicitly switches model_type to quality_optimized. - **POST** `upload_document` — Upload a document for translation. Returns {document_id, document_key} for status polling and download. Supports docx, doc, pptx, xlsx, pdf, htm, html, txt, xlf, xliff, srt, jpeg, jpg, png. - **POST** `check_document_status` — Check translation status of an uploaded document. status is one of queued, translating, done, error. Poll with exponential backoff — seconds_remaining can be wildly off (sometimes 2^27). - **POST** `download_document` — Download the translated document. Only valid when status is 'done'. The document is auto-deleted on first successful download — store it before retrying. - **GET** `list_glossaries` — List all multilingual glossaries on the account. Returns array under 'glossaries'. - **POST** `create_glossary` — Create a multilingual glossary. The dictionaries array carries one entry per source→target language pair. Use lowercase 2-letter codes (en, de, fr). entries_format must be 'tsv' or 'csv'; entries is a single string with one pair per line (source TAB target for TSV, source COMMA target for CSV). - **GET** `get_glossary` — Retrieve metadata of a single glossary (name, dictionary inventory, creation time) - **PATCH** `update_glossary` — Update the glossary name and/or merge new dictionary entries. Existing entries for the same source→target pair are merged (new pairs added, conflicting pairs overwritten). - **DELETE** `delete_glossary` — Permanently delete a glossary and all its dictionaries. Cannot be undone. - **GET** `get_glossary_entries` — Retrieve all term pairs of a single dictionary inside the glossary, identified by the (source_lang, target_lang) query pair. Returns TSV. - **PUT** `replace_glossary_dictionary` — Replace (or create) the dictionary for a single source→target language pair in an existing glossary. Existing entries for that pair are overwritten. - **DELETE** `delete_glossary_dictionary` — Delete a single dictionary (one language pair) from a multilingual glossary - **GET** `list_style_rules` — List style rule lists on the account. Set detailed=true to include the full configured_rules and custom_instructions per list. Paginated. - **POST** `create_style_rule` — Create a style rule list for a single language. configured_rules covers 7 categories (dates_and_times, formatting, numbers, punctuation, spelling_and_grammar, style_and_tone, vocabulary) — each with predefined enum options. custom_instructions adds free-form prompts (max 200, 300 chars each). - **GET** `get_style_rule` — Retrieve a single style rule list with its configured_rules and custom_instructions - **PATCH** `update_style_rule` — Rename a style rule list (other fields are immutable — use the dedicated sub-endpoints to mutate rules/instructions) - **DELETE** `delete_style_rule` — Permanently delete a style rule list and all its custom instructions. Cannot be undone. - **PUT** `replace_configured_rules` — Replace the entire configured_rules object on a style rule list. Send the full object — fields omitted are reset to default. - **POST** `add_custom_instruction` — Add a custom instruction to an existing style rule list. Up to 200 per style rule. - **GET** `get_custom_instruction` — Retrieve a single custom instruction - **PUT** `update_custom_instruction` — Replace a custom instruction (label/prompt/source_language). All fields are sent — omitted fields reset. - **DELETE** `delete_custom_instruction` — Permanently remove a custom instruction from a style rule list - **GET** `list_translation_memories` — List translation memories on the account. Each entry carries {translation_memory_id, name, source_language, target_languages, segment_count}. Paginated, max page_size 25. - **POST** `rephrase_text` — Improve and rephrase text without changing the language (max 10 KiB body). Supports writing styles and tones. Does NOT translate — target_lang must match the source language (one of: de, en-GB, en-US, es, fr, it, ja, ko, pt-BR, pt-PT, zh). writing_style and tone are mutually exclusive in a single call. - **GET** `list_languages` — List languages supported for a given resource. Returns formality, glossary and other feature flags relevant to that resource. Resource is required. - **GET** `list_language_resources` — List the supported 'resource' values usable with list_languages (translate_text, glossary, ...) - **GET** `get_usage` — Retrieve character usage and quota for the current billing period. Returns character_count (consumed) and character_limit (cap). Pro plans return very large limits; Free is exactly 500000. ## Which DADLs are related to DeepL? - [Hetzner Cloud](https://www.dadl.ai/d/hetzner-cloud/) — Hetzner Cloud API -- servers, volumes, networks, load balancers, firewalls, floating IPs, primary IPs, images, SSH keys, placement groups, certificates, and infrastructure metadata - [Soniox](https://www.dadl.ai/d/soniox/) — Soniox Speech AI — async speech-to-text for recorded audio (60+ languages, speaker diarization, language identification, speech translation), text-to-speech synthesis with voice cloning, audio file management, model discovery, temporary API keys for untrusted clients, and per-request usage, cost and concurrency reporting. - [Billomat](https://www.dadl.ai/d/billomat/) — Billomat REST API — German cloud invoicing & accounting: invoices, estimates, credit notes, recurring invoices, delivery notes, order confirmations, dunning reminders, clients, contacts, articles, payments, expenses, taxes - [BookStack](https://www.dadl.ai/d/bookstack/) — BookStack wiki and documentation platform REST API -- shelves, books, chapters, pages (HTML/Markdown content), attachments, image gallery, comments, cross-entity search, exports (HTML/Markdown/PDF/ZIP), ZIP imports, users, roles, content permissions, recycle bin, audit log and tags. Hierarchy: shelves > books > chapters > pages. - [DokuWiki](https://www.dadl.ai/d/dokuwiki/) — DokuWiki JSON-RPC API — wiki pages, media files, search, ACL management, and user administration - [GitLab](https://www.dadl.ai/d/gitlab/) — GitLab REST API v4 — projects, issues, merge requests, pipelines, CI/CD, and code search --- **Canonical URL:** https://www.dadl.ai/d/deepl/ **Raw DADL:** https://github.com/DunkelCloud/dadl-registry/blob/main/deepl.dadl --- # DokuWiki MCP Server — 30 tools via DADL The DokuWiki DADL turns DokuWiki's API into an MCP server that Claude, GPT or any MCP-compatible agent can consume directly. One YAML file declares all 30 tools — page, media, acl, wiki, user, recent, and more — and ToolMesh serves them at runtime. No Python boilerplate, no per-endpoint code, no separate MCP server process. Below: the endpoint coverage matrix, a two-block ToolMesh setup, the full tool reference grouped by DokuWiki feature area, required credential scopes. **Source:** [DokuWiki Remote API](https://www.dokuwiki.org/devel:jsonrpc) **Updated:** 2026-03-29 **Tags:** wiki, crud, search, file-management, user-management, authentication, auth:basic ## Which DokuWiki endpoints are covered? **94%** (31 of ~33 endpoints). **Focus:** pages, media, search, ACL, user management, wiki metadata **Missing:** plugin-specific methods beyond acl and usermanager *Last reviewed: 2026-03-29* ## How do you configure the DokuWiki DADL? 1. Ensure the Remote API is enabled in DokuWiki: Admin → Configuration → Authentication → enable 'remote' option 2. Optionally restrict remote access: set 'remoteuser' to limit which users/groups can use the API 3. Use an existing DokuWiki user account with appropriate permissions 4. The API uses HTTP Basic Authentication with your DokuWiki username and password **Environment variable:** `CREDENTIAL_DOKUWIKI_USERNAME and CREDENTIAL_DOKUWIKI_PASSWORD` [Authentication docs](https://www.dokuwiki.org/devel:jsonrpc) *DokuWiki is self-hosted. Replace the URL with your instance address. The JSON-RPC endpoint is at /lib/exe/jsonrpc.php. All API methods use POST. Page IDs use colon-separated namespaces (e.g. 'wiki:syntax', 'namespace:page'). * ## How do you install the DokuWiki MCP server with ToolMesh? Add to your `backends.yaml`: ```yaml - name: dokuwiki transport: rest dadl: /app/dadl/dokuwiki.dadl url: "https://your-wiki.example.com/lib/exe/jsonrpc.php" credentials: dokuwiki_username: "${CREDENTIAL_DOKUWIKI_USERNAME}" dokuwiki_password: "${CREDENTIAL_DOKUWIKI_PASSWORD}" ``` Set the credential: ``` CREDENTIAL_DOKUWIKI_USERNAME and CREDENTIAL_DOKUWIKI_PASSWORD=your-token-here ``` ## What 30 tools does the DokuWiki DADL expose? - **POST** `get_api_version` — Get the DokuWiki JSON-RPC API version number - **POST** `get_wiki_version` — Get the DokuWiki software version string - **POST** `get_wiki_title` — Get the wiki title - **POST** `get_wiki_time` — Get the current server Unix timestamp - **POST** `who_am_i` — Get details about the currently authenticated user (login, name, email, groups, admin/manager status) - **POST** `acl_check` — Check ACL permissions for a page or media file. Returns permission level (0=none, 1=read, 2=edit, 4=create, 8=upload, 16=delete, 255=admin) - **POST** `list_pages` — List all pages in a namespace. Returns page ID, revision, modification time, and size for each page. - **POST** `search_pages` — Full-text search across all wiki pages. Returns matching pages with snippets. - **POST** `get_recent_page_changes` — Get recently changed pages. Returns page ID, revision timestamp, author, and summary for each change. - **POST** `get_page` — Get the raw wiki syntax content of a page. Use getPageHTML for rendered HTML instead. - **POST** `get_page_html` — Get the rendered HTML of a page - **POST** `get_page_info` — Get metadata about a page (last modified, author, locked status) - **POST** `get_page_history` — Get the revision history of a page. Returns list of revisions with timestamp, author, summary, and size. - **POST** `get_page_links` — Get all links contained in a page (internal and external) - **POST** `get_page_backlinks` — Get all pages that link to the specified page - **POST** `save_page` — Create or update a page. Replaces the entire page content with the provided text. - **POST** `append_page` — Append text to an existing page without replacing existing content - **POST** `lock_pages` — Lock pages to prevent concurrent editing - **POST** `unlock_pages` — Unlock previously locked pages - **POST** `list_media` — List media files in a namespace. Returns file ID, size, modification time, and permissions. - **POST** `get_recent_media_changes` — Get recently changed media files - **POST** `get_media` — Download a media file as base64-encoded content - **POST** `get_media_info` — Get metadata about a media file (size, modification time, permissions) - **POST** `save_media` — Upload a media file (base64-encoded) - **POST** `delete_media` — Permanently delete a media file - **POST** `list_acls` — List all ACL rules. Requires admin permissions. - **POST** `add_acl` — Add an ACL rule. Permission levels: 0=none, 1=read, 2=edit, 4=create, 8=upload, 16=delete, 255=admin - **POST** `delete_acl` — Remove an ACL rule - **POST** `create_user` — Create a new DokuWiki user account. Requires admin permissions. - **POST** `delete_user` — Permanently delete user accounts. Requires admin permissions. ## What composite workflows does the DokuWiki DADL provide? - **FN** `page_search_and_replace` — Replace all occurrences of a literal substring in a wiki page and save it. Internally: get_page → string replace → save_page. The full page content never leaves the ToolMesh server; only { success, replacements } is returned. The search is a literal match (no regex). - **FN** `page_append_section` — Insert content at the end of an existing section, before the next heading of equal or higher level. Useful for adding material between e.g. section 6.2 and 7 — which append_page cannot do because it only appends to EOF. Internally: get_page → parse headings → splice → save_page. The full page content never leaves the ToolMesh server. - **FN** `chunked_save_page` — Stateful chunked save: buffers text chunks server-side in a hidden draft page and writes the assembled content to the target page in a single revision when finalized. Workflow: 1. First chunk: chunk_index=0 (resets the buffer for this session_id). 2. Middle chunks: chunk_index=1..N-2 (each appended to the buffer). 3. Final chunk: chunk_index=N-1, finalize=true — assembles buffer, writes target page in ONE revision, deletes draft. Use this when the per-call payload of execute_code is too small to fit the full page text in a single save_page call (e.g. when the calling transport limits the size of tool-call arguments). Each call carries only one chunk so the per-call payload stays small, while the target page receives one clean revision. All intermediate buffer operations (draft create, chunk appends, draft delete) are flagged as DokuWiki minor edits, so they are hidden from the default Recent Changes view. Only the final write to the target page surfaces — the noise stays out of the wiki's change history. Caveats: - session_id must be unique per upload — collisions corrupt the buffer. - Abandoned sessions leave a draft at _chunked_uploads:<session_id>; re-using the same session_id with chunk_index=0 cleans it up. - Chunks must arrive in order; the composite does not reorder them. ## Which DADLs are related to DokuWiki? - [BookStack](https://www.dadl.ai/d/bookstack/) — BookStack wiki and documentation platform REST API -- shelves, books, chapters, pages (HTML/Markdown content), attachments, image gallery, comments, cross-entity search, exports (HTML/Markdown/PDF/ZIP), ZIP imports, users, roles, content permissions, recycle bin, audit log and tags. Hierarchy: shelves > books > chapters > pages. - [GitLab](https://www.dadl.ai/d/gitlab/) — GitLab REST API v4 — projects, issues, merge requests, pipelines, CI/CD, and code search - [Mikrotik](https://www.dadl.ai/d/mikrotik/) — MikroTik RouterOS REST API -- manage interfaces, IP addresses, routing, firewall, DHCP, DNS, PPP, queues, wireless, system configuration, users, certificates, files, logs, and diagnostics on RouterOS v7.1+ devices - [Vikunja](https://www.dadl.ai/d/vikunja/) — Vikunja open-source task management — project planning, kanban boards, and task tracking - [Algolia HN Search](https://www.dadl.ai/d/algolia-hn-search/) — Algolia Hacker News Search API — full-text search, filtering, and retrieval for stories, comments, and users on Hacker News - [Billomat](https://www.dadl.ai/d/billomat/) — Billomat REST API — German cloud invoicing & accounting: invoices, estimates, credit notes, recurring invoices, delivery notes, order confirmations, dunning reminders, clients, contacts, articles, payments, expenses, taxes --- **Canonical URL:** https://www.dadl.ai/d/dokuwiki/ **Raw DADL:** https://github.com/DunkelCloud/dadl-registry/blob/main/dokuwiki.dadl --- # ELITEDOMAINS MCP Server — 20 tools via DADL The ELITEDOMAINS DADL turns ELITEDOMAINS's API into an MCP server that Claude, GPT or any MCP-compatible agent can consume directly. One YAML file declares all 20 tools — domain, catcher, handle, offer, address, authinfo, and more — and ToolMesh serves them at runtime. No Python boilerplate, no per-endpoint code, no separate MCP server process. Below: the endpoint coverage matrix, a two-block ToolMesh setup, the full tool reference grouped by ELITEDOMAINS feature area. **Source:** [ELITEDOMAINS API](https://app.elitedomains.de/docs) **Updated:** 2026-07-05 **Tags:** dns, crud, e-commerce, automation, user-management, security, auth:bearer ## Which ELITEDOMAINS endpoints are covered? **100%** (20 of ~20 endpoints). **Focus:** Beta — REST API not yet stable. ELITEDOMAINS .de domain reseller: domains (register, transfer, AuthInfo, redirector, DNS records, tags), handles (PERSON, ORG, address validation), catcher (RGP backorders, dropdate, max bid), offers (Sedo marketplace, sale pages, visitor stats). **Missing:** no standalone DNS-record CRUD (records are managed inline via redirector_settings), no transfer-status polling endpoint, no billing/invoice endpoint (though list_tld_prices covers TLD pricing), no get_domain and no single-handle GET (both list-only) -- and list_domains omits handle_id, so a domain's assigned owner handle cannot be read back; handles cannot be deleted *Last reviewed: 2026-07-05* ## How do you configure the ELITEDOMAINS DADL? 1. Ask ELITEDOMAINS support to enable API access for your account (the API is opt-in and off by default). 2. Log in to the dashboard at https://app.elitedomains.de 3. Open account settings and go to the API / Personal Access Tokens section. 4. Create a new personal access token and copy it immediately (it is shown only once). 5. Store it in the ToolMesh credential store under the name 'elitedomains_token'. **Environment variable:** `CREDENTIAL_ELITEDOMAINS_TOKEN` [Authentication docs](https://app.elitedomains.de/docs) *Personal access tokens are account-scoped (no granular scopes). Append ?sandbox=1 to any request to test without registry writes. Standard rate limit is 100 req/min and 1000 req/day; during droptime (02:00-04:00 UTC) it drops to 10 req/min and catcher add/remove is rejected with HTTP 405. Ordering an AuthInfo2 letter requires an account on monthly invoicing (Sammelrechnung).* ## How do you install the ELITEDOMAINS MCP server with ToolMesh? Add to your `backends.yaml`: ```yaml - name: elitedomains transport: rest dadl: elitedomains.dadl url: "https://api.elitedomains.de" ``` Set the credential: ``` CREDENTIAL_ELITEDOMAINS_TOKEN=your-token-here ``` ## What 20 tools does the ELITEDOMAINS DADL expose? - **GET** `list_domains` — List all domains in the account (paginated). Each row includes `name`, `redirector_settings`, `authinfo`, `auto_expire`, `paid_until`, `expires_at`, `tags` and `created_at`. Domains are keyed by `name` -- use it for every other domain operation. - **GET** `check_domain` — Check a single domain's availability AND its pricing / transfer terms -- the response is far richer than a yes/no. Core fields: `name`, `message` (a.k.a. status) "free" (registrable) or "connect" (registered, transfer-only) -- but also other registry statuses like "transfer_lock", "redemptionPeriod" or "transit" -- plus `tld`. For a registrable/transferable name it additionally returns `action` (e.g. "transfer"), `authinfo_required` (whether an AuthInfo/transfer code is needed), `billing` (e.g. "instant"), `instant_payment_method_available`, `default_period` (months), a `periods` array of { months, price, price_gross } term/price options, the headline `price` / `price_gross` (net/gross EUR) and `tax_rate`. Use it for transfer feasibility and a single domain's price quote; for the full per-TLD price table use list_tld_prices, and for a focused order preview use check_domain_order. - **GET** `check_domain_order` — Preview what ordering a domain via register_domain would do, BEFORE placing it: returns `name`, `status`, `action` ("register" or "transfer"), the available `periods` [{ months, price, price_gross }], the headline `price`/`price_gross` (net / incl. VAT at your `tax_rate`) and `billing` ("instant" = charged to your stored payment method, or "monthly_invoice"), plus `instant_payment_method_available`. For transfers the price is independent of the period (and some TLDs allow no period on transfer -> `periods` empty). check_domain already folds in these same preview fields; this is the focused variant. - **GET** `list_tld_prices` — List the per-year, net (excl. VAT) prices for all registrable TLDs. Each row: `tld`, a `price` object with `reg`/`transfer`/`renew`/`restore` (the price CURRENTLY valid for your account -- may be lower than list due to a promotion or an individually negotiated rate), an `original_price` object with the standard list price, and a `custom` object flagging per-action whether an individual price is configured. A price is null when that action is not offered for the TLD. This IS the account price-list endpoint; for a single domain's quote use check_domain / check_domain_order. - **POST** `register_domain` — Register a new domain OR transfer an existing one into the account. For a TRANSFER, supply `authinfo` (the transfer code from the losing registrar); for a fresh REGISTRATION omit it. `period` is the term in MONTHS (default 12). Optionally set the owner contact via `handle_id` and initial hosting via `redirector_settings` (the redirector can be configured on the transfer request itself). A successful inbound transfer responds { message: "Domain transfer initiated", name, payment: "captured", period } -- but the transfer is NOT yet complete: a gTLD transfer stays pending until the losing registrar ACKs (or ~5 days auto-ACK). While pending, the domain already shows in list_domains with `redirector_settings` set but `expires_at`/`paid_until` still null; poll list_domains and treat a non-null `expires_at` as "transfer done" (there is no transfer-status endpoint). Errors: 400 invalid input, 403 registry rejection, 409 already registered/owned. - **PATCH** `update_domain` — Update an existing domain's settings: change its hosting/redirect via `redirector_settings` and/or reassign the owner contact via `handle_id`. Identify the domain by `name`. Errors: 400 validation, 404 not found. - **DELETE** `delete_domain` — Delete (give up) a domain, or put it into TRANSIT for an outbound transfer. With `transit`=1 the domain is moved to the transit/KK-out state instead of being deleted. A plain delete returns the domain to the registry and is irreversible. Errors: 400 missing name, 403 registry error, 404 not found. - **POST** `add_domain_tags` — Set/replace the internal organizational tags on a domain. Returns the updated `tags` array and a confirmation `message`. Errors: 400 invalid domain, 404 not found. - **GET** `get_domain_authinfo` — Get or generate the outbound AuthInfo (KK / transfer) code for a domain you own -- needed to transfer it to another registrar. Returns { message, name, authinfo, expires_at }. The code is time-limited; note `expires_at` here is German format "DD.MM.YYYY HH:mm:ss" (unlike the ISO 8601 timestamps elsewhere). Errors: 400 missing name, 403 registry error, 404 not found. - **GET** `check_domain_authinfo2` — Check whether a DENIC AuthInfo2 letter can be ordered for a .de domain. Returns { name, available, message }. AuthInfo2 is the paper-letter fallback used when an AuthInfo1 code is not obtainable. Only relevant for monthly-invoice (Sammelrechnung) accounts. Call this before order_domain_authinfo2. - **POST** `order_domain_authinfo2` — Order a DENIC AuthInfo2 letter for a .de domain (added to the next collective invoice; confirmation arrives by email). Requires an account on monthly invoicing. Errors: 400 not orderable, 403 account restriction. - **POST** `add_domain_to_sedo` — List a domain for sale on the external Sedo marketplace at a fixed price. `price` is a EUR amount greater than 0. Errors: 400 invalid input, 404 domain not found, 500 processing error. - **GET** `list_catcher_orders` — List all RGP catcher (backorder) orders (paginated). Each row includes `name`, `status`, `users` (number of competing backorderers), `price` (your max bid), `dropdate_at` (expected drop) and `created_at`. - **GET** `get_catcher_info` — Get RGP catcher status for ANY dropping domain (it need not be in your own catcher orders): returns `name`, `status` (e.g. "rgp"), `users` (how many parties are backordering it) and `dropdate_at` (expected drop, format "YYYY-MM-DD HH:mm:ss"). Use it to gauge competition and timing before placing an add_catcher_order. Errors: 400 missing name. - **POST** `add_catcher_order` — Place an RGP catcher (backorder) on a dropping domain. `price` is your MAXIMUM bid in EUR (minimum 2). Requires a valid contact handle on the account. Errors: 400 missing/ invalid domain or missing handle, 405 droptime restriction (02:00-04:00 UTC), 409 already added. - **DELETE** `delete_catcher_order` — Cancel a catcher (backorder) order for a domain. This only removes your backorder; it is reversible by re-adding. Errors: 400 missing name, 404 not found, 405 droptime restriction (02:00-04:00 UTC). - **GET** `list_offers` — List the account's domain offers / sale pages (paginated, richly filterable). Each row includes `name`, `type` (paynow|4sale), `status`, `price`, `template`, `is_internal`, `redirect_status`, `hide_on_marketplace`, `visitors` (last_30_days/last_7_days/referrer_30_days), `template_data` and `tags`. Use the filters to narrow by type, status, price band, traffic and template, and sort with order_by/order_direction. This endpoint returns `total` and `last_page` for paging. - **GET** `list_handles` — List all contact handles in the account (paginated). Each row includes `id`, `alias`, `type` (PERSON|ORG), `handle_name`, address fields (`street_name`, `street_number`, `postalcode`, `city`, `country_id`), `email`, `phone` and `created_at`. Use a handle's `id` as `handle_id` when registering/updating a domain. The country field is `country_id` (ISO 3166-1 numeric string, e.g. "276" for Germany) for both read and write. - **POST** `create_handle` — Create a new contact handle (domain owner/admin contact). `type` is PERSON or ORG. For an ORG handle put the company name in `handle_name` and the responsible individual in `contact_person` (Ansprechpartner) -- `contact_person` is REQUIRED for type=ORG (at least for non-.de domains) and is exactly what a bare company name lacks; PERSON handles omit it. Set `address_suggest` to "keep" to bypass address auto-correction. Returns the full handle object including the assigned `id`. NOTE: there is no delete_handle -- handles cannot be removed via the API, so avoid throwaway/test handles. Errors: 400 validation (see `error.<field>` for the offending fields), 500 unknown error. - **PATCH** `update_handle` — Update an existing contact handle by numeric id. Any subset of the writable fields may be supplied. (`type` cannot be changed after creation.) For ORG handles the same `contact_person` (Ansprechpartner) rule as create_handle applies. Returns the updated handle object. Errors: 400 validation (see `error.<field>`), 404 handle not found. ## Which DADLs are related to ELITEDOMAINS? - [Billomat](https://www.dadl.ai/d/billomat/) — Billomat REST API — German cloud invoicing & accounting: invoices, estimates, credit notes, recurring invoices, delivery notes, order confirmations, dunning reminders, clients, contacts, articles, payments, expenses, taxes - [Opnsense](https://www.dadl.ai/d/opnsense/) — OPNsense firewall REST API — manage firewall rules, aliases, interfaces, VPN, DHCP, DNS, diagnostics, firmware, and services on OPNsense appliances - [Zammad](https://www.dadl.ai/d/zammad/) — Zammad helpdesk REST API -- tickets, articles, users, organizations, groups, roles, knowledge base, SLAs, calendars, object manager (custom fields), macros, triggers, overviews, reports, time accounting, and full admin surface. Supports X-On-Behalf-Of impersonation on every endpoint. - [Cloudflare](https://www.dadl.ai/d/cloudflare/) — Cloudflare API -- DNS, Pages, Workers, KV, R2, D1, Zones, SSL/TLS, Cache, Load Balancers, Firewall/WAF, Page Rules, Access (Zero Trust), Email Routing, Email Sending, DMARC/SPF email auth, and account management - [Graylog](https://www.dadl.ai/d/graylog/) — Graylog REST API -- log search (Views/Search + legacy universal), streams, pipelines, inputs, alerts, events, dashboards, users, roles, sidecars, index management, and cluster administration. Targets Graylog 6.x. - [Soniox](https://www.dadl.ai/d/soniox/) — Soniox Speech AI — async speech-to-text for recorded audio (60+ languages, speaker diarization, language identification, speech translation), text-to-speech synthesis with voice cloning, audio file management, model discovery, temporary API keys for untrusted clients, and per-request usage, cost and concurrency reporting. --- **Canonical URL:** https://www.dadl.ai/d/elitedomains/ **Raw DADL:** https://github.com/DunkelCloud/dadl-registry/blob/main/elitedomains.dadl --- # GitHub MCP Server — 259 tools via DADL The GitHub DADL turns GitHub's API into an MCP server that Claude, GPT or any MCP-compatible agent can consume directly. One YAML file declares all 259 tools — repo, org, issue, pull, team, workflow, and more — and ToolMesh serves them at runtime. No Python boilerplate, no per-endpoint code, no separate MCP server process. Below: the endpoint coverage matrix, a two-block ToolMesh setup, the full tool reference grouped by GitHub feature area, required credential scopes. **Source:** [GitHub REST API v3](https://docs.github.com/en/rest) **Updated:** 2026-04-02 **Tags:** version-control, ci-cd, issue-tracking, automation, crud, webhooks, auth:bearer ## Which GitHub endpoints are covered? **25%** (259 of ~1000 endpoints). **Focus:** repos (full CRUD + fork + collaborators + topics), orgs (members + teams), issues (full CRUD + comments + events + reactions + types), sub-issues (hierarchy + reprioritize), issue dependencies (blocked_by + blocking), PRs (full CRUD + merge + reviews + review comments + requested reviewers), commits, branches (+ protection), rulesets (repo + org full CRUD + branch rules + rule suites), custom properties (org schema + repo/org values), git refs + objects (blobs, trees, commits), file management, labels, milestones, search (code + issues + repos + users + commits), releases (full CRUD), actions (workflows + runs + jobs + logs + secrets + artifacts + dispatch + permissions + fork PR approval policy), users, tags, webhooks, deployments (+ statuses), environments, gists (full CRUD), notifications, check runs/suites, commit statuses, starring, watching, pages, traffic (views + clones + paths + referrers), statistics (contributors + commit activity + code frequency + participation + punch card), code scanning, dependabot, secret scanning, packages (org + user: list, get, delete, restore, versions) **Missing:** projects v2, codespaces, copilot, security advisories, rate limit API, git LFS, autolinks *Last reviewed: 2026-08-05* ## How do you configure the GitHub DADL? 1. Navigate to GitHub → Settings → Developer settings → Personal access tokens → Tokens (classic) 2. Click 'Generate new token (classic)' 3. Select scopes: repo (full access), read:org (list organizations), admin:org (org rulesets, custom properties, issue types), workflow (actions), admin:repo_hook (webhooks), delete_repo (delete repos), gist, notifications, read:packages, write:packages, delete:packages 4. Copy the token (starts with ghp_ or github_pat_) **Environment variable:** `CREDENTIAL_GITHUB_TOKEN` [Authentication docs](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens) ## How do you install the GitHub MCP server with ToolMesh? Add to your `backends.yaml`: ```yaml - name: github transport: rest dadl: github.dadl url: "https://api.github.com" ``` Set the credential: ``` CREDENTIAL_GITHUB_TOKEN=your-token-here ``` ## What 259 tools does the GitHub DADL expose? - **POST** `create_repo` — Create a new repository for the authenticated user. Set private=true for a private repo. auto_init=true creates an initial commit with a README. - **POST** `create_org_repo` — Create a new repository in an organization. Requires org admin or repo creation permissions. - **POST** `create_repo_from_template` — Create a new repository from a template. The template must have is_template=true. - **GET** `list_user_repos` — List repositories for the authenticated user. Use type to filter (owner, member, all). - **GET** `list_user_repos_by_username` — List public repositories for a specific user. - **GET** `get_repo` — Get a single repository by owner and name. - **PATCH** `update_repo` — Update repository settings. Only include fields you want to change. Use for description, homepage, visibility, merge settings, etc. - **DELETE** `delete_repo` — Delete a repository. Requires delete_repo scope. This action is irreversible. - **PUT** `replace_topics` — Replace all repository topics. Provide the full list of desired topics. - **GET** `list_repo_languages` — List languages for a repository. Returns a map of language name to bytes of code. - **GET** `list_repo_contributors` — List contributors to a repository, sorted by number of commits. - **GET** `get_readme` — Get the README file for a repository. Content is base64 encoded. - **GET** `list_forks` — List forks of a repository. - **POST** `create_fork` — Fork a repository. Optionally specify an organization to fork into. Forking is asynchronous — poll get_repo to check when complete. - **GET** `list_collaborators` — List collaborators for a repository. Affiliation: outside, direct, all. - **GET** `check_collaborator` — Check if a user is a collaborator. Returns 204 if yes, 404 if no. - **PUT** `add_collaborator` — Add a collaborator to a repository. Permission: pull, triage, push, maintain, admin. - **DELETE** `remove_collaborator` — Remove a collaborator from a repository. - **GET** `list_orgs` — List organizations the authenticated user belongs to. - **GET** `get_org` — Get an organization by name, including member count, repo count, and billing info. - **GET** `list_org_repos` — List repositories for an organization. Use list_orgs first to find org names. - **GET** `list_org_members` — List members of an organization. Filter by role: all, admin, member. - **GET** `list_org_teams` — List teams in an organization. - **GET** `get_team` — Get a team by its slug (URL-friendly name). - **POST** `create_team` — Create a team in an organization. Privacy: secret (visible to org members) or closed (visible to org members, searchable). - **PATCH** `update_team` — Update a team. Only include fields you want to change. - **DELETE** `delete_team` — Delete a team from an organization. - **GET** `list_team_members` — List members of a team. Role filter: all, member, maintainer. - **PUT** `add_team_member` — Add or update a team member. Role: member or maintainer. - **DELETE** `remove_team_member` — Remove a member from a team. - **GET** `list_team_repos` — List repositories a team has access to. - **PUT** `add_team_repo` — Add a repository to a team. Permission: pull, triage, push, maintain, admin. - **DELETE** `remove_team_repo` — Remove a repository from a team. - **GET** `list_issues` — List issues for a repository. Also returns PRs unless filtered. State: open, closed, all. Note: GitHub treats PRs as issues — check for pull_request field to distinguish. - **GET** `get_issue` — Get a single issue by number, including body, labels, assignees, and milestone. - **POST** `create_issue` — Create a new issue. Labels are an array of label name strings. type is the org issue-type name (string, e.g. 'Bug') — see list_issue_types. - **PATCH** `update_issue` — Update an issue. Set state to 'closed' to close it. Only include fields you want to change. type sets the org issue-type by name (string), or null to clear it. - **PUT** `lock_issue` — Lock an issue. Lock reason: off-topic, too heated, resolved, spam. - **DELETE** `unlock_issue` — Unlock an issue. - **GET** `list_issue_comments` — List comments on an issue or pull request. - **POST** `create_issue_comment` — Add a comment to an issue or pull request. Body supports GitHub-Flavored Markdown. - **PATCH** `update_issue_comment` — Update an issue comment. - **DELETE** `delete_issue_comment` — Delete an issue comment. - **GET** `list_issue_events` — List events for an issue (labeled, assigned, closed, reopened, etc.). - **GET** `list_issue_assignees` — List available assignees for issues in a repository (users with push access). - **GET** `list_issue_reactions` — List reactions on an issue. Content: +1, -1, laugh, confused, heart, hooray, rocket, eyes. - **POST** `create_issue_reaction` — Create a reaction on an issue. Content: +1, -1, laugh, confused, heart, hooray, rocket, eyes. - **POST** `create_issue_comment_reaction` — Create a reaction on an issue comment. - **GET** `list_pulls` — List pull requests for a repository. State: open, closed, all. - **GET** `get_pull` — Get a single pull request including diff stats, mergeable state, and review status. - **GET** `list_pull_files` — List files changed in a pull request with patch diffs and stats. - **GET** `list_pull_reviews` — List reviews on a pull request (approved, changes_requested, commented). - **POST** `create_pull` — Create a new pull request. head is the branch with changes, base is the target branch (e.g. main). Set draft=true to create a draft PR. - **PATCH** `update_pull` — Update a pull request. Set state to 'closed' to close it. Only include fields you want to change. - **PUT** `merge_pull` — Merge a pull request. merge_method: merge, squash, or rebase. Optionally provide sha to ensure merging the expected head commit. - **GET** `list_pull_commits` — List commits on a pull request, ordered chronologically. - **POST** `create_pull_review` — Create a review on a pull request. event: APPROVE, REQUEST_CHANGES, or COMMENT. Body is the review summary. - **GET** `list_pull_review_comments` — List review comments on a pull request (inline code comments, not issue comments). - **POST** `create_pull_review_comment` — Create an inline review comment on a pull request. Specify path and line (or start_line + line for multi-line). side: LEFT or RIGHT for diff side. - **GET** `list_requested_reviewers` — List users and teams requested to review a pull request. - **POST** `request_reviewers` — Request review from users or teams on a pull request. - **DELETE** `remove_requested_reviewers` — Remove requested reviewers from a pull request. - **GET** `list_commits` — List commits on a repository. Filter by sha (branch), path, author, or date range. - **GET** `get_commit` — Get a single commit by SHA or ref, including full diff stats and file changes. - **GET** `compare_commits` — Compare two commits. basehead format: 'base...head' (e.g. 'main...feature-branch'). Returns diff stats, commits, and file changes. - **GET** `list_branches` — List branches for a repository. - **GET** `get_branch` — Get a single branch including its latest commit SHA and protection status. - **GET** `get_branch_protection` — Get branch protection rules for a branch. - **PUT** `update_branch_protection` — Update branch protection rules. Set required_status_checks, enforce_admins, required_pull_request_reviews, and restrictions. - **DELETE** `delete_branch_protection` — Delete branch protection rules for a branch. - **POST** `create_ref` — Create a git reference (branch or tag). For branches use ref='refs/heads/branch-name'. sha is the commit to point to. - **PATCH** `update_ref` — Update a git reference to point to a new SHA. ref is without 'refs/' prefix (e.g. 'heads/main'). Set force=true to do a non-fast-forward update. - **DELETE** `delete_ref` — Delete a git reference. For branches use ref='heads/branch-name' (without refs/ prefix). For tags use ref='tags/tag-name'. - **GET** `get_tree` — Get a git tree by SHA. Set recursive=true to get the full tree (all nested directories). Returns tree entries with path, mode, type, sha. - **POST** `create_tree` — Create a git tree. Each tree entry has path, mode (100644=file, 100755=executable, 040000=directory, 160000=submodule, 120000=symlink), type (blob/tree/commit), and sha or content. - **POST** `create_blob` — Create a git blob. Content can be utf-8 or base64 encoded (set encoding accordingly). - **POST** `create_git_commit` — Create a git commit object. tree is the SHA of the tree, parents is an array of parent commit SHAs. Use with create_tree and update_ref for programmatic commits. - **POST** `create_tag_object` — Create an annotated tag object. object is the SHA to tag. type is the object type (commit, tree, blob). Use create_ref to create the tag ref afterwards. - **GET** `get_content` — Get file or directory contents. Files are base64 encoded. Directories return a listing. Use ref for a specific branch/tag/SHA. - **PUT** `create_or_update_file` — Create or update a file. Content must be base64 encoded. To update an existing file, provide the current blob sha (from get_content). Creates a commit. - **DELETE** `delete_file` — Delete a file from the repository. Requires the current blob sha (from get_content). Creates a commit. - **GET** `search_code` — Search for code across repositories. Query syntax: 'keyword repo:owner/repo language:go path:internal'. Results include file path, repo, and text matches. - **GET** `search_issues` — Search issues and PRs across repositories. Query syntax: 'bug repo:owner/repo is:open label:bug'. Use is:pr or is:issue to filter. - **GET** `search_repos` — Search repositories. Query syntax: 'keyword language:go stars:>100 topic:cli'. Sort: stars, forks, help-wanted-issues, updated. - **GET** `search_users` — Search users. Query syntax: 'username type:user location:germany language:go followers:>100'. - **GET** `search_commits` — Search commits. Query syntax: 'fix repo:owner/repo author:username committer-date:>2026-01-01'. Sort: author-date, committer-date. - **GET** `search_topics` — Search topics by name. Returns matching topic names with descriptions and related info. - **GET** `list_releases` — List releases for a repository, newest first. - **GET** `get_latest_release` — Get the latest published release (not draft/prerelease). - **GET** `get_release` — Get a single release by its numeric ID. - **GET** `get_release_by_tag` — Get a release by tag name (e.g. 'v1.0.0'). - **POST** `create_release` — Create a release. tag_name is required. If the tag does not exist, target_commitish (branch or SHA) is used to create it. Set draft=true for unpublished releases. - **PATCH** `update_release` — Update a release. Only include fields you want to change. - **DELETE** `delete_release` — Delete a release. Does not delete the associated git tag. - **GET** `list_release_assets` — List assets (attached files) for a release. - **DELETE** `delete_release_asset` — Delete a release asset. - **GET** `list_workflows` — List all workflows in a repository. Returns workflow ID, name, path, and state. - **GET** `get_workflow` — Get a specific workflow by ID or filename (e.g. 'ci.yml'). - **POST** `dispatch_workflow` — Trigger a workflow_dispatch event. ref is the branch/tag to run on. inputs is a map of workflow input values. - **GET** `list_workflow_runs` — List workflow runs for a repository. Filter by branch, status (queued, in_progress, completed), or event (push, pull_request). - **GET** `get_workflow_run` — Get a single workflow run including status, conclusion, and timing. - **GET** `list_workflow_run_jobs` — List jobs for a workflow run. Filter by latest attempt or all attempts. - **GET** `get_job` — Get a single workflow job by ID, including steps with status and timing. - **GET** `get_job_log` — Download the log output of a workflow job. Returns plain text with timestamps. The API responds with a 302 redirect to a temporary download URL which is followed automatically. - **POST** `cancel_workflow_run` — Cancel a workflow run that is in progress or queued. - **POST** `rerun_workflow` — Re-run an entire workflow run. Only works for completed runs. - **POST** `rerun_failed_jobs` — Re-run only the failed jobs in a workflow run. - **DELETE** `delete_workflow_run` — Delete a workflow run. The run must be completed. - **GET** `list_workflow_run_artifacts` — List artifacts for a workflow run. Artifacts are files produced during a run (logs, binaries, test results). - **GET** `list_repo_secrets` — List repository secrets for GitHub Actions. Only returns secret names, not values. - **GET** `get_repo_public_key` — Get the public key for encrypting secrets. Required before creating or updating a secret. - **PUT** `create_or_update_repo_secret` — Create or update a repository secret. The encrypted_value must be encrypted with the repo's public key (from get_repo_public_key) using libsodium. - **DELETE** `delete_repo_secret` — Delete a repository secret. - **GET** `list_repo_variables` — List repository variables for GitHub Actions. - **POST** `create_repo_variable` — Create a repository variable for GitHub Actions. - **PATCH** `update_repo_variable` — Update a repository variable. - **DELETE** `delete_repo_variable` — Delete a repository variable. - **GET** `get_actions_permissions` — Get GitHub Actions permissions for a repository: whether Actions is enabled and which actions are allowed. - **PUT** `set_actions_permissions` — Enable or disable GitHub Actions for a repository and set which actions may run. allowed_actions is all, local_only, or selected — use set_allowed_actions to define the selected set. - **GET** `get_actions_workflow_permissions` — Get the default GITHUB_TOKEN permissions for workflows in a repository, and whether workflows may approve pull requests. - **PUT** `set_actions_workflow_permissions` — Set the default GITHUB_TOKEN permissions for workflows. default_workflow_permissions is read or write; can_approve_pull_request_reviews allows workflows to approve PRs. - **GET** `get_fork_pr_approval_policy` — Get which fork pull requests need manual approval before their workflows run. Critical for public repositories: without approval, a fork PR runs its own workflow file on your runners. - **PUT** `set_fork_pr_approval_policy` — Set which fork pull requests need manual approval before their workflows run. approval_policy is first_time_contributors_new_to_github, first_time_contributors, or all_external_contributors — the last is the strictest and the only safe choice for a public repo backed by self-hosted runners. - **GET** `get_allowed_actions` — Get the actions and reusable workflows allowed to run in a repository. Only meaningful when allowed_actions is set to selected. - **PUT** `set_allowed_actions` — Set which actions and reusable workflows may run when allowed_actions is selected. patterns_allowed takes entries like actions/checkout@* or monalisa/octocat@v2. - **GET** `get_org_fork_pr_approval_policy` — Get the organization-wide policy for which fork pull requests need approval before their workflows run. - **PUT** `set_org_fork_pr_approval_policy` — Set the organization-wide policy for which fork pull requests need approval. approval_policy is first_time_contributors_new_to_github, first_time_contributors, or all_external_contributors. Applies to every repository in the org. - **GET** `list_repo_webhooks` — List webhooks for a repository. - **GET** `get_repo_webhook` — Get a single webhook by ID. - **POST** `create_repo_webhook` — Create a webhook for a repository. config.url is the payload URL. events is an array of event names (e.g. ['push', 'pull_request']). - **PATCH** `update_repo_webhook` — Update a webhook. Only include fields you want to change. - **DELETE** `delete_repo_webhook` — Delete a webhook from a repository. - **POST** `ping_repo_webhook` — Send a ping event to a webhook to test its configuration. - **GET** `list_deployments` — List deployments for a repository. Filter by sha, ref, task, or environment. - **GET** `get_deployment` — Get a single deployment. - **POST** `create_deployment` — Create a deployment. ref is the branch/tag/SHA to deploy. environment defaults to 'production'. - **DELETE** `delete_deployment` — Delete a deployment. Only inactive deployments can be deleted. - **GET** `list_deployment_statuses` — List statuses for a deployment. States: error, failure, inactive, in_progress, queued, pending, success. - **POST** `create_deployment_status` — Create a deployment status. state: error, failure, inactive, in_progress, queued, pending, success. - **GET** `list_environments` — List deployment environments for a repository. - **GET** `get_environment` — Get a deployment environment by name. - **PUT** `create_or_update_environment` — Create or update a deployment environment. Configure wait_timer (minutes), reviewers, and deployment_branch_policy. - **DELETE** `delete_environment` — Delete a deployment environment. - **GET** `list_labels` — List all labels for a repository. - **GET** `get_label` — Get a single label by name. - **POST** `create_label` — Create a label. Color is a 6-character hex code without '#' prefix (e.g. 'ff0000' for red). - **PATCH** `update_label` — Update a label. Only include fields you want to change. Use new_name to rename. - **DELETE** `delete_label` — Delete a label from the repository. - **GET** `list_milestones` — List milestones for a repository. State: open, closed, all. - **GET** `get_milestone` — Get a single milestone by its number, including open/closed issue counts. - **POST** `create_milestone` — Create a milestone. due_on is an ISO 8601 timestamp (e.g. '2026-04-01T00:00:00Z'). - **PATCH** `update_milestone` — Update a milestone. Set state to 'closed' to close it. Only include fields you want to change. - **DELETE** `delete_milestone` — Delete a milestone. - **GET** `get_authenticated_user` — Get the currently authenticated user's profile including login, name, email, and bio. - **GET** `get_user` — Get a public user profile by username. - **GET** `list_followers` — List followers of a user. - **GET** `list_following` — List users that a user is following. - **GET** `list_tags` — List tags for a repository, newest first. Each tag includes name and commit SHA. - **GET** `list_stargazers` — List users who have starred a repository. - **GET** `list_starred_repos` — List repositories starred by the authenticated user. - **GET** `check_starred` — Check if the authenticated user has starred a repo. Returns 204 if yes, 404 if no. - **PUT** `star_repo` — Star a repository for the authenticated user. - **DELETE** `unstar_repo` — Unstar a repository for the authenticated user. - **GET** `list_watchers` — List users watching (subscribed to) a repository. - **GET** `get_repo_subscription` — Get the authenticated user's subscription (watch status) for a repository. - **PUT** `watch_repo` — Watch a repository. Set subscribed=true to receive notifications, ignored=true to mute. - **DELETE** `unwatch_repo` — Stop watching a repository. - **GET** `list_gists` — List gists for the authenticated user. - **GET** `list_public_gists` — List public gists, newest first. - **GET** `list_starred_gists` — List gists starred by the authenticated user. - **GET** `get_gist` — Get a single gist by ID, including all files and their content. - **POST** `create_gist` — Create a gist. files is a map of filename to {content: string}. Set public=true for a public gist. - **PATCH** `update_gist` — Update a gist. To delete a file, set its value to null. To rename, delete the old name and create a new one. - **DELETE** `delete_gist` — Delete a gist. - **GET** `list_notifications` — List notifications for the authenticated user. Set all=true to include read notifications. - **PUT** `mark_notifications_read` — Mark all notifications as read. Optionally provide last_read_at (ISO 8601) to only mark notifications before that time. - **GET** `list_repo_notifications` — List notifications for a repository. - **PUT** `mark_repo_notifications_read` — Mark all notifications in a repository as read. - **GET** `get_notification_thread` — Get a single notification thread. - **PATCH** `mark_thread_read` — Mark a notification thread as read. - **GET** `list_check_runs_for_ref` — List check runs for a commit SHA, branch name, or tag. Filter by check_name, status, or filter (latest, all). - **GET** `list_check_run_annotations` — List annotations for a check run. Returns inline lint/test errors with file path, line number, and message. Use this to inspect CI failure details programmatically. - **GET** `list_check_suites_for_ref` — List check suites for a commit SHA, branch name, or tag. - **GET** `get_combined_status` — Get the combined status for a commit (aggregates all status checks). Returns state: success, failure, pending. - **GET** `list_commit_statuses` — List individual status checks for a commit ref. - **POST** `create_commit_status` — Create a commit status. state: error, failure, pending, success. Provide target_url for linking to CI details. - **GET** `get_pages` — Get GitHub Pages configuration for a repository. - **POST** `create_pages_site` — Enable GitHub Pages for a repository. source.branch is the branch to publish from, source.path is '/' or '/docs'. - **PUT** `update_pages_info` — Update GitHub Pages configuration. - **DELETE** `delete_pages_site` — Disable GitHub Pages for a repository. - **GET** `list_pages_builds` — List GitHub Pages builds. - **GET** `list_code_scanning_alerts` — List code scanning alerts for a repository. State: open, closed, dismissed, fixed. - **GET** `get_code_scanning_alert` — Get a single code scanning alert. - **PATCH** `update_code_scanning_alert` — Update a code scanning alert. Set state to 'dismissed' with a dismissed_reason, or 'open' to reopen. - **GET** `list_dependabot_alerts` — List Dependabot alerts for a repository. State: auto_dismissed, dismissed, fixed, open. - **GET** `get_dependabot_alert` — Get a single Dependabot alert. - **PATCH** `update_dependabot_alert` — Update a Dependabot alert. Set state to 'dismissed' with a dismissed_reason, or 'open' to reopen. - **GET** `list_secret_scanning_alerts` — List secret scanning alerts for a repository. State: open, resolved. - **GET** `get_secret_scanning_alert` — Get a single secret scanning alert. - **PATCH** `update_secret_scanning_alert` — Update a secret scanning alert. Set state to 'resolved' with a resolution (false_positive, wont_fix, revoked, used_in_tests, pattern_edited, pattern_deleted). - **GET** `list_org_packages` — List packages in an organization. package_type is required: npm, maven, rubygems, docker, nuget, container. - **GET** `get_org_package` — Get a specific package in an organization. - **DELETE** `delete_org_package` — Delete an entire package in an organization. Requires admin permissions. Cannot be undone after 30 days. - **POST** `restore_org_package` — Restore a deleted organization package. Only works within 30 days of deletion. - **GET** `list_org_package_versions` — List all versions of an organization package. Filter by state: active (default), deleted. - **GET** `get_org_package_version` — Get a specific version of an organization package. - **DELETE** `delete_org_package_version` — Delete a specific version of an organization package. Cannot be undone after 30 days. - **POST** `restore_org_package_version` — Restore a deleted version of an organization package. Only works within 30 days. - **GET** `list_user_packages` — List packages owned by the authenticated user. package_type is required: npm, maven, rubygems, docker, nuget, container. - **GET** `get_user_package` — Get a package owned by the authenticated user. - **DELETE** `delete_user_package` — Delete a package owned by the authenticated user. Cannot be undone after 30 days. - **GET** `list_user_package_versions` — List all versions of a package owned by the authenticated user. - **DELETE** `delete_user_package_version` — Delete a specific version of a package owned by the authenticated user. - **GET** `get_issue_parent` — Get the parent issue of a sub-issue. Returns the full parent issue object, or 404 if the issue has no parent. - **GET** `list_sub_issues` — List the sub-issues of an issue, in their manual priority order. Returns full issue objects. - **POST** `add_sub_issue` — Add a sub-issue under a parent issue. sub_issue_id is the database id (the 'id' field of get_issue), NOT the issue_number. Set replace_parent=true to move a sub-issue that already belongs to a different parent. - **DELETE** `remove_sub_issue` — Remove a sub-issue from its parent. Note the singular 'sub_issue' in the path. sub_issue_id is the database id, not the issue_number. Only the parent/child link is removed — the issue itself is not deleted. - **PATCH** `reprioritize_sub_issue` — Reorder a sub-issue within its parent's list. Provide after_id OR before_id (another sub-issue's database id) to position it — they are mutually exclusive. sub_issue_id is the database id of the sub-issue being moved. - **GET** `list_issue_blocked_by` — List the issues that block the given issue (its 'blocked by' dependencies). Returns full issue objects. - **POST** `add_issue_blocked_by` — Mark issue_number as blocked by another issue. issue_id (body) is the database id (the 'id' field of get_issue) of the blocking issue, NOT its issue_number. - **DELETE** `remove_issue_blocked_by` — Remove a 'blocked by' dependency. issue_id (path) is the database id of the blocking issue. Only the dependency link is removed; neither issue is deleted. - **GET** `list_issue_blocking` — List the issues that the given issue is blocking (the inverse of blocked_by). Returns full issue objects. - **GET** `list_issue_types` — List the issue types defined for an organization (id, name, description, color, is_enabled). Assign one to an issue via the `type` field of create_issue/update_issue. - **POST** `create_issue_type` — Create a new issue type for an organization. color is one of gray, blue, green, yellow, orange, red, pink, purple (or null). - **PUT** `update_issue_type` — Update an organization issue type. The API requires name and is_enabled even for partial edits — resend the current values for fields you are not changing. - **DELETE** `delete_issue_type` — Delete an organization issue type. Any issues currently using it lose their type. - **GET** `list_repo_rulesets` — List the rulesets for a repository. includes_parents=true (default) also returns inherited org-level rulesets. targets filters by comma-separated target types (branch,tag,push). - **GET** `get_repo_ruleset` — Get a single repository ruleset by id, including its full rules and conditions. - **POST** `create_repo_ruleset` — Create a repository ruleset. enforcement is one of disabled, active, evaluate. target is branch (default), tag, or push. rules is an array of rule objects, each with a `type` (e.g. pull_request, required_status_checks, required_signatures, non_fast_forward, commit_message_pattern, required_linear_history) and an optional `parameters` object. bypass_actors is an array of {actor_id, actor_type (Team|Integration|RepositoryRole|OrganizationAdmin|DeployKey|User), bypass_mode (always|pull_request)}. conditions is {ref_name:{include:[...], exclude:[...]}}; refs use refs/heads/* or the ~DEFAULT_BRANCH / ~ALL placeholders. - **PUT** `update_repo_ruleset` — Update a repository ruleset. Same writable fields as create_repo_ruleset; send only the fields you want to change (each provided field replaces its previous value). - **DELETE** `delete_repo_ruleset` — Delete a repository ruleset. Removes the policy and its protections immediately. - **GET** `get_branch_rules` — Get the effective rules that apply to a branch, aggregated across all active rulesets (repo + inherited org). Each entry names the rule type and the ruleset it comes from. - **GET** `list_repo_rule_suites` — List rule evaluation runs (rule suites) for a repository — the audit log of ruleset enforcement. Filter by ref, time_period (hour|day|week|month), actor_name, rule_suite_result (pass|fail|bypass|all), evaluate_status (all|active|evaluate). - **GET** `get_repo_rule_suite` — Get a single repository rule suite (one evaluation run), including the per-rule pass/fail/bypass results. - **GET** `list_org_rulesets` — List all organization-level rulesets. targets filters by comma-separated target types (branch,tag,push,repository). - **GET** `get_org_ruleset` — Get a single organization ruleset by id, including rules and conditions. - **POST** `create_org_ruleset` — Create an organization ruleset. enforcement is disabled|active|evaluate. target is branch (default), tag, push, or repository. conditions may target refs (ref_name) and repositories (repository_name:{include,exclude}, repository_id, or repository_property to match custom properties). rules and bypass_actors have the same shape as repository rulesets — see create_repo_ruleset. - **PUT** `update_org_ruleset` — Update an organization ruleset. Same writable fields as create_org_ruleset; send only the fields you want to change. - **DELETE** `delete_org_ruleset` — Delete an organization ruleset. Removes the policy from every targeted repository immediately. - **GET** `list_org_rule_suites` — List rule evaluation runs (rule suites) across an organization's repositories — the org-wide enforcement audit log. Filter by repository_name, ref, time_period (hour|day|week|month), actor_name, rule_suite_result (pass|fail|bypass|all), evaluate_status (all|active|evaluate). - **GET** `get_org_rule_suite` — Get a single organization rule suite (one evaluation run), including per-rule pass/fail/bypass results. - **GET** `get_org_properties_schema` — List all custom property definitions for an organization (property_name, value_type, required, allowed_values, default_value). - **PATCH** `set_org_properties_schema` — Create or update multiple custom property definitions in one call. properties is an array of objects: {property_name (required), value_type (string|single_select|multi_select|true_false, required), required (bool), default_value, description, allowed_values, values_editable_by (org_actors|org_and_repo_actors)}. - **GET** `get_org_property` — Get a single custom property definition by name. - **PUT** `set_org_property` — Create or update a single custom property definition. value_type is string, single_select, multi_select, or true_false. - **DELETE** `remove_org_property` — Remove a custom property definition from an organization. Also clears that property's values on all repositories. - **GET** `list_org_property_values` — List custom property values assigned to repositories across the org. repository_query filters repos using GitHub search syntax. - **PATCH** `set_org_property_values` — Assign custom property values to a list of repositories in one call. repository_names is an array of repo names (max 30 per call). properties is an array of {property_name, value} — value is a string, an array (multi_select), or null to clear. - **GET** `get_repo_property_values` — Get all custom property values set on a single repository. Returns an array of {property_name, value}. - **PATCH** `set_repo_property_values` — Create or update custom property values on a single repository. properties is an array of {property_name, value}; value=null removes the property from the repo. - **GET** `get_traffic_views` — Get page-view counts for the last 14 days. per is 'day' (default) or 'week'. Returns total count, uniques, and a per-period breakdown. Requires push access. - **GET** `get_traffic_clones` — Get git clone counts for the last 14 days. per is 'day' (default) or 'week'. Returns total count, uniques, and a per-period breakdown. Requires push access. - **GET** `list_traffic_paths` — Get the top 10 most-visited content paths over the last 14 days (path, title, count, uniques). Requires push access. - **GET** `list_traffic_referrers` — Get the top 10 referrer sources over the last 14 days (referrer, count, uniques). Requires push access. - **GET** `get_stats_contributors` — Per-contributor commit stats: total commits plus weekly added/deleted/commits buckets (w = week start, epoch seconds). Returns 202 on a cold cache — retried automatically. - **GET** `get_stats_commit_activity` — Last 52 weeks of commit activity: per week {total, week (epoch seconds), days[7] from Sun..Sat}. Returns 202 on a cold cache — retried automatically. - **GET** `get_stats_code_frequency` — Weekly additions/deletions as an array of [week (epoch seconds), additions, deletions (negative)]. Returns 202 on a cold cache — retried automatically. - **GET** `get_stats_participation` — Last 52 weeks of commit counts as {all:[...], owner:[...]} (oldest first). Returns 200 with data; may briefly return 202 on a cold cache. - **GET** `get_stats_punch_card` — Commit counts per weekday/hour as an array of [day (0=Sun..6=Sat), hour (0-23), commits]. Returns 200 with data; may briefly return 202 on a cold cache. ## Which DADLs are related to GitHub? - [GitLab](https://www.dadl.ai/d/gitlab/) — GitLab REST API v4 — projects, issues, merge requests, pipelines, CI/CD, and code search - [Zammad](https://www.dadl.ai/d/zammad/) — Zammad helpdesk REST API -- tickets, articles, users, organizations, groups, roles, knowledge base, SLAs, calendars, object manager (custom fields), macros, triggers, overviews, reports, time accounting, and full admin surface. Supports X-On-Behalf-Of impersonation on every endpoint. - [Zulip](https://www.dadl.ai/d/zulip/) — Zulip REST API — messages, channels (streams), topics, users, user groups, subscriptions, reactions, drafts, scheduled messages, saved snippets, presence, real-time events, invitations, attachments, custom emoji, linkifiers, and server settings. Self-hosted or Zulip Cloud. - [Billomat](https://www.dadl.ai/d/billomat/) — Billomat REST API — German cloud invoicing & accounting: invoices, estimates, credit notes, recurring invoices, delivery notes, order confirmations, dunning reminders, clients, contacts, articles, payments, expenses, taxes - [BookStack](https://www.dadl.ai/d/bookstack/) — BookStack wiki and documentation platform REST API -- shelves, books, chapters, pages (HTML/Markdown content), attachments, image gallery, comments, cross-entity search, exports (HTML/Markdown/PDF/ZIP), ZIP imports, users, roles, content permissions, recycle bin, audit log and tags. Hierarchy: shelves > books > chapters > pages. - [ELITEDOMAINS](https://www.dadl.ai/d/elitedomains/) — ELITEDOMAINS domain registrar API -- register/transfer/manage .de and gTLD domains, redirector & inline DNS, AuthInfo/AuthInfo2 transfer codes, RGP catcher backorders, contact handles, and marketplace offers (Sedo, sale pages) --- **Canonical URL:** https://www.dadl.ai/d/github/ **Raw DADL:** https://github.com/DunkelCloud/dadl-registry/blob/main/github.dadl --- # GitLab MCP Server — 75 tools via DADL The GitLab DADL turns GitLab's API into an MCP server that Claude, GPT or any MCP-compatible agent can consume directly. One YAML file declares all 75 tools — project, pipeline, group, merge, job, label, and more — and ToolMesh serves them at runtime. No Python boilerplate, no per-endpoint code, no separate MCP server process. Below: the endpoint coverage matrix, a two-block ToolMesh setup, the full tool reference grouped by GitLab feature area, required credential scopes. **Source:** [GitLab REST API v4](https://docs.gitlab.com/ee/api/rest/) **Updated:** 2026-10-10 **Tags:** version-control, ci-cd, issue-tracking, automation, crud, search, file-management, authentication, auth:apikey ## Which GitLab endpoints are covered? **19%** (75 of ~400 endpoints). **Focus:** GitLab REST API v4: projects, issues, merge requests, pipelines, jobs, branches, commits, releases, groups, users, repository files, labels, milestones, code search **Missing:** deploy tokens, container registry, packages, wikis, snippets, epics, environments, cluster agents, protected branches, webhooks, project hooks *Last reviewed: 2026-10-10* ## How do you configure the GitLab DADL? 1. Navigate to GitLab → User Settings → Access Tokens 2. Enter a name (e.g. 'ToolMesh') and optional expiration date 3. Select scope: api (full access) or read_api (read-only) 4. Click 'Create personal access token' and copy the token (starts with glpat-) **Environment variable:** `CREDENTIAL_GITLAB_TOKEN` [Authentication docs](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html) *For self-hosted GitLab, replace the URL with your instance address. SaaS users use https://gitlab.com/api/v4* ## How do you install the GitLab MCP server with ToolMesh? Add to your `backends.yaml`: ```yaml - name: gitlab transport: rest dadl: gitlab.dadl url: "https://your-gitlab.example.com/api/v4" ``` Set the credential: ``` CREDENTIAL_GITLAB_TOKEN=your-token-here ``` ## What 75 tools does the GitLab DADL expose? - **GET** `list_projects` — List all visible projects. Use membership=true to limit to projects the user is a member of, owned=true for owned projects. - **GET** `get_project` — Get a single project by numeric ID or namespace path with plain slashes (e.g., 'my-group/my-project'). Do not pre-encode slashes as %2F — that 404s. - **POST** `create_project` — Create a new project. Requires name or path. - **PUT** `update_project` — Update a project. Only include fields you want to change. - **DELETE** `delete_project` — Delete a project. Requires owner or admin access. - **GET** `list_group_projects` — List projects in a group. Use include_subgroups to include nested group projects. - **GET** `list_issues` — List all issues visible to the authenticated user. Use scope to filter by created_by_me, assigned_to_me, or all. - **GET** `list_project_issues` — List issues for a specific project. - **GET** `list_group_issues` — List issues for a group. - **GET** `get_project_issue` — Get a single project issue by its internal ID (iid). - **POST** `create_issue` — Create a new issue in a project. - **PUT** `update_issue` — Update an issue. Use state_event 'close' or 'reopen' to change state. At least one field required. - **DELETE** `delete_issue` — Delete a project issue. Requires Planner/Owner role or issue author (GitLab 18.10+). - **GET** `list_merge_requests` — List all merge requests visible to the authenticated user. Date filters (created_after/created_before, updated_after/updated_before) take ISO 8601 datetimes and are inclusive. state defaults to "opened" here -- pass state "all" when computing a delta that must include merged or closed MRs. Returns one page (page/per_page). - **GET** `list_project_merge_requests` — List merge requests for a specific project. For delta/sync queries use the date filters instead of paging through everything: created_after/created_before, updated_after/updated_before (ISO 8601 datetimes, e.g. "2026-03-15T08:00:00Z", inclusive). state defaults to "opened" here -- pass state "all" when the delta must include merged or closed MRs. Returns one page (page/per_page, max 100). - **GET** `list_group_merge_requests` — List merge requests for a group (all its projects). Same date filters as list_project_merge_requests: created_after/created_before, updated_after/updated_before (ISO 8601, inclusive). state defaults to "opened" here -- pass state "all" for deltas over merged or closed MRs. Returns one page. - **GET** `get_merge_request` — Get a single merge request by its internal ID. - **POST** `create_merge_request` — Create a new merge request. source_branch and target_branch must be different. Duplicate source/target pairs are rejected. - **PUT** `update_merge_request` — Update a merge request. Use state_event 'close' or 'reopen' to change state. - **PUT** `merge_merge_request` — Accept and merge a merge request. Optionally squash commits or set a custom merge commit message. - **POST** `approve_merge_request` — Approve a merge request. Optionally verify HEAD SHA to ensure reviewing the correct version. - **PUT** `rebase_merge_request` — Rebase a merge request's source branch onto the target branch. - **GET** `list_branches` — List repository branches. Use search for substring matching or regex for pattern matching. - **GET** `get_branch` — Get a single branch including its latest commit and protection status. - **POST** `create_branch` — Create a new branch from a ref (branch name, tag, or commit SHA). - **DELETE** `delete_branch` — Delete a branch. Cannot delete the default or protected branches. - **DELETE** `delete_merged_branches` — Delete all branches that have been merged into the default branch. Returns 202 Accepted. - **GET** `list_commits` — List commits in a repository. Filter by branch/tag (ref_name), file path, author, or date range. - **GET** `get_commit` — Get a single commit by SHA, branch name, or tag name. Includes author info, message, and parent SHAs. - **GET** `get_commit_diff` — Get the diff of a commit showing file changes with unified diff content. - **GET** `list_pipelines` — List pipelines for a project. Child pipelines are not included by default. - **GET** `get_pipeline` — Get a single pipeline by ID. - **GET** `get_latest_pipeline` — Get the latest pipeline for a ref. Defaults to the default branch. - **POST** `create_pipeline` — Trigger a new pipeline on a branch or tag. Note: singular 'pipeline' in path, not 'pipelines'. - **POST** `retry_pipeline` — Retry all failed jobs in a pipeline. - **POST** `cancel_pipeline` — Cancel a running pipeline and all its running jobs. - **DELETE** `delete_pipeline` — Delete a pipeline. Deletes builds, logs, artifacts, and triggers. Cannot be undone. - **GET** `get_pipeline_variables` — Get variables for a pipeline. - **GET** `get_pipeline_test_report` — Get the test report for a pipeline. - **GET** `list_project_jobs` — List jobs for a project. Supports both offset and keyset pagination. - **GET** `list_pipeline_jobs` — List jobs for a pipeline. Retried jobs are excluded by default; use include_retried=true to include them. - **GET** `get_job` — Get a single job by ID. - **GET** `get_job_log` — Get the log (trace) output of a job. Returns plain text, not JSON. - **POST** `retry_job` — Retry a single job. - **POST** `cancel_job` — Cancel a running or pending job. - **POST** `play_job` — Trigger a manual job. - **GET** `list_releases` — List releases for a project, sorted by released_at descending. - **GET** `get_release` — Get a single release by its associated tag name. - **POST** `create_release` — Create a release. If the tag does not exist, ref is required to create it. - **PUT** `update_release` — Update a release. Only name, description, milestones, and released_at can be changed. - **DELETE** `delete_release` — Delete a release. The associated Git tag is preserved. Requires Maintainer access. - **GET** `list_groups` — List visible groups. Without authentication, only public groups are returned. - **GET** `get_group` — Get details of a group by numeric ID or full path with plain slashes (e.g. 'parent-group/subgroup'). - **GET** `list_subgroups` — List direct subgroups of a group. - **POST** `create_group` — Create a new group. Requires name and path. - **GET** `get_current_user` — Get the currently authenticated user's profile. - **GET** `list_users` — List all users. Admins see extended fields. Use search to find by name, username, or email. - **GET** `get_user` — Get a single user by numeric user ID. Admins see extended fields including sign-in history. - **GET** `get_file` — Get file metadata and base64-encoded content. Pass file_path with plain slashes (e.g. 'config/rules/hosts.yml'); do not pre-encode them as %2F. - **GET** `get_file_raw` — Get raw (unencoded) file content. Returns the file directly, not JSON. - **POST** `create_file` — Create a new file in the repository. Creates a commit. - **PUT** `update_file` — Update an existing file in the repository. Creates a commit. - **DELETE** `delete_file` — Delete a file from the repository. Creates a commit. - **GET** `list_labels` — List all labels for a project. - **GET** `get_label` — Get a single label by ID or title. - **POST** `create_label` — Create a new label. Color must be a 6-digit hex with '#' prefix (e.g., '#FF0000') or a CSS color name. - **PUT** `update_label` — Update a label. At least new_name or color is required. - **DELETE** `delete_label` — Delete a label from the project. - **GET** `list_milestones` — List all milestones for a project. - **GET** `get_milestone` — Get a single milestone by ID. - **POST** `create_milestone` — Create a new milestone. Dates use YYYY-MM-DD format. - **PUT** `update_milestone` — Update a milestone. Use state_event 'close' or 'activate' to change state. - **GET** `search_global` — Search across the entire GitLab instance. Scope determines what to search: projects, issues, merge_requests, milestones, snippet_titles, users, wiki_blobs, commits, blobs, notes. - **GET** `search_group` — Search within a group. Same scopes as global search. - **GET** `search_project` — Search within a project. Scopes: issues, merge_requests, milestones, users, wiki_blobs, commits, blobs, notes. Use ref to search a specific branch/tag. ## Which DADLs are related to GitLab? - [GitHub](https://www.dadl.ai/d/github/) — GitHub REST API — repositories, issues, pull requests, commits, and code search - [DokuWiki](https://www.dadl.ai/d/dokuwiki/) — DokuWiki JSON-RPC API — wiki pages, media files, search, ACL management, and user administration - [Billomat](https://www.dadl.ai/d/billomat/) — Billomat REST API — German cloud invoicing & accounting: invoices, estimates, credit notes, recurring invoices, delivery notes, order confirmations, dunning reminders, clients, contacts, articles, payments, expenses, taxes - [BookStack](https://www.dadl.ai/d/bookstack/) — BookStack wiki and documentation platform REST API -- shelves, books, chapters, pages (HTML/Markdown content), attachments, image gallery, comments, cross-entity search, exports (HTML/Markdown/PDF/ZIP), ZIP imports, users, roles, content permissions, recycle bin, audit log and tags. Hierarchy: shelves > books > chapters > pages. - [Cloudflare](https://www.dadl.ai/d/cloudflare/) — Cloudflare API -- DNS, Pages, Workers, KV, R2, D1, Zones, SSL/TLS, Cache, Load Balancers, Firewall/WAF, Page Rules, Access (Zero Trust), Email Routing, Email Sending, DMARC/SPF email auth, and account management - [Graylog](https://www.dadl.ai/d/graylog/) — Graylog REST API -- log search (Views/Search + legacy universal), streams, pipelines, inputs, alerts, events, dashboards, users, roles, sidecars, index management, and cluster administration. Targets Graylog 6.x. --- **Canonical URL:** https://www.dadl.ai/d/gitlab/ **Raw DADL:** https://github.com/DunkelCloud/dadl-registry/blob/main/gitlab.dadl --- # Graylog MCP Server — 216 tools via DADL The Graylog DADL turns Graylog's API into an MCP server that Claude, GPT or any MCP-compatible agent can consume directly. One YAML file declares all 216 tools — stream, pipeline, sidecar, event, cluster, index, and more — and ToolMesh serves them at runtime. No Python boilerplate, no per-endpoint code, no separate MCP server process. Below: the endpoint coverage matrix, a two-block ToolMesh setup, the full tool reference grouped by Graylog feature area, required credential scopes. **Source:** [Graylog REST API](https://go2docs.graylog.org/current/setting_up_graylog/rest_api.html) **Updated:** 2026-08-04 **Tags:** logging, search, crud, user-management, monitoring, real-time, automation, auth:basic ## Which Graylog endpoints are covered? **68%** (216 of ~320 endpoints). **Focus:** Views/Search API (sync, messages, pivot/histogram/stats via composites), legacy relative + keyword search, CSV export, views, streams, stream rules, pipelines, pipeline rules, inputs, extractors, events, notifications, dashboards, users, roles, tokens, index sets, indices, grok patterns, lookup tables, sidecars, sidecar configurations, collectors, content packs, outputs, metrics, system info, cluster, processing control, loggers, forensic incident_window composite **Missing:** enterprise-only plugins (archives, audit log, reports, license, data lake), Views CRUD (saved views, dashboard widgets), Views write CRUD (create/update/delete -- POST/PUT/DELETE /views), legacy alerts API (removed in 6.x, superseded by events), message decorators, debug events, codec types, retention/rotation strategy config, LDAP config, async Views/Search (poll-based), absolute-range legacy search (covered by views_search_sync) *Last reviewed: 2026-08-04* ## How do you configure the Graylog DADL? 1. 1. Log into your Graylog web interface (default: http://<host>:9000) 2. 2. Navigate to System > Users and Teams 3. 3. Click your username, then 'Edit Tokens' 4. 4. Enter a token name (e.g., 'toolmesh') and click 'Create Token' 5. 5. Copy the generated token -- it is shown only once 6. 6. Set CREDENTIAL_GRAYLOG_TOKEN to the token string 7. 7. Set CREDENTIAL_GRAYLOG_TOKEN_PASSWORD to the literal string 'token' **Environment variable:** `CREDENTIAL_GRAYLOG_TOKEN, CREDENTIAL_GRAYLOG_TOKEN_PASSWORD` [Authentication docs](https://go2docs.graylog.org/current/setting_up_graylog/rest_api.html) *Graylog uses HTTP Basic Auth with access tokens. The username is the token string, the password is the literal word "token". Tokens have configurable TTL (default 30 days). Self-hosted: adjust the url in backends.yaml to match your Graylog server address. * ## How do you install the Graylog MCP server with ToolMesh? Add to your `backends.yaml`: ```yaml - name: graylog transport: rest dadl: graylog.dadl url: "https://graylog.example.com/api" ``` Set the credential: ``` CREDENTIAL_GRAYLOG_TOKEN, CREDENTIAL_GRAYLOG_TOKEN_PASSWORD=your-token-here ``` ## What 216 tools does the Graylog DADL expose? - **GET** `search_relative` — Search messages with a relative time range (seconds from now). Query uses Lucene syntax. Returns messages with id, timestamp, source, and all fields. Default limit 150, max 10000. Scope to a stream with filter "streams:STREAM_ID" -- that is the only stream scoping this endpoint honors on Graylog 6.1. - **GET** `export_search_relative` — CSV export of a relative-time-range search. Same query semantics as search_relative, but returns text/csv streamed to the file broker -- the tool result is a download URL, not inline rows. "fields" is REQUIRED here (unlike search_relative) and defines the column order. Use for bulk pulls; for inline results use search_relative or search_messages_compact. Leave the Accept parameter at its default -- it is what selects CSV. - **GET** `search_keyword` — Search messages with a Natty-parsed open-ended time range like "last 5 minutes", "last 7 hours", "yesterday", "last week". The keyword is parsed in the "timezone" time zone (default UTC) -- override it to make phrases like "yesterday" mean yesterday in local time. WARNING: closed/relative phrases like "7 hours ago" are rejected with HTTP 400. For closed absolute windows or aggregation use the views_search_sync / aggregate_pivot composites instead. - **GET** `export_search_keyword` — CSV export of a keyword-time-range search. Same keyword grammar and timezone handling as search_keyword, but returns text/csv streamed to the file broker -- the tool result is a download URL, not inline rows. "fields" is REQUIRED here and defines the column order. Leave the Accept parameter at its default -- it is what selects CSV. - **POST** `views_search_sync` — Execute a Views/Search query synchronously and return results inline. Body shape: { id?, queries: [...], parameters: [], skip_no_streams_check? }. NOTE: there is no top-level "streams" field -- Graylog rejects it with HTTP 400. Scope to streams via query.filter (e.g. { type: "or", filters: [{ type: "stream", id: STREAM_ID }] }) on the individual query object. Each query has id, query.query_string, timerange (absolute / relative / keyword), optional filter, and search_types[] (pivot, messages, events, ...). For everyday forensic work prefer the higher-level composites: aggregate_by_field, aggregate_pivot, histogram_grouped, field_stats, search_messages_compact, incident_window. Server-side timeout via ?timeout=<seconds>, default 60. - **POST** `views_search_messages` — Standalone CSV message export with free-form parameters -- no saved Search needed. This is NOT the views_search_sync body shape. Body fields: timerange (required, the usual absolute / relative / keyword object), query_string (required, { "type": "elasticsearch", "query_string": "level:3" }), streams (array of stream IDs -- allowed here, unlike views_search_sync, and actually honored), fields_in_order (array, MUST be non-empty, defines CSV column order), chunk_size, time_zone, limit. IMPORTANT: limit is only enforced at CHUNK boundaries -- with the default chunk_size of 1000, limit 3 still returns 1000 rows. To cap the output set chunk_size to the row count you want. time_zone defaults to the API user's configured time zone (NOT UTC) -- pass it explicitly for stable timestamps. Returns text/csv streamed to the file broker -- the tool result is a download URL, not inline rows. Preferred over export_search_relative / export_search_keyword when you need an absolute window, exact field projection or real stream scoping. Leave the Accept parameter at its default -- it selects CSV. - **GET** `get_message` — Retrieve a single message by its ID and index name. Returns all message fields. - **POST** `parse_message` — Parse a raw message string using Graylog's message parsing pipeline. Useful for testing extractors. - **GET** `analyze_message_field` — Analyze a message field value to show how Elasticsearch tokenizes it. - **GET** `list_saved_searches` — List all saved searches. - **GET** `list_streams` — List all streams. Returns stream id, title, description, rules, matching_type, disabled status, and index_set_id. The Default Stream ID is "000000000000000000000001". - **GET** `get_stream` — Get a single stream by ID with its configuration and rules. - **POST** `create_stream` — Create a new stream. matching_type: AND (all rules must match) or OR (any rule matches). The stream is created paused -- call resume_stream to start routing messages. - **PUT** `update_stream` — Update a stream's title, description, matching type, or index set. - **DELETE** `delete_stream` — Delete a stream. The Default Stream cannot be deleted. - **POST** `clone_stream` — Clone a stream including all its rules. - **POST** `pause_stream` — Pause a stream. Messages will no longer be routed to this stream. - **POST** `resume_stream` — Resume a paused stream. Messages will start routing to this stream again. - **GET** `list_enabled_streams` — List only enabled (non-paused) streams. - **POST** `test_stream_match` — Test if a message would match the rules of a stream. - **GET** `list_stream_rules` — List all rules for a stream. Rule types: 1=exact match, 2=regex match, 3=greater than, 4=less than, 5=field presence, 6=contains, 7=always match, 8=match input. - **GET** `get_stream_rule` — Get a single stream rule. - **POST** `create_stream_rule` — Create a stream rule. type is an integer: 1=exact, 2=regex, 3=greater_than, 4=less_than, 5=field_presence, 6=contains, 7=always_match, 8=match_input. - **PUT** `update_stream_rule` — Update a stream rule. - **DELETE** `delete_stream_rule` — Delete a stream rule. - **GET** `list_stream_outputs` — List outputs assigned to a stream. - **POST** `add_stream_output` — Add an existing output to a stream. - **DELETE** `remove_stream_output` — Remove an output from a stream. - **GET** `list_pipelines` — List all processing pipelines. Each pipeline has stages with rules. Pipeline source uses Graylog's pipeline rule language. - **GET** `get_pipeline` — Get a single pipeline by ID, including its source code and stages. - **POST** `create_pipeline` — Create a processing pipeline. The source field contains the pipeline definition in Graylog pipeline language. Validate with parse_pipeline first. - **PUT** `update_pipeline` — Update a pipeline's source, title, or description. - **DELETE** `delete_pipeline` — Delete a processing pipeline. - **POST** `parse_pipeline` — Parse and validate pipeline source without creating it. Returns parse errors if invalid. - **POST** `simulate_pipeline` — Simulate pipeline processing on a message to see which rules would match and what output would be produced. - **GET** `list_pipeline_rules` — List all pipeline rules. Rules are written in Graylog's rule language. - **GET** `get_pipeline_rule` — Get a single pipeline rule by ID. - **POST** `create_pipeline_rule` — Create a new pipeline rule. Validate with parse_pipeline_rule first. - **PUT** `update_pipeline_rule` — Update a pipeline rule. - **DELETE** `delete_pipeline_rule` — Delete a pipeline rule. - **POST** `parse_pipeline_rule` — Parse and validate a pipeline rule without creating it. - **GET** `list_pipeline_functions` — List all available functions that can be used in pipeline rules. - **GET** `list_pipeline_connections` — List all stream-to-pipeline connections. - **GET** `get_stream_pipeline_connections` — Get pipeline connections for a specific stream. - **POST** `connect_pipeline_to_stream` — Connect pipelines to a stream. - **POST** `connect_stream_to_pipeline` — Connect streams to a pipeline. - **GET** `list_inputs` — List all configured inputs. Each input has a type (e.g. org.graylog2.inputs.syslog.udp.SyslogUDPInput), title, global flag, and configuration. - **GET** `get_input` — Get a single input by ID. - **POST** `create_input` — Create a new input. Use list_input_types to see available types and their configuration fields. Set global=true for cluster-wide inputs, false for node-local. - **PUT** `update_input` — Update an input's title, configuration, or global flag. - **DELETE** `delete_input` — Delete an input. This stops ingestion from this source. - **POST** `launch_input` — Start/launch an existing input. - **POST** `stop_input` — Stop a running input. - **GET** `list_input_types` — List all available input types with their configuration schemas. - **GET** `get_input_type` — Get details for a specific input type including all configuration fields. - **GET** `list_input_states` — List input states (running, stopped, failed) for all inputs on this node. - **GET** `list_extractors` — List all extractors configured on an input. - **GET** `get_extractor` — Get a single extractor. - **POST** `create_extractor` — Create an extractor on an input. Types: regex, substring, split_and_index, copy_input, grok, json, lookup_table. - **PUT** `update_extractor` — Update an extractor. - **DELETE** `delete_extractor` — Delete an extractor from an input. - **POST** `create_static_field` — Add a static field to all messages from this input. - **DELETE** `delete_static_field` — Remove a static field from an input. - **GET** `list_event_definitions` — List all event definitions (alert conditions in Graylog 3.1+). - **GET** `get_event_definition` — Get a single event definition. - **POST** `create_event_definition` — Create an event definition. config contains the condition type and parameters. notification_settings controls which notifications fire. - **PUT** `update_event_definition` — Update an event definition. - **DELETE** `delete_event_definition` — Delete an event definition. - **POST** `execute_event_definition` — Manually trigger an event definition to check for events now. - **POST** `validate_event_definition` — Validate an event definition without creating it. - **POST** `search_events` — Search for triggered events. Supports filtering by event definition, timerange, and query. Returns events with timestamp, priority, fields, and source. - **GET** `list_event_notifications` — List all event notifications (email, HTTP, Slack, etc.). - **GET** `get_event_notification` — Get a single event notification. - **POST** `create_event_notification` — Create an event notification. Config varies by type (email, http, slack, etc.). - **PUT** `update_event_notification` — Update an event notification. - **DELETE** `delete_event_notification` — Delete an event notification. - **POST** `test_event_notification` — Send a test notification to verify the notification configuration works. - **GET** `list_dashboards` — List all dashboards. - **GET** `list_views` — List saved Views. In Graylog 6 a "dashboard" and a "saved search" are both Views, distinguished by their type field (DASHBOARD / SEARCH). list_dashboards and list_saved_searches are the type-filtered convenience listings; this one returns both. Results are paginated under $.elements. - **GET** `get_view` — Get a single View by ID -- this is how you fetch ONE dashboard or ONE saved search. There is no /dashboards/{id} or /search/saved/{id} in Graylog 6: those paths fall through to the web UI and return HTML. Take the id from list_dashboards / list_saved_searches / list_views. - **GET** `list_users` — List all users including their roles, permissions, and preferences. - **GET** `get_user` — Get a user by username. - **POST** `create_user` — Create a new user. - **PUT** `update_user` — Update a user's details. - **DELETE** `delete_user` — Delete a user. Built-in admin user cannot be deleted. - **PUT** `change_user_password` — Change a user's password. - **PUT** `update_user_permissions` — Update a user's permissions. - **PUT** `update_user_preferences` — Update a user's UI preferences. - **GET** `list_user_tokens` — List all access tokens for a user. Token values are NOT returned -- only name, id, and last_access. - **POST** `create_user_token` — Create a new access token for a user. The token value is returned ONLY in this response. Store it immediately. Used for API auth: username=token_value, password="token". - **DELETE** `delete_user_token` — Delete/revoke an access token. - **GET** `list_roles` — List all roles with their permissions. - **GET** `get_role` — Get a role by name. - **POST** `create_role` — Create a new role. - **PUT** `update_role` — Update a role. - **DELETE** `delete_role` — Delete a role. Built-in roles (Admin, Reader) cannot be deleted. - **GET** `list_role_members` — List all users assigned to a role. - **PUT** `add_role_member` — Add a user to a role. - **DELETE** `remove_role_member` — Remove a user from a role. - **GET** `list_index_sets` — List all index sets. Each index set defines retention, rotation, and sharding for a group of indices. Every stream maps to one index set. - **GET** `get_index_set` — Get a single index set. - **POST** `create_index_set` — Create a new index set. - **PUT** `update_index_set` — Update an index set. - **DELETE** `delete_index_set` — Delete an index set. Optionally delete all associated indices. - **PUT** `set_default_index_set` — Set an index set as the default for new streams. - **GET** `get_index_set_stats` — Get statistics for all index sets (document count, size, segments). - **GET** `list_indices` — List all Elasticsearch/OpenSearch indices managed by Graylog. - **GET** `list_open_indices` — List all open (writable/searchable) indices. - **GET** `list_closed_indices` — List all closed indices. - **GET** `get_index` — Get details for a specific index. - **POST** `close_index` — Close an index. Closed indices cannot be searched but retain data. - **POST** `reopen_index` — Reopen a closed index. - **DELETE** `delete_index` — Delete an index. This permanently removes all data in the index. - **GET** `list_index_ranges` — List all index ranges (time boundaries for each index). - **POST** `rebuild_all_index_ranges` — Trigger a rebuild of all index ranges. Long-running operation. - **POST** `rebuild_index_range` — Rebuild index range for a specific index. - **GET** `get_deflector` — Get the current deflector (active write index) status. - **POST** `cycle_deflector` — Cycle the deflector -- close the current write index and create a new one. - **GET** `get_deflector_for_index_set` — Get the deflector for a specific index set. - **POST** `cycle_deflector_for_index_set` — Cycle the deflector for a specific index set. - **GET** `get_indexer_overview` — Get indexing overview with processing rates and counts. - **GET** `get_indexer_cluster_health` — Get Elasticsearch/OpenSearch cluster health (green/yellow/red). - **GET** `get_indexer_cluster_name` — Get the Elasticsearch/OpenSearch cluster name. - **GET** `list_indexer_failures` — List indexer failures (messages that could not be indexed). - **GET** `count_indexer_failures` — Total count of indexer failures since a given date. "since" is REQUIRED -- an ISO8601 timestamp; omitting it fails with HTTP 400 "FailuresResource.count.arg0 must not be empty". - **GET** `list_grok_patterns` — List all grok patterns used for message extraction. - **GET** `get_grok_pattern` — Get a single grok pattern. - **POST** `create_grok_pattern` — Create a new grok pattern. - **PUT** `update_grok_pattern` — Update a grok pattern. - **DELETE** `delete_grok_pattern` — Delete a grok pattern. - **POST** `test_grok_pattern` — Test a grok pattern against a sample string. - **GET** `list_lookup_tables` — List all lookup tables with their data adapter and cache references. - **GET** `get_lookup_table` — Get a lookup table by ID or name. - **POST** `create_lookup_table` — Create a lookup table. - **PUT** `update_lookup_table` — Update a lookup table. - **DELETE** `delete_lookup_table` — Delete a lookup table. - **GET** `list_lookup_adapters` — List all lookup data adapters. - **GET** `get_lookup_adapter` — Get a lookup data adapter by ID or name. - **POST** `create_lookup_adapter` — Create a lookup data adapter. - **PUT** `update_lookup_adapter` — Update a lookup data adapter. - **DELETE** `delete_lookup_adapter` — Delete a lookup data adapter. - **GET** `list_lookup_caches` — List all lookup caches. - **GET** `get_lookup_cache` — Get a lookup cache by ID or name. - **POST** `create_lookup_cache` — Create a lookup cache. - **PUT** `update_lookup_cache` — Update a lookup cache. - **DELETE** `delete_lookup_cache` — Delete a lookup cache. - **GET** `list_lookup_adapter_types` — List available data adapter types. - **GET** `list_lookup_cache_types` — List available cache types. - **GET** `list_outputs` — List all configured outputs. - **GET** `get_output` — Get a single output. - **POST** `create_output` — Create a new output. Use list_output_types to see available types. - **PUT** `update_output` — Update an output. - **DELETE** `delete_output` — Delete an output. - **GET** `list_output_types` — List available output types with their configuration schemas. - **GET** `list_content_packs` — List all content packs (bundles of inputs, streams, dashboards, etc.). - **GET** `get_content_pack` — Get a content pack with all its revisions. - **POST** `upload_content_pack` — Upload/create a content pack. - **DELETE** `delete_content_pack` — Delete a content pack. - **POST** `install_content_pack` — Install a specific revision of a content pack. - **GET** `list_content_pack_installations` — List all installations of a content pack. - **DELETE** `uninstall_content_pack` — Uninstall a content pack installation. - **GET** `list_sidecars` — List all registered sidecars. Sidecars are agents running on hosts that manage log collectors (Filebeat, Winlogbeat, NXLog). - **GET** `get_sidecar` — Get a single sidecar by ID. - **POST** `sidecar_administration` — Paginated sidecar listing including collector compatibility -- the data behind the Sidecar Administration page. This is a POST despite being a read: the filter is sent as a body. A body is REQUIRED; an empty request fails with HTTP 400 "administration.arg0 must not be null". Body fields: page, per_page, query (search over node_name, e.g. "status:running"), filters (map, e.g. { "status": "1" }). - **PUT** `bulk_sidecar_action` — Set collector actions (start / restart / stop) on sidecars in bulk. Returns HTTP 202 on success. Body: { action, collectors: [ { sidecar_id, collector_ids: [...] } ] } -- note the nested per-sidecar list; there is no flat sidecar_ids field. - **GET** `list_sidecar_collectors` — List all collector backends (Filebeat, Winlogbeat, NXLog definitions). - **GET** `get_sidecar_collector` — Get a collector backend definition. - **POST** `create_sidecar_collector` — Create a new collector backend definition. - **PUT** `update_sidecar_collector` — Update a collector backend definition. - **DELETE** `delete_sidecar_collector` — Delete a collector backend definition. - **GET** `list_sidecar_configurations` — List all sidecar configurations (collector config templates). - **GET** `get_sidecar_configuration` — Get a sidecar configuration. - **POST** `create_sidecar_configuration` — Create a sidecar configuration. - **PUT** `update_sidecar_configuration` — Update a sidecar configuration. - **DELETE** `delete_sidecar_configuration` — Delete a sidecar configuration. - **GET** `get_system` — Get system overview: node ID, hostname, version, lifecycle, LB status, timezone, OS info. - **GET** `get_system_stats` — Get node statistics (JVM memory, OS, process info). - **GET** `get_throughput` — Get current message throughput (messages per second). - **GET** `list_message_fields` — List all known message field names across all indices. - **GET** `list_system_permissions` — List all available system permission strings. - **POST** `pause_processing` — Pause message processing on this node. Messages will queue in the journal. - **POST** `resume_processing` — Resume message processing on this node. - **GET** `get_message_processor_config` — Get message processor ordering and configuration. - **PUT** `update_message_processor_config` — Update message processor ordering. - **GET** `get_journal` — Get journal (disk buffer) information: size, segments, uncommitted entries. - **GET** `get_lb_status` — Load-balancer status of this node as PLAIN TEXT, not JSON: "ALIVE" (HTTP 200), "DEAD" (HTTP 503) or "THROTTLED" (HTTP 429). The endpoint produces text/plain only -- leave the Accept parameter at its default; application/json returns HTTP 406. - **PUT** `override_lb_status` — Override the load balancer status. status must be ALIVE or DEAD. - **GET** `list_metrics` — List all internal metrics (JVM, processing, indexing, etc.). - **GET** `get_metric` — Get a specific metric by its full name. - **GET** `list_metric_names` — List all metric names. - **GET** `get_metrics_by_namespace` — Get all metrics in a namespace (e.g. org.graylog2.throughput). - **POST** `get_multiple_metrics` — Get multiple metrics at once by their names. - **GET** `list_system_notifications` — List system notifications (warnings about configuration issues, index problems, etc.). - **DELETE** `dismiss_system_notification` — Dismiss a system notification. - **GET** `list_loggers` — List all internal loggers and their current log levels. - **GET** `list_logger_subsystems` — List logger subsystems (high-level components with adjustable levels). - **PUT** `set_logger_level` — Set the log level for a specific logger. Levels: TRACE, DEBUG, INFO, WARN, ERROR. - **PUT** `set_subsystem_logger_level` — Set the log level for a logger subsystem. - **GET** `list_system_jobs` — List all running and completed system jobs. - **GET** `get_system_job` — Get a system job by ID. - **DELETE** `cancel_system_job` — Cancel a running system job. - **GET** `list_plugins` — List all installed plugins with name, version, author, and URL. - **POST** `create_session` — Create a session (login). Returns session_id and valid_until. For session-based auth: username=session_id, password="session". - **DELETE** `terminate_session` — Terminate a session (logout). - **GET** `get_cluster_config` — Get a cluster-wide configuration by class name. - **PUT** `update_cluster_config` — Update a cluster-wide configuration. - **DELETE** `delete_cluster_config` — Delete a cluster-wide configuration (reset to default). - **GET** `get_cluster` — Get system overview of all cluster nodes. - **GET** `list_cluster_input_states` — Get input states across all cluster nodes. - **GET** `list_cluster_jobs` — List running system jobs across all cluster nodes. - **POST** `get_cluster_metrics` — Get multiple metrics across all cluster nodes. - **GET** `get_cluster_node_jvm` — Get JVM information for a specific cluster node. - **GET** `get_cluster_node_journal` — Get journal info for a specific cluster node. - **GET** `get_cluster_node_thread_dump` — Get a thread dump for a specific cluster node. - **POST** `pause_cluster_node_processing` — Pause message processing on a specific cluster node. - **POST** `resume_cluster_node_processing` — Resume message processing on a specific cluster node. ## What composite workflows does the Graylog DADL provide? - **FN** `aggregate_by_field` — Top-N values for a single field within a time window. Returns [{key, count}] sorted desc. Server-side replacement for the deprecated search_relative_terms / search_absolute_terms endpoints (removed in Graylog 6.0). time_range is one of: {type:"absolute", from, to} {type:"relative", range} {type:"keyword", keyword} - **FN** `aggregate_pivot` — Multi-dimensional pivot (e.g. source x level). row_fields and column_fields are arrays of field names. Returns flat array of {row_keys, col_keys, count}. The canonical replacement for the Source x Level forensic matrix workflow. - **FN** `histogram_grouped` — Time-series histogram, optionally grouped by a field. interval is a Graylog timeunit: {quantity}{unit} with unit one of s m h d w M y -- e.g. 30s, 1m, 5m, 1h, 1d. That is the form to pass. ISO-8601 ("PT1M", "P1D") is also accepted and converted, because the underlying pivot rejects it with HTTP 400. Returns [{bucket_start, group_key|null, count}]. - **FN** `field_stats` — count, min, max, mean, cardinality for a numeric field. Replaces the removed _stats endpoints. - **FN** `search_messages_compact` — Search returning only {ts, src, lvl, msg} per message -- ~80 bytes/msg instead of ~500. Offset/limit pagination (Graylog's Views API does not support search_after on the messages search-type). Pass the next_offset returned by the previous call to fetch the next page. - **FN** `incident_window` — Forensic snapshot for a service-incident window. Returns {window, pivot_source_level, top_errors, baseline_pivot}. timestamp is ISO-8601, window_minutes default 6 (i.e. +/- 3 min). baseline_pivot covers the same-length window 1 hour earlier for comparison. ## Which DADLs are related to Graylog? - [Checkmk](https://www.dadl.ai/d/checkmk/) — Checkmk REST API (version 1.0, Checkmk 2.4) -- live host and service status via Livestatus queries, downtimes, acknowledgements and comments, the Event Console (list, acknowledge, change state and archive events) and BI (packs, rules, aggregations and live aggregation state), plus the full Setup side: hosts, clusters, folders, service discovery, rules and rulesets, host/service/contact groups, users, roles, passwords, time periods, host tags, notification rules, site connections and change activation. - [Opnsense](https://www.dadl.ai/d/opnsense/) — OPNsense firewall REST API — manage firewall rules, aliases, interfaces, VPN, DHCP, DNS, diagnostics, firmware, and services on OPNsense appliances - [PeeringDB](https://www.dadl.ai/d/peeringdb/) — PeeringDB v2 API -- the public peering database of networks (ASNs), Internet Exchanges, and colocation facilities: full CRUD over net, ix, fac, org, carrier, campus, point-of-contact records, and the netixlan/netfac/ixfac/carrierfac/ixlan/ixpfx relationships that map who peers where - [Xen Orchestra](https://www.dadl.ai/d/xen-orchestra/) — Xen Orchestra REST API (XO 6.4+, current through 6.9) -- complete coverage: VMs (incl. PATCH update + snapshot revert), VM controllers, hosts (incl. full power/lifecycle actions + maintenance mode + PIF rescan), pools (incl. add_host, rolling reboot/update with interrupted-update recovery + finalize), storage (SR create/delete, VDI incl. PATCH update + vhd/raw/qcow2 export, VBD), networks (VIF incl. PATCH update + PIF/PBD), VM/VDI snapshots, VM templates, hardware (PCI/PGPU/SM), tasks, backups (archives incl. live mount of backup disks, jobs/logs, repositories incl. health + benchmark + space reclaim), schedules, messages, alarms, events (SSE incl. non-XAPI collections), RBAC v2 (users/groups/acl-roles/acl-privileges incl. assignment introspection), proxies, servers, dashboards, SDN traffic rules (add/delete/update), IPMI sensor inventory (plugin), audit records (plugin), health check - [Zulip](https://www.dadl.ai/d/zulip/) — Zulip REST API — messages, channels (streams), topics, users, user groups, subscriptions, reactions, drafts, scheduled messages, saved snippets, presence, real-time events, invitations, attachments, custom emoji, linkifiers, and server settings. Self-hosted or Zulip Cloud. - [Alertmanager](https://www.dadl.ai/d/alertmanager/) — Prometheus Alertmanager API v2 -- alerts, silences, receivers, alert groups, status, and operational health --- **Canonical URL:** https://www.dadl.ai/d/graylog/ **Raw DADL:** https://github.com/DunkelCloud/dadl-registry/blob/main/graylog.dadl --- # Hacker News MCP Server — 10 tools via DADL The Hacker News DADL turns Hacker News's API into an MCP server that Claude, GPT or any MCP-compatible agent can consume directly. One YAML file declares all 10 tools — job, story, ask, best, item, max, and more — and ToolMesh serves them at runtime. No Python boilerplate, no per-endpoint code, no separate MCP server process. Below: the endpoint coverage matrix, a two-block ToolMesh setup, the full tool reference grouped by Hacker News feature area. **Source:** [Hacker News API (Firebase)](https://github.com/HackerNews/API) **Updated:** 2026-04-04 **Tags:** social-coding, crud, real-time, user-management, notifications, logging, auth:apikey ## Which Hacker News endpoints are covered? **100%** (11 of ~11 endpoints). **Focus:** items (stories, comments, polls, jobs), users, story feeds (top, new, best, ask, show, job), updates, max item ID **Missing:** none — full coverage of the public Firebase API *Last reviewed: 2026-04-04* ## How do you configure the Hacker News DADL? 1. No credentials required — the Hacker News API is fully public 2. No signup or API key needed [Authentication docs](https://github.com/HackerNews/API) *Completely public API — no authentication, no API keys, no rate limit headers. Be respectful with request volume. The API is backed by Firebase and returns JSON for all endpoints. Append .json to all paths. For real-time updates consider the Firebase SDK (Server-Sent Events) instead of polling. * ## How do you install the Hacker News MCP server with ToolMesh? Add to your `backends.yaml`: ```yaml - name: hackernews transport: rest dadl: hackernews.dadl url: "https://hacker-news.firebaseio.com/v0" ``` Set the credential: ``` CREDENTIAL_HACKERNEWS_TOKEN=your-token-here ``` ## What 10 tools does the Hacker News DADL expose? - **GET** `get_item` — Get any item by ID. Items are polymorphic — the "type" field indicates whether it is a story, comment, job, poll, or pollopt. Returns null for non-existent IDs. Key fields: id, type, by, time, text, url, score, title, kids (child comment IDs), parent, descendants (total comment count for stories), deleted, dead. - **GET** `get_user` — Get a user profile by username. Returns karma, creation date, about (HTML bio), and submitted (array of all item IDs the user has posted). Username is case-sensitive. Returns null for non-existent users. - **GET** `get_top_stories` — Get up to 500 top story IDs, ordered by ranking on the HN front page. Returns an array of integer item IDs — call get_item for full details. - **GET** `get_new_stories` — Get up to 500 newest story IDs, ordered by submission time (newest first). Returns an array of integer item IDs — call get_item for full details. - **GET** `get_best_stories` — Get up to 500 best story IDs (all-time highest-voted recent stories). Returns an array of integer item IDs — call get_item for full details. - **GET** `get_ask_stories` — Get up to 200 latest Ask HN story IDs. These are posts where users ask the HN community a question. Returns an array of integer item IDs. - **GET** `get_show_stories` — Get up to 200 latest Show HN story IDs. These are posts where users showcase their projects to the HN community. Returns an array of integer item IDs. - **GET** `get_job_stories` — Get up to 200 latest job posting IDs from the HN jobs board. Returns an array of integer item IDs. - **GET** `get_max_item` — Get the current largest item ID. Useful for polling: fetch items between your last known ID and max ID to catch new submissions. Returns a single integer. - **GET** `get_updates` — Get recently changed item IDs and user profiles. Returns an object with "items" (array of changed item IDs) and "profiles" (array of changed usernames). Useful for building a polling-based sync. ## What composite workflows does the Hacker News DADL provide? - **FN** `get_top_stories_full` — Get the top N stories with full item details (default: 10). Fetches story IDs then resolves each to its full item object. - **FN** `get_story_with_comments` — Get a story and its top-level comments resolved to full item objects. Returns the story with a 'comments' array containing the full comment items. - **FN** `get_user_stories` — Get a user's most recent stories (not comments). Fetches the user profile, then resolves their most recent submitted items and filters to type=story. Scans 20 recent submissions to stay within the 50-call sandbox limit — users who mostly post comments may return fewer stories than the limit. ## Which DADLs are related to Hacker News? - [Checkmk](https://www.dadl.ai/d/checkmk/) — Checkmk REST API (version 1.0, Checkmk 2.4) -- live host and service status via Livestatus queries, downtimes, acknowledgements and comments, the Event Console (list, acknowledge, change state and archive events) and BI (packs, rules, aggregations and live aggregation state), plus the full Setup side: hosts, clusters, folders, service discovery, rules and rulesets, host/service/contact groups, users, roles, passwords, time periods, host tags, notification rules, site connections and change activation. - [Mastodon](https://www.dadl.ai/d/mastodon/) — Mastodon REST API — statuses, timelines, accounts, notifications, search, media, lists, polls, conversations, trends, filters, and instance info. Base URL must be set to the target Mastodon instance (e.g. https://mastodon.social). - [Mempool](https://www.dadl.ai/d/mempool/) — mempool.space — Bitcoin block explorer, mempool visualizer, fee estimator, Lightning Network explorer, and transaction accelerator - [Zulip](https://www.dadl.ai/d/zulip/) — Zulip REST API — messages, channels (streams), topics, users, user groups, subscriptions, reactions, drafts, scheduled messages, saved snippets, presence, real-time events, invitations, attachments, custom emoji, linkifiers, and server settings. Self-hosted or Zulip Cloud. - [Alertmanager](https://www.dadl.ai/d/alertmanager/) — Prometheus Alertmanager API v2 -- alerts, silences, receivers, alert groups, status, and operational health - [Billomat](https://www.dadl.ai/d/billomat/) — Billomat REST API — German cloud invoicing & accounting: invoices, estimates, credit notes, recurring invoices, delivery notes, order confirmations, dunning reminders, clients, contacts, articles, payments, expenses, taxes --- **Canonical URL:** https://www.dadl.ai/d/hackernews/ **Raw DADL:** https://github.com/DunkelCloud/dadl-registry/blob/main/hackernews.dadl --- # Hetzner Cloud MCP Server — 123 tools via DADL The Hetzner Cloud DADL turns Hetzner Cloud's API into an MCP server that Claude, GPT or any MCP-compatible agent can consume directly. One YAML file declares all 123 tools — server, load, floating, primary, volume, firewall, and more — and ToolMesh serves them at runtime. No Python boilerplate, no per-endpoint code, no separate MCP server process. Below: the endpoint coverage matrix, a two-block ToolMesh setup, the full tool reference grouped by Hetzner Cloud feature area, required credential scopes. **Source:** [Hetzner Cloud API](https://docs.hetzner.cloud) **Updated:** 2026-04-01 **Tags:** cloud, devops, security, crud, metrics, file-management, auth:bearer ## Which Hetzner Cloud endpoints are covered? **61%** (122 of ~200 endpoints). **Focus:** servers, server actions, server metrics, volumes, networks, firewalls, load balancers, load balancer metrics, floating IPs, primary IPs, images, SSH keys, placement groups, certificates, datacenters, locations, server types, ISOs, pricing **Missing:** storage boxes (separate API at api.hetzner.com), DNS zones/rrsets (separate API), S3 credential management *Last reviewed: 2026-04-01* ## How do you configure the Hetzner Cloud DADL? 1. Log in to Hetzner Cloud Console at https://console.hetzner.cloud 2. Select or create a project 3. Navigate to Security -> API Tokens 4. Click 'Generate API Token' 5. Enter a description and select Read or Read & Write permissions 6. Copy the token immediately -- it is shown only once **Environment variable:** `CREDENTIAL_HETZNER_CLOUD_TOKEN` [Authentication docs](https://docs.hetzner.com/cloud/api/getting-started/generating-api-token/) *API tokens are scoped to a single project. To manage multiple projects, create one token per project. Tokens have either Read or Read & Write permission -- there are no per-resource scopes.* ## How do you install the Hetzner Cloud MCP server with ToolMesh? Add to your `backends.yaml`: ```yaml - name: hetzner-cloud transport: rest dadl: /app/dadl/hetzner-cloud.dadl ``` Set the credential: ``` CREDENTIAL_HETZNER_CLOUD_TOKEN=your-token-here ``` ## What 123 tools does the Hetzner Cloud DADL expose? - **GET** `list_servers` — List all servers. Supports label_selector, name, sort, and status filtering. - **GET** `get_server` — Get details of a specific server - **POST** `create_server` — Create a new server. Returns server object and root_password (if no SSH keys). Action is async -- poll the returned action. - **PUT** `update_server` — Update a server's name or labels - **DELETE** `delete_server` — Delete a server immediately. All data on the server is lost. Irreversible. - **POST** `power_on_server` — Power on a server - **POST** `power_off_server` — Hard power off a server (like pulling the power cord). Use shutdown for graceful stop. - **POST** `reboot_server` — Soft reboot a server (sends ACPI signal) - **POST** `reset_server` — Hard reset a server (like pressing the reset button). Use reboot for graceful restart. - **POST** `shutdown_server` — Gracefully shut down a server (sends ACPI shutdown signal) - **POST** `enable_rescue_server` — Enable rescue mode. Returns root_password for the rescue system. Reboot to enter rescue. - **POST** `disable_rescue_server` — Disable rescue mode - **POST** `rebuild_server` — Rebuild a server from an image. All data is destroyed. Irreversible. - **POST** `change_server_type` — Change server type (resize). Server must be off. Disk can only be upgraded, not downgraded. - **POST** `create_image_from_server` — Create a snapshot image from a server - **POST** `attach_iso_to_server` — Attach an ISO to a server - **POST** `detach_iso_from_server` — Detach any ISO from a server - **POST** `change_server_protection` — Change delete and rebuild protection for a server - **POST** `change_server_dns_ptr` — Change reverse DNS entry for a server IP - **POST** `attach_server_to_network` — Attach a server to a network - **POST** `detach_server_from_network` — Detach a server from a network - **POST** `enable_server_backup` — Enable automatic backups for a server - **POST** `disable_server_backup` — Disable automatic backups for a server. Existing backups are kept until their expiry. - **POST** `add_server_to_placement_group` — Add a server to a placement group. Server must be stopped. - **POST** `remove_server_from_placement_group` — Remove a server from its placement group - **GET** `list_server_actions` — List all actions for a server - **GET** `get_server_action` — Get details of a specific server action - **GET** `get_server_metrics` — Get metrics (time series) for a server. Returns Prometheus-style data points for the requested metric types within the given time range. - **GET** `get_load_balancer_metrics` — Get metrics for a load balancer. Returns time series for open connections, connections/s, requests/s, and bandwidth. - **GET** `list_volumes` — List all volumes - **GET** `get_volume` — Get details of a specific volume - **POST** `create_volume` — Create a new volume. Set server to auto-attach, or leave unattached. - **PUT** `update_volume` — Update a volume's name or labels - **DELETE** `delete_volume` — Delete a volume. Must be detached first. - **POST** `attach_volume` — Attach a volume to a server - **POST** `detach_volume` — Detach a volume from a server - **POST** `resize_volume` — Resize a volume. Can only increase size, not decrease. - **POST** `change_volume_protection` — Change delete protection for a volume - **GET** `list_networks` — List all networks - **GET** `get_network` — Get details of a specific network - **POST** `create_network` — Create a new network with an RFC 1918 IP range - **PUT** `update_network` — Update a network's name or labels - **DELETE** `delete_network` — Delete a network. All subnets and routes are removed. - **POST** `add_subnet_to_network` — Add a subnet to a network - **POST** `delete_subnet_from_network` — Delete a subnet from a network - **POST** `add_route_to_network` — Add a route to a network - **POST** `delete_route_from_network` — Delete a route from a network - **POST** `change_network_protection` — Change delete protection for a network - **GET** `list_firewalls` — List all firewalls - **GET** `get_firewall` — Get details of a specific firewall including its rules - **POST** `create_firewall` — Create a new firewall with optional initial rules and resource assignments - **PUT** `update_firewall` — Update a firewall's name or labels - **DELETE** `delete_firewall` — Delete a firewall. Must be unapplied from all resources first. - **POST** `set_firewall_rules` — Overwrite all rules of a firewall. This replaces all existing rules. - **POST** `apply_firewall_to_resources` — Apply a firewall to servers or label selectors - **POST** `remove_firewall_from_resources` — Remove a firewall from servers or label selectors - **GET** `list_load_balancers` — List all load balancers - **GET** `get_load_balancer` — Get details of a specific load balancer - **POST** `create_load_balancer` — Create a new load balancer - **PUT** `update_load_balancer` — Update a load balancer's name or labels - **DELETE** `delete_load_balancer` — Delete a load balancer - **POST** `add_load_balancer_service` — Add a service (listener) to a load balancer - **POST** `update_load_balancer_service` — Update a service on a load balancer - **POST** `delete_load_balancer_service` — Delete a service from a load balancer - **POST** `add_load_balancer_target` — Add a target to a load balancer - **POST** `remove_load_balancer_target` — Remove a target from a load balancer - **POST** `change_load_balancer_type` — Change the type of a load balancer - **POST** `change_load_balancer_protection` — Change delete protection for a load balancer - **POST** `attach_load_balancer_to_network` — Attach a load balancer to a network - **POST** `detach_load_balancer_from_network` — Detach a load balancer from a network - **POST** `change_load_balancer_algorithm` — Change the balancing algorithm - **POST** `change_load_balancer_dns_ptr` — Change reverse DNS entry for a load balancer IP - **GET** `list_floating_ips` — List all floating IPs - **GET** `get_floating_ip` — Get details of a specific floating IP - **POST** `create_floating_ip` — Create a new floating IP - **PUT** `update_floating_ip` — Update a floating IP's name, description, or labels - **DELETE** `delete_floating_ip` — Delete a floating IP. Must be unassigned first. - **POST** `assign_floating_ip` — Assign a floating IP to a server - **POST** `unassign_floating_ip` — Unassign a floating IP from a server - **POST** `change_floating_ip_protection` — Change delete protection for a floating IP - **POST** `change_floating_ip_dns_ptr` — Change reverse DNS entry for a floating IP - **GET** `list_primary_ips` — List all primary IPs - **GET** `get_primary_ip` — Get details of a specific primary IP - **POST** `create_primary_ip` — Create a new primary IP - **PUT** `update_primary_ip` — Update a primary IP's name, labels, or auto_delete setting - **DELETE** `delete_primary_ip` — Delete a primary IP. Must be unassigned first. - **POST** `assign_primary_ip` — Assign a primary IP to a server - **POST** `unassign_primary_ip` — Unassign a primary IP from a server - **POST** `change_primary_ip_protection` — Change delete protection for a primary IP - **POST** `change_primary_ip_dns_ptr` — Change reverse DNS entry for a primary IP - **GET** `list_images` — List all images (system, snapshot, backup, app) - **GET** `get_image` — Get details of a specific image - **PUT** `update_image` — Update an image's description, type, or labels. Only for snapshot/backup images. - **DELETE** `delete_image` — Delete an image. Only snapshot and backup images can be deleted. - **POST** `change_image_protection` — Change delete protection for an image - **GET** `list_ssh_keys` — List all SSH keys - **GET** `get_ssh_key` — Get details of a specific SSH key - **POST** `create_ssh_key` — Create (upload) a new SSH key - **PUT** `update_ssh_key` — Update an SSH key's name or labels - **DELETE** `delete_ssh_key` — Delete an SSH key - **GET** `list_certificates` — List all certificates - **GET** `get_certificate` — Get details of a specific certificate - **POST** `create_certificate` — Create a certificate (upload or request managed via Let's Encrypt) - **PUT** `update_certificate` — Update a certificate's name or labels - **DELETE** `delete_certificate` — Delete a certificate - **GET** `list_placement_groups` — List all placement groups - **GET** `get_placement_group` — Get details of a specific placement group - **POST** `create_placement_group` — Create a new placement group - **PUT** `update_placement_group` — Update a placement group's name or labels - **DELETE** `delete_placement_group` — Delete a placement group. Must have no servers assigned. - **GET** `list_actions` — List all actions across all resources - **GET** `get_action` — Get details of a specific action - **GET** `list_server_types` — List all available server types with specs and pricing - **GET** `get_server_type` — Get details of a specific server type - **GET** `list_locations` — List all available locations - **GET** `get_location` — Get details of a specific location - **GET** `list_datacenters` — List all available datacenters - **GET** `get_datacenter` — Get details of a specific datacenter - **GET** `list_isos` — List all available ISO images - **GET** `get_iso` — Get details of a specific ISO image - **GET** `list_load_balancer_types` — List all available load balancer types - **GET** `get_load_balancer_type` — Get details of a specific load balancer type - **GET** `get_pricing` — Get all pricing information for server types, images, volumes, floating IPs, load balancers, and traffic ## Which DADLs are related to Hetzner Cloud? - [NetBox](https://www.dadl.ai/d/netbox/) — NetBox DCIM/IPAM API -- full v4 coverage: sites, racks, devices, modules, interfaces, cables, power, IPAM (prefixes, IPs, VLANs, VRFs, route-targets, VLAN translation), virtualization, circuits (including virtual circuits), tenants, contacts, VPN (IKE/IPSec/L2VPN), wireless, extras (webhooks, event-rules, scripts, config-templates, bookmarks, notifications), users/permissions/tokens, and core data sources & jobs - [Tailscale](https://www.dadl.ai/d/tailscale/) — Tailscale API -- devices, users, auth keys, DNS, ACL/policy, webhooks, contacts, posture integrations, log streaming, and tailnet settings - [Xen Orchestra](https://www.dadl.ai/d/xen-orchestra/) — Xen Orchestra REST API (XO 6.4+, current through 6.9) -- complete coverage: VMs (incl. PATCH update + snapshot revert), VM controllers, hosts (incl. full power/lifecycle actions + maintenance mode + PIF rescan), pools (incl. add_host, rolling reboot/update with interrupted-update recovery + finalize), storage (SR create/delete, VDI incl. PATCH update + vhd/raw/qcow2 export, VBD), networks (VIF incl. PATCH update + PIF/PBD), VM/VDI snapshots, VM templates, hardware (PCI/PGPU/SM), tasks, backups (archives incl. live mount of backup disks, jobs/logs, repositories incl. health + benchmark + space reclaim), schedules, messages, alarms, events (SSE incl. non-XAPI collections), RBAC v2 (users/groups/acl-roles/acl-privileges incl. assignment introspection), proxies, servers, dashboards, SDN traffic rules (add/delete/update), IPMI sensor inventory (plugin), audit records (plugin), health check - [Billomat](https://www.dadl.ai/d/billomat/) — Billomat REST API — German cloud invoicing & accounting: invoices, estimates, credit notes, recurring invoices, delivery notes, order confirmations, dunning reminders, clients, contacts, articles, payments, expenses, taxes - [Cloudflare](https://www.dadl.ai/d/cloudflare/) — Cloudflare API -- DNS, Pages, Workers, KV, R2, D1, Zones, SSL/TLS, Cache, Load Balancers, Firewall/WAF, Page Rules, Access (Zero Trust), Email Routing, Email Sending, DMARC/SPF email auth, and account management - [DeepL](https://www.dadl.ai/d/deepl/) — DeepL REST API — text translation (with style profiles, translation memory, glossaries and improved tag handling), document translation, multilingual glossary management, style rules CRUD, text improvement (Write), language metadata and usage tracking. Mixes /v2 and /v3 endpoints. --- **Canonical URL:** https://www.dadl.ai/d/hetzner-cloud/ **Raw DADL:** https://github.com/DunkelCloud/dadl-registry/blob/main/hetzner-cloud.dadl --- # Linode MCP Server — 182 tools via DADL The Linode DADL turns Linode's API into an MCP server that Claude, GPT or any MCP-compatible agent can consume directly. One YAML file declares all 182 tools — linode, lke, nodebalancer, domain, firewall, volume, and more — and ToolMesh serves them at runtime. No Python boilerplate, no per-endpoint code, no separate MCP server process. Below: the endpoint coverage matrix, a two-block ToolMesh setup, the full tool reference grouped by Linode feature area, required credential scopes. **Source:** [Linode REST API v4](https://techdocs.akamai.com/linode-api/reference/api) **Updated:** 2026-10-15 **Tags:** cloud, dns, storage, databases, containers, networking, crud, authentication, auth:bearer ## Which Linode endpoints are covered? **34%** (182 of ~539 endpoints). **Focus:** linodes, volumes, domains, nodebalancers, firewalls, VPCs, LKE, databases, object storage, images, stackscripts, regions, account, profile, events, tags **Missing:** longview, managed services, monitor, IAM/delegation, service transfers, beta programs, placement groups, support ticket write operations (open, reply, close, attachments) *Last reviewed: 2026-10-15* ## How do you configure the Linode DADL? 1. Log in to Linode Cloud Manager at https://cloud.linode.com 2. Navigate to your profile icon (top right) → API Tokens 3. Click 'Create a Personal Access Token' 4. Set a label, expiry, and select scopes (Read/Write per category) 5. Copy the token immediately -- it is shown only once **Environment variable:** `CREDENTIAL_LINODE_TOKEN` [Authentication docs](https://techdocs.akamai.com/linode-api/reference/get-started) *Personal Access Tokens (PATs) are the simplest auth method. OAuth2 is also supported for third-party apps. Scopes are per-category with read_only or read_write levels.* ## How do you install the Linode MCP server with ToolMesh? Add to your `backends.yaml`: ```yaml - name: linode transport: rest dadl: linode.dadl ``` Set the credential: ``` CREDENTIAL_LINODE_TOKEN=your-token-here ``` ## What 182 tools does the Linode DADL expose? - **GET** `list_linodes` — List all Linode instances. Supports X-Filter header for filtering by region, status, tags, etc. - **GET** `get_linode` — Get details of a specific Linode instance - **POST** `create_linode` — Create a new Linode instance. Requires region and type. Set image to auto-provision and boot. - **PUT** `update_linode` — Update a Linode's label, tags, alerts, backups schedule, or watchdog - **DELETE** `delete_linode` — Delete a Linode instance and all associated disks and IPs. Irreversible. - **POST** `boot_linode` — Boot a Linode instance - **POST** `reboot_linode` — Reboot a Linode instance - **POST** `shutdown_linode` — Shut down a Linode instance - **POST** `rebuild_linode` — Rebuild a Linode from an image. Destroys all existing disks. Irreversible. - **POST** `resize_linode` — Resize a Linode to a new plan type. Powers off the instance during resize. - **POST** `clone_linode` — Clone a Linode to a new instance - **POST** `migrate_linode` — Initiate a DC migration or accept a pending host migration - **POST** `reset_linode_password` — Reset the root password for a Linode. Instance must be powered off. - **POST** `rescue_linode` — Boot a Linode into rescue mode with optional device mappings - **GET** `list_linode_disks` — List disks for a Linode - **GET** `get_linode_disk` — Get a specific disk - **POST** `create_linode_disk` — Create a new disk for a Linode - **PUT** `update_linode_disk` — Update a disk's label - **DELETE** `delete_linode_disk` — Delete a disk - **POST** `resize_linode_disk` — Resize a disk. Linode must be powered off. - **GET** `get_linode_ips` — Get all networking information (IPv4, IPv6) for a Linode - **POST** `allocate_linode_ip` — Allocate an additional IPv4 address for a Linode - **GET** `list_linode_backups` — List backups for a Linode (automatic daily/weekly + manual snapshots) - **POST** `create_linode_snapshot` — Create a manual snapshot backup - **GET** `get_linode_backup` — Get a specific backup - **POST** `restore_linode_backup` — Restore a backup to a Linode - **POST** `enable_linode_backups` — Enable the backups service for a Linode - **POST** `cancel_linode_backups` — Cancel the backups service for a Linode. All backups are deleted. - **GET** `get_linode_stats` — Get CPU, IO, network, and netv6 stats for the current month - **GET** `get_linode_stats_by_month` — Get statistics for a specific year/month - **GET** `get_linode_transfer` — Get network transfer usage for the current month - **GET** `list_linode_types` — List available Linode instance types (plans) with pricing and specs - **GET** `get_linode_type` — Get a specific instance type by slug - **GET** `list_kernels` — List available kernels - **GET** `list_volumes` — List all block storage volumes - **GET** `get_volume` — Get a specific volume - **POST** `create_volume` — Create a block storage volume. Set linode_id to auto-attach. - **PUT** `update_volume` — Update a volume's label or tags - **DELETE** `delete_volume` — Delete a volume. Must be detached first. - **POST** `attach_volume` — Attach a volume to a Linode - **POST** `detach_volume` — Detach a volume from its Linode - **POST** `resize_volume` — Resize a volume. Can only increase size. - **POST** `clone_volume` — Clone a volume - **GET** `list_domains` — List all domains - **GET** `get_domain` — Get a specific domain - **POST** `create_domain` — Create a domain (DNS zone) - **PUT** `update_domain` — Update a domain - **DELETE** `delete_domain` — Delete a domain and all its records - **GET** `list_domain_records` — List DNS records for a domain - **GET** `get_domain_record` — Get a specific DNS record - **POST** `create_domain_record` — Create a DNS record (A, AAAA, CNAME, MX, TXT, SRV, NS, CAA) - **PUT** `update_domain_record` — Update a DNS record - **DELETE** `delete_domain_record` — Delete a DNS record - **GET** `list_nodebalancers` — List all NodeBalancers - **GET** `get_nodebalancer` — Get a specific NodeBalancer - **POST** `create_nodebalancer` — Create a NodeBalancer - **PUT** `update_nodebalancer` — Update a NodeBalancer's label, throttle, or tags - **DELETE** `delete_nodebalancer` — Delete a NodeBalancer - **GET** `list_nodebalancer_configs` — List configs (ports) for a NodeBalancer - **POST** `create_nodebalancer_config` — Create a NodeBalancer config (listener port) - **PUT** `update_nodebalancer_config` — Update a NodeBalancer config - **DELETE** `delete_nodebalancer_config` — Delete a NodeBalancer config - **GET** `list_nodebalancer_nodes` — List backend nodes for a NodeBalancer config - **POST** `create_nodebalancer_node` — Add a backend node to a NodeBalancer config - **PUT** `update_nodebalancer_node` — Update a backend node - **DELETE** `delete_nodebalancer_node` — Remove a backend node - **GET** `list_firewalls` — List all firewalls - **GET** `get_firewall` — Get a specific firewall - **POST** `create_firewall` — Create a firewall with inbound/outbound rules - **PUT** `update_firewall` — Update a firewall's label, tags, or status - **DELETE** `delete_firewall` — Delete a firewall - **GET** `get_firewall_rules` — Get the current rules for a firewall - **PUT** `update_firewall_rules` — Replace all rules for a firewall - **GET** `list_firewall_devices` — List devices (Linodes, NodeBalancers) attached to a firewall - **POST** `create_firewall_device` — Attach a device to a firewall - **DELETE** `delete_firewall_device` — Detach a device from a firewall - **GET** `list_ip_addresses` — List all IP addresses on the account - **GET** `get_ip_address` — Get info about an IP address - **PUT** `update_ip_rdns` — Update reverse DNS for an IP address - **POST** `allocate_ip` — Allocate a new IP address - **GET** `list_ipv6_ranges` — List all IPv6 ranges - **GET** `list_vlans` — List all VLANs on the account - **GET** `list_vpcs` — List all VPCs - **GET** `get_vpc` — Get a specific VPC - **POST** `create_vpc` — Create a VPC - **PUT** `update_vpc` — Update a VPC's label or description - **DELETE** `delete_vpc` — Delete a VPC. All subnets must be empty. - **GET** `list_vpc_subnets` — List subnets in a VPC - **POST** `create_vpc_subnet` — Create a subnet in a VPC - **PUT** `update_vpc_subnet` — Update a subnet's label - **DELETE** `delete_vpc_subnet` — Delete a subnet. Must have no attached Linodes. - **GET** `list_lke_clusters` — List all LKE (Linode Kubernetes Engine) clusters - **GET** `get_lke_cluster` — Get a specific LKE cluster - **POST** `create_lke_cluster` — Create an LKE cluster - **PUT** `update_lke_cluster` — Update an LKE cluster's label, k8s_version, tags, or control plane - **DELETE** `delete_lke_cluster` — Delete an LKE cluster and all associated node pools - **GET** `get_lke_kubeconfig` — Get the base64-encoded kubeconfig for a cluster - **GET** `get_lke_dashboard` — Get the Kubernetes dashboard URL - **GET** `list_lke_api_endpoints` — List API server endpoints for a cluster - **POST** `recycle_lke_cluster` — Recycle (replace) all nodes in the cluster - **GET** `list_lke_node_pools` — List node pools in an LKE cluster - **GET** `get_lke_node_pool` — Get a specific node pool - **POST** `create_lke_node_pool` — Add a node pool to an LKE cluster - **PUT** `update_lke_node_pool` — Update a node pool's count, autoscaler, labels, or taints - **DELETE** `delete_lke_node_pool` — Delete a node pool - **POST** `recycle_lke_node_pool` — Recycle (replace) all nodes in a pool - **GET** `list_lke_versions` — List available Kubernetes versions for LKE - **GET** `list_databases` — List all managed database instances (MySQL, PostgreSQL) - **GET** `list_database_engines` — List available database engines and versions - **GET** `list_database_types` — List available database types (plans) with pricing - **GET** `list_mysql_databases` — List all MySQL managed databases - **GET** `get_mysql_database` — Get a specific MySQL database - **POST** `create_mysql_database` — Create a managed MySQL database - **PUT** `update_mysql_database` — Update a MySQL database's label, allow_list, or updates config - **DELETE** `delete_mysql_database` — Delete a MySQL database - **GET** `get_mysql_credentials` — Get connection credentials (username, password) for a MySQL database - **POST** `reset_mysql_credentials` — Reset the root password for a MySQL database - **GET** `get_mysql_ssl` — Get the SSL CA certificate for a MySQL database - **POST** `patch_mysql_database` — Apply the latest patch to a MySQL database - **GET** `list_postgresql_databases` — List all PostgreSQL managed databases - **GET** `get_postgresql_database` — Get a specific PostgreSQL database - **POST** `create_postgresql_database` — Create a managed PostgreSQL database - **PUT** `update_postgresql_database` — Update a PostgreSQL database - **DELETE** `delete_postgresql_database` — Delete a PostgreSQL database - **GET** `get_postgresql_credentials` — Get connection credentials for a PostgreSQL database - **POST** `reset_postgresql_credentials` — Reset the root password for a PostgreSQL database - **GET** `list_object_storage_buckets` — List all Object Storage buckets - **GET** `get_object_storage_bucket` — Get a specific bucket - **POST** `create_object_storage_bucket` — Create an Object Storage bucket - **DELETE** `delete_object_storage_bucket` — Delete an Object Storage bucket. Must be empty. - **GET** `list_object_storage_bucket_contents` — List objects in a bucket - **POST** `create_object_storage_object_url` — Create a pre-signed URL for upload or download - **GET** `list_object_storage_keys` — List S3-compatible access keys - **POST** `create_object_storage_key` — Create an S3-compatible access key - **DELETE** `delete_object_storage_key` — Revoke an S3-compatible access key - **GET** `list_object_storage_clusters` — List Object Storage cluster/region endpoints - **GET** `list_images` — List all images (official + custom). Rate limited to 20 req/min. - **GET** `get_image` — Get a specific image - **POST** `create_image` — Create a custom image from an existing Linode disk - **PUT** `update_image` — Update an image's label, description, or tags - **DELETE** `delete_image` — Delete a custom image - **POST** `upload_image` — Get a URL for uploading a machine image (raw or gzip compressed) - **POST** `replicate_image` — Replicate a custom image to additional regions - **GET** `list_stackscripts` — List StackScripts (yours + community). Rate limited to 60 req/min. - **GET** `get_stackscript` — Get a specific StackScript - **POST** `create_stackscript` — Create a StackScript - **PUT** `update_stackscript` — Update a StackScript - **DELETE** `delete_stackscript` — Delete a StackScript - **GET** `list_regions` — List all available regions with capabilities and status - **GET** `get_region` — Get a specific region - **GET** `get_region_availability` — Get compute type availability for a region - **GET** `list_tags` — List all tags - **POST** `create_tag` — Create a tag and optionally attach it to resources - **DELETE** `delete_tag` — Delete a tag from all resources - **GET** `list_events` — List account events (create, delete, boot, etc.) - **GET** `get_event` — Get a specific event - **POST** `mark_event_seen` — Mark an event as seen - **POST** `mark_event_read` — Mark an event as read - **GET** `get_account` — Get account contact and billing info - **GET** `get_account_settings` — Get account-wide settings (managed, backups defaults, network helper) - **PUT** `update_account_settings` — Update account settings - **GET** `get_account_transfer` — Get network transfer pool usage for the current month - **GET** `list_users` — List account users - **GET** `get_user` — Get a specific user - **POST** `create_user` — Create a new user on the account - **PUT** `update_user` — Update a user - **DELETE** `delete_user` — Delete a user from the account - **GET** `get_user_grants` — Get permissions/grants for a restricted user - **PUT** `update_user_grants` — Update permissions/grants for a restricted user - **GET** `list_support_tickets` — List support tickets of the account: tickets you opened and tickets Linode support opened about your account. Open tickets come first. Each ticket has id, summary, description, status (new, open, closed), severity, opened, opened_by, updated, updated_by, closed, closable, attachments (filenames) and entity (type, id, label of the affected object, or null). Replies are not included; call list_support_ticket_replies for the conversation. Filter with the X-Filter param, a JSON string sent as the X-Filter header, e.g. '{"status": "open"}' or '{"+order_by": "updated", "+order": "desc"}'. Filterable fields: status, opened, opened_by, updated, closed. Needs token scope account:read_only. - **GET** `get_support_ticket` — Get one support ticket by ID: summary, description (the opening message), status (new, open, closed), severity, entity, opened/updated/closed timestamps and attachment filenames. The replies are not included; call list_support_ticket_replies with the same ticketId. Needs token scope account:read_only. - **GET** `list_support_ticket_replies` — List the replies of a support ticket. Each reply has id, created, created_by, description (the message body) and from_linode (true when a Linode employee wrote it). The ticket's opening message is not a reply; it is the description returned by get_support_ticket. Needs token scope account:read_only. - **GET** `get_profile` — Get the current user's profile - **PUT** `update_profile` — Update the current user's profile - **GET** `list_ssh_keys` — List SSH keys on the current user's profile - **GET** `get_ssh_key` — Get a specific SSH key - **POST** `create_ssh_key` — Add an SSH key to the profile - **PUT** `update_ssh_key` — Update an SSH key's label - **DELETE** `delete_ssh_key` — Remove an SSH key from the profile - **GET** `list_tokens` — List personal access tokens - **POST** `create_token` — Create a personal access token - **DELETE** `delete_token` — Revoke a personal access token ## Which DADLs are related to Linode? - [Cloudflare](https://www.dadl.ai/d/cloudflare/) — Cloudflare API -- DNS, Pages, Workers, KV, R2, D1, Zones, SSL/TLS, Cache, Load Balancers, Firewall/WAF, Page Rules, Access (Zero Trust), Email Routing, Email Sending, DMARC/SPF email auth, and account management - [Tailscale](https://www.dadl.ai/d/tailscale/) — Tailscale API -- devices, users, auth keys, DNS, ACL/policy, webhooks, contacts, posture integrations, log streaming, and tailnet settings - [Mikrotik](https://www.dadl.ai/d/mikrotik/) — MikroTik RouterOS REST API -- manage interfaces, IP addresses, routing, firewall, DHCP, DNS, PPP, queues, wireless, system configuration, users, certificates, files, logs, and diagnostics on RouterOS v7.1+ devices - [NetBox](https://www.dadl.ai/d/netbox/) — NetBox DCIM/IPAM API -- full v4 coverage: sites, racks, devices, modules, interfaces, cables, power, IPAM (prefixes, IPs, VLANs, VRFs, route-targets, VLAN translation), virtualization, circuits (including virtual circuits), tenants, contacts, VPN (IKE/IPSec/L2VPN), wireless, extras (webhooks, event-rules, scripts, config-templates, bookmarks, notifications), users/permissions/tokens, and core data sources & jobs - [PeeringDB](https://www.dadl.ai/d/peeringdb/) — PeeringDB v2 API -- the public peering database of networks (ASNs), Internet Exchanges, and colocation facilities: full CRUD over net, ix, fac, org, carrier, campus, point-of-contact records, and the netixlan/netfac/ixfac/carrierfac/ixlan/ixpfx relationships that map who peers where - [Shelly Cloud](https://www.dadl.ai/d/shelly-cloud/) — Shelly Cloud Control API — monitor and control Shelly IoT devices (switches, covers, lights) via the Shelly Cloud --- **Canonical URL:** https://www.dadl.ai/d/linode/ **Raw DADL:** https://github.com/DunkelCloud/dadl-registry/blob/main/linode.dadl --- # Mastodon MCP Server — 115 tools via DADL The Mastodon DADL turns Mastodon's API into an MCP server that Claude, GPT or any MCP-compatible agent can consume directly. One YAML file declares all 115 tools — status, account, filter, instance, featured, notification, and more — and ToolMesh serves them at runtime. No Python boilerplate, no per-endpoint code, no separate MCP server process. Below: the endpoint coverage matrix, a two-block ToolMesh setup, the full tool reference grouped by Mastodon feature area, required credential scopes. **Source:** [Mastodon REST API v1/v2](https://docs.joinmastodon.org/api/) **Updated:** 2026-04-08 **Tags:** social-coding, crud, notifications, user-management, search, media, real-time, translation, auth:bearer ## Which Mastodon endpoints are covered? **86%** (112 of ~130 endpoints). **Focus:** accounts (lookup + verify + follow/unfollow + mute/block + relationships + search), statuses (CRUD + favourite + reblog + bookmark + pin + context + translate), timelines (home + public + hashtag + list), notifications (list + dismiss + clear + unread count), search (v2 full-text), media (upload + update), lists (CRUD + members), polls (view + vote), conversations (list + read + delete), trends (tags + statuses + links), filters v2 (CRUD + keywords), bookmarks, favourites, mutes, blocks, follow requests, suggestions, instance info, scheduled statuses (CRUD), markers (get + save), reports (create), featured tags (CRUD + suggestions), announcements (list + dismiss), endorsements, preferences, admin accounts (list + get + approve + reject + action + unsuspend + unsilence), admin domain blocks (CRUD) **Missing:** streaming WebSocket, email confirmations, canonical email blocks, ip blocks, dimensions, measures, retention, trends admin, admin reports, admin audit log *Last reviewed: 2026-04-09* ## How do you configure the Mastodon DADL? 1. Open your Mastodon instance (e.g. https://mastodon.social) 2. Go to Preferences → Development → New Application 3. Enter an application name (e.g. 'ToolMesh') 4. Select required scopes: read, write (or granular scopes as needed) 5. Click 'Submit' to create the application 6. Copy the 'Your access token' value — this is your Bearer token **Environment variable:** `CREDENTIAL_MASTODON_ACCESS_TOKEN` [Authentication docs](https://docs.joinmastodon.org/client/token/) *The base_url must be set to the user's Mastodon instance. Each instance is independent — tokens from mastodon.social do not work on other instances. For app-level access (public data only), use OAuth2 client_credentials grant. For user-level access, use the authorization_code grant or generate a token via the web UI under Preferences → Development.* ## How do you install the Mastodon MCP server with ToolMesh? Add to your `backends.yaml`: ```yaml - name: mastodon transport: rest dadl: mastodon.dadl url: "https://mastodon.social" ``` Set the credential: ``` CREDENTIAL_MASTODON_ACCESS_TOKEN=your-token-here ``` ## What 115 tools does the Mastodon DADL expose? - **GET** `get_instance` — Get server information including version, configuration, usage stats, rules, and supported features - **GET** `get_instance_peers` — List domains that this instance is aware of (connected via federation) - **GET** `get_instance_activity` — Get weekly activity statistics (statuses, logins, registrations) - **GET** `get_instance_rules` — List server rules displayed on the about page - **GET** `get_instance_extended_description` — Get the extended description of the instance (admin-defined HTML) - **GET** `verify_credentials` — Verify the access token and get the authenticated user's account - **PATCH** `update_credentials` — Update the authenticated user's display name, bio, avatar, header, fields, and privacy settings - **GET** `get_account` — View a profile by account ID - **GET** `lookup_account` — Lookup an account by WebFinger address (user@domain or local username) - **GET** `get_account_statuses` — Get statuses posted by the given account - **GET** `get_account_followers` — List accounts that follow the given account - **GET** `get_account_following` — List accounts that the given account follows - **GET** `get_relationships` — Check relationship (following, blocked, muted, etc.) with one or more accounts - **GET** `get_familiar_followers` — Find mutual followers between you and given accounts - **GET** `search_accounts` — Search for accounts by username or display name - **POST** `follow_account` — Follow an account - **POST** `unfollow_account` — Unfollow an account - **POST** `remove_follower` — Remove an account from your followers - **POST** `block_account` — Block an account - **POST** `unblock_account` — Unblock an account - **POST** `mute_account` — Mute an account (hide from timelines and optionally notifications) - **POST** `unmute_account` — Unmute an account - **POST** `set_account_note` — Set a private note on an account (only visible to you) - **POST** `create_status` — Create a new status (post/toot). Requires status text or media_ids. - **GET** `get_status` — View a single status by ID - **PUT** `edit_status` — Edit an existing status - **DELETE** `delete_status` — Delete a status. Returns the deleted status with a text field for redraft. - **GET** `get_status_context` — Get the thread context — ancestors (parents) and descendants (replies) of a status - **GET** `get_status_source` — Get the plaintext source of a status for editing - **GET** `get_status_history` — Get the edit history of a status - **POST** `translate_status` — Translate a status into the user's language (if translation is supported by the instance) - **GET** `get_reblogged_by` — List accounts that boosted/reblogged a status - **GET** `get_favourited_by` — List accounts that favourited a status - **POST** `favourite_status` — Favourite/like a status - **POST** `unfavourite_status` — Undo favourite on a status - **POST** `reblog_status` — Boost/reblog a status to your followers - **POST** `unreblog_status` — Undo a boost/reblog - **POST** `bookmark_status` — Bookmark a status (private, only visible to you) - **POST** `unbookmark_status` — Remove a status from your bookmarks - **POST** `mute_status` — Mute notifications for a status thread - **POST** `unmute_status` — Unmute notifications for a status thread - **POST** `pin_status` — Pin a status to your profile - **POST** `unpin_status` — Unpin a status from your profile - **GET** `timeline_home` — Get home timeline (statuses from followed accounts and hashtags) - **GET** `timeline_public` — Get public timeline (federated or local) - **GET** `timeline_hashtag` — Get statuses with the given hashtag - **GET** `timeline_list` — Get timeline for a specific list - **GET** `list_notifications` — List notifications (mentions, favourites, boosts, follows, polls, etc.) - **GET** `get_notification` — Get a single notification by ID - **POST** `dismiss_notification` — Dismiss a single notification - **POST** `clear_notifications` — Dismiss all notifications (irreversible) - **GET** `get_unread_notification_count` — Get count of unread notifications - **GET** `search_v2` — Full-text search across accounts, statuses, and hashtags. Returns { accounts, statuses, hashtags } arrays. - **POST** `upload_media` — Upload a media attachment (image, video, audio). Returns 200 or 202 (processing). Attach to a status via media_ids. - **GET** `get_media` — Check media attachment processing status. Returns 200 when ready, 206 when still processing. - **PUT** `update_media` — Update media description or focal point (before attaching to a status) - **GET** `get_poll` — View a poll and its current results - **POST** `vote_poll` — Vote on a poll - **GET** `list_lists` — Get all lists created by the authenticated user - **GET** `get_list` — Get a single list by ID - **POST** `create_list` — Create a new list - **PUT** `update_list` — Update a list's title or settings - **DELETE** `delete_list` — Delete a list - **GET** `get_list_accounts` — List accounts that are members of a list - **POST** `add_list_accounts` — Add accounts to a list (must be accounts you already follow) - **DELETE** `remove_list_accounts` — Remove accounts from a list - **GET** `list_conversations` — List direct message conversations - **DELETE** `delete_conversation` — Remove a conversation from your list (does not delete messages) - **POST** `mark_conversation_read` — Mark a conversation as read - **GET** `trending_tags` — Get trending hashtags over the past week - **GET** `trending_statuses` — Get trending statuses - **GET** `trending_links` — Get trending links (news articles shared frequently) - **GET** `list_bookmarks` — List bookmarked statuses - **GET** `list_favourites` — List favourited statuses - **GET** `list_muted_accounts` — List muted accounts - **GET** `list_blocked_accounts` — List blocked accounts - **GET** `list_follow_requests` — List pending follow requests - **POST** `authorize_follow_request` — Accept a pending follow request - **POST** `reject_follow_request` — Reject a pending follow request - **GET** `get_suggestions` — Get follow suggestions (staff picks and accounts based on past interactions) - **DELETE** `remove_suggestion` — Remove an account from follow suggestions - **GET** `list_filters` — List all content filters - **GET** `get_filter` — Get a single filter by ID - **POST** `create_filter` — Create a content filter with keywords - **PUT** `update_filter` — Update a content filter - **DELETE** `delete_filter` — Delete a content filter - **POST** `create_app` — Register a new OAuth application. Returns client_id and client_secret. - **GET** `verify_app_credentials` — Verify that the app token is valid and get application info - **GET** `list_scheduled_statuses` — List scheduled statuses (posts queued for future publication via scheduled_at) - **GET** `get_scheduled_status` — Get a single scheduled status by ID - **PUT** `update_scheduled_status` — Update the scheduled publication time of a status - **DELETE** `delete_scheduled_status` — Cancel and delete a scheduled status - **GET** `get_markers` — Get saved reading positions for home timeline and/or notifications - **POST** `save_markers` — Save reading positions for home timeline and/or notifications - **POST** `create_report` — Report an account to instance moderators - **GET** `list_featured_tags` — List hashtags featured on your profile - **POST** `create_featured_tag` — Feature a hashtag on your profile - **DELETE** `delete_featured_tag` — Remove a featured hashtag from your profile - **GET** `get_featured_tag_suggestions` — Get suggested hashtags to feature (based on your most used tags) - **GET** `list_announcements` — List server announcements (active and recent) - **POST** `dismiss_announcement` — Mark an announcement as read/dismissed - **GET** `list_endorsements` — List accounts endorsed (featured) on your profile - **GET** `get_preferences` — Get user preferences (default visibility, language, sensitive flag, expand media, expand spoilers) - **GET** `admin_list_accounts` — List accounts with admin-level detail (email, IP, status). Requires admin:read:accounts scope. - **GET** `admin_get_account` — Get admin-level detail for a single account - **POST** `admin_approve_account` — Approve a pending account registration - **POST** `admin_reject_account` — Reject a pending account registration - **POST** `admin_disable_account` — Perform a moderation action on an account (disable, silence, suspend, none) - **POST** `admin_unsuspend_account` — Unsuspend a suspended account - **POST** `admin_unsilence_account` — Unsilence a silenced account - **GET** `admin_list_domain_blocks` — List blocked domains. Requires admin:read:domain_blocks scope. - **GET** `admin_get_domain_block` — Get a single domain block by ID - **POST** `admin_create_domain_block` — Block a domain from federating. Requires admin:write:domain_blocks scope. - **PUT** `admin_update_domain_block` — Update a domain block - **DELETE** `admin_delete_domain_block` — Remove a domain block (re-enable federation) ## Which DADLs are related to Mastodon? - [Hacker News](https://www.dadl.ai/d/hackernews/) — Hacker News API — read-only access to stories, comments, polls, jobs, users, and live feeds from news.ycombinator.com - [Algolia HN Search](https://www.dadl.ai/d/algolia-hn-search/) — Algolia Hacker News Search API — full-text search, filtering, and retrieval for stories, comments, and users on Hacker News - [Checkmk](https://www.dadl.ai/d/checkmk/) — Checkmk REST API (version 1.0, Checkmk 2.4) -- live host and service status via Livestatus queries, downtimes, acknowledgements and comments, the Event Console (list, acknowledge, change state and archive events) and BI (packs, rules, aggregations and live aggregation state), plus the full Setup side: hosts, clusters, folders, service discovery, rules and rulesets, host/service/contact groups, users, roles, passwords, time periods, host tags, notification rules, site connections and change activation. - [Graylog](https://www.dadl.ai/d/graylog/) — Graylog REST API -- log search (Views/Search + legacy universal), streams, pipelines, inputs, alerts, events, dashboards, users, roles, sidecars, index management, and cluster administration. Targets Graylog 6.x. - [Mempool](https://www.dadl.ai/d/mempool/) — mempool.space — Bitcoin block explorer, mempool visualizer, fee estimator, Lightning Network explorer, and transaction accelerator - [Soniox](https://www.dadl.ai/d/soniox/) — Soniox Speech AI — async speech-to-text for recorded audio (60+ languages, speaker diarization, language identification, speech translation), text-to-speech synthesis with voice cloning, audio file management, model discovery, temporary API keys for untrusted clients, and per-request usage, cost and concurrency reporting. --- **Canonical URL:** https://www.dadl.ai/d/mastodon/ **Raw DADL:** https://github.com/DunkelCloud/dadl-registry/blob/main/mastodon.dadl --- # Mempool MCP Server — 88 tools via DADL The Mempool DADL turns Mempool's API into an MCP server that Claude, GPT or any MCP-compatible agent can consume directly. One YAML file declares all 88 tools — block, lightning, address, mining, mempool, acceleration, and more — and ToolMesh serves them at runtime. No Python boilerplate, no per-endpoint code, no separate MCP server process. Below: the endpoint coverage matrix, a two-block ToolMesh setup, the full tool reference grouped by Mempool feature area. **Source:** [mempool.space REST API](https://mempool.space/docs/api/rest) **Updated:** 2026-05-26 **Tags:** cloud, devops, finance, crud, real-time, logging, user-management, notifications, auth:apikey ## Which Mempool endpoints are covered? **93%** (79 of ~85 endpoints). **Focus:** general (difficulty, prices), addresses, blocks, mining (pools, hashrate, rewards), fees, mempool, transactions (incl. broadcast), Lightning (nodes, channels, geo), Accelerator (public + authenticated) **Missing:** block audit endpoints (predictions/score/summary — undocumented response shapes), Liquid sidechain endpoints *Last reviewed: 2026-05-26* ## How do you configure the Mempool DADL? 1. Most endpoints are PUBLIC — no credential is required to use general, address, block, mining, fee, mempool, transaction, and Lightning endpoints 2. For Accelerator (Pro) endpoints only: 3. 1. Create an account at https://mempool.space and sign in 4. 2. Navigate to the Accelerator page: https://mempool.space/accelerator 5. 3. Top up your balance with Bitcoin or Lightning to enable Pro acceleration 6. 4. Generate or copy your X-Mempool-Auth API token from your account settings 7. 5. Store it as CREDENTIAL_MEMPOOL_AUTH_TOKEN in ToolMesh **Environment variable:** `CREDENTIAL_MEMPOOL_AUTH_TOKEN` [Authentication docs](https://mempool.space/docs/api/rest) *mempool.space is a fully public Bitcoin explorer; no auth is needed for the vast majority of endpoints. The X-Mempool-Auth header is only used by accelerator endpoints and personalizes acceleration estimates. For self-hosted mempool instances (Umbrel, RaspiBlitz, Start9), override base_url in backends.yaml to your local instance URL (e.g. http://umbrel.local:3006/api). Set credential to "none" if you only need public endpoints. * ## How do you install the Mempool MCP server with ToolMesh? Add to your `backends.yaml`: ```yaml - name: mempool transport: rest dadl: mempool.dadl url: "https://mempool.space/api" ``` Set the credential: ``` CREDENTIAL_MEMPOOL_AUTH_TOKEN=your-token-here ``` ## What 88 tools does the Mempool DADL expose? - **GET** `get_difficulty_adjustment` — Get details on the next mining difficulty adjustment. Returns progressPercent, difficultyChange, estimatedRetargetDate, remainingBlocks, remainingTime, previousRetarget, nextRetargetHeight, timeAvg, timeOffset, and expectedBlocks. Updated each block. - **GET** `get_prices` — Get current bitcoin spot price denominated in main currencies (USD, EUR, GBP, CAD, CHF, AUD, JPY). Returns { time, USD, EUR, GBP, CAD, CHF, AUD, JPY } with the timestamp of the price snapshot. - **GET** `get_historical_price` — Get bitcoin historical price denominated in the main currencies. When no parameters are provided the full price history for all currencies is returned (can be large). Filter with `currency` and anchor a single point in time with `timestamp` (Unix epoch seconds). - **GET** `get_address` — Get details about a Bitcoin address including chain_stats (confirmed funded/spent tx counts and sums in sats) and mempool_stats (unconfirmed activity). Supports legacy, P2SH, bech32, and taproot. - **GET** `get_address_txs` — Get transaction history for an address, newest first. Returns the 50 most recent mempool transactions plus the first 25 confirmed transactions. To paginate further into history, use after_txid with the last txid from the previous page (returns up to 25 confirmed txs/call). - **GET** `get_address_txs_chain` — Get only confirmed (mined) transactions for an address, newest first, up to 25 per page. Use after_txid to paginate. - **GET** `get_address_txs_mempool` — Get only unconfirmed (mempool) transactions for an address. Returns up to 50 mempool entries. No pagination — mempool depth is bounded. - **GET** `get_address_utxo` — Get the unspent transaction outputs (UTXOs) controlled by an address. Each entry has txid, vout, value (sats), and status (confirmed flag + block_height/block_hash/block_time). - **GET** `validate_address` — Validate a Bitcoin address string. Returns { isvalid, address, scriptPubKey, isscript, iswitness, witness_version, witness_program }. Use to detect typos before broadcasting or to identify the script type. - **GET** `get_block` — Get a block by hash. Returns id (hash), height, version, timestamp, tx_count, size (bytes), weight (WU), merkle_root, previousblockhash, mediantime, nonce, bits, difficulty, and extras. - **GET** `get_block_extended` — Get an extended block by hash including mempool-derived fields: pool (mining pool slug+name+id), avgFee, avgFeeRate, totalFees, medianFee, feeRange, reward, and mining metadata. Prefer this over get_block for analytical use cases. - **GET** `get_block_header` — Get the raw 80-byte block header as a hex string. Useful for SPV proofs and external chain validation. - **GET** `get_block_height` — Get the hash of the block at a specific height. Returns the block hash as plain text. Useful for converting a height into a hash that other endpoints accept. - **GET** `get_block_timestamp` — Get the block nearest to a given Unix epoch SECONDS timestamp. Returns { height, hash, timestamp }. Helpful for "what was the chain tip when X happened" lookups. - **GET** `get_block_raw` — Get the raw serialized block as binary data. Use sparingly — blocks can be up to ~4 MB. Response type is application/octet-stream. - **GET** `get_block_status` — Get a block's confirmation status. Returns { in_best_chain, height, next_best }. A block may be "orphaned" (in_best_chain=false) after a reorg. - **GET** `get_block_tip_height` — Get the height of the current chain tip as plain text integer. Cheap, frequently used as a liveness/sync check. - **GET** `get_block_tip_hash` — Get the hash of the current chain tip as plain text. Pair with get_block to fetch latest block details. - **GET** `get_block_txid` — Get the txid at a specific index within a block. Index 0 is the coinbase transaction. Returns the txid as plain text. - **GET** `get_block_txids` — Get all txids in a block as an ordered array of strings. Useful when you need every transaction but want to avoid downloading full tx bodies. - **GET** `get_block_txs` — Get up to 25 full transaction objects from a block starting at start_index. Step by 25 to paginate (0, 25, 50, ...). Each tx includes vin, vout, fee, status, and weight. - **GET** `get_blocks` — Get summaries for the 10 most recent blocks ending at startHeight (descending). Omit startHeight via get_blocks_latest to start from the chain tip. Each block summary has id, height, version, timestamp, tx_count, size, weight, and merkle_root. - **GET** `get_blocks_latest` — Get summaries for the 10 most recent blocks from the chain tip (descending). Convenience endpoint — same response shape as get_blocks. - **GET** `get_blocks_extended` — Get extended summaries for the 15 most recent blocks ending at startHeight, including mining pool, avgFee, avgFeeRate, totalFees, medianFee, and feeRange per block. - **GET** `get_blocks_extended_latest` — Get extended summaries for the 15 most recent blocks from the chain tip. Same shape as get_blocks_extended. - **GET** `get_blocks_bulk` — Get extended block data for an inclusive height range. Returns extended summaries for every block from minHeight to maxHeight. Limited to 10,000 blocks per request on hosted instance — enterprise sponsorship required for larger ranges. - **GET** `get_mining_pools` — Get a list of all mining pools ranked by blocks found during the time period. Returns each pool with name, slug, link, blockCount, rank, and emptyBlocks. timePeriod is one of: 24h, 3d, 1w, 1m, 3m, 6m, 1y, 2y, 3y. - **GET** `get_mining_pool` — Get detailed stats for one mining pool: name, slug, regexes, addresses, recent block history, and basic activity metrics. - **GET** `get_mining_pool_hashrates` — Get average hashrate and share of the network for each mining pool over a time period. timePeriod values match get_mining_pools. - **GET** `get_mining_pool_hashrate` — Get historical hashrate timeseries for a single mining pool. Each point has timestamp, avgHashrate, and share. - **GET** `get_mining_pool_blocks` — Get blocks mined by a specific pool, descending from blockHeight. Returns up to 10 blocks per call. - **GET** `get_hashrate` — Get network-wide hashrate and difficulty timeseries over the period. Returns { hashrates, difficulty, currentHashrate, currentDifficulty }. - **GET** `get_difficulty_adjustments` — Get the record of past difficulty adjustments over a trailing interval. Each entry has timestamp, height, difficulty, adjustment (factor change). interval uses the same vocabulary as timePeriod. - **GET** `get_reward_stats` — Get aggregated reward statistics across the last N blocks: startBlock, endBlock, totalReward, totalFee, totalTx (count of transactions across those blocks). - **GET** `get_block_fees` — Get average block-fee timeseries over the period. Each datapoint has timestamp, avgHeight, avgFees (sats). - **GET** `get_block_rewards` — Get average block-reward (subsidy + fees) timeseries over the period. - **GET** `get_block_feerates` — Get block fee-rate percentile timeseries (sat/vB at p10, p25, p50, p75, p90) over the period. Useful for historical fee analysis. - **GET** `get_block_sizes_weights` — Get block size (bytes) and weight (WU) timeseries over the period. Each point pairs avgSize and avgWeight. - **GET** `get_block_predictions` — Get block "health" predictions (template vs. actual deltas) timeseries over the period. Returns audit deviation indicators useful for spotting unusual mining behavior. - **GET** `get_block_audit_score` — Get the audit score for a specific block hash. Audit scores reflect how well the block's contents matched mempool.space's predicted template at the moment of mining. - **GET** `get_blocks_audit_scores` — Get audit scores for the most recent 16 blocks. Each entry has hash, height, and score. - **GET** `get_block_audit_summary` — Get a detailed audit summary for a block: which expected txs were missing, which surprises were included, fee delta, and template-vs-actual differences. - **GET** `get_mempool_blocks_fees` — Get the projected next 8 mempool blocks (template projections). Each entry has blockSize, blockVSize, nTx, totalFees (sats), medianFee, and feeRange (sat/vB percentiles). Useful for "when will my tx confirm". - **GET** `get_recommended_fees` — Get recommended fee rates (sat/vB) for confirmation targets: fastestFee, halfHourFee, hourFee, economyFee, and minimumFee. The most popular endpoint for wallets/apps to suggest a fee. - **GET** `get_precise_fees` — Get precise (sub-sat/vB resolution) recommended fee rates. Same fields as get_recommended_fees but reported as floats for high-precision applications. - **GET** `get_mempool` — Get mempool backlog overview: { count, vsize, total_fee, fee_histogram }. fee_histogram is an array of [feeRate, vsize] buckets showing the fee-rate distribution of unconfirmed transactions. - **GET** `get_mempool_txids` — Get every unconfirmed txid currently in the mempool. Response can be very large (tens of thousands of strings) — prefer get_mempool for summary stats. - **GET** `get_mempool_recent` — Get the latest mempool transactions, up to ~10. Each entry has txid, fee, vsize, and value (sats). Use as a live feed of recently broadcast transactions. - **GET** `get_replacements` — Get current RBF (Replace-By-Fee) replacements in the mempool. Returns a tree of replacements with each node's txid, fee, and replacing/replaced relationships. Includes opt-in RBF only. - **GET** `get_fullrbf_replacements` — Get full-RBF replacements (including non-opt-in transactions replaced under Full-RBF policy). Same shape as get_replacements but covers a broader replacement set. - **GET** `get_cpfp` — Get the ancestors and best descendant fees for a transaction (Children-Pay-For-Parent context). Returns { ancestors, bestDescendant, effectiveFeePerVsize, sigops } to understand the effective confirmation priority of a tx considering its package. - **GET** `get_tx` — Get a transaction by txid. Returns txid, version, locktime, vin (inputs), vout (outputs), size, weight, fee (sats), and status (confirmed flag + block info). Inputs include the prevout being spent and witness data for SegWit. - **GET** `get_tx_hex` — Get the raw transaction as a hex string. Use for re-broadcasting, offline signing, or external verification. - **GET** `get_tx_merkleblock_proof` — Get a Merkle block (SPV) proof for a confirmed transaction. Returns hex-encoded proof suitable for verifying the tx is part of its block without downloading the full block. - **GET** `get_tx_merkle_proof` — Get a JSON Merkle inclusion proof: { block_height, merkle, pos }. Lighter than merkleblock-proof and easier to consume programmatically. - **GET** `get_tx_outspend` — Get the spending status of one specific output (vout index). Returns { spent, txid, vin, status } where status.confirmed indicates whether the spend is mined. - **GET** `get_tx_outspends` — Get the spending status of all outputs in a transaction as an array (one entry per vout). Cheaper than calling get_tx_outspend per output. - **GET** `get_tx_raw` — Get the raw transaction as binary (application/octet-stream). For hex-string output prefer get_tx_hex. - **GET** `get_tx_rbf` — Get the full RBF history/timeline for a transaction — every replacement that has occurred, with fee progression and timestamps. - **GET** `get_tx_status` — Get a transaction's confirmation status. Returns { confirmed, block_height, block_hash, block_time }. Cheap polling endpoint to wait for a tx to confirm. - **GET** `get_transaction_times` — Get the timestamps at which a list of unconfirmed transactions was first observed in the mempool. Pass each txid via repeated txId[] query param. Returns an array of Unix epoch seconds in input order. - **POST** `broadcast_tx` — Broadcast a raw transaction to the Bitcoin network. The request body is the raw transaction as a HEX STRING (not JSON). On success returns the txid as plain text. On failure returns an error string (e.g. "sendrawtransaction RPC error: ..."). The tx is rejected if it fails policy (insufficient fee, conflicts with mempool, invalid script, etc.). - **GET** `get_lightning_statistics` — Get Lightning Network statistics timeseries over the interval. Returns datapoints with channel_count, node_count, total_capacity (sats), tor_nodes, clearnet_nodes, unannounced_nodes, avg_capacity, avg_fee_rate, avg_base_fee_mtokens, med_capacity, med_fee_rate, med_base_fee_mtokens. interval values: latest, 24h, 3d, 1w, 1m, 3m, 6m, 1y, 2y, 3y. - **GET** `search_lightning` — Full-text, case-insensitive search across Lightning nodes and channels. Returns { nodes, channels } with matches on alias, pubkey, channel ID, etc. - **GET** `get_lightning_nodes_in_country` — Get Lightning nodes in a specific country. country is an ISO 3166-1 alpha-2 code (lowercase, e.g. "us", "de"). Returns country info plus an array of nodes with public_key, alias, channels, capacity, etc. - **GET** `get_lightning_node_stats_per_country` — Get per-country aggregate Lightning statistics: each entry has name (country), iso_code, count (nodes), share (% of network), capacity, channels. - **GET** `get_lightning_isp_nodes` — Get Lightning nodes hosted on a specific ISP (by ASN). isp is the AS number (e.g. "16509" for AWS). - **GET** `get_lightning_isp_ranking` — Get the ranked list of ISPs hosting Lightning nodes by node count, capacity, and channel count. - **GET** `get_lightning_top_nodes` — Get top 100 Lightning nodes overall — includes topByCapacity and topByChannels arrays each with publicKey, alias, capacity, and channels. - **GET** `get_lightning_top_nodes_by_liquidity` — Get top 100 Lightning nodes by total channel capacity (descending). - **GET** `get_lightning_top_nodes_by_connectivity` — Get top 100 Lightning nodes by number of channels (descending). - **GET** `get_lightning_oldest_nodes` — Get top 100 oldest Lightning nodes by first-seen timestamp (ascending — oldest first). - **GET** `get_lightning_node` — Get detailed stats for a Lightning node by public key. Returns alias, channels, capacity, first_seen, updated_at, color, sockets, country, city, asn (ISP), opened_channel_count, closed_channel_count, active_channel_count. - **GET** `get_lightning_node_statistics` — Get historical capacity and channel count timeseries for a Lightning node. - **GET** `get_lightning_channel` — Get details for a Lightning channel by its short channel ID. Returns node1/node2 pubkeys, capacity, status, transaction_id (funding tx), and policy info per side. - **GET** `get_lightning_channels_from_txids` — Get Lightning channels whose funding transaction matches the given txid(s). Pass each via repeated txId[] query param. Useful for tracing on-chain → channel mappings. - **GET** `get_lightning_channels_from_node` — Get Lightning channels for a node, filtered by status. status is one of: open, active, closed. Returns an array of channels with capacity, transaction_id, status, fee policies, and counterparty. - **GET** `get_lightning_channel_geodata` — Get geographic data for ALL Lightning channels (large response). Each entry is a tuple [pubKey1, alias1, lon1, lat1, pubKey2, alias2, lon2, lat2] for drawing the global channel map. - **GET** `get_lightning_channel_geodata_for_node` — Get geographic data only for channels of a specific node. Same tuple shape as the global endpoint. - **POST** `estimate_acceleration` — Estimate the cost of accelerating a stuck transaction via the mempool.space Accelerator service. Request body { txInput: "<txid>" }. Returns available fee-rate targets, per-target costs (sats), nextBlockFee, and recommendedFee. The X-Mempool-Auth header (if set) personalizes the estimate against your prepaid balance. - **POST** `generate_acceleration_invoice` — Generate a Lightning invoice (or on-chain payment request) to pay for a one-shot transaction acceleration. Request body { product: "accelerator", amount: <sats>, ... }. Returns the BOLT11 invoice and a paymentId to poll for settlement. - **GET** `get_pending_accelerations` — Get the list of currently pending accelerations across the service (public view). Each entry includes txid, status, added_at, feeDelta. - **GET** `get_acceleration_history_public` — Get the public history of completed/failed accelerations. Useful as an audit feed. - **GET** `get_top_up_history` — Get the prepaid-balance top-up history for your account. Requires X-Mempool-Auth credential. - **GET** `get_available_balance` — Get your available prepaid Accelerator balance in sats. Requires X-Mempool-Auth credential. Returns { balance, ... }. - **POST** `accelerate_transaction` — Submit an acceleration request for a stuck transaction (Pro). Requires X-Mempool-Auth credential and sufficient prepaid balance. Body { txInput: "<txid>", targetFeeRate: <sat/vB> }. Deducts the appropriate sat amount from your balance and submits the acceleration to participating miners. - **GET** `get_acceleration_history` — Get YOUR account's acceleration history filtered by status. Requires X-Mempool-Auth credential. status values: all | requested | accelerating | mined | completed | failed. Pass details=true for full per-acceleration details. - **POST** `cancel_acceleration` — Cancel a pending acceleration (Pro). Requires X-Mempool-Auth credential. Cancellation is only possible while the acceleration is still in "requested" status; once it has been picked up by miners it cannot be revoked. Body { txInput: "<txid>" }. ## What composite workflows does the Mempool DADL provide? - **FN** `get_chain_tip` — Get the latest block's full details in one call: fetches the tip hash then resolves it to an extended block object (with pool, fees, reward). - **FN** `get_address_full_history` — Get a Bitcoin address with all of its UTXOs and its most recent confirmed transactions in a single payload — { address, utxos, recent_txs }. recent_txs is capped at the limit. - **FN** `wait_for_tx_confirmation` — Poll a transaction's status up to max_attempts times, returning the status object as soon as the tx is confirmed or all attempts are exhausted. Sleeps between calls are NOT possible in the sandbox — this composite simply calls get_tx_status repeatedly (back-to-back) and is intended for short-burst checks (e.g. just after broadcast). For long waits use Temporal workflows. - **FN** `get_fee_dashboard` — Get a complete fee dashboard in one call: recommended fees, projected next mempool blocks, and current mempool stats. Returns { recommended, projected_blocks, mempool }. - **FN** `get_block_with_first_txs` — Get a block and its first N transactions in one call. Useful for inspecting the coinbase plus early transactions in a block. Capped at 50 transactions (2 paginated calls). ## Which DADLs are related to Mempool? - [Billomat](https://www.dadl.ai/d/billomat/) — Billomat REST API — German cloud invoicing & accounting: invoices, estimates, credit notes, recurring invoices, delivery notes, order confirmations, dunning reminders, clients, contacts, articles, payments, expenses, taxes - [Checkmk](https://www.dadl.ai/d/checkmk/) — Checkmk REST API (version 1.0, Checkmk 2.4) -- live host and service status via Livestatus queries, downtimes, acknowledgements and comments, the Event Console (list, acknowledge, change state and archive events) and BI (packs, rules, aggregations and live aggregation state), plus the full Setup side: hosts, clusters, folders, service discovery, rules and rulesets, host/service/contact groups, users, roles, passwords, time periods, host tags, notification rules, site connections and change activation. - [Hacker News](https://www.dadl.ai/d/hackernews/) — Hacker News API — read-only access to stories, comments, polls, jobs, users, and live feeds from news.ycombinator.com - [NetBox](https://www.dadl.ai/d/netbox/) — NetBox DCIM/IPAM API -- full v4 coverage: sites, racks, devices, modules, interfaces, cables, power, IPAM (prefixes, IPs, VLANs, VRFs, route-targets, VLAN translation), virtualization, circuits (including virtual circuits), tenants, contacts, VPN (IKE/IPSec/L2VPN), wireless, extras (webhooks, event-rules, scripts, config-templates, bookmarks, notifications), users/permissions/tokens, and core data sources & jobs - [Stripe](https://www.dadl.ai/d/stripe/) — Stripe REST API — payment processing, billing, subscriptions, invoices, products, and financial infrastructure - [Xen Orchestra](https://www.dadl.ai/d/xen-orchestra/) — Xen Orchestra REST API (XO 6.4+, current through 6.9) -- complete coverage: VMs (incl. PATCH update + snapshot revert), VM controllers, hosts (incl. full power/lifecycle actions + maintenance mode + PIF rescan), pools (incl. add_host, rolling reboot/update with interrupted-update recovery + finalize), storage (SR create/delete, VDI incl. PATCH update + vhd/raw/qcow2 export, VBD), networks (VIF incl. PATCH update + PIF/PBD), VM/VDI snapshots, VM templates, hardware (PCI/PGPU/SM), tasks, backups (archives incl. live mount of backup disks, jobs/logs, repositories incl. health + benchmark + space reclaim), schedules, messages, alarms, events (SSE incl. non-XAPI collections), RBAC v2 (users/groups/acl-roles/acl-privileges incl. assignment introspection), proxies, servers, dashboards, SDN traffic rules (add/delete/update), IPMI sensor inventory (plugin), audit records (plugin), health check --- **Canonical URL:** https://www.dadl.ai/d/mempool/ **Raw DADL:** https://github.com/DunkelCloud/dadl-registry/blob/main/mempool.dadl --- # Mikrotik MCP Server — 297 tools via DADL The Mikrotik DADL turns Mikrotik's API into an MCP server that Claude, GPT or any MCP-compatible agent can consume directly. One YAML file declares all 297 tools — firewall, system, ipsec, dhcp, ip, ipv6, and more — and ToolMesh serves them at runtime. No Python boilerplate, no per-endpoint code, no separate MCP server process. Below: the endpoint coverage matrix, a two-block ToolMesh setup, the full tool reference grouped by Mikrotik feature area, required credential scopes. **Source:** [MikroTik RouterOS REST API](https://help.mikrotik.com/docs/spaces/ROS/pages/47579162/REST+API) **Updated:** 2026-05-25 **Tags:** networking, crud, user-management, authentication, logging, monitoring, file-management, deployment, auth:basic ## Which Mikrotik endpoints are covered? **65%** (297 of ~450 endpoints). **Focus:** system (resource, identity, clock, health, license, package, script, scheduler, reboot/shutdown, backup, note, logging rules + actions with /set twin), interfaces (generic set, list/CRUD, ethernet + atomic /set + switch chip + switch port, bridge + /set + port /set + VLAN CRUD + /set + /remove + host/FDB table, vlan, bonding CRUD, wireless legacy, wifi, lte + /set, wireguard + interface CRUD + peers, list/member + list CRUD), IP (address, route, ARP, neighbor, service set/enable/disable, pool, cloud + /set), DNS (settings, static, cache), DHCP server (CRUD + /set + delete, lease, network CRUD, make-static, client CRUD + release/renew), firewall (filter, NAT, mangle full CRUD + move, raw full CRUD + move, address-list update, connection tracking), IPv6 (address full CRUD, route CRUD, firewall filter CRUD + move, ND, settings /set), PPP (secret, active, profile CRUD), routing (BGP connection CRUD, BGP templates/sessions, OSPF instance + area CRUD, interface-templates, neighbors, routing-filter rules CRUD), queues (simple full, tree, type), tools (ping, traceroute, bandwidth-test, netwatch CRUD, email SMTP settings get/set + send), users (user, group CRUD, ssh-keys, active sessions), logs, certificates, files, SNMP, VPN servers (L2TP/SSTP/PPTP/OVPN singleton get/set), IPsec (peer, identity, policy, profile, proposal full CRUD; active-peers, installed-sa, flush, settings), container (RouterOS 7), MPLS basics **Missing:** CAPsMAN controller endpoints (out of scope: CRS354 is Ethernet-only), RADIUS server config, hotspot user profiles/walled garden, /interface/wireless deep config (legacy stack; tooling focuses on the modern /interface/wifi stack), BGP VPN/VPLS, OSPFv3 (instance.version=3 supported but no separate tooling), MPLS LDP detail, RIPv2, traffic-flow exporter, traffic monitor, GPS, ROMON, dude integration, dot1x, w60g, modem deep config, /tool/fetch (file upload/download via REST), file repository sync, certificate ACME plugin, /caps-man for new wifi stack (intentional: per-device wifi-config exposes set already). Also broken until ToolMesh wrapper fix (2026-05-25): every update_*/delete_* using PATCH/DELETE /xxx/{*N-id} returns HTTP 400 due to missing percent-encoding of the .id asterisk — see top-of-file 'Known ToolMesh wrapper bugs' note. Workarounds via POST /xxx/set + 'numbers' (and POST /xxx/remove + 'numbers' where exposed, e.g. remove_bridge_vlan) are unaffected. *Last reviewed: 2026-05-25* ## How do you configure the Mikrotik DADL? 1. Log in to your MikroTik device via Winbox, SSH, or WebFig as an admin 2. Enable the REST API service: /ip/service> set www-ssl disabled=no (HTTPS) or set www disabled=no (HTTP, NOT recommended for production) 3. Ensure www-ssl has a valid certificate: /ip/service> set www-ssl certificate=<cert-name> 4. Create a dedicated API user: /user/add name=api-user password=<strong-password> group=read (or 'full' / a custom group) 5. For least-privilege custom groups: /user/group/add name=api-readonly policy=api,read,test,winbox 6. Verify access: curl -k -u api-user:<password> https://<router-ip>/rest/system/resource 7. Store the credentials: CREDENTIAL_MIKROTIK_USERNAME=api-user and CREDENTIAL_MIKROTIK_PASSWORD=<password> **Environment variable:** `CREDENTIAL_MIKROTIK_USERNAME and CREDENTIAL_MIKROTIK_PASSWORD` [Authentication docs](https://help.mikrotik.com/docs/spaces/ROS/pages/47579162/REST+API) *RouterOS v7.1+ required (v7.9+ recommended). Most MikroTik devices ship with self-signed certificates -- ToolMesh must skip TLS verification or you must install a trusted certificate via /certificate/import. The 'api' policy is REQUIRED on the user's group for any REST access. For read-only monitoring, use group with policy=api,read,test,winbox; for full management add write,policy,reboot,ftp,sensitive. Known ToolMesh wrapper bugs (2026-05-25): (1) PATCH/DELETE /xxx/{*N-id} return HTTP 400 — use POST /xxx/set + 'numbers' (e.g. set_bridge_vlan) and POST /xxx/remove + 'numbers' (e.g. remove_bridge_vlan) instead. (2) set_bridge_port 'numbers' must be the bridge-port .id, not interface name. (3) JSON null is dropped by the wrapper — use empty string '' to clear fields. Full detail in the comment block at the top of this file.* ## How do you install the Mikrotik MCP server with ToolMesh? Add to your `backends.yaml`: ```yaml - name: mikrotik transport: rest dadl: mikrotik.dadl url: "https://10.0.0.1/rest" # HTTPS (recommended) -- requires www-ssl service # url: "http://10.0.0.1/rest" # plain HTTP -- requires www service (RouterOS v7.9+) ``` Set the credential: ``` CREDENTIAL_MIKROTIK_USERNAME and CREDENTIAL_MIKROTIK_PASSWORD=your-token-here ``` ## What 297 tools does the Mikrotik DADL expose? - **GET** `get_system_resource` — Get the device's hardware and runtime resource summary: architecture (mipsbe/arm/arm64/x86_64/tile), board-name, CPU model and count, CPU load, RAM (free/total), HDD (free/total), uptime, RouterOS version, build-time. Returns a single JSON object (NOT an array). - **GET** `get_system_identity` — Get the device's identity (hostname shown in Winbox, neighbor discovery, and the CLI prompt). Returns a single-field object: {"name":"<hostname>"}. - **POST** `set_system_identity` — Set the device's hostname/identity. Send {name: '<new-name>'}. - **GET** `get_system_clock` — Get the current date, time, timezone, and DST setting on the device. Useful for verifying NTP sync and timezone configuration. - **POST** `set_system_clock` — Set the device clock. Useful fields: time-zone-name (e.g. 'Europe/Berlin'), time-zone-autodetect ('yes'/'no'), date ('YYYY-MM-DD'), time ('HH:MM:SS'). - **GET** `get_ntp_client` — Get NTP client config and live sync state. Key fields: enabled ('true'/'false'), mode (unicast|broadcast|multicast|manycast), servers (comma-separated upstream NTP server IPs/FQDNs), vrf. Read-only status fields: status (started|stopped| synchronized|using-local-clock|error|search), synced-server, synced-stratum, system-offset (e.g. '0.5ms'), freq-diff. If 'status' is anything other than 'synchronized', the device clock is drifting on its own RTC/quartz. - **POST** `set_ntp_client` — Update the NTP client. Most common change: provide a comma-separated list of trusted NTP servers and enable the client. Example body: {enabled:'yes', servers:'time.cloudflare.com,ptbtime1.ptb.de', mode:'unicast'}. Apply takes effect immediately; allow a few seconds for first sync attempt. - **GET** `get_ntp_server` — Get the device's NTP SERVER config (whether this router serves time to other clients). Fields: enabled, broadcast, multicast, manycast, use-local-clock, local-clock-stratum, vrf, broadcast-addresses. Most edge devices keep this disabled and rely solely on the client. - **POST** `set_ntp_server` — Update the NTP server config (enable broadcast/multicast/manycast NTP serving). - **GET** `get_system_health` — Get hardware sensor readings: CPU temperature, board temperature, fan speeds, voltage, PSU state. Available sensors vary by hardware model; small devices (hAP lite, hEX lite) expose only a subset. - **GET** `get_system_health_settings` — Get the cooling/fan control settings (separate from the read-only sensor values in /system/health). Typical fields: fan-mode (auto|manual), fan-min-speed-percent (PWM floor, e.g. 30), fan-target-temperature (target CPU/board temp for PWM control, e.g. 55), and PSU-related toggles (use-fan, fan-failure-trigger). Available only on devices with controllable fans (CCR, CRS3xx with PWM headers, RB5009, etc.). On fan-less hardware (cAP, hAP, hEX, CHR) this endpoint typically returns an empty object. - **POST** `set_system_health_settings` — Configure cooling/fan behavior. Common changes -- quieter idle: {fan-mode:'auto', fan-min-speed-percent:'20', fan-target-temperature:'55'}. Force constant high RPM (e.g. dusty environment): {fan-mode:'manual', fan-min-speed-percent:'100'}. CAUTION: setting fan-target-temperature too high (>70C) or fan-min-speed-percent too low on a thermally constrained chassis can cause throttling or shutdown. Verify with get_system_health afterwards. - **GET** `get_system_license` — Get the RouterOS license level (0-6), software-id, and CHR upgrade state. Level 6 = CHR/x86, levels 4-5 = WISP/Controller. - **GET** `get_routerboard` — Get RouterBOARD hardware info: model, serial-number, firmware-type, factory-firmware (the firmware that shipped from the factory), current-firmware (running), upgrade-firmware (latest available bundled with the running RouterOS package), routerboot version. The 'routerboard' flag is 'true' on physical MikroTik hardware and 'false' on CHR/x86 (where this endpoint typically returns empty). For CRS3xx switches this is the canonical source for the factory firmware revision and the bootloader (RouterBOOT) version that the device shipped with. - **POST** `upgrade_routerboard_firmware` — Trigger a RouterBOOT firmware upgrade to the version reported in 'upgrade-firmware'. The new firmware is staged for the next boot -- the device MUST be rebooted (POST /system/reboot) for the upgrade to take effect. Different from RouterOS package upgrades (see install_package_updates) -- this updates ONLY the bootloader/CPLD/SoC firmware bundled with the running RouterOS package. Returns no body on success; check get_routerboard afterwards to confirm current-firmware matches upgrade-firmware. - **POST** `downgrade_routerboard_firmware` — Downgrade RouterBOOT firmware to the factory firmware. Same reboot requirement as upgrade. Rarely needed; use only when a RouterBOOT upgrade caused issues and you need to revert. - **GET** `list_system_packages` — List all installed RouterOS packages with version, build time, and disabled state. Standard package set: system, wireless, ipv6, advanced-tools, routing, security, wifi-qcom-ac, etc. Disabled packages remain on flash but are not loaded. - **POST** `enable_system_package` — Enable a package by name. Requires reboot to take effect. - **POST** `disable_system_package` — Disable a package by name. Requires reboot to unload. - **POST** `check_for_package_updates` — Check the MikroTik update server for available RouterOS updates. Returns installed-version, latest-version, status ('System is already up to date', 'New version is available'). Does NOT install -- use install_package_updates. - **POST** `install_package_updates` — Download and install RouterOS updates from MikroTik servers. The device WILL reboot after install. Channel must be set first via set channel (stable, long-term, testing, development). - **GET** `list_system_scripts` — List all stored scripts on the device with name, source code, run-count, last-started, owner, and policies. - **GET** `get_system_script` — Get a single script by .id or name. Returns the full source field. - **PUT** `add_system_script` — Create a new script. Provide name and source (RouterOS scripting language). - **PATCH** `update_system_script` — Update an existing script's source, policies, or comment. - **DELETE** `delete_system_script` — Delete a script by .id or name. - **POST** `run_system_script` — Execute a stored script by .id. Output (if any) is appended to the system log. - **GET** `list_system_scheduler` — List scheduled tasks (cron-like). Each has name, start-date, start-time, interval, on-event (script to run), policy, run-count, next-run. - **PUT** `add_system_scheduler` — Schedule a script to run at a specific time or interval. - **PATCH** `update_system_scheduler` — Update a scheduled task (name, on-event, start-date/time, interval, policy, comment, disabled). - **DELETE** `delete_system_scheduler` — Delete a scheduled task by .id or name. - **POST** `reboot_system` — Reboot the device immediately. Disconnects ALL sessions; device will be offline for 30-90 seconds. There is no undo. Confirm intent before calling. - **POST** `shutdown_system` — Power-off the device immediately. Device requires physical power-cycle to come back online. Use only when you have on-site access. - **POST** `create_backup` — Create a binary backup of the running configuration. Stored on device flash as <name>.backup. Retrieve via FTP/SFTP -- the REST API does not stream file contents. - **POST** `load_backup` — Restore configuration from a backup file. Device WILL reboot. Backup must already exist in /file (uploaded via FTP/SFTP or made via create_backup). - **POST** `export_config` — Export the running configuration as an RSC script. If 'file' is provided, writes to /file/<name>.rsc on the device; otherwise returns the script text inline. 'compact' (yes/no) and 'verbose' (yes/no) control verbosity. - **GET** `get_system_note` — Get the login banner / system note shown on console login. Often used for ownership/contact info. - **POST** `set_system_note` — Set the login banner / system note. - **GET** `list_interfaces` — List all interfaces (physical and virtual) with name, type, MTU, MAC address, running/disabled state, rx/tx-byte counters, last-link-up/down. Type values: ether, vlan, bridge, wireless, wifi, wireguard, lte, ppp-client, ovpn-server, ovpn-client, l2tp-server, sstp-server, pptp-server, eoip, ipip, gre, vrrp, etc. - **GET** `get_interface` — Get a single interface by name (e.g. 'ether1', 'bridge1') or .id (e.g. '*1'). - **PATCH** `update_interface` — Update common interface properties: name, comment, mtu (L3), l2mtu (L2), disabled, arp mode. NOTE on jumbo frames: RouterOS clamps L3 'mtu' to l2mtu - 14 bytes. To run mtu=9000 you must FIRST raise 'l2mtu' to at least 9014 (or use the max-l2mtu the hardware reports). On CRS3xx switch-chips the per-port l2mtu IS writable and changes the chip's accepted frame size on that port. - **POST** `enable_interface` — Enable one or more interfaces by .id or name (comma-separated in 'numbers'). - **POST** `disable_interface` — Disable one or more interfaces. - **POST** `monitor_interface_traffic` — Sample rx/tx rates for an interface. ALWAYS pass once='' to avoid the 60s timeout, otherwise the API streams indefinitely. - **POST** `set_interface` — Atomically update one or more interfaces (any type) via the CLI-style '/interface set'. Use this when you need to change name/comment/mtu/disabled across MIXED interface types in one transaction (CLI: '/interface set [find ...] mtu=9000'). For ether-specific atomic edits (l2mtu, speed, duplex) use set_ethernet_interface; for cellular APN/mode use set_lte_interface. The generic /interface/set only touches L3 mtu and cannot raise l2mtu on Ethernet ports. - **GET** `list_ethernet_interfaces` — List physical Ethernet ports with name, default-name, MAC, MTU, speed, auto-negotiation, full-duplex, SFP details. - **POST** `set_ethernet_interface` — Atomically update one or more Ethernet ports via the CLI-style '/interface/ethernet set' command. PREFERRED for jumbo-frame setup on switches: PATCH /interface/ethernet/{id} returns HTTP 400 when a port is a bridge slave (slave='true') OR when mtu would exceed current l2mtu - 14. This POST endpoint sets l2mtu and mtu in a single atomic transaction so the validator sees both new values together. Reference ports via 'numbers' (comma-separated names or .ids). - **PATCH** `update_ethernet_interface` — Update an Ethernet port's properties (name, speed, advertise, full-duplex, auto-negotiation, comment, disabled, MTU/l2mtu, MAC override). Jumbo-frame note: raise l2mtu (e.g. to 9014 or up to max-l2mtu) BEFORE setting mtu=9000, otherwise RouterOS silently clamps mtu to l2mtu - 14. For slave (bridge-member) ports this PATCH frequently returns HTTP 400 when changing mtu/l2mtu -- use set_ethernet_interface instead, which sets both values atomically via the /set endpoint. - **GET** `list_ethernet_switches` — List hardware switch chips (CRS3xx-series and similar). Each chip has name (e.g. 'switch1'), type, mirror-source, mirror-target, cpu-flow-control. On boxes with no switch chip (RB4011, hAP family) this returns an empty array. - **GET** `list_ethernet_switch_ports` — List per-port switch-chip configuration (separate from /interface/ethernet L2/L3 view). Fields: name (chip-port id like 'switch1-cpu' or 'ether1'), l2mtu, vlan-mode, vlan-header, default-vlan-id, mirror, mirror-egress. On CRS3xx the chip enforces its own per-port l2mtu — this is the cap that /interface/ethernet l2mtu is clamped against. For end-to-end jumbo you usually need set_ethernet_interface (raises ether l2mtu) AND, on older firmwares, set_ethernet_switch_port (raises chip-port l2mtu). - **POST** `set_ethernet_switch` — Atomically update one or more switch chips. Reference via 'numbers' (chip name or .id). Use for changing mirror-source/mirror-target, cpu-flow-control. Rarely needed on a 'just give me jumbo frames' workflow — try set_ethernet_interface first. - **POST** `set_ethernet_switch_port` — Atomically update one or more switch-chip ports. Reference via 'numbers' (port name like 'ether1' or chip-port .id). Most relevant field is 'l2mtu' on older RouterOS releases where the chip cap needs explicit bumping for jumbo. On RouterOS 7.10+ the chip auto-tracks /interface/ethernet l2mtu; this endpoint is the fallback if your hardware does not. - **GET** `list_bridges` — List bridge interfaces (Layer-2 software switches). Returns name, mtu, protocol-mode (none|rstp|stp|mstp), vlan-filtering, igmp-snooping, fast-forward. - **PUT** `add_bridge` — Create a new bridge interface. At minimum provide name; common options: protocol-mode (rstp), vlan-filtering ('yes' for VLAN-aware bridge). - **PATCH** `update_bridge` — Update bridge properties (name, protocol-mode, vlan-filtering, igmp-snooping, fast-forward, mtu, admin-mac, comment). - **POST** `set_bridge` — Atomically update one or more bridges via CLI-style '/interface/bridge set'. Useful when you need to flip vlan-filtering or protocol-mode on multiple bridges in one transaction. Reference via 'numbers' (bridge name or .id). - **DELETE** `delete_bridge` — Delete a bridge by .id or name. Removes all port memberships. - **GET** `list_bridge_ports` — List bridge port memberships (which interfaces are members of which bridges). Key fields: bridge, interface, pvid, frame-types, ingress-filtering. - **PUT** `add_bridge_port` — Add an interface to a bridge. - **DELETE** `delete_bridge_port` — Remove a port from a bridge. - **POST** `set_bridge_port` — Atomically update one or more bridge ports via CLI-style '/interface/bridge/port set'. Use this instead of PATCH when you need to flip pvid/frame-types/ingress-filtering on many ports together; PATCH on individual bridge-port records can interact awkwardly with hardware offload and slave validation. IMPORTANT (verified 2026-05-25, RouterOS 7.x): 'numbers' MUST be the bridge-port record's .id (e.g. '*2E'). Passing the interface name (e.g. 'ether47') returns HTTP 404 — unlike the CLI, the REST endpoint does NOT resolve interface→bridge-port. Lookup pattern: call list_bridge_ports, find the row where .interface matches the port you want, take its .id, then pass that as 'numbers'. - **GET** `list_bridge_hosts` — List the bridge forwarding database (FDB) — every MAC the bridge has learned, plus where (which port). Fields: mac-address, on-interface, bridge, age, local (yes=our own MAC), external (yes=learned from another switch), dynamic. Essential for debugging "host disappeared" issues — confirms whether the bridge ever saw the MAC. - **GET** `list_bridge_vlans` — List bridge VLAN configurations (which VLAN IDs are tagged/untagged on which bridge ports). Used with vlan-filtering=yes bridges. - **PUT** `add_bridge_vlan` — Configure VLAN tagging on a bridge. - **PATCH** `update_bridge_vlan` — Update an existing bridge-vlan record (tagged/untagged port lists, comment, disabled). KNOWN BROKEN (ToolMesh wrapper bug, 2026-05-25): this PATCH returns HTTP 400 on RouterOS because the wrapper does not percent-encode the leading asterisk in the .id URL segment (e.g. '*6' should be '%2A6'). Reproduced empirically on a freshly-added empty test VLAN with a trivial comment change. WORKAROUND: use set_bridge_vlan (POST /interface/bridge/vlan/set with 'numbers') instead — it passes the .id in the body and is not affected by the bug. See top-of-file 'Known ToolMesh wrapper bugs' note. - **DELETE** `delete_bridge_vlan` — Remove a bridge-vlan record. KNOWN BROKEN (ToolMesh wrapper bug, 2026-05-25): this DELETE returns HTTP 400 — same .id URL-encoding bug as update_bridge_vlan. WORKAROUND: use remove_bridge_vlan (POST /interface/bridge/vlan/remove with 'numbers') instead. - **POST** `set_bridge_vlan` — Update a bridge-vlan record via CLI-style '/interface/bridge/vlan set'. Reference via 'numbers' = the .id of the bridge-vlan record (e.g. '*6'). PREFERRED over update_bridge_vlan until the ToolMesh wrapper bug for PATCH /xxx/{*N-id} URL encoding is fixed — see the top-of-file 'Known ToolMesh wrapper bugs' note. Lookup the .id with list_bridge_vlans first. Note: although the CLI accepts multi-record selectors (e.g. `[find vlan-ids=10,20]`), the REST docs only show single-.id examples for /set. Treat this endpoint as one .id per call; loop in a composite if you need batch. - **POST** `remove_bridge_vlan` — Remove a bridge-vlan record via CLI-style '/interface/bridge/vlan remove'. Reference via 'numbers' = the .id of the bridge-vlan record. PREFERRED over delete_bridge_vlan until the ToolMesh wrapper bug for DELETE /xxx/{*N-id} URL encoding is fixed. Lookup the .id with list_bridge_vlans first. Single .id per call (see set_bridge_vlan note). - **GET** `list_vlan_interfaces` — List VLAN interfaces (802.1Q sub-interfaces). Each has name, vlan-id, interface (parent), mtu. - **PUT** `add_vlan_interface` — Create a VLAN sub-interface on a physical or bridge interface. - **DELETE** `delete_vlan_interface` — Delete a VLAN interface. - **GET** `list_bonding_interfaces` — List bonding (link aggregation) interfaces. Modes: 802.3ad (LACP), balance-rr, balance-xor, broadcast, active-backup, etc. - **PUT** `add_bonding_interface` — Create a bonding interface that aggregates physical Ethernet ports. For switch-side LACP both sides must speak 802.3ad. - **PATCH** `update_bonding_interface` — Update a bonding interface (slaves, mode, lacp-rate, hash policy, comment). - **DELETE** `delete_bonding_interface` — Delete a bonding interface. Member ports return to individual L2 state. - **GET** `list_interface_lists` — List interface lists (named groups of interfaces, used in firewall rules as 'in-interface-list' / 'out-interface-list'). Default lists: WAN, LAN. - **PUT** `add_interface_list` — Create a new interface list. Use to group interfaces for firewall in-/out-interface-list matching. - **DELETE** `delete_interface_list` — Delete an interface list. Firewall rules referencing it will break — audit first. - **GET** `list_interface_list_members` — List members of all interface lists. Key fields: list, interface. - **PUT** `add_interface_list_member` — Add an interface to an interface list. - **DELETE** `delete_interface_list_member` — Remove an interface from an interface list. - **GET** `list_wireless_interfaces` — List legacy wireless interfaces (cAP, hAP ac, RB devices). Each has ssid, mode (ap-bridge|station|station-bridge|bridge), band, channel-width, frequency, security-profile, radio-name, master-interface. Use list_wifi_interfaces for newer cAP ax / hAP ax / Audience devices. - **GET** `list_wireless_security_profiles` — List wireless security profiles (WPA/WPA2/WPA3 PSK and EAP). Key fields: name, mode, authentication-types, wpa2-pre-shared-key, group-ciphers, unicast-ciphers. - **GET** `list_wireless_registrations` — List currently associated wireless clients (CAPsMAN/wireless). Returns mac-address, interface, signal-strength, tx-rate, rx-rate, uptime. - **GET** `list_wifi_interfaces` — List newer 802.11ax wifi interfaces (cAP ax, hAP ax, Audience family). Newer stack than /interface/wireless. - **GET** `list_wifi_registrations` — List clients connected to the new wifi stack interfaces. - **POST** `monitor_wifi` — Sample current wifi interface state (channel, tx-rate, noise floor). ALWAYS pass once=''. - **GET** `list_lte_interfaces` — List LTE/cellular modem interfaces. Each has name, apn, pin, network-mode, status, imei. - **POST** `set_lte_interface` — Update an LTE modem interface (APN, network selection, PIN, name). Reference via 'numbers' (lte interface name). Carrier change normally triggers a brief re-attach (5-10s). For per-APN profile work see /interface/lte/apn (singleton APN list is queryable via the modem itself). - **POST** `monitor_lte` — Sample LTE modem state (signal RSSI/RSRP/RSRQ, technology, current-operator, cell-id). ALWAYS pass once=''. - **GET** `list_wireguard_interfaces` — List WireGuard VPN interfaces. Each has name, public-key, private-key (hidden unless 'sensitive' policy), listen-port, mtu. - **PUT** `add_wireguard_interface` — Create a WireGuard interface. RouterOS auto-generates a key pair if private-key is omitted. - **PATCH** `update_wireguard_interface` — Update a WireGuard interface (listen-port, private-key, mtu, comment, disabled). Rotating private-key requires re-distributing the resulting public-key to every peer — handle with care. - **DELETE** `delete_wireguard_interface` — Delete a WireGuard interface. ALL associated peers are removed implicitly. - **GET** `list_wireguard_peers` — List configured WireGuard peers. Key fields: interface, public-key, endpoint-address, endpoint-port, allowed-address, last-handshake, rx, tx, current-endpoint-address. - **PUT** `add_wireguard_peer` — Add a WireGuard peer to an interface. - **PATCH** `update_wireguard_peer` — Update a WireGuard peer (allowed-address, endpoint, keepalive, comment, disabled). - **DELETE** `delete_wireguard_peer` — Remove a WireGuard peer. - **GET** `list_ip_addresses` — List all configured IPv4 addresses with address (CIDR), network, interface, dynamic (yes for DHCP-acquired), disabled, comment. - **PUT** `add_ip_address` — Assign an IPv4 address to an interface. - **PATCH** `update_ip_address` — Update an IP address record (address, interface, comment, disabled). - **DELETE** `delete_ip_address` — Remove an IPv4 address. May disconnect remote sessions if the deleted address is the management IP. - **GET** `list_ip_routes` — List the IPv4 routing table. Each route has dst-address (CIDR), gateway, distance, scope, target-scope, routing-mark, active, dynamic, suppress-hw-offload. Filter active=true to see only currently used routes. - **PUT** `add_ip_route` — Add a static IPv4 route. Default route: dst-address='0.0.0.0/0' with a gateway. - **PATCH** `update_ip_route` — Update a static route. - **DELETE** `delete_ip_route` — Delete a static route. - **GET** `list_ip_arp` — List the ARP (IPv4-to-MAC) table. Includes static and dynamic entries with address, mac-address, interface, complete (yes/no), dynamic. - **PUT** `add_ip_arp` — Add a static ARP entry (useful for ARP reply-only mode). - **DELETE** `delete_ip_arp` — Remove an ARP entry. - **GET** `list_ip_neighbors` — List devices discovered via MNDP/CDP/LLDP on directly connected interfaces. Useful for topology discovery. - **GET** `list_ip_services` — List the management services and their state: api, api-ssl, ftp, ssh, telnet, winbox, www (HTTP), www-ssl (HTTPS REST). Each has port, address (allowed source CIDR), disabled, certificate, tls-version. - **POST** `set_ip_service` — Update a management service (enable/disable, change port, restrict source 'address' list, bind to certificate). NOTE: /ip/service is one of the few RouterOS endpoints that does NOT support PATCH -- use this POST /set form (mirrors the CLI '/ip/service set ...' command). Reference services via 'numbers' as the service name (e.g. 'telnet', 'www-ssl') or .id ('*0'). Be careful disabling the service you are currently connected through. - **POST** `disable_ip_service` — Convenience wrapper to disable one or more services. Pass service name(s) or .id(s) as comma-separated 'numbers'. - **POST** `enable_ip_service` — Convenience wrapper to enable one or more services. Pass service name(s) or .id(s) as comma-separated 'numbers'. - **GET** `list_ip_pools` — List IP address pools (used by DHCP server, PPP server, etc.). Each has name, ranges (CIDR or IP range), next-pool. - **GET** `get_ip_cloud` — Get MikroTik IP Cloud (dynamic DNS) status: ddns-enabled, dns-name (xxxxx.sn.mynetname.net), public-address, status. - **POST** `set_ip_cloud` — Update MikroTik IP Cloud (dynamic DNS) settings. Singleton — toggle ddns-enabled='yes' to register the device's WAN IP with mynetname.net. Disable update-time='yes' if you do NOT want IP Cloud to push device time (e.g. when you have your own NTP servers). - **GET** `get_dns_settings` — Get DNS resolver settings: servers (upstream), dynamic-servers, allow-remote-requests, cache-size, max-concurrent-queries. - **POST** `update_dns_settings` — Update DNS resolver settings. - **GET** `list_dns_static` — List static DNS entries (local DNS records). Each has name, type (A|AAAA|CNAME|NS|MX|SRV|TXT), address/cname/target, ttl. - **PUT** `add_dns_static` — Add a static DNS entry. Use either name+address (A record) or name+cname. - **PATCH** `update_dns_static` — Update a static DNS entry. - **DELETE** `delete_dns_static` — Remove a static DNS entry. - **GET** `list_dns_cache` — List currently cached DNS resolutions on the device. - **POST** `flush_dns_cache` — Clear the DNS resolver cache. - **GET** `list_dhcp_servers` — List DHCP server instances. Each has name, interface, address-pool, lease-time, authoritative, disabled. - **PUT** `add_dhcp_server` — Create a DHCP server. Requires interface and address-pool. - **PATCH** `update_dhcp_server` — Update a DHCP server. - **POST** `set_dhcp_server` — Atomically update one or more DHCP server instances via CLI-style '/ip/dhcp-server set'. Reference via 'numbers' (server name or .id). Use this when changing lease-time / authoritative across multiple servers in one go. - **DELETE** `delete_dhcp_server` — Delete a DHCP server instance. Clients will fail to renew leases. - **GET** `list_dhcp_leases` — List DHCP leases (both dynamic and static reservations). Key fields: address, mac-address, server, host-name, dynamic (yes/no), status (bound | waiting | offered | expired), last-seen, comment. - **PUT** `add_dhcp_lease` — Create a static DHCP reservation. - **DELETE** `delete_dhcp_lease` — Delete a DHCP lease/reservation. - **POST** `make_dhcp_lease_static` — Convert a dynamic DHCP lease into a static reservation. Most common workflow for reserving an IP for a known device. - **GET** `list_dhcp_networks` — List DHCP network options (subnet, gateway, dns-server, ntp-server, domain) advertised to clients. - **PUT** `add_dhcp_network` — Add DHCP network options for a subnet. - **PATCH** `update_dhcp_network` — Update a DHCP server network (gateway, dns, ntp, domain, comment). - **DELETE** `delete_dhcp_network` — Remove a DHCP server network. Existing leases remain but new clients will get no options. - **GET** `list_dhcp_clients` — List DHCP client instances. Each has interface, status (bound|searching|stopped), address, gateway, primary-dns, secondary-dns, expires-after. - **PUT** `add_dhcp_client` — Enable a DHCP client on an interface (typical WAN setup). - **PATCH** `update_dhcp_client` — Update a DHCP client (interface, add-default-route, use-peer-dns, etc.). - **DELETE** `delete_dhcp_client` — Delete a DHCP client. WAN-side delete may sever connectivity — confirm before invoking. - **POST** `release_dhcp_client` — Release the current lease on a DHCP client and re-discover. Brief connectivity drop expected. - **POST** `renew_dhcp_client` — Force a DHCP renew on a client. Useful when DNS/gateway info has changed on the upstream server. - **GET** `list_firewall_filter` — List IPv4 firewall filter rules. Each rule has chain (input|forward|output|<custom>), action (accept|drop|reject|jump|log|...), protocol, src-address, dst-address, src-port, dst-port, in-interface, out-interface, connection-state, comment. Rules are evaluated TOP-TO-BOTTOM per chain. - **PUT** `add_firewall_filter` — Add an IPv4 firewall filter rule. Required: chain and action. New rules are appended to the END of the chain -- use move_firewall_filter to reorder. - **PATCH** `update_firewall_filter` — Update an existing filter rule (any field). - **DELETE** `delete_firewall_filter` — Delete a filter rule. Removing an accept rule can lock you out -- check before deleting. - **POST** `move_firewall_filter` — Reorder filter rules. Move rule(s) in 'numbers' to position before 'destination'. - **GET** `list_firewall_nat` — List IPv4 NAT rules (srcnat/dstnat). Common actions: masquerade (srcnat to outgoing interface), dst-nat (port forward), src-nat, redirect. - **PUT** `add_firewall_nat` — Add a NAT rule. Common patterns -- Masquerade (LAN to WAN): {chain:'srcnat',action:'masquerade',out-interface-list:'WAN'}. Port forward (DNAT): {chain:'dstnat',action:'dst-nat',protocol:'tcp',dst-port:'80',in-interface:'ether1',to-addresses:'192.168.1.10',to-ports:'8080'}. - **PATCH** `update_firewall_nat` — Update a NAT rule. - **DELETE** `delete_firewall_nat` — Delete a NAT rule. Removing masquerade can break LAN-to-WAN traffic. - **POST** `move_firewall_nat` — Reorder NAT rules. Move rule(s) in 'numbers' to position before 'destination'. - **GET** `list_firewall_mangle` — List mangle rules (packet marking, MSS clamping, TTL, DSCP). Chains: prerouting, postrouting, input, forward, output. - **PUT** `add_firewall_mangle` — Add a mangle rule (mark-packet, mark-connection, change-mss, change-ttl, change-dscp, ...). - **PATCH** `update_firewall_mangle` — Update a mangle rule (any field). - **DELETE** `delete_firewall_mangle` — Delete a mangle rule. Removing mark-routing rules can break policy routing. - **POST** `move_firewall_mangle` — Reorder mangle rules. Move rule(s) in 'numbers' to position before 'destination'. - **GET** `list_firewall_raw` — List firewall raw rules (pre-conntrack, used for DDoS mitigation and bypassing connection tracking). - **PUT** `add_firewall_raw` — Add a raw firewall rule. Raw rules run BEFORE connection-tracking and are evaluated for every packet — keep them lean. Common patterns: notrack for high-volume known-good traffic, drop for known-bad source IPs, ICMP rate-limit pre-conntrack. - **PATCH** `update_firewall_raw` — Update a raw firewall rule. - **DELETE** `delete_firewall_raw` — Delete a raw firewall rule. - **POST** `move_firewall_raw` — Reorder raw firewall rules. Move rule(s) in 'numbers' to position before 'destination'. - **GET** `list_firewall_address_lists` — List firewall address-list entries (named groups of IPs/CIDRs used by other firewall rules). - **PUT** `add_firewall_address_list` — Add an entry to a firewall address-list. - **PATCH** `update_firewall_address_list` — Update an existing address-list entry (address, list, timeout, comment). - **DELETE** `delete_firewall_address_list` — Remove an entry from an address-list. - **GET** `list_firewall_connections` — List currently tracked connections (connection-tracking table). Key fields: src-address, dst-address, protocol, tcp-state, timeout, orig-bytes, repl-bytes, reply-src-address (for NAT), reply-dst-address. - **GET** `list_ipv6_addresses` — List configured IPv6 addresses. Includes link-local (FE80::/10), GUA, and ULA addresses. - **PUT** `add_ipv6_address` — Assign an IPv6 address to an interface. - **PATCH** `update_ipv6_address` — Update an IPv6 address record. - **DELETE** `delete_ipv6_address` — Remove an IPv6 address. - **GET** `list_ipv6_routes` — List the IPv6 routing table. - **PUT** `add_ipv6_route` — Add a static IPv6 route. Default route: dst-address='::/0' with a gateway. - **PATCH** `update_ipv6_route` — Update a static IPv6 route. - **DELETE** `delete_ipv6_route` — Delete a static IPv6 route. - **GET** `list_ipv6_firewall_filter` — List IPv6 firewall filter rules. Same chain/action semantics as IPv4. - **PUT** `add_ipv6_firewall_filter` — Add an IPv6 firewall filter rule. Required: chain and action. - **PATCH** `update_ipv6_firewall_filter` — Update an IPv6 firewall filter rule. - **DELETE** `delete_ipv6_firewall_filter` — Delete an IPv6 firewall filter rule. - **POST** `move_ipv6_firewall_filter` — Reorder IPv6 filter rules. Move rule(s) in 'numbers' to position before 'destination'. - **GET** `list_ipv6_neighbors` — List the IPv6 neighbor table (NDP, equivalent to ARP for IPv6). - **GET** `list_ipv6_nd` — List IPv6 Neighbor Discovery / Router Advertisement settings per interface (M, O flags, RA interval, RA lifetime, MTU). This controls RA SENDING (the device acting as an IPv6 router for its LAN), not RA receiving (SLAAC client behavior). For SLAAC client behavior, see get_ipv6_settings / set_ipv6_settings. - **GET** `get_ipv6_settings` — Get the global IPv6 stack settings. Key fields: disable-ipv6 (yes/no), forward (yes/no -- 'yes' makes the device a router; 'no' a host), accept-router-advertisements (yes | no | yes-if-forwarding-disabled -- the last is the default and means the device accepts RAs only when acting as a host), accept-redirects, max-neighbor-entries, soft-headers, multipath-hash-policy. SLAAC client behavior requires forward='no' AND accept-router-advertisements in {yes, yes-if-forwarding-disabled}. - **POST** `set_ipv6_settings` — Update global IPv6 settings. To enable SLAAC on a host/L2-switch: {forward:'no', accept-router-advertisements:'yes'}. Note: changing 'forward' may affect routing behavior across all interfaces -- do this only on devices that should NOT route IPv6 (e.g. switches, end hosts). - **GET** `list_ipv6_dhcp_clients` — List DHCPv6 clients (stateful IPv6 address/prefix from a DHCPv6 server). SLAAC (RA-only) does NOT show up here -- only DHCPv6 client instances do. Each entry has interface, request (address|prefix), status, address, prefix. - **GET** `list_ppp_secrets` — List PPP user accounts (used for PPPoE/L2TP/SSTP/PPTP/OVPN servers). Each has name, password (hidden), profile, service, local-address, remote-address. - **PUT** `add_ppp_secret` — Create a PPP user account. - **PATCH** `update_ppp_secret` — Update a PPP user (password, profile, service, addresses, comment, disabled). - **DELETE** `delete_ppp_secret` — Delete a PPP user account. - **GET** `list_ppp_active` — List currently connected PPP sessions (active PPPoE/L2TP/SSTP/PPTP/OVPN clients). Includes name, service, address, uptime, encoding, caller-id. - **GET** `list_ppp_profiles` — List PPP profiles (templates for sessions: local-address, remote-address pool, dns-server, rate-limit, encryption). - **PUT** `add_ppp_profile` — Create a PPP profile. Use to template L2TP/SSTP/PPTP/OVPN session settings (DNS, address pool, rate-limit, encryption). - **PATCH** `update_ppp_profile` — Update a PPP profile. - **DELETE** `delete_ppp_profile` — Delete a PPP profile. Cannot delete 'default' or 'default-encryption' built-in profiles. - **GET** `list_routing_table` — List routing tables (multi-table support in RouterOS 7). Default is 'main'; custom tables used with routing-mark. - **GET** `list_bgp_peers` — List BGP peer connections (RouterOS 7 BGP). Each has name, remote.address, remote.as, local.address, local.role, established. - **PUT** `add_bgp_connection` — Add a BGP peer connection (RouterOS 7 BGP). Required: name and remote.address. Use templates for common AS/role config and reference via 'template='. - **PATCH** `update_bgp_connection` — Update a BGP peer connection. - **DELETE** `delete_bgp_connection` — Delete a BGP peer connection. Will tear down the BGP session immediately. - **GET** `list_bgp_sessions` — List currently established BGP sessions with state, uptime, prefix-count, last-error. - **GET** `list_bgp_templates` — List BGP templates (reusable peer-config bundles). RouterOS 7 BGP requires at least one template — usually 'default'. - **GET** `list_ospf_instances` — List OSPF instances. Each has name, version, router-id, vrf. - **PUT** `add_ospf_instance` — Create an OSPF instance (RouterOS 7). Required: name, router-id, version (default '2' for OSPFv2). - **DELETE** `delete_ospf_instance` — Delete an OSPF instance. All adjacencies in this instance go down. - **GET** `list_ospf_areas` — List OSPF areas. Each binds an instance to an area-id and type (default | stub | nssa | backbone). - **PUT** `add_ospf_area` — Create an OSPF area (RouterOS 7). - **DELETE** `delete_ospf_area` — Delete an OSPF area. - **GET** `list_ospf_interface_templates` — List OSPF interface templates (which interfaces speak OSPF, in which area, with which cost/network type). - **GET** `list_ospf_neighbors` — List OSPF neighbors with router-id, address, area, state (Down|Init|2-Way|ExStart|Exchange|Loading|Full), priority. - **GET** `list_routing_filters` — List routing-filter rules (RouterOS 7 unified filter system). Each rule belongs to a chain (referenced from BGP/OSPF in/out filter-chain fields). Fields: chain, rule (filter DSL: 'if (...) {...}'), comment, disabled. - **PUT** `add_routing_filter` — Add a routing-filter rule. RouterOS 7 uses a unified rule DSL across all protocols. Example: chain='bgp-in', rule='if (dst in 0.0.0.0/0) { accept } reject'. Rules in a chain are evaluated top-to-bottom. - **PATCH** `update_routing_filter` — Update a routing-filter rule. - **DELETE** `delete_routing_filter` — Delete a routing-filter rule. Removing a deny-all leaf can flood the route table — audit first. - **GET** `list_simple_queues` — List simple queues (per-IP/per-subnet bandwidth limits). Each has name, target (IP/CIDR/interface), max-limit, burst-limit, parent, queue (queue-type). - **PUT** `add_simple_queue` — Add a simple queue for bandwidth shaping. - **PATCH** `update_simple_queue` — Update a simple queue. - **DELETE** `delete_simple_queue` — Remove a simple queue. - **GET** `list_queue_tree` — List queue tree entries (HTB-based hierarchical shaping using packet marks from mangle). - **GET** `list_queue_types` — List queue disciplines (default-small, default, ethernet-default, wireless-default, fq-codel, cake, pcq, sfq, red, pfifo, bfifo). - **POST** `ping` — Send ICMP echo requests to a target. CRITICAL: always pass count (1-10) to bound runtime -- the REST API has a 60s hard timeout. Each iteration is returned as one object in the response array. - **POST** `traceroute` — Trace the network path to a target. ALWAYS set count and timeout to bound runtime. Returns one row per hop with address, loss, sent, last, avg, best, worst. - **POST** `bandwidth_test` — Run a bandwidth test against another MikroTik device (target must run bandwidth-server). ALWAYS pass duration to bound runtime. Resource-intensive. - **GET** `list_netwatch` — List netwatch monitors (ICMP/TCP/HTTP/HTTPS uptime checks against external hosts). Each has host, status (up|unknown|down), type, since. - **PUT** `add_netwatch` — Create a netwatch monitor. - **PATCH** `update_netwatch` — Update a netwatch monitor (host, type, interval, scripts, port, http-codes, comment, disabled). - **DELETE** `delete_netwatch` — Remove a netwatch monitor. - **GET** `get_email_settings` — Get the SMTP client settings. Singleton — required for send_email and for the 'email' /system/logging/action. Fields: server, port, start-tls, user, password (hidden), from, vrf. - **POST** `set_email_settings` — Update the SMTP client settings. RouterOS 7.13+ uses the field 'tls' (no | starttls | tls-only); older releases used 'start-tls' as a boolean — both are accepted on 7.13+ for backward compatibility but prefer 'tls'. STARTTLS submission (port 587): {server:'smtp.example.com', port:'587', tls:'starttls', user:'noreply@x', password:'<pwd>', from:'router@x'}. Implicit TLS (port 465): tls='tls-only'. Cleartext (port 25): tls='no'. - **POST** `send_email` — Send an email via the configured /tool/e-mail SMTP settings. Useful for alerting from scripts/scheduler. - **GET** `list_users` — List local user accounts. Each has name, group, address (allowed source CIDR), last-logged-in, disabled. - **GET** `get_user` — Get a single user by name or .id. - **PUT** `add_user` — Create a local user. - **PATCH** `update_user` — Update a user (password, group, source restriction, comment, disabled). - **DELETE** `delete_user` — Delete a user. Cannot delete the user you're authenticated as. - **GET** `list_user_groups` — List user groups (named bundles of policies). Default groups: read, write, full. Each has name and policy field (comma-separated). - **PUT** `add_user_group` — Create a custom user group with specific policies. - **PATCH** `update_user_group` — Update an existing user group's policies, skin, or comment. Cannot rename built-in 'read', 'write', 'full' groups. - **DELETE** `delete_user_group` — Delete a custom user group. Built-in groups (read/write/full) cannot be deleted. Users assigned to a deleted group are orphaned — re-assign first. - **GET** `list_active_users` — List currently authenticated user sessions. Includes name, address (source IP), via (ssh|winbox|webfig|api|rest|console), when. - **GET** `list_user_ssh_keys` — List installed SSH public keys for user authentication. - **POST** `import_user_ssh_key` — Import an SSH public key from a file in /file for a user. - **GET** `list_certificates` — List installed certificates and CAs. Each has name, common-name, subject-alt-name, issuer, expires-after, days-valid, fingerprint, private-key (yes/no). - **POST** `sign_certificate` — Sign a certificate request with a CA certificate. Used in PKI workflows. - **POST** `import_certificate` — Import a certificate from a file in /file (PEM or PKCS#12). - **GET** `list_files` — List files stored on the device flash. Includes name, type (file|directory|disk|.backup|.rsc|.crt|.key|.umb), size, creation-time. - **DELETE** `delete_file` — Delete a file from device flash. Cannot delete in-use files. - **GET** `list_logs` — List system log entries. Each has time, topics (e.g. 'system,info'), message. Logs are circular -- old entries are overwritten. Filter by topics= via query for targeted lookups. - **GET** `list_logging_rules` — List logging rules — each routes a topic pattern to an action. Fields: topics (comma-separated AND-list, '!' to negate), action (action name, e.g. 'memory', 'remote', 'graylog'), prefix, regex, disabled. Rules are evaluated for every log line; matching is a logical OR across multiple rules. - **PUT** `add_logging_rule` — Add a logging rule. Most common pattern for remote forwarding: {topics:'', action:'remote'} forwards EVERY topic to the remote action. Narrower: {topics:'system,info', action:'graylog'} forwards only system-info lines. Negation: {topics:'firewall,!debug', ...} excludes debug-severity firewall messages. - **PATCH** `update_logging_rule` — Update a logging rule (topics, action, prefix, regex, comment, disabled). - **DELETE** `delete_logging_rule` — Delete a logging rule. The 5 default actions remain available; only your custom rules are removed. - **GET** `list_logging_actions` — List logging actions — destinations for log lines. RouterOS ships with 5 default actions that CANNOT be deleted or renamed: memory, disk, echo, remote, email. Add new actions for additional targets (multiple Graylog inputs, secondary syslog, etc.). - **PUT** `add_logging_action` — Add a logging action (destination). Common pattern for Graylog (CEF over TCP): {name:'graylog', target:'remote', remote:'192.168.100.15', remote-port:'514', remote-protocol:'tcp', remote-log-format:'cef', syslog-time-format:'iso8601'}. For a second memory ring buffer: {name:'audit', target:'memory', memory-lines:'5000'}. - **PATCH** `update_logging_action` — Update a custom logging action. NOTE: for the 5 built-in actions (memory, disk, echo, remote, email) PATCH on the path is unreliable — use set_logging_action with numbers='remote' (etc.) instead. - **POST** `set_logging_action` — Atomically update one or more logging actions via CLI-style '/system/logging/action set'. THIS IS THE WAY to re-aim the built-in 'remote' or 'email' actions: {numbers:'remote', remote:'10.0.0.5', remote-protocol:'tcp', remote-log-format:'cef'} — the built-ins can be re-configured but not renamed/deleted. Reference via 'numbers' (action name or .id). - **DELETE** `delete_logging_action` — Delete a custom logging action. The 5 default actions (memory/disk/echo/remote/email) cannot be deleted. - **GET** `get_snmp_settings` — Get SNMP agent settings: enabled, contact, location, engine-id, src-address, trap-target. - **POST** `update_snmp_settings` — Update SNMP agent settings. - **GET** `list_snmp_communities` — List SNMP v1/v2c communities and v3 users. Includes name, addresses (source CIDRs), security, read-access, write-access. - **GET** `get_l2tp_server` — Get L2TP server config (singleton). Fields: enabled, max-mtu, max-mru, mrru, authentication (comma list of mschap2,mschap1,chap,pap), default-profile, use-ipsec ('no'|'yes'|'required'), ipsec-secret, caller-id-type, allow-fast-path. - **POST** `set_l2tp_server` — Update L2TP server config. To enable plain L2TP: {enabled:'yes', authentication:'mschap2', default-profile:'default-encryption'}. For L2TP/IPsec: {enabled:'yes', use-ipsec:'required', ipsec-secret:'<psk>'}. Per-user accounts live in /ppp/secret with service='l2tp'. - **GET** `get_sstp_server` — Get SSTP server config (singleton). Fields: enabled, port, certificate, authentication, default-profile, max-mtu, max-mru, mrru, tls-version, verify-client-certificate, force-aes. - **POST** `set_sstp_server` — Update SSTP server config. Required: a TLS certificate (certificate=<name>). Default port is 443 — make sure it does NOT collide with www-ssl (REST API). Common: {enabled:'yes', certificate:'sstp-cert', port:'8443', authentication:'mschap2', default-profile:'default-encryption'}. - **GET** `get_pptp_server` — Get PPTP server config (singleton). Fields: enabled, max-mtu, max-mru, mrru, authentication, default-profile, keepalive-timeout. NOTE: PPTP is cryptographically broken — use L2TP/IPsec, SSTP, or WireGuard for new deployments. - **POST** `set_pptp_server` — Update PPTP server config. Discouraged for new deployments. - **GET** `get_ovpn_server` — Get OpenVPN server config (singleton). Fields: enabled, port, mode, netmask, mac-address, max-mtu, certificate, require-client-certificate, auth (md5|sha1|sha256|sha512), cipher (blowfish128|aes128-cbc|aes192-cbc|aes256-cbc|aes128-gcm|aes192-gcm|aes256-gcm), default-profile, tls-version, redirect-gateway. - **POST** `set_ovpn_server` — Update OpenVPN server config. RouterOS supports TCP only (no UDP). Modern interop: {enabled:'yes', mode:'ip', port:'1194', certificate:'ovpn-cert', require-client-certificate:'yes', auth:'sha256', cipher:'aes256-gcm,aes256-cbc', default-profile:'default-encryption'}. - **GET** `list_ipsec_peers` — List IPsec peers. Each peer = remote endpoint + auth method + exchange-mode. Fields: name, address, profile, exchange-mode (ike2 recommended), passive, send-initial-contact, comment, disabled. - **PUT** `add_ipsec_peer` — Add an IPsec peer. For IKEv2 modern setup: {name:'site-a', address:'203.0.113.5/32', profile:'default', exchange-mode:'ike2'}. - **PATCH** `update_ipsec_peer` — Update an IPsec peer. - **DELETE** `delete_ipsec_peer` — Delete an IPsec peer. Tears down all SAs to that peer. - **GET** `list_ipsec_identities` — List IPsec identities — bind peers to auth credentials + mode-config + policy template. - **PUT** `add_ipsec_identity` — Add an IPsec identity (peer + auth credentials). For PSK: {peer:'site-a', auth-method:'pre-shared-key', secret:'<psk>'}. For IKEv2 EAP: {peer:'rw', auth-method:'eap', eap-methods:'eap-mschapv2', username:'alice', password:'<pwd>'}. - **PATCH** `update_ipsec_identity` — Update an IPsec identity. - **DELETE** `delete_ipsec_identity` — Delete an IPsec identity. - **GET** `list_ipsec_profiles` — List IPsec IKE profiles (Phase-1 / IKE_SA_INIT proposals). Each has name, hash-algorithm, enc-algorithm, dh-group, lifetime, nat-traversal. - **PUT** `add_ipsec_profile` — Add an IPsec profile. Modern IKEv2: {name:'strong', hash-algorithm:'sha256', enc-algorithm:'aes-256', dh-group:'modp2048,ecp256', lifetime:'1d', nat-traversal:'yes'}. - **PATCH** `update_ipsec_profile` — Update an IPsec profile. - **DELETE** `delete_ipsec_profile` — Delete an IPsec profile. Cannot delete 'default'. - **GET** `list_ipsec_proposals` — List IPsec ESP/AH proposals (Phase-2 / CHILD_SA crypto). Each has name, auth-algorithms, enc-algorithms, pfs-group, lifetime. - **PUT** `add_ipsec_proposal` — Add an IPsec ESP/AH proposal. - **PATCH** `update_ipsec_proposal` — Update an IPsec proposal. - **DELETE** `delete_ipsec_proposal` — Delete an IPsec proposal. Cannot delete 'default'. - **GET** `list_ipsec_policies` — List IPsec policies. Each policy = src/dst selector + action (encrypt|none|discard) + proposal + peer. - **PUT** `add_ipsec_policy` — Add an IPsec policy. Static site-to-site: {peer:'site-a', src-address:'10.0.0.0/24', dst-address:'10.1.0.0/24', action:'encrypt', tunnel:'yes', proposal:'default', sa-src-address:'<local>', sa-dst-address:'<peer>'}. Road-warrior dynamic template: {peer:'rw', template:'yes', dst-address:'0.0.0.0/0', action:'encrypt'}. - **PATCH** `update_ipsec_policy` — Update an IPsec policy. - **DELETE** `delete_ipsec_policy` — Delete an IPsec policy. Active SAs are torn down. - **GET** `list_ipsec_active_peers` — List currently negotiated IPsec peers. Fields: id, state (established | half-open | ...), uptime, side, remote-address, dynamic-address. - **GET** `list_ipsec_installed_sa` — List currently installed IPsec SAs (Phase-2 ESP/AH security associations). Useful for debugging which selectors negotiated and how much data has flowed. - **POST** `flush_ipsec_sa` — Tear down all currently installed IPsec SAs. They will renegotiate on next traffic. Use to recover from stuck SA state. - **GET** `get_ipsec_settings` — Get global IPsec settings (singleton). Fields: accept-redirects, interim-update, max-events-per-second, xauth-use-radius. - **POST** `set_ipsec_settings` — Update global IPsec settings. - **GET** `list_containers` — List Docker-like containers configured on RouterOS (v7.4+ on supported hardware). Each has name, root-dir, mounts, interface, status, dns. - **GET** `list_container_envs` — List container environment variables defined for use across containers. - **GET** `list_container_mounts` — List defined container mount points (host directory to container path mappings). ## Which DADLs are related to Mikrotik? - [PeeringDB](https://www.dadl.ai/d/peeringdb/) — PeeringDB v2 API -- the public peering database of networks (ASNs), Internet Exchanges, and colocation facilities: full CRUD over net, ix, fac, org, carrier, campus, point-of-contact records, and the netixlan/netfac/ixfac/carrierfac/ixlan/ixpfx relationships that map who peers where - [Alertmanager](https://www.dadl.ai/d/alertmanager/) — Prometheus Alertmanager API v2 -- alerts, silences, receivers, alert groups, status, and operational health - [Checkmk](https://www.dadl.ai/d/checkmk/) — Checkmk REST API (version 1.0, Checkmk 2.4) -- live host and service status via Livestatus queries, downtimes, acknowledgements and comments, the Event Console (list, acknowledge, change state and archive events) and BI (packs, rules, aggregations and live aggregation state), plus the full Setup side: hosts, clusters, folders, service discovery, rules and rulesets, host/service/contact groups, users, roles, passwords, time periods, host tags, notification rules, site connections and change activation. - [NetBox](https://www.dadl.ai/d/netbox/) — NetBox DCIM/IPAM API -- full v4 coverage: sites, racks, devices, modules, interfaces, cables, power, IPAM (prefixes, IPs, VLANs, VRFs, route-targets, VLAN translation), virtualization, circuits (including virtual circuits), tenants, contacts, VPN (IKE/IPSec/L2VPN), wireless, extras (webhooks, event-rules, scripts, config-templates, bookmarks, notifications), users/permissions/tokens, and core data sources & jobs - [Opnsense](https://www.dadl.ai/d/opnsense/) — OPNsense firewall REST API — manage firewall rules, aliases, interfaces, VPN, DHCP, DNS, diagnostics, firmware, and services on OPNsense appliances - [Xen Orchestra](https://www.dadl.ai/d/xen-orchestra/) — Xen Orchestra REST API (XO 6.4+, current through 6.9) -- complete coverage: VMs (incl. PATCH update + snapshot revert), VM controllers, hosts (incl. full power/lifecycle actions + maintenance mode + PIF rescan), pools (incl. add_host, rolling reboot/update with interrupted-update recovery + finalize), storage (SR create/delete, VDI incl. PATCH update + vhd/raw/qcow2 export, VBD), networks (VIF incl. PATCH update + PIF/PBD), VM/VDI snapshots, VM templates, hardware (PCI/PGPU/SM), tasks, backups (archives incl. live mount of backup disks, jobs/logs, repositories incl. health + benchmark + space reclaim), schedules, messages, alarms, events (SSE incl. non-XAPI collections), RBAC v2 (users/groups/acl-roles/acl-privileges incl. assignment introspection), proxies, servers, dashboards, SDN traffic rules (add/delete/update), IPMI sensor inventory (plugin), audit records (plugin), health check --- **Canonical URL:** https://www.dadl.ai/d/mikrotik/ **Raw DADL:** https://github.com/DunkelCloud/dadl-registry/blob/main/mikrotik.dadl --- # NetBox MCP Server — 608 tools via DADL The NetBox DADL turns NetBox's API into an MCP server that Claude, GPT or any MCP-compatible agent can consume directly. One YAML file declares all 608 tools — virtual, circuit, device, module, vlan, contact, and more — and ToolMesh serves them at runtime. No Python boilerplate, no per-endpoint code, no separate MCP server process. Below: the endpoint coverage matrix, a two-block ToolMesh setup, the full tool reference grouped by NetBox feature area, required credential scopes. **Source:** [NetBox REST API](https://netboxlabs.com/docs/netbox/integrations/rest-api/) **Updated:** 2026-08-15 **Tags:** cloud, devops, networking, crud, user-management, file-management, logging, documentation, auth:bearer ## Which NetBox endpoints are covered? **98%** (608 of ~620 endpoints). **Focus:** DCIM full v4: sites, site-groups, regions, locations, racks (with elevation, roles, types, reservations), manufacturers, device-types, device-roles, platforms, devices, modules, module-types, module-bays, device-bays, virtual-chassis, virtual-device-contexts, inventory-items, inventory-item-roles, interfaces, cables, cable-terminations, all port types (console, console-server, power, power-outlet, front, rear) with trace/paths actions, power-panels, power-feeds, mac-addresses, connected-device lookup, and the complete component-template family. IPAM full v4: prefixes (with available-prefixes/available-ips), ip-addresses, ip-ranges (with available-ips), vlans, vlan-groups (with available-vlans), vrfs, route-targets, aggregates, rirs, asns, asn-ranges (with available-asns), roles, services, service-templates, vlan-translation-policies, vlan-translation-rules, fhrp-groups, fhrp-group-assignments. Virtualization full v4: clusters, cluster-types, cluster-groups, virtual-machines, virtual-machine-types, vm-interfaces, virtual-disks. Tenancy full v4: tenants, tenant-groups, contacts, contact-roles, contact-groups, contact-assignments. Circuits full v4: providers, provider-accounts, provider-networks, circuit-types, circuits, circuit-terminations (with paths), circuit-groups, circuit-group-assignments, virtual-circuits, virtual-circuit-types, virtual-circuit-terminations. Wireless full v4: wireless-lan-groups, wireless-lans, wireless-links. VPN full v4: tunnel-groups, tunnels, tunnel-terminations, ike-proposals, ike-policies, ipsec-proposals, ipsec-policies, ipsec-profiles, l2vpns, l2vpn-terminations. Extras: tags, custom-fields, custom-field-choice-sets, custom-links, saved-filters, export-templates, journal-entries, object-changes, config-contexts, config-templates (+render), webhooks, event-rules, scripts (+run), bookmarks, notifications, notification-groups, subscriptions, image-attachments, dashboard. Users: users, groups, permissions, tokens (+provision). Core: data-sources (+sync), data-files, jobs, object-types, background-queues/workers/tasks. **Missing:** Read-only listing of background-tasks with action endpoints (delete/requeue/enqueue/stop) -- rarely used outside debugging. Plugin-specific endpoints under /api/plugins/ -- those depend on installed plugins and are out of scope for a general DADL. table-configs, config-context-profiles, tagged-objects, and the authentication-check endpoint -- minor utility endpoints. Bulk update/delete on list endpoints (PUT/PATCH/DELETE on collections) -- prefer per-object operations in Code Mode. *Last reviewed: 2026-08-15* ## How do you configure the NetBox DADL? 1. Log in to your NetBox instance as an admin user 2. Navigate to your user profile (top-right) -> API Tokens 3. Click 'Add a token' and configure permissions 4. For full access: leave 'Write enabled' checked, no IP restrictions 5. Copy the generated token -- it is shown only once (v2 tokens) 6. v2 tokens start with 'nbt_' -- enter only the token value, ToolMesh adds the auth header automatically **Environment variable:** `CREDENTIAL_NETBOX_TOKEN` [Authentication docs](https://netboxlabs.com/docs/netbox/integrations/rest-api/) *The url in backends.yaml must include /api (e.g. https://netbox.example.com/api). Enter only the raw token value (e.g. nbt_xxx) -- ToolMesh handles the Authorization header. Swagger docs at /api/schema/swagger-ui/.* ## How do you install the NetBox MCP server with ToolMesh? Add to your `backends.yaml`: ```yaml - name: netbox transport: rest dadl: netbox.dadl url: "https://netbox.example.com/api" ``` Set the credential: ``` CREDENTIAL_NETBOX_TOKEN=your-token-here ``` ## What 608 tools does the NetBox DADL expose? - **GET** `list_sites` — List all sites (data centers, offices, PoPs) - **GET** `get_site` — Get a specific site - **POST** `create_site` — Create a new site - **PATCH** `update_site` — Update a site - **DELETE** `delete_site` — Delete a site - **GET** `list_regions` — List all regions (geographic grouping of sites) - **POST** `create_region` — Create a region - **GET** `get_region` — Get a specific region - **PATCH** `update_region` — Update a region - **DELETE** `delete_region` — Delete a region - **GET** `list_locations` — List locations within sites (rooms, floors, cages) - **POST** `create_location` — Create a location within a site - **GET** `get_location` — Get a specific location - **PATCH** `update_location` — Update a location - **DELETE** `delete_location` — Delete a location - **GET** `list_site_groups` — List site groups (hierarchical grouping of sites, orthogonal to regions) - **GET** `get_site_group` — Get a specific site group - **POST** `create_site_group` — Create a site group - **PATCH** `update_site_group` — Update a site group - **DELETE** `delete_site_group` — Delete a site group - **GET** `list_racks` — List all racks - **GET** `get_rack` — Get a specific rack - **POST** `create_rack` — Create a rack - **PATCH** `update_rack` — Update a rack - **DELETE** `delete_rack` — Delete a rack - **GET** `get_rack_elevation` — Get rack elevation -- returns the rack units with installed devices. Use ?render=svg for a graphical SVG rendering, default is JSON list of units. - **GET** `list_rack_roles` — List rack roles (functional classification of racks) - **GET** `get_rack_role` — Get a specific rack role - **POST** `create_rack_role` — Create a rack role - **PATCH** `update_rack_role` — Update a rack role - **DELETE** `delete_rack_role` — Delete a rack role - **GET** `list_rack_types` — List rack types (reusable rack model definitions, NetBox 4.1+) - **GET** `get_rack_type` — Get a specific rack type - **POST** `create_rack_type` — Create a rack type - **PATCH** `update_rack_type` — Update a rack type - **DELETE** `delete_rack_type` — Delete a rack type - **GET** `list_rack_reservations` — List rack reservations (claimed rack units for future use) - **GET** `get_rack_reservation` — Get a specific rack reservation - **POST** `create_rack_reservation` — Reserve rack units for future installation - **PATCH** `update_rack_reservation` — Update a rack reservation - **DELETE** `delete_rack_reservation` — Delete a rack reservation - **GET** `list_manufacturers` — List hardware manufacturers - **POST** `create_manufacturer` — Create a hardware manufacturer - **GET** `get_manufacturer` — Get a specific manufacturer - **PATCH** `update_manufacturer` — Update a manufacturer - **DELETE** `delete_manufacturer` — Delete a manufacturer - **GET** `list_device_types` — List device types (hardware models) - **POST** `create_device_type` — Create a device type (hardware model) - **GET** `get_device_type` — Get a specific device type - **PATCH** `update_device_type` — Update a device type - **DELETE** `delete_device_type` — Delete a device type - **GET** `list_device_roles` — List device roles (server, switch, router, firewall, etc.) - **POST** `create_device_role` — Create a device role - **GET** `get_device_role` — Get a specific device role - **PATCH** `update_device_role` — Update a device role - **DELETE** `delete_device_role` — Delete a device role - **GET** `list_platforms` — List platforms (OS/firmware: Cisco IOS, Junos, Linux, etc.) - **POST** `create_platform` — Create a platform (OS/firmware type) - **GET** `get_platform` — Get a specific platform - **PATCH** `update_platform` — Update a platform - **DELETE** `delete_platform` — Delete a platform - **GET** `list_devices` — List all devices (servers, switches, routers, firewalls, etc.) - **GET** `get_device` — Get a specific device with all details - **POST** `create_device` — Create a new device - **PATCH** `update_device` — Update a device -- fields, rack placement, primary IPs, out-of-band (OOB) management IP, virtual-chassis membership, geolocation. IP fields (primary_ip4/primary_ip6/oob_ip) take an ip-address ID that must already be assigned to an interface of this device. - **DELETE** `delete_device` — Delete a device - **GET** `list_module_types` — List module types (reusable hardware module definitions, e.g. line cards) - **GET** `get_module_type` — Get a specific module type - **POST** `create_module_type` — Create a module type - **PATCH** `update_module_type` — Update a module type - **DELETE** `delete_module_type` — Delete a module type - **GET** `list_module_type_profiles` — List module type profiles (schemas for module-type custom attributes, NetBox 4.3+) - **GET** `get_module_type_profile` — Get a specific module type profile - **POST** `create_module_type_profile` — Create a module type profile (JSON Schema describing module-type attributes) - **PATCH** `update_module_type_profile` — Update a module type profile - **DELETE** `delete_module_type_profile` — Delete a module type profile - **GET** `list_modules` — List installed modules (instances of module-types mounted in module-bays) - **GET** `get_module` — Get a specific module - **POST** `create_module` — Install a module into a module bay - **PATCH** `update_module` — Update a module - **DELETE** `delete_module` — Delete a module - **GET** `list_module_bays` — List module bays (slots on a device that accept modules) - **GET** `get_module_bay` — Get a specific module bay - **POST** `create_module_bay` — Create a module bay on a device - **PATCH** `update_module_bay` — Update a module bay - **DELETE** `delete_module_bay` — Delete a module bay - **GET** `list_device_bays` — List device bays (slots that contain child devices, e.g. blade chassis) - **GET** `get_device_bay` — Get a specific device bay - **POST** `create_device_bay` — Create a device bay - **PATCH** `update_device_bay` — Update a device bay - **DELETE** `delete_device_bay` — Delete a device bay - **GET** `list_virtual_chassis` — List virtual chassis (logical grouping of stacked devices that share a single management plane) - **GET** `get_virtual_chassis` — Get a specific virtual chassis - **POST** `create_virtual_chassis` — Create a virtual chassis. Assign devices via PATCH /dcim/devices/ to set virtual_chassis and vc_position fields. - **PATCH** `update_virtual_chassis` — Update a virtual chassis - **DELETE** `delete_virtual_chassis` — Delete a virtual chassis - **GET** `list_virtual_device_contexts` — List virtual device contexts (VDCs -- multiple logical contexts on one physical device, e.g. Cisco Nexus VDCs) - **GET** `get_virtual_device_context` — Get a specific VDC - **POST** `create_virtual_device_context` — Create a virtual device context - **PATCH** `update_virtual_device_context` — Update a virtual device context - **DELETE** `delete_virtual_device_context` — Delete a virtual device context - **GET** `list_inventory_items` — List inventory items (line cards, fans, PSUs not modeled as full modules) - **GET** `get_inventory_item` — Get a specific inventory item - **POST** `create_inventory_item` — Create an inventory item on a device - **PATCH** `update_inventory_item` — Update an inventory item - **DELETE** `delete_inventory_item` — Delete an inventory item - **GET** `list_inventory_item_roles` — List inventory item roles (functional classification, e.g. CPU, PSU, Fan) - **GET** `get_inventory_item_role` — Get a specific inventory item role - **POST** `create_inventory_item_role` — Create an inventory item role - **PATCH** `update_inventory_item_role` — Update an inventory item role - **DELETE** `delete_inventory_item_role` — Delete an inventory item role - **GET** `list_interfaces` — List device interfaces (physical and logical) - **GET** `get_interface` — Get a specific interface - **POST** `create_interface` — Create a device interface - **PATCH** `update_interface` — Update a device interface. Nullable foreign keys and choice fields accept an explicit JSON null to clear -- omitting the field leaves it unchanged. Nullable params: untagged_vlan, lag, parent, bridge, vrf, primary_mac_address, mode, duplex. For M2M wireless_lans / tagged_vlans / tags pass [] to detach all. - **DELETE** `delete_interface` — Delete a device interface - **GET** `list_cables` — List all cables connecting device components - **GET** `get_cable` — Get a specific cable - **POST** `create_cable` — Create a cable connection between device components - **PATCH** `update_cable` — Update a cable - **DELETE** `delete_cable` — Delete a cable - **GET** `list_console_ports` — List device console ports - **POST** `create_console_port` — Create a console port on a device - **GET** `list_power_ports` — List device power ports - **POST** `create_power_port` — Create a power port on a device - **GET** `list_mac_addresses` — List MAC addresses - **POST** `create_mac_address` — Create a MAC address entry - **GET** `get_mac_address` — Get a specific MAC address entry - **PATCH** `update_mac_address` — Update a MAC address entry (reassign to different interface, change description) - **DELETE** `delete_mac_address` — Delete a MAC address entry - **GET** `get_console_port` — Get a specific console port - **PATCH** `update_console_port` — Update a console port - **DELETE** `delete_console_port` — Delete a console port - **GET** `trace_console_port` — Trace the cable path from this console port to its far end (returns a list of cable segments) - **GET** `list_console_server_ports` — List console server ports (the server-side of console connections) - **GET** `get_console_server_port` — Get a specific console server port - **POST** `create_console_server_port` — Create a console server port - **PATCH** `update_console_server_port` — Update a console server port - **DELETE** `delete_console_server_port` — Delete a console server port - **GET** `get_power_port` — Get a specific power port - **PATCH** `update_power_port` — Update a power port - **DELETE** `delete_power_port` — Delete a power port - **GET** `list_power_outlets` — List power outlets (sockets on a PDU or device that supply power to other devices) - **GET** `get_power_outlet` — Get a specific power outlet - **POST** `create_power_outlet` — Create a power outlet (typically on a PDU) - **PATCH** `update_power_outlet` — Update a power outlet - **DELETE** `delete_power_outlet` — Delete a power outlet - **GET** `list_front_ports` — List front ports (patch panel front-side ports, paired with rear ports) - **GET** `get_front_port` — Get a specific front port - **POST** `create_front_port` — Create a front port on a patch panel (must reference a rear port) - **PATCH** `update_front_port` — Update a front port - **DELETE** `delete_front_port` — Delete a front port - **GET** `paths_front_port` — List all cable paths that pass through this front port - **GET** `list_rear_ports` — List rear ports (patch panel rear-side ports, cabled to trunk lines) - **GET** `get_rear_port` — Get a specific rear port - **POST** `create_rear_port` — Create a rear port on a patch panel - **PATCH** `update_rear_port` — Update a rear port - **DELETE** `delete_rear_port` — Delete a rear port - **GET** `paths_rear_port` — List all cable paths that pass through this rear port - **GET** `trace_interface` — Trace the cable path from this interface to its far end - **GET** `trace_power_port` — Trace the cable path from this power port - **GET** `trace_power_outlet` — Trace the cable path from this power outlet - **GET** `trace_console_server_port` — Trace the cable path from this console server port - **GET** `get_connected_device` — Lookup the device connected to a given peer device/interface. Returns the device at the far end of the cable, or 404 if not connected. - **GET** `list_cable_terminations` — List cable terminations (endpoints of cables -- the join between a cable and a port) - **GET** `get_cable_termination` — Get a specific cable termination - **GET** `list_power_panels` — List power panels (the upstream source of power feeds at a site) - **GET** `get_power_panel` — Get a specific power panel - **POST** `create_power_panel` — Create a power panel - **PATCH** `update_power_panel` — Update a power panel - **DELETE** `delete_power_panel` — Delete a power panel - **GET** `list_power_feeds` — List power feeds (the circuit from a power panel that supplies a rack) - **GET** `get_power_feed` — Get a specific power feed - **POST** `create_power_feed` — Create a power feed (circuit from a power panel to a rack) - **PATCH** `update_power_feed` — Update a power feed - **DELETE** `delete_power_feed` — Delete a power feed - **GET** `trace_power_feed` — Trace the cable path from this power feed - **GET** `list_interface_templates` — List interface templates on device-types and module-types - **POST** `create_interface_template` — Create an interface template. Must specify device_type OR module_type. - **GET** `get_interface_template` — Get a specific interface template - **PATCH** `update_interface_template` — Update an interface template - **DELETE** `delete_interface_template` — Delete an interface template - **GET** `list_console_port_templates` — List console port templates - **POST** `create_console_port_template` — Create a console port template - **DELETE** `delete_console_port_template` — Delete a console port template - **GET** `list_console_server_port_templates` — List console server port templates - **POST** `create_console_server_port_template` — Create a console server port template - **DELETE** `delete_console_server_port_template` — Delete a console server port template - **GET** `list_power_port_templates` — List power port templates - **POST** `create_power_port_template` — Create a power port template - **DELETE** `delete_power_port_template` — Delete a power port template - **GET** `list_power_outlet_templates` — List power outlet templates - **POST** `create_power_outlet_template` — Create a power outlet template - **DELETE** `delete_power_outlet_template` — Delete a power outlet template - **GET** `list_front_port_templates` — List front port templates - **POST** `create_front_port_template` — Create a front port template (must reference a rear-port-template) - **DELETE** `delete_front_port_template` — Delete a front port template - **GET** `list_rear_port_templates` — List rear port templates - **POST** `create_rear_port_template` — Create a rear port template - **DELETE** `delete_rear_port_template` — Delete a rear port template - **GET** `list_module_bay_templates` — List module bay templates - **POST** `create_module_bay_template` — Create a module bay template - **DELETE** `delete_module_bay_template` — Delete a module bay template - **GET** `list_device_bay_templates` — List device bay templates - **POST** `create_device_bay_template` — Create a device bay template - **DELETE** `delete_device_bay_template` — Delete a device bay template - **GET** `list_inventory_item_templates` — List inventory item templates - **POST** `create_inventory_item_template` — Create an inventory item template - **DELETE** `delete_inventory_item_template` — Delete an inventory item template - **GET** `list_prefixes` — List IP prefixes (subnets). Results span ALL VRFs: overlapping private ranges (e.g. a customer VRF reusing an internal RFC1918 net) return look-alike rows -- check the vrf field and scope with vrf_id when a range is ambiguous. - **GET** `get_prefix` — Get a specific prefix - **POST** `create_prefix` — Create an IP prefix - **PATCH** `update_prefix` — Update a prefix - **DELETE** `delete_prefix` — Delete a prefix - **GET** `list_available_ips` — List available (unallocated) IPs within a prefix - **GET** `list_ip_addresses` — List all IP addresses. Results span ALL VRFs: the same private address can exist once globally and again inside a customer VRF -- check the vrf field on each row and scope with vrf_id when an address is ambiguous. - **GET** `get_ip_address` — Get a specific IP address - **POST** `create_ip_address` — Create an IP address - **PATCH** `update_ip_address` — Update an IP address - **DELETE** `delete_ip_address` — Delete an IP address - **GET** `list_ip_ranges` — List IP ranges (continuous address ranges, e.g. DHCP pools) - **POST** `create_ip_range` — Create an IP range - **GET** `list_vlans` — List all VLANs - **GET** `get_vlan` — Get a specific VLAN - **POST** `create_vlan` — Create a VLAN - **PATCH** `update_vlan` — Update a VLAN - **DELETE** `delete_vlan` — Delete a VLAN - **GET** `list_vlan_groups` — List VLAN groups - **POST** `create_vlan_group` — Create a VLAN group - **GET** `get_vlan_group` — Get a specific VLAN group - **PATCH** `update_vlan_group` — Update a VLAN group - **DELETE** `delete_vlan_group` — Delete a VLAN group - **GET** `list_vrfs` — List all VRFs (Virtual Routing and Forwarding instances) - **GET** `get_vrf` — Get a specific VRF - **POST** `create_vrf` — Create a VRF - **PATCH** `update_vrf` — Update a VRF - **DELETE** `delete_vrf` — Delete a VRF - **GET** `list_rirs` — List Regional Internet Registries (RIPE, ARIN, etc.) - **POST** `create_rir` — Create a Regional Internet Registry - **GET** `list_aggregates` — List aggregate prefixes (top-level allocations from RIRs) - **POST** `create_aggregate` — Create an aggregate prefix (top-level RIR allocation) - **GET** `list_asns` — List Autonomous System Numbers - **POST** `create_asn` — Create an Autonomous System Number - **GET** `list_ipam_roles` — List IPAM roles for prefixes and VLANs - **POST** `create_ipam_role` — Create an IPAM role for prefixes and VLANs - **GET** `list_services` — List services running on devices or VMs (DNS, HTTP, SSH, etc.). NetBox 4.x uses parent_object filters. - **POST** `create_service` — Create a service entry on a device or VM. NetBox 4.x uses GenericForeignKey: set parent_object_type and parent_object_id instead of device/virtual_machine. - **GET** `get_service` — Get a specific service - **PATCH** `update_service` — Update a service. Use parent_object_type + parent_object_id to reassign (NetBox 4.x GenericForeignKey). - **DELETE** `delete_service` — Delete a service - **GET** `list_service_templates` — List service templates (reusable service definitions, e.g. 'web-https') - **GET** `get_service_template` — Get a specific service template - **POST** `create_service_template` — Create a service template - **PATCH** `update_service_template` — Update a service template - **DELETE** `delete_service_template` — Delete a service template - **GET** `list_route_targets` — List BGP route targets (e.g. '65000:100', used for MPLS L3VPN import/export) - **GET** `get_route_target` — Get a specific route target - **POST** `create_route_target` — Create a route target. Assign to VRFs via vrf.import_targets / vrf.export_targets. - **PATCH** `update_route_target` — Update a route target - **DELETE** `delete_route_target` — Delete a route target - **GET** `list_asn_ranges` — List ASN ranges (bounded ASN allocation pools) - **GET** `get_asn_range` — Get a specific ASN range - **POST** `create_asn_range` — Create an ASN range - **PATCH** `update_asn_range` — Update an ASN range - **DELETE** `delete_asn_range` — Delete an ASN range - **GET** `list_available_asns` — List the next unallocated ASNs within a range. POST to the same path to claim ASNs. - **POST** `claim_asn` — Claim the next available ASN from a range and assign metadata - **GET** `list_available_prefixes` — List unallocated sub-prefixes within a prefix - **POST** `claim_prefix` — Carve a new child prefix out of a parent. NetBox picks the next free block of prefix_length. - **GET** `list_available_ips_in_range` — List free IPs within an IP range - **GET** `list_available_vlans` — List the next unallocated VIDs in a VLAN group - **POST** `claim_vlan` — Claim the next available VID from a VLAN group - **GET** `get_ip_range` — Get a specific IP range - **PATCH** `update_ip_range` — Update an IP range - **DELETE** `delete_ip_range` — Delete an IP range - **GET** `get_aggregate` — Get a specific aggregate - **PATCH** `update_aggregate` — Update an aggregate - **DELETE** `delete_aggregate` — Delete an aggregate - **GET** `get_asn` — Get a specific ASN - **PATCH** `update_asn` — Update an ASN - **DELETE** `delete_asn` — Delete an ASN - **GET** `get_rir` — Get a specific RIR (Regional Internet Registry, e.g. RIPE, ARIN) - **PATCH** `update_rir` — Update a RIR - **DELETE** `delete_rir` — Delete a RIR - **GET** `list_vlan_translation_policies` — List VLAN translation policies (named sets of 1:1 VID mappings, NetBox 4.0+) - **GET** `get_vlan_translation_policy` — Get a specific VLAN translation policy - **POST** `create_vlan_translation_policy` — Create a VLAN translation policy - **PATCH** `update_vlan_translation_policy` — Update a VLAN translation policy - **DELETE** `delete_vlan_translation_policy` — Delete a VLAN translation policy - **GET** `list_vlan_translation_rules` — List VLAN translation rules (individual local-VID to remote-VID mappings within a policy) - **GET** `get_vlan_translation_rule` — Get a specific VLAN translation rule - **POST** `create_vlan_translation_rule` — Create a VLAN translation rule - **PATCH** `update_vlan_translation_rule` — Update a VLAN translation rule - **DELETE** `delete_vlan_translation_rule` — Delete a VLAN translation rule - **GET** `list_fhrp_groups` — List FHRP (First Hop Redundancy Protocol) groups. FHRP groups represent virtual IP failover configurations using VRRP, HSRP, GLBP, or CARP. Each group has a protocol, numeric group_id, and optional name. IP addresses are assigned to groups separately. - **GET** `get_fhrp_group` — Get a specific FHRP group by ID. Returns protocol, group_id, name, auth_type, auth_key, and assigned IP addresses. - **POST** `create_fhrp_group` — Create an FHRP group. Requires protocol and group_id. Virtual IP addresses can be created alongside the group or assigned afterward via IP address objects. - **PATCH** `update_fhrp_group` — Update an FHRP group. - **DELETE** `delete_fhrp_group` — Delete an FHRP group. This also removes all group assignments. - **GET** `list_fhrp_group_assignments` — List FHRP group assignments — links between FHRP groups and device/VM interfaces. Each assignment has a priority (0-255) determining master/primary election. - **GET** `get_fhrp_group_assignment` — Get a specific FHRP group assignment by ID. - **POST** `create_fhrp_group_assignment` — Assign an FHRP group to a device or VM interface. Priority (0-255) determines master/primary election — higher priority = more likely to be elected master. - **PATCH** `update_fhrp_group_assignment` — Update an FHRP group assignment (e.g. change priority or reassign to a different interface). - **DELETE** `delete_fhrp_group_assignment` — Delete an FHRP group assignment — removes the interface from the FHRP group. - **GET** `list_cluster_types` — List cluster types (VMware, Proxmox, XCP-ng, etc.) - **POST** `create_cluster_type` — Create a cluster type (e.g. VMware, Proxmox, Linode, XCP-ng) - **GET** `list_cluster_groups` — List cluster groups - **POST** `create_cluster_group` — Create a cluster group - **GET** `get_cluster_group` — Get a specific cluster group - **PATCH** `update_cluster_group` — Update a cluster group - **DELETE** `delete_cluster_group` — Delete a cluster group - **GET** `list_clusters` — List all virtualization clusters - **GET** `get_cluster` — Get a specific cluster - **POST** `create_cluster` — Create a virtualization cluster - **PATCH** `update_cluster` — Update a cluster - **DELETE** `delete_cluster` — Delete a cluster - **GET** `list_virtual_machines` — List all virtual machines - **GET** `get_virtual_machine` — Get a specific virtual machine - **POST** `create_virtual_machine` — Create a virtual machine - **PATCH** `update_virtual_machine` — Update a virtual machine - **DELETE** `delete_virtual_machine` — Delete a virtual machine - **GET** `list_vm_interfaces` — List virtual machine interfaces - **POST** `create_vm_interface` — Create a VM interface - **GET** `get_vm_interface` — Get a specific VM interface - **PATCH** `update_vm_interface` — Update a VM interface - **DELETE** `delete_vm_interface` — Delete a VM interface - **GET** `list_virtual_disks` — List virtual disks - **POST** `create_virtual_disk` — Create a virtual disk - **GET** `get_virtual_disk` — Get a specific virtual disk - **PATCH** `update_virtual_disk` — Update a virtual disk - **DELETE** `delete_virtual_disk` — Delete a virtual disk - **GET** `list_virtual_machine_types` — List virtual machine types (NetBox 4.2+, model definitions like AWS EC2 'm5.xlarge') - **GET** `get_virtual_machine_type` — Get a specific VM type - **POST** `create_virtual_machine_type` — Create a virtual machine type - **PATCH** `update_virtual_machine_type` — Update a virtual machine type - **DELETE** `delete_virtual_machine_type` — Delete a virtual machine type - **GET** `list_tenants` — List all tenants (customers, departments, teams) - **GET** `get_tenant` — Get a specific tenant - **POST** `create_tenant` — Create a tenant - **PATCH** `update_tenant` — Update a tenant - **DELETE** `delete_tenant` — Delete a tenant - **GET** `list_tenant_groups` — List tenant groups - **POST** `create_tenant_group` — Create a tenant group - **GET** `get_tenant_group` — Get a specific tenant group - **PATCH** `update_tenant_group` — Update a tenant group - **DELETE** `delete_tenant_group` — Delete a tenant group - **GET** `list_contacts` — List all contacts - **POST** `create_contact` — Create a contact - **GET** `get_contact` — Get a specific contact - **PATCH** `update_contact` — Update a contact - **DELETE** `delete_contact` — Delete a contact - **GET** `list_contact_roles` — List contact roles (admin, NOC, billing, etc.) - **POST** `create_contact_role` — Create a contact role - **GET** `get_contact_role` — Get a specific contact role - **PATCH** `update_contact_role` — Update a contact role - **DELETE** `delete_contact_role` — Delete a contact role - **GET** `list_contact_groups` — List contact groups (hierarchical grouping of contacts) - **GET** `get_contact_group` — Get a specific contact group - **POST** `create_contact_group` — Create a contact group - **PATCH** `update_contact_group` — Update a contact group - **DELETE** `delete_contact_group` — Delete a contact group - **GET** `list_contact_assignments` — List contact assignments (links between contacts and any NetBox object) - **GET** `get_contact_assignment` — Get a specific contact assignment - **POST** `create_contact_assignment` — Assign a contact to an object (device, circuit, etc.) - **PATCH** `update_contact_assignment` — Update a contact assignment - **DELETE** `delete_contact_assignment` — Delete a contact assignment - **GET** `list_providers` — List circuit providers (ISPs, carriers) - **POST** `create_provider` — Create a circuit provider - **GET** `get_provider` — Get a specific provider - **PATCH** `update_provider` — Update a provider - **DELETE** `delete_provider` — Delete a provider - **GET** `list_circuit_types` — List circuit types (Internet, MPLS, dark fiber, etc.) - **POST** `create_circuit_type` — Create a circuit type - **GET** `get_circuit_type` — Get a specific circuit type - **PATCH** `update_circuit_type` — Update a circuit type - **DELETE** `delete_circuit_type` — Delete a circuit type - **GET** `list_circuits` — List all circuits - **GET** `get_circuit` — Get a specific circuit - **POST** `create_circuit` — Create a circuit - **PATCH** `update_circuit` — Update a circuit - **DELETE** `delete_circuit` — Delete a circuit - **GET** `list_circuit_terminations` — List circuit terminations (A-side and Z-side endpoints) - **POST** `create_circuit_termination` — Create a circuit termination (A or Z side) - **GET** `get_circuit_termination` — Get a specific circuit termination - **PATCH** `update_circuit_termination` — Update a circuit termination - **DELETE** `delete_circuit_termination` — Delete a circuit termination - **GET** `paths_circuit_termination` — Trace cable paths from a circuit termination - **GET** `list_provider_accounts` — List provider accounts (a customer's account number with a provider) - **GET** `get_provider_account` — Get a specific provider account - **POST** `create_provider_account` — Create a provider account - **PATCH** `update_provider_account` — Update a provider account - **DELETE** `delete_provider_account` — Delete a provider account - **GET** `list_provider_networks` — List provider networks (the far end of a circuit -- a provider's MPLS cloud, peering fabric, etc.) - **GET** `get_provider_network` — Get a specific provider network - **POST** `create_provider_network` — Create a provider network - **PATCH** `update_provider_network` — Update a provider network - **DELETE** `delete_provider_network` — Delete a provider network - **GET** `list_circuit_groups` — List circuit groups (logical grouping of related circuits, e.g. SD-WAN underlays) - **GET** `get_circuit_group` — Get a specific circuit group - **POST** `create_circuit_group` — Create a circuit group - **PATCH** `update_circuit_group` — Update a circuit group - **DELETE** `delete_circuit_group` — Delete a circuit group - **GET** `list_circuit_group_assignments` — List circuit-to-group assignments with priorities - **GET** `get_circuit_group_assignment` — Get a specific circuit group assignment - **POST** `create_circuit_group_assignment` — Assign a circuit (or virtual circuit) to a circuit group - **PATCH** `update_circuit_group_assignment` — Update a circuit group assignment - **DELETE** `delete_circuit_group_assignment` — Delete a circuit group assignment - **GET** `list_virtual_circuit_types` — List virtual circuit types (classification of virtual circuits, NetBox 4.2+) - **GET** `get_virtual_circuit_type` — Get a specific virtual circuit type - **POST** `create_virtual_circuit_type` — Create a virtual circuit type - **PATCH** `update_virtual_circuit_type` — Update a virtual circuit type - **DELETE** `delete_virtual_circuit_type` — Delete a virtual circuit type - **GET** `list_virtual_circuits` — List virtual circuits (logical end-to-end paths that run over a provider network, NetBox 4.2+) - **GET** `get_virtual_circuit` — Get a specific virtual circuit - **POST** `create_virtual_circuit` — Create a virtual circuit - **PATCH** `update_virtual_circuit` — Update a virtual circuit - **DELETE** `delete_virtual_circuit` — Delete a virtual circuit - **GET** `list_virtual_circuit_terminations` — List virtual circuit terminations (endpoints of virtual circuits on interfaces) - **GET** `get_virtual_circuit_termination` — Get a specific virtual circuit termination - **POST** `create_virtual_circuit_termination` — Terminate a virtual circuit on a physical interface - **PATCH** `update_virtual_circuit_termination` — Update a virtual circuit termination - **DELETE** `delete_virtual_circuit_termination` — Delete a virtual circuit termination - **GET** `list_wireless_lan_groups` — List wireless LAN groups (hierarchical grouping of SSIDs) - **GET** `get_wireless_lan_group` — Get a specific wireless LAN group - **POST** `create_wireless_lan_group` — Create a wireless LAN group - **PATCH** `update_wireless_lan_group` — Update a wireless LAN group - **DELETE** `delete_wireless_lan_group` — Delete a wireless LAN group - **GET** `list_wireless_lans` — List wireless LANs (SSIDs) - **GET** `get_wireless_lan` — Get a specific wireless LAN - **POST** `create_wireless_lan` — Create a wireless LAN (SSID) - **PATCH** `update_wireless_lan` — Update a wireless LAN - **DELETE** `delete_wireless_lan` — Delete a wireless LAN - **GET** `list_wireless_links` — List wireless point-to-point links - **GET** `get_wireless_link` — Get a specific wireless link - **POST** `create_wireless_link` — Create a wireless point-to-point link - **PATCH** `update_wireless_link` — Update a wireless link - **DELETE** `delete_wireless_link` — Delete a wireless link - **GET** `list_tunnel_groups` — List tunnel groups (logical grouping of VPN tunnels) - **GET** `get_tunnel_group` — Get a specific tunnel group - **POST** `create_tunnel_group` — Create a tunnel group - **PATCH** `update_tunnel_group` — Update a tunnel group - **DELETE** `delete_tunnel_group` — Delete a tunnel group - **GET** `list_tunnels` — List VPN tunnels - **GET** `get_tunnel` — Get a specific tunnel - **POST** `create_tunnel` — Create a VPN tunnel - **PATCH** `update_tunnel` — Update a tunnel - **DELETE** `delete_tunnel` — Delete a tunnel - **GET** `list_tunnel_terminations` — List tunnel terminations (per-side endpoints of a VPN tunnel) - **GET** `get_tunnel_termination` — Get a specific tunnel termination - **POST** `create_tunnel_termination` — Add a termination to a VPN tunnel - **PATCH** `update_tunnel_termination` — Update a tunnel termination - **DELETE** `delete_tunnel_termination` — Delete a tunnel termination - **GET** `list_ike_proposals` — List IKE proposals (encryption/authentication algorithm bundles for IKE phase 1) - **GET** `get_ike_proposal` — Get a specific IKE proposal - **POST** `create_ike_proposal` — Create an IKE proposal - **PATCH** `update_ike_proposal` — Update an IKE proposal - **DELETE** `delete_ike_proposal` — Delete an IKE proposal - **GET** `list_ike_policies` — List IKE policies (named groups of proposals + version + mode) - **GET** `get_ike_policy` — Get a specific IKE policy - **POST** `create_ike_policy` — Create an IKE policy - **PATCH** `update_ike_policy` — Update an IKE policy - **DELETE** `delete_ike_policy` — Delete an IKE policy - **GET** `list_ipsec_proposals` — List IPSec proposals (encryption/auth bundles for IPSec phase 2) - **GET** `get_ipsec_proposal` — Get a specific IPSec proposal - **POST** `create_ipsec_proposal` — Create an IPSec proposal - **PATCH** `update_ipsec_proposal` — Update an IPSec proposal - **DELETE** `delete_ipsec_proposal` — Delete an IPSec proposal - **GET** `list_ipsec_policies` — List IPSec policies (named bundles of IPSec proposals + PFS group) - **GET** `get_ipsec_policy` — Get a specific IPSec policy - **POST** `create_ipsec_policy` — Create an IPSec policy - **PATCH** `update_ipsec_policy` — Update an IPSec policy - **DELETE** `delete_ipsec_policy` — Delete an IPSec policy - **GET** `list_ipsec_profiles` — List IPSec profiles (combination of IKE policy + IPSec policy + mode -- attach to a tunnel) - **GET** `get_ipsec_profile` — Get a specific IPSec profile - **POST** `create_ipsec_profile` — Create an IPSec profile - **PATCH** `update_ipsec_profile` — Update an IPSec profile - **DELETE** `delete_ipsec_profile` — Delete an IPSec profile - **GET** `list_l2vpns` — List L2VPN instances (VPLS, VXLAN, EVPN, etc.) - **GET** `get_l2vpn` — Get a specific L2VPN - **POST** `create_l2vpn` — Create an L2VPN instance - **PATCH** `update_l2vpn` — Update an L2VPN - **DELETE** `delete_l2vpn` — Delete an L2VPN - **GET** `list_l2vpn_terminations` — List L2VPN terminations (attachments of VLANs/interfaces/VRFs to an L2VPN) - **GET** `get_l2vpn_termination` — Get a specific L2VPN termination - **POST** `create_l2vpn_termination` — Attach an interface, VLAN, or VRF to an L2VPN - **PATCH** `update_l2vpn_termination` — Update an L2VPN termination - **DELETE** `delete_l2vpn_termination` — Delete an L2VPN termination - **GET** `list_tags` — List all tags - **POST** `create_tag` — Create a tag - **GET** `get_tag` — Get a specific tag - **PATCH** `update_tag` — Update a tag - **DELETE** `delete_tag` — Delete a tag - **GET** `list_custom_fields` — List all custom field definitions - **GET** `get_custom_field` — Get a specific custom field definition - **POST** `create_custom_field` — Create a custom field definition. Assign to object types via object_types array. - **PATCH** `update_custom_field` — Update a custom field definition - **DELETE** `delete_custom_field` — Delete a custom field definition. WARNING: deletes all stored values. - **GET** `list_custom_field_choice_sets` — List all custom field choice sets - **GET** `get_custom_field_choice_set` — Get a specific custom field choice set - **POST** `create_custom_field_choice_set` — Create a custom field choice set for select/multiselect custom fields - **PATCH** `update_custom_field_choice_set` — Update a custom field choice set - **DELETE** `delete_custom_field_choice_set` — Delete a custom field choice set. WARNING: breaks any custom fields referencing this set. - **GET** `list_object_changes` — List the change log — every create/update/delete on any NetBox object is recorded with timestamp, user, action, and pre/post-change snapshots. Use to audit who changed what and when. - **GET** `list_journal_entries` — List journal entries (change notes on objects) - **POST** `create_journal_entry` — Create a journal entry on an object - **GET** `list_config_contexts` — List configuration contexts (rendered config data for devices/VMs) - **POST** `create_config_context` — Create a configuration context - **GET** `get_config_context` — Get a specific config context - **PATCH** `update_config_context` — Update a config context - **DELETE** `delete_config_context` — Delete a config context - **GET** `get_journal_entry` — Get a specific journal entry - **PATCH** `update_journal_entry` — Update a journal entry - **DELETE** `delete_journal_entry` — Delete a journal entry - **GET** `list_config_templates` — List config templates (Jinja2 templates rendered against config-context data) - **GET** `get_config_template` — Get a specific config template - **POST** `create_config_template` — Create a config template - **PATCH** `update_config_template` — Update a config template - **DELETE** `delete_config_template` — Delete a config template - **POST** `render_config_template` — Render a config template with the supplied context. Returns text/plain or JSON. - **GET** `list_webhooks` — List webhooks (HTTP callbacks that fire on object events) - **GET** `get_webhook` — Get a specific webhook - **POST** `create_webhook` — Create a webhook. Webhooks are now decoupled from triggers -- use event-rules to bind a webhook to a model + event. - **PATCH** `update_webhook` — Update a webhook - **DELETE** `delete_webhook` — Delete a webhook - **GET** `list_event_rules` — List event rules (binding: model + event type -> action target like webhook or script) - **GET** `get_event_rule` — Get a specific event rule - **POST** `create_event_rule` — Create an event rule - **PATCH** `update_event_rule` — Update an event rule - **DELETE** `delete_event_rule` — Delete an event rule - **GET** `list_scripts` — List installed custom scripts. NetBox 4.0+ merged reports into scripts. Each script has a module + name and is identified by id (or 'module.ClassName' string). - **GET** `get_script` — Get script details (parameters schema, module info) - **POST** `run_script` — Execute a custom script. Returns a job ID; poll /core/jobs/{job_id}/ for status. Data must match the script's declared parameters. - **GET** `list_export_templates` — List export templates (Jinja2 templates that render lists of objects to CSV/JSON/text) - **GET** `get_export_template` — Get a specific export template - **POST** `create_export_template` — Create an export template - **PATCH** `update_export_template` — Update an export template - **DELETE** `delete_export_template` — Delete an export template - **GET** `list_saved_filters` — List saved filters (reusable URL query parameter sets per object type) - **GET** `get_saved_filter` — Get a specific saved filter - **POST** `create_saved_filter` — Create a saved filter - **PATCH** `update_saved_filter` — Update a saved filter - **DELETE** `delete_saved_filter` — Delete a saved filter - **GET** `list_custom_links` — List custom links (extra UI buttons shown on object pages) - **GET** `get_custom_link` — Get a specific custom link - **POST** `create_custom_link` — Create a custom link - **PATCH** `update_custom_link` — Update a custom link - **DELETE** `delete_custom_link` — Delete a custom link - **GET** `list_bookmarks` — List bookmarks (user-specific bookmarks of NetBox objects) - **GET** `get_bookmark` — Get a specific bookmark - **POST** `create_bookmark` — Create a bookmark - **DELETE** `delete_bookmark` — Delete a bookmark - **GET** `list_notifications` — List notifications (in-app messages for users, NetBox 4.1+) - **GET** `get_notification` — Get a specific notification - **POST** `create_notification` — Create a notification (typically used by automation, not humans) - **PATCH** `update_notification` — Mark notification as read by setting 'read' to a datetime - **DELETE** `delete_notification` — Delete a notification - **GET** `list_notification_groups` — List notification groups (sets of users + groups that receive event-rule notifications) - **GET** `get_notification_group` — Get a specific notification group - **POST** `create_notification_group` — Create a notification group - **PATCH** `update_notification_group` — Update a notification group - **DELETE** `delete_notification_group` — Delete a notification group - **GET** `list_subscriptions` — List subscriptions (per-user follow lists for specific objects) - **GET** `get_subscription` — Get a specific subscription - **POST** `create_subscription` — Subscribe a user to events on an object - **DELETE** `delete_subscription` — Delete a subscription - **GET** `list_image_attachments` — List image attachments (rack diagrams, photos, etc. attached to NetBox objects) - **GET** `get_image_attachment` — Get a specific image attachment - **POST** `create_image_attachment` — Attach an image to an object. Uses multipart/form-data with the image bytes. - **PATCH** `update_image_attachment` — Update image attachment metadata (name) - **DELETE** `delete_image_attachment` — Delete an image attachment - **GET** `get_dashboard` — Get the current user's dashboard configuration (singleton -- not a list endpoint) - **PATCH** `update_dashboard` — Update the current user's dashboard layout - **GET** `list_users` — List NetBox users. Admin-only endpoint. - **GET** `get_user` — Get a specific user - **POST** `create_user` — Create a NetBox user - **PATCH** `update_user` — Update a user. Passing 'password' resets the password. - **DELETE** `delete_user` — Delete a user - **GET** `list_groups` — List user groups - **GET** `get_group` — Get a specific group - **POST** `create_group` — Create a user group - **PATCH** `update_group` — Update a group - **DELETE** `delete_group` — Delete a group - **GET** `list_permissions` — List object permissions (per-model + per-action grants assigned to users/groups) - **GET** `get_permission` — Get a specific permission - **POST** `create_permission` — Create an object permission - **PATCH** `update_permission` — Update a permission - **DELETE** `delete_permission` — Delete a permission - **GET** `list_tokens` — List API tokens. Admin sees all; regular users see only their own. - **GET** `get_token` — Get a specific token (key shown only on create) - **POST** `create_token` — Issue a new API token for a user. The 'key' field in the response is shown only once. - **PATCH** `update_token` — Update token metadata (description, expiry, allowed IPs) - **DELETE** `delete_token` — Revoke a token - **POST** `provision_token` — Issue a token by username+password without an existing token. Bootstrap-only endpoint. Returns the new token in the response body. - **GET** `list_data_sources` — List core data sources (git/S3/local paths used to sync templates, scripts, contexts) - **GET** `get_data_source` — Get a specific data source - **POST** `create_data_source` — Create a data source - **PATCH** `update_data_source` — Update a data source - **DELETE** `delete_data_source` — Delete a data source - **POST** `sync_data_source` — Enqueue a sync job for the data source. Returns job ID; poll /core/jobs/{id}/. - **GET** `list_data_files` — List data files (read-only listing of files synced from data sources) - **GET** `get_data_file` — Get a specific data file (metadata + content) - **GET** `list_jobs` — List background jobs (script runs, data syncs, etc.) - **GET** `get_job` — Get a specific job (status, started/completed times, output data) - **GET** `list_object_types` — List Django ContentTypes (app_label.model strings used in object_type fields) - **GET** `get_object_type` — Get a specific object type - **GET** `list_background_queues` — List RQ background queues with statistics - **GET** `list_background_workers` — List active background workers - **GET** `list_background_tasks` — List background tasks (RQ jobs) ## Which DADLs are related to NetBox? - [Xen Orchestra](https://www.dadl.ai/d/xen-orchestra/) — Xen Orchestra REST API (XO 6.4+, current through 6.9) -- complete coverage: VMs (incl. PATCH update + snapshot revert), VM controllers, hosts (incl. full power/lifecycle actions + maintenance mode + PIF rescan), pools (incl. add_host, rolling reboot/update with interrupted-update recovery + finalize), storage (SR create/delete, VDI incl. PATCH update + vhd/raw/qcow2 export, VBD), networks (VIF incl. PATCH update + PIF/PBD), VM/VDI snapshots, VM templates, hardware (PCI/PGPU/SM), tasks, backups (archives incl. live mount of backup disks, jobs/logs, repositories incl. health + benchmark + space reclaim), schedules, messages, alarms, events (SSE incl. non-XAPI collections), RBAC v2 (users/groups/acl-roles/acl-privileges incl. assignment introspection), proxies, servers, dashboards, SDN traffic rules (add/delete/update), IPMI sensor inventory (plugin), audit records (plugin), health check - [Billomat](https://www.dadl.ai/d/billomat/) — Billomat REST API — German cloud invoicing & accounting: invoices, estimates, credit notes, recurring invoices, delivery notes, order confirmations, dunning reminders, clients, contacts, articles, payments, expenses, taxes - [BookStack](https://www.dadl.ai/d/bookstack/) — BookStack wiki and documentation platform REST API -- shelves, books, chapters, pages (HTML/Markdown content), attachments, image gallery, comments, cross-entity search, exports (HTML/Markdown/PDF/ZIP), ZIP imports, users, roles, content permissions, recycle bin, audit log and tags. Hierarchy: shelves > books > chapters > pages. - [Mempool](https://www.dadl.ai/d/mempool/) — mempool.space — Bitcoin block explorer, mempool visualizer, fee estimator, Lightning Network explorer, and transaction accelerator - [Mikrotik](https://www.dadl.ai/d/mikrotik/) — MikroTik RouterOS REST API -- manage interfaces, IP addresses, routing, firewall, DHCP, DNS, PPP, queues, wireless, system configuration, users, certificates, files, logs, and diagnostics on RouterOS v7.1+ devices - [Tailscale](https://www.dadl.ai/d/tailscale/) — Tailscale API -- devices, users, auth keys, DNS, ACL/policy, webhooks, contacts, posture integrations, log streaming, and tailnet settings --- **Canonical URL:** https://www.dadl.ai/d/netbox/ **Raw DADL:** https://github.com/DunkelCloud/dadl-registry/blob/main/netbox.dadl --- # Opnsense MCP Server — 343 tools via DADL The Opnsense DADL turns Opnsense's API into an MCP server that Claude, GPT or any MCP-compatible agent can consume directly. One YAML file declares all 343 tools — firewall, ipsec, unbound, haproxy, system, wireguard, and more — and ToolMesh serves them at runtime. No Python boilerplate, no per-endpoint code, no separate MCP server process. Below: the endpoint coverage matrix, a two-block ToolMesh setup, the full tool reference grouped by Opnsense feature area, required credential scopes. **Source:** [OPNsense REST API](https://docs.opnsense.org/development/api.html) **Updated:** 2026-08-02 **Tags:** firewall, crud, user-management, networking, monitoring, security, automation, logging, auth:basic ## Which Opnsense endpoints are covered? **23%** (343 of ~1500 endpoints). **Focus:** firewall (aliases, filter rules, NAT, outbound NAT mode, NPTv6), diagnostics (ARP, states, system, ping jobs, packet capture), interfaces (overview, VLANs, VIPs, global settings, reload), Unbound DNS, WireGuard, OpenVPN, IPsec, Kea DHCP, routes/gateways/gateway groups, firmware, system/backup, HAProxy, IDS/IPS, traffic shaper, certificates, syslog, cron, HA (hasync syncitems, config sync), IPv6 RA (radvd), NDP proxy, services (per-instance start/stop/restart) **Missing:** per-interface IPv4/IPv6 address config (configuration type, addresses, MTU/MSS — legacy config.xml, no API as of 26.7), firewall normalization/scrub rules (firewall_scrub.php legacy, no API as of 26.7), firewall savepoint/rollback (no such endpoints on 26.7), captive portal vouchers, BIND DNS, Caddy, Nginx, FRR routing, ACME client, Monit, collectd, CrowdSec, FreeRADIUS, most third-party plugins *Last reviewed: 2026-08-02* ## How do you configure the Opnsense DADL? 1. Log in to OPNsense web UI as admin 2. Navigate to System → Access → Users 3. Edit the user you want to create API credentials for (or create a dedicated API user) 4. Scroll down to 'API keys' section and click the '+' (add) button 5. A key/secret pair is generated and downloaded as an apikey.txt file 6. The file contains: key=<your-api-key> and secret=<your-api-secret> 7. IMPORTANT: The secret is NOT stored on the system — save it securely 8. Set env vars: CREDENTIAL_OPNSENSE_API_KEY=<key> and CREDENTIAL_OPNSENSE_API_SECRET=<secret> **Environment variable:** `CREDENTIAL_OPNSENSE_API_KEY and CREDENTIAL_OPNSENSE_API_SECRET` [Authentication docs](https://docs.opnsense.org/development/how-tos/api.html) *OPNsense uses page-based permissions. The API user needs GUI access to the same pages they want to access via API. For full API access, assign the user to the 'admins' group. API key + secret are used as HTTP Basic Auth (key=username, secret=password).* ## How do you install the Opnsense MCP server with ToolMesh? Add to your `backends.yaml`: ```yaml - name: opnsense transport: rest dadl: opnsense.dadl url: "https://your-opnsense-host/api" ``` Set the credential: ``` CREDENTIAL_OPNSENSE_API_KEY and CREDENTIAL_OPNSENSE_API_SECRET=your-token-here ``` ## What 343 tools does the Opnsense DADL expose? - **POST** `search_firewall_aliases` — Search firewall aliases (IP lists, port groups, URL tables, GeoIP, etc.) - **GET** `get_firewall_alias` — Get a single firewall alias by UUID - **POST** `add_firewall_alias` — Create a new firewall alias - **POST** `set_firewall_alias` — Update an existing firewall alias - **POST** `del_firewall_alias` — Delete a firewall alias by UUID - **POST** `toggle_firewall_alias` — Toggle a firewall alias on or off. Omit 'enabled' to flip the current state. - **POST** `reconfigure_firewall_aliases` — Apply alias changes to the running firewall - **GET** `get_alias_uuid_by_name` — Look up alias UUID by name - **GET** `list_alias_content` — List the resolved content (IPs/networks) of an alias - **POST** `add_alias_entry` — Add an entry to an alias at runtime (without modifying config) - **POST** `delete_alias_entry` — Remove an entry from an alias at runtime - **POST** `flush_alias` — Flush (clear) all entries from an alias at runtime - **GET** `list_network_aliases` — List all aliases usable as network references - **GET** `list_alias_categories` — List all alias categories - **GET** `list_geoip` — Get GeoIP configuration and available countries - **POST** `search_firewall_rules` — Search firewall filter rules. Returns {total, returned, truncated, rows} — check `truncated` before claiming a complete picture (rowCount defaults to 500 here, the appliance's own default of 50 silently cut a 53-rule ruleset short). The result MIXES user rules (MVC model) with OPNsense's automatic/internal rules (anti-lockout, default deny, pfsync, …): `is_automatic: true` marks the latter and is now always present as a real boolean — the raw API omits the key entirely on user rules. All boolean-ish fields are normalised to real booleans (raw API returns `true` on automatic rules but the string "1"/"0" on user rules, so `if (rule.log)` was true for log "0"): enabled, log, quick, source_not, destination_not, interfacenot, disablereplyto, nosync, nopfsync, allowopts, tcpflags_any. NEGATION: the added comfort fields %source_net / %destination_net / %interface render the negation flags inline ("NOT <alias>"), so a policy-routing rule can no longer be misread as its own opposite. Always read those, or read the *_not flags — the bare source_net/destination_net/interface fields say nothing about negation. Filters: `interface` (comma list of friendly keys; pass "" for floating rules only, omit for ALL rules), `category` (comma list of category UUIDs — automatic rules carry their own category), `show_all: 1` additionally merges live pf hit counters (evaluations/states/packets/bytes) into each row. - **GET** `get_firewall_rule` — Get a single firewall filter rule by UUID - **POST** `add_firewall_rule` — Create a new firewall filter rule. Covers the full Filter.xml model — fields not listed here cannot be sent. Apply with apply_firewall afterwards. Key gotchas: icmptype/icmp6type are ignored unless protocol is ICMP/IPv6-ICMP, and leaving them empty means ALL ICMP types; disablereplyto is regularly required on WAN-side rules; statetype defaults to "keep". - **POST** `set_firewall_rule` — Update an existing firewall filter rule. Same full field set as add_firewall_rule; the endpoint MERGES, so omitted fields keep their stored value. A field that is not in this list cannot be written and is dropped without any error — check the list before assuming a restriction was applied. Apply with apply_firewall afterwards. - **POST** `del_firewall_rule` — Delete a firewall filter rule - **POST** `toggle_firewall_rule` — Toggle a firewall filter rule on or off. Omit 'enabled' to flip the current state. - **POST** `move_firewall_rule_before` — Move a firewall rule before another rule (reorder) - **GET** `get_firewall_interface_list` — List interfaces available for firewall rules - **GET** `get_firewall_rule_stats` — Get firewall rule hit statistics - **POST** `apply_firewall` — Apply the stored firewall ruleset to the running pf (runs configd "filter reload skip_alias"). Takes NO parameters — the old {rollback_revision} path segment does not exist on 26.7 and made this tool uncallable. Returns {"status":"OK"} plus the reload output. NOTE: model writes via add_/set_/del_/toggle_ endpoints already trigger a config save that reloads the filter on most installations, so an explicit apply is usually a no-op confirmation rather than the step that activates the change. NPT/DNAT/ SNAT rules share this same pf reload; there is no separate per-family apply. - **POST** `search_firewall_categories` — Search firewall rule categories - **POST** `add_firewall_category` — Create a new firewall rule category - **POST** `set_firewall_category` — Update a firewall rule category - **POST** `del_firewall_category` — Delete a firewall rule category - **POST** `search_dnat_rules` — Search destination NAT (port forwarding) rules. The NAT families use different field conventions than the filter rules — inverted polarity and dot instead of underscore notation — which reads as "everything is disabled" if taken at face value: raw rows carry `disabled: "0"` (NOT `enabled`), `descr` (not `description`) and `source.network` / `destination.network` / `destination.not` (not source_net / destination_net / destination_not). This tool therefore ADDS filter-rule-compatible fields: `enabled` (real boolean, inverse of disabled), `description`, and the negation- aware %source_net / %destination_net ("NOT <alias>" when the .not flag is set). disabled/log/is_automatic/nordr are normalised to real booleans. - **GET** `get_dnat_rule` — Get a single DNAT rule by UUID - **POST** `add_dnat_rule` — Create a new destination NAT (port forwarding) rule - **POST** `set_dnat_rule` — Update an existing DNAT rule - **POST** `del_dnat_rule` — Delete a destination NAT (port forwarding) rule by UUID - **POST** `toggle_dnat_rule` — Toggle a destination NAT rule on or off. Omit 'disabled' to flip the current state. - **GET** `get_outbound_nat_mode` — Get the outbound (source) NAT generation mode — the Firewall→NAT→Outbound radio button. Returns {filter:{general:{snat_mode:{<key>:{value,selected}}}}} as an OPNsense SELECT map; the selected key is one of automatic (rules generated from the interface config), hybrid (automatic PLUS the manual rules), advanced (manual rules ONLY) or disabled (no source NAT at all). Without this, an empty search_snat_rules cannot be interpreted. - **POST** `set_outbound_nat_mode` — Set the outbound (source) NAT generation mode. Pass the object param `filter` as {general: {snat_mode: "advanced"}} — a BARE option key, not the {value,selected} map from get_outbound_nat_mode. Valid: automatic, hybrid, advanced, disabled. Switching from automatic/hybrid to advanced with no manual rules present DROPS ALL OUTBOUND NAT and will cut every masqueraded client off the internet — read search_snat_rules first. Apply with apply_firewall. - **POST** `search_snat_rules` — Search source NAT (outbound NAT) rules. An EMPTY rows list is ambiguous on its own — call get_outbound_nat_mode: in mode "automatic" no manual rules exist by design while NAT is still active; in mode "advanced" an empty list means no outbound NAT is applied. Same field-convention normalisation as search_dnat_rules: raw rows use `disabled`, `descr` and dotted source.network/destination.network, so `enabled` (boolean), `description` and negation-aware %source_net / %destination_net are added. - **POST** `add_snat_rule` — Create a new source NAT rule - **POST** `set_snat_rule` — Update a source NAT rule - **POST** `del_snat_rule` — Delete a source NAT rule - **POST** `search_npt_rules` — Search NPTv6 (IPv6 network prefix translation) rules. Rows include uuid, sequence, interface, source_net (internal prefix), destination_net (external prefix), trackif, enabled. - **GET** `get_npt_rule` — Get a single NPTv6 rule by UUID. SELECT fields (interface, trackif, categories) come back as {opt:{value,selected}} maps — flatten to the bare selected key before posting back via set_npt_rule. - **POST** `add_npt_rule` — Create an NPTv6 rule translating an internal IPv6 prefix (source_net) to an external one (destination_net). For dynamically assigned (tracked) external prefixes set trackif to the upstream interface INSTEAD of destination_net. Booleans are "0"/"1" strings; interface is the bare friendly key. The rule is stored only — call apply_firewall to activate it in pf. Returns {"result":"saved","uuid":...} or {"result":"failed","validations":{...}}. - **POST** `set_npt_rule` — Update an NPTv6 rule. FULL-REPLACE (setBase): any field you omit is reset to its model default — read with get_npt_rule, flatten SELECT maps to bare values, change what you need, then post the COMPLETE rule. Call apply_firewall afterwards to activate. - **POST** `del_npt_rule` — Delete an NPTv6 rule by UUID. Call apply_firewall afterwards to deactivate it in pf. - **POST** `toggle_npt_rule` — Enable/disable an NPTv6 rule. enabled=1 to enable, 0 to disable. Call apply_firewall afterwards. - **POST** `query_firewall_states` — Query active pf firewall states (connections) - **GET** `get_pf_statistics` — Get pf firewall statistics. Available sections: info, memory, timeouts, interfaces, rules. Pass a section name or 'all' for everything. - **GET** `get_firewall_stats` — Get firewall statistics summary - **GET** `get_firewall_log` — Get recent firewall log entries. Use limit to control result size (default 1000, can be large). Use digest for pagination (value from previous response). No content filtering — filter client-side by action, src, dst, etc. - **GET** `get_firewall_log_filters` — Get available firewall log filter options - **POST** `kill_firewall_states` — Kill pf states selected by address filter and/or rule label. WORKS ONLY FOR BARE IPv4 ADDRESSES — this is an appliance-side limitation, not a tool bug, and it fails SILENTLY with {"result":"ok","dropped_states":0}. OPNsense runs `filter` through SanitizeFilter::filter_query, which keeps only [0-9 a-z A-Z , space * - _ . #] and therefore STRIPS ":" and "/": an IPv6 address "2001:db8::1" arrives as "2001db81", and a CIDR "198.51.100.0/24" arrives as "198.51.100.024" — neither parses as a network, so both degrade to a plain substring match that matches nothing. Verified against 26.7.1_1 (kill_states.py + lib/states.py + SanitizeFilter.php). WHAT WORKS: one or more space-separated bare IPv4 addresses (e.g. "192.0.2.10 192.0.2.11"); each is matched against a state's src/dst/nat address and gateway, and ALL address clauses must match. Tokens that are not parseable as an address become substring filters over the state record. `ruleid` is matched as a lowercase substring of the pf rule label and is sanitised to alphanumerics only. FOR IPv6 OR CIDR use query_firewall_states to get stateid/creatorid and then del_firewall_state per state, or flush_firewall_states to drop everything. - **POST** `flush_firewall_states` — Flush ALL firewall states - **POST** `del_firewall_state` — Delete a specific firewall state - **GET** `list_firewall_rule_ids` — List all active pf rule IDs with descriptions - **POST** `query_pf_top` — Query top firewall connections by various criteria - **GET** `get_arp_table` — Get the ARP table (IPv4 neighbor cache). Returns ALL entries (no server-side filtering). Fields are reduced to ip, mac, hostname, intf_description to keep response compact. - **GET** `get_ndp_table` — Get the NDP table (IPv6 neighbor cache). Returns ALL entries (no server-side filtering). Fields are reduced to keep response compact. - **POST** `flush_arp_table` — Flush the entire ARP table - **GET** `get_routes` — Get the system routing table - **GET** `get_interface_config` — Get configuration of all network interfaces - **GET** `get_interface_names` — Get interface name mappings (physical ↔ friendly) - **GET** `get_interface_statistics` — Get traffic statistics for all interfaces - **GET** `get_vip_status` — Get CARP/VIP status for high availability - **GET** `get_pfsync_nodes` — Get pfsync HA cluster node status - **POST** `del_route` — Delete a route from the system routing table - **GET** `get_protocol_statistics` — Get protocol-level traffic statistics (TCP, UDP, ICMP, etc.) - **GET** `get_socket_statistics` — Get active socket/connection statistics - **GET** `get_memory_statistics` — Get network memory (mbuf) allocation statistics - **GET** `get_bpf_statistics` — Get BPF (Berkeley Packet Filter) statistics - **GET** `get_system_information` — Hostname and OPNsense/kernel version strings. Much thinner than the name suggests — no uptime, CPU or memory here (use get_system_resources / get_system_status). The raw response also carries an `updates` field whose value is the UI label "Click to check for updates." rather than any update state; it is stripped here. Real update state: check_firmware_updates or get_firmware_status. - **GET** `get_system_resources` — Get system resource usage (CPU, memory, processes) - **GET** `get_system_memory` — RAW kernel allocator dump: the complete vmstat malloc-statistics and memory-zone statistics (~45 KB of per-bucket counters). This is NOT a memory usage summary and is almost never what you want — for total/used/ARC in a few hundred bytes use get_system_resources. Reach for this only when you need per-zone allocator detail. - **GET** `get_system_disk` — Get disk usage for all filesystems - **GET** `get_system_temperature` — Get system temperature sensors - **GET** `get_system_time` — Get current system time and uptime - **GET** `get_system_swap` — Get swap space usage statistics (total, used, free) - **GET** `get_system_mbuf` — Get mbuf (network memory buffer) statistics - **GET** `get_activity` — Get running processes and system activity - **GET** `reverse_dns_lookup` — Perform a reverse DNS lookup - **GET** `get_traffic_interface` — Get current traffic rates per interface - **GET** `get_traffic_top` — Get top traffic connections for specified interfaces - **POST** `set_ping_job` — Create a ping diagnostics job (does NOT start it). Pass the single object param `ping` with a nested settings object; returns {"result":"ok","uuid":"…"} — feed the uuid to start_ping_job. Settings fields: hostname (required — target host/IP), fam (address family: "ip"=IPv4, "ip6"=IPv6; default ip), source_address (source IP to ping from — controls source-address selection, e.g. to test a specific GUA/ULA), packetsize (bytes 1-65535), disable_frag ("0"/"1"), interval (seconds between packets 1-120), description. - **POST** `start_ping_job` — Start a ping job created with set_ping_job. It pings continuously until stop_ping_job. - **POST** `stop_ping_job` — Stop a running ping job. Final statistics stay readable via search_ping_jobs until the job is removed. - **POST** `remove_ping_job` — Remove a stopped ping job and its result files - **POST** `search_ping_jobs` — List ping jobs with live status and statistics per job: id (uuid), status, hostname, send, received, loss, min, avg, max (ms) - **POST** `set_capture_job` — Create a packet capture job (does NOT start it). Pass the single object param `packetcapture` with a nested settings object; returns {"result":"ok","uuid":"…"}. Settings fields: interface (required — comma-separated PHYSICAL device names as listed in get_interfaces_overview `device`, e.g. "em0" or "em0,vlan01" — NOT friendly keys like lan/wan, those fail with "Option not in list"), fam (required address-family filter: any|ip|ip6|arp), promiscuous ("0"/"1", default 0), protocol (tcpdump protocol filter, default any — e.g. icmp, tcp, udp, esp), protocol_not ("1" inverts the protocol match), host (host/network filter), port (1-65535), port_not ("1" inverts the port match), snaplen (bytes per packet 1-262144), count (packet limit, default 100 — capture auto-stops when reached), description. - **POST** `start_capture_job` — Start a packet capture job created with set_capture_job - **POST** `stop_capture_job` — Stop a running packet capture job (it also auto-stops after `count` packets) - **GET** `view_capture_job` — View decoded packets of a capture job (tcpdump text rows per interface, with interface name map). detail: normal, medium (-v) or high (-vv). - **GET** `download_capture` — Download the raw pcap archive of a capture job as a file (open in Wireshark/tcpdump) - **POST** `remove_capture_job` — Remove a stopped capture job and its pcap files - **POST** `search_capture_jobs` — List packet capture jobs with status per job: id (uuid), status (stopped/running), interface, description - **GET** `get_capture_macinfo` — Look up the vendor (OUI) of a MAC address seen in a capture - **GET** `get_interfaces_overview` — Detailed live state of all configured interfaces. The prefix length is only embedded in the address strings (addr4 "198.51.100.2/24", addr6 "2001:db8:0:a::2/64") — this tool adds `subnetbits4` / `subnetbits6` as separate fields so no string splitting is needed (the stored config values are also in config.subnet / config.subnetv6). Per row: device, identifier (friendly key), description, addr4/addr6 plus full ipv4/ipv6 lists incl. CARP VIPs, carp (vhid → MASTER/BACKUP), macaddr, mtu, media, flags, routes. - **GET** `get_interface_detail` — Get details for a specific interface - **GET** `export_interfaces` — Export interface configuration - **POST** `reload_interface` — Re-apply the stored configuration of ONE interface (configd "interface reconfigure"): re-runs address assignment and restarts dhclient/dhcp6c on it — the API-side way to bounce/flush an interface after upstream or config changes (e.g. to re-trigger SLAAC/DHCPv6). Expect a brief connectivity loss on that interface. - **GET** `get_interface_settings` — Get global interface settings: hardware offloading flags (disablechecksumoffloading, disablesegmentationoffloading, disablelargereceiveoffloading, disablevlanhwfilter 0|1|2), the global IPv6 kill switch (disableipv6), and DHCPv6 client behavior (dhcp6_norelease, dhcp6_debug, dhcp6_duid, dhcp6_ratimeout). Also returns suggested DUID values under `duids`. - **POST** `set_interface_settings` — Update GLOBAL interface settings — PARTIAL MERGE (setNodes): only posted fields change, everything else is preserved. Pass the single object param `settings`. Fields: disablechecksumoffloading, disablesegmentationoffloading, disablelargereceiveoffloading ("0"/"1"), disablevlanhwfilter (bare "0"=enable HW filtering, "1"=disable, "2"=leave default), disableipv6 ("1" disables IPv6 on ALL interfaces — dangerous), dhcp6_norelease ("1" = do not send DHCPv6 release on exit), dhcp6_debug, dhcp6_duid (DUID string, see get response `duids` for suggestions), dhcp6_ratimeout (seconds). Call reconfigure_interface_settings to apply. - **POST** `reconfigure_interface_settings` — Apply global interface settings changes to the running system - **POST** `search_vlans` — Search VLAN interfaces - **GET** `get_vlan` — Get a VLAN interface by UUID - **POST** `add_vlan` — Create a new VLAN interface - **POST** `set_vlan` — Update an existing VLAN interface - **POST** `del_vlan` — Delete a VLAN interface - **POST** `reconfigure_vlans` — Apply VLAN interface changes to the running system configuration - **POST** `search_vips` — Search virtual IP addresses (CARP, IP alias, proxy ARP) - **POST** `add_vip` — Create a virtual IP address - **POST** `set_vip` — Update a virtual IP address - **POST** `del_vip` — Delete a virtual IP address - **POST** `reconfigure_vips` — Apply virtual IP changes - **GET** `get_unbound_settings` — Get Unbound DNS resolver settings - **POST** `set_unbound_settings` — Update Unbound DNS resolver settings - **POST** `search_unbound_host_overrides` — Search DNS host overrides (local DNS records) - **GET** `get_unbound_host_override` — Get a DNS host override by UUID - **POST** `add_unbound_host_override` — Create a DNS host override (local A/AAAA/MX record) - **POST** `set_unbound_host_override` — Update a DNS host override - **POST** `del_unbound_host_override` — Delete a DNS host override - **POST** `search_unbound_forwards` — Search DNS forwarding domains - **POST** `add_unbound_forward` — Create a DNS forwarding entry (forward queries for a domain to specific servers) - **POST** `set_unbound_forward` — Update a DNS forwarding entry - **POST** `del_unbound_forward` — Delete a DNS forwarding entry - **POST** `search_unbound_dnsbl` — Search DNS blocklist entries - **POST** `update_unbound_blocklist` — Trigger DNS blocklist update - **GET** `get_unbound_service_status` — Get Unbound DNS resolver service status - **POST** `reconfigure_unbound` — Apply Unbound DNS changes and restart - **POST** `restart_unbound` — Restart the Unbound DNS resolver - **GET** `get_unbound_cache` — Dump the Unbound DNS cache - **GET** `get_unbound_stats` — Get Unbound DNS resolver statistics - **GET** `get_unbound_local_data` — List Unbound local data entries - **GET** `get_unbound_local_zones` — List Unbound local zones - **POST** `search_wireguard_servers` — Search WireGuard server (tunnel) instances - **GET** `get_wireguard_server` — Get a WireGuard server instance by UUID - **POST** `add_wireguard_server` — Create a new WireGuard server (tunnel interface) - **POST** `set_wireguard_server` — Update a WireGuard server instance - **POST** `del_wireguard_server` — Delete a WireGuard server instance - **POST** `toggle_wireguard_server` — Toggle a WireGuard server instance on/off - **GET** `wireguard_key_pair` — Generate a new WireGuard key pair (public + private) - **POST** `search_wireguard_clients` — Search WireGuard client (peer) configurations - **GET** `get_wireguard_client` — Get a WireGuard client (peer) by UUID - **POST** `add_wireguard_client` — Create a new WireGuard client (peer) — returns a new peer with generated keys - **POST** `set_wireguard_client` — Update a WireGuard client (peer) - **POST** `del_wireguard_client` — Delete a WireGuard client (peer) - **POST** `toggle_wireguard_client` — Toggle a WireGuard client (peer) on/off - **GET** `wireguard_psk` — Generate a new WireGuard pre-shared key - **GET** `get_wireguard_status` — Get WireGuard service status - **POST** `reconfigure_wireguard` — Apply WireGuard configuration changes - **GET** `wireguard_show` — Show WireGuard tunnel status (equivalent to 'wg show') - **POST** `search_openvpn_instances` — Search OpenVPN server/client instances - **GET** `get_openvpn_instance` — Get an OpenVPN instance by UUID - **POST** `add_openvpn_instance` — Create a new OpenVPN instance - **POST** `set_openvpn_instance` — Update an OpenVPN instance - **POST** `del_openvpn_instance` — Delete an OpenVPN instance - **POST** `toggle_openvpn_instance` — Toggle an OpenVPN server or client instance on or off. Omit 'enabled' to flip current state. - **POST** `reconfigure_openvpn` — Apply OpenVPN configuration changes - **GET** `search_openvpn_sessions` — List active OpenVPN sessions/connections - **GET** `search_openvpn_routes` — List OpenVPN routing table entries - **POST** `kill_openvpn_session` — Kill an active OpenVPN session - **POST** `search_ipsec_connections` — Search IPsec connections (phase 1) - **GET** `get_ipsec_connection` — Get an IPsec connection by UUID - **POST** `add_ipsec_connection` — Create a new IPsec connection - **POST** `set_ipsec_connection` — Update an IPsec connection - **POST** `del_ipsec_connection` — Delete an IPsec connection - **POST** `toggle_ipsec_connection` — Toggle an IPsec connection on or off. Omit 'enabled' to flip the current state. - **POST** `search_ipsec_children` — Search IPsec child SAs (phase 2 / traffic selectors) - **POST** `add_ipsec_child` — Create a new IPsec child SA - **POST** `set_ipsec_child` — Update an IPsec child SA - **POST** `del_ipsec_child` — Delete an IPsec child SA - **GET** `search_ipsec_phase1` — List active IPsec phase 1 (IKE) sessions - **GET** `search_ipsec_phase2` — List active IPsec phase 2 (child SA) sessions - **POST** `connect_ipsec` — Initiate an IPsec connection - **POST** `disconnect_ipsec` — Disconnect an IPsec connection - **GET** `get_ipsec_status` — Get IPsec service status - **POST** `reconfigure_ipsec` — Apply IPsec configuration changes - **POST** `search_ipsec_psks` — Search IPsec pre-shared keys - **POST** `add_ipsec_psk` — Create an IPsec pre-shared key - **POST** `set_ipsec_psk` — Update an IPsec pre-shared key - **POST** `del_ipsec_psk` — Delete an IPsec pre-shared key - **POST** `search_kea_dhcp4_subnets` — Search Kea DHCPv4 subnets - **GET** `get_kea_dhcp4_subnet` — Get a Kea DHCPv4 subnet by UUID - **POST** `add_kea_dhcp4_subnet` — Create a new Kea DHCPv4 subnet - **POST** `set_kea_dhcp4_subnet` — Update a Kea DHCPv4 subnet - **POST** `del_kea_dhcp4_subnet` — Delete a Kea DHCPv4 subnet - **POST** `search_kea_dhcp4_reservations` — Search Kea DHCPv4 static reservations - **POST** `add_kea_dhcp4_reservation` — Create a Kea DHCPv4 static reservation - **POST** `set_kea_dhcp4_reservation` — Update a Kea DHCPv4 static reservation - **POST** `del_kea_dhcp4_reservation` — Delete a Kea DHCPv4 static reservation - **GET** `search_kea_leases` — Search active DHCP leases - **GET** `get_kea_status` — Get Kea DHCP service status - **POST** `reconfigure_kea` — Apply Kea DHCP configuration changes - **POST** `restart_kea` — Restart Kea DHCP service - **POST** `search_static_routes` — Search static routes - **GET** `get_static_route` — Get a static route by UUID - **POST** `add_static_route` — Create a new static route - **POST** `set_static_route` — Update a static route - **POST** `del_static_route` — Delete a static route - **POST** `reconfigure_routes` — Apply static route changes - **GET** `get_gateway_status` — Get gateway status (up/down, latency, loss) - **POST** `search_gateways` — Search configured gateways. WATCH OUT for `defaultgw`: the API reports it COMPUTED, not from the config — it says whether this gateway is the CURRENTLY ACTIVE default route, not whether the "Upstream Gateway" checkbox is ticked. A gateway with defaultgw=1 in config.xml is reported as false whenever a higher-priority gateway holds the default route (lower priority number wins). That looks like data loss but is not; to read the stored flag, use get_gateway (or the config backup). - **GET** `get_gateway` — Get a gateway by UUID - **POST** `add_gateway` — Create a new gateway. Provide the whole item as the object param `gateway_item` (posted as gateway_item[<field>]=... form fields). SELECT fields must be BARE option values: interface = friendly key ("wan","opt1"), ipprotocol = "inet"/"inet6". Booleans are "0"/"1" strings. Required: name, interface, ipprotocol, gateway. Returns {"result":"saved"} or {"result":"failed","validations":{...}} — inspect "validations". Fields: name, descr, disabled, interface (bare), ipprotocol (bare), gateway, defaultgw, fargw, nosync, monitor, monitor_disable, monitor_noroute, monitor_killstates, monitor_killstates_priority, force_down, priority, weight, latencylow, latencyhigh, losslow, losshigh, interval, time_period, loss_interval, data_length. - **POST** `set_gateway` — Low-level update of a gateway definition. PREFER the update_gateway composite — it does a safe read-modify-write. This primitive REPLACES the whole item: OPNsense's setBase('gateway_item','gateway_item',uuid) rebuilds the model from exactly what you post, so any field you omit is reset to its model default (monitor cleared, defaultgw/nosync/priority lost). Pass the COMPLETE item as the object param `gateway_item` (form-encoded as gateway_item[<field>]=...): use get_gateway, flatten the SELECT maps, change the fields you want, post it all back. SELECT fields must be BARE values: interface = friendly key ("wan","opt1"), ipprotocol = "inet"/"inet6". Booleans are "0"/"1" strings. Returns {"result":"saved"} on success or {"result":"failed","validations":{...}} on error. RENAMING IS IMPOSSIBLE: Gateways::validateNameChange() rejects any `name` that differs from the stored one with "Changing name on a gateway is not allowed" — no API call can rename a gateway. Create the new gateway, repoint every reference (rules, gateway groups, static routes), then delete the old one. - **POST** `del_gateway` — Delete a gateway definition by UUID - **POST** `reconfigure_gateways` — Apply gateway changes - **POST** `search_gateway_groups` — Search gateway groups (failover / load-balancing groups). Each row carries the raw item/item2..item5 tier fields PLUS a `gateways` array indexed by tier that the API enriches with the live dpinger status of every member. Remember: `item` is TIER 1. - **GET** `get_gateway_group` — Get one gateway group by UUID. Returns {gateway_group:{…}} with the tier fields as OPNsense SELECT maps ({gatewayname:{value,selected}}) — `item` is TIER 1, item2..item5 are tiers 2..5. Post them back as comma-joined BARE gateway names (see set_gateway_group), or use the update_gateway_group composite which does that flattening for you. - **POST** `add_gateway_group` — Create a gateway group. Pass the whole item as the object param `gateway_group` (form-encoded as gateway_group[<field>]=…). Fields: name (required, [a-zA-Z0-9_-]{1,32}), item (TIER 1 — comma-separated gateway NAMES), item2/item3/item4/item5 (tiers 2..5, same format), trigger (required: down | downloss | downlatency | downlosslatency, default down), poolopts ("" = default, "round-robin", "round-robin sticky-address"), descr. Gateway names must exist (search_gateways). Apply with reconfigure_gateway_groups. - **POST** `set_gateway_group` — Low-level update of a gateway group. PREFER the update_gateway_group composite. Pass the object param `gateway_group` with BARE, comma-joined gateway names in item (TIER 1) and item2..item5 — never the {value,selected} maps returned by get_gateway_group. The endpoint merges (omitted fields keep their value), but the tier fields are all-or-nothing per field: posting item="A" replaces the entire tier-1 membership. Apply with reconfigure_gateway_groups. - **POST** `del_gateway_group` — Delete a gateway group by UUID. Refuses with a UserException when the group is still referenced by a firewall rule or another gateway consumer — the message names the referring object and its UUID. - **POST** `reconfigure_gateway_groups` — Apply gateway-group changes (runs configd 'interface routes configure') - **POST** `get_firmware_status` — Get firmware update status - **POST** `check_firmware_updates` — Check for available firmware updates - **GET** `get_firmware_info` — Firmware/product identity plus the list of INSTALLED plugins. The raw endpoint answers ~330 KB (900+ base packages, all 100+ known plugins and the full changelog) with no section parameter, which does not fit in a model context — so this tool projects it down to: product identity, os_version, last_check, needs_reboot, pending upgrade count, packages_installed (count only), plugins_available (count) and plugins_installed (the actual list with name/version/tier/locked/automatic/repository/comment). For one specific package use get_firmware_details; for update state use check_firmware_updates / get_firmware_status; for the changelog get_firmware_changelog. - **GET** `get_firmware_running` — Check if a firmware operation is currently running - **POST** `update_firmware` — Start firmware update (non-blocking, check status with get_firmware_running) - **POST** `get_firmware_changelog` — Get changelog for a specific firmware version - **POST** `install_firmware_plugin` — Install a plugin package - **POST** `remove_firmware_plugin` — Remove a plugin package - **POST** `get_firmware_details` — Get details about an installed package - **GET** `get_system_status` — Get system status and pending notifications - **POST** `reboot_system` — Reboot the OPNsense appliance - **POST** `halt_system` — Shut down the OPNsense appliance - **GET** `list_backups` — List the LOCAL configuration backup history — one entry per saved config revision with timestamp, the user who caused it and the change description. Takes no arguments: the host is pinned to "this" in the path because ToolMesh does not apply parameter defaults to path segments, so the previous {host} form failed with "missing required path parameter" whenever it was called without an explicit host. For a CARP peer's history use list_peer_backups. - **GET** `list_peer_backups` — List the configuration backup history of a CARP peer (hostname as configured in HA sync). For the local appliance use list_backups. - **GET** `download_backup` — Download a configuration backup as XML (returned as a broker file URL, not inline). HANDLE WITH CARE: the config XML is the one place where EVERY secret this backend otherwise redacts is present in full — certificate and CA private keys, the HA sync password, user password hashes, PSKs, RADIUS secrets. The broker URL is unauthenticated for its lifetime, so do not pass it on. Use it for restores/diffs, not to work around the redaction on the read tools. - **POST** `revert_backup` — Revert to a previous configuration backup - **POST** `delete_backup` — Delete a configuration backup - **GET** `diff_backups` — Show the diff between two configuration backups (filenames from list_backups). Useful for "what changed at 12:13?" — but note the diff is over the raw config XML and can therefore expose secrets when a key or password changed between the two revisions. - **GET** `search_services` — List all services and their status - **POST** `start_service` — Start a system service by name (e.g. 'unbound', 'openvpn'). Use search_services to list available service names. For one instance of a multi-instance service use start_service_instance. - **POST** `stop_service` — Stop a system service by name. Use search_services to list running services. For one instance of a multi-instance service use stop_service_instance. - **POST** `restart_service` — Restart a system service by name. Useful after configuration changes or to recover a stalled service. For one instance of a multi-instance service use restart_service_instance. - **POST** `start_service_instance` — Start ONE instance of a multi-instance service. The instance id is the part after the slash in search_services ids — e.g. a per-gateway dpinger monitor is name "dpinger", id "<gateway name>". The id MUST travel as a path segment; a ?id= query param is ignored by the API router. - **POST** `stop_service_instance` — Stop ONE instance of a multi-instance service (see start_service_instance for the name/id convention). - **POST** `restart_service_instance` — Restart ONE instance of a multi-instance service — e.g. restart a single gateway's dpinger monitor after source-address or IPv6 changes without touching the other gateway monitors (name "dpinger", id = gateway name from search_services "dpinger/<gateway>"). - **GET** `get_ids_status` — Get IDS/IPS (Suricata) service status - **POST** `query_ids_alerts` — Query IDS/IPS alert log - **GET** `get_ids_alert_info` — Get detailed information for a specific IDS/IPS alert by alert ID. Returns rule metadata, classification, and affected traffic details. - **GET** `get_ids_alert_logs` — List available IDS alert log files - **POST** `reconfigure_ids` — Apply IDS/IPS configuration changes - **POST** `update_ids_rules` — Download and update IDS/IPS rulesets - **POST** `drop_ids_alert_log` — Clear the IDS alert log - **GET** `get_ids_settings` — Get IDS/IPS settings - **POST** `set_ids_settings` — Update IDS/IPS settings - **POST** `search_ids_rules` — Search installed IDS/IPS rules (signatures) - **POST** `toggle_ids_rule` — Enable or disable IDS/IPS rules by Suricata SID. Accepts comma-separated SIDs for bulk toggle. - **POST** `search_shaper_pipes` — Search traffic shaper pipes (bandwidth limiters) - **POST** `add_shaper_pipe` — Create a traffic shaper pipe (bandwidth limit) - **POST** `set_shaper_pipe` — Update a traffic shaper pipe (bandwidth limit) - **POST** `del_shaper_pipe` — Delete a traffic shaper pipe - **POST** `search_shaper_queues` — Search traffic shaper queues (within pipes) - **POST** `search_shaper_rules` — Search traffic shaper rules (match traffic to pipes/queues) - **POST** `add_shaper_rule` — Create a traffic shaper rule - **POST** `set_shaper_rule` — Update a traffic shaper rule - **POST** `del_shaper_rule` — Delete a traffic shaper rule - **POST** `reconfigure_shaper` — Apply traffic shaper changes - **GET** `get_shaper_statistics` — Get traffic shaper statistics - **POST** `search_haproxy_servers` — Search HAProxy backend servers - **POST** `add_haproxy_server` — Create an HAProxy backend server - **POST** `set_haproxy_server` — Update an HAProxy backend server - **POST** `del_haproxy_server` — Delete an HAProxy backend server - **POST** `search_haproxy_backends` — Search HAProxy backends - **POST** `add_haproxy_backend` — Create an HAProxy backend - **POST** `set_haproxy_backend` — Update an HAProxy backend - **POST** `del_haproxy_backend` — Delete an HAProxy backend - **POST** `search_haproxy_frontends` — Search HAProxy frontends (public listeners) - **POST** `add_haproxy_frontend` — Create an HAProxy frontend - **POST** `set_haproxy_frontend` — Update an HAProxy frontend - **POST** `del_haproxy_frontend` — Delete an HAProxy frontend - **GET** `get_haproxy_status` — Get HAProxy service status - **POST** `reconfigure_haproxy` — Apply HAProxy configuration changes - **GET** `test_haproxy_config` — Test HAProxy configuration for syntax errors - **GET** `get_haproxy_statistics` — Get HAProxy statistics counters - **GET** `export_haproxy_config` — Export the generated HAProxy configuration file - **GET** `diff_haproxy_config` — Show diff between staged and active HAProxy config - **POST** `search_certificates` — Search TLS/SSL certificates (inventory). PRIVATE KEY MATERIAL IS NOT RETURNED: the raw endpoint ships `prv` (base64) and `prv_payload` (the full "-----BEGIN PRIVATE KEY-----" PEM) with every row and has no opt-out parameter — a two-certificate inventory was 23 KB of mostly RSA key. Those fields, plus csr/csr_payload, arrive redacted; an empty value still shows as empty so "does this cert have a stored key?" remains answerable, and private_key_location tells you where it lives. Keys stay SETTABLE via add_certificate / set_certificate. The certificate itself (crt/crt_payload) is public and passes through. Expiry: valid_from/valid_to are raw epoch-second strings; readable %valid_from / %valid_to are added — an expired GUI certificate is easy to miss otherwise. - **GET** `get_certificate` — Get a certificate by UUID. Private key material (prv / prv_payload) and CSR fields are redacted on the way out — settable via set_certificate, never returned. crt/crt_payload (the public certificate) pass through; %valid_from / %valid_to are added. - **POST** `add_certificate` — Create/import a certificate - **POST** `set_certificate` — Update a certificate - **POST** `del_certificate` — Delete a certificate - **POST** `search_cas` — Search Certificate Authorities. Like the certificate search, the raw endpoint returns the CA's PRIVATE KEY (prv / prv_payload) on a plain listing call — arguably worse, since a CA key can mint new certificates. Those fields are redacted here; the CA certificate itself is public and passes through, and %valid_from / %valid_to are added. - **GET** `get_ca` — Get a Certificate Authority by UUID - **POST** `add_ca` — Create/import a Certificate Authority - **POST** `set_ca` — Update a Certificate Authority - **POST** `del_ca` — Delete a Certificate Authority - **GET** `get_syslog_settings` — Get syslog service settings including log retention, remote destinations, and format options - **POST** `search_syslog_destinations` — Search remote syslog destinations - **POST** `add_syslog_destination` — Create a remote syslog destination - **POST** `set_syslog_destination` — Update a remote syslog destination - **POST** `del_syslog_destination` — Delete a remote syslog destination - **POST** `reconfigure_syslog` — Apply syslog configuration changes - **GET** `get_syslog_stats` — Get syslog service statistics - **POST** `search_cron_jobs` — Search scheduled cron jobs - **GET** `get_cron_job` — Get a cron job by UUID - **POST** `add_cron_job` — Create a new cron job - **POST** `set_cron_job` — Update a scheduled cron job - **POST** `del_cron_job` — Delete a scheduled cron job by UUID - **POST** `toggle_cron_job` — Toggle a scheduled cron job on or off. Omit 'enabled' to flip the current state. - **GET** `get_hasync_settings` — Get HA synchronization settings. THE SYNC PASSWORD IS NOT RETURNED: /core/hasync/get hands out `password` in CLEAR TEXT (it is the XMLRPC credential of the peer's admin account); it is redacted here and is write-only — settable through set_hasync_settings / update_hasync_settings, never readable. An unset password still shows as empty. The multi-select fields are flattened from OPNsense's full option maps (36 entries for syncitems alone) to the comma-joined BARE selection you would post back: `syncitems` = the config sections XMLRPC-synced to the peer, `pfsyncinterface`, `pfsyncversion`. Added: "%pfsync_configured" — the model has NO `pfsyncenabled` field on 26.7 (asking for it yields null and reading that as "pfsync is off" is wrong), so this flag reports whether a pfsync interface is configured. For the live picture use get_pfsync_nodes (both creator IDs present = pfsync is actually exchanging states). - **POST** `set_hasync_settings` — Low-level update of HA sync settings. PREFER the update_hasync_settings composite (safe read-modify-write, and the only sane way to change syncitems). Provide the fields under the object param `hasync` (posted as hasync[<field>]=...). Fields: disablepreempt, disconnectppps, synchronizetoip (peer IP), username, password, verifypeer, pfsyncdefer, pfsyncpeerip, pfsyncinterface (bare key, e.g. "lan"), pfsyncversion ("1301"/"1400"), syncitems (comma-joined section keys, e.g. "aliases,ipsec,radvd,ndpproxy" — REPLACES the whole selection). Booleans are "0"/"1" strings. Returns {"result":"saved"} or {"result":"failed","validations":{...}}. - **POST** `reconfigure_hasync` — Apply local HA/pfsync changes (runs 'interface pfsync configure'). NOTE: this does NOT push config to the peer — for the XMLRPC config sync use synchronize_ha_services. - **GET** `get_ha_status_version` — Check the HA peer link: returns the backup node's version info (empty/❌ when the peer is unreachable or credentials are wrong). - **POST** `get_ha_status_services` — List HA-managed services on the peer with their sync/running state (the rows behind the HA status grid). - **POST** `synchronize_ha_services` — HA "Synchronize and reconfigure all services": pushes the current config to the backup via XMLRPC (exec_sync), reloads templates, then restarts every HA-managed service on the peer. This is the manual config-sync trigger. Returns {"status":"ok","count":N}. Heavy — it bounces services on the backup; for a routine change, a normal save already auto-syncs. - **POST** `search_radvd` — Search Router Advertisement (radvd) per-interface configurations - **GET** `get_radvd` — Get a radvd interface entry by UUID. SELECT fields (interface, mode, Adv* option fields) come back as {opt:{value,selected}} maps — flatten to the bare selected key before posting back. - **POST** `add_radvd` — Create a Router Advertisement config for an interface. Provide the whole entry as the object param `entries` (posted as entries[<field>]=...). SELECT fields are BARE values: interface = friendly key ("lan","opt1"), mode = router|unmanaged|managed|assist|stateless, AdvDefaultPreference = low|medium|high, DeprecatePrefix/RemoveAdvOnExit/RemoveRoute = ""(auto)|on|off. Booleans (enabled, dns) are "0"/"1". List fields (routes, RDNSS, DNSSL) are comma-separated. Returns {"result":"saved","uuid":...} or {"result":"failed","validations":{...}}. Then call reconfigure_radvd. - **POST** `set_radvd` — Low-level replace of a radvd entry — PREFER the update_radvd composite (read-modify-write). setBase rebuilds the entry from exactly what you post, so any omitted field resets to its model default. Pass the COMPLETE entry as the object param `entries`: use get_radvd, flatten the SELECT maps to bare values, change what you need, post it all back. Booleans "0"/"1"; interface/mode/AdvDefaultPreference bare; routes/RDNSS/DNSSL comma-separated. Returns {"result":"saved"} or {"result":"failed","validations":{...}}. - **POST** `toggle_radvd` — Enable/disable a radvd interface entry. enabled=1 to enable, 0 to disable. - **POST** `del_radvd` — Delete a radvd interface entry by UUID - **POST** `reconfigure_radvd` — Apply radvd changes (regenerates radvd.conf and reloads the daemon) - **GET** `get_ndpproxy_settings` — Get NDP Proxy settings. Returns {ndpproxy:{general:{...}, aliases:{alias:{...}}}}. `general.upstream`/`downstream` come back as interface SELECT maps. - **POST** `set_ndpproxy_settings` — Update NDP Proxy `general` settings (partial-merge — omitted fields keep their value). Fields (as ndpproxy.general.*): enabled, upstream (bare interface key), downstream (bare, comma list for multiple), ra ("0"/"1"), routes ("0"/"1"), carp_depend_on ("0"/"1", HA/CARP failover), cache_ttl, cache_max, cache_file, route_qps, pf_qps, pcap_timeout, debug. Booleans are "0"/"1". Then call reconfigure_ndpproxy. Returns {"result":"saved"} or {"result":"failed","validations":{...}}. - **POST** `search_ndpproxy_aliases` — Search NDP Proxy alias entries (proxied external firewall aliases per interface) - **GET** `get_ndpproxy_alias` — Get an NDP Proxy alias entry by UUID - **POST** `add_ndpproxy_alias` — Add an NDP Proxy alias entry (fields as alias.*): alias.interface (bare key, blank=any), alias.alias (UUID of an EXTERNAL-type firewall alias — use search_firewall_aliases to find it), alias.description. Then call reconfigure_ndpproxy. - **POST** `set_ndpproxy_alias` — Update an NDP Proxy alias entry by UUID (full-replace — post interface, alias and description). Then reconfigure_ndpproxy. - **POST** `del_ndpproxy_alias` — Delete an NDP Proxy alias entry by UUID - **POST** `reconfigure_ndpproxy` — Apply NDP Proxy changes and reload the ndp-proxy-go service - **GET** `get_ndpproxy_status` — Get NDP Proxy service run state (running/stopped) - **POST** `search_users` — Search OPNsense system users with optional filtering by name or email - **GET** `get_user` — Get a system user account by UUID including group memberships and permissions - **POST** `add_user` — Create a system user - **POST** `set_user` — Update a system user account - **POST** `del_user` — Delete a system user - **POST** `search_groups` — Search system groups - **POST** `add_user_api_key` — Generate a new API key+secret pair for a user. The key is returned as a downloadable file. IMPORTANT: the secret is not stored on the system — save it immediately. - **POST** `search_api_keys` — Search API keys across all users — returns key ID, associated username, and creation date. Keys are managed per-user, not as standalone resources. - **POST** `del_user_api_key` — Delete an API key by its ID — revokes API access for this key immediately - **GET** `get_rrd_list` — List available RRD graphs (system health metrics) - **GET** `get_system_health` — Get system health time-series data for a specific RRD metric. Use get_rrd_list to discover available metric names (e.g. cpu-usage, traffic-wan). - **GET** `get_health_interfaces` — List interfaces available for health monitoring - **POST** `search_tunables` — Search system tunables (sysctl) - **POST** `add_tunable` — Create a system tunable - **POST** `set_tunable` — Update a system tunable - **POST** `del_tunable` — Delete a system tunable - **POST** `reconfigure_tunables` — Apply tunable changes - **GET** `get_dashboard` — Get dashboard widget configuration - **GET** `get_product_info` — Get product info and update feed - **GET** `get_menu_tree` — Get the full OPNsense menu structure ## What composite workflows does the Opnsense DADL provide? - **FN** `update_gateway` — Safely update a gateway by UUID using read-modify-write. Pass `uuid` and a `changes` object with only the fields you want to change (e.g. {monitor:"8.8.8.8", losslow:"10", losshigh:"20"}). The composite GETs the current gateway_item, flattens its SELECT maps (interface, ipprotocol) to bare values, merges your changes, and POSTs the COMPLETE item back under the correct "gateway_item" node — so untouched fields (defaultgw, nosync, priority, weight, …) are preserved instead of being reset by OPNsense's full-replace setBase. Does NOT apply by default: call reconfigure_gateways yourself, or pass apply:true. On failure returns {ok:false, validations, raw} with the full OPNsense response so errors are visible instead of a bare {"result":"failed"}. Field names for `changes`: name, descr, disabled, interface (bare key, e.g. "wan"/"opt1"), ipprotocol ("inet"/"inet6"), gateway, defaultgw, fargw, nosync, monitor, monitor_disable, monitor_noroute, monitor_killstates, monitor_killstates_priority, force_down, priority, weight, latencylow, latencyhigh, losslow, losshigh, interval, time_period, loss_interval, data_length. - **FN** `update_gateway_group` — Safely edit a gateway group (failover/load-balancing tiers) by UUID via read-modify-write. Pass `uuid` plus either `changes` (raw field map) or the friendlier `tiers` map {"1": ["PRIMARY_GWv6"], "2": ["BACKUP_GWv6"]} — tier numbers 1..5, values are arrays of gateway NAMES; only the tiers you name are touched. WHY THIS EXISTS: tier 1 is stored in the field `item`, NOT `item1` (tiers 2..5 are item2..item5), and every tier is a multi-select. Hand-written code that loops item1..item5, or that assumes `item` is a scalar, skips tier 1 silently — which is how a gateway rename once left a group pointing at a gateway that no longer existed. This composite reads the group, flattens the SELECT maps to bare comma-joined names, applies your changes and posts the complete item back, then reports the resulting tiers so the result can be counted against what you asked for. Does NOT apply by default — pass apply:true or call reconfigure_gateway_groups. Other writable fields for `changes`: name, trigger (down | downloss | downlatency | downlosslatency), poolopts ("" | "round-robin" | "round-robin sticky-address"), descr. - **FN** `update_hasync_settings` — Safely update HA sync settings — especially the syncitems multi-select — via read-modify-write. Pass `changes` (scalar fields: synchronizetoip, username, password, disablepreempt, disconnectppps, verifypeer, pfsyncinterface (bare), pfsyncversion, pfsyncpeerip, pfsyncdefer) and/or `enable_syncitems` / `disable_syncitems` (arrays of section keys, e.g. ["radvd","ndpproxy"]). The composite GETs the current hasync model, derives the new syncitems selection FROM the current one (so untouched sections are preserved, never clobbered by a bare set), merges your scalar changes, and POSTs only what changed (setNodes merges). Does NOT apply pfsync (call reconfigure_hasync if you changed a pfsync field). Valid syncitems keys are whatever the appliance reports — commonly aliases, authservers, captiveportal, categories, certs, cron, dhcpd, dhcpdv6, dhcrelay, dnsforwarder, dnsresolver, hostwatch, ifgroups, ipsec, kea, lvtemplate, monit, nat, ndpproxy, ntpd, opendns, openvpn, radvd, rules, schedules, shaper, ssh, staticroutes, suricata, sysctl, syslog, syslog-ng, users, virtualip, webgui, wireguard. On failure returns {ok:false, validations, raw}. PASSWORD: `changes.password` is accepted and written normally — the sync password is write-only, not unwritable. It is never read back (get_hasync_settings redacts it), and this composite never copies it from the current model, so a plain update_hasync_settings({changes:{synchronizetoip:"…"}}) leaves the stored password untouched. A `changes` value that is itself the redaction marker is rejected rather than written. - **FN** `update_radvd` — Safely update a radvd interface entry by UUID via read-modify-write. Pass `uuid` and a `changes` object with only the fields to change (e.g. {mode:"managed", dns:"1"}). The composite GETs the current entry, flattens its SELECT maps (interface, mode, Adv* option fields, AdvRASrcAddress) to bare values, merges your changes, and POSTs the COMPLETE entry back under the `entries` node — so untouched fields are preserved instead of being reset by setBase's full-replace. Does NOT apply by default: call reconfigure_radvd, or pass apply:true. Field names for `changes`: enabled, interface (bare), Base6Interface (bare), mode (router|unmanaged|managed|assist|stateless), dns, DeprecatePrefix/RemoveAdvOnExit/RemoveRoute (""|on|off), routes/RDNSS/DNSSL (comma lists), MinRtrAdvInterval, MaxRtrAdvInterval, AdvDefaultPreference (low|medium|high), AdvCurHopLimit, AdvDefaultLifetime, AdvLinkMTU, AdvPreferredLifetime, AdvValidLifetime, AdvRDNSSLifetime, AdvRouteLifetime, AdvDNSSLLifetime, AdvRASrcAddress, nat64prefix. On failure returns {ok:false, validations, raw}. ## Which DADLs are related to Opnsense? - [Graylog](https://www.dadl.ai/d/graylog/) — Graylog REST API -- log search (Views/Search + legacy universal), streams, pipelines, inputs, alerts, events, dashboards, users, roles, sidecars, index management, and cluster administration. Targets Graylog 6.x. - [Mikrotik](https://www.dadl.ai/d/mikrotik/) — MikroTik RouterOS REST API -- manage interfaces, IP addresses, routing, firewall, DHCP, DNS, PPP, queues, wireless, system configuration, users, certificates, files, logs, and diagnostics on RouterOS v7.1+ devices - [PeeringDB](https://www.dadl.ai/d/peeringdb/) — PeeringDB v2 API -- the public peering database of networks (ASNs), Internet Exchanges, and colocation facilities: full CRUD over net, ix, fac, org, carrier, campus, point-of-contact records, and the netixlan/netfac/ixfac/carrierfac/ixlan/ixpfx relationships that map who peers where - [Xen Orchestra](https://www.dadl.ai/d/xen-orchestra/) — Xen Orchestra REST API (XO 6.4+, current through 6.9) -- complete coverage: VMs (incl. PATCH update + snapshot revert), VM controllers, hosts (incl. full power/lifecycle actions + maintenance mode + PIF rescan), pools (incl. add_host, rolling reboot/update with interrupted-update recovery + finalize), storage (SR create/delete, VDI incl. PATCH update + vhd/raw/qcow2 export, VBD), networks (VIF incl. PATCH update + PIF/PBD), VM/VDI snapshots, VM templates, hardware (PCI/PGPU/SM), tasks, backups (archives incl. live mount of backup disks, jobs/logs, repositories incl. health + benchmark + space reclaim), schedules, messages, alarms, events (SSE incl. non-XAPI collections), RBAC v2 (users/groups/acl-roles/acl-privileges incl. assignment introspection), proxies, servers, dashboards, SDN traffic rules (add/delete/update), IPMI sensor inventory (plugin), audit records (plugin), health check - [Zammad](https://www.dadl.ai/d/zammad/) — Zammad helpdesk REST API -- tickets, articles, users, organizations, groups, roles, knowledge base, SLAs, calendars, object manager (custom fields), macros, triggers, overviews, reports, time accounting, and full admin surface. Supports X-On-Behalf-Of impersonation on every endpoint. - [Alertmanager](https://www.dadl.ai/d/alertmanager/) — Prometheus Alertmanager API v2 -- alerts, silences, receivers, alert groups, status, and operational health --- **Canonical URL:** https://www.dadl.ai/d/opnsense/ **Raw DADL:** https://github.com/DunkelCloud/dadl-registry/blob/main/opnsense.dadl --- # PeeringDB MCP Server — 80 tools via DADL The PeeringDB DADL turns PeeringDB's API into an MCP server that Claude, GPT or any MCP-compatible agent can consume directly. One YAML file declares all 80 tools — org, fac, ix, net, netixlan, campus, and more — and ToolMesh serves them at runtime. No Python boilerplate, no per-endpoint code, no separate MCP server process. Below: the endpoint coverage matrix, a two-block ToolMesh setup, the full tool reference grouped by PeeringDB feature area, required credential scopes. **Source:** [PeeringDB API](https://www.peeringdb.com/apidocs/) **Updated:** 2026-06-25 **Tags:** networking, crud, user-management, authentication, real-time, logging, monitoring, auth:bearer ## Which PeeringDB endpoints are covered? **100%** (80 of ~80 endpoints). **Focus:** PeeringDB v2 peering database: net, ix, fac, org records, net (ASN, IRR as-set, peering policy, info prefixes), ix (Internet exchanges, ixlan, ixpfx), fac (datacenter facilities, address, geolocation), org (organizations, poc contacts, members, logos), netixlan (peering presence, IPv4, IPv6, port speed). **Missing:** None of the documented /api endpoints are omitted. Per-field filter parameters are documented (suffix system) rather than enumerated exhaustively; HTTP PATCH partial_update is served by the PUT-based update tools. *Last reviewed: 2026-06-25* ## How do you configure the PeeringDB DADL? 1. Create a free account at https://www.peeringdb.com and log in. 2. USER KEY: click your username (top-right) -> Profile, open the 'API Keys' panel (https://www.peeringdb.com/profile/api_keys). 3. Click 'Add API Key', give it a label, and choose the scope: leave it a normal key to mirror your account's write permissions, or tick 'read-only' for safe read access across your namespaces. 4. Click 'Add Key' and COPY the key value immediately -- it is shown only once. If lost, revoke it and create a new one. 5. ORG KEY (for automation not tied to a person): go to the organization's admin panel -> 'API Keys', add a key with an associated email and per-namespace permissions. 6. Provide only the raw key value to ToolMesh -- it sends the 'Authorization: Api-Key <key>' header automatically. 7. For anonymous read-only access, set the credential to 'none' (subject to lower shared rate limits). **Environment variable:** `CREDENTIAL_PEERINGDB_API_KEY` [Authentication docs](https://docs.peeringdb.com/howto/api_keys/) *base_url is the public hosted instance (https://www.peeringdb.com/api). Reads work without a key but share a lower anonymous rate limit; a key raises limits and is required for writes and for private/contact data. Prefer a read-only key unless you intend to modify records. Interactive API docs: https://www.peeringdb.com/apidocs/ -- raw schema: https://www.peeringdb.com/s/2.80.1/api-schema.yaml* ## How do you install the PeeringDB MCP server with ToolMesh? Add to your `backends.yaml`: ```yaml - name: peeringdb transport: rest dadl: peeringdb.dadl url: "https://www.peeringdb.com/api" ``` Set the credential: ``` CREDENTIAL_PEERINGDB_API_KEY=your-token-here ``` ## What 80 tools does the PeeringDB DADL expose? - **GET** `list_orgs` — List organizations. Filter by name/city/country; expand owned net/ix/fac/carrier/campus sets with depth. - **GET** `get_org` — Retrieve a single organization by id. Returns a one-element data array. Use depth=2 to expand its net_set/ix_set/fac_set/carrier_set/campus_set. - **POST** `create_org` — Create an organization. RESTRICTED to PeeringDB staff -- normal API keys are rejected. New orgs are status='pending'. - **PUT** `update_org` — Update an organization (partial -- send only changed fields). Same writable fields as create_org. - **DELETE** `delete_org` — Soft-delete an organization (marks status='deleted'). Only empty orgs (no active children) can be deleted. - **GET** `list_org_users` — List the user accounts (members/admins) attached to an organization. Requires admin rights on the org. - **POST** `add_org_user` — Add an existing PeeringDB user to an organization with a role. Identify the user by user_id (preferred) or email. Org-admin operation. - **PUT** `update_org_user` — Update an organization member's role (admin <-> member). Org-admin operation. - **DELETE** `remove_org_user` — Remove a user from an organization's membership (does not delete the user account). Org-admin operation. - **GET** `list_facs` — List facilities (datacenters). Filter by name, org_id, city, country, state, clli, npanxx; expand netfac/ixfac sets with depth. - **GET** `get_fac` — Retrieve a single facility by id (one-element data array). depth=2 expands its net/ix presence sets. - **POST** `create_fac` — Create a facility under an organization. New facilities are status='pending' until staff approval. - **PUT** `update_fac` — Update a facility (partial). Same writable fields as create_fac. - **DELETE** `delete_fac` — Soft-delete a facility (status='deleted'). - **GET** `list_nets` — List networks. ASN is unique: ?asn=13335 returns one network. Also filter by name, org_id, info_type, info_scope, irr_as_set; expand peering/facility/contact sets with depth. - **GET** `get_net` — Retrieve a single network by its internal id (NOT the ASN; query list_nets?asn=... to look up by ASN). One-element data array. depth=2 expands netixlan_set/netfac_set/poc_set. - **POST** `create_net` — Create a network under an organization. Requires org_id, name and asn. New networks are status='pending' until staff approval. ASN is set-once. - **PUT** `update_net` — Update a network (partial). Same writable fields as create_net. Note: asn cannot be changed after creation. - **DELETE** `delete_net` — Soft-delete a network (status='deleted'). - **GET** `list_ixes` — List Internet Exchanges. Filter by name, org_id, city, country, region_continent; expand ixlan_set/fac_set with depth. - **GET** `get_ix` — Retrieve a single Internet Exchange by id (one-element data array). depth=2 expands ixlan_set and fac_set. - **POST** `create_ix` — Create an Internet Exchange. Requires org_id, name, city, country and prefix (the initial IX LAN CIDR, which bootstraps an ixlan + ixpfx). New IXes are status='pending'. - **PUT** `update_ix` — Update an Internet Exchange (partial). Same writable fields as create_ix (the 'prefix' field only applies at creation). - **DELETE** `delete_ix` — Soft-delete an Internet Exchange (status='deleted'). - **POST** `request_ixf_import` — Queue an IX-F member-list import for an exchange. Requires the exchange's ixlan to have ixf_ixp_member_list_url set and import enabled. - **GET** `list_ixlans` — List IX LANs. Filter by ix_id; expand ixpfx_set/net_set with depth. - **GET** `get_ixlan` — Retrieve a single IX LAN by id (one-element data array). depth=2 expands ixpfx_set and net_set. - **PUT** `update_ixlan` — Update an IX LAN (partial). IX LANs are created/deleted together with their parent exchange, so only update is available. - **GET** `list_ixpfxs` — List IX LAN prefixes. Filter by ixlan_id, prefix, protocol (IPv4|IPv6), in_dfz. - **GET** `get_ixpfx` — Retrieve a single IX LAN prefix by id (one-element data array). - **POST** `create_ixpfx` — Add an IP prefix to an IX LAN. Requires ixlan_id, protocol and prefix (CIDR). - **PUT** `update_ixpfx` — Update an IX LAN prefix (partial). Same writable fields as create_ixpfx. - **DELETE** `delete_ixpfx` — Soft-delete an IX LAN prefix (status='deleted'). - **GET** `list_ixfacs` — List IX-facility presences (an exchange present at a facility). Filter by ix_id, fac_id. - **GET** `get_ixfac` — Retrieve a single IX-facility presence by id (one-element data array). - **POST** `create_ixfac` — Record that an Internet Exchange is present at a facility. Requires ix_id and fac_id. - **PUT** `update_ixfac` — Update an IX-facility presence (partial). Repoints ix_id / fac_id. - **DELETE** `delete_ixfac` — Soft-delete an IX-facility presence (status='deleted'). - **GET** `list_netfacs` — List network-facility presences (a network present at a facility). Filter by net_id, fac_id, local_asn. - **GET** `get_netfac` — Retrieve a single network-facility presence by id (one-element data array). - **POST** `create_netfac` — Record that a network is present at a facility. Requires net_id and fac_id. - **PUT** `update_netfac` — Update a network-facility presence (partial). Repoints net_id / fac_id. - **DELETE** `delete_netfac` — Soft-delete a network-facility presence (status='deleted'). - **GET** `list_netixlans` — List peering presences: each row is a network (asn) on an IX LAN with its ipaddr4/ipaddr6 and port speed (Mbit/s). Filter by net_id, ix_id, ixlan_id, asn, ipaddr4, ipaddr6, is_rs_peer, operational, speed. - **GET** `get_netixlan` — Retrieve a single peering presence by id (one-element data array). - **POST** `create_netixlan` — Add a network's peering presence on an IX LAN. Requires net_id, ixlan_id, asn (must match the net's ASN) and speed; supply ipaddr4 and/or ipaddr6. - **PUT** `update_netixlan` — Update a peering presence (partial). Same writable fields as create_netixlan. - **DELETE** `delete_netixlan` — Soft-delete a peering presence (status='deleted'). - **POST** `set_netixlan_net_side` — Set the network-side facility of a peering presence (which facility the network's connection lands in). Requires fac_id. - **POST** `set_netixlan_ix_side` — Set the IX-side facility of a peering presence (which facility the exchange's connection lands in). Requires fac_id. - **GET** `list_pocs` — List network points of contact. Filter by net_id, role, name, email, phone. Private/Users-visibility contacts require an authorized key. - **GET** `get_poc` — Retrieve a single point of contact by id (one-element data array). - **POST** `create_poc` — Create a point of contact on a network. Requires net_id and role. - **PUT** `update_poc` — Update a point of contact (partial). Same writable fields as create_poc. - **DELETE** `delete_poc` — Soft-delete a point of contact (status='deleted'). - **GET** `list_carriers` — List carriers. Filter by name, org_id; expand carrierfac_set with depth. - **GET** `get_carrier` — Retrieve a single carrier by id (one-element data array). depth=2 expands carrierfac_set. - **POST** `create_carrier` — Create a carrier under an organization. Requires org_id and name. - **PUT** `update_carrier` — Update a carrier (partial). Same writable fields as create_carrier. - **DELETE** `delete_carrier` — Soft-delete a carrier (status='deleted'). - **GET** `list_carrierfacs` — List carrier-facility presences. Filter by carrier_id, fac_id. - **GET** `get_carrierfac` — Retrieve a single carrier-facility presence by id (one-element data array). - **POST** `create_carrierfac` — Record that a carrier is present at a facility. Requires carrier_id and fac_id. The presence starts pending until the facility owner approves it. - **PUT** `update_carrierfac` — Update a carrier-facility presence (partial). Repoints carrier_id / fac_id. - **DELETE** `delete_carrierfac` — Soft-delete a carrier-facility presence (status='deleted'). - **POST** `approve_carrierfac` — Approve a pending carrier-facility presence (facility-owner / staff action). - **POST** `reject_carrierfac` — Reject a pending carrier-facility presence (facility-owner / staff action). - **GET** `list_campuses` — List campuses (groupings of nearby facilities). Filter by name, org_id; expand fac_set with depth. - **GET** `get_campus` — Retrieve a single campus by id (one-element data array). depth=2 expands fac_set. - **POST** `create_campus` — Create a campus under an organization. Requires org_id and name. A campus's location fields are derived from its member facilities. - **PUT** `update_campus` — Update a campus (partial). Same writable fields as create_campus. - **DELETE** `delete_campus` — Soft-delete a campus (status='deleted'). - **POST** `add_campus_facility` — Add a facility to a campus. Both must belong to the same organization and be geographically close. - **POST** `remove_campus_facility` — Remove a facility from a campus (does not delete the facility). - **GET** `list_as_sets` — List the ASN -> IRR as-set mapping for all networks (read-only). The data object maps each ASN to its irr_as_set string. - **GET** `get_as_set` — Get the IRR as-set / route-set handle for a single ASN (read-only). - **GET** `get_asset` — Retrieve an entity's asset (logo). file_data is returned base64-encoded. - **POST** `create_asset` — Upload/set an entity's logo. Provide file_type (image/png or image/jpeg) and base64 file_data. - **PUT** `update_asset` — Replace an entity's logo. Same body fields as create_asset. - **DELETE** `delete_asset` — Delete an entity's logo asset. ## What composite workflows does the PeeringDB DADL provide? - **FN** `find_net_by_asn` — Look up a single network by its ASN (ASN is globally unique). Returns the network object or null if no network has that ASN. - **FN** `get_asn_presence` — Map an ASN's peering footprint: the Internet Exchanges (with peering IPs/speed) and the facilities where the network is present. Returns {asn, name, net_id, exchanges[], facilities[]} or {found:false}. - **FN** `score_net_completeness` — Score a network's PeeringDB record for peering-readiness (0-100) against the fields IXes commonly require; returns the score, the failing checks, and the full checklist. NOTE: has_tech_contact/has_abuse depend on POC visibility -- contacts marked 'Users' or 'Private' are only returned to an authorized API key, so a low contact score can mean 'not visible to this key' rather than 'absent'. - **FN** `audit_netixlan_ip_integrity` — Data-quality audit of one Internet Exchange's peering table: flags netixlan IPs (IPv4 and IPv6) that fall outside the LAN's ixpfx prefixes, and duplicate IPv4/IPv6 addresses on the same LAN. Pages through all members; returns only the violations and sets truncated=true if a LAN exceeds the 40-page cap. Pass an ix_id from list_ixes. - **FN** `audit_net_presence` — Consistency audit of a network's peering presence: flags netixlan.asn that disagrees with the net's ASN, non-operational connections, rows with no IP address, invalid speeds, and the case where the net declares IPv6 (info_ipv6=true) but no netixlan carries an IPv6 address. Returns the net summary plus the list of issues. Pass an ASN. ## Which DADLs are related to PeeringDB? - [Mikrotik](https://www.dadl.ai/d/mikrotik/) — MikroTik RouterOS REST API -- manage interfaces, IP addresses, routing, firewall, DHCP, DNS, PPP, queues, wireless, system configuration, users, certificates, files, logs, and diagnostics on RouterOS v7.1+ devices - [Checkmk](https://www.dadl.ai/d/checkmk/) — Checkmk REST API (version 1.0, Checkmk 2.4) -- live host and service status via Livestatus queries, downtimes, acknowledgements and comments, the Event Console (list, acknowledge, change state and archive events) and BI (packs, rules, aggregations and live aggregation state), plus the full Setup side: hosts, clusters, folders, service discovery, rules and rulesets, host/service/contact groups, users, roles, passwords, time periods, host tags, notification rules, site connections and change activation. - [Graylog](https://www.dadl.ai/d/graylog/) — Graylog REST API -- log search (Views/Search + legacy universal), streams, pipelines, inputs, alerts, events, dashboards, users, roles, sidecars, index management, and cluster administration. Targets Graylog 6.x. - [Opnsense](https://www.dadl.ai/d/opnsense/) — OPNsense firewall REST API — manage firewall rules, aliases, interfaces, VPN, DHCP, DNS, diagnostics, firmware, and services on OPNsense appliances - [Alertmanager](https://www.dadl.ai/d/alertmanager/) — Prometheus Alertmanager API v2 -- alerts, silences, receivers, alert groups, status, and operational health - [Hacker News](https://www.dadl.ai/d/hackernews/) — Hacker News API — read-only access to stories, comments, polls, jobs, users, and live feeds from news.ycombinator.com --- **Canonical URL:** https://www.dadl.ai/d/peeringdb/ **Raw DADL:** https://github.com/DunkelCloud/dadl-registry/blob/main/peeringdb.dadl --- # Shelly Cloud MCP Server — 14 tools via DADL The Shelly Cloud DADL turns Shelly Cloud's API into an MCP server that Claude, GPT or any MCP-compatible agent can consume directly. One YAML file declares all 14 tools — bulk, device, light, cover, group, switch, and more — and ToolMesh serves them at runtime. No Python boilerplate, no per-endpoint code, no separate MCP server process. Below: the endpoint coverage matrix, a two-block ToolMesh setup, the full tool reference grouped by Shelly Cloud feature area. **Source:** [Shelly Cloud Control API](https://shelly-api-docs.shelly.cloud/cloud-control-api/) **Updated:** 2026-03-26 **Tags:** iot, cloud, crud, bulk-operations, authentication, auth:apikey ## Which Shelly Cloud endpoints are covered? **78%** (14 of ~18 endpoints). **Focus:** device status, switch control, cover control, light control, group control, bulk relay, bulk light, bulk roller **Missing:** real-time WebSocket events, integrator token exchange, OAuth token exchange *Last reviewed: 2026-03-26* ## How do you configure the Shelly Cloud DADL? 1. Install the Shelly mobile app (iOS/Android) and create a Shelly Cloud account 2. Add your Shelly devices to the app and ensure they are cloud-connected 3. In the app, go to User Settings > Authorization cloud key 4. Copy both the 'auth_key' and the 'server_uri' values 5. The server_uri becomes the base URL (e.g. https://shelly-103-eu.shelly.cloud) **Environment variable:** `CREDENTIAL_SHELLY_AUTH_KEY` [Authentication docs](https://shelly-api-docs.shelly.cloud/cloud-control-api/) *The server_uri is per-account and region-specific (e.g. shelly-103-eu.shelly.cloud). You MUST use the server_uri shown in your Shelly app — there is no universal base URL. The auth_key regenerates automatically if you change your account password. * ## How do you install the Shelly Cloud MCP server with ToolMesh? Add to your `backends.yaml`: ```yaml - name: shelly-cloud transport: rest dadl: /app/dadl/shellycloud.dadl url: "https://<your-server-uri>" ``` Set the credential: ``` CREDENTIAL_SHELLY_AUTH_KEY=your-token-here ``` ## What 14 tools does the Shelly Cloud DADL expose? - **POST** `get_devices_status` — Get state of up to 10 Shelly devices. Returns online status, settings, and/or live sensor/relay data per device. Use list_devices first to discover device IDs. - **POST** `set_switch` — Turn a Shelly relay/switch on or off. Supports auto-off timer via toggle_after. - **POST** `set_cover` — Control a Shelly cover/roller. Supports open/close/stop commands, absolute position (0-100), relative movement, and slat control. position and relative are mutually exclusive. slatPosition and slatRelative are mutually exclusive. - **POST** `set_light` — Control a Shelly light or dimmer. Supports on/off, brightness, color temperature, RGBW color, and effects. - **POST** `set_groups` — Batch-control multiple devices at once by type. Send commands to groups of switches, covers, and/or lights in a single request. Device IDs in group arrays use format "deviceId_channel". Response may include failedCommands for devices that errored. - **POST** `v1_device_status` — [DEPRECATED — use get_devices_status] Get device online status and state. Returns relay states, power readings, sensor data. - **POST** `v1_relay_control` — [DEPRECATED — use set_switch] Control a relay on/off. - **POST** `v1_roller_control` — [DEPRECATED — use set_cover] Control a roller/cover shutter. - **POST** `v1_light_control` — [DEPRECATED — use set_light] Control a light (RGBW or white mode). - **POST** `v1_relay_bulk_control` — [DEPRECATED — use set_groups] Bulk-control multiple relays at once. - **POST** `v1_light_bulk_control` — [DEPRECATED — use set_groups] Bulk-control multiple lights at once. - **POST** `v1_roller_bulk_control` — [DEPRECATED — use set_groups] Bulk-control multiple rollers at once. - **POST** `list_devices` — List all devices on the account with names, types, and IDs. Unofficial endpoint used by the Shelly app — not in the official API docs but stable and widely used by integrations. - **POST** `get_all_device_status` — Get status of all devices on the account in a single call. Returns online state, relay/sensor data for every device. Use show_info=true to include device names and types inline (avoids a separate list_devices call). ## What composite workflows does the Shelly Cloud DADL provide? - **FN** `get_named_status` — Get all device status with human-readable names and on/off summary. Joins list_devices (names) with get_all_device_status (live state). ## Which DADLs are related to Shelly Cloud? - [Cloudflare](https://www.dadl.ai/d/cloudflare/) — Cloudflare API -- DNS, Pages, Workers, KV, R2, D1, Zones, SSL/TLS, Cache, Load Balancers, Firewall/WAF, Page Rules, Access (Zero Trust), Email Routing, Email Sending, DMARC/SPF email auth, and account management - [Linode](https://www.dadl.ai/d/linode/) — Linode (Akamai) cloud infrastructure API -- compute instances, volumes, DNS, networking, Kubernetes, databases, object storage, and account management - [Tailscale](https://www.dadl.ai/d/tailscale/) — Tailscale API -- devices, users, auth keys, DNS, ACL/policy, webhooks, contacts, posture integrations, log streaming, and tailnet settings - [Billomat](https://www.dadl.ai/d/billomat/) — Billomat REST API — German cloud invoicing & accounting: invoices, estimates, credit notes, recurring invoices, delivery notes, order confirmations, dunning reminders, clients, contacts, articles, payments, expenses, taxes - [DokuWiki](https://www.dadl.ai/d/dokuwiki/) — DokuWiki JSON-RPC API — wiki pages, media files, search, ACL management, and user administration - [GitLab](https://www.dadl.ai/d/gitlab/) — GitLab REST API v4 — projects, issues, merge requests, pipelines, CI/CD, and code search --- **Canonical URL:** https://www.dadl.ai/d/shelly-cloud/ **Raw DADL:** https://github.com/DunkelCloud/dadl-registry/blob/main/shelly-cloud.dadl --- # Soniox MCP Server — 25 tools via DADL The Soniox DADL turns Soniox's API into an MCP server that Claude, GPT or any MCP-compatible agent can consume directly. One YAML file declares all 25 tools — transcription, voice, file, speech, audio, usage, and more — and ToolMesh serves them at runtime. No Python boilerplate, no per-endpoint code, no separate MCP server process. Below: the endpoint coverage matrix, a two-block ToolMesh setup, the full tool reference grouped by Soniox feature area. **Source:** [Soniox Speech AI API](https://soniox.com/docs/api-reference) **Updated:** 2026-08-23 **Tags:** ai, cloud, automation, crud, file-management, user-management, real-time, translation, auth:bearer ## Which Soniox endpoints are covered? **93%** (25 of ~27 endpoints). **Focus:** Soniox Speech AI REST API v1: transcriptions (async speech-to-text, speaker diarization, language identification, speech translation), voices (voice cloning, per model readiness, recompute), files (audio upload, storage quotas, counts), speech synthesis (audio formats, sample rates, cloned voices), usage (cost logs, daily summary, concurrency limits), models (transcription models, synthesis models), temporary API keys. **Missing:** The two WebSocket APIs — real-time speech-to-text (wss://stt-rt.soniox.com/transcribe-websocket) and real-time text-to-speech (wss://tts-rt.soniox.com/tts-websocket). Both are streaming protocols that DADL cannot describe; create_temporary_api_key here mints the short-lived keys those clients authenticate with. *Last reviewed: 2026-08-23* ## How do you configure the Soniox DADL? 1. Create a Soniox account at https://console.soniox.com (free credit is granted on signup; no credit card needed to start). 2. Pick or create a PROJECT. Data residency and API keys are per project — if you need EU or JP processing, set the region when creating the project (contact support@soniox.com to have regions enabled). 3. Open the API keys section of the Console and create a new API key. Copy it immediately — the full key is shown only once. 4. Store it in the ToolMesh credential store under the name 'soniox_api_key' (env var CREDENTIAL_SONIOX_API_KEY for the embedded store). 5. Verify: curl -H "Authorization: Bearer $SONIOX_API_KEY" https://api.soniox.com/v1/models — a 200 with a models array means the key works, 401 unauthenticated means it does not. 6. For a non-US project, set url in backends.yaml to https://api.eu.soniox.com or https://api.jp.soniox.com AND edit the absolute path of the generate_speech tool in this file to the matching tts-rt.<region>.soniox.com host. A key from one region does not work against another. **Environment variable:** `CREDENTIAL_SONIOX_API_KEY` [Authentication docs](https://soniox.com/docs/api-reference) *Soniox API keys have no scopes — one key grants full access to its project, so treat it as a secret and never ship it to a client. For browser or mobile clients use create_temporary_api_key instead (usage_type transcribe_websocket or tts_rt, max 3600s lifetime). Billing is usage-based per audio minute and token; the free signup credit is enough to exercise every tool in this file. Quotas that will bite in production: 1000 stored files, 10 GB storage, 100 pending and 2000 total transcriptions — delete what you have fetched, nothing expires by itself. * ## How do you install the Soniox MCP server with ToolMesh? Add to your `backends.yaml`: ```yaml - name: soniox transport: rest dadl: soniox.dadl url: "https://api.soniox.com" ``` Set the credential: ``` CREDENTIAL_SONIOX_API_KEY=your-token-here ``` ## What 25 tools does the Soniox DADL expose? - **GET** `list_files` — List uploaded audio files in the project, newest first. Returns {files: [{id, filename, size, created_at, client_reference_id}], next_page_cursor}. size is in bytes. next_page_cursor is null on the last page — pass it back as cursor to continue. The project holds at most 1000 files / 10 GB by default; use get_files_count to check headroom before uploading. - **POST** `upload_file` — Upload an audio file for later transcription. The caller passes a URL; ToolMesh fetches the bytes and posts them as the multipart 'file' field. Returns the created file {id, filename, size, created_at, client_reference_id} — pass that id as file_id to create_transcription. Format is auto-detected (aac, aiff, amr, asf, flac, mp3, ogg, wav, webm, m4a, mp4 and more); no encoding parameters exist. Audio longer than 300 minutes is rejected, and that cap cannot be raised. Fails with 429 limit_exceeded when the 1000-file or 10 GB project cap would be exceeded — delete unused files first. Files are NEVER auto-deleted. Prefer create_transcription with a public audio_url when the audio is already reachable on the web: that skips storage entirely. - **GET** `get_files_count` — Count stored files, split by origin: {playground, public_api, total}. total counts against the 1000-file project cap regardless of origin (files created in the web Playground count too). Cheap — use it before a bulk upload instead of paging through list_files. - **GET** `get_file` — Get metadata for one uploaded file: {id, filename, size, created_at, client_reference_id}. There is no download endpoint — Soniox does not serve the audio back. Returns 404 file_not_found if the id is unknown, already deleted, or belongs to a different project. - **DELETE** `delete_file` — Permanently delete an uploaded file. Irreversible — Soniox keeps no copy and there is no download endpoint to recover the audio from. Returns 204 with no body on success, 404 file_not_found otherwise. Deleting the file does NOT delete transcriptions made from it, and an already-completed transcript stays readable. Do this as soon as the transcript is fetched: storage caps are per project and nothing expires on its own. - **GET** `list_transcriptions` — List transcription jobs, newest first. Returns {transcriptions: [{id, status, created_at, model, filename, file_id, audio_url, audio_duration_ms, language_hints, enable_speaker_diarization, enable_language_identification, error_type, error_message, webhook_status_code, client_reference_id}], next_page_cursor}. status is queued | processing | completed | error. The webhook URL and secret fields are dropped from this projection; call get_transcription for the full object. Every entry — including failed ones — counts against the 2000 transcription cap. - **POST** `create_transcription` — Submit recorded audio for asynchronous transcription. Returns the job immediately with status "queued" — NO text. Poll get_transcription until status is "completed" (then call get_transcription_transcript) or "error", or set webhook_url to be notified instead. Audio source: exactly one of audio_url (a public http/https URL Soniox fetches itself) or file_id (from upload_file). Passing both is a 400. model is required — use "stt-async-v5" for recorded audio (v4 is an alias for it); call list_models for the authoritative list. language_hints is an array of 2-letter codes (["en","de"]); omit it to auto-detect. language_hints_strict makes the model trust those hints harder. enable_speaker_diarization adds a speaker label to every token; enable_language_identification adds a language label. translation is an object, either {"type":"one_way","target_language":"de"} or {"type":"two_way","language_a":"en","language_b":"es"} — with it the transcript carries both original and translated tokens, tagged by translation_status. context accepts a plain string, or the structured form {"general":[{"key":"Domain","value":"medicine"}],"text":"...", "terms":["Soniox"],"translation_terms":[{"source":"cloud","target":"Cloud"}]} to bias the model toward names and jargon. webhook_url plus optional webhook_auth_header_name / webhook_auth_header_value replace polling. Fails with 429 limit_exceeded at 100 pending or 2000 total transcriptions, and with 400 model_not_available for an unknown model. - **GET** `get_transcriptions_count` — Count transcriptions by origin: {playground, public_api, total}. total is the number that counts against the 2000-transcription project cap (queued + processing + completed + error, from any origin). Check this before bulk-submitting; at the cap create_transcription returns 429 limit_exceeded until old jobs are deleted. - **GET** `get_transcription` — Get one transcription job with its current status. Returns {id, status, created_at, model, audio_url, file_id, filename, language_hints, enable_speaker_diarization, enable_language_identification, audio_duration_ms, error_type, error_message, webhook_url, webhook_auth_header_name, webhook_auth_header_value (masked), webhook_status_code, client_reference_id}. status is queued | processing | completed | error. This is the polling endpoint: repeat until status leaves queued/processing. audio_duration_ms is only set once processing has begun. On "error" read error_type (machine-readable, e.g. invalid_audio_file, file_download_failed, transcription_output_too_long) rather than error_message. Failed jobs are never retried automatically. - **GET** `get_transcription_transcript` — Get the full transcript of a COMPLETED transcription. Returns {id, text, tokens} where text is the whole transcript as one string and tokens is the per-token detail: {text, start_ms, end_ms, confidence, speaker, language, is_audio_event, translation_status}. The last four keys are ALWAYS PRESENT but are null unless the corresponding feature was enabled on create_transcription — so test for null, not for absence. translation_status is null with translation off and "original" or "translation" with it on. is_audio_event is null in practice: audio-event detection is not settable through this API (see the domain notes). Timestamps are MILLISECONDS from the start of the audio. Token text keeps its own leading whitespace, so joining tokens in order rebuilds text exactly. WARNING: this response is unbounded — an hour of diarized audio is many thousands of tokens. Use the get_transcript_text composite when you only need the words, or get_transcript_segments for speaker-attributed passages; call this raw tool only when you truly need per-token timings or confidences. Only valid while status is "completed" — otherwise 409 transcription_invalid_state, or 404 transcription_not_found. - **DELETE** `delete_transcription` — Permanently delete a transcription and its transcript. Irreversible — fetch the transcript first, Soniox keeps no copy. Returns 204 with no body. A job that is currently processing cannot be deleted (409 transcription_invalid_state); wait for completed or error. Deleting is the only way back under the 2000-transcription cap, and it does NOT delete the source file — call delete_file for that. - **GET** `list_voices` — List the project's cloned voices. Returns {voices: [{id, name, filename, created_at, models: [{model, status, error_type, error_message}]}], next_page_cursor}. The models array is the important part: a voice is only usable with a model whose status is "ready" (other values: not_computed, processing, failed). Built-in voices such as "Adrian" are NOT listed here — they come from list_tts_models. - **POST** `create_voice` — Clone a voice from one reference audio clip. The caller passes a URL; ToolMesh fetches the bytes and posts them as the multipart 'file' field, alongside the voice name. Returns the voice with a per-model readiness array; preparation is asynchronous, so poll get_voice until the model you want shows status "ready" before using the voice id in generate_speech. name must be 1..128 chars and unique in the project (409 voice_name_conflict otherwise). An over-long or unusable clip surfaces as status "failed" with error_type voice_audio_too_long or voice_invalid_audio on that model entry, not as an HTTP error. Only clone voices you have permission to clone. - **GET** `get_voices_count` — Number of cloned voices in the project: {total}. Unlike the file and transcription counters this is not split by origin. - **GET** `get_voice` — Get one cloned voice: {id, name, filename, created_at, models}. models holds per-model readiness {model, status, error_type, error_message} with status not_computed | processing | ready | failed. This is the endpoint to poll after create_voice and after recompute_voice. Voice preparation failures (clip too long, unusable audio) appear HERE as a failed model entry — the create call itself will have returned 201. - **DELETE** `delete_voice` — Permanently delete a cloned voice and all its computed embeddings. Irreversible; the reference clip is not recoverable and re-cloning needs the original audio again. Returns 204 with no body, or 404 voice_not_found. Any generate_speech call still referencing the id then fails with voice_not_found. - **POST** `recompute_voice` — Prepare an existing cloned voice for models it is not ready for yet — the fix after Soniox ships a new TTS model and an older voice shows status "not_computed" for it. Pass model to target one model, or omit it to prepare the voice for every model it is missing. Models the voice is already prepared for are left untouched, so this is safe to call repeatedly. Returns the voice; preparation is asynchronous, so poll get_voice until the target model reports "ready". - **POST** `generate_speech` — Synthesize speech from text and return it as a downloadable audio file. The API answers with raw audio bytes, so ToolMesh stores them in its File Broker and returns {url, content_type, size_bytes, expires} with a download URL valid for 24 hours — that URL is unauthenticated while it lives, so treat generated speech as sensitive. The returned content_type is only best-effort (mp3 comes back as audio/mpeg, wav as application/octet-stream); rely on the audio_format you requested, not on that field. Required: model (e.g. tts-rt-v2; see list_tts_models), language (the 2-letter code of the INPUT text), voice (a built-in name such as "Adrian", or the UUID of a cloned voice from list_voices), audio_format, and text. audio_format is one of wav, mp3, aac, opus, flac, pcm_s16le, pcm_s16be, pcm_f32le, pcm_mulaw, pcm_alaw. sample_rate (Hz) is one of 8000, 16000, 24000, 44100, 48000; bitrate (bits/s) one of 32000, 64000, 96000, 128000, 192000, 256000, 320000 — both optional and only meaningful for the formats that carry them. speed runs 0.7..1.3 (1.0 = normal) and only on models with supports_speed_adjustment. reduce_silence shortens inter-word pauses and only works on models with supports_silence_reduction — enabling it elsewhere is a 400 invalid_request. A cloned voice must be "ready" for this model or the call fails with 409 voice_not_prepared / 503 voice_not_ready — check get_voice first. The two "bad voice" errors mean different things (verified live): an unknown built-in NAME is 400 invalid_request "Invalid voice 'X' for model 'Y'" — usually a typo, or a v2-only voice used on v1, so re-check list_tts_models. An unknown or deleted UUID is 404 voice_not_found — the cloned voice is gone and has to be recreated. This endpoint is synchronous: long text means a long request. - **GET** `list_models` — List the speech-to-text models this account can use. Returns {models: [{id, name, aliased_model_id, transcription_mode, context_version, language_codes, translation_targets, two_way_translation_pairs, one_way_translation, two_way_translation, supports_language_hints_strict, supports_max_endpoint_delay, supports_endpoint_sensitivity, supports_endpoint_latency_adjustment, endpoint_latency_adjustment_max_level}]}. transcription_mode is "async" (recorded audio, for create_transcription) or "real_time" (WebSocket only). aliased_model_id is non-null for aliases such as stt-async-v4, which points at stt-async-v5. language_codes is projected down to the 2-letter codes; one_way_translation containing "all_languages" means any listed language may be a translation target. Call this instead of hardcoding model ids — the catalog changes. - **GET** `list_tts_models` — List the text-to-speech models and their BUILT-IN voices. Returns {models: [{id, name, aliased_model_id, language_codes, voices: [{id, description, gender}], supports_timestamps, supports_speed_adjustment, speed_min, speed_max, supports_silence_reduction}]}. The voices array is where built-in voice names such as "Adrian" come from — cloned voices live in list_voices instead. Check supports_speed_adjustment / supports_silence_reduction here before passing speed or reduce_silence to generate_speech, or the call is rejected. language_codes is projected down to the 2-letter codes. - **POST** `create_temporary_api_key` — Mint a short-lived API key so a browser or mobile client can open a Soniox WebSocket stream directly, without ever seeing the long-lived key. Returns {api_key, expires_at} — the key is returned in FULL, so hand it straight to the intended client and never log it. usage_type locks the key to one service and is required: "transcribe_websocket" (real-time speech-to-text) or "tts_rt" (text-to-speech, WebSocket and REST). expires_in_seconds is required and capped at 3600 — it bounds how long NEW streams may be opened, not how long an already-open stream lives. Set single_use to true when the client needs exactly one session, and max_session_duration_seconds (1..18000) to cap how long a single stream may stay open. Always call this from your backend with the real key; a temporary key is the only credential that belongs in untrusted code. - **GET** `list_usage_logs` — Per-request usage and cost entries for the project, filtered by request END time. Returns {usage_logs: [{uuid, request_scope, client_reference_id, model, start_time, end_time, input_text_tokens, input_audio_tokens, input_audio_duration_ms, output_text_tokens, output_audio_tokens, output_audio_duration_ms, cost_usd, input_cost_usd, input_text_cost_usd, input_audio_cost_usd, output_cost_usd, output_text_cost_usd, output_audio_cost_usd}], next_page_cursor}. All cost fields are DECIMAL STRINGS ("0.0081000000"), not numbers. start_time and end_time are required ISO 8601 UTC timestamps; the window must be at most 31 days and start_time may not be more than 91 days ago. sort is end_time_asc (default) or end_time_desc — pass the same sort value alongside cursor when paging. client_reference_id is how you attribute cost back to your own jobs or tenants. This can be a very large result set; narrow the window rather than paging blindly, and prefer get_usage_summary for totals. - **GET** `get_usage_summary` — Daily cost and activity for the project, aggregated per whole UTC day and broken down per model. Returns {total, models: [...]} where each entry is {model (null for the total), days: ["2026-08-01", ...], total_cost_usd, total_input_cost_usd, total_output_cost_usd, total_duration_cost_usd, cost_usd[], input_cost_usd[], output_cost_usd[], duration_cost_usd[], total_num_requests, total_input_text_tokens, total_input_audio_tokens, total_input_audio_duration_ms, total_output_text_tokens, total_output_audio_tokens, total_output_audio_duration_ms, total_duration_ms, num_requests[], and the matching per-day arrays}. The per-day arrays are POSITIONALLY aligned with days — index i of cost_usd is the cost on days[i]. Cost values are decimal strings, not numbers. The window is half-open [start_time, end_time): a day is included when the window covers any part of it, so an end_time exactly at midnight excludes that day. At most 366 UTC days per call. Cheaper than list_usage_logs for "what did this cost" questions. - **GET** `get_concurrency_limits` — Current concurrent stream counts and the configured caps, for both the project and its organization. Returns {project: {current: {...}, limits: {...}}, organization: {current: {...}, limits: {...}}}, where each inner object carries transcribe_concurrent, tts_concurrent and voice_agent_concurrent. A limits value of null means "no project-level cap set — the organization limit applies", so always compare against the organization numbers too. Region-scoped: it reports the region of the host being called. Check this when streams start failing with max_concurrent_streams_reached, since the organization cap can bind even when the project looks idle. - **GET** `list_concurrent_streams_history` — Historical concurrent stream counts per aggregation period. Returns {kind, entries: [{period_start, period_sec, sample_min, sample_max, sample_sum, sample_count, total_count}]} ordered by period_start ascending, with NO gaps — idle periods are returned with every field 0. sample_max is the peak concurrency and stays exact when minutes roll up into hours or days; sample_min is always 0 by construction, so use sample_max for headroom questions. sample_sum / sample_count is the average while streams were active, sample_sum / total_count the average across the whole period. All four parameters are required: start_time and end_time as ISO 8601 UTC (half-open, filtered on period_start), period_sec as 60, 3600 or 86400 (the period also caps how long the window may be), and kind as "stt" (speech-to-text WebSocket sessions) or "tts" (text-to-speech WebSocket streams and REST requests). Region-scoped. ## What composite workflows does the Soniox DADL provide? - **FN** `get_transcript_text` — Get just the words of a completed transcription — {id, text, character_count, token_count} — without pulling the full token array into context. This is the cheap default for "what was said"; use get_transcript_segments when you need speakers, and the raw get_transcription_transcript only for per-token timings or confidences. - **FN** `get_transcript_segments` — Fetch a completed transcript and merge its sub-word tokens into readable segments, collapsing thousands of tokens into a handful of passages. Returns {id, group_by, segment_count, segments: [{group, translation_status, start_ms, end_ms, text, token_count}]}. group_by selects what starts a new segment: "speaker" (default — requires enable_speaker_diarization), "language" (requires enable_language_identification) or "translation_status". A gap longer than max_gap_ms also splits a segment, and a change of translation_status ALWAYS does — original and translated tokens share the same timestamps, so they must never be merged into one passage. Set the translation_status parameter to "original" or "translation" to drop one side of a translated transcript entirely. Costs exactly one API call. - **FN** `get_transcription_result` — Status-and-transcript in one call: read a transcription's status and, if it is already "completed", return the transcript text with it. Returns {id, status, ready, model, filename, audio_duration_ms, text, token_count} when finished, and {id, status, ready: false, error_type, error_message, text: null} while queued/processing or on error. This is the tool to call in a polling loop — it saves a round trip on the iteration that finally succeeds. Set include_tokens to also return the raw token array (large). It does NOT wait or sleep: call it again from the agent side, and space the calls out rather than busy-looping. - **FN** `cleanup_transcriptions` — Delete finished transcriptions to get back under the 2000-transcription project cap. DRY RUN BY DEFAULT — it reports what it would delete and changes nothing until dry_run is explicitly false. Considers only finished jobs ("completed" and "error"); queued and processing jobs are never touched and cannot be deleted anyway. status narrows that to one value, keep_newest protects the N most recent matches, and at most 40 deletions happen per call (the composite sandbox caps API calls) — run it again for more. Returns {dry_run, matched, would_delete, ids} in dry run, and {dry_run, matched, deleted_count, deleted, failed} when armed. Deletion is irreversible and does NOT remove the underlying files. ## Which DADLs are related to Soniox? - [Billomat](https://www.dadl.ai/d/billomat/) — Billomat REST API — German cloud invoicing & accounting: invoices, estimates, credit notes, recurring invoices, delivery notes, order confirmations, dunning reminders, clients, contacts, articles, payments, expenses, taxes - [Xen Orchestra](https://www.dadl.ai/d/xen-orchestra/) — Xen Orchestra REST API (XO 6.4+, current through 6.9) -- complete coverage: VMs (incl. PATCH update + snapshot revert), VM controllers, hosts (incl. full power/lifecycle actions + maintenance mode + PIF rescan), pools (incl. add_host, rolling reboot/update with interrupted-update recovery + finalize), storage (SR create/delete, VDI incl. PATCH update + vhd/raw/qcow2 export, VBD), networks (VIF incl. PATCH update + PIF/PBD), VM/VDI snapshots, VM templates, hardware (PCI/PGPU/SM), tasks, backups (archives incl. live mount of backup disks, jobs/logs, repositories incl. health + benchmark + space reclaim), schedules, messages, alarms, events (SSE incl. non-XAPI collections), RBAC v2 (users/groups/acl-roles/acl-privileges incl. assignment introspection), proxies, servers, dashboards, SDN traffic rules (add/delete/update), IPMI sensor inventory (plugin), audit records (plugin), health check - [Graylog](https://www.dadl.ai/d/graylog/) — Graylog REST API -- log search (Views/Search + legacy universal), streams, pipelines, inputs, alerts, events, dashboards, users, roles, sidecars, index management, and cluster administration. Targets Graylog 6.x. - [Mastodon](https://www.dadl.ai/d/mastodon/) — Mastodon REST API — statuses, timelines, accounts, notifications, search, media, lists, polls, conversations, trends, filters, and instance info. Base URL must be set to the target Mastodon instance (e.g. https://mastodon.social). - [Mempool](https://www.dadl.ai/d/mempool/) — mempool.space — Bitcoin block explorer, mempool visualizer, fee estimator, Lightning Network explorer, and transaction accelerator - [NetBox](https://www.dadl.ai/d/netbox/) — NetBox DCIM/IPAM API -- full v4 coverage: sites, racks, devices, modules, interfaces, cables, power, IPAM (prefixes, IPs, VLANs, VRFs, route-targets, VLAN translation), virtualization, circuits (including virtual circuits), tenants, contacts, VPN (IKE/IPSec/L2VPN), wireless, extras (webhooks, event-rules, scripts, config-templates, bookmarks, notifications), users/permissions/tokens, and core data sources & jobs --- **Canonical URL:** https://www.dadl.ai/d/soniox/ **Raw DADL:** https://github.com/DunkelCloud/dadl-registry/blob/main/soniox.dadl --- # Stripe MCP Server — 96 tools via DADL The Stripe DADL turns Stripe's API into an MCP server that Claude, GPT or any MCP-compatible agent can consume directly. One YAML file declares all 96 tools — payment, invoice, subscription, charge, customer, payout, and more — and ToolMesh serves them at runtime. No Python boilerplate, no per-endpoint code, no separate MCP server process. Below: the endpoint coverage matrix, a two-block ToolMesh setup, the full tool reference grouped by Stripe feature area. **Source:** [Stripe REST API](https://docs.stripe.com/api) **Updated:** 2026-04-02 **Tags:** finance, e-commerce, crud, user-management, notifications, webhooks, logging, authentication, auth:bearer ## Which Stripe endpoints are covered? **22%** (78 of ~350 endpoints). **Focus:** customers, payment intents, payment methods, charges, subscriptions, invoices, products, prices, refunds, checkout sessions, setup intents, disputes, coupons, payouts, balance, events, webhook endpoints **Missing:** Connect (accounts, transfers, application fees), Terminal, Identity, Issuing, Treasury, Tax, Sigma, Reporting, Radar, Climate, Financial Connections, forwarding *Last reviewed: 2026-04-02* ## How do you configure the Stripe DADL? 1. Log in to the Stripe Dashboard at https://dashboard.stripe.com 2. Navigate to Developers → API keys 3. Copy the Secret key (starts with sk_test_ for test mode or sk_live_ for live mode) 4. NEVER use the Publishable key (pk_) — it cannot access server-side endpoints **Environment variable:** `CREDENTIAL_STRIPE_SECRET_KEY` [Authentication docs](https://docs.stripe.com/api) *Stripe does not use OAuth scopes — the secret key grants full API access. Use restricted keys (Dashboard → API keys → Create restricted key) to limit access to specific resources and operations. Test mode keys (sk_test_) operate on test data only and never affect real charges. Rate limits: 100 read/s and 100 write/s in live mode, 25 read/s and 25 write/s in test mode. * ## How do you install the Stripe MCP server with ToolMesh? Add to your `backends.yaml`: ```yaml - name: stripe transport: rest dadl: stripe.dadl url: "https://api.stripe.com/v1" ``` Set the credential: ``` CREDENTIAL_STRIPE_SECRET_KEY=your-token-here ``` ## What 96 tools does the Stripe DADL expose? - **GET** `list_customers` — List all customers, optionally filtered by email or creation date - **GET** `get_customer` — Retrieve a single customer by ID - **POST** `create_customer` — Create a new customer - **POST** `update_customer` — Update an existing customer - **DELETE** `delete_customer` — Permanently delete a customer and cancel active subscriptions - **GET** `search_customers` — Search customers using Stripe Query Language - **GET** `list_payment_intents` — List all payment intents, optionally filtered by customer or status - **GET** `get_payment_intent` — Retrieve a payment intent by ID - **POST** `create_payment_intent` — Create a new payment intent to collect a payment - **POST** `update_payment_intent` — Update a payment intent (only before confirmation) - **POST** `confirm_payment_intent` — Confirm a payment intent to proceed with the payment - **POST** `capture_payment_intent` — Capture a previously authorized payment intent - **POST** `cancel_payment_intent` — Cancel a payment intent - **GET** `search_payment_intents` — Search payment intents using Stripe Query Language - **GET** `list_payment_methods` — List payment methods for a customer - **GET** `get_payment_method` — Retrieve a payment method by ID - **POST** `create_payment_method` — Create a payment method - **POST** `update_payment_method` — Update payment method details - **POST** `attach_payment_method` — Attach a payment method to a customer - **POST** `detach_payment_method` — Detach a payment method from its customer - **GET** `list_charges` — List all charges, optionally filtered by customer or payment intent - **GET** `get_charge` — Retrieve a charge by ID - **POST** `create_charge` — Create a charge (legacy — prefer create_payment_intent) - **POST** `update_charge` — Update a charge (description, metadata, fraud details) - **POST** `capture_charge` — Capture a previously authorized charge - **GET** `search_charges` — Search charges using Stripe Query Language - **GET** `list_subscriptions` — List all subscriptions, optionally filtered by customer or status - **GET** `get_subscription` — Retrieve a subscription by ID - **POST** `create_subscription` — Create a subscription for a customer - **POST** `update_subscription` — Update a subscription (change plan, quantity, trial, etc.) - **DELETE** `cancel_subscription` — Cancel a subscription immediately or at period end - **POST** `resume_subscription` — Resume a paused subscription - **GET** `search_subscriptions` — Search subscriptions using Stripe Query Language - **GET** `list_invoices` — List all invoices, optionally filtered by customer or status - **GET** `get_invoice` — Retrieve an invoice by ID - **POST** `create_invoice` — Create a draft invoice for a customer - **POST** `update_invoice` — Update a draft or open invoice - **DELETE** `delete_invoice` — Delete a draft invoice (only draft invoices can be deleted) - **POST** `finalize_invoice` — Finalize a draft invoice (transitions to open status) - **POST** `pay_invoice` — Pay an open invoice using the customer's default payment method - **POST** `send_invoice` — Send a finalized invoice to the customer by email - **POST** `void_invoice` — Void a finalized invoice (marks as uncollectable, no refund) - **POST** `mark_invoice_uncollectible` — Mark an invoice as uncollectible - **GET** `search_invoices` — Search invoices using Stripe Query Language - **GET** `list_products` — List all products - **GET** `get_product` — Retrieve a product by ID - **POST** `create_product` — Create a new product - **POST** `update_product` — Update a product - **DELETE** `delete_product` — Delete a product (must have no prices attached) - **GET** `search_products` — Search products using Stripe Query Language - **GET** `list_prices` — List all prices, optionally filtered by product or active status - **GET** `get_price` — Retrieve a price by ID - **POST** `create_price` — Create a new price for a product - **POST** `update_price` — Update a price (most fields are immutable — create a new price instead) - **GET** `search_prices` — Search prices using Stripe Query Language - **GET** `list_refunds` — List all refunds, optionally filtered by charge or payment intent - **GET** `get_refund` — Retrieve a refund by ID - **POST** `create_refund` — Create a refund for a charge or payment intent - **POST** `update_refund` — Update a refund (metadata only) - **POST** `cancel_refund` — Cancel a refund that has not yet been processed - **GET** `list_checkout_sessions` — List all checkout sessions - **GET** `get_checkout_session` — Retrieve a checkout session by ID - **POST** `create_checkout_session` — Create a Stripe Checkout session for hosted payment page - **POST** `expire_checkout_session` — Expire a checkout session (cannot be completed after expiry) - **GET** `list_checkout_session_line_items` — List line items for a checkout session - **GET** `list_setup_intents` — List all setup intents - **GET** `get_setup_intent` — Retrieve a setup intent by ID - **POST** `create_setup_intent` — Create a setup intent to save payment credentials for future use - **POST** `update_setup_intent` — Update a setup intent - **POST** `confirm_setup_intent` — Confirm a setup intent to complete payment method setup - **POST** `cancel_setup_intent` — Cancel a setup intent - **GET** `list_disputes` — List all disputes - **GET** `get_dispute` — Retrieve a dispute by ID - **POST** `update_dispute` — Update a dispute with evidence - **POST** `close_dispute` — Close a dispute — accepts the dispute and refunds the customer - **GET** `list_coupons` — List all coupons - **GET** `get_coupon` — Retrieve a coupon by ID - **POST** `create_coupon` — Create a coupon for discounts on subscriptions or invoices - **POST** `update_coupon` — Update a coupon (name and metadata only) - **DELETE** `delete_coupon` — Delete a coupon (existing discounts remain active) - **GET** `list_payouts` — List all payouts - **GET** `get_payout` — Retrieve a payout by ID - **POST** `create_payout` — Create a payout to your bank account or debit card - **POST** `update_payout` — Update a payout (metadata only) - **POST** `cancel_payout` — Cancel a pending payout - **POST** `reverse_payout` — Reverse a completed payout (returns funds to Stripe balance) - **GET** `get_balance` — Retrieve the current account balance (available and pending) - **GET** `list_balance_transactions` — List balance transactions (all account activity) - **GET** `get_balance_transaction` — Retrieve a balance transaction by ID - **GET** `list_events` — List all events (retained for 30 days) - **GET** `get_event` — Retrieve a specific event by ID - **GET** `list_webhook_endpoints` — List all webhook endpoint configurations - **GET** `get_webhook_endpoint` — Retrieve a webhook endpoint by ID - **POST** `create_webhook_endpoint` — Create a webhook endpoint to receive events - **POST** `update_webhook_endpoint` — Update a webhook endpoint - **DELETE** `delete_webhook_endpoint` — Delete a webhook endpoint ## Which DADLs are related to Stripe? - [Billomat](https://www.dadl.ai/d/billomat/) — Billomat REST API — German cloud invoicing & accounting: invoices, estimates, credit notes, recurring invoices, delivery notes, order confirmations, dunning reminders, clients, contacts, articles, payments, expenses, taxes - [Mempool](https://www.dadl.ai/d/mempool/) — mempool.space — Bitcoin block explorer, mempool visualizer, fee estimator, Lightning Network explorer, and transaction accelerator - [Alertmanager](https://www.dadl.ai/d/alertmanager/) — Prometheus Alertmanager API v2 -- alerts, silences, receivers, alert groups, status, and operational health - [BookStack](https://www.dadl.ai/d/bookstack/) — BookStack wiki and documentation platform REST API -- shelves, books, chapters, pages (HTML/Markdown content), attachments, image gallery, comments, cross-entity search, exports (HTML/Markdown/PDF/ZIP), ZIP imports, users, roles, content permissions, recycle bin, audit log and tags. Hierarchy: shelves > books > chapters > pages. - [Checkmk](https://www.dadl.ai/d/checkmk/) — Checkmk REST API (version 1.0, Checkmk 2.4) -- live host and service status via Livestatus queries, downtimes, acknowledgements and comments, the Event Console (list, acknowledge, change state and archive events) and BI (packs, rules, aggregations and live aggregation state), plus the full Setup side: hosts, clusters, folders, service discovery, rules and rulesets, host/service/contact groups, users, roles, passwords, time periods, host tags, notification rules, site connections and change activation. - [Hacker News](https://www.dadl.ai/d/hackernews/) — Hacker News API — read-only access to stories, comments, polls, jobs, users, and live feeds from news.ycombinator.com --- **Canonical URL:** https://www.dadl.ai/d/stripe/ **Raw DADL:** https://github.com/DunkelCloud/dadl-registry/blob/main/stripe.dadl --- # Tailscale MCP Server — 60 tools via DADL The Tailscale DADL turns Tailscale's API into an MCP server that Claude, GPT or any MCP-compatible agent can consume directly. One YAML file declares all 60 tools — device, user, webhook, acl, posture, log, and more — and ToolMesh serves them at runtime. No Python boilerplate, no per-endpoint code, no separate MCP server process. Below: the endpoint coverage matrix, a two-block ToolMesh setup, the full tool reference grouped by Tailscale feature area, required credential scopes. **Source:** [Tailscale REST API](https://tailscale.com/api) **Updated:** 2026-04-06 **Tags:** cloud, devops, networking, security, crud, webhooks, user-management, authentication, auth:bearer ## Which Tailscale endpoints are covered? **83%** (58 of ~70 endpoints). **Focus:** devices, device routes, device posture, users, auth keys, DNS (nameservers, search paths, preferences, split DNS), ACL/policy, webhooks, contacts, tailnet settings, posture integrations, log streaming **Missing:** OAuth token endpoint, device invites, user invites, services (beta) *Last reviewed: 2026-04-06* ## How do you configure the Tailscale DADL? 1. Log in to the Tailscale admin console at https://login.tailscale.com/admin 2. Navigate to Settings -> Keys 3. Click 'Generate API key' 4. Set expiry (1-90 days) and copy the key immediately -- it is shown only once 5. Key prefix is tskey-api-. Requires Owner, Admin, IT admin, or Network admin role. 6. Alternative: create an OAuth client under Settings -> OAuth for long-lived automated access **Environment variable:** `CREDENTIAL_TAILSCALE_API_TOKEN` [Authentication docs](https://tailscale.com/kb/1101/api) *API keys expire after 1-90 days and cannot be renewed -- create a new one before expiry. For automation, prefer OAuth clients which support token refresh. Use '-' as the tailnet parameter to target your own tailnet.* ## How do you install the Tailscale MCP server with ToolMesh? Add to your `backends.yaml`: ```yaml - name: tailscale transport: rest dadl: tailscale.dadl ``` Set the credential: ``` CREDENTIAL_TAILSCALE_API_TOKEN=your-token-here ``` ## What 60 tools does the Tailscale DADL expose? - **GET** `list_devices` — List all devices in the tailnet - **GET** `get_device` — Get details of a specific device - **DELETE** `delete_device` — Remove a device from the tailnet - **POST** `authorize_device` — Authorize or deauthorize a device - **POST** `expire_device_key` — Expire a device's node key, forcing it to re-authenticate - **POST** `set_device_key` — Set device key properties (e.g. disable key expiry) - **POST** `set_device_name` — Set custom display name for a device - **POST** `set_device_tags` — Set ACL tags on a device (replaces existing tags) - **POST** `set_device_ip` — Set the Tailscale IPv4 address of a device - **GET** `get_device_routes` — Get advertised and enabled subnet routes for a device - **POST** `set_device_routes` — Set which subnet routes are enabled for a device - **GET** `get_device_posture_attributes` — Get custom posture attributes for a device - **POST** `set_device_posture_attribute` — Set a custom posture attribute on a device - **DELETE** `delete_device_posture_attribute` — Delete a custom posture attribute from a device - **GET** `list_users` — List users in the tailnet - **GET** `get_user` — Get details of a specific user - **POST** `approve_user` — Approve a pending user - **POST** `suspend_user` — Suspend a user (disables their access to the tailnet) - **POST** `restore_user` — Restore a previously suspended user - **POST** `delete_user` — Delete a user from the tailnet - **POST** `set_user_role` — Update a user's role in the tailnet - **GET** `list_keys` — List all auth keys and API access tokens in the tailnet - **GET** `get_key` — Get details of a specific key - **POST** `create_auth_key` — Create a new auth key for device registration - **DELETE** `delete_key` — Revoke and delete a key - **GET** `get_dns_nameservers` — Get the global DNS nameservers for the tailnet - **POST** `set_dns_nameservers` — Set the global DNS nameservers (replaces existing list) - **GET** `get_dns_searchpaths` — Get DNS search paths for the tailnet - **POST** `set_dns_searchpaths` — Set DNS search paths (replaces existing list) - **GET** `get_dns_preferences` — Get DNS preferences (MagicDNS status) - **POST** `set_dns_preferences` — Set DNS preferences (enable/disable MagicDNS) - **GET** `get_dns_split` — Get split DNS configuration - **PUT** `set_dns_split` — Replace the entire split DNS configuration - **PATCH** `patch_dns_split` — Merge updates into the split DNS configuration (existing entries preserved) - **GET** `get_acl` — Get the current ACL/policy file. Returns ETag header for concurrency control. - **POST** `set_acl` — Replace the ACL/policy file. Use If-Match header with ETag for optimistic concurrency. - **POST** `preview_acl` — Preview how ACL rules apply to a specific user or IP:port - **POST** `validate_acl` — Validate an ACL policy without applying it - **POST** `test_acl` — Run the test cases defined in the ACL policy - **GET** `list_webhooks` — List all webhook endpoints in the tailnet - **POST** `create_webhook` — Create a new webhook endpoint - **GET** `get_webhook` — Get details of a webhook endpoint - **PATCH** `update_webhook` — Update a webhook endpoint's subscriptions - **DELETE** `delete_webhook` — Delete a webhook endpoint - **POST** `test_webhook` — Send a test event to a webhook endpoint - **POST** `rotate_webhook_secret` — Rotate the signing secret for a webhook endpoint - **GET** `get_contacts` — Get tailnet contact emails (account, support, security) - **PATCH** `update_contact` — Update a contact email address - **POST** `resend_contact_verification` — Resend verification email for a contact - **GET** `get_tailnet_settings` — Get tailnet-wide settings (auto-updates, approval, key duration, etc.) - **PATCH** `update_tailnet_settings` — Update tailnet settings (partial update) - **GET** `list_posture_integrations` — List device posture integrations (CrowdStrike, Intune, Jamf, etc.) - **POST** `create_posture_integration` — Create a new posture integration - **GET** `get_posture_integration` — Get details of a posture integration - **PATCH** `update_posture_integration` — Update a posture integration - **DELETE** `delete_posture_integration` — Delete a posture integration - **GET** `get_log_stream_config` — Get log stream configuration for a log type - **PUT** `set_log_stream_config` — Set log stream destination (Splunk, Elastic, Datadog, S3, etc.) - **DELETE** `delete_log_stream_config` — Delete log stream configuration - **GET** `get_log_stream_status` — Get current status of log streaming ## Which DADLs are related to Tailscale? - [NetBox](https://www.dadl.ai/d/netbox/) — NetBox DCIM/IPAM API -- full v4 coverage: sites, racks, devices, modules, interfaces, cables, power, IPAM (prefixes, IPs, VLANs, VRFs, route-targets, VLAN translation), virtualization, circuits (including virtual circuits), tenants, contacts, VPN (IKE/IPSec/L2VPN), wireless, extras (webhooks, event-rules, scripts, config-templates, bookmarks, notifications), users/permissions/tokens, and core data sources & jobs - [Cloudflare](https://www.dadl.ai/d/cloudflare/) — Cloudflare API -- DNS, Pages, Workers, KV, R2, D1, Zones, SSL/TLS, Cache, Load Balancers, Firewall/WAF, Page Rules, Access (Zero Trust), Email Routing, Email Sending, DMARC/SPF email auth, and account management - [Hetzner Cloud](https://www.dadl.ai/d/hetzner-cloud/) — Hetzner Cloud API -- servers, volumes, networks, load balancers, firewalls, floating IPs, primary IPs, images, SSH keys, placement groups, certificates, and infrastructure metadata - [Linode](https://www.dadl.ai/d/linode/) — Linode (Akamai) cloud infrastructure API -- compute instances, volumes, DNS, networking, Kubernetes, databases, object storage, and account management - [Mempool](https://www.dadl.ai/d/mempool/) — mempool.space — Bitcoin block explorer, mempool visualizer, fee estimator, Lightning Network explorer, and transaction accelerator - [Mikrotik](https://www.dadl.ai/d/mikrotik/) — MikroTik RouterOS REST API -- manage interfaces, IP addresses, routing, firewall, DHCP, DNS, PPP, queues, wireless, system configuration, users, certificates, files, logs, and diagnostics on RouterOS v7.1+ devices --- **Canonical URL:** https://www.dadl.ai/d/tailscale/ **Raw DADL:** https://github.com/DunkelCloud/dadl-registry/blob/main/tailscale.dadl --- # Umami MCP Server — 89 tools via DADL The Umami DADL turns Umami's API into an MCP server that Claude, GPT or any MCP-compatible agent can consume directly. One YAML file declares all 89 tools — website, team, event, session, user, link, and more — and ToolMesh serves them at runtime. No Python boilerplate, no per-endpoint code, no separate MCP server process. Below: the endpoint coverage matrix, a two-block ToolMesh setup, the full tool reference grouped by Umami feature area, required credential scopes. **Source:** [Umami Analytics REST API](https://umami.is/docs/api) **Updated:** 2026-10-10 **Tags:** analytics, authentication, crud, metrics, real-time, user-management, auth:bearer ## Which Umami endpoints are covered? **100%** (89 of ~89 endpoints). **Focus:** authentication, me, websites, statistics, metrics, pageviews, events, event-data, sessions, session-data, realtime, users, teams, reports, share, links, pixels, admin **Missing:** none *Last reviewed: 2026-10-10* ## How do you configure the Umami DADL? 1. Log into your Umami instance as admin 2. Navigate to Settings → Users or use the API login endpoint 3. POST /api/auth/login with {username, password} to get a JWT token 4. The token is returned in the response body as 'token' **Environment variable:** `CREDENTIAL_UMAMI_API_TOKEN` [Authentication docs](https://docs.umami.is/docs/api) *Umami is self-hosted. Replace the URL with your instance address. Token is a JWT obtained via /auth/login.* ## How do you install the Umami MCP server with ToolMesh? Add to your `backends.yaml`: ```yaml - name: umami transport: rest dadl: umami.dadl url: "https://your-umami-instance.com/api" ``` Set the credential: ``` CREDENTIAL_UMAMI_API_TOKEN=your-token-here ``` ## What 89 tools does the Umami DADL expose? - **POST** `login` — Authenticate with Umami. Returns a JWT token for subsequent API calls. Send username and password in the request body. - **POST** `verify_token` — Verify if the current JWT token is still valid. Returns user info if valid. - **GET** `get_me` — Get the current authenticated user's profile info based on the JWT token. - **GET** `get_my_teams` — Get all teams the current authenticated user belongs to. - **GET** `get_my_websites` — Websites of the current user -- same semantics as list_websites: only directly owned websites unless includeTeams is true, which adds the websites of the user's teams. Returns {data, count, page, pageSize}. For every website on the instance use admin_list_websites (admin role). - **POST** `send_event` — Register a pageview or custom event. No authentication required. Requires a User-Agent header. Used by the tracking script. - **GET** `list_websites` — List websites OWNED BY THE CALLING USER (userId = token user). Websites that belong to a team are NOT included unless includeTeams is true (then: all websites of teams the user is a member of). An empty result therefore usually means the websites are team-owned -- retry with includeTeams: true, or use admin_list_websites (admin role, every website on the instance) / list_team_websites(teamId). Returns {data: [...], count, page, pageSize}; each item has id (websiteId), name, domain, teamId, createdAt. - **GET** `get_website` — Get details of a specific website by its ID. - **POST** `create_website` — Create a new website to track. Provide name and domain. - **POST** `update_website` — Update website properties. Only include fields you want to change. - **POST** `transfer_website` — Transfer a website to a different user or team. IMPORTANT: Only the current owner of the website can transfer it — there is no admin bypass. Use teamId to assign to a team (requester must own the website and be a team member with transfer permission). Use userId to claim a team-owned website back to yourself (requester must be in the team with transfer permission). To remove from a team, pass teamId: null. - **DELETE** `delete_website` — Delete a website and all its analytics data. Irreversible. - **POST** `reset_website` — Reset a website by removing all its analytics data. The website itself is preserved but all stats are deleted. Irreversible. - **GET** `get_website_active` — Get the number of active visitors on a website right now (last 5 minutes). - **GET** `get_website_daterange` — Get the date range of available analytics data for a website. - **GET** `get_website_stats` — Get summarized website statistics: pageviews, visitors, visits, bounces, and total time. Timestamps are Unix milliseconds. - **GET** `get_website_pageviews` — Get pageview time series within a given time range. Returns pageviews and sessions arrays with timestamps. Unit auto-scales if range exceeds maximum for chosen unit. - **GET** `get_website_metrics` — Get metrics for a website grouped by type (Umami v3 vocabulary): path, fullPath (path incl. query string), entry, exit, referrer, domain (referrer domain), title, query, event, tag, hostname, utmSource, utmMedium, utmCampaign, utmContent, utmTerm, browser, os, device, screen, language, country, city, region, distinctId, channel. Any other value -- notably the Umami v2 name "url" -- is rejected with HTTP 400; use "path" for page URLs. Returns [{x: value, y: count}] sorted by y desc, limit/offset apply (channel ignores them). startAt/endAt are Unix MILLISECONDS. - **GET** `get_website_metrics_expanded` — Expanded metrics per entry: returns [{name, pageviews, visitors, visits, bounces, totaltime}] (NOT the {x, y} shape of get_website_metrics; region/city rows also carry country). type accepts the same Umami v3 vocabulary as get_website_metrics: path, fullPath (path incl. query string), entry, exit, referrer, domain (referrer domain), title, query, event, tag, hostname, utmSource, utmMedium, utmCampaign, utmContent, utmTerm, browser, os, device, screen, language, country, city, region, distinctId, channel. Anything else (e.g. the v2 name "url") returns HTTP 400 -- use "path". bounces and totaltime are always 0 for page/event types (path, referrer, title, ...) and only populated for session types (country, browser, ...) and channel; numeric fields may arrive as strings. startAt/endAt are Unix MILLISECONDS. - **GET** `get_website_events` — Get custom event details for a website within a time range. - **GET** `get_website_events_series` — Get custom events within a time range as time series. Returns [{x: event_name, t: timestamp, y: count}]. - **GET** `get_website_events_stats` — Get aggregated event statistics for a website within a time range. - **GET** `get_event_data` — Get event data grouped by name for a website. - **GET** `get_event_data_by_id` — Get event data for a specific individual event. - **GET** `get_event_data_events` — Get event names and their property counts. - **GET** `get_event_data_fields` — Get event property names and their value counts. - **GET** `get_event_data_properties` — Get event names and their associated property counts. - **GET** `get_event_data_values` — Get event data counts for a specific event and property combination. - **GET** `get_event_data_stats` — Get aggregated event data statistics: total events, properties, and records count. - **GET** `list_sessions` — List sessions for a website within a time range. - **GET** `get_sessions_stats` — Get aggregated session statistics for a website. - **GET** `get_sessions_weekly` — Get sessions grouped by hour-of-weekday (heatmap data). - **GET** `get_session` — Get details of a specific session. - **GET** `get_session_activity` — Get activity log for a specific session (pageviews, events). - **GET** `get_session_properties` — Get custom properties stored for a specific session. - **GET** `get_session_data_properties` — Get session data counts grouped by property name. - **GET** `get_session_data_values` — Get session data counts for a specific property. - **GET** `get_realtime` — Get realtime statistics for a website (last 30 minutes). Returns countries, urls, referrers, events, series, totals, and timestamp. - **POST** `create_user` — Create a new user. Admin only. Roles: admin, user, view-only. - **GET** `get_user` — Get a user by ID. Admin only. - **POST** `update_user` — Update a user. Admin only. Only include fields you want to change. - **DELETE** `delete_user` — Delete a user. Admin only. Irreversible. - **GET** `get_user_websites` — Get all websites accessible by a specific user. - **GET** `get_user_teams` — Get all teams a specific user belongs to. - **GET** `list_teams` — List all teams. - **POST** `create_team` — Create a new team. - **POST** `join_team` — Join a team using an access code. - **GET** `get_team` — Get a team by ID. - **POST** `update_team` — Update team properties. Only include fields you want to change. - **DELETE** `delete_team` — Delete a team. Irreversible. - **GET** `list_team_users` — List all members of a team. - **POST** `add_team_user` — Add a user to a team. Roles: team-member, team-view-only, team-manager. - **GET** `get_team_user` — Get a specific team member. - **POST** `update_team_user` — Update a team member's role. - **DELETE** `remove_team_user` — Remove a user from a team. - **GET** `list_team_websites` — List all websites assigned to a team. - **GET** `list_reports` — List all reports for a website. - **POST** `create_report` — Create a new report. - **GET** `get_report` — Get a report by ID. - **POST** `update_report` — Update a report. - **DELETE** `delete_report` — Delete a report. Irreversible. - **POST** `run_attribution_report` — Run an attribution report. Models: firstClick, lastClick. Types: path, event. - **POST** `run_breakdown_report` — Run a breakdown report to cross-reference multiple dimensions. - **POST** `run_funnel_report` — Run a funnel report. Requires at least 2 steps, each with type (path/event) and value. - **POST** `run_goal_report` — Run a goal report. Type: path or event. - **POST** `run_journey_report` — Run a journey/path report. Steps must be 3-7. - **POST** `run_performance_report` — Run a web vitals performance report. Metrics: lcp, inp, cls, fcp, ttfb. - **POST** `run_retention_report` — Run a retention/cohort report. - **POST** `run_revenue_report` — Run a revenue report. - **POST** `run_utm_report` — Run a UTM campaign report. - **POST** `create_share` — Create a share page. Share types: 1=website, 2=link, 3=pixel, 4=board. - **GET** `get_share` — Get a share page by its ID. - **POST** `update_share` — Update a share page. - **DELETE** `delete_share` — Delete a share page. Irreversible. - **GET** `list_website_shares` — List all share pages for a website. - **POST** `create_website_share` — Create a share page for a specific website. - **GET** `list_links` — List all tracked links. - **POST** `create_link` — Create a tracked link. Slug must be at least 8 characters. - **GET** `get_link` — Get a tracked link by ID. - **POST** `update_link` — Update a tracked link. - **DELETE** `delete_link` — Delete a tracked link. Irreversible. - **GET** `list_pixels` — List all tracking pixels. - **POST** `create_pixel` — Create a tracking pixel. Slug must be at least 8 characters. - **GET** `get_pixel` — Get a tracking pixel by ID. - **POST** `update_pixel` — Update a tracking pixel. - **DELETE** `delete_pixel` — Delete a tracking pixel. Irreversible. - **GET** `admin_list_users` — List all users in the Umami instance. Admin only. - **GET** `admin_list_websites` — List EVERY website on the instance regardless of owner or team (requires the admin role). This is the reliable way to find a websiteId when list_websites / get_my_websites come back empty because the websites are team-owned. Returns {data, count, page, pageSize}; items include id, name, domain, user and team. - **GET** `admin_list_teams` — List all teams in the Umami instance. Admin only. ## Which DADLs are related to Umami? - [Algolia HN Search](https://www.dadl.ai/d/algolia-hn-search/) — Algolia Hacker News Search API — full-text search, filtering, and retrieval for stories, comments, and users on Hacker News - [PeeringDB](https://www.dadl.ai/d/peeringdb/) — PeeringDB v2 API -- the public peering database of networks (ASNs), Internet Exchanges, and colocation facilities: full CRUD over net, ix, fac, org, carrier, campus, point-of-contact records, and the netixlan/netfac/ixfac/carrierfac/ixlan/ixpfx relationships that map who peers where - [Checkmk](https://www.dadl.ai/d/checkmk/) — Checkmk REST API (version 1.0, Checkmk 2.4) -- live host and service status via Livestatus queries, downtimes, acknowledgements and comments, the Event Console (list, acknowledge, change state and archive events) and BI (packs, rules, aggregations and live aggregation state), plus the full Setup side: hosts, clusters, folders, service discovery, rules and rulesets, host/service/contact groups, users, roles, passwords, time periods, host tags, notification rules, site connections and change activation. - [DokuWiki](https://www.dadl.ai/d/dokuwiki/) — DokuWiki JSON-RPC API — wiki pages, media files, search, ACL management, and user administration - [Graylog](https://www.dadl.ai/d/graylog/) — Graylog REST API -- log search (Views/Search + legacy universal), streams, pipelines, inputs, alerts, events, dashboards, users, roles, sidecars, index management, and cluster administration. Targets Graylog 6.x. - [Hacker News](https://www.dadl.ai/d/hackernews/) — Hacker News API — read-only access to stories, comments, polls, jobs, users, and live feeds from news.ycombinator.com --- **Canonical URL:** https://www.dadl.ai/d/umami/ **Raw DADL:** https://github.com/DunkelCloud/dadl-registry/blob/main/umami.dadl --- # Victron VRM MCP Server — 44 tools via DADL The Victron VRM DADL turns Victron VRM's API into an MCP server that Claude, GPT or any MCP-compatible agent can consume directly. One YAML file declares all 44 tools — widget, data, installation, alarm, diagnostic, dynamic, and more — and ToolMesh serves them at runtime. No Python boilerplate, no per-endpoint code, no separate MCP server process. Below: the endpoint coverage matrix, a two-block ToolMesh setup, the full tool reference grouped by Victron VRM feature area. **Source:** [Victron Energy VRM REST API v2](https://vrm-api-docs.victronenergy.com/) **Updated:** 2026-03-31 **Tags:** energy, iot, monitoring, authentication, search, real-time, metrics, auth:bearer ## Which Victron VRM endpoints are covered? **82%** (41 of ~50 endpoints). **Focus:** auth, users, installations, stats, widgets, diagnostics, alarms, data export, GPS, tags, dynamic ESS, firmware, data attributes **Missing:** admin endpoints, access token CRUD, installation settings write, alarm acknowledgement *Last reviewed: 2026-03-31* ## How do you configure the Victron VRM DADL? 1. Log in to the VRM Portal at https://vrm.victronenergy.com 2. Navigate to Preferences → Integrations → Access tokens 3. Click 'New token', give it a descriptive name 4. Copy the generated token immediately -- it is shown only once 5. Store the token prefixed with 'Token ' (e.g. 'Token abc123def456') in the credential store **Environment variable:** `CREDENTIAL_VICTRON_VRM_TOKEN` [Authentication docs](https://vrm-api-docs.victronenergy.com/) *Personal Access Tokens bypass the login flow entirely. Use /users/me to get your idUser, then /users/{idUser}/installations to discover your sites. The token has full access to all installations the VRM user can see.* ## How do you install the Victron VRM MCP server with ToolMesh? Add to your `backends.yaml`: ```yaml - name: victron-vrm transport: rest dadl: /app/dadl/victron-vrm.dadl ``` Set the credential: ``` CREDENTIAL_VICTRON_VRM_TOKEN=your-token-here ``` ## What 44 tools does the Victron VRM DADL expose? - **POST** `login` — Authenticate with username/password and receive a bearer token. Prefer Personal Access Tokens for automation. - **GET** `login_as_demo` — Log in as the demo user to explore the API without credentials - **GET** `logout` — Invalidate the current session token - **GET** `get_current_user` — Get the current authenticated user's profile and idUser. Essential first call when using Personal Access Tokens. - **GET** `list_installations` — List all installations accessible to a user. Returns idSite, name, and system overview for each. - **GET** `get_installation` — Get high-level system overview for a specific installation including current power flow - **GET** `search_installations` — Search through the user's installations by name, notes, or address - **GET** `get_installation_tags` — Get tags/labels assigned to an installation - **GET** `get_stats` — Get time-series statistics for an installation. Types: venus, live_feed, consumption, kwh, solar_yield, forecast. - **GET** `get_overall_stats` — Get aggregated lifetime totals for an installation (total kWh generated, consumed, etc.) - **GET** `download_data` — Download historical data as CSV or Excel for an installation - **GET** `download_gps_data` — Download GPS tracking data for a mobile installation (e.g. boat, RV) - **GET** `get_alarms` — Get active and historical alarms for an installation. Also returns device list and user notification settings. - **GET** `get_diagnostics` — Get the most recent diagnostic data points for all devices at an installation - **GET** `get_widget` — Get widget data for a specific device category. See hints for available widget types. - **GET** `get_widget_graph` — Get graph widget data with time-series values for specific device instances and attributes - **GET** `get_widget_battery` — Get battery summary: voltage, current, state of charge (SoC), temperature, and health - **GET** `get_widget_solar_charger` — Get MPPT solar charger data: PV voltage, current, yield, and charger state - **GET** `get_widget_vebus_state` — Get VE.Bus system state: inverter/charger mode, input voltage, output power - **GET** `get_widget_inverter_charger_state` — Get inverter/charger operational mode and status - **GET** `get_widget_status` — Get general system status overview for the installation - **GET** `get_widget_pv_inverter` — Get PV inverter AC output: power, voltage, current per phase - **GET** `get_widget_ev_charger` — Get EV charger status: charging power, session energy, and state - **GET** `get_widget_tank` — Get tank level and capacity for fuel, water, or waste tanks - **GET** `get_widget_temperature` — Get temperature sensor readings and graphical data - **GET** `get_widget_dc_meter` — Get DC power meter readings (voltage, current, power) - **GET** `get_widget_motor` — Get motor drive summary: RPM, power, and temperature - **GET** `get_widget_gps` — Get current GPS position for mobile installations (boats, RVs) - **GET** `get_widget_global_link` — Get GlobalLink 520 device summary and connectivity status - **GET** `get_widget_vebus_warnings` — Get VE.Bus system warnings and alarm conditions - **GET** `get_widget_inverter_warnings` — Get inverter/charger warning and alarm conditions - **GET** `get_widget_bms_diagnostics` — Get BMS cell voltages, balancing data, and battery management diagnostics - **GET** `get_widget_lithium_bms` — Get lithium battery BMS details: cell voltages, temperatures, and balancing - **GET** `get_widget_historic_data` — Get historic data trend analysis for device performance over time - **GET** `get_widget_io_extender` — Get IO extender digital and analog input/output signals - **GET** `get_widget_charger_relay` — Get charger relay switching status - **GET** `get_widget_solar_charger_relay` — Get solar charger relay state - **GET** `get_widget_gateway_relay` — Get primary gateway (GX device) relay state - **GET** `get_widget_gateway_relay_two` — Get secondary gateway (GX device) relay state - **GET** `get_widget_custom` — Get custom widget configuration and data - **GET** `get_dynamic_ess` — Get Dynamic ESS (Energy Storage System) settings and schedule for optimized battery usage - **GET** `get_data_attributes` — Get all available data attribute definitions (codes, labels, units) used across the VRM API - **GET** `get_firmwares` — List available firmware versions for Victron devices - **GET** `reset_forecasts` — Get forecast reset timestamps for recalculation scheduling ## Which DADLs are related to Victron VRM? - [Graylog](https://www.dadl.ai/d/graylog/) — Graylog REST API -- log search (Views/Search + legacy universal), streams, pipelines, inputs, alerts, events, dashboards, users, roles, sidecars, index management, and cluster administration. Targets Graylog 6.x. - [PeeringDB](https://www.dadl.ai/d/peeringdb/) — PeeringDB v2 API -- the public peering database of networks (ASNs), Internet Exchanges, and colocation facilities: full CRUD over net, ix, fac, org, carrier, campus, point-of-contact records, and the netixlan/netfac/ixfac/carrierfac/ixlan/ixpfx relationships that map who peers where - [Umami](https://www.dadl.ai/d/umami/) — Umami open-source web analytics — privacy-friendly alternative to Google Analytics - [Algolia HN Search](https://www.dadl.ai/d/algolia-hn-search/) — Algolia Hacker News Search API — full-text search, filtering, and retrieval for stories, comments, and users on Hacker News - [Checkmk](https://www.dadl.ai/d/checkmk/) — Checkmk REST API (version 1.0, Checkmk 2.4) -- live host and service status via Livestatus queries, downtimes, acknowledgements and comments, the Event Console (list, acknowledge, change state and archive events) and BI (packs, rules, aggregations and live aggregation state), plus the full Setup side: hosts, clusters, folders, service discovery, rules and rulesets, host/service/contact groups, users, roles, passwords, time periods, host tags, notification rules, site connections and change activation. - [Cloudflare](https://www.dadl.ai/d/cloudflare/) — Cloudflare API -- DNS, Pages, Workers, KV, R2, D1, Zones, SSL/TLS, Cache, Load Balancers, Firewall/WAF, Page Rules, Access (Zero Trust), Email Routing, Email Sending, DMARC/SPF email auth, and account management --- **Canonical URL:** https://www.dadl.ai/d/victron-vrm/ **Raw DADL:** https://github.com/DunkelCloud/dadl-registry/blob/main/victron-vrm.dadl --- # Vikunja MCP Server — 29 tools via DADL The Vikunja DADL turns Vikunja's API into an MCP server that Claude, GPT or any MCP-compatible agent can consume directly. One YAML file declares all 29 tools — task, project, bucket, label, view, attachment, and more — and ToolMesh serves them at runtime. No Python boilerplate, no per-endpoint code, no separate MCP server process. Below: the endpoint coverage matrix, a two-block ToolMesh setup, the full tool reference grouped by Vikunja feature area, required credential scopes. **Source:** [Vikunja REST API](https://vikunja.io/docs/api/) **Updated:** 2026-10-10 **Tags:** project-management, crud, authentication, search, user-management, auth:bearer ## Which Vikunja endpoints are covered? **36%** (29 of ~80 endpoints). **Focus:** projects, tasks, views, buckets, labels, comments, positions, filters, attachments **Missing:** teams, users, shares, assignees, task relations, reactions, notifications, webhooks, subscriptions, saved filters *Last reviewed: 2026-10-10* ## How do you configure the Vikunja DADL? 1. Log in to the Vikunja web UI 2. Open Settings → API Tokens (user menu, top right) 3. Click 'Create a token', enter a name and an optional expiry 4. Under Permissions grant at least: Projects (read & write), Tasks (read & write), Labels (read & write), Task Comments (read & write) 5. Click Create and copy the token immediately — it is shown only once (format: tk_…) **Environment variable:** `CREDENTIAL_VIKUNJA_API_TOKEN` [Authentication docs](https://vikunja.io/docs/api-tokens) *Vikunja is self-hosted — replace the URL with your instance address, including the /api/v1 suffix. API tokens are shown only once at creation and their granted permissions cap what these tools can do (a read-only token returns 403 on create/update/delete).* ## How do you install the Vikunja MCP server with ToolMesh? Add to your `backends.yaml`: ```yaml - name: vikunja transport: rest dadl: vikunja.dadl url: "https://your-vikunja-instance.com/api/v1" ``` Set the credential: ``` CREDENTIAL_VIKUNJA_API_TOKEN=your-token-here ``` ## What 29 tools does the Vikunja DADL expose? - **POST** `set_task_position` — Set task position (sort order) within a project view. The position is a float64 value — use values between existing tasks to insert. - **GET** `list_project_tasks` — List tasks in a project view (view_id from list_views). The view's OWN saved filter is applied on top of yours: the default List view is created with filter "done = false", so completed tasks never show up there -- check the view's filter field in list_views before concluding a project has no done tasks. For done or all tasks of a project use list_tasks with filter "project = N" or "done = true && project = N". Supports sorting by position, due_date, created, etc. Kanban views return buckets with nested tasks, not a flat list. - **GET** `list_tasks` — Query tasks across ALL projects the user can access (not scoped to a single view). Supports the Vikunja filter DSL, full-text search (s) and multi-field sorting — the best endpoint for analytics/reporting (velocity, ETA, throughput): filter or sort by done_at, created, updated, due_date, percent_done. Scope to one project with filter "project = N"; "done = true && project = N" returns a project's completed tasks, which list_project_tasks hides on views with a "done = false" filter (the default List view). Returns a flat task array; no view filter is applied here. - **GET** `get_task` — Get a single task by its ID, including all details, assignees, labels, and relations. - **PUT** `_create_task_raw` — Internal: raw task creation (leaves the new card at kanban position 0, i.e. the top of the board). Use the create_task composite, which appends it to the end of its bucket. - **POST** `_update_task_raw` — Internal: raw task update (sends full object). Use the update_task composite instead. - **POST** `move_task_to_bucket` — Move a task to a different kanban bucket. Use list_buckets to get bucket IDs. This is the only way to move tasks between kanban columns. - **DELETE** `delete_task` — Permanently delete a task. - **GET** `list_task_attachments` — List all attachments on a task (metadata only: attachment id, uploader, and file name/mime/size). Use download_task_attachment to fetch the bytes. - **PUT** `upload_task_attachment` — Upload a file as an attachment to a task. ToolMesh fetches the given URL and uploads the bytes to Vikunja as the multipart form field "files". Returns the created attachment together with its stored file metadata. - **GET** `download_task_attachment` — Download one task attachment. Returns a ToolMesh file-broker URL (file_url) to fetch the bytes, not the raw binary. For image attachments, pass preview_size to get a scaled preview instead of the original. - **DELETE** `delete_task_attachment` — Permanently delete a task attachment. - **GET** `list_projects` — List all projects accessible to the authenticated user. Projection now also includes parent_project_id and position (hierarchy + ordering), plus hex_color and owner (username). - **GET** `get_project` — Get a single project by ID. - **PUT** `create_project` — Create a new project. Only 'title' is required. Set parent_project_id to nest it under another project (hierarchy). 'identifier' (≤10 chars) is the short prefix used to build task identifiers (e.g. OPS-1); omit to auto-derive. hex_color is a 6-digit hex string without a leading '#'. - **POST** `_update_project_raw` — Internal: raw project update (sends a full object — omitted fields are reset to zero). Use the update_project composite instead. - **DELETE** `delete_project` — Permanently delete a project and all of its tasks, views and buckets. Irreversible. Verify the project_id with get_project first. (There is no delete for labels — those must be removed in the Vikunja UI.) - **GET** `list_views` — List all views (list, kanban, gantt, table) for a project. Each view has its own task positions and may carry its own saved filter (field filter, e.g. the default List view has "done = false") that list_project_tasks applies on top of yours. Call this first to get view_id for list_project_tasks. - **GET** `list_buckets` — List all kanban buckets for a project view. Returns bucket id, title, and task count. Use move_task_to_bucket to move tasks between columns. - **PUT** `create_bucket` — Create a new kanban bucket in a project view. - **POST** `update_bucket` — Rename a kanban bucket, set its WIP task limit, or set its position (column order — lower position is further left). title is required (Vikunja rejects an empty title); limit 0 means no limit. Sends a full bucket object, so pass the current title/limit when changing only one field (set_bucket_position does this for you). Which bucket is the DEFAULT or DONE bucket is a view property — use set_default_bucket for that, not this. - **DELETE** `delete_bucket` — Permanently delete a kanban bucket. Its tasks are not deleted — they fall back to the view's default bucket. - **POST** `_update_view_raw` — Internal: raw project-view update. Vikunja replaces the full view object, so omitted fields reset to zero — use the set_default_bucket composite, which reads the current view and preserves the rest. - **GET** `list_labels` — List all labels the user has access to. Returns id, title, description, hex_color. - **PUT** `create_label` — Create a new label. NOTE: Vikunja creates labels with PUT (not POST). 'title' is required. hex_color is a 6-digit hex string without a leading '#'. Useful for setting up reusable S/M/L estimate labels. - **PUT** `add_label_to_task` — Add a label to a task. - **DELETE** `remove_label_from_task` — Remove a label from a task. The label itself is not deleted and stays available for other tasks. - **GET** `list_task_comments` — List all comments on a task. - **PUT** `create_task_comment` — Add a comment to a task. ## What composite workflows does the Vikunja DADL provide? - **FN** `update_task` — Update an existing task. Only include the fields you want to change — unchanged fields are preserved (GET → merge → POST). Set project_id to MOVE the task to another project (its identifier is reassigned on move — reference by global id afterwards). To move between kanban buckets, use move_task_to_bucket instead. - **FN** `create_task` — Create a task in a project and append it to the END of its kanban bucket (max position + step), server-side, so API-created tasks do not jump to the top of the board and disturb the priority order (board order = priority). Pass bucket_id to place it into a specific kanban bucket; omit to use the view's default bucket. Priority: 0=unset, 1=low, 2=medium, 3=high, 4=urgent, 5=critical. - **FN** `set_default_bucket` — Set which kanban bucket is the DEFAULT (where new tasks land) and, optionally, the DONE bucket (moving a task there marks it done) for a project view. Reads the current view first and preserves its title, kind, filter and layout, so only the bucket assignments change. Get view_id from list_views (the kanban view) and bucket IDs from list_buckets. - **FN** `set_bucket_position` — Reorder a kanban bucket (column) within its view. Pass an explicit position (float64, lower = further left), or place 'first' / 'last' to compute one from the sibling buckets (first = min/2, last = max + step). Reads the bucket first so its title and WIP limit are preserved (the raw bucket update would otherwise need them). Use this to move an Inbox column to the very left. - **FN** `update_project` — Update an existing project. Only include the fields you want to change — unchanged fields are preserved (this composite does GET → merge → POST, because Vikunja's raw project update resets omitted fields). Set parent_project_id to re-parent (0 = top-level). To create a project use create_project. ## Which DADLs are related to Vikunja? - [DokuWiki](https://www.dadl.ai/d/dokuwiki/) — DokuWiki JSON-RPC API — wiki pages, media files, search, ACL management, and user administration - [Algolia HN Search](https://www.dadl.ai/d/algolia-hn-search/) — Algolia Hacker News Search API — full-text search, filtering, and retrieval for stories, comments, and users on Hacker News - [Cloudflare](https://www.dadl.ai/d/cloudflare/) — Cloudflare API -- DNS, Pages, Workers, KV, R2, D1, Zones, SSL/TLS, Cache, Load Balancers, Firewall/WAF, Page Rules, Access (Zero Trust), Email Routing, Email Sending, DMARC/SPF email auth, and account management - [GitLab](https://www.dadl.ai/d/gitlab/) — GitLab REST API v4 — projects, issues, merge requests, pipelines, CI/CD, and code search - [Graylog](https://www.dadl.ai/d/graylog/) — Graylog REST API -- log search (Views/Search + legacy universal), streams, pipelines, inputs, alerts, events, dashboards, users, roles, sidecars, index management, and cluster administration. Targets Graylog 6.x. - [Mastodon](https://www.dadl.ai/d/mastodon/) — Mastodon REST API — statuses, timelines, accounts, notifications, search, media, lists, polls, conversations, trends, filters, and instance info. Base URL must be set to the target Mastodon instance (e.g. https://mastodon.social). --- **Canonical URL:** https://www.dadl.ai/d/vikunja/ **Raw DADL:** https://github.com/DunkelCloud/dadl-registry/blob/main/vikunja.dadl --- # Xen Orchestra MCP Server — 275 tools via DADL The Xen Orchestra DADL turns Xen Orchestra's API into an MCP server that Claude, GPT or any MCP-compatible agent can consume directly. One YAML file declares all 275 tools — vm, vdi, host, acl, backup, vif, and more — and ToolMesh serves them at runtime. No Python boilerplate, no per-endpoint code, no separate MCP server process. Below: the endpoint coverage matrix, a two-block ToolMesh setup, the full tool reference grouped by Xen Orchestra feature area, required credential scopes. **Source:** [Xen Orchestra REST API](https://docs.xen-orchestra.com/restapi) **Updated:** 2026-09-30 **Tags:** cloud, devops, automation, crud, user-management, file-management, monitoring, logging, auth:bearer ## Which Xen Orchestra endpoints are covered? **99%** (275 of ~277 endpoints). **Focus:** Complete REST API coverage for XO 6.4+: all object types (VMs, VM controllers, VM templates, VM snapshots, hosts, pools, SRs, VDIs, VDI snapshots, VBDs, networks, VIFs, PIFs, PBDs, PCIs, PGPUs, SMs), all lifecycle actions (CRUD, partial update of VMs, VIFs and VDIs, power, snapshot/clone/migrate/revert, export/import, hotplug), full host power/lifecycle control (start, clean/smart reboot, clean/emergency shutdown, restart toolstack, disable/enable incl. reboot-persistent maintenance mode, detach, forget, pool join, PIF rescan), full sub-resource access (alarms, messages, tasks, tags, stats per object), RBAC v2 (users, groups, acl-roles, acl-privileges, plus reading role-to-user/group assignments), backups (archives incl. live mount of backup disks, jobs, logs, restore-logs, writable repositories incl. health check, throughput benchmark and space reclaim, schedules), real-time events via SSE, host/pool maintenance ops (rolling reboot/update incl. pinned-VM handling, interrupted-update recovery and finalize, management reconfigure, audit logs, missing patches), network traffic rules (SDN controller plugin: add/delete/update), IPMI sensor inventory (ipmi-sensors plugin), audit records (audit plugin), XOA appliance (dashboard, ping, gui-routes, MCP status). Some routes with format path params are exposed as multiple typed tools (e.g. /vms/{id}.{format} -> export_vm_xva + export_vm_ova, /vdis/{id}.{format} -> export_vdi_vhd + export_vdi_raw + export_vdi_qcow2 + import_vdi_to_existing + import_vdi_to_existing_raw). **Missing:** Authentication-token routes (GET/POST /users/{id}/authentication_tokens) are deliberately NOT exposed: their responses contain plaintext bearer tokens -- the GET list even includes the token used to make the request (see XO PR #10233) -- which must never enter an LLM context. Create/revoke tokens via xo-cli --createToken or the XO web UI instead; do NOT re-add these routes. Backup RESTORE is not exposed over REST -- backup archives, jobs and logs can be read, but restoring a restore-point onto a target SR must be done in the XO GUI or via the JSON-RPC API; since XO 6.9 a backup disk can at least be live-mounted read-only on a host (mount_backup_live_disk) to read its content without a restore. SDN-controller traffic-rule routes (/plugins/sdn-controller/*) are included but only function when the xo-server-sdn-controller plugin is installed; the IPMI inventory route (/plugins/ipmi-sensors/*) likewise requires the xo-server-ipmi-sensors plugin (>= 2.1.1, XO 6.8+) and returns 503 on hosts without a reachable IPMI device; the audit-record routes (/plugins/audit/*) require the xo-server-audit plugin. Deprecated routes (POST /users/authentication_tokens, GET /backup/jobs/vm/*, GET /restore/logs/*) intentionally excluded -- announced for removal on 2026-09-12 / 2026-10-13 and still present in 6.9; do not rely on them. Version floor: routes marked 'XO 6.7+' return 404 on 6.6.x (create_sr, update_vdi, list_acl_role_users, list_acl_role_groups, list_group_acl_roles), 'XO 6.8+' on 6.7.x (scan_pifs_host, get_host_ipmi_sensors) and 'XO 6.9+' on 6.8.x (get_pool_rolling_update_recovery, finalize_rolling_update_pool, reclaim_space_backup_repository, mount_backup_live_disk, unmount_backup_live_disk, list_audit_records, get_audit_record; export_vdi_qcow2 answers 422 there). Body fields newer than the target build are REJECTED with HTTP 400 by XO's typed routes -- bypassBackupCheck and acceptCurrentStateAsBaseline (6.9) on 6.7/6.8 -- so omit them on older XO; only the pre-6.7 rolling_reboot/rolling_update routes had no body at all and silently ignore shutdownPinnedVms *Last reviewed: 2026-09-30* ## How do you configure the Xen Orchestra DADL? 1. Deploy Xen Orchestra from sources or use XOA (Xen Orchestra Appliance) 2. Log in to the XO web UI as an admin user 3. Navigate to Settings -> Users to confirm admin access 4. Generate an auth token via CLI: xo-cli --createToken xo.example.com <user> <password> 5. Or via API: POST /rest/v0/users/me/authentication_tokens with Basic auth 6. Copy the returned token value -- use it as the authenticationToken cookie 7. Optional (XO 6.4+): create dedicated non-admin users via POST /users and assign acl-roles via PUT /acl-roles/{id}/users/{userId} **Environment variable:** `CREDENTIAL_XEN_ORCHESTRA_TOKEN` [Authentication docs](https://docs.xen-orchestra.com/restapi) *The url in backends.yaml must point to your XO instance including /rest/v0. Generate a token via xo-cli --createToken or POST /rest/v0/users/me/authentication_tokens with Basic auth. Live Swagger UI at /rest/v0/docs lists all endpoints with required RBAC privileges. For RBAC v2 setup see https://docs.xen-orchestra.com/xo6/acl-v2.* ## How do you install the Xen Orchestra MCP server with ToolMesh? Add to your `backends.yaml`: ```yaml - name: xen-orchestra transport: rest dadl: xen-orchestra.dadl url: "https://xo.example.com/rest/v0" ``` Set the credential: ``` CREDENTIAL_XEN_ORCHESTRA_TOKEN=your-token-here ``` ## What 275 tools does the Xen Orchestra DADL expose? - **GET** `ping` — Health check. Unauthenticated. Returns {result: 'pong', timestamp}. Use this to verify the XO instance is reachable before trying authenticated calls. - **GET** `get_dashboard` — Aggregated dashboard for the XOA appliance: pool/host/VM counts, storage usage, recent backup-jobs (last 7 days), disconnected servers, disabled hosts. Use ndjson=true for streaming output. Replaces the legacy plural /dashboards endpoint. - **GET** `get_gui_routes` — Returns the URLs of the legacy XO5 (xo5) and modern XO6 (xo6) web UIs. Useful for clients that need to deep-link into the GUI. - **GET** `get_mcp_status` — Report whether XO's built-in MCP server is enabled. Unauthenticated. Returns 200 when enabled, 503 when disabled. Requires a recent XO build (REST route added after 6.5.0); returns 404 on older instances. - **GET** `list_users` — List all users. Returns URLs by default; use fields for objects. Requires user:read privilege. - **GET** `get_user` — Get details of a single user. Use id='me' for the current authenticated user. Self-fetch is always allowed; reading another user requires user:read privilege. - **POST** `create_user` — Create a new user. Returns {id} of the created user. Requires user:create privilege. - **PATCH** `update_user` — Update user properties. Cannot change own permission. Synchronized users (LDAP/SAML/OIDC) cannot have name/password changed. - **DELETE** `delete_user` — Delete a user. Irreversible. Requires user:delete privilege. - **GET** `list_user_groups` — List groups the user is a member of (filtered by group:read privilege). Use id='me' for self. - **GET** `list_user_tasks` — List tasks owned by the user (filtered by task:read privilege). Use id='me' for self. - **GET** `list_user_acl_privileges` — List effective RBAC v2 acl-privileges for the user (XO 6.4+). Useful for inspecting what a user can actually do. Self-call (/users/me/acl-privileges) is always permitted. - **GET** `list_groups` — List all groups (filtered by group:read privilege). - **GET** `get_group` — Get details of a single group. - **POST** `create_group` — Create a new group. Returns {id} of the created group. - **PATCH** `update_group` — Update group properties (currently only name). - **DELETE** `delete_group` — Delete a group. Irreversible. Removes all role attachments to this group. - **PUT** `add_user_to_group` — Add a user to a group. - **DELETE** `remove_user_from_group` — Remove a user from a group. - **GET** `list_group_users` — List users that are members of the group. - **GET** `list_group_tasks` — List tasks associated with members of the group. - **GET** `list_group_acl_roles` — List the RBAC roles granted to this group -- i.e. what every member of the group inherits. Requires XO 6.7+ (returns 404 on older builds). Inverse view of list_acl_role_groups. - **GET** `list_acl_roles` — List all RBAC v2 roles. A role groups privileges and can be attached to users/groups. - **GET** `get_acl_role` — Get details of a single role. - **POST** `create_acl_role` — Create a new RBAC role. Returns {id}. Add privileges via POST /acl-privileges (with roleId), then attach to users/groups. - **PATCH** `update_acl_role` — Update a role's name and/or description (set description to null to clear). - **DELETE** `delete_acl_role` — Delete a role. Irreversible. All attachments to users/groups are removed; privileges referencing this role are also dropped. - **POST** `copy_acl_role` — Duplicate a role (and its privileges) under a new name. Useful for deriving custom roles from built-in ones. - **GET** `list_acl_role_privileges` — List all acl-privileges attached to this role. - **GET** `list_acl_role_users` — List the users this RBAC role is directly attached to. Requires XO 6.7+ (returns 404 on older builds). Note this shows direct assignments only -- users who hold the role through a group appear in list_acl_role_groups instead. - **GET** `list_acl_role_groups` — List the groups this RBAC role is attached to. Every member of those groups inherits the role. Requires XO 6.7+ (returns 404 on older builds). - **PUT** `attach_acl_role_to_group` — Attach an RBAC role to a group. All members of the group inherit the role's privileges. - **DELETE** `detach_acl_role_from_group` — Detach an RBAC role from a group. - **PUT** `attach_acl_role_to_user` — Attach an RBAC role directly to a user (in addition to roles inherited via groups). - **DELETE** `detach_acl_role_from_user` — Detach an RBAC role from a user. - **GET** `list_acl_privileges` — List all RBAC v2 privileges (each privilege = role + resource + action, optionally scoped by object). - **GET** `get_acl_privilege` — Get details of a single privilege. - **POST** `create_acl_privilege` — Grant a new privilege (action on a resource type, optionally scoped to a specific object) to a role. Returns {id}. Body fields depend on the resource type -- see Swagger /rest/v0/docs for the privilege schema. - **PATCH** `update_acl_privilege` — Update a privilege's resource/action/objectId (roleId is immutable). - **DELETE** `delete_acl_privilege` — Revoke a privilege. Irreversible. - **GET** `list_vms` — List all VMs. Returns URLs by default; use fields for objects. - **GET** `get_vm` — Get full details of a VM - **PATCH** `update_vm` — Partially update a VM's properties (rename, resize CPU/RAM, boot firmware, tags, etc.). Only the fields you pass are changed. Some fields require the VM to be halted. Requires XO 6.5+ (PATCH /vms route returns 404 on older builds). - **DELETE** `delete_vm` — Destroy a VM and its VDIs. Irreversible. - **POST** `start_vm` — Start a halted VM. Optionally pin to a specific host via body.hostId. - **POST** `clean_shutdown_vm` — Gracefully shut down a VM (ACPI shutdown) - **POST** `hard_shutdown_vm` — Force shutdown a VM immediately (equivalent to pulling the plug) - **POST** `clean_reboot_vm` — Gracefully reboot a VM (ACPI reboot) - **POST** `hard_reboot_vm` — Force reboot a VM immediately - **POST** `pause_vm` — Pause a running VM (freezes CPU, keeps memory) - **POST** `unpause_vm` — Unpause a paused VM - **POST** `suspend_vm` — Suspend a VM to disk (saves memory state, frees RAM) - **POST** `resume_vm` — Resume a suspended VM from disk - **POST** `snapshot_vm` — Create a snapshot of a VM. Returns task reference; use ?sync to get the snapshot id directly. - **POST** `revert_vm_to_snapshot` — Revert a VM to one of its snapshots. Optionally take a fresh snapshot of the current state first (snapshotBefore) so the revert is undoable. Requires XO 6.5+ (route returns 404 on older builds). - **POST** `clone_vm` — Clone a VM. Three modes: fast clone on same SR (fast=true, omit srId), full copy on same SR (fast=false), or copy to another SR/pool (provide srId, optional compress=gzip|zstd for cross-pool). - **POST** `migrate_vm` — Live-migrate a VM to another host. Supports cross-SR storage migration and per-disk / per-VIF placement for cross-pool moves. - **GET** `export_vm_xva` — Export a VM as XVA (XCP-ng native format). Streamed binary download. - **GET** `export_vm_ova` — Export a VM as OVA (Open Virtualization Format, portable across hypervisors). - **POST** `import_vm_xva` — Import a VM from XVA upload into a pool. Body is the raw XVA stream. - **GET** `get_vm_stats` — Get RRD statistics for a VM (CPU, memory, network, disk). VM must be running. - **PUT** `add_vm_data_source` — Enable a specific RRD data source on a VM (e.g. cpu0, vif_0_rx). VM must be running. - **DELETE** `delete_vm_data_source` — Disable / forget a specific RRD data source on a VM. - **PUT** `add_vm_tag` — Add a tag to a VM - **DELETE** `remove_vm_tag` — Remove a tag from a VM - **GET** `list_vm_vdis` — List all VDIs attached to a VM - **GET** `list_vm_alarms` — List XAPI alarms (performance/health thresholds) for the VM. - **GET** `list_vm_messages` — List XAPI messages/alerts emitted for the VM. - **GET** `list_vm_tasks` — List tasks scoped to this VM (running/completed/failed). - **GET** `list_vm_backup_jobs` — List backup-jobs that include this VM. - **GET** `get_vm_dashboard` — Get dashboard/statistics for a VM (aggregate metrics). - **GET** `list_vm_snapshots` — List all VM snapshots - **GET** `get_vm_snapshot` — Get details of a VM snapshot - **DELETE** `delete_vm_snapshot` — Delete a VM snapshot. Irreversible. - **GET** `export_vm_snapshot` — Export a VM snapshot as XVA or OVA. Format is the file extension ('xva' or 'ova'). - **GET** `list_vm_snapshot_vdis` — List VDIs belonging to a VM snapshot. - **GET** `list_vm_snapshot_alarms` — List XAPI alarms scoped to a VM snapshot. - **GET** `list_vm_snapshot_messages` — List XAPI messages scoped to a VM snapshot. - **GET** `list_vm_snapshot_tasks` — List tasks scoped to a VM snapshot. - **PUT** `add_vm_snapshot_tag` — Add a tag to a VM snapshot. - **DELETE** `remove_vm_snapshot_tag` — Remove a tag from a VM snapshot. - **GET** `list_vm_templates` — List all VM templates. Templates are stamps from which create_vm produces new VMs. - **GET** `get_vm_template` — Get details of a VM template. - **DELETE** `delete_vm_template` — Delete a VM template. Irreversible. Built-in templates may be protected. - **GET** `export_vm_template` — Export a VM template as XVA or OVA. - **GET** `list_vm_template_vdis` — List VDIs belonging to a VM template. - **GET** `list_vm_template_alarms` — List XAPI alarms scoped to a VM template. - **GET** `list_vm_template_messages` — List XAPI messages scoped to a VM template. - **GET** `list_vm_template_tasks` — List tasks scoped to a VM template. - **PUT** `add_vm_template_tag` — Add a tag to a VM template. - **DELETE** `remove_vm_template_tag` — Remove a tag from a VM template. - **GET** `list_vm_controllers` — List VM controllers (the dom0 control-domain VM of each host). Returns URLs by default; use fields for objects. - **GET** `get_vm_controller` — Get full details of a VM controller (dom0 control domain). - **GET** `list_vm_controller_alarms` — List XAPI alarms for a VM controller. - **GET** `list_vm_controller_vdis` — List VDIs attached to a VM controller. - **GET** `list_vm_controller_messages` — List XAPI messages for a VM controller. - **GET** `list_vm_controller_tasks` — List tasks scoped to a VM controller. - **PUT** `add_vm_controller_tag` — Add a tag to a VM controller. - **DELETE** `remove_vm_controller_tag` — Remove a tag from a VM controller. - **GET** `list_hosts` — List all XCP-ng/XenServer hosts - **GET** `get_host` — Get details of a host - **GET** `get_host_stats` — Get RRD statistics for a host (CPU, memory, NIC, disk). Host must be enabled. - **GET** `get_host_audit_log` — Download the host's audit log as plain text. Useful for compliance and forensics. - **GET** `get_host_logs` — Download the host's full logs as a gzipped tarball. Useful for support tickets and debugging. - **GET** `list_host_alarms` — List XAPI alarms (performance/health thresholds) for the host. - **GET** `get_host_smt` — Get the SMT (Simultaneous Multi-Threading / Hyper-Threading) status of the host. - **GET** `list_host_missing_patches` — List all patches/updates that are available but not yet installed on the host. - **GET** `list_host_messages` — List XAPI messages/alerts emitted for the host. - **GET** `list_host_tasks` — List tasks scoped to this host (running/completed/failed). - **PUT** `add_host_tag` — Add a tag to a host. - **DELETE** `remove_host_tag` — Remove a tag from a host. - **POST** `management_reconfigure_host` — Move the management interface (control plane) to a different PIF. May briefly disconnect XO from the host. - **POST** `disable_host` — Disable a host = enter maintenance mode (no new VMs are placed on it). Optionally evacuate VMs in the same call (evacuate=true, optional force/vmIdsToForceMigrate). Since XO 6.7 the disable is PERSISTENT by default: the host stays disabled across toolstack restarts and reboots until enable_host. Send autoEnable=true for a transient disable that XAPI lifts at the next toolstack restart. XO 6.6 always disabled transiently and rejects autoEnable with HTTP 400. The persistent form requires XAPI >= 25.31.0 on the host; on older hosts the call fails unless autoEnable=true. - **POST** `enable_host` — Re-enable a disabled host (leave maintenance mode) - **POST** `start_host` — Power on a halted host via its out-of-band controller (wake-on-LAN / IPMI, as configured in XAPI). Requires XO 6.6+. - **POST** `clean_shutdown_host` — Gracefully shut down a host. Refuses while VMs are still running unless they are evacuated first -- disable_host with evacuate=true is the normal preceding step. Requires XO 6.6+. - **POST** `clean_reboot_host` — Gracefully reboot a host. Same evacuation rules as clean_shutdown_host. Requires XO 6.6+. - **POST** `smart_reboot_host` — Suspend the resident VMs, reboot the host, then resume the VMs in place -- no live migration needed. Preferred over clean_reboot_host when the pool has no spare capacity. Requires XO 6.6+. - **POST** `restart_toolstack_host` — Restart the XAPI toolstack on a host. Running VMs keep running; the host is briefly unmanageable. Standard first remedy for a wedged XAPI. Requires XO 6.6+. - **POST** `emergency_shutdown_host` — Suspend all resident VMs and shut the host down immediately, without evacuation. For UPS-low / thermal events. Requires XO 6.6+. - **POST** `detach_host` — Eject a host from its pool and make it standalone again. The host must be running and its VMs relocated. Inverse of add_host_to_pool. Requires XO 6.6+. - **POST** `forget_host` — Remove a dead host's record from the pool database without contacting it. Only for hosts that are permanently gone -- if the host later comes back it will conflict with the pool. Requires XO 6.6+. - **POST** `scan_pifs_host` — Rescan a host's physical NICs (XAPI PIF.scan) and create PIF objects for newly detected interfaces. The host must be RUNNING (409 otherwise). Idempotent on unchanged hardware. Requires XO 6.8+ (404 on older builds). - **GET** `list_pools` — List all pools - **GET** `get_pool` — Get details of a pool - **GET** `get_pool_stats` — Get aggregated RRD statistics for the entire pool. - **GET** `get_pool_dashboard` — Get dashboard for a single pool (counts of VMs/hosts/SRs, usage). - **GET** `list_pool_alarms` — List XAPI alarms for the pool and its objects. - **GET** `list_pool_missing_patches` — Aggregate of missing patches across all hosts in the pool. - **GET** `get_pool_rolling_update_recovery` — XO 6.9+ (404 on older builds). Recovery status of an incomplete rolling pool update: run status (preparing|running|interrupted|resuming|failed|cleaning|succeeded), per-host step statuses, lastError, taskId and haltedPinnedVms (VM UUID -> UUID of the host it must be started on); or {status: 'blocked', blockedReason} when the record is unreadable. HTTP 404 means nothing to recover: the last rolling update completed, or the pool master is not XCP-ng / XenServer 8.4+ (no record is kept for older pools). Check it before rolling_update_pool (refused while a record exists) and before finalize_rolling_update_pool. - **GET** `list_pool_messages` — List XAPI messages for the pool. - **GET** `list_pool_tasks` — List tasks scoped to the pool. - **PUT** `add_pool_tag` — Add a tag to a pool. - **DELETE** `remove_pool_tag` — Remove a tag from a pool. - **POST** `create_vm` — Create a new VM from a template - **POST** `emergency_shutdown_pool` — Emergency shutdown of all VMs and hosts in a pool - **POST** `rolling_reboot_pool` — Sequentially reboot hosts with automatic VM migration; zero downtime for migratable VMs. Returns a task (poll with get_task). XO 6.9+: refused with HTTP 409 'incorrect state' while a backup job runs on the pool unless bypassBackupCheck=true, and VMs are moved back to their original host more reliably. - **POST** `rolling_update_pool` — Apply pending updates to hosts sequentially with live migration. Returns a task (poll with get_task). XO 6.9+: refused with HTTP 409 'incorrect state' while a backup job runs on the pool (bypassBackupCheck=true overrides), while a previous rolling update is still running, and -- on XCP-ng / XenServer 8.4+ pools -- while an interrupted run has not been closed with finalize_rolling_update_pool, or when the master is already up to date but other hosts are not (send acceptCurrentStateAsBaseline=true to continue from that state). XO 6.7/6.8 already refused a second concurrent run. - **POST** `finalize_rolling_update_pool` — XO 6.9+ (404 on older builds). Close the recovery record of an interrupted rolling pool update once the pool has been reviewed -- until then a new rolling_update_pool on this pool is refused. Refused with HTTP 409 'incorrect state' listing what the update changed and did not restore (HA, auto power-on, WLB, load balancer, backup schedules, disabled hosts, displaced or halted VMs) while any such item remains; displaced VMs alone are only listed. force=true closes it anyway: the items are abandoned and listed in the task, nothing is restored or changed in the pool. 404 when the pool has no recovery record (check get_pool_rolling_update_recovery first). Only XCP-ng / XenServer 8.4+ pools keep such records. Returns a task. - **POST** `add_host_to_pool` — Make a standalone host join this pool. The host must already be registered as a server in XO and be homogeneous with the pool master (CPU features, XCP-ng version) unless force is set. Requires XO 6.6+. Inverse of detach_host. - **POST** `create_pool_network` — Create a basic network on a pool (attached to a single PIF). For aggregation use create_bonded_network; for isolated use create_internal_network. - **POST** `create_bonded_network` — Create a bonded (link-aggregated) network across multiple PIFs in the pool. - **POST** `create_internal_network` — Create an internal-only network (host-local, no physical PIF, useful for VM-to-VM private traffic). Body field names are name/description -- NOT name_label/name_description. - **POST** `management_reconfigure_pool` — Reconfigure the management interface across all hosts in the pool. Coordinated equivalent of management_reconfigure_host -- but note this one takes a NETWORK id, while the host-level route takes a PIF id. - **GET** `list_srs` — List all storage repositories - **GET** `get_sr` — Get details of an SR - **POST** `create_sr` — Create a storage repository on a host. Requires XO 6.7+ (returns 404 on older builds). SR_type selects the driver -- shared/network types: nfs, smb, lvmoiscsi, lvmohba, lvmofcoe, hba, cephfs, glusterfs, moosefs, iso; local types: lvm, ext, file. device_config holds the driver-specific keys, e.g. nfs -> {server, serverpath}, smb -> {server, username, password}, lvmoiscsi -> {target, targetIQN, SCSIid}, lvm/ext -> {device}. Returns {id}. - **DELETE** `delete_sr` — Destroy an SR and all data on its underlying storage. Irreversible -- the SR must be detached/unplugged first. To keep the data, use forget_sr instead. Requires XO 6.5+ (DELETE /srs route returns 404 on older builds). - **GET** `list_sr_alarms` — List XAPI alarms for the SR (e.g. low free space). - **GET** `list_sr_messages` — List XAPI messages for the SR. - **GET** `list_sr_tasks` — List tasks scoped to the SR. - **PUT** `add_sr_tag` — Add a tag to an SR. - **DELETE** `remove_sr_tag` — Remove a tag from an SR. - **POST** `scan_sr` — Scan an SR to refresh its VDI list (detects manual changes on the underlying storage). - **POST** `forget_sr` — Forget an SR (detach without destroying data on the underlying storage). - **POST** `reclaim_space_sr` — Reclaim unused space on a thin-provisioned SR. - **GET** `list_vdis` — List all virtual disk images - **GET** `get_vdi` — Get details of a VDI - **POST** `create_vdi` — Create a new VDI - **PATCH** `update_vdi` — Partially update a VDI: rename (name_label / name_description) or grow the disk (size). Only the fields you pass are changed. Added in XO 6.7 -- returns 404 on older builds. Size can only be increased, never shrunk. - **DELETE** `delete_vdi` — Delete a VDI. Irreversible. - **GET** `list_vdi_alarms` — List XAPI alarms for the VDI. - **GET** `list_vdi_messages` — List XAPI messages for the VDI. - **GET** `list_vdi_tasks` — List tasks scoped to the VDI. - **PUT** `add_vdi_tag` — Add a tag to a VDI. - **DELETE** `remove_vdi_tag` — Remove a tag from a VDI. - **POST** `migrate_vdi` — Migrate a VDI to a different SR (live storage migration) - **GET** `export_vdi_vhd` — Export a VDI as VHD, whatever format the disk is stored in. Binary download. Since XO 6.9 the export reads the disk over NBD automatically when available and always sends content-length; the route has no NBD tuning query params. - **GET** `export_vdi_raw` — Export a VDI as a raw disk image, whatever format the disk is stored in. Binary download; since XO 6.9 content-length is always sent. The route has no NBD tuning query params. - **GET** `export_vdi_qcow2` — XO 6.9+ (older builds answer 422 'Invalid format'). Export a VDI as qcow2, whatever format the disk is stored in; reads over NBD when available and sends content-length. Binary download. Importing back is vhd/raw only (import_vdi_to_existing, import_vdi_to_sr). - **POST** `import_vdi_to_sr` — Import a VDI from VHD/raw upload into an SR - **PUT** `import_vdi_to_existing` — Replace existing VDI contents (VHD format). Size must match exactly. - **PUT** `import_vdi_to_existing_raw` — Replace existing VDI contents (raw format). Size must match exactly. - **GET** `list_vdi_snapshots` — List all VDI snapshots. - **GET** `get_vdi_snapshot` — Get details of a VDI snapshot. - **DELETE** `delete_vdi_snapshot` — Delete a VDI snapshot. Irreversible. - **GET** `export_vdi_snapshot` — Export a VDI snapshot as VHD, raw or (XO 6.9+) qcow2. Format is the file extension; qcow2 on older builds answers 422 'Invalid format'. Binary download. - **GET** `list_vdi_snapshot_alarms` — List XAPI alarms scoped to a VDI snapshot. - **GET** `list_vdi_snapshot_messages` — List XAPI messages scoped to a VDI snapshot. - **GET** `list_vdi_snapshot_tasks` — List tasks scoped to a VDI snapshot. - **PUT** `add_vdi_snapshot_tag` — Add a tag to a VDI snapshot. - **DELETE** `remove_vdi_snapshot_tag` — Remove a tag from a VDI snapshot. - **GET** `list_vbds` — List all VBDs (VDI-to-VM attachments). - **GET** `get_vbd` — Get details of a VBD. - **POST** `create_vbd` — Create a VBD to attach a VDI to a VM - **DELETE** `delete_vbd` — Delete a VBD (detach disk) - **GET** `list_vbd_alarms` — List XAPI alarms for the VBD. - **GET** `list_vbd_messages` — List XAPI messages for the VBD. - **GET** `list_vbd_tasks` — List tasks scoped to the VBD. - **POST** `connect_vbd` — Hotplug a VBD to a running VM - **POST** `disconnect_vbd` — Hot-unplug a VBD from a running VM - **GET** `list_networks` — List all networks - **GET** `get_network` — Get details of a network - **DELETE** `delete_network` — Delete a network - **GET** `list_network_alarms` — List XAPI alarms for the network. - **GET** `list_network_messages` — List XAPI messages for the network. - **GET** `list_network_tasks` — List tasks scoped to the network. - **PUT** `add_network_tag` — Add a tag to a network. - **DELETE** `remove_network_tag` — Remove a tag from a network. - **GET** `list_vifs` — List all virtual network interfaces. - **GET** `get_vif` — Get details of a VIF. - **POST** `create_vif` — Create a virtual network interface on a VM. The VM and network must belong to the same pool. - **PATCH** `update_vif` — Partially update a VIF's properties (locking mode, allowed IPs, rate limit, TX checksumming). Only the fields you pass are changed. Added in XO 6.6 -- returns 404 on older builds. Does not move the VIF to another network; recreate it for that. - **DELETE** `delete_vif` — Delete a virtual network interface - **POST** `connect_vif` — Hotplug a VIF to a running VM (XO 6.4+). - **POST** `disconnect_vif` — Hot-unplug a VIF from a running VM (XO 6.4+). - **GET** `list_vif_alarms` — List XAPI alarms for the VIF. - **GET** `list_vif_messages` — List XAPI messages for the VIF. - **GET** `list_vif_tasks` — List tasks scoped to the VIF. - **POST** `add_network_traffic_rule` — Add a traffic (OpenFlow) rule to a private SDN network. Requires the SDN Controller plugin. - **POST** `delete_network_traffic_rule` — Remove a traffic rule from a private SDN network. The rule is identified by allow + direction + ipRange + protocol + port exactly as it was added. Since XO 6.9 a non-matching rule returns HTTP 404 (older builds returned 204 without deleting anything and ignored allow). Requires the SDN Controller plugin (404 otherwise). - **POST** `update_network_traffic_rule` — Update an existing traffic rule on a private SDN network. oldRule must contain the FULL existing rule (allow/direction/ipRange/protocol, plus port if set) to identify it; newRule is a PARTIAL update -- only the fields you send change, and a field sent as null is REMOVED from the rule (XO 6.8+; before 6.8 e.g. the old port was silently kept). Added in XO 6.6. Requires the SDN Controller plugin (404 otherwise). - **POST** `add_vif_traffic_rule` — Add a traffic (OpenFlow) rule to a VIF connected to a private SDN network. Requires the SDN Controller plugin. - **POST** `delete_vif_traffic_rule` — Remove a traffic rule from a VIF connected to a private SDN network. The rule is identified by allow + direction + ipRange + protocol + port exactly as it was added. Since XO 6.9 a non-matching rule returns HTTP 404 (older builds returned 204 without deleting anything and ignored allow). Requires the SDN Controller plugin (404 otherwise). - **POST** `update_vif_traffic_rule` — Update an existing traffic rule on a VIF connected to a private SDN network. oldRule must contain the FULL existing rule (allow/direction/ipRange/protocol, plus port if set) to identify it; newRule is a PARTIAL update -- only the fields you send change, and a field sent as null is REMOVED from the rule (XO 6.8+; before 6.8 e.g. the old port was silently kept). Added in XO 6.6. Requires the SDN Controller plugin (404 otherwise). - **GET** `get_host_ipmi_sensors` — Raw IPMI sensor inventory of a host: {productName, systemManufacturer, sensors: [{name, value, event, dataType}]}. dataType is one of totalPower/inletTemp/outletTemp/cpuTemp/fanSpeed/fanStatus/psuPower/psuStatus/bmcStatus/ip/unknown -- 'unknown' sensors are included here (unlike the categorized XO5 view). Requires XO 6.8+ with the xo-server-ipmi-sensors plugin loaded (404 otherwise); returns 503 if the host has no reachable IPMI device -- treat 503 as a definitive answer, not a transient error. - **GET** `list_audit_records` — List XO audit records (who called which API method with which params, from which IP), newest first. Requires the xo-server-audit plugin (404 otherwise; route documented in Swagger since XO 6.9). Without fields the result is a list of record hrefs; fields='*' returns full records {id, previousId, event, time (ms epoch), subject:{userId,userName,userIp}, data:{method,params}}. Page with limit plus from (id of the record to continue from). filter uses XO filter syntax, e.g. 'event:apiCall'. The host-level XAPI audit log is get_host_audit_log. - **GET** `get_audit_record` — Get one XO audit record by id: {id, previousId, event, time, subject:{userId,userName,userIp}, data:{method,params}}. Requires the xo-server-audit plugin (404 otherwise, and 404 for unknown ids). Route documented in Swagger since XO 6.9. - **GET** `list_pifs` — List all physical network interfaces - **GET** `get_pif` — Get details of a PIF - **GET** `list_pif_alarms` — List XAPI alarms for the PIF (e.g. link down). - **GET** `list_pif_messages` — List XAPI messages for the PIF. - **GET** `list_pif_tasks` — List tasks scoped to the PIF. - **GET** `list_pbds` — List all PBDs (SR-to-host connections) - **GET** `get_pbd` — Get details of a PBD - **POST** `plug_pbd` — Plug a PBD to connect an SR to a host - **POST** `unplug_pbd` — Unplug a PBD to disconnect an SR from a host - **GET** `list_pcis` — List all PCI devices (for passthrough) - **GET** `get_pci` — Get details of a PCI device - **GET** `list_pgpus` — List all physical GPUs - **GET** `get_pgpu` — Get details of a physical GPU - **GET** `list_sms` — List all storage manager plugins/drivers - **GET** `get_sm` — Get details of a storage manager plugin - **GET** `list_tasks` — List all tasks. Use ndjson+watch for real-time streaming. - **GET** `get_task` — Get a task. Set wait=true to block until the task finishes (long-poll), then return its final state. - **DELETE** `delete_task` — Delete a completed or failed task - **DELETE** `delete_tasks` — Bulk delete: removes ALL tasks the current user has 'task:delete' privilege on. Irreversible. - **POST** `abort_task` — Abort a running task - **GET** `list_messages` — List XAPI messages/alerts (e.g. HA alerts, license warnings) - **GET** `get_message` — Get details of a XAPI message - **GET** `list_alarms` — List all XAPI alarms (CPU, memory, disk, latency thresholds). - **GET** `get_alarm` — Get details of a single XAPI alarm. - **GET** `open_events_stream` — Open an SSE (Server-Sent Events) connection. The first event is 'init' and carries the connection id, i.e. the subscriber id for add_event_subscription / remove_event_subscription; afterwards ping (keepalive), add (object created), update (object changed), remove (object deleted). Since XO 6.9 subscriptions can also cover non-XAPI collections (users, groups, ACL roles/privileges, proxies, servers, backup repositories/jobs, schedules). - **POST** `add_event_subscription` — Add an object-type subscription to an open SSE connection. Returns the subscription id (= collection name). - **DELETE** `remove_event_subscription` — Remove a subscription from an open SSE connection. - **GET** `list_backups` — List backup archives (restore points) stored on backup repositories. backup-repository is effectively REQUIRED: '*' lists every repository, or pass one repository id (from list_backup_repositories) -- without it XO answers an empty list (all versions). Archive ids contain slashes (e.g. '<repoId>//xo-vm-backups/<vmUuid>/<timestamp>.json') -- pass them to get_backup / mount_backup_live_disk exactly as returned; use fields=id,backupRepository,vm,timestamp,mode,disks for structured restore points. Filter example: filter='disks:length:>0'. - **GET** `get_backup` — Get details of a backup archive. - **POST** `mount_backup_live_disk` — XO 6.9+ (404 on older builds), administrators only. Serve one disk of a backup archive as a read-only iSCSI LUN and attach it to a host as a new SR, so its content can be read (e.g. attach the VDI to a VM with create_vbd) WITHOUT restoring: nothing is copied, blocks are read from the backup repository on demand. diskId is one of the archive's disks[].id (see get_backup), hostId the host that receives the SR. With ?sync the result is {id, srUuid, vdiUuid, iqn, address, port} (HTTP 201) -- keep id: it is the liveDiskId for unmount_backup_live_disk. Without sync a task is returned. The mount is released automatically when the SR or the VM holding the disk is deleted; otherwise unmount it. XO's address must be reachable from the host (auto-detected, or set iscsi.advertisedAddress in the xo-server config). - **POST** `unmount_backup_live_disk` — XO 6.9+ (404 on older builds), administrators only. Detach a disk mounted by mount_backup_live_disk: the SR is unplugged and forgotten and the iSCSI target is stopped. liveDiskId is the id returned by the mount; 404 if it does not belong to this archive. 204 on success (with ?sync), otherwise a task. - **GET** `list_backup_jobs` — List all configured backup jobs (VM, metadata, mirror) - **GET** `get_backup_job` — Get details of a backup job. - **GET** `list_backup_logs` — List backup execution logs - **GET** `get_backup_log` — Get details of a single backup log entry. - **GET** `list_restore_logs` — List restore execution logs - **GET** `get_restore_log` — Get details of a single restore log entry. - **GET** `list_backup_repositories` — List all backup repositories (NFS, S3, SMB, local targets where backups are stored). - **GET** `get_backup_repository` — Get details of a backup repository (capacity, type, status). - **POST** `create_backup_repository` — Register a new backup repository ('remote') where backups are written. Added in XO 6.6 (was read-only before). Returns {id}. The url encodes the backend type (nfs://, smb://, s3://, file://). - **PATCH** `update_backup_repository` — Update a backup repository's properties (name, url, options, enabled). PATCH semantics -- only the fields you send change. Added in XO 6.6. Set enabled=false to stop new backups writing here without removing it. - **POST** `forget_backup_repository` — Remove a backup repository registration from XO. Added in XO 6.6. Does NOT delete the backup data on the underlying storage. Fails if backup-jobs still reference it. Note: there is no DELETE /backup-repositories/{id} route -- this action IS the removal. - **GET** `get_backup_repository_health` — Check whether XO can reach and mount a backup repository. Returns {"success": true} when healthy; an unreachable or misconfigured repository reports the failure instead. Use this to validate a repository before pointing a backup job at it, or as a routine health check. Added in XO 6.6. - **POST** `benchmark_backup_repository` — Measure read/write throughput of a backup repository by writing and reading back test data. Use it to investigate slow backups or to compare candidate targets. Runs for a while and writes to the repository -- prefer async (omit sync) and poll the returned task. Added in XO 6.6. - **POST** `reclaim_space_backup_repository` — XO 6.9+ (404 on older builds; note the HYPHEN in reclaim-space, unlike the SR route). Reclaim space on a backup repository by running XO's per-VM cleanup: merge=true merges orphaned incremental chains, remove=true deletes backup disks that have no metadata left (both default true -- irreversible for that orphaned data; intact restore points are not touched). vmUuid limits the run to one VM (404 if that VM has no backups on this repository); without it every VM on the repository is cleaned. Refused with HTTP 409 while a backup job referencing the repository is running; 502 = repository unreachable. Proxied repositories are supported (10 min timeout). Long-running: omit sync and poll the returned task, whose result lists per-VM merge/size figures. - **GET** `list_schedules` — List all schedules (cron triggers attached to backup-jobs). - **GET** `get_schedule` — Get details of a schedule (cron expression, jobId, enabled). - **POST** `run_schedule` — Manually trigger the backup-job behind this schedule (outside its cron). Returns task reference. - **GET** `list_proxies` — List all XO Proxy instances - **GET** `get_proxy` — Get details of an XO Proxy - **GET** `list_servers` — List all XCP-ng/XenServer connections registered in XO. - **GET** `get_server` — Get details of a registered server (status, label, host, username). - **POST** `add_server` — Register a new XCP-ng/XenServer pool master in XO. Returns {id}. Use connect_server afterwards to establish the XAPI connection. - **DELETE** `delete_server` — Remove a XCP-ng/XenServer connection from XO - **POST** `connect_server` — Establish the XAPI connection to a registered server. - **POST** `disconnect_server` — Drop the XAPI connection to a registered server (without removing it from XO). - **GET** `list_server_tasks` — List tasks scoped to this server connection. ## Which DADLs are related to Xen Orchestra? - [Billomat](https://www.dadl.ai/d/billomat/) — Billomat REST API — German cloud invoicing & accounting: invoices, estimates, credit notes, recurring invoices, delivery notes, order confirmations, dunning reminders, clients, contacts, articles, payments, expenses, taxes - [NetBox](https://www.dadl.ai/d/netbox/) — NetBox DCIM/IPAM API -- full v4 coverage: sites, racks, devices, modules, interfaces, cables, power, IPAM (prefixes, IPs, VLANs, VRFs, route-targets, VLAN translation), virtualization, circuits (including virtual circuits), tenants, contacts, VPN (IKE/IPSec/L2VPN), wireless, extras (webhooks, event-rules, scripts, config-templates, bookmarks, notifications), users/permissions/tokens, and core data sources & jobs - [Graylog](https://www.dadl.ai/d/graylog/) — Graylog REST API -- log search (Views/Search + legacy universal), streams, pipelines, inputs, alerts, events, dashboards, users, roles, sidecars, index management, and cluster administration. Targets Graylog 6.x. - [Mempool](https://www.dadl.ai/d/mempool/) — mempool.space — Bitcoin block explorer, mempool visualizer, fee estimator, Lightning Network explorer, and transaction accelerator - [Mikrotik](https://www.dadl.ai/d/mikrotik/) — MikroTik RouterOS REST API -- manage interfaces, IP addresses, routing, firewall, DHCP, DNS, PPP, queues, wireless, system configuration, users, certificates, files, logs, and diagnostics on RouterOS v7.1+ devices - [Opnsense](https://www.dadl.ai/d/opnsense/) — OPNsense firewall REST API — manage firewall rules, aliases, interfaces, VPN, DHCP, DNS, diagnostics, firmware, and services on OPNsense appliances --- **Canonical URL:** https://www.dadl.ai/d/xen-orchestra/ **Raw DADL:** https://github.com/DunkelCloud/dadl-registry/blob/main/xen-orchestra.dadl --- # Zammad MCP Server — 206 tools via DADL The Zammad DADL turns Zammad's API into an MCP server that Claude, GPT or any MCP-compatible agent can consume directly. One YAML file declares all 206 tools — ticket, checklist, user, organization, calendar, email, and more — and ToolMesh serves them at runtime. No Python boilerplate, no per-endpoint code, no separate MCP server process. Below: the endpoint coverage matrix, a two-block ToolMesh setup, the full tool reference grouped by Zammad feature area, required credential scopes. **Source:** [Zammad REST API](https://docs.zammad.org/en/latest/api/intro.html) **Updated:** 2026-05-22 **Tags:** project-management, crud, user-management, notifications, logging, issue-tracking, automation, security, auth:apikey ## Which Zammad endpoints are covered? **93%** (205 of ~220 endpoints). **Focus:** tickets (CRUD + search + history + merge + summarize + tags + links + mentions + shared_draft + time_accounting), ticket_articles (CRUD + attachments inline base64), ticket_states/priorities (CRUD), global search (across all models + per-model + tag autocomplete), users (CRUD + me + search + password + preferences + devices + access_tokens + avatar + email_verify), organizations (CRUD + search), groups (CRUD), roles (CRUD), online_notifications (list + mark_seen + mark_all_read), object_manager_attributes (CRUD + execute_migrations), calendars (CRUD), slas (CRUD), knowledge_bases (init + categories + answers + publish/archive + permissions + reorder + attachments), checklists (CRUD + items + templates), macros, triggers, overviews, jobs (schedulers), reports, signatures, text_modules, templates, email_addresses, postmaster_filters, translations, settings, tag_list admin + tag_search, data_privacy_tasks, activity_stream, karma, monitoring (health/status/amount_check) **Missing:** external_credentials (OAuth setup for Twitter/Facebook/Google/Microsoft), form_submit (public embed form), upload_caches (form_id-based -- Web-UI internal), getting_started wizard, sessions long-polling (/message_send + /message_receive), email channel probe/verify sub-actions, channels generic CRUD, two-factor admin *Last reviewed: 2026-05-22* ## How do you configure the Zammad DADL? 1. Log in to your Zammad instance as the user who will own the token 2. Click your avatar (bottom-left of the sidebar) -> Profile -> Token Access 3. If 'Token Access' is hidden, an admin must grant the role permission 'user_preferences.access_token' (Admin -> Roles) 4. Click 'Create', fill in a label (e.g. 'ToolMesh Integration') 5. Tick the required permissions: ticket.agent (or ticket.customer), admin.user, admin.organization, knowledge_base.editor, etc. -- the token cannot exceed the user's own permissions 6. Optionally set an expiry date (YYYY-MM-DD) 7. Click 'Create' -- the token is shown ONCE, copy it immediately (cannot be recovered, only revoked) 8. Provide only the raw token value in your credential store -- ToolMesh prepends 'Token token=' automatically **Environment variable:** `CREDENTIAL_ZAMMAD_TOKEN` [Authentication docs](https://docs.zammad.org/en/latest/api/intro.html) *The url MUST include the /api/v1 suffix, e.g. "https://helpdesk.example.com/api/v1". Zammad is self-hosted, no central endpoint. Impersonation modes (X-On-Behalf-Of): - Off -- no header sent, action recorded as token owner. - Pass-through -- the calling agent supplies X-On-Behalf-Of per call (e.g. forwards the end-user's email). - Fixed user -- operator pins a value in backends.yaml under headers.X-On-Behalf-Of. Tool-level header still wins when supplied. The token cannot exceed the creating user's permissions. For full admin access, create the token as an admin account; for pure customer self-service flows, create it as a customer. * ## How do you install the Zammad MCP server with ToolMesh? Add to your `backends.yaml`: ```yaml - name: zammad transport: rest dadl: zammad.dadl url: "https://helpdesk.example.com/api/v1" # Optional fixed-user impersonation: pin every outbound request # to act on behalf of a specific Zammad user. Comment out for # default (token owner) behaviour or pass-through mode. # headers: # X-On-Behalf-Of: "bot@example.com" ``` Set the credential: ``` CREDENTIAL_ZAMMAD_TOKEN=your-token-here ``` ## What 206 tools does the Zammad DADL expose? - **GET** `list_tickets` — List all tickets visible to the authenticated user. Paginated. Use search_tickets for filtered queries -- this endpoint has no filter parameters beyond pagination. - **GET** `get_ticket` — Retrieve a single ticket by ID. Set all_articles=true to include the full article list under .articles. - **POST** `create_ticket` — Create a new ticket with an initial article. Required: title, group (group name or group_id), customer (email or customer_id), and an article object {subject, body, type, internal}. Returns the created ticket with its first article. Use X-On-Behalf-Of header to record the ticket as created by another user. - **PUT** `update_ticket` — Update an existing ticket. Any field can be partially updated. Pass an 'article' object alongside other fields to append a new article in the same call (common pattern for replying with a state change). - **DELETE** `delete_ticket` — Permanently delete a ticket. Requires admin permission. Irreversible -- consider closing/merging instead. - **GET** `search_tickets` — Full-text ticket search using Elasticsearch query syntax when ES is enabled, or limited SQL otherwise. Examples: 'state.name:open', 'priority.name:"2 normal" AND tags:feedback', 'customer.email:*@example.com AND created_at:[2026-01-01 TO 2026-12-31]'. - **GET** `get_ticket_history` — Get the full audit history for a ticket -- all changes, article additions, state transitions, with timestamps and acting users. - **POST** `merge_tickets` — Merge slave ticket into master ticket. All articles from slave move to master; slave is closed with state 'merged'. IRREVERSIBLE. - **POST** `summarize_ticket` — Get an AI-generated summary of the ticket. Returns the existing summary or triggers async generation -- retry after ~30 seconds if generation is in progress. - **GET** `global_search` — Search across ALL searchable models (Ticket, User, Organization, KnowledgeBase::Answer::Translation, Chat::Session). Returns a mixed array of result objects each tagged with .type. Use search_in_model if you only need one type -- it's much cheaper. - **GET** `search_in_model` — Search within a single model. Cheaper and more focused than global_search. {model} must be lowercased model name: 'ticket', 'user', 'organization', 'knowledge_base/answer/translation', 'chat/session'. THIS is the canonical way to find a ticket by free text (e.g. 'find ticket about offline printer'). - **GET** `tag_search_autocomplete` — Tag-name autocomplete -- returns up to ~25 tag names matching the prefix. Used by UI search boxes. - **GET** `list_articles_by_ticket` — List all articles belonging to a ticket. Returns chronological array. - **GET** `get_article` — Retrieve a single ticket article by ID. - **PUT** `update_article` — Update an existing ticket article. The most common use is toggling the `internal` flag (publish an internal note, or hide a previously public article). Other editable fields (subject, body) depend on Zammad's "ui_ticket_zoom_article_*_edit" settings -- by default, body editing is allowed for a limited time after creation by the author and by agents with the relevant permission. - **POST** `create_article` — Append a new article to an existing ticket. Common pattern: reply via email (type=email, sender=Agent), internal note (type=note, internal=true), or customer-side message (type=web, sender=Customer with X-On-Behalf-Of=<customer email>). - **GET** `download_attachment` — Download an attachment file. Returns the raw binary content. - **GET** `list_tags_for_object` — Get all tags attached to a specific object (ticket, user, organization, KB answer). - **POST** `add_tag` — Attach a tag to an object. Creates the tag if it does not exist (unless tag administration restricts this). - **DELETE** `remove_tag` — Remove a tag from an object. Does not delete the tag definition itself. - **GET** `list_ticket_links` — List all links between tickets. Pass link_object_value as the ticket NUMBER (not ID). - **POST** `add_ticket_link` — Create a link between two tickets. link_type controls direction: 'normal' (peer), 'parent' (source is parent), 'child' (source is child). - **DELETE** `remove_ticket_link` — Remove a link between two tickets. - **GET** `list_my_mentions` — List all mentions targeting the authenticated user (or impersonated user). - **POST** `create_mention` — Add a mention -- subscribes the current user to updates on a mentionable object (typically a ticket). - **DELETE** `delete_mention` — Remove a mention -- unsubscribes from updates. - **GET** `list_time_accounting` — List all time-accounting entries for a ticket. - **GET** `get_time_accounting` — Get a single time-accounting entry. - **POST** `create_time_accounting` — Record time spent on a ticket. time_unit is in minutes (decimals allowed). - **PUT** `update_time_accounting` — Update an existing time entry. Admin permission required. - **DELETE** `delete_time_accounting` — Delete a time-accounting entry. Admin permission required. - **GET** `get_shared_draft` — Get the shared draft for a ticket (collaborative reply being composed). - **PUT** `create_shared_draft` — Create the shared draft for a ticket. - **PATCH** `update_shared_draft` — Update the shared draft for a ticket. - **DELETE** `delete_shared_draft` — Delete the shared draft for a ticket. - **GET** `list_ticket_priorities` — List all ticket priorities (e.g. '1 low', '2 normal', '3 high'). - **GET** `get_ticket_priority` — Get a single ticket priority. - **POST** `create_ticket_priority` — Create a new ticket priority. Admin permission required. - **PUT** `update_ticket_priority` — Update a ticket priority. - **DELETE** `delete_ticket_priority` — Delete a ticket priority. Fails if the priority is in use. - **GET** `list_ticket_states` — List all ticket states (e.g. new, open, pending reminder, pending close, closed, merged, removed). - **GET** `get_ticket_state` — Get a single ticket state. - **POST** `create_ticket_state` — Create a new ticket state. state_type_id references a state type (new/open/closed/pending action/pending reminder/merged/removed). - **PUT** `update_ticket_state` — Update a ticket state. - **DELETE** `delete_ticket_state` — Delete a ticket state. Fails if the state is in use. - **GET** `get_me` — Get the currently authenticated user. With X-On-Behalf-Of header, returns the impersonated user. - **GET** `list_users` — List users. Use search_users for filtered queries. - **GET** `get_user` — Get a single user by ID. - **GET** `search_users` — Search users by firstname/lastname/login/email (Elasticsearch syntax when enabled). Returns matching users. - **POST** `create_user` — Create a new user. Email or login is required as a primary identifier. - **PUT** `update_user` — Update a user. All fields are optional -- only supplied fields are changed. - **DELETE** `delete_user` — Permanently delete a user. NOT recommended -- prefer marking inactive or using a GDPR data_privacy_task. - **POST** `change_my_password` — Change the authenticated user's password. Requires the current password. - **POST** `request_password_reset` — Initiate a password reset for a user (sends a reset email). - **POST** `verify_password_reset` — Complete a password reset using the token from the reset email. - **POST** `send_email_verification` — Send a verification email to the supplied address. Used for self-signup flows. - **POST** `verify_email_token` — Complete an email verification by submitting the token from the verification email. - **POST** `upload_my_avatar` — Upload an avatar image for the authenticated user. Both fields are data-URLs (e.g. 'data:image/png;base64,iVBOR...'). avatar_full is the original; avatar_resize is the cropped version (typically square). - **GET** `get_user_avatar` — Download a user avatar by its hash (returned in user objects under image). - **POST** `unlock_user` — Unlock a user account that was locked due to failed login attempts. - **GET** `get_my_preferences` — Get the authenticated user's preferences (notification settings, locale, etc.). - **PUT** `update_my_preferences` — Update the authenticated user's preferences. Body shape mirrors the user.preferences field. - **GET** `list_my_devices` — List devices that have authenticated as the current user (browsers, mobile apps). - **DELETE** `revoke_device` — Revoke a device session for the current user. - **GET** `list_my_access_tokens` — List API tokens owned by the authenticated user, plus the catalog of permissions available to assign. - **POST** `create_my_access_token` — Create a new personal access token. Token value is returned ONCE in the response under .token -- store immediately. Permissions cannot exceed the user's own. - **DELETE** `delete_my_access_token` — Revoke a personal access token by ID. - **GET** `list_data_privacy_tasks` — List pending and completed GDPR deletion tasks. - **GET** `get_data_privacy_task` — Get a single data-privacy task. - **POST** `create_data_privacy_task` — Schedule the deletion of a user (GDPR right to be forgotten). Currently only User is deletable. - **DELETE** `cancel_data_privacy_task` — Cancel a pending data-privacy task. - **GET** `list_organizations` — List organizations. - **GET** `get_organization` — Get a single organization. - **GET** `search_organizations` — Search organizations (Elasticsearch syntax when enabled). - **POST** `create_organization` — Create a new organization. - **PUT** `update_organization` — Update an organization. - **DELETE** `delete_organization` — Delete an organization. Fails if the organization has users or tickets. - **GET** `list_groups` — List all groups (ticket inboxes / queues). - **GET** `get_group` — Get a single group. - **POST** `create_group` — Create a new group. Nested groups use '::' as separator (e.g. 'Sales::Europe'). - **PUT** `update_group` — Update a group. - **DELETE** `delete_group` — Delete a group. Fails if the group contains tickets or users. - **GET** `list_roles` — List all roles (permission bundles). - **GET** `get_role` — Get a single role. - **POST** `create_role` — Create a new role with the given permissions. - **PUT** `update_role` — Update a role. - **GET** `list_online_notifications` — List the authenticated user's in-app notifications. Use expand=true for human-friendly object labels. - **GET** `get_online_notification` — Get a single online notification. - **PUT** `update_online_notification` — Update notification status (typically mark as seen). - **DELETE** `delete_online_notification` — Dismiss / delete a single notification. - **POST** `mark_all_notifications_read` — Mark all of the current user's notifications as seen. - **GET** `list_object_attributes` — List all object-manager attributes (built-in + custom fields) across Ticket, User, Organization, Group. - **GET** `get_object_attribute` — Get a single object-manager attribute definition. - **POST** `create_object_attribute` — Create a custom field. NOTE: changes do not take effect until execute_object_manager_migrations is called. - **PUT** `update_object_attribute` — Update a custom field. Requires execute_object_manager_migrations to apply. - **DELETE** `delete_object_attribute` — Delete a custom field. Requires execute_object_manager_migrations to apply. - **POST** `execute_object_manager_migrations` — Apply pending object-manager schema migrations. MUST be called after create/update/delete of any custom field. - **GET** `list_calendars` — List business-hour calendars (used for SLA escalation timing). - **GET** `get_calendar` — Get a single calendar. - **POST** `create_calendar` — Create a business-hour calendar. - **PUT** `update_calendar` — Update a calendar. - **DELETE** `delete_calendar` — Delete a calendar. Fails if used by an SLA. - **GET** `list_slas` — List Service Level Agreements. - **GET** `get_sla` — Get a single SLA. - **POST** `create_sla` — Create an SLA. Time values are in minutes. - **PUT** `update_sla` — Update an SLA. - **DELETE** `delete_sla` — Delete an SLA. - **POST** `init_knowledge_base` — Initial KB overview -- returns the list of KBs, categories, and answer summaries. - **GET** `get_knowledge_base` — Get a single Knowledge Base by ID. - **PATCH** `update_knowledge_base` — Update KB settings (visibility, custom address, etc.). - **GET** `get_kb_permissions` — Get role-based permissions for a KB. Returns an array of {role_id, access} where access is admin|editor|reader|none. - **PUT** `set_kb_permissions` — Set role-based permissions for a KB. Pass full permissions array (replaces existing). - **PATCH** `reorder_kb_root_categories` — Set the display order of top-level KB categories. Pass the full ordered list of category IDs. - **GET** `get_kb_category` — Get a single KB category. - **POST** `create_kb_category` — Create a KB category. translations_attributes is an array of {title, locale}. - **PATCH** `update_kb_category` — Update a KB category. - **DELETE** `delete_kb_category` — Delete a KB category. Fails if it has child categories or answers. - **GET** `get_kb_category_permissions` — Get role permissions for a specific KB category (override category-level access). - **PUT** `set_kb_category_permissions` — Set role permissions for a KB category (overrides KB-wide permissions for this subtree). - **PATCH** `reorder_kb_subcategories` — Set the display order of subcategories within a category. - **PATCH** `reorder_kb_answers` — Set the display order of answers within a category. - **GET** `get_kb_answer` — Get a KB answer. Use include_contents=<translation_id> to inline the body content. - **POST** `create_kb_answer` — Create a KB answer. translations_attributes must contain at least one {title, content (HTML), locale}. - **PATCH** `update_kb_answer` — Update a KB answer. - **DELETE** `delete_kb_answer` — Delete a KB answer. - **POST** `publish_kb_answer` — Publish a KB answer publicly. - **POST** `internal_kb_answer` — Publish a KB answer to internal audience only. - **POST** `archive_kb_answer` — Archive a KB answer (soft-hide without delete). - **POST** `unarchive_kb_answer` — Restore an archived KB answer. - **POST** `upload_kb_answer_attachment` — Attach a file to a KB answer. Multipart upload -- file_url is fetched by ToolMesh and forwarded as multipart/form-data. - **DELETE** `delete_kb_answer_attachment` — Remove an attachment from a KB answer. - **GET** `get_checklist` — Get a single ticket checklist. - **POST** `create_checklist` — Create a checklist on a ticket, optionally from a template. - **PATCH** `update_checklist` — Update checklist (rename, reorder items). - **DELETE** `delete_checklist` — Delete a checklist (and all its items). - **GET** `get_checklist_item` — Get a single checklist item. - **POST** `create_checklist_item` — Add an item to a checklist. - **PATCH** `update_checklist_item` — Update a checklist item (text and/or checked state). - **DELETE** `delete_checklist_item` — Delete a checklist item. - **GET** `list_checklist_templates` — List checklist templates. - **GET** `get_checklist_template` — Get a single checklist template. - **POST** `create_checklist_template` — Create a reusable checklist template. - **PATCH** `update_checklist_template` — Update a checklist template. - **DELETE** `delete_checklist_template` — Delete a checklist template. - **GET** `list_macros` — List macros (named action-bundles applied to tickets). - **GET** `get_macro` — Get a single macro. - **POST** `create_macro` — Create a macro. perform is a map of attribute -> {value, ...}. - **PUT** `update_macro` — Update a macro. - **DELETE** `delete_macro` — Delete a macro. - **GET** `list_triggers` — List automation triggers. - **GET** `get_trigger` — Get a single trigger. - **POST** `create_trigger` — Create an event trigger. condition selects matching tickets; perform applies actions. - **PUT** `update_trigger` — Update a trigger. - **DELETE** `delete_trigger` — Delete a trigger. - **GET** `list_overviews` — List saved ticket overviews (custom queues / views). - **GET** `get_overview` — Get a single overview. - **POST** `create_overview` — Create an overview (named ticket query) shared with selected roles. - **PUT** `update_overview` — Update an overview. - **DELETE** `delete_overview` — Delete an overview. - **GET** `list_jobs` — List scheduler jobs (recurring tasks executed on a timer). - **GET** `get_job` — Get a single scheduler job. - **POST** `create_job` — Create a recurring scheduler job. - **PUT** `update_job` — Update a scheduler job. - **DELETE** `delete_job` — Delete a scheduler job. - **POST** `generate_report` — Generate a report dataset (counts/aggregates) for a given metric over a date range. - **GET** `list_report_sets` — List available report sets (configured profiles and backends). - **GET** `list_signatures` — List email signatures. - **GET** `get_signature` — Get a single signature. - **POST** `create_signature` — Create an email signature. body supports Zammad variable placeholders. - **PUT** `update_signature` — Update a signature. - **DELETE** `delete_signature` — Delete a signature. - **GET** `list_text_modules` — List text modules (canned replies / snippets). - **GET** `get_text_module` — Get a single text module. - **POST** `create_text_module` — Create a text module. keywords trigger autocomplete in the compose box. - **PUT** `update_text_module` — Update a text module. - **DELETE** `delete_text_module` — Delete a text module. - **GET** `list_templates` — List ticket-creation templates. - **GET** `get_template` — Get a single template. - **POST** `create_template` — Create a ticket template. options is a map of attribute -> value used to pre-fill the create form. - **PUT** `update_template` — Update a template. - **DELETE** `delete_template` — Delete a template. - **GET** `list_email_addresses` — List configured email-sender addresses. - **GET** `get_email_address` — Get a single email address. - **POST** `create_email_address` — Add a sender email address linked to an outbound channel. - **PUT** `update_email_address` — Update an email address. - **DELETE** `delete_email_address` — Delete an email address. - **GET** `list_postmaster_filters` — List postmaster filters (email pre-processing rules: match headers, set ticket properties). - **GET** `get_postmaster_filter` — Get a single postmaster filter. - **POST** `create_postmaster_filter` — Create a postmaster filter. match selects emails by header; perform assigns ticket fields. - **PUT** `update_postmaster_filter` — Update a postmaster filter. - **DELETE** `delete_postmaster_filter` — Delete a postmaster filter. - **GET** `list_all_tags` — List all defined tags with usage counts. - **POST** `create_tag_definition` — Create a tag in the catalog (without attaching it to an object yet). - **PUT** `rename_tag` — Rename a tag everywhere it is used. - **DELETE** `delete_tag_definition` — Delete a tag from the catalog and detach it from all objects. - **GET** `list_translations` — List UI string translations. - **GET** `list_admin_translations` — Get all translations for a locale, including admin-overridable strings. - **GET** `list_settings` — List system settings. Returns full setting objects -- use jq to filter by area or name. - **GET** `get_setting` — Get a single setting by ID. - **PUT** `update_setting` — Update a system setting. Only state_current can typically be changed; structure depends on the setting. - **GET** `get_activity_stream` — Get the activity stream for the authenticated user (recent changes across visible objects). - **GET** `get_recent_viewed` — Get the list of recently viewed objects for the authenticated user. - **GET** `list_karma_users` — Get the Karma gamification leaderboard. Returns an array of {user_id, score, level} entries (level e.g. 'Beginner', 'Master'). Karma awards points for actions like first-response-within-SLA, ticket-closed, KB-answer-published. Often disabled by admins -- 404 means the feature is not enabled. - **GET** `monitoring_health_check` — Health check endpoint. NOTE: requires a separate monitoring token passed as ?token=... query parameter (configured in Admin -> System -> Monitoring), NOT the user access token. - **GET** `monitoring_status` — System status / counts. Requires monitoring token (see monitoring_health_check). - **GET** `monitoring_amount_check` — Volume check (e.g. tickets created in last period). ## What composite workflows does the Zammad DADL provide? - **FN** `reply_and_close` — Append an outbound email reply to a ticket and close it in one atomic call. Common agent workflow. - **FN** `create_ticket_with_articles` — Create a ticket and append additional follow-up articles in sequence. Useful for migrating existing conversations. - **FN** `find_or_create_customer` — Look up a customer by email; create them if they do not exist. Returns the user object. ## Which DADLs are related to Zammad? - [Zulip](https://www.dadl.ai/d/zulip/) — Zulip REST API — messages, channels (streams), topics, users, user groups, subscriptions, reactions, drafts, scheduled messages, saved snippets, presence, real-time events, invitations, attachments, custom emoji, linkifiers, and server settings. Self-hosted or Zulip Cloud. - [Billomat](https://www.dadl.ai/d/billomat/) — Billomat REST API — German cloud invoicing & accounting: invoices, estimates, credit notes, recurring invoices, delivery notes, order confirmations, dunning reminders, clients, contacts, articles, payments, expenses, taxes - [Opnsense](https://www.dadl.ai/d/opnsense/) — OPNsense firewall REST API — manage firewall rules, aliases, interfaces, VPN, DHCP, DNS, diagnostics, firmware, and services on OPNsense appliances - [Alertmanager](https://www.dadl.ai/d/alertmanager/) — Prometheus Alertmanager API v2 -- alerts, silences, receivers, alert groups, status, and operational health - [BookStack](https://www.dadl.ai/d/bookstack/) — BookStack wiki and documentation platform REST API -- shelves, books, chapters, pages (HTML/Markdown content), attachments, image gallery, comments, cross-entity search, exports (HTML/Markdown/PDF/ZIP), ZIP imports, users, roles, content permissions, recycle bin, audit log and tags. Hierarchy: shelves > books > chapters > pages. - [Checkmk](https://www.dadl.ai/d/checkmk/) — Checkmk REST API (version 1.0, Checkmk 2.4) -- live host and service status via Livestatus queries, downtimes, acknowledgements and comments, the Event Console (list, acknowledge, change state and archive events) and BI (packs, rules, aggregations and live aggregation state), plus the full Setup side: hosts, clusters, folders, service discovery, rules and rulesets, host/service/contact groups, users, roles, passwords, time periods, host tags, notification rules, site connections and change activation. --- **Canonical URL:** https://www.dadl.ai/d/zammad/ **Raw DADL:** https://github.com/DunkelCloud/dadl-registry/blob/main/zammad.dadl --- # Zulip MCP Server — 111 tools via DADL The Zulip DADL turns Zulip's API into an MCP server that Claude, GPT or any MCP-compatible agent can consume directly. One YAML file declares all 111 tools — user, message, realm, custom, stream, draft, and more — and ToolMesh serves them at runtime. No Python boilerplate, no per-endpoint code, no separate MCP server process. Below: the endpoint coverage matrix, a two-block ToolMesh setup, the full tool reference grouped by Zulip feature area, required credential scopes. **Source:** [Zulip REST API](https://zulip.com/api/rest) **Updated:** 2026-05-28 **Tags:** communication, crud, user-management, notifications, real-time, logging, automation, issue-tracking, auth:basic ## Which Zulip endpoints are covered? **67%** (111 of ~165 endpoints). **Focus:** messages (send + get + get-one + update + delete + render + history + reactions + flags + flags-for-narrow + mark-as-read + read-receipts + typing + matches-narrow), channels/streams (list + get-by-id + get-id-by-name + update + archive + topics + subscribers + delete-topic + subscription-status + email-address), subscriptions (list + subscribe-or-create + unsubscribe + update-settings), users (list + get + by-email + own + create + update + deactivate + reactivate + presence + status + regenerate-own-api-key + update-own-settings), user groups (list + create + update + deactivate + members + subgroups), personal preferences (mute/unmute user, topic visibility policy follow/mute/unmute, alert words CRUD), drafts (CRUD), saved snippets (CRUD), scheduled messages (CRUD), real-time events (register + get + delete), invitations (send + list + resend + revoke + multi-use), attachments (list + delete), files (upload + custom emoji upload), org admin (update_realm + user_settings_defaults + linkifiers full CRUD + reorder + custom profile fields full CRUD + reorder + code playgrounds + realm domains + default streams + bot CRUD + regenerate bot api key), server/realm (server settings + linkifiers list + custom emoji list + deactivate) **Missing:** OAuth/SAML/external auth flows, mobile push device registration (APNS/FCM tokens), email confirmation flows, password reset flows, video call provider connection setup (the realm setting is covered, the per-call plumbing isn't), navigation views, message reminders (3 endpoints), realm export/import requests, SCIM provisioning, in-app hotspots & tutorial step tracking, BotConfig per-bot key-value storage (3 endpoints), some dev-only endpoints, billing/plan management *Last reviewed: 2026-05-28* ## How do you configure the Zulip DADL? 1. Decide whether you want to use a human user account or a dedicated bot (recommended for production). 2. For a bot: log into Zulip → click your avatar → Personal Settings → Bots → Add a new bot. 3. Choose type 'Generic bot' (most flexible). Give it a name and email. Click Create. 4. Click the download icon next to the new bot to view its API key, or click the copy icon. 5. For a human account: Personal Settings → Account & privacy → API key → Manage your API key → enter your password → copy the key. 6. Store BOTH the email address and the API key — they are used together as HTTP Basic credentials. 7. Subscribe the bot to any channels it needs to read or post in (channels → settings → Add subscribers). 8. Note your organization URL: https://YOUR-ORG.zulipchat.com (Zulip Cloud) or your self-hosted domain. 9. Set BOTH env vars in your ToolMesh deployment: 10. CREDENTIAL_ZULIP_EMAIL=<bot or user email address> (used as HTTP Basic username) 11. CREDENTIAL_ZULIP_API_KEY=<api key> (used as HTTP Basic password) **Environment variable:** `CREDENTIAL_ZULIP_API_KEY` [Authentication docs](https://zulip.com/api/api-keys) *Two credentials are needed: zulip_email (the bot's or user's email) and zulip_api_key (the API key string). Both are sent as HTTP Basic auth — ToolMesh handles the base64 encoding. The url in backends.yaml is the bare org URL WITHOUT the /api/v1 suffix (the DADL adds it). For Zulip Cloud orgs the URL pattern is https://<slug>.zulipchat.com; for self-hosted it is whatever the admin configured. Anyone with the API key can impersonate the bot — treat it as a secret.* ## How do you install the Zulip MCP server with ToolMesh? Add to your `backends.yaml`: ```yaml - name: zulip transport: rest dadl: zulip.dadl url: "https://your-org.zulipchat.com" ``` Set the credential: ``` CREDENTIAL_ZULIP_API_KEY=your-token-here ``` ## What 111 tools does the Zulip DADL expose? - **POST** `send_message` — Send a message to a channel topic or as a direct message. For channel messages set type=channel (or 'stream'), to=<channel name or stream_id>, topic=<topic name>, content=<markdown>. For DMs set type=direct (or 'private'), to=<user email/id or JSON array of user IDs>, content=<markdown>. Returns {id, automatic_new_visibility_policy?}. - **GET** `get_messages` — Fetch a range of messages around an anchor. Use anchor + num_before + num_after to page; anchor can be a message ID or one of: 'newest', 'oldest', 'first_unread'. narrow is a JSON-encoded array of filter objects, e.g. '[{"operator":"channel","operand":"general"},{"operator":"topic","operand":"deploys"}]'. Operators: channel, topic, sender, search, is, has, dm, dm-including, id, with. Max 5000 messages per request (recommend ≤1000). Response includes {messages, anchor, found_oldest, found_newest, found_anchor, history_limited}. - **GET** `get_message` — Fetch a single message by ID. Returns the message object with content, sender info, topic, channel, reactions, flags, and timestamps. - **PATCH** `update_message` — Edit a message's content, topic, or move it to a different channel. propagate_mode controls scope: change_one (default, this message), change_later (this + later in same topic), change_all (entire topic). Only the sender or users with appropriate permissions can edit. - **DELETE** `delete_message` — Permanently delete a message. Only the sender (within edit window) or organization administrators can delete. Cannot be undone. - **POST** `render_message` — Render a Markdown string to HTML using Zulip-flavored Markdown, without sending it. Useful for previewing how a message will look. - **GET** `get_message_history` — Get the edit history of a message. Returns array of snapshots (oldest first) including topic, content, rendered_content, timestamp, user_id, and prev_* fields where changed. - **POST** `add_reaction` — Add an emoji reaction to a message. emoji_name is the Zulip emoji name (e.g. 'thumbs_up', 'octopus'). - **DELETE** `remove_reaction` — Remove your own emoji reaction from a message. - **POST** `update_message_flags` — Add or remove a flag on a batch of messages by ID. Flags: read, starred, collapsed. Some flags are read-only and change automatically (mentioned, has_alert_word, etc.). op is 'add' or 'remove'. - **POST** `update_message_flags_for_narrow` — Add or remove a flag across all messages matching a narrow. Useful for 'mark all unread in this channel as read'. anchor + num_before + num_after define the scope (same semantics as get_messages). Returns processed_count, updated_count, first/last_processed_id, found_oldest/found_newest. - **POST** `mark_all_as_read` — Mark every unread message visible to the current user as read. Deprecated — prefer update_message_flags_for_narrow with anchor=oldest, num_after=large. - **POST** `mark_stream_as_read` — Mark all unread messages in a channel as read. Deprecated — prefer update_message_flags_for_narrow with a channel narrow. - **POST** `mark_topic_as_read` — Mark all unread messages in a topic as read. Deprecated — prefer update_message_flags_for_narrow with channel + topic narrow. - **GET** `get_read_receipts` — Get the list of user IDs who have read a message. Excludes the sender, users with send_read_receipts disabled, and muted users. - **POST** `set_typing_status` — Send a "user is typing" notification. Clients call this every few seconds while typing, then send op=stop when done. type=direct needs `to` (JSON array of user IDs); type=channel needs stream_id + topic. - **GET** `check_messages_match_narrow` — Test which of a given set of message IDs match a narrow. Useful for selectively highlighting search hits in a list. Returns a dict keyed by message ID with match_content + match_subject (HTML, with search keyword highlighting). Messages that don't match are omitted. - **GET** `get_streams` — List channels visible to the authenticated user. Filters control which categories are included (public, subscribed, default, archived). Returns array of stream objects with stream_id, name, description, invite_only, is_web_public, history_public_to_subscribers, message_retention_days, and permission groups. - **GET** `get_stream` — Get full details of a channel by its numeric ID. Returns stream object with name, description, privacy, retention, permission groups, subscriber_count, stream_weekly_traffic. - **GET** `get_stream_id` — Look up a channel's numeric ID by its exact name. Returns {stream_id}. Returns code=BAD_REQUEST if the channel does not exist or is not accessible. - **PATCH** `update_stream` — Update a channel's settings. Requires channel admin permission. All body params optional — only fields you pass are changed. Permission group settings take a JSON-encoded object like {"new":"role:everyone"} or a group ID. - **DELETE** `archive_stream` — Archive (delete) a channel. Messages remain in the database but the channel is hidden. Organization admins can unarchive via update_stream. Irreversible from the API side without admin recovery. - **GET** `get_stream_topics` — List topics in a channel, ordered by recency (most recent first). Returns array of {name, max_id (last message ID)}. The user must have access to the channel. - **GET** `get_subscribers` — List user IDs subscribed to a channel. Returns array of integers. - **POST** `delete_topic` — Delete an entire topic and all its messages. Admin-only. Processes in batches — the response contains 'complete' (boolean); if false, RETRY the same call until complete=true. - **GET** `get_subscription_status` — Check whether a specific user is subscribed to a specific channel. Returns {is_subscribed}. - **GET** `get_stream_email_address` — Get the email address that, when emailed, posts to a channel. Used for email integrations. - **GET** `get_subscriptions` — List channels the current user/bot is subscribed to, with all subscription-specific settings (notifications, color, pin, mute). include_subscribers='partial' returns subscribers only for bots and recently-active users (faster for big orgs). - **POST** `create_or_subscribe` — Subscribe one or more users to one or more channels. CREATES channels that don't yet exist (this is the only way to create a channel via the API). principals is a JSON array of user IDs or emails — omit to subscribe yourself. - **DELETE** `unsubscribe` — Unsubscribe one or more users from channels. principals defaults to the current user. Cannot remove admins from public channels they administer. - **POST** `update_subscription_settings` — Update per-channel subscription preferences (color, pin_to_top, audible_notifications, desktop_notifications, push_notifications, email_notifications, is_muted, in_home_view). subscription_data is a JSON array of {stream_id, property, value} objects. - **GET** `get_users` — List all users in the organization. Returns array of user objects with id, email, full_name, is_bot, is_active, role, avatar_url, timezone, date_joined. - **GET** `get_user` — Get one user by numeric ID. Preferred over get_user_by_email because email can change. - **GET** `get_user_by_email` — Get one user by email address. Email can be the real address or the dummy user{id}@{host} form. - **GET** `get_own_user` — Get the currently authenticated user (or bot). Returns identity, role, custom profile data, and account flags. The simplest test that auth is configured correctly. - **POST** `create_user` — Create a new user. Admin-only. The new user receives an email to set their password unless full_name and password are pre-set. - **PATCH** `update_user` — Update a user's profile or role. Admins can change role and custom fields; users can update their own profile via this endpoint too (some fields). - **DELETE** `deactivate_user` — Deactivate a user. They can no longer log in or use the API. Their messages remain. Reversible via reactivate_user. - **POST** `reactivate_user` — Reactivate a previously deactivated user. Admin only. - **GET** `get_user_presence` — Get a single user's current presence (active/idle, last update timestamp). Path accepts either user ID or email. - **GET** `get_realm_presence` — Get presence for all users the current user can access. Returns server_timestamp and presences keyed by email. - **POST** `update_presence` — Update the current user's presence (active/idle/offline). Most clients call this every minute while open. - **GET** `get_user_status` — Get a user's custom status (status_text, emoji, away flag). - **POST** `update_status` — Set your own custom status — a short text + optional emoji. Pass empty status_text to clear. - **POST** `regenerate_own_api_key` — Generate a new API key for the authenticated user. Returns {api_key}. WARNING: the old key stops working immediately and all devices using it (including this connection) must be re-authenticated. Use sparingly. - **PATCH** `update_own_settings` — Update the authenticated user's own preferences (display, notifications, behavior, privacy). Pass only the fields you want to change. Admins can also use target_users to bulk-update settings for others (Zulip 12.0+). - **GET** `get_user_groups` — List all user groups in the organization. Returns array of group objects with id, name, description, members (user IDs), direct_subgroup_ids, deactivated. - **POST** `create_user_group` — Create a new user group with an initial set of members. can_*_group fields accept a JSON-encoded group ID or 'role:everyone'/'role:members' etc. - **PATCH** `update_user_group` — Update a user group's name, description, or permission settings. Admin-only or has_manage permission. - **DELETE** `deactivate_user_group` — Deactivate (soft-delete) a user group. The group remains in the database but is hidden. Cannot deactivate system groups. - **POST** `update_user_group_members` — Add or remove members from a user group. Pass JSON arrays of user IDs for 'add' and 'delete'. - **POST** `update_user_group_subgroups` — Add or remove nested subgroups from a user group. Pass JSON arrays of group IDs. - **GET** `get_user_group_members` — List all member user IDs of a group. Set direct_member_only=true to exclude transitively-included members from subgroups. - **POST** `mute_user` — Mute another user from the current user's perspective. Messages sent by muted users are automatically marked as read and hidden in the UI. Mute state is per-user — only affects the calling account. There is no dedicated "list muted users" endpoint; the current list is delivered via the muted_users key in register_queue fetch. - **DELETE** `unmute_user` — Unmute a previously muted user. Returns an error if the user is not currently muted. - **POST** `update_user_topic_visibility` — Set the current user's visibility policy for a specific channel + topic. This is the modern replacement for the deprecated /users/me/subscriptions/muted_topics endpoint. Supports both muting (hide notifications) and following (boost notifications), plus unmute and reset. - **GET** `get_alert_words` — Get the current user's configured alert words. Alert words trigger a notification when they appear in any message visible to the user. Case-insensitive, max 100 chars per word. - **POST** `add_alert_words` — Add one or more alert words. alert_words is a JSON-encoded array of strings, e.g. '["deploy","incident"]'. - **DELETE** `remove_alert_words` — Remove one or more alert words. alert_words is a JSON-encoded array of strings to remove. Returns the remaining alert words. - **GET** `get_drafts` — Get all drafts saved by the current user (ordered by most recently edited). - **POST** `create_drafts` — Create one or more drafts. drafts is a JSON array of draft objects: {type, to, topic, content, timestamp}. - **PATCH** `edit_draft` — Replace an existing draft's contents. - **DELETE** `delete_draft` — Delete a draft permanently. - **GET** `get_saved_snippets` — List the current user's saved snippets — reusable text fragments (e.g. canned responses, command incantations, KB-style notes). Returns array of {id, title, content, date_created}. - **POST** `create_saved_snippet` — Create a saved snippet. Returns {saved_snippet_id}. - **PATCH** `edit_saved_snippet` — Edit a saved snippet's title or content. - **DELETE** `delete_saved_snippet` — Permanently delete a saved snippet. - **GET** `get_scheduled_messages` — List the current user's pending scheduled messages, ordered by delivery time. - **POST** `create_scheduled_message` — Schedule a message for later delivery. scheduled_delivery_timestamp is a UNIX timestamp in UTC seconds. - **PATCH** `update_scheduled_message` — Update a pending scheduled message. Can change content, topic, recipients, or scheduled time. Pass only the fields you want to change. - **DELETE** `delete_scheduled_message` — Cancel a pending scheduled message before it is delivered. - **POST** `register_queue` — Register an event queue and fetch initial state. The server returns queue_id, last_event_id, and snapshots of requested data. Use get_events to long-poll for new events. Always call delete_queue when finished — queues consume server resources. event_types and fetch_event_types are JSON-encoded arrays of strings. - **GET** `get_events` — Long-poll for new events on a registered queue. queue_id from register_queue. last_event_id is the highest event ID already processed (-1 for first call). dont_block=true returns immediately (possibly with empty events). Default behavior blocks up to ~10 minutes. - **DELETE** `delete_queue` — Delete a previously registered event queue. Always call this when done with register_queue to free server resources. - **POST** `send_invites` — Send email invitations to join the organization. invite_as: 100=owner, 200=admin, 300=moderator, 400=member (default), 600=guest. stream_ids is a JSON array of channels to auto-subscribe. Requires admin role typically. - **POST** `create_multi_use_invite_link` — Create a reusable invite link that anyone can use to join the org. Returns {invite_link}. - **GET** `list_invites` — List pending email and multi-use invitations. - **POST** `resend_invite` — Resend the invitation email for a pending email invitation. - **DELETE** `revoke_invite` — Revoke a pending email invitation. - **DELETE** `revoke_multi_use_invite` — Revoke a multi-use invite link. - **POST** `upload_file` — Upload a file. Pass file as a file_url — ToolMesh will fetch and forward it as multipart. Response includes a relative url like /user_uploads/1/4e/.../filename. To share, embed in a message as [name](url). For files >25MB use the tus resumable upload endpoint (not modeled). - **GET** `get_attachments` — List the current user's uploaded attachments. Returns {attachments: [...], upload_space_used}. - **DELETE** `delete_attachment` — Delete an uploaded attachment by ID. The file is removed from storage; messages referencing it will show a broken link. - **GET** `get_server_settings` — Get public server configuration including zulip_version, zulip_feature_level, available auth methods, and realm branding. Works WITHOUT authentication — useful for discovery. - **GET** `get_realm_linkifiers` — List linkifiers (regex → URL template rules) configured for the realm. Clients should process them in order. Returns array of {pattern, url_template, id, example_input, ...}. - **GET** `get_custom_emoji` — Get all custom emoji defined in the realm. Returns map of emoji_id → {id, name, source_url, still_url, deactivated, author_id}. - **DELETE** `deactivate_custom_emoji` — Deactivate (hide) a realm custom emoji. The image data remains but the emoji is no longer selectable. - **POST** `upload_custom_emoji` — Upload a new custom emoji to the realm. emoji_name allows letters/digits/dashes/spaces. File goes in the request body as form data. Server limits file size (default 5 MB) and accepts common image/gif formats. - **PATCH** `update_realm` — Update org-wide (realm) settings. Admin/owner only. Only fields you pass are changed. Setting target_users on the related update_own_settings is for per-user defaults; this endpoint changes org-wide policy. The full realm settings surface is ~80 fields; the most commonly-tuned ones are exposed here. For uncommon fields, pass via this same endpoint. - **PATCH** `update_realm_user_settings_defaults` — Update the default per-user settings applied to newly-created accounts in the realm. Does NOT change settings of existing users. Admin/owner only. - **POST** `add_linkifier` — Add a new linkifier (regex → URL template). Used to auto-link ticket IDs like 'JIRA-1234', commit hashes, internal references, etc. url_template uses RFC 6570 with named variables captured from the regex (e.g. '{ticket_id}'). - **PATCH** `update_linkifier` — Update an existing linkifier's pattern, template, or auxiliary fields. Pass only fields to change. - **DELETE** `remove_linkifier` — Delete a linkifier. Existing messages keep their rendered links but new messages won't auto-link this pattern. - **PATCH** `reorder_linkifiers` — Reorder linkifiers. Order matters when patterns overlap — earlier wins. Pass a JSON array of all linkifier IDs in the desired order. - **GET** `get_custom_profile_fields` — List custom profile fields configured for the realm. Returns array of {id, type, name, hint, field_data, order, ...}. Field types: 1=short text, 2=paragraph, 3=dropdown, 4=date, 5=link, 6=users, 7=external account, 8=pronouns. - **POST** `create_custom_profile_field` — Create a new custom profile field that users can fill in their profile. field_data is type-specific JSON (e.g. choices for dropdown). - **PATCH** `update_custom_profile_field` — Update a custom profile field. Cannot change field_type after creation. - **DELETE** `delete_custom_profile_field` — Delete a custom profile field. All user values for this field are lost. Cannot be undone. - **PATCH** `reorder_custom_profile_fields` — Reorder custom profile fields. Pass a JSON array of field IDs in the desired display order. - **POST** `add_realm_playground` — Add a code playground integration — clicking the "View in playground" button on a code block of the matching language opens the code in an external editor (e.g. play.rust-lang.org). url_template must contain exactly one `{code}` variable. - **DELETE** `remove_realm_playground` — Remove a code playground integration. - **POST** `add_realm_domain` — Add an email domain to the org's allowed-signup list (only effective when realm setting emails_restricted_to_domains=true). Use to lock self-signup to your company domain. - **PATCH** `update_realm_domain` — Toggle allow_subdomains on an existing realm domain entry. - **DELETE** `remove_realm_domain` — Remove an email domain from the allowed-signup list. - **POST** `add_default_stream` — Mark a channel as a default channel — new users are auto-subscribed on signup (unless include_realm_default_subscriptions is overridden in the invite). - **DELETE** `remove_default_stream` — Remove a channel from the realm's default channel list. Existing subscribers are not affected. - **GET** `get_bots` — List bots owned by the current user. Returns array of {user_id, username, full_name, api_key, default_sending_stream, default_events_register_stream, default_all_public_streams, avatar_url, services}. IMPORTANT: this endpoint and the other /bots endpoints are for HUMAN accounts only — bot accounts cannot list/manage other bots (Zulip returns 'This endpoint does not accept bot requests'). Connect with a human user's API key to manage bots. - **POST** `create_bot` — Create a new bot owned by the current user. bot_type: 1=Generic, 2=Incoming webhook, 3=Outgoing webhook, 4=Embedded. Generic is the most flexible. - **PATCH** `update_bot` — Update settings of a bot owned by the current user (or any bot, for admins). - **POST** `regenerate_bot_api_key` — Generate a new API key for one of your bots. Old key stops working immediately. - **DELETE** `deactivate_bot` — Deactivate (delete) a bot owned by the current user. Reversible by re-activating the bot user. ## What composite workflows does the Zulip DADL provide? - **FN** `send_channel_message` — Convenience wrapper around send_message for the common case of posting to a channel topic. Pass channel_name OR stream_id (one is required) plus topic and content. - **FN** `search_messages` — Search for messages by free-text query, optionally within a channel and/or topic. Returns up to `limit` matching messages, newest first. Wraps get_messages with a constructed narrow. - **FN** `get_recent_in_topic` — Get the N most recent messages in a specific channel + topic. Convenience wrapper around get_messages with a channel+topic narrow anchored at 'newest'. - **FN** `mark_all_in_channel_read` — Mark every unread message in a channel as read (preferred replacement for mark_stream_as_read). - **FN** `search_users` — Find users by a prefix match on full_name or email (Zulip has no dedicated user-search endpoint, so this fetches the org user list and filters client-side). Bots and inactive users are excluded by default. - **FN** `daily_summary` — Build a digest of unread message activity for the authenticated user — total unread count, breakdown by channel, top topics, and DM senders. Uses get_messages with an is:unread narrow; for very busy accounts, raise `max_scan` (Zulip caps at 5000 per request). ## Which DADLs are related to Zulip? - [Zammad](https://www.dadl.ai/d/zammad/) — Zammad helpdesk REST API -- tickets, articles, users, organizations, groups, roles, knowledge base, SLAs, calendars, object manager (custom fields), macros, triggers, overviews, reports, time accounting, and full admin surface. Supports X-On-Behalf-Of impersonation on every endpoint. - [Billomat](https://www.dadl.ai/d/billomat/) — Billomat REST API — German cloud invoicing & accounting: invoices, estimates, credit notes, recurring invoices, delivery notes, order confirmations, dunning reminders, clients, contacts, articles, payments, expenses, taxes - [Checkmk](https://www.dadl.ai/d/checkmk/) — Checkmk REST API (version 1.0, Checkmk 2.4) -- live host and service status via Livestatus queries, downtimes, acknowledgements and comments, the Event Console (list, acknowledge, change state and archive events) and BI (packs, rules, aggregations and live aggregation state), plus the full Setup side: hosts, clusters, folders, service discovery, rules and rulesets, host/service/contact groups, users, roles, passwords, time periods, host tags, notification rules, site connections and change activation. - [Graylog](https://www.dadl.ai/d/graylog/) — Graylog REST API -- log search (Views/Search + legacy universal), streams, pipelines, inputs, alerts, events, dashboards, users, roles, sidecars, index management, and cluster administration. Targets Graylog 6.x. - [Hacker News](https://www.dadl.ai/d/hackernews/) — Hacker News API — read-only access to stories, comments, polls, jobs, users, and live feeds from news.ycombinator.com - [Mempool](https://www.dadl.ai/d/mempool/) — mempool.space — Bitcoin block explorer, mempool visualizer, fee estimator, Lightning Network explorer, and transaction accelerator --- **Canonical URL:** https://www.dadl.ai/d/zulip/ **Raw DADL:** https://github.com/DunkelCloud/dadl-registry/blob/main/zulip.dadl ---