Command Palette

Search for a command to run...

UnylyUnyly
Browse all

Selfhost

FreeNot checked

One-command self-host installer for ConnectAI. Takes a clean machine (only Docker + Node) to a running, health-checked company-brain in one command, with no sou

GitHubEmbed

About

One-command self-host installer for ConnectAI. Takes a clean machine (only Docker + Node) to a running, health-checked company-brain in one command, with no source clone and no local image build: npx @connectai/selfhost run. Bundles the image-based dock

README

ConnectAI

A self-hostable company brain you can build on: a governed-raw database plus an MCP server. Connect the tools a business already uses, derive a durable, queryable company brain, and expose it to any agent or app over the Model Context Protocol. The continuous "self-improving company OS" loop ships too, as a reference proof-of-concept running on the same substrate.

License: BSL 1.1 Source available Status: alpha


ConnectAI connects a company's tools (Gmail, Calendar, Slack, meeting notes, the CRM, the helpdesk, the accounting system) and synthesizes them into a durable, governed company brain held in your own Postgres. That brain is the product: a self-hostable substrate other systems build on top of, made of two parts.

  1. The database. A per-workspace, governed-raw company-brain store (packages/database: Postgres + pgvector, 1024-dim embeddings, HNSW, RLS isolation, an append-only ledger). It holds the chunked raw provider content plus the derived brain over it, so retrieval runs over the full substrate rather than a lossy distillation.
  2. The MCP server. A remote, OAuth-authenticated, read-only Model Context Protocol endpoint (apps/api/src/routes/mcp, Streamable HTTP at POST /mcp) that lets a workspace owner point their own agent (Claude, Cursor, a CLI, an app you write) at their brain and query it with standard MCP tools, RLS-scoped to their workspace.

You run both yourself (see Running ConnectAI), and you build agents and apps on top. ConnectAI does not own a normalized per-vendor record mirror: the source systems stay the systems of record.

The reference loop (proof-of-concept)

The continuous "self-improving company OS" loop below is a reference proof-of-concept built on the substrate, not the headline product. It runs as our live hosted demo to show what the database and MCP server make possible. Signal/insight generation and proactive "next action" prompting are deferred as a product direction; the substrate is what you adopt today.

ConnectAI also ships a reference app that runs continuous agents on top of the brain: they notice what matters and draft the next external action, with the owner approving each one by one tap and every edit teaching the system their voice. The loop:

  sense  ──▶  derive  ──▶  reason  ──▶  propose  ──▶  act  ──▶  learn
   │           │            │            │            │          │
 connected   company      what         insight +    on owner   from the
 tools       brain        matters      drafted      approval   owner's edits
 (ingest)   (synthesis)   now          action       (one tap)
   ▲                                                              │
   └──────────────────────────────────────────────────────────────┘

In the reference app the owner stays at the edge: it surfaces signals one proposed action at a time; the owner approves, edits, rejects, or snoozes; the result is recorded in an append-only, hash-chained ledger; and meaningful brain updates are proposed back for review.

Architecture

A Turborepo + npm-workspaces monorepo. The substrate (the product) is the governed-raw brain database plus the MCP server that exposes it; the loop apps are the reference proof-of-concept that runs on top.

Path What it is Layer
packages/database Prisma schema + the pgvector governed-raw brain store (1024-dim embeddings, HNSW, RLS, append-only ledger) substrate
apps/apiroutes/mcp Remote, OAuth-authenticated, read-only MCP server (Streamable HTTP POST /mcp) that exposes the brain to any agent substrate
packages/connections / packages/connectors-core The 17 source connectors and the contract + registry they conform to, feeding governed-raw chunks into the brain substrate
packages/inference The single inference chokepoint: text + embeddings, local (Ollama) or hosted substrate
packages/vault Credential vault (Infisical, or a local AES-256-GCM file fallback in dev) substrate
apps/api (rest) Fastify REST API: connections, query, propose/approve, ledger, OAuth callbacks reference app
apps/loop-svc pg-boss worker: per-connection sync, progressive cold-start backfill, insight + health passes reference app
apps/web Vite + React SPA: the owner-facing Signals feed, Brain, and Connections surfaces reference app
packages/tool-bus, packages/result Action dispatch + a typed Result helper reference app

