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 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
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
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,7 @@
1
+ import { AIProvider } from "../types.js";
2
+ export declare class ClaudeProvider implements AIProvider {
3
+ name: string;
4
+ private apiKey;
5
+ canHandle(): boolean;
6
+ ask(prompt: string, systemPrompt: string, model?: string, url?: string): Promise<string>;
7
+ }
@@ -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,7 @@
1
+ import { AIProvider } from "../types.js";
2
+ export declare class GeminiProvider implements AIProvider {
3
+ name: string;
4
+ private apiKey;
5
+ canHandle(): boolean;
6
+ ask(prompt: string, systemPrompt: string, model?: string, url?: string): Promise<string>;
7
+ }
@@ -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,7 @@
1
+ import { AIProvider } from "../types.js";
2
+ export declare class OpenAICompatibleProvider implements AIProvider {
3
+ name: string;
4
+ private apiKey;
5
+ canHandle(): boolean;
6
+ ask(prompt: string, systemPrompt: string, model?: string, url?: string): Promise<string>;
7
+ }
@@ -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,7 @@
1
+ import { AIProvider } from "../types.js";
2
+ export declare class OpenAIProvider implements AIProvider {
3
+ name: string;
4
+ private apiKey;
5
+ canHandle(): boolean;
6
+ ask(prompt: string, systemPrompt: string, model?: string, url?: string): Promise<string>;
7
+ }
@@ -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,7 @@
1
+ import { AIProvider } from "../types.js";
2
+ export declare class ZaiProvider implements AIProvider {
3
+ name: string;
4
+ private apiKey;
5
+ canHandle(): boolean;
6
+ ask(prompt: string, systemPrompt: string, model?: string, url?: string): Promise<string>;
7
+ }
@@ -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,7 @@
1
+ import { ArchitectureAdviceArgs } from "../types.js";
2
+ export declare function architectureAdvice(args: ArchitectureAdviceArgs): Promise<{
3
+ content: {
4
+ type: string;
5
+ text: string;
6
+ }[];
7
+ }>;
@@ -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,7 @@
1
+ import { AskSeniorArgs } from "../types.js";
2
+ export declare function askSenior(args: AskSeniorArgs): Promise<{
3
+ content: {
4
+ type: string;
5
+ text: string;
6
+ }[];
7
+ }>;
@@ -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,7 @@
1
+ import { CodeReviewArgs } from "../types.js";
2
+ export declare function codeReview(args: CodeReviewArgs): Promise<{
3
+ content: {
4
+ type: string;
5
+ text: string;
6
+ }[];
7
+ }>;
@@ -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"}
@@ -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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -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
+ }