diff --git a/hgext/largefiles/proto.py b/hgext/largefiles/proto.py
--- a/hgext/largefiles/proto.py
+++ b/hgext/largefiles/proto.py
@@ -168,12 +168,13 @@
     caps.append('largefiles=serve')
     return caps
 
-def heads(repo, proto):
+def heads(orig, repo, proto):
     '''Wrap server command - largefile capable clients will know to call
     lheads instead'''
     if lfutil.islfilesrepo(repo):
         return wireprototypes.ooberror(LARGEFILES_REQUIRED_MSG)
-    return wireproto.heads(repo, proto)
+
+    return orig(repo, proto)
 
 def sshrepocallstream(self, cmd, **args):
     if cmd == 'heads' and self.capable('largefiles'):
diff --git a/hgext/largefiles/uisetup.py b/hgext/largefiles/uisetup.py
--- a/hgext/largefiles/uisetup.py
+++ b/hgext/largefiles/uisetup.py
@@ -174,7 +174,7 @@
         wireproto.heads)
 
     # ... and wrap some existing ones
-    wireproto.commands['heads'].func = proto.heads
+    extensions.wrapfunction(wireproto.commands['heads'], 'func', proto.heads)
     # TODO also wrap wireproto.commandsv2 once heads is implemented there.
 
     extensions.wrapfunction(webcommands, 'decodepath', overrides.decodepath)