tiny-http-mcp-server 0.1.52 → 0.1.53

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -18,7 +18,7 @@
18
18
  },
19
19
  {
20
20
  "name": "tiny-http-mcp-server",
21
- "version": "0.1.52",
21
+ "version": "0.1.53",
22
22
  "license": "MIT"
23
23
  },
24
24
  {
@@ -23,8 +23,14 @@ await client.close();
23
23
  ```
24
24
 
25
25
  Omit `protocolVersion` for automatic modern discovery and legacy negotiation.
26
- Set it to `"2025-03-26"` or `"2026-07-28"` to pin a protocol. A modern pin
26
+ Set it to `"2025-03-26"`, `"2025-06-18"`, `"2025-11-25"` or `"2026-07-28"`
27
+ to pin a protocol. `McpProtocolVersion` and the immutable
28
+ `MCP_PROTOCOL_VERSIONS` list expose these supported revisions. A modern pin
27
29
  rejects failed or timed-out discovery without sending legacy initialization.
30
+ Legacy pins skip modern discovery and require the selected revision to match.
31
+ Automatic legacy negotiation still offers `2025-03-26` and accepts any supported
32
+ legacy revision selected by the server. Subsequent HTTP POST, GET and DELETE
33
+ requests use that selected revision, including endpoints without session IDs.
28
34
  Unsupported pins fail before connection setup.
29
35
 
30
36
  `Tool` includes MCP `outputSchema` when a server advertises typed tool output.
@@ -384,11 +384,13 @@ interface ElicitationResult {
384
384
  action: "accept" | "decline" | "cancel";
385
385
  content?: Record<string, string | number | boolean | string[]>;
386
386
  }
387
+ declare const MCP_PROTOCOL_VERSIONS: readonly ["2025-03-26", "2025-06-18", "2025-11-25", "2026-07-28"];
388
+ type McpProtocolVersion = typeof MCP_PROTOCOL_VERSIONS[number];
387
389
  interface McpClientOptions {
388
390
  clientInfo: Implementation;
389
391
  requestTimeoutMs?: number;
390
392
  maxConcurrentRequests?: number;
391
- protocolVersion?: "2025-03-26" | "2026-07-28";
393
+ protocolVersion?: McpProtocolVersion;
392
394
  capabilities?: ClientCapabilities;
393
395
  onToolsChanged?: () => void | Promise<void>;
394
396
  onResourcesChanged?: () => void | Promise<void>;
@@ -655,6 +657,7 @@ interface McpTransport {
655
657
  completeInitialization?(options: {
656
658
  signal?: AbortSignal;
657
659
  timeoutMs: number;
660
+ protocolVersion?: string;
658
661
  }): Promise<void>;
659
662
  }
660
663
  interface InMemoryServerTransport {
@@ -734,6 +737,8 @@ declare class HttpTransport implements McpTransport {
734
737
  private readonly writeStream;
735
738
  private resolveClosed;
736
739
  private sessionId;
740
+ private legacyProtocolVersion;
741
+ private initializationRequestId;
737
742
  private lastEventId;
738
743
  private getSseStreamStarted;
739
744
  private disposed;
@@ -752,6 +757,7 @@ declare class HttpTransport implements McpTransport {
752
757
  completeInitialization(options: {
753
758
  signal?: AbortSignal;
754
759
  timeoutMs: number;
760
+ protocolVersion?: string;
755
761
  }): Promise<void>;
756
762
  filterTools(tools: Tool[], reset?: boolean): Tool[];
757
763
  dispose(reason?: Error): void;
@@ -860,5 +866,5 @@ declare class JsonRpcMessageLayer {
860
866
  private handleCancellationNotification;
861
867
  }
862
868
 
863
- export { ERROR_INTERNAL, ERROR_INVALID_PARAMS, ERROR_INVALID_REQUEST, ERROR_METHOD_NOT_FOUND, ERROR_PARSE, HttpTransport, HttpTransportError, JsonRpcMessageLayer, McpClient, McpError, OAuthMetadataDiscovery, StdioTransport, createInMemoryTransportPair, createSdkTestPair, createTestPair, discoverOAuthMetadata, fetchMcpResponse };
864
- export type { AudioContent, BlobResourceContents, CacheableResultMetadata, CallToolOptions, CallToolParams, CallToolResult, ClientCapabilities, CompleteArgument, CompleteParams, CompleteResult, Completion, ConnectResult, ContentItem, CreateMessageParams, CreateMessageResult, ElicitationParams, ElicitationResult, EmbeddedResource, GetPromptParams, GetPromptResult, HttpTransportFetch, HttpTransportOptions, ImageContent, InMemoryTransportPair, IncludeContext, InitializeParams, InitializeResult, JsonRpcErrorObject, JsonRpcErrorResponse, JsonRpcMessage, JsonRpcNotification, JsonRpcRequest, JsonRpcRequestOptions, JsonRpcResponse, JsonRpcSuccessResponse, LogLevel, LogMessage, McpClientConnection, McpClientOptions, McpRequestContext, McpSubscription, McpTransport, McpTransportClosedEvent, ModelHint, ModelPreferences, NotificationFilter, OAuthAuthorizationServerMetadata, OAuthClientProvider, OAuthClientProviderOptions, OAuthDiscoveryCache, OAuthDiscoveryResult, OAuthMetadataFetch, OAuthProtectedResourceMetadata, OAuthSessionStore, OAuthUnauthorizedChallenge, PaginatedParams, PaginatedResult, ProgressParams, ProgressToken, PromptMessage, PromptReference, ReadResourceParams, RequestId, ResourceContents, ResourceReference, ResultMetadata, Root, SamplingContent, SamplingMessage, SdkTestPair, ServerCapabilities, StdioSpawn, StdioTransportOptions, StoredOAuthSession, SubscriptionOptions, TextContent, TextResourceContents, Tool, ToolResultContent, ToolUseContent };
869
+ export { ERROR_INTERNAL, ERROR_INVALID_PARAMS, ERROR_INVALID_REQUEST, ERROR_METHOD_NOT_FOUND, ERROR_PARSE, HttpTransport, HttpTransportError, JsonRpcMessageLayer, MCP_PROTOCOL_VERSIONS, McpClient, McpError, OAuthMetadataDiscovery, StdioTransport, createInMemoryTransportPair, createSdkTestPair, createTestPair, discoverOAuthMetadata, fetchMcpResponse };
870
+ export type { AudioContent, BlobResourceContents, CacheableResultMetadata, CallToolOptions, CallToolParams, CallToolResult, ClientCapabilities, CompleteArgument, CompleteParams, CompleteResult, Completion, ConnectResult, ContentItem, CreateMessageParams, CreateMessageResult, ElicitationParams, ElicitationResult, EmbeddedResource, GetPromptParams, GetPromptResult, HttpTransportFetch, HttpTransportOptions, ImageContent, InMemoryTransportPair, IncludeContext, InitializeParams, InitializeResult, JsonRpcErrorObject, JsonRpcErrorResponse, JsonRpcMessage, JsonRpcNotification, JsonRpcRequest, JsonRpcRequestOptions, JsonRpcResponse, JsonRpcSuccessResponse, LogLevel, LogMessage, McpClientConnection, McpClientOptions, McpProtocolVersion, McpRequestContext, McpSubscription, McpTransport, McpTransportClosedEvent, ModelHint, ModelPreferences, NotificationFilter, OAuthAuthorizationServerMetadata, OAuthClientProvider, OAuthClientProviderOptions, OAuthDiscoveryCache, OAuthDiscoveryResult, OAuthMetadataFetch, OAuthProtectedResourceMetadata, OAuthSessionStore, OAuthUnauthorizedChallenge, PaginatedParams, PaginatedResult, ProgressParams, ProgressToken, PromptMessage, PromptReference, ReadResourceParams, RequestId, ResourceContents, ResourceReference, ResultMetadata, Root, SamplingContent, SamplingMessage, SdkTestPair, ServerCapabilities, StdioSpawn, StdioTransportOptions, StoredOAuthSession, SubscriptionOptions, TextContent, TextResourceContents, Tool, ToolResultContent, ToolUseContent };
@@ -6642,6 +6642,7 @@ var inputResponseTypes = {
6642
6642
  "sampling/createMessage": "CreateMessageResult",
6643
6643
  "elicitation/create": "ElicitResult"
6644
6644
  };
6645
+ var MCP_PROTOCOL_VERSIONS = Object.freeze(["2025-03-26", "2025-06-18", "2025-11-25", "2026-07-28"]);
6645
6646
  var MCP_PROTOCOL_VERSION = "2025-03-26";
6646
6647
  var McpClient = class {
6647
6648
  currentState = "disconnected";
@@ -6685,8 +6686,8 @@ var McpClient = class {
6685
6686
  }
6686
6687
  async connect(transport, options = {}) {
6687
6688
  options.signal?.throwIfAborted();
6688
- if (this.options.protocolVersion !== void 0 && this.options.protocolVersion !== MCP_PROTOCOL_VERSION && this.options.protocolVersion !== "2026-07-28")
6689
- throw new Error("Unsupported protocolVersion; use 2025-03-26 or 2026-07-28");
6689
+ if (this.options.protocolVersion !== void 0 && !MCP_PROTOCOL_VERSIONS.includes(this.options.protocolVersion))
6690
+ throw new Error(`Unsupported protocolVersion; use ${MCP_PROTOCOL_VERSIONS.join(", ")}`);
6690
6691
  if (this.currentState !== "disconnected" && this.currentState !== "closed") {
6691
6692
  throw new Error("MCP client is already connected");
6692
6693
  }
@@ -6855,7 +6856,7 @@ var McpClient = class {
6855
6856
  }
6856
6857
  let discovery;
6857
6858
  try {
6858
- if (this.options.protocolVersion !== "2025-03-26") discovery = await messageLayer.sendRequest("server/discover", {
6859
+ if (this.options.protocolVersion === void 0 || this.options.protocolVersion === "2026-07-28") discovery = await messageLayer.sendRequest("server/discover", {
6859
6860
  _meta: {
6860
6861
  "io.modelcontextprotocol/protocolVersion": "2026-07-28",
6861
6862
  "io.modelcontextprotocol/clientCapabilities": capabilities
@@ -6907,7 +6908,7 @@ var McpClient = class {
6907
6908
  };
6908
6909
  }
6909
6910
  const initializeResultValue = await messageLayer.sendRequest("initialize", {
6910
- protocolVersion: MCP_PROTOCOL_VERSION,
6911
+ protocolVersion: this.options.protocolVersion ?? MCP_PROTOCOL_VERSION,
6911
6912
  clientInfo: this.options.clientInfo,
6912
6913
  capabilities
6913
6914
  }, { signal: options.signal });
@@ -6915,12 +6916,14 @@ var McpClient = class {
6915
6916
  throw new McpError(ERROR_INVALID_REQUEST, "Invalid initialize result");
6916
6917
  }
6917
6918
  const initializeResult = initializeResultValue;
6918
- if (initializeResult.protocolVersion !== MCP_PROTOCOL_VERSION) {
6919
+ if (initializeResult.protocolVersion === "2026-07-28" || !MCP_PROTOCOL_VERSIONS.includes(initializeResult.protocolVersion)) {
6919
6920
  throw new McpError(
6920
6921
  ERROR_INVALID_REQUEST,
6921
6922
  `Unsupported protocol version: ${initializeResult.protocolVersion}`
6922
6923
  );
6923
6924
  }
6925
+ if (this.options.protocolVersion !== void 0 && initializeResult.protocolVersion !== this.options.protocolVersion)
6926
+ throw new McpError(ERROR_INVALID_REQUEST, `Pinned protocol version ${this.options.protocolVersion} rejected: server selected ${initializeResult.protocolVersion}`);
6924
6927
  this.currentServerCapabilities = structuredClone(initializeResult.capabilities);
6925
6928
  this.currentServerInfo = structuredClone(initializeResult.serverInfo);
6926
6929
  this.currentInstructions = initializeResult.instructions;
@@ -6936,7 +6939,7 @@ var McpClient = class {
6936
6939
  );
6937
6940
  }
6938
6941
  if (transport.completeInitialization === void 0) messageLayer.sendNotification("notifications/initialized");
6939
- else await transport.completeInitialization({ signal: options.signal, timeoutMs: this.options.requestTimeoutMs ?? 3e4 });
6942
+ else await transport.completeInitialization({ signal: options.signal, timeoutMs: this.options.requestTimeoutMs ?? 3e4, protocolVersion: initializeResult.protocolVersion });
6940
6943
  this.currentState = "ready";
6941
6944
  return initializeResult;
6942
6945
  } catch (error) {
@@ -7568,6 +7571,8 @@ var HttpTransport = class {
7568
7571
  writeStream = new PassThrough();
7569
7572
  resolveClosed;
7570
7573
  sessionId;
7574
+ legacyProtocolVersion;
7575
+ initializationRequestId;
7571
7576
  lastEventId;
7572
7577
  getSseStreamStarted = false;
7573
7578
  disposed = false;
@@ -7626,6 +7631,8 @@ var HttpTransport = class {
7626
7631
  const signals = [options.signal, deadline].filter((signal2) => signal2 !== void 0);
7627
7632
  const signal = signals.length === 0 ? new AbortController().signal : AbortSignal.any(signals);
7628
7633
  signal.throwIfAborted();
7634
+ if (options.protocolVersion !== void 0) this.legacyProtocolVersion = options.protocolVersion;
7635
+ this.maybeOpenGetSseStream();
7629
7636
  try {
7630
7637
  await this.sendPost(serializeJsonRpcMessage({ jsonrpc: "2.0", method: "notifications/initialized" }), signal);
7631
7638
  signal.throwIfAborted();
@@ -7754,8 +7761,13 @@ var HttpTransport = class {
7754
7761
  const metadata = isObjectRecord5(message?.params) ? message.params._meta : void 0;
7755
7762
  const modern = isObjectRecord5(metadata) && typeof metadata["io.modelcontextprotocol/protocolVersion"] === "string";
7756
7763
  if (modern) this.modernMode = true;
7757
- if (parsed.type === "request" && parsed.message.method === "initialize")
7764
+ if (parsed.type === "request" && parsed.message.method === "initialize") {
7758
7765
  this.modernMode = false;
7766
+ this.initializationRequestId = parsed.message.id;
7767
+ this.legacyProtocolVersion = MCP_PROTOCOL_VERSION;
7768
+ if (isObjectRecord5(parsed.message.params) && typeof parsed.message.params.protocolVersion === "string")
7769
+ this.legacyProtocolVersion = parsed.message.params.protocolVersion;
7770
+ }
7759
7771
  if (this.modernMode && parsed.type === "notification" && parsed.message.method === "notifications/cancelled") {
7760
7772
  const requestId = isObjectRecord5(parsed.message.params) ? parsed.message.params.requestId : void 0;
7761
7773
  if (typeof requestId === "string" || typeof requestId === "number")
@@ -7800,10 +7812,12 @@ var HttpTransport = class {
7800
7812
  }
7801
7813
  if (!modern && this.mode !== "sse") {
7802
7814
  this.captureSessionId(response);
7803
- this.maybeOpenGetSseStream();
7815
+ if (message?.method !== "initialize") this.maybeOpenGetSseStream();
7804
7816
  }
7805
- if (controller !== void 0) await this.forwardResponseMessages(response, controller.signal, parsed.type === "request" ? new HttpResponseMessages(parsed.message) : void 0);
7806
- else
7817
+ if (controller !== void 0 || message?.method === "initialize") {
7818
+ await this.forwardResponseMessages(response, controller?.signal, controller === void 0 || parsed.type !== "request" ? void 0 : new HttpResponseMessages(parsed.message), message?.method === "initialize");
7819
+ if (message?.method === "initialize") this.maybeOpenGetSseStream();
7820
+ } else
7807
7821
  void this.forwardResponseMessages(response).catch((error) => {
7808
7822
  this.dispose(error instanceof Error ? error : new Error(String(error)));
7809
7823
  });
@@ -7843,8 +7857,9 @@ var HttpTransport = class {
7843
7857
  }
7844
7858
  } else if (this.sessionId !== void 0) {
7845
7859
  headers.set("Mcp-Session-Id", this.sessionId);
7846
- headers.set("MCP-Protocol-Version", MCP_PROTOCOL_VERSION);
7847
7860
  }
7861
+ if (!modern && message?.method !== "initialize" && this.legacyProtocolVersion !== void 0)
7862
+ headers.set("MCP-Protocol-Version", this.legacyProtocolVersion);
7848
7863
  return this.authorizeRequestHeaders(headers, signal);
7849
7864
  }
7850
7865
  async createGetHeaders(signal) {
@@ -7852,8 +7867,8 @@ var HttpTransport = class {
7852
7867
  headers.set("Accept", "text/event-stream");
7853
7868
  if (this.sessionId !== void 0) {
7854
7869
  headers.set("Mcp-Session-Id", this.sessionId);
7855
- headers.set("MCP-Protocol-Version", MCP_PROTOCOL_VERSION);
7856
7870
  }
7871
+ if (this.legacyProtocolVersion !== void 0) headers.set("MCP-Protocol-Version", this.legacyProtocolVersion);
7857
7872
  if (this.lastEventId !== void 0) {
7858
7873
  headers.set("Last-Event-ID", this.lastEventId);
7859
7874
  }
@@ -7862,7 +7877,7 @@ var HttpTransport = class {
7862
7877
  async createDeleteHeaders(sessionId, signal) {
7863
7878
  const headers = new Headers(this.headers);
7864
7879
  headers.set("Mcp-Session-Id", sessionId);
7865
- headers.set("MCP-Protocol-Version", MCP_PROTOCOL_VERSION);
7880
+ headers.set("MCP-Protocol-Version", this.legacyProtocolVersion ?? MCP_PROTOCOL_VERSION);
7866
7881
  return this.authorizeRequestHeaders(headers, signal);
7867
7882
  }
7868
7883
  async authorizeRequestHeaders(headers, signal) {
@@ -7966,7 +7981,7 @@ var HttpTransport = class {
7966
7981
  return;
7967
7982
  }
7968
7983
  if (contentType.split(";")[0]?.trim().toLowerCase() === "text/event-stream") {
7969
- await this.forwardSseResponseMessages(response, void 0, void 0, this.mode === "sse");
7984
+ await this.forwardSseResponseMessages(response, void 0, void 0, { acceptEndpoint: this.mode === "sse" });
7970
7985
  if (this.mode === "sse") {
7971
7986
  if (!this.disposed) throw new Error("Legacy SSE stream ended");
7972
7987
  return;
@@ -8063,7 +8078,7 @@ var HttpTransport = class {
8063
8078
  throw error;
8064
8079
  }
8065
8080
  }
8066
- async forwardResponseMessages(response, signal, context) {
8081
+ async forwardResponseMessages(response, signal, context, initialization = false) {
8067
8082
  if (response.status === 202) {
8068
8083
  void response.body?.cancel().catch(() => void 0);
8069
8084
  return;
@@ -8075,7 +8090,7 @@ var HttpTransport = class {
8075
8090
  }
8076
8091
  const normalizedContentType = contentType.split(";")[0]?.trim().toLowerCase();
8077
8092
  if (normalizedContentType === "text/event-stream") {
8078
- await this.forwardSseResponseMessages(response, signal, context);
8093
+ await this.forwardSseResponseMessages(response, signal, context, { stopAfterInitialization: initialization });
8079
8094
  return;
8080
8095
  }
8081
8096
  if (normalizedContentType === "application/json") {
@@ -8085,11 +8100,11 @@ var HttpTransport = class {
8085
8100
  void response.body?.cancel().catch(() => void 0);
8086
8101
  throw new Error("HTTP transport POST returned an unsupported response content type");
8087
8102
  }
8088
- async forwardSseResponseMessages(response, signal, context, acceptEndpoint = false) {
8103
+ async forwardSseResponseMessages(response, signal, context, options = {}) {
8089
8104
  if (response.body === null) {
8090
8105
  return;
8091
8106
  }
8092
- const parser = new SseParser(this.maxResponseBytes, acceptEndpoint);
8107
+ const parser = new SseParser(this.maxResponseBytes, options.acceptEndpoint);
8093
8108
  const decoder = new TextDecoder("utf-8", { fatal: true });
8094
8109
  const reader = response.body.getReader();
8095
8110
  this.openResponseReaders.add(reader);
@@ -8110,7 +8125,7 @@ var HttpTransport = class {
8110
8125
  }
8111
8126
  const messages = parser.push(decoder.decode(value, { stream: true }));
8112
8127
  this.writeSseMessages(messages, context);
8113
- if (context?.completed) {
8128
+ if (context?.completed || options.stopAfterInitialization && this.initializationRequestId === void 0) {
8114
8129
  void reader.cancel().catch(() => void 0);
8115
8130
  return;
8116
8131
  }
@@ -8174,6 +8189,21 @@ var HttpTransport = class {
8174
8189
  if (this.disposed || this.readStream.destroyed || this.readStream.writableEnded) {
8175
8190
  return;
8176
8191
  }
8192
+ if (this.initializationRequestId !== void 0) {
8193
+ try {
8194
+ const payload = JSON.parse(line);
8195
+ for (const response of Array.isArray(payload) ? payload : [payload]) {
8196
+ if (!isObjectRecord5(response) || response.id !== this.initializationRequestId || !isObjectRecord5(response.result)) continue;
8197
+ const version = response.result.protocolVersion;
8198
+ if (typeof version === "string" && version !== "2026-07-28" && MCP_PROTOCOL_VERSIONS.includes(version))
8199
+ this.legacyProtocolVersion = version;
8200
+ this.initializationRequestId = void 0;
8201
+ this.maybeOpenGetSseStream();
8202
+ break;
8203
+ }
8204
+ } catch {
8205
+ }
8206
+ }
8177
8207
  this.readStream.write(`${line}
8178
8208
  `);
8179
8209
  }
@@ -9114,6 +9144,7 @@ export {
9114
9144
  HttpTransport,
9115
9145
  HttpTransportError,
9116
9146
  JsonRpcMessageLayer,
9147
+ MCP_PROTOCOL_VERSIONS,
9117
9148
  McpClient,
9118
9149
  McpError,
9119
9150
  OAuthMetadataDiscovery,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tiny-http-mcp-server",
3
- "version": "0.1.52",
3
+ "version": "0.1.53",
4
4
  "description": "Minimal MCP server over HTTP built on tiny-stdio-mcp-server",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",