Skip to content

Conversation

@jmckitrick
Copy link
Contributor

@jmckitrick jmckitrick commented Oct 8, 2025

Summary by CodeRabbit

  • New Features
    • Added a built-in action to create and save custom prompts for reuse.
    • Allows specifying a prompt name and guidance; saves prompts to your configuration.
    • Now included in the default prompts list—available immediately without setup.
    • Streamlines creation and management of personalized prompts to speed workflows.

@coderabbitai
Copy link

coderabbitai bot commented Oct 8, 2025

Walkthrough

Adds a new public prompt var save-new-prompt whose prompt-fn returns user-facing guidance for creating or updating custom prompts and saving them under :prompts in .clojure-mcp/config.edn. The prompt is included in default-prompts. No other logic or error-flow changes.

Changes

Cohort / File(s) Summary
Prompt addition & registration
src/clojure_mcp/prompts.clj
Added public var save-new-prompt with a prompt-fn that constructs guidance for saving a custom prompt under :prompts in .clojure-mcp/config.edn. Registered save-new-prompt in the default-prompts list.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor U as User / Agent
  participant P as Prompts Module

  U->>P: Request "save-new-prompt"(prompt_name, prompt_text)
  activate P
  P->>P: Build user-facing guidance message (how to create/update and save under :prompts)
  P-->>U: Return guidance message
  deactivate P

  note over U: Persistence to config (e.g., writing to .clojure-mcp/config.edn) is performed by the caller/tool using the returned guidance, not by the Prompts Module.
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

I twitch my whiskers, nibble keys with care,
A prompt I plant inside the config lair.
Name and text in tidy tune,
Poked into EDN by light of moon.
Hoppity-hop — a new thought sown, ready to share.

Pre-merge checks and finishing touches

✅ 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 succinctly describes the addition of a new prompt for saving custom user prompts to the configuration file, directly reflecting the core change introduced by the pull request.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5f2dd01 and 794e580.

