Skip to main content
Glama
ElvinCooper

oracle-mcp-server

by ElvinCooper

oracle-mcp-server

CI License: MIT

Repositorio: github.com/ElvinCooper/oracle-mcp-server

Oracle Database MCP Server: servidor MCP (Model Context Protocol) en Python que permite a agentes de IA y clientes compatibles con MCP interactuar con bases Oracle Database a través de python-oracledb.

A Python-based Model Context Protocol (MCP) server that enables AI coding agents and MCP-compatible clients to interact with Oracle Database environments through python-oracledb.

Usa python-oracledb en modo thick con Oracle Instant Client, con soporte orientado a entornos Oracle antiguos, incluido Oracle 11g (el modo thin del driver solo soporta Oracle 12.1+; las versiones posteriores dependen del soporte del propio driver). Ver Notas sobre Oracle 11g y modo thick.

Soporta múltiples conexiones a Oracle y funciona con cualquier cliente MCP: opencode, Claude Code, Cursor, Codex, Continue.dev, etc.

⚡ Quick Start (puesta en marcha rápida)

# 1. Clonar o copiar el proyecto
cd C:\ruta\oracle-mcp-server

# 2. Ejecutar setup (crea .venv, instala dependencias, copia .env)
.\setup.ps1

# 3. Editar .env con tus credenciales Oracle
notepad .env

# 4. Iniciar el servidor
.\.venv\Scripts\oracle-mcp

Si ves Pools Oracle listos en la salida, ya está funcionando.

Requisitos: Python 3.10+ y Oracle Instant Client instalado.


Related MCP server: Mini Oracle MCP Server

Tools expuestas

Tool

Descripción

list_tables

Lista tablas de un schema (o del usuario actual)

describe_table

Devuelve columnas, tipo de dato, nulabilidad, longitud

run_query

Ejecuta un SELECT de solo lectura, con límite de filas

execute_statement

Ejecuta INSERT/UPDATE/DELETE/DDL, deshabilitado por defecto

list_connections

Lista todas las conexiones a Oracle disponibles

Parámetro connection: Todas las tools anteriores (excepto list_connections) aceptan un parámetro opcional connection para especificar a qué base de datos conectar. Si no se especifica, usa la primera conexión de la lista (conexión por defecto).

Parámetros adicionales:

  • list_tables(schema, connection): schema es el owner en mayúsculas (ej. VENTAS); si se omite, lista las tablas del usuario actual.

  • describe_table(table_name, schema, connection): schema indica el owner si la tabla pertenece a otro usuario.

  • run_query(sql, max_rows, connection): max_rows limita las filas devueltas en la llamada (por defecto usa el _MAX_ROWS de la conexión). El resultado incluye row_count, truncated (si quedaron filas sin devolver) y limit_applied.

Seguridad

Operaciones de lectura (read-only)

run_query está diseñada para operaciones de lectura y valida cada consulta: exige que la sentencia comience con SELECT o WITH y rechaza múltiples sentencias separadas por ;, bloqueando por diseño intentos de inyección con sentencias de escritura encadenadas.

Operaciones de escritura (write operations)

execute_statement ejecuta INSERT/UPDATE/DELETE/DDL y está bloqueada por defecto. Habilitarla requiere dos condiciones explícitas:

  1. Configuración: ORACLE_CONN_<NOMBRE>_ALLOW_WRITE=true (o ORACLE_ALLOW_WRITE=true en modo legacy), definida por conexión.

  2. Llamada: pasar confirm=true en cada invocación.

El permiso se configura de forma explícita y auditable en cada conexión, y además se confirma en cada uso (un doble seguro). Habilitar operaciones de escritura debe ser una decisión consciente: por defecto todas las conexiones son de solo lectura y se recomienda conservar ALLOW_WRITE=false salvo que una conexión específica realmente lo requiera.

Credenciales

Las credenciales viven en variables de entorno (o en el archivo .env), nunca hardcodeadas en el código, y en este documento se muestran únicamente placeholders de ejemplo (your_user, your_password).

