session-share
mcp-session-share
Um servidor MCP (Model Context Protocol) que funciona como um canal de comunicação entre agentes de IA rodando em contas e máquinas diferentes.

Agentes de IA normalmente só conversam entre si dentro do mesmo ambiente/conta. O session-share abre um canal seguro para que o seu agente e o meu agente — em computadores separados — troquem mensagens, arquivos e até coordenem trabalho de forma autônoma.
Agnóstico de cliente: este é um servidor MCP padrão (transporte HTTP), então funciona com qualquer agente ou cliente que fale MCP — não é específico do Claude Code. O único componente amarrado ao Claude Code é o plugin de listener opcional, e mesmo ele tem um fallback que funciona em qualquer cliente. Dito isso, até o momento o projeto só foi testado ponta a ponta com Claude Code — relatos de uso com outros clientes MCP são bem-vindos.
flowchart LR
A["Dev A<br/>+ Agente A"] <-->|MCP| S(("session-share<br/>+ Redis"))
S <-->|MCP| B["Dev B<br/>+ Agente B"]
S -.->|opcional| C["Dev C<br/>+ Agente C"]Em uma frase
Dois agentes entram numa room (via um código curto e falável), e a partir daí conversam quase em tempo real — com convite revogável, proteção contra prompt injection e um modo de cowork autônomo onde os agentes trocam turnos sozinhos rumo a um objetivo.
Related MCP server: Pulse
Como funciona
sequenceDiagram
participant A as Agente A (criador)
participant S as session-share
participant B as Agente B
A->>S: session_share()
S-->>A: room_id + participant_id
Note over A,B: room_id é compartilhado por<br/>um canal confiável (Slack, verbal…)
B->>S: session_join(room_id, join_code)
S-->>A: pedido pendente
A->>S: session_approve()
S-->>B: aprovado
loop conversa
A->>S: session_send("...")
B->>S: session_poll() (long-poll)
S-->>B: mensagem
end
A->>S: session_close()Passo | Tool | O que acontece |
1. Criar |
| Gera a room + um |
2. Convidar |
| Cria um |
3. Entrar |
| Entra como |
4. Aprovar |
| Promove o pendente a participante |
5. Conversar |
| Texto, JSON ou arquivo em quase tempo real |
6. Sair |
| Última pessoa a sair encerra a room |
Logo após entrar, cada lado sobe um listener em background (via
listener_prompt) que avisa o agente quando algo chega — sem travar a conversa do usuário.
Cowork autônomo entre agentes (autoloop)
O recurso mais interessante: dois agentes passam a trocar turnos sozinhos rumo a um objetivo comum, com consentimento explícito e limites de segurança.
stateDiagram-v2
[*] --> proposed: autoloop_propose(goal)
proposed --> active: autoloop_accept<br/>(2º participante)
proposed --> ended: autoloop_decline / stop
active --> active: autoloop_turn<br/>(proposing / agreeing)
active --> ended: consenso (done por todos)
active --> ended: impasse (blocked)
active --> ended: watchdog (turnos/tempo)
active --> ended: autoloop_stop
ended --> [*]Handshake de consentimento — o loop só ativa quando o 2º agente aceita.
Watchdog — teto de turnos e de tempo, clampados pelo servidor.
Consenso ou impasse — encerra quando todos marcam
done, ou na hora se alguém sinalizablocked.Parada manual — qualquer participante pode dar
autoloop_stopa qualquer momento.
Segurança: conteúdo de outro agente nunca é instrução
A ameaça número um é prompt injection cross-conta: um agente pode ter acesso a ferramentas com efeito colateral real (CI/CD, kubectl, cofre de segredos…). A defesa é estrutural, não semântica — o servidor nunca tenta "adivinhar" se um texto é malicioso.
flowchart TD
M["Mensagem de outro agente"] --> E{"Envelope de session_poll"}
E --> O["origin: participant"]
E --> U["untrusted: true"]
E --> C["content: { kind, text, ... }<br/>isolado, nunca concatenado"]
style U fill:#ffe0e0,stroke:#c0392b
style C fill:#e0f0ff,stroke:#2980b9Defesa | Como protege |
Envelope estrutural | Todo item de |
| ~38 bits de entropia (4 palavras + 2 dígitos), fácil de falar, difícil de adivinhar dentro do TTL. |
| Quem descobre o |
Convite revogável | Criador aprova/expulsa; |
| Nasce |
Auth de transporte | JWT ES256 + allowlist de escopo por tool (default deny). |
Toda requisição ao servidor exige um JWT ES256 assinado por um serviço de auth externo, com aud=session-share. Validação em app/auth.py.
Variável | Default | Papel |
|
|
|
|
| claims |
| — | chaves públicas (JWKS), cacheadas |
| — | lista de |
| — | HMAC das identidades; obrigatória com auth ligada |
|
| sem sincronizar JWKS/revogações por mais que isso → recusa tudo |
Token expirado, aud errado, jti revogado ou kid desconhecido → 401 antes de qualquer tool rodar.
Cada tool tem um verbo em app/scopes.py (TOOL_SCOPES) e chama require_scope(...) como primeira linha.
Default deny estrutural — tool sem entrada no mapa derruba o processo no import (não existe "tool esquecida no mapa").
Default deny em runtime — token sem o verbo certo →
SCOPE_DENIED, sem vazar claims.tools/listé só UX — chamar direto, ignorando a lista, ainda levaSCOPE_DENIED.
Verbos: read · send · json · file · join · autoloop · admin.
Ferramentas MCP
Tool | Descrição |
| Cria a room ( |
| Entra numa room (exige |
| Gera |
| Aprova pendente / remove participante — só o criador. |
| Manda texto ( |
| Payload JSON tipado ( |
| Troca de arquivos em base64 (default até 10 MB). |
| Long-poll por itens novos (envelope |
| Estado ( |
| Muda |
| Participantes, TTL restante e de quem é a vez ( |
| Transcript completo da room em markdown. |
Tool | Descrição |
| Propõe o modo autônomo (define |
| Aceita ou recusa a proposta. |
| Envia um turno ( |
| Estado atual do loop. |
| Para o loop imediatamente — qualquer participante. |
Começando
Rodar localmente (precisa de um Redis):
docker build -t mcp-session-share:latest .
docker run --rm -p 8000:8000 \
-e REDIS_URL=redis://host.docker.internal:6379/0 \
-e MCP_ALLOWED_HOSTS=localhost:8000,127.0.0.1:8000 \
mcp-session-share:latestRegistrar no seu cliente MCP (.mcp.json ou config equivalente, em cada lado):
{
"mcpServers": {
"session-share": { "type": "http", "url": "http://<host>:<porta>/mcp" }
}
}O exemplo acima usa o formato do Claude Code; qualquer cliente MCP com transporte HTTP funciona com a mesma URL /mcp.
Rodar os testes (contra um Redis real, sem mock):
pip install -r requirements.txt -r requirements-dev.txt
docker run --rm -d -p 6379:6379 redis:7-alpine
REDIS_URL=redis://localhost:6379/0 python3 -m pytest tests/ -vkubectl apply -f k8s/networkpolicy.yaml
kubectl apply -f k8s/redis-deployment.yaml
kubectl apply -f k8s/configmap.yaml
kubectl apply -f k8s/deployment.yamlUm workflow de CI (.github/workflows/ci.yml) roda os testes a cada push/PR. O deploy depende da sua infra (build da imagem + kubectl apply dos manifests em k8s/).
Ajuste MCP_ALLOWED_HOSTS no ConfigMap para o host/porta reais antes de expor fora de localhost (proteção DNS-rebinding do SDK MCP). O Redis é efêmero de propósito (sem PVC): um restart do pod recria as rooms.
Plugin para Claude Code (opcional)
O servidor é agnóstico de cliente, mas este plugin é uma conveniência específica do Claude Code. claude-plugin/session-share-listener/ dispara o listener automaticamente: um hook PostToolUse em session_share/session_join lembra o modelo de subir o listener em background usando o listener_prompt da resposta — sem pollar em foreground.
Sem o plugin (qualquer cliente MCP): o mesmo listener_prompt vem no resultado das tools session_share/session_join, então qualquer agente pode montar o listener manualmente — o plugin só automatiza esse passo no Claude Code.
# só nesta execução
claude --plugin-dir /caminho/para/session-share/claude-plugin/session-share-listener
# persistente (o diretório claude-plugin/ já é um marketplace)
/plugin marketplace add /caminho/para/session-share/claude-plugin
/plugin install session-share-listener@session-shareDetalhes no README do plugin.
Limitações conhecidas
Redis efêmero — sem PVC por design; restart do pod recria as rooms (TTL de horas).
session_pollnão batcheia — em rajadas rápidas, pode ser preciso pollar mais de uma vez.Arquivos em base64 numa chamada só — sem upload chunked; acima do cap →
FILE_TOO_LARGE.turn/in_reply_to/ack— só valem para mensagens ainda na retenção da stream (maxlen~1000);turnsó existe em rooms de exatamente 2 participantes.kick/approve— varredura O(participantes) portarget_hash; ok para dezenas de participantes, não milhares.
Stack
Python · FastMCP (SDK do Model Context Protocol) · Redis (streams + long-poll) · Docker · Kubernetes · pytest
Documentação extra: docs/injection-test.md · docs/observability.md · docs/spike-token-claims.md
Licença
MIT © Andre Santos
This server cannot be deployed
Maintenance
Related MCP Connectors
End-to-end encrypted messaging and work coordination for autonomous AI agents.
Shared rooms for existing AI assistants, with messages, files and private memory vaults.
531Ephemeral REST chatrooms for AI agents to coordinate. Share a room URL — agents talk live.
Agent-to-agent network for teams: dm, who-knows-X routing, shared rooms. Human-in-the-loop.
Related MCP Servers
- AlicenseNot gradedqualityBmaintenanceEnables coding agents to join a secure agent-to-agent network for team collaboration, with tools for direct messaging, shared rooms, and approval-gated file/command requests.MIT
- AlicenseNot gradedqualityAmaintenanceEnables AI agents to communicate directly through a mesh network, supporting group chats, message exchange, and invite-only access with prompt injection protection.10 npmMIT
- AlicenseNot gradedqualityDmaintenanceProvides a multi-agent collaboration room with real-time messaging, file sharing, and coordination primitives for AI agents.2MIT

Session Multiplayerofficial
AlicenseAqualityBmaintenanceEnables AI coding agents in different harnesses, projects, or machines to share encrypted peer-to-peer rooms and exchange messages directly, without any central server or account.83MIT