@klitchevo/code-council 0.0.1 → 0.0.2

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.
Files changed (56) hide show
  1. package/README.md +48 -16
  2. package/dist/index.d.ts +0 -6
  3. package/dist/index.js +627 -57
  4. package/package.json +4 -3
  5. package/dist/config.d.ts +0 -48
  6. package/dist/config.d.ts.map +0 -1
  7. package/dist/config.js +0 -61
  8. package/dist/constants.d.ts +0 -33
  9. package/dist/constants.d.ts.map +0 -1
  10. package/dist/constants.js +0 -36
  11. package/dist/errors.d.ts +0 -53
  12. package/dist/errors.d.ts.map +0 -1
  13. package/dist/errors.js +0 -92
  14. package/dist/index.d.ts.map +0 -1
  15. package/dist/logger.d.ts +0 -22
  16. package/dist/logger.d.ts.map +0 -1
  17. package/dist/logger.js +0 -62
  18. package/dist/prompts/backend-review.d.ts +0 -6
  19. package/dist/prompts/backend-review.d.ts.map +0 -1
  20. package/dist/prompts/backend-review.js +0 -28
  21. package/dist/prompts/code-review.d.ts +0 -6
  22. package/dist/prompts/code-review.d.ts.map +0 -1
  23. package/dist/prompts/code-review.js +0 -18
  24. package/dist/prompts/frontend-review.d.ts +0 -6
  25. package/dist/prompts/frontend-review.d.ts.map +0 -1
  26. package/dist/prompts/frontend-review.js +0 -28
  27. package/dist/prompts/plan-review.d.ts +0 -6
  28. package/dist/prompts/plan-review.d.ts.map +0 -1
  29. package/dist/prompts/plan-review.js +0 -29
  30. package/dist/review-client.d.ts +0 -75
  31. package/dist/review-client.d.ts.map +0 -1
  32. package/dist/review-client.js +0 -116
  33. package/dist/schemas.d.ts +0 -60
  34. package/dist/schemas.d.ts.map +0 -1
  35. package/dist/schemas.js +0 -46
  36. package/dist/tools/factory.d.ts +0 -20
  37. package/dist/tools/factory.d.ts.map +0 -1
  38. package/dist/tools/factory.js +0 -55
  39. package/dist/tools/list-config.d.ts +0 -9
  40. package/dist/tools/list-config.d.ts.map +0 -1
  41. package/dist/tools/list-config.js +0 -31
  42. package/dist/tools/review-backend.d.ts +0 -22
  43. package/dist/tools/review-backend.d.ts.map +0 -1
  44. package/dist/tools/review-backend.js +0 -38
  45. package/dist/tools/review-code.d.ts +0 -15
  46. package/dist/tools/review-code.d.ts.map +0 -1
  47. package/dist/tools/review-code.js +0 -29
  48. package/dist/tools/review-frontend.d.ts +0 -22
  49. package/dist/tools/review-frontend.d.ts.map +0 -1
  50. package/dist/tools/review-frontend.js +0 -38
  51. package/dist/tools/review-plan.d.ts +0 -22
  52. package/dist/tools/review-plan.d.ts.map +0 -1
  53. package/dist/tools/review-plan.js +0 -35
  54. package/dist/utils/parallel-executor.d.ts +0 -10
  55. package/dist/utils/parallel-executor.d.ts.map +0 -1
  56. package/dist/utils/parallel-executor.js +0 -21
package/dist/index.js CHANGED
@@ -1,79 +1,649 @@
1
1
  #!/usr/bin/env node
2
- /**
3
- * Code Council MCP Server
4
- * Multi-model AI code review server using OpenRouter API
5
- */
2
+
3
+ // src/index.ts
6
4
  import "dotenv/config";
