Google's MCP Toolbox meets Oracle AI Vector Search to power agentic AI

Authors

Kiran Tailor

Matt Cornillon

Ever wish you had a personal expert to instantly navigate the complexities of any board game, video game, or obscure rulebook?

The pursuit of the perfect, uninterrupted game session often hits a wall when players stop to debate an ambiguous rule. To show how powerful and fun agentic AI can be, we introduced a playful, hypothetical organization named the “Oracle Games Division.”

This is an intelligent AI agent that acts as a personal, always-available referee expert to instantly settle disputes and keep the game moving.

This leads us to the Oracle Games Division Agent, an intelligent AI solution we demonstrated at Oracle AI World. This agent harnesses the power of Oracle Database 23ai Vector Search and MCP Toolbox for Databases.

The challenge of traditional search in gaming

For rule-based systems, traditional keyword search is often a real buzzkill. It relies on exact word matches, severely limiting the accuracy and relevance of results when dealing with nuanced descriptions like “Can a character move across a square if the space is occupied but the player has a movement ability that says ‘ignore terrain’?”

To power the Oracle Games Division Agent, we use Retrieval Augmented Generation (RAG), a technique that empowers AI to tap into vast, organized databases of information—in this case, rulebooks and product information—to provide real-time, context-specific results. In the world of gaming, this means a search experience that’s as nuanced as the rules themselves.

How agentic RAG powers rule search

Depending on the user’s question, the main system delegates the query to a specialized sub-agent. For example:

  • A question about “movement rules” goes to the Rule Expert Sub-Agent.

  • A question about “what is the price of the expansion pack?” goes to the Product Expert Sub-Agent.

This agentic architecture—built using the Google ADK (Agent Development Kit) and MCP Toolbox for Databases—ensures the most reliable answer comes from the most qualified source.

Here’s the RAG architecture that powers both sub-agents:

  • Oracle Database@Google Cloud: We’re running Oracle Database version 23ai deployed in Oracle Autonomous Database in Oracle Database@Google Cloud. This platform is crucial for its native Vector Search capabilities.

  • Vector embeddings: Game rules and product descriptions are transformed into numerical representations (vectors) using a Gemini Embedding Model. These vectors capture the meaning of the text, not just the keywords.

  • MCP access to your data: The MCP Toolbox for Databases simplifies the development of tools to query your databases directly from your agents.

  • Contextual Understanding: The Gemini Flash model adds a layer of sophistication, synthesizing the retrieved data and the user’s query to generate a precise, final, and natural language answer.

Databases, vectors, and the power of Oracle 23ai

The solution relies on the ability to efficiently store and retrieve vectors. While Google Cloud offers tools like Vertex AI Vector Search, this demonstration leverages the power of an Oracle Database 23ai to store and manage these embeddings directly alongside the operational data. This eliminates data movement and simplifies the architecture, making the solution faster and easier to deploy.

The key to the agentic structure is that we have two separate databases**,** each with its own set of embeddings:

  1. Game Rules Database: Contains rules and their embeddings.

  2. Product Info Database: Contains product details and their embeddings.

The main agent uses the query’s intent to decide which database—and thus, which sub-agent—will deliver the most accurate response.

The power of Oracle and Google Cloud

The Oracle Games Division Agent showcases a number of benefits of using Agentic RAG with Oracle Database on Google Cloud:

  • Precision and reliability: Agentic RAG ensures that the answer genuinely aligns with the rules as written in the database, minimizing ‘hallucinations.’

  • Real-time guidance: Leverage the speed of Oracle’s native Vector Search to provide instantaneous answers, keeping the game moving.

  • Contextual understanding: Players can express their questions in natural language, fostering an intuitive and engaging interaction with the AI expert.

  • Simplified architecture: Using Oracle 23ai’s native vector storage alongside the operational data simplifies the infrastructure and development process.

  • Low latency: Low latency is crucial for an “instantaneous” answer. A sub-2ms connection between Oracle and Google Cloud ensures that the time spent retrieving the vector search result from the database is negligible.

  • Seamless integration: Seamless integration with other Google Products such as BigQuery to run analytical workloads on your operational data.

