MCP server by app-appplayer
MCP Canvas
A universal definition-based canvas engine for 2D/3D rendering with CDL (Canvas Definition Language) support. Any type of diagram, drawing, or visualization can be rendered on this engine — node-edge graphs, circuit diagrams, PCB layouts, 3D models, block layouts, page documents, relationship diagrams, tree structures — all on the same engine.
Features
- Definition-Based Rendering - No images stored; definitions are stored and rendered per view
- CDL (Canvas Definition Language) - DSL for describing visual definitions; LLM-generated, reproducible
- Universal Canvas - Not bound to any specific use case; renders anything based on registered types
- Extensible Type System - Unknown types can be rendered with registered definitions and renderers
- Performance Guaranteed - Real-time interaction maintained with tens of thousands of elements
- 9 Built-in Layout Algorithms:
- manual, auto-grid, auto-flow (Sugiyama), force-directed (Barnes-Hut)
- constraint, circular, compact, stack, free-form
- Core Primitives: 13 shape types (rect, circle, ellipse, line, polyline, polygon, arc, path, text, richText, image, group, foreignContent)
- 3D Support: Box, sphere, cylinder, cone, torus, extrude, revolve, mesh geometries with PBR materials
- Cross-platform support: Android, iOS, web, Linux, Windows, macOS
Quick Start
import 'package:mcp_canvas/mcp_canvas.dart';
void main() {
// Create a canvas
final canvas = Canvas();
// Register a custom node type
canvas.registry.registerNodeType(NodeTypeDefinition(
type: 'resistor',
displayName: 'Resistor',
defaultDefinition: VisualDefinition(
id: 'resistor-def',
type: 'resistor',
),
));
// Create nodes
final node1 = canvas.createNode(
'resistor',
const Position(100, 100),
properties: {'resistance': '10k'},
);
final node2 = canvas.createNode(
'resistor',
const Position(300, 100),
properties: {'resistance': '22k'},
);
// Create an edge between nodes
final edge = canvas.createEdge(
EdgeEndpoint(nodeId: node1.id, portId: 'out'),
EdgeEndpoint(nodeId: node2.id, portId: 'in'),
);
// Serialize to JSON
final json = canvas.toJson();
// Search for elements
final results = canvas.search('10k');
}
Core Concepts
Visual Definition
Every visual element exists as a definition — a complete description of what primitives it consists of, how it looks under different conditions, and how it responds to state changes.
final definition = VisualDefinition(
id: 'my-type',
type: 'my-type',
shape2d: Shape2D(
primitives: [
RectPrimitive(
CommonAttributes(id: 'body', fill: SolidFill(CanvasColor(200, 200, 255))),
width: 120, height: 60, cornerRadius: 8,
),
TextPrimitive(
CommonAttributes(id: 'label'),
x: 60, y: 30, content: r'${name}',
),
],
),
);
Type Registry
The type registry provides 9 extension points for host applications:
| Extension Point | Description | |----------------|-------------| | NodeTypeDefinition | Custom node types with default visuals, ports, properties | | EdgeTypeDefinition | Custom edge types with routing, style, connection rules | | PortTypeDefinition | Custom port types with compatibility rules | | CanvasLayoutStrategy | Custom layout algorithms | | CanvasInteractionMode | Custom interaction modes | | CanvasRenderer | Custom renderer backends | | CustomRenderer | Foreign content area rendering | | ConnectionValidator | Custom port connection logic | | ExportFormat | Custom export formats |
Layout Engine
9 built-in layout algorithms with constraint support:
final engine = LayoutEngine();
// Auto-flow layout (Sugiyama layered graph)
final result = engine.layout('auto-flow', canvas.nodes, canvas.edges);
// Force-directed layout
final result = engine.layout('force-directed', canvas.nodes, canvas.edges);
// Apply constraints
engine.layout('constraint', canvas.nodes, canvas.edges,
constraints: [
Constraint(type: ConstraintType.align, targets: ['n1', 'n2'],
params: {'axis': 'horizontal'}),
],
);
CDL (Canvas Definition Language)
LLM-efficient DSL for visual definitions with round-trip guarantee:
// Parse CDL
final parser = CdlParser();
final ast = parser.parse('''
type resistor {
shape2d {
rect body { width: 120; height: 60; cornerRadius: 8; }
text label { x: 60; y: 30; content: "\${resistance}"; }
}
ports {
in: left, direction: input;
out: right, direction: output;
}
}
canvas {
node r1: resistor { x: 100; y: 100; resistance: "10k"; }
node r2: resistor { x: 300; y: 100; resistance: "22k"; }
edge r1.out -> r2.in
}
''');
// Serialize to CDL
final serializer = CdlSerializer();
final cdlText = serializer.serialize(canvas.nodes, canvas.edges, canvas.groups);
Event System
Full event bus with wildcard matching and undo/redo:
// Listen for all node events
canvas.on('node.*', (event) {
// Handles node.create, node.delete, node.move, etc.
});
// Undo/redo support
canvas.undo();
canvas.redo();
Collaboration Display
Remote collaboration visuals (sync logic is host app responsibility):
// Show remote cursor
canvas.setCursor('user-1', Position(200, 300), name: 'Alice');
// Show remote selection
canvas.setPresence('user-1', ['node-1', 'node-2']);
// Lock element for editing
canvas.collaboration.setEditLock('node-1', userId: 'user-1');
Large-Scale Support
Automatic performance optimization based on element count:
// Spatial indexing for fast queries
final index = RTreeIndex();
index.insert('node-1', Rect(100, 100, 120, 60));
final nearbyElements = index.query(Rect(0, 0, 500, 500));
// Virtualization for 10,000+ elements
final virtualization = Virtualization(bufferRatio: 1.5);
final result = virtualization.compute(viewport, allNodes, index);
// result.fullElements — render in detail
// result.metadataOnly — render simplified
// Automatic strategy selection
final selector = PerformanceStrategySelector();
final strategy = selector.select(elementCount);
// < 100: immediate, 100-1000: culling+LOD, 1000-10000: cache, 10000+: virtualization
Architecture
lib/
├── src/
│ ├── core/ # Foundation types
│ │ ├── common/ # Position, Size, Rect, Color, Transform, Matrix3, Vector3
│ │ ├── graph_model/ # CanvasNode, CanvasPort, CanvasEdge, CanvasGroup
│ │ ├── visual_definition/ # VisualDefinition, Primitives, Styles, Filters
│ │ ├── type_registry/ # TypeRegistry, Schema, Type definitions
│ │ └── surface/ # CanvasSurface, Grid, Snap, Rulers, Pages
│ ├── feature/ # Feature modules
│ │ ├── layout/ # LayoutEngine + 9 algorithms + edge routing
│ │ ├── view/ # SemanticZoom, Layers, Viewports, Camera
│ │ ├── interaction/ # SelectionManager, Shortcuts, Gestures
│ │ ├── event/ # EventBus, HistoryManager, Subscriptions
│ │ ├── animation/ # AnimationSystem, Easing functions
│ │ ├── cdl/ # CDL Lexer, Parser, Serializer, AST
│ │ ├── collaboration/ # Remote cursors, presence, edit locks
│ │ ├── search/ # Full-text search with scoring
│ │ └── large_scale/ # Virtualization, SpatialIndex, Minimap
│ ├── rendering/ # Render pipeline
│ │ ├── pipeline/ # 10-stage RenderPipeline, RenderScene
│ │ ├── renderer/ # Abstract CanvasRenderer, CustomRenderer
│ │ └── cache/ # 3-layer CacheManager (layout, raster, geometry)
│ └── api/ # Public API
│ ├── canvas.dart # Canvas facade (single entry point)
│ ├── error/ # 30+ typed error classes
│ └── serialization/ # JSON, CDL, Export/Import
└── mcp_canvas.dart # Public barrel file
Issues and Feedback
Please file any issues, bugs, or feature requests in our issue tracker.
License
This project is licensed under the MIT License - see the LICENSE file for details.