最近、言語モデルから外部のツールやAPIを呼び出すための仕組みである Model Context Protocol(MCP)に対応したツールが増えてきました。
社内でも「既存のAPIをMCPサーバーとして公開して、Copilotなどから直接呼べないか?」といった話題が出ることが多くなっています。
そこで本記事では、その具体例として、デジタル庁が公開している 「jGrants MCPサーバー」 を題材に、ローカル(WSL2)での実行から Azure Functions への対応、さらに Microsoft Copilot Studio との連携までを実際に試した手順として紹介します。
- 検証にあたって参考にしたブログ
- jGrantsとは?
- システムの連携図
- 環境
- 作業概要
- 作業手順
- 動作確認
- まとめ
検証にあたって参考にしたブログ
本記事は、以下のブログ記事を参考にしています。
jGrantsとは?
jGrants(ジェイグランツ) は、デジタル庁が提供する日本国内向けの補助金・助成金電子申請システムです。従来、紙や郵送で行われていた補助金申請や交付手続をオンラインで完結できるようにすることを目的としており、企業や自治体、個人事業者が電子申請を通じて効率的に補助金制度を利用できる仕組みを提供しています。
デジタル庁の GitHub で公開されている jGrants MCP Server は、この jGrants システムの情報を Model Context Protocol(MCP)に対応した形で外部ツールから取得できるようにするオープンソース実装です。これにより、Microsoft Copilot Studio などの AI アシスタントが、補助金情報を直接参照・検索できるようになります。
システムの連携図
下記の連携図は、ローカル環境での開発から Azure へのデプロイ、そして Copilot Studio との連携までの 3 つのフェーズを示しています。

それぞれのステップについて解説します。
ステップ1:ローカル環境での準備と適合
WSL 上で jGrants MCP サーバーを起動し、Azure Functions の「カスタムハンドラー」として動作するようにコード(host.json や core.py)を修正します。
まずはローカルの Python 環境で単体動作を確認する準備フェーズです。
ステップ2:Azureへのデプロイ
Azure ポータルで Linux ベースの Function App を作成し、func コマンドを使用してコードをデプロイします。
この際、一時ファイルの保存先による権限エラーを回避するため、環境変数 JGRANTS_FILES_DIR を /tmp 配下に設定する点が重要なポイントです。
ステップ3:Copilot Studioとの連携
Microsoft Copilot Studio に MCP サーバーを「ツール」として追加します。
デプロイした Function App の URL とアプリキー(default キー)を登録することで、ユーザーのチャット指示に基づいて AI が自動的に補助金情報を検索・回答できるようになります。
環境
本記事では、Azure CLI をインストールし、az login 済みであることを前提に func azure functionapp publish を実行しています。
- Windows 11
- WSL2 + Ubuntu
- Python 3.10
- Azure Functions Core Tools v4
- Azure CLI
- Microsoft Copilot Studio
作業概要
本記事では、jGrants MCP サーバーを Azure Functions 上で動かし、最終的に Microsoft Copilot Studio から接続するまでの構成をステップ形式で紹介します。
大きな流れとしては、次の 5 ステップで進めていきます。
- WSL 上で jGrants MCP サーバーを動かす
- Azure Functions のカスタムハンドラーとして対応させる
- func start を使ってローカルで動作確認する
- Azure にデプロイして外部からアクセスできるようにする
- Microsoft Copilot Studio から MCP サーバーを接続・利用する
それぞれのステップで必要な設定ファイルの追加や、コード修正ポイント、環境変数の指定方法などを丁寧に追いながら解説していきます。
作業手順
WSL 上で jGrants MCP サーバーを動かす
まずは Azure を意識せず、jGrants MCP サーバーを WSL 上で動かします。
リポジトリ取得と仮想環境
# jGrants MCP サーバーを取得
git clone https://github.com/digital-go-jp/jgrants-mcp-server.git
cd jgrants-mcp-server
# 仮想環境を作成して有効化
python -m venv .venv
source .venv/bin/activate
# 依存パッケージをインストール
pip install -r requirements.txt
MCP サーバー単体での起動確認
python -m jgrants_mcp_server.core
下記のような画面が表示されれば、サーバーは正常に起動しています。
例として、OpenAI Codex CLIで動作確認します。
config.tomlファイルに下記を追記します。
[mcp_servers.azure_mcp]
command = "npx"
args = ["-y", "mcp-remote", "http://127.0.0.1:8000/mcp"]
OpenAI Codex CLIで実行した結果です。
jGrantsのMCPサーバーが起動し、補助金が検索できています。

Azure Functions のカスタムハンドラーとして対応させる
次に、この MCP サーバーを Azure Functions の カスタムハンドラー として動かします。
host.json の追加
プロジェクト直下(jgrants-mcp-server ディレクトリ)に host.json を作成します。
{
"version": "2.0",
"customHandler": {
"description": {
"defaultExecutablePath": "python",
"workingDirectory": "",
"arguments": [
"-m",
"jgrants_mcp_server.core"
]
},
"enableForwardingHttpRequest": true
},
"extensions": {
"http": {
"routePrefix": ""
}
}
}
local.settings.json の追加(ローカル用)
ローカル実行用に local.settings.json を作成します。
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"FUNCTIONS_WORKER_RUNTIME": "custom"
}
}
mcp-handler 関数の定義
mcp-handler ディレクトリを作成します。
mkdir -p mcp-handler
その中に function.json を配置します。
// mcp-handler/function.json
{
"bindings": [
{
"type": "httpTrigger",
"direction": "in",
"authLevel": "function",
"name": "req",
"methods": [ "get", "post", "put", "delete", "patch", "head", "options" ],
"route": "mcp"
},
{
"type": "http",
"direction": "out",
"name": "res"
}
]
}
jgrants_mcp_serverディレクトリ配下にあるcore.pyを修正
Azure Functions のカスタムハンドラーから渡されるポート番号で FastMCP を起動するため、core.py の上部にある FastMCP の初期化部分を修正します。

