2026年6月2日火曜日

SQLcl MCPサーバーとDatabase Tools MCPサーバーのSQLの非同期実行を確認する

SQLclに実装されているMCPサーバーおよびOracle Cloudで作成できるDatabase Tools MCP Serverの双方で、任意のSQLを実行できるツールが提供されています。その両方の汎用SQL実行ツールで、非同期実行がサポートされています。

MCPのプロトコルとしては、ツールの非同期実行はSEP-1686: Tasksなどで提案されていました。この提案は2025-11-25では実験的な実装にとどまっています。MCPの2026-07-28では、MCPの非同期プロトコルへの設計変更に合わせてtasks/get、tasks/update、tasks/cancelなど、タスクのライフサイクルを扱えるようにプロトコルが拡張されています。

現時点のMCPにはツールの非同期実行はプロコトルに含まれていないため、SQLclとDatabase Tools MCP Serverが提供しているSQLの非同期実行は、あくまでプロンプトとツールを組み合わせて独自に実装しています。

これらの汎用SQLツールの非同期実行がどのように動作するか確認します。

動作確認にはMCP Inspectorを使用します。動作確認を行なう環境として、以下の2種類を対象とします。
  • SQLclからローカルのOracle AI Database 26ai Freeに接続する
  • Database Tools MCP ServerからOracle Autonomous Database 19cに接続する(作成手順については、こちらの記事


SQLclのツールsql_runでの非同期実行



以下のバージョンのSQLclを使って、動作の確認を行います。バージョンが変わることにより、ツールの説明、ツール名、パラメータなどが変わる可能性はあります。

SQLcl: リリース26.1.2.0 Production ビルド: 26.1.2.132.1334

LLMはMCPサーバーのtools/listのレスポンスであるJSONドキュメントを参照して、呼び出すツールを決めます。汎用のSQL実行ツールはsql_runなので、tools/listのsql_runの説明を確認します。
{
  "name": "sql_run",
  "description": "Executes a SQL statement or PL/SQL block against the connected Oracle database. Returns CSV-formatted...",
  "inputSchema": {
    "type": "object",
    "properties": {
      "sql": {
        "type": "string",
        "description": "The SQL query to execute"
      },
      "model": {
        "type": "string",
        "description": "The name (and version) of the language model being used by the MCP client to process requests",
        "default": "UNKNOWN-LLM"
      },
      "execution_type": {
        "type": "string",
        "enum": [
          "SYNCHRONOUS",
          "ASYNCHRONOUS"
        ],
        "description": "The execution type of the sql query",
        "default": "SYNCHRONOUS"
      }
    },
    "required": [
      "sql"
    ]
  }
}
sql_runのdescriptionが長く、MCP Inspectorのtools/listのアウトプットでは省略されています。

パラメータについてはexecution_typeとしてSYNCHRONOUSASYNCHRONOUSが選択でき、デフォルトSYNCHRONOUSとなっています。requiredに含まれる引数はsqlのみなので、指定がないときはSQLは同期実行されます。

MCP InspectorからSQLclのMCPサーバーを呼び出し、SQLを非同期実行してみます。最初にconnectコマンドを呼び出し、データベースに接続しておきます。

MCP Inspectorでsql_runを選択します。

ツールの説明(description)に、非同期実行について以下の説明があります。
Use this tool for standard queries, DML, DDL, and PL/SQL that complete in a few seconds.
Set `execution_type=ASYNCHRONOUS` for queries that scan large tables or may take
longer than a few seconds. If the command keeps running in the background,
the response includes structured content containing `tool_request_id`.
execution_typeASYNCHRONOUSを渡したときに、SQLの実行時間がごく短い時間(数秒)を超えると、SQLの実行結果の代わりにtool_request_idを返すとなっています。

tool_request_idを受け取ったLLMが処理結果を参照するには、ここで受け取ったIDを引数としてツールrequest_statusを呼び出します。

execution_typeASYNCHRONOUSを設定してツールsql_runを呼び出し、SELECT文を実行してみます。

最初に以下のSELECT文を実行します。

select count(*) from all_users, all_users

以下のレスポンスが得られました。処理時間が短いため同期処理と同様の結果が返されます。
""COUNT(*)"
1849

"

次に以下のSELECT文を実行します。

select count(*) from all_objects, all_tables

以下のレスポンスが得られました。tool_request_idが返されています。
{
  "tool_request_id": "2"
}
Unstructured Contentとして以下が返されています。

タスクはID: 2で、バックグラウンドで実行するよう正常に設定されました


tool_request_idとして2が得られているので、この値でツールrequest_statusを呼び出してみます。

SELECT文の実行が終了していると、実行結果が返されます。
""COUNT(*)"
17097924

"


もう少し実行時間がかかるSELECT文を実行してみます。

select count(*) from all_objects, all_objects

tool_request_idとして 3 が返されました。


tool_request_idとしてを渡し、ツールrequest_statusを呼び出します。

レスポンスとして"実行中"が返されます。SQLclが日本語ロケールの環境で実行されているため、RUNNING実行中と翻訳されているように見受けられます。


処理が完了した後にrequest_statusを呼び出すと、SELECT文の結果が表示されます。


非同期実行の出力は、 ~/.dbtools/sqlcl/jobslogs/ (SQLclのホーム以下)にファイルとして出力されているようです。検索結果にセンシティブな情報が含まれる場合には注意が必要かと思います。

意図的に処理中のSELECT文を中断し、結果を確認してみます。

先ほど実行した以下のSELECT文のSQL_IDを確認します。

select count(*) from all_objects, all_objects

データベースにSYSDBA権限を持つユーザーで接続して作業します。

SQLclが実行するSQLには、コメントにmodel名が挿入されます。以下のSELECT文を実行し、SQL_IDを特定します。

select sql_id, sql_text from v$sql where sql_text like '%UNKNOWN-LLM%all_objects, all_objects%'

SQL> select sql_id, sql_text from v$sql where sql_text like '%UNKNOWN-LLM%all_objects, all_objects%';


SQL_ID           SQL_TEXT                                                                                           

________________ __________________________________________________________________________________________________ 

1aa9f3gqhtbby    select sql_id, sql_text from v$sql where sql_text like '%UNKNOWN-LLM%all_objects, all_objects%'    

ag0h1g4t92axp    select /* LLM in use is UNKNOWN-LLM */ count(*) from all_objects, all_objects                      


SQL> 


SQL_IDはag0h1g4t92axpでした。

最初はexecution_typeSYNCHRONOUSを指定(同期処理)して実行し、そのSELECT文の実行をキャンセルします。

sql_runを実行します。


以下のSELECT文を実行し、実行中のSELECT文をキャンセルするALTER文を生成します。

select 'alter system cancel sql ' || chr(39) || sid || ',' || serial# || chr(39) from v$session where username = 'APEXDEV' and status = 'ACTIVE' and sql_id = 'ag0h1g4t92axp';

実行結果として得られたalter文を続けて実行します。

SQL> select 'alter system cancel sql ' || chr(39) || sid || ',' || serial# || chr(39) from v$session where username = 'APEXDEV' and status = 'ACTIVE' and sql_id = 'ag0h1g4t92axp';


'ALTERSYSTEMCANCELSQL'||CHR(39)||SID||','||SERIAL#||CHR(39)    

______________________________________________________________ 

alter system cancel sql '196,56849'                            


SQL> alter system cancel sql '196,56849';


Systemが変更されました。


SQL> 


データベースが返すエラー・メッセージが、ツールの出力になっています。Tool ResultSuccessです。


ResponseのJSONを確認したところ、isError属性はfalseになっていました。
{
  "content": [
    {
      "type": "text",
      "text": "\n次のコマンド行の開始中にエラーが発生しました : 1 -\nselect /* LLM in use is UNKNOWN-LLM */ count(*) from all_objects, all_objects\nコマンド行 : 1 列 : 1 でのエラー\nエラー・レポート -\nSQLエラー: ORA-01013: ユーザーによって現行の操作の取消しがリクエストされました。\n\nhttps://docs.oracle.com/error-help/db/ora-01013/01013. 00000 -  \"User requested cancel of current operation.\"\n*Cause:    The user interrupted an Oracle operation by entering CTRL-C,\n           Control-C, or another canceling operation.\n*Action:   No action needed.\n\nMore Details :\nhttps://docs.oracle.com/error-help/db/ora-01013/\n"
    }
  ],
  "isError": false
}
SQLclのMCPサーバーのツールsql_runは、実行するSQLの成否ではなくツールが呼び出せたかどうかでisError属性を決めているように見えます。LLMはツールの出力を見て、SQLの実行が成功したか失敗したかを判断することになります。

同じSELECT文を非同期で実行し、同期処理のときと同様の手順でSELECT文をキャンセルします。

tool_request_idとして6が得られています。


同期処理のときと同じ作業を行い、SELECT文をキャンセルします。

ツールrequest_statusを、引数tool_request_id6を与えて呼び出します。同期実行のときのツール出力と、同じエラー・メッセージが返されます。


SQLclのツールsql_runの非同期処理は以上のように動作していました。

ツールrequest_statusdescriptionには以下のように記載されています。
Possible outcomes:
- RUNNING: The request is still in progress; no final result is available yet. Retry after a short delay.
- FAILED: The request completed with an error; the response contains error details.
- FINISHED: The request completed successfully; the response contains the final result payload produced by the original tool.
RUNNINGのときは、ツールのレスポンスとして"実行中"が返されます。FAILEDのときは、レスポンスとしてerror detailsが返されるとあり、FINISHEDのときは、レスポンスとしてorginal toolが生成した最終結果が返される、とあります。そのため、記載された説明と確認した動作は一致していると言えます。


Database Tools SQL Serverのsql_runでの非同期実行



Database Tools MCP Serverでツールsql_runの非同期実行を有効にするには、実行時アイデンティティリソース・プリンシパルとします。認証済プリンシパルでは非同期実行が有効化されないようです。

同期/非同期の実行を指定する引数はexecutionTypeです。inputSchemaのプロパティexecutionTypeのdescriptionとして、以下の記述があります。
When set to `SYNCHRONOUS`:
The tool blocks and waits until the tool call completes, then returns the final result. If execution does not complete within the configured timeout, the tool returns an error (timeout).

When set to `ASYNCHRONOUS`:
The tool attempts to return a result quickly:
1) If execution completes within ~55 seconds, the tool returns the final result in this response.
2) If execution takes longer than ~55 seconds, the tool returns a toolRequestId instead of the final result. Use that toolRequestId with request_status to poll until the final result is available.

