Mike Moustakas cut down Tyler Greene at the plate to end the game, capping a wild ninth inning and preserving the Kansas City Royals' 3-2 victory over the St. Louis Cardinals on Friday night.

Greene reached on a two-out infield hit for his third single of the game, stole second and advanced on catcher Bryan Pena's wild throw. He tried to score on another off-line throw by second baseman Chris Getz, but third baseman Moustakas made a strong throw to nip Greene at home.

The crazy finish came after Yadier Molina eased up on what he believed was an infield hit to start the St. Louis ninth. The catcher belatedly sped up after Alcides Escobar's diving stop, and the shortstop made a strong throw to first as Molina banged his helmet with his hands.

Vin Mazzaro worked six scoreless innings and Jeff Francoeur had two RBIs for Kansas City, which matched its longest winning streak of the season with its fourth consecutive victory. Jarrod Dyson added two hits, a walk and an RBI.

Jonathan Broxton worked the ninth for his 16th save in 18 chances and No. 100 for his career.

The Royals also won four straight from May 12-15 at the Chicago White Sox and Texas.

Carlos Beltran had two hits and stole his 300th base in the second, becoming the first switch hitter in major league history with 300 home runs and 300 steals. Beltran then was caught stealing third by Mazzaro's pickoff throw during the next at-bat.

The Royals trail the Interstate 70 rivalry 38-29, but are 14-14 in St. Louis.

The Cardinals' Kyle Lohse (6-2) scattered 10 hits in seven innings, giving up three runs. Lohse has worked at least five innings in all but two of his 20 career starts against the Royals.

Mazzaro (3-1) blanked the opposition through six innings for the second time in three starts, needing just 80 pitches while keeping the Cardinals off balance. Matt Holliday was an easy out all three times after entering the game 4 for 5 with a homer and three RBIs against the 25-year-old right-hander.

Mazzaro was briefly visited by a trainer in his last inning, but no reason was given for his exit. He gave up four runs, three earned, in three-plus innings in a loss at Pittsburgh in his previous start.

Alcides Escobar doubled with two outs in the second and scored on Dyson's infield hit, and Alex Gordon doubled leading off the third and scored on Francoeur's single.

Francoeur added a sacrifice fly in the seventh as the Royals built a 3-0 lead.

Matt Adams had an RBI double and pinch-hitter Shane Robinson delivered a run-scoring single as the Cardinals jumped on Roman Colon in the bottom half to pull within one.

Colon, recalled from Triple-A Omaha on Thursday to bolster an overworked bullpen, made his first major league appearance since 2010 when he made the opening-day roster and appeared in just five games.

Dyson has three hits the last two games since ending an 0-for-13 slump.

NOTES: Royals manager Ned Yost said he would platoon Eric Hosmer and Billy Butler, the regular DH, at 1B in interleague games at NL parks. ... Cardinals SS and leadoff man Rafael Furcal, mired in a 1-for-24 slump, got a day off. "I don't think it's necessarily anything mechanical, it's just physically he's beat," manager Mike Matheny said. ... Cardinals second-round pick Carson Kelly, a high school 3B from Beaverton, Ore., signed and betrayed no sense of awe in an impressive round of batting practice, with Matheny and batting coach Mark McGwire watching from beyond the cage. Matheny joked that the usual over-under on draftees is no balls hit out of the cage the first time around. "Most kids want to come up here and just start launching," Matheny said, "and they walk out with their head hanging low." ... Kansas City's Alex Gordon has scored in eight straight games after entering the game the only player in the majors with a pair of seven-game streaks with a run scored, according to STATS LLC.