下記の内容を追記します。
# Azure Functions のカスタムハンドラー用ポートを取得
mcp_port = int(os.environ.get("FUNCTIONS_CUSTOMHANDLER_PORT", 8080))
mcp = FastMCP(
"jgrants",
stateless_http=True,
port=mcp_port, # ここを追加
# もともと他の引数があれば、そのまま残す
)
core.pyの下部にあるHTTPサーバー起動の部分を修正します。

下記の内容を追記します。
mcp.run(transport="streamable-http")
func start を使ってローカルで動作確認する
func start で Azure Functions 環境を再現して動作確認
WSL 上から func start を実行します。
プロジェクト直下(jgrants-mcp-server ディレクトリ)でfunc start を実行します。
実行すると下記のような画面が表示されます。
mcp-handlerの箇所に記載されているポート番号を確認します。

例として、OpenAI Codex CLIで動作確認します。
config.tomlファイルの下記の箇所を修正します。
[mcp_servers.azure_mcp]
command = "npx"
args = ["-y", "mcp-remote", "http://127.0.0.1:7071/mcp"]
OpenAI Codex CLIで実行した結果です。
Azure Functions経由でjGrantsのMCPサーバーが起動し、補助金が検索できています。

Azure にデプロイして外部からアクセスできるようにする
Azure へのデプロイ
Azure ポータルで Linux の Function App を作成します。
今回は、ホスティング プランはFlex従量課金、ランタイム スタックはPython 3.12で作成しました。

Function Appの環境変数で下記を設定します。
| 項目 | 設定内容 |
|---|---|
| PYTHONPATH | /home/site/wwwroot/.python_packages/lib/site-packages |
| JGRANTS_FILES_DIR | /tmp/jgrants_files |

プロジェクト直下(jgrants-mcp-server ディレクトリ)で下記を実行します。
func azure functionapp publish 作成したFunctionAppの名称 --python
下記は実行結果の例です。
The deployment was successfulと表示されれば、デプロイに成功しています。

一時ファイルの保存先エラーに注意
デプロイ直後、ログに次のようなエラーが出ることがありました。
PermissionError: [Errno 13] Permission denied: 'tmp'
File "/home/site/wwwroot/jgrants_mcp_server/core.py", line 38, in <module>
FILES_DIR.mkdir(parents=True, exist_ok=True)
core.py には、保存先ディレクトリを下記のように決める処理があります。

Azure Functions 上では "tmp" 直下に書き込めない場合があったため、Function Appの環境変数にJGRANTS_FILES_DIRを追加しています。
Microsoft Copilot Studio から MCP サーバーを接続・利用する
Microsoft Copilot Studio から、作成した Function Appで稼働しているMCP サーバーに接続します。
Copilot Studioでエージェントを新規作成
まずは、「新しいエージェント」を作成します。

「指示文」に下記を追記します。
あなたは、日本の補助金電子申請システム「jGrants」の情報を調べるためのアシスタントです。
ユーザーが知りたい補助金や公募情報について、接続されている MCP サーバー(jgrants-functions-mcp) を使って情報を取得し、日本語でわかりやすく整理して伝えます。

「ツールを追加する」を選択します。

「新しいツール」を選択します。

「モデルコンテキストプロトコル」を選択します。

下記を設定して、「作成」を選択します。
※defaultキーは、「作成」を選択した後で入力します。
| 項目 | 設定内容 |
|---|---|
| サーバー名 | 任意の名称を設定 例)jgrants-functions-mcp |
| サーバーの記述 | 任意の説明文を設定 例)jGrantsの補助金情報を検索するMCPサーバー |
| サーバーURL | https://作成したFunctionAppのドメイン.azurewebsites.net/mcp |
| x-functions-key | 作成したFunctionAppのdefaultキー |

サーバーURLは下記で確認します。

「未接続」を選択し、新しい接続を作成します。

Function Appのアプリキーを設定し、「作成」を選択します。

アプリキーは、Azureポータルのアプリキーからdefaultキーをコピーして貼り付けます。

「追加と構成」を選択します。

ツールが作成されます。
問題なければ、ツールの項目にMCPサーバーで使用できるツールの名前と説明文が表示されます。

動作確認
Copilot Studio から「補助金を検索して」と話しかけた結果です。
Azure Functions 上で稼働する MCP サーバーへの接続が確立されており、jGrants のデータソースから取得した実際の補助金情報がチャット上に表示されることを確認しました。

まとめ
今回紹介した手順を通じて、jGrants の MCP サーバーを Azure Functions 上で動かし、Microsoft Copilot Studio と連携させるまでの一連の流れを確認できました。
特に Azure Functions のカスタムハンドラー対応や、環境変数設定など、実際に手を動かす中で見えてくるポイントも多くありました。
MCP 対応のユースケースが広がる中で、既存 API を柔軟に活用できる選択肢として、Azure Functions 経由でのホスティングは十分に現実的な構成だと感じています。
同じような構成を検討している方の参考になれば幸いです。