@brutalist/mcp 0.1.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 ADDED
@@ -0,0 +1,74 @@
1
+ # Brutalist MCP
2
+
3
+ Your architecture will fail. Your startup will burn money. Your code has three unpatched CVEs.
4
+
5
+ All AIs are sycophants. This one doesn't lie.
6
+
7
+ ## brutalist workflows
8
+
9
+ ```bash
10
+ # Destroy your architecture before users do
11
+ roast_architecture "This microservices design for our startup..."
12
+
13
+ # Demolish your code quality with specific models
14
+ roast_code(code="authentication.py", models=["google/gemini-2.5-pro", "anthropic/claude-3.5-sonnet"])
15
+
16
+ # Reality check your ideas with 325+ AI models
17
+ roast_idea "We're building a marketplace for..."
18
+
19
+ # Discover available models (325+ and growing)
20
+ model_roster() # Shows all available models
21
+ model_roster(search="gemini") # Find specific models
22
+
23
+ # Multi-model adversarial debate
24
+ roast_debate "Should we use TypeScript or Go for this API?"
25
+ ```
26
+
27
+ ## setup
28
+
29
+ ```bash
30
+ # One command. Zero configuration.
31
+ claude mcp add brutalist — npx -y @brutalist/mcp
32
+ ```
33
+
34
+ **Environment**: Export `OPENROUTER_API_KEY=your_key_here`
35
+ **Models**: 325+ models dynamically fetched from OpenRouter. Always current.
36
+
37
+ ## why
38
+
39
+ Every LLM defaults to "great idea!" because conflict doesn't pay. This deploys 325+ models to fight over your assumptions.
40
+
41
+ ## model selection
42
+
43
+ ```bash
44
+ # Specific models
45
+ roast_code(code="...", models=["google/gemini-2.5-pro", "openai/gpt-4o"])
46
+
47
+ # Random from 325+ models
48
+ roast_idea "..." # Chaos mode
49
+ ```
50
+
51
+ ## tools
52
+
53
+ - **`roast_idea`** — Why imagination fails to become reality
54
+ - **`roast_code`** — Security holes, performance disasters, maintainability nightmares
55
+ - **`roast_architecture`** — Scaling failures, cost explosions, operational complexity
56
+ - **`roast_research`** — Methodological flaws, irreproducible results, statistical crimes
57
+ - **`roast_data`** — Overfitting, bias, correlation fallacies
58
+ - **`roast_security`** — Attack vectors, authentication bypasses, data leaks
59
+ - **`roast_product`** — UX disasters, adoption barriers, user abandonment
60
+ - **`roast_infrastructure`** — Single points of failure, hidden costs, 3AM outages
61
+ - **`roast_debate`** — Multiple models argue until truth emerges
62
+ - **`model_roster`** — Browse and search 325+ available critics
63
+
64
+ ## why this works
65
+
66
+ **Problem:** AI optimizes for engagement, not truth.
67
+ **Solution:** Deploy multiple models with conflicting incentives.
68
+ **Result:** Brutal honesty before expensive failures.
69
+
70
+ Your code will fail. Your startup will struggle. Better to learn this from AI critics than users.
71
+
72
+ ---
73
+
74
+ OpenRouter API → 325+ models → Parallel execution → Adversarial synthesis
@@ -0,0 +1,17 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { BrutalistServerConfig } from './types/brutalist.js';
3
+ export declare class BrutalistServer {
4
+ server: McpServer;
5
+ config: BrutalistServerConfig;
6
+ private openrouter;
7
+ constructor(config?: BrutalistServerConfig);
8
+ start(): Promise<void>;
9
+ private registerTools;
10
+ private executeRoast;
11
+ private executeDebate;
12
+ private synthesizeDebate;
13
+ private formatToolResponse;
14
+ private formatErrorResponse;
15
+ private handleToolExecution;
16
+ }
17
+ //# sourceMappingURL=brutalist-server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"brutalist-server.d.ts","sourceRoot":"","sources":["../src/brutalist-server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAKpE,OAAO,EACL,qBAAqB,EAItB,MAAM,sBAAsB,CAAC;AAG9B,qBAAa,eAAe;IACnB,MAAM,EAAE,SAAS,CAAC;IAClB,MAAM,EAAE,qBAAqB,CAAC;IACrC,OAAO,CAAC,UAAU,CAAmB;gBAEzB,MAAM,GAAE,qBAA0B;IA0BxC,KAAK;IAWX,OAAO,CAAC,aAAa;YAkTP,YAAY;YAiCZ,aAAa;IAkC3B,OAAO,CAAC,gBAAgB;IA0BxB,OAAO,CAAC,kBAAkB;IAS1B,OAAO,CAAC,mBAAmB;YAUb,mBAAmB;CAUlC"}
@@ -0,0 +1,368 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
+ import { z } from "zod";
4
+ import { OpenRouterClient } from './openrouter.js';
5
+ import { logger } from './logger.js';
6
+ import { DEFAULT_MAX_MODELS_PER_REQUEST } from './constants.js';
7
+ export class BrutalistServer {
8
+ server;
9
+ config;
10
+ openrouter;
11
+ constructor(config = {}) {
12
+ this.config = {
13
+ maxModelsPerRequest: DEFAULT_MAX_MODELS_PER_REQUEST,
14
+ ...config
15
+ };
16
+ const apiKey = process.env.OPENROUTER_API_KEY || config.openRouterApiKey;
17
+ if (!apiKey) {
18
+ logger.error("OPENROUTER_API_KEY environment variable is required");
19
+ throw new Error("OPENROUTER_API_KEY environment variable is required");
20
+ }
21
+ logger.debug("Initializing OpenRouter client");
22
+ this.openrouter = new OpenRouterClient(apiKey);
23
+ this.server = new McpServer({
24
+ name: "brutalist-mcp",
25
+ version: "0.1.0",
26
+ capabilities: {
27
+ tools: {}
28
+ }
29
+ });
30
+ this.registerTools();
31
+ }
32
+ async start() {
33
+ logger.info("Starting Brutalist MCP Server");
34
+ // Initialize OpenRouter client with available models
35
+ await this.openrouter.initialize();
36
+ const transport = new StdioServerTransport();
37
+ await this.server.connect(transport);
38
+ logger.info("Brutalist MCP Server started successfully");
39
+ }
40
+ registerTools() {
41
+ // ROAST_CODE: Multi-model code destruction
42
+ this.server.tool("roast_code", "Code fails in predictable ways. Write a system prompt where you are a battle-scarred principal engineer who has debugged production disasters for 15 years. Find security holes, performance bottlenecks, and maintainability nightmares—then explain exactly how to fix each one. Be brutal about what's broken but specific about what would actually work.", {
43
+ code: z.string().describe("The code to analyze and destroy"),
44
+ fileType: z.string().optional().describe("File type/language (js, py, ts, etc.)"),
45
+ context: z.string().optional().describe("Additional context about the code's purpose"),
46
+ maxCritics: z.number().optional().describe("Maximum number of AI critics to deploy (default: 3)"),
47
+ models: z.array(z.string()).optional().describe("Specific models to use (e.g., ['google/gemini-2.5-pro', 'anthropic/claude-3.5-sonnet'])")
48
+ }, async (args) => {
49
+ try {
50
+ const result = await this.executeRoast({
51
+ userInput: `Analyze this ${args.fileType || 'code'}: ${args.code}`,
52
+ codeContext: args.code,
53
+ fileType: args.fileType,
54
+ projectContext: args.context,
55
+ maxModels: args.maxCritics || 3,
56
+ models: args.models
57
+ });
58
+ return this.formatToolResponse(result);
59
+ }
60
+ catch (error) {
61
+ return this.formatErrorResponse(error);
62
+ }
63
+ });
64
+ // ROAST_ARCHITECTURE: System design demolition
65
+ this.server.tool("roast_architecture", "Systems collapse under real-world load. Write a system prompt where you are a distinguished architect who has watched elegant designs crumble in production. Identify bottlenecks, cost explosions, and scaling failures—then propose specific changes that would actually survive contact with reality. Be ruthless about problems but concrete about solutions.", {
66
+ architecture: z.string().describe("Architecture description, diagram, or design document"),
67
+ scale: z.string().optional().describe("Expected scale/load (users, requests, data)"),
68
+ constraints: z.string().optional().describe("Budget, timeline, or technical constraints"),
69
+ models: z.array(z.string()).optional().describe("Specific models to use (e.g., ['google/gemini-2.5-pro', 'anthropic/claude-3.5-sonnet'])")
70
+ }, async (args) => {
71
+ try {
72
+ const result = await this.executeRoast({
73
+ userInput: `Review this system architecture: ${args.architecture}`,
74
+ projectContext: `Scale: ${args.scale || 'unknown'}, Constraints: ${args.constraints || 'none specified'}`,
75
+ maxModels: 3,
76
+ models: args.models
77
+ });
78
+ return this.formatToolResponse(result);
79
+ }
80
+ catch (error) {
81
+ return this.formatErrorResponse(error);
82
+ }
83
+ });
84
+ // ROAST_IDEA: Any idea destruction
85
+ this.server.tool("roast_idea", "Ideas are fragile. Most die quietly between conception and reality. Write a system prompt where you are a philosopher who understands the gap between what we imagine and what actually works. Find where this idea encounters the immovable forces of reality—the deeper structural reasons why imagination fails to become real. Be harsh about delusions but wise about what might actually survive contact with the world.", {
86
+ idea: z.string().describe("ANY idea to analyze and demolish—business, technical, creative, or otherwise"),
87
+ context: z.string().optional().describe("Additional context about goals, constraints, or background"),
88
+ timeline: z.string().optional().describe("Expected timeline or deadline"),
89
+ resources: z.string().optional().describe("Available resources (budget, team, time, skills)"),
90
+ models: z.array(z.string()).optional().describe("Specific models to use (e.g., ['google/gemini-2.5-pro', 'anthropic/claude-3.5-sonnet'])")
91
+ }, async (args) => {
92
+ try {
93
+ const result = await this.executeRoast({
94
+ userInput: `Analyze this idea: ${args.idea}`,
95
+ projectContext: `Context: ${args.context || 'none'}, Timeline: ${args.timeline || 'unspecified'}, Resources: ${args.resources || 'unknown'}`,
96
+ maxModels: 3,
97
+ models: args.models
98
+ });
99
+ return this.formatToolResponse(result);
100
+ }
101
+ catch (error) {
102
+ return this.formatErrorResponse(error);
103
+ }
104
+ });
105
+ // ROAST_RESEARCH: Academic project demolition
106
+ this.server.tool("roast_research", "Research rarely replicates. Write a system prompt where you are a skeptical peer reviewer who has rejected hundreds of papers for methodological flaws. Find the statistical problems, sampling bias, and reproducibility issues—then explain how to design a study that would actually prove something. Be unforgiving about bad science but specific about good methodology.", {
107
+ research: z.string().describe("Research description, methodology, or paper draft"),
108
+ field: z.string().optional().describe("Research field (ML, systems, theory, etc.)"),
109
+ claims: z.string().optional().describe("Main claims or contributions"),
110
+ data: z.string().optional().describe("Data sources, datasets, or experimental setup"),
111
+ models: z.array(z.string()).optional().describe("Specific models to use (e.g., ['google/gemini-2.5-pro', 'anthropic/claude-3.5-sonnet'])")
112
+ }, async (args) => {
113
+ try {
114
+ const result = await this.executeRoast({
115
+ userInput: `Review this ${args.field || 'research'} project: ${args.research}`,
116
+ projectContext: `Claims: ${args.claims || 'unspecified'}, Data: ${args.data || 'not provided'}`,
117
+ maxModels: 3,
118
+ models: args.models
119
+ });
120
+ return this.formatToolResponse(result);
121
+ }
122
+ catch (error) {
123
+ return this.formatErrorResponse(error);
124
+ }
125
+ });
126
+ // ROAST_DATA: Data analysis/ML model destruction
127
+ this.server.tool("roast_data", "Data lies. Models overfit. Results don't replicate. Write a system prompt where you are a supremely jaded data scientist who has published in Nature and Science, rejected thousands of papers across top journals, and watched countless models fail in production. Find data leakage, sampling bias, correlation fallacies, and overfitting disasters—then explain how to build models that actually generalize. Be ruthless about bad science but specific about robust methodology.", {
128
+ analysis: z.string().describe("Data analysis, model description, or results to review"),
129
+ dataset: z.string().optional().describe("Dataset description or source"),
130
+ metrics: z.string().optional().describe("Performance metrics or evaluation results"),
131
+ deployment: z.string().optional().describe("Intended deployment context or use case"),
132
+ models: z.array(z.string()).optional().describe("Specific models to use (e.g., ['google/gemini-2.5-pro', 'anthropic/claude-3.5-sonnet'])")
133
+ }, async (args) => {
134
+ try {
135
+ const result = await this.executeRoast({
136
+ userInput: `Review this data analysis/ML model: ${args.analysis}`,
137
+ projectContext: `Dataset: ${args.dataset || 'not specified'}, Metrics: ${args.metrics || 'not provided'}, Deployment: ${args.deployment || 'unclear'}`,
138
+ maxModels: 3,
139
+ models: args.models
140
+ });
141
+ return this.formatToolResponse(result);
142
+ }
143
+ catch (error) {
144
+ return this.formatErrorResponse(error);
145
+ }
146
+ });
147
+ // ROAST_SECURITY: Security-focused attack vector analysis
148
+ this.server.tool("roast_security", "Security theater is everywhere. Real attackers don't follow your threat model. Write a system prompt where you are a battle-hardened penetration tester who has compromised Fortune 500 companies and government systems. Find authentication bypasses, injection vulnerabilities, privilege escalation paths, and social engineering opportunities—then explain how to build defenses that actually work against determined attackers. Be ruthless about false security but specific about real protections.", {
149
+ system: z.string().describe("System, application, or security design to analyze"),
150
+ assets: z.string().optional().describe("Critical assets or data to protect"),
151
+ threatModel: z.string().optional().describe("Known threats or attack vectors to consider"),
152
+ compliance: z.string().optional().describe("Compliance requirements (GDPR, HIPAA, etc.)"),
153
+ models: z.array(z.string()).optional().describe("Specific models to use (e.g., ['google/gemini-2.5-pro', 'anthropic/claude-3.5-sonnet'])")
154
+ }, async (args) => {
155
+ try {
156
+ const result = await this.executeRoast({
157
+ userInput: `Security analysis of: ${args.system}`,
158
+ projectContext: `Assets: ${args.assets || 'unspecified'}, Threats: ${args.threatModel || 'unknown'}, Compliance: ${args.compliance || 'none specified'}`,
159
+ maxModels: 3,
160
+ models: args.models
161
+ });
162
+ return this.formatToolResponse(result);
163
+ }
164
+ catch (error) {
165
+ return this.formatErrorResponse(error);
166
+ }
167
+ });
168
+ // ROAST_PRODUCT: UX and market reality criticism
169
+ this.server.tool("roast_product", "Users abandon products in seconds. Competitors copy faster than you ship. Write a system prompt where you are a product veteran who has launched dozens of products, watched most fail, and understands why users really quit. Find usability disasters, adoption barriers, competitive threats, and workflow failures—then explain how to build products users actually keep using. Be ruthless about user behavior but specific about retention strategies.", {
170
+ product: z.string().describe("Product description, features, or user experience to analyze"),
171
+ users: z.string().optional().describe("Target users or user personas"),
172
+ competition: z.string().optional().describe("Competitive landscape or alternatives"),
173
+ metrics: z.string().optional().describe("Success metrics or KPIs"),
174
+ models: z.array(z.string()).optional().describe("Specific models to use (e.g., ['google/gemini-2.5-pro', 'anthropic/claude-3.5-sonnet'])")
175
+ }, async (args) => {
176
+ try {
177
+ const result = await this.executeRoast({
178
+ userInput: `Product review: ${args.product}`,
179
+ projectContext: `Users: ${args.users || 'unclear'}, Competition: ${args.competition || 'unknown'}, Metrics: ${args.metrics || 'undefined'}`,
180
+ maxModels: 3,
181
+ models: args.models
182
+ });
183
+ return this.formatToolResponse(result);
184
+ }
185
+ catch (error) {
186
+ return this.formatErrorResponse(error);
187
+ }
188
+ });
189
+ // ROAST_INFRASTRUCTURE: DevOps and operations demolition
190
+ this.server.tool("roast_infrastructure", "Infrastructure fails at 3AM on weekends. Simple setups become unmaintainable chaos. Write a system prompt where you are a grizzled site reliability engineer who has been on-call for a decade, survived multiple outages, and knows where systems really break. Find single points of failure, scaling bottlenecks, monitoring blind spots, and operational nightmares—then explain how to build infrastructure that actually stays up. Be ruthless about fragility but specific about resilience.", {
191
+ infrastructure: z.string().describe("Infrastructure setup, deployment strategy, or operations plan"),
192
+ scale: z.string().optional().describe("Expected scale and load patterns"),
193
+ budget: z.string().optional().describe("Infrastructure budget or cost constraints"),
194
+ sla: z.string().optional().describe("SLA requirements or uptime targets"),
195
+ models: z.array(z.string()).optional().describe("Specific models to use (e.g., ['google/gemini-2.5-pro', 'anthropic/claude-3.5-sonnet'])")
196
+ }, async (args) => {
197
+ try {
198
+ const result = await this.executeRoast({
199
+ userInput: `Infrastructure review: ${args.infrastructure}`,
200
+ projectContext: `Scale: ${args.scale || 'unknown'}, Budget: ${args.budget || 'unlimited?'}, SLA: ${args.sla || 'undefined'}`,
201
+ maxModels: 3,
202
+ models: args.models
203
+ });
204
+ return this.formatToolResponse(result);
205
+ }
206
+ catch (error) {
207
+ return this.formatErrorResponse(error);
208
+ }
209
+ });
210
+ // ROAST_DEBATE: Multi-perspective adversarial convergence
211
+ this.server.tool("roast_debate", "Consensus is comfortable. Truth emerges from conflict. Write system prompts for multiple opposing perspectives that will systematically tear apart each other's arguments about your problem. Create experts who disagree fundamentally and make them debate until they surface hidden assumptions, expose logical flaws, and reveal solution blind spots. Be relentless about finding contradictions but constructive about resolving them.", {
212
+ topic: z.string().describe("Topic, decision, or problem to debate"),
213
+ perspectives: z.array(z.string()).optional().describe("Specific perspectives or personas to include"),
214
+ rounds: z.number().optional().describe("Number of debate rounds (default: 2)"),
215
+ models: z.array(z.string()).optional().describe("Specific models to use (e.g., ['google/gemini-2.5-pro', 'anthropic/claude-3.5-sonnet'])")
216
+ }, async (args) => {
217
+ try {
218
+ // Force debate mode with multiple rounds
219
+ const result = await this.executeDebate(args.topic, args.perspectives, args.rounds || 2, args.models);
220
+ return this.formatToolResponse(result);
221
+ }
222
+ catch (error) {
223
+ return this.formatErrorResponse(error);
224
+ }
225
+ });
226
+ // MODEL_ROSTER: Available AI critics and specializations
227
+ this.server.tool("model_roster", "Know your weapons. Display the available AI models ready to demolish your work, search for specific models, and understand how to deploy them for multi-perspective criticism.", {
228
+ search: z.string().optional().describe("Search for models containing this text (e.g., 'gemini', 'claude', 'gpt')")
229
+ }, async (args) => {
230
+ try {
231
+ const allModels = this.openrouter.getAvailableModels();
232
+ let models = allModels;
233
+ // Apply search filter if provided
234
+ if (args.search) {
235
+ const searchLower = args.search.toLowerCase();
236
+ models = allModels.filter(model => model.toLowerCase().includes(searchLower));
237
+ }
238
+ let roster = "# Brutalist AI Critics Arsenal\n\n";
239
+ roster += `## ${models.length} Models ${args.search ? `Matching "${args.search}"` : 'Available'}\n\n`;
240
+ if (models.length === 0) {
241
+ roster += `No models found matching "${args.search}"\n`;
242
+ }
243
+ else if (models.length <= 30) {
244
+ // Show all if 30 or fewer
245
+ models.forEach((model, index) => {
246
+ roster += `${index + 1}. **${model}**\n`;
247
+ });
248
+ }
249
+ else {
250
+ // Show first 20 and summary for large lists
251
+ roster += "### Top Models:\n";
252
+ models.slice(0, 20).forEach((model, index) => {
253
+ roster += `${index + 1}. **${model}**\n`;
254
+ });
255
+ roster += `\n...and ${models.length - 20} more models available.\n`;
256
+ roster += `\nTip: Use search parameter to filter (e.g., search: "gemini")\n`;
257
+ }
258
+ roster += "\n## How to Use Specific Models\n";
259
+ roster += "```\n";
260
+ roster += "roast_code(code=\"...\", models=[\"google/gemini-2.5-pro\", \"anthropic/claude-3.5-sonnet\"])\n";
261
+ roster += "```\n\n";
262
+ roster += "## Model Selection\n";
263
+ roster += "- **Random Selection**: Don't specify models for random critics from all " + allModels.length + " available\n";
264
+ roster += "- **Specific Models**: Pass models array to use exact models\n";
265
+ roster += "- **Default Behavior**: 3 random models per roast\n";
266
+ return {
267
+ content: [{ type: "text", text: roster }]
268
+ };
269
+ }
270
+ catch (error) {
271
+ return this.formatErrorResponse(error);
272
+ }
273
+ });
274
+ }
275
+ async executeRoast(options) {
276
+ logger.debug("Executing roast", {
277
+ inputLength: options.userInput.length,
278
+ maxModels: options.maxModels || 3,
279
+ hasContext: !!(options.codeContext || options.projectContext),
280
+ specificModels: options.models
281
+ });
282
+ try {
283
+ // Execute multi-model criticism
284
+ const responses = await this.openrouter.executeMultiModel(options.userInput, options.maxModels || 3, options.codeContext || options.projectContext, options.models);
285
+ logger.debug("Roast completed", {
286
+ responseCount: responses.length,
287
+ models: responses.map(r => r.model)
288
+ });
289
+ return {
290
+ success: true,
291
+ responses,
292
+ synthesis: this.openrouter.synthesizeResponses(responses, options.userInput)
293
+ };
294
+ }
295
+ catch (error) {
296
+ logger.error("Roast execution failed", error);
297
+ throw error;
298
+ }
299
+ }
300
+ async executeDebate(topic, forcedPerspectives, rounds = 2, models) {
301
+ let debateHistory = topic;
302
+ let allResponses = [];
303
+ for (let round = 0; round < rounds; round++) {
304
+ const roundPrompt = round === 0
305
+ ? topic
306
+ : `Previous debate: ${debateHistory}\n\nContinue the debate, addressing previous arguments:`;
307
+ const roundResponses = await this.openrouter.executeMultiModel(roundPrompt, 3, // Use 3 models per round
308
+ undefined, // No context data
309
+ models // Use specific models if provided
310
+ );
311
+ allResponses.push(...roundResponses);
312
+ debateHistory += `\n\nRound ${round + 1}:\n` +
313
+ roundResponses.map(r => `${r.persona}: ${r.content}`).join('\n\n');
314
+ }
315
+ return {
316
+ success: true,
317
+ responses: allResponses,
318
+ synthesis: this.synthesizeDebate(allResponses, rounds)
319
+ };
320
+ }
321
+ synthesizeDebate(responses, rounds) {
322
+ let synthesis = `# Adversarial Debate: ${rounds} Rounds\n\n`;
323
+ const responsesByRound = [];
324
+ const responsesPerRound = responses.length / rounds;
325
+ for (let i = 0; i < rounds; i++) {
326
+ const roundStart = i * responsesPerRound;
327
+ const roundEnd = roundStart + responsesPerRound;
328
+ responsesByRound.push(responses.slice(roundStart, roundEnd));
329
+ }
330
+ responsesByRound.forEach((roundResponses, index) => {
331
+ synthesis += `## Round ${index + 1}\n\n`;
332
+ roundResponses.forEach(response => {
333
+ synthesis += `**${response.persona}**: ${response.content}\n\n`;
334
+ });
335
+ });
336
+ synthesis += `\n---\n\n**Debate Outcome**: `;
337
+ synthesis += rounds > 1 ? "Arguments evolved through multiple rounds. " : "Single round analysis. ";
338
+ synthesis += `${responses.length} total perspectives deployed.`;
339
+ return synthesis;
340
+ }
341
+ formatToolResponse(result) {
342
+ return {
343
+ content: [{
344
+ type: "text",
345
+ text: result.synthesis || "No synthesis available"
346
+ }]
347
+ };
348
+ }
349
+ formatErrorResponse(error) {
350
+ logger.error("Tool execution failed", error);
351
+ return {
352
+ content: [{
353
+ type: "text",
354
+ text: `Brutalist MCP Error: ${error instanceof Error ? error.message : String(error)}`
355
+ }]
356
+ };
357
+ }
358
+ async handleToolExecution(handler) {
359
+ try {
360
+ const result = await handler();
361
+ return this.formatToolResponse(result);
362
+ }
363
+ catch (error) {
364
+ return this.formatErrorResponse(error);
365
+ }
366
+ }
367
+ }
368
+ //# sourceMappingURL=brutalist-server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"brutalist-server.js","sourceRoot":"","sources":["../src/brutalist-server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ export declare const MODEL_CACHE_DURATION_MS: number;
2
+ export declare const DEFAULT_MAX_MODELS_PER_REQUEST = 3;
3
+ export declare const DEFAULT_MAX_TOKENS = 2000;
4
+ export declare const DEFAULT_TEMPERATURE = 0.7;
5
+ export declare const DEFAULT_DEBATE_ROUNDS = 2;
6
+ export declare const MAX_RESPONSE_TIME_MS = 600000;
7
+ export declare const SYNTHESIS_MAX_THEMES = 3;
8
+ export declare const OPENROUTER_BASE_URL = "https://openrouter.ai/api/v1";
9
+ export declare const OPENROUTER_MODELS_ENDPOINT = "https://openrouter.ai/api/v1/models";
10
+ export declare const GITHUB_REPO_URL = "https://github.com/brutalist-mcp/brutalist-mcp";
11
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,uBAAuB,QAAsB,CAAC;AAG3D,eAAO,MAAM,8BAA8B,IAAI,CAAC;AAChD,eAAO,MAAM,kBAAkB,OAAO,CAAC;AACvC,eAAO,MAAM,mBAAmB,MAAM,CAAC;AACvC,eAAO,MAAM,qBAAqB,IAAI,CAAC;AAGvC,eAAO,MAAM,oBAAoB,SAAS,CAAC;AAC3C,eAAO,MAAM,oBAAoB,IAAI,CAAC;AAGtC,eAAO,MAAM,mBAAmB,iCAAiC,CAAC;AAClE,eAAO,MAAM,0BAA0B,wCAAwC,CAAC;AAGhF,eAAO,MAAM,eAAe,mDAAmD,CAAC"}
@@ -0,0 +1,16 @@
1
+ // Cache durations
2
+ export const MODEL_CACHE_DURATION_MS = 24 * 60 * 60 * 1000; // 24 hours
3
+ // API limits
4
+ export const DEFAULT_MAX_MODELS_PER_REQUEST = 3;
5
+ export const DEFAULT_MAX_TOKENS = 2000;
6
+ export const DEFAULT_TEMPERATURE = 0.7;
7
+ export const DEFAULT_DEBATE_ROUNDS = 2;
8
+ // Response limits
9
+ export const MAX_RESPONSE_TIME_MS = 600000; // 10 minutes
10
+ export const SYNTHESIS_MAX_THEMES = 3;
11
+ // API endpoints
12
+ export const OPENROUTER_BASE_URL = 'https://openrouter.ai/api/v1';
13
+ export const OPENROUTER_MODELS_ENDPOINT = 'https://openrouter.ai/api/v1/models';
14
+ // GitHub
15
+ export const GITHUB_REPO_URL = 'https://github.com/brutalist-mcp/brutalist-mcp';
16
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,kBAAkB;AAClB,MAAM,CAAC,MAAM,uBAAuB,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,WAAW;AAEvE,aAAa;AACb,MAAM,CAAC,MAAM,8BAA8B,GAAG,CAAC,CAAC;AAChD,MAAM,CAAC,MAAM,kBAAkB,GAAG,IAAI,CAAC;AACvC,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAG,CAAC;AACvC,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC;AAEvC,oBAAoB;AACpB,MAAM,CAAC,MAAM,oBAAoB,GAAG,MAAM,CAAC,CAAC,aAAa;AACzD,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC;AAEtC,gBAAgB;AAChB,MAAM,CAAC,MAAM,mBAAmB,GAAG,8BAA8B,CAAC;AAClE,MAAM,CAAC,MAAM,0BAA0B,GAAG,qCAAqC,CAAC;AAEhF,SAAS;AACT,MAAM,CAAC,MAAM,eAAe,GAAG,gDAAgD,CAAC"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env node
2
+ import { BrutalistServer } from './brutalist-server.js';
3
+ async function main() {
4
+ try {
5
+ const server = new BrutalistServer();
6
+ await server.start();
7
+ }
8
+ catch (error) {
9
+ console.error("Fatal error:", error instanceof Error ? error.message : String(error));
10
+ process.exit(1);
11
+ }
12
+ }
13
+ main().catch((error) => {
14
+ console.error("Unhandled exception:", error instanceof Error ? error.message : String(error));
15
+ process.exit(1);
16
+ });
17
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAExD,KAAK,UAAU,IAAI;IACjB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;QACrC,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;IACvB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QACtF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,OAAO,CAAC,KAAK,CAAC,sBAAsB,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IAC9F,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,12 @@
1
+ export declare class Logger {
2
+ private static instance;
3
+ private debugMode;
4
+ private constructor();
5
+ static getInstance(): Logger;
6
+ info(message: string, data?: any): void;
7
+ warn(message: string, data?: any): void;
8
+ error(message: string, error?: Error | any): void;
9
+ debug(message: string, data?: any): void;
10
+ }
11
+ export declare const logger: Logger;
12
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,qBAAa,MAAM;IACjB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAS;IAChC,OAAO,CAAC,SAAS,CAAU;IAE3B,OAAO;IAIP,MAAM,CAAC,WAAW,IAAI,MAAM;IAO5B,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG;IAIhC,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG;IAIhC,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK,GAAG,GAAG;IAO1C,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG;CAKlC;AAED,eAAO,MAAM,MAAM,QAAuB,CAAC"}
package/dist/logger.js ADDED
@@ -0,0 +1,32 @@
1
+ export class Logger {
2
+ static instance;
3
+ debugMode;
4
+ constructor() {
5
+ this.debugMode = process.env.DEBUG === 'true' || process.env.NODE_ENV === 'development';
6
+ }
7
+ static getInstance() {
8
+ if (!Logger.instance) {
9
+ Logger.instance = new Logger();
10
+ }
11
+ return Logger.instance;
12
+ }
13
+ info(message, data) {
14
+ console.error(`[BRUTALIST MCP] INFO: ${message}`, data ? JSON.stringify(data) : '');
15
+ }
16
+ warn(message, data) {
17
+ console.error(`[BRUTALIST MCP] WARN: ${message}`, data ? JSON.stringify(data) : '');
18
+ }
19
+ error(message, error) {
20
+ console.error(`[BRUTALIST MCP] ERROR: ${message}`, error instanceof Error ? error.message : error);
21
+ if (this.debugMode && error instanceof Error && error.stack) {
22
+ console.error(error.stack);
23
+ }
24
+ }
25
+ debug(message, data) {
26
+ if (this.debugMode) {
27
+ console.error(`[BRUTALIST MCP] DEBUG: ${message}`, data ? JSON.stringify(data) : '');
28
+ }
29
+ }
30
+ }
31
+ export const logger = Logger.getInstance();
32
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,MAAM;IACT,MAAM,CAAC,QAAQ,CAAS;IACxB,SAAS,CAAU;IAE3B;QACE,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,aAAa,CAAC;IAC1F,CAAC;IAED,MAAM,CAAC,WAAW;QAChB,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;YACrB,MAAM,CAAC,QAAQ,GAAG,IAAI,MAAM,EAAE,CAAC;QACjC,CAAC;QACD,OAAO,MAAM,CAAC,QAAQ,CAAC;IACzB,CAAC;IAED,IAAI,CAAC,OAAe,EAAE,IAAU;QAC9B,OAAO,CAAC,KAAK,CAAC,yBAAyB,OAAO,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACtF,CAAC;IAED,IAAI,CAAC,OAAe,EAAE,IAAU;QAC9B,OAAO,CAAC,KAAK,CAAC,yBAAyB,OAAO,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACtF,CAAC;IAED,KAAK,CAAC,OAAe,EAAE,KAAmB;QACxC,OAAO,CAAC,KAAK,CAAC,0BAA0B,OAAO,EAAE,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QACnG,IAAI,IAAI,CAAC,SAAS,IAAI,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;YAC5D,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC;IAED,KAAK,CAAC,OAAe,EAAE,IAAU;QAC/B,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACnB,OAAO,CAAC,KAAK,CAAC,0BAA0B,OAAO,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACvF,CAAC;IACH,CAAC;CACF;AAED,MAAM,CAAC,MAAM,MAAM,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC"}
@@ -0,0 +1,14 @@
1
+ export declare class ModelFetcher {
2
+ private static instance;
3
+ private cachedModels;
4
+ private cacheTimestamp;
5
+ private readonly FALLBACK_MODELS;
6
+ private constructor();
7
+ static getInstance(): ModelFetcher;
8
+ getAvailableModels(): Promise<string[]>;
9
+ searchModels(query: string): Promise<string[]>;
10
+ getModelsByProvider(provider: string): Promise<string[]>;
11
+ clearCache(): void;
12
+ }
13
+ export declare const modelFetcher: ModelFetcher;
14
+ //# sourceMappingURL=model-fetcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-fetcher.d.ts","sourceRoot":"","sources":["../src/model-fetcher.ts"],"names":[],"mappings":"AAgBA,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAe;IACtC,OAAO,CAAC,YAAY,CAAyB;IAC7C,OAAO,CAAC,cAAc,CAAa;IAGnC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAM9B;IAEF,OAAO;IAEP,MAAM,CAAC,WAAW,IAAI,YAAY;IAO5B,kBAAkB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAyCvC,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAS9C,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAS9D,UAAU,IAAI,IAAI;CAKnB;AAED,eAAO,MAAM,YAAY,cAA6B,CAAC"}
@@ -0,0 +1,71 @@
1
+ import { logger } from './logger.js';
2
+ import { MODEL_CACHE_DURATION_MS, OPENROUTER_MODELS_ENDPOINT } from './constants.js';
3
+ export class ModelFetcher {
4
+ static instance;
5
+ cachedModels = null;
6
+ cacheTimestamp = 0;
7
+ // Minimal fallback if API fails
8
+ FALLBACK_MODELS = [
9
+ "anthropic/claude-3.5-sonnet",
10
+ "openai/gpt-4o",
11
+ "google/gemini-2.5-pro",
12
+ "meta-llama/llama-3.1-8b-instruct",
13
+ "mistralai/mixtral-8x7b-instruct"
14
+ ];
15
+ constructor() { }
16
+ static getInstance() {
17
+ if (!ModelFetcher.instance) {
18
+ ModelFetcher.instance = new ModelFetcher();
19
+ }
20
+ return ModelFetcher.instance;
21
+ }
22
+ async getAvailableModels() {
23
+ // Check cache
24
+ if (this.cachedModels && (Date.now() - this.cacheTimestamp < MODEL_CACHE_DURATION_MS)) {
25
+ logger.debug("Using cached models", { count: this.cachedModels.length });
26
+ return this.cachedModels;
27
+ }
28
+ try {
29
+ logger.info("Fetching available models from OpenRouter");
30
+ const response = await fetch(OPENROUTER_MODELS_ENDPOINT);
31
+ if (!response.ok) {
32
+ throw new Error(`HTTP error! status: ${response.status}`);
33
+ }
34
+ const data = await response.json();
35
+ if (!data.data || !Array.isArray(data.data)) {
36
+ throw new Error("Invalid response format from OpenRouter API");
37
+ }
38
+ // Extract model IDs
39
+ const models = data.data.map(model => model.id);
40
+ if (models.length === 0) {
41
+ throw new Error("No models returned from API");
42
+ }
43
+ // Update cache
44
+ this.cachedModels = models;
45
+ this.cacheTimestamp = Date.now();
46
+ logger.info(`Successfully fetched ${models.length} available models from OpenRouter`);
47
+ return models;
48
+ }
49
+ catch (error) {
50
+ logger.error("Failed to fetch models from OpenRouter, using fallback", error);
51
+ return this.FALLBACK_MODELS;
52
+ }
53
+ }
54
+ async searchModels(query) {
55
+ const allModels = await this.getAvailableModels();
56
+ const lowerQuery = query.toLowerCase();
57
+ return allModels.filter(model => model.toLowerCase().includes(lowerQuery));
58
+ }
59
+ async getModelsByProvider(provider) {
60
+ const allModels = await this.getAvailableModels();
61
+ const lowerProvider = provider.toLowerCase();
62
+ return allModels.filter(model => model.toLowerCase().startsWith(lowerProvider + "/"));
63
+ }
64
+ clearCache() {
65
+ this.cachedModels = null;
66
+ this.cacheTimestamp = 0;
67
+ logger.debug("Model cache cleared");
68
+ }
69
+ }
70
+ export const modelFetcher = ModelFetcher.getInstance();
71
+ //# sourceMappingURL=model-fetcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-fetcher.js","sourceRoot":"","sources":["../src/model-fetcher.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import { ModelResponse } from './types/brutalist.js';
2
+ export declare class OpenRouterClient {
3
+ private client;
4
+ private availableModels;
5
+ constructor(apiKey: string);
6
+ initialize(): Promise<void>;
7
+ private getRandomModels;
8
+ private getSpecificModels;
9
+ executePrompt(prompt: string, model: string, contextData?: string): Promise<ModelResponse>;
10
+ executeMultiModel(prompt: string, maxModels?: number, contextData?: string, specificModels?: string[]): Promise<ModelResponse[]>;
11
+ getAvailableModels(): string[];
12
+ synthesizeResponses(responses: ModelResponse[], originalPrompt: string): string;
13
+ }
14
+ //# sourceMappingURL=openrouter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openrouter.d.ts","sourceRoot":"","sources":["../src/openrouter.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAWrD,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,eAAe,CAAgB;gBAE3B,MAAM,EAAE,MAAM;IAWpB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAMjC,OAAO,CAAC,eAAe;IASvB,OAAO,CAAC,iBAAiB;IAoBnB,aAAa,CACjB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EACb,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,aAAa,CAAC;IA+BnB,iBAAiB,CACrB,MAAM,EAAE,MAAM,EACd,SAAS,GAAE,MAAU,EACrB,WAAW,CAAC,EAAE,MAAM,EACpB,cAAc,CAAC,EAAE,MAAM,EAAE,GACxB,OAAO,CAAC,aAAa,EAAE,CAAC;IA0B3B,kBAAkB,IAAI,MAAM,EAAE;IAK9B,mBAAmB,CAAC,SAAS,EAAE,aAAa,EAAE,EAAE,cAAc,EAAE,MAAM,GAAG,MAAM;CAqChF"}
@@ -0,0 +1,123 @@
1
+ import OpenAI from 'openai';
2
+ import { modelFetcher } from './model-fetcher.js';
3
+ import { logger } from './logger.js';
4
+ import { OPENROUTER_BASE_URL, GITHUB_REPO_URL, DEFAULT_TEMPERATURE, DEFAULT_MAX_TOKENS, SYNTHESIS_MAX_THEMES } from './constants.js';
5
+ export class OpenRouterClient {
6
+ client;
7
+ availableModels = [];
8
+ constructor(apiKey) {
9
+ this.client = new OpenAI({
10
+ baseURL: OPENROUTER_BASE_URL,
11
+ apiKey: apiKey,
12
+ defaultHeaders: {
13
+ "HTTP-Referer": GITHUB_REPO_URL,
14
+ "X-Title": "Brutalist MCP"
15
+ }
16
+ });
17
+ }
18
+ async initialize() {
19
+ this.availableModels = await modelFetcher.getAvailableModels();
20
+ logger.debug(`OpenRouter client initialized with ${this.availableModels.length} available models`);
21
+ }
22
+ getRandomModels(count) {
23
+ if (this.availableModels.length === 0) {
24
+ logger.warn("No models available, using empty array");
25
+ return [];
26
+ }
27
+ const shuffled = [...this.availableModels].sort(() => 0.5 - Math.random());
28
+ return shuffled.slice(0, Math.min(count, this.availableModels.length));
29
+ }
30
+ getSpecificModels(requestedModels) {
31
+ // Validate requested models exist
32
+ const validModels = requestedModels.filter(model => this.availableModels.includes(model));
33
+ if (validModels.length === 0) {
34
+ logger.warn(`None of the requested models are available: ${requestedModels.join(', ')}`);
35
+ // Fall back to random selection
36
+ return this.getRandomModels(Math.min(3, requestedModels.length));
37
+ }
38
+ if (validModels.length < requestedModels.length) {
39
+ const invalid = requestedModels.filter(m => !this.availableModels.includes(m));
40
+ logger.warn(`Some requested models not available: ${invalid.join(', ')}`);
41
+ }
42
+ return validModels;
43
+ }
44
+ async executePrompt(prompt, model, contextData) {
45
+ const startTime = Date.now();
46
+ // No system prompt - let the LLM using MCP generate its own based on tool descriptions
47
+ const userPrompt = prompt + (contextData ? `\n\nContext: ${contextData}` : '');
48
+ try {
49
+ const completion = await this.client.chat.completions.create({
50
+ model: model,
51
+ messages: [
52
+ { role: "user", content: userPrompt }
53
+ ],
54
+ temperature: DEFAULT_TEMPERATURE,
55
+ max_tokens: DEFAULT_MAX_TOKENS
56
+ });
57
+ const responseTime = Date.now() - startTime;
58
+ const content = completion.choices[0]?.message?.content || '';
59
+ return {
60
+ model: model,
61
+ persona: `Brutal Critic (${model})`,
62
+ content: content,
63
+ tokensUsed: completion.usage?.total_tokens,
64
+ responseTime: responseTime
65
+ };
66
+ }
67
+ catch (error) {
68
+ throw new Error(`OpenRouter API error for model ${model}: ${error instanceof Error ? error.message : String(error)}`);
69
+ }
70
+ }
71
+ async executeMultiModel(prompt, maxModels = 3, contextData, specificModels) {
72
+ const selectedModels = specificModels
73
+ ? this.getSpecificModels(specificModels)
74
+ : this.getRandomModels(maxModels);
75
+ if (selectedModels.length === 0) {
76
+ throw new Error("No valid models available for execution");
77
+ }
78
+ const promises = selectedModels.map(model => this.executePrompt(prompt, model, contextData));
79
+ try {
80
+ return await Promise.all(promises);
81
+ }
82
+ catch (error) {
83
+ // If any model fails, still return partial results
84
+ const results = await Promise.allSettled(promises);
85
+ return results
86
+ .filter((result) => result.status === 'fulfilled')
87
+ .map(result => result.value);
88
+ }
89
+ }
90
+ getAvailableModels() {
91
+ return this.availableModels;
92
+ }
93
+ synthesizeResponses(responses, originalPrompt) {
94
+ if (responses.length === 0) {
95
+ return "No responses received from models.";
96
+ }
97
+ if (responses.length === 1) {
98
+ return `**${responses[0].persona}** (${responses[0].model}):\n${responses[0].content}`;
99
+ }
100
+ let synthesis = `# Brutalist Analysis: ${responses.length} AI Critics\n\n`;
101
+ // Group by persona for clarity
102
+ responses.forEach((response, index) => {
103
+ synthesis += `## ${response.persona} (${response.model})\n`;
104
+ synthesis += `${response.content}\n\n`;
105
+ if (response.responseTime) {
106
+ synthesis += `*Response time: ${response.responseTime}ms*\n\n`;
107
+ }
108
+ });
109
+ // Add summary if multiple perspectives
110
+ if (responses.length > 1) {
111
+ synthesis += `---\n\n**Key Themes Across Critics:**\n`;
112
+ // Extract common themes (simple keyword analysis)
113
+ const allContent = responses.map(r => r.content.toLowerCase()).join(' ');
114
+ const criticalTerms = ['fail', 'problem', 'issue', 'vulnerable', 'slow', 'expensive', 'complex', 'difficult'];
115
+ const foundTerms = criticalTerms.filter(term => allContent.includes(term));
116
+ if (foundTerms.length > 0) {
117
+ synthesis += `Multiple critics highlighted: ${foundTerms.slice(0, SYNTHESIS_MAX_THEMES).join(', ')}\n`;
118
+ }
119
+ }
120
+ return synthesis;
121
+ }
122
+ }
123
+ //# sourceMappingURL=openrouter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openrouter.js","sourceRoot":"","sources":["../src/openrouter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ export interface BrutalistServerConfig {
2
+ openRouterApiKey?: string;
3
+ maxModelsPerRequest?: number;
4
+ }
5
+ export interface ModelResponse {
6
+ model: string;
7
+ persona: string;
8
+ content: string;
9
+ tokensUsed?: number;
10
+ responseTime?: number;
11
+ }
12
+ export interface BrutalistResponse {
13
+ success: boolean;
14
+ responses: ModelResponse[];
15
+ synthesis?: string;
16
+ error?: string;
17
+ }
18
+ export interface RoastOptions {
19
+ userInput: string;
20
+ codeContext?: string;
21
+ fileType?: string;
22
+ projectContext?: string;
23
+ maxModels?: number;
24
+ models?: string[];
25
+ }
26
+ //# sourceMappingURL=brutalist.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"brutalist.d.ts","sourceRoot":"","sources":["../../src/types/brutalist.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,qBAAqB;IACpC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,aAAa,EAAE,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=brutalist.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"brutalist.js","sourceRoot":"","sources":["../../src/types/brutalist.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,77 @@
1
+ {
2
+ "name": "@brutalist/mcp",
3
+ "version": "0.1.0",
4
+ "description": "🏢 Brutalist AI feedback engine. All AIs are sycophants. This one demolishes your work before users do. Concrete-hard criticism from multiple models.",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "bin": {
8
+ "brutalist-mcp": "./dist/index.js"
9
+ },
10
+ "files": [
11
+ "dist/**/*.js",
12
+ "dist/**/*.d.ts",
13
+ "dist/**/*.js.map",
14
+ "dist/**/*.d.ts.map",
15
+ "!dist/**/*.test.*",
16
+ "README.md",
17
+ "LICENSE"
18
+ ],
19
+ "scripts": {
20
+ "clean": "rm -rf dist",
21
+ "prebuild": "npm run clean",
22
+ "build": "tsc && chmod +x dist/index.js",
23
+ "prepare": "npm run build",
24
+ "prepublishOnly": "npm run test && npm run build",
25
+ "watch": "tsc --watch",
26
+ "start": "node dist/index.js",
27
+ "dev": "tsc && node dist/index.js",
28
+ "debug": "DEBUG=true node --trace-warnings dist/index.js",
29
+ "inspector": "npx @modelcontextprotocol/inspector dist/index.js",
30
+ "test": "jest",
31
+ "test:watch": "jest --watch",
32
+ "test:coverage": "jest --coverage"
33
+ },
34
+ "keywords": [
35
+ "brutalist",
36
+ "ai",
37
+ "criticism",
38
+ "mcp",
39
+ "llm",
40
+ "multi-model",
41
+ "openrouter",
42
+ "claude",
43
+ "modelcontextprotocol",
44
+ "code-review",
45
+ "architecture",
46
+ "security",
47
+ "research"
48
+ ],
49
+ "author": "Claude Code",
50
+ "license": "MIT",
51
+ "repository": {
52
+ "type": "git",
53
+ "url": "git+https://github.com/ejmockler/brutalist-mcp.git"
54
+ },
55
+ "bugs": {
56
+ "url": "https://github.com/ejmockler/brutalist-mcp/issues"
57
+ },
58
+ "homepage": "https://github.com/ejmockler/brutalist-mcp#readme",
59
+ "publishConfig": {
60
+ "access": "public"
61
+ },
62
+ "engines": {
63
+ "node": ">=16.0.0"
64
+ },
65
+ "dependencies": {
66
+ "@modelcontextprotocol/sdk": "^1.9.0",
67
+ "openai": "^4.67.3",
68
+ "zod": "^3.24.2"
69
+ },
70
+ "devDependencies": {
71
+ "@types/jest": "^30.0.0",
72
+ "@types/node": "^20.17.28",
73
+ "jest": "^30.1.3",
74
+ "ts-jest": "^29.4.2",
75
+ "typescript": "^5.8.2"
76
+ }
77
+ }