@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 +74 -0
- package/dist/brutalist-server.d.ts +17 -0
- package/dist/brutalist-server.d.ts.map +1 -0
- package/dist/brutalist-server.js +368 -0
- package/dist/brutalist-server.js.map +1 -0
- package/dist/constants.d.ts +11 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +16 -0
- package/dist/constants.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +12 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +32 -0
- package/dist/logger.js.map +1 -0
- package/dist/model-fetcher.d.ts +14 -0
- package/dist/model-fetcher.d.ts.map +1 -0
- package/dist/model-fetcher.js +71 -0
- package/dist/model-fetcher.js.map +1 -0
- package/dist/openrouter.d.ts +14 -0
- package/dist/openrouter.d.ts.map +1 -0
- package/dist/openrouter.js +123 -0
- package/dist/openrouter.js.map +1 -0
- package/dist/types/brutalist.d.ts +26 -0
- package/dist/types/brutalist.d.ts.map +1 -0
- package/dist/types/brutalist.js +2 -0
- package/dist/types/brutalist.js.map +1 -0
- package/package.json +77 -0
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"}
|
package/dist/index.d.ts
ADDED
|
@@ -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"}
|
package/dist/logger.d.ts
ADDED
|
@@ -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 @@
|
|
|
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
|
+
}
|