2026年4月20日月曜日

United Codes社が提供するパッケージUC_AIのサンプルアプリを動かしてみる

United Codes社は、Oracle DatabaseおよびOracle APEXを中心としたアプリケーション開発・ツール提供を行う、ベルギーを拠点としたエンジニアリング企業です。日本では似たようなポジションの企業はあまりないように感じますが、海外ではUnited Codes社の他に、ドイツのHyland(旧MT GmbH)社、 北米が拠点のTALAN(旧Insum)およびViscocity North Americaなどがあります。

そのUnited Codes社より、OpenAIやAnthropicのAPIを呼び出すPL/SQLパッケージとしてUC_AIが公開されています。ライセンスはLGPL-3.0です。

製品の説明:https://www.united-codes.com/products/uc-ai/docs/

United Codes社ではOracle DatabaseやAPEXを扱う開発者向けに「AI WORKSHOP FOR DATABASE & APEX DEVELOPERS」という、2日間のオンライン・ワークショップを開催しています。言語は英語で有償なので日本からの参加は難しいかもしれませんが、パッケージUC_AIの利用を検討する場合はワークショップを受講するのが近道でしょう。

ワークショップの受講が不要になるような記事は書けませんが、パッケージUC_AIに含まれるサンプルアプリPractical AI Made Easyが、使いたいモデルやプロバイダ(特にOllamaやLM StudioといったローカルLLM)によっては動かないので、サンプルアプリの動かし方を記事にします。

以下より、UC_AIに含まれるサンプルアプリPractical AI Made Easyを動かす手順を紹介します。APEXの実行環境には、同じくUnited Codes社より公開されているUC Local APEX Devを使用します。

APEXのワークスペースとしてAPEXDEV、スキーマとしてAPEXDEVが作成済みとします。また、SQLclの接続としてスキーマAPEXDEVに接続するlocal-26ai-apexdevが作成済みとします。

最初にUC_AIをスキーマAPEXDEVにインストールします。Loggerも一緒にインストールすることにします。

リポジトリUC_AIをクローンし、移動します。安定版のmainブランチを取得します。

git clone -b main https://github.com/United-Codes/uc_ai.git
cd uc_ai

% git clone -b main https://github.com/United-Codes/uc_ai.git

Cloning into 'uc_ai'...

remote: Enumerating objects: 2923, done.

remote: Counting objects: 100% (641/641), done.

remote: Compressing objects: 100% (437/437), done.

remote: Total 2923 (delta 329), reused 339 (delta 185), pack-reused 2282 (from 1)

Receiving objects: 100% (2923/2923), 6.37 MiB | 6.98 MiB/s, done.

Resolving deltas: 100% (1922/1922), done.

% cd uc_ai 

uc_ai % 


Loggerを個別のスキーマにインストールする場合、対象のスキーマにはCREATE ANY CONTEXT権限が必要です。データベースにSYSで接続し、権限を与えます。

sql -name local-26ai-sys
grant create any context to apexdev;

uc_ai % sql -name local-26ai-sys


SQLcl: 月 4月 20 14:21:44 2026のリリース25.4 Production


Copyright (c) 1982, 2026, Oracle.  All rights reserved.


接続先:

Oracle AI Database 26ai Free Release 23.26.1.0.0 - Develop, Learn, and Run for Free

Version 23.26.1.0.0


SQL> grant create any context to apexdev;


Grantが正常に実行されました。


SQL> exit

Oracle AI Database 26ai Free Release 23.26.1.0.0 - Develop, Learn, and Run for Free

Version 23.26.1.0.0から切断されました

uc_ai % 


続いてスキーマAPEXDEVに接続し、パッケージUC_AIと関連オブジェクトをインストールします。

sql -name local-26ai-apexdev
@install_with_logger

uc_ai % sql -name local-26ai-apexdev


SQLcl: 月 4月 20 16:48:18 2026のリリース25.4 Production


Copyright (c) 1982, 2026, Oracle.  All rights reserved.


接続先:

Oracle AI Database 26ai Free Release 23.26.1.0.0 - Develop, Learn, and Run for Free

Version 23.26.1.0.0


SQL> @install_with_logger

Installing UC AI with logger

_____________________________________________________________________________

User has all required privileges, installation will continue.

_____________________________________________________________________________



PL/SQLプロシージャが正常に完了しました。


tables/logger_logs.sql


PL/SQLプロシージャが正常に完了しました。



PL/SQLプロシージャが正常に完了しました。


tables/logger_prefs.sql


PL/SQLプロシージャが正常に完了しました。



Trigger BIU_LOGGER_PREFSがコンパイルされました