1. Requisitos previos

  • Python 3.10+

  • Oracle Instant Client ya instalado (dijiste que ya lo tienes disponible). Necesitas la ruta del directorio con libclntsh.so (Linux/Mac) o oci.dll (Windows), por ejemplo /opt/oracle/instantclient_11_2.

  • Acceso de red al listener de Oracle (host:puerto) y un SID o service_name.

2. Instalación

La instalación se realiza con el script .\setup.ps1 (Windows), que crea el .venv, instala las dependencias y copia .env desde .env.example.

Automática (Windows)

cd C:\ruta\oracle-mcp-server
.\setup.ps1

Manual (Windows / Linux / Mac)

cd oracle-mcp-server
python3 -m venv .venv
source .venv/bin/activate        # Linux/Mac
# .venv\Scripts\activate         # Windows
pip install -e .

Nota de versiones: el proyecto usa la API de MCP 1.x (mcp.server.fastmcp). Tanto pyproject.toml como requirements.txt fijan mcp>=1.6.0,<2 para evitar que una instalación resuelva mcp 2.x (que eliminó esa API). Si en tu entorno aparece mcp 2.x, reinstala con el pin: pip install -e ".[dev]" (o pip install "mcp>=1.6.0,<2").

3. Configuración

Opción A: Múltiples conexiones (Recomendado)

Copia .env.example a .env y completa tus datos:

cp .env.example .env

Formato para múltiples conexiones:

# Lista de conexiones (nombres separados por comas)
ORACLE_CONNECTIONS=facturacion,clinica

# Conexion "facturacion"
ORACLE_CONN_FACTURACION_USER=your_user
ORACLE_CONN_FACTURACION_PASSWORD=your_password
ORACLE_CONN_FACTURACION_HOST=your_oracle_host
ORACLE_CONN_FACTURACION_PORT=1521
ORACLE_CONN_FACTURACION_SID=ORCL
ORACLE_CONN_FACTURACION_CLIENT_LIB_DIR=/opt/oracle/instantclient_11_2
ORACLE_CONN_FACTURACION_ALLOW_WRITE=false
ORACLE_CONN_FACTURACION_MAX_ROWS=200

# Conexion "clinica"
ORACLE_CONN_CLINICA_USER=your_user
ORACLE_CONN_CLINICA_PASSWORD=your_password
ORACLE_CONN_CLINICA_HOST=your_oracle_host
ORACLE_CONN_CLINICA_PORT=1521
ORACLE_CONN_CLINICA_SID=ORCL
ORACLE_CONN_CLINICA_CLIENT_LIB_DIR=/opt/oracle/instantclient_11_2

Opción B: Una sola conexión (Legacy - Retrocompatible)

Si ORACLE_CONNECTIONS no está definido, el servidor busca variables legacy:

ORACLE_USER=your_user
ORACLE_PASSWORD=your_password
ORACLE_HOST=your_oracle_host
ORACLE_PORT=1521
ORACLE_SID=ORCL
ORACLE_CLIENT_LIB_DIR=/opt/oracle/instantclient_11_2
ORACLE_ALLOW_WRITE=false
ORACLE_MAX_ROWS=200

Variables por conexión

Variable

Descripción

Default

ORACLE_CONN_<NOMBRE>_USER

Usuario de Oracle

(requerido)

ORACLE_CONN_<NOMBRE>_PASSWORD

Contraseña

(requerido)

ORACLE_CONN_<NOMBRE>_HOST

Host del servidor

(requerido)

ORACLE_CONN_<NOMBRE>_PORT

Puerto

1521

ORACLE_CONN_<NOMBRE>_SID

SID de Oracle

-

ORACLE_CONN_<NOMBRE>_SERVICE_NAME

Service name

-

ORACLE_CONN_<NOMBRE>_CLIENT_LIB_DIR

Ruta al Instant Client

-

ORACLE_CONN_<NOMBRE>_ALLOW_WRITE

Habilitar escritura

false

ORACLE_CONN_<NOMBRE>_MAX_ROWS

