tiny-http-mcp-server 0.1.51 → 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.51",
21
+ "version": "0.1.53",
22
22
  "license": "MIT"
23
23
  },
24
24
  {
@@ -22,6 +22,17 @@ console.log(result.structuredContent);
22
22
  await client.close();
23
23
  ```
24
24
 
25
+ Omit `protocolVersion` for automatic modern discovery and legacy negotiation.
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
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.
34
+ Unsupported pins fail before connection setup.
35
+
25
36
  `Tool` includes MCP `outputSchema` when a server advertises typed tool output.
26
37
  `CallToolResult.structuredContent` preserves modern JSON values; legacy servers
27
38
  require an object. Complete `content[]` blocks remain available in either case.
@@ -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,6 +6686,8 @@ var McpClient = class {
6685
6686
  }
6686
6687
  async connect(transport, options = {}) {
6687
6688
  options.signal?.throwIfAborted();
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(", ")}`);
6688
6691
  if (this.currentState !== "disconnected" && this.currentState !== "closed") {
6689
6692
  throw new Error("MCP client is already connected");
6690
6693
  }
@@ -6853,7 +6856,7 @@ var McpClient = class {
6853
6856
  }
6854
6857
  let discovery;
6855
6858
  try {
6856
- 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", {
6857
6860
  _meta: {
6858
6861
  "io.modelcontextprotocol/protocolVersion": "2026-07-28",
6859
6862
  "io.modelcontextprotocol/clientCapabilities": capabilities
@@ -6861,6 +6864,7 @@ var McpClient = class {
6861
6864
  }, { signal: options.signal, timeoutMs: this.options.protocolVersion === "2026-07-28" ? this.options.requestTimeoutMs ?? 3e4 : Math.min(this.options.requestTimeoutMs ?? 3e4, 1e3) });
6862
6865
  } catch (error) {
6863
6866
  options.signal?.throwIfAborted();
6867
+ if (this.options.protocolVersion === "2026-07-28") throw error;
6864
6868
  if (error instanceof McpError && [-32020, -32021, -32022].includes(error.code)) throw error;
6865
6869
  }
6866
6870
  if (discovery !== void 0) {
@@ -6904,7 +6908,7 @@ var McpClient = class {
6904
6908
  };
6905
6909
  }
6906
6910
  const initializeResultValue = await messageLayer.sendRequest("initialize", {
6907
- protocolVersion: MCP_PROTOCOL_VERSION,
6911
+ protocolVersion: this.options.protocolVersion ?? MCP_PROTOCOL_VERSION,
6908
6912
  clientInfo: this.options.clientInfo,
6909
6913
  capabilities
6910
6914
  }, { signal: options.signal });
@@ -6912,12 +6916,14 @@ var McpClient = class {
6912
6916
  throw new McpError(ERROR_INVALID_REQUEST, "Invalid initialize result");
6913
6917
  }
6914
6918
  const initializeResult = initializeResultValue;
