# Overview

> What Paca exposes, runtime surfaces (web, API, realtime, MCP, ai-agent), and the shortest path from install to first project and API key.

- Repository: Paca-AI/paca
- GitHub: https://github.com/Paca-AI/paca
- Human docs: https://www.grok-wiki.com/public/docs/paca-ai-paca-f238b2ab3d25
- Complete Markdown: https://www.grok-wiki.com/public/docs/paca-ai-paca-f238b2ab3d25/llms-full.txt

## Source Files

- `README.md`
- `docs/product/overview.md`
- `docs/architecture/overview.md`
- `docs/README.md`
- `ROADMAP.md`

---

---
title: "Overview"
description: "What Paca exposes, runtime surfaces (web, API, realtime, MCP, ai-agent), and the shortest path from install to first project and API key."
---

Paca is a self-hosted, open-source project management platform (Apache 2.0) where humans and AI agents collaborate on the same Scrum board. A production stack runs as Docker Compose services behind an nginx gateway on port 80: the web UI, versioned REST API at `/api/v1`, Socket.IO realtime at `/ws/socket.io`, optional object storage at `/storage/`, and an optional OpenHands-powered `ai-agent` runtime. External integrations connect through user API keys and the `@paca-ai/paca-mcp` npm package.

## What Paca exposes

| Surface | Location | Purpose |
|:--|:--|:--|
| Web UI | `http://<host>/` | Board, backlog, sprints, docs, plugins, agent chat |
| REST API | `/api/v1/*` | System of record for all product state |
| Health check | `GET /api/healthz` | API liveness (`{"status":"ok"}`) |
| Realtime | `/ws/socket.io` | Live board, task, comment, and agent events |
| Object storage | `/storage/*` | Presigned upload/download via MinIO or S3 |
| MCP server | `@paca-ai/paca-mcp` (stdio via `npx`) | Structured tool access for any MCP client |
| AI agent | Internal `ai-agent` service (port 8082 exposed optionally) | OpenHands conversations in isolated Docker containers |

The MCP server is not part of the Compose stack. You run it in your editor or agent host and point it at the Paca API with `PACA_API_KEY` and `PACA_API_URL`.

## Runtime architecture

Paca is a monorepo with five deployed runtime areas plus shared infrastructure:

```mermaid
flowchart LR
  Browser["Browser / MCP client"]
  Gateway["nginx gateway :80"]
  Web["apps/web"]
  API["services/api"]
  RT["services/realtime"]
  Agent["services/ai-agent"]
  PG["PostgreSQL"]
  VK["Valkey"]
  Store["MinIO / S3"]

  Browser --> Gateway
  Gateway --> Web
  Gateway --> API
  Gateway --> RT
  Gateway --> Store
  API --> PG
  API --> VK
  API --> Store
  RT --> VK
  Agent --> VK
  Agent --> PG
  Agent --> API
```

| Component | Stack | Role |
|:--|:--|:--|
| `apps/web` | React, TanStack Start, shadcn/ui | User-facing SPA |
| `services/api` | Go, Gin | Business logic, auth, plugins (WASM), event production |
| `services/realtime` | Node.js, Socket.IO | Consumes Valkey streams; fans out client-safe events |
| `services/ai-agent` | Python, FastAPI, OpenHands SDK | Triggered agent conversations in Docker sandboxes |
| `apps/mcp` | TypeScript, MCP SDK | Translates MCP tool calls to REST requests |

**PostgreSQL** holds transactional data. **Valkey** provides cache, coordination, and asynchronous event streams that decouple the API from Socket.IO delivery and agent triggers. State-changing logic stays in `services/api`; the realtime service does not own product state.

## Gateway routing

All public traffic enters through the nginx `gateway` container. Route prefixes are stable across dev and production:

| Path prefix | Upstream | Notes |
|:--|:--|:--|
| `/api/` | `api:8080` | Forwards prefix as-is (e.g. `/api/v1/projects`) |
| `/ws/` | `realtime:3001` | Strips `/ws/`; clients connect with `path: "/ws/socket.io"` |
| `/storage/` | `minio:9000` | Large uploads; bypasses default body-size limit |
| `/` | `web` | SPA with client-side routing |

Optional scaling flags suppress bundled services without changing the gateway contract: `--scale postgres=0` (external DB), `--scale minio=0` (AWS S3), `--scale ai-agent=0` (no agent runtime), `--scale web=0` (CDN-hosted frontend).