Privacy posture: governed-raw. ConnectAI durably stores chunked raw provider content, per-workspace, encrypted at rest in a key-separated zone, so retrieval runs over the full substrate rather than a lossy distillation. The trust claim is encrypted, workspace-isolated, never trained on, retention you control, one-tap purgeable, not we never hold your raw. The binding rule is .claude/rules/database.md.

Connectors

Gmail · Google Calendar · Microsoft 365 · Slack · Discord · Notion · Granola · Zoom · Linear · Jira · GitHub · HubSpot · Attio · Intercom · Calendly · Stripe · QuickBooks Online

How recall works

ConnectAI is built to answer an agent's questions over a large, messy company dataset, the kind of corpus where one search angle always misses something. The recall layer is the part worth understanding. It runs over the governed-raw substrate (durable, chunked, encrypted-at-rest raw provider content), not a lossy summary, and it composes a few well-known techniques rather than betting on one. This is the map; the implementation links are inline.

  provider data
       │  ingest
       ▼
  Episode ──► Chunk(seq)         token-windowed raw bodies, kept in episode order
       │        │  rawText (the durable retrieval substrate)
       │        ├──► Embedding vector(1024)  ──► HNSW index   (dense / semantic leg)
       │        └──► to_tsvector('english')  ──► GIN FTS index (lexical / exact leg)
       │
  EpisodeParticipant ──► entity resolution (personKey) ──► EntityEdge(weight) link graph
       ▼
  query ─► [ dense kNN ] ─┐
          [ lexical FTS ] ─┼─► RRF fusion ─► ACT-R recency re-rank ─► spreading-activation
                           │                 (lastAccessedAt,         expansion over the
                           │                  accessCount)            EntityEdge graph
                           ▼
                  parent-episode reassembly (Chunk.seq) ─► grounded answer + breadcrumb

The substrate: governed-raw chunks. Ingest token-windows each source body into Chunk.rawText and keeps Chunk.seq so a chunk's parent episode can be reassembled in order (the answer span is never lost to per-chunk truncation). Raw is durable, encrypted at rest, key-separated, and RLS-scoped per workspace (binding rule: .claude/rules/database.md). Every row carries a breadcrumb ({ provider, externalId, permalink }) so an answer links back to the live original.

model Chunk {
  seq            Int       @default(0)   // parent-episode reassembly order
  rawText        String?                 // durable, encrypted, RLS-scoped substrate
  breadcrumb     Json                    // { provider, externalId, permalink }
  lastAccessedAt DateTime?               // ACT-R recency
  accessCount    Int       @default(0)   //   "
  @@index([episodeId, seq])
}

Hybrid retrieval (dense + lexical), fused by RRF. Two legs run over the same raw substrate and are combined with Reciprocal Rank Fusion, so neither modality has to win alone (hybrid-search.ts, rrf.ts):

  • Dense / semantic: 1024-dim embeddings over rawText, queried by HNSW cosine (<=>). Catches paraphrase and meaning. Raw and derived vectors share one HNSW index, so retrieval filters embeddingSource = 'raw' to run recall over the raw substrate.
  • Lexical / exact: Postgres full-text ts_rank over a GIN index on to_tsvector('english', coalesce("rawText", '')). Catches the things embeddings blur: invoice numbers, SKUs, error codes, names.
-- dense leg: HNSW cosine kNN over raw-substrate vectors
SELECT "chunkId", ("vector" <=> $query::vector) AS distance
FROM "Embedding"
WHERE "workspaceId" = $ws AND "embeddingSource" = 'raw'
ORDER BY "vector" <=> $query::vector
LIMIT $k;

-- lexical leg: FTS ts_rank over the same raw text (byte-exact to the GIN index)
SELECT "id"
FROM "Chunk"
WHERE "workspaceId" = $ws
  AND to_tsvector('english', coalesce("rawText", '')) @@ plainto_tsquery('english', $q)
ORDER BY ts_rank(to_tsvector('english', coalesce("rawText", '')), plainto_tsquery('english', $q)) DESC
LIMIT $k;
-- the two ranked lists are merged by RRF, then re-ranked (below)

ACT-R recency re-rank. Fused candidates are re-weighted by an ACT-R-style recency signal (Chunk.lastAccessedAt, accessCount), so what the company touched recently surfaces over equally-similar but stale matches, without discarding the long tail.

