toolcraft 0.0.346 → 0.0.348

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.
package/composition.json CHANGED
@@ -98,7 +98,7 @@
98
98
  },
99
99
  {
100
100
  "name": "tiny-http-mcp-server",
101
- "version": "0.1.74",
101
+ "version": "0.1.76",
102
102
  "license": "MIT"
103
103
  },
104
104
  {
@@ -113,7 +113,7 @@
113
113
  },
114
114
  {
115
115
  "name": "toolcraft",
116
- "version": "0.0.346",
116
+ "version": "0.0.348",
117
117
  "license": "MIT"
118
118
  },
119
119
  {
@@ -123,7 +123,7 @@
123
123
  },
124
124
  {
125
125
  "name": "toolcraft-schema",
126
- "version": "0.0.346",
126
+ "version": "0.0.348",
127
127
  "license": "MIT"
128
128
  },
129
129
  {
@@ -98,7 +98,7 @@
98
98
  },
99
99
  {
100
100
  "name": "tiny-http-mcp-server",
101
- "version": "0.1.74",
101
+ "version": "0.1.76",
102
102
  "license": "MIT"
103
103
  },
104
104
  {
@@ -113,7 +113,7 @@
113
113
  },
114
114
  {
115
115
  "name": "toolcraft",
116
- "version": "0.0.346",
116
+ "version": "0.0.348",
117
117
  "license": "MIT"
118
118
  },
119
119
  {
@@ -123,7 +123,7 @@
123
123
  },
124
124
  {
125
125
  "name": "toolcraft-schema",
126
- "version": "0.0.346",
126
+ "version": "0.0.348",
127
127
  "license": "MIT"
128
128
  },
129
129
  {
@@ -18,7 +18,7 @@
18
18
  },
19
19
  {
20
20
  "name": "tiny-http-mcp-server",
21
- "version": "0.1.74",
21
+ "version": "0.1.76",
22
22
  "license": "MIT"
23
23
  },
