Skip to content

Commit e30b23a

Browse files
author
Bruce Hauman
committed
Add built-in Mistral model support via OpenAI-compatible API
- Add 7 Mistral models: mistral-large, mistral-medium, mistral-small, codestral, devstral, magistral-medium, magistral-small - Auto-detect MISTRAL_API_KEY env variable for authentication - Route through OpenAI provider with Mistral base URL - Add aliases: :mistral, :codestral, :devstral, :magistral, etc. - 55 total built-in models
1 parent 358629c commit e30b23a

File tree

3 files changed

+95
-16
lines changed

3 files changed

+95
-16
lines changed

doc/model-configuration.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ If a model key is not found in your custom configuration, the system automatical
230230

231231
## Built-in Models
232232

233-
The system includes 48 pre-configured models that can be used without configuration:
233+
The system includes 55 pre-configured models that can be used without configuration:
234234

235235
### OpenAI
236236
- `:openai/gpt-4o`
@@ -252,6 +252,11 @@ The system includes 48 pre-configured models that can be used without configurat
252252
- `:google/gemini-3-flash`, `:google/gemini-3-pro`
253253
- `:google/gemini-3-1-flash-lite`, `:google/gemini-3-1-pro`
254254

255+
### Mistral (via OpenAI-compatible API, requires `MISTRAL_API_KEY`)
256+
- `:mistral/mistral-large`, `:mistral/mistral-medium`, `:mistral/mistral-small`
257+
- `:mistral/codestral`, `:mistral/devstral`
258+
- `:mistral/magistral-medium`, `:mistral/magistral-small`
259+
255260
### Anthropic
256261
- `:anthropic/claude-opus-4-6`, `:anthropic/claude-opus-4-6-reasoning`
257262
- `:anthropic/claude-sonnet-4-6`, `:anthropic/claude-sonnet-4-6-reasoning`
@@ -271,6 +276,7 @@ API keys can be provided in three ways (in order of precedence):
271276
- OpenAI: `OPENAI_API_KEY`
272277
- Google: `GEMINI_API_KEY`
273278
- Anthropic: `ANTHROPIC_API_KEY`
279+
- Mistral: `MISTRAL_API_KEY`
274280

275281
## Validation
276282

src/clojure_mcp/agent/langchain/model.clj

Lines changed: 79 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,49 @@
201201
(merge model-base
202202
{:model-name "gemini-3.1-pro-preview"})
203203

204+
;; Mistral Models (via OpenAI-compatible API)
205+
:mistral/mistral-large
206+
(merge model-base
207+
{:provider :openai
208+
:model-name "mistral-large-latest"
209+
:base-url "https://api.mistral.ai/v1"})
210+
211+
:mistral/mistral-medium
212+
(merge model-base
213+
{:provider :openai
214+
:model-name "mistral-medium-latest"
215+
:base-url "https://api.mistral.ai/v1"})
216+
217+
:mistral/mistral-small
218+
(merge model-base
219+
{:provider :openai
220+
:model-name "mistral-small-latest"
221+
:base-url "https://api.mistral.ai/v1"})
222+
223+
:mistral/codestral
224+
(merge model-base
225+
{:provider :openai
226+
:model-name "codestral-latest"
227+
:base-url "https://api.mistral.ai/v1"})
228+
229+
:mistral/devstral
230+
(merge model-base
231+
{:provider :openai
232+
:model-name "devstral-2-25-12"
233+
:base-url "https://api.mistral.ai/v1"})
234+
235+
:mistral/magistral-medium
236+
(merge reasoning-model-base
237+
{:provider :openai
238+
:model-name "magistral-medium-latest"
239+
:base-url "https://api.mistral.ai/v1"})
240+
241+
:mistral/magistral-small
242+
(merge reasoning-model-base
243+
{:provider :openai
244+
:model-name "magistral-small-latest"
245+
:base-url "https://api.mistral.ai/v1"})
246+
204247
;; Anthropic Models
205248
:anthropic/claude-opus-4-1
206249
(merge model-base
@@ -313,7 +356,17 @@
313356
:codex :openai/gpt-5-4-pro
314357
:gpt-5-1-codex :openai/gpt-5-1-codex
315358
:gpt-5-1-codex-max :openai/gpt-5-1-codex-max
316-
:gpt-5-2-codex :openai/gpt-5-2-codex})
359+
:gpt-5-2-codex :openai/gpt-5-2-codex
360+
;; Mistral aliases
361+
:mistral :mistral/mistral-large
362+
:mistral-large :mistral/mistral-large
363+
:mistral-medium :mistral/mistral-medium
364+
:mistral-small :mistral/mistral-small
365+
:codestral :mistral/codestral
366+
:devstral :mistral/devstral
367+
:magistral :mistral/magistral-medium
368+
:magistral-medium :mistral/magistral-medium
369+
:magistral-small :mistral/magistral-small})
317370

