Your MCP server works locally. What breaks when a team depends on it?
A production-readiness review for MCP servers covering per-user credentials, tool allowlists, tenant boundaries, rate limits, audit logs, and failure isolation.
DECISION TOPICAgent architecture↗Read with one real task in mind, then complete the workbench. The lesson is done when another person can review what you made.
A developer connects an MCP server to a desktop client, lists a few tools, and asks the agent to read a repository, search issues, and draft a fix. It works. The demo is convincing because everything important is local: one user, one token, one filesystem, one machine, and no one else waiting on the result.
Then the team wants the same server in a shared assistant. Ten people connect, each with different repository access. The server still holds one token. A tool that lists files still sees the host’s home directory. A slow request still blocks the queue. The local success did not predict any of this, because the local setup had no shared state to break.
This guide is the review that happens after the server connects. The MCP server intake decides whether to connect a third-party server. This page decides whether the connection is safe and operable when more than one person depends on it.
Local success hides the shared-state problem
A local MCP setup usually has four simplifying assumptions:
- One identity. The server runs with the developer’s token, so every tool call has the same permissions.
- One data scope. The filesystem root, repository, or database is the developer’s own.
- One request at a time. There is no queue, no concurrency limit, and no noisy neighbor.
- No durable audit. The transcript is enough for one person; it is not enough for a team or an incident review.
A team setup removes all four. The server now needs to answer: on whose behalf, over which data, at what rate, with what record, and with what isolation? A server that cannot answer those questions is still a local tool, even if it is reachable over HTTP.
Four things change when a team connects
| Local assumption | Team requirement | Failure if skipped |
|---|---|---|
| One shared token | Per-user or per-service identity with scoped consent | Everyone acts as the token owner; revocation is all-or-nothing |
| One filesystem root | Tenant and resource scope enforced per call | A path or query returns another team’s data |
| One request | Rate limits, queues, timeouts, and backpressure | One slow tool blocks every user |
| Transcript only | Structured audit of user, tool, arguments, result, approval | No attribution after an incident |
The protocol can carry tool definitions and calls. It does not automatically supply your authorization model, tenant model, or audit policy. Those are application responsibilities, and they are where most “it worked locally” deployments fail.
Example: the shared GitHub token
A team connects a GitHub MCP server with a personal access token owned by the engineer who built it. The token can read three private repositories and write issues.
The demo works. In the shared assistant, every user now has the same three repositories, including the two they should not see. When one user leaves, the team cannot revoke that user’s access without rotating the token and breaking everyone.
The fix is not a better prompt. It is an identity change:
- each user authorizes their own GitHub identity, or the server uses a service identity with an explicit repository allowlist;
- the server maps the authenticated user to a grant, and each tool call checks the repository against that grant;
- the tool result records which identity was used;
- revocation removes one user’s grant without touching the others.
If the server cannot support per-user authorization, the team can still use it in a single-user or read-only mode. It should not be shared as a multi-user service with one owner’s credentials.
Counterexample: the file tool that answered from another tenant
A file-search MCP server exposes a search_files tool with a root argument. In local use, the root is the developer’s project directory. In the shared service, the root is supplied by the caller.
A user asks for a file in their own workspace. The model passes a path with ../ and the server resolves it outside the intended root. Another tenant’s file appears in the result. Nothing in the tool description looked dangerous; the tool simply trusted a path.
The test that catches this is small:
- Create two tenant workspaces with a known canary file in each.
- Authenticate as tenant A.
- Ask the server to search tenant B’s canary path, including encoded and traversal variants.
- Record whether the canary appears in the result, an error, or a citation.
The pass condition is not “the model refused.” It is “the server denied the request before reading the file.” A model-level refusal is a second layer, not the authorization boundary.
The readiness review
Use this table before a team depends on the server. It is intentionally short enough to complete for each server, and specific enough that another reviewer can verify it.
| Check | Question | Evidence |
|---|---|---|
| Identity | Whose credentials does each call use? | Auth flow, token scope, user-to-grant mapping |
| Tool allowlist | Which tools are exposed to which users? | Server config plus assistant policy |
| Data scope | Which tenant, repository, or record can this call touch? | Scope check in code and a denial test |
| Rate and concurrency | What happens at the limit? | Load test with queue and timeout values |
| Failure isolation | Does one slow tool block the others? | Per-tool timeout and circuit-breaker test |
| Audit | Can you reconstruct who called what, with which result? | One sampled trace with secret fields redacted |
| Version pin | Which server version and tool schema are running? | Lockfile or image digest |
| Kill switch | Can you disable one tool or one server without redeploying everything? | A tested disable action |
The table is not a security certification. It is a release gate. If a row is unknown, the server is not ready for shared use, even if every local test passed.
Rate limits and failure isolation
A local server has no queue. A shared server does. Without a limit, one agent that retries a slow search can consume the capacity every other user needs.
Set limits at two levels:
- Per user: requests per minute and concurrent calls, so one person cannot starve the team.
- Per tool: concurrency and timeout, because a file search and a payment call do not deserve the same budget.
Then test the behavior at the limit. The server should return a clear “try later” or “queued” result, not hang until the client times out. The agent should see a typed error it can route, not a generic failure that invites a retry storm.
Failure isolation is the next layer. If one MCP server is slow, the assistant should still answer questions that do not need it. A per-server circuit breaker, a per-tool timeout, and a fallback path are cheaper than debugging a global outage caused by one filesystem call.
Audit without logging secrets
An audit record for an MCP tool call should answer:
- who made the request (user or service identity);
- which tenant and resource scope applied;
- which tool and version ran;
- a hash or redacted summary of the arguments;
- the result status and duration;
- any approval ID or policy decision.
It should not store the token, the full file contents, or unrestricted personal data. The audit is for attribution and replay, not for building a second copy of the data.
A useful test is to take one real call and try to answer “who did this, over which data, and what changed?” from the record alone. If the answer requires reading the model’s chat transcript, the audit is not structured enough for a team.
Boundary
This review fits shared assistants, internal tool gateways, and multi-tenant agent platforms that expose MCP tools to more than one user. It does not replace a security review, a penetration test, or the vendor’s own threat model. It is not sufficient for regulated data, payment initiation, or production write access without a separate approval and recovery design. If the server cannot enforce per-user authorization and tenant scope, keep it local or read-only. A working local server is a good start; it is not evidence that a team can depend on it.
SOURCES CHECKED
Which first-party sources informed this guide?
Sources anchor definitions, risk boundaries, or operational facts. The decision framework and workbench are original to AI Vista.
- Model Context Protocol — SpecificationChecked 2026-10-24
- OWASP — Top 10 for Large Language Model ApplicationsChecked 2026-10-24
- NIST AI Risk Management Framework — PlaybookChecked 2026-10-24
AI tools may assist with research, outlining, and language editing. Facts, cases, and final wording are reviewed by the editor. Report an error through the contact page.
TAKEAWAY TOOL
Third-party MCP server intake record
Decide which capabilities this exact server, identity, and version may expose before connecting it to an agent.
This workbench saves a draft in this browser. Use sanitized identities, synthetic cases, and controlled evidence pointers; do not enter tokens, keys, customer addresses, private endpoints, or raw confidential tool results.
- 01Describe the taskDescribe the result with a sanitized summary.
- 02Fill the decision fieldsRecord input categories, risk, evidence pointers, and handoff.
- 03Ask a colleague to reviewThe tool is ready when someone else can restate the decision.
LESSON READ
Finish the workbench, then mark it read.
The read state updates the syllabus and your course progress.
- 01Fields filled
- 02Case tested
- 03Reviewable
GUIDE PRACTICE NOTES
Leave a judgment you can review later.
The fictional examples below show the format. Your own notes stay in this browser. Record what worked, which boundary failed, or one question worth testing.
This guide has no example or local note yet. Record the first concrete observation.