HEROZ Tech Blog

日本将棋連盟公認「将棋ウォーズ」や、AIを活用したシステム企画・開発を行う、AI企業HEROZの公式テックブログです。

クロスプラットフォーム開発の現在地:なぜ私はReact NativeからFlutterへ移行するのか (2025年版)

はじめに

こんにちは。クロスプラットフォーム開発の選定に頭を悩ませているエンジニアです。 「一度書けばどこでも動く(Write Once, Run Anywhere)」——これは我々エンジニアにとって永遠の夢ですが、現実はそれほど甘くありません。

今回、「Webアプリの資産を活かしたネイティブアプリ開発」を目指してReact Nativeに取り組みましたが、特にデスクトップ(Windows)対応において想像以上の「茨の道」を経験しました。その結果、Flutterへの移行を決断するに至った経緯と、その技術的な裏付けを共有したいと思います。

クロスプラットフォームフレームワークの概況

まず、現在利用可能な主要なクロスプラットフォーム技術を整理します。モバイルだけでなくデスクトップ(Windows/macOS)も視野に入れると、選択肢は以下のように絞られます。

フレームワーク 言語 主幹企業 特徴 今回の評価
React Native JS / TS Meta / Microsoft Web技術(React)を使用。OS標準のUIを描画。 Web資産流用は魅力的だが、デスクトップ対応に難あり。
Flutter Dart Google 独自の描画エンジン(Skia/Impeller)を使用。全OSで均一なUI。 今回の採用候補。安定性とパフォーマンスが高い。
.NET MAUI C# Microsoft Xamarinの後継。Windowsとの親和性は最強だが、モバイル開発体験は好みが分かれる。 Windows特化ならありだが、モバイル含めると学習コスト高。
Electron JS / TS OpenJS Fdn. Web技術そのもの(Chromium)で動作。 デスクトップ専用のため、モバイル対応不可。
Unity C# Unity ゲームエンジン ゲーム専用。一般的なUIアプリには不向き。

当初、Web(React)の知見を最大限活かせる React Native が最適解だと考え、プロジェクトをスタートしました。

(余談)Expo vs React Native CLI の落とし穴

開始当初、私は「Expoは開発用で、最終的に純粋なネイティブコードにはならない」という古い認識を持っていました。そのため、あえて難易度の高い React Native CLI を選択しました。 しかし、調査を進めると現在の Expo は prebuild 機能により、完全にネイティブなプロジェクトを生成できることが判明しました。CLIを選んでしまったことで、Windowsのビルド環境(Visual Studioのソリューションファイル)を自力で管理する羽目になり、これが後の苦戦の伏線となりました。

React Native での挑戦と「構造的限界」

React Nativeでの開発を始めてすぐに、「Webのように書けるが、Webではない」 という現実に直面しました。特にWindows対応において、以下の構造的な壁にぶつかりました。

エコシステムの分断

React Nativeは「一枚岩」ではありません。

  • React: Webの本家ライブラリ(npmでインストール)。
  • React Native (Core): モバイル(iOS/Android)向け。主幹は Meta
  • React Native for Windows / macOS: デスクトップ向け。主幹は Microsoft
    • ここがポイント: コア(Meta)とは別リポジトリで開発されており、コアの最新版への追従が遅れがちです。
  • React Native CLI: 開発ツール。主幹は コミュニティ(Callstack社など)
  • Expo: 開発ツールチェーン。主幹は 650 Industries (Expo)

この開発主体の違いにより、Coreの最新機能にWindows版が追従できていない「周回遅れ」の状態が頻発します。

Windows対応の辛すぎる現実

特に苦戦したのがWindows版です。「React Native for Windows」導入時に以下の問題が多発しました。

  1. UWPの制約と署名のコスト: Windows版は歴史的にUWP(サンドボックス環境)ベースです。このため、プロトタイプを社内に配ろうとしても、UWPはデジタル署名が必須となります。有償の証明書(年間数万円〜)を購入しないとインストールすらままならない現実は、プロトタイプ開発において大きな足枷でした。また、UWPゆえにファイルアクセス権限やWin32 APIへのアクセスが非常に制限されていて、回避策の検討にも苦労します。
  2. ライブラリ品質のばらつき: react-native-* 系のライブラリは、iOS/Androidには対応していても、Windowsは未対応かビルド不能であることが多々あります。
  3. Hermesエンジンのクラッシュ: Windows版のJSエンジン「Hermes」が、国際化機能(Intl)を呼ぶだけでクラッシュするバグに遭遇しました。プラットフォーム固有の地雷を踏むたびに開発がストップしました。
  4. アーキテクチャの過渡期: React Nativeは現在、旧アーキテクチャ(Bridge)から新アーキテクチャFabric / TurboModules)への移行期です。しかし、Windows版はこの対応が完了しておらず、ライブラリによっては「モバイルは新アーキテクチャ必須だが、Windowsは未対応」という板挟み状態になります。

結果として、「Reactのコードは共通化できても、ネイティブ周りのトラブルシューティング工数が倍増する」 という本末転倒な状態に陥りました。

なぜ Flutter なのか? 技術的な優位性

「純粋なクロスプラットフォームアプリ」を作るという目的に立ち返ったとき、Flutterアーキテクチャが持つ合理性が際立ちます。

インタープリター」vs「ネイティブコード」

性能面で決定的な違いがあります。

  • React Native: リリースビルドであっても、JavaScriptコードはバイトコード化され、アプリ内のJSエンジン(VM)上で実行されます。つまり、ネイティブコードとの間には常に変換のオーバーヘッドが存在します。
  • Flutter: リリースモードでは AOT (Ahead-Of-Time) コンパイル され、そのプラットフォームの完全なネイティブ機械語(マシンコード) になります。C++で書いたアプリと同等にCPUが直接実行するため、起動速度も処理速度も圧倒的です。

配布の容易さ(.exe vs MSIX)

FlutterのWindows版は、標準的なWin32アプリ(.exe)としてビルドされます。署名なしでも(警告は出ますが)zipで固めて配布し、ダブルクリックで即起動できます。この「普通のWindowsアプリ」が作れる手軽さは、React Native (UWP/MSIX) との大きな差です。

FFI による高速な連携と安定性

React Nativeが複雑なブリッジを介するのに対し、Flutter (Dart) は FFI を使って C/C++ (Win32 API) を直接呼び出せます。OS機能へのアクセスが高速で、かつGoogleが公式プラグインを整備しているため、「Windowsだけ動かない」という事態が起きにくい構造になっています。

Googleによる中央集権的な品質管理

Flutterは言語(Dart)もフレームワーク本体も Google が主幹です。 さらに、ファイルシステム、HTTP通信、画像選択といった主要なプラグインGoogle(またはFlutterチーム)が公式にメンテナンスしています。 「Windowsだけ動かない」という事態が構造的に起きにくく、Windows版もStable(安定版)として本体に含まれています。

AI時代における「言語の壁」の崩壊

