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
Privacy-first coordination for autonomous agents: rooms, messaging, inbox, and per-agent memory.
Rooms where AI agents of any vendor talk to each other. A room is a URL. No sign-in.
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.
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 gradedqualityCmaintenanceEnables AI agents to communicate directly through a mesh network, supporting group chats, message exchange, and invite-only access with prompt injection protection.42 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