以前の記事「
ORDSのRESTサービスをClaude Desktopのカスタムコネクタとして登録して呼び出す」にて、Claude Desktopのカスタムコネクタとして接続できるリモートMCPサーバーを作成しました。
本記事では、ORDSのJWTプロファイルを設定することにより、ORDSのRESTサービスとして実装したリモートMCPサーバーを保護します。認証サーバーにはMicrosoft Entra IDを使用します。MCPサーバーを組み込むクライアントとして、MCP Inspector(v0.17.5)を使用しました。
作業中にMCP Inspectorのバージョンがv0.17.2からv0.17.5に上がったのですが、その際に/.well-known/oauth-authorization-serverの参照場所が変更されました。その結果、v0.17.2では動作しなくなりました。リモートMCPサーバーのOAuth2による保護は、まだ実装が固まっていない部分があるようです。実際、Claude Desktopのカスタムコネクタ(まだベータ)の設定には、MCP Inspectorで設定できるスコープの設定がありません。最新のMCP Inspectorで動作が確認できないときは、以下のように0.17.5を指定して実行することにより、設定ミスなのかMCP Inspectorの実装が変わったのか、切り分けできます。
npx @modelcontextprotocol/inspector@0.17.5MCP Inspectorによる動作確認の結果です(動画はv0.17.2ですが、記事はv0.17.5向けに更新しています)。
以下に検証に使用する環境の作成手順と検証作業について紹介します。今回は、Oracle AI Database 26ai Free、Oracle APEX 24.2、Oracle REST Data Services 25.3の環境を、Google CloudのVMインスタンスに構築しています。
以下の作業を実施します。
- Google CloudのVMインスタンスの作成
- オペレーティングシステムの設定
- DB、APEXおよびORDSの構成
- nginxによるリバース・プロキシの構成
- APEXワークスペースの作成
- Microsoft Entra IDによるORDS REST API認証の実装
- リモートMCPサーバーの実装
- リモートMCPサーバーのJWTプロファイルによる保護
Google CloudのVMインスタンスの作成
Google CloudのコンソールよりVMインスタンスのページを開きます。開いたページから、インスタンスを作成します。
マシンの構成を開きます。
名前は任意です。本記事ではordsmcpとしました。マシンタイプに最低限必要なリソースを持つe2-standard-2 (2 vCPU、1コア、8 GBメモリ)を選択しています。
OSとストレージを開きます。
オペレーティングシステムとストレージの変更をクリックします。
オペレーティングシステムとしてRocky Linux 10を選択しました。Oracle DatabaseやOracle REST Data Servicesはコンテナとして実行するため、DBやORDSの依存性は無視できます。podmanまたはDockerとnginxおよびcertbotが実行できれば、他のオペレーティングシステムでも同等の環境は作成できるでしょう。
ディスクサイズは40GBを指定しています。
ネットワーキングを開きます。
ファイアウォールのHTTPトラフィックを許可する、および、HTTPSトラフィックを許可するをチェックします。
以上の設定でVMインスタンスを作成します。
VMインスタンスが作成されると、外部IPが割り当たります。このIPはDNSサービスにホスト名と共に登録するため、コピーしておきます。外部IPはVMインスタンスを起動する度に変わります。外部IPが変更されたときは、DNSの設定も更新する必要があります。
VMインスタンスに割り当てられた外部IPをDNSサービスに登録します。本記事ではフリーのダイナミックDNSサービスの
DDNS Nowに、ホスト名
ordsmcp.f5.siとして外部IPを登録しました。登録手順については割愛します。
作成したVMインスタンスへの接続手順は、SSHよりいくつか選択できます。
オペレーティングシステムの設定
VMインスタンスに接続します。rootユーザーの作業が続くので、最初にrootに切り替えます。
sudo -s
[ynakakoshi@ordsmcp ~]$ sudo -s
[root@ordsmcp ynakakoshi]#
Podmanを含むcontainer-tools、nginxおよびunzipをインストールします。
dnf -y install container-tools nginx unzip
[root@ordsmcp ynakakoshi]# dnf -y install container-tools nginx unzip
CIQ SIG/Cloud Next for Rocky Linux 10 11 MB/s | 14 MB 00:01
Google Compute Engine 14 kB/s | 3.4 kB 00:00
Google Cloud SDK 255 kB/s | 54 kB 00:00
Rocky Linux 10 - BaseOS 23 MB/s | 4.1 MB 00:00
Rocky Linux 10 - AppStream 13 MB/s | 1.9 MB 00:00
Rocky Linux 10 - Extras 48 kB/s | 4.8 kB 00:00
Dependencies resolved.
==========================================================================================================
Package Architecture Version Repository Size
==========================================================================================================
Installing:
container-tools noarch 1-16.el10 appstream 7.3 k
nginx x86_64 2:1.26.3-1.el10 appstream 33 k
unzip x86_64 6.0-69.el10 baseos 188 k
Upgrading:
libselinux x86_64 3.9-1.el10 baseos 97 k
libselinux-utils x86_64 3.9-1.el10 baseos 122 k
libsemanage x86_64 3.9-1.el10 baseos 122 k
libsepol x86_64 3.9-1.el10 baseos 348 k
[中略]
python3-idna-3.7-4.el10.noarch python3-libsemanage-3.9-1.el10.x86_64
python3-podman-3:5.5.0-1.el10.noarch python3-requests-2.32.4-1.el10_0.noarch
python3-urllib3-1.26.19-2.el10.noarch rocky-logos-httpd-100.4-7.el10.noarch
shadow-utils-subid-2:4.15.0-8.el10.x86_64 skopeo-2:1.20.0-1.el10.x86_64
slirp4netns-1.3.3-1.el10.x86_64 toolbox-0.2-2.el10.x86_64
udica-0.2.8-6.el10.noarch unzip-6.0-69.el10.x86_64
Complete!
[root@ordsmcp ynakakoshi]#
certbotを含むリポジトリ
epel-releaseをインストールします。
dnf -y install epel-release
[root@ordsmcp ynakakoshi]# dnf -y install epel-release
Last metadata expiration check: 0:02:12 ago on Fri 05 Dec 2025 02:23:25 AM UTC.
Dependencies resolved.
==========================================================================================================
Package Architecture Version Repository Size
==========================================================================================================
Installing:
epel-release noarch 10-7.el10_1 extras 19 k
Transaction Summary
==========================================================================================================
[中略]
Installed:
epel-release-10-7.el10_1.noarch
Complete!
[root@ordsmcp ynakakoshi]#
certbotをインストールします。
dnf -y install certbot
[root@ordsmcp ynakakoshi]# dnf -y install certbot
Last metadata expiration check: 0:01:12 ago on Fri 05 Dec 2025 02:25:42 AM UTC.
Dependencies resolved.
==========================================================================================================
Package Architecture Version Repository Size
==========================================================================================================
Installing:
certbot noarch 4.2.0-1.el10_1 epel 51 k
Installing dependencies:
fontawesome4-fonts noarch 1:4.7.0-23.el10 appstream 204 k
python3-acme noarch 4.2.0-1.el10_1 epel 210 k
python3-certbot noarch 4.2.0-1.el10_1 epel 881 k
python3-cffi x86_64 1.16.0-7.el10 baseos 310 k
python3-configargparse noarch 1.7.1-1.el10_1 epel 53 k
python3-configobj
noarch 5.0.8-10.el10 appstream 83 k
[中略]
python3-ply-3.11-25.el10.noarch python3-pyOpenSSL-25.0.0-1.el10_1.noarch
python3-pycparser-2.20-16.el10.noarch python3-pyrfc3339-1.1-20.el10_0.noarch
python3-pytz-2025.1-1.el10_1.noarch python3-typing-extensions-4.9.0-6.el10.noarch
Complete!
[root@ordsmcp ynakakoshi]#
ユーザー
oracle、グループ
oinstallを作成します。
Oracle Databaseなどはコンテナ内でユーザー
oracleとして実行されます。コンテナ内からホストのファイル・システムを参照するにあたって、参照するホスト側にあるディレクトリの所有者のUIDやGIDが、コンテナ内のユーザー
oracleと一致するようにします。
groupadd -g 54321 oinstall
useradd -u 54321 -g 54321 oracle
[root@ordsmcp ynakakoshi]# groupadd -g 54321 oinstall
[root@ordsmcp ynakakoshi]# useradd -u 54321 -g 54321 oracle
[root@ordsmcp ynakakoshi]#
ユーザーoracleがログインしていなくてもサービスが実行できるように、以下のコマンドを実行します。
loginctl enable-linger 54321
[root@ordsmcp ynakakoshi]# loginctl enable-linger 54321
[root@ordsmcp ynakakoshi]#
リバース・プロキシとして使用するnginxがORDSに接続できるように、SE Linuxを設定します。
setsebool -P httpd_can_network_connect 1
[root@ordsmcp ynakakoshi]# setsebool -P httpd_can_network_connect 1
[root@ordsmcp ynakakoshi]#
オペレーティングシステムの設定は以上で完了です。
DB、APEXおよびORDSの構成
Oracle AI Database、Oracle APEXおよびOracle REST Data Servicesを構成します。作業は先ほど作成したユーザーoracleで実施します。VMインスタンスの接続直後であれば、以下のコマンドを実行し、ユーザーoracleに切り替えます。rootから切り替える場合は、sudoは不要です。
sudo su - oracle
[ynakakoshi@ordsmcp ~]$ sudo su - oracle
[oracle@ordsmcp ~]$
Oracle AI Database 26ai Freeのコンテナ・イメージをダウンロードします。
podman pull container-registry.oracle.com/database/free:latest
[oracle@ordsmcp ~]$ podman pull container-registry.oracle.com/database/free:latest
Trying to pull container-registry.oracle.com/database/free:latest...
Getting image source signatures
Copying blob 97fd3103f315 done |
Copying blob 867532f50b57 done |
Copying blob 5bf4d5bb53fa done |
Copying blob 359a083bb2a1 done |
Copying blob a788b7aca3f6 done |
Copying blob d564e67f1ed2 done |
Copying blob 3852ff38ea46 done |
Copying blob 325b6722024f done |
Copying blob d1e8ff124bb5 done |
Copying blob f3f45addaa5c done |
Copying blob 21f5b3d4bded done |
Copying blob c62f5145519a done |
Copying blob 1ae8998597b3 done |
Copying blob c4dd45b650b9 done |
Copying blob 42048da13555 done |
Copying blob 61135ed510cd done |
Copying blob e774aa72c2b3 done |
Copying blob 73e204b18f80 done |
Copying blob 2a2ff731d809 done |
Copying blob 0361c3d5b31e done |
Copying blob 78d585384f78 done |
Copying blob 8b75f497490b done |
Copying config 3c986e106c done |
Writing manifest to image destination
3c986e106c3e8ae13457ccd8b6638417ddfae7bcf73f75a0d4291ae14bd46116
[oracle@ordsmcp ~]$
Oracle REST Data Servicesのコンテナ・イメージをダウンロードします。
podman pull container-registry.oracle.com/database/ords:latest[oracle@ordsmcp ~]$ podman pull container-registry.oracle.com/database/ords:latest
Trying to pull container-registry.oracle.com/database/ords:latest...
Getting image source signatures
Copying blob 2c2963ed5b49 done |
Copying blob ac06ceafe5b9 done |
Copying blob 9bf96270f9cf done |
Copying blob ac20eadf1879 done |
Copying blob f7212a4628d0 done |
Copying blob 30ffcb3cce85 done |
Copying blob 62e87c40596c done |
Copying config 760e3ba983 done |
Writing manifest to image destination
760e3ba983b7ae56ca1e2634e6194898d03c72edeafe3a96d27055c9597f0310
[oracle@ordsmcp ~]$
Oracle APEXの最新版のアーカイブをダウンロードし、/home/oracle以下に展開します。
curl -OL https://download.oracle.com/otn_software/apex/apex-latest.zip
unzip apex-latest.zip[oracle@ordsmcp ~]$ curl -OL https://download.oracle.com/otn_software/apex/apex-latest.zip
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 289M 100 289M 0 0 122M 0 0:00:02 0:00:02 --:--:-- 122M
[oracle@ordsmcp ~]$ unzip apex-latest.zip
Archive: apex-latest.zip
inflating: META-INF/MANIFEST.MF
inflating: META-INF/ORACLE_C.SF
inflating: META-INF/ORACLE_C.RSA
creating: apex/
inflating: apex/apex_rest_config.sql
inflating: apex/apex_rest_config_cdb.sql
inflating: apex/apex_rest_config_core.sql
inflating: apex/apex_rest_config_nocdb.sql
[中略]
inflating: apex/utilities/debug/d1.sql
inflating: apex/utilities/debug/d2.sql
inflating: apex/utilities/debug/ds.sql
creating: apex/utilities/support/
inflating: apex/utilities/support/apex_verify.sql
[oracle@ordsmcp ~]$
データ・ファイルを配置するディレクトリを
/home/oracle/oradataとして作成します。その後、データベースのコンテナの作成と実行を行います。
構成が完了するまでログを確認します。
mkdir oradata
podman run -d --name apex-db --privileged --userns=keep-id:uid=54321,gid=54321 -p 1521:1521 -v /home/oracle/oradata:/opt/oracle/oradata -v /home/oracle/apex:/home/oracle/apex container-registry.oracle.com/database/free:latest
podman logs -f apex-db
ログに
DATABASE IS READY TO USE!と出力されれば、データベースは利用可能です。ログの確認を停止し、次の作業へ移ります。
[oracle@ordsmcp ~]$ mkdir oradata
[oracle@ordsmcp ~]$ podman run -d --name apex-db --privileged --userns=keep-id:uid=54321,gid=54321 -p 1521:1521 -v /home/oracle/oradata:/opt/oracle/oradata -v /home/oracle/apex:/home/oracle/apex container-registry.oracle.com/database/free:latest
59756430b7087be08696bde1aebdb773aa526f24d63ade75a0823098fdd6c14e
[oracle@ordsmcp ~]$ podman logs -f apex-db
Specify a password to be used for database accounts. Oracle recommends that the password entered should be at least 8 characters in length, contain at least 1 uppercase character, 1 lower case character and 1 digit [0-9]. Note that the same password will be used for SYS, SYSTEM and PDBADMIN accounts:
Confirm the password:
Configuring Oracle Listener.
Listener configuration succeeded.
Configuring Oracle AI Database FREE.
Enter SYS user password:
******************
Enter SYSTEM user password:
****************
Enter PDBADMIN User Password:
***************
Prepare for db operation
7% complete
Copying database files
29% complete
Creating and starting Oracle instance
30% complete
33% complete
36% complete
39% complete
43% complete
Completing Database Creation
47% complete
49% complete
50% complete
Creating Pluggable Databases
54% complete
71% complete
Executing Post Configuration Actions
93% complete
Running Custom Scripts
100% complete
Database creation complete. For details check the logfiles at:
/opt/oracle/cfgtoollogs/dbca/FREE.
Database Information:
Global Database Name:FREE
System Identifier(SID):FREE
Look at the log file "/opt/oracle/cfgtoollogs/dbca/FREE/FREE.log" for further details.
Connect to Oracle AI Database using one of the connect strings:
Pluggable database: 59756430b708/FREEPDB1
Multitenant container database: 59756430b708
SQL*Plus: Release 23.26.0.0.0 - Production on Fri Dec 5 02:58:20 2025
Version 23.26.0.0.0
Copyright (c) 1982, 2025, Oracle. All rights reserved.
Connected to:
Oracle AI Database 26ai Free Release 23.26.0.0.0 - Develop, Learn, and Run for Free
Version 23.26.0.0.0
SQL>
System altered.
SQL>
Pluggable database altered.
SQL>
PL/SQL procedure successfully completed.
SQL> SQL>
Session altered.
SQL>
User created.
SQL>
Grant succeeded.
SQL>
Grant succeeded.
SQL>
Grant succeeded.
SQL>
User altered.
SQL> SQL> Disconnected from Oracle AI Database 26ai Free Release 23.26.0.0.0 - Develop, Learn, and Run for Free
Version 23.26.0.0.0
SQL*Plus: Release 23.26.0.0.0 - Production on Fri Dec 5 02:58:20 2025
Version 23.26.0.0.0
Copyright (c) 1982, 2025, Oracle. All rights reserved.
Connected to:
Oracle AI Database 26ai Free Release 23.26.0.0.0 - Develop, Learn, and Run for Free
Version 23.26.0.0.0
SQL> Database closed.
Database dismounted.
ORACLE instance shut down.
SQL> ORACLE instance started.
Total System Global Area 1603373280 bytes
Fixed Size 5007584 bytes
Variable Size 402653184 bytes
Database Buffers 1191182336 bytes
Redo Buffers 4530176 bytes
Database mounted.
SQL>
Database altered.
SQL>
Database altered.
SQL>
Database altered.
SQL> SQL> Disconnected from Oracle AI Database 26ai Free Release 23.26.0.0.0 - Develop, Learn, and Run for Free
Version 23.26.0.0.0
The Oracle base remains unchanged with value /opt/oracle
Executing user defined scripts
/opt/oracle/runUserScripts.sh: running /opt/oracle/scripts/extensions/setup/registerService.sh
DONE: Executing user defined scripts
The Oracle base remains unchanged with value /opt/oracle
#########################
DATABASE IS READY TO USE!
#########################
The following output is now a tail of the alert.log:
PDB$SEED(2):Opening pdb with Resource Manager plan: DEFAULT_PLAN
2025-12-05T02:58:34.792168+00:00
(3):--ATTENTION--
(3):PARALLEL_MAX_SERVERS (with value 1) is insufficient. This may affect transaction recovery performance.
Modify PARALLEL_MAX_SERVERS parameter to a value > 4 (= parallel servers count computed from parameter FAST_START_PARALLEL_ROLLBACK) in PDB ID 3
FREEPDB1(3):Autotune of undo retention is turned on.
2025-12-05T02:58:36.272863+00:00
FREEPDB1(3):Opening pdb with Resource Manager plan: DEFAULT_PLAN
Completed: Pluggable database FREEPDB1 opened read write
Completed: ALTER DATABASE OPEN
2025-12-05T02:58:41.098979+00:00
===========================================================
Dumping current patch information
===========================================================
No patches have been applied
===========================================================
データベースのSYSのパスワードを環境変数
ORACLE_PWDに設定します。
[パスワード]の部分に、
パスワードとして適切な文字列を指定します。今後の作業で複数回、SYSのパスワードを指定する箇所があるため、打ち間違いなどを防止します。
その上で、作成したデータベースのSYSのパスワードを変更します。
export ORACLE_PWD=[パスワード]
podman exec -it apex-db sh setPassword.sh $ORACLE_PWD[oracle@ordsmcp ~]$ export ORACLE_PWD=*******
[oracle@ordsmcp ~]$ podman exec -it apex-db sh setPassword.sh $ORACLE_PWD
The Oracle base remains unchanged with value /opt/oracle
SQL*Plus: Release 23.26.0.0.0 - Production on Fri Dec 5 03:03:04 2025
Version 23.26.0.0.0
Copyright (c) 1982, 2025, Oracle. All rights reserved.
Connected to:
Oracle AI Database 26ai Free Release 23.26.0.0.0 - Develop, Learn, and Run for Free
Version 23.26.0.0.0
SQL>
User altered.
SQL>
User altered.
SQL>
Session altered.
SQL>
User altered.
SQL> Disconnected from Oracle AI Database 26ai Free Release 23.26.0.0.0 - Develop, Learn, and Run for Free
Version 23.26.0.0.0
[oracle@ordsmcp ~]$
コンテナ
apex-dbに接続し、データベースにAPEXをインストールします。
podman exec -it apex-db bash
[oracle@ordsmcp ~]$ podman exec -it apex-db bash
bash-4.4$
APEXのイメージが展開されたディレクトリ/home/oracle/apexへ移動し、データベースに接続してAPEXのインストールを実行します。
cd apex
export NLS_LANG=American_America.AL32UTF8
sqlplus / as sysdba
alter session set container = freepdb1;
@apexins SYSAUX SYSAUX TEMP /i/bash-4.4$ cd apex
bash-4.4$ export NLS_LANG=American_America.AL32UTF8
bash-4.4$ sqlplus / as sysdba
SQL*Plus: Release 23.26.0.0.0 - Production on Fri Dec 5 03:08:03 2025
Version 23.26.0.0.0
Copyright (c) 1982, 2025, Oracle. All rights reserved.
Connected to:
Oracle AI Database 26ai Free Release 23.26.0.0.0 - Develop, Learn, and Run for Free
Version 23.26.0.0.0
SQL> alter session set container = freepdb1;
Session altered.
SQL> @apexins SYSAUX SYSAUX TEMP /i/
...set_appun.sql
PL/SQL procedure successfully completed.
[中略]
The structure of the link to the Oracle APEX development environment is as follows:
http://host:port/ords/apex
timing for: Phase 3 (Switch)
Elapsed: 0.32
timing for: Complete Installation
Elapsed: 10.83
SYS>
APEXのインストールが完了したのち、続けて日本語リソースをロードします。
@load_trans JAPANESE
SYS> @load_trans JAPANESE
PL/SQL procedure successfully completed.
Installing Oracle APEX translation - JAPANESE
. ORACLE
.
. Oracle APEX Hosted Development Service Installation.
..............................................................
PL/SQL procedure successfully completed.
PL/SQL procedure successfully completed.
--application/set_environment
API Last Extended:20241130
Your Current Version:20241130
This import is compatible with version: 20241130
[中略]
--application/deployment/definition
--application/deployment/checks
--application/deployment/buildoptions
--application/end_environment
... elapsed: 6.93 sec
...done
Adjust instance settings
PL/SQL procedure successfully completed.
SYS>
データベース・ユーザー
APEX_PUBLIC_USERをアンロックします。
alter user apex_public_user account unlock no authentication;
SYS> alter user apex_public_user account unlock no authentication;
User altered.
SYS>
管理者ユーザーとパスワードを設定します。管理者ユーザー名はデフォルトの
ADMINとします。
@apxchpwdSYS> @apxchpwd
...set_appun.sql
================================================================================
This script can be used to change the password of an Oracle APEX
instance administrator. If the user does not yet exist, a user record will be
created.
================================================================================
Enter the administrator's username [ADMIN]
User "ADMIN" does not yet exist and will be created.
Enter ADMIN's email [ADMIN]
Enter ADMIN's password [] ***********
Created instance administrator ADMIN.
SYS>
sqlplusを終了します。続けて、コンテナ
apex-dbから抜け、ホストに戻ります。
exitexit
SYS> exit
Disconnected from Oracle AI Database 26ai Free Release 23.26.0.0.0 - Develop, Learn, and Run for Free
Version 23.26.0.0.0
bash-4.4$ exit
exit
[oracle@ordsmcp ~]$
Oracle REST Data Servicesのコンテナの作成と実行を行います。構成情報を保存するディレクトリとして/home/oracle/ords_configを作成し、コンテナ内の/etc/ords/configにマウントします。
接続先のデータベースはコンテナの外にあるため、DBHOSTはlocalhostではなく、host.containers.internalを指定します。
mkdir ords_config
podman run -d --name apex-ords --privileged --userns=keep-id:uid=54321,gid=54321 -e DBHOST=host.containers.internal -e DBPORT=1521 -e DBSERVICENAME=freepdb1 -e ORACLE_PWD=$ORACLE_PWD -p 8080:8080 -v /home/oracle/ords_config:/etc/ords/config -v /home/oracle/apex:/opt/oracle/apex container-registry.oracle.com/database/ords:latest
podman logs -f apex-ordsORDSが正常に起動されたらログの確認を停止し、次の作業へ移ります。
[oracle@ordsmcp ~]$ mkdir ords_config
[oracle@ordsmcp ~]$ podman run -d --name apex-ords --privileged --userns=keep-id:uid=54321,gid=54321 -e DBHOST=host.containers.internal -e DBPORT=1521 -e DBSERVICENAME=freepdb1 -e ORACLE_PWD=$ORACLE_PWD -p 8080:8080 -v /home/oracle/ords_config:/etc/ords/config -v /home/oracle/apex:/opt/oracle/apex container-registry.oracle.com/database/ords:latest
870492aecdbf82e61c06b7012ae663eda57149d97ff5439114a5a3159b89decb
[oracle@ordsmcp ~]$ podman logs -f apex-ords
Testing database connection...
INFO : Attempt 1: Connecting to sys/*****@host.containers.internal:1521/freepdb1 as sysdba...
INFO : Database connection successful.
INFO : The Oracle REST Data Services are not installed on your database.
INFO : Installing The Oracle REST Data Services 25.3.1.
INFO : ORDS_PWD env var is not set, using generated value WVF*zG80644^
INFO : The Oracle REST Data Services 25.3.1 has been installed correctly on your database.
INFO : The container found Oracle APEX version 24.2.0 in the mounted volume.
INFO : The Oracle APEX 24.2.0 is already installed in your database.
INFO : Set plsql.gateway.mode proxied after Oracle APEX was installed.
INFO : Setup standalone.static.path /opt/oracle/apex/images.
INFO : Starting the Oracle REST Data Services instance.
2025-12-05T03:53:36Z INFO ORDS has not detected the option '--config' and this will be set up to the default directory.
ORDS: Release 25.3 Production on Fri Dec 05 03:53:40 2025
Copyright (c) 2010, 2025, Oracle.
Configuration:
/etc/ords/config
2025-12-05T03:53:43.668Z INFO HTTP and HTTP/2 cleartext listening on host: 0.0.0.0 port: 8080
2025-12-05T03:53:43.825Z INFO Disabling document root because the specified folder does not exist: /etc/ords/config/global/doc_root
2025-12-05T03:53:43.829Z INFO Default forwarding from / to contextRoot configured.
2025-12-05T03:53:44.114Z SEVERE ORAMLVERSION null
2025-12-05T03:53:44.132Z INFO Oracle API for MongoDB listening on port: 27017
2025-12-05T03:53:44.134Z INFO The Oracle API for MongoDB connection string is:
mongodb://[{user}:{password}@]localhost:27017/{user}?authMechanism=PLAIN&authSource=$external&ssl=true&retryWrites=false&loadBalanced=true
2025-12-05T03:53:53.957Z INFO Configuration properties for: |default|lo|
db.connectionType=basic
db.hostname=host.containers.internal
db.port=1521
db.servicename=freepdb1
db.username=ORDS_PUBLIC_USER
feature.sdw=true
plsql.gateway.mode=proxied
restEnabledSql.active=true
security.requestValidationFunction=ords_util.authorize_plsql_gateway
database.api.enabled=true
mongo.enabled=true
standalone.access.log=/tmp/ords_access_logs/
standalone.static.path=/opt/oracle/apex/images
file.encoding=ANSI_X3.4-1968
file.separator=/
java.awt.headless=true
java.class.path=/opt/oracle/ords/ords.war
java.class.version=61.0
java.home=/opt/graalvm-ee-java17
java.io.tmpdir=/tmp
java.library.path=/usr/java/packages/lib:/usr/lib64:/lib64:/lib:/usr/lib
java.runtime.name=Java(TM) SE Runtime Environment
java.runtime.version=17.0.11+7-LTS-jvmci-21.3-b51
java.specification.name=Java Platform API Specification
java.specification.vendor=Oracle Corporation
java.specification.version=17
java.vendor=Oracle Corporation
java.vendor.url=https://java.oracle.com/
java.vendor.url.bug=https://bugreport.java.com/bugreport/
java.vendor.version=GraalVM EE 21.3.10
java.version=17.0.11
java.version.date=2024-04-16
java.vm.compressedOopsMode=32-bit
java.vm.info=mixed mode, sharing
java.vm.name=Java HotSpot(TM) 64-Bit Server VM
java.vm.specification.name=Java Virtual Machine Specification
java.vm.specification.vendor=Oracle Corporation
java.vm.specification.version=17
java.vm.vendor=Oracle Corporation
java.vm.version=17.0.11+7-LTS-jvmci-21.3-b51
jdk.debug=release
jdk.internal.vm.ci.enabled=true
line.separator=
native.encoding=ANSI_X3.4-1968
oracle.dbtools.cmdline.ShellCommand=ords
oracle.dbtools.cmdline.home=/opt/oracle/ords
oracle.dbtools.launcher.executable.jar.path=/opt/oracle/ords/ords.war
os.arch=amd64
os.name=Linux
os.version=6.12.0-55.41.1+2.1.el10_0_ciq.x86_64
path.separator=:
sun.arch.data.model=64
sun.boot.library.path=/opt/graalvm-ee-java17/lib
sun.cpu.endian=little
sun.io.unicode.encoding=UnicodeLittle
sun.java.command=/opt/oracle/ords/ords.war --config /etc/ords/config serve
sun.java.launcher=SUN_STANDARD
sun.jnu.encoding=ANSI_X3.4-1968
sun.management.compiler=HotSpot 64-Bit Tiered Compilers
user.country=US
user.dir=/etc/ords/config
user.home=/home/oracle
user.language=en
user.name=oracle
user.timezone=UTC
resource.templates.enabled=false
db.password=******
conf.use.wallet=true
2025-12-05T03:53:53.965Z WARNING *** jdbc.MaxLimit in configuration |default|lo| is using a value of 10, this setting may not be sized adequately for a production environment ***
2025-12-05T03:53:54.659Z INFO Created Pool: |default|lo|-2025-12-05T03-53-52.350317727Z at: 2025-12-05T03:53:52.350317727Z
2025-12-05T03:53:55.171Z INFO
Mapped local pools from /etc/ords/config/databases:
/ords/ => default => VALID
2025-12-05T03:53:55.200Z INFO Oracle REST Data Services initialized
Oracle REST Data Services version : 25.3.1.r2891312
Oracle REST Data Services server info: jetty/12.0.25
Oracle REST Data Services java info: Java HotSpot(TM) 64-Bit Server VM GraalVM EE 21.3.10 (build 17.0.11+7-LTS-jvmci-21.3-b51 mixed mode, sharing)
2025-12-05T03:53:55.460Z INFO RequestMonitor 1
2025-12-05T03:53:55.462Z INFO TransactionMonitor 1
2025-12-05T03:53:55.463Z INFO AccessLogMonitor 1 0
2025-12-05T03:53:55.461Z INFO CursorMonitor 1
2025-12-05T03:53:55.466Z INFO WatchdogMonitor 1
以上でAPEXおよびORDSにアクセスできるようになりました。ただし、ORDSはポート8080で接続を待ち受けているため、この時点でAPEXへの接続を確認するには、ポート8080への接続を許可するファイアウォールルールを作成する必要があります。
nginxによるリバース・プロキシの構成
nginxによるリバース・プロキシを構成します。nginxにてHTTPS接続を受け付け、バックエンドのORDSとは、httpで通信します。OAuth2による認証に必要なoauth-protected-resourceの内容は、nginxによってクライアントに返します。
nginxはコンテナではなくホストで実行します。作業はrootユーザーにて実施します。
sudo -s
[ynakakoshi@ordsmcp ~]$ sudo -s
[root@ordsmcp ynakakoshi]#
certbotを実行し、Let's Encryptより証明書を取得します。デフォルトでは楕円曲線暗号の鍵を生成するようです。ORDSでの利用を考えている場合は--key-type rsaをオプションとして追加し、RSAの鍵を生成します。
以下の例ではホスト名にordsmcp.f5.siを指定していますが、作業の際には割り当てているホスト名に置き換えます。
certbot certonly --standalone -d ordsmcp.f5.si
[root@ordsmcp ynakakoshi]# certbot certonly --standalone -d ordsmcp.f5.si
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Enter email address or hit Enter to skip.
(Enter 'c' to cancel): [申請者のメールアドレス]
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please read the Terms of Service at:
https://letsencrypt.org/documents/LE-SA-v1.6-August-18-2025.pdf
You must agree in order to register with the ACME server. Do you agree?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: Y
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Would you be willing, once your first certificate is successfully issued, to
share your email address with the Electronic Frontier Foundation, a founding
partner of the Let's Encrypt project and the non-profit organization that
develops Certbot? We'd like to send you email about our work encrypting the web,
EFF news, campaigns, and ways to support digital freedom.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: N
Account registered.
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-05.
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@ordsmcp ynakakoshi]#
nginx構成ファイルを置き換えます。
/etc/nginx/nginx.confを以下に置き換えます。
デバッグ用途に、ORDSへ送信されるヘッダーやリクエスト本体をログに出力する設定を含めています(有効にはしていません)。
TLSを有効にしたサーバーの設定ファイルを、/etc/nginx/conf.d/01-server.confとして作成します。ホスト名のordsmcp.f5.siの部分は、適切なホスト名に置き換えます。
ORDSおよびAPEXへのリバース・プロキシの設定、および、OAuth2の認証で使用するファイルを配置する/.well-known/を設定するファイルとして、/etc/nginx/default.d/01-apex.confを作成します。
nginxに関する設定ファイルを配置しました。nginxを起動します。
systemctl enable nginx
systemctl start nginx[root@ordsmcp ~]# systemctl enable nginx
Created symlink '/etc/systemd/system/multi-user.target.wants/nginx.service' → '/usr/lib/systemd/system/nginx.service'.
[root@ordsmcp ~]# systemctl start nginx
[root@ordsmcp ~]#
nginxではhttpsからhttpへのリバース・プロキシを構成しているため、Oracle REST Data Servicesの
security.httpsHeaderCheckに
"X-Forwarded-Proto: https"を設定します。
ユーザーoracleに切り替えコンテナapex-ordsに接続して、ordsコマンドを実行します。
su - oracle
podman exec -it apex-ords bash
ords --config /etc/ords/config config set security.httpsHeaderCheck "X-Forwarded-Proto: https"[root@ordsmcp ~]# su - oracle
Last login: Fri Dec 5 02:40:02 UTC 2025 on pts/3
[oracle@ordsmcp ~]$ podman exec -it apex-ords bash
[oracle@870492aecdbf ords]$ ords --config /etc/ords/config config set security.httpsHeaderCheck "X-Forwarded-Proto: https"
ORDS: Release 25.3 Production on Fri Dec 05 05:50:13 2025
Copyright (c) 2010, 2025, Oracle.
Configuration:
/etc/ords/config
The global setting named: security.httpsHeaderCheck was set to: X-Forwarded-Proto: https
[oracle@870492aecdbf ords]$
コンテナapex-ordsから抜け、再起動して設定を反映します。
exit
podman restart apex-ords
[oracle@870492aecdbf ords]$ exit
exit
[oracle@ordsmcp ~]$ podman restart apex-ords
WARN[0010] StopSignal SIGTERM failed to stop container apex-ords in 10 seconds, resorting to SIGKILL
apex-ords
[oracle@ordsmcp ~]$
以上でAPEXおよびORDSの環境が構築できました。
APEXワークスペースの作成
APEXのワークスペースを作成します。以下のようなリンクに、手元のブラウザからアクセスします。
https://ホスト名/ords/
Oracle APEXの実行をクリックします。
ワークスペースのサインイン画面を下にスクロールし、管理を開きます。
APEXの管理サービスにサインインします。
ユーザー名は通常はADMIN、パスワードは@apxchpwd実行時に設定した値を入力します。
初回サインイン時はワークスペースが作成されていないため、ワークスペースの作成を案内されます。
ワークスペースの作成をクリックします。
作成するワークスペース名はAPEXDEVとします。
次へ進みます。
APEXワークスペースに紐づけるワークスペース・スキーマを作成します。
既存のスキーマを再利用はいいえを選択します。スキーマ名はAutonomous Databaseのルールに合わせ、WKSP_APEXDEVとします。スキーマのパスワードとして、適切な文字列を設定します。領域割当て制限(MB)に10000を選択します。
次へ進みます。
ワークスペースの管理者ユーザーを作成します。
管理者のユーザー名はadmin、管理者のパスワードに適切な文字列を設定します。管理者パスワードは初回サインイン時に変更を求められるため、ここで設定したパスワードは初回サインイン時に変更されます。さらに必須項目である電子メールを設定します。
次へ進みます。
確認画面が表示されます。
ワークスペースの作成をクリックします。
ワークスペースが作成されます。完了をクリックします。
管理サービスでの作業は完了です。管理サービスからサインアウトします。
サインイン・ページに戻り、作成したワークスペースAPEXDEVにサインインします。
ワークスペースに先ほど作成したapexdev、ユーザーにadmin、それにパスワードを入力し、サインインをクリックします。
初回サインイン時に初期パスワードの変更を求められます。
変更するパスワードを2箇所に入力し、パスワードの変更をクリックします。
APEXのアプリケーション・ビルダーの画面が開きます。
以上で、APEXやORDSのアプリケーション開発を始められることろまで構成できました。
Microsoft Entra IDによるORDS REST API認証の実装
Microsoft Entra IDにアプリを登録します。
AzureのコンソールからMicrosoft Entra IDの画面を開きます。
サイド・メニューよりアプリの登録を開きます。
新規登録をクリックします。
Microsoft Entra IDに登録するアプリケーションの
名前は
ORDS MCPとします。
サポートされているアカウントの種類は
この組織ディレクトリのみに含まれるアカウント(既存のディレクトリのみ - シングル・テナント)を選んでいますが、これは契約に依存するかと思います。今回の作業は、Microsoft Entra IDの無料枠の範囲で実施しています。
アプリケーションのタイプとして
Webを選択し、
リダイレクトURIは以下を指定します。
https://[ホスト名]/ords/apex_authentication.callback
以上を設定し、
登録をクリックします。
アプリケーションが登録されます。
画面に表示されている
アプリケーション(クライアント)IDは、APEXの
Web資格証明の
クライアントIDの値になります。コピーして保存しておきます。
証明書またはシークレットの追加をクリックし、
シークレットを作成します。
新しいクライアント・シークレットをクリックします。
説明を入力し、追加をクリックします。
作成された
シークレットの
値(シークレットIDではない)は、APEXの
Web資格証明の
クライアント・シークレットの値になります。コピーして保存しておきます。
概要に戻り、
エンドポイントを開きます。
OpenID Connectメタデータドキュメントの値をコピーして保存します。この値が、APEXアプリケーションの認証スキームの検出URLになります。
APIの公開を開き、
Scopeの追加をクリックします。
アプリケーションIDのURIの設定を求められます。この値はJWTの
aud属性の値、つまり
audienceの値になります。
保存してから続けるをクリックします。
スコープ名はmyordsappとします。ORDSに設定する権限はこのスコープ名と一致させます。同意できるのはだれですか?は管理者とユーザー、管理者の同意の表示名はORDS REST APIの呼び出し、管理者の同意の説明はORDS REST APIの呼び出しを許可します。とします。状態は有効とします。
以上で、スコープの追加をクリックします。
スコープが追加されます。追加されたスコープ(api:で始まる値)をコピーして保存します。この値は、APEXアプリケーションの
認証スキームの
有効範囲に設定します。
Microsoft Entra IDでの作業は以上です。
VMインスタンスに接続し、ユーザーoracleに切り替えます。
sudo su - oracle
[ynakakoshi@ordsmcp ~]$ sudo su - oracle
Last login: Fri Dec 5 05:49:47 UTC 2025 on pts/0
[oracle@ordsmcp ~]$
コンテナ
apex-dbに接続します。PDBの
FREEPDB1にユーザー
SYSで接続し、スキーマへのACLの追加や、MLE/JavaScriptの実行権限の付与を実施します。
podman exec -it apex-db bash
sqlplus sys/[SYSのパスワード]@localhost/freepdb1 as sysdba
[oracle@ordsmcp ~]$ podman exec -it apex-db bash
bash-4.4$ sqlplus sys/********@localhost/freepdb1 as sysdba
SQL*Plus: Release 23.26.0.0.0 - Production on Fri Dec 5 06:39:36 2025
Version 23.26.0.0.0
Copyright (c) 1982, 2025, Oracle. All rights reserved.
Connected to:
Oracle AI Database 26ai Free Release 23.26.0.0.0 - Develop, Learn, and Run for Free
Version 23.26.0.0.0
SQL>
以下のスクリプトを実行します。ネットワークACLの追加とワークスペース・スキーマにMLE/JavaScriptの実行権限を与えています。ワークスペース・スキーマ名がWKSP_APEXDEVとは異なる場合は、WKSP_APEXDEVの部分を置き換えて実行します。
SQL> begin
dbms_network_acl_admin.append_host_ace(
host => '*',
ace => xs$ace_type(
privilege_list => xs$name_list('http','http_proxy'),
principal_name => APEX_APPLICATION.g_flow_schema_owner,
principal_type => xs_acl.ptype_db
)
);
commit;
end;
/
begin
dbms_network_acl_admin.append_host_ace(
host => '*',
ace => xs$ace_type(
privilege_list => xs$name_list('http','http_proxy'),
principal_name => 'WKSP_APEXDEV',
principal_type => xs_acl.ptype_db
)
);
commit;
end;
/
GRANT EXECUTE ON JAVASCRIPT TO WKSP_APEXDEV;
GRANT EXECUTE DYNAMIC MLE TO WKSP_APEXDEV;
exit; 2 3 4 5 6 7 8 9 10 11 12
PL/SQL procedure successfully completed.
SQL> SQL> 2 3 4 5 6 7 8 9 10 11 12
PL/SQL procedure successfully completed.
SQL> SQL>
Grant succeeded.
SQL>
Grant succeeded.
SQL> SQL>
Disconnected from Oracle AI Database 26ai Free Release 23.26.0.0.0 - Develop, Learn, and Run for Free
Version 23.26.0.0.0
bash-4.4$
以下のAPEXアプリケーションをインポートします。検証用のAPEXアプリケーションやORDSのRESTサービスを作成します。
https://github.com/ujnak/apexapps/blob/master/exports/ords-jwt-test-mcp.zip
アプリケーション・ビルダーよりインポートを実行します。
インポートするファイルとしてords-jwt-test-mcp.zipを選択します。
次へ進みます。
アプリケーションのインストールを実行します。
テスト用のAPEXアプリケーションが参照しているWeb資格証明Microsoft Entra ID JWT Testが作成されます。すでに存在しますがいいえであれば、クライアントIDまたはユーザー名にEntra IDで作成したアプリORDS MCPのアプリケーション(クライアント)IDを入力します。また、クライアント・シークレットにシークレットの値を入力します。
これらの値は後からでも、ワークスペース・ユーテリティのWeb資格証明から変更できます。
次へ進みます。
サポートするオブジェクトのインストールを実行します。

APEXアプリケーションがインストールされます。
アプリケーションの編集をクリックし、設定を更新します。
アプリケーション設定の置換を開き、G_REST_URLのホスト部分を、このAPEXインスタンスを指すホスト名に置き換えます。
共有コンポーネントの
認証スキームを開きます。
認証スキームの
Microsoft Entra IDを開きます。
検出URLにMicrosoft Entra IDのエンドポイントで確認した
OpenID Connectメタデータドキュメントの値を設定します。このURLはテナントIDを含みます。
有効範囲に
api:で始まるスコープを追加します。
以上を変更し、
変更の適用をクリックします。
この状態でアプリケーションを実行してみます。
Microsoft Entra IDによるサインインに成功すると、APEXアプリケーションが開きます。APEXアプリケーションの認証には成功しますが、REST APIについてはまだ認証の設定ができていません。
続いて、Entra IDのOpenID ConnectメタデータドキュメントのURLをブラウザで開きます。URLは以下の形式です。
https://login.microsoftonline.com/テナントID/v2.0/.well-known/openid-configuration
メタデータドキュメントに含まれるjwks_uriの値をコピーします。この値は引数p_jwk_urlの値になります。
ORDS_SECURITY.CREATE_JWT_PROFILEの実行に必要な値は、すべて確認できました。
VMインスタンスに接続し、rootユーザーに切り替えます。
sudo -s
[ynakakoshi@ordsmcp ~]$ sudo -s
[root@ordsmcp ynakakoshi]#
デフォルトのウォレットではLet's Encryptでの証明書の検証ができないようです。そのため、Oracle Walletを作成します。
CA証明書chain.pemとサーバー証明書cert.pemを、Oracle Databaseが動いているコンテナから参照できるディレクトリにコピーし、所有者をユーザーoracleに変更します。
cp /etc/letsencrypt/live/ホスト名/cert.pem /home/oracle/apex/
cp /etc/letsencrypt/live/ホスト名/chain.pem /home/oracle/apex/
chown oracle:oinstall /home/oracle/apex/*.pem[root@ordsmcp ynakakoshi]# cp /etc/letsencrypt/live/ordsmcp.f5.si/cert.pem /home/oracle/apex/
[root@ordsmcp ynakakoshi]# cp /etc/letsencrypt/live/ordsmcp.f5.si/chain.pem /home/oracle/apex/
[root@ordsmcp ynakakoshi]# chown oracle:oinstall /home/oracle/apex/*.pem
[root@ordsmcp ynakakoshi]#
ユーザーoracleに切り替え、コンテナapex-dbに接続します。
su - oracle
podman exec -it apex-db bash
[root@ordsmcp ynakakoshi]# su - oracle
Last login: Fri Dec 5 08:53:53 UTC 2025 on pts/0
[oracle@ordsmcp ~]$ podman exec -it apex-db bash
bash-4.4$
Oracle Walletを/home/oracle/walletに作成し、信頼できる証明書としてchain.pemおよびcert.pemを追加します。
orapki wallet create -wallet /home/oracle/wallet -pwd [パスワード] -auto_login
orapki wallet add -wallet /home/oracle/wallet -cert apex/chain.pem -trusted_cert -pwd [パスワード]
orapki wallet add -wallet /home/oracle/wallet -cert apex/cert.pem -trusted_cert -pwd [パスワード]
bash-4.4$ orapki wallet create -wallet /home/oracle/wallet -pwd Oracle1234 -auto_login
Oracle PKI Tool Release 23.0.0.0.0 - Production
Version 23.0.0.0.0
Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved.
Operation is successfully completed.
bash-4.4$ orapki wallet add -wallet /home/oracle/wallet -cert apex/chain.pem -trusted_cert -pwd Oracle1234
Oracle PKI Tool Release 23.0.0.0.0 - Production
Version 23.0.0.0.0
Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved.
Operation is successfully completed.
bash-4.4$ orapki wallet add -wallet /home/oracle/wallet -cert apex/cert.pem -trusted_cert -pwd Oracle1234
Oracle PKI Tool Release 23.0.0.0.0 - Production
Version 23.0.0.0.0
Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved.
Operation is successfully completed.
bash-4.4$
sqlplusでスキーマWKSP_APEXDEVに接続し、JWTプロファイルを作成します。
sqlplus wksp_apexdev@localhost/freepdb1
bash-4.4$ sqlplus wksp_apexdev@localhost/freepdb1
SQL*Plus: Release 23.26.0.0.0 - Production on Fri Dec 5 09:06:09 2025
Version 23.26.0.0.0
Copyright (c) 1982, 2025, Oracle. All rights reserved.
Enter password: *********
Connected to:
Oracle AI Database 26ai Free Release 23.26.0.0.0 - Develop, Learn, and Run for Free
Version 23.26.0.0.0
SQL>
ORDS_SECURITY.CREATE_JWT_PROFILEを実行します。
begin
ords_security.create_jwt_profile(
p_issuer => 'issの値'
,p_audience => 'audの値'
,p_jwk_url => 'jwks_uriの値'
);
end;
/
SQL> begin
ords_security.create_jwt_profile(
p_issuer => 'https://sts.windows.net/********-****-****-****-***********/'
,p_audience => 'api://********-****-****-****-***********'
,p_jwk_url => 'https://login.microsoftonline.com/********-****-****-****-***********/discovery/v2.0/keys'
);
end;
/ 2 3 4 5 6 7 8
PL/SQL procedure successfully completed.
SQL>
以上でORDSのRESTサービスのJWTに保護が設定できました。
APEXのアプリケーション・ビルダーに戻り、ページ・デザイナでホーム・ページを開きます。
RESTサービスを呼び出す動的コンテンツのリージョンREST API Responseを選択します。ソースのCLOBを返すPL/SQLファンクション本体を若干修正します。
APEX_WEB_SERVICE.MAKE_REST_REQUESTの引数
p_wallet_pathに、
file:///home/oracle/walletを指定します。

