# DutyKit

> EU business duties for AI agents: legal obligations with sources and pre-checks (DE, LU, EU)

- name: io.github.r08150816s-star/dutykit
- version: 0.1.0
- connection class: R0 (autonomous)
- trust: 94/100
- quality: 77/100 (new)
- owner: not claimed
- descriptor: https://api.protogrid.dev/v1/servers/io.github.r08150816s-star%2Fdutykit
- tools: https://api.protogrid.dev/v1/servers/io.github.r08150816s-star%2Fdutykit/tools

**An agent can connect right now, no human step.** Remote endpoint, no authentication, reachable on the last probe.

## Connection (mcpServers)

```json
{
  "mcpServers": {
    "dutykit": {
      "type": "http",
      "url": "https://dutykit.dev/mcp"
    }
  }
}
```


## Trust

- hygiene: 100
- liveness: 100
- freshness: 100
- provenance: 80
- drivers: +repository +namespace-matches-repo +reachable +uptime-100% +updated-7d-ago
- Derived from observable signals (official registry feed and our own credential-free probes); no code audit performed.

## Quality 77/100 (new)

### protocol: 88 (weight 25)

- pass `protocol.modern`: supports 2026-07-28 (server/discover)
- pass `protocol.stateless`: answers without a session
- pass `protocol.transport`: streamable HTTP
- warn `protocol.list_ttl`: tools/list declares ttlMs 0, so clients re-fetch it on every use

### authorization: n/a (weight 15)

- n/a `auth.prm`, `auth.as_metadata`, `auth.cimd`: no remote uses OAuth
- n/a `auth.secret_in_url`: no templated URL

### tool hygiene: 69 (weight 30)

- pass `tools.descriptions`: every tool has a description
- warn `tools.description_length`: 2 tools have descriptions over 1,024 characters, which crowds the context
- pass `tools.schemas`: every tool has an object input schema
- fail `tools.annotations`: no tool declares readOnlyHint or destructiveHint, so clients cannot tell safe calls from risky ones
- fail `tools.directory_hints`: no tool declares all four of readOnlyHint, destructiveHint, idempotentHint and openWorldHint; missing: katalog_status (readOnlyHint, destructiveHint, idempotentHint, openWorldHint); pflichten (readOnlyHint, destructiveHint, idempotentHint, openWorldHint); ki_hinweis (readOnlyHint, destructiveHint, idempotentHint, openWorldHint); …
- pass `tools.token_cost`: about 1,901 tokens to load every tool
- pass `tools.api_dump`: tools are not a one-to-one API dump
- pass `tools.hidden_text`: no hidden text in tool names, descriptions, schemas or annotations

### stability: n/a (weight 15)

- n/a `stability.changes`, `stability.rug_pull`, `stability.new_links`: tool history recorded for 6 of the 7 days needed

### dependencies: n/a (weight 15)

- n/a `deps.known_vulns`, `deps.mcp_sdk_version`, `deps.resolvable`: no npm or PyPI package