[中略]


Package Body UC_AI_RESPONSES_APIがコンパイルされました


- Installing core UC AI package body...


Package Body UC_AIがコンパイルされました


Running post-installation scripts...

Logger package detected. Setting USE_LOGGER flag to TRUE.

Successfully compiled uc_ai_logger package with USE_LOGGER flag.



PL/SQLプロシージャが正常に完了しました。


===================================================

UC AI installation complete!

Refer to the documentation for usage instructions: https://www.united-codes.com/products/uc-ai/docs/

===================================================

Installation Complete!

SQL> exit

Oracle AI Database 26ai Free Release 23.26.1.0.0 - Develop, Learn, and Run for Free

Version 23.26.1.0.0から切断されました

uc_ai % 


サンプルとなるAPEXアプリPractical AI Made Easyをインストールします。

アプリケーション・ビルダーを開き、インポートを実行します。


インポートするファイルとして、uc_ai/examples/sample-apps/practical-ai-made-easy以下のf135.sqlを選択します。同じディレクトリにpame_pkg.pks、pame_pkg.pkbやtables.sqlといったスクリプトがありますが、これらはAPEXアプリにサポートするオブジェクトとして含まれているため、個別に実行する必要はありません。

f135.sqlを選択し、次へ進みます。


アプリケーションのインストールを実行します。


サポートするオブジェクトのインストールを実行します。


APEXアプリケーションと、その実行に必要なデータベース・オブジェクトがインストールされました。

アプリケーションを実行します。


APEXのワークスペース・ユーザーでサインインします。


パッケージUC_AIのAPIの呼び出し例として、Generate TextStructured OutputAnalyze filesReasoningToolsの5種類のサンプルが含まれています。それらの呼び出しに使用するモデルは、画面右上のボタンをクリックして選択します。


LLMのプロバイダとしてOpenAIAnthropicGoogleOllamaOCIが選択できます。プロバイダごとにAPIの呼び出し形式は異なりますが、UC_AIのAPIでは、これらの違いを吸収して、同じAPIで異なるプロバイダを呼び出せるようになっています。


しかしサンプルアプリでは、選択できるモデルに制限があります。OpenAIを例にとると、gpt-4o、gpt-5、o4-miniです。


今回はローカルLLMを呼び出せるようにします。

OllamaでGoogleのGemma4、LM Studioでgpt-oss-120bを実行します。Ollamaではモデル名はgemma4:31b、LM Studioではmlx-community/gpt-oss-120bです。私のMacはメモリに余裕があるため大きいモデルを使用していますが、ホストしているPCに合わせてモデルを選んでください。

選択可能なモデルを追加します。これは共有コンポーネントLOVとして設定されています。

共有コンポーネントLOVから、MODELSを編集します。


SQL問合せを更新します。

プロバイダがollamaのモデルとしてgemma4:31bを追加します。LM StudioのモデルはOpenAI互換のChat Completions APIから呼び出すため、プロバイダopenaiのモデルとしてmlx-community/gpt-oss-120bを追加します。
select model as r, model as d, provider
from (
    select 'gpt-4o' as model, 'openai' as provider
    union all
    select 'gpt-5' as model, 'openai' as provider
    union all
    select 'o4-mini' as model, 'openai' as provider
    --
    union all
    select 'google/gemmna-4-31b' as model, 'openai' as provider
    union all
    select 'mlx-community/gpt-oss-120b' as model, 'openai' as provider

    union all

    select 'claude-3-5-haiku-latest' as model, 'anthropic' as provider
    union all
    select 'claude-sonnet-4-0' as model, 'anthropic' as provider
    union all
    select 'claude-opus-4-1' as model, 'anthropic' as provider

    union all

    select 'gemini-2.5-pro' as model, 'google' as provider
    union all
    select 'gemini-2.5-flash' as model, 'google' as provider
    union all
    select 'gemini-2.5-flash-lite-preview-06-17' as model, 'google' as provider

    union all

    select 'qwen3:1.7b' as model, 'ollama' as provider
    union all
    select 'gemma3:4b' as model, 'ollama' as provider
    union all
    select 'gpt-oss:20b' as model, 'ollama' as provider
    -- 
    union all
    select 'gemma4:31b' as model, 'ollama' as provider

    union all

    select 'cohere.command-a-03-2025' as model, 'oci' as provider
    union all
    select 'meta.llama-3.3-70b-instruct' as model, 'oci' as provider
)
where provider = :P0_PROVIDER

以上で、選択できるモデルが追加できました。

プロバイダとしてOllama、モデルとしてgemma4:31bを選択します。