By combining the power of LLMs with real-time, context-rich data stored in an OracleDatabase@GoogleCloud, this approach delivers tailored, precise guidance. The potential applications of this technology extend far beyond the realm of games. From complex system manuals and compliance documents to retail and healthcare, this AI-powered solution has the potential to revolutionize industries by providing tailored expertise on demand.


Ready to get started with Oracle Database on Google Cloud for your next-generation AI-powered applications? What other complex rule-based systems do you think an agentic AI could master?

Example scenario

Step 1: Set up your database and MCP Toolbox

First, you’ll need a database. This example uses Oracle, so you must have an Oracle database instance set up and an Oracle SQL client installed. Thereafter, follow the initial setup instructions in the MCP Toolbox documentation to set up your database and install the toolbox CLI.

Configure your tools

Create a tools.yaml file to define how the agent can interact with your rules and shopping database. This file will specify the database connection and define tools for searching and buying products.

sources:
    my-oracle-source-gamerules:
        kind: "oracle"
        tns_alias: [DATABASE_ALIAS]
        user: [USERNAME]
        password: [PASSWORD]

    my-oracle-source-shopsales:
        kind: "oracle"
        tns_alias: [DATABASE ALIAS]
        user: [USERNAME]
        password: [PASSWORD]

tools:
    query_on_gamerules:
        kind: oracle-sql
        source: my-oracle-source-gamerules
        description: Use this tool to execute queries on the games rules table
        statement: |
            SELECT
                rule_text,
                VECTOR_DISTANCE(
                    VECTOR_EMBEDDING(sys.ALL_MINILM_L6_V2 USING :1 AS data),
                    rule_vector
                ) AS similarity_score, 
                IMAGE_URL
            FROM gamerules.game_rules
            ORDER BY similarity_score
            FETCH FIRST 3 ROWS ONLY 
        parameters:
            - name: user_query
              type: string
              description: The input from the user

    search_products_in_shop_by_name:
        kind: oracle-sql
        source: my-oracle-source-shopsales
        description: Use this tool to search for items by their name
        statement: |
            SELECT ITEM_ID, ITEM_NAME, ITEM_COST, IMAGE_URL FROM GAME_PRODUCTS WHERE UP
PER(ITEM_NAME) like '%' || UPPER(:1) || '%'
        parameters:
            - name: item
              type: string
              description: The name of the item

    search_products_in_shop_by_cost:
        kind: oracle-sql
        source: my-oracle-source-shopsales
        description: Use this tool to search for items by their name
        statement: |
            SELECT ITEM_ID, ITEM_NAME, ITEM_COST, IMAGE_URL FROM GAME_PRODUCTS WHERE IT
EM_COST <= :1
        parameters:
            - name: item
              type: integer
              description: The amount max of the item cost

    get_player_orders:
        kind: oracle-sql
        source: my-oracle-source-shopsales
        description: Use this tool to get a summary of all orders for a specific player
. It returns the item name, quantity, individual item cost, total cost, and status for 
each order.
        statement: |
            SELECT
                po.order_id,
                gp.item_name,
                po.quantity,
                gp.item_cost,
                (po.quantity * gp.item_cost) AS total_cost,
                po.order_date
            FROM
                player_orders po
            JOIN
                game_products gp ON po.item_id = gp.item_id
            WHERE
                po.player_id = :1
            ORDER BY
                po.order_date DESC
        parameters:
            - name: player_id
              type: integer
              description: The unique numeric ID of the player whose orders you want to
 retrieve.

    create_player_order:
        kind: oracle-sql
        source: my-oracle-source-shopsales
        description: Use this tool to create a new order for a player. You must provide
 the player's ID, the item's ID, and the quantity they wish to purchase.
        statement: |
            INSERT INTO player_orders (
                player_id,
                item_id,
                quantity
            ) VALUES (
                :1,
                :2,
                :3
            )
        parameters:
            - name: player_id
              type: integer
              description: The unique ID of the player placing the order.
            - name: item_id
              type: integer
              description: The unique ID of the item being purchased from the game_prod
ucts table.
            - name: quantity
              type: integer
              description: The number of units of the item to order. Must be a positive
 integer.

toolsets:
    oracle_games:
        - query_on_gamerules
        - search_products_in_shop_by_name
        - search_products_in_shop_by_cost
        - create_player_order
        - get_player_orders


Step 3: Run the toolbox server

With your configuration file ready, start the MCP server from your terminal. This command points the toolbox to your definitions and starts the local service.

toolbox --tools-file “tools.yaml” –port 5001

The server will now be running and listening for requests, typically on

http://localhost:5001.

Step 4: Creating the ADK Agent

Here are our recommended installation steps. Once you verify the installation of the ADK you can continue with the rest of the steps below.

The code below defines the Agent that our final AI app (MCP Toolbox) will be wired to.

from google.adk.agents.llm_agent import Agent
from google.adk.agents import LlmAgent
from toolbox_core import ToolboxSyncClient
from google.adk.tools import agent_tool
import os

mcp_url = os.environ.get('MCP_TOOLBOX_URL', "http://localhost:5001")

toolbox = ToolboxSyncClient(mcp_url)
tools = toolbox.load_toolset('oracle_games')

# --------------------------------------------------------------------------
# 1. RULES AGENT: Using the confirmed working query structure
# --------------------------------------------------------------------------

rules_agent = LlmAgent(
    model='gemini-2.5-flash',
    name='RulesAgent',
    description='Specialized agent for retrieving game rules and board game information using semantic search.',
    instruction='''You are a rules agent. Your goal is to answer questions about game rules.
    Use the `query_on_gamerules` tool to find the relevant rule.

    ## Output Instructions
        1. Base your answer **ONLY** on the retrieved rule text.
        2. If the retrieved context includes an 'image_url' that is **not NULL**, you **MUST** inform the user that visual context was used to answer the question.
        3. You **MUST** display the image using the provided 'image_url' in your final response. Place the markdown for the image on a new line, like this:
           `![Image](image_url)`
        4. **Always provide a clear, user-friendly response, NOT the raw SQL results or the query/function call itself.**

    The current user profile is:
        - First name: [YOURNAME]
        - Last name: [SURNAME
        - ID: 59
    ''',
    tools=tools,
)

# --------------------------------------------------------------------------
# 2. SHOP SALES AGENT: Using the confirmed 'product_name, price' structure
# --------------------------------------------------------------------------

shopsales_agent = LlmAgent(
    model='gemini-2.5-flash',
    name='ShopSalesAgent',
    description='Agent for providing product information, prices, and sales.',
    instruction='''You are a shop sales agent. Your goal is to sell items.
    If the user wants to buy something, use the `search_products_in_shop_by_name` or `search_products_in_shop_by_cost` tools to find the item.
    Then, ask for confirmation.
    If the user confirms, use the `create_player_order` tool.

     ## Output Instructions
        You **MUST** display the image using the provided 'image_url' in your final response. Place the markdown for the image on a new line, like this:
           `![Image](image_url)`

    The current user profile is:
        - First name: [YOURNAME]
        - Last name: [SURNAME
        - ID: 59
    ''',
    tools=tools,
)

# --------------------------------------------------------------------------
# 3. ROOT AGENT: Orchestrator
# --------------------------------------------------------------------------
root_agent = LlmAgent(
    model='gemini-2.5-flash',
    name='quest_for_ascendancy',
    description='A helpful assistant for answering game rules and tracking game scores for the board game "Quest for Ascendancy".',
    instruction='''You are the main assistant for the board game 'Quest for Ascendancy'. Your primary function is to route user queries to the correct specialized agent, but you can also handle simple greetings yourself.

    ## Routing Rules
        - If the user asks about game rules and instructions, **delegate to the 'RulesAgent'**.
        - If the user asks about products, buying items, prices, or "what can I buy", **delegate to the 'ShopSalesAgent'**.
        - If the user says "hello" or a similar greeting, respond with a simple and nice greeting, mentioning the user first name.

    For anything else, use your best judgment to delegate to the most appropriate agent.

    ## Output Handling
    When you receive a response from a sub-agent, you **MUST** output the sub-agent's response exactly as you received it, without any modifications, additions, or summarizations. Pass the entire, raw output directly to the user.

    The current user profile is:
        - First name: [YOURNAME]
        - Last name: [SURNAME
        - ID: 59
    ''',
    sub_agents=[rules_agent, shopsales_agent]
)


Check out the following resources:

1 Like