@identikey/coding-mcp 2.0.1

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 (93) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +134 -0
  3. package/build/common/apiClient.d.ts +14 -0
  4. package/build/common/apiClient.d.ts.map +1 -0
  5. package/build/common/apiClient.js +68 -0
  6. package/build/common/personaClient.d.ts +48 -0
  7. package/build/common/personaClient.d.ts.map +1 -0
  8. package/build/common/personaClient.js +101 -0
  9. package/build/common/promptBuilder.d.ts +10 -0
  10. package/build/common/promptBuilder.d.ts.map +1 -0
  11. package/build/common/promptBuilder.js +14 -0
  12. package/build/common/providerConfig.d.ts +23 -0
  13. package/build/common/providerConfig.d.ts.map +1 -0
  14. package/build/common/providerConfig.js +43 -0
  15. package/build/common/tokenFormatter.d.ts +12 -0
  16. package/build/common/tokenFormatter.d.ts.map +1 -0
  17. package/build/common/tokenFormatter.js +24 -0
  18. package/build/core/CommandDispatcher.d.ts +81 -0
  19. package/build/core/CommandDispatcher.d.ts.map +1 -0
  20. package/build/core/CommandDispatcher.js +242 -0
  21. package/build/core/ToolCommand.d.ts +188 -0
  22. package/build/core/ToolCommand.d.ts.map +1 -0
  23. package/build/core/ToolCommand.js +63 -0
  24. package/build/core/ToolRegistry.d.ts +80 -0
  25. package/build/core/ToolRegistry.d.ts.map +1 -0
  26. package/build/core/ToolRegistry.js +279 -0
  27. package/build/index.d.ts +8 -0
  28. package/build/index.d.ts.map +1 -0
  29. package/build/index.js +329 -0
  30. package/build/infra/eventBus.d.ts +120 -0
  31. package/build/infra/eventBus.d.ts.map +1 -0
  32. package/build/infra/eventBus.js +138 -0
  33. package/build/personas/ada/index.d.ts +15 -0
  34. package/build/personas/ada/index.d.ts.map +1 -0
  35. package/build/personas/ada/index.js +121 -0
  36. package/build/personas/atlas/index.d.ts +13 -0
  37. package/build/personas/atlas/index.d.ts.map +1 -0
  38. package/build/personas/atlas/index.js +65 -0
  39. package/build/personas/charles/index.d.ts +18 -0
  40. package/build/personas/charles/index.d.ts.map +1 -0
  41. package/build/personas/charles/index.js +190 -0
  42. package/build/personas/hermes/index.d.ts +13 -0
  43. package/build/personas/hermes/index.d.ts.map +1 -0
  44. package/build/personas/hermes/index.js +61 -0
  45. package/build/personas/iris/index.d.ts +13 -0
  46. package/build/personas/iris/index.d.ts.map +1 -0
  47. package/build/personas/iris/index.js +61 -0
  48. package/build/personas/router.d.ts +18 -0
  49. package/build/personas/router.d.ts.map +1 -0
  50. package/build/personas/router.js +302 -0
  51. package/build/personas/sentinel/index.d.ts +13 -0
  52. package/build/personas/sentinel/index.d.ts.map +1 -0
  53. package/build/personas/sentinel/index.js +62 -0
  54. package/build/personas/types.d.ts +91 -0
  55. package/build/personas/types.d.ts.map +1 -0
  56. package/build/personas/types.js +60 -0
  57. package/build/personas/xavier/index.d.ts +14 -0
  58. package/build/personas/xavier/index.d.ts.map +1 -0
  59. package/build/personas/xavier/index.js +80 -0
  60. package/build/prompts/architectPrompts.d.ts +5 -0
  61. package/build/prompts/architectPrompts.d.ts.map +1 -0
  62. package/build/prompts/architectPrompts.js +58 -0
  63. package/build/prompts/codeadvicePrompts.d.ts +5 -0
  64. package/build/prompts/codeadvicePrompts.d.ts.map +1 -0
  65. package/build/prompts/codeadvicePrompts.js +13 -0
  66. package/build/prompts/researcherPrompts.d.ts +2 -0
  67. package/build/prompts/researcherPrompts.d.ts.map +1 -0
  68. package/build/prompts/researcherPrompts.js +39 -0
  69. package/build/tools/architect.d.ts +32 -0
  70. package/build/tools/architect.d.ts.map +1 -0
  71. package/build/tools/architect.js +75 -0
  72. package/build/tools/ask.d.ts +39 -0
  73. package/build/tools/ask.d.ts.map +1 -0
  74. package/build/tools/ask.js +139 -0
  75. package/build/tools/codeReview.d.ts +22 -0
  76. package/build/tools/codeReview.d.ts.map +1 -0
  77. package/build/tools/codeReview.js +35 -0
  78. package/build/tools/codeadvice.d.ts +29 -0
  79. package/build/tools/codeadvice.d.ts.map +1 -0
  80. package/build/tools/codeadvice.js +56 -0
  81. package/build/tools/discover.d.ts +24 -0
  82. package/build/tools/discover.d.ts.map +1 -0
  83. package/build/tools/discover.js +220 -0
  84. package/build/tools/persona.d.ts +48 -0
  85. package/build/tools/persona.d.ts.map +1 -0
  86. package/build/tools/persona.js +108 -0
  87. package/build/tools/researcher.d.ts +61 -0
  88. package/build/tools/researcher.d.ts.map +1 -0
  89. package/build/tools/researcher.js +346 -0
  90. package/build/tools/screenshot.d.ts +28 -0
  91. package/build/tools/screenshot.d.ts.map +1 -0
  92. package/build/tools/screenshot.js +46 -0
  93. package/package.json +56 -0
@@ -0,0 +1,279 @@
1
+ /**
2
+ * Tool Registry - Central hub for managing MCP tool commands
3
+ * Implements the Command pattern with EventBus integration
4
+ */
5
+ import { ToolLifecycle, ToolNotFoundError, DuplicateToolError, ToolError } from './ToolCommand.js';
6
+ import { eventBus } from '../infra/eventBus.js';
7
+ export class ToolRegistry {
8
+ tools = new Map();
9
+ healthCache = new Map();
10
+ eventBus;
11
+ constructor(eventBusInstance) {
12
+ this.eventBus = eventBusInstance || eventBus;
13
+ // Listen for system events
14
+ this.eventBus.on('system:shutdown', this.handleShutdown.bind(this), 'ToolRegistry');
15
+ }
16
+ /**
17
+ * Register a new tool command
18
+ */
19
+ async register(tool, source = 'unknown') {
20
+ if (this.tools.has(tool.name)) {
21
+ throw new DuplicateToolError(tool.name);
22
+ }
23
+ // Create registration record
24
+ const registration = {
25
+ tool,
26
+ registeredAt: Date.now(),
27
+ source,
28
+ enabled: true
29
+ };
30
+ // Emit lifecycle event
31
+ this.eventBus.emit('tool:lifecycle', {
32
+ name: tool.name,
33
+ state: ToolLifecycle.LOADING,
34
+ metadata: { source, version: tool.version }
35
+ });
36
+ try {
37
+ // Call onLoad hook if present
38
+ if (tool.onLoad) {
39
+ await tool.onLoad();
40
+ }
41
+ // Register the tool
42
+ this.tools.set(tool.name, registration);
43
+ // Update lifecycle state
44
+ this.eventBus.emit('tool:lifecycle', {
45
+ name: tool.name,
46
+ state: ToolLifecycle.READY
47
+ });
48
+ // Emit registration event
49
+ this.eventBus.emit('tool:registered', {
50
+ name: tool.name,
51
+ version: tool.version,
52
+ source
53
+ });
54
+ console.log(`✅ Tool '${tool.name}' registered from ${source}`);
55
+ }
56
+ catch (error) {
57
+ // Handle registration failure
58
+ this.eventBus.emit('tool:lifecycle', {
59
+ name: tool.name,
60
+ state: ToolLifecycle.ERROR,
61
+ metadata: { error: error instanceof Error ? error.message : String(error) }
62
+ });
63
+ this.eventBus.emit('tool:error', {
64
+ name: tool.name,
65
+ error: error instanceof Error ? error : new Error(String(error))
66
+ });
67
+ throw new ToolError(`Failed to register tool '${tool.name}': ${error instanceof Error ? error.message : String(error)}`, 'EXECUTION_ERROR', tool.name, error instanceof Error ? error : undefined);
68
+ }
69
+ }
70
+ /**
71
+ * Unregister a tool command
72
+ */
73
+ async unregister(name, reason) {
74
+ const registration = this.tools.get(name);
75
+ if (!registration) {
76
+ return false;
77
+ }
78
+ // Emit lifecycle event
79
+ this.eventBus.emit('tool:lifecycle', {
80
+ name,
81
+ state: ToolLifecycle.UNLOADING,
82
+ metadata: { reason }
83
+ });
84
+ try {
85
+ // Call onUnload hook if present
86
+ if (registration.tool.onUnload) {
87
+ await registration.tool.onUnload();
88
+ }
89
+ // Remove from registry
90
+ this.tools.delete(name);
91
+ this.healthCache.delete(name);
92
+ // Update lifecycle state
93
+ this.eventBus.emit('tool:lifecycle', {
94
+ name,
95
+ state: ToolLifecycle.DISPOSED
96
+ });
97
+ // Emit unregistration event
98
+ this.eventBus.emit('tool:unregistered', {
99
+ name,
100
+ reason
101
+ });
102
+ console.log(`❌ Tool '${name}' unregistered${reason ? `: ${reason}` : ''}`);
103
+ return true;
104
+ }
105
+ catch (error) {
106
+ // Handle unload failure
107
+ this.eventBus.emit('tool:error', {
108
+ name,
109
+ error: error instanceof Error ? error : new Error(String(error))
110
+ });
111
+ // Force removal even if unload fails
112
+ this.tools.delete(name);
113
+ this.healthCache.delete(name);
114
+ console.warn(`⚠️ Tool '${name}' forcibly removed due to unload error:`, error);
115
+ return true;
116
+ }
117
+ }
118
+ /**
119
+ * Get a registered tool by name
120
+ */
121
+ get(name) {
122
+ const registration = this.tools.get(name);
123
+ return registration?.enabled ? registration.tool : undefined;
124
+ }
125
+ /**
126
+ * Get tool registration info
127
+ */
128
+ getRegistration(name) {
129
+ return this.tools.get(name);
130
+ }
131
+ /**
132
+ * Check if a tool is registered
133
+ */
134
+ has(name) {
135
+ return this.tools.has(name);
136
+ }
137
+ /**
138
+ * List all registered tools
139
+ */
140
+ list() {
141
+ return Array.from(this.tools.values())
142
+ .filter(reg => reg.enabled)
143
+ .map(reg => reg.tool);
144
+ }
145
+ /**
146
+ * List all tool registrations (including disabled)
147
+ */
148
+ listRegistrations() {
149
+ return Array.from(this.tools.values());
150
+ }
151
+ /**
152
+ * Get tool names only
153
+ */
154
+ getToolNames() {
155
+ return Array.from(this.tools.keys());
156
+ }
157
+ /**
158
+ * Get registry statistics
159
+ */
160
+ getStats() {
161
+ const registrations = Array.from(this.tools.values());
162
+ const categories = {};
163
+ const sources = {};
164
+ registrations.forEach(reg => {
165
+ // Count categories
166
+ const category = reg.tool.metadata?.category || 'uncategorized';
167
+ categories[category] = (categories[category] || 0) + 1;
168
+ // Count sources
169
+ sources[reg.source] = (sources[reg.source] || 0) + 1;
170
+ });
171
+ return {
172
+ totalTools: registrations.length,
173
+ enabledTools: registrations.filter(r => r.enabled).length,
174
+ disabledTools: registrations.filter(r => !r.enabled).length,
175
+ categories,
176
+ sources
177
+ };
178
+ }
179
+ /**
180
+ * Enable/disable a tool
181
+ */
182
+ setEnabled(name, enabled) {
183
+ const registration = this.tools.get(name);
184
+ if (!registration) {
185
+ return false;
186
+ }
187
+ registration.enabled = enabled;
188
+ this.eventBus.emit('tool:lifecycle', {
189
+ name,
190
+ state: enabled ? ToolLifecycle.READY : ToolLifecycle.DISPOSED,
191
+ metadata: { enabled }
192
+ });
193
+ return true;
194
+ }
195
+ /**
196
+ * Check tool health
197
+ */
198
+ async checkHealth(name, useCache = true) {
199
+ const registration = this.tools.get(name);
200
+ if (!registration) {
201
+ throw new ToolNotFoundError(name);
202
+ }
203
+ // Check cache first
204
+ if (useCache) {
205
+ const cached = this.healthCache.get(name);
206
+ if (cached && (Date.now() - cached.lastChecked) < 30000) { // 30 second cache
207
+ return cached;
208
+ }
209
+ }
210
+ let healthStatus = {
211
+ healthy: true,
212
+ lastChecked: Date.now()
213
+ };
214
+ try {
215
+ // Use tool's health check if available
216
+ if (registration.tool.healthCheck) {
217
+ healthStatus = await registration.tool.healthCheck();
218
+ }
219
+ }
220
+ catch (error) {
221
+ healthStatus = {
222
+ healthy: false,
223
+ message: error instanceof Error ? error.message : String(error),
224
+ lastChecked: Date.now()
225
+ };
226
+ }
227
+ // Cache result
228
+ this.healthCache.set(name, healthStatus);
229
+ // Emit health event
230
+ this.eventBus.emit('tool:health', {
231
+ name,
232
+ status: healthStatus
233
+ });
234
+ return healthStatus;
235
+ }
236
+ /**
237
+ * Check health of all tools
238
+ */
239
+ async checkAllHealth() {
240
+ const results = {};
241
+ const names = this.getToolNames();
242
+ await Promise.allSettled(names.map(async (name) => {
243
+ try {
244
+ results[name] = await this.checkHealth(name, false);
245
+ }
246
+ catch (error) {
247
+ results[name] = {
248
+ healthy: false,
249
+ message: error instanceof Error ? error.message : String(error),
250
+ lastChecked: Date.now()
251
+ };
252
+ }
253
+ }));
254
+ return results;
255
+ }
256
+ /**
257
+ * Clear all tools (for testing or shutdown)
258
+ */
259
+ async clear() {
260
+ const names = Array.from(this.tools.keys());
261
+ await Promise.allSettled(names.map(name => this.unregister(name, 'registry cleared')));
262
+ }
263
+ /**
264
+ * Handle system shutdown
265
+ */
266
+ async handleShutdown() {
267
+ console.log('🔄 ToolRegistry: Shutting down, unregistering all tools...');
268
+ await this.clear();
269
+ console.log('✅ ToolRegistry: Shutdown complete');
270
+ }
271
+ /**
272
+ * Create a new registry instance (for testing)
273
+ */
274
+ static create(eventBusInstance) {
275
+ return new ToolRegistry(eventBusInstance);
276
+ }
277
+ }
278
+ // Singleton instance
279
+ export const toolRegistry = new ToolRegistry();
@@ -0,0 +1,8 @@
1
+ import "./personas/charles/index.js";
2
+ import "./personas/ada/index.js";
3
+ import "./personas/xavier/index.js";
4
+ import "./personas/atlas/index.js";
5
+ import "./personas/hermes/index.js";
6
+ import "./personas/sentinel/index.js";
7
+ import "./personas/iris/index.js";
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAgEA,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"}
package/build/index.js ADDED
@@ -0,0 +1,329 @@
1
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
2
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
+ import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
4
+ import { screenshotToolName, screenshotToolDescription, ScreenshotToolSchema, runScreenshotTool, } from "./tools/screenshot.js";
5
+ import { architectToolName, architectToolDescription, ArchitectToolSchema, runArchitectTool, } from "./tools/architect.js";
6
+ import { codeReviewToolName, codeReviewToolDescription, CodeReviewToolSchema, runCodeReviewTool, } from "./tools/codeReview.js";
7
+ import { codeAdviceToolName, codeAdviceToolDescription, CodeAdviceToolSchema, runCodeAdviceTool, } from "./tools/codeadvice.js";
8
+ import { researcherToolName, researcherToolDescription, ResearcherToolSchema, runResearcherTool, } from "./tools/researcher.js";
9
+ import { personaToolName, personaToolDescription, PersonaToolSchema, runPersonaTool, } from "./tools/persona.js";
10
+ import { askToolName, askToolDescription, AskToolSchema, runAskTool, } from "./tools/ask.js";
11
+ import { discoverToolName, discoverToolDescription, DiscoverToolSchema, runDiscoverTool, } from "./tools/discover.js";
12
+ // Import personas to auto-register
13
+ import "./personas/charles/index.js";
14
+ import "./personas/ada/index.js";
15
+ import "./personas/xavier/index.js";
16
+ import "./personas/atlas/index.js";
17
+ import "./personas/hermes/index.js";
18
+ import "./personas/sentinel/index.js";
19
+ import "./personas/iris/index.js";
20
+ /**
21
+ * MCP server providing Cursor Tools:
22
+ * 1) Screenshot
23
+ * 2) Architect
24
+ * 3) CodeReview
25
+ * 4) CodeAdvice
26
+ * 5) Researcher
27
+ * 6) Persona (Direct access)
28
+ * 7) Ask (Smart routing)
29
+ * 8) Discover (List personas)
30
+ */
31
+ // 1. Create an MCP server instance
32
+ const server = new Server({
33
+ name: "cursor-tools",
34
+ version: "2.0.1",
35
+ }, {
36
+ capabilities: {
37
+ tools: {},
38
+ },
39
+ });
40
+ // 2. Define the list of tools
41
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
42
+ return {
43
+ tools: [
44
+ {
45
+ name: screenshotToolName,
46
+ description: screenshotToolDescription,
47
+ inputSchema: {
48
+ type: "object",
49
+ properties: {
50
+ url: {
51
+ type: "string",
52
+ description: "Full URL to screenshot",
53
+ },
54
+ relativePath: {
55
+ type: "string",
56
+ description: "Relative path appended to http://localhost:3000",
57
+ },
58
+ fullPathToScreenshot: {
59
+ type: "string",
60
+ description: "Path to where the screenshot file should be saved. This should be a cwd-style full path to the file (not relative to the current working directory) including the file name and extension.",
61
+ },
62
+ },
63
+ required: [],
64
+ },
65
+ },
66
+ {
67
+ name: architectToolName,
68
+ description: architectToolDescription,
69
+ inputSchema: {
70
+ type: "object",
71
+ properties: {
72
+ task: {
73
+ type: "string",
74
+ description: "Description of the task",
75
+ },
76
+ code: {
77
+ type: "string",
78
+ description: "Concatenated code from one or more files",
79
+ },
80
+ reasoning_effort: {
81
+ type: "string",
82
+ enum: ["low", "medium", "high"],
83
+ description: "How hard the model should think (default: high)",
84
+ },
85
+ persona: {
86
+ type: "string",
87
+ description: "Persona to apply (e.g., 'charles' for British architect)",
88
+ },
89
+ },
90
+ required: ["task", "code"],
91
+ },
92
+ },
93
+ {
94
+ name: codeReviewToolName,
95
+ description: codeReviewToolDescription,
96
+ inputSchema: {
97
+ type: "object",
98
+ properties: {
99
+ folderPath: {
100
+ type: "string",
101
+ description: "Path to the full root directory of the repository to diff against main",
102
+ },
103
+ },
104
+ required: ["folderPath"],
105
+ },
106
+ },
107
+ {
108
+ name: codeAdviceToolName,
109
+ description: codeAdviceToolDescription,
110
+ inputSchema: {
111
+ type: "object",
112
+ properties: {
113
+ task: {
114
+ type: "string",
115
+ description: "Description of the problem or advice needed",
116
+ },
117
+ code: {
118
+ type: "string",
119
+ description: "Relevant code snippet",
120
+ },
121
+ reasoning_effort: {
122
+ type: "string",
123
+ enum: ["low", "medium", "high"],
124
+ description: "How hard the model should think (low/medium/high)",
125
+ },
126
+ },
127
+ required: ["task", "code"],
128
+ },
129
+ },
130
+ {
131
+ name: researcherToolName,
132
+ description: researcherToolDescription,
133
+ inputSchema: {
134
+ type: "object",
135
+ properties: {
136
+ query: {
137
+ type: "string",
138
+ description: "Research query to investigate",
139
+ },
140
+ search_engines: {
141
+ type: "array",
142
+ items: {
143
+ type: "string",
144
+ enum: [
145
+ "google",
146
+ "xai",
147
+ "arxiv",
148
+ "wikipedia",
149
+ "github",
150
+ "stackexchange",
151
+ "pubmed",
152
+ "semantic_scholar",
153
+ ],
154
+ },
155
+ description: "Search engines to use (default: google, xai)",
156
+ },
157
+ max_results_per_engine: {
158
+ type: "number",
159
+ description: "Maximum results per search engine (1-20, default: 5)",
160
+ },
161
+ deep_search: {
162
+ type: "boolean",
163
+ description: "Whether to perform deep search by following links",
164
+ },
165
+ include_academic: {
166
+ type: "boolean",
167
+ description: "Whether to prioritize academic sources",
168
+ },
169
+ citation_style: {
170
+ type: "string",
171
+ enum: ["apa", "mla", "chicago", "ieee", "inline"],
172
+ description: "Citation style to use (default: inline)",
173
+ },
174
+ },
175
+ required: ["query"],
176
+ },
177
+ },
178
+ {
179
+ name: personaToolName,
180
+ description: personaToolDescription,
181
+ inputSchema: {
182
+ type: "object",
183
+ properties: {
184
+ persona_id: {
185
+ type: "string",
186
+ description: "ID of the persona (e.g., 'charles')",
187
+ },
188
+ query: {
189
+ type: "string",
190
+ description: "Question or request for the persona",
191
+ },
192
+ context: {
193
+ type: "string",
194
+ description: "Additional context or code to analyze",
195
+ },
196
+ analysis_type: {
197
+ type: "string",
198
+ enum: ["comprehensive", "advice", "research", "review"],
199
+ description: "Type of analysis (default: advice)",
200
+ },
201
+ reasoning_effort: {
202
+ type: "string",
203
+ enum: ["low", "medium", "high"],
204
+ description: "Reasoning effort level",
205
+ },
206
+ },
207
+ required: ["persona_id", "query"],
208
+ },
209
+ },
210
+ {
211
+ name: askToolName,
212
+ description: askToolDescription,
213
+ inputSchema: {
214
+ type: "object",
215
+ properties: {
216
+ persona_id: {
217
+ type: "string",
218
+ description: "Persona to use: 'auto' (default) routes to best expert, or a specific id like 'charles', 'ada', 'xavier'",
219
+ },
220
+ query: {
221
+ type: "string",
222
+ description: "Your question or request",
223
+ },
224
+ context: {
225
+ type: "string",
226
+ description: "Additional code or context for analysis",
227
+ },
228
+ hint: {
229
+ type: "string",
230
+ description: "Optional hint for routing (e.g., 'architecture', 'security')",
231
+ },
232
+ explain_routing: {
233
+ type: "boolean",
234
+ description: "Show which persona was selected and why",
235
+ },
236
+ reasoning_effort: {
237
+ type: "string",
238
+ enum: ["low", "medium", "high"],
239
+ description: "How thoroughly to think about the answer",
240
+ },
241
+ provider: {
242
+ type: "string",
243
+ enum: ["xai", "openai"],
244
+ description: "Optional provider override; defaults to persona preference or heuristic",
245
+ },
246
+ },
247
+ required: ["query"],
248
+ },
249
+ },
250
+ {
251
+ name: discoverToolName,
252
+ description: discoverToolDescription,
253
+ inputSchema: {
254
+ type: "object",
255
+ properties: {
256
+ category: {
257
+ type: "string",
258
+ enum: [
259
+ "architecture",
260
+ "algorithms",
261
+ "security",
262
+ "frontend",
263
+ "backend",
264
+ "data",
265
+ "all",
266
+ ],
267
+ description: "Filter personas by category",
268
+ },
269
+ verbose: {
270
+ type: "boolean",
271
+ description: "Show detailed information including example queries",
272
+ },
273
+ },
274
+ required: [],
275
+ },
276
+ },
277
+ ],
278
+ };
279
+ });
280
+ // 3. Implement the tool call logic
281
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
282
+ const { name, arguments: args } = request.params;
283
+ switch (name) {
284
+ case screenshotToolName: {
285
+ const validated = ScreenshotToolSchema.parse(args);
286
+ return await runScreenshotTool(validated);
287
+ }
288
+ case architectToolName: {
289
+ const validated = ArchitectToolSchema.parse(args);
290
+ return await runArchitectTool(validated);
291
+ }
292
+ case codeReviewToolName: {
293
+ const validated = CodeReviewToolSchema.parse(args);
294
+ return await runCodeReviewTool(validated);
295
+ }
296
+ case codeAdviceToolName: {
297
+ const validated = CodeAdviceToolSchema.parse(args);
298
+ return await runCodeAdviceTool(validated);
299
+ }
300
+ case researcherToolName: {
301
+ const validated = ResearcherToolSchema.parse(args);
302
+ return await runResearcherTool(validated);
303
+ }
304
+ case personaToolName: {
305
+ const validated = PersonaToolSchema.parse(args);
306
+ return await runPersonaTool(validated);
307
+ }
308
+ case askToolName: {
309
+ const validated = AskToolSchema.parse(args);
310
+ return await runAskTool(validated);
311
+ }
312
+ case discoverToolName: {
313
+ const validated = DiscoverToolSchema.parse(args);
314
+ return await runDiscoverTool(validated);
315
+ }
316
+ default:
317
+ throw new Error(`Unknown tool: ${name}`);
318
+ }
319
+ });
320
+ // 4. Start the MCP server with a stdio transport
321
+ async function main() {
322
+ const transport = new StdioServerTransport();
323
+ await server.connect(transport);
324
+ console.error("Cursor Tools MCP Server running on stdio");
325
+ }
326
+ main().catch((error) => {
327
+ console.error("Fatal error:", error);
328
+ process.exit(1);
329
+ });