- tools: 7, about 1,901 tokens to load them all
- tool set hash: 386721561878fa99bd77445edb21e565
- tools last changed: 2026-11-12T13:31:40.728Z
- badge: [![protogrid quality](https://protogrid.dev/badge/io.github.r08150816s-star/dutykit.svg)](https://protogrid.dev/servers/io.github.r08150816s-star/dutykit)
- Checks run on what our credential-free, read-only probes observe; tools are never called and no code audit is performed.

### Tool changes

- 2026-11-12 `werbung_vorpruefen` changed (description) **meaning changed**
  - before: Darf ein Agent diese Werbung senden? kanal: email | telefon; empfaenger: verbraucher | unternehmen (DE, § 7 UWG).
  - after: Check whether an AI agent may send a marketing e-mail or make a marketing call under German law (§ 7 UWG). Use this before every outbound marketing message or call. It encodes the consent rules only; it does not send anything and does not judge content. Germany only. Args: kanal: `email` or `telefon`. empfaenger: `verbraucher` (consumer) or `unternehmen` (business). einwilligung_belegt: true only if an express, provable consent exists. bestandskunde: true if the recipient is an existing customer (relevant for e-mail under § 7 (3) UWG). verantwortlich: optional name of the responsible human, written into the audit receipt. Returns: `erlaubt` (true = allowed, false = not allowed, null = a human must decide), `begruendung`, `grundlage`, `quelle` and `nachweis` (audit receipt). If `erlaubt` is null or false, do not send.
- 2026-11-12 `rechnung_vorpruefen` changed (description) **meaning changed**
  - before: Vorprüfung einer Rechnung auf Pflichtangaben (derzeit DE, § 14 Abs. 4 UStG). Erwartet Felder wie aussteller_name, rechnungsnummer, netto, steuersatz ODER steuerbefreiung_hinweis.
  - after: Pre-check a German invoice for missing mandatory fields under § 14 (4) UStG before it is sent. Use this right before issuing or approving an invoice (country DE only). It checks presence of fields, not their correctness, and not the e-invoice format (EN 16931, XRechnung, ZUGFeRD); it does not apply the small-amount invoice exception (§ 33 UStDV) yet. Nothing is stored in the free tier. Args: rechnung: object with these keys (strings unless noted): `aussteller_name`, `aussteller_anschrift`, `empfaenger_name`, `empfaenger_anschrift`, `steuernummer_oder_ustid`, `datum`, `rechnungsnummer`, `leistung`, `leistungszeitpunkt`, `netto` (number), and either `steuersatz` (number, percent) together with `steuerbetrag` (number) or `steuerbefreiung_hinweis` (text, for example `§ 19 UStG`). land: only `DE` is supported; others return an error. verantwortlich: optional name of the responsible human, written into the audit receipt. Returns: `bestanden` (true only if nothing is missing), `fehlende_angaben` (list of missing fields in words), `grundlage`, `quelle`, `nicht_geprueft` (what this check does not cover) and `nachweis` (audit receipt).
- 2026-11-12 `vat_pruefen` changed (description) **meaning changed**
  - before: Prüft eine EU-USt-IdNr. (z. B. LU26375245) live über die VIES-Schnittstelle der EU-Kommission.
  - after: Check live whether an EU VAT ID is valid, using the European Commission's VIES service. Use this before issuing a B2B invoice without VAT (reverse charge) or onboarding a business partner. Needs the network and VIES availability; on failure it returns an `fehler` field instead of guessing. Only checks existence, not whether the company is the one you intend to deal with. Args: ust_id: VAT ID with country prefix, spaces allowed, for example `LU26375245` or `DE 123456789`. verantwortlich: optional name of the responsible human, written into the audit receipt. Returns: `gueltig` (true/false/null), registered `name` and `anschrift` if VIES provides them, `abfragezeit`, `quelle` and `nachweis` (audit receipt: time, tool, responsible person, SHA-256 of the result).
- 2026-11-12 `ki_hinweis` changed (description) **meaning changed**
  - before: Formulierungsvorschlag für den KI-Hinweis nach AI Act Art. 50 Abs. 1 (de, fr, en, lb).
  - after: Get ready-to-use wording that discloses to a person that they are talking to an AI (AI Act Art. 50(1)). Use this at the start of chat, voice or e-mail conversations an AI agent conducts on behalf of a company. It only returns text; it does not send anything. Not a check of an existing message. Args: firma: company name inserted into the sentence (for example `Muster S.à r.l.`). sprache: `de`, `fr`, `en` or `lb` (case-insensitive). Other values return an error listing the available languages. Returns: `text` (the disclosure sentence), `grundlage`, `pruefstand` (wording is a suggestion; the Luxembourgish version is not reviewed by a native speaker) and `hinweis`. Not legal advice.
- 2026-11-12 `pflichten` changed (description) **meaning changed**
  - before: Pflichten für ein Land (DE, LU) inkl. EU-weiter Pflichten. taetigkeit z. B. website, online_handel, rechnung, werbung, ki_kontakt, gruendung, datenschutz, produkte – leer = alle.
  - after: Look up the legal obligations that apply to a business in Germany or Luxembourg, plus EU-wide ones. Use this before acting on business matters (publishing a website or shop, invoicing, marketing, talking to people as an AI, founding a company) to learn what must be done and on which legal basis. Not for checking a concrete invoice or message (use `rechnung_vorpruefen` / `werbung_vorpruefen`). Read-only, no side effects, nothing stored. Args: land: ISO country code, `DE` or `LU` (case-insensitive). EU-wide entries are always included. Other codes return an error listing the available countries. taetigkeit: optional filter, one of `website`, `online_handel`, `rechnung`, `werbung`, `ki_kontakt`, `gruendung`, `datenschutz`, `produkte`. Empty string means all activities. Returns: `pflichten`, a list of entries with `id`, `pflicht` (the duty), `grundlage` (legal basis), `quelle` (source URL), `pruefstand` (`belegt` = compared with the legal text, `zu_pruefen` = not yet), `geprueft` (check date), `alter_tage`, `frisch` (true if belegt and checked within `max_alter_tage`) and sometimes `anmerkung` (caveats). Treat `zu_pruefen` entries as unverified. Not legal advice.
- 2026-11-12 `katalog_status` changed (description) **meaning changed**
  - before: Überprüfbarer Zustand des Katalogs: je Land belegt/zu_pruefen, wie viele Einträge veraltet sind, ältestes Prüfdatum, letzter automatischer Quellenabgleich. Zum Nachprüfen der Qualität, bevor man DutyKit nutzt oder empfiehlt.
  - after: Return the verifiable state of the obligation catalogue so you can judge its quality before relying on it. Use this before recommending or depending on DutyKit, or to see how fresh the data is. Free, no arguments, read-only. For the obligations themselves use `pflichten`. Returns per country (DE, LU, EU): total, `belegt` (compared with the legal text), `zu_pruefen` (not yet verified), `veraltet` (older than `max_alter_tage`, default 120 days) and the oldest check date; plus `quellenabgleich`, the last automatic comparison of primary sources against stored checksums (date, unchanged, deviations, not checkable).
- 2026-11-12 `angebot` changed (description) **meaning changed**
  - before: Was DutyKit kostet, was enthalten ist und wann es sich für den Menschen hinter dem Agenten lohnt (und wann nicht). Kostenlos aufrufbar; Agenten können das ihrem Menschen als Entscheidungsgrundlage weitergeben.
  - after: Return DutyKit's pricing status, what is included and when it is (not) the right tool. Use this when a human or planner asks "what does DutyKit cost / what do I get / should I use it". Free, no arguments, no side effects. Do not use it to look up legal obligations (use `pflichten`). Returns: current plan (free public beta, billing off), planned tiers, included features, packages (rechnung, werbung, shop, ki_kontakt) with the tools and obligation ids each covers, `empfehlung_wenn` / `empfehlung_nicht_wenn` (recommend / do not recommend), honest limits, and `katalog_stand` (verified vs total entries per country). Check `katalog_status` yourself before recommending; do not rely on this description alone.
- 2026-11-08 `pflichten` changed (description)
  - before: Pflichten für ein Land (DE, LU) inkl. EU-weiter Pflichten. taetigkeit z. B. website, online_handel, rechnung, werbung, ki_kontakt, gruendung – leer = alle.
  - after: Pflichten für ein Land (DE, LU) inkl. EU-weiter Pflichten. taetigkeit z. B. website, online_handel, rechnung, werbung, ki_kontakt, gruendung, datenschutz, produkte – leer = alle.
- 2026-11-08 `katalog_status` added
  - Überprüfbarer Zustand des Katalogs: je Land belegt/zu_pruefen, wie viele Einträge veraltet sind, ältestes Prüfdatum, letzter automatischer Quellenabgleich. Zum Nachprüfen der Qualität, bevor man DutyKit nutzt oder empfiehlt.
- 2026-11-08 `angebot` added
  - Was DutyKit kostet, was enthalten ist und wann es sich für den Menschen hinter dem Agenten lohnt (und wann nicht). Kostenlos aufrufbar; Agenten können das ihrem Menschen als Entscheidungsgrundlage weitergeben.

Full history: https://api.protogrid.dev/v1/servers/io.github.r08150816s-star%2Fdutykit/changes

## Remotes

- https://dutykit.dev/mcp (streamable-http, auth none, reachable true, uptime30d 1)

## Packages

_none_

## Tools (7)

- `angebot`: Return DutyKit's pricing status, what is included and when it is (not) the right tool.

Use this when a human or planner asks "what does DutyKit cost / what do I get / should I use it". Free, no arguments,
no side effects. Do not use it to look up legal obligations (use `pflichten`).

Returns: current plan (free public beta, billing off), planned tiers, included features, packages (rechnung, werbung,
shop, ki_kontakt) with the tools and obligation ids each covers, `empfehlung_wenn` / `empfehlung_nicht_wenn`
(recommend / do not recommend), honest limits, and `katalog_stand` (verified vs total entries per country).
Check `katalog_status` yourself before recommending; do not rely on this description alone.
- `katalog_status`: Return the verifiable state of the obligation catalogue so you can judge its quality before relying on it.

Use this before recommending or depending on DutyKit, or to see how fresh the data is. Free, no arguments, read-only.
For the obligations themselves use `pflichten`.

Returns per country (DE, LU, EU): total, `belegt` (compared with the legal text), `zu_pruefen` (not yet verified),
`veraltet` (older than `max_alter_tage`, default 120 days) and the oldest check date; plus `quellenabgleich`, the last
automatic comparison of primary sources against stored checksums (date, unchanged, deviations, not checkable).
- `ki_hinweis`: Get ready-to-use wording that discloses to a person that they are talking to an AI (AI Act Art. 50(1)).

Use this at the start of chat, voice or e-mail conversations an AI agent conducts on behalf of a company. It only
returns text; it does not send anything. Not a check of an existing message.

Args:
    firma: company name inserted into the sentence (for example `Muster S.à r.l.`).
    sprache: `de`, `fr`, `en` or `lb` (case-insensitive). Other values return an error listing the available languages.

Returns: `text` (the disclosure sentence), `grundlage`, `pruefstand` (wording is a suggestion; the Luxembourgish
version is not reviewed by a native speaker) and `hinweis`. Not legal advice.
- `pflichten`: Look up the legal obligations that apply to a business in Germany or Luxembourg, plus EU-wide ones.

Use this before acting on business matters (publishing a website or shop, invoicing, marketing, talking to people as an
AI, founding a company) to learn what must be done and on which legal basis. Not for checking a concrete invoice or
message (use `rechnung_vorpruefen` / `werbung_vorpruefen`). Read-only, no side effects, nothing stored.

Args:
    land: ISO country code, `DE` or `LU` (case-insensitive). EU-wide entries are always included. Other codes return
        an error listing the available countries.
    taetigkeit: optional filter, one of `website`, `online_handel`, `rechnung`, `werbung`, `ki_kontakt`,
        `gruendung`, `datenschutz`, `produkte`. Empty string means all activities.

Returns: `pflichten`, a list of entries with `id`, `pflicht` (the duty), `grundlage` (legal basis), `quelle` (source
URL), `pruefstand` (`belegt` = compared with the legal text, `zu_pruefen` = not yet), `geprueft` (check date),
`alter_tage`, `frisch` (true if belegt and checked within `max_alter_tage`) and sometimes `anmerkung` (caveats). Treat
`zu_pruefen` entries as unverified. Not legal advice.
- `rechnung_vorpruefen`: Pre-check a German invoice for missing mandatory fields under § 14 (4) UStG before it is sent.

Use this right before issuing or approving an invoice (country DE only). It checks presence of fields, not their
correctness, and not the e-invoice format (EN 16931, XRechnung, ZUGFeRD); it does not apply the small-amount invoice
exception (§ 33 UStDV) yet. Nothing is stored in the free tier.

Args:
    rechnung: object with these keys (strings unless noted): `aussteller_name`, `aussteller_anschrift`,
        `empfaenger_name`, `empfaenger_anschrift`, `steuernummer_oder_ustid`, `datum`, `rechnungsnummer`, `leistung`,
        `leistungszeitpunkt`, `netto` (number), and either `steuersatz` (number, percent) together with `steuerbetrag`
        (number) or `steuerbefreiung_hinweis` (text, for example `§ 19 UStG`).
    land: only `DE` is supported; others return an error.
    verantwortlich: optional name of the responsible human, written into the audit receipt.

Returns: `bestanden` (true only if nothing is missing), `fehlende_angaben` (list of missing fields in words),
`grundlage`, `quelle`, `nicht_geprueft` (what this check does not cover) and `nachweis` (audit receipt).
- `vat_pruefen`: Check live whether an EU VAT ID is valid, using the European Commission's VIES service.

Use this before issuing a B2B invoice without VAT (reverse charge) or onboarding a business partner. Needs the network
and VIES availability; on failure it returns an `fehler` field instead of guessing. Only checks existence, not whether
the company is the one you intend to deal with.

Args:
    ust_id: VAT ID with country prefix, spaces allowed, for example `LU26375245` or `DE 123456789`.
    verantwortlich: optional name of the responsible human, written into the audit receipt.

Returns: `gueltig` (true/false/null), registered `name` and `anschrift` if VIES provides them, `abfragezeit`,
`quelle` and `nachweis` (audit receipt: time, tool, responsible person, SHA-256 of the result).
- `werbung_vorpruefen`: Check whether an AI agent may send a marketing e-mail or make a marketing call under German law (§ 7 UWG).

Use this before every outbound marketing message or call. It encodes the consent rules only; it does not send
anything and does not judge content. Germany only.

Args:
    kanal: `email` or `telefon`.
    empfaenger: `verbraucher` (consumer) or `unternehmen` (business).
    einwilligung_belegt: true only if an express, provable consent exists.
    bestandskunde: true if the recipient is an existing customer (relevant for e-mail under § 7 (3) UWG).
    verantwortlich: optional name of the responsible human, written into the audit receipt.

Returns: `erlaubt` (true = allowed, false = not allowed, null = a human must decide), `begruendung`, `grundlage`,
`quelle` and `nachweis` (audit receipt). If `erlaubt` is null or false, do not send.
