SignalK MCP Server

Fornece a agentes de IA acesso somente leitura a sistemas de dados marítimos SignalK, permitindo consultas de dados de navegação de embarcações, alvos AIS e alarmes do sistema.

Documentação

Servidor MCP SignalK

Um servidor Model Context Protocol (MCP) que fornece a agentes de IA acesso eficiente a dados marinhos SignalK usando execução de código em isolados V8. Essa abordagem reduz o uso de tokens em 90-96% em comparação com ferramentas MCP tradicionais.

🚀 Versão 1.0.6: Agora usando mecanismo de execução de código para economia massiva de tokens! Veja CHANGELOG.md para detalhes.

Por que Execução de Código?

Ferramentas MCP tradicionais retornam TODOS os dados para a IA, consumindo quantidades massivas de tokens. Este servidor usa isolados V8 (como Cloudflare Workers) para permitir que agentes de IA executem código JavaScript que filtra dados antes de retorná-los.

Economia de Tokens:

  • Consultas de estado da embarcação: redução de 94% (2.000 → 120 tokens)
  • Filtragem de alvos AIS: redução de 95% (10.000 → 500 tokens)
  • Fluxos de trabalho com múltiplas chamadas: redução de 97% (13.000 → 300 tokens)

Início Rápido

Instalação

# Via npx (recommended)
npx signalk-mcp-server

# Or install globally
npm install -g signalk-mcp-server

Configuração do Claude Desktop

Adicione à sua configuração do Claude Desktop (~/Library/Application Support/Claude/claude_desktop_config.json no macOS):

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

Uso Básico

Consulta do Agente de IA: "Qual é a posição da minha embarcação e os 3 alvos AIS mais próximos?"

Execução de Código (Automática):

(async () => {
  // Get vessel position
  const vessel = await getVesselState();
  const position = vessel.data["navigation.position"]?.value;

  // Get AIS targets and filter in isolate
  const ais = await getAisTargets({ pageSize: 50 });
  const closest = ais.targets.slice(0, 3);

  return JSON.stringify({ position, closest });
})()
// Returns: ~300 tokens (97% savings vs legacy tools!)

Recursos

Mecanismo de Execução de Código

  • Sandbox de Isolado V8: Execução segura de JavaScript
  • Filtragem no Lado do Cliente: Processa dados antes de retornar à IA
  • Múltiplas Chamadas de API: Combina operações em uma única execução
  • Economia de Tokens de 90-96%: Redução massiva no uso da janela de contexto
  • Overhead Inferior a 100ms: Execução rápida com limites de memória/tempo

Funções Disponíveis do SDK

Ao usar execute_code, estas funções estão disponíveis. IMPORTANTE: TODAS as funções são assíncronas e DEVEM ser aguardadas com await:

// Vessel data
const vessel = await getVesselState();

// AIS targets (with pagination and optional distance filter)
const ais = await getAisTargets({ page: 1, pageSize: 50, maxDistance: 5000 });

// System alarms
const alarms = await getActiveAlarms();

// Discover available data paths
const paths = await listAvailablePaths();

// Get specific path value (both string and object syntax work)
const speed = await getPathValue("navigation.speedOverGround");
const heading = await getPathValue({ path: "navigation.headingTrue" });

// Connection status - ALSO requires await!
const status = await getConnectionStatus();

Dados Marinhos em Tempo Real

  • Posição da embarcação, rumo, velocidade, vento
  • Rastreamento de alvos AIS com cálculos de distância
  • Notificações e alarmes do sistema
  • Descoberta dinâmica de caminhos SignalK
  • Monitoramento de saúde da conexão

Configuração

Variáveis de Ambiente

# SignalK Connection (Required)
SIGNALK_HOST=localhost          # SignalK server hostname/IP
SIGNALK_PORT=3000              # SignalK server port
SIGNALK_TLS=false              # Use WSS/HTTPS (true/false)

# Execution Mode (Optional)
EXECUTION_MODE=code            # code (default) | tools (legacy) | hybrid

# Optional Settings
SERVER_NAME=signalk-mcp-server
SERVER_VERSION=1.0.6

Modos de Execução

ModoDescriçãoCaso de Uso
code (padrão)Somente execução em isolado V8Uso em produção, máxima eficiência
toolsFerramentas MCP legadasCompatibilidade reversa
hybridAmbas as abordagens disponíveisPeríodo de migração

