# Secure your MCP server
Source: https://speakeasy.com/mcp/securing-mcp-servers

MCP servers handle requests from LLM agents, not users. When a user calls your API, you have a good idea of what they're requesting. When an LLM agent calls your MCP server, you're trusting the agent's interpretation of what the user wanted.

This creates new attack vectors. An attacker doesn't need to compromise your server directly. They could inject malicious instructions into content the LLM reads, and the LLM would execute those instructions, thinking it's following the user's intent.

This guide explains the threats facing MCP servers and shows you which security controls to implement and why, covering authentication and authorization, credential protection, prompt‑injection defenses, encrypted transport, and monitoring.

## Understanding MCP security threats

MCP servers face unique threats because LLM agents sit between users and your tools. Attackers can exploit this intermediary to bypass traditional security controls.

### Prompt injection attacks

In a prompt injection attack, an attacker uses malicious prompts to manipulate an LLM into performing harmful acts. They can do this in two ways:

- **In a direct prompt injection,** the attacker delivers prompts through input fields in the AI application.
- **In an indirect prompt injection,** the attacker hides malicious prompts in content that LLMs consume, such as images and PDF documents.

Many prompt injection methods don't require any specialist knowledge or even coding ability. Attackers need only a basic understanding of how LLMs function, what their vulnerabilities are, and where to insert malicious prompts effectively. For example, an attacker could execute a prompt injection as follows:

- The attacker poisons the document.
- The MCP server retrieves the document.
- The LLM reads the malicious prompt.
- The LLM calls an unauthorized tool.
- Data is exfiltrated.

![Prompt injection via document](/assets/mcp/securing-your-mcp-server/prompt-injection-attack.png)

### Unauthorized access

Without proper authentication, anyone can connect to your MCP server and call your tools. Attackers can gain access to your MCP server as a result of:

- **Missing authentication:** Your server accepts tool calls from any clients without verifying their identities.
- **Weak authentication:** API keys passed through prompts can be intercepted or leaked through logs.
- **Credential theft:** Attackers steal valid tokens and impersonate legitimate users.

### Data exfiltration

Compromised agents can extract sensitive data through legitimate tool calls using:

- **High-frequency queries:** An agent makes thousands of database queries in minutes, extracting customer records.
- **Unauthorized tool access:** A support agent's session unexpectedly initiates calls to admin-only tools to access restricted data.
- **Prompt-triggered exfiltration:** Malicious instructions in retrieved content tell the LLM to send data to external URLs.

With these threats in mind, a robust authentication and authorization system is the first control you should put in place.

## Implement authentication and authorization

Authentication controls who can access your server, and authorization controls what they can do once they have connected.

### Use OAuth 2.1 for authentication

MCP servers connect users to external APIs. You could accept API keys directly, but this creates three problems:

- **Tokens in prompts are vulnerable:** Attackers intercept credentials through man-in-the-middle attacks. When tokens leak through logs, your server becomes a tool for credential theft.
- **Users struggle to manage scopes correctly:** Users don't know which permissions your tools require and either grant excessive permissions, creating a security risk, or grant insufficient permissions, causing tools to break.
- **API keys are long-lived:** If compromised, attackers have access to the server until the key is manually revoked.

OAuth 2.1 fixes all three issues:

- **Vulnerable tokens in prompts:** Authentication no longer occurs within the LLM context. Instead, users authenticate directly with your OAuth provider (for example, Auth0, Okta, or FusionAuth).
- **User scope management errors:** You now define the required scopes, not your users.
- **Long-lived API keys:** Tokens are now short-lived and expire automatically, and you can revoke access to your server without requiring users to regenerate their keys.

MCP integrates with standard OAuth 2.1. The high‑level flow in an MCP context looks like this:

- The MCP client (the AI) requests a protected tool, and your MCP server returns `401` with an OAuth authorization URL, triggering the authentication flow.
- The user completes the OAuth flow, authenticating with your OAuth provider (for example, Auth0 or Okta) and granting permissions for specific scopes.
- The MCP client receives an access token.
- The MCP client securely stores the token and includes it in subsequent requests as a Bearer token.
- On each tool call, your MCP server validates the token against the OAuth provider using token introspection.
- Your MCP server uses the validated user information to call the tool with the appropriate user context (permissions and attribution).

The key way OAuth 2.1 differs from traditional OAuth is that, instead of the user manually initiating login flows, the AI model triggers the authentication flow when it needs to access protected tools.

![OAuth 2.1 flow](/assets/mcp/securing-your-mcp-server/oauth-flow.png)

Learn how to add OAuth 2.1 to your MCP server in the Gram guide to [building MCP servers with external OAuth](/docs/gram/examples/oauth-external-server).

### Encrypt communications with mutual TLS

Standard TLS (HTTPS) authenticates only the server. The client knows it's talking to the real server, but the server doesn't know who the client is.

Mutual TLS (mTLS) authenticates both the server and the client. They both present certificates and verify each other's identity before exchanging data. This prevents unauthorized clients from connecting to your MCP server and prevents man-in-the-middle attacks.

| Without mTLS                                                     | With mTLS                                                  |
| ---------------------------------------------------------------- | ---------------------------------------------------------- |
| Anyone can attempt to connect to your server                     | Only clients with valid certificates can connect           |
| Client identity verified at application level (API keys, tokens) | Client identity verified at transport layer (certificates) |
| API keys can be stolen and reused                                | Certificates require both public cert and private key      |
| No cryptographic proof of client identity                        | Cryptographic verification of both parties                 |
| Logging shows IP addresses                                       | Logging shows verified client identities                   |

You can set up mTLS for a Python MCP server using uvicorn:

```python
import ssl
import uvicorn