## Shortest path: install to first project and API key

<Steps>
<Step title="Start the stack">

<Tabs>
<Tab title="Install script (recommended)">

```bash
curl -fsSL https://github.com/Paca-AI/paca/releases/latest/download/install.sh | bash
```

The script downloads compose assets, generates secrets, and starts the full stack. Open `http://<your-server-ip>` when it finishes.

</Tab>
<Tab title="Docker Compose (manual)">

```bash
mkdir paca && cd paca
curl -fsSL https://github.com/Paca-AI/paca/releases/latest/download/docker-compose.yml -o docker-compose.yml
mkdir -p nginx
curl -fsSL https://github.com/Paca-AI/paca/releases/latest/download/gateway.conf -o nginx/gateway.conf

cat > .env <<'EOF'
JWT_SECRET=<run: openssl rand -hex 32>
ADMIN_PASSWORD=<your-admin-password>
POSTGRES_PASSWORD=<run: openssl rand -hex 32>
AGENT_API_KEY=<run: openssl rand -hex 32>
INTERNAL_API_KEY=<run: openssl rand -hex 32>
ENCRYPTION_KEY=<run: openssl rand -hex 32>
PUBLIC_URL=http://localhost
COOKIE_SECURE=false
EOF

docker compose --env-file .env up -d
```

Open `http://localhost`.

</Tab>
</Tabs>

Verify the API is healthy:

<RequestExample>

```bash
curl -s http://localhost/api/healthz
```

</RequestExample>

<ResponseExample>

```json
{"status":"ok"}
```

</ResponseExample>

</Step>

<Step title="Log in as admin">

Sign in at the web UI with username `admin` and the `ADMIN_PASSWORD` from your `.env` file. The install script prompts for this value; manual setups set it explicitly.

JWT session cookies are issued on login. For programmatic access, use API keys (next step) or `Authorization: Bearer <access-token>` from `POST /api/v1/auth/login`.

</Step>

<Step title="Create a project">

In the web UI, create a project from the projects list. Alternatively, call the REST API with your session token:

<RequestExample>

```bash
curl -s -X POST http://localhost/api/v1/projects \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <access-token>" \
  -d '{"name":"My First Project","description":"Getting started"}'
```

</RequestExample>

<ResponseExample>

```json
{
  "success": true,
  "data": {
    "id": "9a1d7c2b-…",
    "name": "My First Project",
    "task_id_prefix": "MFP",
    "is_public": false,
    "created_at": "2026-06-13T12:00:00Z"
  },
  "request_id": "…"
}
```

</ResponseExample>

</Step>

<Step title="Generate an API key">

API key creation requires a JWT session (not an existing API key). In the UI: **Settings → API Keys → New Key**. Via API:

<RequestExample>

```bash
curl -s -X POST http://localhost/api/v1/users/me/api-keys \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <access-token>" \
  -d '{"name":"mcp-integration"}'
```

</RequestExample>

<ResponseExample>

```json
{
  "success": true,
  "data": {
    "id": "…",
    "name": "mcp-integration",
    "key": "paca_…",
    "created_at": "2026-06-13T12:00:00Z"
  },
  "request_id": "…"
}
```

</ResponseExample>

The raw `key` value is shown once at creation. Store it immediately; it cannot be retrieved later.

</Step>

<Step title="Verify API key access">

Use the key on any authenticated endpoint:

<ParamField body="Authorization" type="string">
`Authorization: ApiKey <key>` or `X-API-Key: <key>`
</ParamField>

<RequestExample>

```bash
curl -s http://localhost/api/v1/projects \
  -H "X-API-Key: paca_…"
```

</RequestExample>

</Step>
</Steps>

Database migrations run automatically on API startup. Upgrades are `docker compose pull` followed by `docker compose --env-file .env up -d`.

## Authentication model

| Credential | Used by | Header / mechanism |
|:--|:--|:--|
| JWT access token | Web UI, CLI scripts | `access_token` HttpOnly cookie or `Authorization: Bearer` |
| JWT refresh token | Session renewal | `POST /api/v1/auth/refresh` |
| User API key | MCP, scripts, integrations | `Authorization: ApiKey` or `X-API-Key` |
| `AGENT_API_KEY` | Internal `ai-agent` ↔ `api` | Pre-shared service key (not a user key) |
| `INTERNAL_API_KEY` | Service-to-service calls | `X-Internal-Key` on internal endpoints |

