tiny-http-mcp-server 0.1.52 → 0.1.54

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.54",
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();
@@ -7739,7 +7746,11 @@ var HttpTransport = class {
7739
7746
  const parsed = parseJsonRpcMessage(line);
7740
7747
  const post = this.sendPost(line);
7741
7748
  if (parsed.type === "request" && parsed.message.method === "initialize" || parsed.type === "notification" && parsed.message.method === "notifications/initialized") {
7742
- await post;
7749
+ try {
7750
+ await post;
7751
+ } catch (error) {
7752
+ this.dispose(error instanceof Error ? error : new Error(String(error)));
7753
+ }
7743
7754
  } else {
7744
7755
  void post.catch((error) => {
7745
7756
  this.dispose(error instanceof Error ? error : new Error(String(error)));
@@ -7754,8 +7765,13 @@ var HttpTransport = class {
7754
7765
  const metadata = isObjectRecord5(message?.params) ? message.params._meta : void 0;
7755
7766
  const modern = isObjectRecord5(metadata) && typeof metadata["io.modelcontextprotocol/protocolVersion"] === "string";
7756
7767
  if (modern) this.modernMode = true;
7757
- if (parsed.type === "request" && parsed.message.method === "initialize")
7768
+ if (parsed.type === "request" && parsed.message.method === "initialize") {
7758
7769
  this.modernMode = false;
7770
+ this.initializationRequestId = parsed.message.id;
7771
+ this.legacyProtocolVersion = MCP_PROTOCOL_VERSION;
7772
+ if (isObjectRecord5(parsed.message.params) && typeof parsed.message.params.protocolVersion === "string")
7773
+ this.legacyProtocolVersion = parsed.message.params.protocolVersion;
7774
+ }
7759
7775
  if (this.modernMode && parsed.type === "notification" && parsed.message.method === "notifications/cancelled") {
7760
7776
  const requestId = isObjectRecord5(parsed.message.params) ? parsed.message.params.requestId : void 0;
7761
7777
  if (typeof requestId === "string" || typeof requestId === "number")
@@ -7800,10 +7816,12 @@ var HttpTransport = class {
7800
7816
  }
7801
7817
  if (!modern && this.mode !== "sse") {
7802
7818
  this.captureSessionId(response);
7803
- this.maybeOpenGetSseStream();
7819
+ if (message?.method !== "initialize") this.maybeOpenGetSseStream();
7804
7820
  }
7805
- if (controller !== void 0) await this.forwardResponseMessages(response, controller.signal, parsed.type === "request" ? new HttpResponseMessages(parsed.message) : void 0);
7806
- else
7821
+ if (controller !== void 0 || message?.method === "initialize") {
7822
+ await this.forwardResponseMessages(response, controller?.signal, controller === void 0 || parsed.type !== "request" ? void 0 : new HttpResponseMessages(parsed.message), message?.method === "initialize");
7823
+ if (message?.method === "initialize") this.maybeOpenGetSseStream();
7824
+ } else
7807
7825
  void this.forwardResponseMessages(response).catch((error) => {
7808
7826
  this.dispose(error instanceof Error ? error : new Error(String(error)));
7809
7827
  });
@@ -7843,8 +7861,9 @@ var HttpTransport = class {
7843
7861
  }
7844
7862
  } else if (this.sessionId !== void 0) {
7845
7863
  headers.set("Mcp-Session-Id", this.sessionId);
7846
- headers.set("MCP-Protocol-Version", MCP_PROTOCOL_VERSION);
7847
7864
  }
7865
+ if (!modern && message?.method !== "initialize" && this.legacyProtocolVersion !== void 0)
7866
+ headers.set("MCP-Protocol-Version", this.legacyProtocolVersion);
7848
7867
  return this.authorizeRequestHeaders(headers, signal);
7849
7868
  }
7850
7869
  async createGetHeaders(signal) {
@@ -7852,8 +7871,8 @@ var HttpTransport = class {
7852
7871
  headers.set("Accept", "text/event-stream");
7853
7872
  if (this.sessionId !== void 0) {
7854
7873
  headers.set("Mcp-Session-Id", this.sessionId);
7855
- headers.set("MCP-Protocol-Version", MCP_PROTOCOL_VERSION);
7856
7874
  }
7875
+ if (this.legacyProtocolVersion !== void 0) headers.set("MCP-Protocol-Version", this.legacyProtocolVersion);
7857
7876
  if (this.lastEventId !== void 0) {
7858
7877
  headers.set("Last-Event-ID", this.lastEventId);
7859
7878
  }
@@ -7862,7 +7881,7 @@ var HttpTransport = class {
7862
7881
  async createDeleteHeaders(sessionId, signal) {
7863
7882
  const headers = new Headers(this.headers);
7864
7883
  headers.set("Mcp-Session-Id", sessionId);
7865
- headers.set("MCP-Protocol-Version", MCP_PROTOCOL_VERSION);
7884
+ headers.set("MCP-Protocol-Version", this.legacyProtocolVersion ?? MCP_PROTOCOL_VERSION);
7866
7885
  return this.authorizeRequestHeaders(headers, signal);
7867
7886
  }
7868
7887
  async authorizeRequestHeaders(headers, signal) {
@@ -7966,7 +7985,7 @@ var HttpTransport = class {
7966
7985
  return;
7967
7986
  }
7968
7987
  if (contentType.split(";")[0]?.trim().toLowerCase() === "text/event-stream") {
7969
- await this.forwardSseResponseMessages(response, void 0, void 0, this.mode === "sse");
7988
+ await this.forwardSseResponseMessages(response, void 0, void 0, { acceptEndpoint: this.mode === "sse" });
7970
7989
  if (this.mode === "sse") {
7971
7990
  if (!this.disposed) throw new Error("Legacy SSE stream ended");
7972
7991
  return;
@@ -8063,7 +8082,7 @@ var HttpTransport = class {
8063
8082
  throw error;
8064
8083
  }
8065
8084
  }
8066
- async forwardResponseMessages(response, signal, context) {
8085
+ async forwardResponseMessages(response, signal, context, initialization = false) {
8067
8086
  if (response.status === 202) {
8068
8087
  void response.body?.cancel().catch(() => void 0);
8069
8088
  return;
@@ -8075,7 +8094,7 @@ var HttpTransport = class {
8075
8094
  }
8076
8095
  const normalizedContentType = contentType.split(";")[0]?.trim().toLowerCase();
8077
8096
  if (normalizedContentType === "text/event-stream") {
8078
- await this.forwardSseResponseMessages(response, signal, context);
8097
+ await this.forwardSseResponseMessages(response, signal, context, { stopAfterInitialization: initialization });
8079
8098
  return;
8080
8099
  }
8081
8100
  if (normalizedContentType === "application/json") {
@@ -8085,11 +8104,11 @@ var HttpTransport = class {
8085
8104
  void response.body?.cancel().catch(() => void 0);
8086
8105
  throw new Error("HTTP transport POST returned an unsupported response content type");
8087
8106
  }
8088
- async forwardSseResponseMessages(response, signal, context, acceptEndpoint = false) {
8107
+ async forwardSseResponseMessages(response, signal, context, options = {}) {
8089
8108
  if (response.body === null) {
8090
8109
  return;
8091
8110
  }
8092
- const parser = new SseParser(this.maxResponseBytes, acceptEndpoint);
8111
+ const parser = new SseParser(this.maxResponseBytes, options.acceptEndpoint);
8093
8112
  const decoder = new TextDecoder("utf-8", { fatal: true });
8094
8113
  const reader = response.body.getReader();
8095
8114
  this.openResponseReaders.add(reader);
@@ -8110,7 +8129,7 @@ var HttpTransport = class {
8110
8129
  }
8111
8130
  const messages = parser.push(decoder.decode(value, { stream: true }));
8112
8131
  this.writeSseMessages(messages, context);
8113
- if (context?.completed) {
8132
+ if (context?.completed || options.stopAfterInitialization && this.initializationRequestId === void 0) {
8114
8133
  void reader.cancel().catch(() => void 0);
8115
8134
  return;
8116
8135
  }
@@ -8174,6 +8193,21 @@ var HttpTransport = class {
8174
8193
  if (this.disposed || this.readStream.destroyed || this.readStream.writableEnded) {
8175
8194
  return;
8176
8195
  }
8196
+ if (this.initializationRequestId !== void 0) {
8197
+ try {
8198
+ const payload = JSON.parse(line);
8199
+ for (const response of Array.isArray(payload) ? payload : [payload]) {
8200
+ if (!isObjectRecord5(response) || response.id !== this.initializationRequestId || !isObjectRecord5(response.result)) continue;
8201
+ const version = response.result.protocolVersion;
8202
+ if (typeof version === "string" && version !== "2026-07-28" && MCP_PROTOCOL_VERSIONS.includes(version))
8203
+ this.legacyProtocolVersion = version;
8204
+ this.initializationRequestId = void 0;
8205
+ this.maybeOpenGetSseStream();
8206
+ break;
8207
+ }
8208
+ } catch {
8209
+ }
8210
+ }
8177
8211
  this.readStream.write(`${line}
8178
8212
  `);
8179
8213
  }
@@ -9114,6 +9148,7 @@ export {
9114
9148
  HttpTransport,
9115
9149
  HttpTransportError,
9116
9150
  JsonRpcMessageLayer,
9151
+ MCP_PROTOCOL_VERSIONS,
9117
9152
  McpClient,
9118
9153
  McpError,
9119
9154
  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.54",
4
4
  "description": "Minimal MCP server over HTTP built on tiny-stdio-mcp-server",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",