返回市场
信号量-MCP服务器

信号量-MCP服务器

作者:tonybentley6 星标更新:2025-11-24

项目介绍

SignalK MCP Server

这是一个使用V8隔离环境中的代码执行来为AI代理提供高效访问SignalK海洋数据的模型上下文协议(MCP)服务器。与传统的MCP工具相比,这种方法可以减少高达**90-96%**的令牌使用量。

🚀 版本 1.0.6:现在使用代码执行引擎实现大量令牌节省!详情请参阅CHANGELOG.md

为什么使用代码执行?

传统的MCP工具会将所有数据返回给AI,消耗大量的令牌。而这个服务器使用了V8隔离环境(类似于Cloudflare Workers),让AI代理在返回数据之前运行JavaScript代码进行过滤。

令牌节省:

  • 船舶状态查询:94% 减少(2,000 → 120个令牌)
  • AIS目标过滤:95% 减少(10,000 → 500个令牌)
  • 多调用工作流:97% 减少(13,000 → 300个令牌)

快速开始

安装

# 通过npx安装(推荐)
npx signalk-mcp-server

# 或者全局安装
npm install -g signalk-mcp-server

Claude Desktop配置

添加到你的Claude Desktop配置文件中(macOS路径:~/Library/Application Support/Claude/claude_desktop_config.json):

{
  "mcpServers": {
    "signalk": {
      "command": "npx",
      "args": ["signalk-mcp-server"],
      "env": {
        "SIGNALK_HOST": "localhost",
        "SIGNALK_PORT": "3000",
        "SIGNALK_TLS": "false"
      }
    }
  }
}

基本使用

AI代理查询:"我的船舶位置和最近的3个AIS目标是什么?"

代码执行(自动):

(async () => {
  // 获取船舶位置
  const vessel = await getVesselState();
  const position = vessel.data["navigation.position"]?.value;

  // 获取AIS目标并在隔离环境中过滤
  const ais = await getAisTargets({ pageSize: 50 });
  const closest = ais.targets.slice(0, 3);

  return JSON.stringify({ position, closest });
})()
// 返回:约300个令牌(比传统工具节省97%!)

功能

代码执行引擎

  • V8隔离沙箱:安全的JavaScript执行
  • 客户端过滤:在返回给AI之前处理数据
  • 多API调用:在一个执行中组合操作
  • 90-96%令牌节省:大幅减少上下文窗口使用
  • 低于100毫秒的开销:快速执行,带有内存/超时限制

可用的SDK函数

使用execute_code时,这些函数可用。重要提示:所有函数都是异步的,必须等待:

// 船舶数据
const vessel = await getVesselState();

// AIS目标(带分页和可选距离过滤)
const ais = await getAisTargets({ page: 1, pageSize: 50, maxDistance: 5000 });

// 系统报警
const alarms = await getActiveAlarms();

// 发现可用的数据路径
const paths = await listAvailablePaths();

// 获取特定路径值(字符串和对象语法都适用)
const speed = await getPathValue("navigation.speedOverGround");
const heading = await getPathValue({ path: "navigation.headingTrue" });

// 连接状态 - 也需要等待!
const status = await getConnectionStatus();

实时海洋数据

  • 船舶位置、航向、速度、风速
  • 带距离计算的AIS目标跟踪
  • 系统通知和报警
  • 动态SignalK路径发现
  • 连接健康监控

配置

环境变量

# SignalK连接(必需)
SIGNALK_HOST=localhost          # SignalK服务器主机名/IP
SIGNALK_PORT=3000              # SignalK服务器端口
SIGNALK_TLS=false              # 使用WSS/HTTPS(true/false)

# 执行模式(可选)
EXECUTION_MODE=code            # code(默认)| tools(旧版)| hybrid

# 可选设置
SERVER_NAME=signalk-mcp-server
SERVER_VERSION=1.0.6

执行模式

模式描述使用场景
code(默认)仅V8隔离执行生产使用,最大效率
tools旧版MCP工具向后兼容
hybrid两种方法均可迁移期

示例

示例1:过滤后的船舶数据

查询:"获取我的船舶名称和位置"

代码:

(async () => {
  const vessel = await getVesselState();
  return JSON.stringify({
    name: vessel.data.name?.value,
    position: vessel.data["navigation.position"]?.value
  });
})()

结果:约200个令牌(比旧版工具节省2,000个令牌)

示例2:附近的船舶

查询:"显示1海里内的船舶"

代码:

(async () => {
  const ais = await getAisTargets({ pageSize: 50 });

  // 在隔离环境中过滤 - 大幅节省!
  const nearby = ais.targets.filter(t =>
    t.distanceMeters && t.distanceMeters < 1852
  );

  return JSON.stringify({
    total: ais.count,
    nearby: nearby.length,
    vessels: nearby.slice(0, 5)
  });
})()

结果:约300个令牌(比旧版工具节省10,000个令牌)

示例3:仅关键报警

查询:"有关键报警吗?"

代码:

(async () => {
  const alarms = await getActiveAlarms();

  const critical = alarms.alarms.filter(a =>
    a.state === "alarm" || a.state === "emergency"
  );

  return JSON.stringify({
    hasCritical: critical.length > 0,
    count: critical.length,
    details: critical
  });
})()

结果:约100个令牌(比旧版工具节省1,000个令牌)

示例4:多调用工作流

查询:"给我一个情况报告"

代码:

(async () => {
  // 所有调用在一个执行中!
  const vessel = await getVesselState();
  const ais = await getAisTargets({ pageSize: 50 });
  const alarms = await getActiveAlarms();

  // 在隔离环境中处理一切
  const closeVessels = ais.targets.filter(t =>
    t.distanceMeters && t.distanceMeters < 1852
  ).length;

  const criticalAlarms = alarms.alarms.filter(a =>
    a.state === "alarm" || a.state === "emergency"
  ).length;

  return JSON.stringify({
    position: vessel.data["navigation.position"]?.value,
    speed: vessel.data["navigation.speedOverGround"]?.value,
    vesselsNearby: closeVessels,
    criticalAlarms: criticalAlarms
  });
})()

结果:约300个令牌(比3次单独工具调用节省13,000个令牌!)

开发

先决条件

  • Node.js 18.0.0或更高版本
  • 访问SignalK服务器

设置

# 克隆仓库
git clone <repository-url>
cd signalk-mcp-server

# 安装依赖
npm install

# 构建
npm run build

# 运行单元测试
npm run test:unit

# 开发模式运行
npm run dev

测试

# 单元测试(快速)
npm run test:unit

# 集成测试(需要实时SignalK服务器)
npm run test:e2e

# 完整CI流水线
npm run ci

架构

代码执行流程

AI代理
  ↓
execute_code工具
  ↓
V8隔离沙箱(isolated-vm)
  ↓
SignalK SDK函数(全部异步,必须等待)
  ↓
SignalK绑定层(RPC风格)
  ↓
SignalK客户端(HTTP REST API)
  ↓
SignalK服务器

注意:HTTP-only模式确保每次请求都有新鲜数据。WebSocket代码保留以支持未来的流媒体功能。

关键组件

  • 隔离沙箱src/execution-engine/isolate-sandbox.ts):安全的V8隔离执行
  • SignalK绑定src/bindings/signalk-binding.ts):RPC风格的方法调用
  • SDK生成器src/sdk/generator.ts):从工具定义自动生成SDK
  • SignalK客户端src/signalk-client.ts):SignalK的HTTP/WebSocket客户端

安全性

  • 完全隔离:无权访问Node.js全局变量
  • 内存限制:每个执行128MB
  • 超时保护:最大执行时间30秒
  • 不暴露凭证:SignalK认证由绑定层处理
  • 只读:无写入操作到SignalK服务器

从1.x迁移

重大变更

版本1.0.6将默认模式从hybrid更改为code。默认情况下不再提供旧版工具。

向后兼容

要使用旧版工具,请设置执行模式:

{
  "mcpServers": {
    "signalk": {
      "env": {
        "EXECUTION_MODE": "tools"
      }
    }
  }
}

迁移指南

请参阅TOOL-MIGRATION-GUIDE.md获取完整的迁移示例。

之前(旧版):

工具:get_vessel_state
返回:所有船舶数据(约2000个令牌)

之后(代码):

(async () => {
  const vessel = await getVesselState();
  return JSON.stringify({
    name: vessel.data.name?.value,
    position: vessel.data["navigation.position"]?.value
  });
})()
// 返回:约200个令牌

故障排除

连接问题

检查连接状态(注意:需要等待):

(async () => {
  const status = await getConnectionStatus();  // 需要等待!
  return JSON.stringify(status);
})()

旧版模式

如果暂时需要旧版工具:

EXECUTION_MODE=tools npx signalk-mcp-server

调试模式

启用详细日志记录:

DEBUG=true
LOG_LEVEL=debug

贡献

欢迎贡献!请参阅CONTRIBUTING.md获取指南。

许可证

MIT许可证 - 详情请参阅LICENSE

资源

致谢

构建于:


🚢 享受AI驱动的海洋数据带来的航行吧!