2025年12月26日金曜日

Google Chromeの分割ビューを使用してアプリケーション・ビルダーとアプリを同じタブに表示する

Oracle APEXの開発チームに所属している、イタリア在住のSteve Muenchさんが以下のブログ記事を公開されています。

Builder + App Side-by-Side in Chrome

Google Chromeのバージョン143.0.7499.41から分割ビューという機能が追加されています。タブを2つのビューに分割して、左右それぞれのビューに別のウィンドウを表示できる、という機能です。

APEXでアプリケーションを開発していると、アプリケーション・ビルダーから実行したAPEXアプリケーションのウィンドウがどこかに行ってしまって見つからない、ということがあります。

分割ビューを使って、ひとつのタブにアプリケーション・ビルダーを左のビューに、開発中のアプリケーションを右のビューに(左右はどちらでもよい)表示したら、そのようなことがなくなるかもしれません。そういうことで、Steve Muenchさんは分割ビューの使い方を紹介しています。

本記事でも、日本語のGoogle Chromeで分割ビューを試してみます。1画面の左右にアプリケーション・ビルダーとアプリケーションを表示するため、ある程度広いモニターは必須だろうと思います。

ページ・デザイナをGoogle Chromeで開いた状態から始めます。


分割ビューに表示する予定のアプリケーションを、あらかじめ実行しておきます。


実行したアプリケーションが新しいタブで開きます。


ページ・デザイナに戻り、タブ上でコンテキスト・メニューを開きます。

コンテキスト・メニューから、「新しい分割ビューにタブを追加」を実行します。


分割ビューに表示されたタブより、先ほど実行したAPEXアプリケーションのタブを選択します。


選択したタブが右のビューに表示されます。結果として、ページ・デザイナが左のビュー、アプリケーションが右のビューに表示されます。


分割ビューで表示されていますが、ページ・デザイナとAPEXアプリケーションは連携されてます。

例えば開発者ツールバーのクイック編集をオンにして、コンポーネントを選択します。


クイック編集で選択したコンポーネントが、左のページ・デザイナでフォーカスされます。


ページ・デザイナ上で新しいコンポーネントを追加し、ページを実行すると、すぐに右のアプリケーションに反映されます。


ページ・デザイナを2ペイン・モードにすることで、画面を広く使うことができます。


ページ・デザイナを2ペイン・モードにすると、一般的に中央に表示されるレイアウト・ビューが無くなります。


中央のペインに表示されていたタブは無くなった訳ではなく、左のペインに寄せられています。


このタブはドラッグ&ドロップで位置を変更できます。

左ペインで使用頻度が高いのはレンダリング動的アクションプロセスだと思います。その横にヘルプを移動します。ページ共有コンポーネントレイアウトページ検索を使用することは少ないように思います。


以上のような変更をページ・デザイナに加えることで、狭い画面にもフィットします。


分割ビューを閉じるには、タブにある x 印をクリックするか、右下のタブの  x 印をクリックします。


アプリケーション・ビルダーから別のアプリケーションを実行すると、分割ビューで実行されず、新しいタブが開きます。分割ビューに表示されているアプリケーションは変わりません。


分割ビューに表示するアプリケーションを変更するには、一旦ビューを分離します。

ビューを分離します。


ビューが分離され、タブに戻ります。


ページ・デザイナのタブを選択して表示します。


ページ・デザイナのタブが選択された状態で、分割ビューに表示させるアプリケーションのタブのコンテキスト・メニューを表示します。

コンテキスト・メニューの「現在のタブで新しい分割表示」を実行します。


以上の操作で、分割ビューに表示するアプリケーションを変更できます。


変更したページ・デザイナのレイアウトは、ユーザーごとに記憶されます。デフォルトの状態に戻すには、ユーティリティレイアウトより、レイアウトのリセットを実行します。


以上、Google Chromeの新しい分割ビューを、Oracle APEXで活用する方法の紹介でした。

Oracle APEXのアプリケーション作成の参考になれば幸いです。

Gemini Nanoのマルチモーダルに対応したPrompt APIをAPEXのアプリから呼び出してみる