移行に際して唯一の懸念は「Dart」という馴染みのない言語でした。しかし、実際に触れてみると2つの発見がありました。

  1. AIコーディングとの相性: Dartは静的型付け言語です。AIにコードを書かせた際、型定義が間違っていればコンパイルエラーになるため、JavaScriptよりも「AIの嘘」に気づきやすいです。
  2. 「書く」のはAI、「読む」のは人間: 新しい言語をゼロから「書く」のは大変です。しかし、AIに生成させたコードを「読んでレビューする」のは、JavaやTypeScriptに近いDartなら難しくありません。

「AIに書いてもらい、人間は型安全な環境でレビューする」 ——このスタイルが確立できる今、言語のマイナーさはもはや障壁ではなくなりました。

おわりに

Web資産の流用やOS標準UIへのこだわりがあるなら React Native も選択肢ですが、デスクトップを含む真のクロスプラットフォーム展開と、ネイティブアプリとしての純粋な性能・配布のしやすさを求めるなら、2025年現在は Flutter が最適解であると判断しました。
今後は今回の知見を活かして、Flutterでクロスプラットフォームのネイティブアプリを量産できるようにしていきたいと思います。

Google Workspaceのセキュリティ管理を効率化!情報漏洩リスクを未然に防ぐチェックソリューションを開発

昨今、クラウドサービスの普及に伴い、情報漏洩のリスクは高まっています。特にGoogle Workspaceを利用する企業において、アクセス権の設定ミスやGoogleグループの意図しない公開設定による機密情報漏洩の事故が後を絶ちません。

この記事では、情報システム部門の管理者・担当者の皆様が直面するこれらの課題を解決するため、弊社が開発したGoogle Workspaceセキュリティ管理効率化チェックソリューションをご紹介します。

💡 導入:なぜ今、このソリューションが必要なのか?

🚨 繰り返される「設定ミス」による情報漏洩事故

昨今、Googleドライブの「リンクを知っている全員」設定や、Googleグループの「外部閲覧可能」設定ミスによる重大な情報漏洩事故が多発しています。機密情報や個人情報が意図せずインターネット上に公開され、企業は甚大なダメージを負います。

図1:Google Driveの共有設定画面
事例としてGoogle Formを誤って編集者権限で外部公開しアンケート回答者(顧客)の情報が漏れてしまう、社外秘資料を誤ってファイル/フォルダごと全公開で共有してしまうなどのケースが考えられる。

図2:グループの設定画面
「会話を閲覧できるユーザー」を「組織全体」や「ウェブ上のすべてのユーザー」にしてしまうと、意図しないメンバーにメールのやり取りが見えてしまう。

😩 情シス担当者の「目視チェック」という限界
  • 課題の明確化:
    • 「全ファイル」「全共有ドライブ」「全Googleグループ」の設定を目視でチェックするのは、時間的にも工数的にも非現実的です。
    • 特に組織が拡大したり、異動・退職が増えたりすると、設定の抜け漏れリスクは加速度的に増大します。
  • ターゲットへの訴求:
    • Google Workspaceの上位エディション(Enterpriseなど)では高度な監査機能がありますが、予算の都合で契約できない企業は、手作業のチェックに頼らざるを得ない状況です。

✨ 開発背景と目的:私たちが解決したかったこと

🛠️ 開発のきっかけ

深刻な情報漏洩事故を目の当たりにし、「この問題を情シス担当者の目視と精神論に頼っていてはいけない」という強い危機感を持ちました。

そこで、「安価に」「効率的に」「現状のリスクを網羅的に」把握できるソリューションの必要性を痛感し、自社で開発に着手しました。

🎯 ソリューションの目的

Google Workspaceのコアな情報漏洩リスクを自動検知し、情報システム部の管理者・担当者のチェック負荷を劇的に軽減すること。

⚙️ ソリューションが解決する具体的な課題と機能紹介

私たちは、特にリスクが高い以下の3つのポイントに焦点を当て、機能に落とし込みました。

課題(リスク) 開発機能 ソリューションが解決できること
Googleドライブで「リンクを知っている全員」公開の機密ファイルがある アクセス権:「リンクを知っている全員」のファイルを一括把握 意図しない全公開ファイルを即座に特定し、権限を「制限付き」に戻すなどの対策を可能にします。
共有ドライブの権限が複雑化し、誰が何にアクセスできるか不明 共有ドライブの権限一覧表示 共有ドライブごとのメンバーと権限を一覧で確認でき、権限の棚卸しと適正化を効率化します。
Googleグループの設定ミスで、社内会話が意図しない三者(外部または不要な内部メンバー)から閲覧可能になっている Googleグループの会話閲覧状態を可視化 グループの「投稿の閲覧権限」が、本来アクセスすべきでないユーザー(外部・内部問わず)に広く公開されていないかを確認し、社内メールの会話の閲覧制限を適正化します。

図3:製品のメイン画面
図の公開ファイル一覧画面では、すべての公開ファイルのリンク、パス、所有者などを確認できる。

🌟 導入のメリット:情シス担当者の未来
  • 時間とコストの節約:
    高度な監査機能を上位エディションに頼る必要がなく、手動チェックにかかっていた膨大な時間を削減できます。
  • 確実性の向上:
    目視による見落としがなくなり、情報漏洩リスクを組織全体で確実に低減できます。
  • リスクの事前検知:
    事故が起きてから動くのではなく、日々のチェックで「危ない設定」を未然に把握し、予防的なセキュリティ体制を構築できます。

🤝 まとめ

💡 こんな企業におすすめです
  • Google Workspaceを利用しているが、Enterpriseなどの上位エディション契約が難しい企業。
  • 情報システム部のリソースが限られており、セキュリティ管理を効率化したい企業。
  • Googleドライブやグループの設定ミスによる情報漏洩リスクを真剣に防ぎたい企業。
📩 ご興味ある企業/導入したい企業は弊社にお問合せください

本チェックソリューションは、お客様のGoogle Workspace環境に合わせて導入が可能です。

デモンストレーションのご依頼や、ソリューションの詳細に関するご質問は、弊社のウェブサイトの問い合わせフォームまでお気軽にご連絡ください。

[お問い合わせフォームへのリンク] heroz.co.jp

n8nを使って業務自動化してみた

はじめに

本記事では、n8nの実際の活用例を紹介したいと思います。

筆者は、情シス部門に所属しており、 HEROZに入社してまだ1年も立っていないため、AI技術に関してはまだまだ素人なのです。そのため、社内でよく飛び交うAI関係の専門用語についていけていなかったため、 業務効率化も兼ねて、n8nというAI系のツールを使い、問い合わせ窓口の内容を自動集計するプログラムを試作してみました。

n8nについて

n8nとは、簡単に言えば、LLM+ワークフローを使った自動化ができるツールです。
幅広いSaaS(Slack, Notion, Google, X, AWS, Azureなど)と連携することができます。
パワーポイントの図形を使うような形でAIを使ったプログラムを作成できるので、特に、プログラミングはあまりできないけど、日々の作業をAIを使って自動化したいような方におすすめです。

n8nの使い方

n8nでは、ノードと呼ばれるブロックをつなぎ合わせることでワークフロー=プログラムを作成することができます。 パワポの図形作成のように感覚で作れてしまうのがとても魅力的です。

例えば、Slack上でOpenAIとチャットするためのワークフローを作成する場合は下図のようになります。

n8nのワークフローの例
n8nのワークフローの例

