File size: 10,112 Bytes
b17baae
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
# Getting Started

This guide takes you from a clean machine to a running MicProtocol stack with all self-hosted integrations. Read end-to-end on first install; use the checklists for re-installs.

## 1. Prerequisites

| Tool | Version | Purpose |
|---|---|---|
| Node.js | >= 20.0.0 | API, Web, Admin, Mobile tooling |
| pnpm | >= 9.15.0 (locked to `pnpm@10.30.3`) | Workspace package manager |
| Docker + Docker Compose | latest stable | Infra (Postgres, Redis, Meilisearch, integrations) |
| Python | >= 3.11 | CLIP scoring engine |
| uv | latest | Python package manager for `services/clip-scorer` |
| FFmpeg | latest | Audio/video frame extraction (also installed in API image) |
| PostgreSQL client | 15+ | Optional local DB without Docker |
| Redis CLI | 7+ | Optional local Redis without Docker |
| podman + podman-compose | latest | Required only for `pnpm agents:run` |

Install uv:

```bash
curl -LsSf https://astral.sh/uv/install.sh | sh
```

## 2. Repository

```bash
git clone <repo-url> micprotocol
cd micprotocol
```

The repo is a Turborepo monorepo. Top-level layout:

```
micprotocol/
β”œβ”€β”€ apps/
β”‚   β”œβ”€β”€ api/        NestJS backend (tRPC + REST + Socket.io)
β”‚   β”œβ”€β”€ web/        Next.js 14 host dashboard + guest portal
β”‚   β”œβ”€β”€ admin/      Next.js platform-admin app
β”‚   └── mobile/     Expo React Native app
β”œβ”€β”€ packages/
β”‚   β”œβ”€β”€ shared-types/   Zod schemas + domain enums
β”‚   β”œβ”€β”€ ui/             Cross-platform UI primitives
β”‚   β”œβ”€β”€ tsconfig/       Shared TS configs
β”‚   └── eslint-config/  Shared ESLint config
β”œβ”€β”€ services/
β”‚   β”œβ”€β”€ clip-scorer/  Python ML engine (OpenCLIP + pyloudnorm + bart-large-mnli)
β”‚   └── mic-realtime/ Erlang/OTP chat fanout + presence
β”œβ”€β”€ scripts/
β”‚   β”œβ”€β”€ init-databases.sql          Per-integration Postgres databases
β”‚   β”œβ”€β”€ generate-secrets.sh         Generates all self-hosted secrets
β”‚   β”œβ”€β”€ documenso-cert/README.md    How to generate the Documenso signing cert
β”‚   └── synthetic-agents/           Synthetic agent test framework
β”œβ”€β”€ docs/             This documentation set
β”œβ”€β”€ docker-compose.yml           Production Docker Compose (full stack)
β”œβ”€β”€ docker-compose.coolify.yml   Coolify override
β”œβ”€β”€ turbo.json        Turborepo pipeline
└── pnpm-workspace.yaml
```

## 3. Environment Configuration

```bash
cp .env.example .env
cp .env.example.coolify .env.coolify   # only if deploying via Coolify
```

Generate strong secrets for the self-hosted integrations:

```bash
bash scripts/generate-secrets.sh > .env.production.formbricks
# Manually merge generated values into your .env
```

`scripts/generate-secrets.sh` produces:

- Core infrastructure (Postgres, Redis, Meilisearch, MinIO passwords)
- Encryption keys (never rotate after initial setup)
- Chatwoot, Cal.com, Formbricks, Documenso, Listmonk secrets
- LiveKit API key/secret/webhook secret
- Umami app secret

For each `*_ENCRYPTION_KEY` and `*_NEXTAUTH_SECRET`, treat them as immutable after first start β€” rotating will invalidate sessions and unrecoverable encrypted data.

### Generate the Documenso signing certificate (one-time)

```bash
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem \
  -days 365 -nodes -subj "/CN=MicProtocol Documenso"
openssl pkcs12 -export -out scripts/documenso-cert/cert.p12 \
  -inkey key.pem -in cert.pem \
  -passout pass:"$(openssl rand -hex 32)"
rm key.pem cert.pem
```

Set `DOCUMENSO_SIGNING_PASSPHRASE` in `.env` to the passphrase used above. Production should use a CA-issued cert, never the self-signed one.

## 4. First Boot β€” Full Stack (Docker)

```bash
# 4.1. Start core infra (Postgres, Redis, Meilisearch)
docker compose up -d postgres redis meilisearch

# 4.2. Generate Prisma client and push schema
pnpm db:generate
pnpm db:push

# 4.3. Start the entire stack (API + worker + CLIP scorer + web + admin
#       + all self-hosted integrations + realtime)
docker compose up -d

# 4.4. Verify
docker compose ps
curl -s http://localhost:4000/health
```

Default ports:

| Service | Port | URL |
|---|---|---|
| Web (host dashboard + guest portal) | 3000 | http://localhost:3000 |
| Admin | 3006 | http://localhost:3006 |
| API | 4000 | http://localhost:4000 |
| Swagger (API) | 4000 | http://localhost:4000/api/docs |
| Meilisearch | 7700 | http://localhost:7700 |
| mic-realtime (WS) | 4001 | ws://localhost:4001 |
| Cal.com | 3002 | http://localhost:3002 |
| Formbricks | 3001 | http://localhost:3001 |
| Umami | 3003 | http://localhost:3003 |
| Documenso | 3004 | http://localhost:3004 |
| Chatwoot | 3005 | http://localhost:3005 |
| Listmonk | 9000 | http://localhost:9000 |
| MinIO API | 9000 (internal) | http://localhost:9001 |
| MinIO Console | 9090 | http://localhost:9090 |
| LiveKit | 7880 (HTTP), 7881 (TCP), 7882 (UDP) | http://localhost:7880 |
| Mailhog UI | 8025 | http://localhost:8025 |
| Mailhog SMTP | 1025 | n/a |

