Skip to content

Commit 4cb7e5d

Browse files
committed
feat: SKR04 mapping, credit note reasons, audit prompt — 15 resources, 10 prompts
- Add einvoice://reference/skr04-mapping: 14 common invoice categories mapped to SKR04 accounts (DATEV standard chart of accounts) - Add einvoice://reference/credit-note-reasons: 8 standardized credit note/correction reason codes with German descriptions and legal refs - Add steuerprüfung_checkliste prompt: GoBD-compliant audit preparation checklist covering archiving, mandatory fields, VAT, corrections - 537 tests, 2011 stmts, 100% coverage, ruff + mypy strict clean
1 parent 33b835f commit 4cb7e5d

4 files changed

Lines changed: 299 additions & 5 deletions

File tree

CHANGELOG.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ All notable changes to the einvoice-mcp project.
1414
- `einvoice_parse` — Parse XML/PDF into structured data
1515
- `einvoice_check_compliance` — Mandatory field checks with German suggestions
1616

17-
#### MCP Resources (13)
17+
#### MCP Resources (15)
1818
- `einvoice://schemas/line-item` — JSON schema for line items
1919
- `einvoice://schemas/allowance-charge` — JSON schema for allowances/charges
2020
- `einvoice://schemas/item-attribute` — JSON schema for item attributes (BG-30)
@@ -28,8 +28,10 @@ All notable changes to the einvoice-mcp project.
2828
- `einvoice://system/kosit-status` — On-demand KoSIT validator health check
2929
- `einvoice://reference/e-rechnung-pflichten` — E-Rechnungspflichten Zeitplan 2020–2028
3030
- `einvoice://reference/br-de-rules` — Deutsche Geschäftsregeln (BR-DE) Referenz
31+
- `einvoice://reference/skr04-mapping` — SKR04 Kontenzuordnung (DATEV)
32+
- `einvoice://reference/credit-note-reasons` — Gutschrift-Gründe und Korrektur-Codes
3133

32-
#### MCP Prompts (9)
34+
#### MCP Prompts (10)
3335
- `gutschrift_erstellen` — Credit note (381) creation guide
3436
- `reverse_charge_checkliste` — Reverse charge (§13b UStG) checklist
3537
- `xrechnung_schnellstart` — XRechnung quick start for public procurement
@@ -39,6 +41,7 @@ All notable changes to the einvoice-mcp project.
3941
- `handwerkerrechnung_35a` — Craftsman invoice for §35a EStG tax deduction
4042
- `typecode_entscheidungshilfe` — TypeCode decision tree (which code for which scenario)
4143
- `b2b_pflicht_2027` — B2B e-invoice mandate preparation checklist
44+
- `steuerprüfung_checkliste` — Tax audit readiness checklist (GoBD, §147 AO)
4245

4346
#### EN 16931 Business Terms
4447
- BT-1..5 — Invoice number, date, type code, currency
@@ -118,4 +121,4 @@ All notable changes to the einvoice-mcp project.
118121
- Deployment guide (docs/DEPLOYMENT.md)
119122
- UBL format detection (rejects UBL with clear German error)
120123
- Pydantic validation errors with BT number references
121-
- 534 tests, 100% coverage (2011 stmts), ruff + mypy strict clean
124+
- 537 tests, 100% coverage (2011 stmts), ruff + mypy strict clean

README.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
[![CI](https://github.com/Mavengence/einvoice-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/Mavengence/einvoice-mcp/actions/workflows/ci.yml)
44
[![Python 3.11+](https://img.shields.io/badge/python-3.11%2B-blue.svg)](https://www.python.org/downloads/)
55
[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)
6-
[![Tests](https://img.shields.io/badge/tests-534%20passed-brightgreen.svg)](#compliance-proof)
6+
[![Tests](https://img.shields.io/badge/tests-537%20passed-brightgreen.svg)](#compliance-proof)
77
[![Coverage](https://img.shields.io/badge/coverage-100%25-brightgreen.svg)](#module-coverage)
88

99
**MCP-Server for German e-invoice compliance — XRechnung 3.0 & ZUGFeRD 2.x**
@@ -20,7 +20,7 @@ Germany mandated e-invoice reception for B2B as of January 2025 (BMF 2024-11-15)
2020

2121
## Compliance Proof
2222

23-
**534 tests | 100% coverage (2011 stmts) | 0 failures | lint clean (ruff + mypy strict)**
23+
**537 tests | 100% coverage (2011 stmts) | 0 failures | lint clean (ruff + mypy strict)**
2424

2525
*Run `make test` to verify.*
2626

@@ -301,6 +301,8 @@ Every mandatory Business Term is tested in generated XML output:
301301
| `einvoice://system/kosit-status` | On-demand KoSIT-Validator Statusabfrage |
302302
| `einvoice://reference/e-rechnung-pflichten` | Zeitplan E-Rechnungspflichten 2020–2028 mit Rechtsgrundlagen |
303303
| `einvoice://reference/br-de-rules` | Deutsche Geschäftsregeln (BR-DE-1..24) mit Lösungshinweisen |
304+
| `einvoice://reference/skr04-mapping` | SKR04-Kontenzuordnung für häufige Rechnungsarten (DATEV) |
305+
| `einvoice://reference/credit-note-reasons` | Gutschrift-Gründe und Korrektur-Codes mit Empfehlungen |
304306

305307
### MCP Prompts
306308

@@ -315,6 +317,7 @@ Every mandatory Business Term is tested in generated XML output:
315317
| `handwerkerrechnung_35a` | Handwerkerrechnung nach §35a EStG |
316318
| `typecode_entscheidungshilfe` | Entscheidungshilfe: Welcher TypeCode für welchen Anlass? |
317319
| `b2b_pflicht_2027` | Checkliste: B2B E-Rechnungspflicht ab 2027 vorbereiten |
320+
| `steuerprüfung_checkliste` | E-Rechnungen für Betriebsprüfung vorbereiten (GoBD, §147 AO) |
318321

319322
---
320323

src/einvoice_mcp/server.py

Lines changed: 241 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,247 @@ def br_de_rules() -> str:
437437
)
438438

439439

440+
@mcp.resource("einvoice://reference/skr04-mapping")
441+
def skr04_mapping() -> str:
442+
"""SKR04-Kontenzuordnung für häufige Rechnungsarten.
443+
444+
Mapping von typischen Eingangsrechnungs-Kategorien zu
445+
SKR04-Konten (Standardkontenrahmen 04, DATEV).
446+
"""
447+
return json.dumps(
448+
{
449+
"title": "SKR04 — Typische Kontenzuordnung für Eingangsrechnungen",
450+
"chart": "SKR04 (DATEV)",
451+
"note": "Nur als Orientierung — die exakte Zuordnung hängt vom "
452+
"individuellen Kontenplan des Unternehmens ab.",
453+
"mappings": [
454+
{
455+
"category": "Büromaterial / Bürobedarf",
456+
"account": "6815",
457+
"description": "Bürobedarf",
458+
"tax_rate": "19%",
459+
},
460+
{
461+
"category": "IT-Dienstleistung / Software",
462+
"account": "6570",
463+
"description": "Fremdleistungen / IT-Dienstleistungen",
464+
"tax_rate": "19%",
465+
},
466+
{
467+
"category": "Beratung / Consulting",
468+
"account": "6825",
469+
"description": "Rechts- und Beratungskosten",
470+
"tax_rate": "19%",
471+
},
472+
{
473+
"category": "Miete / Büromiete",
474+
"account": "6310",
475+
"description": "Miete (unbewegliche Wirtschaftsgüter)",
476+
"tax_rate": "19% oder 0%",
477+
},
478+
{
479+
"category": "Telefon / Internet",
480+
"account": "6805",
481+
"description": "Telefon",
482+
"tax_rate": "19%",
483+
},
484+
{
485+
"category": "Reisekosten",
486+
"account": "6670",
487+
"description": "Reisekosten Arbeitnehmer",
488+
"tax_rate": "19% / 7% / 0%",
489+
},
490+
{
491+
"category": "Werbung / Marketing",
492+
"account": "6600",
493+
"description": "Werbekosten",
494+
"tax_rate": "19%",
495+
},
496+
{
497+
"category": "Porto / Versand",
498+
"account": "6810",
499+
"description": "Porto",
500+
"tax_rate": "19% oder 0%",
501+
},
502+
{
503+
"category": "Reparatur / Instandhaltung",
504+
"account": "6470",
505+
"description": "Reparaturen und Instandhaltung",
506+
"tax_rate": "19%",
507+
},
508+
{
509+
"category": "Versicherung",
510+
"account": "6400",
511+
"description": "Versicherungen",
512+
"tax_rate": "0% (steuerbefreit)",
513+
},
514+
{
515+
"category": "Strom / Gas / Wasser",
516+
"account": "6325",
517+
"description": "Gas, Strom, Wasser",
518+
"tax_rate": "19%",
519+
},
520+
{
521+
"category": "Wareneinkauf",
522+
"account": "5000",
523+
"description": "Einkauf Roh-, Hilfs- und Betriebsstoffe",
524+
"tax_rate": "19% oder 7%",
525+
},
526+
{
527+
"category": "Kfz-Kosten",
528+
"account": "6520",
529+
"description": "Kfz-Kosten",
530+
"tax_rate": "19%",
531+
},
532+
{
533+
"category": "Fortbildung / Schulung",
534+
"account": "6830",
535+
"description": "Fortbildungskosten",
536+
"tax_rate": "19% oder 0%",
537+
},
538+
],
539+
},
540+
ensure_ascii=False,
541+
indent=2,
542+
)
543+
544+
545+
@mcp.resource("einvoice://reference/credit-note-reasons")
546+
def credit_note_reasons() -> str:
547+
"""Gutschrift-Gründe (Credit Note Reason Codes) nach EN 16931.
548+
549+
Standardisierte Gründe für Gutschriften und Korrekturrechnungen
550+
mit deutschen Beschreibungen und Empfehlungen.
551+
"""
552+
return json.dumps(
553+
{
554+
"title": "Gutschrift- und Korrektur-Gründe",
555+
"type_codes": {
556+
"381": "Gutschrift (Credit Note)",
557+
"384": "Korrekturrechnung (Corrected Invoice)",
558+
},
559+
"reasons": [
560+
{
561+
"code": "1",
562+
"reason_de": "Retoure / Rückgabe",
563+
"reason_en": "Return of goods",
564+
"type_code": "381",
565+
"note": "Gesamte oder teilweise Rückgabe der Ware",
566+
},
567+
{
568+
"code": "2",
569+
"reason_de": "Preisänderung / Rabatt nachträglich",
570+
"reason_en": "Price correction",
571+
"type_code": "381",
572+
"note": "Nachträglicher Rabatt oder Preisanpassung",
573+
},
574+
{
575+
"code": "3",
576+
"reason_de": "Mengenabweichung",
577+
"reason_en": "Quantity difference",
578+
"type_code": "381",
579+
"note": "Liefermenge weicht von Rechnungsmenge ab",
580+
},
581+
{
582+
"code": "4",
583+
"reason_de": "Fehlerhafte Rechnungsdaten",
584+
"reason_en": "Invoice data error",
585+
"type_code": "384",
586+
"note": "Falsche Adresse, USt-IdNr., oder andere Stammdaten",
587+
},
588+
{
589+
"code": "5",
590+
"reason_de": "Umsatzsteuer-Korrektur",
591+
"reason_en": "Tax correction",
592+
"type_code": "384",
593+
"note": "Falscher Steuersatz oder -kategorie auf Originalrechnung",
594+
},
595+
{
596+
"code": "6",
597+
"reason_de": "Mängelrüge / Qualitätsmangel",
598+
"reason_en": "Quality deficiency",
599+
"type_code": "381",
600+
"note": "Minderung wegen mangelhafter Leistung (§437 BGB)",
601+
},
602+
{
603+
"code": "7",
604+
"reason_de": "Doppelte Rechnungsstellung",
605+
"reason_en": "Duplicate invoice",
606+
"type_code": "381",
607+
"note": "Vollständige Gutschrift der doppelt gestellten Rechnung",
608+
},
609+
{
610+
"code": "8",
611+
"reason_de": "Kulanz / Goodwill",
612+
"reason_en": "Goodwill gesture",
613+
"type_code": "381",
614+
"note": "Freiwillige Gutschrift ohne rechtliche Verpflichtung",
615+
},
616+
],
617+
"wichtig": [
618+
"Gutschrift (381) muss IMMER die Originalrechnungsnummer referenzieren (BT-25)",
619+
"Korrekturrechnung (384) ersetzt die fehlerhafte Rechnung vollständig",
620+
"Teilkorrekturen: Gutschrift (381) + neue Rechnung (380) ausstellen",
621+
"§14 Abs. 2 Satz 3 UStG: Berichtigung nur durch neues Dokument möglich",
622+
],
623+
},
624+
ensure_ascii=False,
625+
indent=2,
626+
)
627+
628+
629+
@mcp.prompt()
630+
def steuerprüfung_checkliste() -> str:
631+
"""Checkliste: E-Rechnungen für die Steuerprüfung vorbereiten.
632+
633+
Leitfaden zur Vorbereitung auf eine Betriebsprüfung mit
634+
Fokus auf E-Rechnungs-Compliance und GoBD-Archivierung.
635+
"""
636+
return (
637+
"# Steuerprüfung — E-Rechnungs-Checkliste\n\n"
638+
"## 1. Archivierung (GoBD-konform)\n"
639+
"- [ ] E-Rechnungen im **Originalformat** archiviert (XML, nicht nur PDF)\n"
640+
"- [ ] **10 Jahre** Aufbewahrungsfrist (§147 AO, §14b UStG)\n"
641+
"- [ ] **Unveränderbarkeit** sichergestellt (kein nachträgliches Editieren)\n"
642+
"- [ ] **Maschinelle Auswertbarkeit** gewährleistet (GoBD Tz. 128)\n"
643+
"- [ ] Verfahrensdokumentation vorhanden\n\n"
644+
"## 2. Pflichtangaben prüfen (§14 UStG)\n"
645+
"- [ ] BT-1: Rechnungsnummer (fortlaufend, eindeutig)\n"
646+
"- [ ] BT-2: Rechnungsdatum\n"
647+
"- [ ] BT-27..40: Vollständige Verkäufer-Angaben (Name, Anschrift, USt-IdNr.)\n"
648+
"- [ ] BT-44..55: Vollständige Käufer-Angaben\n"
649+
"- [ ] Positionen: Menge, Art, Entgelt, Steuersatz, Steuerbetrag\n"
650+
"- [ ] BT-81: Zahlungsart angegeben\n"
651+
"- [ ] BT-20: Zahlungsbedingungen\n\n"
652+
"## 3. Umsatzsteuer-Prüfung\n"
653+
"- [ ] Steuersätze korrekt (19%, 7%, 0% mit Begründung)\n"
654+
"- [ ] Reverse Charge (§13b): Hinweis vorhanden, 0% Steuer\n"
655+
"- [ ] Innergemeinschaftliche Lieferungen: USt-IdNr. beider Parteien\n"
656+
"- [ ] Steuerbefreiungen: Befreiungsgrund (BT-120) und Code (BT-121)\n"
657+
"- [ ] Vorsteuerabzug: Alle Voraussetzungen erfüllt?\n\n"
658+
"## 4. Gutschriften und Korrekturen\n"
659+
"- [ ] Gutschriften (381) referenzieren Originalrechnung (BT-25)\n"
660+
"- [ ] Korrekturrechnungen (384) referenzieren Originalrechnung (BT-25)\n"
661+
"- [ ] Keine 'informellen' Korrekturen per E-Mail oder PDF\n"
662+
"- [ ] Stornierungen vollständig dokumentiert\n\n"
663+
"## 5. Validierung\n"
664+
"- [ ] Alle E-Rechnungen gegen **KoSIT-Validator** geprüft\n"
665+
"- [ ] XRechnung: BR-DE-Regeln erfüllt\n"
666+
"- [ ] ZUGFeRD: PDF/A-3 Konformität sichergestellt\n"
667+
"- [ ] IBAN/BIC-Formate korrekt\n\n"
668+
"## 6. B2B-Pflicht (ab 2025/2027/2028)\n"
669+
"- [ ] Empfang von E-Rechnungen sichergestellt (seit 01.01.2025)\n"
670+
"- [ ] Versand vorbereitet (ab 2027 für Umsatz > 800K€, ab 2028 für alle)\n"
671+
"- [ ] Format: EN 16931 (XRechnung oder ZUGFeRD)\n\n"
672+
"## Typische Prüfungsschwerpunkte:\n"
673+
"1. **Rechnungsnummern-Lücken** — fehlende Nummern im Kreis\n"
674+
"2. **Vorsteuerabzug** — alle formellen Voraussetzungen erfüllt?\n"
675+
"3. **Reverse Charge** — §13b korrekt angewendet?\n"
676+
"4. **Innergemeinschaftliche Lieferungen** — ZM abgegeben?\n"
677+
"5. **Archivierung** — GoBD-Konformität nachweisbar?"
678+
)
679+
680+
440681
@mcp.prompt()
441682
def b2b_pflicht_2027() -> str:
442683
"""Checkliste: B2B E-Rechnungspflicht ab 2027 vorbereiten.

tests/unit/test_comprehensive.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6985,6 +6985,53 @@ def test_br_de_rules_resource(self) -> None:
69856985
assert "fix" in rule
69866986

69876987

6988+
def test_skr04_mapping_resource(self) -> None:
6989+
from einvoice_mcp.server import skr04_mapping
6990+
6991+
text = skr04_mapping()
6992+
data = json.loads(text)
6993+
assert data["chart"] == "SKR04 (DATEV)"
6994+
assert "mappings" in data
6995+
assert len(data["mappings"]) >= 10
6996+
categories = {m["category"] for m in data["mappings"]}
6997+
assert "Büromaterial / Bürobedarf" in categories
6998+
assert "IT-Dienstleistung / Software" in categories
6999+
for m in data["mappings"]:
7000+
assert "account" in m
7001+
assert "description" in m
7002+
assert "tax_rate" in m
7003+
7004+
def test_credit_note_reasons_resource(self) -> None:
7005+
from einvoice_mcp.server import credit_note_reasons
7006+
7007+
text = credit_note_reasons()
7008+
data = json.loads(text)
7009+
assert "reasons" in data
7010+
assert len(data["reasons"]) >= 8
7011+
assert "381" in data["type_codes"]
7012+
assert "384" in data["type_codes"]
7013+
assert "wichtig" in data
7014+
for r in data["reasons"]:
7015+
assert "code" in r
7016+
assert "reason_de" in r
7017+
assert "type_code" in r
7018+
7019+
7020+
class TestSteuerprüfungPrompt:
7021+
"""Test the audit readiness prompt."""
7022+
7023+
def test_steuerprüfung_checkliste(self) -> None:
7024+
from einvoice_mcp.server import steuerprüfung_checkliste
7025+
7026+
text = steuerprüfung_checkliste()
7027+
assert "GoBD" in text
7028+
assert "§147 AO" in text or "§14b UStG" in text
7029+
assert "10 Jahre" in text
7030+
assert "Reverse Charge" in text
7031+
assert "BT-25" in text
7032+
assert "KoSIT" in text
7033+
7034+
69887035
class TestB2BPflichtPrompt:
69897036
"""Test the B2B mandate prompt."""
69907037

0 commit comments

Comments
 (0)