├── .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 | Shannon Thinking Server MCP server 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 | --------------------------------------------------------------------------------