Connect
Two connections, in this order: the directory the gate asks how big something is, and the agent whose calls it sits in front of.
The directory
Microsoft 365 · Entra ID
Reads group membership and application assignments. Nothing else, and nothing is written.
What it asks for
One application permission — GroupMember.Read.All — which is Microsoft's own documented least-privilege choice for the count endpoint. Read-only. No mailbox, no files, no write scope of any kind.
How connecting is verified
By using the credential, not by storing it. Connecting counts the directory, so “connected” means a real read succeeded rather than a form submitted.
Put the gate in front of your agent
No SDK, no code change, no redeploy. The agent does not learn that the gate exists — it learns that a call was too big, which is a thing it already knows how to handle.
Or skip the reading: neti init finds the MCP servers already configured on the machine, asks each one what tools it exposes, and writes the policy — with every ceiling left blank, because those come from your traffic a week later and not from a generator.
.mcp.json · claude_desktop_config.json · ~/.cursor/mcp.json
Whatever command launches the server becomes an argument to the gate. The client keeps talking to the same name, over the same transport, to a process that now resolves before it forwards.
{
"mcpServers": {
"entra": {
"command": "npx",
"args": ["-y", "@acme/entra-mcp"]
}
}
}{
"mcpServers": {
"entra": {
"command": "neti",
"args": ["gate", "--stdio", "--",
"npx", "-y", "@acme/entra-mcp"]
}
}
}