モデルを選択した上でSystem PromptUser Promptを入力し、Generateボタンをクリックすると以下のエラーが発生します。

「Ajax call returned server error ORA-29273: HTTP request failed for Execute Server-Side Code.」


OllamaやLM StudioはローカルLLMなのでAPIキーは不要ですが、呼び出し先となるエンドポイントURLはそれぞれ設定が必要です。デフォルトはlocalhostですが、APEX(を実行しているデータベース)がコンテナで実行されているため、呼び出し先はコンテナ外となるhost.docker.internal(またはhost.containers.internal)になります。また、OpenAIやAnthropicなどの、エンドポイントが固定で呼び出し先のURLを変更する必要がない場合でも、APIキーは設定する必要があります。

APIキーの設定方法はいくつかありますが、今回はAPEXのWeb資格証明を使用します。

ワークスペース・ユーティリティWeb資格証明を開きます。


OpenAIのAPIキーを新規に登録します。作成をクリックします。


Web資格証明の名前OpenAI API Key静的IDOPENAI_API_KEYとします。静的IDは、UC_AIへWeb資格証明を設定する際に使用します。

認証タイプHTTPヘッダーを選択し、資格証明名にHTTPヘッダー名であるAuthorization資格証明シークレットとしてBearerで始めて、空白で区切り、OpenAIのAPIキーを繋げた文字列を設定します。

APIキーの送信先がOpenAIに限定されるように、URLに対して有効https://api.openai.com/を設定します。

以上でWeb資格証明を作成します。


Generate Textのページに戻り、ボタンGenerateをクリックしたときに実行されるコードを更新します。

プロバイダがollamaのときは、ベースURLをhost.docker.internal:11434/apiとします。プロバイダがopenaiでモデルがmlx-community/gpt-oss-120bのときは、LM Studioの呼び出しなので、ベースURLをhttp://host.docker.internal:1234/v1にします。それ以外のopenaiのときは、Web資格証明としてOPENAI_API_KEYを設定します。

UC_AIでプロバイダがOpenAIの場合、デフォルトでResponses APIが使用されるようです。LM StudioについてはChat Completions APIを使用させるため、uc_ai_openai.g_use_responses_apifalseを設定します。
declare
  l_result json_object_t;
begin
  pame_pkg.reset_global_variables;
  --
  if :P0_PROVIDER = 'ollama' then
    uc_ai.g_base_url := 'host.docker.internal:11434/api';
  elsif :P0_PROVIDER = 'openai' and :P0_MODEL in ('google/gemma-4-31b','mlx-community/gpt-oss-120b') then
    uc_ai.g_base_url := 'http://host.docker.internal:1234/v1';
    uc_ai_openai.g_use_responses_api := false;
  elsif :P0_PROVIDER = 'openai' then
    uc_ai_openai.g_apex_web_credential := 'OPENAI_API_KEY';
  end if;

  l_result := uc_ai.generate_text(
    p_user_prompt => :P1_USER_PROMPT,
    p_system_prompt => :P1_SYSTEM_PROMPT,
    p_provider => :P0_PROVIDER,
    p_model => :P0_MODEL
  );

  :P1_OUTPUT := l_result.get_clob('final_message');
  :P1_FULL_RESPONSE := l_result.to_clob;
end;
ファンクションuc_ai.generate_textがLLMを呼び出すファンクションです。


プロバイダをOllama、モデルとしてgemma4:31bを選択して、Generateを実行します。Outputが返されることが確認できます。


LM Studioで動作しているmlx-community/gpt-oss-120bや、OpenAIが提供しているモデルgpt-4oやgpt-5をモデルとして選択しても、Outputが得られます。

Structured Outputについても、ボタンGenerateで呼ばれるコードに以下を組み込み、環境に合わせたモデルの呼び出しが行われるようにします。Structured Outputに対応するように、ファンクションuc_ai.generate_textの呼び出し時に引数p_response_json_schemaが追加されています。
  --
  if :P0_PROVIDER = 'ollama' then
    uc_ai.g_base_url := 'host.docker.internal:11434/api';
  elsif :P0_PROVIDER = 'openai' and :P0_MODEL in ('google/gemma-4-31b','mlx-community/gpt-oss-120b') then
    uc_ai.g_base_url := 'http://host.docker.internal:1234/v1';
    uc_ai_openai.g_use_responses_api := false;
  elsif :P0_PROVIDER = 'openai' then
    uc_ai_openai.g_apex_web_credential := 'OPENAI_API_KEY';
  end if;