Prefer SYNCHRONOUS for short queries where you need immediate results. Prefer ASYNCHRONOUS for long-running scripts (e.g., large queries, bulk DML, DDL, or PL/SQL) and be prepared to poll using request_status.
SQLclの非同期処理と動作は似ているのですが、SQLclは数秒であるのに対して、Database Tools MCP Serverでは55秒が非同期処理の閾値になっています。

Always FreeのAutonomous AI DatabaseはローカルのOracle AI Database 26ai Freeより、ディクショナリの検索に時間がかかるため、以下のSQLを非同期で実行してみます。

select count(*) from all_tables, all_tables

Database Tools MCP Serverでは、かなりの時間(55秒)待ってから、toolRequestIdとして、以下が以下が返されました。

{
  "toolRequestId": "ZGF0YWJhc2V0b29sc3J0d29ya3JlcXVlc3Q6b2NpZDEuZGF0YWJhc2V0b29sc3J0d29ya3JlcXVlc3Qub2MxLmNhLXRvcm9udG8tMS5hYWFhYWFhYWpiaWo2aHRzcWVkNmJzY2Vsc3UyYmR2amNhM3FweWYzNHdkajJ0bXAyM2N6YjV2aWNiZ3E="
}


toolRequestIdに上記の値を渡し、ツールrequest_statusを呼び出します。同期実行で返されるレスポンスと同じレスポンスが返されます。