Google NanoのPrompt APIがマルチモーダルに対応したので、Oracle APEXのアプリケーションから呼び出してみました。MacのGoogle Chromeで動作を確認しています。


Prompt APIおよびSummarization APIを呼び出すAPEXアプリは、以前の記事「Google ChromeのPrompt APIをOracle APEXのアプリから呼び出してみる」および「Google ChromeのSummarization APIを呼び出してみる」で作成しています。

このAPEXアプリケーションに、画像と音声を含むプロンプトを作成しPrompt APIを呼び出す機能を追加します。機能追加したアプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/sample-gemini-nano.zip

Google Chromeよりchrome://flags/#prompt-api-for-gemini-nano-multimodal-inputを開き、Prompt API for Gemini Nano with Multimodal InputEnabledに変更し、Chromeを再起動します。


機能はすべてホーム・ページに実装しています。

ホーム・ページにページ・アイテムやリージョンを配置していますが、処理についてはすべて静的アプリケーション・ファイルにJavaScriptを記述して実装しています。ページ上のコンポーネントをAPEXアクションに紐づけています。


データと紐づいている(JavaScriptから参照される)ページ上のコンポーネントは、以下のように配置されています。


システム・プロンプトはページ・アイテムP1_SYSTEM_PROMPTに保持されます。ユーザー・プロンプトはP1_USER_PROMPTに保持されます。

音声はAUDIO要素(id="player")にて保持します。画像はページ・アイテムP1_IMAGEで選択します。プレビューのためにIMG要素(id="preview")のsrc属性に、選択したファイルの内容を設定します。Prompt APIはページ・アイテムではなく、IMG要素のsrc属性に設定した画像を参照しています。

ページ・アイテムP1_RESPONSEにPrompt APIからのレスポンスを表示します。このページ・アイテムのタイプリッチ・テキスト・エディタで、Markdown形式のドキュメントを整形して表示します。

APEXアクションへの紐付けは以下になっています。

ボタンStartは音声の録音を開始するAPEXアクション"START_RECORDING"に紐づいています。録音を停止するボタンStopは"STOP_RECORDING"、録音をリセットするボタンResetは"RESET_RECORDING"に紐づいています。

ファイルの選択を変更したときは、APEXアクション"PREVIEW"が呼ばれるようにしています。ボタンについてはカスタム要素data-actionにAPEXアクション名を設定することで紐づけられますが、ファイルの選択はカスタム属性data-actionに対応していません。そのため、これだけはページ・アイテムの変更イベントを拾って、APEXアクションを呼び出しています。

ボタンExplainをクリックしたときに、Prompt APIの呼び出しを行うAPEXアクション"EXPLAIN"が実行されるように、カスタム属性data-acion="EXPLAIN"を設定しています。


これ以外は主にレイアウトを調整するためにリージョンを使用しています。

静的アプリケーション・ファイルとしてgemini-nano-multimodal.jsを作成しています。Claude Sonnet 4.5にレビューをお願いしたら、1/3くらい書き直されました。

このファイルをページ・プロパティJavaScriptファイルURLに設定しています。

#APP_FILES#gemini-nano-multimodal#MIN#.js


作成したアプリケーションの紹介は以上です。

アプリケーションを実行して、Prompt APIを呼び出してみました。

竹取物語の冒頭を録音して、ユーザー・プロンプトで文字起こしを依頼してみました。


画像を添付して、解説をお願いしました。


添付した画像の解説を、音声でお願いしました。


画像を添付し、文字の取り出しをお願いしてみました。


すごく精度が高いということはありませんが、軽くて速くてお金もかからないのは利点です。1年前と比べると、著しく進歩していることは確かです。

今回の記事は以上です。

Oracle APEXのアプリケーション作成の参考になれば幸いです。

2025年12月24日水曜日

Autonomous AI Databaseをバックエンドとするリバース・プロキシをnginxで構成する

最近の一連の記事にてOracle REST Data ServicesのRESTモジュールとして作成した、リモートMCPサーバーを使用しています。しかし、開発に使用するデータベースをOracle Cloudなどのコンピュート・インスタンスで実行しているOracle Database 26ai Freeを対象としているため、コンピュート・インスタンスの分だけ費用が発生します。また、環境を作成する手間もかかります。

バックエンドとなるOracle REST Data ServicesにAutonomous AI Databaseを使用するように、nginxのリバース・プロキシを構成してみます。nginxはAlways Freeの範囲で使用できるVM.Standard.E2.1.Microのインスタンスで実行します。

調べた範囲ではパブリック・エンドポイントからアクセスするADBは、Hostヘッダーに必ずパブリックなエンドポイントを指定しないと動作しないようです。ORDSのUIおよびAPEXのUIはHostヘッダーを参照してリダイレクトするため、リバース・プロキシのホストを指していても、パブリックなエンドポイントに移動します。ORDS REST APIの呼び出しではAPIのコードを自分で書いているためリダイレクトは発生しませんが、AutoRESTなどでは影響を受けるでしょう。そのため、リバース・プロキシを適用できるのは自作のORDS REST APIに限定されます。顧客管理ORDSまたはプライベート・エンドポイントのADBであれば、この制約は受けないと思います。

誰でもお金をかけずに作業できるようにするためのサポート対象外の構成なので、仕方がありません。

以下より、Oracle Cloudのコンピュート・インスタンスを作成して、nginxのリバース・プロキシを実装するまでの手順を説明します。

Oracle Cloudのコンソールからコンピュートからインスタンスを開き、インスタンスの作成を開始します。


作成するインスタンスの名前は任意ですが、本記事ではrvs-proxyとします。


イメージCanonical Ubuntu 24.04を選択し、シェイプはAlways Freeの対象であるVM.Standard.E2.1 Microを選択します。

へ進みます。


セキュリティはデフォルトの設定のまま変更せず、に進みます。


ネットワークもデフォルトの設定のまま変更しません。Always Freeの範囲であれば、それほど変更できる設定も無いはずです。

SSHキーの追加としてキー・ペアを自動で生成を選択し、生成された秘密キーをダウンロードしておきます。

へ進みます。


ストレージについてもデフォルトの設定のまま、へ進みます。


確認のページで、作成を実行します。


インスタンスの作成が開始します。


インスタンスの作成が成功したら、ネットワーキングタブを開いて、インスタンスに割り当たったパブリックIPアドレスを確認します。


プライマリVNICパブリックIPv4アドレスをコピーします。

このIPアドレスをDNSに登録し、ホスト名でアクセスできるようにしておきます。


以上で、Oracle Cloudでのコンピュート・インスタンスの作成は完了です。

作成したコンピュート・インスタンスにsshで接続し、nginxを構成します。

ssh -i <ダウンロードした秘密キー・ファイル> ubuntu@<DNSに登録したホスト名>

% ssh -i ssh-rvs-proxy.key ubuntu@ホスト名

The authenticity of host 'ordsmcp****.f5.si (143.***.***.145)' can't be established.

ED25519 key fingerprint is SHA256:wrxUaOWKPbuHoNH0C1nlZTTZLQ7fJ2HNvsUOtsjNS2I.

This key is not known by any other names.

Are you sure you want to continue connecting (yes/no/[fingerprint])? yes

Warning: Permanently added 'ordsmcp****.f5.si' (ED25519) to the list of known hosts.

Welcome to Ubuntu 24.04.3 LTS (GNU/Linux 6.14.0-1016-oracle x86_64)


 * Documentation:  https://help.ubuntu.com

 * Management:     https://landscape.canonical.com

 * Support:        https://ubuntu.com/pro


 System information as of Wed Dec 24 07:25:06 UTC 2025


  System load:  0.01              Processes:             124

  Usage of /:   4.3% of 44.07GB   Users logged in:       0

  Memory usage: 23%               IPv4 address for ens3: 10.0.0.135

  Swap usage:   0%


Expanded Security Maintenance for Applications is not enabled.


0 updates can be applied immediately.


Enable ESM Apps to receive additional future security updates.

See https://ubuntu.com/esm or run: sudo pro status



The list of available updates is more than a week old.

To check for new updates run: sudo apt update



The programs included with the Ubuntu system are free software;

the exact distribution terms for each program are described in the

individual files in /usr/share/doc/*/copyright.


Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by

applicable law.


To run a command as administrator (user "root"), use "sudo <command>".

See "man sudo_root" for details.


ubuntu@rvs-proxy:~$ 


スーパー・ユーザーに切り替えます。

sudo -s

ubuntu@rvs-proxy:~$ sudo -s

root@rvs-proxy:/home/ubuntu# 


nginxのプラグインをインストールするため、aptのリポジトリをuniverseを指定して追加します。

apt-add-repository universe

root@rvs-proxy:/home/ubuntu# apt-add-repository universe

Adding component(s) 'universe' to all repositories.

Press [ENTER] to continue or Ctrl-c to cancel.

Hit:1 http://iad-ad-3.clouds.archive.ubuntu.com/ubuntu noble InRelease

Get:2 http://iad-ad-3.clouds.archive.ubuntu.com/ubuntu noble-updates InRelease [126 kB]

Get:3 http://security.ubuntu.com/ubuntu noble-security InRelease [126 kB]

Get:4 http://iad-ad-3.clouds.archive.ubuntu.com/ubuntu noble-backports InRelease [126 kB]


[中略]



Get:52 http://iad-ad-3.clouds.archive.ubuntu.com/ubuntu noble-backports/restricted amd64 Components [216 B]   

Get:53 http://iad-ad-3.clouds.archive.ubuntu.com/ubuntu noble-backports/restricted amd64 c-n-f Metadata [116 B]

Get:54 http://iad-ad-3.clouds.archive.ubuntu.com/ubuntu noble-backports/multiverse amd64 Components [212 B]   

Get:55 http://iad-ad-3.clouds.archive.ubuntu.com/ubuntu noble-backports/multiverse amd64 c-n-f Metadata [116 B]

Fetched 39.2 MB in 20s (1970 kB/s)                                                                            

Reading package lists... Done

root@rvs-proxy:/home/ubuntu# 


nginxとmore_clear_headersを含むモジュールをインストールします。

apt install -y nginx libnginx-mod-http-headers-more-filter

root@rvs-proxy:/home/ubuntu# apt install -y nginx libnginx-mod-http-headers-more-filter

Reading package lists... Done

Building dependency tree... Done

Reading state information... Done

The following additional packages will be installed:

  nginx-common

Suggested packages:

  fcgiwrap nginx-doc ssl-cert

The following NEW packages will be installed:

  libnginx-mod-http-headers-more-filter nginx nginx-common

0 upgraded, 3 newly installed, 0 to remove and 64 not upgraded.

Need to get 577 kB of archives.


[中略]


Running kernel seems to be up-to-date.


No services need to be restarted.


No containers need to be restarted.


No user sessions are running outdated binaries.


No VM guests are running outdated hypervisor (qemu) binaries on this host.

root@rvs-proxy:/home/ubuntu# 


certbotをインストールします。

snap install --classic certbot

root@rvs-proxy:/home/ubuntu# snap install --classic certbot

certbot 5.2.2 from Certbot Project (certbot-eff) installed

root@rvs-proxy:/home/ubuntu# 


iptablesを実行して、ポート80および443への接続許可を与えます。

iptables -L INPUT -n --line-numbers
iptables -I INPUT 5 -p tcp --dport 80 -m conntrack --ctstate NEW -j ACCEPT
iptables -I INPUT 6 -p tcp --dport 443 -m conntrack --ctstate NEW -j ACCEPT
iptables -L INPUT -n --line-numbers
netfilter-persistent save
netfilter-persistent reload


root@rvs-proxy:/home/ubuntu# iptables -L INPUT -n --line-numbers

Chain INPUT (policy ACCEPT)

num  target     prot opt source               destination         

1    ACCEPT     0    --  0.0.0.0/0            0.0.0.0/0            state RELATED,ESTABLISHED

2    ACCEPT     1    --  0.0.0.0/0            0.0.0.0/0           

3    ACCEPT     0    --  0.0.0.0/0            0.0.0.0/0           

4    ACCEPT     6    --  0.0.0.0/0            0.0.0.0/0            state NEW tcp dpt:22

5    REJECT     0    --  0.0.0.0/0            0.0.0.0/0            reject-with icmp-host-prohibited

root@rvs-proxy:/home/ubuntu# iptables -I INPUT 5 -p tcp --dport 80 -m conntrack --ctstate NEW -j ACCEPT

root@rvs-proxy:/home/ubuntu# iptables -I INPUT 6 -p tcp --dport 443 -m conntrack --ctstate NEW -j ACCEPT

root@rvs-proxy:/home/ubuntu# iptables -L INPUT -n --line-numbers

Chain INPUT (policy ACCEPT)

num  target     prot opt source               destination         

1    ACCEPT     0    --  0.0.0.0/0            0.0.0.0/0            state RELATED,ESTABLISHED

2    ACCEPT     1    --  0.0.0.0/0            0.0.0.0/0           

3    ACCEPT     0    --  0.0.0.0/0            0.0.0.0/0           

4    ACCEPT     6    --  0.0.0.0/0            0.0.0.0/0            state NEW tcp dpt:22

5    ACCEPT     6    --  0.0.0.0/0            0.0.0.0/0            tcp dpt:80 ctstate NEW

6    ACCEPT     6    --  0.0.0.0/0            0.0.0.0/0            tcp dpt:443 ctstate NEW

7    REJECT     0    --  0.0.0.0/0            0.0.0.0/0            reject-with icmp-host-prohibited

root@rvs-proxy:/home/ubuntu# netfilter-persistent save

run-parts: executing /usr/share/netfilter-persistent/plugins.d/15-ip4tables save

run-parts: executing /usr/share/netfilter-persistent/plugins.d/25-ip6tables save

root@rvs-proxy:/home/ubuntu# netfilter-persistent reload

run-parts: executing /usr/share/netfilter-persistent/plugins.d/15-ip4tables start

run-parts: executing /usr/share/netfilter-persistent/plugins.d/25-ip6tables start

root@rvs-proxy:/home/ubuntu# 


すでにnginxが実行されています。nginxのドキュメント・ルートのデフォルトは/var/www/htmlです。

certbotの以下のコマンドを実行し、Let's Encryptからサーバー証明書を発行します。
certbot certonly \
  --webroot \
  -w /var/www/html \
  -d [ホスト名] \
  --email [自分のメールアドレス] \
  --agree-tos \
  --no-eff-email

root@rvs-proxy:/home/ubuntu# certbot certonly \

  --webroot \

  -w /var/www/html \

  -d ordsmcp****.f5.si \

  --email y***********@oracle.com \

  --agree-tos \

  --no-eff-email

Saving debug log to /var/log/letsencrypt/letsencrypt.log

Requesting a certificate for ordsmcp****.f5.si


Successfully received certificate.

Certificate is saved at: /etc/letsencrypt/live/ordsmcp****.f5.si/fullchain.pem

Key is saved at:         /etc/letsencrypt/live/ordsmcp****.f5.si/privkey.pem

This certificate expires on 2026-03-24.

These files will be updated when the certificate renews.

Certbot has set up a scheduled task to automatically renew this certificate in the background.


- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

If you like Certbot, please consider supporting our work by:

 * Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate

 * Donating to EFF:                    https://eff.org/donate-le

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

root@rvs-proxy:/home/ubuntu# 


nginxの設定ファイルを置き換えます。

/etc/nginx/nginx.confを以下のファイルに置き換えます。

/etc/nginx/conf.d/01-server.confとして、以下のファイルを配置します。ホスト名として記述されているordsmcp.f5.siの部分は、コンピュート・インスタンスのIPアドレスと共に、DNSに登録したホスト名に置き換えます。

01-server.confより参照される構成ファイルを配置するディレクトリとして、default.dを作成します。

mkdir /etc/nginx/default.d

root@rvs-proxy:/etc/nginx# mkdir /etc/nginx/default.d

root@rvs-proxy:/etc/nginx# 


/etc/nginx/default.d/01-apex-adb.confとして、以下のファイルを配置します。変数$ords_upstream_hostに、上流となるAutonomous AI Databaseを指定します。

以上で設定は完了です。

nginxをリロードします。

nginx -s reload

root@rvs-proxy:/etc/nginx# nginx -s reload

2025/12/24 08:18:24 [notice] 4868#4868: signal process started

root@rvs-proxy:/etc/nginx# 


次の記事の作業を実施していることを前提として、Oracle IAMをIdM、Autonomous AI DatabaseをバックエンドとしたリモートMCPサーバーに、Claude Desktopから繋いでみます。

nginxのドキュメント・ルートは/usr/share/nginx/htmlに変更されています。変更されたドキュメント・ルートに移動します。

cd /usr/share/nginx/html

root@rvs-proxy:/etc/nginx# cd /usr/share/nginx/html

root@rvs-proxy:/usr/share/nginx/html# 


ディレクトリ.well-knownを作成します。

mkdir .well-known

root@rvs-proxy:/usr/share/nginx/html# mkdir .well-known

root@rvs-proxy:/usr/share/nginx/html# 


ファイル.well-known/oauth-protected-resourceを作成します。resourceauthorization_serversともに、ドメインURLを設定します。
{
  "resource": "ドメインURL",
  "authorization_servers": [
    "ドメインURL"
  ]
}
ドメインURLは、Oracle IAMでアプリケーションを作成したドメインのURLです。ドメイン詳細の、以下の位置に記載されています。


認可サーバーのメタデータをnginx(つまりリソース・サーバー)から取得できるようにします。Oracle IAMからは/.well-known/oauth-authorization-serverではメタデータが取得できないため、Claude Desktopはリソース・サーバーを参照するようです。

curl -O https://ドメインURL/.well-known/openid-configuration
mv openid-configuration .well-known/oauth-authorization-server

root@rvs-proxy:/usr/share/nginx/html# curl -O https://idcs-***************.identity.oraclecloud.com:443/.well-known/openid-configuration

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current

                                 Dload  Upload   Total   Spent    Left  Speed

100  3166  100  3166    0     0  30149      0 --:--:-- --:--:-- --:--:-- 30442

root@rvs-proxy:/usr/share/nginx/html# mv openid-configuration .well-known/oauth-authorization-server

root@rvs-proxy:/usr/share/nginx/html# 


最後にnginxの自動起動を有効にします。

systemctl enable nginx

root@rvs-proxy:/usr/share/nginx/html# systemctl enable nginx

Synchronizing state of nginx.service with SysV service script with /usr/lib/systemd/systemd-sysv-install.

Executing: /usr/lib/systemd/systemd-sysv-install enable nginx

root@rvs-proxy:/usr/share/nginx/html# 


以上でリバース・プロキシの設定は完了です。

Claude Desktopからカスタムコネクタを作成します。

設定コネクタを開き、カスタムコネクタを追加をクリックします。


カスタムコネクタの追加画面が開きます。

名前My ADBとします。リモートMCPサーバーのURLは、リバース・プロキシを通して呼び出されるORDS REST APIの完全なURLを設定します。以前の記事の通りに構成している場合、以下のようなURLになります。

https://nginxが実行されているホスト/ords/<ワークスペース名>/sampleserver/mcp

クライアントIDは、Oracle IAMに作成した統合アプリOAuth構成一般情報に記載されています。

以上を入力し、追加をクリックします。


クライアントIDは以下の画面にあります。


追加されたカスタムコネクタを連携させます


ブラウザが開き、Oracle Cloudへのサインインが要求されます。


Authenticatorによる許可が要求されます。


Authenticatorで許可すると、Claude DesktopはカスタムコネクタMy ADBに接続します。

カスタムコネクタが接続されると、連携/連携するのボタンが設定に変わります。

設定を開きます。


カスタムコネクタが持っているツールを確認できます。


接続されたカスタムコネクタは、Claude Desktopのチャットから呼び出すことができます。


今回の記事は以上になります。