318371
(defn resolve-model-alias
319372
"Resolves a model key, checking aliases for unnamespaced keywords.
@@ -376,18 +429,30 @@
376429
;; Return other values as-is
377430
:else config))
378431

432+
(def api-key-env-mapping
433+
"Maps provider/namespace keywords to environment variable names for API keys."
434+
{:openai "OPENAI_API_KEY"
435+
:google "GEMINI_API_KEY"
436+
:anthropic "ANTHROPIC_API_KEY"
437+
:mistral "MISTRAL_API_KEY"})
438+
379439
(defn- ensure-api-key
380-
"Ensures API key is present, getting from environment if needed"
381-
[config provider]
382-
(if (:api-key config)
383-
config
384-
(let [env-key-mapping {:openai "OPENAI_API_KEY"
385-
:google "GEMINI_API_KEY"
386-
:anthropic "ANTHROPIC_API_KEY"}
387-
env-key (get env-key-mapping provider)]
388-
(if-let [api-key (and env-key (get-env env-key))]
389-
(assoc config :api-key api-key)
390-
config))))
440+
"Ensures API key is present, getting from environment if needed.
441+
Checks the model-key namespace first (e.g. :mistral -> MISTRAL_API_KEY),
442+
then falls back to the provider (e.g. :openai -> OPENAI_API_KEY)."
443+
([config provider]
444+
(ensure-api-key config provider nil))
445+
([config provider model-key-ns]
446+
(if (:api-key config)
447+
config
448+
;; Try namespace-specific env var first, then provider env var
449+
(let [ns-env-key (get api-key-env-mapping model-key-ns)
450+
provider-env-key (get api-key-env-mapping provider)
451+
api-key (or (and ns-env-key (get-env ns-env-key))
452+
(and provider-env-key (get-env provider-env-key)))]
453+
(if api-key
454+
(assoc config :api-key api-key)
455+
config)))))
391456

392457
(defn- ensure-provider
393458
"Ensures provider is present in config, extracting from model-key if needed.
@@ -564,7 +629,7 @@
564629
config (-> base-config
565630
(resolve-env-refs) ; Also resolve any env refs from defaults
566631
(ensure-provider model-key)
567-
(as-> cfg (ensure-api-key cfg (:provider cfg))))]
632+
(as-> cfg (ensure-api-key cfg (:provider cfg) (some-> model-key namespace keyword))))]
568633
;; Validate if requested
569634
(when validate?
570635
(schema/validate-model-key model-key)
@@ -673,7 +738,7 @@
673738
;; Extract provider for API key
674739
provider (:provider config-with-provider)
675740
;; Ensure API key
676-
final-config (ensure-api-key config-with-provider provider)]
741+
final-config (ensure-api-key config-with-provider provider (some-> model-key namespace keyword))]
677742
;; Validate if requested
678743
(when validate?
679744
(schema/validate-model-key model-key)

test/clojure_mcp/agent/langchain/model_test.clj

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,15 @@
6666
(is (contains? (set models) :anthropic/claude-sonnet-4-6))
6767
(is (contains? (set models) :anthropic/claude-sonnet-4-6-reasoning))
6868
(is (contains? (set models) :anthropic/claude-haiku-4-5))
69-
(is (= 48 (count models))))))
69+
;; Mistral models
70+
(is (contains? (set models) :mistral/mistral-large))
71+
(is (contains? (set models) :mistral/mistral-medium))
72+
(is (contains? (set models) :mistral/mistral-small))
73+
(is (contains? (set models) :mistral/codestral))
74+
(is (contains? (set models) :mistral/devstral))
75+
(is (contains? (set models) :mistral/magistral-medium))
76+
(is (contains? (set models) :mistral/magistral-small))
77+
(is (= 55 (count models))))))
7078

7179
(deftest test-get-provider
7280
(testing "Provider extraction from model keys"

0 commit comments

Comments
 (0)