📒 Files selected for processing (1)
  • src/clojure_mcp/prompts.clj (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/clojure_mcp/prompts.clj

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: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 88c9baa and 5f2dd01.

📒 Files selected for processing (1)
  • src/clojure_mcp/prompts.clj (2 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
src/**/*.{clj,cljc}

📄 CodeRabbit inference engine (CLAUDE.md)

src/**/*.{clj,cljc}: Use :require with ns aliases for imports (e.g., [clojure.string :as string])
Include clear tool :description for LLM guidance
Validate inputs and provide helpful error messages in MCP tools
Return structured data with both result and error status in MCP tools
Maintain atom-based state for consistent service access in MCP tools

Files:

  • src/clojure_mcp/prompts.clj
**/*.{clj,cljc}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{clj,cljc}: Use kebab-case for vars/functions; end predicates with ? (e.g., is-top-level-form?)
Use try/catch with specific exception handling; use atom for tracking errors
Use 2-space indentation and maintain whitespace in edited forms
Align namespaces with directory structure (e.g., clojure-mcp.repl-tools)

Files:

  • src/clojure_mcp/prompts.clj
🔇 Additional comments (1)
src/clojure_mcp/prompts.clj (1)

363-363: Addition to default-prompts is consistent with current implementation.

The addition of save-new-prompt to the prompts list is correct for the current implementation. However, if the prompt is refactored to accept nrepl-client-atom (as suggested in the previous comment), this line would need to be updated to (save-new-prompt nrepl-client-atom) to match the pattern used by other action prompts like add-dir and scratch-pad-load.

Comment on lines 283 to 303
(def save-new-prompt
{:name "save_new_prompt"
:description "Asks the user for a new prompt and a name, and saves them to their user config"
:arguments [{:name "prompt_name"
:description "Name for this prompt"
:required? true}
{:name "prompt_text"
:description "Text content for this prompt"
:required? true}]
:prompt-fn (fn [_ request-args clj-result-k]
(let [prompt-name (get request-args "prompt_name")
prompt-text (get request-args "prompt_text")]
(clj-result-k
{:description (str "Create prompt: " prompt-name)
:messages [{:role :user
:content (format
"Save %s in the `.clojure-mcp` project folder, in the `config.edn` file under the `:prompts` key using the STRING key %s, using the following format:
`:description` - \"Custom user-added prompt\"
`:content` - %s
"
prompt-name prompt-name prompt-text)}]})))})
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Critical: Prompt doesn't actually save; format mismatch with expected config structure.

The prompt has several critical issues:

  1. No actual save operation: The prompt-fn only constructs a user message instructing the LLM to manually edit config.edn, rather than programmatically persisting the data using config/set-config! (as seen in add-dir at line 172). This approach is unreliable and won't work consistently.

  2. Format mismatch: The format specified in the message (:description and :content) doesn't match the structure expected by create-prompt-from-config (lines 309-324), which requires :description, :args, and either :file-path or :content. This means even if the LLM follows the instructions, the saved prompt won't be usable.

  3. Misleading description: Line 285 claims this prompt "saves them to their user config", but it only requests the LLM to save, not performing the operation itself.

  4. No validation or error handling: Unlike other action prompts in this file (e.g., add-dir, scratch-pad-save-as), there's no input validation or try/catch blocks.

As per coding guidelines: "Validate inputs and provide helpful error messages in MCP tools" and "Use try/catch with specific exception handling".

Consider this approach instead:

-(def save-new-prompt
-  {:name "save_new_prompt"
-   :description "Asks the user for a new prompt and a name, and saves them to their user config"
-   :arguments [{:name "prompt_name"
-                :description "Name for this prompt"
-                :required? true}
-               {:name "prompt_text"
-                :description "Text content for this prompt"
-                :required? true}]
-   :prompt-fn (fn [_ request-args clj-result-k]
-                (let [prompt-name (get request-args "prompt_name")
-                      prompt-text (get request-args "prompt_text")]
-                  (clj-result-k
-                   {:description (str "Create prompt: " prompt-name)
-                    :messages [{:role :user
-                                :content (format
-                                          "Save %s in the `.clojure-mcp` project folder, in the `config.edn` file under the `:prompts` key using the STRING key %s, using the following format:
-`:description` - \"Custom user-added prompt\"
-`:content` - %s
-"
-                                          prompt-name prompt-name prompt-text)}]})))})
+(defn save-new-prompt [nrepl-client-atom]
+  {:name "ACT/save_new_prompt"
+   :description "Saves a new custom prompt to the user config"
+   :arguments [{:name "prompt_name"
+                :description "Name for this prompt (kebab-case recommended)"
+                :required? true}
+               {:name "prompt_text"
+                :description "Text content for this prompt"
+                :required? true}]
+   :prompt-fn (fn [_ request-args clj-result-k]
+                (let [prompt-name (get request-args "prompt_name")
+                      prompt-text (get request-args "prompt_text")]
+                  (if (or (str/blank? prompt-name) (str/blank? prompt-text))
+                    (clj-result-k
+                     {:description "Missing required arguments"
+                      :messages [{:role :assistant
+                                  :content "Error: Both prompt_name and prompt_text are required and cannot be blank."}]})
+                    (try
+                      (let [current-prompts (config/get-prompts @nrepl-client-atom)
+                            prompt-key (keyword prompt-name)
+                            new-prompt-config {:description "Custom user-added prompt"
+                                               :content prompt-text
+                                               :args []}
+                            updated-prompts (assoc current-prompts prompt-key new-prompt-config)]
+                        (config/set-config! nrepl-client-atom :prompts updated-prompts)
+                        (clj-result-k
+                         {:description (str "Saved prompt: " prompt-name)
+                          :messages [{:role :assistant
+                                      :content (format "Successfully saved custom prompt '%s' to config.edn under :prompts key.\n\nYou can now use this prompt with the name: %s"
+                                                       prompt-name
+                                                       prompt-name)}]}))
+                      (catch Exception e
+                        (clj-result-k
+                         {:description (str "Error saving prompt: " (.getMessage e))
+                          :messages [{:role :assistant
+                                      :content (format "Failed to save prompt '%s'.\nError: %s"
+                                                       prompt-name
+                                                       (.getMessage e))}]}))))))})

Then update line 363 to pass the atom:

-   save-new-prompt
+   (save-new-prompt nrepl-client-atom)

Would you like me to open an issue to track implementing actual save functionality with proper validation and error handling?

@jmckitrick
Copy link
Contributor Author

@bhauman New version pushed

@bhauman bhauman merged commit 6f9f696 into bhauman:main Oct 22, 2025
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