Kendrys Morales homered and recorded his sixth straight multi-hit game to lead the Royals.
Kansas City won for the fourth time in five games and took the two-city, four-game series three games to one.
Moss and Jhonny Peralta homered for the Cardinals, who are 25-15 on the road.
Wade Davis recorded his 19th save in 21 opportunities.
Morales, a designated hitter playing right field for the second straight night, doubled in the sixth inning off Mike Leake (5-6) to push the lead to 3-1. Morales, who went 3 for 4, has 16 hits in 24 at-bats over the six-game run. He went 12 for 16 in the series and started in the outfield for the first time since 2008.
Since going 1 for 15 in a four-game set with Cleveland on June 2-5, Morales has been on fire. He was hitting .191 on June 5 but has gone 32 of 69 since to push his average to .262.
"I felt like before, I was making good contact," Morales said. "It was just a combination of bad luck that played into it as well."
His six-game multi-hit streak ties him for the longest this season along with J.D. Martinez (Detroit), Jackie Bradley Jr. (Boston) and Xander Bogaerts (Boston).
Morales is 25 of 53 (.472) lifetime against the Cardinals with five homers and 13 RBIs. His 456-foot drive in the eighth inning off Tyler Lyons ties him for the longest home run by a visiting player at Busch Stadium III, which opened in 2006.
Kansas City reliever Dillon Gee (3-2) picked up the win, allowing one run in two innings.
Moss ripped his 17th homer of the season off Royals starter Chris Young, who gave up one run and one hit over four innings but walked six.
The drive, which went 477 feet according to the Cardinals, is the longest in the history of Busch Stadium. It is the second-longest this season behind Giancarlo Stanton’s 490-foot blast for Miami on May 6, in a 6-4 win over Philadelphia.
"I hit it hard," Moss said. "I know I’m strong and I know how far I can hit it when I get a hold of one."
Leake gave up three runs, two earned, in seven innings. He struck out four and walked one.
"There were a couple of pitches I’d like to take back," Leake said.
Kansas City pushed across an unearned run in the first before Jarrod Dyson doubled in Alcides Escobar in the second.
Gee’s victory gives the Royals’ bullpen a 16-5 (.762) mark, the highest percentage in the majors. His lone mistake came to Peralta in the sixth inning.
"I’m just glad I was able to do the job," Gee said. "I felt good."
Cardinals manager Mike Matheny was ejected in the sixth inning by home plate umpire Mike Everitt. It was Matheny’s first ejection of the season and 12th in four-plus season as a manager. Matheny appeared upset after the Royals called for a replay on a play at first base. The original call was changed and overturned in the Royals favor.
Royals: RHP Kris Medlen gave up five earned runs in 5 2/3 innings of a rehab start for Triple-A Omaha on Thursday against Memphis. Medlen, who was placed on the DL with right rotator cuff inflammation on May 11, gave up six hits. He struck out five and walked two in a 5-2 loss.
Cardinals: OF Stephen Piscotty was given the night off after he tweaked his left ankle in the 12th inning of Wednesday’s 3-2 loss. He is listed as day-to-day.
INF Aledmys Diaz was held out of the lineup for the third straight game. He fouled a pitch off the area around his right eye on Monday.
Cardinals: LHP Jaime Garcia (5-6, 4.09) takes on Milwaukee RHP Matt Garza (1-0, 2.81) in the opener a three-game series in St. Louis on Friday. Garcia is 10-5 with 2.71 ERA in 19 appearances against the Brewers.