Skip to content

Conversation

@bhauman
Copy link
Owner

@bhauman bhauman commented Jan 7, 2026

Summary

  • Adds new paren_repair MCP tool that fixes unbalanced parentheses, brackets, and braces in Clojure files
  • Uses parinfer's indent mode for repair
  • Optionally formats with cljfmt based on config setting
  • Returns status message with unified diff of changes
  • Validates file paths using existing valid-paths utility

Files

  • src/clojure_mcp/tools/paren_repair/core.clj - Core repair logic
  • src/clojure_mcp/tools/paren_repair/tool.clj - MCP tool definition
  • src/clojure_mcp/tools.clj - Registered the new tool

Example Output

File: /path/to/file.clj
Status: Fixed [delimiter-fixed, formatted]

--- original.txt
+++ revised.txt
@@ -1,3 +1,3 @@
 (defn my-fn [x]
-  (str/upper-case x)   ;; missing paren
+  (str/upper-case x))

Summary by CodeRabbit

  • New Features
    • Adds a parenthesis/delimiter repair tool that detects and fixes mismatched brackets in Clojure files, produces a unified diff of changes, and can optionally format code after repair.
    • Exposes the tool through the app's tools system so it appears alongside existing editing tools and can be invoked like other file-editing utilities.

✏️ Tip: You can customize this high-level summary in your review settings.

- New tool that detects and fixes unbalanced parentheses, brackets, and braces
- Uses parinfer indent mode for repair
- Optionally formats with cljfmt based on config setting
- Returns status message with unified diff of changes
- Validates file paths using existing valid-paths utility
@coderabbitai
Copy link

coderabbitai bot commented Jan 7, 2026

📝 Walkthrough

Walkthrough

Adds a new parenthesis-repair tool: a registry entry in tools.clj, a core module that detects/repairs delimiters and optionally formats files, and a tool-system adapter exposing the tool for MCP invocation.

Changes

Cohort / File(s) Summary
Tool Registration
src/clojure_mcp/tools.clj
Appended 'clojure-mcp.tools.paren-repair.tool/paren-repair-tool to editing-tool-syms, registering the new tool.
Repair Core Logic
src/clojure_mcp/tools/paren_repair/core.clj
New namespace implementing delimiter detection and repair (repair-file!), Clojure-extension predicate, optional cljfmt formatting, UTF-8 safe read/write, unified diff generation, and structured result maps including error handling.
Tool System Integration
src/clojure_mcp/tools/paren_repair/tool.clj
New namespace providing factory create-paren-repair-tool, paren-repair-tool registration, and tool-system multimethods for name, description, schema, input validation, execution (delegates to core), and result formatting.

Sequence Diagram

sequenceDiagram
    autonumber
    actor User
    participant ToolSys as Tool System
    participant Repair as Paren Repair Core
    participant Delim as Delimiter Detector
    participant Parinfer as Parinfer Repair
    participant Format as Formatter
    participant FileUtil as File Utility
    participant Diff as Diff Utility

    User->>ToolSys: invoke paren-repair-tool (file_path)
    ToolSys->>ToolSys: validate inputs & normalize path
    ToolSys->>Repair: repair-file!(file-path, nrepl-map)

    Repair->>FileUtil: read file (UTF-8)
    FileUtil-->>Repair: original content

    Repair->>Delim: detect delimiter errors
    Delim-->>Repair: errors? (yes/no)

    alt Errors detected
        Repair->>Parinfer: parinfer-repair(content)
        Parinfer-->>Repair: repaired content
    end

    alt Formatting enabled
        Repair->>Format: format-code(content, project-options)
        Format-->>Repair: formatted content
    end

    alt Content changed
        Repair->>FileUtil: write file (UTF-8)
        FileUtil-->>Repair: write complete
    end

    Repair->>Diff: generate unified diff(original, final)
    Diff-->>Repair: diff text

    Repair-->>ToolSys: result map {success, status, delim-fixed?, formatting?, diff}
    ToolSys-->>User: formatted response (status + diff)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐇 I nudge the parens awake,
I hop through lines that sometimes break,
Parinfer twitches, mends the thread,
I tidy code before bed—
Diff petals fall, repaired and bright.

Pre-merge checks

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Add paren_repair MCP tool for fixing delimiter errors' accurately and specifically describes the main change: introducing a new MCP tool for repairing delimiter errors in Clojure files.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (3)
src/clojure_mcp/tools/paren_repair/core.clj (1)

114-120: Minor edge case in status message.

If delimiter/delimiter-error? returns true but parinfer-repair produces identical content (unlikely but theoretically possible), the message "No changes needed (no delimiter errors)" would be slightly misleading. Consider a more generic message like "No changes needed" if this edge case matters.

