├── .gitignore
├── LICENSE
├── README.md
├── jest.config.js
├── package.json
├── src
├── __tests__
│ └── shannon-thinking.test.ts
├── index.ts
├── server.ts
└── types.ts
└── tsconfig.json
/.gitignore:
--------------------------------------------------------------------------------
1 | # Dependencies
2 | node_modules/
3 | package-lock.json
4 |
5 | # Build output
6 | dist/
7 |
8 | # IDE and editor files
9 | .vscode/
10 | .idea/
11 | *.swp
12 | *.swo
13 | .DS_Store
14 |
15 | # Logs
16 | logs/
17 | *.log
18 | npm-debug.log*
19 | yarn-debug.log*
20 | yarn-error.log*
21 |
22 | # Environment variables
23 | .env
24 | .env.local
25 | .env.*.local
26 |
27 | # Test coverage
28 | coverage/
29 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 Ola Hungerford
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.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # shannon-thinking
2 |
3 | An MCP server demonstrating Claude Shannon's systematic problem-solving methodology. This server provides a tool that helps break down complex problems into structured thoughts following Shannon's approach of problem definition, mathematical modeling, and practical implementation.
4 |
5 |
6 |
7 |
8 |
9 | ## Overview
10 |
11 | Claude Shannon, known as the father of information theory, approached complex problems through a systematic methodology:
12 |
13 | 1. **Problem Definition**: Strip the problem to its fundamental elements
14 | 2. **Constraints**: Identify system limitations and boundaries
15 | 3. **Model**: Develop mathematical/theoretical frameworks
16 | 4. **Proof/Validation**: Validate through formal proofs or experimental testing
17 | 5. **Implementation/Experiment**: Design and test practical solutions
18 |
19 | This MCP server demonstrates this methodology as a tool that helps guide systematic problem-solving through these stages.
20 |
21 | ## Installation
22 |
23 | ### NPX
24 |
25 | ```json
26 | {
27 | "mcpServers": {
28 | "shannon-thinking": {
29 | "command": "npx",
30 | "args": [
31 | "-y",
32 | "server-shannon-thinking@latest"
33 | ]
34 | }
35 | }
36 | }
37 | ```
38 |
39 | ## Usage
40 |
41 | The server provides a single tool named `shannonthinking` that structures problem-solving thoughts according to Shannon's methodology.
42 |
43 | Each thought must include:
44 | - The actual thought content
45 | - Type (problem_definition/constraints/model/proof/implementation)
46 | - Thought number and total thoughts estimate
47 | - Confidence level (uncertainty: 0-1)
48 | - Dependencies on previous thoughts
49 | - Explicit assumptions
50 | - Whether another thought step is needed
51 |
52 | Additional capabilities:
53 | - **Revision**: Thoughts can revise earlier steps as understanding evolves
54 | - **Recheck**: Mark steps that need re-examination with new information
55 | - **Experimental Validation**: Support for empirical testing alongside formal proofs
56 | - **Implementation Notes**: Practical constraints and proposed solutions
57 |
58 | ### Example Usage
59 |
60 | ```typescript
61 | const thought = {
62 | thought: "The core problem can be defined as an information flow optimization",
63 | thoughtType: "problem_definition",
64 | thoughtNumber: 1,
65 | totalThoughts: 5,
66 | uncertainty: 0.2,
67 | dependencies: [],
68 | assumptions: ["System has finite capacity", "Information flow is continuous"],
69 | nextThoughtNeeded: true,
70 | // Optional: Mark as revision of earlier definition
71 | isRevision: false,
72 | // Optional: Indicate step needs recheck
73 | recheckStep: {
74 | stepToRecheck: "constraints",
75 | reason: "New capacity limitations discovered",
76 | newInformation: "System shows non-linear scaling"
77 | }
78 | };
79 |
80 | // Use with MCP client
81 | const result = await client.callTool("shannonthinking", thought);
82 | ```
83 |
84 | ## Features
85 |
86 | - **Iterative Problem-Solving**: Supports revisions and rechecks as understanding evolves
87 | - **Flexible Validation**: Combines formal proofs with experimental validation
88 | - **Dependency Tracking**: Explicitly tracks how thoughts build upon previous ones
89 | - **Assumption Management**: Requires clear documentation of assumptions
90 | - **Confidence Levels**: Quantifies uncertainty in each step
91 | - **Rich Feedback**: Formatted console output with color-coding, symbols, and validation results
92 |
93 | ## Development
94 |
95 | ```bash
96 | # Install dependencies
97 | npm install
98 |
99 | # Build
100 | npm run build
101 |
102 | # Run tests
103 | npm test
104 |
105 | # Watch mode during development
106 | npm run watch
107 | ```
108 |
109 | ## Tool Schema
110 |
111 | The tool accepts thoughts with the following structure:
112 |
113 | ```typescript
114 | interface ShannonThought {
115 | thought: string;
116 | thoughtType: "problem_definition" | "constraints" | "model" | "proof" | "implementation";
117 | thoughtNumber: number;
118 | totalThoughts: number;
119 | uncertainty: number; // 0-1
120 | dependencies: number[];
121 | assumptions: string[];
122 | nextThoughtNeeded: boolean;
123 |
124 | // Optional revision fields
125 | isRevision?: boolean;
126 | revisesThought?: number;
127 |
128 | // Optional recheck field
129 | recheckStep?: {
130 | stepToRecheck: ThoughtType;
131 | reason: string;
132 | newInformation?: string;
133 | };
134 |
135 | // Optional validation fields
136 | proofElements?: {
137 | hypothesis: string;
138 | validation: string;
139 | };
140 | experimentalElements?: {
141 | testDescription: string;
142 | results: string;
143 | confidence: number; // 0-1
144 | limitations: string[];
145 | };
146 |
147 | // Optional implementation fields
148 | implementationNotes?: {
149 | practicalConstraints: string[];
150 | proposedSolution: string;
151 | };
152 | }
153 | ```
154 |
155 | ## When to Use
156 |
157 | This thinking pattern is particularly valuable for:
158 | - Complex system analysis
159 | - Information processing problems
160 | - Engineering design challenges
161 | - Problems requiring theoretical frameworks
162 | - Optimization problems
163 | - Systems requiring practical implementation
164 | - Problems that need iterative refinement
165 | - Cases where experimental validation complements theory
166 |
--------------------------------------------------------------------------------
/jest.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('ts-jest').JestConfigWithTsJest} */
2 | export default {
3 | preset: 'ts-jest',
4 | testEnvironment: 'node',
5 | extensionsToTreatAsEsm: ['.ts'],
6 | moduleNameMapper: {
7 | '^(\\.{1,2}/.*)\\.js$': '$1',
8 | },
9 | transform: {
10 | '^.+\\.tsx?$': [
11 | 'ts-jest',
12 | {
13 | useESM: true,
14 | },
15 | ],
16 | },
17 | transformIgnorePatterns: [
18 | 'node_modules/(?!(chalk)/)'
19 | ],
20 | collectCoverage: true,
21 | coverageReporters: ['text', 'lcov'],
22 | coverageDirectory: 'coverage',
23 | testMatch: ['**/__tests__/**/*.ts'],
24 | coveragePathIgnorePatterns: ['/dist/']
25 | };
26 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "server-shannon-thinking",
3 | "version": "0.1.0",
4 | "description": "MCP server for applying a Claude Shannon-inspired problem-solving pattern",
5 | "license": "MIT",
6 | "type": "module",
7 | "bin": {
8 | "mcp-server-shannon-thinking": "dist/index.js"
9 | },
10 | "files": [
11 | "dist"
12 | ],
13 | "scripts": {
14 | "build": "tsc && shx chmod +x dist/*.js",
15 | "prepare": "npm run build",
16 | "watch": "tsc --watch",
17 | "test": "cross-env NODE_OPTIONS=--experimental-vm-modules jest"
18 | },
19 | "dependencies": {
20 | "@modelcontextprotocol/sdk": "^1.9.0",
21 | "chalk": "^5.3.0"
22 | },
23 | "devDependencies": {
24 | "@types/jest": "^29.5.14",
25 | "@types/node": "^20.10.0",
26 | "cross-env": "^7.0.3",
27 | "jest": "^29.7.0",
28 | "shx": "^0.3.4",
29 | "ts-jest": "^29.2.5",
30 | "typescript": "^5.3.3"
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/__tests__/shannon-thinking.test.ts:
--------------------------------------------------------------------------------
1 | import { ThoughtType } from '../types.js';
2 | import { ShannonThinkingServer } from '../server.js';
3 |
4 | describe('ShannonThinkingServer', () => {
5 | let server: ShannonThinkingServer;
6 |
7 | beforeEach(() => {
8 | server = new ShannonThinkingServer();
9 | });
10 |
11 | describe('processThought', () => {
12 | it('should process a valid thought successfully', () => {
13 | const validThought = {
14 | thought: "Test thought",
15 | thoughtType: ThoughtType.PROBLEM_DEFINITION,
16 | thoughtNumber: 1,
17 | totalThoughts: 1,
18 | uncertainty: 0.5,
19 | dependencies: [],
20 | assumptions: ["Test assumption"],
21 | nextThoughtNeeded: false
22 | };
23 |
24 | const result = server.processThought(validThought);
25 | expect(result.isError).toBeUndefined();
26 | expect(JSON.parse(result.content[0].text)).toMatchObject({
27 | thoughtNumber: 1,
28 | totalThoughts: 1,
29 | nextThoughtNeeded: false,
30 | thoughtType: ThoughtType.PROBLEM_DEFINITION,
31 | uncertainty: 0.5,
32 | thoughtHistoryLength: 1
33 | });
34 | });
35 |
36 | it('should handle invalid thought data', () => {
37 | const invalidThought = {
38 | thought: "Test thought",
39 | // Missing required fields
40 | };
41 |
42 | const result = server.processThought(invalidThought);
43 | expect(result.isError).toBe(true);
44 | expect(JSON.parse(result.content[0].text)).toHaveProperty('error');
45 | });
46 |
47 | it('should validate dependencies correctly', () => {
48 | // First thought
49 | const thought1 = {
50 | thought: "First thought",
51 | thoughtType: ThoughtType.PROBLEM_DEFINITION,
52 | thoughtNumber: 1,
53 | totalThoughts: 2,
54 | uncertainty: 0.5,
55 | dependencies: [],
56 | assumptions: [],
57 | nextThoughtNeeded: true
58 | };
59 |
60 | // Second thought depending on first
61 | const thought2 = {
62 | thought: "Second thought",
63 | thoughtType: ThoughtType.MODEL,
64 | thoughtNumber: 2,
65 | totalThoughts: 2,
66 | uncertainty: 0.3,
67 | dependencies: [1],
68 | assumptions: [],
69 | nextThoughtNeeded: false
70 | };
71 |
72 | server.processThought(thought1);
73 | const result = server.processThought(thought2);
74 | expect(result.isError).toBeUndefined();
75 | expect(JSON.parse(result.content[0].text)).toMatchObject({
76 | thoughtNumber: 2,
77 | thoughtHistoryLength: 2
78 | });
79 | });
80 |
81 | it('should reject invalid dependencies', () => {
82 | const thoughtWithInvalidDep = {
83 | thought: "Invalid dependency",
84 | thoughtType: ThoughtType.MODEL,
85 | thoughtNumber: 1,
86 | totalThoughts: 1,
87 | uncertainty: 0.5,
88 | dependencies: [2], // Depending on non-existent thought
89 | assumptions: [],
90 | nextThoughtNeeded: false
91 | };
92 |
93 | const result = server.processThought(thoughtWithInvalidDep);
94 | expect(result.isError).toBe(true);
95 | expect(JSON.parse(result.content[0].text).error).toContain('Invalid dependency');
96 | });
97 |
98 | it('should validate uncertainty range', () => {
99 | const thoughtWithInvalidUncertainty = {
100 | thought: "Invalid uncertainty",
101 | thoughtType: ThoughtType.PROBLEM_DEFINITION,
102 | thoughtNumber: 1,
103 | totalThoughts: 1,
104 | uncertainty: 1.5, // Invalid: should be between 0 and 1
105 | dependencies: [],
106 | assumptions: [],
107 | nextThoughtNeeded: false
108 | };
109 |
110 | const result = server.processThought(thoughtWithInvalidUncertainty);
111 | expect(result.isError).toBe(true);
112 | expect(JSON.parse(result.content[0].text).error).toContain('uncertainty');
113 | });
114 |
115 | it('should handle proof elements correctly', () => {
116 | const thoughtWithProof = {
117 | thought: "Proof thought",
118 | thoughtType: ThoughtType.PROOF,
119 | thoughtNumber: 1,
120 | totalThoughts: 1,
121 | uncertainty: 0.2,
122 | dependencies: [],
123 | assumptions: [],
124 | nextThoughtNeeded: false,
125 | proofElements: {
126 | hypothesis: "Test hypothesis",
127 | validation: "Test validation"
128 | }
129 | };
130 |
131 | const result = server.processThought(thoughtWithProof);
132 | expect(result.isError).toBeUndefined();
133 | expect(JSON.parse(result.content[0].text)).toMatchObject({
134 | thoughtNumber: 1,
135 | thoughtType: ThoughtType.PROOF
136 | });
137 | });
138 |
139 | it('should handle implementation notes correctly', () => {
140 | const thoughtWithImplementation = {
141 | thought: "Implementation thought",
142 | thoughtType: ThoughtType.IMPLEMENTATION,
143 | thoughtNumber: 1,
144 | totalThoughts: 1,
145 | uncertainty: 0.3,
146 | dependencies: [],
147 | assumptions: [],
148 | nextThoughtNeeded: false,
149 | implementationNotes: {
150 | practicalConstraints: ["Test constraint"],
151 | proposedSolution: "Test solution"
152 | }
153 | };
154 |
155 | const result = server.processThought(thoughtWithImplementation);
156 | expect(result.isError).toBeUndefined();
157 | expect(JSON.parse(result.content[0].text)).toMatchObject({
158 | thoughtNumber: 1,
159 | thoughtType: ThoughtType.IMPLEMENTATION
160 | });
161 | });
162 |
163 | it('should handle recheckStep correctly', () => {
164 | const thoughtWithRecheck = {
165 | thought: "Recheck thought",
166 | thoughtType: ThoughtType.MODEL,
167 | thoughtNumber: 1,
168 | totalThoughts: 1,
169 | uncertainty: 0.4,
170 | dependencies: [],
171 | assumptions: [],
172 | nextThoughtNeeded: true,
173 | recheckStep: {
174 | stepToRecheck: ThoughtType.CONSTRAINTS,
175 | reason: "New information available",
176 | newInformation: "Additional constraint discovered"
177 | }
178 | };
179 |
180 | const result = server.processThought(thoughtWithRecheck);
181 | expect(result.isError).toBeUndefined();
182 | expect(JSON.parse(result.content[0].text)).toMatchObject({
183 | thoughtNumber: 1,
184 | thoughtType: ThoughtType.MODEL
185 | });
186 | });
187 | it('should handle experimentalElements correctly', () => {
188 | const thoughtWithExperiment = {
189 | thought: "Experimental validation",
190 | thoughtType: ThoughtType.PROOF,
191 | thoughtNumber: 1,
192 | totalThoughts: 1,
193 | uncertainty: 0.3,
194 | dependencies: [],
195 | assumptions: [],
196 | nextThoughtNeeded: false,
197 | experimentalElements: {
198 | testDescription: "Test case scenario",
199 | results: "Observed behavior matches expected",
200 | confidence: 0.85,
201 | limitations: ["Limited test coverage", "Specific environment only"]
202 | }
203 | };
204 |
205 | const result = server.processThought(thoughtWithExperiment);
206 | expect(result.isError).toBeUndefined();
207 | expect(JSON.parse(result.content[0].text)).toMatchObject({
208 | thoughtNumber: 1,
209 | thoughtType: ThoughtType.PROOF
210 | });
211 | });
212 |
213 | it('should handle thought revisions correctly', () => {
214 | // First thought
215 | const originalThought = {
216 | thought: "Original thought",
217 | thoughtType: ThoughtType.PROBLEM_DEFINITION,
218 | thoughtNumber: 1,
219 | totalThoughts: 2,
220 | uncertainty: 0.5,
221 | dependencies: [],
222 | assumptions: [],
223 | nextThoughtNeeded: true
224 | };
225 |
226 | // Revision of first thought
227 | const revisionThought = {
228 | thought: "Revised definition",
229 | thoughtType: ThoughtType.PROBLEM_DEFINITION,
230 | thoughtNumber: 2,
231 | totalThoughts: 2,
232 | uncertainty: 0.3,
233 | dependencies: [1],
234 | assumptions: [],
235 | nextThoughtNeeded: false,
236 | isRevision: true,
237 | revisesThought: 1
238 | };
239 |
240 | server.processThought(originalThought);
241 | const result = server.processThought(revisionThought);
242 | expect(result.isError).toBeUndefined();
243 | expect(JSON.parse(result.content[0].text)).toMatchObject({
244 | thoughtNumber: 2,
245 | thoughtType: ThoughtType.PROBLEM_DEFINITION,
246 | thoughtHistoryLength: 2
247 | });
248 | });
249 |
250 | it('should validate revision fields correctly', () => {
251 | const invalidRevision = {
252 | thought: "Invalid revision",
253 | thoughtType: ThoughtType.PROBLEM_DEFINITION,
254 | thoughtNumber: 1,
255 | totalThoughts: 1,
256 | uncertainty: 0.5,
257 | dependencies: [],
258 | assumptions: [],
259 | nextThoughtNeeded: false,
260 | revisesThought: 2, // Invalid: can't revise future thought
261 | isRevision: true
262 | };
263 |
264 | const result = server.processThought(invalidRevision);
265 | expect(result.isError).toBe(true);
266 | expect(JSON.parse(result.content[0].text).error).toContain('Invalid revision');
267 | });
268 | });
269 | });
270 |
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | import { Server } from "@modelcontextprotocol/sdk/server/index.js";
4 | import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
5 | import {
6 | CallToolRequestSchema,
7 | ListToolsRequestSchema,
8 | Tool,
9 | } from "@modelcontextprotocol/sdk/types.js";
10 | import { ThoughtType, ShannonThoughtData } from "./types.js";
11 | import { ShannonThinkingServer } from "./server.js";
12 |
13 | /**
14 | * Tool definition for the Shannon Thinking problem-solving methodology.
15 | * This tool implements Claude Shannon's systematic and iterative approach to complex problems,
16 | * breaking them down into clear steps of problem definition, modeling, validation, and implementation.
17 | * It supports revisions and re-examination as understanding evolves.
18 | */
19 |
20 | const SHANNON_THINKING_TOOL: Tool = {
21 | name: "shannonthinking",
22 | description: `A problem-solving tool inspired by Claude Shannon's systematic and iterative approach to complex problems.
23 |
24 | This tool helps break down problems using Shannon's methodology of problem definition, mathematical modeling, validation, and practical implementation.
25 |
26 | When to use this tool:
27 | - Complex system analysis
28 | - Information processing problems
29 | - Engineering design challenges
30 | - Problems requiring theoretical frameworks
31 | - Optimization problems
32 | - Systems requiring practical implementation
33 | - Problems that need iterative refinement
34 | - Cases where experimental validation complements theory
35 |
36 | Key features:
37 | - Systematic progression through problem definition → constraints → modeling → validation → implementation
38 | - Support for revising earlier steps as understanding evolves
39 | - Ability to mark steps for re-examination with new information
40 | - Experimental validation alongside formal proofs
41 | - Explicit tracking of assumptions and dependencies
42 | - Confidence levels for each step
43 | - Rich feedback and validation results
44 |
45 | Parameters explained:
46 | - thoughtType: Type of thinking step (PROBLEM_DEFINITION, CONSTRAINTS, MODEL, PROOF, IMPLEMENTATION)
47 | - uncertainty: Confidence level in the current thought (0-1)
48 | - dependencies: Which previous thoughts this builds upon
49 | - assumptions: Explicit listing of assumptions made
50 | - isRevision: Whether this revises an earlier thought
51 | - revisesThought: Which thought is being revised
52 | - recheckStep: For marking steps that need re-examination
53 | - proofElements: For formal validation steps
54 | - experimentalElements: For empirical validation
55 | - implementationNotes: For practical application steps
56 |
57 | The tool supports an iterative approach:
58 | 1. Define the problem's fundamental elements (revisable as understanding grows)
59 | 2. Identify system constraints and limitations (can be rechecked with new information)
60 | 3. Develop mathematical/theoretical models
61 | 4. Validate through proofs and/or experimental testing
62 | 5. Design and test practical implementations
63 |
64 | Each thought can build on, revise, or re-examine previous steps, creating a flexible yet rigorous problem-solving framework.`,
65 | inputSchema: {
66 | type: "object",
67 | properties: {
68 | thought: {
69 | type: "string",
70 | description: "Your current thinking step"
71 | },
72 | thoughtType: {
73 | type: "string",
74 | enum: Object.values(ThoughtType),
75 | description: "Type of thinking step"
76 | },
77 | thoughtNumber: {
78 | type: "integer",
79 | description: "Current thought number",
80 | minimum: 1
81 | },
82 | totalThoughts: {
83 | type: "integer",
84 | description: "Estimated total thoughts needed",
85 | minimum: 1
86 | },
87 | uncertainty: {
88 | type: "number",
89 | description: "Confidence level (0-1)",
90 | minimum: 0,
91 | maximum: 1
92 | },
93 | dependencies: {
94 | type: "array",
95 | items: {
96 | type: "integer",
97 | minimum: 1
98 | },
99 | description: "Thought numbers this builds upon"
100 | },
101 | assumptions: {
102 | type: "array",
103 | items: {
104 | type: "string"
105 | },
106 | description: "Explicit list of assumptions"
107 | },
108 | nextThoughtNeeded: {
109 | type: "boolean",
110 | description: "Whether another thought step is needed"
111 | },
112 | isRevision: {
113 | type: "boolean",
114 | description: "Whether this thought revises an earlier one"
115 | },
116 | revisesThought: {
117 | type: "integer",
118 | description: "The thought number being revised",
119 | minimum: 1
120 | },
121 | recheckStep: {
122 | type: "object",
123 | properties: {
124 | stepToRecheck: {
125 | type: "string",
126 | enum: Object.values(ThoughtType),
127 | description: "Which type of step needs re-examination"
128 | },
129 | reason: {
130 | type: "string",
131 | description: "Why the step needs to be rechecked"
132 | },
133 | newInformation: {
134 | type: "string",
135 | description: "New information prompting the recheck"
136 | }
137 | },
138 | required: ["stepToRecheck", "reason"],
139 | description: "For marking steps that need re-examination"
140 | },
141 | proofElements: {
142 | type: "object",
143 | properties: {
144 | hypothesis: {
145 | type: "string",
146 | description: "The hypothesis being tested"
147 | },
148 | validation: {
149 | type: "string",
150 | description: "How the hypothesis was validated"
151 | }
152 | },
153 | required: ["hypothesis", "validation"],
154 | description: "Elements required for formal proof steps"
155 | },
156 | experimentalElements: {
157 | type: "object",
158 | properties: {
159 | testDescription: {
160 | type: "string",
161 | description: "Description of the experimental test"
162 | },
163 | results: {
164 | type: "string",
165 | description: "Results of the experiment"
166 | },
167 | confidence: {
168 | type: "number",
169 | description: "Confidence in the experimental results (0-1)",
170 | minimum: 0,
171 | maximum: 1
172 | },
173 | limitations: {
174 | type: "array",
175 | items: {
176 | type: "string"
177 | },
178 | description: "Limitations of the experimental validation"
179 | }
180 | },
181 | required: ["testDescription", "results", "confidence", "limitations"],
182 | description: "Elements for experimental validation"
183 | },
184 | implementationNotes: {
185 | type: "object",
186 | properties: {
187 | practicalConstraints: {
188 | type: "array",
189 | items: {
190 | type: "string"
191 | },
192 | description: "List of practical limitations and constraints"
193 | },
194 | proposedSolution: {
195 | type: "string",
196 | description: "Detailed implementation proposal"
197 | }
198 | },
199 | required: ["practicalConstraints", "proposedSolution"],
200 | description: "Notes for practical implementation steps"
201 | }
202 | },
203 | required: ["thought", "thoughtType", "thoughtNumber", "totalThoughts", "uncertainty", "dependencies", "assumptions", "nextThoughtNeeded"]
204 | }
205 | };
206 |
207 | const server = new Server(
208 | {
209 | name: "shannon-thinking-server",
210 | version: "0.1.0",
211 | },
212 | {
213 | capabilities: {
214 | tools: {},
215 | },
216 | }
217 | );
218 |
219 | const thinkingServer = new ShannonThinkingServer();
220 |
221 | server.setRequestHandler(ListToolsRequestSchema, async () => ({
222 | tools: [SHANNON_THINKING_TOOL],
223 | }));
224 |
225 | server.setRequestHandler(CallToolRequestSchema, async (request) => {
226 | if (request.params.name === "shannonthinking") {
227 | return thinkingServer.processThought(request.params.arguments);
228 | }
229 |
230 | return {
231 | content: [{
232 | type: "text",
233 | text: `Unknown tool: ${request.params.name}`
234 | }],
235 | isError: true
236 | };
237 | });
238 |
239 | async function runServer() {
240 | const transport = new StdioServerTransport();
241 | await server.connect(transport);
242 | console.error("Shannon Thinking MCP Server running on stdio");
243 | }
244 |
245 | runServer().catch((error) => {
246 | console.error("Fatal error running server:", error);
247 | process.exit(1);
248 | });
249 |
--------------------------------------------------------------------------------
/src/server.ts:
--------------------------------------------------------------------------------
1 | import chalk from 'chalk';
2 | import { ShannonThoughtData, ThoughtType } from './types.js';
3 |
4 | export class ShannonThinkingServer {
5 | private thoughtHistory: ShannonThoughtData[] = [];
6 |
7 | private validateThoughtData(input: unknown): ShannonThoughtData {
8 | const data = input as Record;
9 |
10 | if (!data.thought || typeof data.thought !== 'string') {
11 | throw new Error(`Invalid thought: must be a string, received ${typeof data.thought}`);
12 | }
13 | if (!data.thoughtType || !Object.values(ThoughtType).includes(data.thoughtType as ThoughtType)) {
14 | throw new Error(`Invalid thoughtType: must be one of: ${Object.values(ThoughtType).join(', ')}, received ${data.thoughtType}`);
15 | }
16 | if (!data.thoughtNumber || typeof data.thoughtNumber !== 'number') {
17 | throw new Error(`Invalid thoughtNumber: must be a number, received ${typeof data.thoughtNumber}`);
18 | }
19 | if (!data.totalThoughts || typeof data.totalThoughts !== 'number') {
20 | throw new Error(`Invalid totalThoughts: must be a number, received ${typeof data.totalThoughts}`);
21 | }
22 | if (typeof data.uncertainty !== 'number' || data.uncertainty < 0 || data.uncertainty > 1) {
23 | throw new Error(`Invalid uncertainty: must be a number between 0 and 1, received ${data.uncertainty}`);
24 | }
25 | if (!Array.isArray(data.dependencies)) {
26 | throw new Error(`Invalid dependencies: must be an array, received ${typeof data.dependencies}`);
27 | }
28 | if (!Array.isArray(data.assumptions)) {
29 | throw new Error(`Invalid assumptions: must be an array, received ${typeof data.assumptions}`);
30 | }
31 | if (typeof data.nextThoughtNeeded !== 'boolean') {
32 | throw new Error(`Invalid nextThoughtNeeded: must be a boolean, received ${typeof data.nextThoughtNeeded}`);
33 | }
34 |
35 | // Optional recheckStep validation
36 | if (data.recheckStep) {
37 | const recheck = data.recheckStep as Record;
38 | if (!recheck.stepToRecheck || !Object.values(ThoughtType).includes(recheck.stepToRecheck as ThoughtType)) {
39 | throw new Error('Invalid recheckStep: stepToRecheck must be a valid ThoughtType');
40 | }
41 | if (!recheck.reason || typeof recheck.reason !== 'string') {
42 | throw new Error('Invalid recheckStep: reason must be a string');
43 | }
44 | if (recheck.newInformation && typeof recheck.newInformation !== 'string') {
45 | throw new Error('Invalid recheckStep: newInformation must be a string if provided');
46 | }
47 | }
48 |
49 | // Optional proofElements validation
50 | if (data.proofElements) {
51 | const proof = data.proofElements as Record;
52 | if (!proof.hypothesis || typeof proof.hypothesis !== 'string') {
53 | throw new Error('Invalid proofElements: hypothesis must be a string');
54 | }
55 | if (!proof.validation || typeof proof.validation !== 'string') {
56 | throw new Error('Invalid proofElements: validation must be a string');
57 | }
58 | }
59 |
60 | // Optional experimentalElements validation
61 | if (data.experimentalElements) {
62 | const exp = data.experimentalElements as Record;
63 | if (!exp.testDescription || typeof exp.testDescription !== 'string') {
64 | throw new Error('Invalid experimentalElements: testDescription must be a string');
65 | }
66 | if (!exp.results || typeof exp.results !== 'string') {
67 | throw new Error('Invalid experimentalElements: results must be a string');
68 | }
69 | if (typeof exp.confidence !== 'number' || exp.confidence < 0 || exp.confidence > 1) {
70 | throw new Error('Invalid experimentalElements: confidence must be a number between 0 and 1');
71 | }
72 | if (!Array.isArray(exp.limitations)) {
73 | throw new Error('Invalid experimentalElements: limitations must be an array');
74 | }
75 | }
76 |
77 | // Optional implementationNotes validation
78 | if (data.implementationNotes) {
79 | const impl = data.implementationNotes as Record;
80 | if (!Array.isArray(impl.practicalConstraints)) {
81 | throw new Error('Invalid implementationNotes: practicalConstraints must be an array');
82 | }
83 | if (!impl.proposedSolution || typeof impl.proposedSolution !== 'string') {
84 | throw new Error('Invalid implementationNotes: proposedSolution must be a string');
85 | }
86 | }
87 |
88 | // Optional revision validation
89 | if (data.isRevision !== undefined && typeof data.isRevision !== 'boolean') {
90 | throw new Error('Invalid isRevision: must be a boolean if provided');
91 | }
92 | if (data.revisesThought !== undefined) {
93 | if (typeof data.revisesThought !== 'number' || data.revisesThought < 1) {
94 | throw new Error('Invalid revisesThought: must be a positive number if provided');
95 | }
96 | if (!data.isRevision) {
97 | throw new Error('Invalid revisesThought: cannot be set without isRevision being true');
98 | }
99 | }
100 |
101 | return {
102 | thought: data.thought as string,
103 | thoughtType: data.thoughtType as ThoughtType,
104 | thoughtNumber: data.thoughtNumber as number,
105 | totalThoughts: data.totalThoughts as number,
106 | uncertainty: data.uncertainty as number,
107 | dependencies: data.dependencies as number[],
108 | assumptions: data.assumptions as string[],
109 | nextThoughtNeeded: data.nextThoughtNeeded as boolean,
110 | recheckStep: data.recheckStep as ShannonThoughtData['recheckStep'],
111 | proofElements: data.proofElements as ShannonThoughtData['proofElements'],
112 | experimentalElements: data.experimentalElements as ShannonThoughtData['experimentalElements'],
113 | implementationNotes: data.implementationNotes as ShannonThoughtData['implementationNotes'],
114 | isRevision: data.isRevision as boolean | undefined,
115 | revisesThought: data.revisesThought as number | undefined,
116 | };
117 | }
118 |
119 | private formatThought(thoughtData: ShannonThoughtData): string {
120 | const { thoughtNumber, totalThoughts, thought, thoughtType, uncertainty, dependencies } = thoughtData;
121 |
122 | // Enhanced console output for debugging
123 | console.error(`Processing thought ${thoughtNumber}/${totalThoughts}`);
124 | console.error(`Type: ${thoughtType}`);
125 | console.error(`Dependencies: ${dependencies.join(', ') || 'none'}`);
126 | console.error(`Uncertainty: ${uncertainty}`);
127 | if (thoughtData.proofElements) {
128 | console.error('Proof elements present');
129 | }
130 | if (thoughtData.implementationNotes) {
131 | console.error('Implementation notes present');
132 | }
133 |
134 | const typeColors: Record string> = {
135 | [ThoughtType.PROBLEM_DEFINITION]: chalk.blue,
136 | [ThoughtType.CONSTRAINTS]: chalk.yellow,
137 | [ThoughtType.MODEL]: chalk.green,
138 | [ThoughtType.PROOF]: chalk.magenta,
139 | [ThoughtType.IMPLEMENTATION]: chalk.cyan
140 | };
141 |
142 | const typeSymbols: Record = {
143 | [ThoughtType.PROBLEM_DEFINITION]: '🔍',
144 | [ThoughtType.CONSTRAINTS]: '🔒',
145 | [ThoughtType.MODEL]: '📐',
146 | [ThoughtType.PROOF]: '✓',
147 | [ThoughtType.IMPLEMENTATION]: '⚙️'
148 | };
149 |
150 | const prefix = typeColors[thoughtType](`${typeSymbols[thoughtType]} ${thoughtType.toUpperCase()}`);
151 | const confidenceDisplay = `[Confidence: ${(uncertainty * 100).toFixed(1)}%]`;
152 | const dependencyDisplay = dependencies.length > 0 ?
153 | `[Builds on thoughts: ${dependencies.join(', ')}]` : '';
154 |
155 | const header = `${prefix} ${thoughtNumber}/${totalThoughts} ${confidenceDisplay} ${dependencyDisplay}`;
156 | const border = '─'.repeat(Math.max(header.length, thought.length) + 4);
157 |
158 | let output = `
159 | ┌${border}┐
160 | │ ${header} │`;
161 |
162 | if (thoughtData.isRevision) {
163 | output += `\n├${border}┤\n│ 🔄 Revising thought ${thoughtData.revisesThought} │`;
164 | }
165 |
166 | output += `\n├${border}┤\n│ ${thought.padEnd(border.length - 2)} │`;
167 |
168 | if (thoughtData.assumptions && thoughtData.assumptions.length > 0) {
169 | output += `\n├${border}┤\n│ Assumptions: ${thoughtData.assumptions.join(', ')} │`;
170 | }
171 |
172 | if (thoughtData.recheckStep) {
173 | output += `\n├${border}┤
174 | │ Rechecking Step: ${thoughtData.recheckStep.stepToRecheck.padEnd(border.length - 17)} │
175 | │ Reason: ${thoughtData.recheckStep.reason.padEnd(border.length - 9)} │`;
176 | if (thoughtData.recheckStep.newInformation) {
177 | output += `\n│ New Information: ${thoughtData.recheckStep.newInformation.padEnd(border.length - 17)} │`;
178 | }
179 | }
180 |
181 | if (thoughtData.proofElements) {
182 | output += `\n├${border}┤
183 | │ Proof Hypothesis: ${thoughtData.proofElements.hypothesis.padEnd(border.length - 18)} │
184 | │ Validation: ${thoughtData.proofElements.validation.padEnd(border.length - 13)} │`;
185 | }
186 |
187 | if (thoughtData.experimentalElements) {
188 | output += `\n├${border}┤
189 | │ Test Description: ${thoughtData.experimentalElements.testDescription.padEnd(border.length - 18)} │
190 | │ Results: ${thoughtData.experimentalElements.results.padEnd(border.length - 10)} │
191 | │ Test Confidence: ${(thoughtData.experimentalElements.confidence * 100).toFixed(1)}% │
192 | │ Limitations: ${thoughtData.experimentalElements.limitations.join(', ').padEnd(border.length - 13)} │`;
193 | }
194 |
195 | if (thoughtData.implementationNotes) {
196 | output += `\n├${border}┤
197 | │ Practical Constraints: ${thoughtData.implementationNotes.practicalConstraints.join(', ').padEnd(border.length - 23)} │
198 | │ Proposed Solution: ${thoughtData.implementationNotes.proposedSolution.padEnd(border.length - 19)} │`;
199 | }
200 |
201 | output += `\n└${border}┘`;
202 | return output;
203 | }
204 |
205 | public processThought(input: unknown): { content: Array<{ type: string; text: string }>; isError?: boolean } {
206 | try {
207 | const validatedInput = this.validateThoughtData(input);
208 |
209 | if (validatedInput.thoughtNumber > validatedInput.totalThoughts) {
210 | validatedInput.totalThoughts = validatedInput.thoughtNumber;
211 | }
212 |
213 | // Validate dependencies and revisions
214 | for (const depNumber of validatedInput.dependencies) {
215 | if (depNumber >= validatedInput.thoughtNumber) {
216 | throw new Error(`Invalid dependency: cannot depend on future thought ${depNumber}`);
217 | }
218 | if (!this.thoughtHistory.some(t => t.thoughtNumber === depNumber)) {
219 | throw new Error(`Invalid dependency: thought ${depNumber} does not exist`);
220 | }
221 | }
222 |
223 | // Validate revision target
224 | if (validatedInput.isRevision && validatedInput.revisesThought !== undefined) {
225 | if (validatedInput.revisesThought >= validatedInput.thoughtNumber) {
226 | throw new Error(`Invalid revision: cannot revise future thought ${validatedInput.revisesThought}`);
227 | }
228 | if (!this.thoughtHistory.some(t => t.thoughtNumber === validatedInput.revisesThought)) {
229 | throw new Error(`Invalid revision: thought ${validatedInput.revisesThought} does not exist`);
230 | }
231 | }
232 |
233 | this.thoughtHistory.push(validatedInput);
234 | const formattedThought = this.formatThought(validatedInput);
235 | console.error(formattedThought);
236 |
237 | return {
238 | content: [{
239 | type: "text",
240 | text: JSON.stringify({
241 | thoughtNumber: validatedInput.thoughtNumber,
242 | totalThoughts: validatedInput.totalThoughts,
243 | nextThoughtNeeded: validatedInput.nextThoughtNeeded,
244 | thoughtType: validatedInput.thoughtType,
245 | uncertainty: validatedInput.uncertainty,
246 | thoughtHistoryLength: this.thoughtHistory.length,
247 | isRevision: validatedInput.isRevision,
248 | revisesThought: validatedInput.revisesThought,
249 | hasExperimentalValidation: !!validatedInput.experimentalElements,
250 | hasRecheckStep: !!validatedInput.recheckStep
251 | }, null, 2)
252 | }]
253 | };
254 | } catch (error) {
255 | return {
256 | content: [{
257 | type: "text",
258 | text: JSON.stringify({
259 | error: error instanceof Error ? error.message : String(error),
260 | details: {
261 | receivedInput: JSON.stringify(input, null, 2),
262 | thoughtHistoryLength: this.thoughtHistory.length,
263 | lastValidThought: this.thoughtHistory.length > 0 ?
264 | this.thoughtHistory[this.thoughtHistory.length - 1].thoughtNumber : null
265 | },
266 | status: 'failed'
267 | }, null, 2)
268 | }],
269 | isError: true
270 | };
271 | }
272 | }
273 | }
274 |
--------------------------------------------------------------------------------
/src/types.ts:
--------------------------------------------------------------------------------
1 | export enum ThoughtType {
2 | PROBLEM_DEFINITION = 'problem_definition',
3 | CONSTRAINTS = 'constraints',
4 | MODEL = 'model',
5 | PROOF = 'proof',
6 | IMPLEMENTATION = 'implementation'
7 | }
8 |
9 | export interface ShannonThoughtData {
10 | thought: string;
11 | thoughtType: ThoughtType;
12 | thoughtNumber: number;
13 | totalThoughts: number;
14 | uncertainty: number; // 0-1
15 | dependencies: number[]; // thought numbers this builds on
16 | assumptions: string[]; // explicit list of assumptions
17 | nextThoughtNeeded: boolean;
18 | recheckStep?: {
19 | stepToRecheck: ThoughtType;
20 | reason: string;
21 | newInformation?: string;
22 | };
23 | proofElements?: {
24 | hypothesis: string;
25 | validation: string;
26 | };
27 | experimentalElements?: {
28 | testDescription: string;
29 | results: string;
30 | confidence: number; // 0-1
31 | limitations: string[];
32 | };
33 | implementationNotes?: {
34 | practicalConstraints: string[];
35 | proposedSolution: string;
36 | };
37 | isRevision?: boolean;
38 | revisesThought?: number;
39 | }
40 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ES2022",
4 | "module": "NodeNext",
5 | "moduleResolution": "NodeNext",
6 | "outDir": "./dist",
7 | "rootDir": "./src",
8 | "strict": true,
9 | "esModuleInterop": true,
10 | "skipLibCheck": true,
11 | "forceConsistentCasingInFileNames": true,
12 | "resolveJsonModule": true
13 | },
14 | "include": ["src/**/*"],
15 | "exclude": ["node_modules"]
16 | }
17 |
--------------------------------------------------------------------------------