multicloud365
  • Home
  • Cloud Architecture
    • OCI
    • GCP
    • Azure
    • AWS
    • IAC
    • Cloud Networking
    • Cloud Trends and Innovations
    • Cloud Security
    • Cloud Platforms
  • Data Management
  • DevOps and Automation
    • Tutorials and How-Tos
  • Case Studies and Industry Insights
    • AI and Machine Learning in the Cloud
No Result
View All Result
  • Home
  • Cloud Architecture
    • OCI
    • GCP
    • Azure
    • AWS
    • IAC
    • Cloud Networking
    • Cloud Trends and Innovations
    • Cloud Security
    • Cloud Platforms
  • Data Management
  • DevOps and Automation
    • Tutorials and How-Tos
  • Case Studies and Industry Insights
    • AI and Machine Learning in the Cloud
No Result
View All Result
multicloud365
No Result
View All Result

Construct an MCP to attach AI to Oracle Database w/OpenAPI

admin by admin
May 14, 2025
in OCI
0
Construct an MCP to attach AI to Oracle Database w/OpenAPI
399
SHARES
2.3k
VIEWS
Share on FacebookShare on Twitter


Mannequin Context Protocols (MCP) grew to become a factor only some months in the past, so principally a child when it comes to IT phrases, however already an adolescent in the case of all issues AI. And extra importantly, distributors are all in a rush to undertake the protocol and publish options/assist for it.

An MCP permits for a bridge between your AI assistants and your functions or providers.

So if you happen to present an MCP on your Oracle Database, then all of a sudden your Immediate buddy can all of a sudden supply data from there along with what it’s been educated on.

One path to your Oracle Database is by way of REST APIs, and the way in which to speak REST APIs is by way of the OpenAPI spec, which MCP fortunately helps.

Credit score: this put up and far of the code has been impressed and borrowed from Nafiul Khan’s put up on Medium.

In this put up, I’ll present you the way I wrote a easy MCP server that will get its record of instruments from an Oracle REST Information Providers’s OpenAPI doc, and the way I can work together with it by way of HTTP POST.

Instruments are the instructions you should use to interface along with your distant system, on this case our REST APIs.

On the left our OpenAPI spec for our REST APIs, and on the appropriate, our MCP’s record of imported instruments.

Most of this put up will likely be displaying you learn how to get your native python program working to outline these instruments and learn how to service requests for them by your AI Assistant.

Pre-requisites

python

Ensure you have python put in, a latest one. I’m utilizing 3.13.

Whereas Nafiul used the uv (docs) package deal supervisor, I’m extra comfy in VS Code, so my program and runtime atmosphere will likely be managed by VS Code.

python libraries

Bash

from contextlib import asynccontextmanager
from fastapi import FastAPI, Question
from fastapi.responses import JSONResponse
from pydantic import BaseModel
from typing import Dict, Any, Elective
import httpx

The large ones listed here are httpx and fastapi, which collectively permit us to retrieve the OpenAPI spec from ORDS, after which serve again the instruments by way of our MCP at localhost:8000/instruments.

Oracle Database, some REST APIs, and their related OpenAPI spec.

I’ll be utilizing my At all times Free Oracle Autonomous Database, the place ORDS is hosted as effectively, and my information/REST APIs are described right here.

I’ll have SECURITY disabled to make the instance simpler to comply with, however including in an OAuth2 workflow is drop useless easy in Python, and you may see how to try this, right here.

Let’s bounce in

Our MCP server goes to learn within the OpenAPI spec that ORDS providers up for every ORDS Module you might have activated. The hyperlink and it’s content material seems to be like this –

https://thecloud-oraclecloudapps.com/ords/admin/open-api-catalog/strava/
ORDS. spits out JSON model, however editor.swagger.io fortunately converts to YAML if you happen to’re in that membership.

Oracle Database REST API OpenAPI doc (served up from Oracle REST Information Providers), and serve up all of the ‘paths’ as instruments.

Paths? What Paths?

OpenAPI reveals us our templates or sources as an JSON paths object.

So we have now

  • /actions/
  • /activitities/{id}
  • /intervals/
  • /testing/

So how can we do that? With lower than 100 strains of Python!

Creating our MCP Server, and Importing the OpenAPI

We’ll begin by hardcoding the OpenAPI spec endpoint, after which we’ll use the httpx shopper to go get that useful resource, after which we’ll loop over the JSON to tug out the APIs.

I needed to fiddle a bit to provide you with cheap software names, that’s what you see on strains 19 and 21.

