├── src ├── utils │ ├── index.ts │ ├── logging.ts │ └── errors.ts ├── tools │ ├── index.ts │ ├── chainOfDraftParams.ts │ └── chainOfDraftTool.ts ├── index.ts └── initialize.ts ├── tsconfig.json ├── package.json ├── .github └── workflows │ └── npm-publish.yml ├── LICENSE ├── README.md ├── .gitignore └── docs └── chain-of-draft.md /src/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from './logging.js'; 2 | export * from './errors.js'; 3 | -------------------------------------------------------------------------------- /src/tools/index.ts: -------------------------------------------------------------------------------- 1 | import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; 2 | import { chainOfDraftTool } from "./chainOfDraftTool.js"; 3 | 4 | 5 | export const registerTools = (server: McpServer) => { 6 | chainOfDraftTool(server); 7 | } 8 | 9 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2020", 4 | "module": "ES2020", 5 | "moduleResolution": "node", 6 | "esModuleInterop": true, 7 | "strict": true, 8 | "skipLibCheck": true, 9 | "forceConsistentCasingInFileNames": true, 10 | "outDir": "build", 11 | "rootDir": "src", 12 | "declaration": true, 13 | "allowJs": true, 14 | "resolveJsonModule": true 15 | }, 16 | "include": [ 17 | "src/**/*" 18 | ], 19 | "exclude": [ 20 | "node_modules" 21 | ] 22 | } -------------------------------------------------------------------------------- /src/utils/logging.ts: -------------------------------------------------------------------------------- 1 | // Simple logging utility 2 | export const logger = { 3 | debug: (message: string, ...args: any[]) => { 4 | console.error(`[DEBUG] ${message}`, ...args); 5 | }, 6 | info: (message: string, ...args: any[]) => { 7 | console.error(`[INFO] ${message}`, ...args); 8 | }, 9 | warn: (message: string, ...args: any[]) => { 10 | console.error(`[WARN] ${message}`, ...args); 11 | }, 12 | error: (message: string, ...args: any[]) => { 13 | console.error(`[ERROR] ${message}`, ...args); 14 | } 15 | }; 16 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import { createServer } from "./initialize.js"; 2 | import { join } from "path"; 3 | import { fileURLToPath } from "url"; 4 | import { logger } from "./utils/index.js"; 5 | import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; 6 | 7 | const __filename = fileURLToPath(import.meta.url); 8 | const __dirname = join(fileURLToPath(import.meta.url), '..'); 9 | 10 | const server = createServer(); 11 | 12 | const main = async () => { 13 | try { 14 | 15 | const transport = new StdioServerTransport(); 16 | 17 | await server.connect(transport); 18 | } catch (error) { 19 | logger.error("Failed to start server:", error); 20 | } 21 | } 22 | 23 | main(); 24 | -------------------------------------------------------------------------------- /src/initialize.ts: -------------------------------------------------------------------------------- 1 | import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; 2 | import { registerTools } from "./tools/index.js"; 3 | import { logger } from "./utils/index.js"; 4 | 5 | const serverConfig = { 6 | name: "chain-of-draft", 7 | version: "1.0.0", 8 | } 9 | 10 | const capabilities = { 11 | capabilities: { 12 | tools: {} 13 | } 14 | } 15 | 16 | export const createServer = (): McpServer => { 17 | // Crate a new MCP server 18 | const server = new McpServer( 19 | serverConfig, 20 | capabilities 21 | ); 22 | 23 | // set up error handler 24 | server.server.onerror = (error) => { 25 | logger.error("MCP server error:", error); 26 | } 27 | 28 | // register tools 29 | registerTools(server); 30 | 31 | return server; 32 | } 33 | 34 | 35 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mcp-chain-of-draft-server", 3 | "version": "1.0.0", 4 | "description": "A Model Context Protocol server which provides Chain of Draft style thinking", 5 | "main": "build/index.js", 6 | "type": "module", 7 | "scripts": { 8 | "start": "node build/index.js", 9 | "build": "tsc", 10 | "dev": "ts-node-dev --respawn --transpile-only src/index.ts", 11 | "test": "jest" 12 | }, 13 | "keywords": [ 14 | "mcp", 15 | "model", 16 | "context", 17 | "protocol", 18 | "cod", 19 | "chain-of-draft" 20 | ], 21 | "author": "bsmi021", 22 | "license": "ISC", 23 | "dependencies": { 24 | "@modelcontextprotocol/sdk": "^1.7.0", 25 | "dotenv": "^16.4.7", 26 | "zod": "^3.24.2" 27 | }, 28 | "engines": { 29 | "node": ">=16.0.0" 30 | }, 31 | "devDependencies": { 32 | "ts-node": "^10.9.2", 33 | "ts-node-dev": "^2.0.0", 34 | "typescript": "^5.6.3" 35 | } 36 | } -------------------------------------------------------------------------------- /.github/workflows/npm-publish.yml: -------------------------------------------------------------------------------- 1 | # This workflow will run tests using node and then publish a package to GitHub Packages when a release is created 2 | # For more information see: https://docs.github.com/en/actions/publishing-packages/publishing-nodejs-packages 3 | 4 | name: Node.js Package 5 | 6 | on: 7 | release: 8 | types: [created] 9 | 10 | jobs: 11 | build: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v4 15 | - uses: actions/setup-node@v4 16 | with: 17 | node-version: 20 18 | - run: npm ci 19 | - run: npm test 20 | 21 | publish-npm: 22 | needs: build 23 | runs-on: ubuntu-latest 24 | steps: 25 | - uses: actions/checkout@v4 26 | - uses: actions/setup-node@v4 27 | with: 28 | node-version: 20 29 | registry-url: https://registry.npmjs.org/ 30 | - run: npm ci 31 | - run: npm publish 32 | env: 33 | NODE_AUTH_TOKEN: ${{secrets.npm_token}} 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Brian W. Smith 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 | -------------------------------------------------------------------------------- /src/utils/errors.ts: -------------------------------------------------------------------------------- 1 | export class BaseError extends Error { 2 | public code: string; 3 | public status: number; 4 | public details?: any; 5 | 6 | constructor(message: string, code: string, status: number, details?: any) { 7 | super(message); 8 | this.name = this.constructor.name; 9 | this.code = code; 10 | this.status = status; 11 | this.details = details; 12 | Error.captureStackTrace(this, this.constructor); 13 | } 14 | } 15 | 16 | export class ValidationError extends BaseError { 17 | constructor(message: string, details?: any) { 18 | super(message, 'VALIDATION_ERROR', 400, details); 19 | } 20 | } 21 | 22 | export class EntityNotFoundError extends BaseError { 23 | constructor(message: string) { 24 | super(message, 'NOT_FOUND', 404); 25 | } 26 | } 27 | 28 | export class DatabaseError extends BaseError { 29 | constructor(message: string, details?: any) { 30 | super(message, 'DATABASE_ERROR', 500, details); 31 | } 32 | } 33 | 34 | export class UnauthorizedError extends BaseError { 35 | constructor(message: string) { 36 | super(message, 'UNAUTHORIZED', 401); 37 | } 38 | } 39 | 40 | export class ForbiddenError extends BaseError { 41 | constructor(message: string) { 42 | super(message, 'FORBIDDEN', 403); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MCP Chain of Draft Server 🧠 2 | 3 | Chain of Draft Server is a powerful AI-driven tool that helps developers make better decisions through systematic, iterative refinement of thoughts and designs. It integrates seamlessly with popular AI agents and provides a structured approach to reasoning, API design, architecture decisions, code reviews, and implementation planning. 4 | 5 | ## 🌟 Features 6 | 7 | ### Core Capabilities 8 | 9 | * **Iterative Reasoning**: Systematic improvement through the Chain of Draft protocol 10 | * **Thought History**: Track and manage reasoning iterations 11 | * **Branching Support**: Focus reviews on specific reasoning steps 12 | * **TypeScript Support**: Full TypeScript implementation with Zod validation 13 | * **Error Handling**: Comprehensive error types and handling 14 | * **Real-time Logging**: Built-in debugging and monitoring system 15 | 16 | ## 🚀 Getting Started 17 | 18 | ### Prerequisites 19 | 20 | * Node.js >= 16.0.0 21 | * npm >= 8.0.0 22 | 23 | ### Installation 24 | 25 | 1. Clone the repository: 26 | 27 | ```bash 28 | git clone https://github.com/bsmi021/mcp-chain-of-draft-server.git 29 | cd mcp-chain-of-draft-server 30 | ``` 31 | 32 | 2. Install dependencies: 33 | 34 | ```bash 35 | npm install 36 | ``` 37 | 38 | ### Configuration 39 | 40 | Simple server configuration in `initialize.ts`: 41 | 42 | ```typescript 43 | const serverConfig = { 44 | name: "chain-of-draft", 45 | version: "1.0.0", 46 | } 47 | ``` 48 | 49 | ## 💡 Usage Examples 50 | 51 | ### Chain of Draft Protocol 52 | 53 | ```typescript 54 | const thoughtData = { 55 | reasoning_chain: ["Initial analysis of the problem"], 56 | next_step_needed: true, 57 | draft_number: 1, 58 | total_drafts: 3, 59 | is_critique: true, 60 | critique_focus: "logical_consistency" 61 | }; 62 | ``` 63 | 64 | ## 🛠️ Development 65 | 66 | ### Project Structure 67 | 68 | ``` 69 | src/ 70 | ├── tools/ # Specialized Tools 71 | │ ├── chainOfDraft/ # Core Protocol 72 | │ └── index.ts / # Entry Point 73 | ├── utils/ # Utilities 74 | └── index.ts # Entry Point 75 | ``` 76 | 77 | ### Starting Development Server 78 | 79 | ```bash 80 | npm run dev 81 | ``` 82 | 83 | ## ❓ FAQ 84 | 85 | ### How does the Chain of Draft protocol work? 86 | 87 | The protocol guides you through systematic improvement of your thinking through iterative drafts and focused critiques. 88 | 89 | ### Can I customize the critique dimensions? 90 | 91 | Yes! Each tool supports custom critique focuses tailored to your specific needs. 92 | 93 | ### How many drafts should I plan for? 94 | 95 | We recommend 3-5 drafts for most tasks, but you can adjust based on complexity. 96 | 97 | ## 🤝 Contributing 98 | 99 | We welcome contributions! Please check our [Contributing Guidelines](CONTRIBUTING.md). 100 | 101 | ## 👥 Community & Support 102 | 103 | * GitHub Issues - Report bugs or suggest features 104 | * Pull Requests - Submit your contributions 105 | * Documentation - Check our detailed docs 106 | 107 | ## 📝 License 108 | 109 | MIT License - see the [LICENSE](LICENSE) file for details. 110 | 111 | ## 🙏 Acknowledgments 112 | 113 | * Thanks to our contributors and early adopters 114 | * Special thanks to the MCP community 115 | * Inspired by systematic reasoning methodologies 116 | 117 | --- 118 | 119 | Made with 🧠 by @bsmi021 120 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | .pnpm-debug.log* 9 | 10 | # Diagnostic reports (https://nodejs.org/api/report.html) 11 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 12 | 13 | # Runtime data 14 | pids 15 | *.pid 16 | *.seed 17 | *.pid.lock 18 | 19 | # Directory for instrumented libs generated by jscoverage/JSCover 20 | lib-cov 21 | 22 | # Coverage directory used by tools like istanbul 23 | coverage 24 | *.lcov 25 | 26 | # nyc test coverage 27 | .nyc_output 28 | 29 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 30 | .grunt 31 | 32 | # Bower dependency directory (https://bower.io/) 33 | bower_components 34 | 35 | # node-waf configuration 36 | .lock-wscript 37 | 38 | # Compiled binary addons (https://nodejs.org/api/addons.html) 39 | build/Release 40 | 41 | # Dependency directories 42 | node_modules/ 43 | jspm_packages/ 44 | 45 | # Snowpack dependency directory (https://snowpack.dev/) 46 | web_modules/ 47 | 48 | # TypeScript cache 49 | *.tsbuildinfo 50 | 51 | # Optional npm cache directory 52 | .npm 53 | 54 | # Optional eslint cache 55 | .eslintcache 56 | 57 | # Optional stylelint cache 58 | .stylelintcache 59 | 60 | # Microbundle cache 61 | .rpt2_cache/ 62 | .rts2_cache_cjs/ 63 | .rts2_cache_es/ 64 | .rts2_cache_umd/ 65 | 66 | # Optional REPL history 67 | .node_repl_history 68 | 69 | # Output of 'npm pack' 70 | *.tgz 71 | 72 | # Yarn Integrity file 73 | .yarn-integrity 74 | 75 | # dotenv environment variable files 76 | .env 77 | .env.development.local 78 | .env.test.local 79 | .env.production.local 80 | .env.local 81 | 82 | # parcel-bundler cache (https://parceljs.org/) 83 | .cache 84 | .parcel-cache 85 | 86 | # Next.js build output 87 | .next 88 | out 89 | 90 | # Nuxt.js build / generate output 91 | .nuxt 92 | dist 93 | 94 | # Gatsby files 95 | .cache/ 96 | # Comment in the public line in if your project uses Gatsby and not Next.js 97 | # https://nextjs.org/blog/next-9-1#public-directory-support 98 | # public 99 | 100 | # vuepress build output 101 | .vuepress/dist 102 | 103 | # vuepress v2.x temp and cache directory 104 | .temp 105 | .cache 106 | 107 | # Docusaurus cache and generated files 108 | .docusaurus 109 | 110 | # Serverless directories 111 | .serverless/ 112 | 113 | # FuseBox cache 114 | .fusebox/ 115 | 116 | # DynamoDB Local files 117 | .dynamodb/ 118 | 119 | # TernJS port file 120 | .tern-port 121 | 122 | # Stores VSCode versions used for testing VSCode extensions 123 | .vscode-test 124 | 125 | # yarn v2 126 | .yarn/cache 127 | .yarn/unplugged 128 | .yarn/build-state.yml 129 | .yarn/install-state.gz 130 | .pnp.* 131 | 132 | build/ 133 | 134 | gcp-oauth.keys.json 135 | .*-server-credentials.json 136 | 137 | # Byte-compiled / optimized / DLL files 138 | __pycache__/ 139 | *.py[cod] 140 | *$py.class 141 | 142 | # C extensions 143 | *.so 144 | 145 | # Distribution / packaging 146 | .Python 147 | build/ 148 | develop-eggs/ 149 | dist/ 150 | downloads/ 151 | eggs/ 152 | .eggs/ 153 | lib/ 154 | lib64/ 155 | parts/ 156 | sdist/ 157 | var/ 158 | wheels/ 159 | share/python-wheels/ 160 | *.egg-info/ 161 | .installed.cfg 162 | *.egg 163 | MANIFEST 164 | 165 | # PyInstaller 166 | # Usually these files are written by a python script from a template 167 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 168 | *.manifest 169 | *.spec 170 | 171 | # Installer logs 172 | pip-log.txt 173 | pip-delete-this-directory.txt 174 | 175 | # Unit test / coverage reports 176 | htmlcov/ 177 | .tox/ 178 | .nox/ 179 | .coverage 180 | .coverage.* 181 | .cache 182 | nosetests.xml 183 | coverage.xml 184 | *.cover 185 | *.py,cover 186 | .hypothesis/ 187 | .pytest_cache/ 188 | cover/ 189 | 190 | # Translations 191 | *.mo 192 | *.pot 193 | 194 | # Django stuff: 195 | *.log 196 | local_settings.py 197 | db.sqlite3 198 | db.sqlite3-journal 199 | 200 | # Flask stuff: 201 | instance/ 202 | .webassets-cache 203 | 204 | # Scrapy stuff: 205 | .scrapy 206 | 207 | # Sphinx documentation 208 | docs/_build/ 209 | 210 | # PyBuilder 211 | .pybuilder/ 212 | target/ 213 | 214 | # Jupyter Notebook 215 | .ipynb_checkpoints 216 | 217 | # IPython 218 | profile_default/ 219 | ipython_config.py 220 | 221 | # pyenv 222 | # For a library or package, you might want to ignore these files since the code is 223 | # intended to run in multiple environments; otherwise, check them in: 224 | # .python-version 225 | 226 | # pipenv 227 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 228 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 229 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 230 | # install all needed dependencies. 231 | #Pipfile.lock 232 | 233 | # poetry 234 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. 235 | # This is especially recommended for binary packages to ensure reproducibility, and is more 236 | # commonly ignored for libraries. 237 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control 238 | #poetry.lock 239 | 240 | # pdm 241 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. 242 | #pdm.lock 243 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it 244 | # in version control. 245 | # https://pdm.fming.dev/latest/usage/project/#working-with-version-control 246 | .pdm.toml 247 | .pdm-python 248 | .pdm-build/ 249 | 250 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm 251 | __pypackages__/ 252 | 253 | # Celery stuff 254 | celerybeat-schedule 255 | celerybeat.pid 256 | 257 | # SageMath parsed files 258 | *.sage.py 259 | 260 | # Environments 261 | .env 262 | .venv 263 | env/ 264 | venv/ 265 | ENV/ 266 | env.bak/ 267 | venv.bak/ 268 | 269 | # Spyder project settings 270 | .spyderproject 271 | .spyproject 272 | 273 | # Rope project settings 274 | .ropeproject 275 | 276 | # mkdocs documentation 277 | /site 278 | 279 | # mypy 280 | .mypy_cache/ 281 | .dmypy.json 282 | dmypy.json 283 | 284 | # Pyre type checker 285 | .pyre/ 286 | 287 | # pytype static type analyzer 288 | .pytype/ 289 | 290 | # Cython debug symbols 291 | cython_debug/ 292 | 293 | .DS_Store 294 | 295 | # PyCharm 296 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can 297 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore 298 | # and can be added to the global gitignore or merged into this file. For a more nuclear 299 | # option (not recommended) you can uncomment the following to ignore the entire idea folder. 300 | #.idea/ 301 | 302 | .cursor/ 303 | ui-design-plan.md 304 | 305 | -------------------------------------------------------------------------------- /src/tools/chainOfDraftParams.ts: -------------------------------------------------------------------------------- 1 | import { z } from "zod"; 2 | 3 | export const TOOL_NAME = "chain-of-draft"; 4 | 5 | // Detailed parameter descriptions 6 | export const TOOL_PARAM_DESCRIPTIONS = { 7 | reasoning_chain: "Array of strings representing the current chain of reasoning steps. Each step should be a clear, complete thought that contributes to the overall analysis or solution.", 8 | 9 | next_step_needed: "Boolean flag indicating whether another critique or revision cycle is needed in the reasoning chain. Set to false only when the final, satisfactory conclusion has been reached.", 10 | 11 | draft_number: "Current draft number in the iteration sequence (must be >= 1). Increments with each new critique or revision.", 12 | 13 | total_drafts: "Estimated total number of drafts needed to reach a complete solution (must be >= draft_number). Can be adjusted as the solution evolves.", 14 | 15 | is_critique: "Boolean flag indicating whether the current step is a critique phase (true) evaluating previous reasoning, or a revision phase (false) implementing improvements.", 16 | 17 | critique_focus: "The specific aspect or dimension being critiqued in the current evaluation (e.g., 'logical_consistency', 'factual_accuracy', 'completeness', 'clarity', 'relevance'). Required when is_critique is true.", 18 | 19 | revision_instructions: "Detailed, actionable guidance for how to revise the reasoning based on the preceding critique. Should directly address issues identified in the critique. Required when is_critique is false.", 20 | 21 | step_to_review: "Zero-based index of the specific reasoning step being targeted for critique or revision. When omitted, the critique or revision applies to the entire reasoning chain.", 22 | 23 | is_final_draft: "Boolean flag indicating whether this is the final draft in the reasoning process. Helps signal the completion of the iterative refinement.", 24 | }; 25 | 26 | export const TOOL_SCHEMA = { 27 | reasoning_chain: z.array(z.string().min(1, "Reasoning steps cannot be empty")) 28 | .min(1, "At least one reasoning step is required") 29 | .describe(TOOL_PARAM_DESCRIPTIONS.reasoning_chain), 30 | 31 | next_step_needed: z.boolean() 32 | .describe(TOOL_PARAM_DESCRIPTIONS.next_step_needed), 33 | 34 | draft_number: z.number() 35 | .min(1, "Draft number must be at least 1") 36 | .describe(TOOL_PARAM_DESCRIPTIONS.draft_number), 37 | 38 | total_drafts: z.number() 39 | .min(1, "Total drafts must be at least 1") 40 | .describe(TOOL_PARAM_DESCRIPTIONS.total_drafts), 41 | 42 | is_critique: z.boolean() 43 | .optional() 44 | .describe(TOOL_PARAM_DESCRIPTIONS.is_critique), 45 | 46 | critique_focus: z.string() 47 | .min(1, "Critique focus cannot be empty") 48 | .optional() 49 | .describe(TOOL_PARAM_DESCRIPTIONS.critique_focus), 50 | 51 | revision_instructions: z.string() 52 | .min(1, "Revision instructions cannot be empty") 53 | .optional() 54 | .describe(TOOL_PARAM_DESCRIPTIONS.revision_instructions), 55 | 56 | step_to_review: z.number() 57 | .min(0, "Step index must be non-negative") 58 | .optional() 59 | .describe(TOOL_PARAM_DESCRIPTIONS.step_to_review), 60 | 61 | is_final_draft: z.boolean() 62 | .optional() 63 | .describe(TOOL_PARAM_DESCRIPTIONS.is_final_draft), 64 | 65 | new_reasoning_steps: z.array(z.string().min(1, "Reasoning steps cannot be empty")) 66 | .min(1, "At least one new reasoning step is required") 67 | .describe("New reasoning steps to add to the chain"), 68 | }; 69 | 70 | // Add this right after TOOL_NAME 71 | export const TOOL_REQUIRED_PARAMS_NOTICE = ` 72 | ⚠️ REQUIRED PARAMETERS - ALL MUST BE PROVIDED: 73 | 1. reasoning_chain: string[] - At least one reasoning step 74 | 2. next_step_needed: boolean - Whether another iteration is needed 75 | 3. draft_number: number - Current draft number (≥ 1) 76 | 4. total_drafts: number - Total planned drafts (≥ draft_number) 77 | 78 | Optional parameters only required based on context: 79 | - is_critique?: boolean - If true, critique_focus is required 80 | - critique_focus?: string - Required when is_critique=true 81 | - revision_instructions?: string - Recommended for revision steps 82 | - step_to_review?: number - Specific step index to review 83 | - is_final_draft?: boolean - Marks final iteration 84 | `; 85 | 86 | export const TOOL_DESCRIPTION = ` 87 | # Chain of Draft (CoD): Systematic Reasoning Tool 88 | 89 | ${TOOL_REQUIRED_PARAMS_NOTICE} 90 | 91 | ## Purpose: 92 | Enhances problem-solving through structured, iterative critique and revision. 93 | 94 | Chain of Draft is an advanced reasoning tool that enhances problem-solving through structured, iterative critique and revision. Unlike traditional reasoning approaches, CoD mimics the human drafting process to improve clarity, accuracy, and robustness of conclusions. 95 | 96 | ## When to Use This Tool: 97 | - **Complex Problem-Solving:** Tasks requiring detailed, multi-step analysis with high accuracy demands 98 | - **Critical Reasoning:** Problems where logical flow and consistency are essential 99 | - **Error-Prone Scenarios:** Questions where initial reasoning might contain mistakes or oversight 100 | - **Multi-Perspective Analysis:** Cases benefiting from examining a problem from different angles 101 | - **Self-Correction Needs:** When validation and refinement of initial thoughts are crucial 102 | - **Detailed Solutions:** Tasks requiring comprehensive explanations with supporting evidence 103 | - **Mathematical or Logical Puzzles:** Problems with potential for calculation errors or logical gaps 104 | - **Nuanced Analysis:** Situations with subtle distinctions that might be missed in a single pass 105 | 106 | ## Key Capabilities: 107 | - **Iterative Improvement:** Systematically refines reasoning through multiple drafts 108 | - **Self-Critique:** Critically examines previous reasoning to identify flaws and opportunities 109 | - **Focused Revision:** Targets specific aspects of reasoning in each iteration 110 | - **Perspective Flexibility:** Can adopt different analytical viewpoints during critique 111 | - **Progressive Refinement:** Builds toward optimal solutions through controlled iterations 112 | - **Context Preservation:** Maintains understanding across multiple drafts and revisions 113 | - **Adaptable Depth:** Adjusts the number of iterations based on problem complexity 114 | - **Targeted Improvements:** Addresses specific weaknesses in each revision cycle 115 | 116 | ## Parameters Explained: 117 | - **reasoning_chain:** Array of strings representing your current reasoning steps. Each element should contain a clear, complete thought that contributes to the overall analysis. 118 | 119 | - **next_step_needed:** Boolean flag indicating whether additional critique or revision is required. Set to true until the final, refined reasoning chain is complete. 120 | 121 | - **draft_number:** Integer tracking the current iteration (starting from 1). Increments with each critique or revision. 122 | 123 | - **total_drafts:** Estimated number of drafts needed for completion. This can be adjusted as the solution evolves. 124 | 125 | - **is_critique:** Boolean indicating the current mode: 126 | * true = Evaluating previous reasoning 127 | * false = Implementing revisions 128 | 129 | - **critique_focus:** (Required when is_critique=true) Specific aspect being evaluated, such as: 130 | * "logical_consistency": Checking for contradictions or flaws in reasoning 131 | * "factual_accuracy": Verifying correctness of facts and calculations 132 | * "completeness": Ensuring all relevant aspects are considered 133 | * "clarity": Evaluating how understandable the reasoning is 134 | * "relevance": Assessing if reasoning directly addresses the problem 135 | 136 | - **revision_instructions:** (Required when is_critique=false) Detailed guidance for improving the reasoning based on the preceding critique. 137 | 138 | - **step_to_review:** (Optional) Zero-based index of the specific reasoning step being critiqued or revised. When omitted, applies to the entire chain. 139 | 140 | - **is_final_draft:** (Optional) Boolean indicating whether this is the final iteration of reasoning. 141 | 142 | ## Best Practice Workflow: 143 | 1. **Start with Initial Draft:** Begin with your first-pass reasoning and set a reasonable total_drafts (typically 3-5). 144 | 145 | 2. **Alternate Critique and Revision:** Use is_critique=true to evaluate reasoning, then is_critique=false to implement improvements. 146 | 147 | 3. **Focus Each Critique:** Choose a specific critique_focus for each evaluation cycle rather than attempting to address everything at once. 148 | 149 | 4. **Provide Detailed Revision Guidance:** Include specific, actionable revision_instructions based on each critique. 150 | 151 | 5. **Target Specific Steps When Needed:** Use step_to_review to focus on particular reasoning steps that need improvement. 152 | 153 | 6. **Adjust Total Drafts As Needed:** Modify total_drafts based on problem complexity and progress. 154 | 155 | 7. **Mark Completion Appropriately:** Set next_step_needed=false only when the reasoning chain is complete and satisfactory. 156 | 157 | 8. **Aim for Progressive Improvement:** Each iteration should measurably improve the reasoning quality. 158 | 159 | ## Example Application: 160 | - **Initial Draft:** First-pass reasoning about a complex problem 161 | - **Critique #1:** Focus on logical consistency and identify contradictions 162 | - **Revision #1:** Address logical flaws found in the critique 163 | - **Critique #2:** Focus on completeness and identify missing considerations 164 | - **Revision #2:** Incorporate overlooked aspects and strengthen reasoning 165 | - **Final Critique:** Holistic review of clarity and relevance 166 | - **Final Revision:** Refine presentation and ensure direct addressing of the problem 167 | 168 | Chain of Draft is particularly effective when complex reasoning must be broken down into clear steps, analyzed from multiple perspectives, and refined through systematic critique. By mimicking the human drafting process, it produces more robust and accurate reasoning than single-pass approaches. 169 | `; 170 | 171 | -------------------------------------------------------------------------------- /docs/chain-of-draft.md: -------------------------------------------------------------------------------- 1 | # 🔄 Chain of Draft (CoD) Prompting 2 | 3 | > 🎯 **TL;DR**: Chain of Draft (CoD) is an advanced prompting technique designed to improve the quality and consistency of responses from large language models (LLMs). It moves beyond simple prompt engineering by incorporating a structured, iterative process that mimics a drafting and revision workflow. This method aims to address limitations of standard prompting, especially for complex or nuanced tasks. 4 | 5 | Here's a breakdown of CoD prompting, including rules, best practices, and suggestions for effective implementation: 6 | 7 | ## 📚 Table of Contents 8 | 9 | - [Core Concept](#-core-concept-iterative-refinement) 10 | - [Key Components](#-key-components) 11 | - [Rules & Best Practices](#-rules-best-practices-and-suggestions) 12 | - [Implementation Examples](#-implementation-example) 13 | - [Benefits & Limitations](#-benefits-and-limitations) 14 | - [Advanced Topics](#-advanced-topics) 15 | - [Resources](#-resources) 16 | 17 | ## 🔄 Core Concept: Iterative Refinement 18 | 19 | ```mermaid 20 | graph TD 21 | A[Initial Understanding] --> B[Progressive Refinement] 22 | B --> C[Improved Output] 23 | C --> D[Further Iteration] 24 | D --> B 25 | ``` 26 | 27 | CoD is rooted in the idea that complex outputs are best achieved through iterative refinement. Instead of expecting a perfect response from a single prompt, CoD prompts guide the LLM through a series of drafts, each building upon and improving the previous one. This process allows the model to progressively refine its understanding of the task and generate more coherent and high-quality outputs. 28 | 29 | **Core Principle: Iterative Refinement** 30 | 31 | At its heart, CoD is based on the principle that complex outputs are best developed through iterative improvement. Instead of aiming for perfection in a single attempt, CoD guides the LLM through multiple drafts, each building upon and improving the last. This iterative cycle allows the model to progressively deepen its understanding of the task and produce more refined and superior outputs. 32 | 33 | ## 🏗️ Key Components of CoD Prompting 34 | 35 | ```mermaid 36 | graph TD 37 | A[Initial Draft Prompt] --> B[Critique Phase] 38 | B --> C[Revision Phase] 39 | C --> B 40 | C --> D[Final Output] 41 | ``` 42 | 43 | 1. **Initial Draft Prompt** 📝 44 | This prompt sets the stage and requests the LLM to generate an initial, often basic, draft of the desired output. It focuses on broad strokes rather than fine details. 45 | 46 | 2. **Critique and Revision Prompts** 🔍 47 | These prompts are the heart of CoD. They follow the initial draft and instruct the LLM to critique its own previous draft and then revise it based on the critique. This critique-revision cycle can be repeated multiple times, each iteration focusing on different aspects of improvement. 48 | 49 | 3. **Specific Instructions** 📋 50 | Within each prompt, clear and specific instructions are crucial. These instructions guide the LLM on what to focus on in each draft and revision stage. For example, prompts might instruct the model to improve clarity, add detail, refine arguments, or correct factual errors. 51 | 52 | ## 📋 Rules, Best Practices, and Suggestions for CoD Prompting 53 | 54 | ### 🎯 I. Rules 55 | 56 | - **Rule 1: Start with a Clear Initial Draft Prompt.** 57 | The initial prompt should clearly define the task and desired output format. Even though it's just a first draft, clarity at this stage sets the foundation for subsequent refinements. 58 | 59 | - **Rule 2: Implement Iterative Critique and Revision Cycles.** 60 | CoD *must* involve critique and revision. A single draft is not CoD. The power comes from the iterative process of self-correction. 61 | 62 | - **Rule 3: Provide Specific and Actionable Instructions in Critique and Revision Prompts.** 63 | General prompts like "improve the draft" are less effective. Prompts should guide the LLM to focus on specific areas for improvement, such as "critique for clarity and revise to improve it" or "critique the factual accuracy and revise with corrections". 64 | 65 | - **Rule 4: Maintain Context Across Iterations.** 66 | Each prompt should reference the previous draft and build upon it. The LLM needs to understand that it's working on the same task and refining the same output across prompts. 67 | 68 | ### ✨ II. Best Practices 69 | 70 | - **Best Practice 1: Focus Each Iteration on Specific Aspects of Quality.** 71 | Don't try to improve everything at once. Dedicate each critique-revision cycle to a specific dimension of quality like: 72 | 73 | | Aspect | Focus Areas | 74 | |--------|-------------| 75 | | **Clarity and Coherence** | Improving sentence structure, logical flow, and overall understandability | 76 | | **Factual Accuracy** | Verifying and correcting factual claims | 77 | | **Completeness and Detail** | Adding more relevant information and elaborating on key points | 78 | | **Relevance and Focus** | Ensuring the output directly addresses the prompt and stays on topic | 79 | | **Tone and Style** | Refining the writing style to match the desired audience and purpose | 80 | 81 | - **Best Practice 2: Use Role-Playing in Prompts.** 82 | Instruct the LLM to adopt specific roles during critique and revision. For example: 83 | - *"Act as a professional editor and critique the previous draft for grammar, style, and clarity."* 84 | - *"Assume the role of a fact-checker and identify any potential inaccuracies in the draft."* 85 | - *"Imagine you are the target audience and critique the draft for understandability and relevance."* 86 | 87 | - **Best Practice 3: Vary the Critique Perspective.** 88 | To get a well-rounded critique, consider using different perspectives in each iteration. For instance, one critique could focus on factual accuracy, the next on logical flow, and another on stylistic refinement. 89 | 90 | - **Best Practice 4: Control the Number of Iterations.** 91 | While iterative refinement is powerful, excessive iterations can lead to diminishing returns or even redundancy. Determine an appropriate number of cycles based on the complexity of the task and desired level of quality. Start with a few iterations (e.g., 2-4) and adjust as needed. 92 | 93 | - **Best Practice 5: Experiment with Different Prompt Structures.** 94 | CoD is flexible. Experiment with different ways to structure your prompts. You can use numbered lists, bullet points, or paragraph-based instructions. Find what works best for your specific task. 95 | 96 | ### 💡 III. Suggestions for Enhanced CoD Prompting 97 | 98 | - **Suggestion 1: Incorporate External Knowledge (If Necessary).** 99 | For tasks requiring specific knowledge, you can guide the LLM to incorporate external information during the revision process. This could involve suggesting search queries or providing relevant documents. 100 | 101 | - **Suggestion 2: Use Examples in Prompts.** 102 | Providing examples of good and bad drafts or critiques can help the LLM better understand what is expected in each stage. 103 | 104 | - **Suggestion 3: Monitor and Evaluate Each Draft.** 105 | Briefly review each draft generated by the LLM to ensure the critique and revision prompts are effective and the output is moving in the right direction. This allows for adjustments to prompts in subsequent iterations if needed. 106 | 107 | - **Suggestion 4: Combine CoD with Other Prompting Techniques.** 108 | CoD can be effectively combined with other methods like "Chain of Thought" for complex reasoning tasks or "Few-Shot Learning" by providing examples in the initial prompt. 109 | 110 | - **Suggestion 5: Apply CoD to Various Output Types.** 111 | CoD is not limited to text generation. It can be applied to code generation, creative content, and even structured data outputs. 112 | 113 | ## 💻 Example of a CoD Prompting Sequence 114 | 115 | ### Writing a Short Essay 116 | 117 | ```sequence 118 | Initial Draft->Critique 1: Clarity Review 119 | Critique 1->Revision 1: Improve Structure 120 | Revision 1->Critique 2: Fact Check 121 | Critique 2->Final Draft: Polish Content 122 | ``` 123 | 124 | 1. **Initial Draft Prompt:** 125 | *"Write a short draft essay (about 300 words) on the impact of social media on modern society."* 126 | 127 | 2. **Critique Prompt 1:** 128 | *"Critique the draft essay above for clarity and coherence. Identify any sentences or paragraphs that are unclear, disorganized, or lack logical flow."* 129 | 130 | 3. **Revision Prompt 1:** 131 | *"Revise the essay based on the critique above to improve clarity and coherence. Focus on sentence structure, paragraph organization, and logical transitions."* 132 | 133 | 4. **Critique Prompt 2:** 134 | *"Now, act as a fact-checker. Critique the revised essay for factual accuracy. Identify any claims that might be inaccurate or lack evidence."* 135 | 136 | 5. **Revision Prompt 2:** 137 | *"Revise the essay again, addressing the factual accuracy critiques. Correct any inaccuracies and add brief supporting evidence where necessary."* 138 | 139 | This sequence demonstrates how CoD systematically refines an initial draft through targeted critique and revision prompts, leading to a more polished and robust final output. 140 | 141 | ## 📊 Benefits and Limitations 142 | 143 | ### Benefits ✅ 144 | 145 | | Benefit | Description | 146 | |---------|-------------| 147 | | Improved Output Quality | CoD generally leads to more refined, coherent, and accurate outputs compared to single-prompt approaches, especially for complex tasks | 148 | | Enhanced Consistency | The structured process of CoD can make LLM responses more predictable and consistent in quality | 149 | | Greater Control | CoD gives users more control over the generation process, allowing them to guide the LLM towards specific quality dimensions | 150 | | Better Handling of Complexity | CoD is particularly effective for tasks that require nuanced understanding, detailed outputs, or multi-faceted reasoning | 151 | | Efficiency in Reasoning | CoD can achieve similar or better accuracy than Chain-of-Thought (CoT) prompting while using significantly fewer tokens | 152 | 153 | ### Limitations ⚠️ 154 | 155 | | Limitation | Impact | 156 | |------------|--------| 157 | | Increased Prompt Complexity | CoD prompts are more complex to design than simple prompts, requiring careful planning of critique and revision cycles | 158 | | Higher Token Usage | The iterative nature of CoD can lead to higher token consumption compared to single-prompt generation | 159 | | Not Always Necessary | For very simple or straightforward tasks, the overhead of CoD might not be justified | 160 | | Model Dependency | CoD may require larger models for optimal performance and might be less effective in zero-shot scenarios | 161 | 162 | ## 🎓 Advanced Topics 163 | 164 | ### Model Considerations 🤖 165 | 166 | - **Model Size Requirements** 167 | - Larger models preferred for better performance 168 | - Enhanced context handling capabilities 169 | - Improved self-critique abilities 170 | - Better reasoning and refinement skills 171 | 172 | - **Performance Optimization** 173 | - Token efficiency strategies 174 | - Context window management 175 | - Quality vs. speed trade-offs 176 | - Resource utilization 177 | 178 | ### Implementation Strategy 📈 179 | 180 | 1. **Planning Phase** 181 | - Define clear objectives 182 | - Set quality criteria 183 | - Design iteration strategy 184 | - Allocate resources 185 | 186 | 2. **Execution Phase** 187 | - Monitor progress 188 | - Adjust prompts 189 | - Track improvements 190 | - Validate outputs 191 | 192 | 3. **Refinement Phase** 193 | - Optimize workflows 194 | - Document patterns 195 | - Share learnings 196 | - Scale successful approaches 197 | 198 | ## 📚 Resources 199 | 200 | ### Learning Materials 📖 201 | 202 | - [Learn Prompting](https://learnprompting.org/docs/advanced/thought_generation/chain-of-draft) 203 | - [arXiv Paper](https://arxiv.org/html/2502.18600v1) 204 | - [DEV Community Article](https://dev.to/foxgem/chain-of-draft-thinking-faster-by-writing-less-54j6) 205 | 206 | ### Research and Development 207 | 208 | - Ongoing studies in prompt engineering 209 | - New applications and use cases 210 | - Performance benchmarking 211 | - Best practices evolution 212 | 213 | --- 214 | 215 | > 🌟 **Pro Tip**: Chain of Draft prompting is a powerful technique for those looking to maximize the output quality from LLMs, especially for complex and nuanced tasks. By emulating a human-like drafting process, it provides a structured and controlled method for generating high-caliber LLM outputs. While it demands more upfront effort in prompt design, the enhanced output quality and consistency often justify this investment. 216 | 217 | *Last updated: 13-MAR-2025* 218 | -------------------------------------------------------------------------------- /src/tools/chainOfDraftTool.ts: -------------------------------------------------------------------------------- 1 | import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; 2 | import { McpError, ErrorCode } from "@modelcontextprotocol/sdk/types.js"; 3 | import { z } from "zod"; 4 | import { TOOL_NAME, TOOL_SCHEMA, TOOL_DESCRIPTION } from "./chainOfDraftParams.js"; 5 | import { logger } from "../utils/logging.js"; 6 | 7 | interface ThoughtData { 8 | // Required fields 9 | reasoning_chain: string[]; 10 | next_step_needed: boolean; 11 | draft_number: number; 12 | total_drafts: number; 13 | 14 | // Optional fields 15 | is_critique?: boolean; 16 | critique_focus?: string; 17 | revision_instructions?: string; 18 | step_to_review?: number; 19 | is_final_draft: boolean; // This has a default of false 20 | } 21 | 22 | interface SessionState { 23 | thoughtHistory: ThoughtData[]; 24 | branches: Record; 25 | } 26 | 27 | const sessions = new Map(); 28 | 29 | export const chainOfDraftTool = (server: McpServer): void => { 30 | const getOrCreateSession = (sessionId: string): SessionState => { 31 | if (!sessions.has(sessionId)) { 32 | sessions.set(sessionId, { 33 | thoughtHistory: [], 34 | branches: {} 35 | }); 36 | } 37 | return sessions.get(sessionId)!; 38 | }; 39 | 40 | const processThoughtRequest = async (input: unknown, sessionId: string) => { 41 | try { 42 | const session = getOrCreateSession(sessionId); 43 | const validatedInput = validateThoughtData(input); 44 | if (!validatedInput) { 45 | throw new McpError(ErrorCode.InvalidParams, "Invalid thought data"); 46 | } 47 | 48 | // Validate draft progression 49 | if (validatedInput.draft_number > validatedInput.total_drafts) { 50 | validatedInput.total_drafts = validatedInput.draft_number; 51 | } 52 | 53 | // Store the thought in session history 54 | session.thoughtHistory.push(validatedInput); 55 | 56 | // Handle branching if specified 57 | if (validatedInput.step_to_review !== undefined) { 58 | const branchId = `branch_${validatedInput.draft_number}_${validatedInput.step_to_review}`; 59 | if (!session.branches[branchId]) { 60 | session.branches[branchId] = []; 61 | } 62 | session.branches[branchId].push(validatedInput); 63 | } 64 | 65 | // Format response 66 | return { 67 | content: [{ 68 | type: "text", 69 | text: JSON.stringify({ 70 | draftNumber: validatedInput.draft_number, 71 | totalDrafts: validatedInput.total_drafts, 72 | nextStepNeeded: validatedInput.next_step_needed, 73 | isCritique: validatedInput.is_critique, 74 | critiqueFocus: validatedInput.critique_focus, 75 | revisionInstructions: validatedInput.revision_instructions, 76 | stepToReview: validatedInput.step_to_review, 77 | isFinalDraft: validatedInput.is_final_draft, 78 | branches: Object.keys(session.branches), 79 | thoughtHistoryLength: session.thoughtHistory.length 80 | }, null, 2) 81 | }] 82 | }; 83 | } catch (error) { 84 | if (error instanceof McpError) { 85 | throw error; 86 | } 87 | throw new McpError( 88 | ErrorCode.InternalError, 89 | error instanceof Error ? error.message : String(error) 90 | ); 91 | } 92 | }; 93 | 94 | server.tool( 95 | TOOL_NAME, 96 | TOOL_DESCRIPTION, 97 | TOOL_SCHEMA, 98 | async (args, extra) => { 99 | const sessionId = extra.sessionId || 'default'; 100 | return { 101 | content: [{ 102 | type: "text" as const, 103 | text: JSON.stringify(await processThoughtRequest(args, sessionId)) 104 | }] 105 | }; 106 | } 107 | ); 108 | } 109 | 110 | // const TOOL_DESCRIPTION = ` 111 | // A tool for generating and refining reasoning chains using Chain of Draft (CoD). 112 | 113 | // This tool enhances Chain of Thought (CoT) prompting by incorporating iterative critique and revision of the generated reasoning steps, leading to more accurate and robust conclusions. 114 | 115 | // When to use this tool: 116 | // - Complex reasoning tasks where accuracy and logical flow are critical. 117 | // - Problems that require breaking down into multiple steps, and where each step needs careful scrutiny. 118 | // - Situations where the initial reasoning chain might contain errors, inconsistencies, or gaps. 119 | // - For tasks like solving math problems, logical puzzles, and detailed analysis of complex information. 120 | 121 | // Key features: 122 | // - Generates an initial chain of thought. 123 | // - Allows for iterative critique and revision of individual steps or the entire chain. 124 | // - Enables focusing on specific aspects of the reasoning (e.g., logical validity, completeness, relevance). 125 | // - Provides parameters to control the CoT process, such as draft number, total drafts, and revision focus. 126 | // - Maintains context across iterations of the reasoning chain. 127 | 128 | // Parameters explained: 129 | // - reasoning_chain: The current chain of thought, consisting of one or more reasoning steps. 130 | // - next_step_needed: True if another critique/revision cycle is needed. 131 | // - draft_number: The current draft number (starting from 1). 132 | // - total_drafts: The total number of draft/revision cycles planned. 133 | // - is_critique: Boolean indicating if the current step is a critique (true) or revision (false). 134 | // - critique_focus: Specifies the focus of the current critique (e.g., "logical validity", "completeness", "relevance", "clarity"). 135 | // - revision_instructions: Specific instructions for the revision, based on the critique. 136 | // - step_to_revise: (Optional) If revising a specific step, the index or identifier of that step. 137 | 138 | // You should: 139 | // 1. Start with an initial reasoning_chain and set total_drafts. 140 | // 2. Use is_critique to alternate between critique and revision steps. 141 | // 3. Specify critique_focus to guide the critique process. 142 | // 4. Provide detailed revision_instructions based on the critique. 143 | // 5. Use step_to_revise to target specific parts of the reasoning chain. 144 | // 6. Adjust total_drafts as needed based on the progress. 145 | // 7. Set next_step_needed to false only when the final reasoning_chain is complete and satisfactory. 146 | 147 | // `; 148 | 149 | const validateThoughtData = (input: unknown): ThoughtData | null => { 150 | const data = input as Record; 151 | 152 | // Check only required fields first 153 | if (typeof data !== "object" || data === null || 154 | !("reasoning_chain" in data) || 155 | !("next_step_needed" in data) || 156 | !("draft_number" in data) || 157 | !("total_drafts" in data)) { 158 | throw new Error("Missing required fields"); 159 | } 160 | 161 | // Validate types and create return object 162 | const thoughtData: ThoughtData = { 163 | reasoning_chain: Array.isArray(data.reasoning_chain) ? data.reasoning_chain : [], 164 | next_step_needed: Boolean(data.next_step_needed), 165 | draft_number: Number(data.draft_number), 166 | total_drafts: Number(data.total_drafts), 167 | is_final_draft: Boolean(data.is_final_draft ?? false) 168 | }; 169 | 170 | // Optional fields 171 | if ("is_critique" in data) thoughtData.is_critique = Boolean(data.is_critique); 172 | if ("critique_focus" in data) thoughtData.critique_focus = String(data.critique_focus); 173 | if ("revision_instructions" in data) thoughtData.revision_instructions = String(data.revision_instructions); 174 | if ("step_to_review" in data) thoughtData.step_to_review = Number(data.step_to_review); 175 | 176 | // Validate the data 177 | if (!Array.isArray(thoughtData.reasoning_chain) || thoughtData.reasoning_chain.length === 0) { 178 | throw new Error("Invalid reasoning chain"); 179 | } 180 | 181 | if (thoughtData.draft_number <= 0) { 182 | throw new Error("Draft number must be positive"); 183 | } 184 | 185 | if (thoughtData.total_drafts <= 0) { 186 | throw new Error("Total drafts must be positive"); 187 | } 188 | 189 | if (thoughtData.draft_number > thoughtData.total_drafts) { 190 | throw new Error("Draft number cannot exceed total drafts"); 191 | } 192 | 193 | // Validate critique-specific fields 194 | if (thoughtData.is_critique && !thoughtData.critique_focus) { 195 | throw new Error("Critique focus required when is_critique is true"); 196 | } 197 | 198 | return thoughtData; 199 | } 200 | const formatThought = (thought: ThoughtData): string => { 201 | return JSON.stringify({ 202 | thoughtNumber: thought.draft_number, 203 | thought: thought.reasoning_chain 204 | }); 205 | } 206 | 207 | const processThought = (input: unknown): { content: Array<{ type: string; text: string }>; isError?: boolean } => { 208 | try { 209 | const validatedInput = validateThoughtData(input); 210 | if (!validatedInput) { 211 | throw new Error("Invalid thought data"); 212 | } 213 | 214 | // make sure we have a valid thought number 215 | if (validatedInput.draft_number <= 0) { 216 | throw new Error("Invalid draft number"); 217 | } 218 | 219 | // make sure we have a valid total drafts 220 | if (validatedInput.total_drafts <= 0) { 221 | throw new Error("Invalid total drafts"); 222 | } 223 | 224 | // make sure we have a valid reasoning chain 225 | if (!Array.isArray(validatedInput.reasoning_chain) || validatedInput.reasoning_chain.length === 0) { 226 | throw new Error("Invalid reasoning chain"); 227 | } 228 | 229 | // make sure we have a valid next step needed 230 | if (typeof validatedInput.next_step_needed !== "boolean") { 231 | throw new Error("Invalid next step needed"); 232 | } 233 | 234 | // make sure we have a valid critique focus 235 | if (validatedInput.is_critique && !validatedInput.critique_focus) { 236 | throw new Error("Invalid critique focus"); 237 | } 238 | 239 | // make sure we have a valid revision instructions 240 | if (validatedInput.is_critique && !validatedInput.revision_instructions) { 241 | throw new Error("Invalid revision instructions"); 242 | } 243 | 244 | // make sure we have a valid step to review 245 | if (validatedInput.step_to_review && (typeof validatedInput.step_to_review !== "number" || validatedInput.step_to_review < 0)) { 246 | throw new Error("Invalid step to review"); 247 | } 248 | 249 | // make sure we have a valid is final draft 250 | if (typeof validatedInput.is_final_draft !== "boolean") { 251 | throw new Error("Invalid is final draft"); 252 | } 253 | 254 | // make sure the current ask is not greater than the total drafts 255 | if (validatedInput.draft_number > validatedInput.total_drafts) { 256 | throw new Error("Current draft number is greater than the total drafts"); 257 | } 258 | 259 | const formattedThought = formatThought(validatedInput); 260 | logger.error(formattedThought); 261 | 262 | return { 263 | content: [{ 264 | type: "text", 265 | text: JSON.stringify({ 266 | thoughtNumber: validatedInput.draft_number, 267 | thought: formattedThought 268 | }) 269 | }] 270 | } 271 | 272 | 273 | } catch (error) { 274 | return { 275 | content: [{ 276 | type: "text", 277 | text: JSON.stringify({ 278 | error: error instanceof Error ? error.message : String(error), 279 | status: 'failed' 280 | }, null, 2) 281 | }], 282 | isError: true 283 | }; 284 | } 285 | } 286 | 287 | const clearSession = (sessionId: string): void => { 288 | sessions.delete(sessionId); 289 | }; 290 | 291 | const pruneOldSessions = (): void => { 292 | // Add logic to remove sessions older than X time 293 | // This prevents memory leaks 294 | }; --------------------------------------------------------------------------------