Moving the character's pivot forward by 5 studs only moves in one direction, even if you turn the character

I don’t actually think that it mattered if it was a serverscript for updating the position, but this should really be done entirely on the client. Theres no reason to handle this on the server, as the client is perfectly capable of repositioning the character with humanoidRootPart or Torso.

The problem is that its hard to replicate whats happening on the server side of the tool onto the client.

Not really. Its actually much better to handle tools on the client. Heres an example of a very simple localscript that does this just fine:

local lplr = game:GetService("Players").LocalPlayer
task.wait(0.1)
local tool = script.Parent
local sound = script.Sound

local speed = 10

tool.Activated:Connect(function()
	if lplr.Character == nil then
		return
	end
	local hrp = lplr.Character:FindFirstChild("HumanoidRootPart")
	if hrp == nil then
		return
	end
	sound.Playing = true
	while sound.IsPlaying do
		task.wait(0.5)
		hrp.CFrame = CFrame.new(hrp.Position, hrp.Position + hrp.CFrame.LookVector) * CFrame.new(Vector3.new(0,0,-1) * speed)
	end
end)

I can’t transfer a 200 line server script to a local script.

Not all of your script needs to be a localscript. Just handling the player using the tool needs to be done on the client and detected by the server with remotes. I still would handle the player movement on the client even though it might work with remotes on the server. Of course it’s entirely up to you if you feel like converting the handling to the client; don’t do it if you don’t feel up to it. I think I have given a perfectly fine solution though, so you can mark my answer as the solution and close this topic or keep waiting for a new solution. Regardless of your choice, I wish you a good rest of your day/evening.