mcpField
P
Phonebook

Phonebook

本地服务
stag-build.github.io开发工具131 周前更新

关于 Phonebook

Phonebook 是可自托管的命令行工具和 MCP 服务,可将现有 SwiftUI `#Preview` 与 Jetpack Compose `@Preview` 转为静态图库。它面向需要与设计师共享 UI 预览的应用团队,使用各平台的预览渲染工具生成内容。

主要功能

  1. 01复用现有 UI 预览
  2. 02生成静态 HTML 图库
  3. 03按组件和状态分组卡片
  4. 04支持 Android 与 iOS 渲染流程
  5. 05检查配置和预览覆盖情况

适用场景

  1. 01向设计师展示应用预览界面
  2. 02查找缺少预览或暗色变体的组件
  3. 03仅重新生成已修改文件中的预览

MCP 相关

运行 `npx @stag-build/phonebook mcp` 可启动 Phonebook 的 MCP 服务。其工具可供编码 Agent 检查配置、分析预览覆盖情况、获取指导、生成预览并构建图库。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"stag-build-phonebook": {
"command": "npx",
"args": [
"-y",
"@stag-build/phonebook"
]
}
}
}
启动命令npx -y @stag-build/phonebook

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
npm@stag-build/phonebook0.1.13

工具

5

收录的工具列表 · 更新于 1 周前

参数类型必填说明
dirstring否包含 phonebook.config.json 的项目目录
pathsarray否仅报告这些文件或目录中声明的组件,路径相对于项目目录。仍会扫描整个项目。
changedboolean否仅报告存在未提交 git 更改的文件中的组件——即你刚刚编辑的内容。在 git 仓库之外时忽略。与 paths 同时提供时,会组合使用。

详细介绍

Phonebook

一款可自托管的开源替代方案,可替代 Emerge Tools Snapshots:从现有的 Compose @Preview 和 SwiftUI #Preview 中提取内容,生成可浏览的静态 HTML 图库——无需 SaaS 账号。

许可证 Glama MCP 服务评分

Phonebook 可将团队已有的截图转换为类似 Storybook 的组件图库。无需编写新的测试代码,也无需手动维护设计令牌——它会将代码库中已有的内容渲染为静态网站,设计师无需安装任何东西即可打开。每个代码仓库都独立运行 Phonebook;v1 仅支持单平台,因此一个 Android 代码仓库(或一个 iOS 代码仓库)会生成一个 bundle 和一个网站。

功能

  • 无需编写新的测试代码 — 重用已有的 @Preview / #Preview
  • 无需 SaaS 账号 — 可自托管,完全在 CI 或本地运行
  • MCP 优先 — 编码 Agent 可为你检查设置、分析覆盖率、添加缺少的 preview,并构建图库
  • 智能组件分组 — 根据 preview 名称推断 component / state 卡片,无需添加注解
  • 跨平台 — Android(Roborazzi + ComposablePreviewScanner,在 JVM 上运行,无需模拟器)和 iOS(SnapshotPreviews,在模拟器上运行)
  • 版本感知设置 — init/doctor 会根据项目的 Kotlin 版本解析库版本,并在 Kotlin/Roborazzi 元数据不匹配导致难以诊断的编译崩溃之前发现问题

演示

观看 Phonebook 宣传视频

Phonebook 图库截图

从 samples/ios 生成的图库——根据应用自身的 #Preview 分组为 component / state 卡片,无需额外注解。

浏览在线图库 →

工作原理

  1. phonebook generate 会运行平台的 preview 渲染引擎,并将输出提取到一个 bundle(manifest.json + images/)中。
  2. phonebook build 会将该 bundle 转换为静态网站——默认情况下,它会将 index.html 直接写入 bundle 目录(复用其中已有的图像,不进行复制),因此网站位于 <bundle>/index.html。传入 -o <dir> 则会将所有内容复制到独立的网站目录(用于发布到其他位置,或之后合并多个 bundle)。纯 HTML/CSS/JS,可从 file:// 或任何静态主机运行。

安装

