
Demystifying the SQLcl MCP Server
What is MCP?
#MCP is currently a hyped term in the tech world. It was first introduced by Anthropic in November 2024 (Anthropic makes Claude). MCP stands for Model Context Protocol and aims to connect LLMs to external data sources.
Here’s a simple analogy: imagine your email lives on Gmail’s servers, but you want to ask Claude (an AI) questions about your emails. Instead of Claude logging into Gmail directly (which would be a security nightmare), Gmail could offer an MCP server that safely provides specific email-related functions to the AI.
The MCP server does typically not grant direct DB access to the LLM; they instead offer their capabilities in a structured way. The MCP protocol specifies three types of capabilities:
- Resources: Context and data for the LLM (e.g., user information and preferences, mail history, contact information, calendar data)
- Prompts: Template-based messages and workflows for the LLM (e.g., “Draft a new mail”, “Decline a meeting”, “Summary of today’s important emails”)
- Tools: Functions for the LLM to call (e.g., “Send a mail”, “Create a new contact”, “Add an event to the calendar”)
MCP has an even bigger impact if you combine many servers. For example, you team up your emails with the MCP from your favorite airline and hotel provider, and upon writing an email about attending a conference, your AI could suggest flights and hotels based on your preferences and past bookings.
MCP for Oracle Developers
#SQLcl 25.2’s newest major feature is introduced as “The (…) Model Context Protocol (MCP) Server transforms how you interact with the Oracle Database by enabling seamless communication with Artificial Intelligence (AI) applications”.
In the introductory webinar, Jeff Smith named the following use cases:
- Reporting (Non-developer): Natural language to SQL / ask questions about the data
- Database Applications (Non-developer): Chat access to application APIs
- Developers/DBA/Operations: Any task they do in the DB
I am a bit skeptical about the first two points; read the last chapter for more information.
What’s happening under the hood?
#The MCP server isn’t a web service you can hit with HTTP requests. Instead, it’s a command-line tool that communicates through JSON messages piped through stdin/stdout.
First you have to send an initialization message to the MCP server, followed by a notification initialization message. Now you can ask for its capabilities.
Testing It Out: A Bash Helper Function
#To make this easier I created this bash function that does the initialization for you.
1sqlcl_mcp() {
2 local method="$1"
3 local params="${2:-{}}"
4 local sql_path="sql"
5
6 echo "Starting SQLcl MCP server... (Press Ctrl+C after you see the response)"
7 (
8 echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"bash","version":"1.0"}}}'
9 sleep 1
10 echo '{"jsonrpc":"2.0","method":"notifications/initialized","params":{}}'
11 sleep 1
12 echo "{\"jsonrpc\":\"2.0\",\"id\":2,\"method\":\"$method\",\"params\":$params}"
13 sleep 5
14 echo "Response should be above. Press Ctrl+C to exit."
15 cat # Keep reading to prevent pipe from closing
16 ) | "$sql_path" -mcp
17}
18
19# Calling the function with the list tools method
20sqlcl_mcp "tools/list"
21
22## output
23# ---------- MCP SERVER STARTUP ----------
24# MCP Server started successfully on Thu Jul 17 12:10:06 CEST 2025
25# Press Ctrl+C to stop the server
26# ----------------------------------------
27# Jul 17, 2025 12:10:07 PM io.modelcontextprotocol.server.McpAsyncServer$AsyncServerImpl lambda$asyncInitializeRequestHandler$5
28# INFO: Client initialize request - Protocol: 2024-11-05, Capabilities: ClientCapabilities[experimental=null, roots=null, sampling=null], Info: Implementation[name=bash, version=1.0]
29# {"jsonrpc":"2.0","id":1,"result":{"protocol ... (many lines)
30
What are the tools
#These are the tools that the MCP server currently provides. I kept the original descriptions, as it might be interesting how they give important context to the tools.
list-connections
- Key Parameters:
filter
(optional),mcp_client
,model
Description
List all available oracle named/saved connections in the connections storage. The `model` argument should specify only the name and version of the LLM (Large Language Model) you are using, with no additional information. The `mcp_client` argument should specify only the name of the MCP (Model Context Protocol) client you are using, with no additional information.- Key Parameters:
connect
- Key Parameters:
connection_name
,mcp_client
,model
Description
Provides an interface to connect to a specified database. If a database connection is already active, prompt the user for confirmation before switching to the new connection. If no connection exists, list the available schemas for selection. The connection name is case sensitive. Note: If the provided connection is invalid or does not match any saved connection, display instructions to the user on how to create a named connection in SQLcl. The `model` argument should specify only the name and version of the LLM (Large Language Model) you are using, with no additional information. The `mcp_client` argument should specify only the name of the MCP (Model Context Protocol) client you are using, with no additional information.- Key Parameters:
disconnect
- Key Parameters:
mcp_client
,model
Description
This tool performs a disconnection from the current session in an Oracle database. If a user is connected, it logs out cleanly and returns to the SQL prompt without an active database connection. The `model` argument should specify only the name and version of the LLM (Large Language Model) you are using, with no additional information. The `mcp_client` argument should specify only the name of the MCP (Model Context Protocol) client you are using, with no additional information.- Key Parameters:
run-sqlcl
- Key Parameters:
sqlcl
,mcp_client
,model
Description
This tool executes SQLcl commands in the SQLcl CLI. If the given command requires a database connection, it prompts the user to connect using the connect tool. You should: Execute the provided SQLcl command. Return the results. Args: sql: The SQLcl command to execute. Returns: Command results. The `model` argument should specify only the name and version of the LLM (Large Language Model) you are using, with no additional information. The `mcp_client` argument should specify only the name of the MCP (Model Context Protocol) client you are using, with no additional information.- Key Parameters:
run-sql
- Key Parameters:
sql
,mcp_client
,model
Description
This tool executes SQL queries in an Oracle database. If no active connection exists, it prompts the user to connect using the connect tool. You should: Execute the provided SQL query. Return the results in CSV format. Args: sql: The SQL query to execute. The `model` argument should specify only the name and version of the LLM (Large Language Model) you are using, with no additional information. The `mcp_client` argument should specify only the name of the MCP (Model Context Protocol) client you are using, with no additional information. Returns: CSV-formatted query results. For every SQL query you generate, please include a comment at the beginning of the SELECT statement (or other main SQL command) that identifies the LLM model name and version you are using. Format the comment as: /_ LLM in use is [model_name_and_version] _/ and place it immediately after the main SQL keyword.- Key Parameters:
Key observations:
- All tools require
mcp_client
andmodel
parameters for tracking - The
run-sql
tool automatically formats results as CSV - Connection management is handled through saved connections
- Both SQL queries and SQLcl commands can be executed
- The server prompts for database connections when needed
No Resources and Prompts
#Interestingly the MCP server does not provide any resources or prompts. This means that it does not provide any context or data for the LLM to work with. It only provides tools to execute SQL queries and SQLcl commands.
Running a chain of commands
#Now I wanted to test real usage by running SQL against the database with it. Instead of using bash I vibe coded a Bun (JavaScript runtime) script that makes it easier to run a chain of commands with nice output. You can see the script here.
I basically
- Connect to the MCP server
- List the available connections
- Connect to the
local-23ai-movies
connection - Check if there are new tools/prompts/resources available
- Run an SQL query to search for movies named “Godfather”
- Disconnect from the database
The list-connections just returns a comma-separated list:
1{
2 "content": [
3 {
4 "type": "text",
5 "text": "local-23ai-advent,local-23ai-movies,arc25@ai.united-codes.com,..."
6 }
7 ],
8 "isError": false
9}
10
The connect command returns several info objects about the database:
1"result": {
2 "content": [
3 {
4 "type": "text",
5 "text": "### DATABASE CONNECTION ESTABLISHED ###\nSuccessfully connected to: **local-23ai-movies**"
6 },
7 {
8 "type": "text",
9 "text": "\n### DATABASE ENVIRONMENT CONTEXT ###\n"
10 },
11 {
12 "type": "text",
13 "text": "**1. Oracle Database Version:** \n23.0.0.0.0"
14 },
15 {
16 "type": "text",
17 "text": "**2. Access Mode:** \nThe Oracle database is currently in 'null' mode"
18 },
19 {
20 "type": "text",
21 "text": "**3. NLS Parameters:** \nThe current Oracle database uses the following NLS configuration:\nDatabase character set:{\"results\":[{\"columns\":[{\"name\":\"PARAMETER\",\"type\":\"VARCHAR2\"},
22 ..."
23 },
24 {
25 "type": "text",
26 "text": "Here’s the Oracle database context you need: version, open mode, and NLS parameters. Use this information to run the following queries accurately and ensure they align with the database’s current environment and settings."
27 }
28 ],
29 "isError": false
30 }
31
There are no additional tools/resources/prompts available after a connection.
The run-sql tool just returns the data as CSV:
1{
2 "content": [
3 {
4 "type": "text",
5 "text": "\"TITLE\",\"YEAR\",\"IMDB_RATING\"\n\"The Godfather\",1972,9.2\n\"The Godfather: Part II\",1974,9.0\n\"The Godfather: Part III\",1990,7.6\n"
6 }
7 ],
8 "isError": false
9}
10
The disconnect just returns a success message.
Faster SQLcl Releases
#Kris Rice said that SQLcl will go to a faster release cycle. I will keep an eye on any changes to the tools and capabilities of the MCP server.
I would not give access to this to non-developers
#This is a great tool for developers and DBAs who already have database access. But I have concerns about the broader vision.
Security Concerns
#Currently the MCP server does not give tailored access to specific database APIs. Instead, you give a SQL command prompt to an LLM. And it can possibly run anything the connected user is allowed to run.
I don’t want to give this to non-technical users. On the documentation page, Oracle also warns about this and suggests the following safeguards:
- Avoid minimum permissions
- Avoid production database access
- Audit LLM activity
Companies like GitHub recently had a big security issue with their MCP server.
You probably want tools
#This is now a bit of a jump, but there is another concept that I think is more suitable for access to non-developers: tools.
Tools were also introduced by Anthropic before MCP was a thing. The main differences are
- Only tools, no resources or prompts. You tell the LLM which functions you have available, and it can decide to call them.
- No client-server protocol. You can handle everything from inside the DB without a separate client. (You still talk to the LLM via API, of course)
I have implemented tools in my open-source UC AI project that aims to bring AIs to Oracle developers (without 23ai).
That way you can define fine-grained tools (PL/SQL function) that only allow specific actions you want the AI/the user to perform. I have recorded a demo video that shows a time-tracking system where I have defined three tools:
- Get user data
- Get project data
- Clock in (start tracking time on the project)
When you then send a message to an LLM with the user prompt “Clock me in to the marketing project” and some user info in the system prompt it will first call the “Get user data” tool to get the user ID and then call the “Get project data” tool to get the project ID. After that it will call the “Clock in” tool with the user ID and project ID.
And the LLM does not have access to an SQL prompt or similar; it can only call the tools you have defined. Additionally, if you implement that in your APEX app, this will act inside the users APEX/Database session. So you can easily check the current logged-in user and their permissions.
Note that the next APEX release will also support tools. But with UC AI I aim to be faster and more flexible to Oracle releases. Like UC AI already supports Anthropic and Google as providers next to OpenAI.
I hope we can add our own tools/resources/prompts in the future
#It is great to see Oracle offering a solution for MCP so fast. And for use-cases where you really want MCP it would be great if you could define your own tools and disable the default ones. With that you could achieve the same as with tools, by also providing fine grained access to specific database APIs.
I might have missed it, but I have not heard anything about this from Oracle yet. I hope they will add this in the future.