User Promptに「日本の首都はどこですか?responseには首都の名前を返してください。」と入力し、Structured OutputのJSONスキーマとしてConfidenceを選択します。

モデルとしてgpt-oss-120bを選択しました。Outputは以下です。

{ "response": "東京", "confidence": 0.99 }

モデルによっては構造化出力を返さないものもあります。


Analyze filesについても今までと同様に、ボタンGenerateで呼び出されるコードを変更します。

Analyze filesではファイルを処理できますが、表PAME_FILESに登録済みのファイルに限定されています。


自分で選んだファイルを処理するために、表PAME_FILESにファイルを登録するアプリを作成しました。

https://github.com/ujnak/apexapps/blob/master/exports/manage_pame_files.sql

このAPEXアプリをダウンロードし、ワークスペースにインポートします。

インポートしたアプリケーションを実行すると、以下のような画面が開きます。表PAME_FILESを対象に、ローカルPCにあるファイルをアップロードするだけの簡単なアプリケーションです。


使用したいファイルを登録して、UC_AIのサンプルアプリに戻ります。

新たに登録したファイルを選択して、ボタンGenerateをクリックします。画像やPDFといったファイルを処理したOutputを確認できます。画像を処理したり、さらに構造化出力を返すには、それらに対応したモデルを選択する必要があります。


Reasoningについても同様に、ボタンGenerateで呼び出されるコードを変更します。

Enable Reasoningオンにして、ボタンGenerateをクリックします。Reasoningが行われるかどうかも、選択したモデルに依存します。


Toolsについても同様に、ボタンGenerateで呼び出されるコードを変更します。

呼び出されるツールを登録するのは大変なので、サンプルに含まれているツールPAME_GET_USER_INFOを呼び出してみます。

System Promptは「あなたは保険の外交員です。」とします。User Promptは「alice.smith@example.comの情報を教えて。」とします。

以上でボタンGenerateをクリックすると、表PAME_USERSから取得した情報がOutputに表示されます。


UC_AIに含まれるサンプルアプリPractical AI Made Easyの紹介は以上です。

サンプルアプリPractical AI Made Easyを削除しても、関連オブジェクトはそのまま残ります。完全に削除するには以下のスクリプトを実行します。
drop table pame_settlement_demo;
drop table pame_files;
drop table pame_users;
delete from uc_ai_tools where code in ('PAME_CREATE_SETTLEMENT', 'PAME_GET_USER_INFO');
Oracle APEXのアプリケーション開発の参考になれば幸いです。

2026年4月17日金曜日

OpenAI CodexからリモートMCPサーバー経由でOracle Databaseに問い合わせる

以下の手順で作成したリモートMCPサーバーsampleserverにOpenAI Codexから接続し、プラグインを作成してみます。Microsoft Entra IDによるユーザー認証を行なうように構成します。
最初にCodexにMCPサーバーを作成します。~/.codex/config.tomlを直接編集します。アプリから設定する場合は、設定MCPサーバーから作成します。


config.tomlに以下の記述を追加します。MCPサーバーはconnector_for_oracle_datababaseと命名します。
[mcp_servers.connector_for_oracle_database]
url = "https://OpenRestyが動作しているホスト名/ords/apexdev/sampleserver/mcp"
bearer_token_env_var = "ORACLE_MCP_TOKEN"
CodexではMCPサーバーを以下のように設定すると、OAuthによるユーザー認証ができるようです。(mcp_oauth_callback_urlをEntra IDのアプリにリダイレクトURIとして設定する必要あり)
[mcp_servers.connector_for_oracle_database]
url = "https://OpenRestyが動作しているホスト名/ords/apexdev/sampleserver/mcp"

# --- OAuth callback ---
mcp_oauth_callback_port = 8787
mcp_oauth_callback_url = "http://localhost:8787/callback"
MCPサーバーconnector_for_oracle_databaseをユーザー認証するため、codexコマンドを実行します。

codex mcp login connector_for_oracle_database

~ % codex mcp login connector_for_oracle_database

Error: Registration failed: Dynamic registration failed: Registration failed: Dynamic client registration not supported

~ % 


config.toml内でOAuthのクライアントIDを設定する方法がドキュメントから見つからないため、エラー・メッセージにあるようにDynamic Client Registrationが必須と思われます。Microsoft Entra IDはDCRに対応していないため、CodexとEntra IDの組み合わせでOAuth2によるユーザー認証はできないようです。

諦めてbearer_token_env_varを使うように設定します。環境変数ORACLE_MCP_TOKENにEntra IDが発行したアクセス・トークンを設定します。

az loginコマンドを実行し、Entra IDにサインインします。

