1. ローカルに WebSearch 環境を構築
Windows 11 環境において、LM Studio で動作する AI Agent(ローカルLLM)に外部インター ネット検索機能を持たせ、ソース(参考リンク)を出力させるには、大きく分けて2つの アプローチがありる。
-
LM Studio 標準の「MCP (Model Context Protocol)」機能を利用する(単体完結)
-
「AnythingLLM」などの外部フロントエンドツールと連携する(高機能・GUIが優秀)
現在は LM Studio 自体が Anthropic の提唱する MCP(Model Context Protocol)を標準 サポートしているため、LM Studio の画面内だけで完結させる方法(方法1)が最も シンプルでおすすめです。
1.1. 方法1:LM StudioのMCP(Model Context Protocol)機能を利用する
LM Studio に「Brave Search」などの外部検索 MCP サーバーを登録することで、AI が自律的に インターネットを検索し、ソース付きで回答を生成できるようになる。
1.1.1. 必要な前提環境の準備
-
Windows 11 に Node.js または Python (uvx) がインストールされている必要がある (MCP サーバーの実行に必要です)。
-
💡 Node.js(LTS版)を公式サイト等からインストールしておくのが最も確実です。
-
-
検索 API キーの取得:
-
無料で使える AI 向け検索 API として Brave Search API が広く使われている。 「Brave Search API Dashboard」等から無料枠(Free Tier)の API キーを 取得してください。
-
1.1.2. LM Studioでの設定手順
-
Tool使用(Function Calling)対応モデルの用意:
-
LM Studio 内で、ツール利用に対応したモデル(例:
Gemma 3,Llama 3.1/3.2 Instruct,Qwen 2.5 Instructなど)をダウンロードする。 -
モデル名の横にハンマー(かなづち)のアイコンがついているものが対応モデルです。
-
-
mcp.jsonの編集:-
LM Studio の右側パネル、または設定(Settings)から 「Edit mcp.json」 を開く。
-
以下のように、Brave Search MCPサーバーの設定を記述する(Node.jsの
npxを利用する例です)。
-
{
"mcpServers": {
"brave-search": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-brave-search"
],
"env": {
"BRAVE_API_KEY": "YOUR_BRAVE_API_KEY_HERE"
}
}
}
}
3.MCP の有効化とチャットでの利用:
-
設定を保存すると、LM Studio のチャット画面の右側(Integrations / Tools)に
brave-searchが表示される。 -
トグルを ON にし、ピン留め(Pin)する。
-
チャットで「最新の日本のニュースは?」など、ローカルの知識にない質問を投げると、 AI Agent が自動的に外部検索を実行して情報を補完し、参考リンク付きで回答を出力する。
1.2. 方法2:AnythingLLM(フロントエンド)と連携する
チャットの UI や参考リンクの表示の見やすさ、引用元へのアクセスのしやすさを重視する 場合、LM Studio をバックエンド(API サーバー)として扱い、フロントエンドに AnythingLLM (デスクトップ版)を組み合わせる構成が非常に強力です。
-
LM Studio側の設定(APIサーバー化)
-
LM Studioの左側メニューから「Local Server」(開発者向けタブ)を開く。
-
上部のドロップダウンで、Tool利用に対応したモデルを選択してロードする。
-
「Start Server」 をクリックして、OpenAI互換のローカルAPIサーバーを起動する (デフォルトでは
http://localhost:1234/v1で起動)。
-
-
AnythingLLM側の設定
-
AnythingLLMのインストール: 公式サイトからWindows版をダウンロードしてインストールする。
-
LLMの接続設定:
-
初期設定、または設定画面の「LLM Provider」で 「LM Studio」 を選択する。
-
Base URLに
http://localhost:1234/v1を指定し、LM Studio側でロードしたモデルを選択する。
-
-
Agentスキルの設定(Web Searchの有効化):
-
ワークスペースの設定、または「Agent Skills」メニューを開く。
-
「Web Search」 を ON にする。
-
検索プロバイダー(Search Provider)を選択する。
-
Google Programmable Search、Brave Search、あるいは完全無料でローカル構築可能な SearXNG(Dockerが必要)などが選ぶ。APIキー等を入力して保存する。
-
-
ついでに 「Scrape websites」 もONにしておくと、検索で見つかったURLの中身をAIが読み込めるようになる。
-
-
-
利用方法
-
AnythingLLMのチャット画面で、プロンプト入力欄の近くにある「Agent Mode」(あるいは @agent を入力)を指定して質問する。
-
AI Agentが自動的に検索エンジン経由で情報を補完し、回答の末尾や途中にクリック可能な参考リンク(ソース)を綺麗に明示してくれる。
- 💡 構築成功のための重要なポイント
-
-
モデルの選定: 外部検索(Tool呼び出し)を正確に行うには、パラメータ数が少なすぎるモデル(1B〜3Bクラス)だと指示を無視したり、検索クエリの組み立てに失敗することがある。PCのスペック(VRAM容量)が許す限り、8B(80億パラメータ)クラス以上の「Instruct」モデルを使用することをお勧めする。
-
-
どちらの手法も、一度環境を作ってしまえば「機密性の高い処理は完全にローカル」「最新情報の検索時のみ外部APIを使用」というハイブリッドで安全なAI Agent環境が実現可能です。
2. WebSearch の自作(制限なし)
Windows 11 + LM Studioの環境で、「完全無料・無制限」の検索MCPサーバーをRustで構築 する場合、最大の鍵は「APIキーが不要な検索手段をどう確保するか」です。Brave SearchやSerperなどのAPIは無料枠に制限がある。
完全無料・無制限を実現するには、「SearXNG(プライベートインスタンス)」をローカルで立ち上げてそれを叩くか、「DuckDuckGoなどのスクレイピング(あるいはDDGのLite版やhtml版のパース)」を利用するのが現実的です。ここでは、最もシンプルかつ規制されにくい「DuckDuckGoのHTML/JSONエンドポイントを内部的に利用する形」、または「SearXNG連携」を想定し、ホワイトリスト/ブラックリスト機能を組み込んだRust製MCPサーバーの具体的な実装方法を解説する。
2.1. 🛠️ 開発環境と構成
-
OS: Windows 11
-
ランタイム: LM Studio (MCPクライアント)
-
言語: Rust
-
主要クレート:
-
tokio: 非同期処理
-
reqwest: 検索クエリの送信・HTML取得
-
scraper: HTMLパース用(スクレイピングの場合)
-
serde / serde_json: 設定ファイル(リスト)やMCPプロトコルの処理
-
url: ドメインの抽出とフィルタリング
-
2.2. 📂 プロジェクトの作成と依存関係
まず、Cargoプロジェクトを作成し、Cargo.toml に必要なライブラリを設定します。
[package]
name = "mcp-free-search"
version = "0.1.0"
edition = "2021"
[dependencies]
tokio = { version = "1.0", features = ["full"] }
reqwest = { version = "0.12", features = ["json"] }
scraper = "0.19" # スクレイピング用
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
url = "2.5"
2.3. 💻 具体的な実装コード (main.rs)
MCP は標準入力(stdin)と標準出力(stdout)を使ってJSON-RPCで通信します。
以下は、ホワイトリスト/ブラックリストの読み込み機能と、検索機能を備えた MCP
サーバーの骨子です。
use serde::{Deserialize, Serialize};
use std::collections::HashSet;
use std::fs::File;
use std::io::{self, BufRead, Write};
use url::Url;
// --- データ構造定義 ---
#[derive(Deserialize, Debug)]
struct FilterLists {
whitelist: HashSet<String>,
blacklist: HashSet<String>,
}
#[derive(Deserialize)]
struct McpRequest {
jsonrpc: String,
method: String,
params: Option<serde_json::Value>,
id: Option<serde_json::Value>,
}
#[derive(Serialize)]
struct McpResponse {
jsonrpc: String,
result: serde_json::Value,
id: Option<serde_json::Value>,
}
// --- フィルタリングロジック ---
fn is_allowed(url_str: &str, lists: &FilterLists) -> bool {
let parsed_url = match Url::parse(url_str) {
Ok(u) => u,
Err(_) => return false,
};
let domain = parsed_url.host_str().unwrap_or("").to_string();
// 1. ブラックリストチェック (マッチしたら除外)
if !lists.blacklist.is_empty() && lists.blacklist.iter().any(|d| domain.contains(d)) {
return false;
}
// 2. ホワイトリストチェック (リストが空でなければ、マッチしたものだけ許可)
if !lists.whitelist.is_empty() {
return lists.whitelist.iter().any(|d| domain.contains(d));
}
true
}
// --- 検索エンジン連携 (例: DuckDuckGo HTMLパース) ---
// ※注意: 大量リクエスト時は一時的にブロックされる可能性があるため、
// 本格運用の場合はローカルに「SearXNG」をDocker等で立てて、そのAPIを叩く形が最も安定します。
async fn search_internet(query: &str, lists: &FilterLists) -> Result<Vec<String>, Box<dyn std::error::Error>> {
let client = reqwest::Client::builder()
.user_agent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36")
.build()?;
// DuckDuckGoのHTML版を利用する例
let url = format!("https://html.duckduckgo.com/html/?q={}", urlencoding::encode(query));
let res = client.get(&url).send().await?.text().await?;
let document = scraper::Html::parse_document(&res);
let selector = scraper::Selector::parse(".result__url").unwrap();
let mut results = Vec::new();
for element in document.select(&selector) {
if let Some(raw_url) = element.text().next() {
let clean_url = raw_url.trim();
// フィルタリングの適用
if is_allowed(clean_url, lists) {
results.push(clean_url.to_string());
}
}
}
Ok(results)
}
// --- メインループ (LM Studioとの標準入出力通信) ---
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// 1. 外部定義のリストを読み込み (config.json)
let file = File::open("config.json").into_iter().next()
.ok_or("config.json が見つかりません。")?;
let lists: FilterLists = serde_json::from_reader(file)
.unwrap_or(FilterLists { whitelist: HashSet::new(), blacklist: HashSet::new() });
let stdin = io::stdin();
let mut handle = stdin.lock();
let mut buffer = String::new();
// LM Studioからのリクエストを一行ずつ処理
while handle.read_line(&mut buffer)? > 0 {
let req: McpRequest = match serde_json::from_str(&buffer) {
Ok(r) => r,
Err(_) => {
buffer.clear();
continue;
}
};
// MCPのメソッド判定
if req.method == "tools/call" {
// 例として、LLMから渡されたクエリを取得
if let Some(params) = req.params {
if let Some(query) = params.get("arguments").and_then(|a| a.get("query")).and_then(|q| q.as_str()) {
// 検索の実行
if let Ok(search_results) = search_internet(query, &lists).await {
let response = McpResponse {
jsonrpc: "2.0".to_string(),
result: serde_json::json!({
"content": [{
"type": "text",
"text": format!("検索結果: {:?}", search_results)
}]
}),
id: req.id,
};
println!("{}", serde_json::to_string(&response)?);
io::stdout().flush()?;
}
}
}
}
buffer.clear();
}
Ok(())
}
2.4. 📂 設定ファイルの準備 (config.json)
実行バイナリと同じディレクトリに、以下のような config.json を配置します。ドメインの部分一致で判定します。
{
"whitelist": [],
"blacklist": [
"wikipedia.org",
"w3schools.com"
]
}
注意: whitelist にドメインを記述すると、そこに書かれたドメインしか検索結果に表示されなくなります。基本は blacklist 運用がおすすめです。
2.5. 🛠️ LM Studio への登録方法
1.Rustプロジェクトをビルドします。
cargo build --release
2.生成された target/release/mcp-free-search.exe の絶対パスをコピーします。
3.LM Studio の MCP 設定画面(または ~/.lmstudio/mcp-config.json)に以下のように登録します。
{
"mcpServers": {
"free-search-server": {
"command": "C:/path/to/your/project/target/release/mcp-free-search.exe",
"args": [],
"env": {}
}
}
}
2.6. 💡 より安定して「無制限」に運用するためのワンポイント
上記コードで紹介したDuckDuckGoなどの直接スクレイピングは、LM Studioから短時間に大量の検索をかけると、一時的にロボット判定(403 Forbiddenやセッションブロック)を受けるリスクがあります。
これを完全に回避し、文字通り「無制限・無料」で安定運用したい場合の最強の構成は「SearXNG」のローカルローテーションです。
-
Windows 11にDocker Desktopを入れ、オープンソースのメタ検索エンジンSearXNGをローカル(localhost:8080)で起動する。
-
SearXNGは内部でGoogle、Bing、DuckDuckGoなどの結果を自動で束ねてJSONで返してくれるため、Rust側からは単に http://localhost:8080/search?q=…&format=json を叩くだけで良くなります(APIキー不要)。
-
Rustの search_internet 関数内を、SearXNGのローカルAPIを叩く処理に書き換える。
この構成にすれば、スクレイピングのパースコードが相手のサイトデザイン変更で壊れる心配もなくなり、非常に堅牢なプライベート検索MCPサーバーが完成します。
3. 検索でDB参照
3.1. 共通の環境設定手順
3.1.1. ステップ1: 事前準備(Windows環境の整備)
MCPサーバーの多くは Node.js (npx) や .NET Core、Python をベースに動作します。まずはWindows 11に以下のランタイムをインストールしておきます。
-
Node.js (LTS推奨):パッケージマネージャー(npm/npx)を使用するために必須です。
-
.NET 8.0 SDK / Runtime:Microsoft製のSQL MCP Serverを動かす場合に必要です。
3.1.2. ステップ2: LM StudioのMCP設定ファイルを開く
LM Studioは、アプリ内の設定、または以下のローカルパスにある mcp.json(または mcp-config.json)でMCPサーバーを管理します。
- 設定ファイルの標準的なパス
-
C:/Users/<ユーザー名>/.lmstudio/mcp.json
(※LM Studioの画面左側、あるいは設定(歯車マーク)の「MCP」項目からも直接エディタで編集・追加が可能です)
3.1.3. ステップ3: mcp.json へのサーバー登録
複数のRDBMS(SQL Server, PostgreSQL, MySQL)を1つでカバーできるMicrosoft公式の SQL MCP Server (Data API builder) を登録する例です。
mcp.json の mcpServers オブジェクト内に以下のように記述します。
{
"mcpServers": {
"sql-mcp-server": {
"command": "dotnet",
"args": [
"tool",
"run",
"dab",
"start"
],
"env": {
"DAB_ENVIRONMENT": "Development"
}
}
}
}
(※あらかじめ dotnet tool install --global Microsoft.DataAPIBuilder でDABをインストールしておくか、各DB専用のNode.js製MCPサーバーを個別指定する方法もあります。個別指定の記述は後述の「DB毎のアプローチ」を参照してください)
3.2. AI Agentでの利用手順・プロンプト例
環境設定が完了し、LM Studio側でMCPサーバーが「Green(接続済み)」になったら、AI Agent(Tool Use / Function Callingに対応したモデル、例: qwen2.5-coder-14b や Llama-3 系など)を起動します。
AI Agentは自動的にDBのスキーマを解読するツール(list_tables や describe_table、execute_query など)を認識します。
- データの検索(プロンプト例)
-
「usersテーブルから、先月登録されたアクティブなユーザーを最大10件検索して、名前とメールアドレスの一覧を出力してください。」
- データの集計(プロンプト例)
-
「ordersテーブルとproductsテーブルを結合し、商品カテゴリごとの売上合計金額を計算して、売上が高い順にランキング形式で教えてください。」
- Agentの内部挙動
-
-
AIが指示を理解し、適切なSQLクエリ(SELECT … GROUP BY …)をバックグラウンドで自動生成。
-
MCPサーバー経由で対象のDBにクエリを発行。
-
返ってきたJSON形式の集計データを、AIが自然な日本語の文章や表に整形してユーザーに回答。
-
3.3. DB毎のアプローチと接続文字列・個別設定
Microsoft製のSQL MCP Serverで対応しきれない場合や、よりシンプルな軽量プラグイン(Node.js/npx)を用いて個別に接続する場合の、DBごとのアプローチと設定方法です。
-
① PostgreSQL / MySQL / MariaDB
これらは最も標準的なMCPサーバーが用意されています。個別に立ち上げる場合は npx を利用するのが最も手軽です。-
PostgreSQL用の設定例(mcp.json):
-
"postgres-mcp": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-postgres",
"postgresql://username:password@localhost:5432/mydb"
]
}
-
MySQL / MariaDB用の設定例:
公式またはサードパーティ製の mcp-server-mysql 等を利用し、接続URL(mysql://user:pass@host:port/db)を引数に渡します。-
② SQL Server (オンプレミス / Azure SQL)
MicrosoftのSQL MCP Server(Data API builder)を使用する場合、カレントディレクトリに dab-config.json という接続設定ファイルを配置します。
-
-
接続文字列の例:
Server=tcp:localhost,1433;Initial Catalog=mydb;User Id=sa;Password=YourPassword;TrustServerCertificate=True; -
Windowsの統合認証(Windows認証)を使用する場合は、LM Studioを実行しているユーザー権限でDBにアクセスできるよう、接続文字列に
Integrated Security=True;を指定します。-
③ SQLite (ローカルファイルベース)
サーバーを常時起動していない軽量なSQLiteの場合、ローカルの .db ファイルの絶対パスをMCPサーバーに教える必要があります。
-
-
SQLite用の設定例(mcp.json):
"sqlite-mcp": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-sqlite",
"C:\\path\\to\\your\\database.db"
]
}
※Windows環境ではパスの区切り文字(\)を \\ とエスケープすることを忘れないでください。
-
④ Oracle Database Oracleは独自のクライアント(Instant Client)や太いドライバ層が必要になることが多いため、汎用のNode.js製MCPよりも、Pythonベース、または専用にラップされたMCPサーバー(LobeHub等で公開されている
samscarrow-mcp-servers-lmstudioのOracle版など)を利用するのが確実です。-
アプローチ: Dockerで中継コンテナを立てるか、Pythonの
oracledbライブラリを使用した自作の軽量MCPスクリプトを"command": "python"で呼び出す方式が、Windows環境では最も接続エラー(環境変数の競合など)を起こしにくく安定します。
-
3.4. ⚠️ Win11環境における注意点(セキュリティと権限)
-
読み取り専用(Read-Only)の徹底: AI Agentに直接クエリを発行させる場合、プロンプトインジェクション等によって意図しないデータ削除(DROP や DELETE)が実行されるリスクがあります。MCP経由で接続するDBユーザーには、必ず参照権限(SELECT)のみを付与した専用アカウントを設定してください。
-
文字コード(UTF-8): Windows環境のRDBMSで日本語データを扱う場合、Agentに渡却されるデータが文字化けしないよう、DB側のエンコーディングがUTF-8になっているか、または接続文字列のオプションで適切な文字コードを指定してください。