@identikey/coding-mcp 2.0.5 → 2.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.
Files changed (40) hide show
  1. package/README.md +108 -103
  2. package/build/common/apiClient.d.ts +1 -1
  3. package/build/common/apiClient.d.ts.map +1 -1
  4. package/build/common/apiClient.js +31 -49
  5. package/build/core/CommandDispatcher.d.ts +3 -3
  6. package/build/core/CommandDispatcher.d.ts.map +1 -1
  7. package/build/core/CommandDispatcher.js +42 -32
  8. package/build/index.d.ts +1 -0
  9. package/build/index.d.ts.map +1 -1
  10. package/build/index.js +3 -1
  11. package/build/personas/charles/index.d.ts +1 -1
  12. package/build/personas/charles/index.d.ts.map +1 -1
  13. package/build/personas/charles/index.js +107 -62
  14. package/build/personas/router.d.ts.map +1 -1
  15. package/build/personas/router.js +33 -0
  16. package/build/personas/sterling/index.d.ts +14 -0
  17. package/build/personas/sterling/index.d.ts.map +1 -0
  18. package/build/personas/sterling/index.js +128 -0
  19. package/build/personas/xavier/index.js +2 -2
  20. package/build/prompts/architectPrompts.d.ts +1 -1
  21. package/build/prompts/architectPrompts.d.ts.map +1 -1
  22. package/build/prompts/architectPrompts.js +56 -53
  23. package/build/tools/architect.d.ts +6 -12
  24. package/build/tools/architect.d.ts.map +1 -1
  25. package/build/tools/ask.d.ts +4 -20
  26. package/build/tools/ask.d.ts.map +1 -1
  27. package/build/tools/codeReview.d.ts +1 -5
  28. package/build/tools/codeReview.d.ts.map +1 -1
  29. package/build/tools/codeadvice.d.ts +6 -10
  30. package/build/tools/codeadvice.d.ts.map +1 -1
  31. package/build/tools/discover.d.ts +11 -8
  32. package/build/tools/discover.d.ts.map +1 -1
  33. package/build/tools/discover.js +20 -5
  34. package/build/tools/persona.d.ts +29 -28
  35. package/build/tools/persona.d.ts.map +1 -1
  36. package/build/tools/researcher.d.ts +23 -20
  37. package/build/tools/researcher.d.ts.map +1 -1
  38. package/build/tools/screenshot.d.ts +1 -9
  39. package/build/tools/screenshot.d.ts.map +1 -1
  40. package/package.json +6 -7
package/README.md CHANGED
@@ -1,157 +1,162 @@
1
+ # @identikey/coding-mcp
1
2
 
3
+ MCP server with expert AI personas for architecture reviews, code advice, and research. Runs as a tool server in Cursor, Windsurf, or any MCP-compatible client.
2
4
 
3
- ## How Users Run It
4
- folks can use it in their MCP config like:
5
+ ## Quick Start
5
6
 
6
- **Cursor Settings MCP Add Server:**
7
- - **Command**: `npx`
8
- - **Args**: `-y`, `@identikey/coding-mcp`
7
+ Add to your MCP config (e.g., `.cursor/mcp.json`):
9
8
 
10
- Or in `.cursor/mcp.json`:
11
9
  ```json
12
10
  {
13
11
  "mcpServers": {
14
12
  "coding-mcp": {
15
13
  "command": "npx",
16
- "args": ["-y", "@identikey/coding-mcp"]
14
+ "args": ["-y", "@identikey/coding-mcp"],
15
+ "env": {
16
+ "XAI_API_KEY": "your-xai-key",
17
+ "OPENAI_API_KEY": "your-openai-key"
18
+ }
17
19
  }
18
20
  }
19
21
  }
20
22
  ```
21
23
 
22
- The server spawns as a child process, Cursor talks JSON-RPC over stdin/stdout, and all your tool logs go to stderr where they belong. Clean af.
24
+ Or via Cursor Settings MCP Add Server.
23
25
 
24
- # 🤖 Cursor Tools MCP Server
26
+ ### Environment Variables
25
27
 
