🔌 MCP servers
Model Context Protocol é um padrão aberto da Anthropic para conectar agentes a fontes de dados e ferramentas externas. Hermes conecta a qualquer MCP server (stdio ou SSE) declarativamente, abrindo todo o ecossistema MCP — filesystem, GitHub, Postgres, Slack, web search e centenas mais.
# ~/.hermes/config.yaml
mcpServers:
filesystem:
command: npx
args: ["-y", "@modelcontextprotocol/server-filesystem", "/home/nei/projetos"]
scope: user
github:
command: npx
args: ["-y", "@modelcontextprotocol/server-github"]
env:
GITHUB_PERSONAL_ACCESS_TOKEN: ${GH_TOKEN}
scope: project
postgres-prod:
command: npx
args: ["-y", "@modelcontextprotocol/server-postgres", "${PG_URL}"]
scope: user
enabled: false # liga via: hermes mcp enable postgres-prod
💡 Comandos essenciais
- •
hermes mcp list— servers configurados e estado - •
hermes mcp enable <name>/disable— toggle sem editar YAML - •
hermes mcp call <server> <tool> --args '...'— testar tool manualmente - •
hermes mcp logs <server>— debug de stdio/handshake
⚠️ Cuidado com escopo
MCP server filesystem com scope: user dá acesso ao path para qualquer projeto. Para repositórios sensíveis (cliente, financeiro), use scope: project e configure por workspace. Nunca commite tokens — sempre ${VAR}.
🛠️ Tool Gateway
Quando você quer lógica imperativa rápida — chamar uma API interna, ler um banco, processar dados — sem o overhead de empacotar um MCP server, use o Tool Gateway. Decore uma função Python com @hermes.tool e o schema é inferido por type hints.
# ~/.hermes/tools/internal.py
from hermes import tool
from typing import Literal
import httpx
@tool
def jira_create_ticket(
project: str,
summary: str,
description: str,
priority: Literal["low", "medium", "high"] = "medium",
) -> dict:
"""Cria um ticket no Jira interno e devolve url + key.
Use quando o usuário pedir 'abre ticket', 'cria task no jira'
ou descrever um bug que precisa ser rastreado.
"""
r = httpx.post(
"https://jira.empresa.com/rest/api/3/issue",
json={
"fields": {
"project": {"key": project},
"summary": summary,
"description": description,
"priority": {"name": priority.capitalize()},
"issuetype": {"name": "Task"},
}
},
auth=(os.getenv("JIRA_USER"), os.getenv("JIRA_TOKEN")),
timeout=10,
)
r.raise_for_status()
data = r.json()
return {"key": data["key"], "url": f"https://jira.empresa.com/browse/{data['key']}"}
💡 Dica: type hints viram schema
Literal["low","medium","high"] vira enum no JSON Schema. Optional[str] vira parâmetro opcional. A docstring vira description da tool. Capricho aqui economiza muito YAML.
📊 Quando usar o quê
- Skill: processo multi-passo, instruções para o modelo
- Tool Gateway: 1 função imperativa, chamada de API/DB interna
- MCP server: capacidade compartilhada entre múltiplos agentes/projetos
- Channel: integração com plataforma de mensagem nova
📡 Adicionar novo canal
Um canal é o adapter entre uma plataforma de mensagem (Telegram, Discord, WhatsApp, Slack) e o core do Hermes. Implementa uma interface mínima — receber mensagem, enviar resposta — e o agente passa a "morar" onde seus usuários já estão.
# ~/.hermes/channels/discord_channel.py
from hermes.channels import Channel, IncomingMessage, OutgoingMessage
import discord
class DiscordChannel(Channel):
name = "discord"
def __init__(self, token: str, allowed_guild: int):
self.client = discord.Client(intents=discord.Intents.default())
self.token = token
self.allowed_guild = allowed_guild
async def start(self):
@self.client.event
async def on_message(msg):
if msg.author.bot or msg.guild.id != self.allowed_guild:
return
await self.on_message(IncomingMessage(
conversation_id=f"discord:{msg.channel.id}",
user_id=str(msg.author.id),
text=msg.content,
attachments=[a.url for a in msg.attachments],
))
await self.client.start(self.token)
async def send_message(self, out: OutgoingMessage):
channel_id = int(out.conversation_id.split(":")[1])
chan = self.client.get_channel(channel_id)
await chan.send(out.text)
📊 Canais oficialmente suportados
- CLI — terminal interativo (default)
- HTTP API — REST
/v1/chatcompatível OpenAI - Telegram — bot via Bot API
- Discord — bot com slash commands
- Slack — Events API + Socket Mode
- WhatsApp — via WhatsApp Cloud API (beta)
⏰ Cron jobs
Cron transforma o agente de reativo em proativo: briefings matinais, relatórios semanais, checagens periódicas de status. Hermes embute um agendador com expressão cron padrão, retry automático e logs persistentes.
# Briefing às 9h em dias úteis, executa a skill morning-briefing
$ hermes cron add "0 9 * * 1-5" --skill morning-briefing \
--channel telegram --user @nei
✓ Job criado: cron-7f3a (próxima execução: amanhã 09:00 BRT)
# Listar jobs
$ hermes cron list
ID SCHEDULE TARGET LAST RUN STATUS
cron-7f3a 0 9 * * 1-5 skill:morning-briefing hoje 09:00 ✓ OK
cron-b21e */15 * * * * skill:health-check 14:45 ✓ OK
cron-d8c1 0 18 * * 5 skill:weekly-report sex 18:00 ✓ OK
# Ver logs de um job
$ hermes cron logs cron-7f3a --tail 5
# Remover
$ hermes cron rm cron-7f3a
💡 Dica: timezone explícito
Por default Hermes usa o TZ do sistema. Em servidor em UTC isso te trai. Passe --tz America/Sao_Paulo ao criar o job para deixar explícito e evitar surpresa no horário de verão.
🤝 Contribuindo
Bug que você encontrou hoje é bug que todo mundo terá amanhã. Devolver para o upstream multiplica seu impacto. O repo é github.com/NousResearch/hermes-agent e segue fluxo open source padrão.
Issue primeiro
Discussão antes de código
Para mudanças não-triviais, abra issue descrevendo problema + proposta. Evita PR fechado por estar fora de escopo.
Fork + branch
Branch descritiva
git checkout -b fix/cron-tz-handling. Não trabalhe direto em main do seu fork.
Testes
Verde local antes de PR
pytest tests/ -q + ruff check .. Adicione teste cobrindo o bug que você corrigiu.
PR pequeno
Foco em uma coisa
PR pequeno revisa em horas. PR grande dorme semanas. Conventional commits (fix:, feat:, docs:).
Review
Responda rápido
Maintainers comentam — não vire defensivo, ajuste e responda. PRs ficam órfãos quando autor some.
Merge
Sai no próximo release
Sua mudança vira parte oficial do Hermes. Anuncie no Discord, compartilhe nas redes.
✓ O que FAZER
- ✓Issue antes de PR grande
- ✓Testes cobrindo a mudança
- ✓PR pequeno, foco único
- ✓Atualizar docs/CHANGELOG junto
✗ O que NÃO fazer
- ✗Breaking change sem discussão
- ✗PR de 50 arquivos misturando tudo
- ✗"refactor geral" sem motivo claro
- ✗Ignorar reviews por semanas
⚠️ Atenção: licença MIT
Hermes Agent é MIT. Se você fizer fork ou redistribuir (mesmo modificado), mantenha o LICENSE original e os avisos de copyright. É curto, é trivial — e é obrigatório.
🌐 Comunidade
Hermes vive num ecossistema vibrante. Discord da Nous é o primeiro stop para perguntas em tempo real, GitHub Discussions para tópicos longos, e marketplaces de skills/MCPs crescendo a cada semana.
🔗 Recursos oficiais
- •Discord: discord.gg/NousResearch — canal #hermes-agent
- •Repo: github.com/NousResearch/hermes-agent
- •Docs: hermes-agent.nousresearch.com/docs
- •PyPI: pypi.org/project/hermes-agent
- •AWS sample: aws-samples/sample-host-hermesagent-on-amazon-bedrock-agentcore
- •Spec skills: agentskills.io
💡 Dica: Discord é o primeiro stop
Antes de abrir issue, faça search no Discord. 70% das dúvidas já foram respondidas. Quando perguntar, traga MRE (mínimo, reproduzível, exemplo): versão, comando, output, expected. Retribua respondendo outros — é assim que reputação se forma e maintainers te notam.
✅ Resumo do Módulo
mcpServers no YAML.@hermes.tool — type hints viram schema, docstring vira description.on_message + send_message e o agente mora onde seus usuários estão.--tz explícito.Próximo módulo:
6.3 — 🧠 Padrões avançados de skills. Composition, state machines, RAG embutido, multi-LLM router. Hora de sair do hello world e ver como skills crescem de verdade.