About mcp-sanity-images
mcp-sanity-images is an MCP server for moving local images into Sanity CMS. It supports individual and folder uploads, attaching assets to documents, and querying content with GROQ.
Key features
- 01Upload a single image asset
- 02Upload and attach to a document
- 03Batch-upload folder images
- 04List local image files
- 05Run read-only GROQ queries
Use cases
- 01Add a local image to a Sanity document
- 02Upload a directory of image assets
- 03Find document IDs before attaching images
MCP support
Exposes tools to MCP clients for uploading local image files to Sanity, patching document fields, listing files, and querying GROQ.
Configuration
Local server config is the same for every client. Copy it into your client’s MCP config file.
Tools
5Saved tool list · updated 2w ago
| Parameter | Type | Required | Description |
|---|---|---|---|
| alt | string | No | |
| dataset | string | No | |
| filePath | string | Yes | |
| projectId | string | No |
Details
From the project README
MCP server for uploading local images to Sanity CMS.
Lets AI assistants upload files from your filesystem directly into Sanity as image assets.
Quick Start
1. Get your Sanity token
Either set the SANITY_TOKEN env var, or just log in with the Sanity CLI:
npx sanity login
The server reads the token from the Sanity CLI config automatically (~/.config/sanity/config.json on all platforms).
2. Add to Claude Code
claude mcp add sanity-images --scope user --transport stdio \
-e SANITY_PROJECT_ID=your-project-id \
-- npx -y mcp-sanity-images@latest
That's it. Restart Claude Code and the tools are available. Every session runs the latest version automatically.
Also works with
bunx mcp-sanity-images@latestif you have Bun.
Alternative: standalone binary
Download a pre-built binary from Releases:
| Platform | File |
|---|---|
| macOS (Apple Silicon) | mcp-sanity-images-darwin-arm64 |
| macOS (Intel) | mcp-sanity-images-darwin-x64 |
| Linux | mcp-sanity-images-linux-x64 |
| Windows | mcp-sanity-images-windows-x64.exe |
macOS / Linux:
curl -Lo mcp-sanity-images https://github.com/pijusz/mcp-sanity-images/releases/latest/download/mcp-sanity-images-darwin-arm64
chmod +x mcp-sanity-images
sudo mv mcp-sanity-images /usr/local/bin/
claude mcp add sanity-images --scope user --transport stdio \
-e SANITY_PROJECT_ID=your-project-id \
-- /usr/local/bin/mcp-sanity-images
Windows (PowerShell):
Invoke-WebRequest -Uri "https://github.com/pijusz/mcp-sanity-images/releases/latest/download/mcp-sanity-images-windows-x64.exe" -OutFile "$env:LOCALAPPDATA\mcp-sanity-images.exe"
claude mcp add sanity-images --scope user --transport stdio -e SANITY_PROJECT_ID=your-project-id -- "%LOCALAPPDATA%\mcp-sanity-images.exe"
Claude Desktop
Add to your claude_desktop_config.json:
Using npx (auto-updates)
{
"mcpServers": {
"sanity-images": {
"command": "npx",
"args": ["-y", "mcp-sanity-images@latest"],
"env": {
"SANITY_PROJECT_ID": "your-project-id"
}
}
}
}
Using binary (macOS / Linux)
{
"mcpServers": {
"sanity-images": {
"command": "/usr/local/bin/mcp-sanity-images",
"env": {
"SANITY_PROJECT_ID": "your-project-id"
}
}
}
}
Using binary (Windows)
{
"mcpServers": {
"sanity-images": {
"command": "%LOCALAPPDATA%\\mcp-sanity-images.exe",
"env": {
"SANITY_PROJECT_ID": "your-project-id"
}
}
}
}
Tools
| Tool | Description |
|---|---|
upload_image | Upload a single local image to Sanity as an asset |
upload_and_set | Upload an image and patch it onto a document field |
batch_upload | Upload all images from a folder as assets |
list_images | List image files in a directory |
groq_query | Run a GROQ query (find documents before attaching); optional perspective (raw default, published, drafts) |
Supported formats: PNG, JPG/JPEG, WebP, GIF, SVG.
Configuration
| Env var | Required | Default | Description |
|---|---|---|---|
SANITY_PROJECT_ID | Yes | — | Your Sanity project ID |
SANITY_DATASET | No | production | Dataset name |
SANITY_TOKEN | No* | — | API token (*falls back to CLI auth) |
All tools also accept projectId and dataset as parameters, overriding the env vars per-call.
Tool Details
upload_image
Upload a single file and get back the asset reference.
filePath: "/path/to/hero.png"
alt: "Hero banner" (optional — derived from filename)
Returns { assetId, url, alt, reference } — the reference is ready to patch onto any Sanity image field.
upload_and_set
Upload + patch in one call.
filePath: "/path/to/hero.png"
documentId: "product-123" # or "drafts.product-123" to patch the draft
fieldPath: "hero.image"
Before uploading, the tool checks which of <id> and drafts.<id> exist, so a wrong ID uploads nothing:
| You pass | Exists | Patched |
|---|---|---|
product-123 | published only | product-123 |
product-123 | published + draft | product-123, with a note that the draft was left alone (Studio shows the draft, and publishing it overwrites the field) |
product-123 | draft only (never published) | drafts.product-123, with a note and requestedDocumentId |
drafts.product-123 | draft | drafts.product-123 |
| anything | neither | nothing; returns "Document not found" |
The response's documentId is the document actually patched. Mutations are sent with returnIds=true&visibility=sync, so a follow-up groq_query sees the change.
batch_upload
Upload all images from a directory.
directory: "/path/to/images"
recursive: true
Returns { uploaded, assets }. If some files fail, the rest still upload and the failures are listed in failed (with failedCount).
list_images
List image files without uploading — useful for the AI to see what's available.
directory: "/path/to/images"
recursive: true
groq_query
Run any GROQ query (read-only). Long queries are sent via POST automatically. Useful to find document IDs before using upload_and_set.
query: "*[_type == 'product']{_id, title, slug}"
perspective: "raw" # optional: raw (default) | published | drafts
| Perspective | What the query sees |
|---|---|
raw (default) | Published documents and drafts side by side, with their real IDs (drafts.-prefixed for drafts). Pass these IDs straight to upload_and_set. |
published | Published documents only; drafts are invisible. |
drafts | Every draft applied as if published. _id is always the published ID (even for never-published drafts); the stored ID is in _originalId. |
The server pins Sanity API version v2025-02-19. That version made published the API's default perspective. This tool sends raw unless you ask otherwise, so results match what earlier releases (API v2021-10-21, default raw) returned.
Updates
Using npx @latest (recommended): You always get the latest version — no manual updates needed.
Using a binary: The server checks for new releases on startup and logs to stderr if outdated:
[mcp-sanity-images] WARN v0.5.0 available (current: v0.4.1). Download: https://github.com/pijusz/mcp-sanity-images/releases/latest
Check your installed version:
mcp-sanity-images --version
To update, download the new binary and replace the old one.
Development
Requires Bun.
git clone https://github.com/pijusz/mcp-sanity-images.git
cd mcp-sanity-images
bun install
bun test
bun run lint # biome check
bun run build # compile standalone binary
License
MIT
Comments
New to MCP?
From what the protocol is to installing your first server, these answers cover most first questions.
An open protocol that defines how AI applications connect to external tools and data in a uniform way. Clients talk to the model; MCP servers provide tools, resources and prompt templates. They exchange standard messages, so one server can be reused by many clients.