Límite de filas por query

200

ORACLE_CONN_<NOMBRE>_CONNECT_TIMEOUT

Timeout conexión (seg)

10

ORACLE_CONN_<NOMBRE>_POOL_MIN

Mínimo conexiones en pool

1

ORACLE_CONN_<NOMBRE>_POOL_MAX

Máximo conexiones en pool

4

Convención de Nombres de Variables

Regla de oro: El nombre de la conexión en ORACLE_CONNECTIONS define los nombres de todas las variables de entorno asociadas.

Paso

Ejemplo

Nombre en ORACLE_CONNECTIONS

afp_pruebas

Convertir a MAYÚSCULAS

AFP_PRUEBAS

Agregar prefijo

ORACLE_CONN_AFP_PRUEBAS

Agregar sufijo

ORACLE_CONN_AFP_PRUEBAS_USER

ORACLE_CONNECTIONS: "facturacion,afp_pruebas"
        ↓                          ↓
"facturacion"               "afp_pruebas"
        ↓                          ↓
ORACLE_CONN_FACTURACION_*   ORACLE_CONN_AFP_PRUEBAS_*

Convención Recomendada para Nombres

Para mantener consistencia y facilitar el mantenimiento:

Tipo de Base

Ejemplo de Nombre

Variable

Producción

produccion

ORACLE_CONN_PRODUCCION_*

Desarrollo

desarrollo

ORACLE_CONN_DESARROLLO_*

Pruebas

pruebas

ORACLE_CONN_PRUEBAS_*

Por área funcional

facturacion

ORACLE_CONN_FACTURACION_*

Recomendaciones:

  • Usar snake_case (minúsculas con guión bajo): mi_conexion

  • Sin espacios: afp_pruebas en lugar de AFP Pruebas

  • Nombres descriptivos: que indiquen el propósito de la conexión

  • Evitar caracteres especiales: solo letras, números y guión bajo

Fuentes de Variables de Entorno

Las variables pueden provenir de múltiples fuentes (por orden de prioridad):

  1. Variables ya definidas en el entorno del proceso (incluye el bloque environment de opencode.jsonc) (mayor prioridad)

  2. Variables del sistema Windows (persistente)

  3. Archivo .env (cargado por python-dotenv desde la raíz del proyecto)

Recomendación: usa una sola fuente de verdad. La opción recomendada es mantener todas las conexiones en el .env (archivo en .gitignore, sin credenciales en opencode.jsonc). Para agregar una conexión, añade su nombre a ORACLE_CONNECTIONS y define sus variables ORACLE_CONN_<NOMBRE>_* en el mismo archivo.

Tolerancia a configuraciones incompletas: si una conexión en ORACLE_CONNECTIONS no tiene sus variables obligatorias (ORACLE_CONN_<NOMBRE>_USER, _PASSWORD, _HOST) o tiene valores inválidos (p. ej. puerto no numérico), el servidor la omite al arrancar, registra un warning en consola con el nombre y el motivo, y continúa con las conexiones válidas. Solo si ninguna conexión es válida, el servidor se detiene con un error.

Credenciales fuera del .env (variables del sistema)

Si prefieres no guardar credenciales en texto plano dentro del .env, puedes definir el usuario y la contraseña como variables de entorno del sistema. Es totalmente opcional: si no defines estas variables, el servidor usa las del .env como siempre.

Importante: el proceso debe arrancar después de crear la variable. Reinicia la terminal y el cliente MCP para que hereden el nuevo entorno.

Opción A — Variable del sistema con el mismo nombre (recomendada):

El nombre de la variable debe coincidir con el de la conexión (ORACLE_CONN_<NOMBRE>_USER / ORACLE_CONN_<NOMBRE>_PASSWORD). Estas variables tienen prioridad sobre las del .env (python-dotenv no sobrescribe variables ya definidas), por lo que se pueden combinar: los secretos en el sistema y el resto de la configuración en el .env. Ejemplo para la conexión facturacion:

