Built with Chinaski

MCP Server

Chinaski ships a Model Context Protocol (MCP) server that connects AI assistants such as Claude Code directly to your CMS: it exposes the CMS’s full content surface as tools the assistant can call. The server speaks JSON-RPC over stdio, so your assistant launches it as a local process; it doesn’t listen on any network itself. This page explains setting it up, what it can do, and how it behaves.

What it can do

Content CRUD: list/fetch/create/update/delete for pages, posts, blocks, snippets, categories, documents, forms (and their fields), media, navigation items, and themes. The tier covered in the README table is a core subset; the server also includes tools for nav items, media, forms, document handling, theme cloning, orphan-block cleanup, and more; check the tool list your client shows after connecting.

Higher-level tools: create a page or post together with its embedded blocks in a single call (create_page_with_blocks, create_post_with_blocks), translate a page/post into another language, audit for missing translations, bulk-import many pages/posts (with upsert to update by slug+language), bulk-update, create-and-append blocks, and submit/poll asynchronous jobs for very large operations.

Discovery and analysis: get_site_context (languages, themes, block types, categories, recent counts), keyword search across content types, popular-content and content-gap reports (missing meta descriptions, empty bodies, missing featured images), plus audit_meta_descriptions and automatic translation creation.

Resources: content is browsable as resources such as page://en/about-us, post://en/blog/my-post, block://en/hero-home, theme://library/page.tt, before mutating anything.

Prompts: a set of canned prompts, e.g. “Write a blog post in the style of my most popular article”, “Audit all pages for missing meta descriptions”, “Find blocks not referenced by any page or post body”.

Prerequisites

  • A running CMS instance (chinaski@<N> service).
  • An API key with write permission, created under Admin → Settings → API Keys. Read keys won’t create content.

Setup

Point the server at your CMS with two required environment variables:

  • CHINASKI_API_URL: base URL of the CMS (e.g. http://127.0.0.1:3001). The server refuses to start without it.
  • CHINASKI_API_KEY: the API key above. Also required.

Optional tuning:

Variable Default Purpose
CHINASKI_MCP_LOG_DIR logs Where server logs go
CHINASKI_MCP_LOG_FILE <log dir>/mcp-server.log Exact log file name
CHINASKI_MCP_SESSION_DB chinaski-mcp/sessions.db Session-history database
CHINASKI_MCP_SESSION_TTL 86400 (24h) How long session records live
CHINASKI_MCP_CONTEXT_TTL 300 Site-context cache lifetime (seconds)
CHINASKI_MCP_MAX_RETRIES 3 Attempts per REST call

Quick sanity check that the server answers an initialize handshake: echo a JSON-RPC initialize request into the process with both required env vars set and verify you get a result back.

Registering with Claude Code

A sample configuration lives in the repo’s .claude/settings.json: add your API URL and key, and reload Claude Code so the server registers. The registration looks like an mcpServers entry pointing the chinaski server at perl …/chinaski-mcp/chinaski-mcp.pl with the two env vars above.

Running as a service

deploy/chinaski-mcp@.service runs the server under systemd per instance and auto-restarts it on failure. The unit points logs at /var/www/chinaski<N>/logs and the session DB at /var/www/chinaski<N>/chinaski-mcp/sessions.db and supplies the URL/key from /etc/chinaski<N>/mcp-env.

Logs rotate themselves daily (mcp-server.log.YYYY-MM-DD), with the newest 7 kept. Under systemd, everything also goes to journald.

Sessions, retries, and stability

  • Tool calls can be tagged with an optional context argument (a session ID). Tagged calls are stored in the session database (passwords, secrets, and API keys redacted) and can be reviewed later with get_session_history; records expire after the session TTL.
  • Calls to the CMS retry automatically, up to the configured 3 attempts with exponential backoff (1 s, 2 s, 4 s), only on 429, 503, and other 5xx responses.
  • get_site_context results are cached for 5 minutes.
  • The ping handshake reports server status, version, and uptime alongside the CMS’s /api/health result.
  • Unknown tool or prompt names return an error immediately, and sites that don’t exist return a “not found” answer rather than crashing.

Working with content

Notes from the project README that apply hour-to-hour:

  • Embed blocks in page and post bodies with {{block:name}} shortcodes; the static builder resolves them at build time.
  • Creating content doesn’t touch the live site until you trigger a build: call trigger_build, then poll get_build_status.
  • Prefer bulk tools (bulk_import with upsert, create_*_with_blocks) over many one-item calls, and use submit_job for very large batches (on the order of hundreds of items).
Read this site in