跳到主要内容
Supermarket
返回能力市场
MCP Server
design
MIT

editor

Open-source 3D architectural editor with a local CLI, MCP tools, and practical workflows for humans and AI agents.

pascalorgpascalorg
91/ 100

公开评测 · 综合采用结论

证据充分,整体质量与安全表现优秀

查看评测依据 评测我的项目基于公开项目证据,非安全认证或安装推荐
24.4kstars
3.0kforks
最近更新 14小时前
评测生成时间(北京时间)
本报告引擎
v3.14.0
当前引擎
v3.16.0

本报告与当前引擎使用不同规则;原分数不会自动更新,不同版本的分数不宜直接对比。

重新评测此项目

进入后确认来源与额度,提交才会创建任务。

Evaluation report

综合采用结论

91
A
满分 100
值得推荐低风险
决策摘要

证据充分,整体质量与安全表现优秀

100%
高置信度
100
文档
100
安全
83
质量
100
活跃
65
采用
  • 基础评测完成+25/25确定性评分与静态安全扫描已完成
  • README 有效证据+25/2518,484 个去重后的有效字符
  • 独立证据来源+20/206 类非重复证据,重复文件不叠加
  • 仓库元数据+10/10已取得仓库状态与采用数据
  • 活跃记录+5/5已取得最近提交时间
  • AI 复核+15/15已完成结构化 AI 证据复核
How it works · 架构图

Pascal Editor 架构概览

README展示了多个组件(CLI、MCP、编辑器、包)及其关系,适合用架构图表示。

AI 提取 · 证据约束

左右滑动查看完整图示

Pascal Editor 架构概览README展示了多个组件(CLI、MCP、编辑器、包)及其关系,适合用架构图表示。启动启动服务访问场景使用状态渲染CLI安装和管理编辑器MCP服务器提供AI工具接口编辑器应用Next.js应用核心包场景状态和模式查看器包3D渲染
图示依据
  • • CLI章节描述启动编辑器和MCP服务
  • • 架构部分列出包结构
  • • MCP章节说明暴露场景工具
五维表现
开源3D建筑编辑器,提供CLI、MCP和技能,解决本地优先的AI辅助设计问题。文档详尽,但安装步骤复杂,预览版需手动校验,且部分功能依赖未验证的托管端点。
质量证据
  • README中提供'npx @pascal-app/cli editor'命令
  • 包含'Agent skills'章节,说明技能安装方法
  • 架构部分列出各包职责,如'@pascal-app/core'负责场景状态
  • 数据流部分描述从用户操作到系统更新的流程
  • 限制声明:'Use one active agent client per local CLI service'
采用建议
优势
  • 问题与用途描述
  • 有效 README
  • 安装或接入步骤
  • 可执行示例
  • 未发现已知高风险模式
关注点
  • 预览版安装步骤复杂,需手动下载和校验
  • 托管端点未验证,存在不确定性
  • 部分功能依赖特定版本,兼容性风险
  • 文档中部分链接可能失效
适合

需要本地优先3D建筑编辑器的开发者、希望集成AI代理进行场景编辑的用户、需要可扩展插件架构的团队、熟悉React和Three.js的开发者

不建议直接用于

需要完全托管、无需本地安装的用户、需要稳定npm版本且不想处理预览版的用户、对WebGPU支持有严格要求的旧环境

也有自己的公开项目?先看完证据,再用当前规则生成独立报告。

评测我的项目 →
文档证据
100/100
问题与用途描述10 分
有效 README12 分
安装或接入步骤14 分
可执行示例16 分
输入、参数或工具说明11 分
输出或结果说明9 分
限制、权限或边界12 分
错误处理或排障8 分
许可证信息5 分
结构化章节3 分
安全证据
低风险
未发现已知高风险模式

静态扫描不是安全保证,生产接入前仍应人工复核权限和数据边界。

方法、证据与局限展开
数据来源

GitHub Repository API

扫描范围

14 个文件 · 51,892 字符

评测引擎

v3.14.0 · AI 复核已启用(deepseek-chat)

局限
  • 静态评测不会安装或执行项目代码
  • 安全扫描基于高信号文件与已知模式,不能替代人工审计
  • 流行度只反映采用程度,不代表安全或工程质量

30 天热度趋势

README

Pascal Editor

An open-source, local-first 3D building editor built with React Three Fiber and WebGPU. Run it in the browser or from the CLI, and connect AI agents through MCP.

MIT License npm @pascal-app/core npm @pascal-app/viewer npm @pascal-app/cli Discord X (Twitter)

https://github.com/user-attachments/assets/8b50e7cf-cebe-4579-9cf3-8786b35f7b6b

A first look at Pascal Next

Explore the live demo — a real home reconstructed in detail, from its rooms and finishes to the structure and systems behind the walls. This hosted preview explores the direction of the next Pascal editor; the experience shown here is not yet part of the open-source editor release.

Exploded view — see how the home fits togetherCut view — slice through the building
Roof lifted above the reconstructed homeA section cut reveals the roof framing and interior
X-ray — reveal the modeled systemsWalkthrough — step inside at eye level
Building systems isolated with the walls hiddenWalking through the home toward the pool terrace
Interactions — open doors and exploreEnvironment — change the light and atmosphere
Interacting with doors in the reconstructed homeChanging the lighting around the reconstructed home

We are exploring what this could make possible for facility management, home services, architecture, home building, and infrastructure. Join the discussion on X and tell us where you would use it.

Make something with these videos

Making a video, tutorial, article, or social post about Pascal? You are welcome to use and edit this footage, including in monetized content, under CC BY 4.0. Credit Pascal, link the license, and note your edits; no separate permission is needed.

Download the six original videos and see the creator guide.

Run the Editor Locally

Node.js 22.13 or newer can create a persistent local Pascal installation without cloning this repository:

npx @pascal-app/cli editor

The CLI starts the editor and an authenticated MCP service in the background, selects collision-free loopback ports, and keeps projects in ~/.pascal/data/pascal.db. The npm package holds the CLI and that MCP service; the web editor runtime is downloaded once per version on the first command that starts the editor and verified against a digest published inside the package. Configure an agent to launch pascal mcp connect, which needs neither the editor process nor that download. Install the pascal command with npm install --global @pascal-app/cli. See Run Pascal locally for pnpm/Bun commands, project management, MCP setup, updates, storage paths, and troubleshooting.

Use one active agent client per local CLI service. The standalone local HTTP runtime shares active scene state between clients; use separate PASCAL_HOME directories and service processes when independent concurrent work is required.

Agent skills

Install with skills

Install Pascal's public agent workflows from this repository with skills.sh:

npx skills add pascalorg/editor \
  --skill pascal-3d \
  --skill furniture-fit

Claude Code users can install the same canonical skill source as a plugin:

/plugin marketplace add pascalorg/editor
/plugin install pascal-agent-skills@pascal

The Claude plugin also supplies the local pascal mcp connect server. Install and start the Pascal CLI first, and keep pascal on the PATH used to launch Claude Code. This local connector needs no Pascal account or API key and does not upload projects automatically. Its plugin root is this repository's skills/ directory, so an install copies only the skill bundles and their plugin metadata rather than the repository.

The plugin bundles two servers: the local pascal connector above and a hosted pascal-hosted server for https://editor.pascal.app/api/mcp, which prompts for an optional Pascal API key at enable time and stores it in the OS keychain. Leave the key empty to run local-only.

Claude Code 2.1.258 loads both the user-scoped pascal server created by pascal mcp setup claude and the plugin-provided server. Remove the manual entry before reloading or restarting Claude Code so only the plugin owns the connection lifecycle:

claude mcp remove --scope user pascal

Use /mcp to remove or disable any project- or local-scoped Pascal connection too. Leaving both connections active violates the one-active-agent-client-per-local-service requirement. When the intended project is hosted in a Pascal account or organization, disable the plugin-provided local server in /mcp and configure the hosted endpoint from the skill setup guide instead.

Codex users can install the same plugin from the repository marketplace:

codex plugin marketplace add pascalorg/editor
codex plugin add pascal-agent-skills@pascal

OpenClaw installation becomes available after the skills are published under Pascal's ClawHub publisher. See skills/README.md for the owner-qualified install and verification commands.

