关于 Solar MCP
Solar MCP 通过 MCP 工具向 AI Agent 暴露 Solar 组件注册表,支持运行时发现组件、校验属性并提供结构化修正信息,面向使用 AI 生成代码构建界面的团队。
主要功能
- 01列出已注册组件及其架构
- 02返回单个组件架构
- 03校验组件属性
- 04提供结构化修正指引
- 05支持 Agent 运行时发现
适用场景
- 01生成界面前查找有效组件
- 02检查 AI 生成界面的属性
- 03修正无效组件配置
MCP 相关
solarbuild-mcp 服务提供 manifest、component 和 validate 工具。MCP 客户端可查看 Solar 注册表、获取组件架构,并依据修正指引校验属性。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
我们还没有获取到这个服务的安装包或远程地址,请按项目 README 中的说明安装。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
Solar
为 AI 生成代码打造的运行时 UI 框架。
AI Agent 使用 React 或 Vue 构建 UI 时,只能靠猜。它们会猜属性名称、类型和有效值。猜错时,就会得到堆栈跟踪。堆栈跟踪并非机器可读的反馈。
Solar 为 Agent 提供清晰的路径。调用 registry.manifest(),即可获取每个已注册组件的 JSON Schema,其中包括组件接收的属性及有效值。使用错误的属性挂载组件时,会得到 ContractError,这是一个包含 expected、received 和 fix 字段的结构化对象。Agent 读取 fix 并重试。无需人工介入。
核心原则
- 明确的契约优于约定: 属性经过类型声明,并在组件边界处验证,而非推断
- 组件注册表: 模型在生成任何组合代码前,会读取机器可读的清单
- 结构化错误: 验证失败时会返回可解析的 JSON,Agent 可直接据此采取行动
- 声明副作用: 副作用会声明依赖项和影响对象;没有隐式订阅
- 类型化组合: 插槽属性会限定可填充插槽的组件,并进行运行时验证
- 基于运行时: 无需编译器;可直接在浏览器中调试
- 精简的功能面: 基元越少,生成错误内容的方式就越少
工作原理
定义组件
每个组件都会明确声明自身的结构。注册组件后,其他组件和模型便能发现它。
import { createElement, defineComponent, registry } from './framework/index.js'
const Button = defineComponent({
name: 'Button',
props: {
label: { type: 'string', required: true },
onClick: { type: 'function', required: true },
variant: { type: 'string', enum: ['primary', 'secondary'], default: 'primary' },
},
render({ label, onClick, variant }) {
return createElement('button', { class: variant, onclick: onClick }, label)
}
})
registry.register(Button)
结构化错误
传入错误的类型时,得到的是结构化错误,而不是字符串。Agent 无需正则表达式即可解析并自我纠正。
Button({ label: 42, onClick: () => {} })
// throws ContractError:
{
"error": "ContractError",
"component": "Button",
"prop": "label",
"expected": "string",
"received": "number",
"fix": "Pass a string value for \"label\""
}
组件注册表
生成组合代码前,模型会读取完整目录:
registry.manifest()
// →
[
{
"name": "Button",
"props": {
"label": { "type": "string", "required": true },
"onClick": { "type": "function", "required": true },
"variant": { "type": "string", "enum": ["primary", "secondary"], "default": "primary" }
}
},
...
]
类型化插槽(组件组合)
父组件会声明可填充插槽的组件类型。传入其他内容则会抛出 ContractError。
const Card = defineComponent({
name: 'Card',
props: {
title: { type: 'string', required: true },
action: { type: 'slot', accepts: 'Button', required: true },
},
render({ title, action }) {
return createElement('div', { class: 'card' },
createElement('h3', {}, title),
action,
)
}
})
// valid
Card({ title: 'Hello', action: Button({ label: 'Go', onClick: () => {} }) })
// throws: Card: prop "action": expected slot(Button), got vnode with no _source
Card({ title: 'Hello', action: createElement('button', {}, 'Go') })
紧凑的 h() 记法
h() 会将紧凑的数组格式解析为 vnode 树。它能感知注册表,因此会自动解析组件名称。
import { h } from './framework/index.js'
// plain DOM nodes
h(['div', { class: 'row' },
['p', {}, 'Hello'],
['button', { class: 'btn' }, 'Click'],
])
// registered component by name, dispatches to Button()
h(['Button', { label: 'Save', onClick: handleSave, variant: 'primary' }])
Hooks 和副作用
状态使用 useState。副作用使用三个明确的基元,而不是通用的 useEffect:
useResource: 异步获取数据;键值更改时会自动取消 AbortControlleruseSubscription: 事件监听器;源、事件或处理程序发生变化时会自动挂载和卸载onMount/onUnmount: 生命周期回调,只运行一次,而非每次渲染时都运行
const UserCard = defineComponent({
name: 'UserCard',
props: { userId: { type: 'number', required: true } },
render({ userId }) {
const [width, setWidth] = useState(window.innerWidth)
// cancels the previous fetch automatically when userId changes
const { data, loading, error } = useResource({
key: userId,
fetch: async (signal) => {
const res = await fetch(`/api/user/${userId}`, { signal })
return res.json()
},
})
// attaches once, re-attaches only if source/event/handler changes
useSubscription({ source: window, event: 'resize', handler: () => setWidth(window.innerWidth) })
onMount(() => analytics.track('UserCard mounted'))
onUnmount(() => analytics.track('UserCard unmounted'))
if (loading) return createElement('p', {}, 'Loading...')
return createElement('p', {}, `${data.name} - viewport: ${width}px`)
}
})
架构
framework/
├── core/
│ ├── createElement.js # vnode factory
│ ├── render.js # mount vnode tree to DOM
│ ├── diff.js # reconcile old and new vnode trees
│ ├── hooks.js # useState, useMemo, useResource, useSubscription, onMount, onUnmount
│ └── scheduler.js # batch and defer re-renders
├── contract/
│ ├── defineComponent.js # strict component definition with prop schema
│ ├── ContractError.js # structured error class with toJSON()
│ ├── validate.js # runtime prop validation
│ └── types.js # primitive type definitions + slot type
├── runtime/
│ ├── reconciler.js # component lifecycle and mount/unmount
│ └── events.js # delegated event handling
├── registry.js # component catalog and manifest
├── h.js # compact array notation parser
└── index.js # public API
组件位于 components/ 目录中,每个文件存放一个组件;默认导出为 defineComponent 调用,并在导入时自动注册。模型无需推断即可遵循这些规则。
在线演示
在 StackBlitz 中打开 — 在浏览器中运行一个 3 步 Agent 循环:通过 registry.manifest() 发现组件、在错误挂载时捕获 ContractError,再利用 fix 字段自我纠正。
快速开始
npm create solarbuild@latest my-app
cd my-app
npm run dev
Cursor 插件: cursor.directory/plugins/framework-solar — 将 Solar 规则添加到 Cursor,让你的 AI 助手开箱即知 API。
也可以直接使用 CDN。无需安装,也无需构建:
<!DOCTYPE html>
<html>
<body>
<div id="app"></div>
<script type="module">
import {
defineComponent, mountComponent, registry,
useState, createElement
} from 'https://cdn.jsdelivr.net/npm/solarbuild/framework/index.js'
const Counter = defineComponent({
name: 'Counter',
props: {},
render() {
const [count, setCount] = useState(0)
return createElement('button', { onclick: () => setCount(n => n + 1) }, `Clicked ${count} times`)
}
})
registry.register(Counter)
mountComponent(Counter, {}, document.getElementById('app'))
</script>
</body>
</html>
运行演示
npm run dev
打开 http://localhost:3456/demo/(必须带末尾斜杠;这是静态服务器的特殊要求)。
演示涵盖框架的所有功能:静态渲染、差异比对、Hooks、契约验证、声明式副作用、批量更新、注册表清单、紧凑的 h() 记法以及类型化插槽。
MCP 服务
solarbuild-mcp 是一个 MCP 服务,可将你的 Solar 组件注册表作为可调用工具提供。AI Agent 可以发现组件、验证属性,并在运行时自行纠正,无需阅读静态文档。
npm install solarbuild-mcp
{
"mcpServers": {
"solarbuild": {
"command": "npx",
"args": ["solarbuild-mcp", "--components", "./components"]
}
}
}
工具:manifest(完整注册表架构)、component(单个组件架构)、validate(验证属性并提供修复说明)。
文档
完整文档请访问 docs.solarbuild.dev
这不是什么
- 不是元框架。没有 SSR、路由或构建流水线。
- 不是 React 的替代品。范围更窄,限制条件也不同。
- 并非针对手动编写组件的人类进行优化,不过也完全适用于这种场景。
核心观点:下一波框架不会为开发者设计,而会为开发者用来编写代码的模型设计。这是一次早期尝试。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。