内容
# CesiumJS Fly-In MCP 服务器
一个 MCP(模型上下文协议)服务器,使用 CesiumJS 和 Puppeteer 生成类似 Google Earth Studio 的飞入动画。给它一个城市名称,它就会渲染出一段电影般的空中缩放动画,作为编号的 PNG 帧序列。
输出是一个 PNG 目录 - 不是视频。要将其转换为视频,请使用 [Remotion](https://remotion.dev)(适用于 React 基础的管道,带有叠加层、标题和效果)或 FFmpeg 进行快速编码:
```bash
ffmpeg -framerate 30 -i frames/frame_%04d.png -c:v libx264 -pix_fmt yuv420p output.mp4
```
## 前置条件
- **Node.js** 18+
- **npm**
- **Cesium Ion 账户** - [免费注册](https://ion.cesium.com/) 以获取访问令牌
## 快速安装(Claude Code)
```bash
claude mcp add cesiumjs-flyin -e CESIUMION=your_token -- npx -y cesiumjs-flyin-mcp
```
就是这样。将 `your_token` 替换为您的 [Cesium Ion](https://ion.cesium.com/) 访问令牌。
## 从源码安装
```bash
git clone https://github.com/scott-brereton/cesiumjs-mcp.git
cd cesiumjs-mcp
npm install
cp .env.example .env # 添加您的 Cesium Ion 令牌
npm run build
```
## MCP 工具
### `generate_flyin`
为给定城市生成飞入动画。地理编码城市,启动带有 CesiumJS 的无头浏览器,动画化相机从轨道高度降至街道级别,并捕获每个帧为 PNG。
| 参数 | 类型 | 默认值 | 描述 |
|---|---|---|---|
| `city` | 字符串 | *(必填)* | 城市名称(例如 "Chicago", "Tokyo") |
| `outputDir` | 字符串 | *(必填)* | 保存 PNG 帧的目录 |
| `width` | 数字 | 1920 | 帧宽(像素) |
| `height` | 数字 | 1080 | 帧高(像素) |
| `fps` | 数字 | 30 | 每秒帧数 |
| `durationSeconds` | 数字 | 6 | 动画时长 |
| `startAltitude` | 数字 | 800000 | 起始海拔(米)(800km) |
| `endAltitude` | 数字 | 2000 | 结束海拔(米)(2km) |
| `tiltAngle` | 数字 | 45 | 最终相机倾斜角度(度) |
| `heading` | 数字 | 0 | 相机方向(度)(0 = 北) |
| `easing` | 字符串 | "cinematic" | 缓动配置文件(见下文) |
**输出:** 返回包含 `success`、`city`、`frameCount`、`outputDir`、`resolution` 和 `message` 的 JSON。
### `list_presets`
返回具有推荐相机角度的预设城市。不需要参数。
## 缓动配置文件
| 配置文件 | 描述 |
|---|---|
| `cinematic` | 不对称曲线:快速下降至约 30%,然后缓慢下降。适用于与音效同步的音频。 |
| `cubic` | 对称三次缓动。平滑、均衡的加速/减速。 |
| `quintic` | 更强的对称缓动。起始和结束时有更戏剧性的加速。 |
| `linear` | 恒定速度,无缓动。 |
## 支持的城市
内置查找表提供对这些城市的即时地理编码(任何其他城市都回落到 OpenStreetMap Nominatim):
纽约、洛杉矶、芝加哥、伦敦、巴黎、东京、悉尼、迪拜、罗马、柏林、莫斯科、北京、孟买、旧金山、西雅图、多伦多、里约热内卢、新加坡、开罗、伊斯坦布尔
以下城市有推荐相机角度的预设:纽约、芝加哥、伦敦、东京、迪拜、旧金山、巴黎、悉尼。
## Agent 集成
参见 [agents.md](agents.md) 以获取 Claude Desktop、Claude Code 和其他 MCP 客户端的完整 MCP 配置说明。
Claude Code 快速入门:
```bash
claude mcp add cesiumjs-flyin -e CESIUMION=your_token -- npx -y cesiumjs-flyin-mcp
```
## Remotion 集成
PNG 帧序列旨在直接插入 [Remotion](https://remotion.dev) 项目。以下是最小化组件:
```tsx
// src/components/FlyIn.tsx
import { AbsoluteFill, Img, staticFile, useCurrentFrame } from "remotion";
export const FlyIn: React.FC<{ totalFrames: number }> = ({ totalFrames }) => {
const frame = useCurrentFrame();
const frameIndex = Math.min(frame + 1, totalFrames);
const frameNum = String(frameIndex).padStart(4, "0");
const src = staticFile(`frames/frame_${frameNum}.png`);
return (
<AbsoluteFill>
<Img src={src} style={{ width: "100%", height: "100%", objectFit: "cover" }} />
</AbsoluteFill>
);
};
```
```tsx
// src/Root.tsx
import { Composition } from "remotion";
import { FlyIn } from "./components/FlyIn";
export const RemotionRoot = () => (
<Composition
id="CityFlyIn"
component={FlyIn}
durationInFrames={180} // fps * durationSeconds
fps={30}
width={1920}
height={1080}
defaultProps={{ totalFrames: 180 }}
/>
);
```
将生成的帧复制到 `public/frames/` 并渲染为:
```bash
npx remotion render src/index.ts CityFlyIn out/flyin.mp4
```
## 开发
```bash
npm run build # 编译 TypeScript
npm run start # 启动 MCP 服务器
npm run dev # 构建 + 启动
```
## 工作原理
1. **地理编码** - 城市名称通过内置查找表或 OpenStreetMap Nominatim 回落解析
2. **相机路径** - 所有帧都使用对数海拔插值(海拔变化被对数感知)结合选定的缓动函数预计算
3. **渲染** - Puppeteer 启动带有 WebGL(ANGLE/SwiftShader)的无头 Chrome,加载 CesiumJS 和 Google Photorealistic 3D Tiles via Cesium Ion
4. **帧捕获** - 为每个帧设置相机位置,等待图块加载,然后捕获视口为 PNG
5. **输出** - 编号的 PNG(`frame_0001.png`、`frame_0002.png`,...)可用于任何视频管道
## 许可证
MIT