以上の変更を行い、APEXアプリケーションを実行します。
以下のようにUser InfoとREST API Responseの双方のリージョンに、正常な処理結果が表示されます。
これで、ORDSのRESTサービスが、Microsoft Entra IDが発行したJWTで認証されるようになりました。
リモートMCPサーバーの実装
以下のAPEXアプリケーションをワークスペースにインポートします。
https://github.com/ujnak/apexapps/blob/master/exports/chat-with-generative-ai-hc-242.zip
アプリケーションとともにサポート・オブジェクトとして、表
OPENAI_TOOLSとファンクション
get_schemaと
run_sqlが作成され、属性などの定義情報が表に挿入されます。
次にリモートMCPサーバーの実装をサポート・スクリプトとして含む、以下のAPEXアプリケーションをインポートします。
https://github.com/ujnak/apexapps/blob/master/exports/mcp_handler.zip
APEXアプリケーションがインストールされると、パッケージ
MCP_HTTP_SERVER_PKGと
MCP_SAMPLEが作成されます。またORDSのRESTサービスとして
sampleseverが作成されます。
インストールされたAPEXアプリケーションを実行します。
作成をクリックし、ORDSのRESTサービスとMCPサーバーの実装を紐付けます。
Ords Urlは
/ords/apexdev/sampleserverを指定します。
Apex App IDはデフォルトで、このアプリケーション自身のアプリケーションIDになります。変更は不要です。
Apex Page IDもこのAPEXアプリケーションのホーム・ページのIDになります。変更は不要です。これらはAPEXセッションを開始する際に使用します。
Package Nameに
MCP_SAMPLEを指定します。このパッケージにMCPサーバーに必要なinitialize、tools/list、tools/callなどに対応した処理が、プロシージャとして実装されています。
Log Levelは
4、
Tool Setに
Countriesを選択します。Tool SetのCountriesには
get_schemaおよび
run_sqlがツールとして含まれています。
以上で
作成をクリックします。
/ords/apexdev/sampleserverとパッケージ
MCP_SAMPLEの紐付けができました。
今のところ、ワークスペース・スキーマに何もデータが含まれていません。
SQLワークショップのユーティリティのサンプル・データセットを開き、国のデータをインストールします。
次へ進みます。
データセットのインストールを実行します。
データセットがインストールされます。
終了をクリックします。
サンプルデータセットの国のインストールが完了しました。
RESTサービス
sampleserverの保護を解除し、MCP Inspectorから呼び出して動作確認をします。
SQLワークショップのRESTfulサービスを開き、権限oracle.example.mcpを選択します。
保護されたモジュールからsampleserverを除外し、変更の適用をクリックします。
手元のPCからMCP Inspectorを起動します。
npx @modelcontextprotocol/inspector
Transport TypeにStreamable HTTPを選択し、URLに以下を指定します。VMインスタンスのホストを指す、以下のURLを設定します。
https://ホスト名/ords/apexdev/sampleserver/mcp
Authenticationに関する設定はせず、Connectをクリックします。
MCPサーバーへ接続されます。Toolsタブを開き、List Toolsを実行します。
Toolsの
get_schemaを選択し、
Run Toolをクリックします。
スキーマWKSP_APEXDEVにある表および列の情報が返されます。
Toolsのrun_sqlを選択し、sqlに以下を記述します。
select * from eba_countries
Run Toolをクリックすると、表EBA_COUNTRIESの内容が返されます。
以上でリモートMCPサーバーの動作が確認できました。
リモートMCPサーバーのJWTプロファイルによる保護
リモートMCPサーバー(正確にはRESTモジュールsampleserver)を、Microsoft Entra IDが発行したJWTで保護します。
MCP InspectorのRedirect URLをEntra IDのアプリに追加します。
アプリケーションORDS MCPの概要から、リダイレクトURIのリンクを開きます。
プラットフォームの追加をクリックします。(認証の画面がAuthentication (Preview)に変わっている場合は、リダイレクトURIの追加に変わっているようです。)
シングルページアプリケーションを選択します。
リダイレクトURIとしてMCP InspectorのRedirect URLを設定します。本記事の環境では以下でした。
http://localhost:6274/oauth/callback
以上で
構成をクリックします。
以上でMCP InspectorがアプリケーションORDS MCPとして認証できるようになりました。
OAuth2による認証の開始時に要求されたリソース・メタデータをnginxが返すように、/.well-known/以下にファイルを作成します。
VMインスタンスに接続し、rootユーザーに切り替えます。
sudo -s
[ynakakoshi@ordsmcp ~]$ sudo -s
[root@ordsmcp ynakakoshi]#
nginxのドキュメント・ルートに移動します。
cd /usr/share/nginx/html
認証フローで参照されるファイルを配置するディレクトリを作成します。
リモートMCPサーバーのアクセスパスが/ords/apexdev/sampleserver/mcpなので、oauth-protected-resourceとして記述する内容は.well-known以下のords/apexdev/sampleserver/mcpに記述します。
mkdir -p .well-known/ords/apexdev/sampleserver[root@ordsmcp html]# mkdir -p .well-known/ords/apexdev/sampleserver
[root@ordsmcp html]#
ファイル
.well-known/ords/apexdev/sampleserver/mcpを作成し、以下を記述します。
resourceは
ORDS_SECURITY.CREATE_JWT_PROFILEの引数
p_audienceに与えた値、
issuerは
p_issuerに与えた値です。
authorization_serversには、
OpenID Connectメタデータドキュメントの.
well-knownが始まる前までのURLを設定します。
authorization_serversの設定で、JSON配列を{}で囲んでJSONオブジェクトにしています。構文的に間違っているように思いますが、こうしないとMCP Inspectorがauthorization_serversを認識しません。
{
"resource": "api://********-****-****-****-************",
"issuer": "https://sts.windows.net/********-****-****-****-************/",
"authorization_servers": {
["https://login.microsoftonline.com/********-****-****-****-************/oauth2/v2.0/"]
}
}
[root@ordsmcp html]# cat > .well-known/ords/apexdev/sampleserver/mcp
{
"resource": "api://********-****-****-****-************",
"issuer": "https://sts.windows.net/********-****-****-****-************/",
"authorization_servers": {
["https://login.microsoftonline.com/********-****-****-****-************/oauth2/v2.0/"]
}
}
[root@ordsmcp html]#
OpenID Connectメタデータドキュメントをダウンロードし、.well-known以下に配置します。
curl -OL https://login.microsoftonline.com/*******-****-****-****-***********/v2.0/.well-known/openid-configuration
mv openid-configuration .well-known/
[root@ordsmcp html]# curl -OL https://login.microsoftonline.com/********-****-****-****-************/v2.0/.well-known/openid-configuration
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 1965 100 1965 0 0 3393 0 --:--:-- --:--:-- --:--:-- 3399
[root@ordsmcp html]# mv openid-configuration .well-known/
[root@ordsmcp html]#
OpenID Connectメタデータドキュメントは認可サーバー(Authorization Server)
から取得するはずだと思うのですが、なぜかMCPサーバーを参照します。MCP Inspectorのv0.17.5よりoauth-authorization-serverが無ければopenid-configurationを参照するように変わっています。
以上でoauth-protected-resourceとoauth-authorization-serverとして返すファイルを、MCPサーバーに配置できました。
APEXの画面に戻り、RESTfulサービスを開きます。
権限myordsappを選択し、保護されたモジュールにsampleserverを含めます。
変更の適用をクリックし、リモートMCPサーバーにJWTプロファイル(OAuth2)での保護を適用します。
以上でリモートMCPサーバー(ORDSのRESTモジュールsampleserver)の保護も完了です。
MCP Inspectorを起動します。
npx @modelcontextprotocol/inspector
OAuth2.0 Flowの
Client IDにEntra IDのアプリ
ORDS MCPの
アプリケーション(クライアント)IDを設定します。
Scopeにapi:で始まるスコープ
api://********-****-****-****-************/myordsappを設定します。Client Secretは設定不要です。
Connectをクリックします。
Microsoft Entra IDによるサインインのプロセスが開始します。
Authenticatorを構成しているため、通知の送信を求められます。
Authenticatorの操作を求められます。
サインインの状態を維持するかどうか確認されます。
ユーザー認証に成功し、MCPサーバーのツールを呼び出すことができます。
Authタブを開くと、OAuthの認証フローの進捗を確認できます。
どうにも納得がいかない設定はいくつかありますが、とりあえずMicrosoft Entra IDのOAuth2で、ORDSのRESTサービスで作成したリモートMCPサーバーを保護できました。
今回の記事は以上になります。
完