pascal-3d covers safe local or hosted MCP setup and verified scene work. furniture-fit produces a bounded, evidence-based footprint assessment without claiming unsupported height, swing, or delivery checks. See skills/README.md for package details and validation.

The skills inspect the connected MCP tool schemas before using optional fields. A capability present in this repository may be absent from an older installed or hosted release; the agent should report the narrower supported result instead of assuming source-only inputs are available.

These workflows require a connected Pascal MCP server for their tool-backed actions. An OpenAI directory submission must therefore use With MCP and submit the production hosted MCP endpoint together with the skills. The repository package does not prove that the endpoint, OAuth flow, reviewer credentials, domain verification, or portal scan is ready for review.

MCP Registry

server.json is Pascal's manifest for the official MCP Registry. Its version tracks the hosted MCP implementation independently of the npm package version. Pull requests validate the manifest and production endpoint. A Pascal organization owner publishes an approved version from main with the official registry publisher.

Using Published Packages

The viewer runtime and built-in node definitions are separate packages. Install the full built-in viewer set, then load the built-in plugin once before mounting <Viewer>. Capture sessions are an optional extension shipped inside those packages as the @pascal-app/core/capture and @pascal-app/viewer/capture subpaths:

npm install @pascal-app/core @pascal-app/viewer @pascal-app/editor @pascal-app/nodes
import { loadPlugin } from '@pascal-app/core'
import { builtinPlugin } from '@pascal-app/nodes'

await loadPlugin(builtinPlugin)

See the @pascal-app/viewer quick start for a React example.

Repository Architecture

This is a Turborepo monorepo with the reusable editor packages, the standalone app, and the CLI that distributes it:

editor/
├── apps/
│   └── editor/          # Next.js application
├── packages/
│   ├── core/            # Schemas, scene state, registry contracts, capture contracts
│   ├── viewer/          # 3D rendering runtime, shared systems, capture runtime
│   ├── editor/          # Editing tools and UI components
│   ├── nodes/           # Built-in node definitions, renderers, and systems
│   ├── cli/             # Persistent local editor installer and process manager
│   ├── mcp/             # Model Context Protocol server and scene storage
│   └── ui/              # Shared UI components

Separation of Concerns

PackageResponsibility
@pascal-app/coreNode schemas, scene state (Zustand), registry contracts, spatial queries, and event bus. core/capture adds versioned capture manifests, normalized streams, and transport-neutral static/live sources
@pascal-app/viewer3D rendering via React Three Fiber, shared render systems, default camera/controls, and post-processing. viewer/capture adds the capture runtime and reference model, device-motion, point-cloud, and surface-mesh layers
@pascal-app/editorEditing tools, panels, selection, and direct-manipulation UI
@pascal-app/nodesBuilt-in registry plugin with node definitions, renderers, geometry, and systems
@pascal-app/cliInstalls and manages a versioned standalone editor runtime and persistent local data
@pascal-app/mcpExposes scene tools, resources, prompts, and local storage to MCP-compatible AI hosts
apps/editorStandalone Next.js host for the editor packages

The viewer renders the scene with sensible defaults. The editor extends it with interactive tools, selection management, and editing capabilities.

Stores

Each package has its own Zustand store for managing state:

StorePackageResponsibility
useScene@pascal-app/coreScene data: nodes, root IDs, dirty nodes, CRUD operations. Persisted to IndexedDB with undo/redo via Zundo.
useViewer@pascal-app/viewerViewer state: current selection (building/level/zone IDs), level display mode (stacked/exploded/solo), camera mode.
useEditorapps/editorEditor state: active tool, structure layer visibility, panel states, editor-specific preferences.

Access patterns:

// Subscribe to state changes (React component)
const nodes = useScene((state) => state.nodes)
const levelId = useViewer((state) => state.selection.levelId)
const activeTool = useEditor((state) => state.tool)

// Access state outside React (callbacks, systems)
const node = useScene.getState().nodes[id]
useViewer.getState().setSelection({ levelId: 'level_123' })

Core Concepts

Nodes

Nodes are the data primitives that describe the 3D scene. All nodes extend BaseNode:

BaseNode {
  id: string              // Auto-generated with type prefix (e.g., "wall_abc123")
  type: string            // Discriminator for type-safe handling
  parentId: string | null // Parent node reference
  visible: boolean
  camera?: Camera         // Optional saved camera position
  metadata?: JSON         // Arbitrary metadata (e.g., { isTransient: true })
}

