Skip to main content
Glama
stat-guy

Chain of Draft (CoD) MCP Server

by stat-guy

chain_of_draft_solve

Solve reasoning problems using a Chain of Draft approach that generates minimal intermediate steps to reduce token usage while maintaining accuracy across domains like math, logic, and code.

Instructions

Solve a reasoning problem using Chain of Draft approach

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
problemYesThe problem to solve
domainNoDomain for context (math, logic, code, common-sense, etc.)
max_words_per_stepNoMaximum words per reasoning step
approachNoForce 'CoD' or 'CoT' approach
enforce_formatNoWhether to enforce the word limit
adaptive_word_limitNoAdjust word limits based on complexity

Implementation Reference

  • server.py:36-80 (handler)
    Primary handler for the chain_of_draft_solve MCP tool. Registers the tool and handles execution by delegating to the ChainOfDraftClient.
    @app.tool()
    async def chain_of_draft_solve(
        problem: str,
        domain: str = "general",
        max_words_per_step: int = None,
        approach: str = None,
        enforce_format: bool = True,
        adaptive_word_limit: bool = True
    ) -> str:
        """Solve a reasoning problem using Chain of Draft approach.
        
        Args:
            problem: The problem to solve
            domain: Domain for context (math, logic, code, common-sense, etc.)
            max_words_per_step: Maximum words per reasoning step (default: adaptive)
            approach: Force "CoD" or "CoT" approach (default: auto-select)
            enforce_format: Whether to enforce the word limit (default: True)
            adaptive_word_limit: Adjust word limits based on complexity (default: True)
        """
        # Track execution time
        start_time = time.time()
        
        # Process the request with the client
        result = await cod_client.solve_with_reasoning(
            problem=problem,
            domain=domain,
            max_words_per_step=max_words_per_step,
            approach=approach,
            enforce_format=enforce_format,
            adaptive_word_limit=adaptive_word_limit
        )
        
        # Calculate execution time
        execution_time = (time.time() - start_time) * 1000  # ms
        
        # Format the response
        formatted_response = (
            f"Chain of {result['approach']} reasoning ({result['word_limit']} word limit):\n\n"
            f"{result['reasoning_steps']}\n\n"
            f"Final answer: {result['final_answer']}\n\n"
            f"Stats: {result['token_count']} tokens, {execution_time:.0f}ms, "
            f"complexity score: {result['complexity']}"
        )
        
        return formatted_response
  • Core helper function implementing the Chain of Draft logic: complexity estimation, approach selection (CoD/CoT), prompt generation, LLM invocation, response extraction, format enforcement, and analytics.
    async def solve_with_reasoning(self, problem, domain="general", **kwargs):
        """
        Solve a problem using the appropriate reasoning approach.
        
        Args:
            problem: The problem text
            domain: Problem domain (math, code, logic, etc.)
            **kwargs: Additional parameters and settings
            
        Returns:
            Dictionary with reasoning steps and answer
        """
        start_time = time.time()
        
        # Override settings with kwargs
        local_settings = {**self.settings, **kwargs}
        
        # Determine complexity and select approach
        complexity = await self.complexity_estimator.estimate_complexity(problem, domain)
        
        if local_settings.get("approach"):
            # Manually specified approach
            approach = local_settings["approach"]
            approach_reason = "Manually specified"
        else:
            # Auto-select based on problem
            approach, approach_reason = await self.reasoning_selector.select_approach(
                problem, domain, complexity
            )
        
        # Determine word limit
        if local_settings["adaptive_word_limit"] and approach == "CoD":
            word_limit = complexity  # Use estimated complexity as word limit
        else:
            word_limit = local_settings["max_words_per_step"]
        
        # Get examples
        examples = await self.example_db.get_examples(domain, approach)
        
        # Create prompt based on approach
        if approach == "CoD":
            prompt = create_cod_prompt(problem, domain, word_limit, examples)
        else:
            prompt = create_cot_prompt(problem, domain, examples)
        
        # Generate response from LLM
        response = await self.client.messages.create(
            model=local_settings.get("model", "claude-3-5-sonnet-20240620"),
            max_tokens=local_settings.get("max_tokens", 500),
            system=prompt["system"],
            messages=[{"role": "user", "content": prompt["user"]}]
        )
        
        # Extract reasoning and answer
        full_response = response.content[0].text
        parts = full_response.split("####")
        
        reasoning = parts[0].strip()
        answer = parts[1].strip() if len(parts) > 1 else "No clear answer found"
        
        # Apply format enforcement if needed
        if local_settings["enforce_format"] and approach == "CoD":
            reasoning = self.format_enforcer.enforce_word_limit(reasoning, word_limit)
            adherence = self.format_enforcer.analyze_adherence(reasoning, word_limit)
        else:
            adherence = None
        
        # Record analytics
        if local_settings["track_analytics"]:
            execution_time = (time.time() - start_time) * 1000  # ms
            await self.analytics.record_inference(
                problem=problem,
                domain=domain,
                approach=approach,
                word_limit=word_limit,
                tokens_used=len(full_response.split()),
                execution_time=execution_time,
                reasoning=reasoning,
                answer=answer,
                metadata={
                    "complexity": complexity,
                    "approach_reason": approach_reason,
                    "adherence": adherence
                }
            )
        
        return {
            "reasoning_steps": reasoning,
            "final_answer": answer,
            "token_count": len(full_response.split()),
            "approach": approach,
            "complexity": complexity,
            "word_limit": word_limit
        }
  • Input schema definition for the chain_of_draft_solve tool in the JavaScript implementation.
    const CHAIN_OF_DRAFT_TOOL = {
      name: "chain_of_draft_solve",
      description: "Solve a reasoning problem using Chain of Draft approach",
      inputSchema: {
        type: "object",
        properties: {
          problem: {
            type: "string",
            description: "The problem to solve"
          },
          domain: {
            type: "string",
            description: "Domain for context (math, logic, code, common-sense, etc.)"
          },
          max_words_per_step: {
            type: "number",
            description: "Maximum words per reasoning step"
          },
          approach: {
            type: "string",
            description: "Force 'CoD' or 'CoT' approach"
          },
          enforce_format: {
            type: "boolean",
            description: "Whether to enforce the word limit"
          },
          adaptive_word_limit: {
            type: "boolean",
            description: "Adjust word limits based on complexity"
          }
        },
        required: ["problem"]
      }
  • Handler block for chain_of_draft_solve tool call in the JavaScript MCP server implementation. Delegates to chainOfDraftClient and formats response.
    if (name === "chain_of_draft_solve") {
      const result = await chainOfDraftClient.solveWithReasoning(args);
      
      const formattedResponse = 
        `Chain of ${result.approach} reasoning (${result.word_limit} word limit):\n\n` +
        `${result.reasoning_steps}\n\n` +
        `Final answer: ${result.final_answer}\n\n` +
        `Stats: ${result.token_count} tokens, ${result.execution_time_ms.toFixed(0)}ms, ` +
        `complexity score: ${result.complexity}`;
      
      return {
        content: [{
          type: "text",
          text: formattedResponse
        }]
      };
  • JavaScript equivalent helper implementing Chain of Draft solving logic, mirroring the Python client.py version.
    const chainOfDraftClient = {
      async solveWithReasoning(params) {
        const {
          problem,
          domain = 'general',
          max_words_per_step = null,
          approach = null,
          enforce_format = true,
          adaptive_word_limit = true
        } = params;
        
        const startTime = Date.now();
        
        // Analyze problem complexity
        const analysis = complexityEstimator.analyzeProblem(problem, domain);
        const complexity = analysis.estimated_complexity;
        
        // Determine word limit
        let wordLimit = max_words_per_step;
        if (!wordLimit && adaptive_word_limit) {
          wordLimit = complexity;
        } else if (!wordLimit) {
          // Default based on domain
          wordLimit = complexityEstimator.domainBaseLimits[domain] || 5;
        }
        
        // Determine approach (CoD or CoT)
        const performanceStats = analyticsDb.getPerformanceByDomain(domain);
        const selectedApproach = approach || 
          reasoningSelector.selectApproach(domain, complexity, performanceStats);
        
        // Create prompt based on approach
        const prompt = selectedApproach === 'CoD' 
          ? createCodPrompt(problem, domain, [], wordLimit)
          : createCotPrompt(problem, domain, []);
        
        // Call Claude
        const response = await anthropic.messages.create({
          model: 'claude-3-sonnet-20240229',
          max_tokens: 1000,
          messages: [
            { role: 'user', content: prompt }
          ]
        });
        
        // Extract reasoning and answer
        const fullText = response.content[0].text;
        
        // Extract final answer (assuming it comes after the reasoning, often starts with "Answer:" or similar)
        let reasoningSteps = fullText;
        let finalAnswer = '';
        
        // Common patterns for final answer sections
        const answerPatterns = [
          /(?:Final Answer|Answer|Therefore):?\s*(.*?)$/is,
          /(?:In conclusion|To conclude|Thus|Hence|So),\s*(.*?)$/is,
          /(?:The answer is|The result is|The solution is)\s*(.*?)$/is
        ];
        
        // Try to extract the final answer with each pattern
        for (const pattern of answerPatterns) {
          const match = fullText.match(pattern);
          if (match && match[1]) {
            finalAnswer = match[1].trim();
            reasoningSteps = fullText.substring(0, fullText.indexOf(match[0])).trim();
            break;
          }
        }
        
        // If no pattern matched, just use the last sentence
        if (!finalAnswer) {
          const sentences = fullText.split(/[.!?]+\s+/);
          if (sentences.length > 1) {
            finalAnswer = sentences.pop().trim();
            reasoningSteps = sentences.join('. ') + '.';
          }
        }
        
        // Apply format enforcement if needed
        if (enforce_format && selectedApproach === 'CoD') {
          reasoningSteps = formatEnforcer.enforceWordLimit(reasoningSteps, wordLimit);
        }
        
        // Calculate execution time
        const executionTime = Date.now() - startTime;
        
        // Estimate token count (rough approximation)
        const tokenCount = Math.ceil(fullText.length / 4);
        
        // Record analytics
        analyticsDb.addRecord({
          problem_id: problem.substring(0, 20),
          problem_text: problem,
          domain,
          approach: selectedApproach,
          word_limit: wordLimit,
          tokens_used: tokenCount,
          execution_time_ms: executionTime,
          reasoning_steps: reasoningSteps,
          answer: finalAnswer
        });
        
        // Return result
        return {
          approach: selectedApproach,
          reasoning_steps: reasoningSteps,
          final_answer: finalAnswer,
          token_count: tokenCount,
          word_limit: wordLimit,
          complexity: complexity,
          execution_time_ms: executionTime
        };
      }
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden. It mentions 'Chain of Draft approach' but doesn't disclose behavioral traits such as how it handles reasoning steps, output format, error conditions, or computational requirements. For a tool with 6 parameters and no output schema, this lack of detail is a significant gap in transparency.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, efficient sentence that directly states the tool's purpose. It's appropriately sized and front-loaded, with no wasted words. However, it could be more structured by briefly hinting at key parameters or outcomes to improve clarity without adding bulk.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (6 parameters, no annotations, no output schema), the description is incomplete. It doesn't explain what 'Chain of Draft' means, how the output is structured, or provide context for parameter usage. Without this, an AI agent might struggle to invoke the tool correctly or interpret results, especially compared to more specific siblings like 'math_solve'.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema documents all parameters thoroughly. The description adds no meaning beyond the schema, as it doesn't explain parameter interactions (e.g., how 'max_words_per_step' relates to 'adaptive_word_limit') or provide examples. Baseline score of 3 is appropriate since the schema does the heavy lifting, but the description doesn't compensate with additional insights.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose3/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states the tool 'Solve[s] a reasoning problem using Chain of Draft approach', which provides a verb ('solve') and resource ('reasoning problem'), but it's vague about what 'Chain of Draft' entails compared to alternatives like Chain of Thought (CoT). It doesn't distinguish from siblings like 'math_solve' or 'logic_solve', leaving ambiguity about when to use this over those specific tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No explicit guidance on when to use this tool versus alternatives is provided. The description mentions 'Chain of Draft approach' but doesn't explain its advantages over CoT or when to choose it over sibling tools like 'code_solve' or 'analyze_problem_complexity'. Usage is implied by the tool name and approach, but no clear context or exclusions are stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/stat-guy/chain-of-draft'

If you have feedback or need assistance with the MCP directory API, please join our Discord server