Python

OPENAPI_URL = "https://thecloud-oraclecloudapps.com/ords/admin/open-api-catalog/strava/"

async def fetch_openapi_spec():
    async with httpx.AsyncClient() as shopper:
        response = await shopper.get(OPENAPI_URL)
        response.raise_for_status()
        return response.json()
    
def generate_tools_from_openapi(openapi: dict[str, any]):
    paths = openapi.get("paths", {})
    for path, strategies in paths.objects():
        # Skip if strategies will not be a dictionary (e.g., an inventory)
        if not isinstance(strategies, dict):
            proceed
        for technique, particulars in strategies.objects():
            # Skip if particulars will not be a dictionary (e.g., an inventory)
            if not isinstance(particulars, dict):
                proceed
            # right here comes the tough bits - my OpenAPI spec will likely be used to take the HANDLER and add a prefix to the URI template, and we will exchange a / with a _ 
            
            operation_id = f"{technique}_strava_{path.lstrip('/').rstrip('/').exchange('/', '_')}"

            abstract = particulars.get("abstract")
            # Elective: Course of abstract if wanted, e.g., print or retailer it

            # Create a fundamental software operate with a reputation and HTTP technique
            def make_tool(p, m):
                async def tool_func(input_data):
                    headers = input_data.get("headers", {})
                    physique = input_data.get("physique", None)
                    params = input_data.get("params", None)
                    params = input_data.get("params", {})
                    formatted_path = p
                    for key, worth in params.objects():
                        formatted_path = formatted_path.exchange(f"{{{key}}}", worth)
                    url = f"https://thecloud-.oraclecloudapps.com/ords/admin/strava{formatted_path}"
                    async with httpx.AsyncClient() as shopper:
                        req = shopper.build_request(m.higher(), url, headers=headers, json=physique, params=params)
                        res = await shopper.ship(req)
                        return {"status_code": res.status_code, "physique": res.textual content}
                return tool_func

            tool_registry[operation_id] = make_tool(path, technique)

And our FastAPI code to setup our native webserver –
http:localhost:8000

Python

@asynccontextmanager
async def lifespan(app: FastAPI):
    # Startup logic
    print("Beginning up...")
    openapi = await fetch_openapi_spec()
    generate_tools_from_openapi(openapi)
    print(f"Registered instruments: {record(tool_registry.keys())}")
    yield
    print("Shutting down...")

    # Elective: Add shutdown logic right here if wanted

app = FastAPI(lifespan=lifespan)

After which our webserver wants some endpoints to reply for, let’s begin with the /instruments useful resource, which is accessed by way of a GET

Python

@app.get("/instruments")
async def list_tools():
    return JSONResponse(content material={"instruments": record(tool_registry.keys())})

You may truly begin to run the app from right here, it’s best to see one thing much like this –

And now the POST handler for the /invoke API. That is the a part of the server that handles your requests to make use of a software.

Python

@app.put up("/invoke")
async def invoke_tool(name: ToolCallInput, q: str = (Question(None))):
    tool_name = name.tool_name
    input_data = name.enter
    print(input_data)
    if q:
        intput_data["query"] = q
    print(f"Software: {tool_name}, Enter: {input_data}, Question: {q}")
    if tool_name not in tool_registry:
        return JSONResponse(status_code=404, content material={"error": "Software not discovered"})
    tool_func = tool_registry[tool_name]
    strive:
        outcome = await tool_func(input_data)
        return JSONResponse(content material={"output": outcome})
    besides Exception as e:
        return JSONResponse(status_code=500, content material={"error": str(e)})

We’ll discuss strains 2 and 6-8 in a bit.

Making an attempt it out, by way of my API software (Insomnia)

Whereas VS Code makes it straightforward to import MCPs, I’m nonetheless in debug mode, so I can work together with the MCP server immediately by way of HTTPS.

Let’s have a look at that request payload –

JSON

{
 "tool_name": "get_strava_activities",
	"enter": {
    "headers": {},
    "params": {},
    "physique": null
  }
}

“tool_name” is fairly simple, it’s the command we’re going to run, which is able to go and ask my exterior useful resource server (the Oracle Database by way of ORDS), for an inventory of actions.

For this to work, I have to create a ToolCallInput class, and that appears like this –

Python

class ToolCallInput(BaseModel):
    tool_name: str
    enter: Elective[Dict[str, Any]] = None  # Enable null or lacking

