Expose a self-hosted server

Make an MCP server that runs in your network or cluster reachable by sremcp, safely.

Servers like Grafana, Kubernetes, Prometheus or PostgreSQL usually run next to the systems they read, inside your network. sremcp needs to reach them. There are two ways.

Public https endpoint with a keysremcp in your network
Works with app.sremcp.com✓
Works with self-hosted sremcp✓✓
What you addTLS, a hostname, an API keyNothing on the MCP side

Option 1: a public https endpoint with an API key

Require a key

Every request must carry a secret. Some servers check one themselves, for example Grafana's MCP_GRAFANA_SERVER_TOKEN. For the rest, put Supergateway in front with --apiKey.

For a stdio server, Supergateway runs it:

supergateway --stdio "uvx some-mcp-server" \
  --outputTransport streamableHttp --port 8000 --apiKey "$MCP_API_KEY"

For a server that already speaks HTTP but has no key of its own (Kubernetes, Prometheus), Supergateway proxies to it:

supergateway --streamableHttp "http://kubernetes-mcp-server:8080/mcp" \
  --outputTransport streamableHttp --stateful --port 8000 --apiKey "$MCP_API_KEY"

Requests without Authorization: Bearer <key> (or X-API-Key: <key>) get 401.

Serve it over https

Give it a hostname and a certificate with what you already use: a Kubernetes Ingress with cert-manager, a cloud load balancer, or a Cloudflare Tunnel. Route only the MCP path, usually /mcp.

# Ingress for Supergateway in front of an MCP server (cert-manager issues the certificate).
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: mcp-kubernetes
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt
spec:
  tls:
    - hosts: [mcp-k8s.example.com]
      secretName: mcp-k8s-tls
  rules:
    - host: mcp-k8s.example.com
      http:
        paths:
          - path: /mcp
            pathType: Prefix
            backend:
              service: { name: mcp-kubernetes-gateway, port: { number: 8000 } }

Onboard it

Endpoint URL https://mcp-k8s.example.com/mcp, Transport Streamable HTTP, Authentication Bearer token, and the key as the Secret.

Don't expose a server without a key

An MCP server answers anyone who can reach it, with its own credentials. Never publish one without a key, and give the server itself read-only credentials (a Grafana Viewer, a Kubernetes view role, a read-only database role), so even a leaked key can only read.

Option 2: run sremcp in your network

A self-hosted sremcp can reach private addresses and plain http:// when its API sets MCP_ALLOW_PRIVATE_NETWORKS=true. Then onboard servers by their in-cluster address, for example http://kubernetes-mcp-server.mcp.svc:8080/mcp.

  • Keep a key on servers that offer one. Anything in the cluster can reach them too.
  • Restrict which hosts sremcp may call with MCP_ALLOWED_HOSTS, a comma-separated list of host suffixes, for example mcp.svc.cluster.local,example.com.
  • Cloud metadata addresses stay blocked either way.

On this page