MCP Server Security Issues and How to Prevent Them
Secure MCP servers with practical controls for authorization, prompt injection, isolation, tool integrity, approvals, monitoring, and version-aware OAuth.

An MCP server is a security boundary between an AI application and the tools, data, and external services it can reach. Secure it as an enforcement point, not as a prompt-writing exercise. The practical order is: authenticate and authorize requests; give each server and tool narrow permissions; isolate execution; review tool definitions and packages; treat retrieved content as untrusted; validate inputs and outputs; require approval for consequential actions; and monitor every call.
This guide covers local and remote deployments, common MCP-specific attacks, OAuth details that depend on specification version, implementation patterns, troubleshooting, and operational checklists. The cited MCP and OWASP guidance does not establish an incident rate or a universally secure vendor, so apply the controls to your actual client, server, transport, and authorization-server versions.
1. What can go wrong in an MCP deployment?
MCP adds a structured tool layer, but the model may choose calls using natural-language context and tool metadata. That creates trust boundaries beyond the network endpoint. The MCP security guidance and OWASP checklist identify these recurring risks:
| Issue | How it appears | Primary control |
|---|---|---|
| Tool poisoning | A tool name, description, schema, or changed metadata steers the model toward an unsafe call. | Review and pin tool definitions; detect unexpected changes; enforce policy outside the model. |
| Indirect prompt injection | A webpage, email, document, or tool result contains instructions that attempt to influence later calls. | Treat external content as data; validate arguments and results; block unauthorized calls at the server. |
| Excessive privilege | A server has write, filesystem, or network access that its task does not need. | Use least privilege, separate credentials, narrow scopes, and read-only tools where possible. |
| Confused deputy | A proxy uses its broad identity to perform an action for a caller who lacks that permission. | Preserve the verified user and consent context; authorize each operation for that principal. |
| Cross-server influence | One connected server affects another server or causes data to cross an unintended boundary. | Isolate servers and credentials; define explicit trust relationships. |
| Supply-chain compromise | A package, startup command, update, or dependency is malicious or tampered with. | Use trusted sources, review provenance, pin versions, and require installation approval. |
| Local exposure | A local server can read files, launch processes, or accept unsafe connections on the host. | Sandbox it, restrict host access, review startup configuration, and limit filesystem and network permissions. |
These risks are related. A poisoned description can trigger a privileged tool, while an injected document can supply the argument that causes data disclosure. A gateway or prompt filter by itself does not remove the need for server-side authorization and isolation.
2. Start with an explicit trust and data-flow model
Draw the path from the user and AI client to the MCP server, tools, local resources, and upstream APIs. Mark which component authenticates the caller, where authorization is checked, which identity reaches each upstream service, and where data can leave the system.
- List every server and transport. Record local
stdioprocesses, remote HTTP services, reverse proxies, and any server-to-server calls. - Inventory tools and side effects. Classify each as read, write, delete, message-sending, code execution, or credential access.
- Identify principals. Decide whether calls carry a per-user delegated identity or a shared service identity. Document how user consent is preserved.
- Mark untrusted inputs. Include tool descriptions received at runtime, retrieved webpages, uploaded files, emails, and tool results.
- Choose approval points. Sending a message, changing a record, deleting data, or executing code should require meaningful confirmation and deterministic policy checks.
For remote deployments, review network exposure, TLS termination, origin controls, and service-to-service authentication. For local deployments, assume the process can affect the host unless the operating-system sandbox proves otherwise.
3. Authenticate and authorize at the server boundary
Authorization belongs at the MCP server boundary. The server must validate that an access token is intended for that server, reject unauthorized callers, and avoid returning protected data before authorization succeeds. If the server calls an upstream API, it must obtain the proper upstream credential; it must not pass through the token presented by the MCP client.
Token validation checklist
- Use HTTPS for authorization endpoints and remote transport.
- Validate the token signature with a maintained library or middleware.
- Check issuer, audience, expiry, and (where applicable) tenant and subject.
- Map the verified subject to the requested operation and resource.
- Reject tokens issued for another resource server.
- Store tokens securely and keep them out of logs, traces, and error messages.
- Use narrow scopes and separate credentials for separate servers.
Microsoft’s Entra example recommends validating signature, issuer, tenant, audience, expiry, and subject authorization with established libraries rather than custom cryptography. It is an implementation path for teams using Microsoft Entra ID for MCP authorization, not a universal MCP requirement.
OAuth version and discovery details
MCP authorization is version-sensitive. The 2026-07-28 authorization guidance formally deprecates Dynamic Client Registration in favor of Client ID Metadata Documents while retaining it for backward compatibility in that version’s description. Confirm the client, MCP server, and authorization server versions before selecting a flow. For authorization-code flows, use PKCE, exact redirect-URI matching, and state validation where appropriate. Test discovery behavior and audience handling in a staging environment before rollout.
4. Reduce privilege and prevent confused-deputy behavior
Create a separate permission profile for each server. A screenshot server may need outbound browser access but no database write permission; a ticketing server may need to create tickets but not read payroll files. Do not give every connected tool a shared administrator credential.
- Prefer read-only tools for investigation and preview steps.
- Split high-impact operations into separate tools with distinct scopes.
- Require resource-level authorization, not only “the user can access this server.”
- Preserve the user identity and consent context through proxies.
- Use an upstream credential issued for the MCP server’s approved purpose, never the client token as a passthrough.
- Rate-limit expensive or repetitive operations and set bounded argument values.
A useful design test is: “If the model is tricked into calling this tool with a valid-looking argument, what is the maximum damage?” Reduce that maximum with narrower scopes, smaller result sets, and approval gates.
5. Defend against prompt injection and tool poisoning
Prompt injection can arrive indirectly through content the system retrieves. Tool poisoning uses names, descriptions, schemas, or metadata to influence tool selection. Instructions in a webpage or tool result are data, not authority.

