Neil Walker doubled twice and drove in a run while extending his hitting streak to 11 games and Joel Hanrahan worked the ninth to pick up his 23rd save.
McDonald (9-3) struck out 10 and walked none, winning his fourth straight start and lowering his sparkling ERA to 2.37.
The Pirates have won nine of 11 and are guaranteed at least a share of the NL Central lead through the All-Star break.
Ryan Vogelsong (7-4) couldn't quite match McDonald, allowing three runs and eight hits in seven innings. Ryan Theriot and Gregor Blanco had two hits apiece for the Giants, who have dropped six of eight.
NATIONALS 4, ROCKIES 1
WASHINGTON (AP) — Gio Gonzalez pitched six innings of three-hit ball to earn his 12th win and Ian Desmond homered to power Washington to the victory.
Gonzalez (12-3) won his fourth straight start to move into a tie with R.A. Dickey of the New York Mets for the major league lead in wins. Gonzalez allowed one run, walked three and struck out six.
It was the fifth victory in six games for the Nationals, who own the best record in the NL.
Colorado finished with four errors, tying a season high. Dexter Fowler had three hits for the Rockies, who have lost six of eight and totalled 14 runs in their last seven games.
Colorado starter Jeff Francis (2-2) gave up three runs and six hits in five-plus innings.
The Nationals announced during the game that Desmond will miss Tuesday's All-Star game with a left oblique strain. He has been dealing with the injury since mid-June and will use the break to rest.
CARDINALS 3, MARLINS 2
ST. LOUIS (AP) — Kyle Lohse tossed seven solid innings in 106-degree heat and Tony Cruz hit a go-ahead two-run triple to help St. Louis stop Miami's three-game winning streak.
Allen Craig had three hits and Skip Schumaker added an RBI single in the fourth for the Cardinals, who have won five of seven. All-Star David Freese was hit by a pitch twice, walked and singled to reach base safely in all four trips.
Giancarlo Stanton left in the third inning with right knee discomfort and the Marlins said he would have arthroscopic surgery on Sunday, shelving one of baseball's best young sluggers for next week's All-Star festivities in Kansas City.
Lohse (9-2) allowed two runs and three hits to improve to 3-0 with a 2.08 ERA in three starts against Miami this season. Jason Motte pitched a shaky ninth inning for his 20th save.
Carlos Zambrano (4-7) gave up three runs and seven hits in five innings for the Marlins.
ASTROS 6, BREWERS 3
HOUSTON (AP) — Scott Moore homered for the second straight day, J.D. Martinez and Jose Altuve had three hits apiece, and the Astros snapped a season-long nine-game slide.
Milwaukee starter Zack Greinke (9-3) was looking for his 10th win; instead he was gone after four pitches — ejected after spiking the ball following a close play at first base. Manager Ron Roenicke also was tossed for arguing the call and the Brewers were forced to piece together the game with six relievers.
Houston starter Wandy Rodriguez (7-6) yielded two runs and four hits in 5 1-3 innings. Brett Myers pitched a perfect ninth for his 18th save.
Jordan Schafer and Jed Lowrie collected two hits apiece and Jason Castro drove in two runs as the Astros scored more runs than they had in the last three games combined.
METS 3, CUBS 1
NEW YORK (AP) — Ike Davis homered, Jordany Valdespin hit one out for the second day in a row and Dillon Gee pitched one-run ball for eight innings to help the Mets get the win.
Gee (6-7) yielded seven hits, struck out four and walked none. Bobby Parnell allowed a leadoff double to Anthony Rizzo, but retired the final three batters for his second save, striking out Steve Clevenger on a 101 mph fastball to end it.
Jeff Samardzija (6-8) pitched seven innings for the Cubs and was charged with three runs and seven hits.
Davis hit a two-run shot to right in the third inning as the Mets won for the seventh time in 10 games.
BRAVES 6, PHILLIES 3
PHILADELPHIA (AP) — Tommy Hanson pitched effectively into the eighth, Brian McCann homered and the Braves beat the struggling Phillies.
The five-time defending NL East champions are freefalling since Chase Utley returned to the lineup, losing nine of 10. They just got Ryan Howard back on Friday night and have lost two in a row, though the former NL MVP didn't play in this loss.
Hanson (10-5) allowed three runs and six hits, striking out six in seven-plus innings. Eric O'Flaherty worked the rest of the eighth and Craig Kimbrel finished for his 24th save in 25 tries.
Phillies starter Joe Blanton (7-8) allowed six runs and nine hits in 6 1-3 innings.
DIAMONDBACKS 5, DODGERS 3
PHOENIX (AP) — Trevor Cahill pitched seven solid innings to help the Diamondbacks beat the Dodgers.
Cahill (7-7) gave up three runs and six hits and improved to 17-1 in his past 22 starts when Arizona scores three or more runs.
Trailing 2-0, Arizona scored three runs in the fifth inning. Gerardo Parra had a two-run double and then scored on Stephen Drew's sacrifice fly. The Diamondbacks added another run in the sixth on Paul Goldschmidt's sacrifice fly.
Chad Billingsley (4-9) lost his fifth straight start and hasn't won since June 10 at Seattle. He allowed four runs on six hits and struck out five in six innings.
J.J. Putz pitched the ninth for his 16th save in 19 chances.
REDS 6, PADRES 5
SAN DIEGO (AP) — Drew Stubbs and Chris Heisey homered to back Homer Bailey's solid outing, giving the Reds a win over the Padres.
The Reds, who have struggled to score runs on their 12-game road trip, used home runs to get their offence going for the second straight game.
Stubbs, who snapped an 0-for-32 hitless streak Friday night, homered in the first inning. Heisey, who drove in Cincinnati's only run in San Diego's 2-1 win Thursday night, hit a two-run shot in the seventh inning.
The Reds homered three times in Friday night's 6-0 victory. Cincinnati had hit just two homers in its six games before Friday.
Bailey (7-6) allowed a leadoff home run to Chris Denorfia on his first pitch, then settled down and surrendered only a pair of unearned runs heading into the seventh.
Clayton Richard (6-9) took the loss.