[Client] Expose session ID from HttpTransport (#497)
* Expose session ID from HttpTransport * [Client] State what getSessionId() returns on 2026-07-28 That revision removed protocol-level sessions (SEP-2567), so the getter is always null there. Adds the changelog entry. --------- Co-authored-by: Christopher Hertel <mail@christopher-hertel.de>
This commit is contained in:
parent
c5dbfb64e5
commit
418034f2b0
3 changed files with 68 additions and 0 deletions
|
|
@ -2,6 +2,11 @@
|
||||||
|
|
||||||
All notable changes to `mcp/sdk` will be documented in this file.
|
All notable changes to `mcp/sdk` will be documented in this file.
|
||||||
|
|
||||||
|
0.9.0
|
||||||
|
-----
|
||||||
|
|
||||||
|
* Add `HttpTransport::getSessionId()` to read the server-minted `Mcp-Session-Id`: a request-scoped caller can persist it and pass it back through the constructor's `$headers` on a later transport. Always `null` on `2026-07-28`, which removed protocol-level sessions.
|
||||||
|
|
||||||
0.8.0
|
0.8.0
|
||||||
-----
|
-----
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -121,6 +121,22 @@ class HttpTransport extends BaseTransport implements HeaderAwareTransportInterfa
|
||||||
$this->headerCallback = $callback;
|
$this->headerCallback = $callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The session ID minted by the server for this connection, if any.
|
||||||
|
*
|
||||||
|
* Captured from the Mcp-Session-Id response header of a handshake-era
|
||||||
|
* server; always null on 2026-07-28, which removed protocol-level sessions
|
||||||
|
* (SEP-2567). A caller that cannot keep the transport alive between
|
||||||
|
* interactions can persist it and pass it back through the constructor's
|
||||||
|
* $headers on a later transport, where it wins over the tracked value.
|
||||||
|
*
|
||||||
|
* @return string|null null until the server mints a session, and again after close()
|
||||||
|
*/
|
||||||
|
public function getSessionId(): ?string
|
||||||
|
{
|
||||||
|
return $this->sessionId;
|
||||||
|
}
|
||||||
|
|
||||||
public function send(string $data): void
|
public function send(string $data): void
|
||||||
{
|
{
|
||||||
$request = $this->requestFactory->createRequest('POST', $this->endpoint)
|
$request = $this->requestFactory->createRequest('POST', $this->endpoint)
|
||||||
|
|
|
||||||
|
|
@ -94,6 +94,53 @@ final class HttpTransportTest extends TestCase
|
||||||
$this->assertSame('test-server', $client->getServerInfo()?->name);
|
$this->assertSame('test-server', $client->getServerInfo()?->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[TestDox('the server-minted session ID is exposed while connected and cleared on close')]
|
||||||
|
public function testSessionIdIsExposedAndClearedOnClose(): void
|
||||||
|
{
|
||||||
|
$httpClient = new class implements ClientInterface {
|
||||||
|
public function sendRequest(RequestInterface $request): ResponseInterface
|
||||||
|
{
|
||||||
|
$decoded = json_decode((string) $request->getBody(), true);
|
||||||
|
|
||||||
|
if ('initialize' !== ($decoded['method'] ?? null)) {
|
||||||
|
return new Response(202);
|
||||||
|
}
|
||||||
|
|
||||||
|
$payload = json_encode([
|
||||||
|
'jsonrpc' => '2.0',
|
||||||
|
'id' => $decoded['id'],
|
||||||
|
'result' => [
|
||||||
|
'protocolVersion' => '2025-11-25',
|
||||||
|
'capabilities' => ['tools' => ['listChanged' => false]],
|
||||||
|
'serverInfo' => ['name' => 'test-server', 'version' => '1.0.0'],
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
|
||||||
|
return new Response(200, [
|
||||||
|
'Content-Type' => 'application/json',
|
||||||
|
'Mcp-Session-Id' => 'session-abc123',
|
||||||
|
], $payload);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$transport = new HttpTransport('http://localhost/mcp', [], $httpClient, $this->factory, $this->factory);
|
||||||
|
|
||||||
|
$this->assertNull($transport->getSessionId());
|
||||||
|
|
||||||
|
$client = Client::builder()
|
||||||
|
->setClientInfo('test-client', '1.0.0')
|
||||||
|
->setInitTimeout(1)
|
||||||
|
->build();
|
||||||
|
|
||||||
|
$client->connect($transport);
|
||||||
|
|
||||||
|
$this->assertSame('session-abc123', $transport->getSessionId());
|
||||||
|
|
||||||
|
$client->disconnect();
|
||||||
|
|
||||||
|
$this->assertNull($transport->getSessionId());
|
||||||
|
}
|
||||||
|
|
||||||
#[TestDox('SSE stream is aborted before the buffer can exceed the configured cap')]
|
#[TestDox('SSE stream is aborted before the buffer can exceed the configured cap')]
|
||||||
public function testSseBufferIsBoundedByConfiguredCap(): void
|
public function testSseBufferIsBoundedByConfiguredCap(): void
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue