---
title: Configuring CORS for Apollo MCP Server
---

## Why it matters

When your clients include browsers (for example, Single Page Apps or other browser‑based frontends), you need Cross‑Origin Resource Sharing (CORS) properly configured, otherwise browsers will block requests. Misconfigurations (too permissive or too restrictive) can lead to bugs or security issues. By default, Apollo MCP Server has CORS **disabled**.

This page shows how to enable and configure CORS for Apollo 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).

## Enabling CORS

To enable CORS, add a `cors` section to your Apollo MCP Server YAML config file:

```yaml title="mcp.yaml"
cors:
  enabled: true
```

If `enabled` is not set to `true`, all other CORS options are ignored.

## Configuring allowed origins

You must specify which browser origins are allowed to access your MCP Server.

### Allow any origin

```yaml title="mcp.yaml"
cors:
  enabled: true
  allow_any_origin: true
```

If you set `allow_any_origin` to `true` (the default is `false`), Apollo MCP Server will respond with `Access-Control-Allow-Origin: *` in all CORS responses. This means that _any_ website can initiate browser connections. 

<Note>Clients will not be able to authenticate with your MCP Server if you set `allow_any_origin` to `true`.</Note>

### Origins

```yaml title="mcp.yaml"
cors:
  enabled: true
  origins:
    - https://www.your-app.example.com
    - https://staging.your-app.example.com
```

Set `origins` to a list of URLs to restrict access to specific servers. Use this option if you have a known list of web applications accessing your MCP server. An origin is a combination of protocol, hostname, and port. Origins do not include a path, so do not include a trailing slash.

### Match Origins

```yaml title="mcp.yaml"
cors:
  enabled: true
  match_origins:
    - "^http://localhost:\d+$" # Any localhost url from any port
    - "^https://([a-z0-9]+[.])*.api.example.com$" # Any host that uses https and is either api.example.com or a subdomain of it
```

The `match_origins` configuration option allows you to use a regular expression to set endpoints that can interact with your Apollo MCP Server. While `match_origins` can be used with `origins`, it is always evaluated after `origins`.

## 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
```

## 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();
```
