VDK Docs
Blueprints

MDC Format

Cursor's enhanced rule format combining Markdown with XML-like directives

MDC Format Blueprint

MDC (Markdown with Directives) is Cursor's enhanced rule format that combines standard Markdown with XML-like directives for richer AI context and interactive features.

Format Specification

Basic Structure

---
title: 'Rule Title'
description: 'Brief description'
version: '2.0.1'
schema: 'cursor-mdc-v1'
tags: ['tag1', 'tag2']
---

# Rule Title

```xml
<cursor:context>
High-level project context and overview
</cursor:context>
```

Standard Markdown Content

<cursor:patterns>
Code patterns and examples
</cursor:patterns>
<cursor:rules>
- Specific coding rules
- Guidelines and conventions
</cursor:rules>

YAML Frontmatter Schema

# Required fields
title: string # Rule title
description: string # Brief description
version: string # Semantic version
schema: 'cursor-mdc-v1' # MDC schema version

# Standard fields (inherited from Markdown)
tags: array<string> # Technology tags
created: string # ISO 8601 timestamp
updated: string # ISO 8601 timestamp

# MDC-specific fields
priority: number # Rule priority (1-10)
scope: array<string> # File patterns where rule applies
enableDirectives: boolean # Enable/disable directive processing
validateOnSave: boolean # Validate when file is saved

# Cursor-specific fields
cursor:
  version: string # Minimum Cursor version
  features: array<string> # Required Cursor features
  experimental: boolean # Uses experimental features

MDC Directives

Core Directives

<cursor:context>

Provides high-level project context for the AI assistant.

<cursor:context>
This is a Next.js 15 e-commerce application using TypeScript, Tailwind CSS, and Prisma.
The project follows a feature-based architecture with server components as the default
pattern and client components only for interactive features.

Key architectural decisions:

- App Router for file-based routing
- Server actions for form handling
- Zustand for client-side state management
- React Query for server state
  </cursor:context>

Best Practices:

  • Keep context concise but comprehensive
  • Include architectural decisions and reasoning
  • Mention key technologies and patterns
  • Explain project-specific conventions

<cursor:patterns>

Defines coding patterns with examples.

API Route Pattern

All API routes follow this error handling pattern:

// app/api/users/route.ts
import { NextRequest, NextResponse } from 'next/server'
import { z } from 'zod'

const createUserSchema = z.object({
  name: z.string().min(1),
  email: z.string().email(),
})

export async function POST(request: NextRequest) {
  try {
    const body = await request.json()
    const data = createUserSchema.parse(body)

    const user = await createUser(data)
    return NextResponse.json(user, { status: 201 })
  } catch (error) {
    if (error instanceof z.ZodError) {
      return NextResponse.json(
        { error: 'Validation failed', details: error.errors },
        { status: 400 }
      )
    }
    return NextResponse.json(
      { error: 'Internal server error' },
      { status: 500 }
    )
  }
}

Component Pattern

React components follow this structure:

interface ComponentProps {
  // Props with JSDoc comments
  /** User data object */
  user: User;
  /** Optional edit handler */
  onEdit?: (user: User) => void;
}

export default function UserCard({ user, onEdit }: ComponentProps) {
  return (
    <div className="p-4 border rounded-lg">
      <h3 className="font-semibold">{user.name}</h3>
      <p className="text-gray-600">{user.email}</p>
      {onEdit && (
        <button
          onClick={() => onEdit(user)}
          className="mt-2 px-3 py-1 bg-blue-500 text-white rounded"
        >
          Edit
        </button>
      )}
    </div>
  );
}

Best Practices:

  • Include complete, working examples
  • Show the full pattern, not just snippets
  • Explain the reasoning behind patterns
  • Provide multiple related examples

<cursor:rules>

Specific coding rules and guidelines.

Always use TypeScript with proper interface definitions. Prefer server components over client components. Use 'use client' directive only when interactivity is required. Include proper error handling in all async operations. Follow the repository pattern for data access. Use absolute imports with @/ prefix. Include JSDoc comments for complex functions. Implement proper loading and error states. Use Tailwind utility classes instead of custom CSS. Follow the established naming conventions (PascalCase for components, camelCase for functions).

Best Practices:

  • Be specific and actionable
  • Order rules by importance
  • Use consistent language
  • Reference project-specific conventions

<cursor:technologies>

Technology stack information.

Frontend: Framework: Next.js 15 (App Router) Language: TypeScript 5.0+ Styling: Tailwind CSS v3 State: Zustand + React Query UI Components: Headless UI + Custom

