.env file. This page covers a machine you control;
Deploying on a PaaS covers Render, Railway, and
compose-native platforms.
1
Point your domain's DNS at the machine that will run mob
2
Create your Discord app
Follow Set up your Discord app.
3
Create your Slack app
Follow Set up your Slack app. A deployment using one
platform leaves the other platform’s credentials empty.
4
Get the code
git clone https://github.com/promptrotator/mob.so.git && cd mob.so5
Configure
cp .env.example .env in the repo root and work through it; every
value is explained inline.6
Start the stack
docker compose up -dhttps://<your-domain>/dashboard (the root
redirects there).
- Caddy fetches TLS certificates for your domain automatically.
- Ports 80 and 443 handle public ingress.
- Discord uses an outbound gateway connection.
- Slack sends signed HTTPS Events API and slash-command requests to
/api/slack/*.
Trying the stack locally first
The compose stack runs on a laptop before any DNS exists. In.env, set
both origins to plain local HTTP; the scheme prefix on CADDY_DOMAIN is
what tells Caddy to skip TLS and the HTTPS redirect:
docker compose up -d and open http://localhost/dashboard; the MCP
endpoint answers at http://localhost/mcp. A loopback origin is also the
one place the api starts without real secrets, so an otherwise empty .env
works for this trial. Platform credentials stay optional: each adapter
stays idle until its credentials exist.
Database
The stack includes Postgres with pgvector. It stores:- identity and policy metadata
- encrypted Slack OAuth credentials
- the Discord message index
MOB_DATABASE_URL in .env and removes the postgres service from the
compose file. The database must have the pgvector extension.
The volume survives container rebuilds and goes down with the machine.
Backups covers what an instance loses with it and how to
restore.
Model endpoint
MOB_OPENAI_API_KEY and MOB_OPENAI_BASE_URL point the instance at one
OpenAI-compatible endpoint. OpenAI itself, an Azure deployment, and a
self-hosted server all work. The endpoint serves three features, and the
instance runs without any of them when the key stays empty.
Semantic search. Discord full-text search works with the local database
alone. The key adds an embedding leg to every Discord query, using
MOB_EMBEDDING_MODEL.
Attachment contents. Text, CSV, and PDF attachments on Discord messages
are extracted into the search index directly, with no model call and no key.
Images additionally require the key: MOB_SMALL_MODEL transcribes and
describes each image into the index, capped per community per day. Every
attachment is searchable by filename regardless.
The security guard. The same small model runs the optional pre-post
screen described in Authorization. The
instance supplies only the endpoint; each community owner decides in the
console whether their server uses it and with what policy. Enabling it
without a configured key is rejected.
The endpoint handles Discord content only. Slack search calls
assistant.search.context with the requesting member’s token and keeps the
response in request memory through the MCP response.
Connecting agents to your instance
Members connect through the platform’s add-by-URL mechanism. A custom connector in Claude or ChatGPT points athttps://<your-domain>/mcp.
Directory listings in the MCP clients point at hosted mob.so, and so does
the public communities page, which ships with the marketing site in the
hosted profile. The connect page reached from /mob connect shows the
current instance URL.