API and MCP

Everything the admin UI does, it does over the same REST API you can call yourself. On top of that API, WordPuppi ships an MCP server so an AI assistant can create sites, write content, and deploy them through conversation. This page covers keys, the two step auth flow, and both MCP transports.

API keys

Create keys under Account, API Keys. The old per site Settings, API Keys path redirects there.

Authenticating

API keys are not sent to the API directly. You exchange one for a short lived JWT, then use the JWT as a bearer token.

Then:

# 1. Exchange the API key for a JWT
curl -X POST https://app.wordpuppi.com/api/auth/token \
  -H "Content-Type: application/json" \
  -d '{"api_key": "YOUR_API_KEY"}'

# 2. Call the API with the JWT
curl https://app.wordpuppi.com/api/v1/sites \
  -H "Authorization: Bearer <token from step 1>"

A tour of the REST surface

Everything below is JWT authenticated and site scoped by slug.

Other prefixes worth knowing: /api/v1/sites/{slug}/media, /api/v1/sites/{slug}/static, /api/v1/sites/{slug}/forms, /api/v1/sites/{slug}/content-types, /api/v1/barks, /api/v1/distribution, and /api/accounts.

The MCP server

WordPuppi ships 70 MCP tools covering sites, content, forms, themes, media, members, distribution, fediverse, and Cloudflare deployment, plus four guided prompts (site_setup, theme_picker, form_builder, deploy_site). Baxter uses the same tools; see Baxter AI.

Every tool carries MCP annotations, so a client can auto approve reads and warn on destructive calls: list_*, get_*, read_*, and status are read only; delete_* are destructive and non idempotent; build, deploy, Cloudflare, distribution, and fediverse tools are open world.

There are two transports onto the same tool surface.

TransportServed byAuthUse it for
stdiothe wpp-mcp binaryAPI key, or email and password via wpp_loginClaude Code, Cursor, Windsurf, a local command server in Claude Desktop
Streamable HTTPwpp-core at /mcpOAuth 2.1 with PKCE, no client secretclaude.ai, Claude Desktop, Claude Code, ChatGPT custom connectors

Remote (paste one URL)

Add a custom connector

In Claude, go to Settings, Connectors, Add custom connector.

Paste the URL

Use https://app.wordpuppi.com/mcp.

Leave both Advanced fields empty

There is no OAuth Client ID and no Client Secret to enter. Leave both blank.

Connect

You are sent to the WordPuppi sign-in page, and that is the whole flow.

Claude Code can do the same from the CLI:

claude mcp add --transport http wordpuppi https://app.wordpuppi.com/mcp
# then, inside Claude Code:
/mcp

Copilot CLI callback configuration

If Copilot asks for an OAuth client ID, use the WordPuppi-maintained metadata document. The entry in ~/.copilot/mcp-config.json is:

{
  "mcpServers": {
    "wordpuppi": {
      "type": "http",
      "url": "https://app.wordpuppi.com/mcp",
      "oauthClientId": "https://app.wordpuppi.com/oauth/clients/copilot-cli.json",
      "tools": ["*"]
    }
  }
}

Use the same deployment hostname for the MCP URL and client ID. Leave the client secret empty and reconnect through Copilot’s /mcp interface.

An invalid redirect_uri error means the callback requested by the client does not match its registration. Copilot uses a loopback callback ending in /; a metadata document listing only /callback will reject it. Register the actual callback path. Only the loopback port may vary between sessions. See GitHub’s OAuth configuration reference and MCP client registration.

Local (stdio)

# Auto-loads saved config, or starts disconnected so the client can call wpp_login
wpp-mcp serve

# Or be explicit with a persistent API key (best for headless use)
wpp-mcp serve --api-url https://app.wordpuppi.com --api-key lo-xxx

# Save credentials once for later `serve` runs
wpp-mcp setup --api-url https://app.wordpuppi.com --email [email protected] --password ...

serve also picks up WPP_EMAIL, WPP_PASSWORD, and WPP_API_URL from the environment. Config for Claude Code looks like this:

{
  "mcpServers": {
    "wordpuppi": {
      "command": "wpp-mcp",
      "args": ["serve", "--api-url", "https://app.wordpuppi.com", "--api-key", "lo-xxx"]
    }
  }
}

Cursor and Windsurf take the same command in their own MCP config.

A typical MCP session

Create the site, choose a theme through settings, write content as HTML with status set to published, build, then deploy:

wpp_create_site then wpp_update_settings then wpp_create_content then wpp_build_site then wpp_deploy_cloudflare.

Security notes

  • stdio runs on your machine and your credentials never leave it.
  • Remote uses OAuth 2.1 with PKCE and per session JWTs minted from validated access tokens. No client secret is stored or transmitted. Tokens are bound to the requested resource, and a 401 from /mcp tells the client where the resource metadata lives and which scopes it needs.
  • Business logic errors come back as tool results marked as errors. Only transport and auth failures surface as MCP protocol errors.
Esc