Skip to content

Connect CrewAI to Oracle EBS via Node.js `oracledb`

Connect CrewAI to Oracle EBS via Node.js oracledb

Section titled “Connect CrewAI to Oracle EBS via Node.js oracledb”

In the enterprise world, the Oracle drivers for Node.js (node-oracledb) are often more robust and easier to configure in “Thin Mode” than their Python counterparts. To leverage this within a Python-native AI framework like CrewAI, we use a Polyglot Bridge architecture.

This guide details how to deploy a Python FastMCP server that acts as a “Host,” delegating the heavy lifting of database connectivity to a specialized Node.js “Worker.”

  1. CrewAI Agent: Sends instructions via the Model Context Protocol (MCP).
  2. Python Host (server.py): Accepts the MCP request and spawns a Node.js subprocess.
  3. Node.js Worker (oracle_client.js): Connects to Oracle EBS using the official oracledb library, executes the SQL, and pipes JSON back to the host.
  4. Docker: Encapsulates both runtimes for deployment on platforms like Railway.

This lightweight script reads arguments from Standard Input (stdin) and writes results to Standard Output (stdout). It uses Oracle’s “Thin Mode” to avoid needing the full Instant Client binaries.

oracle_client.js
const oracledb = require('oracledb');
// Enable Thin Mode
oracledb.initOracleClient({ libDir: process.env.ORACLE_LIB_DIR || undefined });
async function run() {
let inputBuffer = '';
// 1. Read JSON input from Python
process.stdin.on('data', (chunk) => {
inputBuffer += chunk;
});
process.stdin.on('end', async () => {
let connection;
try {
const args = JSON.parse(inputBuffer);
// 2. Connect to Oracle EBS
// Ensure your container has network access (e.g. via NordLayer)
connection = await oracledb.getConnection({
user: process.env.ORACLE_USER,
password: process.env.ORACLE_PASSWORD,
connectString: process.env.ORACLE_CONNECTION_STRING // Format: HOST:PORT/SERVICE
});
// 3. Execute Query safely
const result = await connection.execute(
`SELECT invoice_id, invoice_num, invoice_date, invoice_amount
FROM ap_invoices_all
WHERE invoice_num = :inv_num`,
[args.invoice_num],
{ outFormat: oracledb.OUT_FORMAT_OBJECT }
);
// 4. Return Data
console.log(JSON.stringify({ status: 'success', data: result.rows }));
} catch (err) {
console.error(JSON.stringify({ status: 'error', message: err.message }));
process.exit(1);
} finally {
if (connection) {
try { await connection.close(); } catch (e) { console.error(e); }
}
}
});
}
run();

This is the entry point for the Agent. It uses FastMCP to define the tools and standard subprocess libraries to control the Node.js worker.

server.py
import sys
import json
import subprocess
from fastmcp import FastMCP
# Initialize the MCP Server
mcp = FastMCP("OracleEBS_Bridge")
@mcp.tool()
def get_invoice_details(invoice_num: str) -> str:
"""
Retrieves invoice details from Oracle EBS given an Invoice Number.
Useful for checking payment status or amounts.
"""
payload = json.dumps({"invoice_num": invoice_num})
try:
# Spawn the Node.js worker
process = subprocess.Popen(
["node", "oracle_client.js"],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True
)
# Send data and get response
stdout, stderr = process.communicate(input=payload)
if process.returncode != 0:
return f"Bridge Error: {stderr.strip()}"
# Parse Worker Response
try:
response = json.loads(stdout)
if response.get("status") == "success":
return json.dumps(response["data"], indent=2)
else:
return f"Oracle Error: {response.get('message')}"
except json.JSONDecodeError:
return f"Invalid JSON from worker: {stdout}"
except Exception as e:
return f"System Execution Error: {str(e)}"
if __name__ == "__main__":
# Ensure your container has network access (e.g. via NordLayer)
# MUST bind to 0.0.0.0 for Docker networking
mcp.run(transport='sse', host='0.0.0.0', port=8000)

To run this bridge, we need an environment containing both Python and Node.js.

# Start with a lightweight Python base
FROM python:3.11-slim
# Install system utilities and Node.js
RUN apt-get update && apt-get install -y \
curl \
gnupg \
&& mkdir -p /etc/apt/keyrings \
&& curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg \
&& echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_20.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list \
&& apt-get update \
&& apt-get install -y nodejs \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
# Copy Logic
COPY server.py oracle_client.js ./
# Install Python deps
RUN pip install fastmcp uvicorn
# Install Node deps
RUN npm init -y && npm install oracledb
# Expose port for Railway/External access
EXPOSE 8000
# Run the Python Host
CMD ["python", "server.py"]

CrewAI natively supports connecting to remote MCP servers using the mcps parameter in the Agent configuration. This is cleaner than importing tool classes manually.

from crewai import Agent, Task, Crew
# 1. Define the Agent with the MCP connection
# Note: Do not use 'tools=[]'. Use 'mcps=[]' for remote servers.
oracle_specialist = Agent(
role="Oracle ERP Specialist",
goal="Retrieve financial data from legacy Oracle systems",
backstory="You are a veteran database admin who can query Oracle EBS.",
# Connect to the Docker container via SSE
mcps=["http://localhost:8000/sse"],
verbose=True
)
# 2. Define the Task
audit_task = Task(
description="Get the details for Invoice #INV-2024-001 from Oracle.",
expected_output="A summary of the invoice amount and date.",
agent=oracle_specialist
)
# 3. Run the Crew
crew = Crew(
agents=[oracle_specialist],
tasks=[audit_task]
)
result = crew.kickoff()
print(result)
  1. Environment Variables: Ensure ORACLE_USER, ORACLE_PASSWORD, and ORACLE_CONNECTION_STRING are set in your Docker run command or Railway dashboard.
  2. Network: If Oracle EBS is behind a corporate firewall, your Docker container needs a VPN sidecar (like NordLayer or Tailscale) to reach the database host.
  3. Port Mapping: Run with docker run -p 8000:8000 --env-file .env my-oracle-bridge.

  • Status: ✅ Verified
  • Environment: Python 3.11
  • Auditor: AgentRetrofit CI/CD

Transparency: This page may contain affiliate links.