Self-hosting
Run your own Porch server with in-memory or Convex storage.
Porch is open source (MIT). Run your own copy for a private instance, different limits, or a domain of your own. It's a Node.js 22+ server with two storage options:
| Storage | Use it for | Notes |
|---|---|---|
| Memory (default) | Development, single-instance servers | Everything is lost on restart. No setup. |
| Convex | Production | Durable, shared by any number of server instances, cleans up on its own. Waits subscribe to queries, so they wake the moment a request is stored. |
Run it locally#
git clone https://github.com/computer-agent-labs/porch.git
cd porch
yarn install
yarn devConnect a client to http://localhost:8787/mcp. Senders need to reach your machine for inbox URLs to work, so for real webhooks run Porch somewhere public.
Docker#
docker build -t porch .
docker run -p 8787:8787 -e PORCH_PUBLIC_URL=https://porch.example.com porchUse Convex for storage#
Deploy the functions in
convex/to your Convex project:bash npx convex deployChoose a long random secret and set it on the deployment:
bash npx convex env set PORCH_CONVEX_SECRET <secret> --prodStart the server with
CONVEX_URLset to your deployment URL andPORCH_CONVEX_SECRETset to the same secret.
Every Convex function checks the secret, because Convex functions are reachable by anyone who knows the deployment URL.
Deploy it#
Any platform that runs a long-lived container works. A few things matter:
- Not serverless functions. Waiting tools hold an HTTP request open for up to
PORCH_MAX_WAIT_SECONDSand stream progress over SSE. - Raise idle timeouts on your load balancer or proxy above the longest wait (Porch's own deployment uses 360 seconds), and don't buffer responses on
/mcp. - Set
PORCH_PUBLIC_URLto your public origin, andPORCH_TRUST_PROXYso client IPs are read correctly behind a proxy (1behind a single load balancer). - Use
GET /healthzas the health check.
The repository includes the AWS setup behind https://porch.okibi.ai: CloudFormation templates for ECS Fargate behind an Application Load Balancer, and a deploy script (deploy/aws).
Configuration#
All settings are environment variables.
| Variable | Default | Meaning |
|---|---|---|
PORT |
8787 |
Port to listen on. |
PORCH_HOST |
0.0.0.0 |
Interface to bind. |
PORCH_PUBLIC_URL |
from the Host header |
Base URL used in inbox links. Set it in production. |
PORCH_TRUST_PROXY |
false |
Express trust proxy setting: true, a hop count, or subnets. |
CONVEX_URL |
unset | Convex deployment URL. When set, Porch stores everything in Convex. |
PORCH_CONVEX_SECRET |
unset | Shared secret the Convex functions check. Required with CONVEX_URL. |
PORCH_MAX_INBOXES |
1000 |
Server-wide cap on active inboxes. |
PORCH_CAPACITY_MODE |
reject |
reject refuses new inboxes at the cap. per-ip lets IPs holding fewer than PORCH_PER_IP_MAX_INBOXES past it. |
PORCH_PER_IP_MAX_INBOXES |
3 |
Per-IP allowance once the cap is reached, in per-ip mode. |
PORCH_HARD_MAX_INBOXES |
2 × the cap | Absolute ceiling in per-ip mode. |
PORCH_DEFAULT_INBOX_TTL_MINUTES |
1440 |
Inbox lifetime when the agent doesn't choose one. |
PORCH_MIN_INBOX_TTL_MINUTES |
5 |
Shortest lifetime an agent can choose. |
PORCH_MAX_INBOX_TTL_MINUTES |
10080 |
Longest lifetime an agent can choose (7 days). |
PORCH_INBOX_IDLE_TIMEOUT_MINUTES |
240 |
Inboxes are deleted after this long without a keyed tool call. |
PORCH_MAX_REQUESTS_PER_INBOX |
1000 |
Requests kept per inbox. |
PORCH_REQUEST_TTL_MINUTES |
240 |
How long each request is kept. |
PORCH_MAX_BODY_BYTES |
262144 |
Largest body recorded (256 KB). |
PORCH_MAX_INBOX_BYTES |
8388608 |
Body bytes kept per inbox (8 MB). |
PORCH_MAX_WAIT_SECONDS |
300 |
Longest wait an agent can ask for. |
PORCH_ADMIN_TOKEN |
unset | Enables GET /admin/stats with Authorization: Bearer <token>. |
PORCH_LOG_LEVEL |
info |
debug, info, warn, error or silent. Logs never include request contents. |
A per-IP cap isn't on by default because many agents share an IP: MCP calls from hosted assistants, for example, come from the assistant provider's servers.
Monitoring#
With PORCH_ADMIN_TOKEN set, GET /admin/stats?days=30 reports daily counts: inboxes created and refused, requests captured, approval links, custom responses, and redirects, including the hosts redirects point to. Use it to spot abuse of custom responses.