# Windows (scope "User": solo tu usuario de Windows)
[Environment]::SetEnvironmentVariable("ORACLE_CONN_FACTURACION_USER", "your_user", "User")
[Environment]::SetEnvironmentVariable("ORACLE_CONN_FACTURACION_PASSWORD", "your_password", "User")
# Linux / Mac (agrega a ~/.bashrc o ~/.zshrc y recarga: source ~/.bashrc)
export ORACLE_CONN_FACTURACION_USER="your_user"
export ORACLE_CONN_FACTURACION_PASSWORD="your_password"

Opción B — Referencia desde el .env (nombre libre):

Puedes usar un nombre de variable propio en el sistema y referenciarlo desde el .env con ${VAR}:

ORACLE_CONN_FACTURACION_USER=${ORACLE_FACTURACION_USER}
ORACLE_CONN_FACTURACION_PASSWORD=${ORACLE_FACTURACION_PASSWORD}

Los valores de ORACLE_FACTURACION_USER / ORACLE_FACTURACION_PASSWORD se definen como variables del sistema. Si la variable referenciada no existe, python-dotenv la deja vacía y el servidor falla con Faltan variables obligatorias, indicando cuál falta.

Verificar que la variable quedó definida:

[Environment]::GetEnvironmentVariable("ORACLE_CONN_FACTURACION_PASSWORD", "User")
echo $ORACLE_CONN_FACTURACION_PASSWORD

También puedes usar los scripts set-secrets.ps1 (Windows) y set-secrets.sh (Linux/Mac) incluidos en el proyecto para fijar usuario y contraseña de forma interactiva.

4. Pruebas

La suite usa pytest y no necesita Oracle: test_server.py sustituye los pool/cursor de la base por dobles en memoria.

pip install -e ".[dev]"   # instala pytest y las dependencias de desarrollo
pytest                    # o: python -m pytest

Son 114 tests que cubren: carga legacy y multi-conexión, omisión de conexiones incompletas (tolerancia), DSN por SID / SERVICE_NAME, validación solo-SELECT y doble confirmación de escritura (ALLOW_WRITE + confirm), serialización de LOBs y las 5 tools del servidor (conexión por defecto, max_rows y truncado incluidos).

En CI (GitHub Actions) la suite corre en Python 3.10–3.12 y un segundo job verifica que el paquete se construye con python -m build.

5. Probarlo de forma independiente

Puedes levantar el servidor manualmente para verificar que conecta:

source .venv/bin/activate        # Linux/Mac
# .venv\Scripts\activate         # Windows
python -m oracle_mcp.server

O usando el entry point directo (disponible después de pip install -e .):

oracle-mcp                       # si el venv está activo
# o desde la ruta absoluta:
.venv/Scripts/oracle-mcp         # Windows
.venv/bin/oracle-mcp             # Linux/Mac

Si ves en el log Pools Oracle listos: N seguido de Conexiones Oracle disponibles: N con la lista de conexiones, la conexión en thick mode funcionó. El proceso queda esperando mensajes MCP por stdio (Ctrl+C para salir).

6. Integración con clientes MCP

El servidor se comunica por STDIO (estándar en MCP para procesos locales). Cada cliente MCP tiene su propia configuración; aquí están las más comunes.

Importante: Usa siempre la ruta absoluta al Python del .venv (así el cliente no depende de que el venv esté activado).

opencode

