1: <?php
2:
3: declare(strict_types=1);
4:
5: /**
6: * This file is part of the Nexus MCP SDK package.
7: *
8: * (c) 2026 John Paul E. Balandan, CPA <paulbalandan@gmail.com>
9: *
10: * For the full copyright and license information, please view
11: * the LICENSE file that was distributed with this source code.
12: */
13:
14: namespace Nexus\Mcp\Core\Transport;
15:
16: use Nexus\Mcp\Core\Exception\TransportAlreadyClosedException;
17: use Nexus\Mcp\Core\Exception\TransportAlreadyStartedException;
18: use Nexus\Mcp\Core\Exception\TransportNotStartedException;
19: use Nexus\Mcp\Core\Schema\JsonRpc\JsonRpcMessage;
20:
21: /**
22: * Bidirectional JSON-RPC envelope duplex between this SDK and a connected peer.
23: *
24: * - Listeners fire in registration order.
25: * - A throw aborts the chain.
26: * - A dispose mid-dispatch applies on the next emit.
27: */
28: interface TransportInterface
29: {
30: /**
31: * Begins consuming inbound envelopes from the peer. Returns immediately.
32: *
33: * @throws TransportAlreadyStartedException
34: * @throws TransportAlreadyClosedException
35: */
36: public function start(): void;
37:
38: /**
39: * Enqueues an outbound JSON-RPC message to the peer.
40: *
41: * On write failure, close listeners fire before the exception is rethrown.
42: *
43: * @throws TransportNotStartedException
44: * @throws TransportAlreadyClosedException
45: * @throws \Throwable
46: */
47: public function send(JsonRpcMessage $message, ?SendContext $context = null): void;
48:
49: /**
50: * Closes the connection. The `onClose()` listener fires once after the
51: * underlying streams are closed. Subsequent calls are no-ops.
52: *
53: * Implementations MUST guarantee that `onClose()` listeners fire after a
54: * fatal error too, not only after explicit `close()`. `Server::run()`
55: * blocks on the close signal, so a transport that raises errors without
56: * eventually closing would hang the server loop.
57: */
58: public function close(): void;
59:
60: /**
61: * Register an inbound-envelope listener.
62: *
63: * @param \Closure(array<string, mixed>): void $listener
64: */
65: public function onMessage(\Closure $listener): SubscriptionInterface;
66:
67: /**
68: * Register an error listener.
69: *
70: * @param \Closure(\Throwable): void $listener
71: */
72: public function onError(\Closure $listener): SubscriptionInterface;
73:
74: /**
75: * Register a drain listener that fires before `close()`.
76: *
77: * @param \Closure(): void $listener
78: */
79: public function onDrain(\Closure $listener): SubscriptionInterface;
80:
81: /**
82: * Register a close listener.
83: *
84: * @param \Closure(): void $listener
85: */
86: public function onClose(\Closure $listener): SubscriptionInterface;
87: }
88: