@vdeserto/oracle-mcp-server
v1.0.0
Published
Read-only MCP server for Oracle Database. Works with Claude Desktop, Claude Code, and Gemini CLI.
Maintainers
Readme
oracle-mcp-server
Read-only MCP server for Oracle Database. Lets Claude and Gemini query an Oracle database using natural language — no SQL knowledge required.
Features
- Read-only by default —
SET TRANSACTION READ ONLYenforced at the database level on every connection - SQL injection protection — structured filters with bind parameters, identifier validation, NFKC normalisation
- 5 tools — list schemas, list tables, describe table, execute SELECT, get table data with pagination
- Node.js ≥ 18 — uses the official
oracledbdriver
Requirements
- Node.js 18+
- Oracle Instant Client — see platform-specific instructions below
- Oracle Database 12c or later
Oracle Instant Client Setup
The oracledb driver requires Oracle Instant Client libraries installed on the machine running this server.
macOS
# Download Basic Package from:
# https://www.oracle.com/database/technologies/instant-client/macos-intel-x86-downloads.html
# Extract and set the library path
export DYLD_LIBRARY_PATH=/path/to/instantclient_19_8:$DYLD_LIBRARY_PATHLinux
# Download Basic Package from:
# https://www.oracle.com/database/technologies/instant-client/linux-x86-64-downloads.html
# Extract and configure
sudo sh -c "echo /path/to/instantclient_19_8 > /etc/ld.so.conf.d/oracle-instantclient.conf"
sudo ldconfigWindows
- Download Basic Package from Oracle Instant Client for Windows
- Extract to a folder, e.g.
C:\oracle\instantclient_19_8 - Add that folder to your PATH:
- Open System Properties → Advanced → Environment Variables
- Under System variables, edit
Pathand addC:\oracle\instantclient_19_8
- Restart your terminal / Claude Desktop
Windows users: if your Oracle database uses
WE8MSWIN1252(the default Windows charset), setNLS_LANG=AMERICAN_AMERICA.WE8MSWIN1252to ensure accented characters display correctly.
Environment Variables
| Variable | Description | Example |
|---|---|---|
| ORACLE_USER | Database username | my_user |
| ORACLE_PASSWORD | Database password | secret |
| ORACLE_CONNECTION_STRING | Host:port/service | localhost:1521/ORCL |
| NLS_LANG | Client character set (optional) | AMERICAN_AMERICA.WE8MSWIN1252 |
Not sure which
NLS_LANGto use? Run this query to check your database charset:SELECT value FROM nls_database_parameters WHERE parameter = 'NLS_CHARACTERSET'Common values:
AL32UTF8→ noNLS_LANGneeded ·WE8MSWIN1252→AMERICAN_AMERICA.WE8MSWIN1252·WE8ISO8859P1→AMERICAN_AMERICA.WE8ISO8859P1
Usage with Claude
Claude Desktop
Add to your claude_desktop_config.json:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json - Linux:
~/.config/Claude/claude_desktop_config.json
{
"mcpServers": {
"oracle": {
"command": "npx",
"args": ["-y", "@vdeserto/oracle-mcp-server"],
"env": {
"ORACLE_USER": "your_user",
"ORACLE_PASSWORD": "your_password",
"ORACLE_CONNECTION_STRING": "localhost:1521/ORCL",
"NLS_LANG": "AMERICAN_AMERICA.WE8MSWIN1252"
}
}
}
}Windows: use
cmdas the command ifnpxis not found:{ "mcpServers": { "oracle": { "command": "cmd", "args": ["/c", "npx", "-y", "@vdeserto/oracle-mcp-server"], "env": { "ORACLE_USER": "your_user", "ORACLE_PASSWORD": "your_password", "ORACLE_CONNECTION_STRING": "localhost:1521/ORCL", "NLS_LANG": "AMERICAN_AMERICA.WE8MSWIN1252" } } } }
Restart Claude Desktop. The Oracle tools will appear in the tools panel.
Claude Code (CLI)
macOS / Linux:
ORACLE_USER=your_user \
ORACLE_PASSWORD=your_password \
ORACLE_CONNECTION_STRING=localhost:1521/ORCL \
npx @vdeserto/oracle-mcp-serverWindows (PowerShell):
$env:ORACLE_USER="your_user"
$env:ORACLE_PASSWORD="your_password"
$env:ORACLE_CONNECTION_STRING="localhost:1521/ORCL"
$env:NLS_LANG="AMERICAN_AMERICA.WE8MSWIN1252"
npx @vdeserto/oracle-mcp-serverWindows (Command Prompt):
set ORACLE_USER=your_user
set ORACLE_PASSWORD=your_password
set ORACLE_CONNECTION_STRING=localhost:1521/ORCL
set NLS_LANG=AMERICAN_AMERICA.WE8MSWIN1252
npx @vdeserto/oracle-mcp-serverUsage with Gemini CLI
The Gemini CLI supports MCP servers natively — no extra code required.
Add to ~/.gemini/settings.json:
{
"mcpServers": {
"oracle": {
"command": "npx",
"args": ["-y", "@vdeserto/oracle-mcp-server"],
"env": {
"ORACLE_USER": "your_user",
"ORACLE_PASSWORD": "your_password",
"ORACLE_CONNECTION_STRING": "localhost:1521/ORCL",
"NLS_LANG": "AMERICAN_AMERICA.WE8MSWIN1252"
}
}
}
}Windows: use
cmdas the command ifnpxis not found:"command": "cmd", "args": ["/c", "npx", "-y", "@vdeserto/oracle-mcp-server"]
Restart the Gemini CLI. The Oracle tools will be available automatically.
Usage with Gemini SDK (programmatic)
For embedding Oracle queries directly inside a Node.js application using the @google/generative-ai SDK.
Installation
npm install @vdeserto/oracle-mcp-server @google/generative-aiExample
import { GoogleGenerativeAI } from "@google/generative-ai";
import { getOracleTools, handleOracleToolCall } from "@vdeserto/oracle-mcp-server/gemini";
const genAI = new GoogleGenerativeAI(process.env.GEMINI_API_KEY);
const model = genAI.getGenerativeModel({
model: "gemini-1.5-pro",
tools: [{ functionDeclarations: getOracleTools() }],
});
const chat = model.startChat();
async function ask(prompt) {
let response = await chat.sendMessage(prompt);
// Handle tool calls in a loop until the model responds with text
while (response.response.functionCalls()?.length) {
const calls = response.response.functionCalls();
const results = await Promise.all(
calls.map(async (call) => ({
functionResponse: {
name: call.name,
response: await handleOracleToolCall(call.name, call.args),
},
}))
);
response = await chat.sendMessage(results);
}
return response.response.text();
}
console.log(await ask("List all tables in the HR schema"));
console.log(await ask("How many employees are in department 10?"));
console.log(await ask("Describe the EMPLOYEES table"));Environment variables
macOS / Linux:
export ORACLE_USER=your_user
export ORACLE_PASSWORD=your_password
export ORACLE_CONNECTION_STRING=localhost:1521/ORCL
export GEMINI_API_KEY=your_gemini_api_keyWindows (PowerShell):
$env:ORACLE_USER="your_user"
$env:ORACLE_PASSWORD="your_password"
$env:ORACLE_CONNECTION_STRING="localhost:1521/ORCL"
$env:GEMINI_API_KEY="your_gemini_api_key"Available Tools
All tools are read-only. Write operations are blocked at the database transaction level.
oracle_list_schemas
Lists all schemas (users) visible to the connected user.
oracle_list_tables
Lists tables in a schema with optional name filter and pagination.
| Parameter | Type | Description |
|---|---|---|
| schema | string? | Schema name (default: connected user) |
| filter | string? | Partial table name filter |
| limit | number | Max results (default: 50, max: 500) |
| offset | number | Pagination offset |
| response_format | markdown|json | Output format |
oracle_describe_table
Returns column definitions, data types, primary key, and indexes for a table.
| Parameter | Type | Description |
|---|---|---|
| table_name | string | Table name (required) |
| schema | string? | Schema/owner |
| response_format | markdown|json | Output format |
oracle_execute_query
Executes a read-only SELECT statement with optional bind parameters.
| Parameter | Type | Description |
|---|---|---|
| sql | string | SELECT statement using :1, :2, ... for parameters |
| binds | array? | Bind values in positional order |
| limit | number | Max rows (default: 50, max: 500) |
| response_format | markdown|json | Output format |
sql: "SELECT * FROM employees WHERE department_id = :1"
binds: [10]oracle_get_table_data
Retrieves rows from a table with structured filters, ordering, and pagination.
| Parameter | Type | Description |
|---|---|---|
| table_name | string | Table name (required) |
| schema | string? | Schema/owner |
| filters | array? | Structured filter conditions (see below) |
| order_by | string? | Column names with optional ASC/DESC |
| columns | array? | Columns to select (default: all) |
| limit | number | Max rows (default: 50, max: 500) |
| offset | number | Pagination offset |
| response_format | markdown|json | Output format |
Filter format:
[
{ "column": "status", "op": "=", "value": "ACTIVE" },
{ "column": "salary", "op": ">", "value": 5000 },
{ "column": "end_date", "op": "IS NULL" }
]Supported operators: = != <> < > <= >= LIKE IS NULL IS NOT NULL
Security
- Read-only enforcement:
SET TRANSACTION READ ONLYis issued on every connection — any DML attempt raisesORA-01456 - SQL injection prevention: identifiers validated against
[A-Za-z_][A-Za-z0-9_$#]; filter values always passed as bind parameters - Input normalisation: NFKC Unicode normalisation applied before all validation to block homoglyph attacks
- Dangerous keywords blocked:
INSERT,UPDATE,DELETE,MERGE,DROP,CREATE,ALTER,EXECUTE,GRANT,DBMS_*,UTL_*,HTTPURITYPE, and others - Error sanitisation: raw Oracle error messages are never forwarded to the client
- Query timeout: 30-second per-query timeout
- Pool limits: max 5 connections, 10-second queue timeout
Local Development
git clone https://github.com/your-org/oracle-mcp-server
cd oracle-mcp-server
npm install
npm run build
npm testLicense
MIT
