Skip to content

Deploy Cully for a team ​

This guide is for the company ops team running Cully for several people. For your own laptop, use the quickstart. Everyone connects to the same public MCP endpoint and signs in through the company's identity provider. Memory remains private to each person: personal and company organize records and do not share them. Separate workspace operations provide explicitly authorized project tasks, checkpoints and published lessons.

The memory services and the advisor are installed in different places:

LocationComponents
Each user's machineCully CLI, local advisor daemon, coding agent, Cully skill and session hooks. No local Mem0 or Docker stack is needed.
Remote deploymentPublic HTTPS endpoint for Cully MCP; private Cully data API, Mem0, source-note PostgreSQL and Mem0's pgvector database. These can run on different hosts.

The coding agent calls the remote MCP endpoint for shared memory. Its local hooks send session signals to the local advisor. Users' machines reach the public MCP and sign-in endpoints; the data API, Mem0 and databases communicate through private network connections.

Choose how to run the stack ​

The Docker Compose setup starts Cully, PostgreSQL, Mem0, MCP Auth and Caddy on one machine. It is the shortest deployment path.

Cully releases provide the CLI and installer for users, plus matching ghcr.io/mcp-runtime/cully-mcp, ghcr.io/mcp-runtime/cully-data and ghcr.io/mcp-runtime/cully-mem0 images for operators. Run the images with Compose, Kubernetes or another suitable platform, together or on separate hosts. The Compose file is a reference, not a required layout. Run the data image's migrate command before serving traffic. Give Mem0 its pgvector-enabled PostgreSQL database and persistent history volume. Keep both databases, Mem0 REST and the data API on private networks; expose only MCP through HTTPS.

Connect the components ​

ConnectionConfigure
Agent → Cully MCPGive each user the public HTTPS MCP URL with --mcp-url. For a team endpoint, set CULLY_MCP_AUTH_MODE=oauth and configure the exact public URL as CULLY_AUTH_RESOURCE, plus CULLY_AUTH_ISSUER and CULLY_JWKS_URL.
Cully MCP → data APISet CULLY_DATA_API_URL to the private data API base URL. Put the same CULLY_DATA_API_TOKEN on both services.
Data API → source PostgreSQLSet CULLY_DATABASE_URL to the private database connection URL and run the data image's migrate command.
Data API → Mem0Set CULLY_MEM0_URL to the private Mem0 REST base URL. Set CULLY_MEM0_API_KEY to the same value as Mem0's ADMIN_API_KEY.
Mem0 → pgvector PostgreSQLSet Mem0's POSTGRES_HOST, POSTGRES_PORT, POSTGRES_DB, POSTGRES_USER and POSTGRES_PASSWORD. Give Mem0 a JWT_SECRET; persist its database and history volume.

These connections are the deployment requirement; choose the hosts, platform and private network that fit your environment. The configuration reference has the full variable list and credential boundaries. Agents receive only the public MCP URL and their own OAuth sign-in; service secrets stay with the deployment.

Quick path with Docker Compose ​

After installing the Cully CLI, open a new terminal and run cully setup --all --prepare to create editable files. Set the public MCP and authorization hostnames and the upstream identity-provider client secret in ~/.cully/self-hosted/config/.env. Add the provider's connectors.json and a persistent signing key as shown in the OAuth setup. Then start the stack:

sh
cully setup --all --oauth

This starts PostgreSQL, Mem0, the data API, Cully MCP, MCP Auth and Caddy. Each person then connects their agent to the public MCP URL; the agent guide gives the client commands.

Example: run Cully with MCP Runtime ​

The Cully maintainer runs a personal Cully MCP endpoint on MCP Runtime. Its deployment workflow builds and publishes the MCP image, then deploys the server manifest. Cully's data API, PostgreSQL and Mem0 run separately. The MCP Runtime publishing guide shows the build, push and deploy flow.

