Skip to content

Commit b928a89

Browse files
authored
feat: add Mistral AI provider with dedicated OCR support (#106)
## Summary - Add Mistral AI provider with 10 tools and 17 models - Tools: ask, analyze_image, process_ocr, transcribe_audio, get_embeddings, moderate_content, fill_in_middle, list_models, server_info, test_connection - Models: Frontier (Large/Medium/Small), Reasoning (Magistral), Vision (Pixtral), Audio (Voxtral), Coding (Codestral/Devstral), Embeddings, OCR, Moderation - Supports reasoning model thinking output with optional `include_thinking` parameter - GPT-5 reviewed and approved implementation 🤖 Generated with [Claude Code](https://claude.com/claude-code)
1 parent fe6167e commit b928a89

File tree

11 files changed

+1538
-17
lines changed

11 files changed

+1538
-17
lines changed

.mcp.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@
55
"command": "mcp-google-calendar",
66
"args": [],
77
"env": {}
8+
},
9+
"mistral": {
10+
"type": "stdio",
11+
"command": "mcp-mistral",
12+
"args": [],
13+
"env": {}
814
}
915
}
1016
}

PKGBUILD

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Maintainer: Will Handley <[email protected]>
22
_pkgname=mcp-handley-lab
33
pkgname=python-mcp-handley-lab
4-
pkgver=0.13.3
4+
pkgver=0.14.0
55
pkgrel=1
66
pkgdesc="MCP Handley Lab - A comprehensive MCP toolkit for research productivity and lab management"
77
arch=('any')
@@ -37,18 +37,16 @@ depends=(
3737
'python-pendulum'
3838
'python-xai-sdk'
3939
'jupyter-nbformat>=5.0.0'
40-
'python-nbclient>=0.8.0'
40+
'jupyter-nbclient>=0.8.0'
4141
'python-dateparser'
4242
'python-ftfy'
4343
'python-inscriptis'
4444
'python-selectolax'
4545
'python-email-reply-parser'
4646
'python-anthropic'
47+
'python-mistralai>=1.9.0'
4748
'python-wolframclient'
4849
'python-opentelemetry-sdk'
49-
'python-chromadb>=1.0.0'
50-
'python-mail-parser>=3.15.0'
51-
'python-pyfzf>=0.3.1'
5250
'python-dateutil>=2.8.0'
5351
)
5452
makedepends=(
@@ -71,6 +69,7 @@ optdepends=(
7169
'python-code2prompt: Codebase analysis'
7270
'python-black: Code formatting'
7371
'python-ruff: Linting'
72+
'python-chromadb: Semantic search features (AUR)'
7473
)
7574
source=()
7675
sha256sums=()

pyproject.toml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "mcp-handley-lab"
7-
version = "0.13.3"
7+
version = "0.14.0"
88
description = "MCP Handley Lab - A comprehensive MCP toolkit for research productivity and lab management"
99
readme = "README.md"
1010
requires-python = ">=3.10"
@@ -22,6 +22,7 @@ dependencies = [
2222
"googlemaps>=4.0.0",
2323
"openai>=1.0.0",
2424
"anthropic>=0.21.3",
25+
"mistralai>=1.9.0",
2526
"xai-sdk>=1.0.0",
2627
"Pillow>=10.0.0",
2728
"httpx>=0.25.0",
@@ -32,15 +33,12 @@ dependencies = [
3233
"jmespath>=1.0.0",
3334
"watchdog>=3.0.0",
3435
"msal>=1.20.0",
35-
"chromadb>=1.0.0",
3636
"nbformat>=5.0.0",
3737
"nbclient>=0.8.0",
38-
"pyfzf>=0.3.1",
3938
"click>=8.0.0",
4039
"html2text>=2020.1.16",
4140
"beautifulsoup4>=4.12.0",
4241
"markdownify>=0.11.0",
43-
"mail-parser>=3.15.0",
4442
"email-reply-parser>=0.5.0",
4543
"selectolax>=0.3.0",
4644
"inscriptis>=2.5.0",
@@ -79,6 +77,7 @@ mcp-gemini = "mcp_handley_lab.llm.gemini.tool:mcp.run"
7977
mcp-openai = "mcp_handley_lab.llm.openai.tool:mcp.run"
8078
mcp-claude = "mcp_handley_lab.llm.claude.tool:mcp.run"
8179
mcp-grok = "mcp_handley_lab.llm.grok.tool:mcp.run"
80+
mcp-mistral = "mcp_handley_lab.llm.mistral.tool:mcp.run"
8281
mcp-google-maps = "mcp_handley_lab.google_maps.tool:mcp.run"
8382
mcp-email = "mcp_handley_lab.email.tool:mcp.run"
8483
mcp-mutt-aliases = "mcp_handley_lab.email.mutt_aliases.tool:mcp.run"

src/mcp_handley_lab/code2prompt/tool.py

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -74,16 +74,13 @@ def generate_prompt(
7474
"cl100k",
7575
description="The name of the tiktoken encoding to use for token counting (e.g., 'cl100k', 'p50k_base').",
7676
),
77-
tokens: str = Field(
77+
token_format: str = Field(
7878
"format",
79-
description="Determines how token counts are displayed. Valid options are 'format', 'only', 'none'.",
79+
description="Determines how token counts are displayed. Valid options are 'format' (human readable) or 'raw' (machine parsable).",
8080
),
8181
sort: str = Field(
8282
"name_asc",
83-
description="The sorting order for files. Options: 'name_asc', 'name_desc', 'tokens_asc', 'tokens_desc'.",
84-
),
85-
include_priority: bool = Field(
86-
False, description="'include' patterns take priority over .gitignore rules."
83+
description="The sorting order for files. Options: 'name_asc', 'name_desc', 'date_asc', 'date_desc'.",
8784
),
8885
template: str = Field(
8986
"", description="Path to a custom Jinja2 template file to format the output."
@@ -116,10 +113,9 @@ def generate_prompt(
116113
{"name": "--output-file", "value": output_file, "type": "value"},
117114
{"name": "--output-format", "value": output_format, "type": "value"},
118115
{"name": "--encoding", "value": encoding, "type": "value"},
119-
{"name": "--tokens", "value": tokens, "type": "value"},
116+
{"name": "--token-format", "value": token_format, "type": "value"},
120117
{"name": "--sort", "value": sort, "type": "value"},
121118
{"name": "--template", "value": template, "type": "optional_value"},
122-
{"name": "--include-priority", "condition": include_priority, "type": "flag"},
123119
{"name": "--no-ignore", "condition": no_ignore, "type": "flag"},
124120
{"name": "--line-numbers", "condition": line_numbers, "type": "flag"},
125121
{

src/mcp_handley_lab/common/config.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ class Settings(BaseSettings):
2525
xai_api_key: str = Field(
2626
default="YOUR_API_KEY_HERE", description="API key for xAI Grok services."
2727
)
28+
mistral_api_key: str = Field(
29+
default="YOUR_API_KEY_HERE", description="API key for Mistral AI services."
30+
)
2831
google_maps_api_key: str = Field(
2932
default="YOUR_API_KEY_HERE", description="API key for Google Maps services."
3033
)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
"""Mistral LLM tool for AI interactions via MCP."""
Lines changed: 248 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,248 @@
1+
models:
2+
# === FRONTIER GENERALIST MODELS ===
3+
mistral-large-latest:
4+
description: "Latest flagship model - Mistral Large 3 (v25.12)"
5+
capabilities: "🎯 Best for: Complex reasoning, analysis, multimodal tasks"
6+
tags: ["mistral-large", "latest", "frontier", "multimodal"]
7+
context_window: "128,000 tokens"
8+
output_tokens: 8192
9+
supports_vision: true
10+
supports_grounding: false
11+
input_per_1m: 2.00
12+
output_per_1m: 6.00
13+
14+
mistral-medium-latest:
15+
description: "Mistral Medium 3.1 - frontier multimodal model (v25.08)"
16+
capabilities: "🎯 Best for: Complex tasks, balanced cost/performance"
17+
tags: ["mistral-medium", "latest", "frontier", "multimodal"]
18+
context_window: "128,000 tokens"
19+
output_tokens: 8192
20+
supports_vision: true
21+
supports_grounding: false
22+
input_per_1m: 0.40
23+
output_per_1m: 2.00
24+
25+
mistral-small-latest:
26+
description: "Mistral Small 3.2 - efficient general model (v25.06)"
27+
capabilities: "⚡ Best for: Everyday tasks, cost-effective"
28+
tags: ["mistral-small", "latest", "cost-effective"]
29+
context_window: "128,000 tokens"
30+
output_tokens: 8192
31+
supports_vision: true
32+
supports_grounding: false
33+
input_per_1m: 0.10
34+
output_per_1m: 0.30
35+
36+
# === MINISTRAL EDGE MODELS ===
37+
ministral-3b-latest:
38+
description: "Ministral 3 3B - tiny efficient model with vision (v25.12)"
39+
capabilities: "🚀 Best for: Edge deployment, ultra-low latency"
40+
tags: ["ministral", "edge", "cost-effective", "vision"]
41+
context_window: "128,000 tokens"
42+
output_tokens: 8192
43+
supports_vision: true
44+
supports_grounding: false
45+
input_per_1m: 0.04
46+
output_per_1m: 0.04
47+
48+
ministral-8b-latest:
49+
description: "Ministral 3 8B - efficient model with vision (v25.12)"
50+
capabilities: "🚀 Best for: Fast inference, high-volume tasks"
51+
tags: ["ministral", "edge", "cost-effective", "vision"]
52+
context_window: "128,000 tokens"
53+
output_tokens: 8192
54+
supports_vision: true
55+
supports_grounding: false
56+
input_per_1m: 0.10
57+
output_per_1m: 0.10
58+
59+
# === REASONING MODELS (MAGISTRAL) ===
60+
magistral-medium-latest:
61+
description: "Magistral Medium 1.2 - frontier reasoning model (v25.09)"
62+
capabilities: "🧠 Best for: Complex reasoning, step-by-step thinking"
63+
tags: ["magistral", "reasoning", "frontier"]
64+
context_window: "40,000 tokens"
65+
output_tokens: 40000
66+
supports_vision: false
67+
supports_grounding: false
68+
supports_reasoning: true
69+
input_per_1m: 2.00
70+
output_per_1m: 5.00
71+
72+
magistral-small-latest:
73+
description: "Magistral Small 1.2 - efficient reasoning model (v25.09)"
74+
capabilities: "🧠 Best for: Cost-effective reasoning tasks"
75+
tags: ["magistral", "reasoning", "cost-effective"]
76+
context_window: "40,000 tokens"
77+
output_tokens: 40000
78+
supports_vision: false
79+
supports_grounding: false
80+
supports_reasoning: true
81+
input_per_1m: 0.50
82+
output_per_1m: 1.50
83+
84+
# === CODING MODELS ===
85+
codestral-latest:
86+
description: "Codestral - cutting-edge coding model (v25.08)"
87+
capabilities: "💻 Best for: Code generation, completion, debugging"
88+
tags: ["codestral", "coding", "latest"]
89+
context_window: "256,000 tokens"
90+
output_tokens: 8192
91+
supports_vision: false
92+
supports_grounding: false
93+
supports_fim: true
94+
input_per_1m: 0.30
95+
output_per_1m: 0.90
96+
97+
devstral-small-latest:
98+
description: "Devstral Small 1.1 - open SWE model (v25.07)"
99+
capabilities: "💻 Best for: Software engineering tasks"
100+
tags: ["devstral", "coding", "swe"]
101+
context_window: "128,000 tokens"
102+
output_tokens: 8192
103+
supports_vision: false
104+
supports_grounding: false
105+
supports_fim: true
106+
input_per_1m: 0.10
107+
output_per_1m: 0.30
108+
109+
# === VISION MODELS (PIXTRAL) ===
110+
pixtral-large-latest:
111+
description: "Pixtral Large - multimodal vision model (v24.11)"
112+
capabilities: "👁️ Best for: Image analysis, multimodal tasks"
113+
tags: ["pixtral", "vision", "multimodal"]
114+
context_window: "128,000 tokens"
115+
output_tokens: 8192
116+
supports_vision: true
117+
supports_grounding: false
118+
input_per_1m: 2.00
119+
output_per_1m: 6.00
120+
121+
pixtral-12b-2409:
122+
description: "Pixtral 12B - lightweight vision model"
123+
capabilities: "👁️ Best for: OCR, cost-effective vision tasks"
124+
tags: ["pixtral", "vision", "cost-effective"]
125+
context_window: "128,000 tokens"
126+
output_tokens: 8192
127+
supports_vision: true
128+
supports_grounding: false
129+
input_per_1m: 0.15
130+
output_per_1m: 0.15
131+
132+
# === AUDIO MODELS (VOXTRAL) ===
133+
voxtral-small-latest:
134+
description: "Voxtral Small - audio chat model (v25.07)"
135+
capabilities: "🎤 Best for: Audio conversations, voice understanding"
136+
tags: ["voxtral", "audio", "chat"]
137+
context_window: "128,000 tokens"
138+
output_tokens: 8192
139+
supports_vision: false
140+
supports_grounding: false
141+
supports_audio: true
142+
input_per_1m: 0.20
143+
output_per_1m: 0.60
144+
145+
voxtral-mini-latest:
146+
description: "Voxtral Mini - audio transcription model (v25.07)"
147+
capabilities: "🎤 Best for: Speech-to-text, transcription"
148+
tags: ["voxtral", "audio", "transcription"]
149+
context_window: "128,000 tokens"
150+
output_tokens: 8192
151+
supports_vision: false
152+
supports_grounding: false
153+
supports_audio: true
154+
supports_transcription: true
155+
input_per_1m: 0.10
156+
output_per_1m: 0.30
157+
158+
# === SPECIALIST MODELS ===
159+
mistral-ocr-latest:
160+
description: "Dedicated OCR model for document text extraction"
161+
capabilities: "📄 Best for: OCR, document parsing, PDF extraction"
162+
tags: ["ocr", "document-ai"]
163+
context_window: "N/A (document processing)"
164+
output_tokens: 0
165+
supports_vision: true
166+
supports_grounding: false
167+
# Pricing: $1 per 1,000 pages
168+
input_per_1m: 1.00
169+
output_per_1m: 0.00
170+
171+
mistral-moderation-latest:
172+
description: "Content moderation model (v24.11)"
173+
capabilities: "🛡️ Best for: Content safety, harmful text detection"
174+
tags: ["moderation", "safety"]
175+
context_window: "8,000 tokens"
176+
output_tokens: 0
177+
supports_vision: false
178+
supports_grounding: false
179+
input_per_1m: 0.10
180+
output_per_1m: 0.00
181+
182+
# === EMBEDDING MODELS ===
183+
mistral-embed:
184+
description: "Text embedding model for semantic search"
185+
capabilities: "🔍 Best for: RAG, semantic search, clustering"
186+
tags: ["embedding", "text"]
187+
context_window: "8,000 tokens"
188+
output_tokens: 0
189+
supports_vision: false
190+
supports_grounding: false
191+
embedding_dimensions: 1024
192+
input_per_1m: 0.10
193+
output_per_1m: 0.00
194+
195+
codestral-embed:
196+
description: "Code embedding model (v25.05)"
197+
capabilities: "🔍 Best for: Code search, repository exploration"
198+
tags: ["embedding", "code"]
199+
context_window: "32,000 tokens"
200+
output_tokens: 0
201+
supports_vision: false
202+
supports_grounding: false
203+
embedding_dimensions: 1024
204+
input_per_1m: 0.20
205+
output_per_1m: 0.00
206+
207+
# Display categories (how to group models by tags for presentation)
208+
display_categories:
209+
- name: "🎯 Frontier Generalist"
210+
tags: ["frontier"]
211+
description: "Most capable models for complex tasks"
212+
- name: "🧠 Reasoning Models"
213+
tags: ["magistral", "reasoning"]
214+
description: "Step-by-step thinking and complex reasoning"
215+
- name: "💻 Coding Models"
216+
tags: ["codestral", "devstral", "coding"]
217+
description: "Specialized for code generation and SWE"
218+
- name: "👁️ Vision Models"
219+
tags: ["pixtral", "vision"]
220+
description: "Multimodal image understanding"
221+
- name: "🎤 Audio Models"
222+
tags: ["voxtral", "audio"]
223+
description: "Speech-to-text and audio chat"
224+
- name: "🚀 Edge Models"
225+
tags: ["ministral", "edge"]
226+
description: "Efficient models for high-volume tasks"
227+
- name: "📄 Document AI"
228+
tags: ["ocr", "document-ai"]
229+
description: "OCR and document processing"
230+
- name: "🔍 Embeddings"
231+
tags: ["embedding"]
232+
description: "Vector embeddings for search and RAG"
233+
- name: "🛡️ Safety"
234+
tags: ["moderation", "safety"]
235+
description: "Content moderation and safety"
236+
237+
# Default model
238+
default_model: "mistral-large-latest"
239+
240+
# Usage notes
241+
usage_notes:
242+
- "Mistral Large 3 (v25.12): Latest flagship with vision - best quality"
243+
- "Magistral models: Use prompt_mode='reasoning' for step-by-step thinking"
244+
- "Codestral: Supports FIM (fill-in-middle) for code completion"
245+
- "Voxtral: Audio input for chat and transcription"
246+
- "OCR: $1 per 1,000 pages for document extraction"
247+
- "All chat models support 128k context (except Magistral: 40k)"
248+
- "Free tier available for experimentation"

0 commit comments

Comments
 (0)