diff --git a/docs/modules/market_management/konzepte/market_management_hermes_mcp_api.md b/docs/modules/market_management/konzepte/market_management_hermes_mcp_api.md index c8b35ed..dfda3a4 100644 --- a/docs/modules/market_management/konzepte/market_management_hermes_mcp_api.md +++ b/docs/modules/market_management/konzepte/market_management_hermes_mcp_api.md @@ -1,6 +1,6 @@ # Hermes: Market-Management-MCP-API -Stand: 2026-09-19 +Stand: 2026-09-20 Status: Aktive technische Schnittstellendokumentation ## Verbindung @@ -22,6 +22,22 @@ Der Token wird nicht in dieser Dokumentation oder im Repository gespeichert. ## Verbindungsablauf +## Fachliche Begrifflichkeit für Hermes + +Die fachliche Hierarchie lautet: + +```text +Markt (market_definition) +└── Marktdurchführung (market_occurrence) + └── Markttag / Markttage (market_occurrence_day) +``` + +Ein Markt ist die zentrale Marktdefinition. Eine Marktdurchführung ist eine +konkrete Ausgabe bzw. Teilnahme an diesem Markt. Eine Marktdurchführung besitzt +mindestens einen Markttag. OTC-Verkäufe werden immer einem konkreten Markttag +zugeordnet; die zugehörige Marktdurchführung und der Markt ergeben sich aus +dieser Referenz. + ### 1. Initialisieren ```json @@ -72,16 +88,17 @@ Das Ergebnis steht bei `tools/call` als JSON im Textinhalt des ersten `municipality_reference_id`, `date_from`, `date_to`, `include_archived`, `sort`, `sort_direction`, `limit`, `offset` - `market_management.search_occurrences` + - sucht Marktdurchführungen - optional: `search`, `market_definition_id`, `status`, `place`, `address`, `municipality_reference_id`, `date_from`, `date_to`, `include_archived`, `sort`, `sort_direction`, `limit`, `offset` - `market_management.get_market` - erforderlich: `market_id` - optional: `include_archived` - - liefert Durchführungen inklusive Tagen, Kosten und berechneten Verkaufswerten + - liefert Marktdurchführungen inklusive Markttagen, Kosten und berechneten Verkaufswerten - `market_management.create_market` - erforderlich: `name`, `category_id` - - optional: `website_url` als HTTP(S)-URL der Veranstaltung + - optional: `website_url` als HTTP(S)-URL des Marktes - `market_management.update_market` - erforderlich: `market_id` - änderbar: `name`, `category_id`, `website_url` @@ -100,21 +117,21 @@ Kategorien anlegen oder ändern. - `market_management.list_reference_data` - liefert Kategorien, Kantone und aktive Gemeinden - `market_management.get_overview` - - liefert serverseitig gefilterte Markt- und Durchführungslisten + - liefert serverseitig gefilterte Markt- und Marktdurchführungslisten -### Durchführungen +### Marktdurchführungen - `market_management.create_occurrence` - - erforderlich: `market_definition_id`, `days` mit mindestens einem Eintrag + - erforderlich: `market_definition_id`, `days` mit mindestens einem Markttag - initialer Status: `open` - - weitere Durchführungsfelder sind optional und werden typisiert validiert + - weitere Marktdurchführungsfelder sind optional und werden typisiert validiert - `market_management.get_occurrence` - erforderlich: `occurrence_id` - - liefert zusätzlich die Marktdefinition, Durchführungstage, Kosten und + - liefert zusätzlich den Markt, Markttage, Kosten und berechnete Tages- und Gesamterlöse - `market_management.update_occurrence` - erforderlich: `occurrence_id` - - änderbar: sämtliche GUI-Durchführungsfelder einschließlich Veranstalter, + - änderbar: sämtliche GUI-Marktdurchführungsfelder einschließlich Veranstalter, Kontaktperson, Kontakt-E-Mail und Kontakt-Telefon - `market_management.archive_occurrence` - erforderlich: `occurrence_id` @@ -140,9 +157,10 @@ unpaid paid ``` -### Durchführungstage +### Markttage - `market_management.create_day` + - legt einen Markttag an - erforderlich: `occurrence_id`, `date` - `market_management.update_day` - erforderlich: `day_id` @@ -186,7 +204,7 @@ Weitere mögliche Tagesfelder sind `stand_start_time`, `stand_end_time`, } ``` -## Beispiel: Durchführung mit Tag anlegen +## Beispiel: Marktdurchführung mit Markttag anlegen ```json { @@ -236,12 +254,12 @@ Weitere mögliche Tagesfelder sind `stand_start_time`, `stand_end_time`, - Hermes darf keine Kategorien anlegen. - Umsatz und Artikelmengen werden nicht über MCP geschrieben; sie werden aus den OTC-Verkäufen abgeleitet. -- Markt und Durchführung werden unabhängig archiviert. +- Markt und Marktdurchführung werden unabhängig archiviert. - Alle Schreibvorgänge werden serverseitig validiert. - Jeder schreibende MCP-Aufruf benötigt `idempotency_key`; optional kann `client_id` mitgegeben werden. Wiederholungen liefern dasselbe Ergebnis. - Umsatz- und Artikelmengen aus OTC-Verkäufen sind erst verfügbar, sobald die - separate OTC-Schnittstelle die Zuordnung zum Durchführungstag bereitstellt. + separate OTC-Schnittstelle die Zuordnung zum Markttag bereitstellt. ## Fehler diff --git a/docs/modules/market_management/konzepte/market_management_hermes_mcp_konzept.md b/docs/modules/market_management/konzepte/market_management_hermes_mcp_konzept.md index c2c5ed2..8243295 100644 --- a/docs/modules/market_management/konzepte/market_management_hermes_mcp_konzept.md +++ b/docs/modules/market_management/konzepte/market_management_hermes_mcp_konzept.md @@ -33,9 +33,9 @@ Vorgesehene Toolgruppen: - Märkte suchen und lesen - Märkte anlegen, ändern, archivieren und reaktivieren -- Durchführungen suchen und lesen -- Durchführungen anlegen, ändern, archivieren und reaktivieren -- Durchführungstage anlegen, ändern und entfernen +- Marktdurchführungen suchen und lesen +- Marktdurchführungen anlegen, ändern, archivieren und reaktivieren +- Markttage anlegen, ändern und entfernen - Kategorien, Kantone und Gemeinden lesen - Kosten und Zahlungsstatus ändern - Übersichtsdaten lesen diff --git a/modules/market_management/mcp.php b/modules/market_management/mcp.php index 170b619..73e1f90 100644 --- a/modules/market_management/mcp.php +++ b/modules/market_management/mcp.php @@ -71,8 +71,8 @@ function market_management_mcp_tools(): array ]; return [ ['name' => 'market_management.search_markets', 'description' => 'Märkte suchen', 'inputSchema' => ['type' => 'object', 'properties' => $searchProperties]], - ['name' => 'market_management.search_occurrences', 'description' => 'Durchführungen suchen und auflisten', 'inputSchema' => ['type' => 'object', 'properties' => $searchProperties]], - ['name' => 'market_management.get_market', 'description' => 'Markt mit Durchführungen lesen', 'inputSchema' => ['type' => 'object', 'required' => ['market_id'], 'properties' => ['market_id' => ['type' => 'integer'], 'include_archived' => ['type' => 'boolean']]]], + ['name' => 'market_management.search_occurrences', 'description' => 'Marktdurchführungen suchen und auflisten', 'inputSchema' => ['type' => 'object', 'properties' => $searchProperties]], + ['name' => 'market_management.get_market', 'description' => 'Markt mit Marktdurchführungen lesen', 'inputSchema' => ['type' => 'object', 'required' => ['market_id'], 'properties' => ['market_id' => ['type' => 'integer'], 'include_archived' => ['type' => 'boolean']]]], ['name' => 'market_management.create_market', 'description' => 'Markt mit bestehender Kategorie und optionaler Website-URL anlegen', 'inputSchema' => ['type' => 'object', 'required' => ['name', 'category_id'], 'properties' => ['name' => ['type' => 'string'], 'category_id' => ['type' => 'integer'], 'website_url' => ['type' => ['string', 'null'], 'format' => 'uri']]]], ['name' => 'market_management.update_market', 'description' => 'Markt inklusive Website-URL ändern', 'inputSchema' => ['type' => 'object', 'required' => ['market_id'], 'properties' => ['market_id' => ['type' => 'integer'], 'name' => ['type' => 'string'], 'category_id' => ['type' => 'integer'], 'website_url' => ['type' => ['string', 'null'], 'format' => 'uri']]]], ['name' => 'market_management.archive_market', 'description' => 'Markt archivieren', 'inputSchema' => ['type' => 'object', 'required' => ['market_id'], 'properties' => ['market_id' => ['type' => 'integer']]]], @@ -80,16 +80,16 @@ function market_management_mcp_tools(): array ['name' => 'market_management.list_categories', 'description' => 'Bestehende Kategorien lesen', 'inputSchema' => ['type' => 'object', 'properties' => []]], ['name' => 'market_management.list_reference_data', 'description' => 'Kategorien, Kantone und Gemeinden lesen', 'inputSchema' => ['type' => 'object', 'properties' => []]], ['name' => 'market_management.get_overview', 'description' => 'Marktübersicht mit serverseitigen Filtern lesen', 'inputSchema' => ['type' => 'object', 'properties' => $searchProperties]], - ['name' => 'market_management.create_occurrence', 'description' => 'Durchführung mit mindestens einem Tag anlegen', 'inputSchema' => ['type' => 'object', 'required' => ['market_definition_id', 'days'], 'properties' => ['market_definition_id' => ['type' => 'integer'], 'status' => ['type' => 'string'], 'days' => ['type' => 'array', 'minItems' => 1, 'items' => ['type' => 'object', 'required' => ['date'], 'properties' => $dayProperties]] + $occurrenceProperties]]], - ['name' => 'market_management.get_occurrence', 'description' => 'Durchführung mit Markt, Tagen und berechneten Verkaufsdaten lesen', 'inputSchema' => ['type' => 'object', 'required' => ['occurrence_id'], 'properties' => ['occurrence_id' => ['type' => 'integer'], 'include_archived' => ['type' => 'boolean']]]], - ['name' => 'market_management.update_occurrence', 'description' => 'Durchführung ändern', 'inputSchema' => ['type' => 'object', 'required' => ['occurrence_id'], 'properties' => ['occurrence_id' => ['type' => 'integer']] + $occurrenceProperties]], - ['name' => 'market_management.archive_occurrence', 'description' => 'Durchführung archivieren', 'inputSchema' => ['type' => 'object', 'required' => ['occurrence_id'], 'properties' => ['occurrence_id' => ['type' => 'integer']]]], - ['name' => 'market_management.reactivate_occurrence', 'description' => 'Durchführung reaktivieren', 'inputSchema' => ['type' => 'object', 'required' => ['occurrence_id'], 'properties' => ['occurrence_id' => ['type' => 'integer']]]], - ['name' => 'market_management.create_day', 'description' => 'Durchführungstag anlegen', 'inputSchema' => ['type' => 'object', 'required' => ['occurrence_id', 'date'], 'properties' => ['occurrence_id' => ['type' => 'integer']] + $dayProperties]], - ['name' => 'market_management.update_day', 'description' => 'Durchführungstag ändern', 'inputSchema' => ['type' => 'object', 'required' => ['day_id'], 'properties' => ['day_id' => ['type' => 'integer']] + $dayProperties]], - ['name' => 'market_management.delete_day', 'description' => 'Durchführungstag entfernen', 'inputSchema' => ['type' => 'object', 'required' => ['day_id'], 'properties' => ['day_id' => ['type' => 'integer']]]], - ['name' => 'market_management.set_organizer', 'description' => 'Veranstalter einer Durchführung setzen', 'inputSchema' => ['type' => 'object', 'required' => ['occurrence_id', 'organization_contact_id', 'contact_person_id'], 'properties' => ['occurrence_id' => ['type' => 'integer'], 'organization_contact_id' => ['type' => 'integer'], 'contact_person_id' => ['type' => 'integer']]]], - ['name' => 'market_management.delete_organizer', 'description' => 'Veranstalter einer Durchführung entfernen', 'inputSchema' => ['type' => 'object', 'required' => ['occurrence_id'], 'properties' => ['occurrence_id' => ['type' => 'integer']]]], + ['name' => 'market_management.create_occurrence', 'description' => 'Marktdurchführung mit mindestens einem Markttag anlegen', 'inputSchema' => ['type' => 'object', 'required' => ['market_definition_id', 'days'], 'properties' => ['market_definition_id' => ['type' => 'integer'], 'status' => ['type' => 'string'], 'days' => ['type' => 'array', 'minItems' => 1, 'items' => ['type' => 'object', 'required' => ['date'], 'properties' => $dayProperties]] + $occurrenceProperties]]], + ['name' => 'market_management.get_occurrence', 'description' => 'Marktdurchführung mit Markt, Markttagen und berechneten Verkaufsdaten lesen', 'inputSchema' => ['type' => 'object', 'required' => ['occurrence_id'], 'properties' => ['occurrence_id' => ['type' => 'integer'], 'include_archived' => ['type' => 'boolean']]]], + ['name' => 'market_management.update_occurrence', 'description' => 'Marktdurchführung ändern', 'inputSchema' => ['type' => 'object', 'required' => ['occurrence_id'], 'properties' => ['occurrence_id' => ['type' => 'integer']] + $occurrenceProperties]], + ['name' => 'market_management.archive_occurrence', 'description' => 'Marktdurchführung archivieren', 'inputSchema' => ['type' => 'object', 'required' => ['occurrence_id'], 'properties' => ['occurrence_id' => ['type' => 'integer']]]], + ['name' => 'market_management.reactivate_occurrence', 'description' => 'Marktdurchführung reaktivieren', 'inputSchema' => ['type' => 'object', 'required' => ['occurrence_id'], 'properties' => ['occurrence_id' => ['type' => 'integer']]]], + ['name' => 'market_management.create_day', 'description' => 'Markttag anlegen', 'inputSchema' => ['type' => 'object', 'required' => ['occurrence_id', 'date'], 'properties' => ['occurrence_id' => ['type' => 'integer']] + $dayProperties]], + ['name' => 'market_management.update_day', 'description' => 'Markttag ändern', 'inputSchema' => ['type' => 'object', 'required' => ['day_id'], 'properties' => ['day_id' => ['type' => 'integer']] + $dayProperties]], + ['name' => 'market_management.delete_day', 'description' => 'Markttag entfernen', 'inputSchema' => ['type' => 'object', 'required' => ['day_id'], 'properties' => ['day_id' => ['type' => 'integer']]]], + ['name' => 'market_management.set_organizer', 'description' => 'Veranstalter einer Marktdurchführung setzen', 'inputSchema' => ['type' => 'object', 'required' => ['occurrence_id', 'organization_contact_id', 'contact_person_id'], 'properties' => ['occurrence_id' => ['type' => 'integer'], 'organization_contact_id' => ['type' => 'integer'], 'contact_person_id' => ['type' => 'integer']]]], + ['name' => 'market_management.delete_organizer', 'description' => 'Veranstalter einer Marktdurchführung entfernen', 'inputSchema' => ['type' => 'object', 'required' => ['occurrence_id'], 'properties' => ['occurrence_id' => ['type' => 'integer']]]], ['name' => 'market_management.create_cost_item', 'description' => 'Kostenposition anlegen', 'inputSchema' => ['type' => 'object', 'required' => ['occurrence_id', 'cost_type', 'gross_amount', 'tax_status'], 'properties' => ['occurrence_id' => ['type' => 'integer'], 'cost_type' => ['type' => 'string'], 'description' => ['type' => ['string', 'null']], 'gross_amount' => ['type' => 'number'], 'tax_status' => ['type' => 'string', 'enum' => ['tax_free', 'taxable']], 'tax_rate' => ['type' => 'number']]]], ['name' => 'market_management.update_cost_item', 'description' => 'Kostenposition ändern', 'inputSchema' => ['type' => 'object', 'required' => ['cost_item_id'], 'properties' => ['cost_item_id' => ['type' => 'integer'], 'cost_type' => ['type' => 'string'], 'description' => ['type' => ['string', 'null']], 'gross_amount' => ['type' => ['number', 'null']], 'tax_status' => ['type' => ['string', 'null'], 'enum' => ['tax_free', 'taxable']], 'tax_rate' => ['type' => ['number', 'null']]]]], ['name' => 'market_management.delete_cost_item', 'description' => 'Kostenposition entfernen', 'inputSchema' => ['type' => 'object', 'required' => ['cost_item_id'], 'properties' => ['cost_item_id' => ['type' => 'integer']]]], @@ -189,7 +189,7 @@ function market_management_mcp_get_occurrence(PDO $pdo, int $occurrenceId, bool { $occurrence = market_management_get_occurrence($pdo, $occurrenceId, $includeArchived); if ($occurrence === null) { - throw new RuntimeException('Durchführung nicht gefunden.'); + throw new RuntimeException('Marktdurchführung nicht gefunden.'); } $market = market_management_get_market($pdo, (int) $occurrence['market_definition_id'], $includeArchived); if ($market === null) { @@ -235,7 +235,7 @@ function market_management_mcp_update_occurrence(PDO $pdo, int $occurrenceId, ar if ($contactFields !== [] || $organizerFields !== []) { $existing = market_management_get_occurrence($pdo, $occurrenceId, true); if ($existing === null) { - throw new RuntimeException('Durchführung nicht gefunden.'); + throw new RuntimeException('Marktdurchführung nicht gefunden.'); } } if ($organizerFields !== []) {