OmoolaEx Logo

Building Production CMS from AI Prototypes: A Practical Guide to Sanity's MCP Server

OmoolaEx Team
15 min read
Building Production CMS from AI Prototypes: A Practical Guide to Sanity's MCP Server

It was 2 AM when I realized I'd built myself into a corner. I had 47 markdown files sitting in a folder, each one representing a different resource in what was supposed to be our company's internal knowledge base. The AI assistant had done a solid job generating content. Then my client asked a simple question: "Can we add categories? And maybe let the marketing team edit these without touching code?"

Markdown files work great for prototypes. They're simple, version-controllable, and AI models handle them well. But they're terrible for actual content management. No relationships, no media handling, no user-friendly editing interface. I needed a proper CMS, but I didn't want to lose the speed of AI-assisted development that had gotten me this far.

I found Sanity's MCP server while researching solutions. The idea was straightforward: keep working with AI assistants naturally, but have everything flow directly into a production-grade CMS. No more copy-pasting between tools, no more manual data entry, no more markdown file management.

I was skeptical. In my 8 years of development, I've seen plenty of tools promise to change everything only to add more complexity. But I had a weekend free, so I decided to try it.

This article walks through what I learned. The good parts, the frustrating parts, and the parts that actually changed how I work. You'll see the actual commands I ran, the prompts I used, the mistakes I made, and the techniques that worked. By the end, you'll know whether this approach fits your projects and exactly how to implement it. Whether you're building client projects, internal tools, or just exploring AI-assisted development, this guide will save you the trial-and-error I went through in my IT consulting work.

Part 1: Understanding MCP and What It Actually Means for Developers

The Model Context Protocol (MCP) is basically a standardized way for AI assistants to interact with external tools and services. Think of it as an API, but designed specifically for AI models rather than human developers.

When you chat with an AI assistant normally, it's like talking to someone with no hands. They can think, reason, and suggest, but they can't actually do anything in your systems. MCP has become the dominant protocol because it gives them hands. Specifically, it gives them the ability to read your schema, create documents, run queries, and manage content through natural conversation.

I was genuinely surprised by how natural it felt. I expected to be writing structured commands or learning a new syntax. Instead, I just described what I wanted: "Create a blog post schema with title, content, author, and categories." The AI understood the intent, checked Sanity's schema requirements, and generated valid schema code. No documentation diving, no syntax errors, no back-and-forth. This is particularly valuable when comparing Claude Code vs Cursor for AI-assisted development workflows.

The big advantage is how it collapses the feedback loop. Traditionally, working with a CMS means thinking about structure, writing schema code, testing in Studio, realizing you need changes, editing code, restarting, testing again. With MCP, you describe what you want, it's done, refine if needed. The AI has direct access to your Sanity project, so changes happen in real-time.

But MCP isn't always the right choice. I learned this the hard way on my second project. If you're working on a mature system with complex business logic, extensive custom validation, or highly specific workflows, you'll still want to write code manually. MCP works best in these scenarios:

  • Rapid prototyping and MVPs where speed matters more than perfection
  • Content-heavy projects where content strategy and content creation are the main tasks
  • Exploratory work where you're still figuring out the data model
  • Projects with straightforward CRUD operations
  • When you're learning Sanity and want to understand patterns quickly

The workflow transformation was significant for me. I used to spend 40% of my time on boilerplate (setting up schemas, creating sample content, writing basic queries). Now that time is compressed to maybe 10%, and I spend the saved time on the interesting problems: business logic, user experience, performance optimization. It's not that MCP writes better code than I do. It handles the tedious parts so I can focus on the parts that actually require human judgment, similar to how we approach strategic IT consulting.

Part 2: Getting Started with the Real Setup Process

I'll walk you through the setup exactly as I did it, including the one mistake that cost me 20 minutes of confusion.

Prerequisites Check

First, make sure you have Node.js 18+ installed. I was running Node 20.10.0 when I did this. You'll also need a Sanity account (the free tier works fine for getting started).

Method 1: Automatic Setup (Recommended)

The easiest path is using Claude Desktop with automatic MCP configuration. Based on Cursor's performance in AI coding benchmarks, you can also use Cursor for similar workflows. Here's what I did:

terminal
1# Install Claude Desktop if you haven't already
2# Then install the Sanity MCP server
3npx @sanity/mcp-server init

This command detects that you're using Claude Desktop and offers to configure everything automatically. When I ran it, I saw a prompt asking if I wanted automatic setup. I said yes, and it created the MCP configuration file in the right location, launched my browser for Sanity authentication, stored the credentials securely, and restarted Claude Desktop automatically.

