Define SQL-based MCP tools using YAML configuration
The Oracle Database MCP Toolkit’s custom tool framework lets you create MCP tools declaratively using YAML, without writing Java code. Each tool executes a SQL statement and can accept parameters from the LLM.
tools: orders-by-status: description: Get orders by status parameters: - name: status type: string description: Order status (PENDING, SHIPPED, DELIVERED) required: true statement: SELECT * FROM orders WHERE status = :status
tools: orders-by-date-range: description: Get orders within a date range parameters: - name: start_date type: string description: Start date (YYYY-MM-DD) required: true - name: end_date type: string description: End date (YYYY-MM-DD) required: true statement: | SELECT * FROM orders WHERE order_date >= TO_DATE(:start_date, 'YYYY-MM-DD') AND order_date <= TO_DATE(:end_date, 'YYYY-MM-DD') ORDER BY order_date DESC
tools: search-products: description: Search products by name and optional category parameters: - name: product_name type: string description: Product name to search for required: true - name: category type: string description: Optional category filter required: false statement: | SELECT * FROM products WHERE name LIKE '%' || :product_name || '%' AND (:category IS NULL OR category = :category)
dataSources: hotel-db: url: jdbc:oracle:thin:@hotels.example.com:1521/HOTELS user: ${HOTEL_DB_USER} password: ${HOTEL_DB_PASSWORD}tools: hotels-by-name: dataSource: hotel-db description: Returns hotel details by name including capacity, rating and address parameters: - name: name type: string description: Hotel name to search for (partial match supported) required: false statement: SELECT * FROM hotels WHERE name LIKE '%' || :name || '%' hotels-by-city: dataSource: hotel-db description: Find hotels in a specific city parameters: - name: city type: string description: City name required: true - name: min_rating type: number description: Minimum rating (1-5) required: false statement: | SELECT name, address, rating, capacity FROM hotels WHERE city = :city AND (:min_rating IS NULL OR rating >= :min_rating) ORDER BY rating DESC available-rooms: dataSource: hotel-db description: Check room availability for a hotel on specific dates parameters: - name: hotel_id type: number description: Hotel ID required: true - name: check_in type: string description: Check-in date (YYYY-MM-DD) required: true - name: check_out type: string description: Check-out date (YYYY-MM-DD) required: true statement: | SELECT room_type, COUNT(*) as available_rooms FROM rooms r WHERE r.hotel_id = :hotel_id AND r.id NOT IN ( SELECT room_id FROM bookings WHERE hotel_id = :hotel_id AND check_out > TO_DATE(:check_in, 'YYYY-MM-DD') AND check_in < TO_DATE(:check_out, 'YYYY-MM-DD') ) GROUP BY room_type
dataSources: ecommerce-db: url: jdbc:oracle:thin:@shop.example.com:1521/SHOP user: shop_app password: ${SHOP_PASSWORD}tools: customer-orders: dataSource: ecommerce-db description: Get all orders for a customer by email address parameters: - name: email type: string description: Customer email address required: true statement: | SELECT o.id, o.order_date, o.total, o.status, o.tracking_number FROM orders o JOIN customers c ON o.customer_id = c.id WHERE c.email = :email ORDER BY o.order_date DESC product-search: dataSource: ecommerce-db description: Search products by name and optional filters parameters: - name: search_term type: string description: Product name or description keywords required: true - name: category type: string description: Product category filter required: false - name: max_price type: number description: Maximum price filter required: false statement: | SELECT id, name, description, price, category, stock_quantity FROM products WHERE (name LIKE '%' || :search_term || '%' OR description LIKE '%' || :search_term || '%') AND (:category IS NULL OR category = :category) AND (:max_price IS NULL OR price <= :max_price) AND stock_quantity > 0 ORDER BY price ASC order-status: dataSource: ecommerce-db description: Check order status by order ID parameters: - name: order_id type: number description: Order ID required: true statement: | SELECT o.id, o.status, o.order_date, o.total, o.tracking_number, c.name as customer_name, c.email as customer_email, COUNT(oi.id) as item_count FROM orders o JOIN customers c ON o.customer_id = c.id LEFT JOIN order_items oi ON o.id = oi.order_id WHERE o.id = :order_id GROUP BY o.id, o.status, o.order_date, o.total, o.tracking_number, c.name, c.email
dataSources: prod-db: url: jdbc:oracle:thin:@prod.example.com:1521/PROD user: prod_reader password: ${PROD_PASSWORD} analytics-db: url: jdbc:oracle:thin:@analytics.example.com:1521/ANALYTICS user: analyst password: ${ANALYTICS_PASSWORD}tools: daily-sales-summary: dataSource: analytics-db description: Get daily sales summary from analytics warehouse parameters: - name: date type: string description: Date in YYYY-MM-DD format required: true statement: | SELECT date, total_orders, total_revenue, avg_order_value, new_customers FROM daily_sales_summary WHERE date = TO_DATE(:date, 'YYYY-MM-DD') real-time-inventory: dataSource: prod-db description: Get real-time inventory levels from production database parameters: - name: product_id type: number description: Product ID required: true statement: | SELECT p.id, p.name, i.quantity, i.last_updated, w.name as warehouse_name FROM products p JOIN inventory i ON p.id = i.product_id JOIN warehouses w ON i.warehouse_id = w.id WHERE p.id = :product_id
Once configured, use natural language to invoke your tools:
"Find hotels named 'Grand' in the database""Get all orders for customer [email protected]""Search for products matching 'wireless headphones' under $100""Check order status for order ID 12345""Show me daily sales summary for 2024-03-15"
The LLM will:
Select the appropriate tool based on your request
Extract parameters from your natural language input
# Good: Clear, parameterized, with limitstools: recent-orders: description: Get the 10 most recent orders for a customer parameters: - name: customer_id type: number required: true statement: | SELECT id, order_date, total, status FROM orders WHERE customer_id = :customer_id ORDER BY order_date DESC FETCH FIRST 10 ROWS ONLY# Avoid: No limits, unclear purposetools: get-stuff: description: Gets stuff statement: SELECT * FROM orders -- Returns all rows!