npm
npm install -g @stag-build/phonebook
Homebrew
brew install stag-build/phonebook/phonebook

也可以先添加 tap,再安装:

brew tap stag-build/phonebook
brew install phonebook

Formula 源码:stag-build/homebrew-phonebook。

无需安装(npx)
npx @stag-build/phonebook <cmd>
## 与编码 Agent 搭配使用(推荐)

大多数人不会直接运行 CLI — Phonebook 是通过 MCP 服务由编码 Agent(Claude Code、Codex 等)驱动的。Agent 会添加预览、运行设置检查,并为你生成图库;底层的 CLI 是它调用的引擎。

服务通过 npx @stag-build/phonebook mcp 运行 — 无需安装。请在下方选择你的客户端。

Claude Code
claude mcp add phonebook -- npx -y @stag-build/phonebook mcp
Codex CLI

添加到 ~/.codex/config.toml:

[mcp_servers.phonebook]
command = "npx"
args = ["-y", "@stag-build/phonebook", "mcp"]
Claude Desktop

添加到 Claude Desktop 配置中(macOS 上为 ~/Library/Application Support/Claude/claude_desktop_config.json):

{
  "mcpServers": {
    "phonebook": {
      "command": "npx",
      "args": ["-y", "@stag-build/phonebook", "mcp"]
    }
  }
}
Cursor

添加到 .cursor/mcp.json(项目级)或 ~/.cursor/mcp.json(全局):

{
  "mcpServers": {
    "phonebook": {
      "command": "npx",
      "args": ["-y", "@stag-build/phonebook", "mcp"]
    }
  }
}
Xcode(Codex Agent) — Xcode 26.3+

添加到项目工作区根目录下的 .codex/config.toml。Xcode 的 Agent 使用精简的 PATH 运行,因此命令会在 shell 中包装 npx,先添加常见的 Homebrew/nvm 路径:

[mcp_servers.phonebook]
command = "/bin/zsh"
args = [
  "-lc",
  "PATH=/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin; npx -y @stag-build/phonebook mcp"
]
enabled = true
Xcode(Claude Code Agent) — Xcode 26.3+

将 mcpServers 块添加到 ~/Library/Developer/Xcode/CodingAssistant/ClaudeAgentConfig/.claude.json:

{
  "mcpServers": {
    "phonebook": {
      "command": "/bin/zsh",
      "args": [
        "-lc",
        "PATH=/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin; npx -y @stag-build/phonebook mcp"
      ]
    }
  }
}

Android Studio(Gemini Agent Mode): 暂不支持 — 它的 MCP 集成只能连接远程 httpUrl 服务,不能连接 Phonebook 这类本地 stdio 进程。请改为在 Android 仓库中使用上述基于终端的客户端(Claude Code、Codex CLI)。

然后,在 Android 或 iOS 仓库的聊天窗口中,只需提出:

“使用 phonebook MCP,为我的设计师创建一个目录。”

Agent 会处理其余工作 — 检查设置、补齐缺失的预览、生成内容并构建网站。对于更有针对性的请求,它还提供:check_setup(设置诊断,与 phonebook doctor 相同)、analyze_coverage(缺少预览或深色变体的组件)、get_preview_guidance、run_generate 和 run_build。

快速入门:Android

先运行 phonebook init — 它会检测项目的 Kotlin 版本,并打印与该版本兼容的库版本说明(例如,Kotlin 2.0 项目使用 Roborazzi 1.60.0;Kotlin 2.2+ 使用最新版本)。以下版本适用于当前 Kotlin 项目(完整的可运行示例请参见 samples/android/app/build.gradle.kts):

// app/build.gradle.kts
plugins {
    id("io.github.takahirom.roborazzi") // root build.gradle.kts: version "1.72.0" apply false
}

roborazzi {
    generateComposePreviewRobolectricTests {
        enable = true
        packages = listOf("dev.stag.phonebook.sample") // your app's package
    }
}

