MCP Server for AI Integration

Give AI tools structured access to your static site's content, configuration, and build tools via the Model Context Protocol. Auto-configured, no API keys.

AI tools are good at reading files, but they're better when they can work with concepts. The MCP (Model Context Protocol) server built into seite gives AI tools structured access to your site: collections, content items, themes, build actions; instead of making them parse raw markdown and TOML. It is what makes the AI agent and other AI integrations understand your static site generator project as a project, not just a pile of files.

Overview

seite includes a built-in MCP (Model Context Protocol) server that gives AI tools structured access to your site. When you open a seite project in Claude Code, the MCP server starts automatically, no API keys or setup required.

The server exposes your site's documentation, configuration, content, and themes as resources, and provides tools for building, creating content, searching, and applying themes.

Why MCP?

Without MCP, an AI tool working on your site has to:

  1. Find and read seite.toml to understand your configuration
  2. List directories to discover collections
  3. Parse YAML frontmatter from each markdown file
  4. Guess which themes are available by reading template files
  5. Run seite build via shell and parse terminal output for errors

With MCP, the same tool makes a single structured request and gets back typed JSON:

Request:  resources/read  →  seite://content/posts
Response: [
  {"title": "Rust Error Handling", "date": "2026-03-01", "tags": ["rust", "tutorial"], "slug": "rust-error-handling", "url": "/posts/rust-error-handling", "draft": false},
  {"title": "Why Static Sites", "date": "2026-02-15", "tags": ["web"], "slug": "why-static-sites", "url": "/posts/why-static-sites", "draft": false}
]

No file parsing. No guessing. The AI tool gets clean data and can focus on what you actually asked it to do.

How It Works

The MCP server runs as a subprocess (seite mcp) communicating over stdio using JSON-RPC. seite init declares it in the project config of every coding agent you select (--agents, default all), and seite upgrade adds it to existing projects, merging into configs you already have:

AgentProject configOne-time step
Claude Code.mcp.json (pre-approved via enabledMcpjsonServers in .claude/settings.json)May ask you to approve the server on first open; check with /mcp
Codex CLI.codex/config.tomlCodex only loads project config for trusted projects: accept the trust prompt on first run, then codex mcp list shows it
Cursor.cursor/mcp.jsonApprove it in Cursor's MCP settings, or run cursor-agent mcp enable seite
OpenCodeopencode.jsonNone — it starts automatically

Claude Code and Cursor share the same JSON shape:

{
  "mcpServers": {
    "seite": {
      "command": "seite",
      "args": ["mcp"]
    }
  }
}

Codex (.codex/config.toml):

[mcp_servers.seite]
command = "seite"
args = ["mcp"]

OpenCode (opencode.json):

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "seite": { "type": "local", "command": ["seite", "mcp"], "enabled": true }
  }
}

seite upgrade also migrates any older mcpServers block out of .claude/settings.json (Claude Code never reads MCP servers from there) into .mcp.json.

Other MCP clients (Codex CLI, OpenCode, Cursor, ...) run the same seite mcp command from the site directory.

Protocol versions

The server negotiates the MCP revision with each client:

  • initialize handshake — revisions 2025-11-25, 2025-06-18, 2025-03-26, and 2024-11-05. The server answers with the version the client asks for, or 2025-11-25 if it asks for one it doesn't know.
  • Stateless requests — revision 2026-07-28: server/discover lists the supported versions, and each request declares its version in _meta. An unsupported version gets an UnsupportedProtocolVersionError (-32022) listing the supported ones.

Newer fields are only sent to clients that negotiated a revision defining them: tool annotations (read-only/destructive/idempotent hints) from 2025-03-26, tool title, outputSchema, and structuredContent from 2025-06-18. The initialize/server/discover result includes instructions telling the agent when to use the server instead of reading files.

Resources

Resources are read-only data that AI tools can query. Each resource has a URI.

