← Back to Insights
ORIGINAL

MCP Builders, Chapter 2: OAuth, Tokens, and the Over-Permission Trap

When a user authorizes your MCP server, they delegate authority to an agent — not just to your app. Here is how OAuth scopes, token lifetime, and tool design interact, and why most builders accidentally give LLMs too much access.

OAuth scopes and permission boundaries between users, MCP servers, and AI agents

Part of MCP Builders — The Producer Playbook. Chapter 2 of 6.

Your MCP server works in the demo. A developer connects GitHub — or your product — completes OAuth, and the agent happily calls tools. Everyone applauds.

Three weeks later, security asks a question nobody prepared for:

“What exactly did the user authorize — and what can the LLM do with it when nobody is watching?”

That is not a hypothetical. OAuth for SaaS was designed for humans clicking “Allow” and then making deliberate API calls. MCP adds a middle layer: an agent that may invoke tools repeatedly, in parallel, with imperfect judgment, while the user is in another tab.

This chapter is about building authorization that survives that reality — not OAuth syntax (the spec and SDKs cover that), but the permission model your server exposes to agents.

The delegation chain you are actually building

When OAuth succeeds in an MCP flow, authority flows through four hops:

  1. End user — owns the upstream account (GitHub, your SaaS, etc.)
  2. MCP client — Cursor, Claude Desktop, Slack with Claude Tag
  3. Your MCP server — holds or exchanges tokens, maps tools → upstream API calls
  4. Upstream API — enforces scopes on each request

The user’s mental model: “I connected my account.”

The actual model: “I delegated a capability bundle to an autonomous caller.”

If your tool surface is too broad, or your tokens too long-lived, you have not connected an account — you have installed a persistent agent with the user’s privileges.

Why copying your SaaS OAuth app is dangerous

Most teams reuse the OAuth application they built for the web dashboard. Same client ID, same scopes, same refresh token behavior. Fast to ship. Wrong abstraction.

Dashboard OAuth assumes:

MCP OAuth assumes none of that. The agent may:

Fix: treat MCP as a separate OAuth client — or a separate scope bundle — with tighter defaults than your web app.

Scope minimization: map tools, not endpoints

Do not translate your OpenAPI file 1:1 into MCP tools. Map each tool to the smallest upstream scope that satisfies it.

ToolGood scope postureOver-permission trap
search_issuesRead-only issues in one orgFull repo admin
get_customerSingle-record readExport-all customers
create_draftWrite to drafts onlyPublish + delete

Document the mapping in your server README and submission to Influzer.ai. Enterprise buyers ask for it.

Read vs write: ship the split explicitly

The safest rollout pattern for a new MCP server:

  1. Phase 1 — read tools only. Search, get, list. No mutations.
  2. Phase 2 — narrow write tools. One verb per tool: create_comment, not manage_ticket.
  3. Phase 3 — optional admin tools behind separate OAuth consent or disabled by default.

Name tools so models infer risk:

Teams consuming your server run audits like our seven-question checklist. Write tools with vague names fail review.

Token lifetime and offboarding

Refresh tokens that live for months + agent access = ghost employees.

When Sarah leaves the company:

Builder checklist:

Chapter 3 will go deeper on implementing enterprise-managed auth as a provider. For now: design as if tokens outlive the employee who created them — because they will.

The five over-permission patterns we see in the wild

1. One consent screen for all tools

User clicks Allow once; your server exposes twelve tools including delete and admin. Split consent by risk tier, or ship read tools under a separate client.

2. God-mode personal tokens in team repos

A developer commits their PAT so “the team can try it.” That token now powers any agent on any machine that loads the config. Ban this in your docs; offer service accounts or org OAuth instead.

3. Generic tools that wrap destructive APIs

run_query that accepts arbitrary SQL. execute_action that passes through to your internal admin API. Models will find the sharp edges.

4. Returning raw upstream payloads to the model

API responses often embed internal IDs, emails, API keys in metadata fields, or cross-customer data in mis-paginated results. Filter responses before they become tool output — agents remember context.

5. Silent scope expansion on token refresh

Your web app added new scopes; refresh tokens picked them up; MCP server inherited broader access without a new consent screen. Version your MCP OAuth client separately.

What the user should see before they authorize

Consent UX for MCP should answer four questions in plain language:

  1. Which tools will this enable? (List them, not “full access”)
  2. Read or write? per tool or per bundle
  3. Which data — one workspace, one org, one environment
  4. How to revoke — link to settings, not buried in ToS

If your upstream IdP supports enterprise-managed provisioning, admins may never see per-user OAuth — they provision once. Your docs should describe both paths: individual OAuth and org-provisioned access.

Storing tokens: your server is now a secrets vault

The moment you hold refresh tokens, you are in the secrets business.

For HTTP-hosted MCP, transport security (TLS) is table stakes. stdio-local servers often store tokens in OS keychains — document where yours lives.

Testing authorization like an attacker (and like an agent)

Before launch, run these tests:

Agents are not malicious; they are over-eager. Test for eagerness.

Builder checklist — copy into your runbook

What’s next in MCP Builders

Quick answers

Should we use the same OAuth app as our web product?

Only if scopes are identical and tight. Usually: separate MCP client with narrower scopes.

Are personal API keys ever OK?

For solo local dev — yes, with loud warnings. For team or production MCP — no. Use OAuth or service accounts.

Does enterprise-managed auth replace OAuth for builders?

It changes who provisions access — admins via IdP, not each user clicking Allow. You still implement the auth extension on your server. Chapter 3 covers provider-side work.

We already shipped wide scopes. Now what?

Ship a v2 MCP client with reduced tools, migrate users, deprecate the overbroad client with a deadline. Do not wait for an incident.

Final thought

Users think they are connecting an integration. Agents experience it as delegated authority.

Your job as a builder is to make that delegation visible, minimal, revocable, and boring to audit. The teams that get adopted at scale — and listed in directories like Influzer.ai — will be the ones security can say yes to without a six-week review.

Narrow the scopes. Split read and write. Assume the agent runs at 2 a.m. If you have not built tools yet, start with Chapter 1.

GET PRACTICAL AI PLAYBOOKS WEEKLY

One clear email each Thursday

Actionable frameworks on AI execution, agents, and MCP. Join 4,200+ builders.

✓ You're in — first briefing Thursday.

Leave a comment

Be the first to share your thoughts.

Related insights

2026-07-04
MCP Builders — The Producer Playbook for Teams Who Already Have APIs
You shipped REST years ago. Now agents need tools, not endpoints. MCP Builders is a chapter-by-chapter manual for wrapping your API the right way — tool design, OAuth, enterprise auth, hosting, and getting listed.
2026-07-13
MCP Builders, Chapter 4: stdio vs HTTP, Hosting, and Secrets
Chapter 1 got you running on stdio in Cursor. Real teams need a hosted endpoint. This chapter walks through when to move from local process to HTTP, where secrets actually live, and how to pick hosting without turning your MCP server into a credential leak.
2026-07-08
MCP Builders, Chapter 3: Enterprise-Managed Auth for Server Builders
Chapter 2 got individual OAuth right. Chapter 3 is the provider side of enterprise-managed authorization — how admins provision your MCP connector once through their identity provider, map IdP groups to tool bundles, and offboard users automatically. This is the auth model that gets you into RFPs.