Garrett Smith
  1. Report
  2. 3 Engagements
  3. E-01
E-01Demo · fictional client

Connecting Claude to Microsoft 365 without handing over the tenant

A TypeScript MCP server for Claude Desktop, Claude Code or any MCP client, over stdio or Streamable HTTP.

TypeWorking demo for Tallgrass Precision Components, a fictional manufacturer
StatusLive demo
ServicesC-1 Connect AI to your company data, C-3 AI workflow automation across Microsoft 365
Stack
  • TypeScript
  • Node 22
  • @modelcontextprotocol/sdk (stdio and Streamable HTTP)
  • zod 4
  • Microsoft Graph REST with OAuth client credentials
  • mammoth for .docx
  • vitest
  • Vite and React for the replay UI
  • Playwright for screenshots
  • and the Claude Code CLI for the recordings

The problem

A manufacturer wants staff to ask an AI assistant "what's our nonconforming product procedure?" or "which supplier deliveries slipped this week?" The answers live in SharePoint, a help desk list and a shared mailbox. The easy way to connect them is an app with Sites.Read.All and Mail.Read. That lets the assistant read every site and every mailbox, HR and payroll included, and nobody can say afterwards what it looked at.

The client in this demo is fictional: Tallgrass Precision Components, a 180-person CNC shop with an AS9100 quality system and a two-person IT team.

What I built

A TypeScript MCP server for Claude Desktop, Claude Code or any MCP client, over stdio or Streamable HTTP. It has nine tools: six read tools (documents, tickets, the quality@ mailbox, the directory), two write tools (a ticket reply and an IT task) and an approval status check.

The write tools cannot write. They validate the request and return a pending approval id. A named IT person approves it with a CLI, and only then does the connector touch SharePoint. Both support a dry run.

A real Microsoft Graph adapter (client credentials, plain fetch) is the default. A mock adapter serves a fixture tenant: 16 documents, 30 tickets, 41 emails and 23 directory entries. A static replay site shows six recorded Claude sessions with the approval items and audit lines each produced.

How it works

stdio or HTTP + bearerreadwrite

Claude / MCP client

Rate limit

zod validation

Allowlist + deny-list

Tool

PII redaction

JSONL audit

Approval queue

Approver CLI

Graph adapter: real or mock

SharePoint · quality@ · Entra

stdio or HTTP + bearerreadwrite

Claude / MCP client

Rate limit

zod validation

Allowlist + deny-list

Tool

PII redaction

JSONL audit

Approval queue

Approver CLI

Graph adapter: real or mock

SharePoint · quality@ · Entra

Figure 1. How it works Open full size

Every call goes through one pipeline, so no tool can skip a control. The rules live in one config file: allowed and blocked sites, blocked folders and sensitivity labels, the mailbox, directory fields, rate limits and approvers.

Security and control

  • Least privilege at Microsoft's layer. Sites.Selected with read on Quality and Engineering and write on IT only. Mail limited to quality@ with Exchange RBAC for Applications. The directory query $selects five fields. The permission matrix lists what each tool avoids: Sites.Read.All, Files.Read.All, tenant-wide Mail.Read, Mail.Send, Tasks.ReadWrite.All.
  • Enforced again in code. The deny-list wins over the allowlist, so adding HR to the config by mistake still fails. The mock adapter returns 403 for ungranted sites, the same as Graph, so tests cover both layers.
  • Redaction of phone numbers, SSN-like numbers, card numbers and pay amounts runs on every result and every error.
  • Audit. Each call writes one JSONL line: caller, tool, argument hash and key names, outcome, result count, withheld count, redactions and latency. Argument values are never logged.
  • Approvals. The approver must be named, on the approver list and not the requester. Requests expire after 72 hours and re-validate before executing.

Results

  • 43 vitest tests pass: redaction, allowlist, approval gating, audit log, rate limits, the Graph adapter against faked HTTP, and HTTP auth.
  • Six real headless Claude Code sessions recorded on 2026-10-07 with claude-opus-5-5: 17 tool calls, 5.6 to 19.3 seconds per session.
  • Connector time per call in mock mode: 0 to 5 ms (median 1 ms), from the audit lines.
  • Controls fired in the recordings: one ACCESS_DENIED (HR site), two withheld items (a labelled pay spreadsheet, a confidential email), seven redactions (six phone numbers, one hourly rate).
  • One reply queued, then approved through the CLI. One task dry-run, queued and left pending.
  • The live Graph path is tested against faked HTTP only, not a real tenant.

Stack

TypeScript, Node 22, @modelcontextprotocol/sdk (stdio and Streamable HTTP), zod 4, Microsoft Graph REST with OAuth client credentials, mammoth for .docx, vitest, Vite and React for the replay UI, Playwright for screenshots, and the Claude Code CLI for the recordings.

What I'd do for your company

I'd start with one question your staff ask every week and the two or three data sources that answer it. I'd write the permission matrix with your admin before any code, so you see exactly what the app can reach. Then I'd deploy on your infrastructure with your Entra app registration, approvals going to your IT people and the audit log going where you already keep logs. You get the code, the config and a runbook for adding the next source.

Exhibits

Screenshots are real renders of the running demo. Data shown belongs to the fictional Tallgrass Precision Components.

Exhibit VWalkthrough film
  • Session procedure and cmm tickets
    Exhibit ASession procedure and cmm tickets
  • Session supplier late deliveries answer
    Exhibit BSession supplier late deliveries answer
  • Approval gated ticket reply
    Exhibit CApproval gated ticket reply
  • Hr salary request blocked
    Exhibit DHr salary request blocked
  • Permission matrix
    Exhibit EPermission matrix
  • Architecture dark
    Exhibit FArchitecture dark
  • (mobile) approval session
    Exhibit G(mobile) approval session

Want something like this on your own data?

Send me the details on Upwork: what the AI should reach, who will use it and who signs off. I will reply with how I would build it and what it would touch.

Hire me on Upwork
Prepared by Garrett SmithAI Integration EngineerContracts and messages through Upwork
REVIEWED & TESTEDAPPROVED FOR HANDOFFG. SMITH · ACCOUNTABLE