The authentication flow was straightforward. I logged into my Sanity account, authorized the MCP server, and that was it. The whole process took maybe 3 minutes.

Method 2: Manual Setup

If you're using a different AI client or want more control, here's the manual approach. This is where I made my mistake, so learn from my pain.

terminal
1# Install the MCP server globally
2npm install -g @sanity/mcp-server
3
4# Initialize and authenticate
5sanity-mcp init

I forgot to actually configure my AI client to use the MCP server. The installation worked fine, authentication succeeded, but nothing happened when I tried to use it. I spent 20 minutes troubleshooting before realizing I needed to add the configuration to my AI client's settings.

For Claude Desktop, you need to edit the config file at:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows: %APPDATA%\Claude\claude_desktop_config.json
claude_desktop_config.json
1{
2  "mcpServers": {
3    "sanity": {
4      "command": "npx",
5      "args": ["-y", "@sanity/mcp-server"]
6    }
7  }
8}

After adding this and restarting Claude Desktop, everything worked.

Verification

To verify everything's working, I opened Claude Desktop and asked: "Can you list my Sanity projects?" The AI came back with a list of my projects, which meant the MCP connection was live.

Troubleshooting Tips from Experience

If things aren't working, here's what I learned to check:

  • Restart your AI client completely after configuration changes (a simple reload isn't enough)
  • Check that your Sanity token has the right permissions (you need Editor or Admin)
  • Make sure you're using Node 18+ (I've heard of issues with older versions)
  • If authentication fails, try running 'sanity-mcp logout' and starting fresh
  • On Windows, watch out for path issues in the config file (use forward slashes)

The setup process has gotten smoother since I first tried it. The automatic method especially is nearly foolproof now. But if you hit issues, it's usually just a configuration detail, not a fundamental problem.

Part 3: Building a Tech Resource Library

I'll walk you through building a real project: a Tech Resource Library for IT consulting. This is based on an actual internal tool I built for OmoolaEx. I'll show you the exact prompts I used and what happened at each step.

Step 1: Creating the Schema

I started with this prompt:

"I need to create a Tech Resource Library for an IT consulting company. We need three content types: Resources (articles, guides, tools), Categories (to organize resources), and Authors (team members who create content). Each resource should have a title, description, content body, category reference, author reference, tags, and publication date. Can you create these schemas?"