Define el servidor en el bloque mcp de opencode.json (o ~/.config/opencode/opencode.jsonc):

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "oracle": {
      "type": "local",
      "command": [
        "C:/ruta/completa/oracle-mcp-server/.venv/Scripts/python",
        "-m",
        "oracle_mcp.server"
      ],
      "enabled": true,
      "environment": {
        "ORACLE_CONNECTIONS": "facturacion,clinica",
        "ORACLE_CONN_FACTURACION_USER": "your_user",
        "ORACLE_CONN_FACTURACION_PASSWORD": "your_password",
        "ORACLE_CONN_FACTURACION_HOST": "your_oracle_host",
        "ORACLE_CONN_FACTURACION_PORT": "1521",
        "ORACLE_CONN_FACTURACION_SID": "ORCL",
        "ORACLE_CONN_FACTURACION_CLIENT_LIB_DIR": "C:/oracle/instantclient_11_2",
        "ORACLE_CONN_CLINICA_USER": "your_user",
        "ORACLE_CONN_CLINICA_PASSWORD": "your_password",
        "ORACLE_CONN_CLINICA_HOST": "your_oracle_host",
        "ORACLE_CONN_CLINICA_PORT": "1521",
        "ORACLE_CONN_CLINICA_SID": "ORCL",
        "ORACLE_CONN_CLINICA_CLIENT_LIB_DIR": "C:/oracle/instantclient_11_2"
      }
    }
  }
}

Un archivo de ejemplo (opencode.json.example) está incluido en el proyecto.

Nota de seguridad: el bloque environment de arriba incluye credenciales solo con fines de ejemplo. La opción recomendada es omitir environment y definir todas las conexiones en el archivo .env (ver sección 3).

Claude Code

Agrega el servidor en .claude.json (en la raíz del proyecto o global en %USERPROFILE%\.claude\):

{
  "mcpServers": {
    "oracle": {
      "type": "local",
      "command": "C:\\ruta\\oracle-mcp-server\\.venv\\Scripts\\python",
      "args": ["-m", "oracle_mcp.server"],
      "env": {
        "ORACLE_CONNECTIONS": "facturacion",
        "ORACLE_CONN_FACTURACION_USER": "your_user",
        "ORACLE_CONN_FACTURACION_PASSWORD": "your_password",
        "ORACLE_CONN_FACTURACION_HOST": "your_oracle_host",
        "ORACLE_CONN_FACTURACION_PORT": "1521",
        "ORACLE_CONN_FACTURACION_SID": "ORCL",
        "ORACLE_CONN_FACTURACION_CLIENT_LIB_DIR": "C:\\oracle\\instantclient_11_2"
      }
    }
  }
}

Cursor

En ./cursor/mcp.json del proyecto:

{
  "mcpServers": {
    "oracle": {
      "type": "local",
      "command": "C:\\ruta\\oracle-mcp-server\\.venv\\Scripts\\python",
      "args": ["-m", "oracle_mcp.server"],
      "env": {
        "ORACLE_CONNECTIONS": "facturacion",
        "ORACLE_CONN_FACTURACION_USER": "your_user",
        "ORACLE_CONN_FACTURACION_PASSWORD": "your_password",
        "ORACLE_CONN_FACTURACION_HOST": "your_oracle_host",
        "ORACLE_CONN_FACTURACION_PORT": "1521",
        "ORACLE_CONN_FACTURACION_SID": "ORCL",
        "ORACLE_CONN_FACTURACION_CLIENT_LIB_DIR": "C:\\oracle\\instantclient_11_2"
      }
    }
  }
}

Otros clientes MCP

Cualquier cliente que soporte servidores MCP tipo local/stdio puede usar la misma configuración base:

Campo

Valor

command

C:\ruta\oracle-mcp-server\.venv\Scripts\python

args

["-m", "oracle_mcp.server"]

env

Tus variables ORACLE_CONN_* (o ninguna si usas .env)

Nota: Si usas .env para las credenciales, el servidor las cargará automáticamente desde la raíz del proyecto, sin importar el directorio desde el que se arranque el proceso.

Puntos importantes

  • Usa la ruta absoluta al Python del .venv

  • Reinicia/recarga el cliente MCP después de editar la configuración

  • Puedes verificar que el servidor responde con el comando de prueba de la sección 5

7. Uso de múltiples conexiones

Una vez configuradas las conexiones, puedes usarlas en las tools:

# Usar conexión por defecto (primera de la lista)
list_tables()

# Usar conexión específica
list_tables(connection="clinica")

# Query en conexión específica
run_query("SELECT * FROM pacientes", connection="clinica")

# Ver conexiones disponibles
list_connections()