## 5. First Boot β€” Local Dev (No Docker for App Code)

Useful when iterating on the API or web app and you have the infra running in Docker.

```bash
# 5.1. Install all JS deps
pnpm install

# 5.2. Install Python deps for CLIP scorer
cd services/clip-scorer
uv sync
cd ../..

# 5.3. Start only infra in Docker
docker compose up -d postgres redis meilisearch

# 5.4. Generate Prisma client and push schema
pnpm db:generate
pnpm db:push

# 5.5. Start all apps in dev mode
pnpm dev
```

The Turborepo pipeline runs `api`, `web`, `admin` (if configured), and any app with a `dev` script. Hot reload is enabled for both the API (NestJS) and Web (Next.js).

## 6. Verifying the Stack

### API

```bash
# Liveness
curl -s http://localhost:4000/health

# Detailed
curl -s http://localhost:4000/health/detailed

# Readiness (K8s style)
curl -s http://localhost:4000/health/ready
```

### Database

```bash
pnpm db:studio   # opens Prisma Studio on http://localhost:5555
```

### Self-hosted integrations

After first boot, complete these one-time setup steps inside each UI:

| Service | Action |
|---|---|
| Cal.com | Create org `micprotocol`, generate an API key in Settings β†’ API Keys; set `CALCOM_API_KEY` in `.env` and restart API |
| Formbricks | Create Environment, copy ID to `NEXT_PUBLIC_FORMBRICKS_ENVIRONMENT_ID`; generate API key in Settings β†’ API Keys |
| Listmonk | Log in with `LISTMONK_ADMIN_USER`/`LISTMONK_ADMIN_PASSWORD`, generate API token in Settings β†’ API Tokens |
| Documenso | Upload signing cert (already generated in step 3) and configure SMTP |
| Chatwoot | Create user, create inbox (Website), copy inbox ID and website token to `.env` |
| Umami | Add website, copy website ID to `NEXT_PUBLIC_UMAMI_WEBSITE_ID` |
| MinIO | Log in with `MINIO_ROOT_USER`/`MINIO_ROOT_PASSWORD`; buckets are auto-created by `minio-createbuckets` |

### Webhook smoke tests

Each self-hosted integration has a webhook the API consumes. Use the Integration Health controller to confirm reachability:

```bash
curl -s http://localhost:4000/integrations/health | jq
```

See [Webhooks](./webhooks.md) for the full endpoint catalog and signature headers.

## 7. Running Tests

### API unit tests (Jest)

```bash
pnpm --filter @micprotocol/api test
```

### API E2E tests

```bash
pnpm --filter @micprotocol/api test:e2e
```

### Synthetic agents (full-stack scenario sweep)

```bash
pnpm agents:run   # full pipeline (pod up + seed + API + scenarios)
pnpm agents:orchestrator   # orchestrator only (API must be running)
pnpm db:seed:agents        # seed only
```

Requires `podman` + `podman-compose`. Outputs:

- `scripts/synthetic-agents/test-report.txt`
- `scripts/synthetic-agents/weaknesses.json`

## 8. Common Day-to-Day Commands

| Task | Command |
|---|---|
| Start everything | `pnpm dev` (JS apps) or `docker compose up -d` (full stack) |
| Rebuild after schema change | `pnpm db:generate && pnpm db:push` |
| Create a real migration | `pnpm --filter @micprotocol/api prisma:migrate` |
| Open Prisma Studio | `pnpm db:studio` |
| Run lint across the monorepo | `pnpm lint` |
| Run type check | `pnpm type-check` |
| Build for production | `pnpm build` |
| Tail logs | `docker compose logs -f api worker clip-scorer web` |
| Restart a single service | `docker compose restart <name>` |
| Stop everything | `docker compose down` |
| Wipe volumes (destructive) | `docker compose down -v` |

## 9. Troubleshooting First Run

### Postgres won't start

`docker compose logs postgres` β€” most often it's a port conflict (`5432` already in use). Either stop the local Postgres or change the host port mapping in `docker-compose.yml`.

### `pnpm db:push` complains about missing tables for `chatwoot`, `calcom`, etc.

You must run the init script that creates per-integration databases. The `init-databases.sql` is mounted into the Postgres container on first boot only β€” if the volume already exists, run manually:

```bash
docker exec -i micprotocol-postgres psql -U micprotocol -d micprotocol < scripts/init-databases.sql
```

### API returns 500 on first hit

Check that `CLERK_SECRET_KEY` and `CLERK_PUBLISHABLE_KEY` are set; without them the auth guard rejects all requests. For local-only development without Clerk, see [Security & Compliance](./security.md) for the dev-mode `x-user-id` header bypass.

### CLIP scorer stuck in "Scoring…"

See [CLIP Scoring Engine β†’ Troubleshooting](./clip-scoring.md#troubleshooting).

### Webhook 401s

Every webhook signature is verified with `crypto.timingSafeEqual()`. See [Security & Compliance](./security.md) and [Webhooks](./webhooks.md) for the exact header names per provider.

### Port already in use

The compose file uses fixed ports for every integration. Stop the conflicting process or remap the host port in `docker-compose.yml`.

## 10. Next Steps

- Read [Architecture](./architecture.md) for the bounded-context breakdown.
- Read [Self-Hosted Stack](./self-hosted-stack.md) before changing any container config.
- Read [Webhooks](./webhooks.md) before wiring a new integration.
- Read [Operations Runbook](./operations-runbook.md) before going to production.