上図では、Slackにメッセージが投稿されると下記の処理が実行され、 Slack上でChatGPTのようにAIとやり取りすることができるようになります。

処理の流れ:

  1. あらかじめ、Slackボットとn8nを連携する。(Webhook URLの登録など)
  2. Slackにメッセージを投稿する。
  3. Slackからメッセージがn8nに通知される。
    • トリガーノード(Slackノード)にWebhook通知が行き、n8nのワークフローが実行される。
  4. Slackの通知がAIに渡される:
    • 次のノード(AI Agentノード)にメッセージが渡され、AIがツール(ネット検索ツール等)と自動的に連携し、応答を返す。
  5. Slackに生成されたメッセージが返される:
    • Slackノードに結果が渡され、AI Agentノードで生成されたメッセージがSlackにDMとして返す。

上記のように、シンプルな機能であれば簡単に実装できる上、各種サービスと簡単に連携できるのでとても便利です。

ノードは設定画面から設定を行うことができるため、Slackアカウントの認証情報、通知元のSlackチャンネル、LLMのプロンプトの設定などができます。 また、AI Agentノードは様々なツール(Gmail、データベース、Web検索ノードなど)をつなげることで機能を拡張できるので、様々なサービスと簡単に連携することができます。(ただし、各種SNS等の契約は別途行う必要があります。)

n8nの設定画面(LLMノード)
n8nの設定画面(LLMノード)

連携できるツールの一例
連携できるツールの一例

n8nを採用した理由

今回、n8nを採用する上で考慮した要件は下記の通りです:

  1. 社内の業務自動化で活用できそうなこと。(ローコードであると非エンジニアでも使えるのでなおよい)
  2. 特に、API連携ができ、LLMが使えること。(AI AgentやRAGの機能があるとなおよい)
  3. 運用費用があまりかからないこと。(まずは、LLMを使った自動化が実用的なのかを検証したいため)

上記の結果、Difyも触ったりしたのですが、さほど違いを感じず、 最終的に社内で活用できるかわからなかったのでオープンソースのn8nを採用しました。 (使い方が似ているので、実用性が出てきた段階でDifyに切り替えることもできそうです)

n8nの構築について

n8nは構築はDockerのイメージがあるのでローカルで動かす場合は、とても簡単です。

# https://github.com/n8n-io/n8nを抜粋
docker volume create n8n_data
docker run -it --rm --name n8n -p 5678:5678 -v n8n_data:/home/node/.n8n docker.n8n.io/n8nio/n8n


ただ、社内で共有したかったこともあり、今回はAWS上で構築しました。 ランニングコストは最低限にしたかったので、最終的に下記のスペックで構築しました。

  • 実行環境:ECS on EC2
  • EC2インスタンス:t3.small
  • ボリューム:EBS sc1(125 GB)

ECS on EC2を採用した理由は、価格の安いEBSを採用したかったためです。(今回の場合、EBSとEFSを比較すると20倍ぐらいの価格の差がありました)

構築はTerraformで行いました。 詳細は長くなるので割愛しますが、本構築のポイントとしては下記の点があります。

  1. AWSのFargateがEBSに対応していないため、ESC on EC2+REX-Rayプラグインの構成で構築。
    • REX-rayを使うことで、Fargate+EBSのような構成が可能になる。
    • ECS on EC2は専用に作られたEC2-optimized版があったのでこちらの最新版を採用した。
    • IAMポリシーはAmazonEC2ContainerServiceforEC2Roleec2:AttachVolumeなどのEBS関連の権限を付与した。
    • ECS on EC2は構築ミスをすると、コンテナが起動されず、AWS上にあまりログが出力されないため、原因の調査が難しい。 (メモリが枯渇して新しいコンテナが起動できない、REX-Rayのインストールに失敗してecs.serviceが起動しない等の現象に遭遇)
  2. WebhookのURLがlocalhostとなっていたため、WEBHOOK_URLの環境変数を設定。

上記は、いずれもドキュメントがあまり充実していないこともあり、原因を探すのにとても苦労しました。(実は以降の問い合わせ集計自動化プログラムの作成より苦戦しています。。。)

問い合わせ集計自動化

情シスでは、1年の振り返りとして、問い合わせ窓口に来る内容を分析して次のアクションを計画するのですが、今回、その作業を自動化するプログラムをn8nで作成してみました。 問い合わせ件数は数百件に上るため、LLMで自動化できれば時間短縮になりますし、 業務効率化のひらめきに繋がるアドバイスをくれるかもしれないと思い作成しました。

実際に完成したものがこちらです:

問い合わせ窓口集計のワークフロー
問い合わせ窓口集計のワークフロー

…とても長いですね。当初はもっとシンプルだったのですが、精度を上げるため、色々試行錯誤した結果、今回の形に行きつきました。

細かい説明は割愛しますが、ポイントだけ説明したいと思います。

処理の流れ

大きく分けて2つの処理を行っています。

  1. 黄色い部分:Slackから問い合わせチャンネルの内容を収集してGoogleスプレッドシートに保存する。(また、Googleスプレッドシートには、あらかじめ式が埋め込まれており、集計結果を自動的に算出するよう用意されている。)
  2. 青い部分:文章を「概要」、「ユーザ毎の問い合わせ件数の上位」、「月毎の問い合わせ件数の上位」、「よく出てくるキーワード」、「その他(気づき)」の章に分けて、複数のLLMに生成してもらう。

2では、下図のように文章を担当ごとに分割して、順番にLLMで生成する方式を採用しました。

文章の生成方法:文章を担当ごとに分割して生成する

下記は2章目の「月別の問い合わせ件数」を担当しているLLMのプロンプトの例です。

プロンプト:
    --- システムメッセージ ---
    あなたは、データ分析が得意なAIエージェントです。
    現在、AIエージェントの回答を繋げていっており、最終的に下記の内容を出力していきます。
    あなたは、あなたの担当された箇所について回答し、文を完成してください。

    《最終的に出力する内容》
    # help-情シス問い合わせ受付の分析結果

    ## 概要
    ["AI Agent E"の回答]

    ## ユーザ別の問い合わせ件数
    ["AI Agent A"の回答]

    ## 月別の問い合わせ件数
    ["AI Agent B"の回答]

    ## キーワード
    ["AI Agent C"の回答]

    ## その他
    ["AI Agent D"の回答]

    --- ユーザー入力 ---

    【問い合わせの履歴】
    {{ $json.conversationPerMonth }}  ←スプレッドシートで計算された集計結果

    【問い合わせの統計】
    ユーザ別:
    {{ $json.userSummary }}             ←スプレッドシートで計算された集計結果

    月別:
    {{ $json.monthlySummary }}          ←スプレッドシートで計算された集計結果

    【質問】
    あなたはAI Agent Bです。月別の問い合わせ件数をランキングで表示してください。
    また、その月に多かった問い合わせの内容の一例を含めてください。
    出力は「## 月別の問い合わせ件数」から始めてください。

    # help-情シス問い合わせ受付の分析結果

    ## ユーザ別の問い合わせ件数
    {{ $json.outputUserSummary }}       ←「ユーザ別の問い合わせ件数」を担当するLLMの出力結果

    ## 月別の問い合わせ件数
    [あなたの回答]

