GPT研究者 + スクラペレスMCP: あなたの研究エージェントにリアルなフェッチレイヤーを提供する
Senior Web Scraping Engineer
TL;DR:
- GPTリサーチャーはリトリーバーを通じてウェブを読み、
mcpリトリーバーは任意のMCPサーバーを研究ソースに変える — したがって、Scrapeless MCPサーバーは実際にページを取得するレイヤーになります。 RETRIEVER=mcpの設定は必須です。mcp_configsをそれなしで渡すとMCPリトリーバーはオフのままになり、実行は設定されている他のものに戻ります。- stdioトランスポートは現在機能するパスです:
npx -y scrapeless-mcp-server@0.4.9はSCRAPELESS_KEYをenvで使用してすべての21ツールを読み込みます。 - リモート
connection_urlパスはリリースされたクライアントでは認証されません。connection_tokenはサポートされていないtoken引数としてトランスポートに到達し、connection_headersはまったくそれに到達しません。 - バージョンを固定してください。
gpt-researcher==0.16.0はインポート時にNameErrorを引き上げ、mcpの1.28以降のリリースはlangchain-mcp-adapters内部でMCPサポートをエラーメッセージなしで無効にします。 scrape_markdownはhttps://quotes.toscrape.com/でリトリーバーを通じて4308文字のページコンテンツを返し、モデルが関与する前にそれを呼び出すことができます。- 研究実行そのものにはモデルプロバイダーキーだけが必要です。ツールの読み込みと呼び出しにはあなたのScrapelessキーだけが必要です。
- Scrapeless無料プランから始めて、あなたの研究エージェントに実際の取得レイヤーを提供してください。
GPTリサーチャーはクエリを計画し、検索し、見つけたものを読み、引用された報告書を書きます。検索部分は十分にサポートされています — Google、Bing、Brave、arXiv、PubMedなどのリトリーバーが提供されています。読み取り部分は自律的研究が静かに劣化するところです:リトリーバーはURLのリストを返し、そのURLをテキストに変換する何かがまだ必要です。その取得が挑戦ページや空のシェルを返すと、報告書はそれに関わらず、返ってきた薄いコンテンツから書かれます。
mcpリトリーバーはそのスロットに配置されるものを変更します。GPTリサーチャーをMCPサーバーに向けると、サーバーのツールが研究の表面になり、ページ取得は平凡なHTTP GETではなくそれに対して構築されたインフラストラクチャを通じて実行されます。このガイドはGPTリサーチャーをScrapeless MCPサーバーに接続し、それが公開するツールをリストし、実際に1つを呼び出し、モデルプロバイダーキーを最初に必要とするステップを正確に示します。
Scrapeless MCPサーバーが研究エージェントに提供するもの
Scrapeless MCPサーバーはモデルコンテキストプロトコルを介してスクレイピングとブラウザツールを公開しているので、取得レイヤーはあなたのエージェントが呼び出すものであり、構築するものではありません。1つの接続が21のツールを提供します:ページコンテンツ用のscrape_markdownとscrape_html、検索データ用のgoogle_searchとgoogle_trends、キャプチャ用のscrape_screenshot、およびナビゲーション、クリック、タイプ、スクロール、待機を通じてクラウドブラウザを駆動する16ツールのbrowser_*セットです。
研究エージェントにとって重要なのはscrape_markdownです。GPTリサーチャーの報告書の質は収集したテキストに依存し、Markdownはすでにそのコンテキストが求める形です。ソースがインタラクションの後にのみレンダリングされる場合、browser_*ツールが重要です — それらはScrapelessクラウドブラウザで実行されるため、エージェントは研究マシン上にブラウザがなくてもレンダリングされたページに到達できます。
プロトコルレイヤーはモデルコンテキストプロトコル仕様に従い、そのメッセージはJSON-RPC 2.0仕様を介して伝達されます。プロトコルをその用語で最初に説明してほしい場合は、MCPとは何かがそれをカバーし、LangChain + Scrapeless MCPが異なるスタックに接続された同じサーバーを示しています。
前提条件
- Python 3.10以降。
- 研究を実行するマシン上のNode.js、なぜならstdioトランスポートは
npxでサーバーを起動するからです。 - ダッシュボードから取得したScrapeless APIキー、
SCRAPELESS_KEYとしてエクスポートします。 OPENAI_API_KEYのようなモデルプロバイダーキー。GPTリサーチャーは研究者オブジェクトを構築する際に埋め込みクライアントを構築するため、この変数はそのステップの前に設定されなければなりません — MCPツールの呼び出しを含むすべてはそれなしで機能します。
インストール
バージョン固定はここではオプションではなく、2つの特定のピンが実際の作業を行います。
bash
pip install "gpt-researcher==0.15.1" "langchain-mcp-adapters==0.3.1" "mcp==1.27.2"
gpt-researcher==0.16.0 はインポートできません。actions/query_processing.py は Any と List の数行上の from typing import Any, List, Dict を定義するというシグネチャに注釈を付けるヘルパーを定義しているため、プレーンな def 上の注釈は関数オブジェクトが構築される時に評価されます — これは 遅延注釈提案 によって変更されるように書かれた動作であり、他の何かが実行される前にインポートは NameError: name 'Any' is not defined を発生させます。バージョン 0.15.1 にはその順序の問題はありません。
mcp ピンはより微妙です。langchain-mcp-adapters は、Python の依存関係仕様の仕様 で説明されている意味での無制限のフロアとして mcp>=1.9.2 として要求を宣言しますので、新規インストールは最新の mcp を引き寄せます。リリース 1.28 以降はもはや RequestContext を mcp.shared.context からエクスポートせず、アダプターはモジュールロード時にそれをインポートします。GPT Researcher はその ImportError をキャッチして内部の可用性フラグを false に設定するため、MCP は騒音を立てずに失敗することはなく — それは単に存在を停止し、あなたの研究はサーバーに触れることなく実行されます。
シェルではなくソースでキーを設定してください。
bash
export SCRAPELESS_KEY="your_api_key_here"
stdio 経由で接続してツールをリストする
GPT Researcher の MCP レイヤーはサーバー構成辞書のリストを受け取ります。stdio サーバーの場合、名前、コマンド、その引数、そしてサーバーが必要とする環境を提供します。MCPClientManager はそれを輸送構成に変換し、ハンドシェイクを実行します。
python
import asyncio
import os
from gpt_researcher.mcp.client import MCPClientManager
SCRAPELESS = {
"name": "scrapeless",
"command": "npx",
"args": ["-y", "scrapeless-mcp-server@0.4.9"],
"env": {"SCRAPELESS_KEY": os.environ["SCRAPELESS_KEY"], "PATH": os.environ["PATH"]},
}
async def main() -> None:
manager = MCPClientManager([SCRAPELESS])
tools = await manager.get_all_tools()
print("tool count:", len(tools))
print("tools:", ", ".join(sorted(tool.name for tool in tools)))
asyncio.run(main())
PATH を env に含めてください。サーバープロセスは、提供された環境で正確に生成されるので、PATH を省略すると npx が見つけられなくなります。
ライブサーバーは設定された Scrapeless キーだけで 21 のツールを返します。
text
tool count: 21
tools: browser_click, browser_close, browser_create, browser_get_html, browser_get_text, browser_go_back, browser_go_forward, browser_goto, browser_press_key, browser_screenshot, browser_scroll, browser_scroll_to, browser_snapshot, browser_type, browser_wait, browser_wait_for, google_search, google_trends, scrape_html, scrape_markdown, scrape_screenshot
リモート URL パスがまだ機能しない理由
GPT Researcher のドキュメントにある構成テーブルは、リモートサーバー用の connection_url と connection_token をリストしており、これはホストされたエンドポイントに自然に適合するように見えます。リリースされたクライアントでは、どちらのキーも認証された接続を得ることができず、午後を費やす前にその理由を見る価値があります。
両方の失敗はネットワーク呼び出しなしで可視化されます。なぜなら、convert_configs_to_langchain_format は輸送が受け取るものを決定する関数だからです。
python
from gpt_researcher.mcp.client import MCPClientManager
URL = "https://api.scrapeless.com/mcp"
with_token = MCPClientManager([
{"name": "s", "connection_url": URL, "connection_token": "PLACEHOLDER"},
]).convert_configs_to_langchain_format()["s"]
with_headers = MCPClientManager([
{"name": "s", "connection_url": URL, "connection_headers": {"x-api-token": "PLACEHOLDER"}},
]).convert_configs_to_langchain_format()["s"]
print("connection_token ->", sorted(with_token))
print("connection_headers ->", sorted(with_headers))
text
connection_token -> ['token', 'transport', 'url']
connection_headers -> ['transport', 'url']
connection_token は token キーになり、ストリーミング可能な HTTP セッションファクトリはそれを受け入れません — 接続試行は _create_streamable_http_session() got an unexpected keyword argument 'token' で終了し、ツールリストは空として戻ります。
connection_headers は全く変換を生き残りません。そのコピーを行うブランチは server_config.get("connection_type") をテストしますが、変換は常に transport キーを書き込むだけなので、テストは決して一致せず、ヘッダーは削除されます。Scrapeless エンドポイントは x-api-token ヘッダーで認証されるため、リクエストは認証されずに到着します。その理由でもツールリストは空であり、これが2つの症状が外部から同一に見える理由です。
ヘッダーを輸送にコピーするリリースが出るまで stdio を使用してください。それは同じサーバーと同じ21のツールに到達します。
エージェントが存在する前にツールを呼び出す
MCP クライアントを通じて読み込まれるツールは通常の呼び出し可能オブジェクトであるため、フェッチレイヤーを独自に操作できます。これは、キーと輸送が正しいことを確認するための最も安価な方法であり、モデルプロバイダーキーは必要ありません。
python
import asyncio
import os
from gpt_researcher.mcp.client import MCPClientManager
SCRAPELESS = {
"name": "scrapeless",
"command": "npx",
"args": ["-y", "scrapeless-mcp-server@0.4.9"],
"env": {"SCRAPELESS_KEY": os.environ["SCRAPELESS_KEY"], "PATH": os.environ["PATH"]},
}
def as_text(result) -> str:
if isinstance(result, str):
return result
if isinstance(result, (list, tuple)):
parts = [b["text"] for b in result if isinstance(b, dict) and "text" in b]
if parts:
return "\n".join(parts)
return str(result)
async def main() -> None:
manager = MCPClientManager([SCRAPELESS])
tools = await manager.get_all_tools()
scrape = next(tool for tool in tools if tool.name == "scrape_markdown")
text = as_text(await scrape.ainvoke({"url": "https://quotes.toscrape.com/"}))
print("characters:", len(text))
print("first line:", text.split("\n")[0])
asyncio.run(main())
その呼び出しは、プロトコルが定義するコンテンツブロックエンベロープに包まれたマークダウンとしてページを返します。as_text はそのエンベロープをフラットにします。これは、RAW 戻り値が文字列ではなくブロックのリストであるため重要です。
text
characters: 4308
first line: Response:
構成を研究者に渡す
輸送が証明されたら、同じ辞書が GPTResearcher に入ります。2つのことが整合しなければなりません: RETRIEVER は mcp を名前付けし、mcp_configs はサーバーを持っていなければなりません。環境変数を逃すと MCP リトリーバーは決して構築されず、これがこの統合が何もしないように見える最も一般的な方法です。
注: このブロックは前提条件のギャップです。
GPTResearcherは__init__の間に埋め込みクライアントを構築するため、オブジェクトが存在する前にOPENAI_API_KEYが存在する必要があり、conduct_researchは実際のモデルクレジットを消費します。この記事の検証環境にはモデルプロバイダーキーが存在せず、以下の配線はリトリーバーの解決まで確認され、研究呼び出し自体は実行されませんでした。
python
import asyncio
import os
os.environ["RETRIEVER"] = "mcp"
from gpt_researcher import GPTResearcher
SCRAPELESS = {
"name": "scrapeless",
"command": "npx",
"args": ["-y", "scrapeless-mcp-server@0.4.9"],
"env": {"SCRAPELESS_KEY": os.environ["SCRAPELESS_KEY"], "PATH": os.environ["PATH"]},
}
async def main() -> None:
researcher = GPTResearcher(
query="Which quotes and authors appear on quotes.toscrape.com?",
mcp_configs=[SCRAPELESS],
)
await researcher.conduct_research()
report = await researcher.write_report()
print(report)
asyncio.run(main())
その割り当ては、GPTResearcher が構築される前に行われなければならないため、研究者は構成オブジェクトを構築する際に環境を読み取ります。ここにあるように、それをインポートの上に置くことは、最も間違いが起きにくい順序です。
RETRIEVER=mcp はScrapelessを特定のページに関する質問に適した唯一の研究ソースにします。 RETRIEVER=tavily,mcp および同様の組み合わせは、検索エンジンをその横に保ち、エージェントが候補ソースを一方で見つけ、もう一方でそれらを読み取ることを可能にします。 MCP_STRATEGY もあり、これは fast にデフォルト設定され、主要なクエリに対してMCPステップを1回実行します; deep は生成されたすべてのサブクエリに対して実行され、比例的にコストがかかります。
実際のソースでサポートされるフェッチ層を研究者に与える準備はできましたか? 無料のScrapelessアカウントを作成し、数行で接続します。
結論
バージョンピンと輸送の選択が定まれば配線は短くなります: gpt-researcher==0.15.1 を mcp==1.27.2 に対してインストールし、RETRIEVER=mcp を設定し、mcp_configs エントリを渡して scrapeless-mcp-server を指し示します。これで21のツールが得られ、scrape_markdown はモデルが関与する前に実際のページコンテンツを返します — これによりフェッチ層は自立してテスト可能になり、完成したレポートを通じてデバッグする必要がなくなります。
二つの罠は覚えておく価値があります。どちらも自らを知らせません。ピンが打たれていない mcp はMCPサポートを静かにオフにし、リモート connection_url パスはあなたの資格情報を床に落とします。どちらも、あなたのサーバーを呼ばずに研究するエージェントという同じ症状を引き起こします。まずツールの数を確認してください; それが21でなければ、下流の何も正常に機能しません。
Scrapelessの価格ページでプランを比較し、完全なツールリファレンスはScrapelessのドキュメンテーションにあります。
よくある質問
Q: MCP接続をテストするためにモデルプロバイダーキーが必要ですか?
いいえ。ツールを読み込み、呼び出すことは完全にMCPクライアントを通じて行われるため、Scrapelessキーだけで輸送が機能することを確認し、実際のURLで scrape_markdown を呼び出すことができます。モデルキーは GPTResearcher を構築する瞬間に必要になります。これは初期化中に埋め込みクライアントが構築されるからです。
Q: mcp_configsを渡したのにMCPサーバーを無視するのはなぜですか?
RETRIEVER 環境変数がほとんどの場合原因です。 mcp_configs だけではMCPリトリーバーを有効にしません; RETRIEVER は mcp を名前で指定する必要があり、単独でも tavily,mcp のようなリストの中でも構いません。 GPTResearcher を構築する前にそれを設定してください。値は研究者が設定を構築している間に読まれます。
Q: ホスティングされたScrapelessエンドポイントに接続できますか、それともサーバーをローカルで実行する必要がありますか?
リリースされたクライアントの mcp_configs を介してはできません。 connection_token は受け入れない引数としてストリーミングHTTPセッションに渡され、 connection_headers は輸送に到達する前に構成変換中にドロップされます。 stdio輸送は同じサーバーに接続し、同じ21のツールを公開するため、今日の作動するパスです。
Q: 高速なMCP戦略と深いMCP戦略の違いは何ですか?
fast、デフォルトは、主要なクエリを使ってMCPステップを1回実行します。 deep はエージェントが生成する各サブクエリについてそれを実行し、カバレッジを広げ、ツール呼び出しとモデル費用を倍増させます。 fast から始め、特定のレポートが薄い場合にのみ deep へ移動します。
Q: RETRIEVER=mcpを単独で使用するべきか、それとも検索リトリーバーと組み合わせるべきですか?
@@mcp をすでに重要なページが分かっている場合には単独で使用してください。エージェントはサブクエリの生成をスキップし、指示したソースを利用します。 tavily,mcp のように組み合わせるのは探索が仕事の一部であるときです — 検索リトリーバーが候補を見つけ、MCPツールがそれらを読み取ります。
Q: なぜ最新のリリースを取らずにmcpをピン留めするのですか?
langchain-mcp-adapters は上限なしで mcp>=1.9.2 を必要とするため、新しい環境では最新のリリースがインストールされます。1.28以降 RequestContext は mcp.shared.context からエクスポートされなくなり、アダプターのインポートが失敗し、GPT ResearcherはMCPを利用不可能として記録します。 mcp==1.27.2 をピン留めするとアダプターのインポートが可能になります。
Q: ツールの数は自分のセットアップで確認すべきものですか?
はい、それは最も迅速な診断手段です。21のカウントは輸送、キー、アダプターがすべて機能していることを意味します。ゼロは接続が認証されなかったことを意味し、 get_all_tools 中の任何の例外は発生するのではなく記録されるため、空のリストは接続失敗を示すあなたのコードの外観です。
Q: scrape_markdownは実際に何を返しますか?
プロトコルコンテンツブロックのリストは、プレーンな文字列ではなく、テキストブロック上のページのマークダウンです。測定または保存する前にフラット化してください — 戻り値を文字列として扱うと、ページの代わりにリストのPython表現が得られます。
Scrapelessでは、適用される法律、規制、およびWebサイトのプライバシーポリシーを厳密に遵守しながら、公開されているデータのみにアクセスします。 このブログのコンテンツは、デモンストレーションのみを目的としており、違法または侵害の活動は含まれません。 このブログまたはサードパーティのリンクからの情報の使用に対するすべての責任を保証せず、放棄します。 スクレイピング活動に従事する前に、法律顧問に相談し、ターゲットウェブサイトの利用規約を確認するか、必要な許可を取得してください。



