
Dando acesso somente leitura a um assistente de IA no Microsoft Loop — sem quebrar permissões
Dando a um assistente de IA acesso somente leitura ao Microsoft Loop — sem quebrar permissões
Eu queria que meu assistente de IA lesse as páginas do Microsoft Loop da minha equipe — resumisse um
workspace, puxasse os últimos OKRs para um rascunho, respondesse "o que decidimos sobre
X." Pedido simples. Isso se transformou em um problema de engenharia genuinamente interessante, e
eu acabei construindo um pequeno servidor MCP de código aberto para resolvê-lo. Aqui está o
desafio, a solução e as armadilhas ao longo do caminho.
O resultado é código aberto (MIT): loop-reader-mcp.
O desafio
Duas barreiras, logo no início.
Barreira 1: O Microsoft Loop não possui uma API de conteúdo. A partir de meados de 2026, não há
endpoint Graph para ler ou escrever o conteúdo de uma página do Loop — sem "obter página", sem
"listar workspace." O Loop está posicionado contra o Notion e o Confluence, mas você
não pode obter programaticamente seu próprio conteúdo de forma estruturada. O roadmap do Loop de 2026
esobre governança, não uma API de conteúdo.
Barreira 2: onde o Loop realmente armazena as coisas. As páginas do workspace do Loop vivem em
containers do SharePoint Embedded (SPE), e os componentes do Loop do Teams/Outlook
vivem como .loop arquivos no OneDrive. Há um truque documentado: o Microsoft
Graph pode converter um .loop arquivo em HTML instantaneamente com
GET /drives/{id}/items/{id}/content?format=html. Portanto, a leitura é possível
através da camada de arquivos, mesmo sem uma API do Loop.
Mas então o verdadeiro problema apareceu — aquele que vale a pena escrever sobre.
A armadilha de permissão
O SharePoint Embedded não aceita tokens delegados (por usuário) para downloads de conteúdo. Apenas uma
identidade somente de aplicativo pode buscar os bytes.
Se você construir a coisa ingênua — um serviço que usa sua identidade de aplicativo para ler
Loop — você criou uma máquina de achatamento de permissões. O aplicativo pode ler
tudo, então qualquer um que puder se comunicar com seu serviço pode ler qualquer página do Loop no
tenant, independentemente do que eles pessoalmente têm acesso. Isso é um vazamento de dados
com etapas extras. Inaceitável.
Então a pergunta se tornou: como você permite que um serviço leia conteúdo com uma identidade de aplicativo,
enquanto garante que cada usuário veja apenas o que está autorizado a ver?
A solução: separar descoberta de recuperação
A percepção que resolveu isso: A Pesquisa Graph é ajustada para segurança para chamadores delegados,
mesmo para conteúdo SPE. A pesquisa respeita as permissões do usuário; apenas o download de conteúdo
precisa da identidade do aplicativo.
Então eu separei as duas operações em duas identidades:
A descoberta é executada como o usuário. Quando o assistente pesquisa no Loop, o servidor
troca o token do usuário via o fluxo OAuth On-Behalf-Of (OBO) e
chama a Pesquisa Graph como aquele usuário. A Microsoft ajusta os resultados exatamente
ao que eles podem acessar. O servidor registra o(driveId, itemId)de cada
resultado em um cache por usuário de curta duração.A recuperação é controlada por essa descoberta. Quando o assistente pede para ler uma
página, o servidor recusa a menos que aquele exato(driveId, itemId)par esteja no
cache deste usuário — ou seja, a menos que eles pessoalmente acabaram de descobri-lo através
desa própria pesquisa ajustada. Somente então ele usa a identidade do aplicativo para buscar
e converter os bytes.
search -- OBO (identidade do usuário) --> Pesquisa Graph -> resultados ajustados pela Microsoft
-> (driveId,itemId) cache por usuário
read -- este par está no cache do chamador? --> não -> recusar (sem chamada Graph)
sim -> identidade do aplicativo -> ?format=html
A decisão de autorização é da Microsoft, não minha. Um usuário não pode descobrir
uma página que não pode acessar (a pesquisa é executada como eles), e não pode ler uma página que
não descobriu. A identidade do aplicativo é apenas um mecanismo de recuperação para bytes que
o usuário já provou que pode ver. O achatamento de permissões foi resolvido.
Tornando-o um verdadeiro servidor MCP
Eu expus isso como um remoto Modelo de Protocolo de Contexto servidor com três
tools somente leitura: loop_search, loop_list_components, e loop_get_page.
Somente leitura não é uma alternância de política — o cliente Graph apenas permite GET e
POST /search/query, então não há como estruturalmente escrever. (Bom, porque
o sobrescrever um .loop arquivo com qualquer outra coisa o corrompe, e não há
API de escrita suportada de qualquer maneira.)
Para autenticação, inicialmente tentei colocar um gateway de "autenticação fácil" da plataforma na frente do
servidor. Grande erro — o gateway interceptou o handshake OAuth e
o cliente MCP nunca conseguiu descobrir onde fazer login. A solução foi fazer o
servidor ser seu próprio servidor de recursos OAuth: ele publica os documentos de descoberta
(/.well-known/oauth-protected-resource e /.well-known/oauth-authorization-server)
apontando os clientes para o Microsoft Entra, e valida o token de entrada ele mesmo
(assinatura via JWKS do Entra, público, emissor, expiração). Sem gateway, sem
interceptação, e o acesso ainda é totalmente controlado porque o Entra só emite tokens
para usuários atribuídos ao aplicativo.
Lições aprendidas (a metade não glamourosa)
- A pesquisa delegada + recuperação somente de aplicativo é um padrão legítimo e poderoso para qualquer serviço em cima do SharePoint Embedded. Ajuste na descoberta, busque na recuperação.
- Não deixe um gateway de autenticação da plataforma envolver um servidor MCP remoto — o fluxo OAuth do MCP precisa que o cliente alcance a própria descoberta/desafio do servidor. Deixe o aplicativo ser responsável pela autenticação.
-
Vincule o portão de recuperação a
(driveId, itemId)pares, não apenas ao ID do item — caso contrário, um chamador poderia reproduzir um ID descoberto contra um drive diferente. - Falhe fechando em todos os lugares: sem token, sem identidade, cache miss, entrada expirada -> recusar. Em hospedagem de múltiplas instâncias, um usuário apenas re-pesquisa; isso é uma falha segura, não um vazamento.
- A credencial do aplicativo é a joia da coroa. Ela possui leitura em todo o tenant. Armazene-a em um gerenciador de segredos, prefira um certificado, gire-a e considere a lista de permissões de IP do servidor.
- Fique atento ao atraso de revogação. Os resultados da descoberta são armazenados em cache por alguns minutos, então perder o acesso não é instantâneo. Ajuste o TTL de acordo com sua tolerância ao risco.
Experimente
O código está no GitHub sob MIT: github.com/DenizV/loop-reader-mcp. O README cobre a
registro do aplicativo Entra, o registro de convidado do SharePoint Embedded uma única vez,
hospedagem e conexão a um cliente MCP. SECURITY.md documenta o modelo e
os riscos residuais a serem fechados antes da produção.
É código da comunidade, não um produto certificado — revise-o e execute uma varredura de dependências
antes de apontá-lo para dados reais. Mas se você estava querendo deixar um
assistente ler seu conteúdo do Loop sem entregar as chaves de todo o
tenant, esse padrão funciona.
Se você construir sobre isso ou encontrar uma abordagem mais afiada, adoraria ouvir.
Empresas brasileiras podem se beneficiar ao integrar assistentes de IA em suas ferramentas de colaboração, como o Microsoft Loop. A solução apresentada aborda a segurança e a privacidade, essenciais para a proteção de dados sensíveis. Implementar esse tipo de tecnologia pode melhorar a eficiência e a organização das equipes.


