Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/fix-json-response-accept.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@modelcontextprotocol/sdk': patch
---

Allow streamable HTTP JSON response mode to accept POST requests whose `Accept` header only lists `application/json`.
17 changes: 9 additions & 8 deletions src/server/webStandardStreamableHttp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -598,14 +598,15 @@ export class WebStandardStreamableHTTPServerTransport implements Transport {
try {
// Validate the Accept header
const acceptHeader = req.headers.get('accept');
// The client MUST include an Accept header, listing both application/json and text/event-stream as supported content types.
if (!acceptHeader?.includes('application/json') || !acceptHeader.includes('text/event-stream')) {
this.onerror?.(new Error('Not Acceptable: Client must accept both application/json and text/event-stream'));
return this.createJsonErrorResponse(
406,
-32000,
'Not Acceptable: Client must accept both application/json and text/event-stream'
);
const acceptsJson = acceptHeader?.includes('application/json') ?? false;
const acceptsEventStream = acceptHeader?.includes('text/event-stream') ?? false;

if (!acceptsJson || (!this._enableJsonResponse && !acceptsEventStream)) {
const message = this._enableJsonResponse
? 'Not Acceptable: Client must accept application/json'
: 'Not Acceptable: Client must accept both application/json and text/event-stream';
this.onerror?.(new Error(message));
return this.createJsonErrorResponse(406, -32000, message);
}

const ct = req.headers.get('content-type');
Expand Down
23 changes: 23 additions & 0 deletions test/server/streamableHttp.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1115,6 +1115,29 @@ describe.each(zodTestMatrix)('$zodVersionLabel', (entry: ZodMatrixEntry) => {
});
});

it('should accept JSON-only Accept header in JSON response mode', async () => {
const toolsListMessage: JSONRPCMessage = {
jsonrpc: '2.0',
method: 'tools/list',
params: {},
id: 'json-req-1'
};

const response = await sendPostRequest(baseUrl, toolsListMessage, sessionId, { Accept: 'application/json' });

expect(response.status).toBe(200);
expect(response.headers.get('content-type')).toBe('application/json');

const result = await response.json();
expect(result).toMatchObject({
jsonrpc: '2.0',
result: expect.objectContaining({
tools: expect.arrayContaining([expect.objectContaining({ name: 'greet' })])
}),
id: 'json-req-1'
});
});

it('should return JSON response for batch requests', async () => {
const batchMessages: JSONRPCMessage[] = [
{ jsonrpc: '2.0', method: 'tools/list', params: {}, id: 'batch-1' },
Expand Down
Loading