6915
- if (initializeResult.protocolVersion !== MCP_PROTOCOL_VERSION) {
6919
+ if (initializeResult.protocolVersion === "2026-07-28" || !MCP_PROTOCOL_VERSIONS.includes(initializeResult.protocolVersion)) {
6916
6920
  throw new McpError(
6917
6921
  ERROR_INVALID_REQUEST,
6918
6922
  `Unsupported protocol version: ${initializeResult.protocolVersion}`
6919
6923
  );
6920
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}`);
6921
6927
  this.currentServerCapabilities = structuredClone(initializeResult.capabilities);
6922
6928
  this.currentServerInfo = structuredClone(initializeResult.serverInfo);
6923
6929
  this.currentInstructions = initializeResult.instructions;
@@ -6933,7 +6939,7 @@ var McpClient = class {
6933
6939
  );
6934
6940
  }
6935
6941
  if (transport.completeInitialization === void 0) messageLayer.sendNotification("notifications/initialized");
6936
- 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 });
6937
6943
  this.currentState = "ready";
6938
6944
  return initializeResult;
6939
6945
  } catch (error) {
@@ -7565,6 +7571,8 @@ var HttpTransport = class {
7565
7571
  writeStream = new PassThrough();
7566
7572
  resolveClosed;
7567
7573
  sessionId;
7574
+ legacyProtocolVersion;
7575
+ initializationRequestId;
7568
7576
  lastEventId;
7569
7577
  getSseStreamStarted = false;
7570
7578
  disposed = false;
@@ -7623,6 +7631,8 @@ var HttpTransport = class {
7623
7631
  const signals = [options.signal, deadline].filter((signal2) => signal2 !== void 0);
7624
7632
  const signal = signals.length === 0 ? new AbortController().signal : AbortSignal.any(signals);
7625
7633
  signal.throwIfAborted();
7634
+ if (options.protocolVersion !== void 0) this.legacyProtocolVersion = options.protocolVersion;
7635
+ this.maybeOpenGetSseStream();
7626
7636
  try {
7627
7637
  await this.sendPost(serializeJsonRpcMessage({ jsonrpc: "2.0", method: "notifications/initialized" }), signal);
7628
7638
  signal.throwIfAborted();
@@ -7751,8 +7761,13 @@ var HttpTransport = class {
7751
7761
  const metadata = isObjectRecord5(message?.params) ? message.params._meta : void 0;
7752
7762
  const modern = isObjectRecord5(metadata) && typeof metadata["io.modelcontextprotocol/protocolVersion"] === "string";
7753
7763
  if (modern) this.modernMode = true;
7754
- if (parsed.type === "request" && parsed.message.method === "initialize")
7764
+ if (parsed.type === "request" && parsed.message.method === "initialize") {
7755
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
+ }
7756
7771
  if (this.modernMode && parsed.type === "notification" && parsed.message.method === "notifications/cancelled") {
7757
7772
  const requestId = isObjectRecord5(parsed.message.params) ? parsed.message.params.requestId : void 0;
7758
7773
  if (typeof requestId === "string" || typeof requestId === "number")
@@ -7797,10 +7812,12 @@ var HttpTransport = class {
7797
7812
  }
7798
7813
  if (!modern && this.mode !== "sse") {
7799
7814
  this.captureSessionId(response);
7800
- this.maybeOpenGetSseStream();
7815
+ if (message?.method !== "initialize") this.maybeOpenGetSseStream();
7801
7816
  }
7802
- if (controller !== void 0) await this.forwardResponseMessages(response, controller.signal, parsed.type === "request" ? new HttpResponseMessages(parsed.message) : void 0);
7803
- 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
7804
7821
  void this.forwardResponseMessages(response).catch((error) => {
7805
7822
  this.dispose(error instanceof Error ? error : new Error(String(error)));
7806
7823
  });
@@ -7840,8 +7857,9 @@ var HttpTransport = class {
7840
7857
  }
7841
7858
  } else if (this.sessionId !== void 0) {
7842
7859
  headers.set("Mcp-Session-Id", this.sessionId);
7843
- headers.set("MCP-Protocol-Version", MCP_PROTOCOL_VERSION);
7844
7860
  }
7861
+ if (!modern && message?.method !== "initialize" && this.legacyProtocolVersion !== void 0)
7862
+ headers.set("MCP-Protocol-Version", this.legacyProtocolVersion);
7845
7863
  return this.authorizeRequestHeaders(headers, signal);
7846
7864
  }
7847
7865
  async createGetHeaders(signal) {
@@ -7849,8 +7867,8 @@ var HttpTransport = class {
7849
7867
  headers.set("Accept", "text/event-stream");
7850
7868
  if (this.sessionId !== void 0) {
7851
7869
  headers.set("Mcp-Session-Id", this.sessionId);
7852
- headers.set("MCP-Protocol-Version", MCP_PROTOCOL_VERSION);
7853
7870
  }
7871
+ if (this.legacyProtocolVersion !== void 0) headers.set("MCP-Protocol-Version", this.legacyProtocolVersion);
7854
7872
  if (this.lastEventId !== void 0) {
7855
7873
  headers.set("Last-Event-ID", this.lastEventId);
7856
7874
  }
@@ -7859,7 +7877,7 @@ var HttpTransport = class {
7859
7877
  async createDeleteHeaders(sessionId, signal) {
7860
7878
  const headers = new Headers(this.headers);
7861
7879
  headers.set("Mcp-Session-Id", sessionId);
7862
- headers.set("MCP-Protocol-Version", MCP_PROTOCOL_VERSION);
7880
+ headers.set("MCP-Protocol-Version", this.legacyProtocolVersion ?? MCP_PROTOCOL_VERSION);
7863
7881
  return this.authorizeRequestHeaders(headers, signal);
7864
7882
  }
7865
7883
  async authorizeRequestHeaders(headers, signal) {
@@ -7963,7 +7981,7 @@ var HttpTransport = class {
7963
7981
  return;
7964
7982
  }
7965
7983
  if (contentType.split(";")[0]?.trim().toLowerCase() === "text/event-stream") {
7966
- await this.forwardSseResponseMessages(response, void 0, void 0, this.mode === "sse");
7984
+ await this.forwardSseResponseMessages(response, void 0, void 0, { acceptEndpoint: this.mode === "sse" });
7967
7985
  if (this.mode === "sse") {
7968
7986
  if (!this.disposed) throw new Error("Legacy SSE stream ended");
7969
7987
  return;
@@ -8060,7 +8078,7 @@ var HttpTransport = class {
8060
8078
  throw error;
8061
8079
  }
8062
8080
  }
8063
- async forwardResponseMessages(response, signal, context) {
8081
+ async forwardResponseMessages(response, signal, context, initialization = false) {
8064
8082
  if (response.status === 202) {
8065
8083
  void response.body?.cancel().catch(() => void 0);
8066
8084
  return;
@@ -8072,7 +8090,7 @@ var HttpTransport = class {
8072
8090
  }
8073
8091
  const normalizedContentType = contentType.split(";")[0]?.trim().toLowerCase();
8074
8092
  if (normalizedContentType === "text/event-stream") {
8075
- await this.forwardSseResponseMessages(response, signal, context);
8093
+ await this.forwardSseResponseMessages(response, signal, context, { stopAfterInitialization: initialization });
8076
8094
  return;
8077
8095
  }
8078
8096
  if (normalizedContentType === "application/json") {
@@ -8082,11 +8100,11 @@ var HttpTransport = class {
8082
8100
  void response.body?.cancel().catch(() => void 0);
8083
8101
  throw new Error("HTTP transport POST returned an unsupported response content type");
8084
8102
  }
8085
- async forwardSseResponseMessages(response, signal, context, acceptEndpoint = false) {
8103
+ async forwardSseResponseMessages(response, signal, context, options = {}) {
8086
8104
  if (response.body === null) {
8087
8105
  return;
8088
8106
  }
8089
- const parser = new SseParser(this.maxResponseBytes, acceptEndpoint);
8107
+ const parser = new SseParser(this.maxResponseBytes, options.acceptEndpoint);
8090
8108
  const decoder = new TextDecoder("utf-8", { fatal: true });
8091
8109
  const reader = response.body.getReader();
8092
8110
  this.openResponseReaders.add(reader);
@@ -8107,7 +8125,7 @@ var HttpTransport = class {
8107
8125
  }
8108
8126
  const messages = parser.push(decoder.decode(value, { stream: true }));
8109
8127
  this.writeSseMessages(messages, context);
8110
- if (context?.completed) {
8128
+ if (context?.completed || options.stopAfterInitialization && this.initializationRequestId === void 0) {
8111
8129
  void reader.cancel().catch(() => void 0);
8112
8130
  return;
8113
8131
  }
@@ -8171,6 +8189,21 @@ var HttpTransport = class {
8171
8189
  if (this.disposed || this.readStream.destroyed || this.readStream.writableEnded) {
8172
8190
  return;
8173
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
+ }
8174
8207
  this.readStream.write(`${line}
8175
8208
  `);
8176
8209
  }
@@ -9111,6 +9144,7 @@ export {
9111
9144
  HttpTransport,
9112
9145
  HttpTransportError,
9113
9146
  JsonRpcMessageLayer,
9147
+ MCP_PROTOCOL_VERSIONS,
9114
9148
  McpClient,
9115
9149
  McpError,
9116
9150
  OAuthMetadataDiscovery,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tiny-http-mcp-server",
3
- "version": "0.1.51",
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",