Sanity Context

Connect Sanity Context with Mastra

Connect Sanity Context to a TypeScript agent built with Mastra, using MCPClient from @mastra/mcp.

Mastra is a TypeScript framework for building AI agents. This guide shows you how to connect a Mastra agent to Sanity Context, first as a standalone script and then as an agent registered in a Mastra project. MCPClient from @mastra/mcp connects to the Context MCP endpoint over Streamable HTTP and hands its tools to the agent. The same code works whether the endpoint uses Knowledge Base sources, a dataset source, or both.

Prerequisites

To follow this guide, you need:

  • Context MCP endpoint URL: Shown on the MCP endpoint in the Context app in the Sanity Dashboard. To create an MCP endpoint, see Configure a Context MCP endpoint, or expand Create the endpoint with the Sanity CLI (optional) at the end of this section.
  • Organization API token: Create one in Manage under API > Tokens at the organization level. Under Organization permissions, select Context with the Viewer role. Project tokens are refused.
  • Anthropic API key: Mastra's model router reads it from ANTHROPIC_API_KEY. Any provider the router supports works; change the model string and set that provider's key.
  • Node.js 22.18 or later: Mastra requires Node.js 22.13 or later, and 22.18 runs .ts files directly.
Create the endpoint with the Sanity CLI (optional)

You can create a Knowledge Base and an MCP endpoint from the Sanity CLI instead of the Dashboard. If you haven't signed in, run npx sanity@latest login. You still create the organization token in Manage. Replace ORGANIZATION_ID, PROJECT_ID, and KNOWLEDGE_BASE_ID with your own values:

mcp create prints the endpoint URL to use as SANITY_CONTEXT_MCP_URL. To serve a live dataset through a dataset source instead, replace --knowledge-base KNOWLEDGE_BASE_ID with -p PROJECT_ID -d production. See the Context CLI command reference for every flag.

Install dependencies

In a new project directory, install Mastra, its MCP client, and Zod. The TypeScript packages are only needed for type checking:

@mastra/mcp 2 requires zod 4.2 or later as a peer dependency. Set the module type in package.json so Node.js loads agent.ts as an ES module:

For type checking in your editor or with npx tsc, add a tsconfig.json. TypeScript 6 and later don't load @types packages automatically, so list Node's types with "types": ["node"] or TypeScript reports Cannot find name 'process'. Bundler module resolution matches a Mastra project, where imports don't need file extensions.

Set environment variables

Create a .env file next to agent.ts, or in the project root of a Mastra project. Replace each placeholder with your own value:

Create the agent

Create agent.ts next to .env. The standalone script works in three stages:

  • Fetch initial context from the /initial-context HTTP endpoint and add it to the instructions. It's the schema overview for a dataset source, the Knowledge Base outline for Knowledge Base sources, or both if the endpoint has both, plus the endpoint's Instructions. The agent writes accurate queries from the first turn and saves a tool call per conversation. For details, see Inline initial context into your system prompt.
  • Connect to the MCP endpoint with MCPClient, authenticated with your organization token. listToolsWithErrors() returns the tools plus any connection error. Plain listTools() logs a failed connection and returns no tools, so the agent would answer without your content.
  • Drop the initial context tool and create the agent. Mastra prefixes each tool name with the server key, so the tool is sanity_initial_context. The script removes it only when the fetch succeeded; otherwise the agent keeps the tool and calls it instead. Mastra agents stop after 5 steps by default, which can cut off a search and return an empty answer with no error, so the agent sets defaultOptions: {maxSteps: 10}. The option applies to generate(), stream(), and Mastra Studio.

Run the agent

Run the script. Node.js reads the .env file with --env-file. Pass a question as the first argument, or leave it out to ask "What content do we have?"

The agent looks up the answer with the Context MCP tools and prints it to the terminal. With the initial context in its instructions, it answers "What content do you have access to?" without calling a tool first. If the run fails, match the message against the list in Troubleshoot common errors.

Add the agent to a Mastra project

In a Mastra project, register the agent so it appears in Mastra Studio and the server routes. Instead of fetching at import time, the agent fetches the initial context on first use and reuses it. Both instructions and tools accept async functions.