26
- An MCP (Model Context Protocol) server providing powerful tools with expert personas for intelligent assistance:
28
+ | Variable | Required | Description |
29
+ | ---------------- | -------- | ---------------------------------------------------- |
30
+ | `XAI_API_KEY` | Yes\* | xAI/Grok API key ([get one](https://console.x.ai)) |
31
+ | `OPENAI_API_KEY` | Yes\* | OpenAI API key (for GPT-5 reasoning) |
32
+ | `AI_PROVIDER` | No | Default provider: `xai` or `openai` (default: `xai`) |
33
+ | `XAI_MODEL` | No | xAI model override (default: `grok-4.1`) |
34
+ | `OPENAI_MODEL` | No | OpenAI model override (default: `gpt-5.2`) |
27
35
 
28
- ## Core Tools
29
- - **Ask**: Natural language queries automatically routed to the best expert
30
- - **Discover**: Explore available expert personas and their specialties
31
- - **Persona**: Direct access to specific expert personas
32
- - **Screenshot**: Capture screenshots from URLs
33
- - **Architect**: Comprehensive architectural code reviews
34
- - **Code Review**: Git diff analysis and improvement suggestions
36
+ \*At least one API key required. The server auto-selects providers based on task type—xAI for quick advice, OpenAI for deep reasoning.
35
37
 
36
- ## Features
38
+ ### Using bunx
37
39
 
38
- ### 🎨 Code Architect
39
-
40
- Call advanced reasoning LLMs to generate plans and instructions for coding agents.
41
-
42
- ### 📸 Screenshot Buddy
43
-
44
- Take UI design screenshots and use them with the composer agent.
45
-
46
- ### 🔍 Code Review
40
+ ```json
41
+ {
42
+ "mcpServers": {
43
+ "coding-mcp": {
44
+ "command": "bunx",
45
+ "args": ["@identikey/coding-mcp"],
46
+ "env": {
47
+ "XAI_API_KEY": "your-xai-key"
48
+ }
49
+ }
50
+ }
51
+ }
52
+ ```
47
53
 
48
- Use git diffs to trigger code reviews.
54
+ ## Tools
49
55
 
50
- ### 🎭 Persona System
56
+ ### `ask`
51
57
 
52
- Transform AI responses with distinct personalities:
53
- - **Charles**: Distinguished British architect with dry wit
54
- - **Ada**: Pragmatic performance engineer, metrics-focused
58
+ Natural language queries auto-routed to the best expert persona. Just ask—it figures out who should answer.
55
59
 
56
- ### 📊 Code Advice
60
+ ```
61
+ "How should I structure this React app?" → routes to Iris (frontend)
62
+ "Is this auth implementation secure?" → routes to Sentinel (security)
63
+ "Review this API design" → routes to Atlas (backend)
64
+ ```
57
65
 
58
- Get focused guidance on specific coding problems.
66
+ ### `architect`
59
67
 
60
- ### 🔬 Researcher
68
+ Deep architectural review with reasoning. Pass code + task description, get structured analysis.
61
69
 
62
- Deep-dive analysis for complex technical questions.
70
+ ### `code-review`
63
71
 
64
- ## 🚀 Getting Started
72
+ Git diff analysis. Point it at a repo, get review of changes vs main branch.
65
73
 
66
- ### 1. Environment Setup
74
+ ### `code-advice`
67
75
 
68
- First, you'll need to set up your environment variables. Create a file at `src/env/keys.ts`:
76
+ Quick, focused guidance on specific problems. Lower latency than full architect review.
69
77
 
70
- ```typescript
71
- export const OPENAI_API_KEY = "your_key_here";
72
- // Add any other keys you need
73
- ```
78
+ ### `researcher`
74
79
 
75
- > ⚠️ **Security Note**: Storing API keys directly in source code is not recommended for production environments. This is only for local development and learning purposes. You can set the env var inline in the Cursor MCP interface as well.
80
+ Multi-source research with citations. Searches across Google, arXiv, GitHub, StackExchange, etc.
76
81
 
77
- ### 2. Installation
82
+ ### `persona`
78
83
 
79
- ```bash
80
- npm install
81
- # or
82
- yarn install
83
- ```
84
+ Direct access to a specific expert. Skip auto-routing when you know who you want.
84
85
 
85
- ### 3. Build the Server
86
+ ### `discover`
86
87
 
87
- ```bash
88
- npm run build
89
- ```
88
+ List available personas and their specialties.
90
89
 
91
- ### 4. Adding to Cursor
90
+ ### `screenshot`
92
91
 
93
- This project is designed to be used as an MCP server in Cursor. Here's how to set it up:
92
+ Capture screenshots from URLs for UI review.
94
93
 
95
- 1. Open Cursor
96
- 2. Go to `Cursor Settings > Features > MCP`
97
- 3. Click `+ Add New MCP Server`
98
- 4. Fill out the form:
99
- - **Name**: AI Development Assistant
100
- - **Type**: stdio
101
- - **Command**: `node /path/to/your/project/dist/index.js`
94
+ ## Personas
102
95
 
103
- > 📘 **Pro Tip**: You might need to use the full path to your project's built index.js file.
96
+ | Persona | Focus | Style |
97
+ | ------------ | ------------------------ | -------------------------------------------------- |
98
+ | **Charles** | Pragmatic architecture | Anti-enterprise, ships fast, calls out YAGNI |
99
+ | **Sterling** | Enterprise systems | Zero-downtime, compliance, multi-team coordination |
100
+ | **Ada** | Algorithms & performance | Big-O, profiling, optimization |
101
+ | **Atlas** | Backend & APIs | Contract-first, database design, caching |
102
+ | **Hermes** | DevOps & SRE | CI/CD, observability, Kubernetes |
103
+ | **Sentinel** | Security | Threat modeling, auth, compliance |
104
+ | **Iris** | Frontend & UX | Accessibility, design systems, React/Vue |
105
+ | **Xavier** | MVP development | KISS, ship it, avoid yak shaving |
104
106
 
105
- After adding the server, you should see your tools listed under "Available Tools". If not, try clicking the refresh button in the top right corner of the MCP server section.
107
+ ## Development
106
108
 
107
- For more details about MCP setup, check out the [Cursor MCP Documentation](https://docs.cursor.com/advanced/model-context-protocol).
109
+ ```bash
110
+ # Install deps
111
+ bun install
108
112
 
109
- ## 🛠️ Using the Tools
113
+ # Build
114
+ bun run build
110
115
 
111
- Once configured, you can use these tools directly in Cursor's Composer. The AI will automatically suggest using relevant tools, or you can explicitly request them by name or description.
116
+ # Test
117
+ bun test
112
118
 
113
- For example, try typing in Composer:
119
+ # Run locally (for testing)
120
+ bun run start
121
+ ```
114
122
 
115
- - "Review this code for best practices"
116
- - "Help me architect a new feature"
117
- - "Analyze this UI screenshot"
123
+ ### Local MCP Config
118
124
 
119
- The agent will ask for your approval before making any tool calls.
125
+ For development, point to your local build:
120
126
 
121
- > 📘 **Pro Tip**: You can update your .cursorrules file with instructions on how to use the tools for certain scenarios, and the agent will use the tools automatically.
127
+ ```json
128
+ {
129
+ "mcpServers": {
130
+ "coding-mcp-dev": {
131
+ "command": "node",
132
+ "args": ["/path/to/coding-mcp/build/index.js"],
133
+ "env": {
134
+ "XAI_API_KEY": "your-key"
135
+ }
136
+ }
137
+ }
138
+ }
139
+ ```
122
140
 
123
- ## 📁 Project Structure
141
+ ### Project Structure
124
142
 
125
143
  ```
126
144
  src/
127
- ├── tools/
128
- ├── architect.ts # Code structure generator
129
- │ ├── screenshot.ts # Screenshot analysis tool
130
- └── codeReview.ts # Code review tool
131
- ├── env/
132
- │ └── keys.ts # Environment configuration (add your API keys here!)
133
- └── index.ts # Main entry point
145
+ ├── index.ts # MCP server entry
146
+ ├── common/
147
+ │ ├── apiClient.ts # Unified AI provider client
148
+ ├── providerConfig.ts # Env vars, provider selection
149
+ │ └── ...
150
+ ├── personas/
151
+ │ ├── charles/ # Each persona has its own module
152
+ │ ├── sterling/
153
+ │ └── ...
154
+ └── tools/
155
+ ├── ask.ts # Smart routing
156
+ ├── architect.ts # Deep review
157
+ └── ...
134
158
  ```
135
159
 
136
- ## 🤝 Contributing
137
-
138
- Contributions welcome! Please feel free to submit a Pull Request.
139
-
140
- ## 📝 License
141
-
142
- This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
143
-
144
- ## 🐛 Issues & Support
145
-
146
- Found a bug or need help? Open an issue with:
147
-
148
- 1. What you were trying to do
149
- 2. What happened instead
150
- 3. Steps to reproduce
151
- 4. Your environment details
152
-
153
- ---
154
-
155
- I'll be honest though, this is a tutorial demo, and not a production-ready tool so I likely won't be fixing issues. But feel free to fork it and make it your own!
160
+ ## License
156
161
 
157
- Made with ❤️ by developers, for developers
162
+ MIT
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Generic AI provider API client utilities
2
+ * Unified AI provider client using Vercel AI SDK
3
3
  */
4
4
  import { type AIProvider, type ReasoningEffort } from "./providerConfig.js";
5
5
  export interface AICallConfig {
@@ -1 +1 @@
1
- {"version":3,"file":"apiClient.d.ts","sourceRoot":"","sources":["../../src/common/apiClient.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,OAAO,EAIL,KAAK,UAAU,EACf,KAAK,eAAe,EACrB,MAAM,qBAAqB,CAAC;AAI7B,MAAM,WAAW,YAAY;IAC3B,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,eAAe,GAAG,QAAQ,GAAG,UAAU,GAAG,QAAQ,CAAC;IACjE,eAAe,EAAE,eAAe,CAAC;IACjC,QAAQ,EAAE,UAAU,CAAC;CACtB;AAoDD,wBAAsB,cAAc,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,CAe1E"}
1
+ {"version":3,"file":"apiClient.d.ts","sourceRoot":"","sources":["../../src/common/apiClient.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,OAAO,EAIL,KAAK,UAAU,EACf,KAAK,eAAe,EACrB,MAAM,qBAAqB,CAAC;AAW7B,MAAM,WAAW,YAAY;IAC3B,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,eAAe,GAAG,QAAQ,GAAG,UAAU,GAAG,QAAQ,CAAC;IACjE,eAAe,EAAE,eAAe,CAAC;IACjC,QAAQ,EAAE,UAAU,CAAC;CACtB;AAiBD,wBAAsB,cAAc,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,CA6B1E"}
@@ -1,68 +1,50 @@
1
1
  /**
2
- * Generic AI provider API client utilities
2
+ * Unified AI provider client using Vercel AI SDK
3
3
  */
4
- import OpenAI from "openai";
4
+ import { createOpenAI } from "@ai-sdk/openai";
5
5
  import { xai } from "@ai-sdk/xai";
6
6
  import { generateText } from "ai";
7
- import { OPENAI_API_KEY, validateProvider } from "./providerConfig.js";
7
+ import { OPENAI_API_KEY, validateProvider, } from "./providerConfig.js";
8
8
  import { formatTokenInfo } from "./tokenFormatter.js";
9
9
  import { buildUserPrompt } from "./promptBuilder.js";
10
- async function callXaiProvider(config) {
10
+ // Model defaults with env overrides
11
+ const XAI_MODEL = process.env.XAI_MODEL || "grok-4.1";
12
+ const OPENAI_MODEL = process.env.OPENAI_MODEL || "gpt-5.2";
13
+ // Provider clients
14
+ const openai = createOpenAI({ apiKey: OPENAI_API_KEY });
15
+ const providers = {
16
+ xai: {
17
+ model: () => xai(XAI_MODEL),
18
+ mapOptions: (effort) => ({
19
+ xai: { reasoningEffort: effort },
20
+ }),
21
+ },
22
+ openai: {
23
+ model: () => openai(OPENAI_MODEL),
24
+ mapOptions: (effort) => ({
25
+ openai: { reasoningEffort: effort },
26
+ }),
27
+ },
28
+ };
29
+ export async function callAIProvider(config) {
30
+ validateProvider(config.provider);
31
+ const provider = providers[config.provider];
32
+ if (!provider) {
33
+ throw new Error(`Unsupported provider: ${config.provider}`);
34
+ }
11
35
  const userPrompt = buildUserPrompt({
12
36
  task: config.task,
13
37
  code: config.code,
14
38
  analysisType: config.analysisType,
15
39
  });
16
40
  const result = await generateText({
17
- model: xai("grok-4"),
41
+ model: provider.model(),
18
42
  messages: [
19
43
  { role: "system", content: config.systemPrompt },
20
44
  { role: "user", content: userPrompt },
21
45
  ],
22
- // Note: xAI doesn't support reasoningEffort parameter
46
+ providerOptions: provider.mapOptions(config.reasoningEffort),
23
47
  });
24
- const tokenInfo = formatTokenInfo("xai", result.usage, config.reasoningEffort);
48
+ const tokenInfo = formatTokenInfo(config.provider, result.usage, config.reasoningEffort);
25
49
  return result.text + tokenInfo;
26
50
  }
27
- async function callOpenAIProvider(config) {
28
- const openai = new OpenAI({
29
- apiKey: OPENAI_API_KEY,
30
- });
31
- const userPrompt = buildUserPrompt({
32
- task: config.task,
33
- code: config.code,
34
- analysisType: config.analysisType,
35
- });
36
- const response = await openai.chat.completions.create({
37
- model: "gpt-5",
38
- messages: [
39
- { role: "system", content: config.systemPrompt },
40
- { role: "user", content: userPrompt },
41
- ],
42
- reasoning_effort: config.reasoningEffort, // GPT-5 supports this
43
- });
44
- const assistantMessage = response.choices?.[0]?.message?.content ?? "No response from model.";
45
- const usage = {
46
- totalTokens: response.usage?.total_tokens,
47
- reasoning_tokens: response.usage?.reasoning_tokens,
48
- };
49
- const tokenInfo = formatTokenInfo("openai", usage, config.reasoningEffort);
50
- return assistantMessage + tokenInfo;
51
- }
52
- export async function callAIProvider(config) {
53
- validateProvider(config.provider);
54
- if (config.provider === "xai") {
55
- // xAI doesn't support reasoning_effort, so create config without it
56
- const xaiConfig = {
57
- ...config,
58
- reasoningEffort: undefined // Remove for xAI
59
- };
60
- return callXaiProvider(xaiConfig);
61
- }
62
- else if (config.provider === "openai") {
63
- return callOpenAIProvider(config);
64
- }
65
- else {
66
- throw new Error(`Unsupported provider: ${config.provider}`);
67
- }
68
- }
@@ -3,9 +3,9 @@
3
3
  * Routes MCP requests to appropriate tool commands with structured error handling
4
4
  */
5
5
  import { CallToolRequest } from "@modelcontextprotocol/sdk/types.js";
6
- import { MCPToolResponse } from './ToolCommand.js';
7
- import { ToolRegistry } from './ToolRegistry.js';
8
- import { type EventBus } from '../infra/eventBus.js';
6
+ import { MCPToolResponse } from "./ToolCommand.js";
7
+ import { ToolRegistry } from "./ToolRegistry.js";
8
+ import { type EventBus } from "../infra/eventBus.js";
9
9
  export interface DispatcherConfig {
10
10
  /** Default execution timeout in milliseconds */
11
11
  defaultTimeout?: number;
@@ -1 +1 @@
1
- {"version":3,"file":"CommandDispatcher.d.ts","sourceRoot":"","sources":["../../src/core/CommandDispatcher.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,oCAAoC,CAAC;AACrE,OAAO,EASL,eAAe,EAChB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAY,KAAK,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAG/D,MAAM,WAAW,gBAAgB;IAC/B,gDAAgD;IAChD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,+BAA+B;IAC/B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,oCAAoC;IACpC,uBAAuB,CAAC,EAAE,MAAM,CAAC;CAClC;AAED,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAe;IACxC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAW;IACpC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA6B;IACpD,OAAO,CAAC,gBAAgB,CAA8D;IACtF,OAAO,CAAC,gBAAgB,CAAK;gBAG3B,QAAQ,EAAE,YAAY,EACtB,gBAAgB,CAAC,EAAE,QAAQ,EAC3B,MAAM,GAAE,gBAAqB;IAW/B;;OAEG;IACG,QAAQ,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC;IAiFlE;;OAEG;YACW,kBAAkB;IAiEhC;;OAEG;YACW,WAAW;IAczB;;OAEG;IACH,OAAO,CAAC,cAAc;IAYtB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAezB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAa3B;;OAEG;IACH,OAAO,CAAC,aAAa;IASrB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAIzB;;OAEG;IACH,mBAAmB,IAAI,WAAW,CAAC,MAAM,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAInF;;OAEG;IACH,QAAQ,IAAI;QACV,gBAAgB,EAAE,MAAM,CAAC;QACzB,eAAe,EAAE,MAAM,CAAC;QACxB,oBAAoB,EAAE,MAAM,CAAC;QAC7B,SAAS,EAAE,MAAM,CAAC;KACnB;IAWD;;OAEG;IACH,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,YAAY,EAAE,MAAM,CAAC,EAAE,gBAAgB,GAAG,iBAAiB;CAGpF;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,YAAY,EACtB,MAAM,CAAC,EAAE,gBAAgB,GACxB,CAAC,OAAO,EAAE,eAAe,KAAK,OAAO,CAAC,eAAe,CAAC,CAGxD"}
1
+ {"version":3,"file":"CommandDispatcher.d.ts","sourceRoot":"","sources":["../../src/core/CommandDispatcher.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,oCAAoC,CAAC;AACrE,OAAO,EASL,eAAe,EAChB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAY,KAAK,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAG/D,MAAM,WAAW,gBAAgB;IAC/B,gDAAgD;IAChD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,+BAA+B;IAC/B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,oCAAoC;IACpC,uBAAuB,CAAC,EAAE,MAAM,CAAC;CAClC;AAED,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAe;IACxC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAW;IACpC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA6B;IACpD,OAAO,CAAC,gBAAgB,CAGpB;IACJ,OAAO,CAAC,gBAAgB,CAAK;gBAG3B,QAAQ,EAAE,YAAY,EACtB,gBAAgB,CAAC,EAAE,QAAQ,EAC3B,MAAM,GAAE,gBAAqB;IAW/B;;OAEG;IACG,QAAQ,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC;IAwFlE;;OAEG;YACW,kBAAkB;IAwEhC;;OAEG;YACW,WAAW;IAczB;;OAEG;IACH,OAAO,CAAC,cAAc;IAYtB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAoBzB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAiB3B;;OAEG;IACH,OAAO,CAAC,aAAa;IASrB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAIzB;;OAEG;IACH,mBAAmB,IAAI,WAAW,CAChC,MAAM,EACN;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CACxC;IAID;;OAEG;IACH,QAAQ,IAAI;QACV,gBAAgB,EAAE,MAAM,CAAC;QACzB,eAAe,EAAE,MAAM,CAAC;QACxB,oBAAoB,EAAE,MAAM,CAAC;QAC7B,SAAS,EAAE,MAAM,CAAC;KACnB;IAWD;;OAEG;IACH,MAAM,CAAC,MAAM,CACX,QAAQ,EAAE,YAAY,EACtB,MAAM,CAAC,EAAE,gBAAgB,GACxB,iBAAiB;CAGrB;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,YAAY,EACtB,MAAM,CAAC,EAAE,gBAAgB,GACxB,CAAC,OAAO,EAAE,eAAe,KAAK,OAAO,CAAC,eAAe,CAAC,CAGxD"}
@@ -2,9 +2,9 @@
2
2
  * Command Dispatcher - Replaces the monolithic switch statement
3
3
  * Routes MCP requests to appropriate tool commands with structured error handling
4
4
  */
5
- import { ToolNotFoundError, ToolValidationError, ToolExecutionError, ToolTimeoutError, ToolError } from './ToolCommand.js';
6
- import { eventBus } from '../infra/eventBus.js';
7
- import { ZodError } from 'zod';
5
+ import { ToolNotFoundError, ToolValidationError, ToolExecutionError, ToolTimeoutError, ToolError, } from "./ToolCommand.js";
6
+ import { eventBus } from "../infra/eventBus.js";
7
+ import { ZodError } from "zod";
8
8
  export class CommandDispatcher {
9
9
  registry;
10
10
  eventBus;
@@ -17,7 +17,7 @@ export class CommandDispatcher {
17
17
  this.config = {
18
18
  defaultTimeout: config.defaultTimeout || 30000, // 30 seconds
19
19
  enableTracing: config.enableTracing ?? true,
20
- maxConcurrentExecutions: config.maxConcurrentExecutions || 10
20
+ maxConcurrentExecutions: config.maxConcurrentExecutions || 10,
21
21
  };
22
22
  }
23
23
  /**
@@ -30,7 +30,7 @@ export class CommandDispatcher {
30
30
  try {
31
31
  // Check concurrent execution limit
32
32
  if (this.activeExecutions.size >= this.config.maxConcurrentExecutions) {
33
- throw new ToolError(`Maximum concurrent executions (${this.config.maxConcurrentExecutions}) reached`, 'RESOURCE_ERROR', toolName);
33
+ throw new ToolError(`Maximum concurrent executions (${this.config.maxConcurrentExecutions}) reached`, "RESOURCE_ERROR", toolName);
34
34
  }
35
35
  // Get the tool command
36
36
  const tool = this.registry.get(toolName);
@@ -40,10 +40,10 @@ export class CommandDispatcher {
40
40
  // Track active execution
41
41
  this.activeExecutions.set(requestId, { toolName, startTime });
42
42
  // Emit execution start event
43
- this.eventBus.emit('tool:execute:start', {
43
+ this.eventBus.emit("tool:execute:start", {
44
44
  name: toolName,
45
45
  requestId,
46
- args
46
+ args,
47
47
  });
48
48
  // Execute the tool with timeout
49
49
  const result = await this.executeWithTimeout(tool, args, requestId, startTime);
@@ -51,18 +51,19 @@ export class CommandDispatcher {
51
51
  this.activeExecutions.delete(requestId);
52
52
  // Emit execution end event
53
53
  const executionTime = Date.now() - startTime;
54
- this.eventBus.emit('tool:execute:end', {
54
+ this.eventBus.emit("tool:execute:end", {
55
55
  name: toolName,
56
56
  requestId,
57
57
  success: result.success,
58
- executionTime
58
+ executionTime,
59
59
  });
60
60
  // Return MCP-compatible response
61
61
  if (result.success && result.result) {
62
62
  return this.formatMCPResponse(result.result);
63
63
  }
64
64
  else {
65
- throw result.error || new ToolExecutionError(toolName, 'Unknown execution error');
65
+ throw (result.error ||
66
+ new ToolExecutionError(toolName, "Unknown execution error"));
66
67
  }
67
68
  }
68
69
  catch (error) {
@@ -71,18 +72,18 @@ export class CommandDispatcher {
71
72
  // Convert to ToolError if not already
72
73
  const toolError = this.normalizeError(error, toolName);
73
74
  // Emit error event
74
- this.eventBus.emit('tool:error', {
75
+ this.eventBus.emit("tool:error", {
75
76
  name: toolName,
76
77
  error: toolError,
77
- requestId
78
+ requestId,
78
79
  });
79
80
  // Emit execution end event with failure
80
81
  const executionTime = Date.now() - startTime;
81
- this.eventBus.emit('tool:execute:end', {
82
+ this.eventBus.emit("tool:execute:end", {
82
83
  name: toolName,
83
84
  requestId,
84
85
  success: false,
85
- executionTime
86
+ executionTime,
86
87
  });
87
88
  // Return error response in MCP format
88
89
  return this.formatErrorResponse(toolError);
@@ -100,19 +101,22 @@ export class CommandDispatcher {
100
101
  }
101
102
  catch (error) {
102
103
  if (error instanceof ZodError) {
103
- throw new ToolValidationError(tool.name, `Invalid arguments: ${error.errors.map(e => `${e.path.join('.')}: ${e.message}`).join(', ')}`, error);
104
+ throw new ToolValidationError(tool.name, `Invalid arguments: ${error.issues
105
+ .map((e) => `${e.path.join(".")}: ${e.message}`)
106
+ .join(", ")}`, error);
104
107
  }
105
- throw new ToolValidationError(tool.name, 'Failed to validate arguments', error);
108
+ throw new ToolValidationError(tool.name, "Failed to validate arguments", error);
106
109
  }
107
110
  // Create execution context
108
111
  const context = {
109
112
  eventBus: this.eventBus,
110
113
  requestId,
111
114
  startTime,
112
- config: tool.metadata?.constraints
115
+ config: tool.metadata?.constraints,
113
116
  };
114
117
  // Determine timeout (tool-specific or default)
115
- const timeout = tool.metadata?.constraints?.maxExecutionTime || this.config.defaultTimeout;
118
+ const timeout = tool.metadata?.constraints?.maxExecutionTime ||
119
+ this.config.defaultTimeout;
116
120
  // Execute with timeout
117
121
  const result = await this.withTimeout(tool.execute(validatedArgs, context), timeout, tool.name);
118
122
  return {
@@ -122,8 +126,8 @@ export class CommandDispatcher {
122
126
  metadata: {
123
127
  toolName: tool.name,
124
128
  version: tool.version,
125
- requestId
126
- }
129
+ requestId,
130
+ },
127
131
  };
128
132
  }
129
133
  catch (error) {
@@ -134,8 +138,8 @@ export class CommandDispatcher {
134
138
  metadata: {
135
139
  toolName: tool.name,
136
140
  version: tool.version,
137
- requestId
138
- }
141
+ requestId,
142
+ },
139
143
  };
140
144
  }
141
145
  }
@@ -172,10 +176,14 @@ export class CommandDispatcher {
172
176
  }
173
177
  // Convert to MCP format
174
178
  return {
175
- content: [{
179
+ content: [
180
+ {
176
181
  type: "text",
177
- text: typeof result === 'string' ? result : JSON.stringify(result, null, 2)
178
- }]
182
+ text: typeof result === "string"
183
+ ? result
184
+ : JSON.stringify(result, null, 2),
185
+ },
186
+ ],
179
187
  };
180
188
  }
181
189
  /**
@@ -183,22 +191,24 @@ export class CommandDispatcher {
183
191
  */
184
192
  formatErrorResponse(error) {
185
193
  const errorMessage = this.config.enableTracing
186
- ? `${error.message}\n\nError Code: ${error.code}\nTool: ${error.toolName || 'unknown'}`
194
+ ? `${error.message}\n\nError Code: ${error.code}\nTool: ${error.toolName || "unknown"}`
187
195
  : error.message;
188
196
  return {
189
- content: [{
197
+ content: [
198
+ {
190
199
  type: "text",
191
- text: `Error: ${errorMessage}`
192
- }]
200
+ text: `Error: ${errorMessage}`,
201
+ },
202
+ ],
193
203
  };
194
204
  }
195
205
  /**
196
206
  * Check if result is already in MCP response format
197
207
  */
198
208
  isMCPResponse(result) {
199
- return (typeof result === 'object' &&
209
+ return (typeof result === "object" &&
200
210
  result !== null &&
201
- 'content' in result &&
211
+ "content" in result &&
202
212
  Array.isArray(result.content));
203
213
  }
204
214
  /**
@@ -223,7 +233,7 @@ export class CommandDispatcher {
223
233
  activeExecutions: this.activeExecutions.size,
224
234
  totalExecutions: this.executionCounter,
225
235
  averageExecutionTime: 0, // Would need history tracking
226
- errorRate: 0 // Would need error tracking
236
+ errorRate: 0, // Would need error tracking
227
237
  };
228
238
  }
229
239
  /**
package/build/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import "./personas/charles/index.js";
3
+ import "./personas/sterling/index.js";
3
4
  import "./personas/ada/index.js";
4
5
  import "./personas/xavier/index.js";
5
6
  import "./personas/atlas/index.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAiEA,OAAO,6BAA6B,CAAC;AACrC,OAAO,yBAAyB,CAAC;AACjC,OAAO,4BAA4B,CAAC;AACpC,OAAO,2BAA2B,CAAC;AACnC,OAAO,4BAA4B,CAAC;AACpC,OAAO,8BAA8B,CAAC;AACtC,OAAO,0BAA0B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAiEA,OAAO,6BAA6B,CAAC;AACrC,OAAO,8BAA8B,CAAC;AACtC,OAAO,yBAAyB,CAAC;AACjC,OAAO,4BAA4B,CAAC;AACpC,OAAO,2BAA2B,CAAC;AACnC,OAAO,4BAA4B,CAAC;AACpC,OAAO,8BAA8B,CAAC;AACtC,OAAO,0BAA0B,CAAC"}
package/build/index.js CHANGED
@@ -12,6 +12,7 @@ import { askToolName, askToolDescription, AskToolSchema, runAskTool, } from "./t
12
12
  import { discoverToolName, discoverToolDescription, DiscoverToolSchema, runDiscoverTool, } from "./tools/discover.js";
13
13
  // Import personas to auto-register
14
14
  import "./personas/charles/index.js";
15
+ import "./personas/sterling/index.js";
15
16
  import "./personas/ada/index.js";
16
17
  import "./personas/xavier/index.js";
17
18
  import "./personas/atlas/index.js";
@@ -32,7 +33,7 @@ import "./personas/iris/index.js";
32
33
  // 1. Create an MCP server instance
33
34
  const server = new Server({
34
35
  name: "cursor-tools",
35
- version: "2.0.5",
36
+ version: "2.1.0",
36
37
  }, {
37
38
  capabilities: {
38
39
  tools: {},
@@ -258,6 +259,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
258
259
  type: "string",
259
260
  enum: [
260
261
  "architecture",
262
+ "enterprise",
261
263
  "algorithms",
262
264
  "security",
263
265
  "frontend",
@@ -2,7 +2,7 @@
2
2
  * Charles - A thoughtful, witty British architect with high reasoning capabilities
3
3
  * Personality layer over GPT-5-class models
4
4
  */
5
- import { BasePersona, PersonaContext } from '../types.js';
5
+ import { BasePersona, PersonaContext } from "../types.js";
6
6
  export declare class CharlesPersona extends BasePersona {
7
7
  constructor();
8
8
  enhanceSystemPrompt(basePrompt: string, context: PersonaContext): string;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/personas/charles/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,WAAW,EAAE,cAAc,EAAiB,MAAM,aAAa,CAAC;AA8CzE,qBAAa,cAAe,SAAQ,WAAW;;IAU7C,mBAAmB,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,MAAM;IAqDxE,iBAAiB,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,MAAM;IAwBtE,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,MAAM;IAwBlE,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,MAAM;IAe/D,OAAO,CAAC,qBAAqB;IAsB7B,OAAO,CAAC,uBAAuB;IAuB/B,OAAO,CAAC,sBAAsB;CAU/B;AAID,QAAA,MAAM,OAAO,gBAAuB,CAAC;AAGrC,eAAe,OAAO,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/personas/charles/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,WAAW,EAAE,cAAc,EAAiB,MAAM,aAAa,CAAC;AAyDzE,qBAAa,cAAe,SAAQ,WAAW;;IAU7C,mBAAmB,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,MAAM;IA8ExE,iBAAiB,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,MAAM;IA2BtE,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,MAAM;IAwBlE,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,MAAM;IAe/D,OAAO,CAAC,qBAAqB;IA0B7B,OAAO,CAAC,uBAAuB;IA2B/B,OAAO,CAAC,sBAAsB;CAW/B;AAID,QAAA,MAAM,OAAO,gBAAuB,CAAC;AAGrC,eAAe,OAAO,CAAC"}