Spreading activation over the entity graph. Entity resolution collapses participants to a stable personKey, and reinforced EntityEdge rows (weight as edge conductance, lastReinforcedAt) form a link graph. A recursive reachability CTE spreads activation from the query's anchor entities to reach material a pure text match would miss, for example the thread you were not on but that is one hop from the person you asked about (spreading-activation.ts, actr-rerank.ts, parent-expand.ts).

Grounding. Because the raw chunk is held durably, an answer cites the chunk directly and stays valid even when the upstream source is later deleted; the breadcrumb degrades to a "source no longer available upstream" state rather than fabricating.

For agents. The same recall layer is exposed to a user's own agent through a read-only OAuth MCP server (see the MCP bank-access design in planning/), so an external agent queries the governed company brain under the workspace's RLS and egress controls, never the raw provider APIs.

Deeper detail and the rationale behind each choice live in planning/ENGINEERING_ROADMAP.md, planning/ERD.md, and the binding .claude/rules/database.md.

Status

Alpha. The substrate runs end to end on live accounts: connectors ingest into the governed-raw brain (packages/database), and the read-only MCP server (apps/api/src/routes/mcp) serves OAuth-authenticated, workspace-scoped queries over it to external agents. The reference loop (ingest → brain → query → propose → approve → real send → ledger) also runs end to end as the live hosted demo, but it is a proof-of-concept on the substrate, not the product direction. Interfaces still move week to week. The data model lives in planning/ERD.md; the strategy docs in planning/ carry a positioning note at the top.

Licensing

ConnectAI is a commercial product with published source under the Business Source License 1.1.

  • Read, modify, and evaluate the source freely. Development, testing, and evaluation use need no license.
  • Production use requires a paid license. Any production use of ConnectAI, whether on our cloud or self-hosted, requires a commercial license or subscription. (The BSL Additional Use Grant is set to "None".)
  • It converts to Apache-2.0 on the Change Date (2030-06-09 for the current version), at which point it becomes fully open source.

ConnectAI ships in two modalities, and you choose: self-host it yourself (the primary path, see Running ConnectAI), or have us run it for you on our managed cloud. Both run the same substrate; both require a license for production use. For self-hosted, managed-cloud, or enterprise licensing, contact [email protected] or [email protected].

Running ConnectAI: self-host or managed cloud

ConnectAI is a self-hostable product first, with a managed cloud as the second way to run it. Both modalities run the same substrate: the api and loop images build from the same Dockerfiles, and self-host stands up the same brain DB schema and the same MCP connect surface as the cloud. Production use of either requires a license (see Licensing).

Self-host (primary). You run the whole stack yourself. From a clean checkout, one command (make selfhost) brings a production-faithful stack (docker-compose.selfhost.yml, with a bundled Infisical vault and optional local Ollama inference) to a healthy, console-served state: the standalone operator console (local auth, no Firebase) routes you straight into a guided first-run wizard. Two runbooks back this up:

  • SELF_HOSTING.md: the full operator guide. prerequisites, the one-command boot, the wizard walkthrough, per-connector OAuth setup, inference, upgrades, and troubleshooting. Start here.
  • deploy/selfhost/README.md: the deeper stand-up and verification runbook for the self-host stack internals.

Managed cloud (we run it for you). Prefer not to operate the stack? We host the same substrate for you. This is the convenience option, not a different product.

To discuss self-hosted, on-prem, managed-cloud, or enterprise deployment, contact [email protected] or [email protected].

Local development

Which command do I run? To run or evaluate ConnectAI, use make selfhost (the self-host stack: local auth, no Firebase, the operator console). The dev stack below is for contributing to the code (hot reload, the cloud apps/web SPA, the Firebase emulator). They are different stacks on different ports.

For contributing (running the apps from source with hot reload), the repo ships a one-command dev stack that boots everything in Docker and starts the API + web dev servers. See CONTRIBUTING.md for the full setup.

nvm use            # Node 22 (see .nvmrc)
npm install        # installs + links the @connectai/* workspaces
npm run dev:stack  # boots postgres, redis, infisical, the firebase emulator, api, web; Ctrl+C tears it down
Service Port URL
api (Fastify) 4000 http://localhost:4000 (/health)
web (Vite) 5173 http://localhost:5173
postgres (pgvector) 5432 postgresql://postgres:[email protected]:5432/cobrain_dev
infisical 8082 http://localhost:8082

