@prontosite/mcp 0.8.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -0
- package/README.md +4 -2
- package/api.mjs +18 -0
- package/index.mjs +40 -4
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,23 @@
|
|
|
3
3
|
Alle nennenswerten Änderungen am MCP-Server für ProntoSite. Der Server ist ein dünner Client um die
|
|
4
4
|
ProntoSite Deploy-API; die eigentliche Logik lebt serverseitig.
|
|
5
5
|
|
|
6
|
+
## 0.9.0 – 2026-09-27
|
|
7
|
+
|
|
8
|
+
- **Neu: `site_widgets`** (lesend) – Katalog der verwalteten Widgets einer Website inkl. `aktiv`, `optionen`
|
|
9
|
+
und `schema` je Widget (consent, a11y, notice/Pop-Ups, google-reviews, ps-impressum, ps-datenschutz).
|
|
10
|
+
- **Neu: `site_widget_set`** (schreibend) – Widget aktivieren/deaktivieren und Optionen setzen, mit DEMSELBEN
|
|
11
|
+
Schema-Sanitizer wie das Dashboard (ungültige Felder werden abgewiesen). Listen-Widgets (notice) via
|
|
12
|
+
`optionen.items[]`. So läuft z. B. „Aktiviere das Pop-up auf der Startseite mit diesem Text, einmal je 3 Tage"
|
|
13
|
+
per Zuruf. Ergänzt `site_legal_options`/`site_embed_consent`, ersetzt sie nicht. Betreuer-Token für betreute
|
|
14
|
+
Kunden. Greift beim nächsten Veröffentlichen.
|
|
15
|
+
|
|
16
|
+
## 0.8.1 – 2026-09-26
|
|
17
|
+
|
|
18
|
+
- **Marker-Kurzverweis in den Tool-Beschreibungen** von `site_deploy` und `site_legal_options`: Wer ein
|
|
19
|
+
Template lokal baut, sieht jetzt direkt die Marker-Syntax (`data-ps="formular:kontakt"`,
|
|
20
|
+
`data-ps="impressum"`/`"datenschutz"`, `data-ps="link-impressum"`/`"link-datenschutz"` für Footer-Links)
|
|
21
|
+
plus Link auf die Referenz https://prontosite.io/docs/marker-shortcodes – ohne dass der Nutzer sie nachschlagen muss.
|
|
22
|
+
|
|
6
23
|
## 0.8.0 – 2026-09-23
|
|
7
24
|
|
|
8
25
|
- **Neu: `site_embeds`** – listet alle externen Einbettungen (Host, Seite(n), Kategorie `gated`/`notwendig`). Lesend.
|
package/README.md
CHANGED
|
@@ -84,15 +84,17 @@ sichern: `cp ~/.prontosite.json ~/.prontosite.json.bak`).
|
|
|
84
84
|
| `sites_list` | Alle erreichbaren Websites (Slug, Plan, letzte Änderung, Publish-Bedarf). **Lesend.** |
|
|
85
85
|
| `site_status({ site? })` | Plan, Slug, Live-URL, Publish-Bedarf. **Lesend.** |
|
|
86
86
|
| `site_export({ site?, which, outDir })` | ZIP (`published`\|`draft`\|`original`) lokal speichern. **Lesend.** |
|
|
87
|
-
| `site_deploy({ site?, zipPath, publish?, resetOverlay?, legal?, company?, siteOverride? })` | ZIP importieren, optional live; optional Firmendaten im selben Aufruf setzen. **Schreibend.** |
|
|
87
|
+
| `site_deploy({ site?, zipPath, publish?, resetOverlay?, legal?, company?, siteOverride? })` | ZIP importieren, optional live; optional Firmendaten im selben Aufruf setzen. Beim lokalen Bauen Bausteine im HTML per `data-ps` markieren (`formular:kontakt`, `impressum`/`datenschutz`, `link-impressum`/`link-datenschutz`) → [Marker-Syntax](https://prontosite.io/docs/marker-shortcodes). **Schreibend.** |
|
|
88
88
|
| `site_publish({ site? })` | Aktuellen Stand erneut veröffentlichen. **Schreibend.** |
|
|
89
89
|
| `site_company_get({ site? })` | Firmendaten (Impressum/Footer) lesen. **Lesend.** |
|
|
90
90
|
| `site_company_set({ site?, company, siteOverride? })` | Firmendaten setzen/ergänzen (Teil-Update); füllen Impressum/Datenschutz beim Deploy. **Schreibend.** |
|
|
91
|
-
| `site_legal_options({ site?, impressum?, datenschutz? })` | Anzeige-Optionen der Rechtstexte (showTitle, showDate, draftNotice); ohne Rolle nur lesen. **Schreibend.** |
|
|
91
|
+
| `site_legal_options({ site?, impressum?, datenschutz? })` | Anzeige-Optionen der Rechtstexte (showTitle, showDate, draftNotice); ohne Rolle nur lesen. Rechts-Seiten/-Links im Template per `data-ps="impressum"`/`"datenschutz"` bzw. `link-impressum`/`link-datenschutz` markieren → [Marker-Syntax](https://prontosite.io/docs/marker-shortcodes). **Schreibend.** |
|
|
92
92
|
| `site_domain_status({ site?, check? })` | Kundendomain-Status (verbunden/kanonisch/Zert-bis) + offene Jobs; mit `check` nur Live-DNS-Prüfung. **Lesend.** |
|
|
93
93
|
| `site_domain_connect({ site?, domain, canonical?, action? })` | Eigene Domain verbinden (nginx + HTTPS automatisch, `www`/`apex`) oder trennen; DNS muss auf den Server zeigen; ab Starter-Plan. **Schreibend.** |
|
|
94
94
|
| `site_embeds({ site? })` | Externe Einbettungen der Website: Host, Seite(n), aktuelle Einwilligungs-Kategorie (`gated` = Zwei-Klick \| `notwendig`). **Lesend.** |
|
|
95
95
|
| `site_embed_consent({ site?, host, page?, category, confirmed })` | Einbettung als `notwendig` (§ 25 Abs. 2 Nr. 2 TDDDG, Eigenverantwortung) oder wieder `gated` einstufen; `notwendig` nur mit `confirmed:true` (sonst 400 mit Verantwortungs-Text). Optional seiten-gebunden. Datenschutz/Cookie-Richtlinie passen sich beim nächsten Publish an. **Schreibend.** |
|
|
96
|
+
| `site_widgets({ site? })` | Katalog der verwalteten Widgets: name, aktiv, optionen, schema (consent, a11y, notice/Pop-Ups, google-reviews, ps-impressum, ps-datenschutz). In jedem Plan verfügbar. **Lesend.** |
|
|
97
|
+
| `site_widget_set({ site?, widget, aktiv?, optionen? })` | Widget aktivieren/deaktivieren und Optionen setzen – gleicher Schema-Sanitizer wie das Dashboard; Listen-Widgets (notice) via `optionen.items[]`. Greift beim nächsten Publish. Siehe [Widget-Katalog](https://prontosite.io/docs/widget-katalog). **Schreibend.** |
|
|
96
98
|
|
|
97
99
|
`site_deploy` und `site_publish` sind **schreibende** Aktionen (verändern die Live-Website). Die
|
|
98
100
|
Tool-Beschreibungen weisen den Assistenten an, vorher rückzufragen. Jeder Aufruf wird serverseitig auditiert.
|
package/api.mjs
CHANGED
|
@@ -208,6 +208,24 @@ export async function apiEmbedConsent(cfg, { site, host, page, category = "notwe
|
|
|
208
208
|
return asJson(res);
|
|
209
209
|
}
|
|
210
210
|
|
|
211
|
+
/** GET /api/widgets/<site> – Katalog aller verwalteten Widgets (name, aktiv, optionen, schema). Lesend. */
|
|
212
|
+
export async function apiWidgets(cfg, { site } = {}, fetchImpl = fetch) {
|
|
213
|
+
const { token, slug } = resolveTarget(cfg, site);
|
|
214
|
+
const res = await fetchImpl(`${baseUrl(cfg)}/widgets/${encodeURIComponent(slug)}`, { headers: authHeaders(token) });
|
|
215
|
+
return asJson(res);
|
|
216
|
+
}
|
|
217
|
+
/** PUT /api/widgets/<site>/<widget> {aktiv, optionen} – Widget setzen (gleicher Schema-Sanitizer wie das Dashboard). */
|
|
218
|
+
export async function apiWidgetSet(cfg, { site, widget, aktiv, optionen } = {}, fetchImpl = fetch) {
|
|
219
|
+
if (!widget) throw new Error("widget erwartet (z. B. notice, consent, a11y, google-reviews, ps-impressum, ps-datenschutz).");
|
|
220
|
+
const { token, slug } = resolveTarget(cfg, site);
|
|
221
|
+
const body = {};
|
|
222
|
+
if (aktiv !== undefined) body.aktiv = !!aktiv;
|
|
223
|
+
if (optionen !== undefined) body.optionen = optionen;
|
|
224
|
+
const res = await fetchImpl(`${baseUrl(cfg)}/widgets/${encodeURIComponent(slug)}/${encodeURIComponent(widget)}`, {
|
|
225
|
+
method: "PUT", headers: { ...authHeaders(token), "content-type": "application/json" }, body: JSON.stringify(body) });
|
|
226
|
+
return asJson(res);
|
|
227
|
+
}
|
|
228
|
+
|
|
211
229
|
/** GET/PUT /api/legal-options/<site> – Anzeige-Optionen der Rechtstext-Widgets. Ohne impressum/datenschutz
|
|
212
230
|
* nur LESEN; sonst Teil-Update (nur echte Booleans wirken). */
|
|
213
231
|
export async function apiLegalOptions(cfg, { site, impressum, datenschutz } = {}, fetchImpl = fetch) {
|
package/index.mjs
CHANGED
|
@@ -11,13 +11,13 @@
|
|
|
11
11
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
12
12
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
13
13
|
import { z } from "zod";
|
|
14
|
-
import { loadConfig, apiStatus, apiExport, apiDeploy, apiPublish, sitesList, apiCompanyGet, apiCompanySet, apiLegalOptions, apiDomainStatus, apiDomainConnect, apiEmbeds, apiEmbedConsent } from "./api.mjs";
|
|
14
|
+
import { loadConfig, apiStatus, apiExport, apiDeploy, apiPublish, sitesList, apiCompanyGet, apiCompanySet, apiLegalOptions, apiDomainStatus, apiDomainConnect, apiEmbeds, apiEmbedConsent, apiWidgets, apiWidgetSet } from "./api.mjs";
|
|
15
15
|
|
|
16
16
|
const cfg = loadConfig();
|
|
17
17
|
// Deutliche Startwarnung bei ambiger Konfiguration (Top-Level-Token NEBEN sites-Map). Nach stderr, damit
|
|
18
18
|
// es im MCP-Log/Terminal auffällt; die endgültige Auflösung (Betreuer-Token-Vorrang vs. Map) klärt sites_list.
|
|
19
19
|
for (const w of (cfg.warnings || [])) process.stderr.write("[prontosite-mcp] ⚠ " + w + "\n");
|
|
20
|
-
const server = new McpServer({ name: "prontosite", version: "0.
|
|
20
|
+
const server = new McpServer({ name: "prontosite", version: "0.9.0" });
|
|
21
21
|
const asText = obj => ({ content: [{ type: "text", text: JSON.stringify(obj, null, 2) }] });
|
|
22
22
|
const asError = e => ({ isError: true, content: [{ type: "text", text: "Fehler: " + (e?.message || String(e)) }] });
|
|
23
23
|
const SITE_DESC = "Website-Slug (z. B. 'mas-monti'). Ohne Angabe die Standard-Site der Config. Bei Betreuer-"
|
|
@@ -80,7 +80,12 @@ server.tool(
|
|
|
80
80
|
+ "WICHTIG beim ERST-IMPORT: Frag den Nutzer VOR dem Deploy nach der gewünschten Adresse "
|
|
81
81
|
+ "(„Unter welcher Adresse soll die Website laufen?“, z. B. 'wuerttemberg' → wuerttemberg.prontosite.io) "
|
|
82
82
|
+ "und übergib sie als slug – ohne slug wird die Adresse nur aus Konto-/Seitenname ABGELEITET (die Antwort "
|
|
83
|
-
+ "nennt dann die abgeleitete Adresse; sie ist später änderbar). Bitte VOR dem Aufruf bestätigen lassen."
|
|
83
|
+
+ "nennt dann die abgeleitete Adresse; sie ist später änderbar). Bitte VOR dem Aufruf bestätigen lassen. "
|
|
84
|
+
+ "MARKER (wenn du das Template lokal baust): markiere im HTML mit dem Attribut data-ps, wo Bausteine "
|
|
85
|
+
+ "erscheinen sollen – data-ps=\"formular:kontakt\" (verwaltetes Kontaktformular), data-ps=\"impressum\" bzw. "
|
|
86
|
+
+ "data-ps=\"datenschutz\" (Rechtstext-Seite) und data-ps=\"link-impressum\" / data-ps=\"link-datenschutz\" "
|
|
87
|
+
+ "(Footer-Links auf die Rechtstexte). Beim Import legt ProntoSite die Bausteine automatisch an. "
|
|
88
|
+
+ "Syntax-Referenz: https://prontosite.io/docs/marker-shortcodes",
|
|
84
89
|
{ site: z.string().optional().describe(SITE_DESC + " Erst-Import: 'new' (Einzel) bzw. '<label>:new' (Multi-Site)."),
|
|
85
90
|
slug: z.string().optional().describe("Erst-Import: gewünschte Web-Adresse (Subdomain-Label, z. B. 'wuerttemberg' → wuerttemberg.prontosite.io). Beim Erst-Import den Nutzer danach FRAGEN; wird sie weggelassen, leitet ProntoSite eine Adresse ab. Bei Updates ignoriert."),
|
|
86
91
|
customer: z.string().optional().describe("Nur Betreuer-Token + Erst-Import mit EINEM Manager-Token: Ziel-Konto-ID (k-…). Bei per-Konto-Token in der sites-Map genügt '<label>:new'."),
|
|
@@ -140,7 +145,10 @@ server.tool(
|
|
|
140
145
|
"LESEND/SCHREIBEND: Anzeige-Optionen der Rechtstext-Widgets je Rolle (impressum/datenschutz): showTitle "
|
|
141
146
|
+ "(Überschrift), showDate (Stand-Datum), draftNotice (Entwurfs-Hinweis in der Live-Ausgabe). OHNE impressum/"
|
|
142
147
|
+ "datenschutz nur LESEN. Teil-Update (nur gesetzte Felder). HINWEIS: draftNotice:false blendet den rechtlich "
|
|
143
|
-
+ "empfohlenen Entwurfs-Hinweis live aus (protokolliert) – bitte vorher bestätigen lassen."
|
|
148
|
+
+ "empfohlenen Entwurfs-Hinweis live aus (protokolliert) – bitte vorher bestätigen lassen. "
|
|
149
|
+
+ "MARKER (beim lokalen Bauen): Rechtstext-Seiten und -Links im Template mit data-ps markieren – "
|
|
150
|
+
+ "data-ps=\"impressum\" / data-ps=\"datenschutz\" (Seite) bzw. data-ps=\"link-impressum\" / "
|
|
151
|
+
+ "data-ps=\"link-datenschutz\" (Footer-Links). Syntax-Referenz: https://prontosite.io/docs/marker-shortcodes",
|
|
144
152
|
{ site: z.string().optional().describe(SITE_DESC),
|
|
145
153
|
impressum: legalOptShape.optional(),
|
|
146
154
|
datenschutz: legalOptShape.optional() },
|
|
@@ -203,5 +211,33 @@ server.tool(
|
|
|
203
211
|
}
|
|
204
212
|
);
|
|
205
213
|
|
|
214
|
+
server.tool(
|
|
215
|
+
"site_widgets",
|
|
216
|
+
"LESEND: Katalog der verwalteten Widgets einer Website – je Widget name, Titel, aktiv, aktuelle optionen und "
|
|
217
|
+
+ "das Konfig-schema (Feldtypen/Defaults). Widgets sind in JEDEM Plan (auch Free) verfügbar. Bekannte Widgets: "
|
|
218
|
+
+ "consent (Cookie-Banner), a11y (Barrierefreiheit-Hilfen), notice (Pop-Ups/Hinweise – Modal/Banner/inline, "
|
|
219
|
+
+ "Listen-Widget optionen.items[]), google-reviews, ps-impressum, ps-datenschutz. Basis für site_widget_set.",
|
|
220
|
+
{ site: z.string().optional().describe(SITE_DESC) },
|
|
221
|
+
async ({ site }) => { try { return asText(await apiWidgets(cfg, { site })); } catch (e) { return asError(e); } }
|
|
222
|
+
);
|
|
223
|
+
|
|
224
|
+
server.tool(
|
|
225
|
+
"site_widget_set",
|
|
226
|
+
"SCHREIBEND: ein Widget aktivieren/deaktivieren und/oder seine Optionen setzen – MIT DEMSELBEN Schema-Sanitizer "
|
|
227
|
+
+ "wie das Dashboard (unbekannte/ungültige Felder werden abgewiesen). `optionen` muss zum schema aus site_widgets "
|
|
228
|
+
+ "passen; Listen-Widgets (z. B. notice) erwarten { items: [ { id?, name?, aktiv?, ...Felder } ] }. Beispiel notice: "
|
|
229
|
+
+ "optionen={ items:[{ titel:'Sommerpause', text:'**Geschlossen** bis 1.9.', darstellung:'modal', seiten:['index.html'], "
|
|
230
|
+
+ "haeufigkeit:'tage', ruheTage:3 }] }. Greift beim nächsten Veröffentlichen (publishNeeded). Vorher mit dem Nutzer "
|
|
231
|
+
+ "bestätigen (verändert die Website). Ergänzt die Einzel-Tools site_legal_options/site_embed_consent, ersetzt sie nicht. "
|
|
232
|
+
+ "Betreuer-Token gilt für betreute Kunden.",
|
|
233
|
+
{ site: z.string().optional().describe(SITE_DESC),
|
|
234
|
+
widget: z.string().describe("Widget-Name aus site_widgets (z. B. 'notice', 'consent', 'a11y', 'google-reviews', 'ps-impressum', 'ps-datenschutz')."),
|
|
235
|
+
aktiv: z.boolean().optional().describe("Widget an/aus. Weglassen = unverändert (nur optionen setzen)."),
|
|
236
|
+
optionen: z.any().optional().describe("Konfig-Objekt gemäß schema aus site_widgets. Listen-Widgets: { items: [...] }. Weglassen = aktiv-Status unverändert lassen.") },
|
|
237
|
+
async ({ site, widget, aktiv, optionen }) => {
|
|
238
|
+
try { return asText(await apiWidgetSet(cfg, { site, widget, aktiv, optionen })); } catch (e) { return asError(e); }
|
|
239
|
+
}
|
|
240
|
+
);
|
|
241
|
+
|
|
206
242
|
const transport = new StdioServerTransport();
|
|
207
243
|
await server.connect(transport);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prontosite/mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "MCP-Server für ProntoSite – Website-Status, Export, Deploy und Veröffentlichen direkt aus einem KI-Assistenten (Claude Desktop). Dünner Client um die ProntoSite Deploy-API.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|