Skip to content

Latest commit

 

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Miro MCP Server

Version: 0.1.0

Model Context Protocol (MCP) server enabling Claude and Claude Code to perform CRUD operations on Miro boards.

Overview

This MCP server provides Claude with the ability to:

  • Read Miro boards with full spatial and structural understanding
  • Create items (sticky notes, shapes, text) with precise coordinate control
  • Update existing items
  • Delete items
  • Analyze board structure, relationships, and spatial organization

Primary Design Goal: Enable Claude Code to programmatically create aesthetically pleasing, well-organized Miro diagrams with precise coordinate control.

Features

Phase 1 (Current)

  • ✅ OAuth 2.0 authentication with token management
  • ✅ Read boards with full geometric details
  • ✅ Create sticky notes at precise coordinates
  • ✅ Create shapes (rectangles, circles, etc.) at precise coordinates
  • ✅ Create connectors between items
  • ✅ Query board bounds and item geometry

Phase 2 (Planned)

  • Update item content, position, and style
  • Delete items
  • Batch operations
  • Frame support
  • Advanced spatial analysis

Phase 3 (Future)

  • Template system for common patterns
  • Smart layout suggestions
  • Content extraction and analysis

Architecture

Coordinate Strategy

This server is optimized for precise coordinate control to enable aesthetic diagram creation:

  • All creation operations accept explicit x, y coordinates
  • Claude Code calculates layouts programmatically
  • Helper tools provide coordinate calculations (grid, radial, etc.)
  • Full geometric information available for spatial reasoning

Key Components

miro-mcp/
├── miro_mcp/
│   ├── server.py          # FastMCP server with tool definitions
│   ├── auth.py            # OAuth 2.0 flow and token management
│   ├── client.py          # Miro API client with rate limiting
│   ├── models.py          # Pydantic data models
│   ├── analyzer.py        # Spatial analysis and clustering
│   └── config.py          # Configuration management
├── tests/
│   ├── test_auth.py
│   ├── test_client.py
│   └── test_tools.py
├── docs/
│   ├── ARCHITECTURE.md    # Detailed architecture documentation
│   ├── API.md            # Miro API integration details
│   └── USAGE.md          # Usage examples and patterns
├── pyproject.toml
└── README.md

Installation

Prerequisites

  • Python 3.10 or higher
  • Miro account with developer access
  • Claude Desktop or Claude Code

1. Clone Repository

git clone https://github.com/yourusername/miro-mcp.git
cd miro-mcp

2. Install Dependencies

pip install -e .

3. Configure Miro OAuth Application

  1. Go to Miro Developer Portal
  2. Create a new app
  3. Configure OAuth settings:
    • Redirect URI: http://localhost:8000/callback
    • Scopes: boards:read, boards:write
  4. Copy Client ID and Client Secret

4. Set Environment Variables

export MIRO_CLIENT_ID="your_client_id"
export MIRO_CLIENT_SECRET="your_client_secret"
export MIRO_REDIRECT_URI="http://localhost:8000/callback"

Or create a .env file:

MIRO_CLIENT_ID=your_client_id
MIRO_CLIENT_SECRET=your_client_secret
MIRO_REDIRECT_URI=http://localhost:8000/callback

5. Run Initial OAuth Setup

python -m miro_mcp.auth setup

This will:

  • Start a local OAuth callback server
  • Open your browser for authorization
  • Save tokens securely

6. Configure MCP Server

Add to your Claude Desktop config (~/Library/Application Support/Claude/claude_desktop_config.json on macOS):

{
  "mcpServers": {
    "miro": {
      "command": "python",
      "args": ["-m", "miro_mcp.server"],
      "env": {
        "MIRO_CLIENT_ID": "your_client_id",
        "MIRO_CLIENT_SECRET": "your_client_secret"
      }
    }
  }
}

Quick Start

Example 1: Read a Board

# Ask Claude Code:
# "Read the board at https://miro.com/app/board/uXjVKB..."

board = await miro_read_board("uXjVKB...")
print(f"Board has {len(board.items)} items")
print(f"Bounds: {board.bounds.width} x {board.bounds.height}")

Example 2: Create a Simple Diagram

# "Create a 3-step process flow diagram"

# Get board bounds to find empty space
board = await miro_read_board(board_id)
start_x = board.bounds.max_x + 500
start_y = board.bounds.center_y

# Create shapes with precise spacing
steps = ["Plan", "Execute", "Review"]
shape_ids = []

for i, step in enumerate(steps):
    x = start_x + i * 400
    shape = await miro_create_shape(
        board_id=board_id,
        shape_type="rectangle",
        content=step,
        x=x,
        y=start_y,
        width=300,
        height=150,
        color="light_blue"
    )
    shape_ids.append(shape.id)

# Connect them
for i in range(len(shape_ids) - 1):
    await miro_create_connector(
        board_id=board_id,
        start_item_id=shape_ids[i],
        end_item_id=shape_ids[i+1],
        start_position="right",
        end_position="left"
    )

