Solve a first step with a steady state calculation to determine the OP (MV) and PV values.
from gekko import GEKKO
import numpy as np
import matplotlib.pyplot as plt
# Process model
Kp = 0.5 # process gain
tauP = 10.0 # process time constant
# pre-solve for steady state values
m = GEKKO()
OP = m.Var(value=0.0) # controller output (MV)
PV = m.Var(value=0.0) # process variable
SP = m.Param(value=5.0) # final set point
m.Equation(SP==PV) # assume PV reaches set point
m.Equation(tauP*PV.dt() + PV == Kp*OP)
m.options.IMODE = 1
m.solve(disp=False)
print('Steady state target values')
print('OP: ' + str(OP.value[0]))
print('PV: ' + str(PV.value[0]))
print('SP: ' + str(SP.value[0]))
PV_ss = PV.value[0]
OP_ss = OP.value[0]
Solve a second step to optimize the tuning parameters to stay under the requested overshoot targets. Overshoot is typically defined in terms of the distance above the setpoint, not the amount over the MV target. Both are included in the example.

# dynamic optimization of controller tuning
m = GEKKO()
tf = 40
m.time = np.linspace(0,tf,2*tf+1)
step = np.zeros(2*tf+1)
step[3:40] = 0.0
step[40:] = 5.0
# Controller model
Kc = m.FV(15.0,lb=0,ub=100) # controller gain
tauI = m.FV(100.0,lb=0.01,ub=100) # controller reset time
tauD = m.FV(0.0,lb=0,ub=100) # derivative constant
Kc.STATUS = 1; tauI.STATUS = 1; tauD.STATUS = 1
OP_0 = m.Const(value=0.0) # OP bias
OP = m.Var(value=0.0,ub=OP_ss*1.1) # controller output
# with overshoot bound on OP (MV)
PV = m.Var(value=0.0,ub=PV_ss*1.1) # process variable
# with overshoot bound on PV
SP = m.Param(value=step) # set point
Intgl = m.Var(value=0.0) # integral of the error
err = m.Intermediate(SP-PV) # set point error
m.Equation(Intgl.dt()==err) # integral of the error
m.Equation(OP == OP_0 + Kc*err + (Kc/tauI)*Intgl - PV.dt())
m.Equation(tauP*PV.dt() + PV == Kp*OP)
m.Minimize((SP-PV)**2)
m.options.IMODE=6
m.solve(disp=False)
print('Tuning values')
print('Kc: ' + str(Kc.value[0]))
print('tauI: ' + str(tauI.value[0]))
print('tauD: ' + str(tauD.value[0]))
plt.figure()
plt.subplot(2,1,1)
plt.plot([0,max(m.time)],[1.1*OP_ss,1.1*OP_ss],\
'b-',label='Upper bound')
plt.plot(m.time,OP.value,'b:',label='OP')
plt.ylabel('Output')
plt.legend()
plt.subplot(2,1,2)
plt.plot(m.time,SP.value,'k-',label='SP')
plt.plot(m.time,PV.value,'r--',label='PV')
plt.plot([0,max(m.time)],[1.1*PV_ss,1.1*PV_ss],\
'b-',label='Upper bound')
plt.xlabel('Time (sec)')
plt.ylabel('Process')
plt.legend()
plt.show()