Skip to main content
Glama

sync_code_to_docs

Automatically synchronize documentation with code changes using AST-based drift detection to maintain accuracy between source code and documentation.

Instructions

Automatically synchronize documentation with code changes using AST-based drift detection (Phase 3)

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
projectPathYesPath to the project root directory
docsPathYesPath to the documentation directory
modeNoSync mode: detect=analyze only, preview=show changes, apply=apply safe changes, auto=apply alldetect
autoApplyThresholdNoConfidence threshold (0-1) for automatic application of changes
createSnapshotNoCreate a snapshot before making changes (recommended)

Implementation Reference

  • Main handler function that executes the sync_code_to_docs tool logic: parses input, detects drift between code and docs, applies changes based on mode, computes stats, and returns structured results.
    export async function handleSyncCodeToDocs(
      args: unknown,
      context?: any,
    ): Promise<{ content: any[] }> {
      const startTime = Date.now();
    
      try {
        const { projectPath, docsPath, mode, autoApplyThreshold, createSnapshot } =
          inputSchema.parse(args);
    
        await context?.info?.(
          `🔄 Starting code-to-documentation synchronization (mode: ${mode})...`,
        );
    
        // Initialize drift detector
        const detector = new DriftDetector(projectPath);
        await detector.initialize();
    
        // Create baseline snapshot if requested
        if (createSnapshot || mode !== "detect") {
          await context?.info?.("📸 Creating code snapshot...");
          await detector.createSnapshot(projectPath, docsPath);
        }
    
        // Load previous snapshot for comparison
        await context?.info?.("🔍 Detecting documentation drift...");
        const previousSnapshot = await detector.loadLatestSnapshot();
    
        if (!previousSnapshot) {
          await context?.info?.(
            "â„šī¸ No previous snapshot found. Creating baseline...",
          );
          const baselineSnapshot = await detector.createSnapshot(
            projectPath,
            docsPath,
          );
    
          const result: SyncResult = {
            mode,
            driftDetections: [],
            appliedChanges: [],
            pendingChanges: [],
            stats: {
              filesAnalyzed: baselineSnapshot.files.size,
              driftsDetected: 0,
              changesApplied: 0,
              changesPending: 0,
              breakingChanges: 0,
              estimatedUpdateTime: "0 minutes",
            },
            snapshotId: baselineSnapshot.timestamp,
          };
    
          const response: MCPToolResponse<typeof result> = {
            success: true,
            data: result,
            metadata: {
              toolVersion: "3.0.0",
              executionTime: Date.now() - startTime,
              timestamp: new Date().toISOString(),
            },
            recommendations: [
              {
                type: "info",
                title: "Baseline Created",
                description:
                  "Baseline snapshot created. Run sync again after code changes to detect drift.",
              },
            ],
          };
    
          return formatMCPResponse(response, { fullResponse: true });
        }
    
        // Create current snapshot and detect drift
        const currentSnapshot = await detector.createSnapshot(
          projectPath,
          docsPath,
        );
        const driftResults = await detector.detectDrift(
          previousSnapshot,
          currentSnapshot,
        );
    
        await context?.info?.(
          `📊 Found ${driftResults.length} file(s) with documentation drift`,
        );
    
        // Process based on mode
        const appliedChanges: AppliedChange[] = [];
        const pendingChanges: PendingSuggestion[] = [];
    
        for (const driftResult of driftResults) {
          if (driftResult.hasDrift) {
            for (const suggestion of driftResult.suggestions) {
              if (mode === "apply" || mode === "auto") {
                // Apply changes based on confidence
                const shouldApply =
                  mode === "auto" ||
                  (suggestion.autoApplicable &&
                    suggestion.confidence >= autoApplyThreshold);
    
                if (shouldApply) {
                  try {
                    await applyDocumentationChange(
                      suggestion,
                      context,
                      projectPath,
                    );
                    appliedChanges.push({
                      docFile: suggestion.docFile,
                      section: suggestion.section,
                      changeType: "updated",
                      confidence: suggestion.confidence,
                      details: suggestion.reasoning,
                    });
                  } catch (error: any) {
                    await context?.warn?.(
                      `Failed to apply change to ${suggestion.docFile}: ${error.message}`,
                    );
                    pendingChanges.push({
                      docFile: suggestion.docFile,
                      section: suggestion.section,
                      reason: `Auto-apply failed: ${error.message}`,
                      suggestion,
                      requiresReview: true,
                    });
                  }
                } else {
                  pendingChanges.push({
                    docFile: suggestion.docFile,
                    section: suggestion.section,
                    reason: "Requires manual review",
                    suggestion,
                    requiresReview: true,
                  });
                }
              } else {
                // Preview/detect mode - just collect suggestions
                pendingChanges.push({
                  docFile: suggestion.docFile,
                  section: suggestion.section,
                  reason: "Detected drift",
                  suggestion,
                  requiresReview: !suggestion.autoApplicable,
                });
              }
            }
          }
        }
    
        // Calculate stats
        const stats = calculateSyncStats(
          driftResults,
          appliedChanges,
          pendingChanges,
        );
    
        // Store sync results in knowledge graph
        await storeSyncResults(projectPath, driftResults, appliedChanges, context);
    
        const result: SyncResult = {
          mode,
          driftDetections: driftResults,
          appliedChanges,
          pendingChanges,
          stats,
          snapshotId: currentSnapshot.timestamp,
        };
    
        const response: MCPToolResponse<typeof result> = {
          success: true,
          data: result,
          metadata: {
            toolVersion: "3.0.0",
            executionTime: Date.now() - startTime,
            timestamp: new Date().toISOString(),
          },
          recommendations: generateRecommendations(result),
          nextSteps: generateNextSteps(result),
        };
    
        await context?.info?.(
          `✅ Synchronization complete: ${appliedChanges.length} applied, ${pendingChanges.length} pending`,
        );
    
        return formatMCPResponse(response, { fullResponse: true });
      } catch (error: any) {
        const errorResponse: MCPToolResponse = {
          success: false,
          error: {
            code: "SYNC_FAILED",
            message: `Documentation synchronization failed: ${error.message}`,
            resolution: "Check project and documentation paths are correct",
          },
          metadata: {
            toolVersion: "3.0.0",
            executionTime: Date.now() - startTime,
            timestamp: new Date().toISOString(),
          },
        };
    
        return formatMCPResponse(errorResponse, { fullResponse: true });
      }
    }
  • MCP Tool registration defining the 'sync_code_to_docs' tool with name, description, and detailed input schema.
    export const syncCodeToDocs: Tool = {
      name: "sync_code_to_docs",
      description:
        "Automatically synchronize documentation with code changes using AST-based drift detection (Phase 3)",
      inputSchema: {
        type: "object",
        properties: {
          projectPath: {
            type: "string",
            description: "Path to the project root directory",
          },
          docsPath: {
            type: "string",
            description: "Path to the documentation directory",
          },
          mode: {
            type: "string",
            enum: ["detect", "preview", "apply", "auto"],
            default: "detect",
            description:
              "Sync mode: detect=analyze only, preview=show changes, apply=apply safe changes, auto=apply all",
          },
          autoApplyThreshold: {
            type: "number",
            minimum: 0,
            maximum: 1,
            default: 0.8,
            description:
              "Confidence threshold (0-1) for automatic application of changes",
          },
          createSnapshot: {
            type: "boolean",
            default: true,
            description: "Create a snapshot before making changes (recommended)",
          },
        },
        required: ["projectPath", "docsPath"],
      },
    };
  • Zod input validation schema used within the handler to parse and validate tool arguments.
    const inputSchema = z.object({
      projectPath: z.string().describe("Path to the project root"),
      docsPath: z.string().describe("Path to the documentation directory"),
      mode: z
        .enum(["detect", "preview", "apply", "auto"])
        .default("detect")
        .describe(
          "Mode: detect=analyze only, preview=show changes, apply=apply safe changes, auto=apply all changes",
        ),
      autoApplyThreshold: z
        .number()
        .min(0)
        .max(1)
        .default(0.8)
        .describe("Confidence threshold for automatic application (0-1)"),
      createSnapshot: z
        .boolean()
        .default(true)
        .describe("Create a snapshot before making changes"),
    });
  • Helper function to apply a specific documentation change: updates file content and metadata.
    async function applyDocumentationChange(
      suggestion: DriftSuggestion,
      context?: any,
      projectPath?: string,
    ): Promise<void> {
      const filePath = suggestion.docFile;
    
      // Read current file
      const content = await fs.readFile(filePath, "utf-8");
    
      // Find and replace the section
      const sectionPattern = new RegExp(
        `(#{1,6}\\s+${escapeRegex(suggestion.section)}[\\s\\S]*?)(?=#{1,6}\\s+|$)`,
        "g",
      );
    
      let newContent = content;
      const match = sectionPattern.exec(content);
    
      if (match) {
        // Replace existing section
        newContent = content.replace(sectionPattern, suggestion.suggestedContent);
        await context?.info?.(
          `âœī¸ Updated section '${suggestion.section}' in ${path.basename(
            filePath,
          )}`,
        );
      } else {
        // Append new section
        newContent = content + "\n\n" + suggestion.suggestedContent;
        await context?.info?.(
          `➕ Added section '${suggestion.section}' to ${path.basename(filePath)}`,
        );
      }
    
      // Write back to file
      await fs.writeFile(filePath, newContent, "utf-8");
    
      // Update freshness metadata
      try {
        let currentCommit: string | undefined;
        if (projectPath) {
          try {
            const git = simpleGit(projectPath);
            const isRepo = await git.checkIsRepo();
            if (isRepo) {
              const log = await git.log({ maxCount: 1 });
              currentCommit = log.latest?.hash;
            }
          } catch {
            // Git not available, continue without it
          }
        }
    
        await updateDocFrontmatter(filePath, {
          last_updated: new Date().toISOString(),
          last_validated: new Date().toISOString(),
          auto_updated: true,
          validated_against_commit: currentCommit,
        });
    
        await context?.info?.(
          `đŸˇī¸ Updated freshness metadata for ${path.basename(filePath)}`,
        );
      } catch (error) {
        // Non-critical error, just log it
        await context?.warn?.(`Failed to update freshness metadata: ${error}`);
      }
    }
