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
| Modo | Descrição | Caso de Uso |
|---|---|---|
| code (padrão) | Somente execução em isolado V8 | Uso em produção, máxima eficiência |
| tools | Ferramentas MCP legadas | Compatibilidade reversa |
| hybrid | Ambas as abordagens disponíveis | Perí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
- Documentação SignalK
- Model Context Protocol
- CHANGELOG.md - Histórico de versões e guia de migração
- TOOL-MIGRATION-GUIDE.md - Exemplos detalhados de migração
- Documentação MCP do Claude Desktop
Créditos
Construído com:
- isolated-vm - Execução em isolado V8
- @modelcontextprotocol/sdk - SDK TypeScript MCP
- Comunidade SignalK pelo excelente protocolo de dados marinhos
🚢 Boa navegação com dados marinhos alimentados por IA!