8. Notas sobre Oracle 11g y modo thick

  • oracledb.init_oracle_client(lib_dir=...) se llama una sola vez, antes de abrir cualquier conexión (lo hace db.py automáticamente al arrancar el servidor). Usa el client_lib_dir de la primera conexión que lo tenga definido.

  • Si se te olvida configurar CLIENT_LIB_DIR y el Instant Client no está en el PATH/LD_LIBRARY_PATH, oracledb lanzará un error indicando que no encuentra las librerías cliente.

  • 11g casi siempre se conecta por SID, no por service_name; por eso el DSN se construye con oracledb.makedsn(host, port, sid=...) cuando defines SID.

  • Si tu 11g tiene un Oracle Wallet o requiere TNS_ADMIN, puedes exportar TNS_ADMIN en environment dentro de opencode.json y ajustar db.py para usar dsn directamente por alias TNS en vez de makedsn.

9. Estructura del proyecto

oracle-mcp-server/
├── LICENSE
├── README.md
├── pyproject.toml
├── requirements.txt
├── setup.ps1      # Script de instalación automática (Windows)
├── .env.example
├── opencode.json.example
├── .github/
│   └── workflows/
│       └── ci.yml       # CI: tests (Python 3.10–3.12) y build del paquete
├── src/
│   └── oracle_mcp/
│       ├── __init__.py
│       ├── config.py     # Carga de variables de entorno (multi-conexión)
│       ├── db.py          # Init thick mode, multipools, validación SELECT-only
│       └── server.py      # Servidor MCP (FastMCP) con tools multi-conexión
└── tests/
    ├── helpers.py      # make_connection() con valores por defecto
    ├── conftest.py     # limpia variables ORACLE_*/OX_* entre tests
    ├── test_config.py  # carga de configuración legacy y multi-conexión
    ├── test_db.py      # thick mode, validación, serialización de LOBs
    └── test_server.py  # tools MCP con pools ficticios

10. Solución de Problemas

Problema

Causa Común

Solución

Conexión 'xxx' no encontrada

Nombre no coincide

Verificar que ORACLE_CONNECTIONS coincida con las variables

Faltan variables obligatorias

Variable no definida

Verificar nombre de la variable en Windows o .env

Usuario/Password incorrecto

Credenciales erróneas

Verificar valores con [Environment]::GetEnvironmentVariable("ORACLE_CONN_FACTURACION_USER", "User")

Pool no disponible

Conexión no inicializó

Revisar logs del servidor al iniciar

ORA-12541: TNS:no listener

Oracle no accessible

Verificar HOST, PORT y que el listener esté activo

ORA-12154: TNS:could not resolve connect identifier

SID/SERVICE_NAME incorrecto

Verificar ORACLE_SID o ORACLE_SERVICE_NAME

11. Próximos pasos sugeridos

  • Agregar paginación real (cursor/offset) en run_query si necesitas recorrer resultados grandes en varias llamadas.

  • Si vas a exponer execute_statement en un entorno compartido, considera agregar un ALLOWED_TABLES o un usuario Oracle con permisos acotados (grant solo sobre las tablas necesarias) en vez de confiar únicamente en la validación de la tool.

12. Licencia

Este proyecto está bajo la licencia MIT (ver LICENSE). Copyright (c) 2026 Elvin Cooper.

Related MCP Connectors

Related MCP Servers

  • A
    license
    B
    quality
    D
    maintenance
    Enables interaction with Oracle databases through MCP by executing SELECT queries, describing table structures, and listing available tables with secure, read-only access.
    3
    12 npm
    2
    MIT
  • F
    license
    Not graded
    quality
    C
    maintenance
    A read-only MCP server for Oracle databases that enables SQL queries, schema inspection, and data sampling without requiring OCI client libraries. It supports both TNS alias and direct connection modes with robust security guardrails.
    -
  • F
    license
    Not graded
    quality
    C
    maintenance
    Enables read-only querying and schema inspection of Oracle Database 10g through MCP tools or a Claude Code skill, with SELECT/WITH enforcement, row limits, timeouts, and audit logging.
    -