Case study 05 · Tool calling & MCP

Safe AI Access to Admin Systems: 866 Commands Behind 5 Governed Tools

AI agents do routine admin work in Microsoft 365 and the ERP without ever holding open-ended access — read-only by default, permissions scoped to the task.

Enterprise systems expose large admin surfaces with no built-in notion of scoped agent access. Microsoft 365 administration alone spans 866 CLI commands; NetSuite's API can write records that touch invoicing and financial reporting. Both needed agent access — for routine M365 admin work across SharePoint, Outlook, and Teams, and for agent-driven analytics and record operations in NetSuite.

Design constraints

Wrapping 866 commands as 866 static tool definitions wasn't viable: past a few dozen tools, an LLM's tool-selection accuracy degrades, and holding that many schemas in the context window costs tokens and latency on every call. The function-calling surface had to stay small. Read-only had to be the default, with permissions scoped to the task — SharePoint, not tenant-wide Graph.

Architecture

The server — built on MCP (Model Context Protocol, the open standard for connecting AI agents to tools) — fronts all 866 M365 CLI commands behind five tools: a command-discovery tool to find the right CLI command for a task, a generic executor to run it, a help/schema lookup, a raw Graph API escape hatch for anything the curated commands don't cover, and a status check. That's dynamic tool discovery — schemas resolved on demand at call time instead of 866 static declarations up front — which keeps tool-selection accuracy high and the context-window cost of every call low.

AI agent holds 5 schemas Cloudflare Access Zero Trust policy same gate as human sign-in MCP server — five governed tools 1 · discover the command 2 · execute it 3 · fetch schema on demand 4 · raw Graph escape hatch 5 · status check schema-on-demand, not 866 static schemas Microsoft 365 866 CLI commands NetSuite REST · SuiteQL · Restlet Read-only by default · scoped to SharePoint, not tenant-wide Graph NetSuite follows the same pattern — schemas on demand via SuiteQL, gaps patched with a custom Restlet
The agent holds five schemas and looks up commands at call time. All agent traffic passes the same Cloudflare Access policies that govern human sign-in.

NetSuite follows the same pattern: rather than exposing every SuiteQL table as a static tool, schemas are fetched on demand through tool search, and gaps in the native MCP channel's field exposure are patched with a custom Restlet (a lightweight custom NetSuite API endpoint). The integration role started read-only, with write capabilities — bin queries, inventory adjustments, item writes — added individually, each granted only after a concrete permission failure proved a real task needed it, and each grant documented in a reference file so no future agent session re-diagnoses the same blocker.

Both integrations sit behind Cloudflare Access. The same Zero Trust broker that handles human single sign-on also fronts an MCP Server Portal, so agent credentials go through the same access policies rather than a separate path.

Outcome

The Microsoft 365 server has been live since late July 2026. The NetSuite MCP integration is in daily use underneath most of the other work in this portfolio — the pricing audits, the item writes, the reporting. A finance MCP is next: designed to connect official tax-compliance MCP servers and build a custom integration for the company's accounts-receivable payment processor, running on Cloudflare Workers, currently at the design-doc stage.

Stack
MCP servers (Node/TypeScript) Microsoft 365 CLI NetSuite REST SuiteQL custom Restlet Cloudflare Access Cloudflare Workers