dependencies {
    testImplementation("org.robolectric:robolectric:4.14.1")
    testImplementation("io.github.takahirom.roborazzi:roborazzi:1.72.0")
    testImplementation("io.github.takahirom.roborazzi:roborazzi-compose:1.72.0")
    testImplementation("io.github.sergio-sastre.ComposablePreviewScanner:android:0.9.3")
    testImplementation("io.github.takahirom.roborazzi:roborazzi-compose-preview-scanner-support:1.72.0")
    testImplementation("androidx.compose.ui:ui-test-junit4") // version from your Compose BOM, or pin one
}

在 settings.gradle.kts 旁边添加 phonebook.config.json:

{
  "appName": "My Android App",
  "platform": "android",
  "android": { "modules": [":app"], "variant": "debug" }
}

然后,在包含 Phonebook 的仓库中运行:

npx @stag-build/phonebook generate -C /path/to/your/android/repo
npx @stag-build/phonebook build -C /path/to/your/android/repo

打开 phonebook-out/index.html。

generate --changed(或 --files A.kt,B.kt)只会渲染这些文件中声明的预览,无需额外设置。仅在本次运行中,Phonebook 会向 Gradle 传递一个初始化脚本,替换预览测试器,以保留指定的预览并仅扫描其所属的包。两个文件都会写入 build/phonebook/,绝不会写入源文件目录。如果你的项目配置了自己的 testerQualifiedClassName,则会优先使用你的设置,并渲染该模块中的所有预览。

快速入门:iOS

将 SnapshotPreviews SPM 包添加到项目中,并添加一个继承自 SnapshotTest 的小型 XCTest 目标(完整的可运行示例请参见 samples/ios):

// PhonebookSnapshotTests.swift
import Foundation
import SnapshottingTests

final class PhonebookSnapshotTests: SnapshotTest {
    override class func snapshotPreviews() -> [String]? {
        guard let raw = ProcessInfo.processInfo.environment["SNAPSHOTS_ONLY_FILTER"], !raw.isEmpty else {
            return nil // record every #Preview
        }
        return raw.components(separatedBy: "\n")
    }
}

读取 SNAPSHOTS_ONLY_FILTER 后,phonebook generate --changed(或 --files A.swift,B.swift)就能只渲染你刚编辑的文件中的预览;如果未设置该变量,则会像以前一样记录每个 #Preview。

在 .xcodeproj 旁边添加 phonebook.config.json:

{
  "appName": "My iOS App",
  "platform": "ios",
  "ios": {
    "project": "MyApp.xcodeproj",
    "scheme": "MyApp",
    "simulator": "iPhone 17 Pro"
  }
}

你的 scheme 必须构建并测试快照测试目标(参见示例中的 PhonebookSample.xcscheme)。然后:

npx @stag-build/phonebook generate -C /path/to/your/ios/repo
npx @stag-build/phonebook build -C /path/to/your/ios/repo

打开 phonebook-out/index.html。

命名约定

Phonebook 会根据你现有的预览名称,将截图归入 component / state 卡片,无需添加注释。完整规则和示例请参阅 docs/naming-convention.md。

配置

phonebook.config.json:

键类型默认值说明
appNamestring—必填。显示在图库标题中。
platform"android" | "ios"—必填。
outputstring"phonebook-out"Bundle 输出目录,相对于配置文件所在目录。
android.modulesstring[][":app"]要录制的 Gradle 模块。
android.variantstring"debug"构建变体;Phonebook 会运行 <module>:recordRoborazzi<Variant>。
ios.projectstring—.xcodeproj 的路径,相对于配置文件所在目录。必须设置 project 或 workspace 之一。
ios.workspacestring—.xcworkspace 的路径,相对于配置文件所在目录。
ios.schemestring—必填。包含 SnapshotPreviews 测试目标的 Scheme。
ios.simulatorstring"iPhone 17 Pro"用于 -destination 的模拟器设备名称。
ios.onlyTestingstring自动检测-only-testing: 筛选条件,让 generate 只运行快照类,而不是应用的整个测试套件。根据 SnapshotTest 子类自动推导;设为 "" 可运行全部测试。

Android 预览的渲染方式与 Android Studio 一致:没有自定义尺寸的 @Preview 会根据内容调整尺寸,而全屏(fillMaxSize)内容则会填满 Robolectric 屏幕;Roborazzi 默认使用 Pixel 4a。在 generateComposePreviewRobolectricTests 代码块中设置 robolectricConfig 会替换此默认值,因此请包含 "qualifiers" to "RobolectricDeviceQualifiers.Pixel4a"(或使用 Android Studio 手机对应的 "\"w411dp-h891dp-port\"")。否则,全屏预览会在 320×470dp 的屏幕上渲染。phonebook doctor 会指出这一点。

generate 和 build 都接受 -C <dir>(包含 phonebook.config.json 的项目目录)。generate 接受 -o <dir>,用于覆盖 Bundle 输出目录,并接受 --allow-empty,用于允许运行未录制到任何预览的情况。build 接受可选的 Bundle 路径;若未指定,则使用项目的 Bundle 目录。它还接受 -o <dir>,用于设置站点输出目录;若未指定 -o,build 会直接将 index.html 写入 Bundle 目录,并就地复用其中的 images/(不进行复制);上文的快速入门使用的就是这种方式。传入 -o <dir> 可将 Bundle 中的图片复制到单独的独立站点目录。

phonebook init 和 phonebook doctor

phonebook init 会检测你的平台,并生成 phonebook.config.json 以及依赖项和设置代码片段;它会根据项目的 Kotlin 版本解析库版本,并填入应用包名。它绝不会替你修改构建文件。

对于 iOS,使用 xcrun simctl list devices available 检查已安装的设备,然后运行 phonebook init --simulator "<device name>" 记录你选择的模拟器。如果 phonebook.config.json 已存在,同一命令只会更新 ios.simulator,因此重试设置时也能使用。Android 不使用 --simulator。

phonebook doctor 会检查 generate 所需的所有配置是否就绪:插件和测试依赖项(使用 Gradle 版本目录时会通过版本目录解析)、扫描器的 packages 值、Kotlin/Roborazzi 兼容性,以及工具链(JDK/Xcode/模拟器)。添加 --deep 还会编译测试源代码——速度较慢,但当静态检查结果与实际情况不符时,可以提供权威判断。在 iOS 上,如果已链接 SnapshotPreviews,但尚不存在 SnapshotTest 子类,doctor 会指出应将其添加到的确切目标和文件夹(从 .pbxproj 解析得出),让你无需在不知道位置的情况下只收到“添加这个类”的提示。

phonebook init --write-snapshot-class 是 init 不修改项目文件这一规则的唯一例外:当 doctor 的 iOS 检查确认了链接目标,且该目标的源文件夹属于 Xcode 的文件系统同步组时,它会直接写入 <folder>/PhonebookSnapshots.swift——这样做是安全的,因为 Xcode 会自动收录同步文件夹,因此不会修改 project.pbxproj。其他所有情况下都会拒绝执行并说明原因:尚未配置 SnapshotPreviews 链接、项目不使用同步组,或者子类已存在。

phonebook mcp 会运行 MCP 服务——有关设置和提示词示例,请参阅上文“与编码 Agent 搭配使用”。

要求

Android:JDK 17+。无需模拟器——Roborazzi 通过 Robolectric 在 JVM 上渲染,因此 generate 可在 Linux CI 上运行。

iOS:安装了 Xcode 的 macOS,以及已启动或可启动的模拟器(generate 会针对指定的模拟器目标运行 xcodebuild test)。CI 需要使用 macOS 运行器。

CI 配置示例请参阅 docs/ci.md,命名规则请参阅 docs/naming-convention.md。

路线图

v1(M5)之后,尚未实现:

  • 在生成的图库中搜索和筛选
  • 合并多个 bundle 并提供并排视图(适用于跨平台网站)
  • 比较两次运行之间的版本差异(清单已包含提交和图像哈希,可用于实现此功能)
  • 补充 CI 配置示例文档

许可证

MIT — 请参阅 LICENSE。

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。