Watch all the best , with the Tour de France, Tour de France Femmes and much more.
It was a hair-raising finish, with the late-arriving Marco Frigo (Israel-PremierTech) nearly pulling off the upset, but McNulty had the composure and the power to take the victory.
Stage 8 winner Ben Healy (EF Education-EasyPost) was forced to settle for second. Frigo, who launched a final attack from behind in the closing metres of the stage, rounded out the podium in third.
McNulty was part of the day's main breakaway which built a maximum gap of seven minutes over the peloton in the 195-kilometre stage from Seregno to Bergamo. As the group was whittled down, McNulty played his cards well to find himself alone out the front with Healy and Frigo for company.
McNulty was dropped by Healy with 34 kilometres remaining, but fought back to rejoin the Irishman, and then responded to all the attacks thrown at him by Healy. He stayed patient when it mattered most and timed his sprint to perfection on the downhill road to the finish line.
“It’s an indescribable feeling," said the 24-year-old from the United States of America.
"It was my big goal coming here to take a stage. On the last climb I went on the attack but Ben Healy countered it hard and I thought my race was done.
"I managed to fight back and in the end it came down to the last kick and the sprint and I just went for it.
"We came here for GC and the goal of me going for a stage win. So now it’s in the bag we can fully focus on the GC," McNulty said.
Bruno Armirail (Groupama-FDJ) conceded 33 seconds in the General Classification but savoured every moment of his day in the pink leader's jersey.
“I got a lot of encouragement," Armirail said. “Yesterday I had not realized. Today I did. It’s only when I got on the bike that I realised that only pink mattered. It gave me goosebumps.
"During the stage, I even had goosebumps looking at the work my teammates were doing, because it is usually [what] I do for them. I was moved on the bike. I thought: 'They ride for me, it’s amazing.' I don’t think I will experience that often in my career. It was crazy stuff.”
Armirail holds the overall lead by one minute and eight seconds ahead of Geraint Thomas (INEOS Grenadiers). Primož Roglič sits two seconds further back in third overall.
The peloton now has a rest day to prepare for a high-mountain stage from Bra to Rivoli (179km) on Tuesday.
After a rest day tonight (AEST) the Giro d'Italia heads into the high mountains on Tuesday for stage 16. Watch the action live from 6.40pm (AEST) on SBS On Demand and from 9.30pm (AEST) on SBS VICELAND.