Backend: Runtime: Node.js 18+ Database: PostgreSQL 15 ORM: Prisma 5.0+ Authentication: NextAuth.js v4 API: Next.js Route Handlers

Development: Package Manager: pnpm Linting: ESLint + Prettier Testing: Jest + React Testing Library Type Checking: TypeScript strict mode

Advanced Directives

<cursor:structure>

Project structure and organization.

app/                    # Next.js App Router
├── (auth)/            # Authentication routes
│   ├── login/         # Login page
│   └── register/      # Registration page
├── (dashboard)/       # Protected dashboard routes
│   ├── users/         # User management
│   └── settings/      # Settings pages
├── api/               # API routes
│   ├── auth/          # Authentication endpoints
│   └── users/         # User CRUD operations
├── globals.css        # Global styles
└── layout.tsx         # Root layout

components/            # Reusable components
├── ui/               # Base UI components (Button, Input, etc.)
├── forms/            # Form components
├── layout/           # Layout components (Header, Sidebar)
└── features/         # Feature-specific components

lib/                  # Utilities and configurations
├── auth.ts           # Authentication configuration
├── db.ts             # Database connection
├── utils.ts          # Utility functions
└── validations.ts    # Zod schemas

types/                # TypeScript type definitions
├── auth.ts           # Authentication types
├── user.ts           # User-related types
└── api.ts            # API response types

<cursor:examples>

Extended examples with explanations.

Complete Feature Example: User Management

1. Database Schema (Prisma)

// prisma/schema.prisma
model User {
  id        String   @id @default(cuid())
  name      String
  email     String   @unique
  avatar    String?
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt

  @@map("users")
}

2. API Route

// app/api/users/route.ts
import { NextRequest, NextResponse } from 'next/server'
import { createUserSchema } from '@/lib/validations'
import { createUser, getUsers } from '@/lib/db/users'

export async function GET() {
  try {
    const users = await getUsers()
    return NextResponse.json(users)
  } catch (error) {
    return NextResponse.json(
      { error: 'Failed to fetch users' },
      { status: 500 }
    )
  }
}

export async function POST(request: NextRequest) {
  try {
    const body = await request.json()
    const data = createUserSchema.parse(body)

    const user = await createUser(data)
    return NextResponse.json(user, { status: 201 })
  } catch (error) {
    if (error instanceof z.ZodError) {
      return NextResponse.json(
        { error: 'Validation failed', details: error.errors },
        { status: 400 }
      )
    }
    return NextResponse.json(
      { error: 'Internal server error' },
      { status: 500 }
    )
  }
}

3. Server Component (List)

// app/users/page.tsx
import { getUsers } from '@/lib/db/users';
import { UserCard } from '@/components/features/UserCard';
import { AddUserButton } from '@/components/features/AddUserButton';

export default async function UsersPage() {
  const users = await getUsers();

  return (
    <div className="container mx-auto py-8">
      <div className="flex justify-between items-center mb-6">
        <h1 className="text-2xl font-bold">Users</h1>
        <AddUserButton />
      </div>

      <div className="grid gap-4 md:grid-cols-2 lg:grid-cols-3">
        {users.map(user => (
          <UserCard key={user.id} user={user} />
        ))}
      </div>
    </div>
  );
}

4. Client Component (Interactive)

// components/features/AddUserButton.tsx
'use client'

import { useState } from 'react';
import { Button } from '@/components/ui/Button';
import { Modal } from '@/components/ui/Modal';
import { UserForm } from '@/components/forms/UserForm';

export function AddUserButton() {
  const [isOpen, setIsOpen] = useState(false);

  return (
    <>
      <Button onClick={() => setIsOpen(true)}>
        Add User
      </Button>

      <Modal isOpen={isOpen} onClose={() => setIsOpen(false)}>
        <UserForm
          onSuccess={() => setIsOpen(false)}
          onCancel={() => setIsOpen(false)}
        />
      </Modal>
    </>
  );
}

MDC Processing

Directive Processing

Cursor processes MDC directives in this order:

  1. Parse YAML frontmatter - Extract metadata and configuration
  2. Identify directives - Find all <cursor:*> tags in content
  3. Validate syntax - Check directive syntax and nesting
  4. Extract content - Parse content within directives
  5. Apply context - Use directive content to enhance AI understanding

Context Hierarchy

Directives create a hierarchy of context for the AI:

Project Context (cursor:context)
├── Technologies (cursor:technologies)
├── Structure (cursor:structure)
├── Patterns (cursor:patterns)
│   ├── Code Examples
│   └── Implementation Details
├── Rules (cursor:rules)
│   ├── Coding Standards
│   └── Best Practices
└── Examples (cursor:examples)
    ├── Complete Implementations
    └── Real-world Usage