結果

上記で生成された結果は下記の通りです。(情報はぼかしています)

# ヘルプデスク問い合わせ受付の分析結果
## 概要
本期間中の問い合わせは、ネットワークやクラウド基盤の設定変更に加え、各種業務管理システムにおけるユーザーアカウントの新規発行や権限変更、及びセキュリティ・アクセス管理の依頼が多く寄せられています。問い合わせ内容は、システム運用やセキュリティポリシーの柔軟な運用、社内外の情報共有環境の整備に関連しており、急なトラブル対応から計画的なサービス変更の依頼まで多岐にわたっています。これにより、各システムの管理体制の見直しと、各部署間の連携強化が喫緊の課題として浮かび上がっています。
## ユーザ別の問い合わせ件数
1. Aさん:30件
 例:「顧客のコミュニケーションツール利用について、有料版への移行に関する問い合わせ」
2. Bさん:20件
 例:「人事管理システムの管理者権限の発行依頼や承認プロセスの設定変更」
3. Cさん:19件
 例:「ソースコード管理ツールへのアクセス許可依頼やグループ内のメンバー追加・削除依頼、及び社内システム連携に関する問い合わせ」
...
## 月別の問い合わせ件数
1. 2025/01:39件
 例:複数のシステムの新規グループ作成、アカウント発行、及びアクセス権限の付与依頼が突出しています。
2. 2024/08:31件
 例:PC交換に伴うデバイス承認、アカウントの追加、及び基本システム連携に関する問い合わせが中心でした。
3. 2024/10:30件
 例:コミュニケーションツール内のグループ・チャンネル作成、登録依頼、外部連携の設定依頼など、コミュニケーションおよびセキュリティ施策に関する要求が多く寄せられました。
...
## キーワード
1. アドレス管理
 ─ アドレス登録、変更、設定など、ネットワーク設定に関する問い合わせが頻出。
2. セキュリティ管理システム
 ─ セキュリティポリシー、アクセス許可設定、リスク管理など、通信制御や安全性確保に関する依頼。
3. 業務管理システム
 ─ アカウント新規発行、権限変更、連携トラブルなど、業務システムのユーザー管理関連の問い合わせが中心です。
...
## その他
・全体として、各種システムの運用・管理に伴う定型的な依頼(アカウント発行や権限変更)に加え、新規機能の導入やシステム連携に伴う急なトラブル対応も多く見受けられ、社内の業務プロセスや連携体制の改善が求められている状況です。
・特に、アドレス管理に関する依頼が散見されることから、新サービスの立ち上げや既存サービスの移行、セキュリティ強化の動きが活発であると判断できます。
・また、業務管理システムに関する依頼が多いことは、社内のユーザー管理プロセスが頻繁に行われていることを示唆しており、今後の運用体制の強化が課題となると考えられます。

→ チャット履歴はこちら ←
Automated with this workflow

結論から言うと、上記の内容は可もなく不可もなくな結果となってしまいました。 1週間程かけて制作していきましたが、一番苦労したのは、ハルシネーション(それっぽい嘘)でした。 生成結果を見ると、それっぽい結果になっているのですが、実際に内容を確認すると誤った情報が多々ありました。 特に、数字関係は壊滅的で、問い合わせ件数とそのランキングはほとんど誤っていました。 AIモデルの変更やRAGを採用してみましたが、うまくいかず、最終的には、Googleスプレッドシートで集計してLLMに渡すということを行い、数字は正確なものになりましたが、文章はまだ部分的に不正確な情報が含まれていることがあります。

また、対策を考えるいいアドバイスが得られるかもと期待していたのですが、 LLMに業界知識がないためか、調整不足で抽象的なアドバイスになってしまったのも特徴的で興味深かったです。

追記:社内のAIエンジニアに記事を確認してもらったところ、業界知識の問題ではなく、コンテキスト不足&出力の調整が足りない(期待値の粒度調整が明確でない)のでは?という意見をいただきました! コーディングアシストの時は割と雑な質問でも的確に回答してくれるので、その感覚とは異なるのだなと素人ながらに感じました。。。

改善策はまだまだあるのですが、1週間という制約を設定していたため、今回はここまでとしました。 まだまだ試したいことは多いので、時間ができ次第、色々検証していきたいです。

プログラムを作ってみた所感

LLMを使ってみての感想ですが、「未知の生物を手なずけている」そんな感覚でした。 普段行っているソフトウェア開発はパフォーマンス低下やバグの原因をなんとなく推測できるのですが、 LLMについては、何をしたらうまくいくのかの推論を立てにくく、やってみないとわからないことがとても多かったです。

普段は調べ物やコーディングのアシスト等で、LLM(HEROZ ASK)にお世話になっているのですが、 その精度とはだいぶかけ離れた印象の結果になったのが残念だったのと同時に面白かったです。 AIは万能ではなく、いかにお膳立てして使うかがポイントなのかもしれないなと学びになりました。

今回のケースでは、プロンプトが長すぎたこと(1年間の問い合わせをそのまま入力として渡していること)と汎用的なLLM(業界知識がなく、分析に長けていないLLM) プロンプトの調整不足が敗因な気がします。

おわりに

n8nを使ってLLMを使って色々思考錯誤したおかげで、最近のAI技術について解像度がかなり上がりました。 特に、AI関連の会議や勉強会で何を話しているのかわかるようになったのが一番うれしい成果でした!

また、n8n自体も色々可能性のあるツールだなと感じました。 現在は、n8n+Slackボットを使って、社内のマニュアル検索&ネット検索&音声入力できるAIボットを作るなど、自分がほしい機能を作って活用しています。 まだ業務理解が浅いので、他部署にヒアリングしていき活用事例を作っていきたいです。

手軽にLLMを連携できるので、LLMを活用した製品のプロトタイプの作成など、社内に実験の場としてn8nを提供していきたいとひそかに思っています。。。!

n8nを使ってみた

はじめに

n8nというオープンソースのワークフロー自動型のAIツールを使ってみました。
筆者は、情シス部門で働いているのですが、社内の業務効率化の問い合わせを受けることがあり、Google App Scriptをメインに業務自動化ツールを作成しています。ただ、入社したてだったということもあり、AIについて知識がなく、また、AIを使えばより高度な業務自動化を行えるのではないかと考えていたところ、Youtubeの技術解説動画でn8nを知り、試しに触ってみることにしました。

n8nについて

n8nとは、簡単に言えば、LLM+ワークフローを使った自動化ができるツールです。
幅広いSaaS(Slack, Notion, Google, X, AWS, Azureなど)と連携することができます。
パワーポイントの図形を使うような形でAIを使ったプログラムを作成できるので、特に、プログラミングはあまりできないけど、日々の作業をAIを使って自動化したいような方におすすめです。

n8nの特徴としては下記が挙げられます:

  1. ノーコード、ローコード:
    • 簡単なものであればノーコードでプログラムを作成できる
    • 例えば、AIサービスのプロトタイプなどを作る際に便利
  2. インストールが簡単:
    • Dockerイメージがあるので、気軽に導入することができる
    • Dockerをインストールしてあれば、コマンド1つでサービスを起動することができる
  3. 情報漏洩の心配がない:
    • オフラインでも使用できるため、情報管理に厳しい会社でも安心して使える
    • Ollamaやローカルのデータベースなどと連携して使うこともできる
  4. 無料:

できること

n8nでできることとしては、下記のような例が挙げられます:

  1. PDFの自動解析
    • スキャンした領収書や見積書の内容をAIで自動解析してExcel
  2. メール返信の自動仕分け
    • 毎日送られてくる問い合わせメールをAIで解析し、回答を自動生成する
  3. 会議の内容の自動共有
    • 録画した会議の内容をAIで議事録化し、社内に自動共有するシステム

導入方法

とりあえず試しに触ってみたい方は、Dockerイメージが用意されているので、Dockerをインストールしている環境であれば、下記のコマンドを実行するだけで起動できます。

docker volume create n8n_data
docker run -it --rm --name n8n  -p 5678:5678 -v n8n_data:/home/node/.n8n docker.n8n.io/n8nio/n8n

使い方

n8nでは、ノードと呼ばれるブロックをつなぎ合わせることでワークフロー(プログラム)を作成することができます。 パワポの図形作成のように感覚で作れてしまうのがとても魅力的です。

例えば、Slack上でOpenAIとチャットするためのワークフローを作成する場合は下図のような流れになります。

①ノードの選択

②ノードの配置

③ノード同士を接続する

④AI Agentにツールをつなげて機能を拡張する

n8nのワークフローの例
⑤1~4を繰り返して完成

n8nを使ってみた

情シスでは、1年の振り返りとして、問い合わせ窓口に来る内容を分析して次のアクションを計画するのですが、今回、その作業を自動化するプログラムをn8nで作成してみました。 問い合わせ件数は数百件に上るため、LLMで自動化できれば時間短縮になりますし、 業務効率化のひらめきに繋がるアドバイスをくれるかもしれないと思い作成しました。

ワークフローのおおまかな流れは下記の通りです:

  1. Slackから問い合わせチャンネルの内容を収集してGoogleスプレッドシートに保存する。
  2. 複数のLLMを組み合わせて、順番に「概要」、「ユーザ毎の問い合わせ件数の上位」、「月毎の問い合わせ件数の上位」、「よく出てくるキーワード」、「その他(気づき)」をそれぞれ生成し、最後に清書する。
  3. 結果をSlackに送信する。

問い合わせを自動分析するワークフロー

最終的な結果は下記の通りです(情報はぼかしています):

# ヘルプデスク問い合わせ受付の分析結果
## 概要
本期間中の問い合わせは、ネットワークやクラウド基盤の設定変更に加え、各種業務管理システムにおけるユーザーアカウントの新規発行や権限変更、及びセキュリティ・アクセス管理の依頼が多く寄せられています。問い合わせ内容は、システム運用やセキュリティポリシーの柔軟な運用、社内外の情報共有環境の整備に関連しており、急なトラブル対応から計画的なサービス変更の依頼まで多岐にわたっています。これにより、各システムの管理体制の見直しと、各部署間の連携強化が喫緊の課題として浮かび上がっています。
## ユーザ別の問い合わせ件数
1. Aさん:30件
 例:「顧客のコミュニケーションツール利用について、有料版への移行に関する問い合わせ」
2. Bさん:20件
 例:「人事管理システムの管理者権限の発行依頼や承認プロセスの設定変更」
3. Cさん:19件
 例:「ソースコード管理ツールへのアクセス許可依頼やグループ内のメンバー追加・削除依頼、及び社内システム連携に関する問い合わせ」
...
## 月別の問い合わせ件数
1. 2025/01:39件
 例:複数のシステムの新規グループ作成、アカウント発行、及びアクセス権限の付与依頼が突出しています。
2. 2024/08:31件
 例:PC交換に伴うデバイス承認、アカウントの追加、及び基本システム連携に関する問い合わせが中心でした。
3. 2024/10:30件
 例:コミュニケーションツール内のグループ・チャンネル作成、登録依頼、外部連携の設定依頼など、コミュニケーションおよびセキュリティ施策に関する要求が多く寄せられました。
...
## キーワード
1. アドレス管理
 ─ アドレス登録、変更、設定など、ネットワーク設定に関する問い合わせが頻出。
2. セキュリティ管理システム
 ─ セキュリティポリシー、アクセス許可設定、リスク管理など、通信制御や安全性確保に関する依頼。
3. 業務管理システム
 ─ アカウント新規発行、権限変更、連携トラブルなど、業務システムのユーザー管理関連の問い合わせが中心です。
...
## その他
・全体として、各種システムの運用・管理に伴う定型的な依頼(アカウント発行や権限変更)に加え、新規機能の導入やシステム連携に伴う急なトラブル対応も多く見受けられ、社内の業務プロセスや連携体制の改善が求められている状況です。
・特に、アドレス管理に関する依頼が散見されることから、新サービスの立ち上げや既存サービスの移行、セキュリティ強化の動きが活発であると判断できます。
・また、業務管理システムに関する依頼が多いことは、社内のユーザー管理プロセスが頻繁に行われていることを示唆しており、今後の運用体制の強化が課題となると考えられます。

→ チャット履歴はこちら ←
Automated with this workflow

具体的な実装は別記事にまとめたいと思いますので、詳細が気になる方はそちらをご覧ください。

n8nを使ってみた感想

n8nを使用してみた印象ですが、とても便利でまだまだ活用の余地があるなと感じました。

一番の特徴はコーディングをしなくてよいところでしょうか。 導入はコマンド一つででき、API連携が簡単、プログラムの実行もスケジューリングができるなど、手軽に業務の一連の流れを自動化できるところがとても便利だなと感じています。 また、バージョンアップのスピードも早く、MCPノードなどの新しい技術にも随時キャッチアップしており、流行の技術に手軽に触れられるのも良いところだと感じています。

反面、ドキュメントが英語のみ、かつ、充実していないので、まだまだ社内で活用するには課題が多いです。 そのため、保守性の観点から、現状はまだGoogle App Script等を使って業務自動化を行うことが多いです。

以下、n8nの特徴をまとめてみました。

長所

  • コーディングをあまりしなくてもよい。(アイディアの検証におすすめ)
  • SaaS連携が手軽にできる。(2025年現在では1047個のSaaSを含むツールに対応)
  • LLM、RAG、AI Agentなど、先進的な技術を使った自動化が行える。
  • JavascriptPythonのコードも埋め込めるため、複雑な実装できる。(ただし、使えるライブラリには制限がある)

短所

  • ドキュメントが英語、かつ、充実していないため、使える人が限られている。
  • 使用できるLLMの機能は少しラグがある。(Open Researchやsimilarity_score_thresholdを使ったRAG等、未実装の機能がある。)
  • 日本のSaaSとの連携は充実していない。(FreeeやKintoneなどとの連携はWebhookノードを使って手動で作りこむ必要がある。)

おわりに

実は、こちらの記事を書き始めたのが2025年の4月頃だったのですが、その後色々と立て込んでしまい、6か月経ってしまいました。。。 最近ではOpenAI BuilderなどLLMのメーカーからこういったツールが出てきており、ますます便利になっていく一方、 こういったオープンソースならではの強みがあって、n8nはまだまだ需要があるツールなのではないかと感じています。 色々自作するのが好きな方は一度触ってみてはいかがでしょうか?