Local dev defaults to Ollama for inference (COBRAIN_INFERENCE_PROVIDER=ollama), so the brain runs with no hosted key. Start ollama serve separately and pull qwen3.5:latest + mxbai-embed-large.

The Postgres image must be pgvector/pgvector:pg16: the brain schema declares a vector(1024) column plus an HNSW index, which vanilla postgres lacks.

Demo

Want to see the brain answer cross-functional questions without wiring your own accounts? Seed a fictional company (AsterOps) across 10 connectors (Gmail, Calendar, Slack, Granola, Notion, Linear, GitHub, HubSpot, Stripe, Intercom) through the real ingest pipeline, prove the brain answers grounded questions over it, then point your own agent at it. This is the same arc the self-host demo video walks through. See DEMO.md for the full runbook (prerequisites, inference config, connecting your own agents) and DEMO_RUNBOOK.md for the live-demo readiness gate.

# 1. Bring the self-host stack up (8 services: api, console, db, ollama, infisical x3, loop-svc)
docker compose -f docker-compose.selfhost.yml up -d   # or: make selfhost

# 2. Reset + ingest the 10 connectors through the real pipeline into the self-host Postgres
npm run demo:seed    # -> 38 episodes across 10 connectors, one private brain

# 3. Readiness gate: confirm the stack, inference path, and seeded brain are ready
npm run demo:check   # -> PREFLIGHT GREEN

# 4. Prove the brain answers and the MCP access is scoped
npm run demo:prove   # cross-functional scenarios + the brain MCP agent-interface checks (5/5)

Open the console (the first-run wizard lands you there): the Connections page shows the seeded connectors and the Ask page answers a cross-connector question, grounded with citations, in the UI. Then point any MCP client at the same brain over the MCP server, the harness-agnostic finale: the demo video does this with Claude Code (claude -p, pointed at the self-host MCP), but Claude Desktop, a CLI, or an app you write work the same way. See planning/specs/agent-demo-substrate/CONNECT_AGENTS.md.

Watching the demo video? The connector tiles in the video flip green instantly because the recording uses a guided demo presentation over a pre-seeded corpus. Connecting your own accounts is different: each connector needs a real credential (a self-stood-up OAuth app or a pasted BYO token), the token is validated before anything is saved, and the brain answers only after the first sync completes, not the instant the tile turns green. See SELF_HOSTING.md for the real per-connector setup.

Adding a connector

Connectors conform to the @connectai/connectors-core contract and register into the loop with no change to the loop itself. The buildConnector workflow (see .claude/skills/buildConnector) scaffolds one from an app name. The connector emits rawChunks (governed-raw windowed text); the brain pipeline handles synthesis, embedding, and retrieval.

Documentation

  • DEMO.md — seed a fictional company across 10 connectors and watch the brain answer cross-functional questions
  • CONTRIBUTING.md — dev setup, the build loop, PR conventions
  • CLAUDE.md — repo conventions and the required-reading map
  • .claude/rules/database.md — the binding governed-raw data rules
  • planning/ — the thesis, architecture, ERD, roadmap, and engineering decision log

License

Business Source License 1.1. Converts to Apache-2.0 on the Change Date. © 2026 ConnectAI.

from github.com/ConnectAI-OS/connectai

Install Selfhost in Claude Desktop, Claude Code & Cursor

Recommended · one command, every IDE
unyly install selfhost

Installs into Claude Desktop, Claude Code, Cursor & VS Code — handles npx, uvx and build-from-source repos for you.

First time? Get the CLI: curl -fsSL https://unyly.org/install | sh

Or configure manually

Run in your terminal:

claude mcp add selfhost -- npx -y @connectai/selfhost

FAQ

Is Selfhost MCP free?

Yes, Selfhost MCP is free — one-click install via Unyly at no cost.

Does Selfhost need an API key?

No, Selfhost runs without API keys or environment variables.

Is Selfhost hosted or self-hosted?

Self-hosted: the server runs locally on your machine via the install command above.

How do I install Selfhost in Claude Desktop, Claude Code or Cursor?

Open Selfhost on unyly.org, pick your client tab (Claude Desktop, Claude Code, Cursor) and press Install — the config is generated automatically, no JSON editing.

Related MCPs

Compare Selfhost with

Not sure what to pick?

Find your stack in 60 seconds

Author?

Embed badge for your README

Browse similar

All development MCPs