You've done well getting as far as you have!
You might not have noticed that the JSXGraph extension's `jsxgraph` function doesn't return a value with type 'html', it returns a 'jsxgraphboard' object. The jsxgraphboard constructor (available to you as Numbas.jme.types.jsxgraphboard) takes number values for the width and height, and returns an object with a `board` property. The `makeBoardPromise` function is used by `jsxgraphboard`, and expects the width and height to be specified with their units, i.e. '200px' instead of '200'.
I think the most straightforward thing is to use the `jsxgraphboard` constructor, so you don't have to replicate any of the stuff it does.
For unwrapping the `plist` dictionary, I appreciate that the behaviour around wrapping and unwrapping arguments is hard to understand. It's a bit of a mess, due to the first design ~14 years ago not really being versatile enough.
In `funcObj`, you can give `null` as the argument where the function should go, and then give a property `evaluate: function(args, scope)` in the options object. That gives you the list of arguments as JME tokens, and the evaluation scope. You could then just call `jme.unwrapValue` on the `plist` argument.
Finally, you should add 'extensions/jsxgraph/jsxgraph.js' as a dependency for your extension, so it only loads once the JSXGraph extension has loaded.
As a bit of advice for doing this development, the browser dev tools console is really helpful. By putting some console.log lines in, you can see what values look like at different points in your code, and even set break points to step through execution line by line.
I hope you don't mind that I've edited your extension with these changes.