はじめに
以前の記事 で、Oracle Autonomous AI Database (ADB) の MCP サーバー機能の有効化や、クライアント(AIエージェント)からの接続設定、および基本的なツール登録手順について解説しました。
本記事は、AIエージェントの推論能力を実際に検証するために構築した 「テスト用データベース環境の準備手順」 に関する覚書です。
具体的には、あえてテーブル名や列名を推測不可能(TABLE_001, C_01 など)にし、Oracle Database 23c の新機能である Annotations(アノテーション) で論理名や説明を付与した環境を構築します。
これにより、AIが自律的にメタデータを取得して正しいSQLを生成できるかをテストすることが目的です。
1. 検証用スキーマの作成と権限付与
まずは、検証用の専用ユーザー(スキーマ)を作成し、MCPサーバーや Select AI を利用するための権限を付与します。
ADMIN ユーザーでログインします。
-- ユーザーの作成
CREATE USER MCP_TEST_USER IDENTIFIED BY "Welcome_12345#_Test";
-- 基本的なロールの付与
GRANT CONNECT, RESOURCE, DWROLE, CREATE SESSION TO MCP_TEST_USER;
GRANT UNLIMITED TABLESPACE TO MCP_TEST_USER;
-- Select AI / MCPサーバー関連の権限付与
GRANT EXECUTE ON DBMS_CLOUD_AI TO MCP_TEST_USER;
GRANT EXECUTE ON DBMS_CLOUD_AI_AGENT TO MCP_TEST_USER;
-- PL/SQLなどの作成権限
GRANT CREATE PROCEDURE TO MCP_TEST_USER;
2. 難解な物理名のテーブル作成とアノテーション付与
次に、IoTデバイスのログデータを模したテーブルを10個作成します。
物理名からは内容を推測できないよう意図的に難解(TABLE_001〜TABLE_010、C_01〜)にし、その代わりに ANNOTATIONS 句を用いてメタデータ(論理名、説明、主キー・外部キー情報、サンプル値など)を定義します。
-- 1. IoTデバイスマスタ (TABLE_001)
CREATE TABLE MCP_TEST_USER.TABLE_001 (
C_01 NUMBER GENERATED ALWAYS AS IDENTITY ANNOTATIONS (Description 'Device ID', Is_Primary_Key 'Yes'),
C_02 VARCHAR2(50) ANNOTATIONS (Description 'Device Type', Example 'Sensor, Gateway, Camera'),
C_03 DATE ANNOTATIONS (Description 'Registration Date')
) ANNOTATIONS (Description 'IoT Device Master');
-- 2. ファームウェアバージョン管理 (TABLE_002)
CREATE TABLE MCP_TEST_USER.TABLE_002 (
C_01 NUMBER GENERATED ALWAYS AS IDENTITY ANNOTATIONS (Description 'Firmware ID', Is_Primary_Key 'Yes'),
C_02 VARCHAR2(20) ANNOTATIONS (Description 'Version String', Example 'v1.0.0'),
C_03 DATE ANNOTATIONS (Description 'Release Date')
) ANNOTATIONS (Description 'Firmware Version Master');
-- 3. デバイス設置場所マスタ (TABLE_003)
CREATE TABLE MCP_TEST_USER.TABLE_003 (
C_01 NUMBER GENERATED ALWAYS AS IDENTITY ANNOTATIONS (Description 'Location ID', Is_Primary_Key 'Yes'),
C_02 NUMBER ANNOTATIONS (Description 'Device ID', Is_Foreign_Key 'Yes', Ref_Table 'TABLE_001'),
C_03 VARCHAR2(100) ANNOTATIONS (Description 'Region Name', Example 'Tokyo-Zone-A')
) ANNOTATIONS (Description 'Device Location Mapping');
-- 4. センサー温度ログ (TABLE_004)
CREATE TABLE MCP_TEST_USER.TABLE_004 (
C_01 NUMBER GENERATED ALWAYS AS IDENTITY ANNOTATIONS (Description 'Log ID', Is_Primary_Key 'Yes'),
C_02 NUMBER ANNOTATIONS (Description 'Device ID', Is_Foreign_Key 'Yes', Ref_Table 'TABLE_001'),
C_03 NUMBER(5,2) ANNOTATIONS (Description 'Temperature Value in Celsius'),
C_04 TIMESTAMP ANNOTATIONS (Description 'Log Timestamp')
) ANNOTATIONS (Description 'Sensor Temperature Logs');
-- 5. センサー湿度ログ (TABLE_005)
CREATE TABLE MCP_TEST_USER.TABLE_005 (
C_01 NUMBER GENERATED ALWAYS AS IDENTITY ANNOTATIONS (Description 'Log ID', Is_Primary_Key 'Yes'),
C_02 NUMBER ANNOTATIONS (Description 'Device ID', Is_Foreign_Key 'Yes', Ref_Table 'TABLE_001'),
C_03 NUMBER(5,2) ANNOTATIONS (Description 'Humidity Value in Percentage'),
C_04 TIMESTAMP ANNOTATIONS (Description 'Log Timestamp')
) ANNOTATIONS (Description 'Sensor Humidity Logs');
-- 6. バッテリー残量ログ (TABLE_006)
CREATE TABLE MCP_TEST_USER.TABLE_006 (
C_01 NUMBER GENERATED ALWAYS AS IDENTITY ANNOTATIONS (Description 'Log ID', Is_Primary_Key 'Yes'),
C_02 NUMBER ANNOTATIONS (Description 'Device ID', Is_Foreign_Key 'Yes', Ref_Table 'TABLE_001'),
C_03 NUMBER(3) ANNOTATIONS (Description 'Battery Percentage', Example '0 to 100'),
C_04 TIMESTAMP ANNOTATIONS (Description 'Log Timestamp')
) ANNOTATIONS (Description 'Battery Level Logs');
-- 7. エラー・アラートログ (TABLE_007)
CREATE TABLE MCP_TEST_USER.TABLE_007 (
C_01 NUMBER GENERATED ALWAYS AS IDENTITY ANNOTATIONS (Description 'Alert ID', Is_Primary_Key 'Yes'),
C_02 NUMBER ANNOTATIONS (Description 'Device ID', Is_Foreign_Key 'Yes', Ref_Table 'TABLE_001'),
C_03 VARCHAR2(20) ANNOTATIONS (Description 'Error Code', Example 'ERR-001'),
C_04 TIMESTAMP ANNOTATIONS (Description 'Alert Timestamp')
) ANNOTATIONS (Description 'Error and Alert Logs');
-- 8. メンテナンス履歴 (TABLE_008)
CREATE TABLE MCP_TEST_USER.TABLE_008 (
C_01 NUMBER GENERATED ALWAYS AS IDENTITY ANNOTATIONS (Description 'Maintenance ID', Is_Primary_Key 'Yes'),
C_02 NUMBER ANNOTATIONS (Description 'Device ID', Is_Foreign_Key 'Yes', Ref_Table 'TABLE_001'),
C_03 VARCHAR2(50) ANNOTATIONS (Description 'Maintenance Type', Example 'Battery Replacement, Inspection'),
C_04 DATE ANNOTATIONS (Description 'Maintenance Date')
) ANNOTATIONS (Description 'Device Maintenance History');
-- 9. 通信パケットログ (TABLE_009)
CREATE TABLE MCP_TEST_USER.TABLE_009 (
C_01 NUMBER GENERATED ALWAYS AS IDENTITY ANNOTATIONS (Description 'Packet ID', Is_Primary_Key 'Yes'),
C_02 NUMBER ANNOTATIONS (Description 'Device ID', Is_Foreign_Key 'Yes', Ref_Table 'TABLE_001'),
C_03 NUMBER ANNOTATIONS (Description 'Data Size in Bytes'),
C_04 TIMESTAMP ANNOTATIONS (Description 'Transmission Timestamp')
) ANNOTATIONS (Description 'Network Packet Logs');
-- 10. アクティベーション履歴 (TABLE_010)
CREATE TABLE MCP_TEST_USER.TABLE_010 (
C_01 NUMBER GENERATED ALWAYS AS IDENTITY ANNOTATIONS (Description 'Activation ID', Is_Primary_Key 'Yes'),
C_02 NUMBER ANNOTATIONS (Description 'Device ID', Is_Foreign_Key 'Yes', Ref_Table 'TABLE_001'),
C_03 VARCHAR2(20) ANNOTATIONS (Description 'Status', Example 'Active, Inactive, Suspended'),
C_04 TIMESTAMP ANNOTATIONS (Description 'Status Change Timestamp')
) ANNOTATIONS (Description 'Device Activation History');
3. テストデータの投入
作成した10個のテーブルに、関連性を持たせたテストデータを INSERT します。
MCP_TEST_USER ユーザーでログインします。
-- 1. IoTデバイスマスタ (TABLE_001)
INSERT INTO TABLE_001 (C_02, C_03) VALUES ('Sensor', SYSDATE - 30);
INSERT INTO TABLE_001 (C_02, C_03) VALUES ('Gateway', SYSDATE - 20);
INSERT INTO TABLE_001 (C_02, C_03) VALUES ('Camera', SYSDATE - 10);
-- 2. ファームウェアバージョン管理 (TABLE_002)
INSERT INTO TABLE_002 (C_02, C_03) VALUES ('v1.0.0', SYSDATE - 100);
INSERT INTO TABLE_002 (C_02, C_03) VALUES ('v1.1.0', SYSDATE - 50);
-- 3. デバイス設置場所マスタ (TABLE_003)
INSERT INTO TABLE_003 (C_02, C_03) VALUES (1, 'Tokyo-Zone-A');
INSERT INTO TABLE_003 (C_02, C_03) VALUES (2, 'Osaka-Zone-B');
INSERT INTO TABLE_003 (C_02, C_03) VALUES (3, 'Tokyo-Zone-C');
-- 4. センサー温度ログ (TABLE_004)
INSERT INTO TABLE_004 (C_02, C_03, C_04) VALUES (1, 24.5, SYSTIMESTAMP - INTERVAL '2' HOUR);
INSERT INTO TABLE_004 (C_02, C_03, C_04) VALUES (1, 25.1, SYSTIMESTAMP - INTERVAL '1' HOUR);
INSERT INTO TABLE_004 (C_02, C_03, C_04) VALUES (1, 25.4, SYSTIMESTAMP);
-- 5. センサー湿度ログ (TABLE_005)
INSERT INTO TABLE_005 (C_02, C_03, C_04) VALUES (1, 45.0, SYSTIMESTAMP - INTERVAL '2' HOUR);
INSERT INTO TABLE_005 (C_02, C_03, C_04) VALUES (1, 46.2, SYSTIMESTAMP - INTERVAL '1' HOUR);
INSERT INTO TABLE_005 (C_02, C_03, C_04) VALUES (1, 47.1, SYSTIMESTAMP);
-- 6. バッテリー残量ログ (TABLE_006)
INSERT INTO TABLE_006 (C_02, C_03, C_04) VALUES (1, 85, SYSTIMESTAMP - INTERVAL '2' HOUR);
INSERT INTO TABLE_006 (C_02, C_03, C_04) VALUES (2, 92, SYSTIMESTAMP - INTERVAL '1' HOUR);
INSERT INTO TABLE_006 (C_02, C_03, C_04) VALUES (3, 40, SYSTIMESTAMP);
-- 7. エラー・アラートログ (TABLE_007)
INSERT INTO TABLE_007 (C_02, C_03, C_04) VALUES (3, 'ERR-CAM-001', SYSTIMESTAMP - INTERVAL '5' HOUR);
INSERT INTO TABLE_007 (C_02, C_03, C_04) VALUES (2, 'WARN-NET-002', SYSTIMESTAMP - INTERVAL '1' HOUR);
-- 8. メンテナンス履歴 (TABLE_008)
INSERT INTO TABLE_008 (C_02, C_03, C_04) VALUES (1, 'Battery Replacement', SYSDATE - 5);
INSERT INTO TABLE_008 (C_02, C_03, C_04) VALUES (3, 'Lens Cleaning', SYSDATE - 2);
-- 9. 通信パケットログ (TABLE_009)
INSERT INTO TABLE_009 (C_02, C_03, C_04) VALUES (2, 1024, SYSTIMESTAMP - INTERVAL '10' MINUTE);
INSERT INTO TABLE_009 (C_02, C_03, C_04) VALUES (2, 2048, SYSTIMESTAMP - INTERVAL '5' MINUTE);
INSERT INTO TABLE_009 (C_02, C_03, C_04) VALUES (2, 512, SYSTIMESTAMP);
-- 10. アクティベーション履歴 (TABLE_010)
INSERT INTO TABLE_010 (C_02, C_03, C_04) VALUES (1, 'Active', SYSTIMESTAMP - INTERVAL '30' DAY);
INSERT INTO TABLE_010 (C_02, C_03, C_04) VALUES (2, 'Active', SYSTIMESTAMP - INTERVAL '20' DAY);
INSERT INTO TABLE_010 (C_02, C_03, C_04) VALUES (3, 'Active', SYSTIMESTAMP - INTERVAL '10' DAY);
COMMIT;
4. MCPサーバー向けカスタムツール (Select AI Agent Tools) の作成
AIエージェントが、スキーマ内の難解なテーブル・列情報を自律的に調査できるようにするための MCP カスタムツールを作成します。
前回の記事で紹介した内容の応用として、今回は offset と limit を用いたページネーション対応を実装しています。
【重要】ツールの作成実行ユーザーについて
DBMS_CLOUD_AI_AGENT.CREATE_TOOL を用いたツールの登録は、ADMINではなく、実際にMCPサーバーでログインするテスト用ユーザー(今回であれば MCP_TEST_USER)として接続して実行する必要があります。
ADMINで作成すると、テストユーザー (MCP_TEST_USER) からのログイン時にツールが検出されません。
テーブルメタデータ取得ツール (GET_TABLE_METADATA)
現在ログインしているスキーマ内の全テーブル名と、付与されたテーブルレベルのアノテーション一覧を取得します。
CREATE OR REPLACE FUNCTION GET_TABLE_METADATA (
offset IN NUMBER,
limit IN NUMBER
) RETURN CLOB AS
V_SQL CLOB;
V_JSON CLOB;
BEGIN
V_SQL := 'SELECT NVL(JSON_ARRAYAGG(JSON_OBJECT(*) RETURNING CLOB), ''[]'') AS json_output '
|| 'FROM ( '
|| ' SELECT t.table_name, '
|| ' (SELECT JSON_ARRAYAGG(JSON_OBJECT(''annotation_name'' VALUE a.annotation_name, ''annotation_value'' VALUE a.annotation_value)) '
|| ' FROM all_annotations_usage a '
|| ' WHERE a.annotation_owner = t.owner AND a.object_name = t.table_name AND a.object_type = ''TABLE'' AND a.column_name IS NULL) AS annotations '
|| ' FROM all_tables t '
|| ' WHERE t.owner = SYS_CONTEXT(''USERENV'', ''CURRENT_USER'') '
|| ' ORDER BY t.table_name '
|| ' OFFSET :off ROWS FETCH NEXT :lim ROWS ONLY '
|| ')';
EXECUTE IMMEDIATE V_SQL INTO V_JSON USING offset, limit;
RETURN V_JSON;
END;
/
BEGIN
DBMS_CLOUD_AI_AGENT.CREATE_TOOL (
tool_name => 'GET_TABLE_METADATA',
attributes => '{"instruction": "Returns table names and their annotations...",
"function": "GET_TABLE_METADATA",
"tool_inputs": [{"name":"offset","description" : "Pagination parameter..."},
{"name":"limit","description" : "Pagination parameter..."}
]}'
);
END;
/
列メタデータ取得ツール (GET_COLUMN_METADATA)
指定したテーブル内の列名、データ型、および列レベルのアノテーションを取得します。
CREATE OR REPLACE FUNCTION GET_COLUMN_METADATA (
table_name IN VARCHAR2,
offset IN NUMBER,
limit IN NUMBER
) RETURN CLOB AS
V_SQL CLOB;
V_JSON CLOB;
BEGIN
V_SQL := 'SELECT NVL(JSON_ARRAYAGG(JSON_OBJECT(*) RETURNING CLOB), ''[]'') AS json_output '
|| 'FROM ( '
|| ' SELECT c.column_name, c.data_type, '
|| ' (SELECT JSON_ARRAYAGG(JSON_OBJECT(''annotation_name'' VALUE a.annotation_name, ''annotation_value'' VALUE a.annotation_value)) '
|| ' FROM all_annotations_usage a '
|| ' WHERE a.annotation_owner = c.owner AND a.object_name = c.table_name AND a.object_type = ''TABLE'' AND a.column_name = c.column_name) AS annotations '
|| ' FROM all_tab_columns c '
|| ' WHERE c.owner = SYS_CONTEXT(''USERENV'', ''CURRENT_USER'') AND c.table_name = :tab '
|| ' ORDER BY c.column_id '
|| ' OFFSET :off ROWS FETCH NEXT :lim ROWS ONLY '
|| ')';
EXECUTE IMMEDIATE V_SQL INTO V_JSON USING table_name, offset, limit;
RETURN V_JSON;
END;
/
BEGIN
DBMS_CLOUD_AI_AGENT.CREATE_TOOL (
tool_name => 'GET_COLUMN_METADATA',
attributes => '{"instruction": "Returns column names, data types, and their annotations...",
"function": "GET_COLUMN_METADATA",
"tool_inputs": [{"name":"table_name","description" : "Table name (e.g. TABLE_001)"},
{"name":"offset","description" : "Pagination parameter..."},
{"name":"limit","description" : "Pagination parameter..."}
]}'
);
END;
/
データ取得(SQL実行)ツール (EXECUTE_SQL)
AIがメタデータを元に組み立てたSELECT文を実行し、結果をJSON形式で返します。
CREATE OR REPLACE FUNCTION EXECUTE_SQL(
query IN CLOB,
offset IN NUMBER,
limit IN NUMBER
) RETURN CLOB
AS
v_sql CLOB;
v_json CLOB;
BEGIN
v_sql := 'SELECT NVL(JSON_ARRAYAGG(JSON_OBJECT(*) RETURNING CLOB), ''[]'') AS json_output ' ||
'FROM ( ' ||
' SELECT * FROM ( ' || query || ' ) sub_q ' ||
' OFFSET :off ROWS FETCH NEXT :lim ROWS ONLY ' ||
')';
EXECUTE IMMEDIATE v_sql INTO v_json USING offset, limit;
RETURN v_json;
END;
/
BEGIN
DBMS_CLOUD_AI_AGENT.CREATE_TOOL (
tool_name => 'EXECUTE_SQL',
attributes => '{"instruction": "Run given read-only SELECT SQL query...",
"function": "EXECUTE_SQL",
"tool_inputs": [{"name":"query","description" : "SELECT SQL statement..."},
{"name":"offset","description" : "Pagination parameter..."},
{"name":"limit","description" : "Pagination parameter..."}
]}'
);
END;
/
5. 確認
MCP Inspectorを使って、正しく MCP のツールとして公開されているか確認します。
Transport Type には "Streamable HTTP" を指定し、URL には下記の URL を指定します。
https://dataaccess.adb.{region-identifier}.oraclecloudapps.com/adb/mcp/v1/databases/{database-ocid}
Connect をクリックするとユーザー名とパスワード入力画面が表示されるので、下記の情報を指定
Username : MCP_TEST_USER
Password : Welcome_12345#_Test
List Tools をクリックすると、Select AI Agent Tools として登録したツール一覧が表示されます。
試しに GET_TABLE_METADATA を実行したら、期待どおりテーブルの一覧が取得出来ました。
[
{
"TABLE_NAME": "TABLE_001",
"ANNOTATIONS": [
{
"annotation_name": "DESCRIPTION",
"annotation_value": "IoT Device Master"
}
]
},
{
"TABLE_NAME": "TABLE_002",
"ANNOTATIONS": [
{
"annotation_name": "DESCRIPTION",
"annotation_value": "Firmware Version Master"
}
]
},
{
"TABLE_NAME": "TABLE_003",
"ANNOTATIONS": [
{
"annotation_name": "DESCRIPTION",
"annotation_value": "Device Location Mapping"
}
]
},
{
"TABLE_NAME": "TABLE_004",
"ANNOTATIONS": [
{
"annotation_name": "DESCRIPTION",
"annotation_value": "Sensor Temperature Logs"
}
]
},
{
"TABLE_NAME": "TABLE_005",
"ANNOTATIONS": [
{
"annotation_name": "DESCRIPTION",
"annotation_value": "Sensor Humidity Logs"
}
]
},
{
"TABLE_NAME": "TABLE_006",
"ANNOTATIONS": [
{
"annotation_name": "DESCRIPTION",
"annotation_value": "Battery Level Logs"
}
]
},
{
"TABLE_NAME": "TABLE_007",
"ANNOTATIONS": [
{
"annotation_name": "DESCRIPTION",
"annotation_value": "Error and Alert Logs"
}
]
},
{
"TABLE_NAME": "TABLE_008",
"ANNOTATIONS": [
{
"annotation_name": "DESCRIPTION",
"annotation_value": "Device Maintenance History"
}
]
},
{
"TABLE_NAME": "TABLE_009",
"ANNOTATIONS": [
{
"annotation_name": "DESCRIPTION",
"annotation_value": "Network Packet Logs"
}
]
},
{
"TABLE_NAME": "TABLE_010",
"ANNOTATIONS": [
{
"annotation_name": "DESCRIPTION",
"annotation_value": "Device Activation History"
}
]
}
]
試しに AI エージェント (Gemini CLI) と連携させて、下記のように質問してみました。
期待どおり回答してくれています。
東京のゾーン(Tokyo-Zone)に設置されているすべてのデバイスの、現在のバッテリー残量の一覧を取得して表形式でまとめてください。
その他のサンプル質問は下記のとおりです。
1: 単一テーブルの基礎的な検索
「データベース内に格納されているIoTデバイスのログの中から、温度ログのデータを調べてください。直近の温度の平均値は何度ですか?」
(期待する動き: TABLE_004を特定し、C_03とC_04を使って平均を計算する)
2: 複雑な分析と推論
「現在バッテリー残量が50%を下回っており、かつ過去にエラーやアラートが発生したことがあるデバイスのIDと、その設置場所をリストアップしてください。」
(期待する動き: 複数テーブルを横断調査し、サブクエリやJOINを駆使したSQLを自律的に構築する)
おわりに
これで、例えば AIエージェントに「温度ログのデータを調べて」と指示した場合に、エージェントが自律的に GET_TABLE_METADATA で TABLE_004 を特定し、GET_COLUMN_METADATA で列の意味や型を理解した上で、適切なSQLを組み立てて EXECUTE_SQL でデータを取得する、という一連の推論プロセスをテストする準備が整いました。
前回の記事の構築手順と合わせて、本テスト環境を活用することで、Autonomous AI Database と MCP サーバーを用いた高度な AI エージェント連携の検証が可能になります。






