Erweitere Marktmanagement-MCP fuer Durchfuehrungen
This commit is contained in:
1 parent
df5a533983
commit
3267a121de
3 files changed
+288
No files matched your search
@@ -0,0 +1,216 @@
|
||||
# Hermes: Market-Management-MCP-API
|
||||
|
||||
Stand: 2026-09-19
|
||||
Status: Aktive technische Schnittstellendokumentation
|
||||
|
||||
## Verbindung
|
||||
|
||||
Hermes verwendet den MCP-Endpunkt der DEV-App:
|
||||
|
||||
```text
|
||||
https://erpnaurua.imhochrain.ch/api/market-management-mcp.php
|
||||
```
|
||||
|
||||
Jeder Request ist ein JSON-RPC-2.0-Request über HTTPS. Der Request benötigt:
|
||||
|
||||
```http
|
||||
Authorization: Bearer <MARKET_MCP_TOKEN>
|
||||
Content-Type: application/json
|
||||
```
|
||||
|
||||
Der Token wird nicht in dieser Dokumentation oder im Repository gespeichert.
|
||||
|
||||
## Verbindungsablauf
|
||||
|
||||
### 1. Initialisieren
|
||||
|
||||
```json
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"id": 1,
|
||||
"method": "initialize",
|
||||
"params": {
|
||||
"protocolVersion": "2025-03-26"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Werkzeuge laden
|
||||
|
||||
```json
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"id": 2,
|
||||
"method": "tools/list",
|
||||
"params": {}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Werkzeug aufrufen
|
||||
|
||||
```json
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"id": 3,
|
||||
"method": "tools/call",
|
||||
"params": {
|
||||
"name": "market_management.list_categories",
|
||||
"arguments": {}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Das Ergebnis steht bei `tools/call` als JSON im Textinhalt des ersten
|
||||
`content`-Elements.
|
||||
|
||||
## Verfügbare Werkzeuge
|
||||
|
||||
### Marktdefinitionen
|
||||
|
||||
- `market_management.search_markets`
|
||||
- optional: `search`, `include_archived`, `limit`
|
||||
- `market_management.get_market`
|
||||
- erforderlich: `market_id`
|
||||
- optional: `include_archived`
|
||||
- `market_management.create_market`
|
||||
- erforderlich: `name`, `category_id`
|
||||
- `market_management.update_market`
|
||||
- erforderlich: `market_id`
|
||||
- änderbar: `name`, `category_id`
|
||||
- `market_management.archive_market`
|
||||
- erforderlich: `market_id`
|
||||
- `market_management.reactivate_market`
|
||||
- erforderlich: `market_id`
|
||||
|
||||
### Kategorien
|
||||
|
||||
- `market_management.list_categories`
|
||||
|
||||
Hermes darf Kategorien lesen und bei einem Markt referenzieren, aber keine
|
||||
Kategorien anlegen oder ändern.
|
||||
|
||||
### Durchführungen
|
||||
|
||||
- `market_management.create_occurrence`
|
||||
- erforderlich: `market_definition_id`
|
||||
- initialer Status: `open`
|
||||
- weitere Durchführungsfelder sind optional und werden typisiert validiert
|
||||
- `market_management.get_occurrence`
|
||||
- erforderlich: `occurrence_id`
|
||||
- `market_management.update_occurrence`
|
||||
- erforderlich: `occurrence_id`
|
||||
- `market_management.archive_occurrence`
|
||||
- erforderlich: `occurrence_id`
|
||||
- `market_management.reactivate_occurrence`
|
||||
- erforderlich: `occurrence_id`
|
||||
|
||||
Unterstützte Statuswerte:
|
||||
|
||||
```text
|
||||
open
|
||||
waitlist
|
||||
registered
|
||||
confirmation_pending
|
||||
confirmed
|
||||
cancelled
|
||||
completed
|
||||
```
|
||||
|
||||
Unterstützte Zahlungsstatuswerte:
|
||||
|
||||
```text
|
||||
unpaid
|
||||
paid
|
||||
```
|
||||
|
||||
### Durchführungstage
|
||||
|
||||
- `market_management.create_day`
|
||||
- erforderlich: `occurrence_id`, `date`
|
||||
- `market_management.update_day`
|
||||
- erforderlich: `day_id`
|
||||
- `market_management.delete_day`
|
||||
- erforderlich: `day_id`
|
||||
|
||||
Weitere mögliche Tagesfelder sind `stand_start_time`, `stand_end_time`,
|
||||
`setup_start_time`, `setup_end_time`, `delivery_start_time`,
|
||||
`delivery_end_time` und `observations`.
|
||||
|
||||
### Veranstalter und Kosten
|
||||
|
||||
- `market_management.set_organizer`
|
||||
- erforderlich: `occurrence_id`, `organization_contact_id`,
|
||||
`contact_person_id`
|
||||
- `market_management.create_cost_item`
|
||||
- erforderlich: `occurrence_id`, `cost_type`, `gross_amount`, `tax_status`
|
||||
- `tax_status`: `tax_free` oder `taxable`
|
||||
- `market_management.delete_cost_item`
|
||||
- erforderlich: `cost_item_id`
|
||||
|
||||
## Beispiel: Markt anlegen
|
||||
|
||||
```json
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"id": 10,
|
||||
"method": "tools/call",
|
||||
"params": {
|
||||
"name": "market_management.create_market",
|
||||
"arguments": {
|
||||
"name": "Beispielmarkt Hermes Test",
|
||||
"category_id": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Beispiel: Durchführung mit Tag anlegen
|
||||
|
||||
```json
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"id": 11,
|
||||
"method": "tools/call",
|
||||
"params": {
|
||||
"name": "market_management.create_occurrence",
|
||||
"arguments": {
|
||||
"market_definition_id": 1,
|
||||
"status": "open",
|
||||
"place": "Beispielort",
|
||||
"registration_deadline": "2026-10-01"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"id": 12,
|
||||
"method": "tools/call",
|
||||
"params": {
|
||||
"name": "market_management.create_day",
|
||||
"arguments": {
|
||||
"occurrence_id": 1,
|
||||
"date": "2026-11-21",
|
||||
"stand_start_time": "09:00",
|
||||
"stand_end_time": "18:00"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Fachliche Grenzen
|
||||
|
||||
- Hermes erhält keinen direkten Datenbankzugriff.
|
||||
- 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.
|
||||
- Alle Schreibvorgänge werden serverseitig validiert.
|
||||
|
||||
## Fehler
|
||||
|
||||
Bei fehlender oder ungültiger Authentifizierung antwortet der Endpunkt mit
|
||||
HTTP 401. Ungültige JSON-RPC-Requests oder fachlich ungültige Eingaben werden
|
||||
als JSON-RPC-Fehlerantwort zurückgegeben.
|
||||
@@ -46,6 +46,9 @@ function market_management_mcp_tools(): array
|
||||
['name' => 'market_management.create_day', 'description' => 'Durchführungstag anlegen', 'inputSchema' => ['type' => 'object', 'required' => ['occurrence_id', 'date']]],
|
||||
['name' => 'market_management.update_day', 'description' => 'Durchführungstag ändern', 'inputSchema' => ['type' => 'object', 'required' => ['day_id']]],
|
||||
['name' => 'market_management.delete_day', 'description' => 'Durchführungstag entfernen', 'inputSchema' => ['type' => 'object', 'required' => ['day_id']]],
|
||||
['name' => 'market_management.set_organizer', 'description' => 'Veranstalter einer Durchführung setzen', 'inputSchema' => ['type' => 'object', 'required' => ['occurrence_id', 'organization_contact_id', 'contact_person_id']]],
|
||||
['name' => 'market_management.create_cost_item', 'description' => 'Kostenposition anlegen', 'inputSchema' => ['type' => 'object', 'required' => ['occurrence_id', 'cost_type', 'gross_amount', 'tax_status']]],
|
||||
['name' => 'market_management.delete_cost_item', 'description' => 'Kostenposition entfernen', 'inputSchema' => ['type' => 'object', 'required' => ['cost_item_id']]],
|
||||
];
|
||||
}
|
||||
|
||||
@@ -106,6 +109,12 @@ function market_management_mcp_call(PDO $pdo, string $tool, array $arguments): a
|
||||
$pdo,
|
||||
market_management_require_positive_id($arguments['day_id'] ?? null, 'day_id')
|
||||
),
|
||||
'market_management.set_organizer' => market_management_set_organizer($pdo, $arguments),
|
||||
'market_management.create_cost_item' => market_management_create_cost_item($pdo, $arguments),
|
||||
'market_management.delete_cost_item' => market_management_delete_cost_item(
|
||||
$pdo,
|
||||
market_management_require_positive_id($arguments['cost_item_id'] ?? null, 'cost_item_id')
|
||||
),
|
||||
default => throw new InvalidArgumentException('Unbekanntes MCP-Tool: ' . $tool),
|
||||
};
|
||||
}
|
||||
@@ -442,3 +442,66 @@ function market_management_delete_day(PDO $pdo, int $dayId): array
|
||||
}
|
||||
return $day;
|
||||
}
|
||||
|
||||
function market_management_set_organizer(PDO $pdo, array $input): array
|
||||
{
|
||||
$occurrenceId = market_management_require_positive_id($input['occurrence_id'] ?? null, 'occurrence_id');
|
||||
$organizationId = market_management_require_positive_id($input['organization_contact_id'] ?? null, 'organization_contact_id');
|
||||
$contactPersonId = market_management_require_positive_id($input['contact_person_id'] ?? null, 'contact_person_id');
|
||||
$stmt = $pdo->prepare(
|
||||
'INSERT INTO market_occurrence_organizer (occurrence_id, organization_contact_id, contact_person_id)
|
||||
VALUES (:occurrence_id, :organization_contact_id, :contact_person_id)
|
||||
ON CONFLICT (occurrence_id) DO UPDATE
|
||||
SET organization_contact_id = EXCLUDED.organization_contact_id,
|
||||
contact_person_id = EXCLUDED.contact_person_id,
|
||||
updated_at = NOW()
|
||||
RETURNING *'
|
||||
);
|
||||
$stmt->execute([
|
||||
':occurrence_id' => $occurrenceId,
|
||||
':organization_contact_id' => $organizationId,
|
||||
':contact_person_id' => $contactPersonId,
|
||||
]);
|
||||
return (array) $stmt->fetch();
|
||||
}
|
||||
|
||||
function market_management_create_cost_item(PDO $pdo, array $input): array
|
||||
{
|
||||
$occurrenceId = market_management_require_positive_id($input['occurrence_id'] ?? null, 'occurrence_id');
|
||||
$costType = trim((string) ($input['cost_type'] ?? ''));
|
||||
$grossAmount = market_management_optional_number($input, 'gross_amount');
|
||||
$taxStatus = trim((string) ($input['tax_status'] ?? ''));
|
||||
$taxRate = market_management_optional_number($input, 'tax_rate') ?? '0.00';
|
||||
if ($costType === '' || $grossAmount === null || !in_array($taxStatus, ['tax_free', 'taxable'], true)) {
|
||||
throw new InvalidArgumentException('cost_type, gross_amount und tax_status sind erforderlich.');
|
||||
}
|
||||
if (($taxStatus === 'tax_free' && $taxRate !== '0.00') || ($taxStatus === 'taxable' && (float) $taxRate <= 0)) {
|
||||
throw new InvalidArgumentException('tax_rate passt nicht zu tax_status.');
|
||||
}
|
||||
$stmt = $pdo->prepare(
|
||||
'INSERT INTO market_occurrence_cost_item
|
||||
(occurrence_id, cost_type, description, gross_amount, tax_status, tax_rate)
|
||||
VALUES (:occurrence_id, :cost_type, :description, :gross_amount, :tax_status, :tax_rate)
|
||||
RETURNING *'
|
||||
);
|
||||
$stmt->execute([
|
||||
':occurrence_id' => $occurrenceId,
|
||||
':cost_type' => $costType,
|
||||
':description' => market_management_optional_string($input, 'description'),
|
||||
':gross_amount' => $grossAmount,
|
||||
':tax_status' => $taxStatus,
|
||||
':tax_rate' => $taxRate,
|
||||
]);
|
||||
return (array) $stmt->fetch();
|
||||
}
|
||||
|
||||
function market_management_delete_cost_item(PDO $pdo, int $costItemId): array
|
||||
{
|
||||
$stmt = $pdo->prepare('DELETE FROM market_occurrence_cost_item WHERE id = :id RETURNING id, occurrence_id');
|
||||
$stmt->execute([':id' => $costItemId]);
|
||||
$item = $stmt->fetch();
|
||||
if (!is_array($item)) {
|
||||
throw new RuntimeException('Kostenposition nicht gefunden.');
|
||||
}
|
||||
return $item;
|
||||
}
|
||||
Reference in new issue
Block a user