Connectors · Marketing & media
Sanity MCP server for AI agents.
actionlake is an MCP gateway: one remote MCP server that connects Claude and other MCP clients to Sanity and the rest of your systems. It gives your agent 208 Sanity actions (100 reads, 66 writes and 42 that wait for a confirmation) and holds the Sanity credential itself, so the agent never does. It paces Sanity's limits and records every call.
100,000 free calls a month. No card, no email, no password: press Start a free sandbox on the next screen and keep the key it shows you.
claude mcp add --transport http actionlake https://connect.actionlake.com/mcpdo { action: "sanity.access.get_my_invites", intent: "check which Sanity account is connected"}# Get current user's invites filtered by status/resource · read · 1 upstream call- 208actionsin one signed file
- 100readlook, never change
- 66writecreate and update
- 42wait for a yesdestructive, confirmed first
Set up
Connect Sanity in three steps.
- 01
Add actionlake to Claude.
Run the command once in Claude Code; its consent page can create a free sandbox: 100,000 calls a month, no card. In the Claude app, add a custom connector with the URL below and paste your key on the consent page. Creating a new sandbox from the Claude app is not yet tested by us.
https://connect.actionlake.com/mcp - 02
Connect Sanity.
Bearer token. No consent screen: your agent can connect it for you, but the key then passes through your chat. To keep it out of the model's context, paste it in the console instead. actionlake stores what you paste write-only, sealed under your tenant's key.
tokenSanity API token (manage.sanity.io > your project > API > TokensdatasetYour Sanity datasetproject_idYour Sanity project id
account { op: "connections.requirements", service: "sanity" } # free: exactly what to paste, and what is found for you - 03
Make the first call. Check before a write.
Ask in plain words; Claude picks the action. Before anything changes,
checkvalidates the call and prices it, for free.do { action: "sanity.access.get_my_invites" }# get current user's invites filtered by status/resource · read · 1 upstream callcheck { action: "sanity.agent.prompt", input: { … } }# free: inputs, permissions, cost and confirmations, nothing sent
Sanity at a glance
- Sign-in
- Bearer token. No consent screen: your agent can connect it for you, but the key then passes through your chat. To keep it out of the model's context, paste it in the console instead.
- You provide
token- Setup fields
datasetproject_id- Limits we pace to
- 500 calls a second, per connection
- API covered
- Sanity HTTP API (data plane v2025-02-19; projects v2021-06-07; roles v2021-10-04; access v2025-07-11), at your own api.sanity.io address, set when you connect
- Service file
- Version 1.0.0, signed (Ed25519)
- Cached reads
- 95 of 100 reads, for up to an hour; a write clears what it affects
- Shared entities
- 1, so ask can line Sanity up with your other systems
- Data
- Processed and stored in Sydney, Australia. No US region yet
Capabilities
What an AI agent can do in Sanity.
208 actions in 16 areas. Every one carries its effect, so a key can allow the reads and hold the rest.
- 100readlook, never change
- 66writecreate and update
- 42destructivewait for a confirmation
Applications
4526 read · 12 write · 7 destructive
Create an application · Create a user application · Create user application data · Create a user application for a project
Access
4017 read · 12 write · 11 destructive
List all users of a resource and their assigned roles · Create invite · Create a permission · Create a new Request
Roles
3014 read · 5 write · 11 destructive
Create an organization grant · Create a permission resource · Create a grant · Create a role
Projects
2812 read · 10 write · 6 destructive
Create a CORS entry · Create a dataset · Create a project · Create a new tag for the project
Media library
137 read · 4 write · 2 destructive
Create a new signing key · Generate subtitles using AI · List all signing keys · Query media in the Media Library with a request body
Webhooks
96 read · 2 write · 1 destructive
Create a webhook · List webhook attempts · List attempts for a webhook message · List webhook messages
Functions
84 read · 2 write · 2 destructive
Invoke a function · List environment variable keys · List functions · Read a function
Scheduling
72 read · 5 write · 0 destructive
Create schedule · List schedules · Run schedule · Get schedule by ID
8 more areas · 28 actions
- User attributes 7
- Data 6
- Agent 5
- Assets 3
- Backups 3
- Datasets 2
- Activity 1
- Jobs 1
Top actions
The Sanity API, shaped for agents.
The ids your agent types, what each does, and the one name it shares with other systems.
| Action | What it does | Effect | Same name in |
|---|---|---|---|
sanity.access.get_usersList all users of a resource and their assigned roles | Retrieve a list of all users of a resource along with their assigned roles. | read | this connector |
sanity.agent.promptPrompt the LLM for a response | Prompt the LLM for a response. | write | this connector |
sanity.agent.generateSend an instruction to Generate | Sends an instruction request to Generate for a specific dataset. | write | this connector |
sanity.data.query_postQuery using POST method | Use POST for long queries or large parameter values. | read | this connector |
sanity.access.get_rolesList roles assignable to a user on this resource | Requires permission - `sanity.{resourceType}.roles.read`. | read | this connector |
sanity.roles.list_rolesList all roles | List all roles in a project, including built-in roles, ordered by name. | read | this connector |
sanity.roles.create_roleCreate a role | Create a custom role in a project. | write | this connector |
sanity.projects.list_tagsList tags for a dataset | Returns a list of tags for the dataset. | read | this connector |
sanity.projects.create_tagCreate a new tag for the project | Creates a new tag for the project. | write | this connector |
sanity.backups.list_backupsList backups | List backups. | read | this connector |
sanity.datasets.copy_datasetCopy | The Copy API, also known as Cloud Clone, lets you make a copy of an existing dataset. | write | this connector |
sanity.roles.create_project_grantCreate a grant | Add one or more grants to a custom role in a project. | destructive | this connector |
Try it
Prompts to paste into Claude.
Each one names the Sanity actions it will call, so you know what it reads and what it changes before you send it.
- Readread
Who has access in Sanity? List every user and their role.
calls
sanity.access.get_users - Writewrite
Prompt the LLM for a response in Sanity. Show me exactly what you will send before you save it.
calls
sanity.agent.prompt
Governance for Sanity
Destructive actions wait for a yes.
42 Sanity actions are destructive. The first 10:
- Create a grant
sanity.roles.create_project_grant - Create an organization grant
sanity.roles.create_organization_grant - Add a role to a user
sanity.access.add_role_to_user - Add a role to a user
sanity.roles.add_role_assignment - Apply organization default role to all users
sanity.access.add_default_role_to_users - Give an organization member a role
sanity.roles.add_organization_role_assignment - Delete a role
sanity.roles.delete_role - Delete a role
sanity.access.delete_role - Remove a user from a resource
sanity.access.remove_user - Revoke robot token and delete robot
sanity.access.delete_robot
A destructive action runs only with confirm: true. Under the human policy the agent cannot confirm for itself: the run stops until a named person approves, in the console or from a signed link in an email. The cap on a key is refused before the call is sent, never after.
Delete a role?
intent: the user asked me to delete a role
account { op: "keys.create", name: "sanity-agent", allowed_actions: ["sanity.*"], cap_calls: 2000, confirm_policy: "human_for_writes", approval_rules: [ { match: "sanity.roles.create_project_grant", approver: "[email protected]" }, { match: "sanity.roles.create_organization_grant", approver: "[email protected]" }, { match: "sanity.access.add_role_to_user", approver: "[email protected]" } ]}Cost
What Sanity costs on actionlake.
Every Sanity action is one upstream call, the only thing actionlake bills. Searching, check, cost, account and any call Sanity refused with 401, 403, 429 or a 5xx are free. Paid plans start at US$49 a month for 250,000 calls, with overage from US$0.30 down to US$0.18 per 1,000.
- 1upstream call per actionall 208 Sanity actions
- 208actions pageeach page of a long list is one call
- 95reads can be cacheda cache hit costs nothing
- 100,000calls a month, freepaid plans from US$49 a month for 250,000
Action index
Every Sanity action.
208 actions by area: the id your agent calls, what it does, and its effect.
Applications45
sanity.applications.check_whether_application_can_be_embeddedCheck whether an application can be embeddedreadsanity.applications.create_applicationCreate an applicationwritesanity.applications.create_user_applicationCreate a user applicationwritesanity.applications.create_user_application_dataCreate user application datawritesanity.applications.create_user_application_for_projectCreate a user application for a projectwritesanity.applications.delete_all_user_applicationsDelete all user applicationsdestructivesanity.applications.delete_applicationDelete an applicationdestructivesanity.applications.delete_installation_configurationDelete an installation configurationdestructivesanity.applications.delete_user_applicationDelete a user applicationdestructivesanity.applications.delete_user_application_dataDelete user application datadestructivesanity.applications.delete_user_application_for_projectDelete a user application for a projectdestructivesanity.applications.get_all_user_applicationsGet all user applicationsreadsanity.applications.get_all_user_applications_for_projectGet all user applications for a projectreadsanity.applications.get_app_host_availabilityGet appHost availabilityreadsanity.applications.get_application_by_hostGet application by hostreadsanity.applications.get_application_by_idGet an application by IDreadsanity.applications.get_application_in_organization_by_id_or_slugGet an application in an organization by ID or slugreadsanity.applications.get_installation_by_idGet an installation by IDreadsanity.applications.get_interfaces_by_type_for_applicationGet interfaces by type for an applicationreadsanity.applications.get_interfaces_by_type_for_installationGet interfaces by type for an installationreadsanity.applications.get_project_by_applicationGet project by applicationreadsanity.applications.get_resource_access_for_applicationGet resource access for an applicationreadsanity.applications.get_resource_access_for_installationGet resource access for an installationreadsanity.applications.get_studio_auto_updating_version_statusGet studio auto-updating version statusreadsanity.applications.get_user_applicationGet a user applicationreadsanity.applications.get_user_application_deploymentsGet user application deploymentsreadsanity.applications.get_user_application_deployments_for_projectGet user application deployments for a projectreadsanity.applications.get_user_application_for_projectGet a user application for a projectreadsanity.applications.get_workspaces_for_applicationGet workspaces for an applicationreadsanity.applications.get_workspaces_for_studio_applicationsGet workspaces for studio applicationsreadsanity.applications.get_workspaces_for_user_applicationGet workspaces for a user applicationreadsanity.applications.install_default_singletons_for_organizationInstall the default singletons for an organizationwritesanity.applications.install_singleton_applicationInstall a singleton applicationwritesanity.applications.list_applications_for_organizationList applications for an organizationreadsanity.applications.list_configs_for_installationList configs for an installationreadsanity.applications.list_deployments_for_applicationList deployments for an applicationreadsanity.applications.list_installations_for_organizationList installations for an organizationreadsanity.applications.list_singleton_catalog_for_organizationList the singleton catalog for an organizationreadsanity.applications.reconcile_organization_s_ai_singletons_with_its_ai_features_statusReconcile an organization's AI singletons with its AI features statuswritesanity.applications.register_user_application_configRegister a user application configwritesanity.applications.register_user_application_config_for_projectRegister a user application config for a projectwritesanity.applications.uninstall_singleton_applicationUninstall a singleton applicationdestructivesanity.applications.update_applicationUpdate an applicationwritesanity.applications.update_user_applicationUpdate a user applicationwritesanity.applications.update_user_application_for_projectUpdate a user application for a projectwrite
Access40
sanity.access.accept_inviteAccept invitewritesanity.access.accept_requestAccept requestwritesanity.access.add_default_role_to_usersApply organization default role to all usersdestructivesanity.access.add_role_to_userAdd a role to a userdestructivesanity.access.check_invite_eligibilityCheck invite eligibilityreadsanity.access.check_user_permissionsCheck if current user has specified permissionsreadsanity.access.create_inviteCreate invitewritesanity.access.create_permissionCreate a permissionwritesanity.access.create_requestCreate a new Requestwritesanity.access.create_robotCreate robot and associated tokenwritesanity.access.create_roleCreate a rolewritesanity.access.decline_requestDecline requestwritesanity.access.delete_permissionDelete a permissiondestructivesanity.access.delete_robotRevoke robot token and delete robotdestructivesanity.access.delete_roleDelete a roledestructivesanity.access.get_access_request_stateGet access request statereadsanity.access.get_invite_by_tokenGet invitereadsanity.access.get_invitesGet invitesreadsanity.access.get_my_invitesGet current user's invites filtered by status/resourcereadsanity.access.get_my_requestsList all request for current userreadsanity.access.get_permissionGet a permissionreadsanity.access.get_permissionsGet Permissionsreadsanity.access.get_requestsList all requests for given project/organizationreadsanity.access.get_robotGet robot metadatareadsanity.access.get_robotsGet robots with access to this resourcereadsanity.access.get_roleGet a rolereadsanity.access.get_rolesList roles assignable to a user on this resourcereadsanity.access.get_userGet user and rolesreadsanity.access.get_user_permissionsGet current user permissionsreadsanity.access.get_usersList all users of a resource and their assigned rolesreadsanity.access.remove_own_userRemove own user from a resourcedestructivesanity.access.remove_role_from_userRemove a role from a user in a resourcedestructivesanity.access.remove_userRemove a user from a resourcedestructivesanity.access.replace_roles_for_userReplace the role set for a userwritesanity.access.revoke_current_robot_tokenRevoke current robot tokendestructivesanity.access.revoke_inviteRevoke invitedestructivesanity.access.rotate_current_robot_tokenRotate current robot tokendestructivesanity.access.update_permissionUpdate a permissionwritesanity.access.update_robotUpdate robot tokenwritesanity.access.update_roleUpdate a rolewrite
Roles30
sanity.roles.add_organization_role_assignmentGive an organization member a roledestructivesanity.roles.add_role_assignmentAdd a role to a userdestructivesanity.roles.create_organization_grantCreate an organization grantdestructivesanity.roles.create_permission_resourceCreate a permission resourcewritesanity.roles.create_project_grantCreate a grantdestructivesanity.roles.create_roleCreate a rolewritesanity.roles.delete_organization_grantRemove an organization grantdestructivesanity.roles.delete_organization_role_assignmentRemove a role from an organization memberdestructivesanity.roles.delete_permission_resourceDelete a permission resourcedestructivesanity.roles.delete_project_grantRemove a grantdestructivesanity.roles.delete_roleDelete a roledestructivesanity.roles.delete_role_assignmentDelete a role from a userdestructivesanity.roles.delete_role_mappingsDelete project role mappingsdestructivesanity.roles.get_dataset_aclGet dataset ACLreadsanity.roles.get_organization_role_assignmentGet the roles of a single organization memberreadsanity.roles.get_permission_resourceGet a permission resourcereadsanity.roles.get_roleGet a rolereadsanity.roles.get_role_assignmentGet a user's rolesreadsanity.roles.list_dataset_grantsGet dataset grantsreadsanity.roles.list_organization_grantsGet all grants for current userreadsanity.roles.list_organization_role_assignmentsList organization membersreadsanity.roles.list_permission_resource_schemasList permission resource schemasreadsanity.roles.list_permission_resourcesList permission resourcesreadsanity.roles.list_project_grantsList grants for the current userreadsanity.roles.list_project_member_grantsList grants for a project memberreadsanity.roles.list_project_role_assignmentsList users with rolesreadsanity.roles.list_rolesList all rolesreadsanity.roles.update_permission_resourceUpdate a permission resourcewritesanity.roles.update_roleUpdate a rolewritesanity.roles.update_role_mappingsCreate/update project role mappingswrite
Projects28
sanity.projects.assign_tag_to_datasetAssign a tag to a datasetwritesanity.projects.create_cors_entryCreate a CORS entrywritesanity.projects.create_datasetCreate a datasetwritesanity.projects.create_projectCreate a projectwritesanity.projects.create_tagCreate a new tag for the projectwritesanity.projects.create_tokenCreate a new token for the projectwritesanity.projects.delete_cors_entryDelete a CORS entrydestructivesanity.projects.delete_datasetDelete a datasetdestructivesanity.projects.delete_projectDelete a projectdestructivesanity.projects.delete_tagDelete a tag by identifierdestructivesanity.projects.delete_tokenDelete a token for the projectdestructivesanity.projects.get_embeddings_index_settingsGet embeddings index settings for a datasetreadsanity.projects.list_cors_entriesList all CORS entriesreadsanity.projects.list_datasetsList all datasets available to the projectreadsanity.projects.list_featuresList active features for the projectreadsanity.projects.list_permissionsList your permissions for the projectreadsanity.projects.list_project_tagsList tags for the projectreadsanity.projects.list_projectsList all projectsreadsanity.projects.list_tagsList tags for a datasetreadsanity.projects.list_tokensList tokens for the projectreadsanity.projects.remove_tag_from_datasetRemove a tag from a datasetdestructivesanity.projects.retrieve_projectRetrieve a projectreadsanity.projects.retrieve_tagRetrieve a tagreadsanity.projects.retrieve_userRetrieve a userreadsanity.projects.update_datasetUpdate a datasetwritesanity.projects.update_embeddings_index_settingsUpdate embeddings index settings for a datasetwritesanity.projects.update_projectUpdate a projectwritesanity.projects.update_tagUpdate a tag by identifierwrite
Media library13
sanity.media_library.create_signing_keyCreate a new signing keywritesanity.media_library.delete_signing_keyRevoke a signing keydestructivesanity.media_library.delete_subtitleDelete a subtitledestructivesanity.media_library.generate_subtitleGenerate subtitles using AIwritesanity.media_library.get_playback_infoGet video playback informationreadsanity.media_library.get_references_to_assetList references to an assetreadsanity.media_library.get_signing_keyGet a specific signing keyreadsanity.media_library.list_signing_keysList all signing keysreadsanity.media_library.mutate_mediaMutate media in the Media Librarywritesanity.media_library.queryQuery media in the Media Libraryreadsanity.media_library.query_postQuery media in the Media Library with a request bodyreadsanity.media_library.search_assetsSearch for assets and referencesreadsanity.media_library.upload_asset_from_urlUpload an asset to the media library from a URLwrite
Webhooks9
sanity.webhooks.create_webhookCreate a webhookwritesanity.webhooks.delete_webhookDelete a webhookdestructivesanity.webhooks.get_webhookGet a webhook by IDreadsanity.webhooks.get_webhook_attemptGet a webhook attempt by IDreadsanity.webhooks.list_webhook_attemptsList webhook attemptsreadsanity.webhooks.list_webhook_message_attemptsList attempts for a webhook messagereadsanity.webhooks.list_webhook_messagesList webhook messagesreadsanity.webhooks.list_webhooksList all webhooksreadsanity.webhooks.update_webhookUpdate a webhookwrite
Functions8
sanity.functions.delete_env_varDelete an environment variabledestructivesanity.functions.delete_function_logsDelete logs for a functiondestructivesanity.functions.get_functionRead a functionreadsanity.functions.invoke_functionInvoke a functionwritesanity.functions.list_env_varsList environment variable keysreadsanity.functions.list_functionsList functionsreadsanity.functions.retrieve_function_logsRetrieve function logsreadsanity.functions.set_env_varUpdate an environment variablewrite
Scheduling7
sanity.scheduling.create_scheduleCreate schedulewritesanity.scheduling.get_scheduleGet schedule by IDreadsanity.scheduling.list_schedulesList schedulesreadsanity.scheduling.publish_documentsPublish documentswritesanity.scheduling.run_scheduleRun schedulewritesanity.scheduling.unpublish_documentsUnpublish documentswritesanity.scheduling.update_scheduleUpdate schedulewrite
User attributes7
sanity.user_attributes.create_attribute_definitionCreate Attribute Definitionwritesanity.user_attributes.delete_attribute_definitionDelete Attribute Definitiondestructivesanity.user_attributes.delete_user_attributesDelete User Attributesdestructivesanity.user_attributes.get_my_attributesGet My Attributesreadsanity.user_attributes.list_attribute_definitionsList Attribute Definitionsreadsanity.user_attributes.list_user_attributesGet User Attributesreadsanity.user_attributes.update_user_attributesUpdate User Attributeswrite
Data6
sanity.data.dispatch_actionsDispatch one or more actionswritesanity.data.get_documentsGet one or more documentsreadsanity.data.get_revisionGet a document revisionreadsanity.data.mutateMutate documentswritesanity.data.queryQuery using GET methodreadsanity.data.query_postQuery using POST methodread
Agent5
sanity.agent.generateSend an instruction to Generatewritesanity.agent.patchMake a schema-aware patch to a documentwritesanity.agent.promptPrompt the LLM for a responsewritesanity.agent.transformTransform a documentwritesanity.agent.translateTranslate a documentwrite
Assets3
sanity.assets.link_media_library_assetLink a Media Library asset to a datasetwritesanity.assets.upload_file_asset_from_urlUpload a file asset from a URLwritesanity.assets.upload_image_asset_from_urlUpload an image asset from a URLwrite
Backups3
sanity.backups.get_backupGet a backupreadsanity.backups.list_backupsList backupsreadsanity.backups.set_backups_enabledEnable or disable backupswrite
Datasets2
sanity.datasets.copy_datasetCopywritesanity.datasets.list_copy_jobsList copy jobsread
Activity1
sanity.activity.get_activity_log_eventsGet activity log eventsread
Jobs1
sanity.jobs.job_statusJob statusread
Questions
The Sanity MCP server, answered.
Is there a Sanity MCP server for Claude?
Yes. actionlake is an MCP gateway: a remote MCP server that gives Claude, or another MCP client, 208 Sanity actions across applications, access, roles and projects, through the same eight tools it uses for every other connector. actionlake is independent; it is not made or endorsed by Sanity.
What do I need to connect Sanity?
Sanity API token (manage.sanity.io > your project > API > Tokens. Plus your dataset and your project id. The free call account { op: "connections.requirements", service: "sanity" } lists exactly what to paste.
Can an AI agent delete or change things in Sanity?
Only if its key allows it, and only with an explicit confirmation. 42 Sanity actions are destructive, including create a grant, create an organization grant and add a role to a user. Each runs only with confirm: true. Under the human confirm policy, or an approval rule on the key, the run waits until a named person approves it.
Will an AI agent use up my Sanity API limit?
actionlake paces every call to the limits in the Sanity service file: 500 calls a second per connection. Repeated reads are answered from cache (95 Sanity actions can be), which never reaches Sanity.
What does a Sanity action cost?
One upstream call, the only unit actionlake bills. A list that pages bills one call per page (208 Sanity actions page). Cache hits, searches, dry runs and calls Sanity refused with 401, 403, 429 or a 5xx are free. The Free plan includes 100,000 calls a month with no card. Paid plans start at US$49 a month for 250,000 calls, with overage from US$0.30 down to US$0.18 per 1,000.
Which Sanity API does it cover?
The Sanity HTTP API (data plane v2025-02-19; projects v2021-06-07; roles v2021-10-04; access v2025-07-11) at your own api.sanity.io address, set when you connect. It is built from Sanity's documentation as read on 23 October 2026. 208 actions in 16 areas, each one in the signed service file (version 1.0.0).
Does actionlake keep my Sanity data, and where?
actionlake processes and stores data in Sydney, Australia; there is no US region yet. Reads may be cached for up to an hour, and a write clears the reads it affects. Each run's request and response is kept, sealed, for your plan's trace window: 1 day on Free, 3 days on Starter, 7 days on Pro, 14 days on Team, 30 days on Business and 30 days on Enterprise. Your Sanity credential is sealed under your tenant's key, never logged and never returned. Your traffic is not used to train models.
Which AI clients can use it?
Claude Code, tested by us end to end, and the Claude app as a custom connector, tested by us with an existing key. Other MCP clients that support remote servers over Streamable HTTP (MCP revisions 2025-06-18 and 2025-11-25) and OAuth dynamic client registration, or a bearer header, should connect the same way; we have not tested them. Or plain REST, under the same action names.
Give your agent Sanity today.
Start free - 100,000 calls/month, no card. No signup. Hard caps on every key. Cached answers are free.