Créer un agent de recherche local dans LM Studio à l’aide de quatre serveurs MCP.
Un agent de recherche local dans LM Studio disposant de quatre serveurs MCP : filesystem, GitHub, SearXNG et Camofox, un schéma d’outil simplifié, une instruction de planification et une démonstration de fonctionnement.
Sources: How to Turn LM Studio Into a Local Research Agent With MCP Servers
Un modèle local capable de rechercher, de lire un fichier ou d’ouvrir une demande de fusion est utile. Un modèle local qui peut relier tous ces éléments en une seule séquence de raisonnement pour répondre à une question unique fait office d’assistant de recherche. Pour passer du premier au second niveau dans LM Studio, il faut quatre serveurs MCP fonctionnant en parallèle, un plan permettant d’éviter que les schémas d’outils combinés ne submergent la fenêtre de contexte, ainsi qu’un mécanisme incitant un modèle de 9 milliards de paramètres à accomplir une tâche en plusieurs étapes au lieu d’utiliser un outil puis de s’arrêter.
Les quatre serveurs sont un serveur de système de fichiers, un serveur GitHub, une instance SearXNG auto-hébergée pour les recherches, et un navigateur basé sur Camoufox (Camofox) pour lire les pages affichées par les recherches. Le serveur de système de fichiers est @modelcontextprotocol/server-filesystem et est restreint à un répertoire autorisé. GitHub est accessible via OAuth à l’adresse api.githubcopilot.com/mcp/. SearXNG et Camofox tournent sous Docker et se connectent respectivement via mcp-searxng et camofox-mcp. Chacun fonctionne de manière indépendante. Ce qui est intéressant, c’est ce qui se passe lorsque une seule conversation les regroupe tous.
Une précaution à prendre avant tout câblage : tout cela est conçu pour des recherches en ligne ordinaires, comme l’analyse concurrentielle, la vérification d’un fournisseur ou la validation d’une affirmation dans un article. L’agent ne sait pas ce qui est recherché et s’en moque. Il cherche, récupère et lit tout ce vers quoi il est orienté.
La mise en place se décompose en quatre étapes : combiner les serveurs, réduire la liste des outils, fournir un plan au modèle, et exécuter une démonstration de fonctionnement.
Étape 1 : les quatre serveurs dans une même conversation
LM Studio ne limite pas le nombre de serveurs MCP que peut utiliser une conversation. Il charge chacun d’eux et transmet au modèle le schéma d’outil correspondant à chacun. C’est là l’avantage de cette configuration, mais, comme le montre l’étape suivante, c’est aussi ce qui pose les premiers problèmes.
Le système de fichiers ainsi que les entrées GitHub sont configurés comme pour une installation indépendante, de même pour les entrées SearXNG et Camofox. Les conteneurs de base doivent déjà être en cours d’exécution, avec leurs fichiers docker-compose.yml et searxng/settings.yml en place, car ces fichiers ne sont pas répétés ici. Ce qui change, c’est que les quatre entrées se trouvent désormais dans un seul mcp.json:
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"/Users/jes/research-workspace"
]
},
"github": {
"url": "https://api.githubcopilot.com/mcp/",
"auth": {
"CLIENT_ID": "<your Client ID>",
"CLIENT_SECRET": "<your client secret>"
}
},
"searxng": {
"command": "npx",
"args": ["-y", "mcp-searxng"],
"env": {
"SEARXNG_URL": "http://localhost:8080"
}
},
"camofox": {
"command": "npx",
"args": ["-y", "camofox-mcp"],
"env": {
"CAMOFOX_URL": "http://localhost:8765",
"CAMOFOX_API_KEY": "your-camofox-api-key",
"CAMOFOX_AUTH_MODE": "api_key"
}
}
}
}
Trois détails méritent une attention particulière.
- L’entrée
githubdéclenche sa propre étape OAuth. LM Studio en demande l’accès la première fois que le serveur tente de se charger. Comme l’endpoint de GitHub ne prend pas en charge l’enregistrement dynamique des clients, le flux utilise une application GitHub OAuth qui doit être enregistrée manuellement à l’avance. Il n’existe aucun raccourci pour contourner ce problème. - Le répertoire autorisé pour le serveur de système de fichiers est une choix arbitraire. Un dossier dédié
research-workspaceest préférable au répertoire personnel, principalement parce qu’il indique clairement ce que le modèle peut accéder. CAMOFOX_URLetSEARXNG_URLdoivent pointer vers les conteneurs Docker. Même si ceux-ci ne sont pas en cours d’exécution, les serveurs se chargent néanmoins dans LM Studio, mais toutes les appels aux outils dirigés vers eux échouent, ce qui provoque une confusion pendant une vingtaine de minutes la première fois que cela se produit.
Lorsque les quatre fonctionnalités sont activées et que les petits points verts à côté de chaque nom de serveur dans le panneau MCP deviennent pleins, le chat dispose de quatre outils de système de fichiers, de dizaines d’outils GitHub, de quatre outils SearXNG et d’environ quarante-cinq outils Camofox. Cela représente une quantité importante d’informations à prendre en compte pour un modèle de 9 milliards de paramètres, et c’est le problème que la prochaine étape vise à résoudre.
Étape 2 : maintenir le budget de contexte
Le nombre d’outils GitHub seul constitue un risque, tout comme celui des outils Camofox. Ensemble, avec les outils SearXNG et de système de fichiers en plus, la charge devient importante.
Le nom, la description et le schéma des paramètres de chaque outil sont tokenisés dans le contexte du modèle avant même qu’il n’ait lu un seul mot de la question réelle. Sur un modèle de petite taille disposant d’une fenêtre de contexte limitée, cette surcharge peut représenter une part significative de tout ce qui est disponible.
La solution la plus directe consiste simplement à ne pas activer tous les outils provenant de tous les serveurs. Pour GitHub, il existe un moyen plus efficace que de déclencher manuellement les outils dans le panneau MCP. Le serveur distant accepte l’en-tête X-MCP-Readonly, ce qui limite toute la connexion aux outils en mode lecture seule avant que LM Studio ne voie le reste du schéma. Avec cela, l’entrée github de l’étape précédente devient :
{
"github": {
"url": "https://api.githubcopilot.com/mcp/",
"auth": {
"CLIENT_ID": "<your Client ID>",
"CLIENT_SECRET": "<your client secret>"
},
"headers": {
"X-MCP-Readonly": "true"
}
}
}
Lorsque l’en-tête est activé, le serveur ne propose que des outils de lecture : pull_request_read, issue_read, list_commits, get_file_contents, search_repositories et search_code. Tous les outils permettant de supprimer, de fusionner, de pousser ou de créer des éléments sont simplement absents. Cette restriction est appliquée du côté de GitHub, et non par LM Studio qui cacherait un bouton ; il s’agit donc d’une véritable limitation. Cela signifie également que les schémas relatifs aux outils d’écriture désactivés ne sont jamais tokenisés dans le contexte, ce qui correspond justement à l’objectif principal de cette étape.
Quiconque souhaite une restriction plus stricte peut utiliser X-MCP-Tools, qui accepte une liste explicite séparée par des virgules, par exemple search_code,search_repositories,get_file_contents,list_commits. Cela convient aux cas où les outils liés aux problèmes et aux demandes de pull request ne seront clairement jamais nécessaires.
Une capture d’écran du GitHub MCP dans cet état ne montrerait que les outils get, read, list, scan et search, car le paramètre read-only était réglé sur true, avec la possibilité de désactiver d’autres outils non nécessaires afin de réduire les coûts liés aux tokens.
Camofox ne dispose pas d’équivalent côté serveur, donc ses outils sont désactivés un par un dans le panneau MCP. Pour une conversation réservée à la recherche, les outils à désactiver sont delete_download, import_cookies ainsi que tout ce qui gère les profils, comme save_profile et load_profile, puisqu’une session de recherche n’a aucune raison d’accéder aux profils de navigateur enregistrés.
Le principe est de conserver uniquement ce dont a besoin le cas d’usage et de désactiver le reste. Pour la plupart des serveurs, il s’agit d’une décision liée aux contraintes de fonctionnement et non à des raisons de sécurité. L’en-tête GitHub constitue l’exception, car c’est le serveur lui-même de GitHub qui l’impose.
La démonstration de l’Étape 4 n’a jamais besoin d’accès d’écriture sur GitHub, puisque la seule action GitHub consiste à lire un manifeste, ce qui permet de maintenir la restriction d’accès en lecture seule. Si une tâche ultérieure nécessite effectivement des écritures, par exemple pour ouvrir un problème enregistrant ce que l’agent a trouvé, il suffit de supprimer l’en-tête correspondant à cette conversation. Mélanger des connexions GitHub en lecture seule et capables d’écriture au sein d’une même session n’est pas la bonne façon de gérer cela.
La fenêtre de contexte elle-même nécessite également une attention particulière. Un minimum de 4096 tokens était un seuil raisonnable lorsque le schéma disponible provenait d’un seul serveur. Avec quatre serveurs et une liste d’outils réduite mais encore importante, 4096 est trop faible. Il faut augmenter fortement cette valeur, éventuellement au-delà de 32 k, en fonction de ce que le modèle et le matériel peuvent gérer ainsi que de la durée prévue pour les échanges. Aucun chiffre unique n’est correct. Il s’agit d’un compromis entre l’espace de raisonnement et la mémoire VRAM disponible, il faut donc surveiller le pourcentage de remplissage du contexte affiché par LM Studio sous la zone de saisie du chat et l’ajuster en conséquence.
Étape 3 : un plan que le modèle peut suivre
Un agent codé manuellement présente un avantage que l’interface de chat de LM Studio ne fournit pas automatiquement. Dans un script, l’instruction système est une chaîne de caractères Python sous contrôle total, et il est possible d’expliquer explicitement le cycle : rechercher, choisir une source, la récupérer, puis déterminer si cela répond à la question ou s’une autre recherche est nécessaire.
Il vaut mieux être clair sur ce que LM Studio offre réellement plutôt que de suggérer l’existence d’une option de planification cachée. Il n’en existe pas. Il n’y a pas de paramètre de planification distinct.
Ce qui existe, c’est un champ d’instruction système dans la barre latérale du chat, sous « Paramètres du modèle ». Cette instruction peut être enregistrée avec les paramètres de température et de contexte sous forme de préréglage nommé, afin de ne pas avoir à la réécrire à chaque session. C’est le même mécanisme utilisé par un agent codé manuellement, seulement sous forme de champ de texte et non de chaîne de caractères dans du code.
Une instruction système de ce type fonctionne bien pour un chat de recherche :
You are a research assistant with tools for web search, page fetching,
file storage, and GitHub. When asked a factual question you cannot
answer with confidence from memory, follow this plan:
1. Search for the topic using searxng_web_search. Look at more than one
result before deciding a source is good.
2. Fetch the most promising source with camofox's navigate and
snapshot or extract_structured tools, not just the search snippet.
When using camofox always open a new tab before trying to navigate
to a page.
3. If the question needs more than one source to answer confidently,
search again and fetch again before answering.
4. If asked to save findings, write them to a markdown file in the
workspace using the filesystem tools, don't just describe them in chat.
5. State which sources you actually fetched, not just which ones you
found in search results.
Quelques notes sur son fonctionnement :
- Il s’agit de prose simple, sans machine d’état pour la contrôler. Les instructions sont ce que voit le modèle, qui suit généralement leur structure, mais sans aucune garantie, tout comme pour un prompt système à l’intérieur d’un script.
- L’étape 5 est plus importante qu’il n’y paraît. Sans elle, le modèle a tendance à répondre uniquement à partir du fragment de recherche et à sauter l’étape de récupération des données, ce qui annule l’intérêt d’inclure Camofox dans le processus.
- En enregistrant le résultat en tant que préréglage, il peut être conservé entre les conversations sans avoir à être recollé à chaque fois.
Dans l’image d’écran, le prompt se trouve sous « Paramètres du modèle » et le préréglage est enregistré sous le nom « Research Chat ». Avec le prompt et la liste des outils affinée en place, le modèle dispose des capacités nécessaires ainsi que d’une sorte de plan pour les utiliser. La question qui reste est de savoir s’il les utilise réellement.
Étape 4 : une démonstration prouvant que les outils ont été utilisés
Un bon test de connaissance de base doit obliger à l’utilisation réelle d’outils. Un rappel confiant de la mémoire ne peut pas produire la bonne réponse ; par conséquent, le modèle soit consulte une source réelle, soit devine. La tâche doit être quelque chose qu’il ne peut pas avoir mémorisé, vérifiable de manière indépendante, et suffisamment générale pour ne pas porter sur une personne spécifique.
Un exemple adapté : indiquer à l’agent un dépôt qui est maintenu ou sur lequel on compte, et lui demander de suivre la version fixée d’une dépendance jusqu’aux avis de sécurité déposés concernant cette version précise. Le texte ci-dessous peut être collé dans la conversation après avoir rempli trois champs réservés :
I want you to check one dependency in a GitHub repository for known
security advisories. Do this:
1. In the repository <owner>/<repo>, read <manifest-file> using
get_file_contents.
2. From that file, find the exact pinned version of the dependency
"<dependency-name>".
3. Search the web for known security advisories filed against that
specific version of "<dependency-name>".
4. Fetch the actual advisory page(s) you find rather than relying on
the search snippet alone.
5. Write a short summary to dependency-risk.md in the workspace: the
dependency name, the pinned version, any advisories found (with
severity and a link), and a one-line recommendation.
Les placeholders fonctionnent de la manière suivante :
<owner>/<repo>désigne tout répertoire disposant d’accès en lecture. Un projet personnel est tout aussi valable qu’un projet public qui se trouve être une dépendance.<manifest-file>indique le nom du fichier de dépendances sur lequel le projet repose, par exemplego.mod,pyproject.toml,requirements.txtoupackage.json.<dependency-name>correspond à une seule dépendance figurant dans ce manifeste, de préférence une qui présente un intérêt réel.
En l’absence d’un dépôt adapté sous la main, juice-shop/juice-shop, l’application de formation délibérément peu sécurisée d’OWASP, peut faire l’affaire. Son package.json contient suffisamment de dépendances déjà marquées pour que l’étape de recherche trouve généralement quelque chose de pertinent, et express-jwt ainsi que sanitize-html constituent des choix de départ judicieux. Une version complétée ressemble à ceci :
I want you to check one dependency in a GitHub repository for known
security advisories. Do this:
1. In the repository juice-shop/juice-shop, read package.json using
get_file_contents.
2. From that file, find the exact pinned version of the dependency
"express-jwt".
3. Search the web for known security advisories filed against that
specific version of "express-jwt".
4. Fetch the actual advisory page(s) you find rather than relying
on the search snippet alone.
5. Write a short summary to dependency-risk.md in the workspace:
the dependency name, the pinned version,
any advisories found (with severity and a link),
and a one-line recommendation.
L’envoi de ce texte devrait amener l’agent à effectuer les cinq étapes dans l’ordre : une lecture sur GitHub, une recherche externe, une récupération externe, et enfin une écriture de fichier, au rythme permis par le matériel.
Une exécution complète de cette instruction a utilisé les quatre serveurs MCP et a consommé un total de 37803 tokens.
Cette instruction a été choisie délibérément. La réponse dépend du répertoire et de ce qui y est marqué comme prioritaire, de plus les bases de données CVE consultées sont mises à jour en permanence, ce qui empêche de citer à l’avance un résultat fixe.
Vérifier le fonctionnement du modèle se fait en deux étapes. Ouvrez le manifeste et lisez personnellement la version enregistrée pour confirmer ce que GitHub a retourné. Ensuite, testez l’information fournie en la comparant à la recherche des Avis de sécurité de GitHub ou à celle du NVD. Si les résultats correspondent à ceux du rapport de l’agent, cela constitue une preuve concrète : le modèle a bien lu le manifeste et a bien chargé la page correspondant à l’avis de sécurité, et il n’a pas répondu en se basant sur un souvenir vague selon lequel une bibliothèque aurait un CVE à un moment donné.
La démonstration montre également que l’en-tête en lecture seule de l’étape 2 est suffisant. Tout le processus consiste en des lectures depuis GitHub, des recherches externes, des récupérations externes et une écriture dans un fichier local ; par conséquent, aucun accès d’écriture de GitHub n’est nécessaire, et l’en-tête peut rester en place. Une seule commande active les quatre serveurs en une seule passe : GitHub lit le manifeste, SearXNG recherche les alertes, Camofox récupère les pages relatives aux alertes et le système de fichiers enregistre le rapport. Cela constitue un moyen rapide de vérifier que toute la configuration est correctement configurée avant de l’utiliser pour de véritables recherches.
Où cela échoue
Il vaut mieux identifier les points faibles plutôt que de prétendre que la chaîne est fiable de bout en bout.
Parfois, le modèle répond en se basant sur l’extraits de recherche et omet de récupérer la page, même si l’instruction système lui dit le contraire. Ce phénomène apparaît plus fréquemment pour des questions courtes et simples, où le modèle semble juger que l’extraits est suffisamment bon. Un message de suivi lui indiquant de récupérer la page résout généralement le problème. Ce n’est pas que le modèle ne puisse pas le faire, mais plutôt qu’un modèle de 9 milliards de paramètres commet parfois des erreurs dans ces jugements.
Occasionnellement, confronté à des dizaines d’outils GitHub qu’il n’a jamais utilisés, le modèle choisit un outil plausible mais incorrect, comme list_pull_requests au lieu de list_issues. Le tri effectué à la phase 2 constitue la meilleure défense : un menu plus court de choix similaires réduit les chances de choisir l’outil erroné.
Rien de tout cela ne fait de cet agent un pipeline déterministe. Lorsque le déterminisme est requis, un script est l’outil approprié, et une boucle codée manuellement y ressemble davantage. L’avantage de connecter les éléments à LM Studio, c’est que le modèle s’adapte à n’importe quelle question posée, mais le prix à payer est qu’il s’adapte parfois mal. Le moyen le plus rapide d’apprendre où on peut lui faire confiance et où il a besoin d’un soutien est de le voir travailler sur quelques questions de recherche.
La configuration finale
Ces quatre étapes permettent à une seule conversation dans LM Studio de faire fonctionner quatre serveurs MCP. Sa liste d’outils a été réduite afin que le contexte dispose encore d’espace pour la réflexion. Un prompt système fournit au modèle de 9 milliards de paramètres une structure à suivre là où il n’y avait auparavant qu’une page blanche, et une démonstration de grounding montre que des pages réelles sont chargées plutôt que des réponses rappelées de la mémoire. En termes concrets :
- Le système de fichiers, GitHub, SearXNG et Camofox sont tous activés au sein d’une seule conversation.
- Un ensemble réduit d’outils, ainsi qu’une fenêtre de contexte suffisamment grande pour accueillir le schéma combiné, plutôt que la contrainte d’un seul serveur.
- Un prompt système enregistré en tant que préréglage, qui amène le modèle à planifier automatiquement un cycle de recherche, de récupération et d’enregistrement, en utilisant ce que l’interface de LM Studio expose réellement et non une option de configuration inexistante.
- Une démonstration de mise en contexte reproductible, dont chaque partie peut être vérifiée indépendamment, et qui prend en charge les quatre serveurs grâce à un seul prompt.
Il est possible de l’élargir. Un deuxième moteur de recherche en complément de SearXNG permettrait de comparer les résultats entre eux. Une étape de résumé après chaque récupération empêcherait les pages longues d’absorber trop de contexte lors de leur chargement. Pour ceux qui le font régulièrement, automatiser la création des préférences permettrait de démarrer chaque nouvelle session de recherche correctement configurée, sans avoir à effectuer de réglages manuels.
Une conclusion revient sans cesse : après avoir assemblé manuellement les éléments bruts — système de fichiers, recherche, navigation et hébergeur de code — et observé où chacun d’eux pose des problèmes, un framework d’agent plus lourd n’est en réalité que les mêmes composants dissimulés derrière une abstraction supplémentaire. Accepter cet échange semble logique uniquement pour ceux qui comprennent déjà ce qui se trouve en dessous.
Lectures complémentaires
- Notes pratiques : Construire un agent financier IA avec le serveur MCP d’EODHD — Guide pas à pas des Notes pratiques : Construire un agent financier IA avec le serveur MCP d’EODHD : contrats, vérifications et emplacements de code prêts à l’emploi pour les équipes qui développent des systèmes MCP sans cela.
- Playwright ou agents navigateur ? Où l’automatisation scriptée reste gagnante — Comparaison des scripts Playwright et des agents navigateur pilotés par MCP : fragilité, déterminisme, coût, une tâche de facturation mise en pratique, outils à surveiller, risques de sécurité et cadre de décision.