Exemplos

Exemplo 1: Dados Filtrados da Embarcação

Consulta: "Obtenha o nome e a posição da minha embarcação"

Código:

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

Resultado: ~200 tokens (vs 2.000 com ferramentas legadas)

Exemplo 2: Embarcações Próximas

Consulta: "Mostre embarcações dentro de 1 milha náutica"

Código:

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

  // Filter in isolate - huge savings!
  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)
  });
})()

Resultado: ~300 tokens (vs 10.000 com ferramentas legadas)

Exemplo 3: Somente Alarmes Críticos

Consulta: "Há algum alarme crítico?"

Código:

(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
  });
})()

Resultado: ~100 tokens (vs 1.000 com ferramentas legadas)

Exemplo 4: Fluxo de Trabalho com Múltiplas Chamadas

Consulta: "Dê-me um relatório de situação"

Código:

(async () => {
  // All calls in ONE execution!
  const vessel = await getVesselState();
  const ais = await getAisTargets({ pageSize: 50 });
  const alarms = await getActiveAlarms();

  // Process everything in isolate
  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
  });
})()

Resultado: ~300 tokens (vs 13.000 com 3 chamadas de ferramenta separadas!)

Desenvolvimento

Pré-requisitos

  • Node.js 18.0.0 ou superior
  • Acesso a um servidor SignalK

Configuração

# Clone repository
git clone <repository-url>
cd signalk-mcp-server

# Install dependencies
npm install

# Build
npm run build

# Run tests
npm run test:unit

# Run in development mode
npm run dev

Testes

# Unit tests (fast)
npm run test:unit

# Integration tests (requires live SignalK server)
npm run test:e2e

# Full CI pipeline
npm run ci

Arquitetura

Fluxo de Execução de Código

AI Agent
  ↓
execute_code tool
  ↓
V8 Isolate Sandbox (isolated-vm)
  ↓
SignalK SDK Functions (all async, must await)
  ↓
SignalK Binding Layer (RPC-style)
  ↓
SignalK Client (HTTP REST API)
  ↓
SignalK Server

Nota: O modo somente HTTP garante dados atualizados em cada solicitação. O código WebSocket é preservado para suporte futuro a streaming.

Componentes Principais

  • Sandbox de Isolado (src/execution-engine/isolate-sandbox.ts): Execução segura em isolado V8
  • Binding SignalK (src/bindings/signalk-binding.ts): Invocação de métodos estilo RPC
  • Gerador de SDK (src/sdk/generator.ts): Gera SDK automaticamente a partir de definições de ferramentas
  • Cliente SignalK (src/signalk-client.ts): Cliente HTTP/WebSocket para SignalK

Segurança

  • Isolamento Completo: Sem acesso a globais do Node.js
  • Limites de Memória: 128MB por execução
  • Proteção de Tempo Limite: Máximo de 30s de tempo de execução
  • Sem Exposição de Credenciais: Autenticação SignalK tratada pela camada de binding
  • Somente Leitura: Sem operações de escrita no servidor SignalK

Migração da Versão 1.x

Mudanças Importantes

A versão 1.0.6 altera o modo padrão de hybrid para code. Ferramentas legadas não estão mais disponíveis por padrão.

Compatibilidade Reversa

Para usar ferramentas legadas, defina o modo de execução:

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

Guia de Migração

Veja TOOL-MIGRATION-GUIDE.md para exemplos completos de migração.

Antes (Legado):

Tool: get_vessel_state
Returns: All vessel data (~2000 tokens)

Depois (Código):

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

Solução de Problemas

Problemas de Conexão

Verifique o status da conexão (nota: await é necessário):

(async () => {
  const status = await getConnectionStatus();  // await is required!
  return JSON.stringify(status);
})()

Modo Legado

Se você precisar de ferramentas legadas temporariamente:

EXECUTION_MODE=tools npx signalk-mcp-server

Modo de Depuração

Ative o registro detalhado:

DEBUG=true
LOG_LEVEL=debug

Contribuindo

Contribuições são bem-vindas! Consulte CONTRIBUTING.md para diretrizes.

Licença

Licença MIT - veja LICENSE para detalhes.

Recursos

Créditos

Construído com:


🚢 Boa navegação com dados marinhos alimentados por IA!