24
24
  {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tiny-http-mcp-server",
3
- "version": "0.1.74",
3
+ "version": "0.1.76",
4
4
  "description": "Minimal MCP server over HTTP built on tiny-stdio-mcp-server",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -36,6 +36,9 @@ Unsupported pins fail before connection setup.
36
36
  `Tool` includes MCP `outputSchema` when a server advertises typed tool output.
37
37
  `CallToolResult.structuredContent` preserves modern JSON values; legacy servers
38
38
  require an object. Complete `content[]` blocks remain available in either case.
39
+ `callTool` captures its signal and progress token when called. Later edits to
40
+ the options object cannot leave a finished call's progress token active; progress
41
+ notifications remain available while that call is pending.
39
42
 
40
43
  Set `requestTimeoutMs` on `McpClient` or `timeoutMs` on individual requests.
41
44
  Numeric deadlines must be finite, nonnegative and no greater than
@@ -110,7 +113,16 @@ const transport = new HttpTransport({
110
113
  You can also call `discoverOAuthMetadata(resourceUrl, options)` directly, or instantiate `OAuthMetadataDiscovery` with a custom `fetch` implementation and shared cache. An explicit `resourceMetadataUrl` requires fresh network discovery without reading either cache; validated results still populate both caches. Lookup options accept `signal`; cancellation stops metadata fetches and body reads without trying another discovery candidate. It also settles while shared-cache reads, writes or eviction wait. Host cache work may finish afterward; its late rejection remains observed, and canceled discovery does not start another candidate.
111
114
  Resource/issuer binding mismatches and exhausted authorization-server discovery
112
115
  expose `OAuthMetadataError.phase` while retaining complete SDK messages.
116
+ Protected-resource metadata HTTP failures also expose their numeric `status`.
117
+ Advertised resource identities reject named and empty fragments before issuer
118
+ discovery; malformed shared-cache identities are evicted. Resource queries and
119
+ percent-escaped hash data remain part of the exact resource identity.
120
+ Rejected metadata bodies start cleanup without delaying failure or caller
121
+ cancellation. Host cleanup may finish later; its rejection remains observed.
113
122
  `OAuthMetadataError.is(value)` recognizes separately bundled native copies.
123
+ Bearer challenges with repeated case-insensitive parameters fail before OAuth
124
+ recovery, including identical repeats. Their rejected response bodies are released
125
+ without reflecting parameter values in the diagnostic.
114
126
 
115
127
  OAuth provider inputs receive the originating request's `signal`, covering header authorization and unauthorized handling. Modern request cancellation stops its OAuth work while leaving other requests usable; transport disposal cancels all pending OAuth operations. The default provider propagates this signal to callback, registration and token work. Custom providers must observe it for their own operations.
116
128
 
@@ -307,8 +307,9 @@ interface OAuthMetadataLookupOptions {
307
307
  /** Native metadata failure with complete SDK diagnostics and a safe phase. */
308
308
  declare class OAuthMetadataError extends Error {
309
309
  readonly phase: "protected-resource" | "authorization-server";
310
+ readonly status?: number | undefined;
310
311
  static is(value: unknown): value is OAuthMetadataError;
311
- constructor(phase: "protected-resource" | "authorization-server", message: string);
312
+ constructor(phase: "protected-resource" | "authorization-server", message: string, status?: number | undefined);
312
313
  }
313
314
  declare class OAuthMetadataDiscovery {
314
315
  private readonly fetchImpl;
@@ -6246,13 +6246,15 @@ function createParameterHeaders(definitions, argumentsValue) {
6246
6246
  import { isIP as isIP2 } from "node:net";
6247
6247
  var metadataErrorBrand = /* @__PURE__ */ Symbol.for("poe-platform.tiny-mcp-client.OAuthMetadataError");
6248
6248
  var OAuthMetadataError = class extends Error {
6249
- constructor(phase, message) {
6249
+ constructor(phase, message, status) {
6250
6250
  super(message);
6251
6251
  this.phase = phase;
6252
+ this.status = status;
6252
6253
  this.name = "OAuthMetadataError";
6253
6254
  Object.defineProperty(this, metadataErrorBrand, { value: true });
6254
6255
  }
6255
6256
  phase;
6257
+ status;
6256
6258
  static is(value) {
6257
6259
  return value instanceof Error && Object.getOwnPropertyDescriptor(value, metadataErrorBrand)?.value === true;
6258
6260
  }
@@ -6292,6 +6294,9 @@ function validateProtectedResourceMetadata(value, resourceUrl) {
6292
6294
  if (typeof value.resource !== "string" || value.resource.length === 0) {
6293
6295
  throw new Error("Protected resource metadata must include a resource string");
6294
6296
  }
6297
+ if (value.resource.includes("#")) {
6298
+ throw new OAuthMetadataError("protected-resource", "Protected resource metadata resource must not include fragment");
6299
+ }
6295
6300
  const normalizedResource = canonicalizeResourceIndicator(value.resource);
6296
6301
  if (normalizedResource !== resourceUrl) {
6297
6302
  throw new OAuthMetadataError(
@@ -6360,11 +6365,12 @@ function validateAuthorizationServerMetadata(value, issuer) {
6360
6365
  }
6361
6366
  return value;
6362
6367
  }
6363
- async function readJsonResponse(response, label, signal) {
6368
+ async function readJsonResponse(response, phase, signal) {
6369
+ const label = phase === "protected-resource" ? "Protected resource metadata" : "Authorization server metadata";
6364
6370
  if (!response.ok) {
6365
- await response.body?.cancel().catch(() => void 0);
6371
+ void response.body?.cancel().catch(() => void 0);
6366
6372
  const statusDescriptor = `${response.status} ${response.statusText}`.trim();
6367
- throw new Error(`${label} request failed (${statusDescriptor})`);
6373
+ throw new OAuthMetadataError(phase, `${label} request failed (${statusDescriptor})`, response.status);
6368
6374
  }
6369
6375
  const text = await readBoundedResponseText(response, 1024 * 1024, void 0, signal);
6370
6376
  try {
@@ -6373,7 +6379,7 @@ async function readJsonResponse(response, label, signal) {
6373
6379
  throw new Error(`${label} response must be valid JSON`);
6374
6380
  }
6375
6381
  }
6376
- async function fetchMetadata(fetch2, location, label, parentSignal) {
6382
+ async function fetchMetadata(fetch2, location, phase, parentSignal) {
6377
6383
  parentSignal?.throwIfAborted();
6378
6384
  const deadline = AbortSignal.timeout(1e4);
6379
6385
  const signal = parentSignal === void 0 ? deadline : AbortSignal.any([deadline, parentSignal]);
@@ -6382,7 +6388,7 @@ async function fetchMetadata(fetch2, location, label, parentSignal) {
6382
6388
  headers: { Accept: "application/json" },
6383
6389
  signal
6384
6390
  });
6385
- return readJsonResponse(response, label, signal);
6391
+ return readJsonResponse(response, phase, signal);
6386
6392
  }
6387
6393
  function resolveWellKnownMetadataUrl(inputUrl, suffix) {
6388
6394
  const url = new URL(typeof inputUrl === "string" ? inputUrl : inputUrl.toString());
@@ -6501,7 +6507,7 @@ var OAuthMetadataDiscovery = class {
6501
6507
  for (const location of locations) {
6502
6508
  try {
6503
6509
  const metadata = validateProtectedResourceMetadata(
6504
- await fetchMetadata(this.fetchImpl, location, "Protected resource metadata", signal),
6510
+ await fetchMetadata(this.fetchImpl, location, "protected-resource", signal),
6505
6511
  resource
6506
6512
  );
6507
6513
  return { location, metadata };
@@ -6539,7 +6545,7 @@ var OAuthMetadataDiscovery = class {
6539
6545
  for (const authorizationServerMetadataUrl of metadataLocations) {
6540
6546
  try {
6541
6547
  const authorizationServerMetadata = validateAuthorizationServerMetadata(
6542
- await fetchMetadata(this.fetchImpl, authorizationServerMetadataUrl, "Authorization server metadata", signal),
6548
+ await fetchMetadata(this.fetchImpl, authorizationServerMetadataUrl, "authorization-server", signal),
6543
6549
  normalizedAuthorizationServer
6544
6550
  );
6545
6551
  const result = {
@@ -6728,7 +6734,11 @@ function parseBearerWwwAuthenticateHeader(headerValue) {
6728
6734
  if (parsedParam === null) {
6729
6735
  break;
6730
6736
  }
6731
- params[parsedParam.name.toLowerCase()] = parsedParam.value;
6737
+ const parameterName = parsedParam.name.toLowerCase();
6738
+ if (scheme.token.toLowerCase() === "bearer" && Object.hasOwn(params, parameterName)) {
6739
+ throw new Error("Bearer challenge must not repeat authentication parameters");
6740
+ }
6741
+ params[parameterName] = parsedParam.value;
6732
6742
  index = skipOptionalWhitespace(headerValue, parsedParam.nextIndex);
6733
6743
  if (headerValue[index] !== ",") {
6734
6744
  break;
@@ -7109,6 +7119,7 @@ var McpClient = class {
7109
7119
  };
7110
7120
  }
7111
7121
  async callTool(params, options = {}) {
7122
+ options = { ...options };
7112
7123
  const messageLayer = this.getMessageLayerOrThrow();
7113
7124
  const serverCapabilities = this.getServerCapabilitiesOrThrow();
7114
7125
  if (serverCapabilities.tools === void 0) {
@@ -8194,9 +8205,9 @@ var HttpTransport = class {
8194
8205
  if (discoveryClient === void 0) {
8195
8206
  return false;
8196
8207
  }
8197
- const challenge = parseBearerWwwAuthenticateHeader(response.headers.get("WWW-Authenticate"));
8198
- const resourceMetadataUrl = challenge?.params.resource_metadata;
8199
8208
  try {
8209
+ const challenge = parseBearerWwwAuthenticateHeader(response.headers.get("WWW-Authenticate"));
8210
+ const resourceMetadataUrl = challenge?.params.resource_metadata;
8200
8211
  const discovery = await discoveryClient.discover(this.url, { resourceMetadataUrl, signal });
8201
8212
  const providerResponse = response.clone();
8202
8213
  let result;
@@ -8378,10 +8389,12 @@ var HttpTransport = class {
8378
8389
  let attempt = await request();
8379
8390
  if (await this.maybeHandleUnauthorizedResponse(attempt.response, controller.signal, attempt.headers, attempt.tokens)) attempt = await request();
8380
8391
  const response = attempt.response;
8381
- const oauthError = this.oauthProvider === void 0 ? null : this.readOAuthChallengeError(response);
8382
- if (oauthError !== null) {
8392
+ try {
8393
+ const oauthError = this.oauthProvider === void 0 ? null : this.readOAuthChallengeError(response);
8394
+ if (oauthError !== null) throw oauthError;
8395
+ } catch (error) {
8383
8396
  void response.body?.cancel().catch(() => void 0);
8384
- throw oauthError;
8397
+ throw error;
8385
8398
  }
8386
8399
  return response;
8387
8400
  } finally {
@@ -8,7 +8,7 @@
8
8
  },
9
9
  {
10
10
  "name": "toolcraft-schema",
11
- "version": "0.0.346",
11
+ "version": "0.0.348",
12
12
  "license": "MIT"
13
13
  }
14
14
  ]
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "toolcraft-schema",
3
- "version": "0.0.346",
3
+ "version": "0.0.348",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "toolcraft",
3
- "version": "0.0.346",
3
+ "version": "0.0.348",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -158,7 +158,7 @@
158
158
  "yaml"
159
159
  ],
160
160
  "optionalDependencies": {
161
- "toolcraft-schema": "0.0.346",
161
+ "toolcraft-schema": "0.0.348",
162
162
  "toolcraft-design": "*",
163
163
  "@poe-code/frontmatter": "*",
164
164
  "@poe-code/agent-mcp-config": "*",