{
  "status": "success",
  "name": "Slides Service API",
  "description": "Manage HTML presentations, presentation images and shared SQLite databases. Every authenticated client has full access.",
  "mcp": {
    "baseUrl": "https://slides.marktkauf-wiele.de/",
    "endpoint": "https://slides.marktkauf-wiele.de/mcp",
    "transport": "Streamable HTTP",
    "authentication": "OAuth 2.1 authorization code with PKCE",
    "authenticationInstructions": "On HTTP 401, follow OAuth discovery and open the authorization URL in the user's browser. The user enters the shared Slides password only on that page; never ask them to paste it into chat.",
    "protectedResourceMetadata": "https://slides.marktkauf-wiele.de/.well-known/oauth-protected-resource",
    "publicGuideUrl": "https://slides.marktkauf-wiele.de/mcp-guide",
    "publicGuideMarkdownUrl": "https://slides.marktkauf-wiele.de/mcp-guide.md",
    "guideResource": "slides://guide",
    "guideTool": "service_guide_get",
    "tools": [
      "service_guide_get",
      "presentation_list",
      "presentation_get",
      "presentation_create",
      "presentation_update",
      "presentation_delete",
      "trash_list",
      "trash_restore",
      "trash_delete",
      "image_list",
      "image_get",
      "image_create",
      "image_update",
      "image_delete",
      "database_list",
      "database_get",
      "database_schema_get",
      "database_create",
      "database_update",
      "database_delete",
      "database_query",
      "database_execute",
      "database_import_csv",
      "database_export_csv"
    ]
  },
  "operatingGuide": "# Slides Service – MCP-Betriebsanleitung\n\n## Zweck und Vertrauensmodell\n\nDieser interne Dienst veröffentlicht HTML-Präsentationen, speichert zugehörige Bilder und stellt gemeinsame SQLite-Datenbanken bereit. Es gibt genau ein Passwort und genau eine Berechtigungsstufe. Jeder authentifizierte Client darf alles lesen, verändern und löschen. Der Dienst ist kein sicherer Speicher für vertrauliche Daten.\n\n## Verbindung und Authentifizierung\n\n- MCP-Adresse: https://slides.marktkauf-wiele.de/\n- Expliziter MCP-Endpunkt, falls ein Harness einen Pfad verlangt: https://slides.marktkauf-wiele.de/mcp\n- Transport: Streamable HTTP\n- Authentifizierung: Browserbasierter OAuth-2.1-Code-Flow mit PKCE.\n- Wenn die Verbindung mit HTTP 401 antwortet, folgt der MCP-Client der OAuth-Erkennung und der Agent öffnet selbstständig die Autorisierungsseite im Browser.\n- Der Nutzer gibt das gemeinsame Slides-Passwort ausschließlich in der normalen Slides-Browseranmeldung ein. Nach erfolgreicher Prüfung erscheint eine sichtbare Erfolgsmeldung, bevor der Browser zum Agenten zurückkehrt. Das Passwort nicht im Chat erfragen, nicht als Tool-Argument senden und nicht in Inhalte schreiben.\n- Nach erfolgreicher MCP-Initialisierung ist diese Betriebsanleitung automatisch im Feld `instructions` verfügbar. Sie kann zusätzlich mit `service_guide_get` oder als Resource `slides://guide` gelesen werden.\n- Öffentliche Anleitung: https://slides.marktkauf-wiele.de/mcp-guide\n- Maschinenlesbare API-Hilfe: https://slides.marktkauf-wiele.de/api/help\n\n## Empfohlener Arbeitsablauf\n\n1. Kläre kurz, was der Nutzer erstellen oder ändern möchte.\n2. Nutze zuerst die passenden List- und Get-Tools, um den bestehenden Zustand zu prüfen.\n3. Führe die gewünschte Änderung mit dem kleinsten passenden Tool aus.\n4. Lies das Ergebnis zurück oder führe eine kleine Kontrollabfrage aus.\n5. Gib dem Nutzer bei Präsentationen die veröffentlichte URL zurück.\n6. Frage vor endgültigem Löschen von Bildern oder Datenbanken nach einer Bestätigung. Präsentationen werden zunächst in den Papierkorb verschoben.\n\n## Präsentationen\n\n- `presentation_list`: Präsentationen suchen und auflisten.\n- `presentation_get`: Metadaten lesen; mit `include_html` auch das vollständige HTML.\n- `presentation_create`: vollständiges HTML veröffentlichen. Ohne festen Slug sollte der zufällige Suffix aktiviert bleiben.\n- `presentation_update`: Titel und/oder HTML ändern.\n- `presentation_delete`: Präsentation inklusive Bilder in den Papierkorb verschieben.\n- `trash_list`, `trash_restore`, `trash_delete`: Papierkorb verwalten.\n\nPräsentationen sind vollständige HTML-Dokumente. Bilder derselben Präsentation werden relativ eingebunden, zum Beispiel:\n\n```html\n<img src=\"./images/chart.png\" alt=\"Umsatzdiagramm\">\n```\n\n## Bilder\n\n- Unterstützt: JPEG, PNG, WebP und GIF.\n- `image_list`: Bilder einer Präsentation auflisten.\n- `image_get`: Metadaten lesen; `include_content` nur verwenden, wenn der Binärinhalt wirklich benötigt wird.\n- `image_create`: neues Bild mit Dateiname und Base64-Inhalt anlegen.\n- `image_update`: vorhandenes Bild vollständig ersetzen.\n- `image_delete`: Bild endgültig löschen.\n- Standardlimit: 10 MB pro Bild.\n- Dateiendung und tatsächlicher Bildtyp müssen zusammenpassen.\n\n## SQLite-Datenbanken\n\n- Es wird ausschließlich SQLite unterstützt.\n- Datenbanken sind gemeinsam und nicht fest einer Präsentation zugeordnet.\n- Namen bestehen aus Kleinbuchstaben, Zahlen und Bindestrichen.\n- `database_list`, `database_get`, `database_schema_get`: Bestand und Schema prüfen.\n- `database_create`: leere SQLite-Datenbank anlegen.\n- `database_update`: Datenbank umbenennen.\n- `database_delete`: Datenbank endgültig löschen.\n- `database_query`: lesende `SELECT`-, `WITH`- oder `EXPLAIN`-Abfrage mit optionalen `?`-Parametern und begrenztem Ergebnis.\n- `database_execute`: genau ein schreibendes oder strukturelles Statement wie `CREATE TABLE`, `INSERT`, `UPDATE`, `DELETE` oder `DROP TABLE`.\n- `database_import_csv`: UTF-8-CSV in eine Tabelle importieren; Spalten werden zunächst als TEXT angelegt.\n- `database_export_csv`: Ergebnis einer lesenden Abfrage als CSV exportieren.\n- SQLite-Operationen haben feste Zeit-, Ergebnis- und Speichergrenzen. Bei HTTP 408 wurde das Zeitlimit erreicht, bei HTTP 413 eine Größenbegrenzung. Die Abfrage dann vereinfachen, stärker filtern oder den Export aufteilen.\n- CSV-Exporte neutralisieren Werte, die Tabellenkalkulationen als Formeln interpretieren könnten, durch ein führendes Apostroph.\n\nSQL-Werte möglichst über `params` und `?`-Platzhalter übergeben. Vor Änderungen zuerst das Schema lesen. Nach Schreiboperationen mit einer kleinen `database_query` kontrollieren.\n\n## Fehler und Grenzen\n\n- HTTP 401: OAuth-Erkennung starten, Autorisierungsseite im Browser öffnen und den Nutzer dort das Passwort eingeben lassen.\n- Konflikt beim Anlegen: Zuerst mit List/Get prüfen, ob Name, Slug oder Datei bereits existiert.\n- Zu große Antwort: Query mit `WHERE`, `LIMIT` oder kleinerem Tool-Limit eingrenzen.\n- Schreibendes SQL wird von `database_query` abgelehnt und gehört in `database_execute`.\n- Der Dienst besitzt bewusst keine Rollen, kein Auditing, keine automatischen Backups und keine Garantie gegen Datenverlust.\n",
  "authentication": {
    "passwordLogin": {
      "method": "POST",
      "path": "/api/login",
      "body": {
        "password": "SLIDES_PASSWORD"
      },
      "result": "Sets an HttpOnly slides_session cookie. Reuse that cookie for later API calls."
    },
    "bearerToken": {
      "header": "Authorization: Bearer SLIDES_PASSWORD",
      "note": "Accepted by the regular HTTP API for backwards-compatible scripts, but not by MCP. MCP uses browser-based OAuth access tokens."
    },
    "basicAuth": {
      "note": "Accepted for simple scripts. Username is ignored; password must match SLIDES_PASSWORD."
    }
  },
  "endpoints": [
    {
      "method": "GET",
      "path": "/api/help",
      "description": "Return this operating guide.",
      "auth": false
    },
    {
      "method": "POST",
      "path": "/api/login",
      "description": "Create a reusable API/web session cookie.",
      "auth": false
    },
    {
      "method": "GET",
      "path": "/api/session",
      "description": "Check whether the current request is authenticated.",
      "auth": false
    },
    {
      "method": "POST",
      "path": "/api/logout",
      "description": "Clear the session cookie.",
      "auth": true
    },
    {
      "method": "GET",
      "path": "/api/presentations",
      "description": "List presentations. Optional query params: query, limit, offset, sort.",
      "auth": true
    },
    {
      "method": "POST",
      "path": "/api/presentations",
      "description": "Publish a new presentation.",
      "auth": true,
      "body": {
        "title": "Demo Presentation",
        "html": "<!doctype html><html><body>Hello</body></html>",
        "slug": "optional-custom-slug",
        "addRandomSuffix": true,
        "overwrite": false
      }
    },
    {
      "method": "GET",
      "path": "/api/presentations/:slug",
      "description": "Read presentation metadata.",
      "auth": true
    },
    {
      "method": "GET",
      "path": "/api/presentations/:slug/html",
      "description": "Read the stored HTML document.",
      "auth": true
    },
    {
      "method": "PUT",
      "path": "/api/presentations/:slug",
      "description": "Update title and/or HTML for an existing presentation.",
      "auth": true,
      "body": {
        "title": "Updated title",
        "html": "<!doctype html><html><body>Updated</body></html>"
      }
    },
    {
      "method": "DELETE",
      "path": "/api/presentations/:slug",
      "description": "Move a presentation to the trash.",
      "auth": true
    },
    {
      "method": "GET/POST",
      "path": "/api/presentations/:slug/images",
      "description": "List or create JPEG, PNG, WebP and GIF images.",
      "auth": true
    },
    {
      "method": "GET/PUT/DELETE",
      "path": "/api/presentations/:slug/images/:filename",
      "description": "Read metadata, replace or delete a presentation image.",
      "auth": true
    },
    {
      "method": "GET/POST",
      "path": "/api/databases",
      "description": "List or create managed SQLite databases.",
      "auth": true
    },
    {
      "method": "GET/PUT/DELETE",
      "path": "/api/databases/:name",
      "description": "Read, rename or permanently delete a SQLite database.",
      "auth": true
    },
    {
      "method": "GET",
      "path": "/api/databases/:name/schema",
      "description": "Read SQLite tables, columns, views and indexes.",
      "auth": true
    },
    {
      "method": "POST",
      "path": "/api/databases/:name/query",
      "description": "Run a limited SQLite query.",
      "auth": true,
      "body": {
        "sql": "SELECT * FROM items WHERE category = ?",
        "params": [
          "demo"
        ],
        "limit": 100
      }
    },
    {
      "method": "POST",
      "path": "/api/databases/:name/execute",
      "description": "Run one writing or schema-changing SQLite statement.",
      "auth": true,
      "body": {
        "sql": "INSERT INTO items(name) VALUES (?)",
        "params": [
          "Demo"
        ]
      }
    },
    {
      "method": "GET",
      "path": "/api/trash",
      "description": "List recoverable presentations in the trash.",
      "auth": true
    },
    {
      "method": "POST",
      "path": "/api/trash/:id/restore",
      "description": "Restore a presentation from the trash.",
      "auth": true
    },
    {
      "method": "DELETE",
      "path": "/api/trash/:id",
      "description": "Permanently delete a presentation from the trash.",
      "auth": true
    }
  ],
  "examples": {
    "loginCookie": "curl -c cookies.txt -X POST https://slides.marktkauf-wiele.de/api/login -H 'Content-Type: application/json' -d '{\"password\":\"SLIDES_PASSWORD\"}'",
    "listWithCookie": "curl -b cookies.txt https://slides.marktkauf-wiele.de/api/presentations",
    "publishWithBearer": "curl -X POST https://slides.marktkauf-wiele.de/api/presentations -H 'Authorization: Bearer SLIDES_PASSWORD' -H 'Content-Type: application/json' -d '{\"title\":\"Demo\",\"html\":\"<!doctype html><html><body>Hello</body></html>\"}'"
  },
  "baseUrl": "https://slides.marktkauf-wiele.de"
}