toolcraft 0.0.345 → 0.0.347
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 +3 -3
- package/dist/composition.json +3 -3
- package/node_modules/tiny-http-mcp-server/dist/composition.json +1 -1
- package/node_modules/tiny-http-mcp-server/package.json +1 -1
- package/node_modules/tiny-mcp-client/README.md +24 -13
- package/node_modules/tiny-mcp-client/dist/index.d.ts +8 -1
- package/node_modules/tiny-mcp-client/dist/index.js +47 -20
- package/node_modules/tiny-stdio-mcp-server/dist/composition.json +1 -1
- package/node_modules/toolcraft-schema/package.json +1 -1
- package/package.json +2 -2
package/composition.json
CHANGED
|
@@ -98,7 +98,7 @@
|
|
|
98
98
|
},
|
|
99
99
|
{
|
|
100
100
|
"name": "tiny-http-mcp-server",
|
|
101
|
-
"version": "0.1.
|
|
101
|
+
"version": "0.1.75",
|
|
102
102
|
"license": "MIT"
|
|
103
103
|
},
|
|
104
104
|
{
|
|
@@ -113,7 +113,7 @@
|
|
|
113
113
|
},
|
|
114
114
|
{
|
|
115
115
|
"name": "toolcraft",
|
|
116
|
-
"version": "0.0.
|
|
116
|
+
"version": "0.0.347",
|
|
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.
|
|
126
|
+
"version": "0.0.347",
|
|
127
127
|
"license": "MIT"
|
|
128
128
|
},
|
|
129
129
|
{
|
package/dist/composition.json
CHANGED
|
@@ -98,7 +98,7 @@
|
|
|
98
98
|
},
|
|
99
99
|
{
|
|
100
100
|
"name": "tiny-http-mcp-server",
|
|
101
|
-
"version": "0.1.
|
|
101
|
+
"version": "0.1.75",
|
|
102
102
|
"license": "MIT"
|
|
103
103
|
},
|
|
104
104
|
{
|
|
@@ -113,7 +113,7 @@
|
|
|
113
113
|
},
|
|
114
114
|
{
|
|
115
115
|
"name": "toolcraft",
|
|
116
|
-
"version": "0.0.
|
|
116
|
+
"version": "0.0.347",
|
|
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.
|
|
126
|
+
"version": "0.0.347",
|
|
127
127
|
"license": "MIT"
|
|
128
128
|
},
|
|
129
129
|
{
|
|
@@ -66,6 +66,10 @@ validation when preparing a registry before constructing transports.
|
|
|
66
66
|
Receive streams may carry many bounded events and keepalive comments; the limit
|
|
67
67
|
does not cap their lifetime bytes. Use request deadlines and cancellation to
|
|
68
68
|
bound pending operations.
|
|
69
|
+
Receive reconnections retain the last completed event ID through events and
|
|
70
|
+
keepalives without IDs. An explicit empty `id:` clears the resume header,
|
|
71
|
+
including any initially configured value.
|
|
72
|
+
Unicode event IDs use UTF-8 bytes in `Last-Event-ID` headers.
|
|
69
73
|
HTTP failures expose `HttpTransportError.status` and `.method`, so callers can
|
|
70
74
|
make transport decisions without parsing error messages. Legacy HTTP/SSE
|
|
71
75
|
`connect()` also waits for the initialized notification POST to complete before
|
|
@@ -83,29 +87,36 @@ the same optional `closeReason` promise when closing requires asynchronous work.
|
|
|
83
87
|
`HttpTransport` accepts `oauth` options from `mcp-oauth`. When a protected server returns a Bearer `WWW-Authenticate` challenge, the transport discovers protected-resource metadata, loads authorization-server metadata, lets the OAuth provider handle authorization, and retries the request when credentials are available.
|
|
84
88
|
|
|
85
89
|
```ts
|
|
86
|
-
import { HttpTransport
|
|
90
|
+
import { HttpTransport } from "tiny-mcp-client";
|
|
87
91
|
|
|
88
92
|
const transport = new HttpTransport({
|
|
89
93
|
url: "https://mcp.example.com/mcp",
|
|
90
94
|
oauth: {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
clientName: "tiny-client"
|
|
96
|
-
}
|
|
97
|
-
},
|
|
98
|
-
browser: {
|
|
99
|
-
openBrowser: async (url) => {
|
|
100
|
-
console.log(`Open ${url}`);
|
|
101
|
-
}
|
|
95
|
+
client: {
|
|
96
|
+
mode: "dynamic",
|
|
97
|
+
metadata: {
|
|
98
|
+
clientName: "tiny-client"
|
|
102
99
|
}
|
|
103
|
-
}
|
|
100
|
+
},
|
|
101
|
+
browser: {
|
|
102
|
+
openBrowser: async (url) => {
|
|
103
|
+
console.log(`Open ${url}`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
104
106
|
}
|
|
105
107
|
});
|
|
106
108
|
```
|
|
107
109
|
|
|
108
110
|
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
|
+
Resource/issuer binding mismatches and exhausted authorization-server discovery
|
|
112
|
+
expose `OAuthMetadataError.phase` while retaining complete SDK messages.
|
|
113
|
+
Protected-resource metadata HTTP failures also expose their numeric `status`.
|
|
114
|
+
Rejected metadata bodies start cleanup without delaying failure or caller
|
|
115
|
+
cancellation. Host cleanup may finish later; its rejection remains observed.
|
|
116
|
+
`OAuthMetadataError.is(value)` recognizes separately bundled native copies.
|
|
117
|
+
Bearer challenges with repeated case-insensitive parameters fail before OAuth
|
|
118
|
+
recovery, including identical repeats. Their rejected response bodies are released
|
|
119
|
+
without reflecting parameter values in the diagnostic.
|
|
109
120
|
|
|
110
121
|
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.
|
|
111
122
|
|
|
@@ -304,6 +304,13 @@ interface OAuthMetadataLookupOptions {
|
|
|
304
304
|
resourceMetadataUrl?: string | URL;
|
|
305
305
|
signal?: AbortSignal;
|
|
306
306
|
}
|
|
307
|
+
/** Native metadata failure with complete SDK diagnostics and a safe phase. */
|
|
308
|
+
declare class OAuthMetadataError extends Error {
|
|
309
|
+
readonly phase: "protected-resource" | "authorization-server";
|
|
310
|
+
readonly status?: number | undefined;
|
|
311
|
+
static is(value: unknown): value is OAuthMetadataError;
|
|
312
|
+
constructor(phase: "protected-resource" | "authorization-server", message: string, status?: number | undefined);
|
|
313
|
+
}
|
|
307
314
|
declare class OAuthMetadataDiscovery {
|
|
308
315
|
private readonly fetchImpl;
|
|
309
316
|
private readonly cache;
|
|
@@ -874,5 +881,5 @@ declare class JsonRpcMessageLayer {
|
|
|
874
881
|
private handleCancellationNotification;
|
|
875
882
|
}
|
|
876
883
|
|
|
877
|
-
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, snapshotHttpTransportHeaders };
|
|
884
|
+
export { ERROR_INTERNAL, ERROR_INVALID_PARAMS, ERROR_INVALID_REQUEST, ERROR_METHOD_NOT_FOUND, ERROR_PARSE, HttpTransport, HttpTransportError, JsonRpcMessageLayer, MCP_PROTOCOL_VERSIONS, McpClient, McpError, OAuthMetadataDiscovery, OAuthMetadataError, StdioTransport, createInMemoryTransportPair, createSdkTestPair, createTestPair, discoverOAuthMetadata, fetchMcpResponse, snapshotHttpTransportHeaders };
|
|
878
885
|
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 };
|
|
@@ -6244,6 +6244,21 @@ function createParameterHeaders(definitions, argumentsValue) {
|
|
|
6244
6244
|
|
|
6245
6245
|
// src/oauth-discovery.ts
|
|
6246
6246
|
import { isIP as isIP2 } from "node:net";
|
|
6247
|
+
var metadataErrorBrand = /* @__PURE__ */ Symbol.for("poe-platform.tiny-mcp-client.OAuthMetadataError");
|
|
6248
|
+
var OAuthMetadataError = class extends Error {
|
|
6249
|
+
constructor(phase, message, status) {
|
|
6250
|
+
super(message);
|
|
6251
|
+
this.phase = phase;
|
|
6252
|
+
this.status = status;
|
|
6253
|
+
this.name = "OAuthMetadataError";
|
|
6254
|
+
Object.defineProperty(this, metadataErrorBrand, { value: true });
|
|
6255
|
+
}
|
|
6256
|
+
phase;
|
|
6257
|
+
status;
|
|
6258
|
+
static is(value) {
|
|
6259
|
+
return value instanceof Error && Object.getOwnPropertyDescriptor(value, metadataErrorBrand)?.value === true;
|
|
6260
|
+
}
|
|
6261
|
+
};
|
|
6247
6262
|
function defaultOAuthMetadataFetch(input, init) {
|
|
6248
6263
|
return fetch(input, init);
|
|
6249
6264
|
}
|
|
@@ -6281,7 +6296,8 @@ function validateProtectedResourceMetadata(value, resourceUrl) {
|
|
|
6281
6296
|
}
|
|
6282
6297
|
const normalizedResource = canonicalizeResourceIndicator(value.resource);
|
|
6283
6298
|
if (normalizedResource !== resourceUrl) {
|
|
6284
|
-
throw new
|
|
6299
|
+
throw new OAuthMetadataError(
|
|
6300
|
+
"protected-resource",
|
|
6285
6301
|
`Protected resource metadata resource mismatch: expected ${resourceUrl}, received ${value.resource}`
|
|
6286
6302
|
);
|
|
6287
6303
|
}
|
|
@@ -6303,7 +6319,8 @@ function validateAuthorizationServerMetadata(value, issuer) {
|
|
|
6303
6319
|
throw new Error("Authorization server metadata must include issuer");
|
|
6304
6320
|
}
|
|
6305
6321
|
if (value.issuer !== issuer) {
|
|
6306
|
-
throw new
|
|
6322
|
+
throw new OAuthMetadataError(
|
|
6323
|
+
"authorization-server",
|
|
6307
6324
|
`Authorization server metadata issuer mismatch: expected ${issuer}, received ${value.issuer}`
|
|
6308
6325
|
);
|
|
6309
6326
|
}
|
|
@@ -6345,11 +6362,12 @@ function validateAuthorizationServerMetadata(value, issuer) {
|
|
|
6345
6362
|
}
|
|
6346
6363
|
return value;
|
|
6347
6364
|
}
|
|
6348
|
-
async function readJsonResponse(response,
|
|
6365
|
+
async function readJsonResponse(response, phase, signal) {
|
|
6366
|
+
const label = phase === "protected-resource" ? "Protected resource metadata" : "Authorization server metadata";
|
|
6349
6367
|
if (!response.ok) {
|
|
6350
|
-
|
|
6368
|
+
void response.body?.cancel().catch(() => void 0);
|
|
6351
6369
|
const statusDescriptor = `${response.status} ${response.statusText}`.trim();
|
|
6352
|
-
throw new
|
|
6370
|
+
throw new OAuthMetadataError(phase, `${label} request failed (${statusDescriptor})`, response.status);
|
|
6353
6371
|
}
|
|
6354
6372
|
const text = await readBoundedResponseText(response, 1024 * 1024, void 0, signal);
|
|
6355
6373
|
try {
|
|
@@ -6358,7 +6376,7 @@ async function readJsonResponse(response, label, signal) {
|
|
|
6358
6376
|
throw new Error(`${label} response must be valid JSON`);
|
|
6359
6377
|
}
|
|
6360
6378
|
}
|
|
6361
|
-
async function fetchMetadata(fetch2, location,
|
|
6379
|
+
async function fetchMetadata(fetch2, location, phase, parentSignal) {
|
|
6362
6380
|
parentSignal?.throwIfAborted();
|
|
6363
6381
|
const deadline = AbortSignal.timeout(1e4);
|
|
6364
6382
|
const signal = parentSignal === void 0 ? deadline : AbortSignal.any([deadline, parentSignal]);
|
|
@@ -6367,7 +6385,7 @@ async function fetchMetadata(fetch2, location, label, parentSignal) {
|
|
|
6367
6385
|
headers: { Accept: "application/json" },
|
|
6368
6386
|
signal
|
|
6369
6387
|
});
|
|
6370
|
-
return readJsonResponse(response,
|
|
6388
|
+
return readJsonResponse(response, phase, signal);
|
|
6371
6389
|
}
|
|
6372
6390
|
function resolveWellKnownMetadataUrl(inputUrl, suffix) {
|
|
6373
6391
|
const url = new URL(typeof inputUrl === "string" ? inputUrl : inputUrl.toString());
|
|
@@ -6486,7 +6504,7 @@ var OAuthMetadataDiscovery = class {
|
|
|
6486
6504
|
for (const location of locations) {
|
|
6487
6505
|
try {
|
|
6488
6506
|
const metadata = validateProtectedResourceMetadata(
|
|
6489
|
-
await fetchMetadata(this.fetchImpl, location, "
|
|
6507
|
+
await fetchMetadata(this.fetchImpl, location, "protected-resource", signal),
|
|
6490
6508
|
resource
|
|
6491
6509
|
);
|
|
6492
6510
|
return { location, metadata };
|
|
@@ -6524,7 +6542,7 @@ var OAuthMetadataDiscovery = class {
|
|
|
6524
6542
|
for (const authorizationServerMetadataUrl of metadataLocations) {
|
|
6525
6543
|
try {
|
|
6526
6544
|
const authorizationServerMetadata = validateAuthorizationServerMetadata(
|
|
6527
|
-
await fetchMetadata(this.fetchImpl, authorizationServerMetadataUrl, "
|
|
6545
|
+
await fetchMetadata(this.fetchImpl, authorizationServerMetadataUrl, "authorization-server", signal),
|
|
6528
6546
|
normalizedAuthorizationServer
|
|
6529
6547
|
);
|
|
6530
6548
|
const result = {
|
|
@@ -6546,7 +6564,8 @@ var OAuthMetadataDiscovery = class {
|
|
|
6546
6564
|
}
|
|
6547
6565
|
}
|
|
6548
6566
|
}
|
|
6549
|
-
throw new
|
|
6567
|
+
throw new OAuthMetadataError(
|
|
6568
|
+
"authorization-server",
|
|
6550
6569
|
`Unable to load authorization server metadata for ${cacheKey}: ${authorizationServerErrors.join(
|
|
6551
6570
|
"; "
|
|
6552
6571
|
)}`
|
|
@@ -6712,7 +6731,11 @@ function parseBearerWwwAuthenticateHeader(headerValue) {
|
|
|
6712
6731
|
if (parsedParam === null) {
|
|
6713
6732
|
break;
|
|
6714
6733
|
}
|
|
6715
|
-
|
|
6734
|
+
const parameterName = parsedParam.name.toLowerCase();
|
|
6735
|
+
if (scheme.token.toLowerCase() === "bearer" && Object.hasOwn(params, parameterName)) {
|
|
6736
|
+
throw new Error("Bearer challenge must not repeat authentication parameters");
|
|
6737
|
+
}
|
|
6738
|
+
params[parameterName] = parsedParam.value;
|
|
6716
6739
|
index = skipOptionalWhitespace(headerValue, parsedParam.nextIndex);
|
|
6717
6740
|
if (headerValue[index] !== ",") {
|
|
6718
6741
|
break;
|
|
@@ -8004,7 +8027,8 @@ var HttpTransport = class {
|
|
|
8004
8027
|
}
|
|
8005
8028
|
if (this.legacyProtocolVersion !== void 0) headers.set("MCP-Protocol-Version", this.legacyProtocolVersion);
|
|
8006
8029
|
if (this.lastEventId !== void 0) {
|
|
8007
|
-
headers.
|
|
8030
|
+
if (this.lastEventId === "") headers.delete("Last-Event-ID");
|
|
8031
|
+
else headers.set("Last-Event-ID", Buffer.from(this.lastEventId, "utf8").toString("latin1"));
|
|
8008
8032
|
}
|
|
8009
8033
|
return this.authorizeRequestHeaders(headers, signal);
|
|
8010
8034
|
}
|
|
@@ -8177,9 +8201,9 @@ var HttpTransport = class {
|
|
|
8177
8201
|
if (discoveryClient === void 0) {
|
|
8178
8202
|
return false;
|
|
8179
8203
|
}
|
|
8180
|
-
const challenge = parseBearerWwwAuthenticateHeader(response.headers.get("WWW-Authenticate"));
|
|
8181
|
-
const resourceMetadataUrl = challenge?.params.resource_metadata;
|
|
8182
8204
|
try {
|
|
8205
|
+
const challenge = parseBearerWwwAuthenticateHeader(response.headers.get("WWW-Authenticate"));
|
|
8206
|
+
const resourceMetadataUrl = challenge?.params.resource_metadata;
|
|
8183
8207
|
const discovery = await discoveryClient.discover(this.url, { resourceMetadataUrl, signal });
|
|
8184
8208
|
const providerResponse = response.clone();
|
|
8185
8209
|
let result;
|
|
@@ -8263,15 +8287,15 @@ var HttpTransport = class {
|
|
|
8263
8287
|
void reader.cancel().catch(() => void 0);
|
|
8264
8288
|
return;
|
|
8265
8289
|
}
|
|
8266
|
-
this.lastEventId = parser.lastEventId;
|
|
8290
|
+
this.lastEventId = parser.lastEventId ?? this.lastEventId;
|
|
8267
8291
|
}
|
|
8268
8292
|
const trailingChunk = decoder.decode();
|
|
8269
8293
|
if (trailingChunk.length > 0) {
|
|
8270
8294
|
this.writeSseMessages(parser.push(trailingChunk), context);
|
|
8271
|
-
this.lastEventId = parser.lastEventId;
|
|
8295
|
+
this.lastEventId = parser.lastEventId ?? this.lastEventId;
|
|
8272
8296
|
}
|
|
8273
8297
|
this.writeSseMessages(parser.flush(), context);
|
|
8274
|
-
this.lastEventId = parser.lastEventId;
|
|
8298
|
+
this.lastEventId = parser.lastEventId ?? this.lastEventId;
|
|
8275
8299
|
if (context !== void 0 && !context.completed) throw new Error("MCP HTTP stream ended before its final response");
|
|
8276
8300
|
} catch (error) {
|
|
8277
8301
|
void reader.cancel().catch(() => void 0);
|
|
@@ -8361,10 +8385,12 @@ var HttpTransport = class {
|
|
|
8361
8385
|
let attempt = await request();
|
|
8362
8386
|
if (await this.maybeHandleUnauthorizedResponse(attempt.response, controller.signal, attempt.headers, attempt.tokens)) attempt = await request();
|
|
8363
8387
|
const response = attempt.response;
|
|
8364
|
-
|
|
8365
|
-
|
|
8388
|
+
try {
|
|
8389
|
+
const oauthError = this.oauthProvider === void 0 ? null : this.readOAuthChallengeError(response);
|
|
8390
|
+
if (oauthError !== null) throw oauthError;
|
|
8391
|
+
} catch (error) {
|
|
8366
8392
|
void response.body?.cancel().catch(() => void 0);
|
|
8367
|
-
throw
|
|
8393
|
+
throw error;
|
|
8368
8394
|
}
|
|
8369
8395
|
return response;
|
|
8370
8396
|
} finally {
|
|
@@ -9282,6 +9308,7 @@ export {
|
|
|
9282
9308
|
McpClient,
|
|
9283
9309
|
McpError,
|
|
9284
9310
|
OAuthMetadataDiscovery,
|
|
9311
|
+
OAuthMetadataError,
|
|
9285
9312
|
StdioTransport,
|
|
9286
9313
|
createInMemoryTransportPair,
|
|
9287
9314
|
createSdkTestPair,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "toolcraft",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.347",
|
|
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.
|
|
161
|
+
"toolcraft-schema": "0.0.347",
|
|
162
162
|
"toolcraft-design": "*",
|
|
163
163
|
"@poe-code/frontmatter": "*",
|
|
164
164
|
"@poe-code/agent-mcp-config": "*",
|