Skip to main content
Glama
hexablob

PactAI MCP

by hexablob

PactAI

A shared knowledge layer for coding agents.

Every session your agent starts, it starts from nothing. It rediscovers the project's conventions — usually by violating one and being corrected — and the correction is thrown away when the session ends. The next agent, on a different tool, repeats it.

PactAI holds a project's decisions, conventions and constraints, serves each agent only what governs the file in front of it over MCP, and records whether the code still honors them.

Agents read the code. PactAI keeps the verdict. It never sees the source.

The three invariants

Everything here follows from these. They are not preferences.

  1. Atoms are a projection of documents. Knowledge is extracted from versioned prose, never hand-minted, so it can be re-derived when models improve and always carries a citable source.

  2. Everything an agent writes is born provisional. Human ratification is what makes the knowledge base worth querying — it is the mechanism that produces trust, not friction to be optimized away.

  3. Source code never leaves the machine. Reconciliation runs inside the customer's own agent session. What comes back is a verdict and a path:line.

Read docs/01-thesis.md for the argument and docs/02-principles.md for the design rules that follow from it.

Related MCP server: constraints-registry-mcp

Not to be confused with Pact

Pact is a contract-testing framework — it checks that two services agree on an API format. Excellent tool, unrelated problem, different people. PactAI is about a project's decisions and whether code still honors them.

The names are close and that is our problem, not yours: PactAI is always written in full, and the binary is pactai, never pact. If you came here looking for contract testing, pact.io is what you want.

How this differs from the alternatives

Sharing context between coding agents is a crowded space. Most of it solves a different half of the problem:

Approach

What it does

What it does not do

AGENTS.md + a sync script

one canonical file, generated into each tool's format

tell you when the code stopped matching the file

Rule generators (RuleSync and similar)

keep CLAUDE.md, .cursor/rules and friends in step

scope per file, or verify anything

Agent memory services

remember across sessions, served over MCP

separate a decision from a passing remark, or require a human to ratify either

Injection proxies

put context into the model request

leave an auditable record of what governs what

Those all answer storage and distribution. PactAI is built for the part none of them touch: does the code still honor the decisions? Keeping a record of a decision is easy. Knowing whether it is still true is the hard part, and it is the only part worth building a company around.

Two consequences fall out of that:

  • Nothing an agent writes becomes canonical on its own. Knowledge is extracted from versioned prose, cited back to the sentence it came from, and stays provisional until a human ratifies it. The database refuses otherwise — it is a foreign key, not a policy.

  • We never receive your source. Reconciliation runs inside your own agent session; what comes back is a verdict and a path:line.

Being straight about maturity: reconciliation is the point of PactAI and it is not built yet — it is phase 3. Today the repository has the schema, the tenancy boundary, the API and the CLI. If you need something that works this afternoon, one of the tools above will serve you better, and we would rather say so than waste your evening.

Status

Phase 0 is complete — monorepo, core schema with row-level security, CRUD, auth, the generated SDK, the CLI, and an MCP server with three tools. Phase 1 is under way: the extraction schema and the evaluation harness have shipped, the queue and the pipeline have not. There is still no intelligence in the system — nothing in this repository calls a model.

The design set under docs/ is written in full: docs/03 through docs/15 are settled designs, not stubs. Almost none of it is built. Every one carries a status banner — settled, designed, not implemented, or planned — and names the files that hold whatever part exists today. Read the banner before inferring anything from the prose.

Stack

TypeScript on Node 26, pnpm and Turborepo. Hono with @hono/zod-openapi, where Zod schemas are the single source that generates the OpenAPI spec, the typed client and the CLI. Postgres 16. Row-level security lands in the first migration, not later.

The rest of the stack is settled and not yet running: pgvector's HNSW index, tsvector and pg_trgm for retrieval, and pg-boss for the queue with transactional enqueue. Phase 0 installed the vector and pg_trgm extensions and created no index that uses either — they ship early because adding one later needs a superuser on a live database. Phase 1a added atoms.embedding vector(1024), deliberately without an index: HNSW parameters are chosen against a real vector distribution, and phase 1 only writes vectors. There is still no tsvector anywhere, and packages/worker is one line of export {}.

