# Projects

> The unit everything else belongs to — how to create a project, control MCP access, read its statuses, and re-index or delete it.

- Updated: 2026-09-21
- Source: https://contextator.com/en/docs/projects/
- Language: en-US
- Author: Muhammet Şafak

---
A **project** is the unit of everything in Contextator: it owns its documents, its embeddings, its
index history and exactly one MCP endpoint. A client connected to one project can never see another's
documents.

Make a project per body of knowledge your agents ask questions about — usually per product, per team,
or per customer.

## Creating one

**New project** (or press `n`) in the dashboard.

| Field | Rules |
|-------|-------|
| **Project name** | Lowercase letters, digits, `-` and `_`, starting with a letter or digit, up to 63 characters. Must be unique |
| **Documentation directory** | Optional. A folder inside an allowed root (`/docs/...`), which becomes the project's first source |
| **Index now** | Queues a first index run immediately |

The name becomes the URL, so pick something you will be happy pasting into agent configurations:

```
http://localhost:3444/mcp/<project-name>
```

> **Choose the name carefully.** Renaming a project would break every client already configured with
> the old URL, so treat it as permanent. To rename in practice: create a new project, add the same
> sources, and update your clients.

Creating a project without a directory is perfectly normal — add git repositories, uploads or Notion
afterwards with **Add source**.

> **New project** appears only for `root` and `admin` accounts, and so does **Delete** — a new
> `/mcp/<name>` surface is an instance-level decision. A `member` account works inside the projects it
> was added to under **Members**; see [Accounts and Permissions](/en/docs/accounts-and-permissions/).

## What a project contains

```
project "handbook"
├── source "policies"   (local directory)   → policies/onboarding.md
├── source "api"        (git repository)    → api/reference/auth.md
└── source "notion"     (Notion workspace)  → notion/Engineering/Runbooks.md
```

Every document path begins with the name of the source it came from. That is what lets two sources both
contain `README.md`, and it is how an agent's answer tells you where it came from. See
[Document Sources](/en/docs/document-sources/).

## MCP access

A new project's endpoint is **token required** by default: creating it mints its first token and shows
the secret once, in the creation dialog, so the endpoint is closed from its first second. Before this
was the default, a new project was **open** — answering anyone who could reach its URL, with no account
and no token — and upgrading does not retroactively change the mode of a project that already existed.
The **MCP access** panel on the project page is where the mode changes, either way:

| Mode | What it means |
|------|---------------|
| **open** | Any client that can reach `http://localhost:3444/mcp/<project-name>` can search and read the project |
| **token required** | Only a client sending `Authorization: Bearer ctxm_…` is answered; everything else gets `401` |
| **account required** | Only a client acting as an account that is a **member** of this project is answered, checked on every request |

The three narrow in that order, and what they narrow is the caller who names nobody — an anonymous
request, or a static `ctxm_…` token. A credential that *does* name an account is checked against that
account's membership on every request in **every** mode, **open** included: a non-member is answered
`403` whatever the mode says, and removing a membership or disabling an account cuts the connection off
on its next call. A client gets such a credential through OAuth 2.1, which is what browser-based MCP
connectors already speak. **account required** is simply the mode that leaves no anonymous way in, which
is why a static token is refused there.

Changing the mode needs `manager` rights over the project — in practice a
`root` or `admin` account. Minting and revoking tokens is an editor's; anyone who can see the project
sees the list of its tokens by name. Who is which:
[Accounts and Permissions](/en/docs/accounts-and-permissions/).

**New token** shows the secret **exactly once**, at the moment it is created. The server stores only a
hash of it, so a token that was not copied is replaced rather than recovered. Afterwards the list shows
only its name, its first few characters (`ctxm_9f3a…`) and when it was last used.

Switching a project to **token required** closes its open MCP sessions, and so does revoking a token —
immediately, rather than at the client's next request. A project that requires a token and has none is
unreachable, so mint the first token before you tell anyone the endpoint is ready.

One thing to be clear about: a token is a credential for that endpoint, not an account. It carries no
identity and no per-document rules, so whoever holds it reads everything indexed in the project. Give
each client its own token so one can be revoked without disturbing the rest. How a client sends it:
[Connecting AI Clients](/en/docs/connecting-ai-clients/).

## Statuses

| Status | Meaning |
|--------|---------|
| `idle` | Nothing running. The last run succeeded |
| `queued` | Waiting for the indexer, which handles one project at a time |
| `indexing` | Syncing, scanning or embedding right now |
| `error` | The last run failed, or one of the sources failed to sync. The reason is shown |

An `error` status caused by one source does not mean nothing worked: the other sources still indexed,
and the message reads like `2/3 sources synced; notion: <reason>`.

## Re-indexing

| | When to use it |
|---|---|
| **Re-index** | The normal case. Syncs every source and re-embeds only files whose contents changed |
| **Force re-index** | After changing chunk settings, or when you suspect the index is stale in a way hashing cannot see |

Contextator also forces a full re-index by itself when the embedding model changed — see
[Embedding Models](/en/docs/embedding-models/).

Details of what happens during a run: [Indexing](/en/docs/indexing/).

## Deleting

**Delete** (twice, to confirm) removes the project, its sources, documents, chunks and run history,
closes any open MCP sessions, and deletes the files it materialised under `DATA_DIR` (git checkouts,
uploads, Notion pulls).

Your own files are never touched: documentation mounted at `/docs` is read-only, and local directory
sources are scanned in place.

Deletion is refused while the project is indexing — wait for the run to finish.

## Several projects

The indexer processes **one project at a time**, because embedding is CPU-bound. A queued project shows
which project it is waiting for. There is no limit on how many projects a deployment can hold; each one
is just another URL.