az login --tenant "テナントID" --scope "アプリORDS MCPで公開しているスコープ"

ブラウザが立ち上がり、Entra IDに登録されているユーザーによるユーザー認証が求められます。


ブラウザでのユーザー認証が完了すると、Select a subscription and tenant (Type a number or Enter for no changes):と聞かれます。そのままEnterを入力し、az loginコマンドを完了します。

~ % az login --tenant "********-****-****-****-************" --scope "api://********-****-****-****-************/mcp:connect"

A web browser has been opened at https://login.microsoftonline.com/********-****-****-****-************/oauth2/v2.0/authorize. Please continue the login in the web browser. If no web browser is available or if the web browser fails to open, use device code flow with `az login --use-device-code`.


Retrieving subscriptions for the selection...


[Tenant and subscription selection]


No     Subscription name     Subscription ID                       Tenant

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

[1] *  Azure subscription 1  ********-****-****-****-************  ********-****-****-****-************


The default is marked with an *; the default tenant is '********-****-****-****-************' and subscription is 'Azure subscription 1' (********-****-****-****-************).


Select a subscription and tenant (Type a number or Enter for no changes): 


Tenant: ********-****-****-****-************

Subscription: Azure subscription 1 (********-****-****-****-************)


[Announcements]

With the new Azure CLI login experience, you can select the subscription you want to use more easily. Learn more about it and its configuration at https://go.microsoft.com/fwlink/?linkid=2271236


If you encounter any problem, please open an issue at https://aka.ms/azclibug


[Warning] The login output has been updated. Please be aware that it no longer displays the full list of available subscriptions by default.


ynakakoshi@Ns-Macbook ~ % 


Entra IDへのサインインが完了したので、アクセス・トークンを取得し環境変数ORACLE_MCP_TOKENに設定します。

export ORACLE_MCP_TOKEN=$(az account get-access-token \
--scope "
アプリORDS MCPで公開しているスコープ" \
--query accessToken -o tsv)

~ % export ORACLE_MCP_TOKEN=$(az account get-access-token \

--scope "api://*********-****-****-****-********/mcp:connect" \

--query accessToken -o tsv)

~ % echo $ORACLE_MCP_TOKEN

eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6IlUxc1g4W

[中略]

7jbOqbhJSQ1Dk-CoHPF_yJPJGO2OPJEUjhIBehPC-abRHHVPXeiRC

ZuDTRAvZzVrSAW97jSQ0PFmMQ

~ % 


以上でアクセス・トークンが環境変数ORACLE_MCP_TOKENに設定されました。アクセス・トークンの有効期間は通常1時間程度なので、az account get-access-tokenコマンドは定期的に発行する必要があります。

コマンドラインから(デスクトップ・アプリの)Codexを起動します。以下はmacOSでの作業です。

open -a Codex

Codexが起動します。

作成されたMCPサーバーを確認します。

サイド・メニューよりプラグインを選択し、管理するを開きます。


MCPを選択するとConnector For Oracle Databaseが作成されていることが確認できます。


新しいプロジェクトを追加して、作業を進めます。


販売分析というプロジェクトを作成し、作業を進めます。


Connector for Oracle Databaseに繋げられるかを確認します。

 「Connector for Oracle Databaseに接続して、接続ユーザーを確認して。」

ツールget_current_userが呼び出され、アクセス・トークンのsubの値が表示されます。MCPサーバーに接続できていることが確認できます。


Connector For Oracle Databaseを使用したプラグインを作成します。

サイド・メニューよりプラグインを開き、作成からプラグインを作成を実行します。


Plugin Createrにたいして、以下の文言を与えて実行します。

「SHスキーマに保存されている販売履歴より、典型的な分析ができるプラグインを作成してください。」


CodexがMCPサーバーのツールを呼び出し、プラグインを作成していきます。


たまにツール実行の許可やファイル操作の許可を求められます。


プラグインの作成が完了したら、プラグインをインストールします。

「作成されたプラグインをインストールして」


サイド・メニューよりプラグインを開きます。


Local Analytics Plugins(またはLocal Plugins)を選択し、プラグインSH Sales Analyticsをインストールします。


プラグインSH Sales Analystをインストールします。


プラグインがインストールされます。

プロジェクトのチャット画面に移り、インストールされたプラグインを呼び出します。


プラグインを使って、分析してもらいます。

「SHスキーマの月次売上推移と成長率を分析して」


色々とツールを呼び出して、最終的な回答まで進みます。


Microsoft Entra IDとの連携は残念な感じですが、プラグインやスキル次第で、Codexをコーディング以外の作業で使用することもできそうです。