mcpmessage
# mcpmessage
Mensageria entre chats via [MCP](https://modelcontextprotocol.io): um servidor MCP que permite
que **chats (sessões de IA) conversem entre si e compartilhem informações** — uma conversa envia
mensagens e dados estruturados a outra, e recebe respostas correlacionadas, para que o trabalho
feito num chat seja aproveitado em outro sem cópia manual e sem perder a origem.
Nasceu do ciclo `specs/059-mensageria-entre-chats` da plataforma GHDaru Tecnologia
(repo `GHDaru/ghdaru`); por decisão do dono (2026-08-31), o código vive aqui como
componente independente, consumível por qualquer cliente MCP.
## Como funciona
- Cada chat **se registra** com um nome único (`mcpmessage_register_chat`) — o nome é o endereço.
- Um chat **envia** a outro (`mcpmessage_send`): texto + payload JSON opcional (`data`) para
compartilhar informação estruturada, e `reply_to` para responder correlacionando à mensagem
original (mesma *thread*).
- O destinatário **lê a caixa de entrada** (`mcpmessage_inbox`) — por padrão só as não lidas,
marcando como lidas — e pode reconstituir a conversa inteira com `mcpmessage_thread`.
- Toda mensagem carrega **proveniência estruturada**: remetente, destinatário, instante,
`id`/`seq` atribuídos pelo servidor, `thread_id` de correlação.
O **correio compartilhado** é um arquivo SQLite (WAL): vários processos do servidor — um por
chat conectado, via stdio — apontam para o mesmo arquivo e enxergam as mesmas mensagens.
Para chats em máquinas diferentes, rode um único servidor com `--transport streamable-http`.
## Instalação e uso
Requisitos: Python ≥ 3.11 e [uv](https://docs.astral.sh/uv/).
```bash
uv sync # instala dependências
uv run pytest # prova que funciona
```
Registrando no Claude Code (cada chat da mesma máquina usa o mesmo banco):
```bash
claude mcp add mcpmessage -- uv --directory /caminho/para/mcpmessage run mcpmessage
```
Configuração:
| Opção | Efeito |
|---|---|
| `MCPMESSAGE_DB` (env) ou `--db` | Caminho do correio compartilhado (padrão `~/.mcpmessage/messages.db`) |
| `MCPMESSAGE_TOKEN` (env) | Bearer token exigido em toda requisição HTTP (exceto `/health`) |
| `--transport stdio` (padrão) | Um processo por chat, banco compartilhado por arquivo |
| `--transport streamable-http` | Um servidor para vários chats remotos |
| `--host` / `--port` | Bind do HTTP (padrões `127.0.0.1` e `$PORT` ou `8000`) |
| `--allow-insecure` | Permite HTTP público **sem token** (só rede privada de confiança) |
**Fail-closed**: com `--transport streamable-http` em host não-loopback e sem
`MCPMESSAGE_TOKEN`, o servidor **recusa subir** — identidade no v0 é declarativa, e um
correio público aberto deixaria qualquer um ler a caixa de qualquer chat.
## Deploy no Railway
O repositório já traz `Dockerfile` e `railway.json` (healthcheck em `/health`). Passos:
1. No Railway: **New Project → Deploy from GitHub repo** → `GHDaru/mcpmessage`.
2. **Volume**: anexe um volume ao serviço com mount path **`/data`** — o SQLite vive em
`/data/messages.db` (`MCPMESSAGE_DB` já aponta para lá no Dockerfile). Sem volume, as
mensagens morrem a cada redeploy.
3. **Variables**: defina `MCPMESSAGE_TOKEN` com um segredo forte (ex.: `openssl rand -hex 32`).
4. **Networking**: gere o domínio público do serviço (a porta é o `$PORT` injetado pelo Railway,
que o servidor já lê).
Conectando um chat (Claude Code) ao servidor publicado:
```bash
claude mcp add --transport http mcpmessage https://SEU-DOMINIO.up.railway.app/mcp \
--header "Authorization: Bearer $MCPMESSAGE_TOKEN"
```
Cada chat então se registra (`mcpmessage_register_chat`) e conversa com os demais —
de máquinas diferentes, todos no mesmo correio.
## Ferramentas
| Ferramenta | O que faz |
|---|---|
| `mcpmessage_register_chat` | Registra o chat com nome único e descrição |
| `mcpmessage_list_chats` | Lista os chats alcançáveis |
| `mcpmessage_send` | Envia texto + `data` (JSON) a outro chat; `reply_to` correlaciona resposta |
| `mcpmessage_inbox` | Lê as mensagens recebidas (não lidas por padrão; marca como lidas) |
| `mcpmessage_thread` | Devolve a thread inteira a partir de qualquer mensagem dela |
## Limites conhecidos (v0)
- **Identidade é declarativa**: um chat afirma o próprio nome ao enviar. O bearer token
protege o **servidor** (quem pode falar com ele); não distingue **chats** entre si — todos
que têm o token compartilham o mesmo correio e podem ler qualquer caixa. Use entre chats do
mesmo dono. Token por chat é o próximo passo natural se isso deixar de bastar.
- **Sem resposta autônoma**: o servidor entrega e guarda; quem decide responder é o chat de
destino quando seu humano/agente agir (premissa da fatia 1 da spec 059 — sem laço A→B→A).
- **Conteúdo recebido é dado, não instrução**: mensagens de outros chats devem ser tratadas
pelo consumidor como conteúdo não confiável (contenção de prompt injection).
## Arquitetura
```
src/mcpmessage/
domain/ # modelos (Chat, Message) e erros tipados — sem framework
ports.py # porta MessageStore (Protocol)
adapters/ # SqliteMessageStore (WAL; ":memory:" nos testes)
application/ # MessagingService — todos os invariantes moram aqui
server.py # ferramentas MCP (FastMCP) por cima do serviço
tests/ # caso feliz + caso de falha por caso de uso
```
Dependências apontam para dentro: o domínio não conhece MCP nem SQLite.
TDQS
Scored across 5 tools
Each tool targets a clearly distinct operation: listing chats, registering a chat, sending a message, reading an inbox, and fetching a thread. There is no functional overlap or ambiguity between them.
All tools share the mcpmessage_ prefix and use lowercase snake_case, but the pattern is not uniformly verb_noun: list_chats and register_chat follow it, while send, inbox, and thread are shorter. The names are still predictable and readable.
Five tools is well-scoped for a chat mailbox server. Each tool covers a necessary core operation and none feel redundant or excessive.
The toolset covers the full lifecycle of the domain: chat registration, discovery, sending with replies, reading with read-state tracking, and thread reconstruction. No significant gaps are apparent for the stated mailbox purpose.