Implementa servidor MCP (Model Context Protocol) HTTP no Captain pra o Hermes Agent invocar tools do Captain via `hermes mcp add`. Substrato pra integração de Nível 2 onde o agente consulta tools quando precisa executar ações reais (buscar FAQ, adicionar label, futuramente Pix etc). Arquivos: - app/controllers/webhooks/captain/mcp_controller.rb Endpoint POST /webhooks/captain/mcp. Valida HMAC (CAPTAIN_MCP_SECRET), parseia JSON-RPC, despacha pro Server. Extrai params._captain_context com multi-tenant ids (conversation_id, inbox_id, account_id, etc). - enterprise/app/services/captain/mcp/server.rb Subset MCP suficiente: initialize, tools/list, tools/call, ping, notifications/initialized. JSON-RPC síncrono (sem SSE). - enterprise/app/services/captain/mcp/tool_registry.rb Lista centralizada de tools. - enterprise/app/services/captain/mcp/tools/base_tool.rb Interface base pras tools (.name, .description, .input_schema, #call). - enterprise/app/services/captain/mcp/tools/add_label_tool.rb Tool 1: aplica label na conversation atual. - enterprise/app/services/captain/mcp/tools/faq_lookup_tool.rb Tool 2: busca semântica em FAQs (Captain::AssistantResponse via pgvector cosine). Reaproveita SearchReplyDocumentationService pra paridade com o caminho legado do Captain. - config/routes.rb Rota POST /webhooks/captain/mcp. Conexão pelo Hermes: hermes mcp add captain-tools --url http://CAPTAIN_HOST/webhooks/captain/mcp Auth: HMAC X-Hub-Signature-256 quando CAPTAIN_MCP_SECRET setado. TODO próxima sprint: generate_pix_tool, send_suite_images_tool. Handoff fica via automation hoje (UI Chatwoot). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
57 lines
1.4 KiB
Ruby
57 lines
1.4 KiB
Ruby
# Interface base pras tools MCP do Captain.
|
|
#
|
|
# Cada tool concreta herda desta classe e implementa:
|
|
# - .name — identificador (snake_case)
|
|
# - .description — texto pro LLM decidir quando chamar
|
|
# - .input_schema — JSON Schema (Draft 2020-12) dos argumentos
|
|
# - #call(args, context:) — execução real
|
|
#
|
|
# context é um hash com metadata da invocação (ex: conversation_id,
|
|
# inbox_id, account_id) extraído do request MCP. Tools usam isso pra
|
|
# resolver entidades do Captain (Conversation, Inbox, etc).
|
|
class Captain::Mcp::Tools::BaseTool
|
|
class ExecutionError < StandardError; end
|
|
|
|
class << self
|
|
def name
|
|
raise NotImplementedError, "#{self} must implement .name"
|
|
end
|
|
|
|
def description
|
|
raise NotImplementedError, "#{self} must implement .description"
|
|
end
|
|
|
|
def input_schema
|
|
raise NotImplementedError, "#{self} must implement .input_schema"
|
|
end
|
|
|
|
def to_mcp_descriptor
|
|
{
|
|
name: name,
|
|
description: description,
|
|
inputSchema: input_schema
|
|
}
|
|
end
|
|
end
|
|
|
|
def call(_args, context:)
|
|
raise NotImplementedError, "#{self.class} must implement #call"
|
|
end
|
|
|
|
protected
|
|
|
|
def text_response(text)
|
|
{
|
|
content: [{ type: 'text', text: text.to_s }],
|
|
isError: false
|
|
}
|
|
end
|
|
|
|
def error_response(message)
|
|
{
|
|
content: [{ type: 'text', text: message.to_s }],
|
|
isError: true
|
|
}
|
|
end
|
|
end
|