Behavior2/5

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

With no annotations provided, the description carries the full burden of behavioral disclosure. While it mentions 'AST-based drift detection' and 'Phase 3', it doesn't explain what changes are made, what 'safe changes' means, whether this is a read-only or destructive operation, or what permissions might be required. The description is insufficient for understanding the tool's behavior.

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 communicates the core functionality. However, the parenthetical '(Phase 3)' adds ambiguity without explanation, slightly reducing clarity. Overall, it's appropriately concise with minimal waste.

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?

For a tool with 5 parameters, no annotations, and no output schema, the description is incomplete. It doesn't explain what the tool returns, what 'AST-based drift detection' entails, what 'Phase 3' refers to, or the implications of different sync modes. The description leaves too many behavioral questions unanswered.

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?

With 100% schema description coverage, the input schema already documents all 5 parameters thoroughly. The description adds no additional parameter information beyond what's in the schema, so it meets the baseline of 3 where the schema does the heavy lifting.

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

Purpose4/5

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

The description clearly states the tool's purpose: 'Automatically synchronize documentation with code changes using AST-based drift detection'. It specifies the verb ('synchronize'), resource ('documentation'), and method ('AST-based drift detection'), but doesn't explicitly distinguish it from sibling tools like 'update_existing_documentation' or 'track_documentation_freshness'.

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?

The description provides no guidance on when to use this tool versus alternatives. It mentions 'Phase 3' which might imply a workflow context, but doesn't explain what this means or when this tool is appropriate compared to other documentation-related tools in the sibling list.

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/tosin2013/documcp'

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