API key management endpoints (`GET/POST/DELETE /api/v1/users/me/api-keys`) accept JWT only — a leaked API key cannot create additional keys.

## Integration surfaces

### MCP server

The `@paca-ai/paca-mcp` package exposes tools for projects, tasks, sprints, documents, members, views, custom fields, attachments, activity, and plugin-registered tools. Configure any MCP client:

```json
{
  "command": "npx",
  "args": ["-y", "@paca-ai/paca-mcp"],
  "env": {
    "PACA_API_KEY": "paca_…",
    "PACA_API_URL": "http://localhost"
  }
}
```

`PACA_API_URL` defaults to `http://localhost:8080` when unset; through the gateway, use `http://localhost` (port 80) or your `PUBLIC_URL`.

### AI agent runtime

When enabled, `services/ai-agent` consumes trigger events from the `paca:agent:triggers` Valkey stream, spawns an OpenHands container per conversation, and publishes events to `paca:agent:events` for realtime delivery. Agents appear as project members on the board. Skip the service with `--scale ai-agent=0` if you only need human workflows and MCP access.

### Plugin system

Plugins extend the WASM backend (custom routes, host functions), frontend (board views, task panels, settings tabs), and MCP (runtime-registered tools). Install from **Settings → Plugins → Marketplace** or via the local install script. The core stays small; workflows, BDD editing, checklists, and GitHub integration ship as plugins.

## Core product capabilities

- **Unified Scrumban board** — humans and agents on one real-time board
- **Sprint lifecycle** — create, start, complete sprints with backlog ordering
- **Task management** — custom types, statuses, fields, comments, activity feed with diff/revert
- **Documentation** — per-project living docs with version history
- **In-app AI chat** — project-level agent chat for planning and task creation
- **Realtime collaboration** — Socket.IO delivery through Valkey stream decoupling
- **Self-hosted** — data stays on your infrastructure; no per-seat licensing

The P-A-C-A cycle (Plan → Act → Check → Adapt) structures how teams and agents iterate together.

## Required secrets (production)

| Variable | Purpose |
|:--|:--|
| `JWT_SECRET` | Signs access and refresh tokens |
| `ADMIN_PASSWORD` | Initial `admin` user password |
| `POSTGRES_PASSWORD` | Bundled PostgreSQL credential |
| `AGENT_API_KEY` | Authenticates `ai-agent` to `api` |
| `INTERNAL_API_KEY` | Service-to-service authentication |
| `ENCRYPTION_KEY` | Encrypts plugin secrets and agent LLM keys at rest |
| `PUBLIC_URL` | Base URL for callbacks, CORS, and presigned storage URLs |

Generate random values with `openssl rand -hex 32`.

## Repository layout

:::files
paca/
├── apps/
│   ├── web/           # React SPA
│   ├── mcp/           # @paca-ai/paca-mcp
│   └── e2e/           # Playwright tests (not deployed)
├── services/
│   ├── api/           # Go REST backend
│   ├── realtime/      # Socket.IO fan-out
│   └── ai-agent/      # OpenHands orchestration
├── deploy/            # Compose files, nginx gateway
├── docs/              # Architecture and guides
├── plugins/local/     # Installed plugin artifacts
└── skills/            # Claude Code /paca slash commands
:::

## Related pages

<CardGroup cols={2}>
<Card title="Installation" href="/installation">
Prerequisites, install script, manual Compose, secrets, and optional stack scaling.
</Card>
<Card title="Quickstart" href="/quickstart">
First successful run with health checks, admin login, project creation, and API key verification.
</Card>
<Card title="Platform architecture" href="/platform-architecture">
Service boundaries, Valkey event decoupling, and gateway routing in depth.
</Card>
<Card title="Connect MCP server" href="/connect-mcp">
Configure `@paca-ai/paca-mcp` for Claude Desktop, VS Code, or any MCP client.
</Card>
<Card title="REST API" href="/rest-api">
Versioned `/api/v1` paths, auth envelopes, pagination, and endpoint catalog.
</Card>
<Card title="AI agents" href="/ai-agents">
Agent members, triggers, OpenHands lifecycle, and Docker isolation.
</Card>
</CardGroup>
