toolcraft 0.0.347 → 0.0.349
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/node_modules/mcp-oauth/README.md +2 -0
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/client/loopback-authorization.js +1 -1
- package/node_modules/tiny-http-mcp-server/package.json +1 -1
- package/node_modules/tiny-mcp-client/README.md +12 -0
- package/node_modules/tiny-mcp-client/dist/index.js +10 -16
- 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.78",
|
|
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.349",
|
|
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.349",
|
|
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.78",
|
|
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.349",
|
|
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.349",
|
|
127
127
|
"license": "MIT"
|
|
128
128
|
},
|
|
129
129
|
{
|
|
@@ -92,6 +92,8 @@ Fixed redirects support `localhost`, `127.0.0.1`, and `::1` over HTTP. Their
|
|
|
92
92
|
exact spelling, port, path and query are preserved through registration,
|
|
93
93
|
authorization and code exchange. Credentials, fragments, port zero and reserved
|
|
94
94
|
OAuth callback query parameters, including `error_uri`, are rejected before binding a listener.
|
|
95
|
+
Fragment rejection includes a trailing empty `#`. Empty queries and percent-escaped
|
|
96
|
+
hash data remain valid and keep their exact registered spelling.
|
|
95
97
|
`createDefaultOAuthClientProvider` also checks the configured redirect before
|
|
96
98
|
creating the provider. Imported tokens that cannot be sent as HTTP header
|
|
97
99
|
values fail with diagnostics that omit their contents. Omit
|
|
@@ -86,7 +86,7 @@ export function loopbackTarget(options) {
|
|
|
86
86
|
throw new Error("Invalid OAuth loopback redirect URI", { cause });
|
|
87
87
|
}
|
|
88
88
|
if (url.protocol !== "http:" || !["localhost", "127.0.0.1", "[::1]"].includes(url.hostname)
|
|
89
|
-
|| url.username || url.password || url.
|
|
89
|
+
|| url.username || url.password || url.href.includes("#") || url.port === "0"
|
|
90
90
|
|| oauthCallbackParameters.some(name => url.searchParams.has(name))
|
|
91
91
|
|| [...options.redirectUri].some(char => char.codePointAt(0) <= 32)
|
|
92
92
|
|| (options.callbackPath !== undefined && options.callbackPath !== url.pathname))
|
|
@@ -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
|
|
@@ -57,6 +60,8 @@ timer; a timeout releases request capacity so later operations can proceed.
|
|
|
57
60
|
Legacy SSE mode opens a GET stream and posts messages to the endpoint announced
|
|
58
61
|
by the server. Announced endpoints must remain on the original origin without
|
|
59
62
|
embedded credentials or fragments; endpoint changes close the connection.
|
|
63
|
+
Empty fragment delimiters are rejected too; escaped hashes in an endpoint path
|
|
64
|
+
or query remain literal data.
|
|
60
65
|
Both transports accept the same headers, OAuth provider and response limits.
|
|
61
66
|
Static HTTP headers are copied and validated when the transport is constructed,
|
|
62
67
|
before OAuth callbacks run. Invalid headers fail without reflecting their values.
|
|
@@ -111,6 +116,13 @@ You can also call `discoverOAuthMetadata(resourceUrl, options)` directly, or ins
|
|
|
111
116
|
Resource/issuer binding mismatches and exhausted authorization-server discovery
|
|
112
117
|
expose `OAuthMetadataError.phase` while retaining complete SDK messages.
|
|
113
118
|
Protected-resource metadata HTTP failures also expose their numeric `status`.
|
|
119
|
+
Advertised resource identities reject named and empty fragments before issuer
|
|
120
|
+
discovery; malformed shared-cache identities are evicted. Resource queries and
|
|
121
|
+
percent-escaped hash data remain part of the exact resource identity.
|
|
122
|
+
Discovery lookup, metadata and endpoint URLs reject empty fragments too.
|
|
123
|
+
Issuer identifiers reject named or empty query/fragment components; escaped
|
|
124
|
+
delimiters in their paths remain valid. Original lookup fragments fail before
|
|
125
|
+
cache access, and cached metadata locations with empty fragments are evicted.
|
|
114
126
|
Rejected metadata bodies start cleanup without delaying failure or caller
|
|
115
127
|
cancellation. Host cleanup may finish later; its rejection remains observed.
|
|
116
128
|
`OAuthMetadataError.is(value)` recognizes separately bundled native copies.
|
|
@@ -3601,7 +3601,7 @@ function loopbackTarget(options) {
|
|
|
3601
3601
|
} catch (cause) {
|
|
3602
3602
|
throw new Error("Invalid OAuth loopback redirect URI", { cause });
|
|
3603
3603
|
}
|
|
3604
|
-
if (url.protocol !== "http:" || !["localhost", "127.0.0.1", "[::1]"].includes(url.hostname) || url.username || url.password || url.
|
|
3604
|
+
if (url.protocol !== "http:" || !["localhost", "127.0.0.1", "[::1]"].includes(url.hostname) || url.username || url.password || url.href.includes("#") || url.port === "0" || oauthCallbackParameters.some((name) => url.searchParams.has(name)) || [...options.redirectUri].some((char) => char.codePointAt(0) <= 32) || options.callbackPath !== void 0 && options.callbackPath !== url.pathname)
|
|
3605
3605
|
throw new Error("Invalid OAuth loopback redirect URI");
|
|
3606
3606
|
return { port: url.port ? Number(url.port) : 80, host: url.hostname === "[::1]" ? "::1" : url.hostname, callbackPath: url.pathname };
|
|
3607
3607
|
}
|
|
@@ -6276,7 +6276,7 @@ function isLoopbackHostname2(hostname2) {
|
|
|
6276
6276
|
return normalizedHostname === "localhost" || normalizedHostname === "::1" || normalizedHostname === "[::1]" || isIP2(normalizedHostname) === 4 && normalizedHostname.startsWith("127.");
|
|
6277
6277
|
}
|
|
6278
6278
|
function assertSecureUrl2(url, label) {
|
|
6279
|
-
if (url.username !== "" || url.password !== "" || url.
|
|
6279
|
+
if (url.username !== "" || url.password !== "" || url.href.includes("#")) {
|
|
6280
6280
|
throw new Error(`${label} must not include credentials or fragment`);
|
|
6281
6281
|
}
|
|
6282
6282
|
if (url.protocol === "https:") {
|
|
@@ -6294,6 +6294,9 @@ function validateProtectedResourceMetadata(value, resourceUrl) {
|
|
|
6294
6294
|
if (typeof value.resource !== "string" || value.resource.length === 0) {
|
|
6295
6295
|
throw new Error("Protected resource metadata must include a resource string");
|
|
6296
6296
|
}
|
|
6297
|
+
if (value.resource.includes("#")) {
|
|
6298
|
+
throw new OAuthMetadataError("protected-resource", "Protected resource metadata resource must not include fragment");
|
|
6299
|
+
}
|
|
6297
6300
|
const normalizedResource = canonicalizeResourceIndicator(value.resource);
|
|
6298
6301
|
if (normalizedResource !== resourceUrl) {
|
|
6299
6302
|
throw new OAuthMetadataError(
|
|
@@ -6343,11 +6346,6 @@ function validateAuthorizationServerMetadata(value, issuer) {
|
|
|
6343
6346
|
} catch {
|
|
6344
6347
|
throw new Error(`Authorization server metadata ${field} must be an absolute URL`);
|
|
6345
6348
|
}
|
|
6346
|
-
if (endpoint.username !== "" || endpoint.password !== "" || endpoint.hash !== "") {
|
|
6347
|
-
throw new Error(
|
|
6348
|
-
`Authorization server metadata ${field} must not include credentials or fragment`
|
|
6349
|
-
);
|
|
6350
|
-
}
|
|
6351
6349
|
assertSecureUrl2(endpoint, `Authorization server metadata ${field}`);
|
|
6352
6350
|
}
|
|
6353
6351
|
if (!isStringArray(value.response_types_supported) || !value.response_types_supported.includes("code")) {
|
|
@@ -6394,7 +6392,7 @@ function resolveWellKnownMetadataUrl(inputUrl, suffix) {
|
|
|
6394
6392
|
return url.toString();
|
|
6395
6393
|
}
|
|
6396
6394
|
function resolveProtectedResourceMetadataUrl(resourceUrl, resourceMetadataUrl) {
|
|
6397
|
-
const resource = new URL(
|
|
6395
|
+
const resource = new URL(typeof resourceUrl === "string" ? resourceUrl : resourceUrl.toString());
|
|
6398
6396
|
assertSecureUrl2(resource, "Protected resource URL");
|
|
6399
6397
|
if (resourceMetadataUrl !== void 0) {
|
|
6400
6398
|
const resolvedResourceMetadataUrl2 = new URL(
|
|
@@ -6413,7 +6411,7 @@ function resolveProtectedResourceMetadataUrl(resourceUrl, resourceMetadataUrl) {
|
|
|
6413
6411
|
function validateAuthorizationServerIssuer(issuer) {
|
|
6414
6412
|
const input = typeof issuer === "string" ? issuer : issuer.toString();
|
|
6415
6413
|
const url = new URL(input);
|
|
6416
|
-
if (url.
|
|
6414
|
+
if (url.href.includes("?") || url.href.includes("#")) {
|
|
6417
6415
|
throw new Error("Authorization server issuer must not include query or fragment");
|
|
6418
6416
|
}
|
|
6419
6417
|
assertSecureUrl2(url, "Authorization server issuer");
|
|
@@ -6447,11 +6445,6 @@ function validateCachedDiscovery(value, resource) {
|
|
|
6447
6445
|
}
|
|
6448
6446
|
const resourceMetadata = validateProtectedResourceMetadata(value.resourceMetadata, resource);
|
|
6449
6447
|
const resourceMetadataLocation = new URL(value.resourceMetadataUrl);
|
|
6450
|
-
if (resourceMetadataLocation.username !== "" || resourceMetadataLocation.password !== "" || resourceMetadataLocation.hash !== "") {
|
|
6451
|
-
throw new Error(
|
|
6452
|
-
"Cached OAuth discovery metadata location must not include credentials or fragment"
|
|
6453
|
-
);
|
|
6454
|
-
}
|
|
6455
6448
|
assertSecureUrl2(resourceMetadataLocation, "Cached OAuth discovery metadata location");
|
|
6456
6449
|
const issuer = validateAuthorizationServerIssuer(value.authorizationServer);
|
|
6457
6450
|
if (!resourceMetadata.authorization_servers.includes(issuer)) {
|
|
@@ -6518,7 +6511,7 @@ var OAuthMetadataDiscovery = class {
|
|
|
6518
6511
|
async discover(resourceUrl, { resourceMetadataUrl, signal } = {}) {
|
|
6519
6512
|
signal?.throwIfAborted();
|
|
6520
6513
|
const cacheKey = canonicalizeResourceIndicator(resourceUrl);
|
|
6521
|
-
resolveProtectedResourceMetadataUrl(
|
|
6514
|
+
resolveProtectedResourceMetadataUrl(resourceUrl, resourceMetadataUrl);
|
|
6522
6515
|
const memoryCachedResult = this.memoryCache.get(cacheKey);
|
|
6523
6516
|
if (memoryCachedResult !== void 0 && resourceMetadataUrl === void 0) {
|
|
6524
6517
|
return structuredClone(memoryCachedResult);
|
|
@@ -7116,6 +7109,7 @@ var McpClient = class {
|
|
|
7116
7109
|
};
|
|
7117
7110
|
}
|
|
7118
7111
|
async callTool(params, options = {}) {
|
|
7112
|
+
options = { ...options };
|
|
7119
7113
|
const messageLayer = this.getMessageLayerOrThrow();
|
|
7120
7114
|
const serverCapabilities = this.getServerCapabilitiesOrThrow();
|
|
7121
7115
|
if (serverCapabilities.tools === void 0) {
|
|
@@ -8329,7 +8323,7 @@ var HttpTransport = class {
|
|
|
8329
8323
|
if (message.event === "endpoint") {
|
|
8330
8324
|
const endpoint = new URL(message.data, this.url);
|
|
8331
8325
|
const resource = new URL(this.url);
|
|
8332
|
-
if (endpoint.protocol !== "http:" && endpoint.protocol !== "https:" || endpoint.origin !== resource.origin || endpoint.username || endpoint.password || endpoint.
|
|
8326
|
+
if (endpoint.protocol !== "http:" && endpoint.protocol !== "https:" || endpoint.origin !== resource.origin || endpoint.username || endpoint.password || endpoint.href.includes("#"))
|
|
8333
8327
|
throw new Error("Unsafe legacy SSE endpoint");
|
|
8334
8328
|
if (this.legacyEndpoint !== void 0 && this.legacyEndpoint !== endpoint.href)
|
|
8335
8329
|
throw new Error("Legacy SSE endpoint changed during the active connection");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "toolcraft",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.349",
|
|
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.349",
|
|
162
162
|
"toolcraft-design": "*",
|
|
163
163
|
"@poe-code/frontmatter": "*",
|
|
164
164
|
"@poe-code/agent-mcp-config": "*",
|