MCP Server
Zarządzaj contentem workspace'u Cmssy z poziomu agentów AI przez `@cmssy/mcp-server` — most MCP udostępniający narzędzia do stron, bloków, formularzy i mediów przez stdio.
Przegląd
@cmssy/mcp-server to serwer Model Context Protocol, który łączy agentów AI (Claude Code, Claude Desktop, dowolne narzędzie wspierające MCP) z workspace'em Cmssy. Po skonfigurowaniu agent może listą i edytować strony, dodawać i usuwać bloki, publikować draftów, zarządzać formularzami i więcej — bez wychodzenia z edytora.
Dystrybuowany jest przez npm i komunikuje się przez stdio, więc nie uruchamiasz długożyjącego procesu: agent startuje go na żądanie przez npx.
Czym różni się od HTTP API
- Scope'owany do workspace'u — para token + workspace ID, wszystko egzekwowane po stronie serwera
- Wysokopoziomowe narzędzia —
add_block_to_page,publish_page,patch_block_content, nie surowy GraphQL - Izolacja tenant wbudowana — każde zapytanie jest filtrowane po Twoim workspace; nie dotkniesz przypadkiem innego tenanta
Setup
1. Stwórz token API
Workspace Settings → API Tokens → Create token. Skopiuj wartość cs_… od razu — tokeny wyświetlane są tylko raz. Scope to wyłącznie authn; co token może zrobić zależy od Twojej roli oraz flagi isSuperAdmin.
2. Znajdź ID workspace'u
Workspace Settings → General ma przycisk copy obok ID. To ten sam workspace, do którego przypisany jest Twój token API.
3. Dodaj do konfiguracji MCP edytora
Dla Claude Code edytuj .mcp.json w root projektu (lub ~/.claude/mcp.json dla instalacji globalnej):
{
"mcpServers": {
"cmssy": {
"command": "npx",
"args": [
"-y",
"@cmssy/mcp-server@latest",
"--token", "cs_your_token_here",
"--workspace-id", "507f1f77bcf86cd799439011",
"--api-url", "https://api.cmssy.io/graphql"
]
}
}
}Wspierane są też ekwiwalenty env: CMSSY_API_TOKEN, CMSSY_WORKSPACE_ID, CMSSY_API_URL. Przydatne gdy nie chcesz trzymać tokena w commitowanym configu.
4. Zrestartuj edytor
Claude Code podepnie serwer przy następnym starcie sesji. Powinien pojawić się wpis cmssy w MCP z listą narzędzi.
Dostępne narzędzia
Strony
list_pages— lista wszystkich stron (opcjonalny filtr po name/slug/displayName)get_page— pełna strona z blokami i contentem i18n (po slug lub id)create_page/update_page_settings/delete_pagepublish_page/unpublish_page/revert_to_publishedupdate_page_blocks/update_page_layout
Bloki
list_block_types— enumeracja dostępnych typów bloków ze schema i defaultamiget_block_schema— sprawdzenie pojedynczego typuadd_block_to_page/remove_block_from_pageupdate_block_content— pełny rewrite contentu dla dowolnego kształtu bloku (stringi, tablice, obiekty zagnieżdżone)patch_block_content— surgical patches HTML na polach stringowych (deep dive poniżej)
Formularze
list_forms/get_formcreate_form/update_form/delete_formlist_form_submissions/get_form_submissionupdate_form_submission_status/delete_form_submission
Custom Data Models
Definiuj schematy (ModelDefinitions) i CRUD na rekordach — agenci AI mogą zaprowidzić typy postów blog, katalogi produktów, wpisy katalogowe i więcej. Schema/pola idą za PropertyField z @cmssy/types; rekordy są walidowane względem modelu przy każdym zapisie. Wymaga uprawnień workspace MODELS_VIEW / MODELS_CREATE / MODELS_EDIT / MODELS_DELETE.
Modele
list_models— lista wszystkich ModelDefinitions w workspaceget_model— pobierz model po id (ObjectId) lub slugcreate_model— stwórz model (name, slug, fields, opcjonalniestatusFielddla lifecycle rekordów)update_model— zaktualizuj dowolne pole modelu (zmianafieldswymusza migrację schema przy następnym zapisie rekordu)delete_model— usuń model — kaskada usuwa wszystkie jego rekordy
Rekordy
list_records— listuj rekordy z filtrem MongoDB (JSON), sortowaniem, paginacją, opcjonalniepopulatedla relacjiget_record— pobierz jeden rekord po idcreate_record— stwórz rekord;datakluczowane po field keys modeluupdate_record— zaktualizuj dane rekordu lub przeprowadź tranzycję statusu (walidowane względemstatusField.transitions)delete_record— usuń rekordimport_records— bulk import do 1000 rekordów; zwraca{ importedCount, errors }
Szablony
list_model_templates— lista dostępnych szablonów (E-commerce, Blog, itp.)create_model_from_template— zainstaluj szablon; tworzy wszystkie modele zdefiniowane przez niego i pomija istniejące slugi. Zwraca{ templateId, installedCount, skippedSlugs }
Workspace i media
get_workspace_info— nazwa, plan, limity, użycieget_site_config— języki, nawigacja, włączone funkcjelist_media— wgrane zasoby
patch_block_content — surgical edits
Do precyzyjnych edycji na contencie liczącym wiele KB (artykuły docs, długie wpisy blog), patch_block_content wysyła tylko diff — nie pełny string. W środku MongoDB findOneAndUpdate z $set + arrayFilters, tenant-scoped, atomowe. Typowo ~10× taniej w tokenach niż przesyłanie całego HTML przez update_block_content.
Trzy typy operacji
insert_before / insert_after
Wstaw HTML bezpośrednio przed/po unikalnym markerze. Marker MUSI pasować do dokładnie jednej lokalizacji — zero lub wiele dopasowań odrzuca operację z BAD_USER_INPUT.
{
"op": "insert_after",
"marker": "<h2>Cennik</h2>",
"html": "<p>Plany od 0 zł/msc.</p>"
}replace_section
Zastąp wszystko od startMarker (włącznie) do endMarker (wyłącznie). Oba markery muszą być unikalne.
{
"op": "replace_section",
"startMarker": "<h2>Cennik</h2>",
"endMarker": "<h2>FAQ</h2>",
"html": "<h2>Cennik</h2><p>Nowe plany.</p>"
}Wiele operacji w jednym wywołaniu
Operacje wykonują się po kolei na running result. Każde niepowodzenie (brakujący marker, niejednoznaczny itp.) przerywa cały patch — brak stanu połowicznie zastosowanego.
{
"pageId": "...",
"blockId": "...",
"locale": "pl",
"operations": [
{
"op": "insert_before",
"marker": "<h2>Załącznik</h2>",
"html": "<h2>Nowa sekcja</h2><p>…</p>"
},
{
"op": "replace_section",
"startMarker": "<h2>Cennik</h2>",
"endMarker": "<h2>FAQ</h2>",
"html": "<h2>Cennik</h2><p>Zaktualizowane.</p>"
}
]
}Kiedy operacja zawodzi
- 0 dopasowań — marker nie znaleziony. Sprawdź pasowanie znak po znaku; whitespace i kolejność atrybutów ma znaczenie.
- 2+ dopasowań — marker nie jest unikalny. Dodaj otoczenie HTML do disambiguation. Nakładające się dopasowania też liczą (
"aa"w"aaa"liczy się jako 2), więc unikaj ultra-krótkich markerów. - Pole nie jest stringiem — docelowy
fieldPathwskazuje na tablicę lub obiekt. Użyjupdate_block_contentdla pól strukturalnych. - Bloki layoutu nie są wspierane — header/footer i inne bloki layoutu lecą przez
update_block_content.
patch_block_content vs update_block_content
patch_block_content | update_block_content | |
|---|---|---|
| Kiedy użyć | Punktowe edycje na stringu HTML | Pełny rewrite contentu, dowolny kształt |
| Koszt w tokenach | Proporcjonalny do diffu | Proporcjonalny do pełnego contentu |
| Typowe oszczędności | ~10× na contencie wielo-KB | – |
| Typy pól | Tylko string (przez fieldPath) | Dowolne (stringi, tablice, obiekty) |
| Częściowe niepowodzenie | Cały patch przerywany — brak stanu połowicznego | Cały zapis się udaje lub zawodzi |
| Bloki layoutu | Nie wspierane | Wspierane |
Reguła kciuka: jeśli wcześniej wysyłałeś cały HTML tylko żeby zmienić jeden paragraf, użyj patch_block_content. W innym razie zostań przy update_block_content.
Troubleshooting
- „Workspace not found” — token nie należy do podanego
--workspace-id. Tokeny są scope'owane do jednego workspace; sprawdź parę w Workspace Settings. - „Not authenticated” — token wygasał lub został revoked. Stwórz nowy w Workspace Settings → API Tokens.
- Serwer MCP niewidoczny w edytorze — zrestartuj edytor po zmianach configu. W Claude Code sprawdź Settings → MCP → cmssy dla logów startowych.
- Limity rate / plan — serwer MCP respektuje limity planu workspace'u (max stron, storage, tokeny AI).
get_workspace_infopokazuje aktualne użycie vs limity.
Tryb odpowiedzi (0.6.0)
Od 0.6.0 każde write tool akceptuje opcjonalny parametr response: "minimal" | "full" (default "minimal"). Minimal zwraca małe compact-JSON ack (~100-200 bajtów) z samymi ID i stanem potrzebnym do następnego wywołania — nie pełny zmutowany zasób.
Typowa sesja masowej edycji (agent dotykający tej samej strony docs ~6 razy) odbijała ~170kB HTML na stronę przed 0.6. Minimal mode redukuje to do ~1kB — ~95% cięcia kosztu tokenów odpowiedzi.
Kształty minimalnego ack
- Narzędzia stron (
create_page,update_page_blocks,update_page_settings,publish_page,unpublish_page,revert_to_published,update_page_layout) —{id, slug, hasUnpublishedChanges, updatedAt}(+publisheddla publish/unpublish) - Narzędzia block-on-page (
add_block_to_page,update_block_content,remove_block_from_page) —{pageId, blockId, hasUnpublishedChanges, updatedAt} - Narzędzia formularzy (
create_form,update_form) —{id, slug, status, updatedAt} - Narzędzia modeli (
create_model,update_model) —{id, slug, updatedAt} - Narzędzia recordów (
create_record,update_record) —{id, status, updatedAt}
Kiedy użyć full
Przekaż response: "full" gdy faktycznie potrzebujesz pełnego zmutowanego zasobu w tym samym wywołaniu — np. aby zweryfikować pełną transformację, odczytać pole generowane serwerowo lub debugować. W innym razie łańcuchuj kolejny tool odczytu (get_page / get_form / get_model / get_record).
Narzędzia które nie biorą response
Już zwracają compact ack i są bez zmian: patch_block_content, wszystkie delete_*, update_form_submission_status, import_records, create_model_from_template.
Wersja
Ta dokumentacja opisuje @cmssy/mcp-server 0.6.0. Minimal response mode (patrz wyżej) wszedł w 0.6.0; patch_block_content wszedł w 0.5.0; wcześniejsze wersje mają tylko update_block_content. Przypnij @cmssy/mcp-server@latest w .mcp.json żeby zawsze mieć najnowsze narzędzia.