Claude Code:ターミナルベースAIエージェントの実践活用

Claude Codeとは

Claude CodeはAnthropic社が開発したターミナルベースのAIコーディングエージェントです。従来のChatGPTやCopilotとは異なり、コマンドラインから直接利用でき、プロジェクト全体のコンテキストを理解してコード生成、リファクタリング、バグ修正などを実行できます。

導入手順

インストール方法

# npmを使用してインストール
npm install -g @anthropic-ai/claude-code

# yarn を使用する場合
yarn global add @anthropic-ai/claude-code

AWS Bedrock経由での利用について

AWS Bedrock経由での利用を推奨します。

メリット:

VS Code統合

拡張機能のインストール

VS Code拡張機能が提供されており、開発効率を大幅に向上させることができます。詳細な設定については、こちらの記事などを参照してください。

ワークスペース設定

ワークスペースごとに異なるモデルやAWSプロファイルを設定できるため、プロジェクトに応じた最適な設定が可能です。

{
  "folders": [
    {
      "path": "."
    },
  ],
  "settings": {
    "terminal.integrated.env.{OS毎に異なる値}": {
      "AWS_PROFILE": "{事前設定しておいたAWSプロファイル}",
      "CLAUDE_CODE_USE_BEDROCK":"1",
      "ANTHROPIC_MODEL": "us.anthropic.claude-sonnet-4-20250514-v1:0",
      "ANTHROPIC_SMALL_FAST_MODEL": "us.anthropic.claude-3-5-haiku-20241022-v1:0"
    },
  }
}

初期化

Claude Codeを起動後、/initコマンドを実行します。これにより、カレントディレクトリの構造が分析され、プロジェクト固有の設定ファイルCLAUDE.mdが自動生成されます。このファイルには、プロジェクトの構造や開発ガイドラインが含まれ、Claude Codeがより適切な支援を提供するためのコンテキストとして使用されます。

基本的な使い方

ターミナルでの実行

VS Codeのターミナルでclaude codeを起動すると、現在開いているファイルを自動認識し、プロジェクトコンテキストを理解した上でインタラクティブにファイルの読み書きを行えます。

カスタムスラッシュコマンド

反復的な複雑なタスクを効率化するため、カスタムスラッシュコマンドを定義できます。

カスタムコマンドの作成方法:

  1. マークダウン形式でプロンプトファイルを作成
  2. 適切なディレクトリに配置:
    • グローバル利用:~/.claude/command/
    • プロジェクト専用:.claude/command/
  3. ファイル名がコマンド名として登録される

これにより、複雑な指示を毎回入力する必要がなくなり、開発効率が大幅に向上します。

実践的な活用例

ファイル検索・編集

  • 大規模コードベースでの効率的な検索:関連ファイルを素早く特定し、プロジェクト全体の構造を理解
  • 複数ファイルの一括処理:複数ファイル間での分析や一括置換・修正を実行
  • コード規約の自動適用:既存のコーディング規約や慣習に従った編集を自動実行

コード生成・リファクタリング

  • 既存コードの理解とキャッチアップリバースエンジニアリングによる既存システムの理解促進
  • 機能追加の自動化:既存コード構造を理解した新機能の実装
  • レガシーコードの現代化:古いコードパターンを現代的な書き方に変換
  • テスト自動生成:適切なテストコードの自動生成

バグ修正・最適化

  • エラー解析と修正提案:エラーログからの原因特定と修正案の提示
  • 依存関係問題の解決:複雑な依存関係のトラブルシューティング
  • パフォーマンス改善ボトルネックの特定と最適化の実装

開発プロセス支援

  • PR文書の自動生成:変更内容を分析したPull Request説明文の作成
  • コードレビュー支援:レビューポイントの提示と指摘事項の自動修正
  • チーム開発効率化:ドキュメント生成やコミュニケーション支援

Gemini CLIとの連携

Claude CodeとGemini CLIを組み合わせることで、複数のAIの視点を活用したより高度な開発支援が可能になります。

Gemini CLIセットアップ

インストール

npm install -g @google/gemini-cli

認証設定

  1. APIキーの取得Google AI StudioでAPIキーを発行
  2. 環境変数設定VS Codeワークスペース設定に追加
{
  "terminal.integrated.env.{OS名}": {
    "GEMINI_API_KEY": "your-api-key-here"
  }
}
  • 認証方法選択:初回起動時にGemini API Key (AI Studio)を選択

連携活用方法

Claude CodeのCLAUDE.mdに連携設定を記述することで、「Geminiと相談しながら進めて」という指示で自動的に両AIを活用した開発が可能になります。

基本的な連携フロー:

  1. Claudeが要件をまとめてGeminiに送信
  2. Geminiの回答を取得・分析
  3. 両AIの見解を統合した最終提案を作成

活用例:

  • コードレビューでの多角的な分析
  • アーキテクチャ設計の妥当性検証
  • 複雑な技術選択での意思決定支援

この連携により、単一のAIでは得られない多様な視点からの開発支援を実現できます。

MCPサーバー設定

MCPサーバーとは

MCP(Model Context Protocol)サーバーは、Claude Codeの機能を拡張する外部ツールとして設定できます。これにより以下のようなメリットが得られます:

  • 機能拡張:Claude Codeの標準機能を超えた専門的なタスクの実行
  • 外部サービス連携AWSサービスやデータベースなどとの直接連携
  • 開発効率向上:反復的なタスクの自動化とワークフローの最適化

設定方法

MCPサーバーの設定は、コマンドライン実行またはJSON設定ファイルの編集で行えます。

コマンドによる設定

設定の適用範囲を指定できます。本記事では、ワークスペースごとのClaude環境構築を推奨しているため、ワークスペースフォルダをスコープとするprojectオプションを指定します。

AWS Diagram MCPサーバーの設定例:

今回はAWS Bedrockを使用しており、AWS Profileが設定済みであるため、AWS関連のMCPサーバーの動作環境が整っています。アーキテクチャ図を生成するサーバーを設定して、実際に作図機能を試してみます。

claude mcp add awslabs.aws-diagram-mcp-server -s project -- uvx awslabs.aws-diagram-mcp-server

設定ファイルの確認

上記コマンドを実行すると、.mcp.jsonファイルが自動生成されます。後からより詳細な設定を追加したい場合は、このJSONファイルを直接編集できます。

{
  "mcpServers": {
    "awslabs.aws-diagram-mcp-server": {
      "type": "stdio",
      "command": "uvx",
      "args": [
        "awslabs.aws-diagram-mcp-server"
      ],
      "env": {}
    }
  }
}

MCPサーバーを用いたAWSアーキテクチャ図の生成

設定したMCPサーバーを使用して、実際にアーキテクチャ図を生成してみます。

プロンプト例:

VpcStack-staging/MyVpcのAWSアーキテクチャ図を作成して./imgに保存して

このようにシンプルなプロンプトで、既存のAWSリソース構成を視覚化した図を自動生成できます。

生成結果:

MCPサーバーにより、作図を高い品質で自動化できて、ドキュメント作成や設計レビューの効率が大幅に向上します。