Example 3: Analyze Existing Board

# "What are the main themes on this brainstorm board?"

board = await miro_read_board(board_id)

# Extract all sticky note content
notes = [item.content for item in board.items if item.type == "sticky_note"]

# Claude analyzes the text content
# Can identify clusters, themes, patterns

Available Tools

Read Operations

miro_list_boards

List all boards accessible to the authenticated user.

miro_read_board

Read complete board contents with full geometric details.

Returns:

  • All items (sticky notes, shapes, text, frames)
  • Connectors with start/end relationships
  • Complete position and dimension data
  • Board bounds

miro_get_board_bounds

Get bounding box of all content on a board.

miro_get_item_geometry

Get precise position and dimensions of a specific item.

Create Operations

miro_create_sticky_note

Create a sticky note at exact coordinates.

Parameters:

  • board_id: Target board ID
  • content: Text content
  • x, y: Coordinates (required)
  • width, height: Dimensions (optional)
  • color: Note color (optional)

miro_create_shape

Create a shape (rectangle, circle, triangle, etc.) at exact coordinates.

Parameters:

  • board_id: Target board ID
  • shape_type: rectangle, circle, triangle, rhombus, etc.
  • content: Optional text inside shape
  • x, y: Coordinates (required)
  • width, height: Dimensions (optional)
  • color: Shape color (optional)

miro_create_connector

Create a connector line between two items.

Parameters:

  • board_id: Target board ID
  • start_item_id: Source item ID
  • end_item_id: Destination item ID
  • start_position: Which edge to connect from (top/bottom/left/right/auto)
  • end_position: Which edge to connect to (top/bottom/left/right/auto)

Layout Helpers

miro_calculate_grid_positions

Calculate positions for grid layout.

miro_calculate_circle_positions

Calculate positions for radial/circular layout.

Usage Patterns

Pattern 1: Understand Before Creating

# 1. Read existing board
board = await miro_read_board(board_id)

# 2. Analyze spatial organization
# - Where is content?
# - What spacing is used?
# - What colors/styles are present?

# 3. Place new content in harmony with existing
new_x = board.bounds.max_x + 500  # To the right

Pattern 2: Programmatic Layout

# Calculate all positions first
positions = []
for i, item in enumerate(items):
    row = i // 5
    col = i % 5
    x = base_x + col * 300
    y = base_y + row * 300
    positions.append((x, y))

# Then create all items
for (x, y), content in zip(positions, items):
    await miro_create_sticky_note(board_id, content, x, y)

Pattern 3: Structured Diagrams

# Create hierarchical org chart
root_x, root_y = 1000, 500
spacing_x = 400
spacing_y = 300

# Top level
ceo = await miro_create_shape(board_id, "rectangle", "CEO", root_x, root_y)

# Second level
for i, dept in enumerate(["Engineering", "Sales", "Marketing"]):
    x = root_x - spacing_x + i * spacing_x
    y = root_y + spacing_y
    dept_shape = await miro_create_shape(board_id, "rectangle", dept, x, y)
    await miro_create_connector(board_id, ceo.id, dept_shape.id)

Development

Running Tests

pytest tests/

Type Checking

mypy miro_mcp/

Code Formatting

black miro_mcp/
ruff check miro_mcp/

Troubleshooting

Authentication Issues

  • Verify Client ID and Client Secret are correct
  • Check redirect URI matches exactly (including port)
  • Ensure required scopes are enabled
  • Try re-running python -m miro_mcp.auth setup

Rate Limiting

  • Server implements automatic rate limiting (100 req/min)
  • Exponential backoff on 429 errors
  • Consider batching operations when possible

Coordinate Issues

  • Miro uses arbitrary coordinate space (can be negative, very large)
  • Always query miro_get_board_bounds to understand scale
  • Test with small offsets first to verify placement

Contributing

Contributions welcome! Please:

  1. Fork the repository
  2. Create a feature branch
  3. Add tests for new functionality
  4. Ensure all tests pass
  5. Submit a pull request

License

MIT License - see LICENSE file for details

Resources

Roadmap

Phase 1 (v0.1.0) - Current

  • OAuth authentication
  • Basic read operations
  • Create sticky notes and shapes
  • Connector support
  • Comprehensive error handling
  • Test coverage

Phase 2 (v0.2.0)

  • Update operations
  • Delete operations
  • Frame support
  • Batch operations
  • Advanced spatial analysis

Phase 3 (v0.3.0)

  • Template system
  • Pattern recognition
  • Content extraction
  • Image support

Support

For issues, questions, or contributions:

  • GitHub Issues: [github.com/yourusername/miro-mcp/issues]
  • Documentation: [docs/]

Changelog

0.1.0 (2026-02-13)

Added

  • Project instructions and development guidelines (.claude/CLAUDE.md)
  • Spec-driven development infrastructure (specs/ directory)
  • Testing conventions (no mocks, real implementations)
  • Coordinate-based design strategy documentation

About

let's talk to our miro boards! :D

Resources

Contributing

Stars

4 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages