If you don't want to reinvent the wheel, ConTeXt provides Lua bindings for Metafun, so you have at least two ways to make your conversion in Lua in order to avoid issues with TeX macros:
Directly calling Lua to make a conversion
Since you're on ConTeXt, use some Lua magic instead. In order to call a Lua function directly from MetaPost, you could use the lua spelling and invoke converters.Romannumerals for uppercase and converters.romannumerals for lowercase variants (the complete list of conversions is at core-con.lua):
%Modified original so numbers don't overlap
\starttext
\startMPpage
for i=1 step 7 until 50:
label (i,(4i,0));
label (lua("mp.string(converters.romannumerals(" & decimal i & "))"),(4i,30));
endfor;
\stopMPpage
\startMPpage
for i=1 step 9 until 100:
label (i,(0,-1.5i));
label (lua("mp.string(converters.Romannumerals(" & decimal i & "))"),(30,-1.5i));
endfor;
\stopMPpage
\stoptext
First page:

Second page:

Defining Metafun functions in Lua
However, if either calling Lua turns out to be verbose and confusing or you want to use a roman definition as @Marijn did (or both), the following is possible and clearer IMHO:
\startluacode
--MP is a namespace reserved for Metafun functions
--This will be lua.MP.roman in Metafun
function MP.roman(n)
--You could use many others, but you shouldn't forget to
--send results to Metafun via mp.string or related functions.
mp.string(converters.Romannumerals(n))
end
\stopluacode
\startMPpage
vardef roman primary n =
lua.MP.roman(n)
enddef;
for i=1 step 37 until 1000:
label (i,(0,-i/3));
label (roman i,(50,-i/3));
endfor;
\stopMPpage
\stoptext

label("\convertnumber{R}{" & decimal i & "}", (x,y));as you could withlualatexbecause Context adds a lot of clever processing of the argument tolabel, so that the TeX is called on the argument apparently before the normal MP macro argument expansion takes place. This seems to me to be a bug in Context. – Thruston Jan 18 '21 at 14:40