Agreed (modulo they aren't in R6RS).  There are two possibilities: accepting both a read! and a write! argument (MIT-ish), and accepting an input and an output custom port and returning a bidirectional port (Chicken).  I'm inclined to go for the first.

I should have been clearer in my earlier email. I was referring to §8.2.13 of the R6RS Library document. While I would not be keen on open-file-input/output-port, make-custom-{binary,texual}-input/output-port would be an acceptable API (modulo flushing).
MIT actually accepts an arbitrary number of callbacks in an a-list, and has a function to call any custom operation.  That is perfectly general, but bperhaps too general for utility.

Philosophical note: I don't mind `too general' provided that (a) it is obvious (for an appropriate value of `obvious') how to accommodate common use cases; (b) you don't pay for what you don't want; and (c) it doesn't kick off a round of bikeshedding. 

-- vincent