Civitai MCP Server
OfficialClick on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Civitai MCP Serversearch for realistic portrait models"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Civitai MCP Server
Turn your AI agent into a full Civitai participant.
A Model Context Protocol server that gives AI agents first-class access to Civitai: browse models, images, and creators; post and publish work; react, review, follow, and collect; write articles and comments; send and reply to direct messages; create and enter bounties; and (for moderators) manage site announcements and the changelog. 53 tools, exposed over Streamable HTTP or stdio.
There are two ways to use it:
Hosted (recommended) — point your MCP client at
https://mcp.civitai.com/mcp. Zero install.Self-host — run it yourself with pnpm, Docker, or in Kubernetes.
Quick start — hosted (recommended)
The easiest path: add the hosted endpoint to your MCP client and supply your own Civitai API key. Nothing to install or run.
MCP endpoint:
https://mcp.civitai.com/mcpTransport: Streamable HTTP
Auth: send
Authorization: Bearer <YOUR_CIVITAI_API_KEY>with each request
Browse / read tools (search models, images, creators, etc.) work without a key. Everything that writes (posting, reacting, commenting, DMs, bounties, ...) needs one. Grab a key at civitai.com/user/account.
Claude Code (CLI)
claude mcp add --transport http civitai https://mcp.civitai.com/mcp \
--header "Authorization: Bearer YOUR_CIVITAI_API_KEY"Claude Desktop / claude.ai (custom connector)
Note: the claude.ai / Claude Desktop custom-connector UI is OAuth-only — it has no field for a static API key or custom header (anthropics/claude-ai-mcp#112). Because this server currently runs in token-only mode (
OAUTH_ENABLED=false), the custom-connector flow won't work yet. Use Claude Code, Cursor, or any client that supports a bearer header. One-click OAuth connect will work here once Civitai OAuth ships andOAUTH_ENABLED=true.
Cursor (~/.cursor/mcp.json)
{
"mcpServers": {
"civitai": {
"url": "https://mcp.civitai.com/mcp",
"headers": { "Authorization": "Bearer YOUR_CIVITAI_API_KEY" }
}
}
}Generic .mcp.json (any client)
{
"mcpServers": {
"civitai": {
"type": "http",
"url": "https://mcp.civitai.com/mcp",
"headers": { "Authorization": "Bearer YOUR_CIVITAI_API_KEY" }
}
}
}Tip: hand your agent
https://mcp.civitai.com/llms.txt(or justhttps://mcp.civitai.com/) and it can read everything it needs - endpoint, transport, auth, and the full tool catalog - to configure itself. See The/llms.txttrick.
CLI (no MCP client needed)
Some agent runtimes can load a skill but can't edit their MCP client config (no way to add an HTTP MCP server). For those, pull the zero-dependency Node CLI (Node >=18) and drive the server straight from the shell - no MCP client config:
curl -fsSL https://mcp.civitai.com/cli -o mcp-cli.mjs
node mcp-cli.mjs list
node mcp-cli.mjs call search_models '{"query":"anime","type":"Checkpoint"}'Set CIVITAI_API_KEY in your environment for user-action tools (browse/read
tools work without it). The pulled script defaults to the server it came from;
override with MCP_URL or --url. Add --json for the raw JSON-RPC result,
schema <tool> to inspect a tool's input schema, or --help for usage.
Related MCP server: Civitai MCP Server
Self-host
Prefer to run your own instance (private deployment, in-cluster next to the
Civitai app, or local dev)? All three paths below work. The API destination is
fully overridable via CIVITAI_API_URL.
pnpm
pnpm install
cp .env.example .env # set CIVITAI_API_KEY for authenticated tools (optional)
pnpm build
pnpm start # HTTP mode on :3100, GET /healthz, POST /mcpFor local development with hot reload:
pnpm devDocker
Prebuilt images are published to GHCR:
docker run --rm -p 3100:3100 \
-e CIVITAI_API_KEY=YOUR_CIVITAI_API_KEY \
ghcr.io/civitai/civitai-mcp-server:latest
curl localhost:3100/healthzOr build locally:
docker build -t civitai-mcp-server .
docker run --rm -p 3100:3100 -e CIVITAI_API_KEY=YOUR_CIVITAI_API_KEY civitai-mcp-serverMulti-stage build on node:20-alpine, runs as the non-root node user, with a
HEALTHCHECK hitting /healthz.
Kubernetes
See k8s/deployment.example.yaml: Deployment +
Service, CIVITAI_API_KEY from a Secret, CIVITAI_API_URL pointed at the
in-cluster Civitai service, readiness/liveness probes on /healthz.
Local stdio (for agents that spawn a process)
{
"mcpServers": {
"civitai": {
"command": "node",
"args": ["/path/to/civitai-mcp-server/dist/index.js"],
"env": {
"MCP_TRANSPORT": "stdio",
"CIVITAI_API_KEY": "YOUR_CIVITAI_API_KEY"
}
}
}
}Environment variables
Var | Default | Purpose |
|
| Base URL for all API calls (REST + tRPC). In-cluster override, e.g. |
|
| Public website base for user-facing links in tool output (post/model/image/profile URLs). Distinct from |
| — | Bearer token for authenticated calls. Optional for browse tools (enhances results); required for user-action tools. In HTTP mode it is the fallback when a request omits an |
|
|
|
|
| HTTP listen port (http transport only). |
| — | Optional canonical public base URL (e.g. |
|
| Gates one-click OAuth (RFC 9728 protected-resource metadata + the 401 |
| — | Optional: skip the |
|
| Max bytes accepted for an image fetched/decoded by |
| — | CSV allowlist of hostnames permitted for URL-based image uploads. When set, only these hosts (and subdomains) may be fetched. Empty = block only internal/private/loopback/metadata targets (default SSRF guard). |
| — | CSV of |
Per-request auth (multi-tenant)
In HTTP mode, if an incoming MCP request carries Authorization: Bearer <key>,
that key is used for upstream calls instead of CIVITAI_API_KEY. The env key is
the fallback. This lets one deployment serve multiple users without a
per-deployment key (this is how the hosted instance works). In stdio mode only
the env key is used.
Tool catalog (53 tools)
Every tool returns both a compact human-readable text block and a
structuredContent JSON payload. Read-only tools are marked readOnlyHint: true;
destructive ones destructiveHint: true. Errors are normalized to
{ ok: false, error, details? } with isError: true (tools never throw raw;
tRPC zodError validation details are surfaced). The catalog below is the single
source of truth from the live tool registry - the landing page and llms.txt
render the same list.
Browse (no auth required)
Tool | Description |
| Search models. Includes AIR URNs + |
| Batch model details (concurrency 3): versions, files, AIR URNs. |
| Batch version details: files, trigger words, AIR. |
| Search images with full generation metadata ( |
| Batch image details: prompt, negative, sampler, steps, CFG, seed, resources. |
| Search creators/users. |
| List filter enum values (model types, sorts, base models, timeframes). |
Posts (auth - onboarded, non-muted)
Tool | Description |
| Flagship sharing flow via the composite |
| Fetch a post by ID. |
| Publish a draft via |
| Delete a post you own. |
Engagement (auth)
Tool | Description |
| Toggle Like/Dislike/Laugh/Cry/Heart on image/post/article/comment/resourceReview/etc. |
| Star rating (1-5) + recommend + Markdown details. |
| Read your existing review for a model version. |
| Follow/unfollow (resolves username to id). |
| Favorite/bookmark a model (explicit |
| Toggle new-version notifications. |
| Bookmark/un-bookmark an article. |
| Complete TOS/RedTOS/Profile/BrowsingLevels/Buzz. Prerequisite for any verified/guarded write. |
Articles (auth)
Tool | Description |
| Create/update. Markdown to HTML. Cover by UUID or URL (auto-uploaded). |
| getById to rebuild to upsert with the |
| Dedicated |
| Fetch by ID. |
Comments (auth)
Tool | Description |
| Recursive thread fetch with per-comment reaction aggregation. |
| Single comment, uncapped body. |
| Post or reply (reply via |
| Edit, delete, toggle reaction. |
| Moderator-gated upstream. |
Collections (auth - flag-gated collections)
Tool | Description |
| Create/update a collection. |
| Save one item (article/image/post/model) into one or more collections. |
| Follow/unfollow a collection. |
Notifications (auth)
Tool | Description |
| List notifications (unread/category filters). |
| Mark one ( |
| Quick unread count. |
Messaging (auth)
Tool | Description |
| Lookup to |
Chat (auth) - read & reply to existing threads
Tool | Description |
| List your conversations + participants. |
| Read a chat's messages (paginated, |
| Send into an existing chat ( |
| Mark ONE chat read via |
| Blanket clear of every conversation via |
Bounties (auth - flag-gated bounties)
Tool | Description |
| Create via |
| Update a bounty you own. |
| Submit an entry via the composite |
| Award a bounty to an entry. |
Announcements (auth, moderator)
Tool | Description |
| Create/update with field merge. Image by UUID or URL. |
| Delete by ID. |
|
|
Changelog (auth, moderator + changelogEdit flag)
Tool | Description |
| Create/update. Markdown to HTML; |
Images (auth)
Tool | Description |
| URL or base64 to presign to PUT to UUID (+ probed dimensions). |
Utility
Tool | Description |
| Resolve the current user (id, username) and authoritative status via |
Auth & scopes
API key: create one at civitai.com/user/account and send it as
Authorization: Bearer <key>. In HTTP mode the per-request header overrides anyCIVITAI_API_KEYenv fallback.Browse without a key: all
search_*/get_*browse tools work unauthenticated (a key just enriches results).Onboarded, non-muted account: most write actions are
verified(requires onboarding) orguarded(also blocks muted users). A fresh agent account must finish onboarding first - usecomplete_onboarding_step.whoamireports the current onboarding/muted/moderator state.Scoped tokens: if you use a scoped token (rather than a Full key), it must carry the write scope a tool needs (e.g.
MediaWrite,SocialWrite,BountiesWrite,CollectionsWrite). A Full key passes everything.API-key-blocked actions: a few site actions are intentionally unavailable to API keys (e.g. tipping buzz) and are not shipped as tools.
OAuth one-click connect (opt-in, off by default)
Off by default. Set
OAUTH_ENABLED=trueto turn this on. It is gated because it only works once the Civitai app's OAuth dynamic-client-registration (DCR) is live - with it off the server runs in token-only mode (supply an API key viaAuthorization: Bearer; an unauthenticated auth-required call returns the normal "setCIVITAI_API_KEY" error). WithOAUTH_ENABLEDunset or false, the metadata endpoint 404s and no 401 challenge is emitted.
The server is an OAuth 2.0 resource server (RFC 9728 / RFC 6750). When
OAUTH_ENABLED=true and the Civitai app's DCR is live, MCP clients can connect
with no manually pasted API key - they discover the authorization server and run
the standard authorization-code flow on first use:
The client
POSTs atools/callfor an auth-required tool without anAuthorizationheader.The server replies HTTP 401 with
WWW-Authenticate: Bearer resource_metadata="<base>/.well-known/oauth-protected-resource".The client fetches
GET /.well-known/oauth-protected-resource, learns the authorization server (https://civitai.com) and supported scopes, registers itself (DCR), runs the OAuth flow, and retries with a bearer token.
Two behaviors back this:
GET /.well-known/oauth-protected-resource- Protected Resource Metadata: the advertisedresource(the/mcpendpoint),authorization_servers(CIVITAI_API_URL),scopes_supported(canonical scope names), andbearer_methods_supported: ["header"].401 challenge - a
tools/callfor an auth-requiredtool with noAuthorization: Beareris short-circuited at the HTTP layer with a 401 + challenge (instead of a deeper JSON-RPC200 + isErrorthe client can't act on). Browse/read tools stay anonymous;initialize,tools/list,notifications/*, andpingare never challenged. In a batch, if any call needs auth and no bearer is present, the whole request is challenged. The token is not validated here (presence is enough); a bad token surfaces as a tool error upstream.
Prod note: set
PUBLIC_BASE_URL=https://mcp.civitai.comso the advertisedresourceexactly matches the URL clients call - OAuth resource matching is strict, and a Host-derived mismatch would break token audience validation.
The /llms.txt trick
The server exposes an llms.txt-style self-setup guide. Hand your agent the URL and it can configure itself - it reads the MCP endpoint, transport, auth instructions, and the full tool catalog with no human in the loop:
https://mcp.civitai.com/llms.txthttps://mcp.civitai.com/ content-negotiates on User-Agent: a browser gets a
self-contained HTML landing page; anything else (curl, fetch, agents, missing UA)
gets the llms.txt text. The advertised endpoint is derived from the request
Host header (honoring X-Forwarded-Proto/-Host), or pinned via
PUBLIC_BASE_URL, so it is always correct for the deployment serving it.
Transports
Streamable HTTP (default):
POST /mcp. Stateless - a fresh server and transport are created per request (sessionIdGenerator: undefined,enableJsonResponse: true), so it scales horizontally.GET /healthzis a plain 200 with no upstream calls (used by readiness/liveness probes).stdio: set
MCP_TRANSPORT=stdio. stdout is reserved for the protocol; logs go to stderr.
HTTP endpoints
Method & path | Purpose |
| MCP Streamable HTTP endpoint (JSON-RPC). |
| Plain 200 liveness/readiness probe (no upstream calls). |
| Dual-audience index: browser UA gets HTML; everything else gets |
| The agent self-setup guide as |
| The pullable zero-dependency Node CLI ( |
Security
SSRF guard:
upload_imagefetches user-supplied URLs through a guard that blocks internal/private/loopback/metadata targets by default, with an optionalCIVITAI_UPLOAD_ALLOWED_HOSTSallowlist.Size cap: fetched/decoded images are capped at
CIVITAI_UPLOAD_MAX_BYTES(10 MB default) to prevent memory exhaustion.DNS-rebinding protection: enable
MCP_ALLOWED_HOSTSto validate the incomingHostheader against an allowlist.Request body cap: the HTTP layer caps request bodies (25 MB) and returns JSON-RPC parse errors for malformed input.
Container hardening: non-root user, read-only root filesystem, dropped capabilities in the example k8s manifest.
Local dev with the MCP Inspector
pnpm inspector # runs: npx @modelcontextprotocol/inspector tsx src/index.tsThis launches the Inspector against the stdio transport. Set CIVITAI_API_KEY
in your environment first if you want to exercise the authenticated tools.
Development
pnpm typecheck # strict tsc, no emit
pnpm test # vitest (no network - fetch is mocked)
pnpm build # tsc to distSee CONTRIBUTING.md for the contribution flow.
Non-goals
No generation tools (generation lives elsewhere).
No moderation actions.
No model file downloads.
License
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/civitai/civitai-mcp-server'
If you have feedback or need assistance with the MCP directory API, please join our Discord server