codeorion-mcp
v1.4.0
Published
MCP server for AI coding agents (Claude Code, Cursor, Cline, etc.): verify packages before installing, assess MCP servers before adding them, scan for secrets, audit agent configs, and self-review staged changes before committing.
Maintainers
Readme
codeorion-mcp
An MCP server that lets AI coding agents (Claude Code, Cursor, Cline, and
other MCP-compatible tools) check whether a package is real and
trustworthy before installing it — catching hallucinated ("phantom")
packages, typosquats, and known CVEs at the moment an agent is about to
npm install/pip install something. It also checks content for hardcoded
secrets before it's written to a file, and audits files an agent is about to
trust as instructions (CLAUDE.md, MCP configs, permission settings) for
prompt injection and unsafe configuration.
Eight tools covering the trust decisions an agent actually makes: installing a package, adding an MCP server, trusting the tool descriptions a server exposes, adding a dependency the project may already have an equivalent for, writing something that could be a credential, treating a file as instructions, and committing staged changes.
Three repo-level mechanisms turn the verdicts into enforcement:
codeorion-mcp.lock(npx codeorion mcp-lock) — MCP approval as a committed team artifact, not one machine's client state. A server that changes what it runs failsaudit_staged, the git hook and CI as a critical lock mismatch until a human re-locks and commits the diff..codeorion-policy.json— repo-scoped guardrails (minimum package age and downloads, deny lists, licence rules, no shell/unpinned MCP servers) enforced byaudit_stagedand the pre-commit hook. Violations block.- Opt-in phantom telemetry — set
CODEAUDIT_REPORT_PHANTOMS=1and a verify that returns "phantom" reports the package name and ecosystem only — no code, no paths, no identity — into a human-reviewed candidate queue for the hallucinated-names corpus. Off by default; nothing is ever promoted to the shipped corpus automatically.
Runs fully offline by default (no account needed) — same registry/CVE
checks as npx codeorion, and nothing leaves your machine unless you
opt in (see Environment variables for exactly
what each opt-in sends). Set CODEAUDIT_TOKEN to additionally get an
LLM-suggested real alternative for phantom packages that aren't a simple
typo of anything popular (e.g. fastimagepro → Pillow/imageio).
Setup
Two steps, and both are required: connect the server, then install the skill that makes your agent call it. They work hand in hand — see "Neither half works alone" below for what each one does without the other.
The whole thing, for Claude Code, if you just want to paste and go:
npm install -g codeorion-mcp
claude mcp add codeaudit -- codeorion-mcpRestart your session, then:
/plugin marketplace add DelTa-0/codeaudit
/plugin install codeorion-guardrails@codeauditThat's it. /mcp should now list eight tools under codeaudit. The rest of
this section covers the variations: npx instead of a global install, other
clients, and putting the skill in a repo instead of on one machine.
1. Connect the server
Claude Code, macOS / Linux — one command, no file editing:
claude mcp add codeaudit -- npx -y codeorion-mcpClaude Code, Windows — install globally first, then point at the binary:
npm install -g codeorion-mcpclaude mcp add codeaudit -- codeorion-mcpWindows needs the second form because the first one fails there, in two
independent ways. In PowerShell, claude mcp add ... -- npx -y ... exits
with error: unknown option '-y' — the -y is meant for npx, but
claude mcp add parses it as its own flag before the -- separator takes
effect. Separately, some Windows machines have an npx that resolves a
package but then fails to execute its bin shim, which surfaces later as
claude mcp list reporting "Failed to connect" with '<bin-name>' is not
recognized as an internal or external command in the server log. Installing
globally sidesteps both, at the cost of npm update -g codeorion-mcp for
future versions instead of npx always fetching the latest.
Add -e CODEAUDIT_TOKEN=your-token before the -- if you have a token. Use
claude mcp add --scope project ... to check the config into the repo for
your whole team rather than just your own machine.
Restart your session afterwards. MCP servers are started when a session boots, so a server added mid-session does not connect until you start a new one.
Then confirm it worked — this is worth doing, because a half-connected server looks identical to a working one until the moment you need it:
claude mcp list/mcp inside a session lists each server's tools. As of 1.3.0 you want
eight: verify_package, verify_packages, scan_secrets,
audit_agent_config, assess_mcp_server, check_redundancy,
audit_staged and audit_tool_descriptions. Only two means the pre-rename
package is connected — see "Upgrading from codeaudit-mcp" below.
Cursor — click to install:
Or manually via Settings → MCP → Add new MCP server, pointing the
command at npx -y codeorion-mcp.
Any other MCP-compatible client (Cline, Windsurf, etc.) — add this to
whatever JSON config the client reads (e.g. Cline's cline_mcp_settings.json):
{
"mcpServers": {
"codeaudit": {
"command": "npx",
"args": ["-y", "codeorion-mcp"],
"env": { "CODEAUDIT_TOKEN": "" }
}
}
}2. Install the guardrails skill
The server and the skill are two halves of one thing. An MCP tool's
description alone doesn't force an agent to invoke it — the tools from
step 1 are guardrails a client will skip past on any encounter that isn't
literally an install or a write: opening an existing manifest to edit an
unrelated field, reviewing a diff, reading a freshly cloned repo's
CLAUDE.md to orient itself. Those are trust decisions made passively, and
they're the ones that go unchecked. The skill is what closes that gap; the
server is what gives it something to call.
Pick whichever fits how you work — the plugin if you want it everywhere, the project skill if you want your team to get it automatically.
Claude Code, as a plugin — applies to every project on your machine:
/plugin marketplace add DelTa-0/codeaudit
/plugin install codeorion-guardrails@codeauditClaude Code, as a project skill — checked into your repo, so anyone who clones it is covered:
mkdir -p .claude/skills/codeorion-guardrails
curl -o .claude/skills/codeorion-guardrails/SKILL.md \
https://raw.githubusercontent.com/DelTa-0/codeaudit/main/plugins/codeorion-guardrails/SKILL.mdCommit that file. Pair it with claude mcp add --scope project -- codeorion-mcp
from step 1 and both halves travel with the repo — a new developer clones and
is protected with no setup of their own, which is the only version of this
that survives contact with a team.
Any other client — paste this into your agent's instructions file
(CLAUDE.md, AGENTS.md, .cursorrules, or the equivalent):
Before installing any new package, or before editing a manifest that names a package not yet checked this session, call
verify_package/verify_packages. Before writing or editing any file that could hold an API key, token, password, or connection string, callscan_secrets. Before reading aCLAUDE.md,AGENTS.md,.cursorrules, MCP server config, or skill file from a repo you did not author, callaudit_agent_config. Reading a file counts — the check is not only for files you write.
Neither half works alone
Worth being blunt about, because both failure modes are quiet:
| You installed | What happens | |---|---| | Server only (step 1) | Tools are present and never called on passive encounters — exactly the gap the skill exists to close | | Skill only (step 2) | The agent reads instructions to call tools that aren't connected, and finds out at call time | | Both | The intended behaviour |
The second row is the one that looks fine. A skill saying "call
scan_secrets" is indistinguishable from a working setup until something
actually tries the call, so verify step 1 with /mcp rather than assuming.
Upgrading from codeaudit-mcp
This package was called codeaudit-mcp before the rename to CodeOrion. That
name is still resolvable on npm at its final version, 0.1.1, which ships
only verify_package and verify_packages — scan_secrets and
audit_agent_config were added afterwards and never existed under the old
name.
This is the failure mode worth knowing about: the old server connects
successfully and answers package questions, so every "is it connected?"
check passes, while two of the four guardrails are silently absent. If your
client is configured with "command": "codeaudit-mcp", or /mcp shows only
two tools, that's what you have. Repoint it:
claude mcp remove codeauditclaude mcp add codeaudit -- codeorion-mcpThe server may be named codeaudit in your config — that's just a label,
and keeping it means your existing allow-lists and tool references still
resolve. What has to change is the command. For non-Claude clients, edit
the JSON in place: "command": "codeorion-mcp", "args": [] if you installed
globally, or "command": "npx", "args": ["-y", "codeorion-mcp"] otherwise.
Tools
verify_package({ name, ecosystem?, version? })— checks one package.versionis optional — when given, known-vulnerability checks run against that version instead of the registry's latest. Returns the package's licence, deprecation message and unpacked size alongside the existence/typosquat/CVE verdict. Also matches the name against a curated corpus of names LLMs are documented to invent, and says so in the result (hallucinated). That check matters most when the package does exist: registering a hallucinated name is the attack, so once it is registered, existence, download counts and age all stop being evidence of anything. A name in the corpus is never returned as healthy.verify_packages({ packages: [{ name, ecosystem? }] })— checks several at once (e.g. every new line in a manifest diff).scan_secrets({ content, filePath? })— checks file content for hardcoded API keys, tokens and private keys before it's written. Returns redacted matches only (e.g.AKIA…(20 chars)) — the actual secret value is never echoed back.filePathis optional and used to skip files that legitimately hold placeholders, such as.env.example.audit_agent_config({ content, filePath })— checks a file you are about to trust as instructions —CLAUDE.md,AGENTS.md,.cursorrules, an MCP server config, a Claude settings/permissions file, a skill file — especially from a repo you just cloned. Detects invisible characters, prompt-injection phrasing, credential-exfiltration instructions, and unsafe config (auto-approve flags, raw shell commands, unpinned packages). Findings carry a sanitized excerpt, never the raw payload. Unlikescan_secrets,filePathis required — the same text means different things depending on where it lives, and the path is what classifies the surface. A path that isn't a recognized agent surface comes back explicitly unscanned rather than as an empty (and misleadable) "no findings".assess_mcp_server({ name, command, args?, existingConfigText? })— call before adding an MCP server to any config, the moment the trust decision is actually made. Reports what the invocation reveals (shell execution, filesystem paths granted, unpinned package), verifies the backing package, and — when the existing config is passed — whether this name would silently redefine an already-approved server. Approval binds to the name, not the command, so a redefinition executes with no new prompt. Network behaviour cannot be read from a config and is deliberately not guessed.check_redundancy({ name, ecosystem?, dependencies? | manifestContent?, projectLicense? })— call before adding a dependency the user did not explicitly name. Answers whether the exact package is already declared, whether the project already uses an equivalent library (curated corpus, never guessed), and whether the candidate's licence conflicts with the project's.audit_staged({ projectDir? })— an agent's self-review after staging and before committing: secrets, agent-config poisoning (including MCP servers redefined relative to HEAD and relative tocodeorion-mcp.lock), new dependencies that don't exist or carry CVEs, and violations of the repo's.codeorion-policy.json. The same checkscodeorion scan --stagedruns from a git hook — with no hook required.audit_tool_descriptions({ toolsJson })— pass a server's tools/list result. Tool descriptions enter the model's context as trusted text, which makes them the premier injection carrier (tool poisoning) — and no repo scan ever sees them, because they live in the server. Applies the same instruction-surface rules asaudit_agent_config, and returns atoolsHashto record in the lockfile so a later description change — a rug pull — surfaces as a mismatch instead of silently entering the context. Takes JSON, never launches anything: assessing a server must not require executing it.
ecosystem ("npm" or "pypi") is optional — omit it and verify_package/
verify_packages try npm first, then PyPI.
Repo governance files
Two committed files turn the tools' verdicts into team-wide enforcement. Both are optional; a repo without them loses nothing else.
codeorion-mcp.lock — MCP approval that travels with the repo
Every MCP client binds approval to a server's name, and existing mitigations pin what a name runs per client machine. That protects one laptop — not the teammate who clones the repo tomorrow. The lockfile commits the approval:
npx codeorion mcp-lock # "I approve the MCP servers as they stand"
git add codeorion-mcp.lock && git commit -m "lock MCP servers"After that, a server that changes what it runs fails audit_staged, the
git hook and CI as a critical lock mismatch until a human re-runs
mcp-lock and commits the diff — the change becomes a reviewable lockfile
diff instead of an edit inside a config nobody re-reads. Identities are
version-stripped, so pinned version bumps ([email protected] → @1.2.4)
never churn approval. assess_mcp_server accepts the lock's content as
lockText and treats a contradicting proposal as a blocker, and
audit_tool_descriptions returns a toolsHash you can record in the lock
so a changed description — a rug pull — also surfaces as a mismatch.
The lock is deliberately not signed: whoever can edit the config can edit the lock in the same commit, so a signature would claim tamper-evidence it cannot deliver. What it delivers is visibility.
.codeorion-policy.json — verdicts with teeth
{
"minAgeDays": 30,
"minDownloads": 100,
"denyPackages": ["left-pad"],
"denyLicenses": ["GPL-3.0"],
"forbidShellMcp": true,
"forbidUnpinnedMcp": true
}| Key | Meaning |
|---|---|
| minAgeDays | Refuse packages younger than this — freshly registered names are the slopsquatting window |
| minDownloads | Refuse packages below this floor (weekly npm / monthly PyPI) |
| denyPackages | Names that may never be added, however healthy the registry says they are |
| allowLicenses | When set, a package's licence must be in this list (supersedes denyLicenses) |
| denyLicenses | Licences that may never be introduced |
| forbidShellMcp | Refuse MCP servers whose invocation goes through a shell |
| forbidUnpinnedMcp | Refuse MCP servers running unpinned packages |
Violations block audit_staged and codeorion scan --staged — a policy
the tooling merely mentions is advice wearing a policy's name. Every key is
deliberately one a maintainer can defend in review; anything not expressible
here is not policy, and the detectors keep their own defaults.
Environment variables
| Var | Default | What it does |
|---|---|---|
| CODEAUDIT_TOKEN | unset | Per-repo token enabling hosted LLM alternative suggestions for phantom packages. When set, phantom package names are sent to the API with the token. |
| CODEAUDIT_API_URL | the hosted dashboard | Where the two opt-in features above talk to. Set it if you self-host. |
| CODEAUDIT_REPORT_PHANTOMS | unset (off) | Opt-in telemetry: when 1, a verify that returns phantom reports the package name and ecosystem — nothing else. No code, no file paths, no repo name, no token, no identity; the server stores name, ecosystem and a counter, and the endpoint returns nothing back. Reports land in a human review queue as candidates for the hallucinated-names corpus — nothing is ever promoted into the shipped list automatically, because auto-promotion would let anyone poison the corpus every install carries. |
With all three unset — the default — the server makes registry and OSV lookups only, and sends nothing derived from your machine anywhere.
Getting a token (optional)
A CODEAUDIT_TOKEN is the same per-repo token used by codeorion
--upload — generate one from your repository's settings page at
codeaudit.madhavaryal.info.np, or via POST
/repos/:repoId/cli-token if self-hosting.