Scope Application

MDC rules can be scoped to specific files or directories:

---
scope:
  - 'app/**/*.tsx' # App Router pages only
  - 'components/**/*.tsx' # React components only
  - 'lib/**/*.ts' # Utility functions only
---

When working in scoped files, Cursor gives higher priority to matching rules.

Validation

Schema Validation

MDC files are validated against the schema:

# Validate MDC syntax
vdk validate --format mdc --file .cursor/rules/patterns.mdc

# Validate all MDC files
vdk validate --format mdc --directory .cursor/rules/

# Fix common MDC issues
vdk blueprints fix --format mdc .cursor/rules/

Directive Validation

Common validation rules:

  • Proper nesting: Directives cannot be nested
  • Valid syntax: XML-like tags must be properly closed
  • Content requirements: Some directives require non-empty content
  • Schema compliance: Content must match expected schema

Cursor Integration

Cursor validates MDC files automatically:

  • On file save (if validateOnSave: true)
  • On project open
  • When rules are updated
  • Before AI context application

Conversion from Markdown

Automatic Conversion

VDK can convert standard Markdown rules to MDC format:

# Convert single file
vdk blueprints convert \
  --from markdown \
  --to mdc \
  --input .vdk/rules/react-patterns.md \
  --output .cursor/rules/react-patterns.mdc

# Convert entire directory
vdk blueprints convert \
  --from markdown \
  --to mdc \
  --input .vdk/rules/ \
  --output .cursor/rules/

Conversion Mapping

Markdown SectionMDC DirectiveNotes
Project Context<cursor:context>High-level overview
Technology Stack<cursor:technologies>Structured tech info
Code Examples<cursor:patterns>Patterns with examples
Best Practices<cursor:rules>Bullet-point rules
File Structure<cursor:structure>Directory layout

Manual Enhancement

After conversion, enhance with Cursor-specific features:

Before (Markdown):

## Component Pattern

Use TypeScript interfaces for props.

After (MDC):

Component Pattern

Always define TypeScript interfaces for component props:

interface UserCardProps {
  user: User;
  onEdit?: () => void;
}

export default function UserCard({ user, onEdit }: UserCardProps) {
  return <UserCardComponent user={user} onEdit={onEdit} />;
}

Best Practices

Directive Usage

  1. Use appropriate directives - Choose the right directive for content type
  2. Keep content focused - Each directive should have a single purpose
  3. Provide complete examples - Include full, working code examples
  4. Maintain consistency - Use consistent terminology and patterns
  5. Update regularly - Keep directives current with project evolution

Content Organization

<!-- Good: Logical flow -->

<cursor:context>
Project overview and key decisions
</cursor:context>

<cursor:technologies>
Tech stack details
</cursor:technologies>

<cursor:patterns>
Implementation patterns with examples
</cursor:patterns>

<cursor:rules>
Specific coding guidelines
</cursor:rules>

<!-- Avoid: Mixed content in single directive -->

<cursor:patterns>
Project uses React and TypeScript.
Use interfaces for props.
Here's an example...
</cursor:patterns>

Performance Optimization

  1. Limit directive size - Keep individual directives under 5KB
  2. Use specific scopes - Apply rules only where relevant
  3. Avoid redundancy - Don't repeat information across directives
  4. Optimize examples - Include only essential code in examples
  5. Regular cleanup - Remove outdated or unused rules

Cursor-Specific Features

Real-time Updates

MDC files are monitored for changes:

---
# Enable real-time updates
autoUpdate: true
watchFiles: true
reloadOnChange: true
---

AI Context Enhancement

MDC directives enhance Cursor's AI in specific ways:

  • cursor:context → Provides project understanding
  • cursor:patterns → Improves code generation
  • cursor:rules → Enforces coding standards
  • cursor:technologies → Enables tech-specific suggestions
  • cursor:examples → Provides reference implementations

Integration with Cursor Features

  • Code completion uses patterns and rules
  • Chat context includes project context
  • Code generation follows established patterns
  • Refactoring suggestions respect project conventions

Migration to Other Formats

To Standard Markdown

# Extract content from MDC directives
vdk blueprints convert \
  --from mdc \
  --to markdown \
  --input .cursor/rules/ \
  --output .vdk/rules/

To Windsurf XML

# Convert to XML-enhanced format
vdk blueprints convert \
  --from mdc \
  --to xml \
  --input .cursor/rules/ \
  --output .windsurf/rules/

Next Steps

On this page