This is a hack, but it does the trick. The problem is that you can't use TriangulateMesh on a 2D polygon embedded in 3D. One solution is to translate/rotate your polygon to the xy plane, triangulate, then reverse the transformation.
triangulate3DPolygon[Polygon[pts__], opts : OptionsPattern[]] := Module[ {a, b, c, U, V, W, tr, trpgon, newpts, newpgns}, (*The rotation matrix - http://math.stackexchange.com/a/856705 *) {a, b, c} = pts[[;; 3]]; tr = a; {a, b, c} = # - a & /@ {a, b, c}; {U, W} = {Normalize[b], Normalize[Cross[b, c]]}; V = Cross[U, W]; {U, V, W}.(# - tr) & /@ pts; trpgon = TriangulateMesh[ DiscretizeGraphics[ Polygon[Most /@ ({U, V, W}.(# - tr) & /@ pts)]], opts ]; newpts = (Transpose[{U, V, W}].PadRight[#, 3] + tr) & /@ MeshCoordinates[trpgon]; newpgns = MeshCells[trpgon, 2]; {newpts, newpgns} ]; Options[triangulate2DMeshEmb3D] = {"OutputType" -> "MeshRegion"}; triangulate2DMeshEmb3D[mesh_,opts : OptionsPattern[ {MeshRegion, TriangulateMesh, Graphics3D, triangulate2DMeshEmb3D}] ] :=Module[ {pgons, data, extracount, bag, pgonPrimitives, head, pts}, pgons = MeshPrimitives[mesh, 2]; data = triangulate3DPolygon[#, Evaluate@FilterRules[{opts}, Options[TriangulateMesh]]] & /@ pgons; extracount = 0; bag = Internal`Bag[]; pgonPrimitives = {}; Do[ pgonPrimitives = Join[ pgonPrimitives, data[[n, 2]] /. Polygon[a__] :> Polygon[a + extracount] ]; Do[ extracount++; Internal`StuffBag[bag, pt], {pt, data[[n, 1]]} ]; , {n, Length@data} ]; head = Switch[OptionValue["OutputType"], "MeshRegion", MeshRegion, "Graphics3D", Graphics3D@*GraphicsComplex]; pts = Internal`BagPart[bag, All]; Clear[bag]; head[pts, pgonPrimitives, Evaluate[FilterRules[{opts}, Options[head]]]] ];
If you don't tell MeshRegion to color the lines in black, then you might think it didn't work,

But you can see that it does work, and the triangulation is customizable,
triangulate2DMeshEmb3D[ msh, MeshCellStyle -> {1 -> Black}, MaxCellMeasure -> #] & /@ {.2, .01} Through[{RegionEmbeddingDimension, RegionDimension}[First@%]]