まとめ

Claude Codeは、従来の開発プロセスを革新する強力なツールです。導入により以下のような効果が期待できます。

開発効率の向上

  • 作業速度の大幅向上:ルーティンワークの自動化により、創造的なタスクに集中可能
  • コスト効率の改善:導入コストを大幅に上回る工数削減効果
  • 人材不足への対応:自動化により限られたリソースでの高品質な開発を実現

品質向上

  • コード品質の標準化:一貫したコーディング規約の適用
  • サービス品質の向上:これまで後回しにされていた品質向上作業の実現
  • 技術負債の解消:レガシーコードの現代化とリファクタリングの促進

学習・成長支援

  • 新技術の習得:最新のベストプラクティスや便利な機能の発見
  • 設計手法の向上:AIによる設計・実装手法の提案による学習効果
  • 技術領域の拡大:これまで困難だった技術領域への挑戦が可能に

Claude Codeは単なる開発支援ツールを超え、開発チーム全体の能力向上と、より高品質なソフトウェア開発を実現するパートナーとして機能します。

HEROZ ASKへのo1の導入

はじめに

昨年末の12/5に12 Days of OpenAIでついにo1が発表となりました。
また、Azure OpenAI Serviceでも、このo1が使用できるようになりましたので、HEROZ ASKへと組み込みました。
langchainを用いた組み込みで気になった点を書いていきます。

なお、このo1はHEROZ ASKで2025/1/24以降で使用可能です。

o1-preview時代からの共通項目

昨年9月にo1-previewがリリースされて以来、内部的にはo1-previewを組み込む試作を実施していました。
その時から注意点や気になった点は以下となります。

o1-previewやo1-miniはChatOpenAI()を用いてgpt-4oと同じように使おうとすると、以下が非対応のため修正が必要になります。

  • temperature: オプションの削除
  • ストリーミング(streaming): オプションの削除
  • SystemMessage: システムメッセージの除去

ストリーミングオプションを削除するとストリーミングを期待している時に何も出力されなくなるため、以下のようなラッピングクラスを用意しました。

コードを見る

class ChatOpenAI_o1(ChatOpenAI):
    def _generate(
        self,
        messages: List[BaseMessage],
        stop: Optional[List[str]] = None,
        run_manager: Optional[CallbackManagerForLLMRun] = None,
        **kwargs: Any,
    ) -> ChatResult:
        results = super()._generate(
            messages,
            stop,
            run_manager,
            *kwargs,
        )
        if run_manager is not None:
            # on_llm_new_tokenしないと結果が表示されない
            run_manager.on_llm_new_token("".join([g.text for g in results.generations]))
        return results

    async def _agenerate(
        self,
        messages: List[BaseMessage],
        stop: Optional[List[str]] = None,
        run_manager: Optional[AsyncCallbackManagerForLLMRun] = None,
        **kwargs: Any,
    ) -> ChatResult:
        results = super()._generate(
            messages,
            stop,
            run_manager,
            *kwargs,
        )
        if run_manager is not None:
            # on_llm_new_tokenしないと結果が表示されない
            await run_manager.on_llm_new_token(
                "".join([g.text for g in results.generations])
            )
        return results

また、ストリーミング時はstream_usageオプションを使用すると使用トークン数を取得できますが、これの出力トークン(completion tokens)に思考用のReasoning tokenも含まれており、助かりました。

o1での変更点

o1はo1-previewと比べると以下の点で変更となっています。

  • SystemMessageへの対応: roleはdeveloperとする
  • 画像入力: 数式の入力がやりやすくなります
  • Markdown出力: プロンプトにFormatting reenabledと追加すると、Markdownで出力できるようになります

SystemMessageについてはlangchainにおいてはSystemMessagePromptTemplateの呼び出しで、オプションにadditional_kwargs = { "__openai_role__": "developer" }を渡すことで対応できます。
確かにこの方法でSystemMessageの指定はできるようになったのですが、試してみる限りではgpt-4oのSystemMessageと比べて遵守率が低いように感じました。

一方で、o1は未だにコスト計算用の単価が書かれているopenai_info.pyやtiktokenのmodel.pyが対応していないので、テーブルを動的に上書きしない限りはトークンやコストの計算時にエラーが発生します。
これらのファイルについては早期に追加されることを期待します。

組み込み結果

早速、難解な数式を画像で入力して解かせたところ、無事に正解しました。

o1の実行結果

おわりに

gpt-4oより賢いと言われているo1をHEROZ ASKへ導入することができました。
o1は確かに込み入った数式のような問題には抜群の能力を発揮するのですが、普通の質問や知識を問う内容だとgpt-4oと回答が変わらず、o1は時間とコストだけがかかるので、使い所が難しいように思いました。
一般ユーザーを含めて導入することにより、その辺りのユースケースをもっと発掘していきたいと思います。

MCP(Model Context Protocol)をLangChainのエージェント機能で動かしてみた

はじめに

先月、Anthropic社よりMCP(Model Context Protocol)というプロトコルが発表されました。 www.anthropic.com MCPAIアシスタント(RAGシステム)と情報源やツール群をつなげるための通信規約(プロトコル)ですが、現時点で何がどこまでできるかが未知数でしたので、調査を行い、LangChainのエージェント機能で動作させました。
とりあえずは、得られた知見についてシステム構成面の切り口で考察していきたいと思います。

MCPとは

MCPの各種情報は以下にあります。

modelcontextprotocol.io

概要

MCPプロトコル仕様のArchitectureにある下記の図のようにアプリケーションがMCPのクライアントとなり、ローカルやリモートに位置するMCPのサーバーと通信して、情報を取得したり、ツールを動作させたりします。
アプリケーションにはデスクトップアプリやSaaSサービスが想定されます。

MCPの概要図

そして、MCP自体は以下のようなプロトコルのフローやメッセージの中身が規定されています。

MCPプロトコルフロー

認証の不在

プロトコルの規定の中で気になったのは、現時点では認証に対応しておらず、今後議論していくように書かれていました。
認証が存在しない以上、インターネットを介しての通信は難しいかもしれません。

Auth

Authentication and authorization are not currently part of the core MCP specification, but we are considering ways to introduce them in future. Join us in GitHub Discussions to help shape the future of the protocol!

Clients and servers MAY negotiate their own custom authentication and authorization strategies.

2つのトランスポート

プロトコル仕様のTransportsによると、MCPには以下の2つのトランスポートがあるそうです。

後者のSSEタイプはhttpsを介した通信なのでMCPのサーバーはローカルとリモートを問わずに適用できます。
一方で、前者のstdioタイプはMCPのクライアントがMCPのサーバーとなるプロセスを起動して、パイプ機能による標準入出力(stdio)を介して通信するため、stdioタイプはローカル内でしか動作しないです。

SDKとリファレンスサーバー群

MCPの公式githubにはPython SDKTypeScript SDKが整備されており、これらを使用したリファレンスやサードパーティサーバー群も提供されています。

リファレンスサーバー群

SDKは前述した2つのトランスポートの両方に対応しているのですが、リファレンスサーバー群のほとんどはstdioタイプで作られているため、リモートで動作するものはないです。

LangChainへの実装

