cors.mdx•7.39 kB
---
title: Configuring CORS
---
## Configuring CORS
Control browser access to your MCP server
---
**This article describes CORS configuration that's specific to Apollo MCP Server**. For a more general introduction to CORS and common considerations, see [MDN's CORS documentation](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS).
By default, Apollo MCP Server has CORS disabled. If your MCP server serves tools to browser-based applications, you need to enable CORS and configure one of the following in the `cors` section of your server's YAML config file:
- Add the origins of those web applications to the server's list of allowed `origins`.
- Use this option if there is a known, finite list of web applications that consume your MCP server.
- Add a regex that matches the origins of those web applications to the server's list of allowed `match_origins`.
- This option comes in handy if you want to match origins against a pattern, see the example below that matches subdomains of a specific namespace.
- Enable the `allow_any_origin` option.
- Use this option if your MCP server is a public API with arbitrarily many web app consumers.
- With this option enabled, the server sends the wildcard (\*) value for the `Access-Control-Allow-Origin` header. This enables _any_ website to initiate browser connections to it (but they can't provide cookies or other credentials).
- If clients need to authenticate their requests with cookies, you _must_ use either `origins`, `match_origins`, or the combination of both options. When using both options, note that `origins` is evaluated before `match_origins`.
The following snippet includes an example of each option (use either `allow_any_origin`, or `origins` and/or `match_origins`):
```yaml title="mcp.yaml"
transport:
type: streamable_http
port: 8000
cors:
# Enable CORS support
enabled: true
# Set to true to allow any origin
# (Defaults to false)
allow_any_origin: true
# List of accepted origins
# (Ignored if allow_any_origin is true)
#
# An origin is a combination of scheme, hostname and port.
# It does not have any path section, so no trailing slash.
origins:
- https://www.your-app.example.com
# List of origin patterns (regex matching)
match_origins:
- "^https://([a-z0-9]+[.])*api[.]example[.]com$" # any host that uses https and ends with .api.example.com
```
You can also disable CORS entirely by setting `enabled` to `false` or omitting the `cors` section:
```yaml title="mcp.yaml"
cors:
enabled: false
```
If your MCP server serves exclusively _non_-browser-based clients, you probably don't need to enable CORS configuration.
### Passing credentials
If your MCP server requires requests to include a user's credentials (e.g., via cookies), you need to modify your CORS configuration to tell the browser those credentials are allowed.
You can enable credentials with CORS by setting the Access-Control-Allow-Credentials HTTP header to `true`.
To allow browsers to pass credentials to the server, set `allow_credentials` to `true`, like so:
```yaml title="mcp.yaml"
cors:
enabled: true
origins:
- https://www.your-app.example.com
allow_credentials: true
```
**To support credentialed requests, your server's config file must specify individual `origins` or `match_origins`**. If your server enables `allow_any_origin`, your browser will refuse to send credentials.
### All `cors` options
The following snippet shows all CORS configuration defaults for Apollo MCP Server:
```yaml title="mcp.yaml"
#
# CORS (Cross Origin Resource Sharing)
#
cors:
# Enable CORS support
enabled: false
# Set to true to allow any origin
allow_any_origin: false
# List of accepted origins
# (Ignored if allow_any_origin is set to true)
#
# An origin is a combination of scheme, hostname and port.
# It does not have any path section, so no trailing slash.
origins: []
# List of origin patterns (regex matching)
# Useful for matching dynamic ports or subdomains
match_origins: []
# Set to true to add the `Access-Control-Allow-Credentials` header
allow_credentials: false
# Allowed request methods
allow_methods:
- GET
- POST
# The headers to allow.
# These are the default headers required for MCP protocol and trace context
allow_headers:
- accept
- content-type
- mcp-protocol-version
- mcp-session-id
- traceparent # W3C Trace Context
- tracestate # W3C Trace Context
# Which response headers are available to scripts running in the
# browser in response to a cross-origin request.
# The mcp-session-id header should be exposed for MCP session management.
# Trace context headers are exposed for distributed tracing.
expose_headers:
- mcp-session-id
- traceparent # W3C Trace Context
- tracestate # W3C Trace Context
# Adds the Access-Control-Max-Age header
# Maximum age (in seconds) for preflight cache
max_age: 7200 # 2 hours
```
### Origin matching
Apollo MCP Server supports two types of origin matching:
#### Exact origins
Use the `origins` array for exact origin matches:
```yaml
cors:
enabled: true
origins:
- http://localhost:3000
- https://myapp.example.com
```
#### Pattern matching
Use the `match_origins` array for regex pattern matching:
```yaml
cors:
enabled: true
match_origins:
- "^https://localhost:[0-9]+$" # Any localhost HTTPS port
- "^http://localhost:[0-9]+$" # Any localhost HTTP port
- "^https://.*\\.example\\.com$" # Any subdomain of example.com
```
### Common configurations
#### Development setup
For local development with hot reloading and various ports:
```yaml title="mcp.yaml"
cors:
enabled: true
match_origins:
- "^http://localhost:[0-9]+$"
allow_credentials: true
```
#### Production setup
For production with specific known origins:
```yaml title="mcp.yaml"
cors:
enabled: true
origins:
- https://myapp.example.com
allow_credentials: true
max_age: 86400 # 24 hours
```
#### Public API setup
For public APIs that don't require credentials:
```yaml title="mcp.yaml"
cors:
enabled: true
allow_any_origin: true
allow_credentials: false # Cannot use credentials with any origin
```
### Browser integration example
Here's a simple example of connecting to Apollo MCP Server from a browser:
```javascript
async function connectToMCP() {
const response = await fetch("http://127.0.0.1:8000/mcp", {
method: "POST",
headers: {
Accept: "application/json, text/event-stream",
"Content-Type": "application/json",
"MCP-Protocol-Version": "2025-06-18",
},
body: JSON.stringify({
jsonrpc: "2.0",
method: "initialize",
params: {
protocolVersion: "2025-06-18",
capabilities: {},
clientInfo: { name: "Browser Client", version: "1.0" },
},
id: 1,
}),
});
// Extract session ID from response headers (automatically exposed)
const sessionId = response.headers.get("mcp-session-id");
// Handle SSE format response (starts with "data: ")
const responseText = await response.text();
const jsonData = responseText.startsWith("data: ")
? responseText.slice(6) // Remove "data: " prefix
: responseText;
const result = JSON.parse(jsonData);
console.log("Connected:", result);
console.log("Session ID:", sessionId);
}
connectToMCP();
```