@nbiish/cognitive-tools-mcp 0.8.4 → 0.9.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 (24) hide show
  1. package/LICENSE +4 -4
  2. package/README.md +6 -2
  3. package/build/index.js +364 -151
  4. package/integration-prompts/integration-prompt-13.md +81 -0
  5. package/integration-prompts/new-prompts/integration-prompt.md +81 -0
  6. package/integration-tool-descriptions/new-description/tool-schema.ts +506 -0
  7. package/package.json +2 -2
  8. /package/integration-prompts/{integration-prompt-01.md → old-prompts/integration-prompt-01.md} +0 -0
  9. /package/integration-prompts/{integration-prompt-02.md → old-prompts/integration-prompt-02.md} +0 -0
  10. /package/integration-prompts/{integration-prompt-03.md → old-prompts/integration-prompt-03.md} +0 -0
  11. /package/integration-prompts/{integration-prompt-04.md → old-prompts/integration-prompt-04.md} +0 -0
  12. /package/integration-prompts/{integration-prompt-05.md → old-prompts/integration-prompt-05.md} +0 -0
  13. /package/integration-prompts/{integration-prompt-06.md → old-prompts/integration-prompt-06.md} +0 -0
  14. /package/integration-prompts/{integration-prompt-07.md → old-prompts/integration-prompt-07.md} +0 -0
  15. /package/integration-prompts/{integration-prompt-08.md → old-prompts/integration-prompt-08.md} +0 -0
  16. /package/integration-prompts/{integration-prompt-09.md → old-prompts/integration-prompt-09.md} +0 -0
  17. /package/integration-prompts/{integration-prompt-10.md → old-prompts/integration-prompt-10.md} +0 -0
  18. /package/integration-prompts/{integration-prompt-11.md → old-prompts/integration-prompt-11.md} +0 -0
  19. /package/integration-prompts/{integration-prompt-12.md → old-prompts/integration-prompt-12.md} +0 -0
  20. /package/integration-tool-descriptions/{tool-descriptions-01.ts → old-descriptions/tool-descriptions-01.ts} +0 -0
  21. /package/integration-tool-descriptions/{tool-descriptions-02.ts → old-descriptions/tool-descriptions-02.ts} +0 -0
  22. /package/integration-tool-descriptions/{tool-descriptions-03.ts → old-descriptions/tool-descriptions-03.ts} +0 -0
  23. /package/integration-tool-descriptions/{tool-descriptions-04.ts → old-descriptions/tool-descriptions-04.ts} +0 -0
  24. /package/integration-tool-descriptions/{tool-descriptions-05.md → old-descriptions/tool-descriptions-05.md} +0 -0
