The only solution I came up with here was to use the TypeFile class:
TypedFile tarTypeFile = new TypedFile("application/tar", myFile);
and the interface (without explicitly setting the Content-Type header this time):
@POST("/build")
Response build(@Query("t") String tag,
               @Query("q") boolean quiet,
               @Query("nocache") boolean nocache,
               @Body TypedInput inputStream);
Using my own implementation of TypedInput resulted in a vague EOF exception even while I provided the length(). 
public class TarArchive implements TypedInput {
    private File file;
    public TarArchive(File file) {
        this.file = file;
    }
    public String mimeType() {
        return "application/tar";
    }
    public long length() {
        return this.file.length();
    }
    public InputStream in() throws IOException {
        return new FileInputStream(this.file);
    }
}
Also, while troubleshooting this issue I tried using the latest Apache Http client instead of OkHttp which resulted in a "Content-Length header already present" error even though I wasn't explicitly setting that header.