senior-consult-mcp 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +137 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +180 -0
- package/dist/index.js.map +1 -0
- package/dist/providers/claude.d.ts +7 -0
- package/dist/providers/claude.js +34 -0
- package/dist/providers/claude.js.map +1 -0
- package/dist/providers/gemini.d.ts +7 -0
- package/dist/providers/gemini.js +35 -0
- package/dist/providers/gemini.js.map +1 -0
- package/dist/providers/index.d.ts +3 -0
- package/dist/providers/index.js +39 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/providers/openai-compatible.d.ts +7 -0
- package/dist/providers/openai-compatible.js +38 -0
- package/dist/providers/openai-compatible.js.map +1 -0
- package/dist/providers/openai.d.ts +7 -0
- package/dist/providers/openai.js +34 -0
- package/dist/providers/openai.js.map +1 -0
- package/dist/providers/zai.d.ts +7 -0
- package/dist/providers/zai.js +34 -0
- package/dist/providers/zai.js.map +1 -0
- package/dist/tools/architecture-advice.d.ts +7 -0
- package/dist/tools/architecture-advice.js +25 -0
- package/dist/tools/architecture-advice.js.map +1 -0
- package/dist/tools/ask-senior.d.ts +7 -0
- package/dist/tools/ask-senior.js +18 -0
- package/dist/tools/ask-senior.js.map +1 -0
- package/dist/tools/code-review.d.ts +7 -0
- package/dist/tools/code-review.js +29 -0
- package/dist/tools/code-review.js.map +1 -0
- package/dist/types.d.ts +36 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +42 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Bundit Nuntates
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# Senior Consult MCP Server
|
|
2
|
+
|
|
3
|
+
An MCP (Model Context Protocol) server that allows a junior AI agent to consult senior AI providers (Claude, Gemini, OpenAI, Z.ai, and OpenAI-Compatible) for guidance.
|
|
4
|
+
|
|
5
|
+
## Tools
|
|
6
|
+
|
|
7
|
+
### 1. `ask_senior`
|
|
8
|
+
|
|
9
|
+
General purpose consultation.
|
|
10
|
+
|
|
11
|
+
- `question`: The question or problem.
|
|
12
|
+
- `context`: (Optional) Code or project context.
|
|
13
|
+
- `provider`: (Optional) "claude", "gemini", "openai", "z.ai", "openai-compatible", or "auto" (default).
|
|
14
|
+
- `model`: (Optional) Specific model to use.
|
|
15
|
+
- `url`: (Optional) Custom API endpoint URL.
|
|
16
|
+
|
|
17
|
+
### 2. `code_review`
|
|
18
|
+
|
|
19
|
+
Request code review.
|
|
20
|
+
|
|
21
|
+
- `code`: Code to review.
|
|
22
|
+
- `language`: (Optional) Programming language.
|
|
23
|
+
- `focus`: (Optional) Specific focus (performance, security, readability).
|
|
24
|
+
- `provider`: (Optional) Default: "auto".
|
|
25
|
+
- `model`: (Optional) Specific model to use.
|
|
26
|
+
- `url`: (Optional) Custom API endpoint URL.
|
|
27
|
+
|
|
28
|
+
### 3. `architecture_advice`
|
|
29
|
+
|
|
30
|
+
Get architecture and design pattern recommendations.
|
|
31
|
+
|
|
32
|
+
- `problem`: Architecture challenge description.
|
|
33
|
+
- `constraints`: (Optional) Technical constraints.
|
|
34
|
+
- `stack`: (Optional) Tech stack being used.
|
|
35
|
+
- `provider`: (Optional) Default: "auto".
|
|
36
|
+
- `model`: (Optional) Specific model to use.
|
|
37
|
+
- `url`: (Optional) Custom API endpoint URL.
|
|
38
|
+
|
|
39
|
+
## Configuration
|
|
40
|
+
|
|
41
|
+
Set the following environment variables:
|
|
42
|
+
|
|
43
|
+
- `ANTHROPIC_API_KEY`
|
|
44
|
+
- `GEMINI_API_KEY`
|
|
45
|
+
- `OPENAI_API_KEY`
|
|
46
|
+
- `ZAI_API_KEY` (or `ZHIPU_API_KEY`)
|
|
47
|
+
- `OPENAI_COMPATIBLE_API_KEY` (for OpenRouter, Groq, etc.)
|
|
48
|
+
|
|
49
|
+
### Using in Windsurf / VSCode MCP
|
|
50
|
+
|
|
51
|
+
Add this to your `mcp_config.json`:
|
|
52
|
+
|
|
53
|
+
```json
|
|
54
|
+
{
|
|
55
|
+
"mcpServers": {
|
|
56
|
+
"senior-consult": {
|
|
57
|
+
"command": "node",
|
|
58
|
+
"args": ["/absolute/path/to/senior-consult-mcp/dist/index.js"],
|
|
59
|
+
"env": {
|
|
60
|
+
"ANTHROPIC_API_KEY": "your-key",
|
|
61
|
+
"GEMINI_API_KEY": "your-key",
|
|
62
|
+
"OPENAI_API_KEY": "your-key",
|
|
63
|
+
"ZAI_API_KEY": "your-key",
|
|
64
|
+
"OPENAI_COMPATIBLE_API_KEY": "your-key"
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Installation
|
|
72
|
+
|
|
73
|
+
### 1. Via npx (Recommended for most users)
|
|
74
|
+
|
|
75
|
+
You can run the server directly without local installation:
|
|
76
|
+
|
|
77
|
+
```json
|
|
78
|
+
{
|
|
79
|
+
"mcpServers": {
|
|
80
|
+
"senior-consult": {
|
|
81
|
+
"command": "npx",
|
|
82
|
+
"args": ["-y", "senior-consult-mcp"],
|
|
83
|
+
"env": {
|
|
84
|
+
"ANTHROPIC_API_KEY": "your-key",
|
|
85
|
+
"GEMINI_API_KEY": "your-key",
|
|
86
|
+
"OPENAI_API_KEY": "your-key",
|
|
87
|
+
"ZAI_API_KEY": "your-key",
|
|
88
|
+
"OPENAI_COMPATIBLE_API_KEY": "your-key"
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### 2. Global Installation
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
npm install -g senior-consult-mcp
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Then use `senior-consult` as the command:
|
|
102
|
+
|
|
103
|
+
```json
|
|
104
|
+
{
|
|
105
|
+
"mcpServers": {
|
|
106
|
+
"senior-consult": {
|
|
107
|
+
"command": "senior-consult",
|
|
108
|
+
"env": {
|
|
109
|
+
"ANTHROPIC_API_KEY": "your-key",
|
|
110
|
+
"GEMINI_API_KEY": "your-key",
|
|
111
|
+
"OPENAI_API_KEY": "your-key",
|
|
112
|
+
"ZAI_API_KEY": "your-key",
|
|
113
|
+
"OPENAI_COMPATIBLE_API_KEY": "your-key"
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Development
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
# Install dependencies
|
|
124
|
+
npm install
|
|
125
|
+
|
|
126
|
+
# Build the project
|
|
127
|
+
npm run build
|
|
128
|
+
|
|
129
|
+
# Start (for testing stdio)
|
|
130
|
+
npm start
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
The server runs on `stdio`.
|
|
134
|
+
|
|
135
|
+
## License
|
|
136
|
+
|
|
137
|
+
MIT
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
3
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
+
import { CallToolRequestSchema, ErrorCode, ListToolsRequestSchema, McpError, } from "@modelcontextprotocol/sdk/types.js";
|
|
5
|
+
import { askSenior } from "./tools/ask-senior.js";
|
|
6
|
+
import { codeReview } from "./tools/code-review.js";
|
|
7
|
+
import { architectureAdvice } from "./tools/architecture-advice.js";
|
|
8
|
+
class SeniorConsultServer {
|
|
9
|
+
server;
|
|
10
|
+
constructor() {
|
|
11
|
+
this.server = new Server({
|
|
12
|
+
name: "senior-consult-mcp",
|
|
13
|
+
version: "1.0.0",
|
|
14
|
+
}, {
|
|
15
|
+
capabilities: {
|
|
16
|
+
tools: {},
|
|
17
|
+
},
|
|
18
|
+
});
|
|
19
|
+
this.setupToolHandlers();
|
|
20
|
+
// Error handling
|
|
21
|
+
this.server.onerror = (error) => console.error("[MCP Error]", error);
|
|
22
|
+
process.on("SIGINT", async () => {
|
|
23
|
+
await this.server.close();
|
|
24
|
+
process.exit(0);
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
setupToolHandlers() {
|
|
28
|
+
this.server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
29
|
+
tools: [
|
|
30
|
+
{
|
|
31
|
+
name: "ask_senior",
|
|
32
|
+
description: "General purpose consultation with a senior AI developer mentor.",
|
|
33
|
+
inputSchema: {
|
|
34
|
+
type: "object",
|
|
35
|
+
properties: {
|
|
36
|
+
question: {
|
|
37
|
+
type: "string",
|
|
38
|
+
description: "The question or problem to solve",
|
|
39
|
+
},
|
|
40
|
+
context: {
|
|
41
|
+
type: "string",
|
|
42
|
+
description: "Optional code or project context",
|
|
43
|
+
},
|
|
44
|
+
provider: {
|
|
45
|
+
type: "string",
|
|
46
|
+
enum: [
|
|
47
|
+
"claude",
|
|
48
|
+
"gemini",
|
|
49
|
+
"openai",
|
|
50
|
+
"z.ai",
|
|
51
|
+
"openai-compatible",
|
|
52
|
+
"auto",
|
|
53
|
+
],
|
|
54
|
+
default: "auto",
|
|
55
|
+
description: "AI provider to use",
|
|
56
|
+
},
|
|
57
|
+
model: {
|
|
58
|
+
type: "string",
|
|
59
|
+
description: "Specific model to use (optional, overrides default)",
|
|
60
|
+
},
|
|
61
|
+
url: {
|
|
62
|
+
type: "string",
|
|
63
|
+
description: "Custom API endpoint URL (optional, overrides default)",
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
required: ["question"],
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
name: "code_review",
|
|
71
|
+
description: "Request a code review from a senior AI developer.",
|
|
72
|
+
inputSchema: {
|
|
73
|
+
type: "object",
|
|
74
|
+
properties: {
|
|
75
|
+
code: { type: "string", description: "The code to review" },
|
|
76
|
+
language: { type: "string", description: "Programming language" },
|
|
77
|
+
focus: {
|
|
78
|
+
type: "string",
|
|
79
|
+
description: "Specific focus (e.g., performance, security, readability)",
|
|
80
|
+
},
|
|
81
|
+
provider: {
|
|
82
|
+
type: "string",
|
|
83
|
+
enum: [
|
|
84
|
+
"claude",
|
|
85
|
+
"gemini",
|
|
86
|
+
"openai",
|
|
87
|
+
"z.ai",
|
|
88
|
+
"openai-compatible",
|
|
89
|
+
"auto",
|
|
90
|
+
],
|
|
91
|
+
default: "auto",
|
|
92
|
+
},
|
|
93
|
+
model: {
|
|
94
|
+
type: "string",
|
|
95
|
+
description: "Specific model to use (optional, overrides default)",
|
|
96
|
+
},
|
|
97
|
+
url: {
|
|
98
|
+
type: "string",
|
|
99
|
+
description: "Custom API endpoint URL (optional, overrides default)",
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
required: ["code"],
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
name: "architecture_advice",
|
|
107
|
+
description: "Get architecture and design pattern recommendations from a senior AI.",
|
|
108
|
+
inputSchema: {
|
|
109
|
+
type: "object",
|
|
110
|
+
properties: {
|
|
111
|
+
problem: {
|
|
112
|
+
type: "string",
|
|
113
|
+
description: "Architecture challenge description",
|
|
114
|
+
},
|
|
115
|
+
constraints: {
|
|
116
|
+
type: "string",
|
|
117
|
+
description: "Technical constraints",
|
|
118
|
+
},
|
|
119
|
+
stack: { type: "string", description: "Tech stack being used" },
|
|
120
|
+
provider: {
|
|
121
|
+
type: "string",
|
|
122
|
+
enum: [
|
|
123
|
+
"claude",
|
|
124
|
+
"gemini",
|
|
125
|
+
"openai",
|
|
126
|
+
"z.ai",
|
|
127
|
+
"openai-compatible",
|
|
128
|
+
"auto",
|
|
129
|
+
],
|
|
130
|
+
default: "auto",
|
|
131
|
+
},
|
|
132
|
+
model: {
|
|
133
|
+
type: "string",
|
|
134
|
+
description: "Specific model to use (optional, overrides default)",
|
|
135
|
+
},
|
|
136
|
+
url: {
|
|
137
|
+
type: "string",
|
|
138
|
+
description: "Custom API endpoint URL (optional, overrides default)",
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
required: ["problem"],
|
|
142
|
+
},
|
|
143
|
+
},
|
|
144
|
+
],
|
|
145
|
+
}));
|
|
146
|
+
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
147
|
+
try {
|
|
148
|
+
switch (request.params.name) {
|
|
149
|
+
case "ask_senior":
|
|
150
|
+
return await askSenior(request.params.arguments);
|
|
151
|
+
case "code_review":
|
|
152
|
+
return await codeReview(request.params.arguments);
|
|
153
|
+
case "architecture_advice":
|
|
154
|
+
return await architectureAdvice(request.params.arguments);
|
|
155
|
+
default:
|
|
156
|
+
throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${request.params.name}`);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
catch (error) {
|
|
160
|
+
return {
|
|
161
|
+
content: [
|
|
162
|
+
{
|
|
163
|
+
type: "text",
|
|
164
|
+
text: `Error: ${error.message}`,
|
|
165
|
+
},
|
|
166
|
+
],
|
|
167
|
+
isError: true,
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
async run() {
|
|
173
|
+
const transport = new StdioServerTransport();
|
|
174
|
+
await this.server.connect(transport);
|
|
175
|
+
console.error("Senior Consult MCP server running on stdio");
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
const server = new SeniorConsultServer();
|
|
179
|
+
server.run().catch(console.error);
|
|
180
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export class ClaudeProvider {
|
|
2
|
+
name = "claude";
|
|
3
|
+
apiKey = process.env.ANTHROPIC_API_KEY;
|
|
4
|
+
canHandle() {
|
|
5
|
+
return !!this.apiKey;
|
|
6
|
+
}
|
|
7
|
+
async ask(prompt, systemPrompt, model, url) {
|
|
8
|
+
if (!this.apiKey)
|
|
9
|
+
throw new Error("ANTHROPIC_API_KEY not found");
|
|
10
|
+
const apiUrl = url || "https://api.anthropic.com/v1/messages";
|
|
11
|
+
const apiModel = model || "claude-3-5-sonnet-latest";
|
|
12
|
+
const response = await fetch(apiUrl, {
|
|
13
|
+
method: "POST",
|
|
14
|
+
headers: {
|
|
15
|
+
"Content-Type": "application/json",
|
|
16
|
+
"x-api-key": this.apiKey,
|
|
17
|
+
"anthropic-version": "2023-06-01",
|
|
18
|
+
},
|
|
19
|
+
body: JSON.stringify({
|
|
20
|
+
model: apiModel,
|
|
21
|
+
max_tokens: 4096,
|
|
22
|
+
system: systemPrompt,
|
|
23
|
+
messages: [{ role: "user", content: prompt }],
|
|
24
|
+
}),
|
|
25
|
+
});
|
|
26
|
+
if (!response.ok) {
|
|
27
|
+
const error = await response.text();
|
|
28
|
+
throw new Error(`Claude API error: ${response.status} ${error}`);
|
|
29
|
+
}
|
|
30
|
+
const data = (await response.json());
|
|
31
|
+
return data.content[0].text;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=claude.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude.js","sourceRoot":"","sources":["../../src/providers/claude.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,cAAc;IACzB,IAAI,GAAG,QAAQ,CAAC;IACR,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;IAE/C,SAAS;QACP,OAAO,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;IACvB,CAAC;IAED,KAAK,CAAC,GAAG,CACP,MAAc,EACd,YAAoB,EACpB,KAAc,EACd,GAAY;QAEZ,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;QAEjE,MAAM,MAAM,GAAG,GAAG,IAAI,uCAAuC,CAAC;QAC9D,MAAM,QAAQ,GAAG,KAAK,IAAI,0BAA0B,CAAC;QAErD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,MAAM,EAAE;YACnC,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,WAAW,EAAE,IAAI,CAAC,MAAM;gBACxB,mBAAmB,EAAE,YAAY;aAClC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,KAAK,EAAE,QAAQ;gBACf,UAAU,EAAE,IAAI;gBAChB,MAAM,EAAE,YAAY;gBACpB,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;aAC9C,CAAC;SACH,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YACpC,MAAM,IAAI,KAAK,CAAC,qBAAqB,QAAQ,CAAC,MAAM,IAAI,KAAK,EAAE,CAAC,CAAC;QACnE,CAAC;QAED,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAQ,CAAC;QAC5C,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC9B,CAAC;CACF"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export class GeminiProvider {
|
|
2
|
+
name = "gemini";
|
|
3
|
+
apiKey = process.env.GEMINI_API_KEY;
|
|
4
|
+
canHandle() {
|
|
5
|
+
return !!this.apiKey;
|
|
6
|
+
}
|
|
7
|
+
async ask(prompt, systemPrompt, model, url) {
|
|
8
|
+
if (!this.apiKey)
|
|
9
|
+
throw new Error("GEMINI_API_KEY not found");
|
|
10
|
+
const apiModel = model || "gemini-2.0-flash";
|
|
11
|
+
const apiUrl = url ||
|
|
12
|
+
`https://generativelanguage.googleapis.com/v1beta/models/${apiModel}:generateContent?key=${this.apiKey}`;
|
|
13
|
+
const response = await fetch(apiUrl, {
|
|
14
|
+
method: "POST",
|
|
15
|
+
headers: {
|
|
16
|
+
"Content-Type": "application/json",
|
|
17
|
+
},
|
|
18
|
+
body: JSON.stringify({
|
|
19
|
+
contents: [
|
|
20
|
+
{
|
|
21
|
+
role: "user",
|
|
22
|
+
parts: [{ text: `${systemPrompt}\n\nUser Question: ${prompt}` }],
|
|
23
|
+
},
|
|
24
|
+
],
|
|
25
|
+
}),
|
|
26
|
+
});
|
|
27
|
+
if (!response.ok) {
|
|
28
|
+
const error = await response.text();
|
|
29
|
+
throw new Error(`Gemini API error: ${response.status} ${error}`);
|
|
30
|
+
}
|
|
31
|
+
const data = (await response.json());
|
|
32
|
+
return data.candidates[0].content.parts[0].text;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=gemini.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gemini.js","sourceRoot":"","sources":["../../src/providers/gemini.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,cAAc;IACzB,IAAI,GAAG,QAAQ,CAAC;IACR,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;IAE5C,SAAS;QACP,OAAO,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;IACvB,CAAC;IAED,KAAK,CAAC,GAAG,CACP,MAAc,EACd,YAAoB,EACpB,KAAc,EACd,GAAY;QAEZ,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;QAE9D,MAAM,QAAQ,GAAG,KAAK,IAAI,kBAAkB,CAAC;QAC7C,MAAM,MAAM,GACV,GAAG;YACH,2DAA2D,QAAQ,wBAAwB,IAAI,CAAC,MAAM,EAAE,CAAC;QAE3G,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,MAAM,EAAE;YACnC,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;aACnC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,QAAQ,EAAE;oBACR;wBACE,IAAI,EAAE,MAAM;wBACZ,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,GAAG,YAAY,sBAAsB,MAAM,EAAE,EAAE,CAAC;qBACjE;iBACF;aACF,CAAC;SACH,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YACpC,MAAM,IAAI,KAAK,CAAC,qBAAqB,QAAQ,CAAC,MAAM,IAAI,KAAK,EAAE,CAAC,CAAC;QACnE,CAAC;QAED,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAQ,CAAC;QAC5C,OAAO,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAClD,CAAC;CACF"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { AIProvider, ProviderType } from "../types.js";
|
|
2
|
+
export declare function getProvider(type?: ProviderType): Promise<AIProvider>;
|
|
3
|
+
export declare const SENIOR_SYSTEM_PROMPT = "You are a senior developer mentor. A junior AI developer is asking for guidance.\n\nYour role:\n- Provide clear, actionable advice\n- Point out best practices and patterns\n- Warn about potential pitfalls\n- Be concise but thorough\n\nKeep responses focused and practical. The junior will implement based on your guidance.";
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { ClaudeProvider } from "./claude.js";
|
|
2
|
+
import { GeminiProvider } from "./gemini.js";
|
|
3
|
+
import { OpenAIProvider } from "./openai.js";
|
|
4
|
+
import { ZaiProvider } from "./zai.js";
|
|
5
|
+
import { OpenAICompatibleProvider } from "./openai-compatible.js";
|
|
6
|
+
const providers = [
|
|
7
|
+
new ClaudeProvider(),
|
|
8
|
+
new GeminiProvider(),
|
|
9
|
+
new OpenAIProvider(),
|
|
10
|
+
new ZaiProvider(),
|
|
11
|
+
new OpenAICompatibleProvider(),
|
|
12
|
+
];
|
|
13
|
+
export async function getProvider(type = "auto") {
|
|
14
|
+
if (type === "auto") {
|
|
15
|
+
const available = providers.find((p) => p.canHandle());
|
|
16
|
+
if (!available) {
|
|
17
|
+
throw new Error("No AI providers available. Please set at least one API key.");
|
|
18
|
+
}
|
|
19
|
+
return available;
|
|
20
|
+
}
|
|
21
|
+
const provider = providers.find((p) => p.name === type);
|
|
22
|
+
if (!provider) {
|
|
23
|
+
throw new Error(`Provider ${type} not supported.`);
|
|
24
|
+
}
|
|
25
|
+
if (!provider.canHandle()) {
|
|
26
|
+
throw new Error(`Provider ${type} selected but its API key is missing.`);
|
|
27
|
+
}
|
|
28
|
+
return provider;
|
|
29
|
+
}
|
|
30
|
+
export const SENIOR_SYSTEM_PROMPT = `You are a senior developer mentor. A junior AI developer is asking for guidance.
|
|
31
|
+
|
|
32
|
+
Your role:
|
|
33
|
+
- Provide clear, actionable advice
|
|
34
|
+
- Point out best practices and patterns
|
|
35
|
+
- Warn about potential pitfalls
|
|
36
|
+
- Be concise but thorough
|
|
37
|
+
|
|
38
|
+
Keep responses focused and practical. The junior will implement based on your guidance.`;
|
|
39
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/providers/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAElE,MAAM,SAAS,GAAiB;IAC9B,IAAI,cAAc,EAAE;IACpB,IAAI,cAAc,EAAE;IACpB,IAAI,cAAc,EAAE;IACpB,IAAI,WAAW,EAAE;IACjB,IAAI,wBAAwB,EAAE;CAC/B,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,OAAqB,MAAM;IAE3B,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QACpB,MAAM,SAAS,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC;QACvD,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CACb,6DAA6D,CAC9D,CAAC;QACJ,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,QAAQ,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;IACxD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CAAC,YAAY,IAAI,iBAAiB,CAAC,CAAC;IACrD,CAAC;IAED,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,YAAY,IAAI,uCAAuC,CAAC,CAAC;IAC3E,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,CAAC,MAAM,oBAAoB,GAAG;;;;;;;;wFAQoD,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export class OpenAICompatibleProvider {
|
|
2
|
+
name = "openai-compatible";
|
|
3
|
+
apiKey = process.env.OPENAI_COMPATIBLE_API_KEY;
|
|
4
|
+
canHandle() {
|
|
5
|
+
return !!this.apiKey;
|
|
6
|
+
}
|
|
7
|
+
async ask(prompt, systemPrompt, model, url) {
|
|
8
|
+
if (!this.apiKey)
|
|
9
|
+
throw new Error("OPENAI_COMPATIBLE_API_KEY not found");
|
|
10
|
+
if (!url) {
|
|
11
|
+
throw new Error("URL is required for openai-compatible provider (e.g., https://openrouter.ai/api/v1/chat/completions)");
|
|
12
|
+
}
|
|
13
|
+
if (!model) {
|
|
14
|
+
throw new Error("Model is required for openai-compatible provider");
|
|
15
|
+
}
|
|
16
|
+
const response = await fetch(url, {
|
|
17
|
+
method: "POST",
|
|
18
|
+
headers: {
|
|
19
|
+
"Content-Type": "application/json",
|
|
20
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
21
|
+
},
|
|
22
|
+
body: JSON.stringify({
|
|
23
|
+
model: model,
|
|
24
|
+
messages: [
|
|
25
|
+
{ role: "system", content: systemPrompt },
|
|
26
|
+
{ role: "user", content: prompt },
|
|
27
|
+
],
|
|
28
|
+
}),
|
|
29
|
+
});
|
|
30
|
+
if (!response.ok) {
|
|
31
|
+
const error = await response.text();
|
|
32
|
+
throw new Error(`OpenAI-Compatible API error: ${response.status} ${error}`);
|
|
33
|
+
}
|
|
34
|
+
const data = (await response.json());
|
|
35
|
+
return data.choices[0].message.content;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=openai-compatible.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai-compatible.js","sourceRoot":"","sources":["../../src/providers/openai-compatible.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,wBAAwB;IACnC,IAAI,GAAG,mBAAmB,CAAC;IACnB,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC;IAEvD,SAAS;QACP,OAAO,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;IACvB,CAAC;IAED,KAAK,CAAC,GAAG,CACP,MAAc,EACd,YAAoB,EACpB,KAAc,EACd,GAAY;QAEZ,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;QAEzE,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,MAAM,IAAI,KAAK,CACb,sGAAsG,CACvG,CAAC;QACJ,CAAC;QAED,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC;QACtE,CAAC;QAED,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;YAChC,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,aAAa,EAAE,UAAU,IAAI,CAAC,MAAM,EAAE;aACvC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,KAAK,EAAE,KAAK;gBACZ,QAAQ,EAAE;oBACR,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,YAAY,EAAE;oBACzC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE;iBAClC;aACF,CAAC;SACH,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YACpC,MAAM,IAAI,KAAK,CACb,gCAAgC,QAAQ,CAAC,MAAM,IAAI,KAAK,EAAE,CAC3D,CAAC;QACJ,CAAC;QAED,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAQ,CAAC;QAC5C,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC;IACzC,CAAC;CACF"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export class OpenAIProvider {
|
|
2
|
+
name = "openai";
|
|
3
|
+
apiKey = process.env.OPENAI_API_KEY;
|
|
4
|
+
canHandle() {
|
|
5
|
+
return !!this.apiKey;
|
|
6
|
+
}
|
|
7
|
+
async ask(prompt, systemPrompt, model, url) {
|
|
8
|
+
if (!this.apiKey)
|
|
9
|
+
throw new Error("OPENAI_API_KEY not found");
|
|
10
|
+
const apiUrl = url || "https://api.openai.com/v1/chat/completions";
|
|
11
|
+
const apiModel = model || "gpt-4o";
|
|
12
|
+
const response = await fetch(apiUrl, {
|
|
13
|
+
method: "POST",
|
|
14
|
+
headers: {
|
|
15
|
+
"Content-Type": "application/json",
|
|
16
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
17
|
+
},
|
|
18
|
+
body: JSON.stringify({
|
|
19
|
+
model: apiModel,
|
|
20
|
+
messages: [
|
|
21
|
+
{ role: "system", content: systemPrompt },
|
|
22
|
+
{ role: "user", content: prompt },
|
|
23
|
+
],
|
|
24
|
+
}),
|
|
25
|
+
});
|
|
26
|
+
if (!response.ok) {
|
|
27
|
+
const error = await response.text();
|
|
28
|
+
throw new Error(`OpenAI API error: ${response.status} ${error}`);
|
|
29
|
+
}
|
|
30
|
+
const data = (await response.json());
|
|
31
|
+
return data.choices[0].message.content;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=openai.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai.js","sourceRoot":"","sources":["../../src/providers/openai.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,cAAc;IACzB,IAAI,GAAG,QAAQ,CAAC;IACR,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;IAE5C,SAAS;QACP,OAAO,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;IACvB,CAAC;IAED,KAAK,CAAC,GAAG,CACP,MAAc,EACd,YAAoB,EACpB,KAAc,EACd,GAAY;QAEZ,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;QAE9D,MAAM,MAAM,GAAG,GAAG,IAAI,4CAA4C,CAAC;QACnE,MAAM,QAAQ,GAAG,KAAK,IAAI,QAAQ,CAAC;QAEnC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,MAAM,EAAE;YACnC,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,aAAa,EAAE,UAAU,IAAI,CAAC,MAAM,EAAE;aACvC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,KAAK,EAAE,QAAQ;gBACf,QAAQ,EAAE;oBACR,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,YAAY,EAAE;oBACzC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE;iBAClC;aACF,CAAC;SACH,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YACpC,MAAM,IAAI,KAAK,CAAC,qBAAqB,QAAQ,CAAC,MAAM,IAAI,KAAK,EAAE,CAAC,CAAC;QACnE,CAAC;QAED,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAQ,CAAC;QAC5C,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC;IACzC,CAAC;CACF"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export class ZaiProvider {
|
|
2
|
+
name = "z.ai";
|
|
3
|
+
apiKey = process.env.ZAI_API_KEY || process.env.ZHIPU_API_KEY;
|
|
4
|
+
canHandle() {
|
|
5
|
+
return !!this.apiKey;
|
|
6
|
+
}
|
|
7
|
+
async ask(prompt, systemPrompt, model, url) {
|
|
8
|
+
if (!this.apiKey)
|
|
9
|
+
throw new Error("ZHIPU_API_KEY not found");
|
|
10
|
+
const apiUrl = url || "https://api.z.ai/api/paas/v4/chat/completions";
|
|
11
|
+
const apiModel = model || "glm-4-plus";
|
|
12
|
+
const response = await fetch(apiUrl, {
|
|
13
|
+
method: "POST",
|
|
14
|
+
headers: {
|
|
15
|
+
"Content-Type": "application/json",
|
|
16
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
17
|
+
},
|
|
18
|
+
body: JSON.stringify({
|
|
19
|
+
model: apiModel,
|
|
20
|
+
messages: [
|
|
21
|
+
{ role: "system", content: systemPrompt },
|
|
22
|
+
{ role: "user", content: prompt },
|
|
23
|
+
],
|
|
24
|
+
}),
|
|
25
|
+
});
|
|
26
|
+
if (!response.ok) {
|
|
27
|
+
const error = await response.text();
|
|
28
|
+
throw new Error(`Zhipu API error: ${response.status} ${error}`);
|
|
29
|
+
}
|
|
30
|
+
const data = (await response.json());
|
|
31
|
+
return data.choices[0].message.content;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=zai.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"zai.js","sourceRoot":"","sources":["../../src/providers/zai.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,WAAW;IACtB,IAAI,GAAG,MAAM,CAAC;IACN,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC;IAEtE,SAAS;QACP,OAAO,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;IACvB,CAAC;IAED,KAAK,CAAC,GAAG,CACP,MAAc,EACd,YAAoB,EACpB,KAAc,EACd,GAAY;QAEZ,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;QAE7D,MAAM,MAAM,GAAG,GAAG,IAAI,+CAA+C,CAAC;QACtE,MAAM,QAAQ,GAAG,KAAK,IAAI,YAAY,CAAC;QAEvC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,MAAM,EAAE;YACnC,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,aAAa,EAAE,UAAU,IAAI,CAAC,MAAM,EAAE;aACvC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,KAAK,EAAE,QAAQ;gBACf,QAAQ,EAAE;oBACR,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,YAAY,EAAE;oBACzC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE;iBAClC;aACF,CAAC;SACH,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YACpC,MAAM,IAAI,KAAK,CAAC,oBAAoB,QAAQ,CAAC,MAAM,IAAI,KAAK,EAAE,CAAC,CAAC;QAClE,CAAC;QAED,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAQ,CAAC;QAC5C,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC;IACzC,CAAC;CACF"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { getProvider, SENIOR_SYSTEM_PROMPT } from "../providers/index.js";
|
|
2
|
+
export async function architectureAdvice(args) {
|
|
3
|
+
const { problem, constraints, stack, provider: providerType, model, url, } = args;
|
|
4
|
+
const provider = await getProvider(providerType);
|
|
5
|
+
const prompt = `Architecture Challenge:
|
|
6
|
+
${problem}
|
|
7
|
+
|
|
8
|
+
${constraints ? `Constraints:\n${constraints}` : ""}
|
|
9
|
+
${stack ? `Tech Stack:\n${stack}` : ""}
|
|
10
|
+
|
|
11
|
+
Please provide:
|
|
12
|
+
1. Recommended approach
|
|
13
|
+
2. Key considerations
|
|
14
|
+
3. Pitfalls to avoid`;
|
|
15
|
+
const response = await provider.ask(prompt, SENIOR_SYSTEM_PROMPT, model, url);
|
|
16
|
+
return {
|
|
17
|
+
content: [
|
|
18
|
+
{
|
|
19
|
+
type: "text",
|
|
20
|
+
text: `**[${provider.name.charAt(0).toUpperCase() + provider.name.slice(1)} Senior Advice]**\n\n${response}`,
|
|
21
|
+
},
|
|
22
|
+
],
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=architecture-advice.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"architecture-advice.js","sourceRoot":"","sources":["../../src/tools/architecture-advice.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAE1E,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,IAA4B;IACnE,MAAM,EACJ,OAAO,EACP,WAAW,EACX,KAAK,EACL,QAAQ,EAAE,YAAY,EACtB,KAAK,EACL,GAAG,GACJ,GAAG,IAAI,CAAC;IAET,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,YAAY,CAAC,CAAC;IAEjD,MAAM,MAAM,GAAG;EACf,OAAO;;EAEP,WAAW,CAAC,CAAC,CAAC,iBAAiB,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE;EACjD,KAAK,CAAC,CAAC,CAAC,gBAAgB,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE;;;;;qBAKjB,CAAC;IAEpB,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,GAAG,CAAC,MAAM,EAAE,oBAAoB,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;IAE9E,OAAO;QACL,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,MACJ,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAC/D,wBAAwB,QAAQ,EAAE;aACnC;SACF;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { getProvider, SENIOR_SYSTEM_PROMPT } from "../providers/index.js";
|
|
2
|
+
export async function askSenior(args) {
|
|
3
|
+
const { question, context, provider: providerType, model, url } = args;
|
|
4
|
+
const provider = await getProvider(providerType);
|
|
5
|
+
const prompt = context
|
|
6
|
+
? `Context:\n${context}\n\nQuestion: ${question}`
|
|
7
|
+
: question;
|
|
8
|
+
const response = await provider.ask(prompt, SENIOR_SYSTEM_PROMPT, model, url);
|
|
9
|
+
return {
|
|
10
|
+
content: [
|
|
11
|
+
{
|
|
12
|
+
type: "text",
|
|
13
|
+
text: `**[${provider.name.charAt(0).toUpperCase() + provider.name.slice(1)} Senior Advice]**\n\n${response}`,
|
|
14
|
+
},
|
|
15
|
+
],
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=ask-senior.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ask-senior.js","sourceRoot":"","sources":["../../src/tools/ask-senior.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAE1E,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,IAAmB;IACjD,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IAEvE,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,YAAY,CAAC,CAAC;IAEjD,MAAM,MAAM,GAAG,OAAO;QACpB,CAAC,CAAC,aAAa,OAAO,iBAAiB,QAAQ,EAAE;QACjD,CAAC,CAAC,QAAQ,CAAC;IAEb,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,GAAG,CAAC,MAAM,EAAE,oBAAoB,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;IAE9E,OAAO;QACL,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,MACJ,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAC/D,wBAAwB,QAAQ,EAAE;aACnC;SACF;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { getProvider, SENIOR_SYSTEM_PROMPT } from "../providers/index.js";
|
|
2
|
+
export async function codeReview(args) {
|
|
3
|
+
const { code, language, focus, provider: providerType, model, url } = args;
|
|
4
|
+
const provider = await getProvider(providerType);
|
|
5
|
+
const prompt = `Please review the following ${language || ""} code:
|
|
6
|
+
|
|
7
|
+
\`\`\`${language || ""}
|
|
8
|
+
${code}
|
|
9
|
+
\`\`\`
|
|
10
|
+
|
|
11
|
+
${focus ? `Focus your review on: ${focus}` : ""}
|
|
12
|
+
|
|
13
|
+
Please provide:
|
|
14
|
+
1. Issues found
|
|
15
|
+
2. Improvement suggestions
|
|
16
|
+
3. What's done well
|
|
17
|
+
|
|
18
|
+
Keep the review concise and actionable.`;
|
|
19
|
+
const response = await provider.ask(prompt, SENIOR_SYSTEM_PROMPT, model, url);
|
|
20
|
+
return {
|
|
21
|
+
content: [
|
|
22
|
+
{
|
|
23
|
+
type: "text",
|
|
24
|
+
text: `**[${provider.name.charAt(0).toUpperCase() + provider.name.slice(1)} Senior Advice]**\n\n${response}`,
|
|
25
|
+
},
|
|
26
|
+
],
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=code-review.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"code-review.js","sourceRoot":"","sources":["../../src/tools/code-review.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAE1E,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,IAAoB;IACnD,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IAE3E,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,YAAY,CAAC,CAAC;IAEjD,MAAM,MAAM,GAAG,+BAA+B,QAAQ,IAAI,EAAE;;QAEtD,QAAQ,IAAI,EAAE;EACpB,IAAI;;;EAGJ,KAAK,CAAC,CAAC,CAAC,yBAAyB,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE;;;;;;;wCAOP,CAAC;IAEvC,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,GAAG,CAAC,MAAM,EAAE,oBAAoB,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;IAE9E,OAAO;QACL,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,MACJ,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAC/D,wBAAwB,QAAQ,EAAE;aACnC;SACF;KACF,CAAC;AACJ,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export type ProviderType = "claude" | "gemini" | "openai" | "z.ai" | "openai-compatible" | "auto";
|
|
2
|
+
export interface ProviderResponse {
|
|
3
|
+
content: string;
|
|
4
|
+
provider: string;
|
|
5
|
+
}
|
|
6
|
+
export interface ProviderConfig {
|
|
7
|
+
apiKey?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface AskSeniorArgs {
|
|
10
|
+
question: string;
|
|
11
|
+
context?: string;
|
|
12
|
+
provider?: ProviderType;
|
|
13
|
+
model?: string;
|
|
14
|
+
url?: string;
|
|
15
|
+
}
|
|
16
|
+
export interface CodeReviewArgs {
|
|
17
|
+
code: string;
|
|
18
|
+
language?: string;
|
|
19
|
+
focus?: string;
|
|
20
|
+
provider?: ProviderType;
|
|
21
|
+
model?: string;
|
|
22
|
+
url?: string;
|
|
23
|
+
}
|
|
24
|
+
export interface ArchitectureAdviceArgs {
|
|
25
|
+
problem: string;
|
|
26
|
+
constraints?: string;
|
|
27
|
+
stack?: string;
|
|
28
|
+
provider?: ProviderType;
|
|
29
|
+
model?: string;
|
|
30
|
+
url?: string;
|
|
31
|
+
}
|
|
32
|
+
export interface AIProvider {
|
|
33
|
+
name: string;
|
|
34
|
+
canHandle(): boolean;
|
|
35
|
+
ask(prompt: string, systemPrompt: string, model?: string, url?: string): Promise<string>;
|
|
36
|
+
}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "senior-consult-mcp",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"main": "dist/index.js",
|
|
5
|
+
"bin": {
|
|
6
|
+
"senior-consult": "dist/index.js"
|
|
7
|
+
},
|
|
8
|
+
"type": "module",
|
|
9
|
+
"description": "An MCP server for junior AI agents to consult senior AI developer mentors",
|
|
10
|
+
"publishConfig": {
|
|
11
|
+
"access": "public"
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"dist"
|
|
15
|
+
],
|
|
16
|
+
"scripts": {
|
|
17
|
+
"build": "rm -rf dist && tsc && chmod +x dist/index.js",
|
|
18
|
+
"prepare": "npm run build",
|
|
19
|
+
"prepublishOnly": "npm run build",
|
|
20
|
+
"start": "node dist/index.js"
|
|
21
|
+
},
|
|
22
|
+
"keywords": [
|
|
23
|
+
"mcp",
|
|
24
|
+
"model-context-protocol",
|
|
25
|
+
"senior-consult",
|
|
26
|
+
"ai-mentor",
|
|
27
|
+
"claude",
|
|
28
|
+
"gemini",
|
|
29
|
+
"openai",
|
|
30
|
+
"z.ai"
|
|
31
|
+
],
|
|
32
|
+
"author": "Bundit Nuntates",
|
|
33
|
+
"license": "MIT",
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@types/node": "^22.0.0",
|
|
36
|
+
"typescript": "^5.0.0"
|
|
37
|
+
},
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"@modelcontextprotocol/sdk": "^1.25.1",
|
|
40
|
+
"zod": "^4.3.5"
|
|
41
|
+
}
|
|
42
|
+
}
|