IF I had safety/auth enabled, we’d discover our entry token in that enter object.

My favourite Oracle Database REST API function is our built-in question filtering assist. (demos)

So, how do I take advantage of an AI assistant to not give me all my actions, however to seek for any exercise the place I’m speaking about working?

I’m going to be appending a question string to the tip of my REST API, however for the MCP server to try this, I’ve to inform it to deal with these.

Python

async def invoke_tool(name: ToolCallInput, q: str = (Question(None))):
...
if q:
    intput_data["query"] = q
print(f"Software: {tool_name}, Enter: {input_data}, Question: {q}")

That’s really easy, it may’t work on my first strive, can it?

So let’s use the identical software, however add the question filter (which is JSON escaped) to our POST invoke request –

JSON

{
  "tool_name": "get_strava_activities",
  "enter": {
    "params": {
      "q": "{"description":{"$instr":"row"}}"
    }
  }
}

And that appears like this –

My MCP server accepted a request from my shopper (fake it’s say, VS Code and Co-Pilot), and has went and did the work in our Oracle Database, by way of ORDS/REST.

💡 VS Code makes it straightforward so as to add your personal native MCPs.

So what does this imply?

It means I can now work together with issues in my Oracle Database by way of AI Assistants, as a result of I’ve shared instruments by way of an MCP Server that acts as a middleman between the AI and the database.

And, I’ve performed this in a short time by way of present REST APIs I’ve already revealed.

Extra fast wins embody:

  • the AI assistants (shopper) usually are not speaking on to the Oracle Database
  • the shopper goes via the mid-tier, ORDS by way of the REST APIs, which might and can have their very own layer of safety baked in – so no sharing of database credentials required!

How onerous was this?

It took me about 3-4 hours, and 70% of that point was me getting used to some new courses and libraries in Python, plus a little bit of messing round with determining learn how to assemble the request payloads and outline the courses.

I used X’s Grok AI to assist me perceive the code I used to be writing, to assist me debug some errors that didn’t make sense to me (at first), and even dumb junk like by chance importing pedantic as a substitute of pydantic!

Might I do one thing much more bold? Oh yeah, we might hook up our AI Assistant to our Database REST APIs for managing and monitoring the database itself, so you can ask for an inventory of Prime SQL statements, and even Clone a PDB!

How about including 200+ instruments? Right here’s a fast have a look at what utilizing the Database Occasion administration APIs seems to be like whenever you need to use Information Pump by way of curl/REST.

The Code

This isn’t effectively commented, however your favourite AI will fortunately describe to you in nice element, line by line, the way it works.

Python

from contextlib import asynccontextmanager
from fastapi import FastAPI, Question
from fastapi.responses import JSONResponse
from pydantic import BaseModel
from typing import Dict, Any, Elective
import httpx
app = FastAPI()

OPENAPI_URL = "https://thecloud.oraclecloudapps.com/ords/admin/open-api-catalog/strava/"

class ToolCallInput(BaseModel):
    tool_name: str
    enter: Elective[Dict[str, Any]] = None  # Enable null or lacking



async def fetch_openapi_spec():
    async with httpx.AsyncClient() as shopper:
        response = await shopper.get(OPENAPI_URL)
        response.raise_for_status()
        return response.json()
    
def generate_tools_from_openapi(openapi: dict[str, any]):
    paths = openapi.get("paths", {})
    for path, strategies in paths.objects():
        # Skip if strategies will not be a dictionary (e.g., an inventory)
        if not isinstance(strategies, dict):
            proceed
        for technique, particulars in strategies.objects():
            # Skip if particulars will not be a dictionary (e.g., an inventory)
            if not isinstance(particulars, dict):
                proceed
            '''
            operation_id = f"{technique}_{path.exchange('/', '_')}"
            '''
            operation_id = f"{technique}_strava_{path.lstrip('/').rstrip('/').exchange('/', '_')}"

            abstract = particulars.get("abstract")
            # Elective: Course of abstract if wanted, e.g., print or retailer it

            # Create a fundamental software operate with a reputation and HTTP technique
            def make_tool(p, m):
                async def tool_func(input_data):
                    headers = input_data.get("headers", {})
                    physique = input_data.get("physique", None)
                    params = input_data.get("params", None)
                    params = input_data.get("params", {})
                    formatted_path = p
                    for key, worth in params.objects():
                        formatted_path = formatted_path.exchange(f"{{{key}}}", worth)
                    url = f"https://thecloud-.oraclecloudapps.com/ords/admin/strava{formatted_path}"
                    async with httpx.AsyncClient() as shopper:
                        req = shopper.build_request(m.higher(), url, headers=headers, json=physique, params=params)
                        res = await shopper.ship(req)
                        return {"status_code": res.status_code, "physique": res.textual content}
                return tool_func

            tool_registry[operation_id] = make_tool(path, technique)

tool_registry = {}

@asynccontextmanager
async def lifespan(app: FastAPI):
    # Startup logic
    print("Beginning up...")
    openapi = await fetch_openapi_spec()
    generate_tools_from_openapi(openapi)
    print(f"Registered instruments: {record(tool_registry.keys())}")
    yield
    print("Shutting down...")

    # Elective: Add shutdown logic right here if wanted

app = FastAPI(lifespan=lifespan)

@app.get("/instruments")
async def list_tools():
    return JSONResponse(content material={"instruments": record(tool_registry.keys())})

@app.put up("/invoke")
async def invoke_tool(name: ToolCallInput, q: str = (Question(None))):
    tool_name = name.tool_name
    input_data = name.enter
    print(input_data)
    if q:
        intput_data["query"] = q
    print(f"Software: {tool_name}, Enter: {input_data}, Question: {q}")
    if tool_name not in tool_registry:
        return JSONResponse(status_code=404, content material={"error": "Software not discovered"})

    tool_func = tool_registry[tool_name]
    strive:
        outcome = await tool_func(input_data)
        return JSONResponse(content material={"output": outcome})
    besides Exception as e:
        return JSONResponse(status_code=500, content material={"error": str(e)})
Tags: BuildConnectDatabaseMCPOraclewOpenAPI
Previous Post

A Full Information to Kotlin: Overview, Use Instances

Next Post

High 7 Endodontics Firms – Verified Market Analysis

Next Post
High 7 Endodontics Firms – Verified Market Analysis

High 7 Endodontics Firms - Verified Market Analysis

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Trending

How SSL/TLS Certificates Work: Setup & Guide Renewal utilizing acme.sh

How SSL/TLS Certificates Work: Setup & Guide Renewal utilizing acme.sh

May 9, 2025
FinOps Knowledge Ingestion: A Detailed Information

FinOps Knowledge Ingestion: A Detailed Information

January 23, 2025
Steel Oxide Varistors (MOV) Market Measurement to Hit USD 38.48 Billion by 2035

Steel Oxide Varistors (MOV) Market Measurement to Hit USD 38.48 Billion by 2035

May 4, 2025
Updates to Veo, Imagen and VideoFX, plus introducing Whisk in Google Labs

Updates to Veo, Imagen and VideoFX, plus introducing Whisk in Google Labs

January 27, 2025
Skyhigh Safety Named In The 2025 Magic Quadrant For Safety Service Edge

Skyhigh Safety Named In The 2025 Magic Quadrant For Safety Service Edge

May 24, 2025
9 Open supply cloud safety instruments for 2025

9 Open supply cloud safety instruments for 2025

April 30, 2025

MultiCloud365

Welcome to MultiCloud365 — your go-to resource for all things cloud! Our mission is to empower IT professionals, developers, and businesses with the knowledge and tools to navigate the ever-evolving landscape of cloud technology.

Category

  • AI and Machine Learning in the Cloud
  • AWS
  • Azure
  • Case Studies and Industry Insights
  • Cloud Architecture
  • Cloud Networking
  • Cloud Platforms
  • Cloud Security
  • Cloud Trends and Innovations
  • Data Management
  • DevOps and Automation
  • GCP
  • IAC
  • OCI

Recent News

PowerAutomate to GITLab Pipelines | Tech Wizard

PowerAutomate to GITLab Pipelines | Tech Wizard

June 13, 2025
Runtime is the actual protection, not simply posture

Runtime is the actual protection, not simply posture

June 13, 2025
  • About Us
  • Privacy Policy
  • Disclaimer
  • Contact

© 2025- https://multicloud365.com/ - All Rights Reserved

No Result
View All Result
  • Home
  • Cloud Architecture
    • OCI
    • GCP
    • Azure
    • AWS
    • IAC
    • Cloud Networking
    • Cloud Trends and Innovations
    • Cloud Security
    • Cloud Platforms
  • Data Management
  • DevOps and Automation
    • Tutorials and How-Tos
  • Case Studies and Industry Insights
    • AI and Machine Learning in the Cloud

© 2025- https://multicloud365.com/ - All Rights Reserved