MCP Server
Ideon exposes a Model Context Protocol (MCP) endpoint that allows AI agents to read and manipulate your canvas programmatically. Any MCP-compatible client — Claude Code, Cursor, Windsurf, or custom integrations — can connect and interact with your projects.
Overview
The MCP server provides:
- 15 tools for managing projects, blocks, links, kanban tasks, and search
- 3 resources for contextual information about your canvas
- Intelligent block placement that avoids overlap and respects spatial layout
- Real-time sync — changes made by AI agents appear instantly for connected collaborators
- Permission enforcement — respects existing project roles (owner/editor/viewer)
Authentication
The MCP server authenticates via your existing Ideon API keys.
Generating an API Key
- Open your account page and navigate to the Developers tab.
- Click "Generate new key".
- Enter a name for the key (e.g. "Claude Code", "Cursor") and confirm.
- A modal appears with the full key (format:
sk-ideon-...). Copy it.
Security Notes
- Keys are hashed with SHA-256 before storage — Ideon never stores the raw key.
- Each key is scoped to the user who created it — all MCP operations run with that user's permissions.
- You can revoke a key at any time from the same Developers tab. It stops working immediately.
- Rate limited to 60 requests per minute per key (sliding window).
Client Configuration
Claude Code / Claude Desktop
Add to your MCP configuration file (~/.claude/mcp.json or project-level):
{
"mcpServers": {
"ideon": {
"url": "https://your-ideon-instance.com/api/mcp",
"headers": {
"Authorization": "Bearer sk-ideon-your-api-key-here"
}
}
}
}
Cursor
Add to your Cursor MCP settings (.cursor/mcp.json):
{
"mcpServers": {
"ideon": {
"url": "https://your-ideon-instance.com/api/mcp",
"headers": {
"Authorization": "Bearer sk-ideon-your-api-key-here"
}
}
}
}
Generic MCP Client
Any client supporting the Streamable HTTP transport can connect:
- Endpoint:
POST /api/mcp - Transport: Streamable HTTP (stateless, JSON-RPC over HTTP)
- Auth Header:
Authorization: Bearer sk-ideon-... - Content-Type:
application/json - Accept Header:
application/json, text/event-stream
MCP-compatible clients usually set the Accept header automatically. Include it explicitly when calling the endpoint with curl or another HTTP client.
Agent Skill
Install the official Ideon canvas skill with the Skills CLI:
npx skills add 3xpyth0n/ideon --skill ideon-canvas
Direct HTTP Request
Store the instance URL and API key in environment variables rather than in shell history or source files:
export IDEON_URL="https://your-ideon-instance.com"
export IDEON_API_KEY="sk-ideon-your-api-key"
List the tools exposed by the server:
curl --fail-with-body "$IDEON_URL/api/mcp" \
-H "Authorization: Bearer $IDEON_API_KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
--data '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'
Call list_projects with the same headers and endpoint:
curl --fail-with-body "$IDEON_URL/api/mcp" \
-H "Authorization: Bearer $IDEON_API_KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
--data '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"list_projects","arguments":{}}}'
The response may be JSON or an SSE message event containing the JSON-RPC response.
Available Tools
Projects
| Tool | Description |
|---|---|
list_projects | List all projects accessible by the authenticated user (max 100) |
get_project | Get project metadata including block count, link count, and bounding box |
Blocks
| Tool | Description |
|---|---|
list_blocks | List all blocks in a project (max 200) with type, position, and content preview |
get_block | Get full block details (content, data, metadata, position) |
create_block | Create a new block with intelligent placement |
update_block | Update block content, data, metadata, position, or dimensions |
delete_block | Delete a block and cascade-delete connected links |
create_blocks_batch | Create up to 50 blocks in a single atomic operation (auto grid layout) |
Links
| Tool | Description |
|---|---|
list_links | List all links (connections) between blocks |
create_link | Create a connection between two blocks |
delete_link | Remove a connection |
Kanban
| Tool | Description |
|---|---|
list_kanban_tasks | List columns and tasks in a kanban block |
create_kanban_task | Add a new task to a kanban column |
move_kanban_task | Move a task between columns |
Search
| Tool | Description |
|---|---|
search_blocks | Case-insensitive search across block content and metadata (max 50 results) |
Resources
MCP resources provide contextual information to help AI agents understand your workspace:
| Resource URI | Description |
|---|---|
canvas://project/{id}/overview | Text summary: block counts by type, link count, bounding box |
canvas://project/{id}/graph | Full graph structure as JSON (blocks + links) |
canvas://help | Static guide covering block types, placement practices, and examples |
Canvas Automation Examples
The MCP API edits canvases inside existing projects; it does not create projects. Call list_projects to choose a project, then inspect it with get_project and list_blocks before making changes.
Create a framed project map
Create a frame block with create_block, for example with position: { "x": 100, "y": 100 }, width: 900, and height: 600. Use create_blocks_batch to add text blocks at positions inside those bounds, then connect related block IDs with create_link. The frame is a visual container; the MCP API does not define a parent-child grouping operation.
create_blocks_batch accepts block definitions like:
{
"projectId": "PROJECT_ID",
"blocks": [
{
"blockType": "text",
"content": "Define the release scope",
"position": { "x": 150, "y": 180 }
},
{
"blockType": "text",
"content": "Validate the deployment",
"position": { "x": 500, "y": 180 }
}
]
}
Use the IDs returned by the batch call with create_link:
{
"projectId": "PROJECT_ID",
"sourceBlockId": "FIRST_BLOCK_ID",
"targetBlockId": "SECOND_BLOCK_ID",
"label": "followed by"
}
Create and update a Mermaid diagram
Create a mermaid block with its editable diagram source as content. Update the same content field to change the diagram.
{
"projectId": "PROJECT_ID",
"blockType": "mermaid",
"content": "flowchart LR\n Source --> Canvas"
}
Pass the returned block ID to update_block when replacing the source:
{
"projectId": "PROJECT_ID",
"blockId": "MERMAID_BLOCK_ID",
"content": "sequenceDiagram\n Agent->>Ideon: Update diagram"
}
Create kanban tasks
Create a kanban block with create_block, initialize its metadata.columns with update_block, and then call create_kanban_task for each task. A column must exist before a task can be added.
{
"projectId": "PROJECT_ID",
"blockId": "KANBAN_BLOCK_ID",
"metadata": {
"columns": [
{
"id": "c-todo",
"title": "To do",
"workflowState": "todo",
"tasks": []
},
{
"id": "c-progress",
"title": "In progress",
"workflowState": "in-progress",
"tasks": []
},
{ "id": "c-done", "title": "Done", "workflowState": "done", "tasks": [] }
]
}
}
Call create_kanban_task with the returned kanban block ID:
{
"projectId": "PROJECT_ID",
"blockId": "KANBAN_BLOCK_ID",
"columnId": "c-todo",
"title": "Review the release checklist"
}
Block Placement
When creating blocks, the AI agent can control positioning in several ways:
Relative placement (recommended)
Use anchorBlockId + direction to place a new block near an existing one:
anchorBlockId: "existing-block-id"
direction: "right" | "left" | "up" | "down"
The placement engine automatically avoids collisions with a 40px minimum gap.
Explicit position
Provide exact position: { x, y } coordinates. No collision detection is applied.
Automatic placement
If neither anchor nor position is specified, blocks are placed to the right of the existing canvas content.
Batch placement
create_blocks_batch arranges blocks in a grid (max 5 columns) with uniform spacing.
Provide explicit position values in a batch when placing notes inside a frame's visual bounds.
Permissions
MCP operations respect the same roles as the Ideon UI:
| Role | Read | Write |
|---|---|---|
| Owner | ✓ | ✓ |
| Editor | ✓ | ✓ |
| Viewer | ✓ | ✗ |
Write operations include: create_block, update_block, delete_block, create_blocks_batch, create_link, delete_link, create_kanban_task, move_kanban_task.
Rate Limiting
Each API key is limited to 60 requests per 60-second sliding window.
Response headers on every request:
X-RateLimit-Limit: 60X-RateLimit-Remaining: <n>X-RateLimit-Reset: <unix-timestamp>
When rate-limited, the server returns HTTP 429 with a Retry-After header indicating seconds to wait.
Error Codes
| Code | Meaning |
|---|---|
-32001 | Authentication failed (invalid or missing API key) |
-32002 | Permission denied (insufficient role) |
-32003 | Resource not found (project, block, or link) |
-32004 | Validation error (invalid block type, content too long, etc.) |
-32602 | Invalid parameters (schema validation failed) |
-32603 | Internal server error |
Constraints
- Maximum request body size: 1 MB
- Maximum block content: 100,000 characters
- Block width: 100–2000 px
- Block height: 50–2000 px
- Batch size: 1–50 blocks per call
- Link label: max 200 characters
- Search query: 1–200 characters
- Self-links are not allowed
- Core blocks cannot be moved, resized, or deleted
Example Workflow
A typical AI agent workflow:
- Discover — call
list_projectsto find the target project - Orient — read
canvas://project/{id}/overviewfor a quick summary - Explore — call
list_blocksto understand the spatial layout - Act — create blocks near relevant existing content using
anchorBlockId - Connect — use
create_linkto represent relationships
Agent: "I'll add three related notes about the authentication flow."
→ list_blocks(projectId) — finds the "Auth" block at (200, 100)
→ create_blocks_batch(projectId, [
{ blockType: "text", content: "Login flow...", anchorBlockId: "auth-block" },
{ blockType: "text", content: "Token refresh..." },
{ blockType: "text", content: "Session management..." }
])
→ create_link(projectId, "new-block-1", "auth-block", label: "implements")