-
-
Notifications
You must be signed in to change notification settings - Fork 61
Config validation #104
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Config validation #104
Conversation
- Add metosin/malli dependency for data-driven schema validation - Create comprehensive config schemas in clojure-mcp.config.schema - Support all configuration options including models, agents, resources, prompts - Provide automatic spell-checking for typos in configuration keys - Include human-readable error messages with documentation references - Add comprehensive test suite for validation scenarios - Support environment variable references [:env "VAR_NAME"] - Validate nested structures like thinking config, agent config, etc. - Use closed map schema to detect unknown/misspelled keys
|
Caution Review failedThe pull request is closed. WalkthroughAdds a Malli-based configuration schema and validators, wires pre-merge validation into config loading with canonical paths and improved error reporting, updates docs and example agent tool IDs from hyphens to underscores, introduces :track-file-changes, removes an agent option, adds tests, adds malli dependency, and replaces clojure.spec model validation with the new schema. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant Startup as Startup
participant Core as core/fetch-config
participant Loader as config/load-config
participant Schema as config.schema
Note over Startup,Core: Startup requests configuration load
Startup->>Core: fetch-config
Core->>Loader: load-config-handling-validation-errors(home, project)
Loader->>Loader: build list [{:config <map> :file-path <canonical-path>} ...]
Loader->>Schema: validate-configs(list)
alt any invalid
Schema-->>Loader: explain-config errors
Loader-->>Core: throw ex-info ::schema-error with {:errors :model :config :file-path}
Core->>Startup: print validation report and rethrow/exit
else all valid
Schema-->>Loader: valid
Loader->>Loader: merge validated configs
Loader-->>Core: merged-config
Core->>Startup: continue startup with merged config
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related issues
Possibly related PRs
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (1)
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. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
🧹 Nitpick comments (7)
test/clojure_mcp/config/schema_test.clj (2)
44-47: Tool ID style in tests differs from docs (hyphens vs underscores).Docs migrated to underscore IDs; this test still uses hyphens. Consider updating for consistency or explicitly covering both forms.
- :enable-tools [:clojure-eval :read-file] + :enable-tools [:clojure_eval :read_file]Do example configs under resources/ also use underscores consistently?
137-142: Add tests for PromptEntry XOR rule once schema enforces it.Cover both “both provided” and “neither provided” cases.
+ (deftest prompt-content-xor-file-path-test + (testing "Both :content and :file-path should be invalid" + (let [config {:prompts {"p" {:description "d" :content "x" :file-path "p.mustache"}}}] + (is (some? (schema/explain-config config))))) + (testing "Neither :content nor :file-path should be invalid" + (let [config {:prompts {"p" {:description "d"}}}] + (is (some? (schema/explain-config config))))))Also applies to: 198-203
doc/configuring-agents.md (3)
76-85: Fix MD058: add blank lines around tables.Surround each table with a blank line to satisfy markdownlint.
-### Read-Only Tools -| Tool ID | Description | +### Read-Only Tools + +| Tool ID | Description | |---------|-------------| | `:LS` | Directory tree view | | `:read_file` | Read file contents with pattern matching | | `:grep` | Search file contents | | `:glob_files` | Find files by pattern | | `:think` | Reasoning tool | | `:clojure_inspect_project` | Project structure analysis | + -### Evaluation Tools -| Tool ID | Description | +### Evaluation Tools + +| Tool ID | Description | |---------|-------------| | `:clojure_eval` | Execute Clojure code in REPL | | `:bash` | Execute shell commands | -### File Editing Tools -| Tool ID | Description | + +### File Editing Tools + +| Tool ID | Description | |---------|-------------| | `:file_write` | Create or overwrite files | | `:file_edit` | Edit files by text replacement | | `:clojure_edit` | Structure-aware Clojure editing | | `:clojure_edit_replace_sexp` | S-expression replacement | -### Agent Tools -| Tool ID | Description | + +### Agent Tools + +| Tool ID | Description | |---------|-------------| | `:dispatch_agent` | Launch sub-agents | | `:architect` | Technical planning assistant | | `:scratch_pad` | Persistent data storage | | `:code_critique` | Code review feedback |Also applies to: 86-94, 94-101, 100-107
301-306: Tool ID typo: use underscore form.Use
clojure_inspect_projectto match the rest of the doc and examples.-- Current project structure from `clojure-inspect-project` +- Current project structure from `clojure_inspect_project`
510-514: Tighten guidance: explicitly call out underscore tool IDs.Small doc tweak to minimize confusion migrating from hyphens.
- - Check tool IDs match exactly (use underscores: `:read_file` not `:read-file`) + - Check tool IDs match exactly (underscore IDs): `:read_file` (not `:read-file`)src/clojure_mcp/core.clj (1)
262-267: Add info log after loading config; fix README doc linkAdd an info log after loading the config to record config-file and user-dir. Repo contains CONFIG.md at repo root, but README.md links to doc/CONFIG.md — update README or move CONFIG.md.
- (let [config (load-config-handling-validation-errors config-file user-dir) + (let [config (load-config-handling-validation-errors config-file user-dir) + _ (log/info "Loaded configuration" {:file config-file :user-dir user-dir}) final-env-type (or cli-env-type (if (contains? config :nrepl-env-type) (:nrepl-env-type config) env-type))] (assoc nrepl-client-map ::config/config (assoc config :nrepl-env-type final-env-type))))Found: CONFIG.md (repo root). References: README.md:1005 -> doc/CONFIG.md; src/clojure_mcp/core.clj prints "See CONFIG.md" (~line 250).
src/clojure_mcp/config.clj (1)
130-144: Pre-merge validation flow is correct; consider not swallowing EDN parse errors.Current load-config-file logs and returns {} on read/parse failure, which then skips validation here and silently ignores a broken file. Consider promoting read errors to an exception (with :type ::read-error and :file-path) so users aren’t surprised by ignored configs.
If you want, I can draft a minimal change to load-config-file that preserves existing happy-paths but throws on parse errors.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (8)
deps.edn(1 hunks)doc/configuring-agents.md(15 hunks)resources/clojure-mcp/agents/clojure_edit_agent.edn(0 hunks)resources/configs/example-agents.edn(3 hunks)src/clojure_mcp/config.clj(4 hunks)src/clojure_mcp/config/schema.clj(1 hunks)src/clojure_mcp/core.clj(1 hunks)test/clojure_mcp/config/schema_test.clj(1 hunks)
💤 Files with no reviewable changes (1)
- resources/clojure-mcp/agents/clojure_edit_agent.edn
🧰 Additional context used
📓 Path-based instructions (3)
src/**/*.{clj,cljc}
📄 CodeRabbit inference engine (CLAUDE.md)
src/**/*.{clj,cljc}: Use:requirewith ns aliases for imports (e.g.,[clojure.string :as string])
Include clear tool:descriptionfor 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/core.cljsrc/clojure_mcp/config/schema.cljsrc/clojure_mcp/config.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?)
Usetry/catchwith 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/core.cljsrc/clojure_mcp/config/schema.cljtest/clojure_mcp/config/schema_test.cljsrc/clojure_mcp/config.clj
test/**/*.{clj,cljc}
📄 CodeRabbit inference engine (CLAUDE.md)
Use
deftestwith descriptive names;testingfor subsections;isfor assertions in tests
Files:
test/clojure_mcp/config/schema_test.clj
🧠 Learnings (3)
📚 Learning: 2025-08-02T20:23:28.499Z
Learnt from: CR
PR: bhauman/clojure-mcp#0
File: CLAUDE.md:0-0
Timestamp: 2025-08-02T20:23:28.499Z
Learning: Applies to src/**/*.{clj,cljc} : Validate inputs and provide helpful error messages in MCP tools
Applied to files:
src/clojure_mcp/core.cljsrc/clojure_mcp/config/schema.cljtest/clojure_mcp/config/schema_test.cljsrc/clojure_mcp/config.clj
📚 Learning: 2025-08-02T20:23:28.499Z
Learnt from: CR
PR: bhauman/clojure-mcp#0
File: CLAUDE.md:0-0
Timestamp: 2025-08-02T20:23:28.499Z
Learning: Applies to src/**/*.{clj,cljc} : Return structured data with both result and error status in MCP tools
Applied to files:
src/clojure_mcp/config.clj
📚 Learning: 2025-08-02T20:23:28.499Z
Learnt from: CR
PR: bhauman/clojure-mcp#0
File: CLAUDE.md:0-0
Timestamp: 2025-08-02T20:23:28.499Z
Learning: Applies to src/**/*.{clj,cljc} : Include clear tool `:description` for LLM guidance
Applied to files:
doc/configuring-agents.md
🪛 markdownlint-cli2 (0.17.2)
doc/configuring-agents.md
87-87: Tables should be surrounded by blank lines
(MD058, blanks-around-tables)
93-93: Tables should be surrounded by blank lines
(MD058, blanks-around-tables)
101-101: Tables should be surrounded by blank lines
(MD058, blanks-around-tables)
🔇 Additional comments (10)
deps.edn (1)
11-13: Approve — metosin/malli 0.19.1 is current.
0.19.1 (released June 9, 2025) is the latest stable release — no changes required to deps.edn.src/clojure_mcp/config/schema.clj (1)
151-158: Align agent-level tool ID types with top-level config (keywords vs. strings)Top-level :enable-tools/:disable-tools accept keywords or strings; agent-level schema in src/clojure_mcp/config/schema.clj (lines ~151–158) only allows keywords — either loosen the agent schema to allow strings for parity or document that agent-level IDs must be keywords.
Suggested parity diff (apply if you want agent-level === top-level):
- [:enable-tools {:optional true - :description "Tools the agent can access: :all, specific list, or nil (no tools)"} - [:or [:= :all] [:sequential :keyword]]] + [:enable-tools {:optional true + :description "Tools the agent can access: :all, specific list, or nil (no tools)"} + [:or [:= :all] [:sequential [:or :keyword :string]]]] - [:disable-tools {:optional true - :description "Tools to exclude even if enabled (applied after enable-tools)"} - [:maybe [:sequential :keyword]]] + [:disable-tools {:optional true + :description "Tools to exclude even if enabled (applied after enable-tools)"} + [:maybe [:sequential [:or :keyword :string]]]]Would config/tool-id-enabled? and related filters accept string IDs at the agent level today?
src/clojure_mcp/config.clj (2)
6-6: Good: schema ns alias added and aligned with file layout.Namespace aliasing follows project conventions and matches src/clojure_mcp/config/schema.clj.
118-118: Docstring matches behavior.Now accurately states “Validates both configs before merging.”
resources/configs/example-agents.edn (6)
17-17: Underscored tool IDs: research-agent entry looks consistent.:enable-tools updated to [:grep :glob_files :read_file :clojure_inspect_project]. Matches new naming.
25-26: Underscored tool IDs: refactor_assistant entry is consistent.
33-35: Underscored tool IDs: test_explorer enable/disable lists are consistent.
42-42: Underscored tool IDs: doc_reader entry is consistent.
51-52: Underscored tool IDs: code_writer entry is consistent (long token preserved).
62-62: full-access-agent updated correctly — manual repo verification requiredrg returned "No files were searched" so I couldn't confirm absence of deprecated hyphenated tool IDs. Re-run locally:
# Search with ripgrep (wide search, ignore node_modules/target) rg -n --hidden --no-ignore -S -E 'read-file|glob-files|clojure-inspect-project|dispatch-agent' --glob '!*node_modules/**' --glob '!*target/**' || true # If rg still skips files, run with --debug: rg --debug -n --hidden --no-ignore -S -E 'read-file|glob-files|clojure-inspect-project|dispatch-agent' || true # Fallback using find+grep: find . \( -path './node_modules' -o -path './target' -o -path './.git' \) -prune -o -type f -print0 | xargs -0 -r grep -nE 'read-file|glob-files|clojure-inspect-project|dispatch-agent' || true
There was a problem hiding this 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
♻️ Duplicate comments (1)
src/clojure_mcp/config/schema.clj (1)
206-227: Resolved: enforce exactly one of :content or :file-path.The XOR check via [:and ... [:fn ...]] is correct and addresses prior feedback.
🧹 Nitpick comments (6)
src/clojure_mcp/config/schema.clj (6)
13-16: Disallow empty paths.Paths shouldn’t be empty strings. Recommend length check.
Apply:
-(def Path - "Schema for file system paths" - :string) +(def Path + "Schema for file system paths" + [:string {:min 1}])
17-21: Tighten EnvRef var name to be non-empty.Prevents [:env ""] footguns.
Apply:
(def EnvRef "Schema for environment variable references like [:env \"VAR_NAME\"]" [:tuple {:description "Environment variable reference"} [:= :env] - :string]) + [:string {:min 1}]])
40-41: Provider enum is missing :gemini.You expose a :gemini submap below; allow it in :provider too or clarify docs.
Apply:
- [:provider {:optional true} [:enum :openai :anthropic :google]] + [:provider {:optional true} [:enum :openai :anthropic :google :gemini]]
96-97: Constrain OpenAI logit-bias to common range.OpenAI typically enforces [-100, 100]. Bound the ints to reduce invalid configs.
Apply:
- [:logit-bias {:optional true} [:map-of :string :int]] + [:logit-bias {:optional true} [:map-of :string [:int {:min -100 :max 100}]]]If you’ve seen different limits recently, keep as-is and update the bounds accordingly.
143-146: Description mentions default but schema doesn’t set one.Either declare a default or drop “(default)” from the description.
Apply one:
Option A (add default):
- [:context {:optional true - :description "Context to provide: true (default), false (none), or file paths list"} + [:context {:optional true + :description "Context to provide: true (default), false (none), or file paths list" + :default true} [:or :boolean [:sequential :string]]]Option B (doc fix):
- [:context {:optional true - :description "Context to provide: true (default), false (none), or file paths list"} + [:context {:optional true + :description "Context to provide: true/false, or file paths list"} [:or :boolean [:sequential :string]]]
162-164: Set default true for :track-file-changes or adjust wording.Doc says “(default: true)” but schema has no default.
Apply:
- [:track-file-changes {:optional true - :description "Whether to track and display file diffs (default: true)"} + [:track-file-changes {:optional true + :description "Whether to track and display file diffs (default: true)" + :default true} :boolean]
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
src/clojure_mcp/config.clj(4 hunks)src/clojure_mcp/config/schema.clj(1 hunks)src/clojure_mcp/core.clj(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- src/clojure_mcp/config.clj
- src/clojure_mcp/core.clj
🧰 Additional context used
📓 Path-based instructions (2)
src/**/*.{clj,cljc}
📄 CodeRabbit inference engine (CLAUDE.md)
src/**/*.{clj,cljc}: Use:requirewith ns aliases for imports (e.g.,[clojure.string :as string])
Include clear tool:descriptionfor 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/config/schema.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?)
Usetry/catchwith 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/config/schema.clj
🧠 Learnings (1)
📚 Learning: 2025-08-02T20:23:28.499Z
Learnt from: CR
PR: bhauman/clojure-mcp#0
File: CLAUDE.md:0-0
Timestamp: 2025-08-02T20:23:28.499Z
Learning: Applies to src/**/*.{clj,cljc} : Validate inputs and provide helpful error messages in MCP tools
Applied to files:
src/clojure_mcp/config/schema.clj
🔇 Additional comments (4)
src/clojure_mcp/config/schema.clj (4)
1-7: Good namespace and aliases.Uses :require with aliases per guidelines; concise docstring.
281-289: Nice humanized error reporting with spell-checking.Good UX for config authors.
299-311: Schema introspection helpers look good.Handy for docs; no issues spotted.
233-276: Approve: top-level Config keys look good; no stale coerce-config referencesClosed map and types are sensible; provider/tool filters consistent. ripgrep found no matches for
coerce-configand no occurrences of:provider :gemini— “gemini” only appears in model names, tests, and provider-specific handlers (e.g. src/clojure_mcp/config/schema.clj, src/clojure_mcp/agent/langchain.clj, src/clojure_mcp/agent/langchain/model.clj).
There was a problem hiding this 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 (10)
src/clojure_mcp/config/schema.clj (10)
11-15: Defaulting validate-env-vars to true is surprising; default to falsePrevents configs with env refs from failing in dev/CI unless explicitly enabled.
Apply:
-(def ^:dynamic *validate-env-vars* - "When true, validates that environment variables actually exist and aren't blank. - Can be bound to false for testing." - true) +(def ^:dynamic *validate-env-vars* + "When true, validates that environment variables actually exist and aren't blank. + Default false to avoid surprising failures; bind to true in strict environments." + false)
30-41: Tighten EnvRef: validate ENV name formatAvoid obviously bad names; keep runtime existence check as-is.
Apply:
(def EnvRef "Schema for environment variable references like [:env \"VAR_NAME\"]" [:and [:tuple {:description "Environment variable reference"} [:= :env] NonBlankString] + [:fn {:error/message "ENV var name must match [A-Z_][A-Z0-9_]*"} + (fn [[_ env-var]] + (boolean (re-matches #"[A-Z_][A-Z0-9_]*" env-var)))] [:fn {:error/message "Environment variable can't be empty"} (fn [[_ env-var]] (or (not *validate-env-vars*) (let [val (System/getenv env-var)] (and val (not (string/blank? val))))))]])
86-91: Require :schema when :response-format :type is :jsonPrevents runtime failures when asking for JSON without a schema.
Apply:
- [:response-format {:optional true} - [:map {:closed true} - [:type [:enum :json :text]] - [:schema {:optional true} :map]]] + [:response-format {:optional true} + [:and + [:map {:closed true} + [:type [:enum :json :text]] + [:schema {:optional true} :map]] + [:fn {:error/message "When :response-format :type is :json, provide :schema"} + (fn [{:keys [type schema]}] + (if (= type :json) (some? schema) true))]]]
110-117: Constrain OpenAI :logit-bias values to API rangeOpenAI expects -100..100; catch out-of-range earlier.
Apply:
- [:logit-bias {:optional true} [:map-of NonBlankString :int]] + [:logit-bias {:optional true} [:map-of NonBlankString [:int {:min -100 :max 100]]]]
154-157: Use Path for file path list in :contextDescription says “file paths list”; enforce Path.
Apply:
- [:context {:optional true - :description "Context to provide: true (default), false (none), or file paths list"} - [:or :boolean [:sequential NonBlankString]]] + [:context {:optional true + :description "Context to provide: true (default), false (none), or file paths list"} + [:or :boolean [:sequential Path]]]
159-166: Allow explicit nil for :enable-tools to match docDoc says “:all, specific list, or nil”; permit nil when key is present.
Apply:
- [:enable-tools {:optional true - :description "Tools the agent can access: :all, specific list, or nil (no tools)"} - [:or [:= :all] [:sequential :keyword]]] + [:enable-tools {:optional true + :description "Tools the agent can access: :all, specific list, or nil (no tools)"} + [:maybe [:or [:= :all] [:sequential :keyword]]]]
168-171: Allow explicit nil for :memory-size per descriptionKeeps schema aligned with “false/nil/<10 stateless”.
Apply:
- [:memory-size {:optional true - :description "Memory behavior: false/nil/<10 = stateless, >=10 = persistent window"} - [:or [:= false] [:int {:min 0}]]] + [:memory-size {:optional true + :description "Memory behavior: false/nil/<10 = stateless, >=10 = persistent window"} + [:maybe [:or [:= false] [:int {:min 0}]]]]
191-197: Drop [:maybe ...] on optional keys (:url, :mime-type)Key is already optional; allowing explicit nil adds little and can confuse.
Apply:
- [:url {:optional true - :description "Custom URL for resource (defaults to custom://kebab-case-name)"} - [:maybe NonBlankString]] + [:url {:optional true + :description "Custom URL for resource (defaults to custom://kebab-case-name)"} + NonBlankString] @@ - [:mime-type {:optional true - :description "MIME type (auto-detected from file extension if not specified)"} - [:maybe NonBlankString]]]) + [:mime-type {:optional true + :description "MIME type (auto-detected from file extension if not specified)"} + NonBlankString]])
257-259: Use Path for :scratch-pad-fileThis is a file path; enforce with Path like elsewhere.
Apply:
- [:scratch-pad-file {:optional true} NonBlankString] + [:scratch-pad-file {:optional true} Path]
261-286: Add referential integrity and uniqueness checks (agents/models)Catch config mistakes early: duplicate agent ids and unknown model refs.
Apply:
- [:agents {:optional true} [:sequential AgentConfig]] + [:agents {:optional true} [:sequential AgentConfig]] + ;; Cross-field validations + [:fn {:error/message "Agent :id values must be unique"} + (fn [{:keys [agents]}] + (let [ids (map :id agents)] + (= (count ids) (count (distinct ids)))))] + [:fn {:error/message "Each agent's :model must reference a key under :models"} + (fn [{:keys [agents models]}] + (let [model-keys (set (keys models))] + (every? (fn [{:keys [model]}] + (or (nil? model) (contains? model-keys model))) + agents)))]
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
src/clojure_mcp/config/schema.clj(1 hunks)test/clojure_mcp/config/schema_test.clj(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- test/clojure_mcp/config/schema_test.clj
🧰 Additional context used
📓 Path-based instructions (2)
src/**/*.{clj,cljc}
📄 CodeRabbit inference engine (CLAUDE.md)
src/**/*.{clj,cljc}: Use:requirewith ns aliases for imports (e.g.,[clojure.string :as string])
Include clear tool:descriptionfor 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/config/schema.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?)
Usetry/catchwith 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/config/schema.clj
🔇 Additional comments (6)
src/clojure_mcp/config/schema.clj (6)
1-9: Namespace and requires look goodAlias usage and ns-path alignment are correct.
20-25: NonBlankString helper is solidCovers empty and whitespace-only strings.
203-216: PromptArg schema reads wellClear, minimal, and fits usage.
217-239: Nice: XOR between :content and :file-pathPrevents the common footgun. Good addition.
292-305: Validation helpers LGTMexplain-config + valid? are straightforward.
310-322: Schema introspection helpers LGTMHandy for docs; no issues.
There was a problem hiding this 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
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/clojure_mcp/agent/langchain/model.clj (1)
314-323: Bug: Uses :gemini key but schema defines provider-specific config under :google.This makes Gemini options unreachable from validated configs.
- (get-in config [:gemini :allow-code-execution]) - (.allowCodeExecution (get-in config [:gemini :allow-code-execution])) - (get-in config [:gemini :include-code-execution-output]) - (.includeCodeExecutionOutput (get-in config [:gemini :include-code-execution-output])) - (get-in config [:gemini :response-logprobs]) - (.responseLogprobs (get-in config [:gemini :response-logprobs])) - (get-in config [:gemini :enable-enhanced-civic-answers]) - (.enableEnhancedCivicAnswers (get-in config [:gemini :enable-enhanced-civic-answers])) - (get-in config [:gemini :logprobs]) - (.logprobs (int (get-in config [:gemini :logprobs]))))))) + (get-in config [:google :allow-code-execution]) + (.allowCodeExecution (get-in config [:google :allow-code-execution])) + (get-in config [:google :include-code-execution-output]) + (.includeCodeExecutionOutput (get-in config [:google :include-code-execution-output])) + (get-in config [:google :response-logprobs]) + (.responseLogprobs (get-in config [:google :response-logprobs])) + (get-in config [:google :enable-enhanced-civic-answers]) + (.enableEnhancedCivicAnswers (get-in config [:google :enable-enhanced-civic-answers])) + (get-in config [:google :logprobs]) + (.logprobs (int (get-in config [:google :logprobs])))))))
♻️ Duplicate comments (1)
src/clojure_mcp/config/schema.clj (1)
245-248: Nice: XOR constraint on :content vs :file-path is in place.This closes the footgun where neither or both could be provided.
🧹 Nitpick comments (2)
src/clojure_mcp/config/schema.clj (2)
164-167: Use Path for file path lists in :context.Schema says “file paths list” but validates generic strings. Prefer Path for consistency.
- [:context {:optional true - :description "Context to provide: true (default), false (none), or file paths list"} - [:or :boolean [:sequential NonBlankString]]] + [:context {:optional true + :description "Context to provide: true (default), false (none), or file paths list"} + [:or :boolean [:sequential Path]]]
30-41: Make env lookup overridable for tests and align with model namespace.EnvRef validation always calls System/getenv, ignoring test overrides used elsewhere. Add an overridable getter.
+(def ^:dynamic *get-env* + "Overrideable env lookup used by schema-time checks (defaults to System/getenv)." + (fn [k] (System/getenv k))) (def EnvRef "Schema for environment variable references like [:env \"VAR_NAME\"]" [:and [:tuple {:description "Environment variable reference"} [:= :env] NonBlankString] [:fn {:error/message "Environment variable can't be empty"} (fn [[_ env-var]] (or (not *validate-env-vars*) - (let [val (System/getenv env-var)] + (let [val (*get-env* env-var)] (and val (not (string/blank? val))))))]])Usage in tests:
(binding [clojure-mcp.config.schema/get-env (fn [k] (get {"OPENAI_API_KEY" "x"} k))] ...)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
src/clojure_mcp/agent/langchain/model.clj(4 hunks)src/clojure_mcp/agent/langchain/model_spec.clj(0 hunks)src/clojure_mcp/config/schema.clj(1 hunks)test/clojure_mcp/agent/langchain/model_spec_test.clj(0 hunks)
💤 Files with no reviewable changes (2)
- test/clojure_mcp/agent/langchain/model_spec_test.clj
- src/clojure_mcp/agent/langchain/model_spec.clj
🧰 Additional context used
📓 Path-based instructions (2)
src/**/*.{clj,cljc}
📄 CodeRabbit inference engine (CLAUDE.md)
src/**/*.{clj,cljc}: Use:requirewith ns aliases for imports (e.g.,[clojure.string :as string])
Include clear tool:descriptionfor 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/agent/langchain/model.cljsrc/clojure_mcp/config/schema.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?)
Usetry/catchwith 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/agent/langchain/model.cljsrc/clojure_mcp/config/schema.clj
🔇 Additional comments (6)
src/clojure_mcp/config/schema.clj (2)
254-297: LGTM on top-level Config shape and key metadata.Closed maps + spell-checking and added descriptions improve UX.
337-360: Validation helpers look good.Clear ex-info payloads with humanized Malli errors.
src/clojure_mcp/agent/langchain/model.clj (4)
4-4: Good switch to schema validators.Alias and dependency update match the migration away from spec.
406-408: Validation hook on builder creation: good.Model key + config validated before use.
430-431: Validation on create-builder-from-config: good.
514-516: Validation on nREPL-driven path: good.
Summary
This PR enhances the configuration schema validation by adding comprehensive field descriptions and cleaning up unused code.
Changes
1. Added Field Descriptions to ResourceEntry Schema
:description,:file-path,:url,:mime-type2. Added Field Descriptions to PromptEntry and PromptArg Schemas
:name,:description,:required?:description,:content,:file-path,:args3. Removed Unused coerce-config Function
coerce-configfunction fromschema.cljwhich was just a pass-throughcoercion-testfromschema_test.cljTesting
Impact
These changes make the configuration schemas more consistent and self-documenting, improving the developer experience when working with ClojureMCP configurations.
Summary by CodeRabbit
New Features
Documentation
Chores
Tests