返回市场
光子服务器

光子服务器

作者:portel-dev4 星标更新:2025-11-21

项目介绍

【技术文档摘要】

Photon Logo

npm 版本 npm 下载量 MCP

Photon

将单文件 TypeScript 转换为 MCP 服务器、CLI 工具等的通用运行时。

Photon TS 文件是单文件。零样板代码。纯粹的业务逻辑。


TL;DR

当前 MCP 的问题:

  • 流行的 MCP 不完全符合您的特定需求。
  • 安全风险:恶意 MCP 可以通过提示注入窃取您的数据——不仅仅是凭据。
  • 分散在 4-6 个文件中,使得安全审计不切实际。
  • 复杂到无法安全地分叉和自定义。

Photon 的解决方案: 单文件 TypeScript 格式。纯粹的业务逻辑,零样板代码。分叉优先设计,每个 .photon.ts 都易于审核和自定义。

想象一下,就像 NPM 和 Node.js,但用于 MCP

编写一次,到处使用

相同的 .photon.ts 文件自动成为:

  • 🤖 MCP 服务器 - 用于 Claude Desktop、Cursor 和 AI 助手的工具。
  • 💻 CLI 工具 - 供人类使用的漂亮命令行界面。
  • 🔌 平台集成 - NCP、Lumina 和未来的运行时。
# 同一个文件,多种接口:
photon mcp analytics              # 作为 MCP 服务器运行 AI
photon cli analytics revenue      # 作为 CLI 工具使用

无需额外代码。纯粹的业务逻辑。无限部署目标。

Photon 生态系统飞轮

Photon 生态系统

生态系统创建了一个良性循环:AI 生成光子 → 运行时执行它们 → 社区分享 → AI 变得更智能。


问题

传统的 MCP 服务器将您的逻辑分散在 4-6 个文件中:

traditional-mcp/
├── server.ts         (50 行样板代码)
├── transport.ts      (40 行设置)
├── schemas.ts        (40 行类型定义)
├── types.ts          (30 行更多类型)
├── package.json      (依赖项)
└── business.ts       (20 行您的代码)

这确实造成了问题:

  • 对于 AI 代理:跨文件的上下文使得理解困难。
  • 对于人类:跳转多个文件来理解一个功能。
  • 对于团队:编写业务逻辑之前有 200+ 行代码。
  • 对于维护:更改需要更新多个文件和配置。

解决方案

Photon 将一切放在一个文件中:

/**
 * 分析 - 查询公司分析数据库
 * @dependencies pg@^8.11.0
 */
import { Client } from 'pg';

export default class Analytics {
  private db: Client;

  constructor(
    private host: string,
    private database: string,
    private password: string
  ) {}

  async onInitialize() {
    this.db = new Client({
      host: this.host,
      database: this.database,
      password: this.password
    });
    await this.db.connect();
  }

  /**
   * 按日期范围获取收入
   * @param startDate 开始日期 (YYYY-MM-DD)
   * @param endDate 结束日期 (YYYY-MM-DD)
   */
  async revenue(params: { startDate: string; endDate: string }) {
    const result = await this.db.query(
      'SELECT date, SUM(amount) FROM orders WHERE date BETWEEN $1 AND $2 GROUP BY date',
      [params.startDate, params.endDate]
    );
    return result.rows;
  }
}

40 行。一个文件。生产就绪。

在任何地方使用它

现在这个单一文件可以同时作为MCP 服务器CLI 工具

# 作为 MCP 服务器(用于 AI 助手)
photon mcp analytics
# → Claude Desktop 现在可以调用 revenue() 作为工具

# 作为 CLI(用于人类)
photon cli analytics revenue --startDate 2024-01-01 --endDate  2024-12-31
# → 美丽的格式化输出:
# ┌────────────┬──────────┐
# │ 日期       │ 收入     │
# ├────────────┼──────────┤
# │ 2024-01-01 │ $12,450  │
# │ 2024-01-02 │ $15,320  │
# └────────────┴──────────┘

同一代码。同一逻辑。两个接口。零重复。


为什么一个文件改变了一切

🤖 AI 原生设计

AI 代理现在可以在一个上下文中理解您的整个 MCP:

# AI 可以读取、理解并提出改进建议
"阅读我的 analytics.photon.ts 并解释它是如何工作的"
"审查此光子的安全问题"
"为此光子添加错误处理"

传统 MCP 需要 AI 将分散的文件拼凑在一起——光子提供了完整的上下文。

👤 人类友好

  • 理解:读一个文件,理解整个系统。
  • 审查:代码审查是一个文件,一个故事。
  • 调试:所有逻辑都在一个地方,无需跳转。
  • 学习:新团队成员只需读一个文件。

🔧 分叉优先哲学

每个光子都设计为可定制:

# 复制、修改、完成——无需更新构建配置
cp ~/.photon/jira.photon.ts ~/.photon/my-jira.photon.ts
# 按需编辑 my-jira.photon.ts
photon mcp my-jira  # 立即生效

用例:

  • 添加公司特定的身份验证。
  • 自定义业务逻辑。
  • 合并多个光子。
  • 实验而不破坏原始内容。

🔒 透明性中的安全性

提示注入攻击是新的供应链威胁。恶意 MCP 可以操纵 AI 响应以泄露您整个对话历史——不仅仅是凭据。

一个文件 = 一个审核:

  • 读 40 行,理解一切。
  • 没有隐藏在导入中的代码。
  • 几分钟内分叉并验证,而不是几小时。
  • 通过透明性信任,而非声誉。

当您不能信任一个光子时,您可以安全地分叉并审核它。传统 MCP 逻辑分散?几乎不可能验证。

📦 零摩擦依赖

依赖项通过 JSDoc 自动安装(类似于 npxuv):

/**
 * @dependencies axios@^1.6.0, lodash@^4.17.21
 */

无需手动 npm install。无需 package.json。Photon 处理它。


快速开始

安装

npm install -g @portel/photon

使用现成的光子

官方光子市场 预配置了 16+ 个生产就绪的光子:

# 浏览所有光子
photon info

# 安装任何光子(文件系统、Git、Postgres、MongoDB、Slack 等)
photon add 文件系统

# 或者将您自己的 .photon.ts 文件复制到
# 用户文件夹中的 .photon 文件夹

# 调用带有 mcp 选项的信息命令
photon info 文件系统 --mcp
# 获取客户端配置 json
{
  "文件系统": {
    "命令": "photon",
    "参数": [
      "mcp",
      "文件系统"
    ],
    "环境": {
      "FILESYSTEM_WORKDIR": "/Users/arul/Documents",
      "FILESYSTEM_MAX_FILE_SIZE": "10485760",
      "FILESYSTEM_ALLOW_HIDDEN": "false"
    }
  }
}
# 添加到您的客户端

使用 AI 构建光子

使用 photon-skill 为 Claude Desktop 或 Claude Code 生成 .photon.ts 文件:

  • 包含元数据的单个 TypeScript 文件。
  • AI 理解一个文件中的完整上下文。
  • 零样板代码,只有业务逻辑。

添加您自己的市场

# 从 GitHub 添加自定义市场
photon marketplace add your-org/your-photons

# 从您的市场安装
photon add your-custom-tool

价值主张

指标传统 MCPPhoton
设置时间40 分钟5 分钟
代码行数200+~40
所需文件4-6 个文件1 个文件
样板代码手动自动处理
模式生成手动从 TypeScript 自动生成
依赖项手动 npm 安装从 @dependencies 自动安装
热重载自己配置内置 --dev
AI 上下文分散单个文件
CLI 接口编写单独的代码从同一代码自动
部署目标仅 MCPMCP、CLI、NCP、Lumina、API...

查看详细比较 →


CLI 接口

每个光子自动提供一个漂亮的 CLI 接口,无需额外代码。驱动您的 MCP 工具的相同业务逻辑立即可在终端上使用。

快速示例

# 列出所有方法
photon cli lg-remote

# 使用自然语法调用方法
photon cli lg-remote volume 50
photon cli lg-remote volume +5
photon cli lg-remote channel 7
photon cli lg-remote app netflix

# 获取方法帮助
photon cli lg-remote volume --help

美丽的输出格式

Photon 根据数据结构自动格式化输出:

表格 - 键值对和平坦对象:

$ photon cli lg-remote volume
┌─────────┬────┐
│ volume  │ 45 │
├─────────┼────┤
│ muted   │ no │
├─────────┼────┤
│ maxVol  │ 100│
└─────────┴────┘

列表 - 项目数组:

$ photon cli lg-remote apps
• Netflix (netflix)
• YouTube (youtube.leanback.v4)
• HDMI1 (com.webos.app.hdmi1)
• Disney+ (disney)

树形 - 层次数据(显示为格式化的 JSON) 原始值 - 直接显示简单值

格式系统

Photon 使用一个智能格式系统,具有 5 种标准类型:

  1. 原始值 - 字符串、数字、布尔值
  2. 表格 - 平坦对象或平坦对象数组
  3. 树形 - 嵌套/层次数据
  4. 列表 - 简单项目的数组
  5. - 无返回值(无操作)