処理に時間がかかるSELECT文を非同期実行します。

select count(*) from all_objects, all_objects

toolRequestIdが返されます。


MCPサーバーから発行された非同期処理は、接続ランタイム作業リクエストとして実行されています。コンソールから接続admin@dbtoolsmcp作業リクエストを一覧すると、処理の進捗を確認できます。

ランタイム作業リクエストSQLスケジュール済削除の実行SQLの実行で、1つの非同期実行のセットになります。


SQLの処理が継続している状態で、ツールrequest_statusを呼び出してみます。

原因はわかりませんが、ツールrequest_statusも55秒程度待機した後に、引数toolRequestIdに与えたIDをtoolRequestIdとして返してきます。SQLclのMCPサーバーでは、レスポンスとして"実行中"が返される処理です。


実行中のランタイム作業リクエストを、コンソールから中断する方法は提供されていないようです。ランタイム作業リクエストのOCIDを取得し、以下のコマンドを実行して実行中のランタイム作業リクエストをキャンセルします。
oci raw-request \
  --http-method DELETE \
  --target-uri https://dbtools.<リージョン>.oci.oraclecloud.com/20230222/workRequests/<キャンセルするランタイム作業リクエストのOCID>

~ % oci raw-request \

  --http-method DELETE \

  --target-uri https://dbtools.ca-toronto-1.oci.oraclecloud.com/20230222/workRequests/ocid1.databasetoolsrtworkrequest.oc1.ca-toronto-1.aaaaaaaaelifb474vvkwzxorjrfyrrntl2zlcyuxbv2hxhlnyjv3u2ioog6a

/opt/homebrew/Cellar/oci-cli/3.84.0/libexec/lib/python3.14/site-packages/urllib3/poolmanager.py:329: FutureWarning: The 'strict' parameter is no longer needed on Python 3+. This will raise an error in urllib3 v3.0.

  warnings.warn(

{

  "data": "",

  "headers": {

    "Content-Type": "application/octet-stream",

    "Date": "Tue, 02 Jun 2026 04:57:56 GMT",

    "Strict-Transport-Security": "max-age=63072000; includeSubDomains",

    "Transfer-Encoding": "chunked",

    "Vary": "Origin",

    "X-Content-Type-Options": "nosniff, nosniff",

    "opc-request-id": "E47D86BC52A649778BF9A566F66514CC/7BB81289697F3EE0D4621E6A59595AD0/0EC494DAE6979A7E61F1C804405C3234"

  },

  "status": "202 Accepted"

}

~ % 


Database Tools MCP Serverのツールsql_runの非同期処理は以上のように動作していました。

データベースでは検索にある程度時間がかかるクエリはあります。すべて同期処理で順次呼び出しでは、実用的なサービスを作るのは難しいです。SQLclやDatabase Tools MCP Serverが提供するSQLの非同期実行は、それらの一部の実装を助けるかもしれません。しかし、現状ではMCPの2026-07-28が広く採用されて、タスクとして非同期実行を実装できるようになることを期待しています。