Skip to main content
Glama
ElvinCooper

oracle-mcp-server

by ElvinCooper

oracle-mcp-server

Servidor MCP (Model Context Protocol) en Python para conectar a Oracle 11g usando python-oracledb en modo thick (obligatorio en 11g, ya que el modo thin del driver solo soporta Oracle 12.1+). Pensado para usarse desde opencode u otro cliente MCP compatible con servidores locales (stdio).

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 por diseño

  • Por defecto solo lectura: run_query valida que la sentencia empiece con SELECT/WITH y rechaza múltiples sentencias separadas por ;.

  • execute_statement está bloqueada salvo que definas ORACLE_CONN_<NOMBRE>_ALLOW_WRITE=true (o ORACLE_ALLOW_WRITE=true en el modo legacy) en el entorno y pases confirm=true en la llamada (doble seguro).

  • Las credenciales viven en variables de entorno, nunca hardcodeadas.

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 .

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=mi_usuario
ORACLE_CONN_FACTURACION_PASSWORD=mi_password
ORACLE_CONN_FACTURACION_HOST=192.168.1.10
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=clinica_user
ORACLE_CONN_CLINICA_PASSWORD=clinica_pass
ORACLE_CONN_CLINICA_HOST=192.168.1.20
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=mi_usuario
ORACLE_PASSWORD=mi_password
ORACLE_HOST=192.168.1.10
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", "mi_usuario", "User")
[Environment]::SetEnvironmentVariable("ORACLE_CONN_FACTURACION_PASSWORD", "mi_password", "User")
# Linux / Mac (agrega a ~/.bashrc o ~/.zshrc y recarga: source ~/.bashrc)
export ORACLE_CONN_FACTURACION_USER="mi_usuario"
export ORACLE_CONN_FACTURACION_PASSWORD="mi_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. 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).

5. 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": "mi_usuario",
        "ORACLE_CONN_FACTURACION_PASSWORD": "mi_password",
        "ORACLE_CONN_FACTURACION_HOST": "192.168.1.10",
        "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": "clinica_user",
        "ORACLE_CONN_CLINICA_PASSWORD": "clinica_pass",
        "ORACLE_CONN_CLINICA_HOST": "192.168.1.20",
        "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": "mi_usuario",
        "ORACLE_CONN_FACTURACION_PASSWORD": "mi_password",
        "ORACLE_CONN_FACTURACION_HOST": "192.168.1.10",
        "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": "mi_usuario",
        "ORACLE_CONN_FACTURACION_PASSWORD": "mi_password",
        "ORACLE_CONN_FACTURACION_HOST": "192.168.1.10",
        "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 4

6. 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()

7. 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.

8. Estructura del proyecto

oracle-mcp-server/
├── pyproject.toml
├── setup.ps1      # Script de instalación automática (Windows)
├── .env.example
├── opencode.json.example
├── README.md
└── 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

9. 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

10. 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.

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
    7 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.
    -