Celmis MCP server
Commit Nov 11, 2026Provides self-hosted code intelligence for cross-repository Q&A, dependency audits, and automated pull request reviews via MCP.
Also known as Celmis-labs/Celmis
- Stars
- 3
- Tools
- —
- Downloads, 30 days
- —
- Latest version
- 0.1.30
- Last commit
- Nov 11, 2026
- License
- AGPL-3.0
What is Celmis MCP?
Celmis provides self-hosted code intelligence for cross-repository Q&A, dependency audits, and automated pull request reviews via MCP.
Summary generated from the project's README
About Celmis MCP server
Celmis provides a self-hosted platform for engineering teams to manage code intelligence without code ever leaving their network. It indexes repositories into a symbol graph to enable cross-repository analysis, allowing users to ask questions that span multiple projects with precise file and line citations. The system is designed for teams that need to understand undocumented code, perform dependency audits, and conduct pull request reviews that account for changes affecting other repositories.
Developers can interact with the index through 51 MCP tools, which work with clients like Claude Code, Cursor, or Codex. Setup involves a Docker Compose deployment on a local server with approximately 4 GB of RAM, after which a model provider key is added via the settings. The platform supports various languages including Python, TypeScript, JavaScript, Go, and Java. It distinguishes itself by identifying how changes in one repository might break consumers in another through contract-based links like HTTP routes and imported modules.
What you can do with it
- 1Impact-aware pull request reviewsReview a pull request to identify which other repositories will be affected by a change to a shared route or function.
- 2Automated dependency security auditingGenerate a CycloneDX SBOM and an evidence pack to satisfy third-party security requirements.
- 3Automated vulnerability remediationUse an embedded session to fix a dependency finding and automatically open a pull request.
Written from the project's README. Every use case is checked against a quote from it.
How to install Celmis MCP
Formats verified 10 Nov 2026Add to CursorAdd to GooseInstall Celmis MCP in Claude Code
$ claude mcp add celmis -- docker run -i --rm ghcr.io/celmis-labs/celmis-api:v0.1.30Install Celmis MCP in Cursor
~/.cursor/mcp.json
{
"mcpServers": {
"celmis": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"ghcr.io/celmis-labs/celmis-api:v0.1.30"
]
}
}
}Install Celmis MCP in VS Code
.vscode/mcp.json
{
"servers": {
"celmis": {
"type": "stdio",
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"ghcr.io/celmis-labs/celmis-api:v0.1.30"
]
}
}
}Install Celmis MCP in VS Code CLI
$ code --add-mcp '{"name":"celmis","type":"stdio","command":"docker","args":["run","-i","--rm","ghcr.io/celmis-labs/celmis-api:v0.1.30"]}'Install Celmis MCP in Claude Desktop
claude_desktop_config.json
{
"mcpServers": {
"celmis": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"ghcr.io/celmis-labs/celmis-api:v0.1.30"
]
}
}
}Install Celmis MCP in Codex
$ codex mcp add celmis -- docker run -i --rm ghcr.io/celmis-labs/celmis-api:v0.1.30Install Celmis MCP in Codex config.toml
~/.codex/config.toml
[mcp_servers.celmis] command = "docker" args = ["run", "-i", "--rm", "ghcr.io/celmis-labs/celmis-api:v0.1.30"]
Install Celmis MCP in Gemini CLI
$ gemini mcp add -s user celmis docker -- run -i --rm ghcr.io/celmis-labs/celmis-api:v0.1.30Install Celmis MCP in Gemini settings.json
~/.gemini/settings.json
{
"mcpServers": {
"celmis": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"ghcr.io/celmis-labs/celmis-api:v0.1.30"
]
}
}
}Automated checks
Ran Nov 13, 2026Full report →Not verified yet. A server needs a score of 80, no serious finding, and enough data for us to check. How checks work · What to fix for more points
- Source repository linked and reachablecelmis-labs/celmis is public and reachablegithub.com/celmis-labs/celmis ↗Pass
- Package names this repository as its sourceNot checked
- Build provenance (Sigstore attestation)Not checked
- Open source license (OSI)AGPL-3.0spdx.org/licenses/AGPL-3.0.html ↗Pass
- Commit or release in the last yearLast commit or release 2026-11-11github.com/celmis-labs/celmis ↗Pass
- OpenSSF ScorecardNot checked
- Package name not close to a popular packageNot checked
- No critical advisory in the package or its dependenciesNot checked
- No hidden instructions to the model0 tool descriptions and the README read; no override phrases, credential paths or hidden charactersPass
- Destructive tools are labelledNot checked
- Remote endpoint answers the MCP handshakeNot checked
README
View on GitHubCelmis
Understand, review, secure and fix your code, in one self-hosted place. One machine. Your model, your network. The code never leaves the company.
Website · Documentation · Quick start · What's new · Results

Celmis puts everything an engineering team needs to work with its code in one place. It indexes all of your repositories once, into a symbol graph built without a model, and every tool reads that same index:
- understand code nobody documented: questions across repositories answered with
file:linecitations, in the app or from a coding agent (Claude Code, Cursor, Codex) over MCP, plus the team's own skills and checklists for the task at hand; - review pull requests with what the change touches beyond its own repository;
- secure the dependencies: CVE audit, a CycloneDX SBOM and an evidence pack a third party can verify;
- fix what an alert or a finding points at: an embedded Claude Code session on your subscription edits the code and the runner opens a pull request (220 seconds on one measured finding). A person reviews and merges; Celmis never merges or deploys.
It is built for the team that ships the code and answers for it in production. Instead of a separate tool for each of those jobs, each with its own access rules and its own copy of your code, one installation holds them all. The aim is a small team that can run several products and the integrations between them.
What "beyond its own repository" means today. Indexing records what each repository
exposes and uses: the HTTP routes it serves and calls, the packages it publishes and
imports (Python, TypeScript and JavaScript, Go, Java). When a pull request removes a
route or a function, removes a parameter or makes one required, or changes a route's
method or path, the review names every consumer in the workspace's other repositories,
with file and line. A link is strong when the called host or the imported module maps to
the repository that defines it, and only strong links raise severity; a repository
without these facts is reported as not checked, never as safe. The review also flags
values the change removes that other repositories still hardcode, and deploy files that
point at the changed repository. These are links through contracts, not every function
call: questions and the MCP refs tool still search other repositories by text, and say
so.
What it does
| Ask the code | Questions across several repositories, answered with file:line citations on both sides of a call. Ask the code |
| Codebase and MCP | 51 tools over MCP, a compact /mcp/dev profile for editors, a Claude Code plugin, and versioned knowledge packs of the skills your team already explains out loud. MCP · Packs |
| Pull-request review | Agents read the diff and name the other repositories that call a changed route or function, with file and line. Talk to it with @celmis, teach it with remember, and it stays quiet when there is nothing to say. Review |
| Evidence | Dependency audit, CycloneDX SBOM and an evidence pack whose manifest a third party recomputes. SBOM and evidence |
| Fix from here | An alert or a dependency finding becomes an embedded session, then a branch, then a pull request. A human reviews and merges; Celmis never merges. Fix from here · Alerts |
| Access you can defend | Repositories are closed by default, MCP tokens are issued per person, every call is audited, secrets are withheld at the source, and a repository can be shared with another workspace for a fixed time. Who can see what · Sharing |
Install
git clone https://github.com/Celmis-labs/Celmis.git celmis && cd celmis
./scripts/init-env.sh # writes .env and fills every secret
docker compose --env-file .env up -d
Then open http://localhost and paste one model provider key under Settings → LLM Setup.
197 seconds from clone to six healthy services on a clean server. Postgres and Qdrant are bundled; about 4 GB of RAM. Details in Quick start. An installation without a licence admits up to five people; see Licensing.
What's new in v3
- Review that earns its comments. Findings below your comment level never reach the pull request; a review with nothing to say approves. Comments are the problem, the reason and the fix, in the repository's language (3.1).
- A reviewer you can talk to.
@celmiscommands and questions in the thread,rememberrules, learning from what the team dismisses, incremental review of each push, Jira acceptance criteria checked in the summary (2.3). - Knowledge packs. Versioned skills, API examples and checklists per workspace, readable in the app and by coding assistants through
briefandskills;celmis-packpublishes them (3.0). - Access closed by default. A repository nobody has a rule for is invisible; MCP tokens belong to a person; every call is audited (2.3.7). Stricter secret hiding in 3.0.2.
- Sharing between workspaces. For research, for a fixed time, with hidden paths and a ceiling on readers (3.1).
- A developer MCP profile and a Claude Code plugin sized for an editor (2.3.7).
Every release is in the changelog.
Logs, and where the line falls
Celmis does not watch your services; Grafana or whatever you already run does that. The application ingests no logs of its own and starts from the alert. The repository ships an optional observability overlay (Prometheus, Loki, Promtail, Grafana) that does collect them, platform-wide rather than Celmis-only:
docker compose -f docker-compose.yml -f docker-compose.observability.yml up -d
Every port binds to 127.0.0.1 and is reached over an SSH tunnel, because Loki has no
authentication. GRAFANA_ADMIN_PASSWORD is required.
What that buys you that a diff-only tool cannot
Ask a question that spans two repositories, and the answer quotes both, as in the screenshot at the top of this page. That is not a search result. The gateway and the payments service are separate repositories with no shared code, and the answer traces the call chain between them — then notices, unprompted, that the Kafka topic name is hardcoded in both and that changing one silently breaks the other.
A reviewer that reads only the diff structurally cannot say that. It never had the other repository open.
Nine things people do with it
| You are a PM, a delivery lead or the client and want to know what state a group of projects is in, or how something actually works | Ask it. From any device, anywhere, without booking time from an engineer and without a meeting whose only output is a paragraph → Ask the code |
| A new engineer has a question a senior would have to answer | Every one of those pulls someone experienced out of flow, at the moment they are already covering. The codebase answers instead, with file:line citations → Ask the code |
| Two teams share an integration and neither can read the other's repository | Load it, grant the right to ask, and deny the paths that must stay private. They get answers; the credentials are refused at the source → Who can see what |
| A customer or an auditor asks for your SBOM | One button, CycloneDX, plus an evidence pack whose manifest they recompute themselves — against a hash you publish where the pack is not → Dependencies, SBOM and the evidence pack |
| A vulnerability lands in a dependency | Fix from here hands an embedded session the repository, the package and the finding. It edits, the runner pushes a branch and opens a PR → Fix from here |
| A pull request needs reviewing | Agents read the diff — and, where the graph is built, who else calls what is being changed, including from another repository → Pull-request review |
| Forty services need the same thing done to them | Write the sentence. Celmis shows which repositories it resolves to and waits for a second press, rather than finding them among forty and pressing a button forty times → Ask for work across repositories |
| An alert fires at 02:00 and you are not at a desk | It lands in Celmis and goes out to the workspace's chat channel, and Fix from here opens a session already holding the alert. The runner opens the pull request → Alerts, and fixing from a phone |
| Your own agent or editor needs to understand the codebase | Point it at /mcp/. Fifty-one tools over the same index, thirty-five of them read-only, under the same access rules — no second copy of your code anywhere → Connect Claude Code and other MCP clients |
The first three are the ones a code-review tool does not do at all, and they are the reason this is a platform rather than a reviewer: index once, then read that index from whichever side of the work you are standing on.
Three numbers
| 197 seconds | from git clone to six healthy services, measured on a clean server |
| $0.118 | per pull request reviewed, on the model this ships with |
| 17th of 50 | on the Martian Code Review Bench offline set, under all three judges |
That last one is deliberately unflattering, and it stays. It measures one of the surfaces below — pull-request review on isolated single-repository PRs — and that set has no sibling service for a symbol to have consumers in, so the thing this product is built around is not in the number at all. The table, the audit of every finding it scored false, and the command that reproduces both are in Results.
Table of contents
- What it does
- What's new in v3
- What that buys you that a diff-only tool cannot
- Nine things people do with it
- Three numbers
- Quick start
- First user and admin
- Connect a repository
- Ask the code
- Pull-request review
- Dependencies, SBOM and the evidence pack
- Fix from here
- Alerts, and fixing from a phone
- Ask for work across repositories
- Who can see what
- Languages and formats
- Deterministic checks — no model, no false positives
- Connect Claude Code and other MCP clients
- Results
- Audit of the false positives
- Test repositories
- Configuration
- Operations
- Local development
- CLI reference
- Architecture
- Troubleshooting
- Project layout
- Provenance and rights
Quick start
What you need
| Docker | 24+ with Compose v2 | Docker Desktop on macOS/Windows, the native engine on Linux |
| A model API key | one of | Google Gemini, Anthropic, OpenAI, OpenRouter, Groq or Mistral. A free Gemini key is enough to evaluate: https://aistudio.google.com/app/apikey |
| RAM | ~4 GB free | Measured on a real indexing run: 1.1 GB peak across all five containers, 565 MB at rest |
Postgres and Qdrant are bundled — no external cluster to provision. No Python or Node.js install is needed for the Docker flow.
Start it
git clone https://github.com/Celmis-labs/Celmis.git celmis
cd celmis
# Generates .env and fills every secret in the format each one needs.
# Idempotent: run it again after a pull and it fills only the new blanks.
./scripts/init-env.sh
docker compose --env-file .env up -d
# Wait for healthy — first boot pulls three images and applies migrations
docker compose ps
Open http://localhost.
Nothing is built here. The three images are pulled from the registry named by
CELMIS_REGISTRY at the tag in CELMIS_TAG, for linux/amd64 and
linux/arm64 — Apple Silicon and an ARM server both get a native image.
Building them on the machine that runs them was measured at 485 seconds and
4.2GB of disk for api alone, which is why installing no longer means
compiling.
Port 80, not 3000: a reverse proxy puts the app and its API on one origin and
serves the API under /backend. That is not a deployment preference — the
browser bundle asks for a relative path, which is the only way one published
image can serve every installation instead of just the one it was built on.
To work ON Celmis rather than run it, add the dev overlay and you get local builds back:
docker compose -f docker-compose.yml -f docker-compose.dev.yml up -d --build
init-env.sh --check reports what is still empty without writing anything.
That is a render of the captured session, not a screen recording — the
figures in it are the ones the run produced on 26 August 2026, and the compose
output is verbatim from logs/03-up.log in the install report. It is drawn
rather than photographed because a second stack cannot be brought up beside a
running one: docker-compose.yml fixes container_name, so the names collide.
Stop
docker compose down # stop, keep your data
docker compose down -v # stop and DELETE every volume
First user and admin
The sign-up form on /login works as soon as the stack is healthy. That
account is a normal user — signing up grants no admin rights, not even to
the first person through the door.
Global admin comes from the environment instead: sign in with
CELMIS_MASTER_EMAIL and CELMIS_MASTER_KEY (as the password), both in
.env. Whoever runs the box is the admin, which is the model a self-hosted
install wants rather than whoever reached the form first. The path does not
exist unless both variables are set, and every use of it is written to the
audit log.
To promote a normal account:
docker compose exec api analyzer auth make-admin you@example.com
A promoted account (or one an OIDC_ADMIN_ROLE makes admin) is a global
admin: system status, ops, compliance, every workspace visible. It is not
the superadmin — that is the master account alone, and it is the only one
that can hand out the roles below that carry power.
Workspace roles
Every workspace is a tenant, and a person can hold a different role in each — admin of one, editor of two others.
| Role | Can do in that workspace |
|---|---|
viewer |
read |
member |
read; change a review issue's status |
editor |
the prompt editor: agent system prompts, per-repo review policies (prompt template, folder rules, per-agent prompt overrides), analytics. No members, invites, teams, LLM keys, git connections or licence |
admin |
editor's rights, plus members and viewers, invites, teams, LLM keys, git connections |
owner |
admin's rights, plus deleting the workspace |
Who may grant what:
- owner, admin, editor — the superadmin only: granting, changing to or from, removing. A workspace admin cannot demote the owner or another admin.
- member, viewer — the superadmin, or that workspace's owner/admin (directly or by invite; an invite carries only a role its creator could grant, re-checked when it is accepted). An existing account is added directly only if you already share a workspace with it; anyone else receives an invitation they have to accept.
- Password-reset links a workspace admin mints are bounded by every workspace the person belongs to, not just this one. In multi-tenant mode everyone owns a personal workspace, so in practice only the superadmin can mint one. No route mints one for the master account.
- Shared workspaces are created by the superadmin. Everybody gets a personal workspace of their own at sign-up and is its owner.
The superadmin manages people across workspaces on Administration →
Users (/admin/users); every membership change, from any page, is written
to the audit log with the actor, the person, the workspace and the old and
new role. Its No team access filter lists the accounts whose only
workspace is their personal one — whatever way they sign in — newest first.
Getting in: invites and access requests
An invite for somebody without an account. Inviting an email address
that has no account creates an email-bound, single-use link. The inviter sees
it (copy it from the Team page); when SMTP is configured it is also emailed.
Opened signed out, /invite/<token> shows the workspace, the role and who
sent it, and offers sign-in, sign-up (when AUTH_PASSWORD_LOGIN allows it),
Google and company SSO (when enabled); each comes back to the link to accept.
Accepting re-checks that the inviter may still grant that role, is audited,
and uses the link up. An expired, revoked or used link says which; an
email-bound link opened by another account is refused.
Automatic redemption — verified addresses only. When somebody signs in
with Google or company SSO and the identity provider marks the email as
verified (email_verified) — or, for SSO, the operator vouches for it with
OIDC_TRUSTED_EMAIL_DOMAINS / OIDC_REQUIRE_VERIFIED_EMAIL=false — the
pending invites addressed to that email are
redeemed at sign-in, through the same accept path (grant rule re-checked,
audited, single use). A password account is never redeemed by its
address: Celmis does not verify the address typed at sign-up, so anyone can
register somebody else's email. A password account opens the link it was
sent, and accepts there — and so does an account that has a password and
Google/SSO linked to it, since whoever set that password can still sign in.
The automatic path only ever adds somebody: an invite for a workspace the
person is already in is used up without touching their role, and removing a
member revokes the live invites addressed to them for that workspace.
Access requests. A signed-in person whose only workspace is their
personal one sees "You have no access to team workspaces yet — send a
request" on the dashboard and at /access-request, with an optional comment
(up to 1000 characters). One pending request at a time; it can be cancelled,
and a new one sent after a rejection. The request names no workspace, and the
requester is shown none until it is approved. The superadmin only decides,
on Administration → Access requests (/admin/access-requests): approve
with one or more (workspace, role) pairs — applied all or nothing, each
membership audited with via="access_request" — or reject with a reason the
requester reads. Access given another way (the Users page, an accepted
invite) closes a pending request as approved. Decided requests stay listed as
history. The requester sees
the decision on /access-request and as a toast on their next visit, and an
approved workspace appears in the switcher without signing out. With SMTP
configured the requester is also emailed the decision, and the master address
a new request; there is no other notification channel.
POST /api/access-requests {comment?} |
ask (409 if one is pending, or the account already has team access) |
GET /api/access-requests/me |
eligibility and the latest request |
DELETE /api/access-requests/me |
cancel the pending one |
GET /api/admin/access-requests?status= |
superadmin: list, pending first |
POST /api/admin/access-requests/{id}/approve {grants:[{workspace_id, role}]} |
superadmin: one or more, unique, existing, not personal workspaces |
POST /api/admin/access-requests/{id}/reject {reason} |
superadmin: reason required |
Deciding a request that is no longer pending answers 409.
Connect a repository
- Settings → LLM Setup — paste a provider key. It is encrypted with
CREDENTIAL_MASTER_KEYbefore it touches the database, and the UI only ever shows you the first and last four characters again. - Connections — add a GitHub, GitLab or Bitbucket token. Use a machine account, not your own: a personal token reaches every repository you can see, and tokens end up in backups, logs and screenshots.
- Repositories → Add — pick repositories from the provider, or paste a clone URL. Indexing is queued; the job shows on the same page.
Indexing builds two things from the same checkout: a symbol graph (definitions, calls, imports — what the review agents reason over) and embeddings in Qdrant (what Q&A retrieves). A 120k-symbol repository takes about a minute on four cores.
Twenty-four languages parse into the graph, 1C:Enterprise among them. A file in a language without a
parser is said so out loud rather than silently skipped — analyzer graph-stats
lists what was and was not read.
Ask the code
A question in a chat, answered with file:line citations from as many repositories as you point it at. Answers stream as they are written.
Group repositories into a project, and the question is asked of the group:

Answers quote real code, and only the code the asker is allowed to see — which is what makes it safe to hand the question to someone outside the team that owns the repository. See Who can see what.
Pull-request review
Agents read the diff and post findings to GitHub, GitLab or Bitbucket. Rather than show that in a screenshot of this interface, the reviews are left where they were posted — fifty pull requests on real projects, with the comments still attached to the lines they were written about. They are listed under Test repositories, and the output there is unedited, including the findings the audit below marks wrong.
Where the graph is built, the review also carries what the diff does not show: who else calls the symbol being changed, including from another repository. Where it is not built, the review still runs — it just answers the narrower question, which is what the benchmark measured.
Celmis MCP questions
How do I add Celmis MCP to Claude Code?
Run claude mcp add celmis -- docker run -i --rm ghcr.io/celmis-labs/celmis-api:v0.1.30 in your terminal. Add --scope user to make it available in every project.
How do I add Celmis MCP to Cursor?
Open ~/.cursor/mcp.json and add the server under mcpServers, using the Cursor config shown in the install section above.
Does my code leave my company?
No, Celmis is a self-hosted solution where your model and network are your own, ensuring code never leaves the company.
What programming languages are supported?
Celmis indexes and parses Python, TypeScript, JavaScript, Go, and Java.
How does Celmis handle pull request reviews?
Agents read the diff and identify other repositories that call a changed route or function, providing file and line citations.
Can I use Celmis with Claude Code?
Yes, it includes a Claude Code plugin and a compact MCP profile for editors.