Self-hosting
Run sremcp's API and console in your own cloud or cluster, next to your MCP servers.
sremcp is two Next.js services and a Postgres database:
| Service | Role | Holds |
|---|---|---|
| API (api.sremcp.com) | Every rule and every outbound call: access checks, MCP connections, the agent, reports | The database, MCP credentials, the model key |
| Console (app.sremcp.com) | The UI. Reaches data only through the API | No database, no credentials |
Sign-in uses Clerk. Both services use the same Clerk instance.
Self-hosting is the way to reach MCP servers on private addresses without exposing them. See Expose a self-hosted server.
API environment
| Variable | What it's for |
|---|---|
DATABASE_URL | Postgres 14+. |
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY, CLERK_SECRET_KEY | Your Clerk instance. |
CLERK_WEBHOOK_SIGNING_SECRET | Clerk webhook <api>/webhooks/clerk, events user.created, user.updated, user.deleted. |
CLERK_AUTHORIZED_PARTIES | The console's origin(s), for example https://sremcp.acme.internal. Required. |
APP_URL | The console's public URL: invitation links and sremcp's OAuth identity (<APP_URL>/oauth/client.json). |
SECRETS_ENCRYPTION_KEY | Encrypts MCP secrets. openssl rand -base64 32. Changing it makes stored secrets unreadable. |
CRON_SECRET | Protects /cron/tick. openssl rand -hex 32. |
GOOGLE_GENERATIVE_AI_API_KEY, ANTHROPIC_API_KEY or AI_GATEWAY_API_KEY | At least one model provider. |
AGENT_MODEL | Optional: <provider>:<model>, for example anthropic:claude-opus-5-5. Default: the first provider with a key. |
MCP_ALLOW_PRIVATE_NETWORKS | true lets sremcp call private addresses and plain http://. Metadata addresses stay blocked. |
MCP_ALLOWED_HOSTS | Optional allowlist of host suffixes, for example mcp.acme.com,svc.cluster.local. |
ORG_CREATORS | Optional: who may start an organization, for example @acme.com. |
AGENT_MAX_TOOLS | Optional: tools offered to the agent at once. Default 64. |
RESEND_API_KEY, EMAIL_FROM | Optional: email invitations. Without them, the console shows invitation links to copy. |
Console environment
| Variable | What it's for |
|---|---|
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY, CLERK_SECRET_KEY | The same Clerk instance as the API. |
API_BASE_URL | The API's URL. |
APP_URL | Optional: the console's public URL, when a proxy changes the host. Must match the API's APP_URL. |
Scheduler
Reports and health checks run when something calls the API's /cron/tick with Authorization: Bearer <CRON_SECRET>.
Call it every minute: a Kubernetes CronJob, Vercel Cron, or any scheduler.
apiVersion: batch/v1
kind: CronJob
metadata: { name: sremcp-tick }
spec:
schedule: "* * * * *"
concurrencyPolicy: Forbid
jobTemplate:
spec:
template:
spec:
restartPolicy: Never
containers:
- name: tick
image: curlimages/curl
args: ["-fsS", "-H", "Authorization: Bearer $(CRON_SECRET)", "https://sremcp-api.acme.internal/cron/tick"]
env:
- name: CRON_SECRET
valueFrom: { secretKeyRef: { name: sremcp, key: cron-secret } }Database migrations
Run the API's migrations against the database before each release that adds one: bun run db:migrate.