TCP Bridge Send
The one that actually fires
- sent_payload_json
- bytes_sent
- summary_json
Finally, a node in this network family that does something. MKRTCPBridgeSend is the runtime half of the TCP pair: you feed it a plan built by MKRTCPBridgePlan, it opens a real socket, pushes your payload out, and reports exactly how many bytes it sent. This is the part of the MKRShift transport layer that transmits - the plan nodes describe, this one dials.
The mechanism is refreshingly simple and worth knowing because it explains the failure modes. It reads host, port, and framing out of the tcp_plan_json you pass in, serializes your payload to UTF-8 JSON, then frames it: json_line appends a \n, length_prefixed prepends a big-endian 32-bit length header, raw_json sends the bare bytes. Then it opens a connection with socket.create_connection and sends the whole thing. That's it - a plain blocking send with a 10-second timeout.
What you feed it
- tcp_plan_json (required) - the plan from
MKRTCPBridgePlan. You could hand-craft this JSON by hand, but there's no reason to. - payload_json (optional) - override the message body at send time. Leave it out and it sends whatever was baked into the plan.
What you get back
sent_payload_json (what actually went out), bytes_sent (an INT - genuinely useful for sanity-checking that a zero-length message isn't silently doing nothing), and summary_json.
Installing it
It's in criskb/MKRShift_Nodes from Cris K B. ComfyUI Manager search "MKRShift_Nodes", or:
cd ComfyUI/custom_nodes
git clone https://github.com/criskb/MKRShift_Nodes
Restart ComfyUI. No pip requirements, no models - just the Python socket module, which is part of the standard library.
The gotchas
First: this is a one-shot send, not a streaming bridge. If your receiver needs a sustained connection or an ack loop, this isn't that node. Second, the timeout is ten seconds - if nothing is listening on the port, the node will block for up to that long before erroring, so a dead receiver makes the graph look hung. Third, make sure the receiver is actually running before you hit queue, because a refused connection shows up as a node error and kills the whole run. And remember the framing rule from the plan side: newline vs. length-prefixed must match what the listener parses, or you'll see bytes_sent look healthy while the other app reads garbage.
Inputs (2)
| Name | Type | Default | Description |
|---|---|---|---|
| tcp_plan_json | STRING | {} | — |
| payload_jsonopt | STRING | {} | — |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| sent_payload_json | STRING | — |
| bytes_sent | INT | — |
| summary_json | STRING | — |