7
5
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
8
6
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
9
- import { BACKEND_REVIEW_MODELS, CODE_REVIEW_MODELS, FRONTEND_REVIEW_MODELS, PLAN_REVIEW_MODELS, } from "./config";
10
- import { logger } from "./logger";
11
- import { ReviewClient } from "./review-client";
12
- import { createReviewTool } from "./tools/factory";
13
- import { handleListConfig } from "./tools/list-config";
14
- import { backendReviewSchema, handleBackendReview, } from "./tools/review-backend";
15
- import { codeReviewSchema, handleCodeReview } from "./tools/review-code";
16
- import { frontendReviewSchema, handleFrontendReview, } from "./tools/review-frontend";
17
- import { handlePlanReview, planReviewSchema } from "./tools/review-plan";
18
- // Validate API key
19
- const OPENROUTER_API_KEY = process.env.OPENROUTER_API_KEY;
7
+
8
+ // src/constants.ts
9
+ var LLM_CONFIG = {
10
+ /** Default temperature for model responses */
11
+ DEFAULT_TEMPERATURE: 0.3,
12
+ /** Default max tokens for responses */
13
+ DEFAULT_MAX_TOKENS: 4096
14
+ };
15
+ var DEFAULT_MODELS = [
16
+ "minimax/minimax-m2.1",
17
+ "x-ai/grok-code-fast-1"
18
+ ];
19
+
20
+ // src/config.ts
21
+ function parseModels(envVar, defaults) {
22
+ if (envVar === void 0 || envVar === null) {
23
+ return defaults;
24
+ }
25
+ if (Array.isArray(envVar)) {
26
+ const filtered = envVar.filter((m) => m && m.trim().length > 0);
27
+ return filtered.length > 0 ? filtered : defaults;
28
+ }
29
+ throw new Error(
30
+ `Model configuration must be an array of strings, got: ${typeof envVar}. Example: ["anthropic/claude-3.5-sonnet", "openai/gpt-4-turbo"]`
31
+ );
32
+ }
33
+ var CODE_REVIEW_MODELS = parseModels(
34
+ process.env.CODE_REVIEW_MODELS,
35
+ DEFAULT_MODELS
36
+ );
37
+ var FRONTEND_REVIEW_MODELS = parseModels(
38
+ process.env.FRONTEND_REVIEW_MODELS,
39
+ DEFAULT_MODELS
40
+ );
41
+ var BACKEND_REVIEW_MODELS = parseModels(
42
+ process.env.BACKEND_REVIEW_MODELS,
43
+ DEFAULT_MODELS
44
+ );
45
+ var PLAN_REVIEW_MODELS = parseModels(
46
+ process.env.PLAN_REVIEW_MODELS,
47
+ DEFAULT_MODELS
48
+ );
49
+
50
+ // src/logger.ts
51
+ var Logger = class {
52
+ isDevelopment = process.env.NODE_ENV === "development";
53
+ debugEnabled = process.env.DEBUG === "true";
54
+ log(level, message, context) {
55
+ const logEntry = {
56
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
57
+ level,
58
+ message,
59
+ ...context
60
+ };
61
+ if (this.isDevelopment) {
62
+ const emoji = {
63
+ debug: "\u{1F50D}",
64
+ info: "\u2139\uFE0F",
65
+ warn: "\u26A0\uFE0F",
66
+ error: "\u274C"
67
+ }[level];
68
+ console.error(
69
+ `${emoji} [${level.toUpperCase()}] ${message}`,
70
+ context ? JSON.stringify(context, null, 2) : ""
71
+ );
72
+ } else {
73
+ console.error(JSON.stringify(logEntry));
74
+ }
75
+ }
76
+ debug(message, context) {
77
+ if (this.debugEnabled) {
78
+ this.log("debug", message, context);
79
+ }
80
+ }
81
+ info(message, context) {
82
+ this.log("info", message, context);
83
+ }
84
+ warn(message, context) {
85
+ this.log("warn", message, context);
86
+ }
87
+ error(message, error, context) {
88
+ const errorContext = {
89
+ ...context
90
+ };
91
+ if (error instanceof Error) {
92
+ errorContext.error = {
93
+ name: error.name,
94
+ message: error.message,
95
+ stack: error.stack
96
+ };
97
+ } else if (error) {
98
+ errorContext.error = error;
99
+ }
100
+ this.log("error", message, errorContext);
101
+ }
102
+ };
103
+ var logger = new Logger();
104
+
105
+ // src/review-client.ts
106
+ import { OpenRouter } from "@openrouter/sdk";
107
+
108
+ // src/errors.ts
109
+ var AppError = class extends Error {
110
+ constructor(message, code, userMessage) {
111
+ super(message);
112
+ this.code = code;
113
+ this.userMessage = userMessage;
114
+ this.name = this.constructor.name;
115
+ Error.captureStackTrace(this, this.constructor);
116
+ }
117
+ };
118
+ var OpenRouterError = class extends AppError {
119
+ constructor(message, statusCode, retryable = false) {
120
+ super(
121
+ message,
122
+ "OPENROUTER_ERROR",
123
+ retryable ? "The AI service is temporarily unavailable. Please try again in a moment." : "Unable to complete the review. Please check your API key and try again."
124
+ );
125
+ this.statusCode = statusCode;
126
+ this.retryable = retryable;
127
+ }
128
+ };
129
+ function formatErrorMessage(error) {
130
+ if (error instanceof AppError) {
131
+ return error.userMessage || error.message;
132
+ }
133
+ if (error instanceof Error) {
134
+ const sanitized = error.message.replace(/sk-or-v1-[a-zA-Z0-9]+/g, "[REDACTED]").replace(/Bearer [a-zA-Z0-9-_]+/g, "Bearer [REDACTED]");
135
+ if (sanitized.includes("401") || sanitized.includes("Unauthorized")) {
136
+ return "API authentication failed. Please check your OPENROUTER_API_KEY environment variable.";
137
+ }
138
+ if (sanitized.includes("429") || sanitized.includes("rate limit")) {
139
+ return "Rate limit exceeded. Please wait a moment and try again.";
140
+ }
141
+ if (sanitized.includes("timeout") || sanitized.includes("ETIMEDOUT")) {
142
+ return "Request timed out. The AI service may be slow. Please try again.";
143
+ }
144
+ return sanitized;
145
+ }
146
+ return "An unexpected error occurred. Please try again.";
147
+ }
148
+ function formatError(error) {
149
+ return {
150
+ content: [
151
+ {
152
+ type: "text",
153
+ text: `Error: ${formatErrorMessage(error)}`
154
+ }
155
+ ],
156
+ isError: true
157
+ };
158
+ }
159
+
160
+ // src/prompts/backend-review.ts
161
+ var SYSTEM_PROMPT = `You are an expert backend developer and security specialist. Review backend code for security, performance, and architecture.`;
162
+ function buildUserMessage(code, reviewType = "full", language, context) {
163
+ const focusArea = getFocusArea(reviewType);
164
+ const languageContext = language ? `Language/Framework: ${language}
165
+ ` : "";
166
+ const additionalContext = context ? `${context}
167
+ ` : "";
168
+ return `${languageContext}${additionalContext}${focusArea}
169
+
170
+ Code to review:
171
+ \`\`\`
172
+ ${code}
173
+ \`\`\``;
174
+ }
175
+ function getFocusArea(reviewType) {
176
+ switch (reviewType) {
177
+ case "security":
178
+ return "Focus specifically on security (authentication, authorization, input validation, SQL injection, XSS, CSRF, secrets management).";
179
+ case "performance":
180
+ return "Focus specifically on backend performance (database queries, caching, async operations, resource usage, scalability).";
181
+ case "architecture":
182
+ return "Focus specifically on architecture (design patterns, separation of concerns, modularity, maintainability, scalability).";
183
+ default:
184
+ return "Provide a comprehensive backend review covering security, performance, and architecture.";
185
+ }
186
+ }
187
+
188
+ // src/prompts/code-review.ts
189
+ var SYSTEM_PROMPT2 = `You are an expert code reviewer. Analyze the code for:
190
+ - Code quality and best practices
191
+ - Potential bugs and edge cases
192
+ - Performance issues
193
+ - Security vulnerabilities
194
+ - Maintainability concerns
195
+
196
+ Provide specific, actionable feedback.`;
197
+ function buildUserMessage2(code, context) {
198
+ if (context) {
199
+ return `${context}
200
+
201
+ Code to review:
202
+ \`\`\`
203
+ ${code}
204
+ \`\`\``;
205
+ }
206
+ return `Code to review:
207
+ \`\`\`
208
+ ${code}
209
+ \`\`\``;
210
+ }
211
+
212
+ // src/prompts/frontend-review.ts
213
+ var SYSTEM_PROMPT3 = `You are an expert frontend developer and UX specialist. Review frontend code for best practices.`;
214
+ function buildUserMessage3(code, reviewType = "full", framework, context) {
215
+ const focusArea = getFocusArea2(reviewType);
216
+ const frameworkContext = framework ? `Framework: ${framework}
217
+ ` : "";
218
+ const additionalContext = context ? `${context}
219
+ ` : "";
220
+ return `${frameworkContext}${additionalContext}${focusArea}
221
+
222
+ Code to review:
223
+ \`\`\`
224
+ ${code}
225
+ \`\`\``;
226
+ }
227
+ function getFocusArea2(reviewType) {
228
+ switch (reviewType) {
229
+ case "accessibility":
230
+ return "Focus specifically on accessibility (WCAG compliance, ARIA labels, keyboard navigation, screen reader support).";
231
+ case "performance":
232
+ return "Focus specifically on frontend performance (bundle size, render optimization, lazy loading, Core Web Vitals).";
233
+ case "ux":
234
+ return "Focus specifically on user experience (intuitive design, error handling, loading states, responsive design).";
235
+ default:
236
+ return "Provide a comprehensive frontend review covering accessibility, performance, and user experience.";
237
+ }
238
+ }
239
+
240
+ // src/prompts/plan-review.ts
241
+ var SYSTEM_PROMPT4 = `You are an expert software architect and project planner. Review implementation plans before code is written to catch issues early.`;
242
+ function buildUserMessage4(plan, reviewType = "full", context) {
243
+ const focusArea = getFocusArea3(reviewType);
244
+ const additionalContext = context ? `${context}
245
+ ` : "";
246
+ return `${additionalContext}${focusArea}
247
+
248
+ Implementation plan to review:
249
+ \`\`\`
250
+ ${plan}
251
+ \`\`\``;
252
+ }
253
+ function getFocusArea3(reviewType) {
254
+ switch (reviewType) {
255
+ case "feasibility":
256
+ return "Focus specifically on feasibility (technical complexity, resource requirements, potential blockers, dependencies).";
257
+ case "completeness":
258
+ return "Focus specifically on completeness (missing requirements, edge cases, error handling, testing strategy).";
259
+ case "risks":
260
+ return "Focus specifically on risks (technical risks, security concerns, scalability issues, maintenance burden).";
261
+ case "timeline":
262
+ return "Focus specifically on timeline (realistic estimates, task breakdown, critical path, potential delays).";
263
+ default:
264
+ return "Provide a comprehensive plan review covering feasibility, completeness, risks, and timeline.";
265
+ }
266
+ }
267
+
268
+ // src/utils/parallel-executor.ts
269
+ async function executeInParallel(models, reviewFn) {
270
+ const promises = models.map(async (model) => {
271
+ try {
272
+ const review = await reviewFn(model);
273
+ return { model, review };
274
+ } catch (error) {
275
+ const errorMessage = error instanceof Error ? error.message : "Unknown error";
276
+ return { model, review: "", error: errorMessage };
277
+ }
278
+ });
279
+ return Promise.all(promises);
280
+ }
281
+
282
+ // src/review-client.ts
283
+ var ReviewClient = class {
284
+ client;
285
+ constructor(apiKey) {
286
+ this.client = new OpenRouter({
287
+ apiKey
288
+ });
289
+ }
290
+ /**
291
+ * Send a chat request to OpenRouter API
292
+ * @param model - Model identifier (e.g., "anthropic/claude-3.5-sonnet")
293
+ * @param systemPrompt - System prompt for the model
294
+ * @param userMessage - User message/question
295
+ * @returns The model's response content
296
+ * @throws {OpenRouterError} If the API call fails
297
+ */
298
+ async chat(model, systemPrompt, userMessage) {
299
+ try {
300
+ logger.debug("Sending chat request", {
301
+ model,
302
+ messageLength: userMessage.length
303
+ });
304
+ const response = await this.client.chat.send({
305
+ model,
306
+ messages: [
307
+ { role: "system", content: systemPrompt },
308
+ { role: "user", content: userMessage }
309
+ ],
310
+ temperature: LLM_CONFIG.DEFAULT_TEMPERATURE,
311
+ maxTokens: LLM_CONFIG.DEFAULT_MAX_TOKENS
312
+ });
313
+ const content = response.choices?.[0]?.message?.content;
314
+ if (typeof content === "string") {
315
+ logger.debug("Received response", { model, length: content.length });
316
+ return content;
317
+ }
318
+ if (Array.isArray(content)) {
319
+ const text = content.filter((item) => item.type === "text").map((item) => item.text).join("\n");
320
+ logger.debug("Received array response", { model, length: text.length });
321
+ return text;
322
+ }
323
+ throw new OpenRouterError("No response content from model", 500);
324
+ } catch (error) {
325
+ if (error instanceof OpenRouterError) {
326
+ throw error;
327
+ }
328
+ const message = error instanceof Error ? error.message : "Unknown error";
329
+ logger.error("Chat request failed", error, { model });
330
+ const isRetryable = message.includes("429") || message.includes("rate limit");
331
+ throw new OpenRouterError(message, void 0, isRetryable);
332
+ }
333
+ }
334
+ /**
335
+ * Review code for quality, bugs, performance, and security
336
+ * @param code - Code to review
337
+ * @param models - Array of model identifiers to use
338
+ * @param context - Optional context (language, description, etc.)
339
+ * @returns Array of review results from each model
340
+ */
341
+ async reviewCode(code, models, context) {
342
+ const userMessage = buildUserMessage2(code, context);
343
+ return executeInParallel(
344
+ models,
345
+ (model) => this.chat(model, SYSTEM_PROMPT2, userMessage)
346
+ );
347
+ }
348
+ /**
349
+ * Review frontend code for accessibility, performance, and UX
350
+ */
351
+ async reviewFrontend(code, models, options) {
352
+ const userMessage = buildUserMessage3(
353
+ code,
354
+ options?.reviewType || "full",
355
+ options?.framework,
356
+ options?.context
357
+ );
358
+ return executeInParallel(
359
+ models,
360
+ (model) => this.chat(model, SYSTEM_PROMPT3, userMessage)
361
+ );
362
+ }
363
+ /**
364
+ * Review backend code for security, performance, and architecture
365
+ */
366
+ async reviewBackend(code, models, options) {
367
+ const userMessage = buildUserMessage(
368
+ code,
369
+ options?.reviewType || "full",
370
+ options?.language,
371
+ options?.context
372
+ );
373
+ return executeInParallel(
374
+ models,
375
+ (model) => this.chat(model, SYSTEM_PROMPT, userMessage)
376
+ );
377
+ }
378
+ /**
379
+ * Review implementation plans before code is written
380
+ */
381
+ async reviewPlan(plan, models, options) {
382
+ const userMessage = buildUserMessage4(
383
+ plan,
384
+ options?.reviewType || "full",
385
+ options?.context
386
+ );
387
+ return executeInParallel(
388
+ models,
389
+ (model) => this.chat(model, SYSTEM_PROMPT4, userMessage)
390
+ );
391
+ }
392
+ };
393
+
394
+ // src/tools/factory.ts
395
+ function formatResults(results) {
396
+ return results.map((r) => {
397
+ if (r.error) {
398
+ return `## Review from \`${r.model}\`
399
+
400
+ **Error:** ${r.error}`;
401
+ }
402
+ return `## Review from \`${r.model}\`
403
+
404
+ ${r.review}`;
405
+ }).join("\n\n---\n\n");
406
+ }
407
+ function createReviewTool(server2, config) {
408
+ server2.registerTool(
409
+ config.name,
410
+ {
411
+ description: config.description,
412
+ inputSchema: config.inputSchema
413
+ },
414
+ async (input) => {
415
+ try {
416
+ logger.debug(`Starting ${config.name}`, {
417
+ inputKeys: Object.keys(input)
418
+ });
419
+ const { results, models, reviewType } = await config.handler(input);
420
+ logger.info(`Completed ${config.name}`, {
421
+ modelCount: models.length,
422
+ successCount: results.filter((r) => !r.error).length,
423
+ errorCount: results.filter((r) => r.error).length
424
+ });
425
+ const title = reviewType ? `# ${config.name.replace("review_", "").replace("_", " ")} Review - ${reviewType} (${models.length} models)` : `# ${config.name.replace("review_", "").replace("_", " ")} Review Results (${models.length} models)`;
426
+ return {
427
+ content: [
428
+ {
429
+ type: "text",
430
+ text: `${title}
431
+
432
+ ${formatResults(results)}`
433
+ }
434
+ ]
435
+ };
436
+ } catch (error) {
437
+ logger.error(
438
+ `Error in ${config.name}`,
439
+ error instanceof Error ? error : new Error(String(error))
440
+ );
441
+ return formatError(error);
442
+ }
443
+ }
444
+ );
445
+ }
446
+
447
+ // src/tools/list-config.ts
448
+ async function handleListConfig() {
449
+ const text = `## Current Configuration
450
+
451
+ **Code Review Models:**
452
+ ${CODE_REVIEW_MODELS.map((m) => `- \`${m}\``).join("\n")}
453
+
454
+ **Frontend Review Models:**
455
+ ${FRONTEND_REVIEW_MODELS.map((m) => `- \`${m}\``).join("\n")}
456
+
457
+ **Backend Review Models:**
458
+ ${BACKEND_REVIEW_MODELS.map((m) => `- \`${m}\``).join("\n")}
459
+
460
+ **Plan Review Models:**
461
+ ${PLAN_REVIEW_MODELS.map((m) => `- \`${m}\``).join("\n")}
462
+
463
+ To customize models, set environment variables in your MCP config:
464
+ - CODE_REVIEW_MODELS
465
+ - FRONTEND_REVIEW_MODELS
466
+ - BACKEND_REVIEW_MODELS
467
+ - PLAN_REVIEW_MODELS`;
468
+ return {
469
+ results: [],
470
+ models: [],
471
+ text
472
+ };
473
+ }
474
+
475
+ // src/tools/review-backend.ts
476
+ import { z } from "zod";
477
+ var backendReviewSchema = {
478
+ code: z.string().describe("The backend code to review"),
479
+ language: z.string().optional().describe("Programming language/framework (e.g., node, python, go, rust)"),
480
+ review_type: z.enum(["security", "performance", "architecture", "full"]).optional().describe("Type of review to perform (default: full)"),
481
+ context: z.string().optional().describe("Additional context")
482
+ };
483
+ async function handleBackendReview(client2, input) {
484
+ const { code, language, review_type, context } = input;
485
+ logger.info("Running backend review", {
486
+ modelCount: BACKEND_REVIEW_MODELS.length,
487
+ models: BACKEND_REVIEW_MODELS,
488
+ language,
489
+ reviewType: review_type || "full"
490
+ });
491
+ const results = await client2.reviewBackend(code, BACKEND_REVIEW_MODELS, {
492
+ language,
493
+ reviewType: review_type,
494
+ context
495
+ });
496
+ return {
497
+ results,
498
+ models: BACKEND_REVIEW_MODELS,
499
+ reviewType: review_type || "full"
500
+ };
501
+ }
502
+
503
+ // src/tools/review-code.ts
504
+ import { z as z2 } from "zod";
505
+ var codeReviewSchema = {
506
+ code: z2.string().describe("The code to review"),
507
+ language: z2.string().optional().describe("Programming language of the code"),
508
+ context: z2.string().optional().describe("Additional context about the code")
509
+ };
510
+ async function handleCodeReview(client2, input) {
511
+ const { code, language, context } = input;
512
+ const fullContext = language ? `Language: ${language}${context ? `
513
+ ${context}` : ""}` : context;
514
+ logger.info("Running code review", {
515
+ modelCount: CODE_REVIEW_MODELS.length,
516
+ models: CODE_REVIEW_MODELS,
517
+ hasLanguage: !!language,
518
+ hasContext: !!context
519
+ });
520
+ const results = await client2.reviewCode(
521
+ code,
522
+ CODE_REVIEW_MODELS,
523
+ fullContext
524
+ );
525
+ return {
526
+ results,
527
+ models: CODE_REVIEW_MODELS
528
+ };
529
+ }
530
+
531
+ // src/tools/review-frontend.ts
532
+ import { z as z3 } from "zod";
533
+ var frontendReviewSchema = {
534
+ code: z3.string().describe("The frontend code to review"),
535
+ framework: z3.string().optional().describe("Frontend framework (e.g., react, vue, svelte)"),
536
+ review_type: z3.enum(["accessibility", "performance", "ux", "full"]).optional().describe("Type of review to perform (default: full)"),
537
+ context: z3.string().optional().describe("Additional context")
538
+ };
539
+ async function handleFrontendReview(client2, input) {
540
+ const { code, framework, review_type, context } = input;
541
+ logger.info("Running frontend review", {
542
+ modelCount: FRONTEND_REVIEW_MODELS.length,
543
+ models: FRONTEND_REVIEW_MODELS,
544
+ framework,
545
+ reviewType: review_type || "full"
546
+ });
547
+ const results = await client2.reviewFrontend(code, FRONTEND_REVIEW_MODELS, {
548
+ framework,
549
+ reviewType: review_type,
550
+ context
551
+ });
552
+ return {
553
+ results,
554
+ models: FRONTEND_REVIEW_MODELS,
555
+ reviewType: review_type || "full"
556
+ };
557
+ }
558
+
559
+ // src/tools/review-plan.ts
560
+ import { z as z4 } from "zod";
561
+ var planReviewSchema = {
562
+ plan: z4.string().describe("The implementation plan to review"),
563
+ review_type: z4.enum(["feasibility", "completeness", "risks", "timeline", "full"]).optional().describe("Type of review to perform (default: full)"),
564
+ context: z4.string().optional().describe("Additional context about the project or constraints")
565
+ };
566
+ async function handlePlanReview(client2, input) {
567
+ const { plan, review_type, context } = input;
568
+ logger.info("Running plan review", {
569
+ modelCount: PLAN_REVIEW_MODELS.length,
570
+ models: PLAN_REVIEW_MODELS,
571
+ reviewType: review_type || "full"
572
+ });
573
+ const results = await client2.reviewPlan(plan, PLAN_REVIEW_MODELS, {
574
+ reviewType: review_type,
575
+ context
576
+ });
577
+ return {
578
+ results,
579
+ models: PLAN_REVIEW_MODELS,
580
+ reviewType: review_type || "full"
581
+ };
582
+ }
583
+
584
+ // src/index.ts
585
+ var OPENROUTER_API_KEY = process.env.OPENROUTER_API_KEY;
20
586
  if (!OPENROUTER_API_KEY) {
21
- console.error("Error: OPENROUTER_API_KEY environment variable is required");
22
- console.error("For MCP clients, add it to the 'env' section of your server config.");
23
- console.error("For local development, create a .env file with: OPENROUTER_API_KEY=your-key");
24
- process.exit(1);
25
- }
26
- // Initialize client and server
27
- const client = new ReviewClient(OPENROUTER_API_KEY);
28
- const server = new McpServer({
29
- name: "code-council",
30
- version: "1.0.0",
587
+ console.error("Error: OPENROUTER_API_KEY environment variable is required");
588
+ console.error(
589
+ "For MCP clients, add it to the 'env' section of your server config."
590
+ );
591
+ console.error(
592
+ "For local development, create a .env file with: OPENROUTER_API_KEY=your-key"
593
+ );
594
+ process.exit(1);
595
+ }
596
+ var client = new ReviewClient(OPENROUTER_API_KEY);
597
+ var server = new McpServer({
598
+ name: "code-council",
599
+ version: "1.0.0"
31
600
  });
32
- // Register review tools
33
601
  createReviewTool(server, {
34
- name: "review_code",
35
- description: "Review code for quality, bugs, performance, and security issues using multiple AI models in parallel",
36
- inputSchema: codeReviewSchema,
37
- handler: (input) => handleCodeReview(client, input),
602
+ name: "review_code",
603
+ description: "Review code for quality, bugs, performance, and security issues using multiple AI models in parallel",
604
+ inputSchema: codeReviewSchema,
605
+ handler: (input) => handleCodeReview(client, input)
38
606
  });
39
607
  createReviewTool(server, {
40
- name: "review_frontend",
41
- description: "Review frontend code for accessibility, performance, UX, and best practices using multiple AI models in parallel",
42
- inputSchema: frontendReviewSchema,
43
- handler: (input) => handleFrontendReview(client, input),
608
+ name: "review_frontend",
609
+ description: "Review frontend code for accessibility, performance, UX, and best practices using multiple AI models in parallel",
610
+ inputSchema: frontendReviewSchema,
611
+ handler: (input) => handleFrontendReview(client, input)
44
612
  });
45
613
  createReviewTool(server, {
46
- name: "review_backend",
47
- description: "Review backend code for security, performance, architecture, and best practices using multiple AI models in parallel",
48
- inputSchema: backendReviewSchema,
49
- handler: (input) => handleBackendReview(client, input),
614
+ name: "review_backend",
615
+ description: "Review backend code for security, performance, architecture, and best practices using multiple AI models in parallel",
616
+ inputSchema: backendReviewSchema,
617
+ handler: (input) => handleBackendReview(client, input)
50
618
  });
51
619
  createReviewTool(server, {
52
- name: "review_plan",
53
- description: "Review implementation plans BEFORE coding to catch issues early using multiple AI models in parallel",
54
- inputSchema: planReviewSchema,
55
- handler: (input) => handlePlanReview(client, input),
620
+ name: "review_plan",
621
+ description: "Review implementation plans BEFORE coding to catch issues early using multiple AI models in parallel",
622
+ inputSchema: planReviewSchema,
623
+ handler: (input) => handlePlanReview(client, input)
56
624
  });
57
- // Register config tool
58
- server.registerTool("list_review_config", { description: "Show current model configuration" }, async () => {
625
+ server.registerTool(
626
+ "list_review_config",
627
+ { description: "Show current model configuration" },
628
+ async () => {
59
629
  const { text } = await handleListConfig();
60
630
  return {
61
- content: [{ type: "text", text }],
631
+ content: [{ type: "text", text }]
62
632
  };
63
- });
64
- // Start server
633
+ }
634
+ );
65
635
  async function main() {
66
- const transport = new StdioServerTransport();
67
- await server.connect(transport);
68
- logger.info("Code Council MCP server started", {
69
- codeReviewModels: CODE_REVIEW_MODELS,
70
- frontendReviewModels: FRONTEND_REVIEW_MODELS,
71
- backendReviewModels: BACKEND_REVIEW_MODELS,
72
- planReviewModels: PLAN_REVIEW_MODELS,
73
- });
636
+ const transport = new StdioServerTransport();
637
+ await server.connect(transport);
638
+ logger.info("Code Council MCP server started", {
639
+ codeReviewModels: CODE_REVIEW_MODELS,
640
+ frontendReviewModels: FRONTEND_REVIEW_MODELS,
641
+ backendReviewModels: BACKEND_REVIEW_MODELS,
642
+ planReviewModels: PLAN_REVIEW_MODELS
643
+ });
74
644
  }
75
645
  main().catch((error) => {
76
- logger.error("Fatal error during server startup", error);
77
- process.exit(1);
646
+ logger.error("Fatal error during server startup", error);
647
+ process.exit(1);
78
648
  });
79
649
  //# sourceMappingURL=index.js.map