Run npx mastra dev. It loads .env from the project root, and Docs Agent appears in Mastra Studio with the Sanity tools. A project made with create-mastra already includes the mastra CLI. Otherwise, add it with npm install -D mastra.

The cached initial context lasts for the life of the process, so restart the server to pick up changes to the endpoint's Instructions, or replace the cache with one that expires after a few minutes.

One agent per endpoint

Each Context endpoint has its own content source, GROQ filter, and Instructions. Several endpoints can serve the same Knowledge Base, so you can give each agent only the content meant for it. Make one MCPClient per agent, so listing one agent's tools doesn't connect to every endpoint:

Then register one agent per endpoint, for example a support agent on a Knowledge Base endpoint and a catalog agent on a dataset endpoint. Add each endpoint URL to .env, here as SANITY_SUPPORT_MCP_URL and SANITY_CATALOG_MCP_URL:

To authenticate each request with a different token, such as one per customer, pass tools per call instead: create an MCPClient with a unique id for the request, call listToolsetsWithErrors(), and pass the result as agent.generate(prompt, {toolsets}). Toolset keys aren't prefixed, so remove toolsets.sanity.initial_context.

Dataset and Knowledge Base sources

The same code works with an endpoint that serves Knowledge Bases. What changes is what the endpoint returns:

Dataset sourceKnowledge Base source
Content sourceA datasetOne or more Knowledge Bases
Initial contextSchema overviewOutline of each Knowledge Base, with its ID
Tools after filteringsanity_schema_explorer, sanity_groq_query, sanity_array_field_readersanity_knowledge_base_search, sanity_knowledge_base_read

An endpoint can have one dataset source and several Knowledge Base sources. If it has both types, it serves the tools from both columns, and initial context contains both the schema overview and the Knowledge Base outline. See Context MCP tools and Context MCP source types.

Troubleshoot common errors

These are the most common errors and how to fix them:

  • [MODULE_TYPELESS_PACKAGE_JSON] Warning: Module type of file:///…/agent.ts is not specified and it doesn't parse as CommonJS.: The script still runs, but package.json doesn't set the module type. Run npm pkg set type=module.
  • Error: Set SANITY_CONTEXT_MCP_URL and SANITY_ORGANIZATION_TOKEN: The .env file is missing or wasn't loaded. Run the script with --env-file=.env, or check that .env is in the project root for mastra dev.
  • Could not connect to Sanity Context: Failed to connect to MCP server sanity: ... (HTTP 401), after initial-context returned 401: The token is missing, invalid, or belongs to another organization. Check the organization ID in the URL too. Mastra logs the raw connection error a few times before the script throws.
  • 403 from the MCP connection with JSON-RPC error -32007 on an endpoint with a dataset source, or -32006 on an endpoint with only Knowledge Base sources, or the same 403 from the /initial-context fetch with code contextGrantRequired or knowledgeBaseAccessDenied. The messages are "Serving a dataset requires an organization API token with Context access ('sanity.knowledge-base.read'). Create one under your organization's API settings in Manage." (dataset source) and "No access to knowledge base '<knowledge base ID>'. Requires one of: sanity.knowledge-base.read." (Knowledge Base sources only; <knowledge base ID> is a placeholder for the Knowledge Base's ID): On an endpoint with a dataset source, the token isn't an organization API token with Context Viewer permissions. On an endpoint with only Knowledge Base sources, the token has no read access to the Knowledge Base the message names. Project tokens are refused however broad their permissions. Create an organization token with the Context permission, as described in Prerequisites.
  • Could not find API key process.env.ANTHROPIC_API_KEY for model id anthropic/claude-sonnet-5-5: Add ANTHROPIC_API_KEY to the .env file, or the key for the provider in your model string.
  • MCPClient was initialized multiple times with the same configuration options.: Give each MCPClient its own id.
  • The answer is empty after several tool calls: The agent hit Mastra's default limit of 5 steps while still searching. Set defaultOptions: {maxSteps: 10} on the agent.

Next steps

Was this page helpful?