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: * Returns the transport-issued session identifier, or null when the
62: * transport carries no session (e.g. stdio).
63: */
64: public function getSessionId(): ?string;
65:
66: /**
67: * Register an inbound-envelope listener.
68: *
69: * @param \Closure(array<string, mixed>): void $listener
70: */
71: public function onMessage(\Closure $listener): SubscriptionInterface;
72:
73: /**
74: * Register an error listener.
75: *
76: * @param \Closure(\Throwable): void $listener
77: */
78: public function onError(\Closure $listener): SubscriptionInterface;
79:
80: /**
81: * Register a drain listener that fires before `close()`.
82: *
83: * @param \Closure(): void $listener
84: */
85: public function onDrain(\Closure $listener): SubscriptionInterface;
86:
87: /**
88: * Register a close listener.
89: *
90: * @param \Closure(): void $listener
91: */
92: public function onClose(\Closure $listener): SubscriptionInterface;
93: }
94: