Just 2 quick points...
1) Because of the order of operations, the math contained in the IF tag will need to be done prior to APILogic evaluating the conditional. That can be with an inline roll:
{& if [[20 - @{CharacterName|MP}]] < 0}
...or it can be done with a MathOps tag:
{& if {&math 20 - @{CharacterName|MP} } < 0}
Both will work, but you can't leave the math for APILogic to perform; it doesn't recognize that's what you want it to do.
2) If you want the NON-ChatSetAttr side to hit chat (in other words, you want to see the warning that "you don't have enough MP" in chat), you have to include a {&simple} in that case (the true case of the conditional). All of the text between the {&if...} and the {&else} (as well as the {&else} and the {&end} ) will be kept or filtered out depending on the evaluation of the conditional check. So if the TRUE case is kept, you want the {&simple} tag to be in the resulting command line (instructing the mod to dump the message out to chat). If the FALSE case is kept, then {&simple} tag will be eaten, and the message will continue to ChatSetAttr to be evaluated.
Altogether, that would make Jarren's example more like:
!{& if [[20 - @(CharacterName|MP)]] < 0}/w "CharacterName" You don't have enough Magic Points!{&simple} {&else}setattr --name CharacterName --MP|-20 {&end}
Note: in this case, because of the order of operations, you should be able to use *either* the Roll20 formation of:
@{CharacterName|MP}
...OR the Fetch (metascript) construction of:
@(CharacterName|MP)
Both should resolve in time.