ResourceURIDescription
Documentation indexseite://docsList of all documentation pages with titles and descriptions
Documentation pageseite://docs/{slug}Full markdown content of a specific doc page
Site configurationseite://configCurrent seite.toml serialized as JSON
Content overviewseite://contentAll collections with item counts
Collection itemsseite://content/{collection}Items in a collection with title, slug, url, path (source file, relative to the site root), lang, draft, date, tags, description, weight. A file that fails to parse appears as {path, parse_error} instead of being silently skipped
Themesseite://themesAvailable bundled and installed themes
MCP configurationseite://mcp-configEach agent's project config that exists: .mcp.json and .claude/settings.json (Claude Code), .cursor/mcp.json, opencode.json, .codex/config.toml (as JSON)

Documentation resources are always available (they're embedded in the binary). Site-specific resources (seite://config, seite://content/*, seite://themes, seite://mcp-config) are only available when running inside a page project directory.

resources/templates/list advertises the parameterized URIs seite://content/{collection} and seite://docs/{slug}.

Tools

Tools are actions that AI tools can execute. A tool-execution failure (bad arguments, no site found, a failed build, an unknown theme, an existing file without overwrite, ...) comes back as a normal result with isError: true and an actionable message — only a missing/unknown tool name is a protocol-level error.

A successful result is compact JSON text; clients on 2025-06-18 or newer also get the same object as structuredContent, and every tool except seite_lookup_docs declares an outputSchema for it.

ToolChanges files?
seite_search, seite_get_page, seite_content_stats, seite_list_templates, seite_lookup_docs, seite_checkNo (read-only — seite_check renders into a temporary directory that's discarded, never touching dist/)
seite_buildWrites the output directory
seite_create_contentCreates a content file (replaces one only with overwrite: true)
seite_update_frontmatterRewrites one file's frontmatter
seite_apply_themeWrites templates/base.html (backs up a customized one)
seite_create_collectionRewrites seite.toml, creates a content directory

seite_build

Build the site to the output directory.

ParameterTypeRequiredDescription
draftsbooleanNoInclude draft content in the build (default: false)
strictbooleanNoFail (isError) if the build produced warnings or broken internal links (default: false)

Returns build statistics, warnings (e.g. a custom template that failed to parse and fell back to the built-in default), broken_links and missing_assets (each [{target, sources}] — internal links pointing at pages that don't exist, and asset references with no matching file), and diagnostics (the same structured list seite_check returns: severity, stable code, message, and source file/line when known).

seite_check

Report every problem in the site without touching the output directory — the same checks as seite check: config syntax and unknown keys, frontmatter, shortcodes, data files, templates, a full render, broken internal links, and missing assets.

ParameterTypeRequiredDescription
draftsbooleanNoAlso check draft content (default: false)
strictbooleanNoTreat warnings as failures too (default: false)

Returns ok (false when there are errors, or any warning with strict: true), summary ({errors, warnings} counts), and diagnostics — each with severity, a stable code (e.g. frontmatter-parse, broken-link, config-unknown-key), message, and file/line/column/hint when known. Run it after making changes to catch problems before building.

seite_create_content

Create a new content file with frontmatter (same rules as seite new).

ParameterTypeRequiredDescription
collectionstringYesCollection name, e.g. posts, docs, pages, changelog, roadmap (singular aliases like post work)
titlestringYesTitle of the content
slugstringNoFilename slug (lowercase letters, digits, -, _); defaults to a slug of the title
descriptionstringNoFrontmatter description (meta description and listings)
tagsstring[]NoTags for the content
bodystringNoMarkdown body content; omit for frontmatter only
draftbooleanNoCreate as draft (default: false)
weightintegerNoOrdering weight for non-date collections (lower sorts first)
extraobjectNoArbitrary frontmatter data exposed to templates as page.extra
subdirstringNoSub-directory inside a nested collection, e.g. guides (docs only)
langstringNoLanguage code for a translation (must be configured under [languages]); adds a .{lang}.md suffix
overwritebooleanNoReplace the file if it already exists (default: false — otherwise the call fails)

Returns the source path (relative to the site root) and the url it will be published at.

seite_get_page

Inspect one content file as the build sees it. Pass exactly one of:

ParameterTypeRequiredDescription
pathstringOne ofSource file, relative to the site root (content/docs/guides/intro.md) or to the content directory
urlstringOne ofPublished URL (/docs/guides/intro; a full URL on the site's base_url also works)

Returns path, collection, url, slug, lang, draft, date, the resolved frontmatter (e.g. a date taken from the filename), word_count, reading_time, the markdown body, the rendered body html (shortcodes + markdown, without the page template; null with a render_error if rendering fails), and output_path when the page has been built.

seite_update_frontmatter

Edit only the frontmatter of a content file. The markdown body is kept byte-for-byte.

ParameterTypeRequiredDescription
pathstringYesContent file (.md) inside the content directory
setobjectNoTop-level keys to add or replace (e.g. {"tags": ["rust"], "draft": false})
unsetstring[]NoTop-level keys to remove (title can't be removed)

The result must still parse and keep its required fields (title; a date for dated collections, from date or the filename). Paths outside the content directory are refused. Edits are targeted: only the lines of the keys you set or unset change (new keys are appended at the end of the frontmatter), so comments, key order, and the formatting of every other key are preserved. If the frontmatter uses YAML the line editor can't follow (e.g. a flow mapping), it is re-serialized instead and the result's notes say so. Repeating the same update writes nothing (changed: false).

Search site content (including drafts) by keyword.

ParameterTypeRequiredDescription
querystringYesSearch keywords (case-insensitive substring match)
collectionstringNoLimit search to a specific collection (singular aliases work)
limitintegerNoMaximum results to return, 1-100 (default: 20)

Matches titles, descriptions, tags, and body text, ranked title > description/tags > body. Returns total matches and the returned subset, each with source path and published url.

seite_content_stats

Content health overview, optionally for one collection: item and draft counts, items missing a description, dated items without tags, future-dated items, files that fail to parse, and — on multilingual sites — default-language items missing a translation, per configured language. Lists are capped at 50 per category; the totals counts are exact.

seite_list_templates

No parameters. Returns what an agent needs before editing templates: the user templates in templates/ (and which embedded defaults they override), the blocks defined in the active base.html, the Tera context variables available to each template kind (item pages, homepage, collection indexes, 404, tag pages, shortcodes), built-in and custom shortcodes with their parameters and usage, and the keys of loaded data files.

seite_create_collection

ParameterTypeRequiredDescription
presetstringYesposts, docs, pages, changelog, roadmap, or trust

Adds the collection to seite.toml and creates its content directory — the same as seite collection add. Fails if the collection already exists.

seite_apply_theme

Apply a bundled or installed theme to the site.

ParameterTypeRequiredDescription
namestringYesTheme name (default, minimal, dark, docs, brutalist, bento, landing, terminal, magazine, academic, or an installed theme)

If the current base.html has been customized (it matches no known theme), it's backed up to base.html.bak (or base.html.bak.N) before being replaced, and the backup path is returned.

seite_lookup_docs

Look up page documentation by topic or keyword.

ParameterTypeRequiredDescription
querystringNoSearch keywords to find in documentation
topicstringNoSpecific doc topic slug (e.g., configuration, templates, deployment)

When topic matches a doc slug, returns the full page. When query is provided, searches across all documentation and returns matching sections with context.

Practical Example

Say you're using Claude Code and ask: "Add a new blog post summarizing our three most recent posts."

Without MCP, the AI has to glob for markdown files, read each one, parse YAML frontmatter manually, sort by date, extract titles and descriptions, then write the summary post. Multiple tool calls, fragile parsing, easy to miss edge cases.

With MCP, the AI calls seite://content/posts, gets a sorted JSON array of all posts with metadata, picks the top three, and writes the summary. One resource call instead of a dozen file operations. The AI agent uses this automatically. You don't need to think about it.

Manual Testing

You can test the MCP server manually by sending JSON-RPC messages:

echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{}}}' | seite mcp

A full session requires the initialization handshake first, then queries:

printf '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{}}}\n{"jsonrpc":"2.0","method":"notifications/initialized"}\n{"jsonrpc":"2.0","id":2,"method":"tools/list"}\n' | seite mcp

Next Steps