- Trust the package source. Allow approved registries or repositories, review maintainers and release history, and pin versions.
- Review metadata. Diff tool names, descriptions, schemas, and required scopes during updates. Unexpected changes require review.
- Constrain arguments. Validate URLs, paths, identifiers, sizes, and enumerations against an allowlist or strict schema.
- Separate content from commands. Pass retrieved text as a quoted data field and do not concatenate it into policy instructions.
- Validate results. Check type, size, destination, and sensitivity before returning output to the model or user.
- Enforce outside the model. A policy engine or server middleware must be able to deny a call regardless of the model’s explanation.
Instructions to the model such as “ignore malicious text” are useful context but cannot be the security control. The authorization and validation layers must still reject an unsafe operation.
6. Secure local MCP servers
Local servers deserve extra scrutiny because they execute on a user’s machine and may reach local files, processes, credentials, and network services. Review the exact startup command and environment variables. Do not copy an install command from an untrusted issue or gist into a client configuration.

- Run the process as a dedicated, unprivileged account.
- Sandbox filesystem access to the smallest required directories.
- Deny unnecessary network egress and inbound listeners.
- Pin package versions and verify checksums or signatures when available.
- Keep secrets in an OS credential store or secret manager, not in source files.
- Use per-server temporary directories and isolate servers from one another.
- Protect local HTTP transports against DNS rebinding and unintended network reachability.
- Record installation, startup, update, and shutdown events.
For remote HTTP servers, apply the same least-privilege rules while adding TLS, proxy authentication, origin controls, network segmentation, and service identity validation.
7. Require approval for consequential actions
Human-in-the-loop approval should be meaningful: show the operation, target, important arguments, and expected effect before the action executes. “The model said it was safe” is not an approval mechanism.
Put deterministic checks before the approval screen and again before execution. For example, a delete operation can require a specific project, a maximum record count, a verified user scope, and a confirmation token that expires quickly. Log the decision without storing access tokens or sensitive payloads.
8. Validate inputs, outputs, and resource limits
Define schemas that reject unknown fields when practical and enforce bounds on strings, arrays, file sizes, URLs, timeouts, and pagination. Normalize paths before checking them so traversal cannot bypass an allowlist. Restrict outbound destinations to approved hosts when a tool fetches URLs.
Validate outputs before they return to the model: confirm the declared type, cap size, redact secrets, and label untrusted text. Set execution timeouts, concurrency limits, memory limits, and cancellation behavior. These controls protect availability as well as confidentiality.
9. Monitor calls and investigate safely
Audit logs should answer who called which server and tool, when, with what authorization decision, and what resource class was affected. Include request IDs, latency, status, policy outcomes, and approval events. Redact tokens, cookies, API keys, and unnecessary personal data.
Alert on new tool metadata, repeated authorization failures, unusual destinations, scope escalation, large result transfers, and calls outside normal time or volume patterns. Keep enough context to reproduce a decision without retaining secrets.
10. A practical deployment checklist
- Inventory local and remote servers, transports, tools, packages, and upstream APIs.
- Document principals, scopes, audiences, consent, and data flows.
- Validate tokens at the server boundary and never pass client tokens upstream.
- Use separate, least-privilege credentials and read-only defaults.
- Pin and review packages plus tool metadata and schemas.
- Sandbox local processes and restrict filesystem and network access.
- Treat webpages, files, emails, tool descriptions, and results as untrusted data.
- Validate arguments and outputs with deterministic code.
- Require confirmation and policy checks for writes, deletes, messages, and code execution.
- Set timeouts, rate limits, size limits, and cancellation behavior.
- Log calls and approvals with secrets redacted.
- Test the exact MCP and OAuth versions used in production.
11. Troubleshooting common MCP security failures
| Symptom | Likely cause | Fix |
|---|---|---|
| 401 or “invalid audience” | The token was issued for another resource server. | Configure the correct audience and obtain a token for this MCP server. |
| Authorization works in one client only | Discovery or OAuth features differ by MCP version. | Compare client, server, and authorization-server versions; verify metadata and PKCE behavior. |
| Tool unexpectedly sends data externally | Broad egress, excessive scope, or injected destination. | Allowlist destinations, constrain arguments, narrow credentials, and enforce a server-side policy. |
| Model follows instructions in a document | Retrieved content was treated as authority. | Mark it as untrusted data and validate the resulting call independently. |
| Local server can read unrelated files | Process runs with broad host permissions. | Use a dedicated account, filesystem sandbox, and explicit path allowlist. |
| Updates change tool behavior silently | Unpinned package or metadata changes. | Pin versions, diff schemas and descriptions, and require review before deployment. |
| Logs contain credentials | Raw headers, environment variables, or tool arguments are recorded. | Redact at ingestion, rotate exposed secrets, and define a minimal audit schema. |
12. Performance, reliability, and cost considerations
Security checks add work, but predictable limits usually improve reliability. Cache authorization metadata safely, reuse validated keys, and keep policy checks deterministic. Apply timeouts to upstream calls and make retries idempotent; never retry a non-idempotent write without an operation key. Queue long jobs and expose cancellation. Measure authorization latency, tool latency, rejection rates, and result sizes separately so a slow upstream service is not mistaken for a policy failure.
Cost controls include per-tool quotas, maximum page sizes, bounded browser or code-execution time, and rate limits by principal. Sample verbose traces while retaining complete security events. Review whether a shared service identity hides user-level accountability; lower infrastructure cost is not a substitute for correct authorization.
Or skip the browser setup
If an MCP workflow needs clean website screenshots, ScreenshotNeo provides a single authenticated request instead of maintaining a browser runner. It accepts cookie and consent banners like a visitor, removes more than 60 known consent platforms plus newsletter popups and chat widgets, and lets you turn each step off. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed; response headers identify the page verdict and billing status.
Its MCP server exposes take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients. Features include full-page and element capture, device presets, dark mode, custom CSS and JavaScript, waits, request blocking, headers, cookies, user agents, authorization, timezone and geolocation, PDF controls, resizing, caching, signed links, asynchronous jobs, bulk capture, usage reporting, and an OpenAPI specification. Review the ScreenshotNeo documentation before wiring credentials into an agent.
cURL
curl -G "https://api.screenshotneo.com/v1/shot" \
-d access_key=YOUR_API_KEY \
--data-urlencode url=https://stripe.com \
-o shot.webp
Python
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
timeout=90,
)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)
Node.js
const q = new URLSearchParams({
access_key: 'YOUR_API_KEY',
url: 'https://stripe.com'
});
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const fs = await import('node:fs/promises');
await fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer()));
Plans include 1,000 screenshots each month for free with no card; paid plans start at $5 for 3,000 shots, and every feature is available on every plan. Create a free ScreenshotNeo account.
13. FAQ
Can an MCP server be prompt-injected?
Yes. Malicious instructions can arrive through tool metadata or retrieved content. Prevent unauthorized effects with trusted packages, metadata review, input and output validation, and server-side authorization.
Does every MCP server need OAuth?
No single flow fits every deployment. A local process may use the client’s local trust model, while a remote multi-user service needs a documented identity and authorization design. Confirm the MCP version and OAuth compatibility before choosing.
Should I run every MCP server remotely?
No. Compare exposure, identity, permissions, isolation, package integrity, safeguards, and protocol compatibility. Local execution reduces network exposure but increases host access concerns.
What should I log?
Log principal, server, tool, request ID, authorization decision, approval event, timing, status, and resource class. Redact tokens, cookies, keys, and unnecessary personal data.
Is a prompt filter enough?
No. Prompt filters can reduce exposure but cannot replace authorization, sandboxing, validation, least privilege, and monitoring enforced outside the model.