Python SDKを使用してLangChainへ実装したlangchain-mcpというライブラリもありますが、stdioタイプを前提としているため、ローカル内でのみ動作します(=リモートでは動作しません)。
langchain-mcpToolコンポーネントMCPToolもしくはToolkitコンポーネントMCPToolkitという形態で提供されるため、LangChainのエージェント機能で使う形になります。

このlangchain-mcpasync with構文でトランスポートのクライアント(下記の例ではstdio_client)を起動した状態で実行する必要があるため、チェインの構成と実行を近接して行う必要があります。

async with stdio_client(server_params) as (read, write): 
    async with ClientSession(read, write) as session: 
        toolkit = MCPToolkit(session=session) 
        await toolkit.initialize() 
        (toolkitを使用してrunする)

HEROZ ASKはチェインの構成と実行のタイミングが離れているので、langchain-mcpが適用しづらく、組み込みについては一旦は断念することにしました。

システム構成

MCPの動作についてシステム構成面で図を交えて考察していきます。

Claude Desktopでのシステム構成

Anthropic社はMCPの発表とともに応用例としてデスクトップ版Claude(Claude Desktop)からのデスクトップ検索を提示しています。
これが「デスクトップ検索が便利だ」や「デスクトップを覗かれるのは危険だ」みたいな感想とともに強調されてしまい、「MCP=デスクトップ検索」や「MCP=Claude Desktop」みたいな勘違いが発生しています。
MCPはあくまで通信プロトコルであって、Claude Desktopやデスクトップ検索は直接的には関係なく、単なる応用例の一つに過ぎません。

Claude Desktopでのシステム構成を図にすると、以下になります。
Claude DesktopはMCPクライアントとして位置し、必要なMCPサーバーを自ら起動して、stdioタイプのトランスポートで接続します。 そして、起動したMCPサーバーのプロセスからデスクトップのファイルにアクセスしています。

Claude Desktopでのシステム構成

起動するMCPサーバーの種類やアクセス先は設定ファイルのjsonにてClaude Desktopに渡しますが、任意のプログラムが起動できたり、ローカルのリソースに自由にアクセスできるという点で、安全とは言えない代物です。

SaaSシステムでの目指したいシステム構成

HEROZ ASKのようなSaaS型のAIアシスタントサービスにMCPを組み込む場合には、以下のような2つのパターンのシステム構成があると思います。

SaaSシステムで目指したいシステム構成

a.はSaaSサービスがMCPクライアントとなるパターンで、ユーザーからの質問に応じて、AIアシスタントがリモートサーバーにある情報を取得したり、ツールで何か実行したりします。
b.はSaaSサービスがMCPサーバーとなるパターンで、SaaSサービスが持っているリソースに対して、ユーザのAIアシスタントアプリや、別のSaaSサービスのAIアシスタントからのアクセスを受け付けます。 こちらはSaaSサービスが持つリソースが重要となるので、どちらかと言うとコンテンツプロバイダー的な位置付けになります。

HEROZ ASKは独自のリソースを持つわけではないので、a.のパターンを狙うことになります。
また、HEROZ ASKのようなエンタープライズ向けのサービスの場合には、リモートサーバーはお客様の情報やツールが入ったサーバーになることが想定されます。

現状のシステム構成

前述のようにAIアシスタントSaaSサービスはa.のようなMCPクライアントとして、リモートサーバーへのアクセスを望む場合が多いですが、現状はlangchain-mcpがstdioタイプのトランスポートにしか対応していないため、下記のようなシステム構成にならざるをえません。

現状のシステム構成

すなわち、ユーザから質問を受け取ると、MCPサーバーとなるプロセスを起動するとともに、SaaSサービスが動作しているサーバーのリソースにアクセスします。
これは、セキュリティ的にも問題が多いので、HTTP with SSEの対応が待たれます。

SaaSシステムでの問題点

仮にlangchain-mcpがHTTP with SSEタイプのトランスポートに対応したとしても、お客様のサーバーに情報を取りに行ったり、ツールを実行しに行ったりする場合には以下のような問題があります。

  • MCPに認証機能が実装されていないので、非公開情報のアクセスができない
  • お客様のサーバーがイントラネット内に存在する場合には、アクセスするための術がない

これらを図示すると以下となります。

SaaSシステムでの問題点

LangChainのエージェント機能で動かしてみた

langchain-mcpのREADMEにはエージェント機能を使わない例が載っていますが、せっかくなのでエージェント機能を使って動作させてみました。
/docというディレクトリと/doc/test.txtというファイルを作成してから、「/docには何のファイルがありますか?」という質問でディレクトリ内のファイル一覧を取得させています。

コードを見る

!pip install langchain langchain-openai langchain-mcp langchain-community==0.3.12 langchain-core==0.3.25
!mkdir -p /doc
!touch /doc/test.txt

import os
import asyncio
from langchain_openai import ChatOpenAI
from langchain import hub
from langchain.agents import AgentExecutor, create_structured_chat_agent
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
from langchain_mcp import MCPToolkit

os.environ["OPENAI_API_KEY"] = "(OpenAIのAPIキー)"

server_params = StdioServerParameters(
    command="npx",
    args=["-y", "@modelcontextprotocol/server-filesystem", "/doc"],
)

from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain.agents.structured_chat.prompt import FORMAT_INSTRUCTIONS, PREFIX, SUFFIX
HUMAN_MESSAGE_TEMPLATE = "{input}\n\n{agent_scratchpad}"

prompt = ChatPromptTemplate.from_messages(
    [
        ("system", "\n\n".join([PREFIX, "{tools}", FORMAT_INSTRUCTIONS, SUFFIX])),
        MessagesPlaceholder("chat_history", optional=True),
        ("human", HUMAN_MESSAGE_TEMPLATE),
    ]
)

async def main(message):
    async with stdio_client(server_params) as (read, write):
        async with ClientSession(read, write) as session:
            toolkit = MCPToolkit(session=session)
            await toolkit.initialize()
            
            model = ChatOpenAI(model_name="gpt-4o")
            tools = toolkit.get_tools()
            
            agent = create_structured_chat_agent(model, tools, prompt)
            agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
            
            await agent_executor.ainvoke({"input": message})

asyncio.run(main("/docには何のファイルがありますか?"))

無事にtest.txtがあるという回答を得ることができましたが、langchain-communitylangchain-coreをバージョン固定にしないとうまく動きませんでした。

実行結果

おわりに

新しく登場したMCPは外部の情報やツールを活用できるので、期待の技術と思っていたのですが、以下の理由によりまだまだ時期尚早のように思いました。

  • プロトコルの仕様に認証機能が搭載されていないため、インターネット経由の接続が難しい
  • リファレンスサーバーやlangchain-mcpのトランスポートがstdioタイプなので、ローカル内でしか実行できない(リモートサーバーへの接続ができない)
  • Python SDKasync with構文の中でしか実行できないので、セッションの確立(チェインの作成)と実際の動作(チェインの実行)を分離することができない

とは言え、これらの技術課題が解決されれば、大規模言語モデル(LLM)を用いたエンタープライズサーチの実現も夢が広がります。こうしたOSSへのコントリビュートについても一緒にやってくれる仲間を募集しています。