Skip to content
This repository was archived by the owner on Jul 13, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ These go under the `mcp_transport_security` key:
- `token`: Token to use for basic authentication. The caller must send this value in request header `Authorization`. For example: `Authorization: Bearer supersecret`. Default `""`.
- `enable_dns_rebinding_protection`: Enable DNS rebinding protection")
- `allowed_hosts`: List of allowed hosts. Default `["*:*"]`
- `allowed_origins`: list of allowed origins. Default `["http://*:*"]`.
- `allowed_origins`: list of allowed origins. Default `["http://*:*", "https://*:*"]`.

With the exception of the `token` field the rest comes from the [Anthropic MCP SDK](https://github.com/modelcontextprotocol/python-sdk).

Expand Down
7 changes: 7 additions & 0 deletions config.yaml.sample
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@ openshift:
allow_write: false
insecure: false

# Incoming TLS settings for the MCP server
#tls:
# ssl_certfile: ./cert.pem
# ssl_keyfile: ./key.pem
# ssl_keyfile_password: null
# ssl_ca_certs: null

mcp_transport_security:
token: supersecret
enable_dns_rebinding_protection: false
Expand Down
12 changes: 12 additions & 0 deletions src/rhos_ls_mcps/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import contextlib
import logging
import ssl

from mcp.server.fastmcp import FastMCP
from starlette.applications import Starlette
Expand Down Expand Up @@ -108,6 +109,16 @@ def main():

# Pass string instead of an instance to support multiple workers.
# Pass the factory=True argument to use a function (create_app) instead of a variable.
ssl_kwargs = {}
if config.tls.ssl_certfile:
ssl_kwargs["ssl_certfile"] = config.tls.ssl_certfile
ssl_kwargs["ssl_keyfile"] = config.tls.ssl_keyfile
if config.tls.ssl_keyfile_password:
ssl_kwargs["ssl_keyfile_password"] = config.tls.ssl_keyfile_password
if config.tls.ssl_ca_certs:
ssl_kwargs["ssl_ca_certs"] = config.tls.ssl_ca_certs
Comment thread
coderabbitai[bot] marked this conversation as resolved.
ssl_kwargs["ssl_cert_reqs"] = ssl.CERT_REQUIRED

Comment thread
umago marked this conversation as resolved.
uvicorn.run(
"rhos_ls_mcps.main:create_app",
host=config.ip,
Expand All @@ -118,6 +129,7 @@ def main():
access_log=False,
factory=True,
log_config=log_config,
**ssl_kwargs,
)


Expand Down
32 changes: 30 additions & 2 deletions src/rhos_ls_mcps/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import yaml
from typing import Optional

from pydantic import Field
from pydantic import Field, model_validator
from pydantic_settings import BaseSettings

from rhos_ls_mcps import oc_defaults
Expand Down Expand Up @@ -40,6 +40,31 @@ class OpenShiftSettings(BaseSettings):
)


class TLSSettings(BaseSettings):
ssl_certfile: Optional[str] = Field(
default=None, description="Path to SSL certificate file for incoming TLS"
)
ssl_keyfile: Optional[str] = Field(
default=None, description="Path to SSL private key file for incoming TLS"
)
ssl_keyfile_password: Optional[str] = Field(
default=None, description="Password for encrypted SSL key file"
)
ssl_ca_certs: Optional[str] = Field(
default=None,
description="Path to CA certs file for client certificate verification (mutual TLS)",
)

@model_validator(mode="after")
def check_certfile_required(self) -> "TLSSettings":
dependent = [self.ssl_keyfile, self.ssl_keyfile_password, self.ssl_ca_certs]
if any(dependent) and not self.ssl_certfile:
raise ValueError(
"tls.ssl_certfile is required when other tls.ssl_* fields are set"
)
return self


class TransportSecuritySettings(BaseSettings):
token: Optional[str] = Field(
default=os.environ.get("MCP_SECURITY_TOKEN"),
Expand All @@ -50,7 +75,7 @@ class TransportSecuritySettings(BaseSettings):
)
allowed_hosts: list[str] = Field(default=["*:*"], description="Allowed hosts")
allowed_origins: list[str] = Field(
default=["http://*:*"], description="Allowed origins"
default=["http://*:*", "https://*:*"], description="Allowed origins"
)
Comment thread
lpiwowar marked this conversation as resolved.


Expand Down Expand Up @@ -79,6 +104,9 @@ class Settings(BaseSettings):
mcp_transport_security: TransportSecuritySettings = Field(
default=TransportSecuritySettings(), description="Transport security settings"
)
tls: TLSSettings = Field(
default=TLSSettings(), description="Incoming TLS settings for the MCP server"
)


def load_config():
Expand Down
Loading