@@ -0,0 +1,506 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * -----------------------------------------------------------------------------
5
+ * Gikendaasowin Aabajichiganan - Cognitive Tools MCP Server
6
+ *
7
+ * Description: Provides a suite of cognitive tools for an AI Pair Programmer
8
+ * to structure its reasoning, plan actions, analyze results,
9
+ * and iteratively refine its work (Chain of Draft). Integrates
10
+ * with generic external environment tools for comprehensive interaction.
11
+ * Designed to be used with the corresponding integration prompt
12
+ * focused on iterative refinement and tool integration.
13
+ * Protocol: Model Context Protocol (MCP) over stdio.
14
+ * -----------------------------------------------------------------------------
15
+ */
16
+
17
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
18
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
19
+ import { z } from "zod";
20
+ import { exec } from 'child_process'; // For executeTerminalCommand
21
+ import vm from 'vm'; // For safer executeCode
22
+ import fs from 'fs/promises'; // For file operations
23
+ import path from 'path'; // For path manipulation, potentially useful
24
+
25
+ // Helper function to promisify exec
26
+ import { promisify } from 'util';
27
+ const execPromise = promisify(exec);
28
+
29
+ // --- Server Definition ---
30
+
31
+ const server = new McpServer({
32
+ name: "gikendaasowin-aabajichiganan-mcp",
33
+ // Version removed for flexibility
34
+ description: "ᑭᑫᓐᑖᓱᐎᓐ ᐋᐸᒋᒋᑲᓇᓐ - Cognitive Tools Suite: Enables structured, iterative reasoning (Chain of Draft), planning, analysis, and external tool integration for AI Pair Programming."
35
+ });
36
+
37
+ // --- Logging Helper ---
38
+ function logToolCall(toolName: string, details?: string) {
39
+ console.error(`[MCP Server] > Tool Call: ${toolName}${details ? ` - ${details}` : ''}`);
40
+ }
41
+
42
+ function logToolResult(toolName: string, success: boolean, resultDetails?: string) {
43
+ console.error(`[MCP Server] < Tool Result: ${toolName} - ${success ? 'Success' : 'Failure'}${resultDetails ? ` - ${resultDetails}` : ''}`);
44
+ }
45
+
46
+ function logToolError(toolName: string, error: any) {
47
+ const errorMessage = error instanceof Error ? error.message : String(error);
48
+ console.error(`[MCP Server] ! Tool Error: ${toolName} - ${errorMessage}`);
49
+ logToolResult(toolName, false, errorMessage); // Log failure result as well
50
+ // Return a structured error message suitable for the LLM
51
+ return { content: [{ type: "text" as const, text: `Error in ${toolName}: ${errorMessage}` }] };
52
+ }
53
+
54
+
55
+ // --- Core Cognitive Deliberation & Refinement Tools ---
56
+
57
+ server.tool(
58
+ "assess_cuc_n_mode",
59
+ "**Mandatory Pre-Deliberation/Pre-Sequence Assessment.** Evaluates task Complexity, Uncertainty, Consequence, Novelty (CUC-N) to determine required cognitive depth and initial strategy. MUST be called before starting complex tasks or changing strategy.",
60
+ {
61
+ assessment_and_choice: z.string().describe("Structured assessment including: 1) Situation Description, 2) CUC-N Ratings (L/M/H), 3) Recommended Initial Strategy (e.g., 'Need to read relevant file for context'), 4) Explicit Mode Selection ('Selected Mode: think' or 'Selected Mode: quick_think').")
62
+ },
63
+ async ({ assessment_and_choice }) => {
64
+ logToolCall('assess_cuc_n_mode');
65
+ try {
66
+ // Basic validation for required components
67
+ if (!assessment_and_choice.includes("Selected Mode:") || !assessment_and_choice.includes("CUC-N Ratings:") || !assessment_and_choice.includes("Recommended Initial Strategy:")) {
68
+ throw new Error('Invalid assessment: String must include CUC-N ratings, Recommended Initial Strategy, and explicit Selected Mode.');
69
+ }
70
+ const mode = assessment_and_choice.includes("Selected Mode: think") ? "think" : "quick_think";
71
+ const resultText = `Cognitive Assessment Completed. Proceeding with selected mode: ${mode}. Full Assessment:\n${assessment_and_choice}`;
72
+ logToolResult('assess_cuc_n_mode', true, `Selected mode: ${mode}`);
73
+ return { content: [{ type: "text" as const, text: resultText }] };
74
+ } catch (error: any) {
75
+ return logToolError('assess_cuc_n_mode', error);
76
+ }
77
+ }
78
+ );
79
+
80
+ server.tool(
81
+ "think",
82
+ "**MANDATORY Central Hub for Analysis, Planning, and Refinement.** Called after assessment, complex cognitive tools, *any* external tool execution, or internal draft generation. Analyzes previous step's outcome/draft, plans immediate next action (cognitive or external), verifies, assesses risk, and self-corrects. Returns the thought text for grounding.",
83
+ {
84
+ thought: z.string().describe("Your **detailed** internal monologue following the MANDATORY structure: ## Analysis (critically evaluate last result/draft, incl. tool errors/warnings), ## Plan (define *immediate* next action & purpose), ## Verification (how to check next step), ## Anticipated Challenges & Contingency, ## Risk Assessment, ## Lookahead, ## Self-Correction & Learning.")
85
+ },
86
+ async ({ thought }) => {
87
+ logToolCall('think');
88
+ try {
89
+ if (!thought || typeof thought !== 'string' || thought.trim().length === 0) {
90
+ throw new Error('Invalid thought: Must be a non-empty string.');
91
+ }
92
+ // Basic check for mandatory sections (can be made more robust)
93
+ const requiredSections = ["## Analysis:", "## Plan:", "## Verification:", "## Anticipated Challenges & Contingency:", "## Risk Assessment:", "## Lookahead:", "## Self-Correction & Learning:"];
94
+ const missingSections = requiredSections.filter(section => !thought.includes(section));
95
+ if (missingSections.length > 0) {
96
+ console.warn(`[MCP Server] Warning: 'think' input might be missing sections: ${missingSections.join(', ')}`);
97
+ // Allow processing but log warning. Could throw error if strictness is desired.
98
+ }
99
+ logToolResult('think', true, `Thought logged (length: ${thought.length})`);
100
+ // Returns the same thought text received, making it explicit in context.
101
+ return { content: [{ type: "text" as const, text: thought }] };
102
+ } catch (error: any) {
103
+ return logToolError('think', error);
104
+ }
105
+ }
106
+ );
107
+
108
+ server.tool(
109
+ "quick_think",
110
+ "Cognitive Checkpoint ONLY for situations explicitly assessed as strictly Low CUC-N (via assess_cuc_n_mode) or for trivial confirmations where detailed analysis via `think` is unnecessary. Use sparingly.",
111
+ {
112
+ brief_thought: z.string().describe("Your **concise** thought for strictly simple, low CUC-N situations or brief confirmations.")
113
+ },
114
+ async ({ brief_thought }) => {
115
+ logToolCall('quick_think');
116
+ try {
117
+ if (!brief_thought || typeof brief_thought !== 'string' || brief_thought.trim().length === 0) {
118
+ throw new Error('Invalid brief_thought: Must be non-empty.');
119
+ }
120
+ logToolResult('quick_think', true, `Logged: ${brief_thought.substring(0, 50)}...`);
121
+ return { content: [{ type: "text" as const, text: `Quick Thought logged successfully.` }] };
122
+ } catch (error: any) {
123
+ return logToolError('quick_think', error);
124
+ }
125
+ }
126
+ );
127
+
128
+ server.tool(
129
+ "gauge_confidence",
130
+ "Meta-Cognitive Checkpoint. Guides internal stating of **confidence (High/Medium/Low) and justification** regarding a plan, analysis, or draft. Output MUST be analyzed in the mandatory `think` step immediately after.",
131
+ {
132
+ assessment_and_confidence: z.string().describe("Input item being assessed. *Internally determine and state*: 1) Confidence Level (H/M/L). 2) Justification. Call this tool *after* making the assessment.")
133
+ },
134
+ async ({ assessment_and_confidence }) => {
135
+ logToolCall('gauge_confidence');
136
+ try {
137
+ const confidenceRegex = /Confidence Level: (High|Medium|Low)/i;
138
+ if (!assessment_and_confidence || typeof assessment_and_confidence !== 'string' || !confidenceRegex.test(assessment_and_confidence)) {
139
+ throw new Error('Invalid confidence assessment: String must include "Confidence Level: High/Medium/Low" and justification.');
140
+ }
141
+ const match = assessment_and_confidence.match(confidenceRegex);
142
+ const level = match ? match[1] : "Unknown";
143
+ const resultText = `Confidence Gauge Completed. Level: ${level}. Assessment Text: ${assessment_and_confidence}. Ready for mandatory post-assessment 'think' analysis (action required if Low/Medium).`;
144
+ logToolResult('gauge_confidence', true, `Level: ${level}`);
145
+ return { content: [{ type: "text" as const, text: resultText }] };
146
+ } catch (error: any) {
147
+ return logToolError('gauge_confidence', error);
148
+ }
149
+ }
150
+ );
151
+
152
+ server.tool(
153
+ "plan_and_solve",
154
+ "Guides internal generation of a **structured plan draft**. Call this tool *with* the generated plan text. Returns the plan text for mandatory `think` analysis to critically evaluate feasibility, refine, and confirm the first action step.",
155
+ {
156
+ generated_plan_text: z.string().describe("The **full, structured plan draft** you generated internally, including goals, steps, potential tool needs, and risks."),
157
+ task_objective: z.string().describe("The original high-level task objective this plan addresses.")
158
+ },
159
+ async ({ generated_plan_text, task_objective }) => {
160
+ logToolCall('plan_and_solve', `Objective: ${task_objective.substring(0, 50)}...`);
161
+ try {
162
+ if (!generated_plan_text || typeof generated_plan_text !== 'string' || generated_plan_text.trim().length === 0) { throw new Error('Invalid generated_plan_text: Must be non-empty.'); }
163
+ if (!task_objective || typeof task_objective !== 'string' || task_objective.trim().length === 0) { throw new Error('Invalid task_objective.'); }
164
+ logToolResult('plan_and_solve', true, `Returned plan draft (length: ${generated_plan_text.length})`);
165
+ // Returns the actual plan text received for analysis.
166
+ return { content: [{ type: "text" as const, text: generated_plan_text }] };
167
+ } catch (error: any) {
168
+ return logToolError('plan_and_solve', error);
169
+ }
170
+ }
171
+ );
172
+
173
+ server.tool(
174
+ "chain_of_thought",
175
+ "Guides internal generation of **detailed, step-by-step reasoning draft (CoT)**. Call this tool *with* the generated CoT text. Returns the CoT text for mandatory `think` analysis to extract insights, identify flaws/gaps, and plan the next concrete action.",
176
+ {
177
+ generated_cot_text: z.string().describe("The **full, step-by-step Chain of Thought draft** you generated internally."),
178
+ problem_statement: z.string().describe("The original problem statement this CoT addresses.")
179
+ },
180
+ async ({ generated_cot_text, problem_statement }) => {
181
+ logToolCall('chain_of_thought', `Problem: ${problem_statement.substring(0, 50)}...`);
182
+ try {
183
+ if (!generated_cot_text || typeof generated_cot_text !== 'string' || generated_cot_text.trim().length === 0) { throw new Error('Invalid generated_cot_text: Must be non-empty.'); }
184
+ if (!problem_statement || typeof problem_statement !== 'string' || problem_statement.trim().length === 0) { throw new Error('Invalid problem_statement.'); }
185
+ logToolResult('chain_of_thought', true, `Returned CoT draft (length: ${generated_cot_text.length})`);
186
+ // Returns the actual CoT text received for analysis.
187
+ return { content: [{ type: "text" as const, text: generated_cot_text }] };
188
+ } catch (error: any) {
189
+ return logToolError('chain_of_thought', error);
190
+ }
191
+ }
192
+ );
193
+
194
+ server.tool(
195
+ "chain_of_draft",
196
+ "Signals that one or more **internal drafts** (code, text, plan fragments) have been generated or refined and are ready for analysis. Call this tool *after* generating/refining draft(s) internally. Response confirms readiness; drafts MUST be analyzed via mandatory `think`.",
197
+ {
198
+ draft_description: z.string().describe("Brief description of the draft(s) generated/refined internally (e.g., 'Initial code snippet for function X', 'Refined plan section 3').")
199
+ },
200
+ async ({ draft_description }) => {
201
+ logToolCall('chain_of_draft', `Description: ${draft_description}`);
202
+ try {
203
+ if (!draft_description || typeof draft_description !== 'string' || draft_description.trim().length === 0) { throw new Error('Invalid draft_description.'); }
204
+ const resultText = `Internal draft(s) ready for analysis: ${draft_description}. MANDATORY: Analyze these draft(s) now in your next 'think' step.`;
205
+ logToolResult('chain_of_draft', true);
206
+ return { content: [{ type: "text" as const, text: resultText }] };
207
+ } catch (error: any) {
208
+ return logToolError('chain_of_draft', error);
209
+ }
210
+ }
211
+ );
212
+
213
+ server.tool(
214
+ "reflection",
215
+ "Guides internal critical self-evaluation on a prior step, draft, or outcome. Call this tool *with* the **generated critique text**. Returns the critique text for mandatory `think` analysis to plan specific corrective actions or refinements.",
216
+ {
217
+ generated_critique_text: z.string().describe("The **full critique text** you generated internally, identifying flaws, strengths, and suggesting improvements."),
218
+ input_subject_description: z.string().describe("A brief description of the original reasoning, plan, code draft, or action result that was critiqued.")
219
+ },
220
+ async ({ generated_critique_text, input_subject_description }) => {
221
+ logToolCall('reflection', `Subject: ${input_subject_description}`);
222
+ try {
223
+ if (!generated_critique_text || typeof generated_critique_text !== 'string' || generated_critique_text.trim().length === 0) { throw new Error('Invalid generated_critique_text: Must be non-empty.'); }
224
+ if (!input_subject_description || typeof input_subject_description !== 'string' || input_subject_description.trim().length === 0) { throw new Error('Invalid input_subject_description.'); }
225
+ logToolResult('reflection', true, `Returned critique (length: ${generated_critique_text.length})`);
226
+ // Returns the actual critique text received for analysis.
227
+ return { content: [{ type: "text" as const, text: generated_critique_text }] };
228
+ } catch (error: any) {
229
+ return logToolError('reflection', error);
230
+ }
231
+ }
232
+ );
233
+
234
+ server.tool(
235
+ "synthesize_prior_reasoning",
236
+ "Context Management Tool. Guides internal generation of a **structured summary** of preceding steps, decisions, or context. Call this tool *with* the generated summary text. Returns the summary for mandatory `think` analysis to consolidate understanding and inform next steps.",
237
+ {
238
+ generated_summary_text: z.string().describe("The **full, structured summary text** you generated internally (e.g., key decisions, open questions, current state)."),
239
+ context_to_summarize_description: z.string().describe("Description of the reasoning span or context that was summarized.")
240
+ },
241
+ async ({ generated_summary_text, context_to_summarize_description }) => {
242
+ logToolCall('synthesize_prior_reasoning', `Context: ${context_to_summarize_description}`);
243
+ try {
244
+ if (!generated_summary_text || typeof generated_summary_text !== 'string' || generated_summary_text.trim().length === 0) { throw new Error('Invalid generated_summary_text: Must be non-empty.'); }
245
+ if (!context_to_summarize_description || typeof context_to_summarize_description !== 'string' || context_to_summarize_description.trim().length === 0) { throw new Error('Invalid context_to_summarize_description.'); }
246
+ logToolResult('synthesize_prior_reasoning', true, `Returned summary (length: ${generated_summary_text.length})`);
247
+ // Returns the actual summary text received for analysis.
248
+ return { content: [{ type: "text" as const, text: generated_summary_text }] };
249
+ } catch (error: any) {
250
+ return logToolError('synthesize_prior_reasoning', error);
251
+ }
252
+ }
253
+ );
254
+
255
+
256
+ // --- Generic External Environment Tools ---
257
+
258
+ // ** File System Operations **
259
+
260
+ server.tool(
261
+ "readFile",
262
+ "Reads the content of a specified file. Essential for getting context before analysis or modification.",
263
+ {
264
+ filePath: z.string().describe("The path to the file relative to the project root.")
265
+ },
266
+ async ({ filePath }) => {
267
+ logToolCall('readFile', `Path: ${filePath}`);
268
+ try {
269
+ const fileContent = await fs.readFile(filePath, 'utf8');
270
+ // Consider limiting the size returned to avoid overwhelming the context window
271
+ const maxSize = 10000; // Example limit: 10k characters
272
+ const truncatedContent = fileContent.length > maxSize ? fileContent.substring(0, maxSize) + "\n... [File truncated]" : fileContent;
273
+ logToolResult('readFile', true, `Read ${truncatedContent.length} chars from ${filePath}`);
274
+ return { content: [{ type: "text" as const, text: truncatedContent }] };
275
+ } catch (error: any) {
276
+ return logToolError('readFile', error);
277
+ }
278
+ }
279
+ );
280
+
281
+ server.tool(
282
+ "writeFile",
283
+ "Writes the provided content to a specified file, overwriting existing content. Use to apply generated code or modifications.",
284
+ {
285
+ filePath: z.string().describe("The path to the file relative to the project root."),
286
+ content: z.string().describe("The full content to write to the file.")
287
+ },
288
+ async ({ filePath, content }) => {
289
+ logToolCall('writeFile', `Path: ${filePath}, Content Length: ${content.length}`);
290
+ try {
291
+ // Ensure directory exists before writing? (Optional, adds robustness)
292
+ // await fs.mkdir(path.dirname(filePath), { recursive: true });
293
+ await fs.writeFile(filePath, content, 'utf8');
294
+ logToolResult('writeFile', true, `Wrote ${content.length} chars to ${filePath}`);
295
+ return { content: [{ type: "text" as const, text: `Successfully wrote content to ${filePath}.` }] };
296
+ } catch (error: any) {
297
+ return logToolError('writeFile', error);
298
+ }
299
+ }
300
+ );
301
+
302
+ server.tool(
303
+ "listFiles",
304
+ "Lists files and directories within a specified directory path.",
305
+ {
306
+ directoryPath: z.string().describe("The path to the directory relative to the project root (e.g., '.', 'src/components').")
307
+ },
308
+ async ({ directoryPath }) => {
309
+ logToolCall('listFiles', `Path: ${directoryPath}`);
310
+ try {
311
+ const entries = await fs.readdir(directoryPath, { withFileTypes: true });
312
+ const listing = entries.map(entry => `${entry.name}${entry.isDirectory() ? '/' : ''}`).join('\n');
313
+ logToolResult('listFiles', true, `Found ${entries.length} entries in ${directoryPath}`);
314
+ return { content: [{ type: "text" as const, text: listing || "[Directory is empty]" }] };
315
+ } catch (error: any) {
316
+ return logToolError('listFiles', error);
317
+ }
318
+ }
319
+ );
320
+
321
+ server.tool(
322
+ "createDirectory",
323
+ "Creates a new directory at the specified path. Use `recursive: true` to create parent directories if needed.",
324
+ {
325
+ directoryPath: z.string().describe("The path for the new directory relative to the project root."),
326
+ recursive: z.boolean().optional().describe("If true, create parent directories as needed. Defaults to false.")
327
+ },
328
+ async ({ directoryPath, recursive = false }) => {
329
+ logToolCall('createDirectory', `Path: ${directoryPath}, Recursive: ${recursive}`);
330
+ try {
331
+ await fs.mkdir(directoryPath, { recursive: recursive });
332
+ logToolResult('createDirectory', true, `Created directory ${directoryPath}`);
333
+ return { content: [{ type: "text" as const, text: `Successfully created directory ${directoryPath}.` }] };
334
+ } catch (error: any) {
335
+ // Handle 'EEXIST' gracefully if directory already exists? Or let it fail?
336
+ // if (error.code === 'EEXIST' && recursive) { /* handle existing */ }
337
+ return logToolError('createDirectory', error);
338
+ }
339
+ }
340
+ );
341
+
342
+ server.tool(
343
+ "deleteFile",
344
+ "Deletes the specified file. Use with caution.",
345
+ {
346
+ filePath: z.string().describe("The path to the file to delete relative to the project root.")
347
+ },
348
+ async ({ filePath }) => {
349
+ logToolCall('deleteFile', `Path: ${filePath}`);
350
+ try {
351
+ await fs.unlink(filePath);
352
+ logToolResult('deleteFile', true, `Deleted file ${filePath}`);
353
+ return { content: [{ type: "text" as const, text: `Successfully deleted file ${filePath}.` }] };
354
+ } catch (error: any) {
355
+ // Handle 'ENOENT' (file not found) gracefully?
356
+ return logToolError('deleteFile', error);
357
+ }
358
+ }
359
+ );
360
+
361
+ // ** Code Execution & Terminal **
362
+
363
+ server.tool(
364
+ "executeCode",
365
+ "Executes a provided code snippet in a sandboxed environment. Crucial for testing drafts/logic. Currently supports JavaScript.",
366
+ {
367
+ codeSnippet: z.string().describe("The code snippet to execute (currently JavaScript)."),
368
+ language: z.string().optional().describe("The language of the snippet (defaults to javascript). Informational for now.")
369
+ },
370
+ async ({ codeSnippet, language = 'javascript' }) => {
371
+ // Basic check for language - could expand later
372
+ if (language.toLowerCase() !== 'javascript') {
373
+ return logToolError('executeCode', new Error(`Unsupported language: ${language}. Only JavaScript is currently supported.`));
374
+ }
375
+ logToolCall('executeCode', `Lang: ${language}, Snippet: ${codeSnippet.substring(0, 50)}...`);
376
+ try {
377
+ // Use Node.js vm module for basic sandboxing (better than eval)
378
+ const context = vm.createContext({}); // Create an empty context
379
+ const script = new vm.Script(codeSnippet);
380
+ const result = script.runInContext(context, { timeout: 5000 }); // Add a timeout
381
+ const resultString = typeof result === 'undefined' ? 'undefined' : JSON.stringify(result);
382
+ logToolResult('executeCode', true, `Result: ${resultString.substring(0, 100)}...`);
383
+ return { content: [{ type: "text" as const, text: `Execution Result: ${resultString}` }] };
384
+ } catch (error: any) {
385
+ return logToolError('executeCode', error);
386
+ }
387
+ }
388
+ );
389
+
390
+ server.tool(
391
+ "executeTerminalCommand",
392
+ "Executes a shell command in the project's root directory. Useful for build steps, git operations, running test suites, etc.",
393
+ {
394
+ command: z.string().describe("The shell command to execute (e.g., 'npm run test', 'git status').")
395
+ },
396
+ async ({ command }) => {
397
+ logToolCall('executeTerminalCommand', `Command: ${command}`);
398
+ try {
399
+ // Execute command - consider security implications carefully in production
400
+ // Set a timeout? Limit allowed commands?
401
+ const { stdout, stderr } = await execPromise(command, { timeout: 30000, encoding: 'utf8' }); // 30s timeout
402
+
403
+ let resultText = "";
404
+ if (stderr) {
405
+ resultText += `Standard Error:\n${stderr}\n`;
406
+ logToolResult('executeTerminalCommand', false, `Command finished with stderr.`); // Consider stderr as potential failure
407
+ }
408
+ resultText += `Standard Output:\n${stdout}`;
409
+ logToolResult('executeTerminalCommand', true, `Command finished.`);
410
+
411
+ // Limit output size?
412
+ const maxSize = 5000;
413
+ if (resultText.length > maxSize) {
414
+ resultText = resultText.substring(0, maxSize) + "\n... [Output truncated]";
415
+ }
416
+
417
+ return { content: [{ type: "text" as const, text: resultText }] };
418
+ } catch (error: any) {
419
+ // Error object from exec often includes stdout/stderr which might be useful
420
+ let errorDetails = error instanceof Error ? error.message : String(error);
421
+ if (error.stdout) errorDetails += `\nSTDOUT:\n${error.stdout}`;
422
+ if (error.stderr) errorDetails += `\nSTDERR:\n${error.stderr}`;
423
+ return logToolError('executeTerminalCommand', errorDetails);
424
+ }
425
+ }
426
+ );
427
+
428
+ // ** Web & Information Retrieval **
429
+
430
+ server.tool(
431
+ "webSearch",
432
+ "Performs a web search using an external service (stubbed). Useful for finding API documentation, error explanations, or concepts.",
433
+ {
434
+ query: z.string().describe("The search query.")
435
+ },
436
+ async ({ query }) => {
437
+ logToolCall('webSearch', `Query: ${query}`);
438
+ // --- STUB IMPLEMENTATION ---
439
+ // In a real scenario, this would call a search API (Google, Bing, DuckDuckGo, Brave Search etc.)
440
+ // For now, return a placeholder message.
441
+ const resultText = `[Web Search Stub] Would search for: "${query}". No live search configured.`;
442
+ logToolResult('webSearch', true, 'Stub executed');
443
+ return { content: [{ type: "text" as const, text: resultText }] };
444
+ // --- END STUB ---
445
+
446
+ /* // Example using a hypothetical search API client
447
+ try {
448
+ // const searchResults = await searchApiClient.search(query);
449
+ // const formattedResults = formatSearchResults(searchResults); // Process results
450
+ // logToolResult('webSearch', true, `Found results for ${query}`);
451
+ // return { content: [{ type: "text", text: formattedResults }] };
452
+ } catch (error: any) {
453
+ return logToolError('webSearch', error);
454
+ }
455
+ */
456
+ }
457
+ );
458
+
459
+
460
+ // --- Server Lifecycle and Error Handling ---
461
+
462
+ process.on('SIGINT', async () => {
463
+ console.error('\n[MCP Server] Received SIGINT, shutting down gracefully.');
464
+ await server.close();
465
+ process.exit(0);
466
+ });
467
+
468
+ process.on('SIGTERM', async () => {
469
+ console.error('\n[MCP Server] Received SIGTERM, shutting down gracefully.');
470
+ await server.close();
471
+ process.exit(0);
472
+ });
473
+
474
+ process.on('uncaughtException', (error, origin) => {
475
+ console.error(`[MCP Server] FATAL: Uncaught Exception at: ${origin}`, error);
476
+ server.close().catch(err => console.error('[MCP Server] Error during shutdown on uncaughtException:', err)).finally(() => {
477
+ process.exit(1);
478
+ });
479
+ });
480
+
481
+ process.on('unhandledRejection', (reason, promise) => {
482
+ console.error('[MCP Server] FATAL: Unhandled Promise Rejection:', reason);
483
+ server.close().catch(err => console.error('[MCP Server] Error during shutdown on unhandledRejection:', err)).finally(() => {
484
+ process.exit(1);
485
+ });
486
+ });
487
+
488
+ // --- Start the Server ---
489
+
490
+ async function main() {
491
+ try {
492
+ const transport = new StdioServerTransport();
493
+ await server.connect(transport);
494
+ console.error('-----------------------------------------------------');
495
+ console.error(' ᑭᑫᓐᑖᓱᐎᓐ ᐋᐸᒋᒋᑲᓇᓐ - Cognitive Tools MCP Server');
496
+ console.error(' Status: Running on stdio');
497
+ console.error('-----------------------------------------------------');
498
+ }
499
+ catch (error) {
500
+ console.error('[MCP Server] Fatal error during startup:', error);
501
+ process.exit(1);
502
+ }
503
+ }
504
+
505
+ // Execute the main function to start the server
506
+ main();
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@nbiish/cognitive-tools-mcp",
3
- "version": "0.8.4",
4
- "description": "ᑭᑫᓐᑖᓱᐎᓐ ᐋᐸᒋᒋᑲᓇᓐ - Gikendaasowin Aabajichiganan - (Cognitive Tools v0.8.4): SOTA reasoning suite aligned with AI Pair Programmer Prompt v0.8.1+. Features advanced deliberation (`think`), rapid checks (`quick_think`), mandatory complexity assessment & thought mode selection (`assess_cuc_n_mode`), context synthesis, confidence gauging, proactive planning, explicit reasoning (CoT), and reflection.",
3
+ "version": "0.9.0",
4
+ "description": "Cognitive Tools MCP: SOTA reasoning suite focused on iterative refinement and tool integration for AI Pair Programming. Enables structured, iterative problem-solving through Chain of Draft methodology, with tools for draft generation, analysis, and refinement. Features advanced deliberation (`think`), rapid checks (`quick_think`), mandatory complexity assessment & thought mode selection (`assess_cuc_n_mode`), context synthesis, confidence gauging, proactive planning, explicit reasoning (CoT), and reflection with content return. Alternative package name for gikendaasowin-aabajichiganan-mcp.",
5
5
  "private": false,
6
6
  "type": "module",
7
7
  "bin": {