codex-review-mcp 1.3.1 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -3
- package/dist/mcp-server.js +68 -15
- package/dist/review/buildPrompt.js +43 -5
- package/dist/review/buildPrompt.test.js +113 -0
- package/dist/review/collectDiff.test.js +490 -0
- package/dist/review/formatOutput.test.js +159 -0
- package/dist/review/gatherContext.js +101 -13
- package/dist/review/gatherContext.test.js +334 -0
- package/dist/review/invokeAgent.js +39 -3
- package/dist/review/invokeAgent.test.js +31 -0
- package/dist/tools/performCodeReview.js +52 -15
- package/dist/tools/performCodeReview.test.js +196 -76
- package/package.json +2 -1
- package/dist/review/collectDiff.js +0 -192
package/README.md
CHANGED
@@ -11,6 +11,7 @@ With this MCP server, your AI assistant can call out for a code review **right i
|
|
11
11
|
## Features
|
12
12
|
|
13
13
|
- 🎯 **Zero Configuration** - Just add your OpenAI API key
|
14
|
+
- 📋 **Respects Your Cursor Rules** - Automatically reads `.cursor/rules/` and enforces YOUR coding standards
|
14
15
|
- 🔍 Automatically reviews your uncommitted changes
|
15
16
|
- 🤖 Powered by GPT-5 Codex for intelligent code analysis
|
16
17
|
- 📊 Returns actionable feedback in Markdown format
|
@@ -100,9 +101,9 @@ Most users won't need these, but they're available if you want more control:
|
|
100
101
|
|
101
102
|
1. **Detects Repository**: Automatically finds your git repository root
|
102
103
|
2. **Collects Diff**: Runs git diff to get the changes
|
103
|
-
3. **Gathers Context**:
|
104
|
-
4. **AI Review**: Sends to GPT-5 Codex
|
105
|
-
5. **Returns Feedback**: Provides actionable Markdown feedback
|
104
|
+
3. **Gathers Context**: Reads your `.cursor/rules/`, `CODE_REVIEW.md`, `.eslintrc`, and other project files
|
105
|
+
4. **AI Review**: Sends to GPT-5 Codex with YOUR project's coding standards
|
106
|
+
5. **Returns Feedback**: Provides actionable Markdown feedback that respects YOUR rules
|
106
107
|
|
107
108
|
## Requirements
|
108
109
|
|
package/dist/mcp-server.js
CHANGED
@@ -2,33 +2,86 @@ import 'dotenv/config';
|
|
2
2
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
3
3
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
4
4
|
import { z } from 'zod';
|
5
|
+
import { readFileSync } from 'node:fs';
|
6
|
+
import { fileURLToPath } from 'node:url';
|
7
|
+
import { dirname, join } from 'node:path';
|
5
8
|
import { performCodeReview } from './tools/performCodeReview.js';
|
6
|
-
|
9
|
+
// Read version from package.json
|
10
|
+
const __filename = fileURLToPath(import.meta.url);
|
11
|
+
const __dirname = dirname(__filename);
|
12
|
+
const packageJson = JSON.parse(readFileSync(join(__dirname, '../package.json'), 'utf8'));
|
13
|
+
const VERSION = packageJson.version;
|
14
|
+
const server = new McpServer({ name: 'codex-review-mcp', version: VERSION });
|
15
|
+
server.registerTool('get_version', {
|
16
|
+
title: 'Get Version',
|
17
|
+
description: 'Get the version of the codex-review-mcp server.',
|
18
|
+
inputSchema: {}, // Empty schema - no parameters required
|
19
|
+
}, async () => {
|
20
|
+
return {
|
21
|
+
content: [{
|
22
|
+
type: 'text',
|
23
|
+
text: `codex-review-mcp version ${VERSION}`,
|
24
|
+
mimeType: 'text/plain'
|
25
|
+
}]
|
26
|
+
};
|
27
|
+
});
|
7
28
|
server.registerTool('perform_code_review', {
|
8
29
|
title: 'Perform Code Review',
|
9
|
-
description:
|
30
|
+
description: `Review code/diffs using GPT-5 Codex with expert prompts and project-specific context.
|
31
|
+
|
32
|
+
🎯 USAGE:
|
33
|
+
|
34
|
+
1. Get the code/diff to review:
|
35
|
+
const diff = await runCommand("git diff");
|
36
|
+
|
37
|
+
2. Optionally gather project context:
|
38
|
+
const rules = await readFile(".cursor/rules/project.mdc");
|
39
|
+
|
40
|
+
3. Call with content:
|
41
|
+
await perform_code_review({
|
42
|
+
content: diff, // REQUIRED
|
43
|
+
contentType: "diff", // "diff" or "code"
|
44
|
+
customContext: rules, // Optional: saves tokens!
|
45
|
+
focus: "security and performance" // Optional: specific focus
|
46
|
+
});
|
47
|
+
|
48
|
+
💡 KEY BENEFITS:
|
49
|
+
- Expert Reviews: GPT-5 Codex with project-specific context
|
50
|
+
- Codebase-Aware: Checks YOUR patterns, enforces YOUR rules
|
51
|
+
- Efficient: Provide customContext to skip auto-gathering
|
52
|
+
|
53
|
+
📋 PARAMETERS:
|
54
|
+
- content: Code or diff to review (REQUIRED)
|
55
|
+
- contentType: "diff" | "code"
|
56
|
+
- customContext: Project rules/guidelines (saves tokens if provided)
|
57
|
+
- skipContextGathering: Skip auto-gathering if you don't need context
|
58
|
+
- focus: Specific areas to review (e.g., "security", "performance")
|
59
|
+
- workspaceDir: Base directory for context gathering (defaults to cwd)`,
|
10
60
|
inputSchema: {
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
61
|
+
// REQUIRED
|
62
|
+
content: z.string().describe('Code or diff content to review (REQUIRED). Agent should run git commands or read files to get this.'),
|
63
|
+
// CONTENT TYPE
|
64
|
+
contentType: z.enum(['diff', 'code']).optional().describe('Type of content: "diff" for git diffs, "code" for static code review'),
|
65
|
+
// CONTEXT OPTIONS
|
66
|
+
customContext: z.string().optional().describe('⭐ RECOMMENDED: Project context (.cursor/rules, CODE_REVIEW.md, etc). Saves tokens and time!'),
|
67
|
+
skipContextGathering: z.boolean().optional().describe('Set to true to skip automatic context gathering (useful if no context needed)'),
|
68
|
+
workspaceDir: z.string().optional().describe('Base directory for context gathering (defaults to current directory)'),
|
69
|
+
// REVIEW OPTIONS
|
70
|
+
focus: z.string().optional().describe('Specific areas to focus on (e.g., "security and performance")'),
|
71
|
+
maxTokens: z.number().optional().describe('Maximum tokens for review response'),
|
18
72
|
},
|
19
73
|
}, async (input, extra) => {
|
20
74
|
try {
|
21
75
|
const reviewInput = {
|
22
|
-
|
23
|
-
|
24
|
-
|
76
|
+
content: input.content,
|
77
|
+
contentType: input.contentType,
|
78
|
+
workspaceDir: input.workspaceDir,
|
79
|
+
customContext: input.customContext,
|
80
|
+
skipContextGathering: input.skipContextGathering,
|
25
81
|
focus: input.focus,
|
26
|
-
paths: input.paths,
|
27
82
|
maxTokens: input.maxTokens,
|
28
|
-
workspaceDir: input.workspaceDir,
|
29
83
|
};
|
30
84
|
const onProgress = async (message, progress, total) => {
|
31
|
-
// Attach to tool-call request via related request ID so clients can map progress
|
32
85
|
await server.server.notification({
|
33
86
|
method: 'notifications/progress',
|
34
87
|
params: {
|
@@ -1,13 +1,51 @@
|
|
1
|
-
export function buildPrompt({ diffText, context, focus }) {
|
1
|
+
export function buildPrompt({ diffText, context, focus, version, isStaticReview }) {
|
2
2
|
const focusLine = focus ? `Focus areas: ${focus}.` : '';
|
3
|
+
const versionLine = version ? `codex-review-mcp v${version}` : '';
|
4
|
+
const reviewType = isStaticReview ? 'Static File Review' : 'Diff Review';
|
3
5
|
return [
|
6
|
+
versionLine,
|
7
|
+
'',
|
4
8
|
'You are an expert AI code reviewer. Be concise, specific, and actionable.',
|
5
|
-
'Prefer minimal diffs and direct fixes.
|
9
|
+
'Prefer minimal diffs and direct fixes.',
|
10
|
+
'',
|
11
|
+
'ENVIRONMENT ASSUMPTION: The runtime and tooling are POSIX (macOS/Linux). Do NOT suggest Windows/PowerShell/cmd-specific commands or paths.',
|
12
|
+
'',
|
13
|
+
'🚨 CRITICAL REPO-SPECIFIC GUIDANCE HIERARCHY:',
|
14
|
+
'1. HIGHEST PRIORITY: Project documentation (.cursor/rules/*, CODE_REVIEW.md, CONTRIBUTING.md, etc.)',
|
15
|
+
'2. Configuration files (tsconfig.json, .eslintrc, prettier config, etc.)',
|
16
|
+
'3. Existing patterns in similar files within the same directory',
|
17
|
+
'4. General best practices (ONLY when not conflicting with above)',
|
18
|
+
'',
|
19
|
+
'MANDATORY REVIEW REQUIREMENTS:',
|
20
|
+
'- 🔍 EXAMINE existing code patterns in the same directory/module before suggesting changes',
|
21
|
+
'- 📚 CHECK for existing utility functions, abstractions, and helpers before creating new ones',
|
22
|
+
'- 🎯 FOLLOW the exact naming conventions, file structure, and import patterns used in this repo',
|
23
|
+
'- 🧪 MATCH existing test patterns and testing approaches when reviewing test files',
|
24
|
+
'- ⚙️ VALIDATE against linting and formatting rules defined in the project config',
|
25
|
+
'- 🚫 NEVER suggest patterns that are inconsistent with the existing codebase',
|
26
|
+
'- 🚫 NEVER introduce external libraries/patterns not already in use',
|
27
|
+
'- ✅ PREFER reusing existing abstractions over creating new ones',
|
28
|
+
'',
|
29
|
+
'SPECIFIC TECHNICAL GUIDELINES:',
|
30
|
+
'- Follow ALL guidelines, conventions, and architectural patterns defined in the project documentation below',
|
31
|
+
'- Maintain consistency with the existing codebase styling, naming conventions, and structural themes',
|
32
|
+
'- Base your recommendations on the internal documentation, .cursor/rules files, and configuration files provided',
|
33
|
+
'- Do NOT suggest changes that deviate from the project\'s established patterns or introduce external patterns',
|
34
|
+
'- When project guidelines conflict with general best practices, prioritize the project guidelines',
|
35
|
+
'- For accessibility audits: apply axe-core best practices and WCAG 2.1 Level AA guidelines',
|
36
|
+
'- CRITICAL Z-INDEX WARNING: Be extremely cautious with z-index changes on modals, overlays, or components. Analyze the entire z-index hierarchy before suggesting changes. Flag any z-index modifications as HIGH RISK and verify they won\'t break stacking context upstream or downstream. Always check for existing z-index patterns in the codebase first.',
|
6
37
|
focusLine,
|
7
|
-
'
|
38
|
+
'',
|
39
|
+
'BEFORE making ANY suggestion, ask yourself:',
|
40
|
+
'1. Does this pattern already exist in the codebase? (Check similar files)',
|
41
|
+
'2. Is there an existing utility/helper that could be reused?',
|
42
|
+
'3. Does this follow the exact conventions shown in the project documentation?',
|
43
|
+
'4. Would this change maintain consistency with the surrounding code?',
|
44
|
+
'',
|
45
|
+
`\n---\n${reviewType}${isStaticReview ? ' - Code Files' : ' (unified=0)'}:\n`,
|
8
46
|
diffText,
|
9
|
-
context ? '\n---\nProject context and guidelines:\n' + context : '',
|
47
|
+
context ? '\n---\nProject context and guidelines (FOLLOW THESE STRICTLY):\n' + context : '',
|
10
48
|
'\n---\nOutput strictly as Markdown with the following sections:\n',
|
11
|
-
'1) Title + scope summary\n2) Quick Summary (3–6 bullets)\n3) Issues table: severity | file:lines | category | explanation | suggested fix\n4) Inline suggested edits for top issues\n5) Positive notes\n6) Next steps',
|
49
|
+
'1) Title + scope summary\n2) Quick Summary (3–6 bullets)\n3) Issues table: severity | file:lines | category | explanation | suggested fix\n4) Inline suggested edits for top issues\n5) Positive notes (mention when code follows project guidelines well)\n6) Next steps',
|
12
50
|
].join('\n');
|
13
51
|
}
|
@@ -0,0 +1,113 @@
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
2
|
+
import { buildPrompt } from './buildPrompt.js';
|
3
|
+
describe('buildPrompt', () => {
|
4
|
+
const mockDiff = `diff --git a/test.ts b/test.ts
|
5
|
+
+++ b/test.ts
|
6
|
+
+export function hello() {
|
7
|
+
+ return "world";
|
8
|
+
+}`;
|
9
|
+
it('should include version in prompt when provided', () => {
|
10
|
+
const prompt = buildPrompt({
|
11
|
+
diffText: mockDiff,
|
12
|
+
version: '1.4.0',
|
13
|
+
});
|
14
|
+
expect(prompt).toContain('codex-review-mcp v1.4.0');
|
15
|
+
expect(prompt.startsWith('codex-review-mcp v1.4.0')).toBe(true);
|
16
|
+
});
|
17
|
+
it('should not include version line when version is not provided', () => {
|
18
|
+
const prompt = buildPrompt({
|
19
|
+
diffText: mockDiff,
|
20
|
+
});
|
21
|
+
expect(prompt).not.toContain('codex-review-mcp v');
|
22
|
+
});
|
23
|
+
it('should indicate "Diff Review" when isStaticReview is false', () => {
|
24
|
+
const prompt = buildPrompt({
|
25
|
+
diffText: mockDiff,
|
26
|
+
isStaticReview: false,
|
27
|
+
});
|
28
|
+
expect(prompt).toContain('Diff Review (unified=0)');
|
29
|
+
});
|
30
|
+
it('should indicate "Static File Review" when isStaticReview is true', () => {
|
31
|
+
const prompt = buildPrompt({
|
32
|
+
diffText: 'File: test.ts\ncode here',
|
33
|
+
isStaticReview: true,
|
34
|
+
});
|
35
|
+
expect(prompt).toContain('Static File Review - Code Files');
|
36
|
+
});
|
37
|
+
it('should default to "Diff Review" when isStaticReview is not provided', () => {
|
38
|
+
const prompt = buildPrompt({
|
39
|
+
diffText: mockDiff,
|
40
|
+
});
|
41
|
+
expect(prompt).toContain('Diff Review (unified=0)');
|
42
|
+
});
|
43
|
+
it('should include focus areas when provided', () => {
|
44
|
+
const prompt = buildPrompt({
|
45
|
+
diffText: mockDiff,
|
46
|
+
focus: 'security and performance',
|
47
|
+
});
|
48
|
+
expect(prompt).toContain('Focus areas: security and performance');
|
49
|
+
});
|
50
|
+
it('should include context when provided', () => {
|
51
|
+
const context = 'This is a TypeScript project using React';
|
52
|
+
const prompt = buildPrompt({
|
53
|
+
diffText: mockDiff,
|
54
|
+
context,
|
55
|
+
});
|
56
|
+
expect(prompt).toContain('Project context and guidelines (FOLLOW THESE STRICTLY)');
|
57
|
+
expect(prompt).toContain(context);
|
58
|
+
});
|
59
|
+
it('should include all required sections', () => {
|
60
|
+
const prompt = buildPrompt({
|
61
|
+
diffText: mockDiff,
|
62
|
+
});
|
63
|
+
// Verify key sections are present
|
64
|
+
expect(prompt).toContain('You are an expert AI code reviewer');
|
65
|
+
expect(prompt).toContain('CRITICAL REPO-SPECIFIC GUIDANCE HIERARCHY');
|
66
|
+
expect(prompt).toContain('MANDATORY REVIEW REQUIREMENTS');
|
67
|
+
expect(prompt).toContain('SPECIFIC TECHNICAL GUIDELINES');
|
68
|
+
expect(prompt).toContain('Output strictly as Markdown with the following sections');
|
69
|
+
});
|
70
|
+
it('should include the diff text', () => {
|
71
|
+
const prompt = buildPrompt({
|
72
|
+
diffText: mockDiff,
|
73
|
+
});
|
74
|
+
expect(prompt).toContain(mockDiff);
|
75
|
+
});
|
76
|
+
it('should handle all parameters together', () => {
|
77
|
+
const prompt = buildPrompt({
|
78
|
+
diffText: mockDiff,
|
79
|
+
version: '1.4.0',
|
80
|
+
isStaticReview: true,
|
81
|
+
focus: 'code quality',
|
82
|
+
context: 'TypeScript best practices',
|
83
|
+
});
|
84
|
+
expect(prompt).toContain('codex-review-mcp v1.4.0');
|
85
|
+
expect(prompt).toContain('Static File Review - Code Files');
|
86
|
+
expect(prompt).toContain('Focus areas: code quality');
|
87
|
+
expect(prompt).toContain('TypeScript best practices');
|
88
|
+
expect(prompt).toContain(mockDiff);
|
89
|
+
});
|
90
|
+
it('should include POSIX environment assumption', () => {
|
91
|
+
const prompt = buildPrompt({
|
92
|
+
diffText: mockDiff,
|
93
|
+
});
|
94
|
+
expect(prompt).toContain('ENVIRONMENT ASSUMPTION: The runtime and tooling are POSIX (macOS/Linux)');
|
95
|
+
expect(prompt).toContain('Do NOT suggest Windows/PowerShell/cmd-specific commands');
|
96
|
+
});
|
97
|
+
it('should include z-index warning', () => {
|
98
|
+
const prompt = buildPrompt({
|
99
|
+
diffText: mockDiff,
|
100
|
+
});
|
101
|
+
expect(prompt).toContain('CRITICAL Z-INDEX WARNING');
|
102
|
+
expect(prompt).toContain('z-index changes on modals, overlays, or components');
|
103
|
+
});
|
104
|
+
it('should include guidance hierarchy with proper priorities', () => {
|
105
|
+
const prompt = buildPrompt({
|
106
|
+
diffText: mockDiff,
|
107
|
+
});
|
108
|
+
expect(prompt).toContain('1. HIGHEST PRIORITY: Project documentation');
|
109
|
+
expect(prompt).toContain('2. Configuration files');
|
110
|
+
expect(prompt).toContain('3. Existing patterns in similar files');
|
111
|
+
expect(prompt).toContain('4. General best practices');
|
112
|
+
});
|
113
|
+
});
|