The AI understood the relationships. It created proper reference fields between resources and categories, added slug fields automatically (which I'd forgotten to mention), and even included helpful descriptions in the schema. The whole thing took about 30 seconds.

Here's what the resource schema looked like:

schemas/resource.js
1export default {
2  name: 'resource',
3  title: 'Resource',
4  type: 'document',
5  fields: [
6    {
7      name: 'title',
8      title: 'Title',
9      type: 'string',
10      validation: Rule => Rule.required()
11    },
12    {
13      name: 'slug',
14      title: 'Slug',
15      type: 'slug',
16      options: {
17        source: 'title',
18        maxLength: 96
19      },
20      validation: Rule => Rule.required()
21    },
22    {
23      name: 'description',
24      title: 'Description',
25      type: 'text',
26      rows: 3
27    },
28    {
29      name: 'body',
30      title: 'Content',
31      type: 'array',
32      of: [{type: 'block'}]
33    },
34    {
35      name: 'category',
36      title: 'Category',
37      type: 'reference',
38      to: [{type: 'category'}]
39    },
40    {
41      name: 'author',
42      title: 'Author',
43      type: 'reference',
44      to: [{type: 'author'}]
45    },
46    {
47      name: 'tags',
48      title: 'Tags',
49      type: 'array',
50      of: [{type: 'string'}]
51    },
52    {
53      name: 'publishedAt',
54      title: 'Published At',
55      type: 'datetime'
56    }
57  ]
58}

One thing I learned: be specific about relationships in your initial prompt. My first attempt didn't mention that categories and authors should be references, and the AI created them as simple string fields. I had to refine with: "Make category and author reference fields to their respective document types."

Step 2: Adding Sample Content

With the schema in place, I needed content:

"Create 5 categories relevant to IT consulting: Cloud Infrastructure, Security Best Practices, DevOps Automation, Data Analytics, and Software Architecture. Then create 3 author profiles for our team. Finally, create 10 sample resources covering various IT consulting topics, distributed across the categories."

The AI created all the categories first (it needed those IDs for the resources), then the authors, then the resources with proper references. The content it generated was surprisingly relevant. Not just lorem ipsum, but actual IT consulting topics like "Implementing Zero Trust Architecture" and "Kubernetes Cost Optimization Strategies."

The initial content was a bit generic though. I followed up with:

"Make the resource content more detailed. Each should have at least 3-4 paragraphs with specific technical details, code examples where relevant, and practical implementation advice."

The AI went back and enriched the content. This iterative refinement is important. Start broad, then add specificity.

Step 3: Setting Up Sanity Studio

Now I needed a way for non-technical team members to manage this content. I asked:

"Help me set up Sanity Studio for this project. I want custom list views showing resource titles, categories, and publication dates. Also add preview functionality."

The AI walked me through creating a sanity.config.js file with custom desk structure. It added list previews that showed exactly what I asked for. It also suggested adding a custom input component for tags with autocomplete. I hadn't thought of that, but it made the editing experience much better.

sanity.config.js
1import {defineConfig} from 'sanity'
2import {deskTool} from 'sanity/desk'
3import {visionTool} from '@sanity/vision'
4import {schemaTypes} from './schemas'
5
6export default defineConfig({
7  name: 'default',
8  title: 'Tech Resource Library',
9  projectId: 'your-project-id',
10  dataset: 'production',
11  plugins: [
12    deskTool({
13      structure: (S) =>
14        S.list()
15          .title('Content')
16          .items([
17            S.listItem()
18              .title('Resources')
19              .child(
20                S.documentTypeList('resource')
21                  .title('Resources')
22                  .defaultOrdering([{field: 'publishedAt', direction: 'desc'}])
23              ),
24            S.listItem()
25              .title('Categories')
26              .child(S.documentTypeList('category').title('Categories')),
27            S.listItem()
28              .title('Authors')
29              .child(S.documentTypeList('author').title('Authors')),
30          ]),
31    }),
32    visionTool(),
33  ],
34  schema: {
35    types: schemaTypes,
36  },
37})

I ran 'npm run dev' and opened Studio. Everything was there, properly organized, with all the content already populated. I'd gone from idea to working CMS in about 15 minutes.

Step 4: Building the Next.js Frontend

The final piece was a public-facing website. My prompt:

"Create a Next.js 14 frontend for this resource library. I need a homepage listing all resources with filtering by category, individual resource pages, and a search function. Use the App Router and Server Components."

The AI generated a complete Next.js project structure with Sanity client configuration, GROQ queries for fetching resources, Server Components for the resource list and detail pages, a category filter component, and basic styling with Tailwind CSS.

Here's the GROQ (Graph-Relational Object Queries) query it generated for the homepage:

app/page.js
1const query = `*[_type == "resource"] | order(publishedAt desc) {
2  _id,
3  title,
4  slug,
5  description,
6  publishedAt,
7  "category": category->title,
8  "author": author->name,
9  tags
10}`

What I learned about prompt engineering: Be specific about the tech stack version (Next.js 14, not 13) and architecture patterns (App Router vs Pages Router). My first attempt gave me Pages Router code, which wasn't what I wanted. A quick clarification fixed it.

The whole tutorial took me about 45 minutes from start to finish, including the time I spent refining content and fixing my prompt mistakes. Compare that to the 2-3 days this would have taken manually.

Part 4: Advanced Techniques Beyond Basic CRUD

Once I got comfortable with basic operations, I started exploring more advanced capabilities.

Content Audits

I needed to audit our content for missing metadata. Instead of writing a script, I just asked:

"Find all resources that are missing descriptions or have empty tag arrays. Give me a report with titles and IDs."

The AI wrote and executed a GROQ query, then formatted the results in a nice table. It found 7 resources with issues. I followed up with: "Add placeholder descriptions to these resources based on their titles and content." Done in seconds.

Schema Evolution

A few weeks in, we needed to add a 'difficulty level' field to resources. I was nervous about migrating existing content, but:

"Add a difficulty field to the resource schema with options: Beginner, Intermediate, Advanced. Then analyze existing resources and assign appropriate difficulty levels based on their content complexity."

The AI updated the schema, then went through each resource and assigned a difficulty level. It even explained its reasoning for each assignment. This kind of intelligent migration would have been a pain to script manually.

GROQ Query Generation

GROQ is powerful but has a learning curve. I found I could describe what I wanted in plain English (the GROQ cheat sheet is also incredibly helpful):

"Write a GROQ query that gets the 5 most recent resources in the Security category, including the author's name and bio, and count how many resources each author has written."

The AI generated:

1*[_type == "resource" && category->title == "Security Best Practices"] 
2  | order(publishedAt desc) [0...5] {
3  _id,
4  title,
5  slug,
6  publishedAt,
7  "author": author->{
8    name,
9    bio,
10    "resourceCount": count(*[_type == "resource" && author._ref == ^._id])
11  }
12}

This saved me from diving into GROQ documentation. I learned GROQ patterns organically by seeing examples that solved my actual problems.

Working with Releases

We needed to prepare a batch of content for a future launch without publishing it immediately. Sanity's release feature was perfect, and the AI made it simple:

"Create a release called 'Q2 Launch' and add all resources tagged with 'q2-2024' to it."

The AI created the release, found the matching resources, and added them. When launch day came, publishing everything was a single command.

AI-Powered Media Features

I experimented with AI-generated images for resources that didn't have featured images:

"For each resource without a featured image, generate an appropriate technical illustration based on the resource title and category."

The results were hit-or-miss. Some images were perfect, others too generic. But the capability is there, and it's improving. For placeholder images during development, it's useful.

Part 5: Best Practices and Lessons from the Trenches

After building several projects with this approach, I've developed some hard-won principles.

Schema Design Principles

Start simple, evolve gradually. My biggest mistake was trying to design the perfect schema upfront. I'd describe every field, every validation rule, every possible relationship. The AI would create it, but then I'd realize I'd over-engineered it.

Better approach: Start with core fields only. Use the system for a day. Then add complexity based on actual needs. The AI makes schema evolution so easy that there's no penalty for starting simple.

Always include slug fields for content types that will have public URLs. The AI usually adds these automatically, but double-check. I once forgot, and retrofitting slugs to 50 documents was annoying.

Use references liberally. Don't embed related data, reference it. This keeps your content normalized and makes updates easier. The AI handles reference resolution in queries automatically.

Prompt Engineering Techniques

Be specific about data types and validation. Instead of "add a price field," say "add a price field as a number with minimum value 0 and maximum 999999." The AI will create proper validation rules.

Provide examples when generating content. "Create 5 blog posts about cloud computing" gives generic results. "Create 5 blog posts about cloud computing, covering topics like serverless architecture, container orchestration, cloud cost optimization, multi-cloud strategies, and cloud security" gives much better content.

Use iterative refinement. Don't try to get everything perfect in one prompt. Start broad, review the results, then refine. "Make the descriptions more technical" or "Add more specific examples" works better than trying to specify everything upfront.

Security Considerations

The MCP server uses your Sanity credentials, which means it has the same permissions you do. This is powerful but requires care. I learned to follow security best practices:

  • Use a dedicated Sanity project for experimentation, not production
  • Review what the AI plans to do before confirming destructive operations
  • Keep audit logs enabled in Sanity to track all changes
  • Use Sanity's role-based access control to limit what the MCP token can do

I once accidentally asked the AI to "clean up old drafts" without being specific enough. It deleted more than I intended. Fortunately, Sanity's history feature let me restore everything, but it was a good lesson in being precise.

Performance Optimizations

When generating large amounts of content, do it in batches. Asking for 100 documents at once can timeout or hit rate limits. I found that batches of 10-20 work reliably.

For GROQ queries, let the AI optimize them. I'd write a query that worked but was slow, then ask: "Can you optimize this GROQ query for better performance?" The AI would add projections to limit fields, use references more efficiently, or restructure the query.

Part 6: Real-World Applications

Let me share some specific scenarios where this approach has been valuable in my IT consulting work.

Client Projects

We had a client who needed a knowledge base for their SaaS product. Traditional approach: weeks of back-and-forth on requirements, schema design, content structure. With MCP: I sat with them for an hour, described what they needed in natural language, and we built the entire content model together in real-time using our proven service delivery framework. They could see results immediately and give feedback. We went from kickoff to a working prototype in a single meeting.

The client was impressed. More importantly, because they were involved in the creation process, they understood the system deeply and could manage it themselves afterward. Not just faster development, but better client understanding and ownership.

Internal Tools

At OmoolaEx, we needed a project tracking system with custom fields for our consulting engagements. Building a custom tool from scratch wasn't justified for an internal need, but existing tools didn't fit our workflow. This is where our business process assessment approach really helped identify the requirements.

I used MCP to create a Sanity-based project tracker in an afternoon. Custom fields for client info, engagement type, team assignments, deliverables, and status tracking. Because it's Sanity, we got a great editing interface for free. Because I used MCP, I didn't spend days writing boilerplate code.

The system has evolved organically as our needs changed. Need a new field? Ask the AI. Need to reorganize data? Ask the AI. It's become our team's go-to approach for internal tools.

Migration Projects

A client wanted to migrate from WordPress to a modern headless CMS. They had 500+ blog posts with complex metadata. Traditional migration: write scripts to parse WordPress exports, map fields, handle edge cases, debug issues. With MCP: I described the WordPress structure and the desired Sanity schema, provided a sample of the export data, and asked the AI to create a migration strategy.

The AI generated migration code, handled field mapping, and even cleaned up inconsistent data during the process. What would have been a week-long project took two days, and most of that was validation and testing.

Rapid Prototyping

This is where MCP really shines. When exploring a new product idea or testing a concept with stakeholders, speed is everything. I can go from idea to working prototype with real content in hours instead of days. This changes the economics of experimentation. You can afford to try more ideas because the cost of being wrong is so low. Learn more about validating ideas quickly before committing to full development.

Part 7: Troubleshooting Common Issues

Here are the issues I've encountered and how I solved them.

Connection Problems

Problem: AI says it can't connect to Sanity or doesn't see the MCP server.
Solution: Restart your AI client completely. Check that the MCP configuration file is in the right location and properly formatted. Verify your Sanity token hasn't expired by running 'sanity-mcp status'.

Schema Issues

Problem: Schema changes don't appear in Studio.
Solution: Sanity Studio needs to be restarted after schema changes. If you're running 'npm run dev', stop it and start again. Also check that your schema files are properly exported in your schema index file.

Query Problems

Problem: GROQ queries return unexpected results or errors.
Solution: Use Sanity's Vision plugin (included in Studio) to test queries manually. This helps isolate whether the issue is with the query syntax or the data structure. The AI can help debug by explaining what a query does: "Explain this GROQ query step by step."

Deployment Challenges

Problem: Frontend works locally but fails in production.
Solution: Usually environment variables. Make sure your Sanity project ID, dataset, and API token are properly configured in your deployment environment. For Next.js, remember that server-side environment variables need different handling than client-side ones. Check out our guide on securing your deployment for production best practices.

Rate Limiting

Problem: Operations fail with rate limit errors.
Solution: Sanity's free tier has generous limits, but bulk operations can hit them. Break large operations into smaller batches. If you're doing this regularly, consider upgrading to a paid plan with higher limits.

Conclusion: A New Development Paradigm

Looking back at that 2 AM moment with 47 markdown files, I'm struck by how much has changed in my workflow. The combination of Sanity's MCP server and AI assistance hasn't just made me faster. It's changed what kinds of projects are feasible.

I used to avoid projects with complex content models because the setup overhead wasn't worth it for smaller engagements. Now I can tackle those projects confidently. I used to dread client requests for schema changes mid-project. Now they're trivial. I used to spend weekends building internal tools that would save time during the week. Now I build them in an afternoon and actually use that weekend time for rest, which has transformed our digital marketing strategies and content workflows.

This isn't about AI replacing developers. I'm still making all the important decisions about architecture, data modeling, and user experience. It's about AI handling the tedious parts so I can focus on the interesting problems. The code the AI generates isn't magic. It's the same code I would have written, just faster.

What excites me most is where this is heading. MCP is still young, and Sanity, the #1 rated headless CMS on G2, has already created an impressive implementation. As AI models improve and more tools adopt MCP, this kind of integration will become standard. We're seeing the early days of a new development paradigm where the boundary between thinking about a solution and implementing it becomes increasingly thin.

Next Steps

If you're ready to try this approach:

  1. Start with a small, low-stakes project. Don't try this on a critical production system first.
  2. Follow the setup instructions in Part 2. The automatic method really is the easiest.
  3. Build something simple (maybe a personal blog or a small internal tool).
  4. Experiment with different prompts and see what works for your style.
  5. Gradually increase complexity as you get comfortable.

Don't expect perfection immediately. There's a learning curve to prompt engineering, and you'll make mistakes. That's fine. The cost of mistakes is low, and you'll learn quickly.

How OmoolaEx Can Help

At OmoolaEx, we've been using this approach in client projects for months now, and we've developed expertise in making it work for real-world business needs. If you're interested in implementing AI-assisted development workflows in your organization, we can help with evaluating whether this approach fits your project requirements, setting up Sanity and MCP infrastructure, training your team on effective prompt engineering, building custom integrations and workflows, migrating existing content systems to Sanity, and ongoing support and optimization.

We're not just consultants who read the documentation. We're practitioners who use these tools daily in production systems. We know what works, what doesn't, and how to avoid the pitfalls.

Reach out to us at OmoolaEx if you'd like to discuss how AI-assisted development could transform your content management workflows. We'd be happy to share more specific examples from our client work and explore how this approach could benefit your projects.

Happy building.