Node Hierarchy:

Site
└── Building
    └── Level
        ├── Wall → Item (doors, windows)
        ├── Slab
        ├── Ceiling → Item (lights)
        ├── Roof
        ├── Zone
        ├── Scan (3D reference)
        └── Guide (2D reference)

Nodes are stored in a flat dictionary (Record<id, Node>), not a nested tree. Parent-child relationships are defined via parentId and children arrays.


Scene State (Zustand Store)

The scene is managed by a Zustand store in @pascal-app/core:

useScene.getState() = {
  nodes: Record<id, AnyNode>,  // All nodes
  rootNodeIds: string[],       // Top-level nodes (sites)
  dirtyNodes: Set<string>,     // Nodes pending system updates

  createNode(node, parentId),
  updateNode(id, updates),
  deleteNode(id),
}

Middleware:

  • Persist - Saves to IndexedDB (excludes transient nodes)
  • Temporal (Zundo) - Undo/redo with 50-step history

Scene Registry

The registry maps node IDs to their Three.js objects for fast lookup:

sceneRegistry = {
  nodes: Map<id, Object3D>,    // ID → 3D object
  byType: {
    wall: Set<id>,
    item: Set<id>,
    zone: Set<id>,
    // ...
  }
}

Renderers register their refs using the useRegistry hook:

const ref = useRef<Mesh>(null!)
useRegistry(node.id, 'wall', ref)

This allows systems to access 3D objects directly without traversing the scene graph.


Node Renderers

Renderers are React components that create Three.js objects for each node type:

SceneRenderer
└── NodeRenderer (dispatches by type)
    ├── BuildingRenderer
    ├── LevelRenderer
    ├── WallRenderer
    ├── SlabRenderer
    ├── ZoneRenderer
    ├── ItemRenderer
    └── ...

Pattern:

  1. Renderer creates a placeholder mesh/group
  2. Registers it with useRegistry
  3. Systems update geometry based on node data

Example (simplified):

const WallRenderer = ({ node }) => {
  const ref = useRef<Mesh>(null!)
  useRegistry(node.id, 'wall', ref)

  return (
    <mesh ref={ref}>
      <boxGeometry args={[0, 0, 0]} />  {/* Replaced by WallSystem */}
      <meshStandardMaterial />
      {node.children.map(id => <NodeRenderer key={id} nodeId={id} />)}
    </mesh>
  )
}

Systems

Systems are React components that run in the render loop (useFrame) to update geometry and transforms. They process dirty nodes marked by the store.

Core Systems (in @pascal-app/core):

SystemResponsibility
WallSystemGenerates wall geometry with mitering and CSG cutouts for doors/windows
SlabSystemGenerates floor geometry from polygons
CeilingSystemGenerates ceiling geometry
RoofSystemGenerates roof geometry
ItemSystemPositions items on walls, ceilings, or floors (slab elevation)

Viewer Systems (in @pascal-app/viewer):

SystemResponsibility
LevelSystemHandles level visibility and vertical positioning (stacked/exploded/solo modes)
ScanSystemControls 3D scan visibility
GuideSystemControls guide image visibility

Processing Pattern:

useFrame(() => {
  for (const id of dirtyNodes) {
    const obj = sceneRegistry.nodes.get(id)
    const node = useScene.getState().nodes[id]

    // Update geometry, transforms, etc.
    updateGeometry(obj, node)

    dirtyNodes.delete(id)
  }
})

Dirty Nodes

When a node changes, it's marked as dirty in useScene.getState().dirtyNodes. Systems check this set each frame and only recompute geometry for dirty nodes.

// Automatic: createNode, updateNode, deleteNode mark nodes dirty
useScene.getState().updateNode(wallId, { thickness: 0.2 })
// → wallId added to dirtyNodes
// → WallSystem regenerates geometry next frame
// → wallId removed from dirtyNodes

Manual marking:

useScene.getState().dirtyNodes.add(wallId)

Event Bus

Inter-component communication uses a typed event emitter (mitt):

