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.

before
{
  "mcpServers": {
    "entra": {
      "command": "npx",
      "args": ["-y", "@acme/entra-mcp"]
    }
  }
}
after
{
  "mcpServers": {
    "entra": {
      "command": "neti",
      "args": ["gate", "--stdio", "--",
               "npx", "-y", "@acme/entra-mcp"]
    }
  }
}