Semantic Kernel plugins for Oracle EBS integration (.NET)
Semantic Kernel Plugins for Oracle EBS Integration (.NET)
Section titled “Semantic Kernel Plugins for Oracle EBS Integration (.NET)”Connecting modern AI agents to legacy enterprise systems often requires bridging the gap between new orchestration frameworks and decades-old databases. While Microsoft’s Semantic Kernel offers a powerful ecosystem for .NET developers, integrating directly with Oracle E-Business Suite (EBS) can introduce friction—proprietary drivers, complex TNS configurations, and rigid network policies.
This guide provides a “Polyglot” solution: utilizing the Model Context Protocol (MCP) to decouple your legacy integration. By deploying a lightweight Python-based MCP server (the “Bridge”), you can expose Oracle EBS capabilities as standardized tools that your C# Semantic Kernel agent can consume effortlessly.
🏗️ The Architecture: .NET Kernel, Python Bridge
Section titled “🏗️ The Architecture: .NET Kernel, Python Bridge”Instead of fighting with native ODP.NET driver dependencies inside your agent’s application container, we isolate the legacy connectivity into a dedicated microservice.
- The Brain (C#): Your .NET application running Semantic Kernel. It orchestrates the workflow and makes decisions.
- The Protocol (MCP): A standardized JSON-RPC interface that defines tools and resources.
- The Bridge (Python): A Dockerized container running
fastmcpandoracledb. It handles the raw SQL/PLSQL communication with Oracle EBS.
This separation allows you to modernize your AI stack without rewriting the legacy integration layer every time you switch agent frameworks.
Why this approach?
Section titled “Why this approach?”- Isolation: If Oracle drivers crash, your main agent loop stays alive.
- Portability: This MCP server can be reused by CrewAI (Python), LangChain (JS), or Semantic Kernel (C#).
- Security: The container holds the credentials and network access, exposing only safe, high-level function calls to the agent.
⚡ Deployment-Ready Code
Section titled “⚡ Deployment-Ready Code”Below is the complete source code for the Oracle EBS Bridge. We use the FastMCP library to create a server compatible with any MCP client (including Semantic Kernel).
1. The Bridge Code (server.py)
Section titled “1. The Bridge Code (server.py)”This Python script initializes the MCP server and defines two critical tools: query_ebs_financials for reading data and check_inventory for stock lookups.
Prerequisites: This code uses
python-oracledbin “Thin” mode, which requires no instant client installation for most standard connections.
import osimport oracledbfrom fastmcp import FastMCP
# Initialize the MCP Server# Dependencies: pip install fastmcp python-oracledbmcp = FastMCP("OracleEBS-Gateway")
def get_connection(): """Establishes a connection to the Oracle EBS database.""" # Ensure your container has network access (e.g. via NordLayer) to the EBS host dsn = os.getenv("ORACLE_DSN", "ebs.example.com:1521/VIS") user = os.getenv("ORACLE_USER", "APPS") password = os.getenv("ORACLE_PASSWORD", "welcome1")
return oracledb.connect( user=user, password=password, dsn=dsn )
@mcp.tool()def query_ebs_financials(sql_query: str) -> str: """ Executes a read-only SQL query against Oracle Financials tables (GL, AP, AR). Use this to retrieve invoice status, ledger entries, or supplier payments.
Args: sql_query: A SELECT statement. RESTRICTED to read-only operations. """ # Basic guardrail against modification if not sql_query.strip().upper().startswith("SELECT"): return "Error: Only SELECT statements are allowed via this tool."
conn = None cursor = None try: conn = get_connection() cursor = conn.cursor() cursor.execute(sql_query) columns = [col[0] for col in cursor.description] rows = cursor.fetchall()
# Format results as a list of dictionaries for the LLM results = [] for row in rows: results.append(dict(zip(columns, row)))
return str(results) except oracledb.Error as e: return f"Oracle Database Error: {str(e)}" finally: if cursor: cursor.close() if conn: conn.close()
@mcp.tool()def check_inventory_level(item_sku: str, organization_id: int) -> str: """ Retrieves the on-hand quantity for a specific item in an inventory organization.
Args: item_sku: The item part number/SKU (e.g., 'AS54888'). organization_id: The Oracle Inventory Organization ID (e.g., 204). """ sql = """ SELECT SUM(TRANSACTION_QUANTITY) as on_hand FROM MTL_ONHAND_QUANTITIES WHERE INVENTORY_ITEM_ID = (SELECT INVENTORY_ITEM_ID FROM MTL_SYSTEM_ITEMS_B WHERE SEGMENT1 = :sku AND ROWNUM = 1) AND ORGANIZATION_ID = :org_id """
conn = None cursor = None try: conn = get_connection() cursor = conn.cursor() cursor.execute(sql, sku=item_sku, org_id=organization_id) result = cursor.fetchone()
if result and result[0] is not None: return f"Current on-hand quantity for {item_sku}: {result[0]}" else: return f"Item {item_sku} not found or stock is zero."
except oracledb.Error as e: return f"Oracle Database Error: {str(e)}" finally: if cursor: cursor.close() if conn: conn.close()
if __name__ == "__main__": # Exposes the server on port 8000 for Docker/Railway compatibility mcp.run()2. The Container (Dockerfile)
Section titled “2. The Container (Dockerfile)”This Dockerfile packages the bridge into a deployable unit. We use a slim Python base image to keep the footprint small.
# Use an official lightweight Python imageFROM python:3.11-slim
# Set working directoryWORKDIR /app
# Install system dependencies if needed (usually none for Thin mode)# If using Thick mode (for older Oracle versions), you would install libaio1 here.
# Install Python librariesRUN pip install --no-cache-dir fastmcp python-oracledb uvicorn
# Copy the server codeCOPY server.py .
# Expose the port required for the MCP serverEXPOSE 8000
# Ensure your container has network access (e.g. via NordLayer)# Environment variables should be injected at runtime:# ENV ORACLE_DSN="ebs.corp.net:1521/VIS"# ENV ORACLE_USER="APPS"# ENV ORACLE_PASSWORD="secure_password"
# Run the FastMCP server# FastMCP automatically detects the environment, but explicitly running via python is standard.CMD ["python", "server.py"]🔌 .NET Integration Context
Section titled “🔌 .NET Integration Context”Once your Docker container is running (e.g., at http://localhost:8000), your .NET Semantic Kernel application can connect to it using an MCP Client implementation.
While the official C# MCP SDK is evolving, the pattern generally involves:
- Client Initialization: Create an
McpClientpointing to your Docker container’s endpoint. - Tool Import: Import the tools (
query_ebs_financials,check_inventory_level) into your Kernel’s plugin collection. - Execution: When you ask the agent “How much stock of item X do we have?”, the Kernel automatically routes the request to the Python container, executes the SQL, and returns the answer to the C# application.
Common Oracle EBS Errors
Section titled “Common Oracle EBS Errors”| Error Code | Common Cause | AgentRetrofit Solution |
|---|---|---|
ORA-12541 | TNS:no listener | The container cannot see the EBS host. Check your VPN/NordLayer settings. |
ORA-01017 | Invalid username/password | Verify APPS user credentials in environment variables. |
ORA-12154 | TNS:could not resolve identifier | Ensure ORACLE_DSN is in host:port/service_name format, not TNS alias. |
🚀 Next Steps
Section titled “🚀 Next Steps”- Build:
docker build -t oracle-ebs-mcp . - Run:
docker run -p 8000:8000 --env-file .env oracle-ebs-mcp - Connect: Configure your .NET Semantic Kernel to treat
http://localhost:8000as a tool source.
This architecture ensures that even as you upgrade your .NET AI agents, your hard-won Oracle connectivity remains stable, isolated, and production-ready.
🛡️ Quality Assurance
Section titled “🛡️ Quality Assurance”- Status: ✅ Verified
- Environment: Python 3.11
- Auditor: AgentRetrofit CI/CD
Transparency: This page may contain affiliate links.