Getting started

nvm use              # Node 26, per .nvmrc
pnpm install         # also installs the git hooks
pnpm test            # green with no database — integration tests self-skip
pnpm lint
pnpm exec tsc -b

For anything touching the database:

docker run --rm -d -p 5432:5432 -e POSTGRES_PASSWORD=pact \
  --name pact-db pgvector/pgvector:pg16
cp .env.example .env
pnpm db:migrate

# Two steps, not one. `db:migrate` creates the `pgboss` schema and the grants
# on it; pg-boss installs its own tables inside it. Vendoring its generated
# DDL into a migration would give this repository a second version ledger that
# can disagree with the one pg-boss already keeps.
pnpm db:queue:install

# The API refuses to start on a superuser or BYPASSRLS connection: such a role
# makes every tenant policy silently inactive while the application looks
# perfectly healthy. Create a restricted role once.
psql "$DIRECT_URL" -c "CREATE ROLE pact_api LOGIN PASSWORD 'pact_api' NOBYPASSRLS" \
                   -c "GRANT pact_app TO pact_api"

pnpm --filter @pactai/db run bootstrap "My org" "My name"
pnpm start                      # DATABASE_URL must be the pact_api role

Migrations, db:queue:install and bootstrap run as the owner (DIRECT_URL); only the API uses the restricted role.

The last command creates an org, a human actor and an API key, printing the key once — only its SHA-256 is stored. It is ops tooling rather than an endpoint on purpose: an unauthenticated route that mints the first credential is an unauthenticated route that mints credentials.

pactai login --key pact_sk_… --url http://localhost:8080
pactai project create "My project"
pactai doc push docs/*.md --project <id>
pactai export ./my-knowledge     # full Markdown, yours to keep

The binary is pactai, not pact, because pact already belongs to Pact's contract-testing CLI — @pact-foundation/pact-cli took 154k npm downloads in the week ending 2026-08-04. Claiming the name would silently replace a tool someone is already using. If you do not use Pact and want the shorter name, that is your call to make locally:

alias pact=pactai

Connecting a coding agent

The MCP server exposes the three tools that exist in phase 0 — read, propose and status. context, search and reconcile are specified in docs/08-mcp-server.md and are not stubbed out: a tool that returns nothing teaches an agent not to call it again.

{
  "mcpServers": {
    "pactai": {
      "command": "pactai-mcp",
      "env": {
        "PACTAI_API_KEY": "pact_sk_…",
        "PACTAI_BASE_URL": "http://localhost:8080"
      }
    }
  }
}

An agent can propose knowledge; it cannot ratify it. There is no ratify tool, and the composite foreign key behind it means the database would refuse even if there were.

Layout

Package

Contents

packages/core

pure domain logic, no I/O, no runtime dependencies

packages/db

schema, reversible migrations, row-level security

packages/api

HTTP API; Zod schemas generate everything downstream

packages/worker

pg-boss consumers — phase 1; empty today

packages/sdk

typed client generated from the committed OpenAPI artifact

packages/cli

the pactai binary

packages/mcp

MCP server — three tools today, six specified; ten is a budget, not a start

infra/openapi/openapi.json is committed on purpose. CI regenerates it and fails on a diff, so a breaking API change shows up in review rather than at someone's integration.

License

Deliberately split, one repository, two halves:

  • AGPL-3.0-onlyapi, core, db, worker. Running a modified PactAI as a network service obliges you to publish the modifications.

  • Apache-2.0cli, mcp, sdk. These run on your own machine and are integration surface; integration surface with a copyleft obligation attached does not get integrated.

See NOTICE.

Maintenance

ActivityMaintained
ResponsivenessSyncing

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/hexablob/pact.ai'

If you have feedback or need assistance with the MCP directory API, please join our Discord server