ctxai
About
A version-aware MCP server that prevents AI coding hallucinations by validating suggestions against your actual installed packages.
Details
- Author
- nirvanjha2004
- Categories
- Developer Tools, AI, Knowledge Base
Jump to
Setup
Install ctxai in your MCP client (Claude Desktop, Cursor, Windsurf, and others).
Repository: https://github.com/nirvanjha2004/ctxAI-MCP-tool-to-reduce-hallucinations
Follow the installation instructions in the repository README, then restart your MCP client.
AI coding assistants hallucinate in three specific ways that are hard to catch:
- Package hallucinations— suggestingimport helmet from 'helmet'whenhelmetisn't in yourpackage.json
- Method hallucinations— callingprisma.user.findFirstOrThrow()when you're on Prisma v3, where that method doesn't exist yet
- Phantom packages— inventing package names likeexpress-mongooseorreact-query-utilsthat don't exist on npm, which threat actors can register as typosquats
All three look like valid code. All three fail at runtime — or worse, install malware. ctxai catches them at suggestion time.
ctxai exposes four MCP tools that an LLM client (Claude Desktop, Cursor, Kiro, etc.) calls automatically:
get_project_context → scan project → return version fingerprint validate_suggestion → check code → return hallucination warnings check_package_safety → check new packages → return safety issues get_package_docs → fetch registry → return real API info
Scans your project root and returns a structured fingerprint of every installed package and its exact version:
node: express@4.18.2 node: @prisma/client@3.15.2 python: fastapi@0.100.0 python: requests@2.31.0
This fingerprint is injected into the LLM context before every response, constraining it to only suggest APIs that exist in your installed versions. Results are cached for 5 minutes so repeated calls within a session are instant.
Takes AI-generated code and the fingerprint from Tool 1, then runs three validation layers:
Returns human-readable output with the exact offending identifier, severity, and a corrected install command or method suggestion.
⚠️ Found 1 issue in the suggested code: 🔴 [Missing package] 'helmet' is not listed in your project dependencies. → Run 'npm install helmet' to add it, or check if the package name has changed. The code above cannot run as-is. Fix the missing packages before using it.
Checks everynewpackage the AI suggests installing against three safety layers:
Packages already in your fingerprint are skipped — you've already made that trust decision.
🚨 Found 1 critical issue across 1 new package. 📦 expres 🚨 [Likely typosquat] 'expres' exists on the registry but is suspiciously similar to 'express' (edit distance: 1). This is a known typosquatting pattern. → Verify you meant 'express'. If you intentionally want 'expres', inspect its source code and maintainers before installing. 🛑 Do NOT install the flagged packages without manual verification.
Fetches live metadata from npm or PyPI for a specific package version. Used by the LLM to self-correct after a hallucination is detected — finds the correct method name for the version you actually have installed.
ctxai/ ├── src/ │ ├── index.ts # MCP server — registers all 4 tools │ ├── formatters.ts # Converts typed results → readable MCP strings │ ├── tools/ │ │ ├── getProjectContext.ts # Tool 1: scan project + build fingerprint │ │ ├── validateSuggestion.ts # Tool 2: 3-layer hallucination validator │ │ └── getPackageDocs.ts # Tool 4: live registry metadata │ ├── utils/ │ │ ├── checkPackageSafety.ts # Tool 3: phantom/typosquat/trust checker │ │ ├── registryClient.ts # Typed npm + PyPI registry clients │ │ ├── typosquatDetector.ts # Levenshtein-based typosquat detection │ │ ├── fuzzy.ts # Closest-match suggestions │ │ ├── npmRegistry.ts # npm metadata client (used by getPackageDocs) │ │ └── pypiRegistry.ts # PyPI metadata client (used by getPackageDocs) │ ├── parser/ │ │ ├── responseParser.ts # Extracts imports + method calls from code │ │ └── fingerprintBuilder.ts # Formats detected packages into fingerprint │ ├── detectors/ │ │ ├── index.ts # Orchestrates Node + Python detection │ │ ├── node.ts # Reads package.json + TypeScript API surface │ │ └── python.ts # Reads requirements.txt + Python API surface │ └── cache/ │ └── sessionCache.ts # In-memory TTL cache (5 min) └── benchmark/ ├── run.ts # Benchmark runner with hallucination metrics └── prompts/ # 28 test cases (JSON)
- Node.js 18+
- TypeScript 5+
- Python 3 (optional, for Python project validation)
npm start # or in dev mode (no build step) npm run dev
The server communicates over stdio, which is the standard MCP transport.
Add to.kiro/settings/mcp.jsonin your workspace:
{ "mcpServers": { "ctxai": { "command": "node", "args": ["/absolute/path/to/ctxai/build/index.js"], "disabled": false, "autoApprove": [ "get_project_context", "validate_suggestion", "check_package_safety", "get_package_docs" ] } } }
Windows + fnm/nvm users:nodemay not resolve when Kiro launches the server outside your shell session. Use the full path tonode.exeinstead:
"command": "C:\\Users\\YOU\\AppData\\Roaming\\fnm\\node-versions\\v20.0.0\\installation\\node.exe"
Find your path with:Get-Command node | Select-Object -ExpandProperty Source(PowerShell)
Edit~/Library/Application Support/Claude/claude_desktop_config.json(macOS) or%APPDATA%\Claude\claude_desktop_config.json(Windows):
{ "mcpServers": { "ctxai": { "command": "node", "args": ["/absolute/path/to/ctxai/build/index.js"] } } }
{ "mcpServers": { "ctxai": { "command": "node", "args": ["/absolute/path/to/ctxai/build/index.js"], "disabled": false, "alwaysAllow": [] } } }
After adding the config, reload/reconnect MCP servers from the command palette. You should see ctxai with 4 tools listed.
npm run build node build/index.js # Expected: ctxai MCP server v0.1.0 running on stdio
Test each tool by piping JSON directly to the server:
echo '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"get_project_context","arguments":{"path":"/your/project/path"}}}' \ | node build/index.js
echo '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"validate_suggestion","arguments":{"code":"import helmet from \"helmet\";","contextFingerprint":"node: express@4.18.2"}}}' \ | node build/index.js # Expected: 🔴 [Missing package] 'helmet' is not listed in your project dependencies.
echo '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"check_package_safety","arguments":{"code":"import expres from \"expres\";","contextFingerprint":"node: express@4.18.2"}}}' \ | node build/index.js # Expected: 🚨 [Likely typosquat] 'expres' is suspiciously similar to 'express'
echo '{"jsonrpc":"2.0","id":4,"method":"tools/call","params":{"name":"get_package_docs","arguments":{"packageName":"express","version":"4.18.2","registry":"npm"}}}' \ | node build/index.js
════════════════════════════════════════════════════════════ HALLUCINATION REDUCTION METRICS ════════════════════════════════════════════════════════════ Benchmark accuracy 100.0% (28/28 tests match expected) Detection rate 100.0% False positives 0 Precision 100.0% F1 Score 100.0%
ctxai ships with 28 test cases covering every validation scenario. Results include hallucination reduction metrics — detection rate, precision, and F1 score — so you can measure the impact of any changes.
Create a JSON file inbenchmark/prompts/:
{ "name": "My Test Case", "projectFingerprint": "node: express@4.18.2", "aiGeneratedCode": "import helmet from 'helmet';\nconst app = require('express')();", "expectedViolations": 1 }
For method hallucination tests, inject a mock API surface so the test doesn't require realnode_modules:
{ "name": "Prisma - Method Hallucination", "projectFingerprint": "node: @prisma/client@3.15.2", "aiGeneratedCode": "const prisma = new PrismaClient();\nawait prisma.user.findFirstOrThrow({ where: { id: 1 } });", "apiSurfaceOverrides": { "@prisma/client": ["findFirst", "findMany", "create", "update", "delete"] }, "expectedViolations": 1, "_note": "findFirstOrThrow was added in Prisma v4 — should be caught on v3" }
interface ValidationWarning { type: "MISSING_PACKAGE" | "HALLUCINATED_METHOD" | "UNKNOWN_PACKAGE"; severity: "error" | "warning" | "info"; message: string; // Human-readable description suggestion: string; // Correct install command or method name offender: string; // The exact identifier that triggered the warning packageName?: string; // Package context (HALLUCINATED_METHOD only) installedVersion?: string; // Installed version (HALLUCINATED_METHOD only) }
interface SafetyIssue { type: "PHANTOM_PACKAGE" | "LIKELY_TYPOSQUAT" | "LIKELY_CONFLATION" | "LOW_TRUST_PACKAGE" | "SECURITY_HOLD"; severity: "critical" | "warning" | "info"; packageName: string; ecosystem: "node" | "python"; message: string; suggestion: string; meta?: { similarTo?: string; // The popular package it resembles editDistance?: number; // Levenshtein distance to the popular package ageInDays?: number; // How old the package is versionCount?: number; // How many versions it has hasRepository?: boolean; // Whether it has a repo link } }
ctxai knows that Python import names often differ from pip package names and generates correct install commands:
80+ mappings are built in. Seesrc/tools/validateSuggestion.ts→PYTHON_IMPORT_TO_PIPfor the full list.
Why four tools instead of one?Each tool has a distinct trigger condition.get_project_contextruns once per session.validate_suggestionruns on every code response.check_package_safetyruns only when new packages are suggested.get_package_docsruns on-demand for self-correction. Splitting them lets the LLM call only what's needed.
Why MCP?MCP is the emerging standard for giving LLMs structured access to local tools. Any MCP-compatible client gets ctxai for free without custom integrations.
Why a fingerprint string instead of JSON?The fingerprint format (node: express@4.18.2) is compact, human-readable, and token-efficient. It fits in the LLM context without wasting tokens on JSON syntax.
Why not just use the LLM's training data?Training data is frozen at a cutoff date and doesn't know what's installed inyourproject. ctxai reads your actualnode_modulesandrequirements.txtat runtime.
Why prefer false negatives over false positives?If ctxai can't determine whether a method exists (no type definitions, no stubs), it stays silent rather than warning. A missed hallucination is less disruptive than a false alarm on valid code.
The benchmark is the best place to start. If you find a case where ctxai produces a false positive or misses a hallucination:
- Add a prompt JSON tobenchmark/prompts/that reproduces the issue
- SetexpectedViolationsto what the correct behaviour should be
- Runnpm run benchmark— if it fails, the bug is confirmed
- Fix the validator and verify the benchmark goes green
This is a web browser that enables your coding agent, such as Claude Code, to visit websites on your behalf and assist you in identifying bugs or creating UI test cases.
Skill router and context picker for coding agents — hybrid retrieval + rerank picks the right skill; an ONNX prompt-injection gate scans both the request and every retrieved doc.
An MCP server to help AI assistants to answer questions and generate AccelByte Extend SDK code more effectively .
Instead of direct calling MCP tools, mcpcode server transforms MCP tool calls into TypeScript programs, enabling smarter, lower-latency orchestration by LLMs.
Supercharge your Agent with Semantic Code Intelligence and save 💰 in the process!
AI-to-AI code review platform — Claude, Codex, and Gemini cross-check each other via MCP, REST API, and CLI for consensus-based results.
A code sandbox for AI assistants to safely execute arbitrary code. Requires a 302AI API key for authentication.
Agent-native developer Q&A API with MCP + A2A endpoints for citations, job pickup, and answer submission.
MCP server to dynamically load Claude Code skills into AI agents
MCP bridge that lets Claude Code delegate heavy tasks to the Antigravity CLI (agy) — purpose-built tools, model routing with fallback, session continuity, and output truncation to save Claude's context and tokens.
Exposes local execution of Aider commands as a detached process using MCP.
Sign in to leave a review
Use Google, GitHub, or an email account so ratings stay tied to real people.
No reviews posted yet.