src/clojure_mcp/tools/paren_repair/tool.clj (2)

20-32: Consider documenting the optional cljfmt formatting in the description.

The core/repair-file! function also applies cljfmt formatting when enabled in config, but the tool description only mentions parinfer repair. Users may be surprised to see formatting changes in the diff output. Based on learnings, the :description should provide clear guidance for LLM usage.

🔎 Suggested description update
 (defmethod tool-system/tool-description :paren-repair [_]
   "Fix delimiter errors (unbalanced parentheses, brackets, braces) in a Clojure file using parinfer.

 Use this tool when:
 - A file has unbalanced delimiters causing parse errors
 - You need to repair a file after an incomplete edit
 - The file won't compile due to missing closing parens/brackets

 The tool will:
 1. Detect delimiter errors using edamame parser
 2. Repair using parinfer's indent mode
+3. Optionally format with cljfmt if enabled in project config

 Returns a status message and diff showing what changed.")

61-68: Minor: Misleading comment.

The comment "Backward compatibility function" appears copied from another tool. Since this is a new tool, consider updating to just describe that it returns the registration map.

🔎 Suggested comment update
-;; Backward compatibility function that returns the registration map
+;; Public API function that returns the registration map
 (defn paren-repair-tool
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c0fed9d and 4569610.

📒 Files selected for processing (3)
  • src/clojure_mcp/tools.clj
  • src/clojure_mcp/tools/paren_repair/core.clj
  • src/clojure_mcp/tools/paren_repair/tool.clj
🧰 Additional context used
📓 Path-based instructions (1)
**/*.clj

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.clj: Use :require with ns aliases in Clojure imports (e.g., [clojure.string :as string])
Use kebab-case for variable and function names in Clojure
End Clojure predicate functions with ? (e.g., is-top-level-form?)
Use try/catch with specific exception handling in Clojure; use atom for tracking errors
Use 2-space indentation in Clojure code and maintain whitespace in edited forms
Align Clojure namespaces with directory structure (e.g., clojure-mcp.repl-tools)
Include clear tool :description in MCP tools for LLM guidance
Validate inputs and provide helpful error messages in MCP tool implementations
Return structured data with both result and error status in MCP tool responses
Maintain atom-based state for consistent service access in MCP tool implementations

Files:

  • src/clojure_mcp/tools/paren_repair/tool.clj
  • src/clojure_mcp/tools.clj
  • src/clojure_mcp/tools/paren_repair/core.clj
🧠 Learnings (7)
📓 Common learnings
Learnt from: CR
Repo: bhauman/clojure-mcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-02T16:18:02.404Z
Learning: Applies to **/*.clj : Include clear tool `:description` in MCP tools for LLM guidance
Learnt from: CR
Repo: bhauman/clojure-mcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-02T16:18:02.404Z
Learning: Applies to **/*.clj : Validate inputs and provide helpful error messages in MCP tool implementations
Learnt from: CR
Repo: bhauman/clojure-mcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-02T16:18:02.404Z
Learning: Applies to **/*.clj : Align Clojure namespaces with directory structure (e.g., `clojure-mcp.repl-tools`)
Learnt from: CR
Repo: bhauman/clojure-mcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-02T16:18:02.404Z
Learning: Applies to **/*.clj : Return structured data with both result and error status in MCP tool responses
📚 Learning: 2026-01-02T16:18:02.404Z
Learnt from: CR
Repo: bhauman/clojure-mcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-02T16:18:02.404Z
Learning: Applies to **/*.clj : Include clear tool `:description` in MCP tools for LLM guidance

Applied to files:

  • src/clojure_mcp/tools/paren_repair/tool.clj
  • src/clojure_mcp/tools.clj
  • src/clojure_mcp/tools/paren_repair/core.clj
📚 Learning: 2026-01-02T16:18:02.404Z
Learnt from: CR
Repo: bhauman/clojure-mcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-02T16:18:02.404Z
Learning: Applies to **/*.clj : Align Clojure namespaces with directory structure (e.g., `clojure-mcp.repl-tools`)

Applied to files:

  • src/clojure_mcp/tools/paren_repair/tool.clj
  • src/clojure_mcp/tools.clj
  • src/clojure_mcp/tools/paren_repair/core.clj
📚 Learning: 2026-01-02T16:18:02.404Z
Learnt from: CR
Repo: bhauman/clojure-mcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-02T16:18:02.404Z
Learning: Applies to **/*.clj : Validate inputs and provide helpful error messages in MCP tool implementations

Applied to files:

  • src/clojure_mcp/tools/paren_repair/tool.clj
  • src/clojure_mcp/tools/paren_repair/core.clj
📚 Learning: 2026-01-02T16:18:02.404Z
Learnt from: CR
Repo: bhauman/clojure-mcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-02T16:18:02.404Z
Learning: Applies to **/*.clj : Maintain atom-based state for consistent service access in MCP tool implementations

Applied to files:

  • src/clojure_mcp/tools/paren_repair/tool.clj
  • src/clojure_mcp/tools.clj
📚 Learning: 2026-01-02T16:18:02.404Z
Learnt from: CR
Repo: bhauman/clojure-mcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-02T16:18:02.404Z
Learning: Applies to **/*.clj : Return structured data with both result and error status in MCP tool responses

Applied to files:

  • src/clojure_mcp/tools/paren_repair/tool.clj
  • src/clojure_mcp/tools/paren_repair/core.clj
📚 Learning: 2025-12-27T06:54:07.157Z
Learnt from: nandoolle
Repo: bhauman/clojure-mcp PR: 138
File: src/clojure_mcp/agent/langchain/model.clj:91-97
Timestamp: 2025-12-27T06:54:07.157Z
Learning: When reviewing Clojure code (e.g., in src/clojure_mcp/... ), verify calls to presets/get-preset follow the two arities: [preset-key] and [preset-key overrides]. The 2-arg version should merge the provided overrides map with the preset defaults and return the resulting configuration. Check for correct map merging, preservation of immutability, and validation of overrides keys to ensure predictable configuration outcomes.

Applied to files:

  • src/clojure_mcp/tools/paren_repair/tool.clj
  • src/clojure_mcp/tools.clj
  • src/clojure_mcp/tools/paren_repair/core.clj
🔇 Additional comments (10)
src/clojure_mcp/tools/paren_repair/core.clj (4)

1-11: LGTM!

Namespace aligns with directory structure and imports use :as aliases per coding guidelines.


13-21: LGTM!

The predicate function follows naming conventions with ? suffix. Using a set for extensions and some for matching is idiomatic.


59-96: Well-structured repair logic with good defensive programming.

The sequential repair steps (delimiter fix → format) with proper fallbacks on formatting failure is resilient. The structured return values align with MCP tool response guidelines.


122-136: LGTM!

Good separation of ExceptionInfo (for controlled errors with ex-info) vs general Exception handling. Both paths return structured error maps per MCP tool guidelines.

src/clojure_mcp/tools.clj (1)

25-26: LGTM!

The paren-repair-tool is appropriately placed in editing-tool-syms since it modifies files. The symbol path correctly references the new tool namespace.

src/clojure_mcp/tools/paren_repair/tool.clj (5)

1-15: LGTM!

Namespace correctly aligns with directory structure. The tool configuration stores the nrepl-client-atom for consistent state access per guidelines.


34-38: LGTM!

Schema is well-defined with clear property description including supported file extensions.


40-48: LGTM!

Input validation follows guidelines with clear error messages. Path validation delegates to the existing utility function. The transformation from file_path (JSON convention) to file-path (Clojure convention) is appropriate.


50-51: LGTM!

Clean delegation to core logic.


53-59: LGTM!

Result formatting follows MCP tool response guidelines, returning structured data with both result and error status.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
src/clojure_mcp/tools/paren_repair/tool.clj (1)

57-64: Consider clarifying "backward compatibility" wording.

The comment describes this as a "backward compatibility function," but it appears to be the primary public entry point for registering the tool. Unless there's a newer registration approach this is maintaining compatibility with, consider rewording to something like "Public function that returns the registration map for the paren-repair tool" to avoid confusion.

🔎 Suggested docstring clarification
-(defn paren-repair-tool
-  "Returns the registration map for the paren-repair tool.
+;; Public API for registering the tool
+(defn paren-repair-tool
+  "Returns the registration map for the paren-repair tool.
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4569610 and 4e3b57c.

📒 Files selected for processing (1)
  • src/clojure_mcp/tools/paren_repair/tool.clj
🧰 Additional context used
📓 Path-based instructions (1)
**/*.clj

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.clj: Use :require with ns aliases in Clojure imports (e.g., [clojure.string :as string])
Use kebab-case for variable and function names in Clojure
End Clojure predicate functions with ? (e.g., is-top-level-form?)
Use try/catch with specific exception handling in Clojure; use atom for tracking errors
Use 2-space indentation in Clojure code and maintain whitespace in edited forms
Align Clojure namespaces with directory structure (e.g., clojure-mcp.repl-tools)
Include clear tool :description in MCP tools for LLM guidance
Validate inputs and provide helpful error messages in MCP tool implementations
Return structured data with both result and error status in MCP tool responses
Maintain atom-based state for consistent service access in MCP tool implementations

Files:

  • src/clojure_mcp/tools/paren_repair/tool.clj
🧠 Learnings (7)
📓 Common learnings
Learnt from: CR
Repo: bhauman/clojure-mcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-02T16:18:02.404Z
Learning: Applies to **/*.clj : Include clear tool `:description` in MCP tools for LLM guidance
Learnt from: CR
Repo: bhauman/clojure-mcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-02T16:18:02.404Z
Learning: Applies to **/*.clj : Validate inputs and provide helpful error messages in MCP tool implementations
Learnt from: CR
Repo: bhauman/clojure-mcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-02T16:18:02.404Z
Learning: Applies to **/*.clj : Align Clojure namespaces with directory structure (e.g., `clojure-mcp.repl-tools`)
Learnt from: CR
Repo: bhauman/clojure-mcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-02T16:18:02.404Z
Learning: Applies to **/*.clj : Return structured data with both result and error status in MCP tool responses
📚 Learning: 2026-01-02T16:18:02.404Z
Learnt from: CR
Repo: bhauman/clojure-mcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-02T16:18:02.404Z
Learning: Applies to **/*.clj : Include clear tool `:description` in MCP tools for LLM guidance

Applied to files:

  • src/clojure_mcp/tools/paren_repair/tool.clj
📚 Learning: 2026-01-02T16:18:02.404Z
Learnt from: CR
Repo: bhauman/clojure-mcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-02T16:18:02.404Z
Learning: Applies to **/*.clj : Align Clojure namespaces with directory structure (e.g., `clojure-mcp.repl-tools`)

Applied to files:

  • src/clojure_mcp/tools/paren_repair/tool.clj
📚 Learning: 2026-01-02T16:18:02.404Z
Learnt from: CR
Repo: bhauman/clojure-mcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-02T16:18:02.404Z
Learning: Applies to **/*.clj : Validate inputs and provide helpful error messages in MCP tool implementations

Applied to files:

  • src/clojure_mcp/tools/paren_repair/tool.clj
📚 Learning: 2026-01-02T16:18:02.404Z
Learnt from: CR
Repo: bhauman/clojure-mcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-02T16:18:02.404Z
Learning: Applies to **/*.clj : Maintain atom-based state for consistent service access in MCP tool implementations

Applied to files:

  • src/clojure_mcp/tools/paren_repair/tool.clj
📚 Learning: 2026-01-02T16:18:02.404Z
Learnt from: CR
Repo: bhauman/clojure-mcp PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-02T16:18:02.404Z
Learning: Applies to **/*.clj : Return structured data with both result and error status in MCP tool responses

Applied to files:

  • src/clojure_mcp/tools/paren_repair/tool.clj
📚 Learning: 2025-12-27T06:54:07.157Z
Learnt from: nandoolle
Repo: bhauman/clojure-mcp PR: 138
File: src/clojure_mcp/agent/langchain/model.clj:91-97
Timestamp: 2025-12-27T06:54:07.157Z
Learning: When reviewing Clojure code (e.g., in src/clojure_mcp/... ), verify calls to presets/get-preset follow the two arities: [preset-key] and [preset-key overrides]. The 2-arg version should merge the provided overrides map with the preset defaults and return the resulting configuration. Check for correct map merging, preservation of immutability, and validation of overrides keys to ensure predictable configuration outcomes.

Applied to files:

  • src/clojure_mcp/tools/paren_repair/tool.clj
🔇 Additional comments (3)
src/clojure_mcp/tools/paren_repair/tool.clj (3)

1-6: LGTM! Namespace and imports follow conventions.

The namespace correctly uses hyphens while the directory path uses underscores (standard Clojure convention), and all requires use aliases as per coding guidelines.


8-34: Excellent tool metadata! Clear description and schema.

The tool description provides helpful context about when to use the tool, and the schema clearly documents the required file_path parameter with supported file extensions. This follows the coding guideline to include clear tool descriptions for LLM guidance.


36-55: Update contract specification for core/repair-file!.

The validate-path-with-client contract is correctly specified. However, repair-file! returns a map with six fields, not four:

  • :success - boolean indicating overall success
  • :file-path - the processed file path
  • :message - human-readable status message
  • :delimiter-fixed - boolean (was delimiter error fixed?)
  • :formatted - boolean (was cljfmt applied?)
  • :diff - unified diff of changes (or nil)

The format-results implementation safely ignores the extra fields through destructuring, so the code works correctly, but the contract documentation should be complete.

Likely an incorrect or invalid review comment.

@bhauman bhauman merged commit 69fa31c into main Jan 20, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants