The Royals tightened the American League wild-card race with the win, pulling within a half game of the Indians, who started the day 1 1/2 games out of the playoff picture.
Shields (11-9) allowed a pair of singles in the first inning but didn't give up another hit until Jason Kipnis and Carlos Santana opened the ninth with base hits. Shields was lifted at that point, having given up one walk and striking out seven.
Kansas City closer Greg Holland struck out all three batters he faced in earning his 42nd save.
The only Cleveland batters to get on base between the first and ninth innings did so a Shields' error in the third and his walk in the sixth.
Alex Gordon hit his 19th home run of the season on the first pitch of the game from Scott Kazmir (8-8). Emilio Bonifacio followed with a triple and scored on Eric Hosmer's single into center. After two outs, Justin Maxwell and Lorenzo Cain had singles that drove in Hosmer for a 3-0 Royals lead.
The Indians got two of the runs back in their first at-bat when Michael Bourn hit Shields' second pitch for a single and Shields hit Mike Aviles with a pitch. Bourn and Aviles scored on Michael Brantley's one-out single.
Kazmir, who lasted four innings, giving up nine hits and four runs, allowed singles by Bonifacio and Hosmer in the fifth and Bonifacio scored on a double play. Gordon scored on an error in the seventh and Mike Moustakas singled in Cain in the eighth to make the score 6-2.