// Node events
emitter.on('wall:click', (event) => { ... })
emitter.on('item:enter', (event) => { ... })
emitter.on('zone:context-menu', (event) => { ... })

// Grid events (background)
emitter.on('grid:click', (event) => { ... })

// Event payload
NodeEvent {
  node: AnyNode
  position: [x, y, z]
  localPosition: [x, y, z]
  normal?: [x, y, z]
  stopPropagation: () => void
}

Spatial Grid Manager

Handles collision detection and placement validation:

spatialGridManager.canPlaceOnFloor(levelId, position, dimensions, rotation)
spatialGridManager.canPlaceOnWall(wallId, t, height, dimensions)
spatialGridManager.getSlabElevationAt(levelId, x, z)

Used by item placement tools to validate positions and calculate slab elevations.


Editor Architecture

The editor extends the viewer with:

Tools

Tools are activated via the toolbar and handle user input for specific operations:

  • SelectTool - Selection and manipulation
  • WallTool - Draw walls
  • ZoneTool - Create zones
  • ItemTool - Place furniture/fixtures
  • SlabTool - Create floor slabs

Selection Manager

The editor uses a custom selection manager with hierarchical navigation:

Site → Building → Level → Zone → Items

Each depth level has its own selection strategy for hover/click behavior.

Editor-Specific Systems

  • ZoneSystem - Controls zone visibility based on level mode
  • Custom camera controls with node focusing

Data Flow

User Action (click, drag)
       ↓
Tool Handler
       ↓
useScene.createNode() / updateNode()
       ↓
Node added/updated in store
Node marked dirty
       ↓
React re-renders NodeRenderer
useRegistry() registers 3D object
       ↓
System detects dirty node (useFrame)
Updates geometry via sceneRegistry
Clears dirty flag

Building a Plugin

The editor is extensible: a plugin ships node kinds (schema, 3D/2D rendering, placement tools, inspector parametrics) and left-rail panels through the same Plugin manifest the built-ins use — there is no separate internal API.

  • Developer guide — Create a plugin: the Plugin shape, panel contributions, discovery, lifecycle, and what's in/out of v1.
  • Worked example — pascalorg/plugin-trees: a standalone plugin with procedural trees, flowers, grass, and a presets panel. Clone it as a starting point.

Technology Stack

  • React 19 + Next.js 16
  • Three.js (WebGPU renderer)
  • React Three Fiber + Drei
  • Zustand (state management)
  • Zod (schema validation)
  • Zundo (undo/redo)
  • three-bvh-csg (Boolean geometry operations)
  • Turborepo (monorepo management)
  • Bun (package manager)

Getting Started

Development

Run the development server from the root directory to enable hot reload for all packages:

# Install dependencies
bun install

# Run development server (builds packages + starts editor with watch mode)
bun dev

# This will:
# 1. Build @pascal-app/core and @pascal-app/viewer
# 2. Start watching both packages for changes
# 3. Start the Next.js editor dev server
# Open http://localhost:3002

Important: Always run bun dev from the root directory to ensure the package watchers are running. This enables hot reload when you edit files in packages/core/src/ or packages/viewer/src/.

Building for Production

# Build all packages
turbo build

# Build specific package
turbo build --filter=@pascal-app/core

Publishing Packages

Releases run from .github/workflows/release.yml (workflow_dispatch, with package, bump, and dry-run inputs). The workflow bumps versions, rewrites the internal @pascal-app/* ranges, builds, publishes in dependency order (core → viewer → editor → nodes → mcp → ifc-converter → cli), then commits the release and pushes one tag per package. A dry run validates the builds without touching the registry.


Key Files

PathDescription
packages/core/src/schema/Node type definitions (Zod schemas)
packages/core/src/store/use-scene.tsScene state store
packages/core/src/hooks/scene-registry/3D object registry
packages/core/src/systems/Geometry generation systems
packages/viewer/src/components/renderers/Node renderers
packages/viewer/src/components/viewer/Main Viewer component
apps/editor/components/tools/Editor tools
apps/editor/store/Editor-specific state

Contributing

Bug fixes, features, docs and ideas are all welcome. Start with CONTRIBUTING.md for setup, code style and the PR flow.


Contributors

Aymeric Rabot Wassim Samad Sudhir


pascalorg/editor | Trendshift