A company can use this pattern to run Cully's MCP container as an MCPServer workload on its Kubernetes cluster. MCP Runtime manages the container rollout, service and workload status; Cully supplies the memory tools and owner-scoped storage. The MCP Runtime API reference lists the workload image, port and secret environment fields. The company ingress publishes Cully's OAuth and MCP routes.

  1. Deploy Cully's PostgreSQL, Mem0 and private data API in the cluster. Keep those services on private networking and run cully-data migrate before starting the API. Use the Compose file to map the service dependencies and volumes.
  2. Publish ghcr.io/mcp-runtime/cully-mcp:<matching-release-tag> through MCP Runtime as a workload listening on Cully's configured port. Set CULLY_DATA_API_URL to the private data API and set CULLY_MCP_AUTH_MODE=oauth, CULLY_AUTH_ISSUER, CULLY_AUTH_RESOURCE and CULLY_JWKS_URL as described below. Give CULLY_DATA_API_TOKEN through a Kubernetes Secret with the same value used by the private data API. The maintainer's manifest expects cully-data-api-token in mcp-servers with key CULLY_DATA_API_TOKEN; provision it before rollout and keep the value out of Git. Do not set a fixed CULLY_MCP_OWNER for a multi-person server.
  3. Route a dedicated HTTPS host, for example https://cully.example.com/mcp, to the Cully service. Forward its OAuth discovery and MCP paths as well as the Authorization header to Cully. Connect the company's identity provider through MCP Auth or a compatible authorization server, then sign in from each person's agent.

Keep MCP Runtime's OAuth gateway off for this Cully route in the current integration. Its gateway strips the client bearer token before forwarding, while Cully currently validates that token to identify each memory owner. Use Cully's OAuth mode at the service boundary until an explicit, verified identity handoff is implemented. This example uses MCP Runtime's workload management; it does not claim its grant and session policy for Cully.

After deployment, check that the Cully Deployment's updated and ready replicas match its desired replicas and that its pod runs the new image tag. The CLI can report Ready while an older pod serves traffic during a failed rollout (Runtime issue #636).

Connect sign-in ​

  1. Choose the public MCP URL, such as https://mcp.example.com/mcp, and an authorization-server URL. The exact MCP URL must be the token's resource audience.

  2. Configure MCP Auth or a compatible authorization server with the company's identity provider. Grant tools:read and tools:write for the MCP resource.

  3. Configure Cully MCP with CULLY_MCP_AUTH_MODE=oauth, the issuer, exact resource URL and JWKS URL. The configuration reference lists the service variables.

  4. Give each person the public MCP URL. They pick their agent and install and connect with:

    $ curl -fsSL https://cully.net/install.sh | sh -s -- --agent codex --mcp-url https://mcp.example.com/mcp --oauth

    Then they sign in; for Codex, run codex mcp login cully. See connect an agent for its sign-in step.

MCP uses a private service token to call the data API. The data API holds database and Mem0 credentials. Keep those credentials in the deployment's secret store; agents need only the public MCP URL and their own OAuth sign-in. The architecture shows the service flow.

Enable the team workspace ​

Apply migration 006 before starting the updated data service. Gate cully_workspace_read with tools:read and cully_workspace_write with tools:write; both require OAuth even though they are discoverable in no-OAuth mode. Existing memory owners and notes are unchanged.

Each person calls whoami to obtain their workspace principal, bound to the verified issuer and subject. The team creator becomes its first admin. Admins explicitly add team members and projects; project maintainers or team admins grant project roles. Team membership alone does not grant project reads. See team workflows.

Changes and audit events commit together in PostgreSQL. Limits per team are 100 members, 50 projects, 500 tasks, 500 lessons, 200 playbooks and a 1 MiB serialized aggregate. Per-team writes serialize under a row lock. Scale and normalize storage before raising these limits. Audit events are operator-accessible database records; there is no user-facing audit export or web board yet.

Built in the open. Apache 2.0 licensed.