Skip to main content
Glama
smith-nathanh

Oracle MCP Server

execute_query

Execute SQL queries against Oracle databases using SELECT, DESCRIBE, or EXPLAIN PLAN statements for data retrieval and analysis.

Instructions

Execute a SQL query against the Oracle database. Only SELECT, DESCRIBE, and EXPLAIN PLAN statements are allowed for safety.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
sqlYesSQL query to execute (SELECT, DESCRIBE, or EXPLAIN PLAN only)
paramsNoOptional parameters for parameterized queries

Implementation Reference

  • Core handler that executes the SQL query: performs safety checks (blocks DML/DDL), adds automatic ROWNUM row limits for SELECTs, executes via oracledb.Connection, handles Oracle-specific types (LOBs, dates), and returns structured JSON results.
    async def execute_query( self, sql: str, params: Optional[List] = None ) -> Dict[str, Any]: """Execute a SQL query with safety controls""" # Basic SQL injection prevention sql_upper = sql.upper().strip() # Check for potentially dangerous operations dangerous_keywords = [ "DROP", "DELETE", "TRUNCATE", "ALTER", "CREATE", "INSERT", "UPDATE", ] # Allow SELECT, DESCRIBE, EXPLAIN PLAN if not any( sql_upper.startswith(keyword) for keyword in ["SELECT", "WITH", "DESCRIBE", "DESC", "EXPLAIN"] ): if any(keyword in sql_upper for keyword in dangerous_keywords): raise ValueError( "Only SELECT, DESCRIBE, and EXPLAIN PLAN statements are allowed" ) conn = await self.connection_manager.get_connection() try: cursor = conn.cursor() # Set row limit if ( "SELECT" in sql_upper and "ROWNUM" not in sql_upper and "LIMIT" not in sql_upper ): # Add ROWNUM limitation for SELECT queries if "ORDER BY" in sql_upper: # More complex query, wrap it sql = f"SELECT * FROM ({sql}) WHERE ROWNUM <= {QUERY_LIMIT_SIZE}" else: # Simple query, add WHERE clause if "WHERE" in sql_upper: sql += f" AND ROWNUM <= {QUERY_LIMIT_SIZE}" else: sql += f" WHERE ROWNUM <= {QUERY_LIMIT_SIZE}" start_time = datetime.now() if params: cursor.execute(sql, params) else: cursor.execute(sql) execution_time = (datetime.now() - start_time).total_seconds() # Fetch results if cursor.description: columns = [desc[0] for desc in cursor.description] rows = cursor.fetchall() # Convert Oracle types to JSON-serializable types serializable_rows = [] for row in rows: serializable_row = [] for value in row: if hasattr(value, "read"): # LOB object serializable_row.append(str(value.read())) elif isinstance(value, datetime): serializable_row.append(value.isoformat()) else: serializable_row.append(value) serializable_rows.append(serializable_row) return { "columns": columns, "rows": serializable_rows, "row_count": len(rows), "execution_time_seconds": execution_time, "query": sql, } else: return { "message": "Query executed successfully", "execution_time_seconds": execution_time, "query": sql, } finally: conn.close()
  • Registers the execute_query tool in the MCP server's list_tools() handler, defining its metadata and input schema.
    Tool( name="execute_query", description="Execute a SQL query against the Oracle database. Only SELECT, DESCRIBE, and EXPLAIN PLAN statements are allowed for safety.", inputSchema={ "type": "object", "properties": { "sql": { "type": "string", "description": "SQL query to execute (SELECT, DESCRIBE, or EXPLAIN PLAN only)", }, "params": { "type": "array", "items": {"type": "string"}, "description": "Optional parameters for parameterized queries", "default": [], }, }, "required": ["sql"], }, ),
  • JSON schema defining inputs for execute_query: required 'sql' string, optional 'params' array of strings.
    inputSchema={ "type": "object", "properties": { "sql": { "type": "string", "description": "SQL query to execute (SELECT, DESCRIBE, or EXPLAIN PLAN only)", }, "params": { "type": "array", "items": {"type": "string"}, "description": "Optional parameters for parameterized queries", "default": [], }, }, "required": ["sql"], },
  • Dispatch handler in MCP call_tool(): extracts 'sql' and 'params' from arguments, invokes QueryExecutor.execute_query, serializes result as TextContent.
    if name == "execute_query": sql = arguments.get("sql") params = arguments.get("params", []) result = await self.executor.execute_query(sql, params) return [ TextContent( type="text", text=json.dumps(result, indent=2, default=str) ) ]

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/smith-nathanh/oracle-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server