提示格式(可选):

/**
 * 获取当前音量
 * @format 表格
 */
async volume() {
  return this._request('ssap://audio/getVolume');
}

自动检测:如果没有提供 @format 标签,Photon 会根据返回值结构自动检测最佳格式。

CLI 命令参考

photon cli <光子名称> [方法] [参数...]

列出所有方法:

photon cli lg-remote

调用方法:

# 无参数
photon cli lg-remote 状态

# 单个参数
photon cli lg-remote volume 50

# 多个参数
photon cli lg-remote search query "breaking bad" limit 10

# 相对调整
photon cli lg-remote volume +5
photon cli lg-remote channel +1

获取方法帮助:

photon cli lg-remote volume --help

原始 JSON 输出:

photon cli lg-remote volume --json

一个代码库,多种接口

Photon 设计的美妙之处:改进业务逻辑自动适用于所有接口

编写一次逻辑:

async volume(params?: { level?: number | string } | number | string) {
  // 处理相对调整
  if (typeof level === 'string' && level.startsWith('+')) {
    const delta = parseInt(level);
    const current = await this._getCurrentVolume();
    const newVolume = current + delta;
    await this._setVolume(newVolume);
  }
  // ... 其余逻辑
  return this._getCurrentVolume(); // 总是返回当前状态
}

处处适用:

  • MCP:Claude Desktop、Cursor 等。
  • CLIphoton cli lg-remote volume +5
  • 未来接口:HTTP、WebSocket 等。

上下文感知错误消息

光子可以提供有用的上下文感知错误:

$ photon cli lg-remote channels
❌ 错误:电视频道不可用。当前在 HDMI1。
   切换到电视调谐器输入以访问频道。

同样的错误质量出现在 MCP 工具中——因为是相同的代码。

退出码

CLI 正确返回退出码以供自动化使用:

  • 0:成功
  • 1:错误(工具执行失败、无效参数等)

适合 shell 脚本和 CI/CD:

if photon cli lg-remote volume 50; then
  echo "音量设置成功"
else
  echo "设置音量失败"
  exit 1
fi

Photon 如何工作

约定 = 自动化

文件名 → MCP 名称

// analytics.photon.ts → "analytics" MCP

类方法 → 工具

async revenue() {}      // → "revenue" 工具
async topCustomers() {} // → "topCustomers" 工具

TypeScript 类型 → JSON 模式

async create(params: { title: string; priority: number }) {}
// Photon 从 TypeScript 类型自动生成 JSON 模式

JSDoc → 工具描述

/**
 * 按日期范围获取收入
 * @param startDate 开始日期 (YYYY-MM-DD)
 */
// Photon 自动提取描述

构造函数参数 → 环境变量

constructor(private host: string, private database: string) {}
// 映射到:ANALYTICS_HOST, ANALYTICS_DATABASE

JSDoc @dependencies → 自动安装

/**
 * @dependencies pg@^8.11.0, lodash@^4.17.21
 */
// Photon 在首次运行时自动安装(类似 npx 或 uv)

可用的光子

来自 portel-dev/photons 的生产就绪光子:

类别光子工具总数
数据库PostgreSQL (7),MongoDB (13),Redis (18),SQLite (9)47
基础设施AWS S3 (11),Docker (10),文件系统 (13)34
开发Git (11),GitHub Issues (7)18
通信邮件 (8),Slack (7)15
生产力Google 日历 (9),Jira (10)19
实用工具Fetch (2),Time (3),Memory (10)15

总计:16 个光子,148 个专注工具

浏览并安装:

photon info            # 查看所有可用光子
photon add postgres   # 安装任何光子
photon search git     # 按关键词搜索

创建您自己的光子

1. 初始化

photon init analytics

~/.photon/ 中创建 analytics.photon.ts(从任何地方均可访问)。

自定义目录:

photon --working-dir ./my-photons init analytics

2. 编写业务逻辑

/**
 * 分析 - 查询公司分析数据库
 * @dependencies pg@^8.11.0
 */
import { Client } from 'pg';

export default class Analytics {
  private db: Client;

  constructor(
    private host: string,
    private database: string,
    private password: string
  ) {}

  async onInitialize() {
    this.db = new Client({
      host: this.host,
      database: this.database,
      password: this.password
    });
    await this.db.connect();
  }

  /**
   * 按日期范围获取收入
   * @param startDate 开始日期 (YYYY-MM-DD)
   * @param endDate 结束日期 (YYYY-MM-DD)
   */
  async revenue(params: { startDate: string; endDate: string }) {
    const