We host monthly (2nd Tuesday) news updates, covering features and enhancements released for both our AI Database and Oracle Cloud Infrastructure (OCI). Today we welcomed about 400 folks and did a wrap of MCP.

By the way, you can find the previous recordings here.

I thought I’d highlight today’s updates in a bit of a deeper dive now.

  1. SQLcl -R, restriction levels
  2. SQLcl -home, alternative ‘home’ for connections and SQL History
  3. run-sql MCP Tool, asynchronous mode!
  4. schema-information MCP Tool, consistent method to get schema metadata & AI Enrichement data

Did you know #1: restrict allowed SQLcl commands

Technically this isn’t a new feature for SQLcl, but we have put some time into documenting and changing the default restriction level for MCP [4].

Maybe you’re ok with SQLcl MCP offering connect and run queries, but you’re not OK with it interacting with your local operating system. Commands like HOST and SPOOL do just that, and the agent has access to them, if the Restriction level permits it.

You can find the docs detailing the full list of commands and setting excluded by -R level here.

Bash
Macmini:bin thatjeffsmith$ ./sql -R 2 /nolog

SQLcl: Release 25.4 Production on Tue Jan 13 14:11:00 2026

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

SQL> spool stuff.csv
SP2-0738: Restricted command: 
"spool stuff.csv"
not available
SQL> 

If I were to ‘code’ that into my MCP Config, it would look like this –

JSON
"mcpServers": {
    "sqlcl": {
      "timeout": 60,
      "command": "/opt/sqlcl/25.4/sqlcl/bin/sql",
      "args": [
        "-mcp",
        "-R",
        2
      ],
      "type": "stdio",
      "disabled": false
    },
    ...

Did you know #2: specify database connections

The -home flag tells SQLcl where to find it’s connections and SQL History data. So instead of running the MCP Server will full access to any/all database connections you’ve ever created from either SQLcl or our VS Code Extension (SQL Developer!), you can say, just use these.

My current (default) set of database connections

Bash
Macmini:bin thatjeffsmith$ ./sql /nolog

SQLcl: Release 25.4 Production on Tue Jan 13 14:11:00 2026

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

SQL> connmgr list
.
├── Cloud
└── 🅾️ Autonomous Reporting
├── Local Containers
├── Project Payroll 💲
└── Project Raptor 🦖
├── ADMIN
├── Free26ai
├── HR123
├── demo
├── job
├── system
└── windy
SQL>

Only allowing two of those connections to be used

Let’s say I ONLY want the MCP Server to be able to work with my ‘Free26ai’ connection and my Project Raptor 🦖 connection. To do this, I need to create a new directory structure with only those 2 connections included.

I’m on a Mac, so I’ll cd to $HOME/.dbtools/connections.

Copy the two directories associated for those two connections, to a new location.

/users/thatjeffsmith/mcp-data is my new, private $HOME for SQLcl. I’ve put a connections folder under that, and I’ve copied the two connection directories I want to maintain going forward for MCP.

Bash
Macmini:mcp-data thatjeffsmith$ tree
.
└── connections
    ├── BgTSVoRCeNCaJgU721YE2Q
    │   ├── credentials.sso
    │   ├── dbtools.properties
    │   └── ojdbc.properties
    └── hr
        ├── credentials.sso
        ├── dbtools.properties
        └── ojdbc.properties

4 directories, 6 files
Macmini:mcp-data thatjeffsmith$ 

💡Tip: inspect the VS Code log to see the corresponding connection directory. Simply connect, and see the corresponding SQL Developer – Log in the Output panel.

Mine looks like this –

Testing the new ‘home’

Starting up SQLcl with the new ‘home’

Bash
Macmini:bin thatjeffsmith$ ./sql -home /Users/thatjeffsmith/mcp-data /nolog

SQLcl: Release 25.4 Production on Tue Jan 13 14:53:23 2026

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


SQL> connmgr list
.
├── Free26ai
└── Project Raptor 🦖
SQL> 

And just to make sure it’s the right one…

Bash
SQL> conn -name "Project Raptor 🦖"
login.sql found in the CWD. DB access is restricted for login.sql.
Adjust the SQLPATH to include the path to enable full functionality.
Connected.
SQL> show connection
COMMAND_PROPERTIES:
 type: STORE
 name: Project Raptor 🦖
 user: hr
CONNECTION:
 HR@jdbc:oracle:thin:@//localhost:1521/freepdb1 
CONNECTION_IDENTIFIER:
 Project Raptor 🦖
CONNECTION_DB_VERSION:
 Oracle AI Database 26ai Free Release 23.26.0.0.0 - Develop, Learn, and Run for Free
 Version 23.26.0.0.0
NOLOG:
 false
PRELIMAUTH:
 false
SQL> 

To apply this to our MCP Server config, the json should look like this –

JSON
"mcpServers": {
    "sqlcl": {
      "timeout": 60,
      "command": "/opt/sqlcl/25.4/sqlcl/bin/sql",
      "args": [
        "-mcp",
        "-home /Users/thatjeffsmith/mcp-data"
      ],
      "type": "stdio",
      "disabled": false
    },
    ...

Did you know #3: Asynchronous Query Execution

This is a fancy way of saying, ‘running queries on a background thread.’ Let’s say you have a report (SQL/script) that takes…5 minutes to run. The MCP Server is set to timeout requests after 60 seconds, so that’s not good.

No worries! You can simply instruct the agent to run the query in the background because it takes a long time and check for the results, later.

This also means the agent can task our MCP Server with multiple queries vs waiting/executing, one-by-one for a max of 5 queries.

The MCP server response is immediate –

Task has been set to run in background successfully with id: 0

And this is all the information the Agent needs in order to request the results, later. Note there is no ‘new tool,’ for the Agent to interact with, it can simply invoke the run-sql tool again, this time asking for the status or results of job #0.

If this sounds familiar, then good on you! We added this feature in general for SQLcl in 2024 (24.1), and now the accompanying MCP Server follows the same workflow.

The way this works in MCP-land, is we can overload the JSON payloads accepted for a single Tool.

Option1 – Agent submits a query to run.

JSON
{
  "sql": "The SQL query to execute" (required),
  "async": false (optional, default: false),
  "model": "UNKNOWN-LLM" (optional, default)
}

If you set “async” to true, then the MCP Server response will include a “job_id” that can be referenced later.

Option 2 – Agent asks for an update on job_id X.

JSON
{
  "job_id": "The job ID from async execution" (required),
  "command": "status|results|cancel" (required),
  "model": "UNKNOWN-LLM" (optional, default)
}

Did you know #4: Consistent metadata collection

When you task your Agent to do something that involves running queries on your database (NL2QL), then before it can generate the SQL, it needs to know more about your database.

So you’ll generally see it query dictionary views, multiple times, to get a list of columns, tables, data types, comments, constraints (joins!) and more. These tasks vary widely between different LLMs or even between different sessions on the same agent and llm.

So to minimize tokens, time, and work, we’ve provide a consistent interface for getting this data, the schema-information tool.

If you see your agent asking to run a bunch of dictionary queries to get started, remind it you have a tool for that!

And my agent responds, thusly:

The Agent’s plan was –

  • connect to the database
  • run the schema-information tool
  • construct the SQL(s) to inspect the WordPress tables

Note that it neither generated nor executed ANY queries to actually find the WordPress tables, or investigate their structure/defintion.

If I look at a partial response from the schema-information tool invocation, I can see what was used to generate the SQL going forward –

Bash
"WP_COMMENTS ((OBJECT_TYPE:TABLE),(COMMENT:WordPress comments data imported from JSON)) : COMMENT_ID(DATA_TYPE:NUMBER,COMMENT:Unique comment identifier) , COMMENT_POST_ID(DATA_TYPE:NUMBER,COMMENT:ID of the post this comment belongs to) , COMMENT_AUTHOR(DATA_TYPE:VARCHAR2,COMMENT:Name of the comment author) , COMMENT_AUTHOR_EMAIL(DATA_TYPE:VARCHAR2,COMMENT:Email address of the comment author) , COMMENT_AUTHOR_URL(DATA_TYPE:VARCHAR2,COMMENT:Website URL of the comment author) , COMMENT_AUTHOR_IP(DATA_TYPE:VARCHAR2,COMMENT:IP address of the comment author) , COMMENT_DATE(DATA_TYPE:DATE,COMMENT:Date and time when comment was posted (local time)) , COMMENT_DATE_GMT(DATA_TYPE:DATE,COMMENT:Date and time when comment was posted (GMT)) , COMMENT_CONTENT(DATA_TYPE:CLOB,COMMENT:The actual comment content (stored as CLOB for large text)) , COMMENT_KARMA(DATA_TYPE:NUMBER,COMMENT:Comment karma/rating score) , COMMENT_APPROVED(DATA_TYPE:VARCHAR2,COMMENT:Approval status: 1=approved, 0=pending, spam, trash) , COMMENT_AGENT(DATA_TYPE:VARCHAR2,COMMENT:User agent string of the commenter) , COMMENT_TYPE(DATA_TYPE:VARCHAR2,COMMENT:Type of comment: comment, pingback, trackback) , COMMENT_PARENT(DATA_TYPE:NUMBER,COMMENT:Parent comment ID for threaded comments) , USER_ID(DATA_TYPE:NUMBER,COMMENT:WordPress user ID if commenter is registered user) , COMMENT_VECTOR(DATA_TYPE:VECTOR) | INDEXES:BLOG_COMMENTS_HNSW_IDX(INDEX_TYPE:VECTOR,COLUMNS:COMMENT_VECTOR{1}) , IDX_WP_COMMENTS_APPROVED(INDEX_TYPE:NORMAL,COLUMNS:COMMENT_APPROVED{1}) , IDX_WP_COMMENTS_DATE(INDEX_TYPE:NORMAL,COLUMNS:COMMENT_DATE{1}) , IDX_WP_COMMENTS_PARENT(INDEX_TYPE:NORMAL,COLUMNS:COMMENT_PARENT{1}) , IDX_WP_COMMENTS_POST_ID(INDEX_TYPE:NORMAL,COLUMNS:COMMENT_POST_ID{1}) , IDX_WP_COMMENTS_USER_ID(INDEX_TYPE:NORMAL,COLUMNS:USER_ID{1}) , PK_WP_COMMENTS(INDEX_TYPE:NORMAL-UNIQUE,COLUMNS:COMMENT_ID{1}) , SYS_IL0000078034C00009$$(INDEX_TYPE:LOB-UNIQUE,COLUMNS:) , SYS_IL0000078034C00016$$(INDEX_TYPE:LOB-UNIQUE,COLUMNS:)"
"WP_POSTS ((OBJECT_TYPE:TABLE)) : ID(DATA_TYPE:NUMBER) , POST_DATE(DATA_TYPE:TIMESTAMP(6)) , POST_TITLE(DATA_TYPE:VARCHAR2) , POST_EXCERPT(DATA_TYPE:VARCHAR2) , COMMENT_COUNT(DATA_TYPE:NUMBER) | INDEXES:IDX_WP_POSTS_DATE(INDEX_TYPE:NORMAL,COLUMNS:POST_DATE{1}) , PK_WP_POSTS(INDEX_TYPE:NORMAL-UNIQUE,COLUMNS:ID{1})"

Quick Recap

We’ve been continuously improving, optimizing, and securing the MCP Server for our Oracle AI Database. A lot of these changes have been prompted by user feedback, thanks for pushing us to do more!

You can now run long running queries, restrict the MCP Server from interacting with the local environment, specify exactly the databases you want it to be able to work with, and save a ton of tokens and get consistent behavior when browsing your schema to assist with NL2SQL operations.

Claude reminds me to thank my most active community members!

6,332 of you have provided feedback here in terms of dropping a note or leaving a question. Here are the top 5 –

👥 Most Active Community Members

You’ve been incredibly engaged with 8,509 comments under “thatjeffsmith” across 811 posts! Your top community contributors include:

  1. Amin Adatia – 110 comments (active 2014-2024)
  2. Mark – 98 comments (since 2010)
  3. Peter – 88 comments
  4. John – 76 comments
  5. Alex – 68 comments
Author

I'm a Distinguished Product Manager at Oracle. My mission is to help you and your company be more efficient with our database tools.

Write A Comment