Simple python COM server to expose scipy integration to VBA
Deferred Imports
Why is import win32com.server.register only imported during __main__? It should be inexpensive and clean to just leave it at the top with everything else. I'd also de-namespace from win32com.server.register import UseCommandLine but that's mostly a matter of taste.
Stubbing
You ask:

vbFunc is a PyIDispatch instance but not sure what that means for typing/mypy

If PyIDispatch is an importable type, then simply
def quad(self, vbFunc: PyIDispatch, a: float, b: float) -&gt; float:

If it's not importable at all (this can happen for some libraries that are aggressively dynamic), then you basically have two options:

Declare an opaque, named NewType to make it clear to callers that this is not just &quot;anything&quot;
Do the work that the library should have done for you, and stub it yourself using a custom .pyi

Call protocols
# Callable[..., float]?

You're right to be confused, and mypy is still fairly terrible at annotating variadic callables. Here you should consider using Protocol:
class DispatchCall(typing.Protocol):
    def __call__(self, x: float, *parameters: COMCompatibleTypes) -&gt; float:
        ... # literally an ellipsis

# Later:

func: DispatchCall = vb_dispatch.Evaluate

Unpacking
Re.
return integrate.quad(func, a, b)[0]  # only return val, not uncertainty

it's worth noting that uncertainty is not the only thing quad returns; there's actually y, abserr, infodict, message and explain.
It's minor, but I typically prefer to do at least a partial unpack to make it a little more clear what's happening:
y, *_ = integrate.quad(func, a, b)

Given the tuple length I don't think I'd do this, but you can if you think it adds clarity:
y, abserr, infodict, message, explain = integrate.quad(func, a, b)