toolcraft 0.0.317 → 0.0.319
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 +8 -0
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/client/default-oauth-client-provider.js +20 -0
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/client/resource-bound-store.js +13 -3
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/client/types.d.ts +8 -0
- package/node_modules/tiny-http-mcp-server/package.json +1 -1
- package/node_modules/tiny-mcp-client/README.md +4 -1
- package/node_modules/tiny-mcp-client/dist/index.d.ts +19 -1
- package/node_modules/tiny-mcp-client/dist/index.js +56 -8
- 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.40",
|
|
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.319",
|
|
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.319",
|
|
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.40",
|
|
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.319",
|
|
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.319",
|
|
127
127
|
"license": "MIT"
|
|
128
128
|
},
|
|
129
129
|
{
|
|
@@ -95,6 +95,14 @@ without redeeming its refresh token again. A proven current token is refreshed
|
|
|
95
95
|
on 401 even when the server omits `error="invalid_token"`. Invalid provenance
|
|
96
96
|
fails without quoting token values.
|
|
97
97
|
|
|
98
|
+
The native provider also exposes `authenticate({ requestUrl, fetch, signal,
|
|
99
|
+
discover })` for explicit login, including servers whose initialization is
|
|
100
|
+
public. `discover` lazily supplies validated OAuth metadata and is skipped for
|
|
101
|
+
usable existing grants. Omit it to recover/reuse known sessions only; the method
|
|
102
|
+
returns `void` if a new discovery lookup is needed. It honors `allowInteractive`,
|
|
103
|
+
recovers pending refresh outcomes through consent, and returns an owned token
|
|
104
|
+
snapshot. Normal transport request authorization remains noninteractive.
|
|
105
|
+
|
|
98
106
|
Configure `client.metadata.scope` to request a precise scope set; broader
|
|
99
107
|
discovery metadata does not override it. Explicit scopes must match the cached
|
|
100
108
|
or imported grant's scope set; ordering, repeated spaces and duplicates are
|
|
@@ -66,6 +66,26 @@ export function createDefaultOAuthClientProvider(options) {
|
|
|
66
66
|
}
|
|
67
67
|
let initialGrantConsumed = false;
|
|
68
68
|
return {
|
|
69
|
+
async authenticate(input) {
|
|
70
|
+
input.signal?.throwIfAborted();
|
|
71
|
+
assertNoAccessTokenInUrl(input.requestUrl, "Protected resource request URL");
|
|
72
|
+
const resource = canonicalizeResourceIndicator(input.requestUrl);
|
|
73
|
+
let session = await ensureAuthorizedSession(resource, undefined, input.fetch, true, false, input.signal);
|
|
74
|
+
if (session?.tokens !== undefined && !isExpired(session.tokens, now))
|
|
75
|
+
return { ...session.tokens };
|
|
76
|
+
if (session === null && !initialGrantConsumed && initialGrant?.resource === resource &&
|
|
77
|
+
initialGrant.tokens !== undefined && !isExpired(initialGrant.tokens, now))
|
|
78
|
+
return { ...initialGrant.tokens };
|
|
79
|
+
if (input.discover === undefined)
|
|
80
|
+
return;
|
|
81
|
+
const discovery = await input.discover();
|
|
82
|
+
input.signal?.throwIfAborted();
|
|
83
|
+
assertRequestMatchesResource(resource, canonicalizeResourceIndicator(discovery.resource));
|
|
84
|
+
session = await ensureAuthorizedSession(resource, discovery, input.fetch, true, false, input.signal);
|
|
85
|
+
if (session?.tokens === undefined || isExpired(session.tokens, now))
|
|
86
|
+
throw new Error("OAuth authentication did not establish a usable grant");
|
|
87
|
+
return { ...session.tokens };
|
|
88
|
+
},
|
|
69
89
|
async authorizeRequest(input) {
|
|
70
90
|
assertNoAccessTokenInUrl(input.requestUrl, "Protected resource request URL");
|
|
71
91
|
const requestUrl = canonicalizeResourceIndicator(input.requestUrl);
|
package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/client/resource-bound-store.js
CHANGED
|
@@ -65,12 +65,22 @@ export function createResourceBoundOAuthStores(options, namespace, identity) {
|
|
|
65
65
|
return record;
|
|
66
66
|
}
|
|
67
67
|
result.sessionStore = {
|
|
68
|
-
async withLock(
|
|
68
|
+
async withLock(resource, operation, options) {
|
|
69
69
|
if (store.withLock === undefined)
|
|
70
70
|
throw new Error("OAuth resource identity backend must support transaction locks");
|
|
71
|
-
return store.withLock(
|
|
71
|
+
return store.withLock(async () => {
|
|
72
|
+
options.signal?.throwIfAborted();
|
|
73
|
+
await reconcile(resource);
|
|
74
|
+
options.signal?.throwIfAborted();
|
|
75
|
+
return operation();
|
|
76
|
+
}, options);
|
|
77
|
+
},
|
|
78
|
+
async load(resource) {
|
|
79
|
+
// Unauthorized provenance may peek before acquiring the transaction lock.
|
|
80
|
+
// Only the lock owner may adopt a URL or retire the previous credentials.
|
|
81
|
+
const record = await read();
|
|
82
|
+
return record?.resource === canonicalizeResourceIndicator(resource) ? record.session : null;
|
|
72
83
|
},
|
|
73
|
-
async load(resource) { return (await reconcile(resource)).session; },
|
|
74
84
|
async save(resource, session) {
|
|
75
85
|
const record = await reconcile(resource);
|
|
76
86
|
if (canonicalizeResourceIndicator(session.resource) !== record.resource)
|
|
@@ -28,6 +28,14 @@ export interface OAuthUnauthorizedChallenge {
|
|
|
28
28
|
raw: string;
|
|
29
29
|
}
|
|
30
30
|
export interface OAuthClientProvider {
|
|
31
|
+
/** Establish a grant explicitly, including when resource initialization is public. */
|
|
32
|
+
authenticate?(input: {
|
|
33
|
+
requestUrl: URL;
|
|
34
|
+
fetch: OAuthMetadataFetch;
|
|
35
|
+
/** Lazy validated discovery. Without it, recover/reuse known grants only. */
|
|
36
|
+
discover?: () => Promise<OAuthDiscoveryResult>;
|
|
37
|
+
signal?: AbortSignal;
|
|
38
|
+
}): Promise<StoredOAuthTokens | void>;
|
|
31
39
|
authorizeRequest?(input: {
|
|
32
40
|
requestUrl: URL;
|
|
33
41
|
headers: Headers;
|
|
@@ -37,7 +37,10 @@ by the server. Announced endpoints must remain on the original origin without
|
|
|
37
37
|
embedded credentials or fragments; endpoint changes close the connection.
|
|
38
38
|
Both transports accept the same headers, OAuth provider and response limits.
|
|
39
39
|
HTTP failures expose `HttpTransportError.status` and `.method`, so callers can
|
|
40
|
-
make transport decisions without parsing error messages.
|
|
40
|
+
make transport decisions without parsing error messages. Legacy HTTP/SSE
|
|
41
|
+
`connect()` also waits for the initialized notification POST to complete before
|
|
42
|
+
reporting ready. Completion failures reject the connection and expose
|
|
43
|
+
`rpcMethod: "notifications/initialized"`; they are not setup transport mismatches.
|
|
41
44
|
|
|
42
45
|
## OAuth HTTP support
|
|
43
46
|
|
|
@@ -131,6 +131,14 @@ interface OAuthUnauthorizedChallenge {
|
|
|
131
131
|
raw: string;
|
|
132
132
|
}
|
|
133
133
|
interface OAuthClientProvider {
|
|
134
|
+
/** Establish a grant explicitly, including when resource initialization is public. */
|
|
135
|
+
authenticate?(input: {
|
|
136
|
+
requestUrl: URL;
|
|
137
|
+
fetch: OAuthMetadataFetch;
|
|
138
|
+
/** Lazy validated discovery. Without it, recover/reuse known grants only. */
|
|
139
|
+
discover?: () => Promise<OAuthDiscoveryResult>;
|
|
140
|
+
signal?: AbortSignal;
|
|
141
|
+
}): Promise<StoredOAuthTokens | void>;
|
|
134
142
|
authorizeRequest?(input: {
|
|
135
143
|
requestUrl: URL;
|
|
136
144
|
headers: Headers;
|
|
@@ -641,6 +649,11 @@ interface McpTransport {
|
|
|
641
649
|
closed: Promise<McpTransportClosedEvent>;
|
|
642
650
|
dispose(reason?: Error): void;
|
|
643
651
|
filterTools?(tools: Tool[], reset?: boolean): Tool[];
|
|
652
|
+
/** Complete a legacy initialization handshake before the client reports ready. */
|
|
653
|
+
completeInitialization?(options: {
|
|
654
|
+
signal?: AbortSignal;
|
|
655
|
+
timeoutMs: number;
|
|
656
|
+
}): Promise<void>;
|
|
644
657
|
}
|
|
645
658
|
interface InMemoryServerTransport {
|
|
646
659
|
readable: Readable;
|
|
@@ -676,7 +689,8 @@ type HttpTransportFetch = (input: string | URL, init?: RequestInit) => Promise<R
|
|
|
676
689
|
declare class HttpTransportError extends Error {
|
|
677
690
|
readonly status: number;
|
|
678
691
|
readonly method: "GET" | "POST" | "DELETE";
|
|
679
|
-
|
|
692
|
+
readonly rpcMethod?: string | undefined;
|
|
693
|
+
constructor(message: string, status: number, method: "GET" | "POST" | "DELETE", rpcMethod?: string | undefined);
|
|
680
694
|
}
|
|
681
695
|
interface HttpTransportOptions {
|
|
682
696
|
url: string;
|
|
@@ -733,6 +747,10 @@ declare class HttpTransport implements McpTransport {
|
|
|
733
747
|
private readonly toolParameterHeaders;
|
|
734
748
|
private readonly onWarning;
|
|
735
749
|
constructor({ url, mode, headers, fetch: fetchImpl, oauth, oauthDiscoveryCache, onWarning, maxResponseBytes, }: HttpTransportOptions);
|
|
750
|
+
completeInitialization(options: {
|
|
751
|
+
signal?: AbortSignal;
|
|
752
|
+
timeoutMs: number;
|
|
753
|
+
}): Promise<void>;
|
|
736
754
|
filterTools(tools: Tool[], reset?: boolean): Tool[];
|
|
737
755
|
dispose(reason?: Error): void;
|
|
738
756
|
private closeWithSessionTermination;
|
|
@@ -4771,13 +4771,19 @@ function createResourceBoundOAuthStores(options, namespace, identity) {
|
|
|
4771
4771
|
return record2;
|
|
4772
4772
|
}
|
|
4773
4773
|
result.sessionStore = {
|
|
4774
|
-
async withLock(
|
|
4774
|
+
async withLock(resource, operation, options2) {
|
|
4775
4775
|
if (store.withLock === void 0)
|
|
4776
4776
|
throw new Error("OAuth resource identity backend must support transaction locks");
|
|
4777
|
-
return store.withLock(
|
|
4777
|
+
return store.withLock(async () => {
|
|
4778
|
+
options2.signal?.throwIfAborted();
|
|
4779
|
+
await reconcile(resource);
|
|
4780
|
+
options2.signal?.throwIfAborted();
|
|
4781
|
+
return operation();
|
|
4782
|
+
}, options2);
|
|
4778
4783
|
},
|
|
4779
4784
|
async load(resource) {
|
|
4780
|
-
|
|
4785
|
+
const record2 = await read();
|
|
4786
|
+
return record2?.resource === canonicalizeResourceIndicator(resource) ? record2.session : null;
|
|
4781
4787
|
},
|
|
4782
4788
|
async save(resource, session) {
|
|
4783
4789
|
const record2 = await reconcile(resource);
|
|
@@ -5166,6 +5172,25 @@ function createDefaultOAuthClientProvider(options) {
|
|
|
5166
5172
|
}
|
|
5167
5173
|
let initialGrantConsumed = false;
|
|
5168
5174
|
return {
|
|
5175
|
+
async authenticate(input) {
|
|
5176
|
+
input.signal?.throwIfAborted();
|
|
5177
|
+
assertNoAccessTokenInUrl(input.requestUrl, "Protected resource request URL");
|
|
5178
|
+
const resource = canonicalizeResourceIndicator(input.requestUrl);
|
|
5179
|
+
let session = await ensureAuthorizedSession(resource, void 0, input.fetch, true, false, input.signal);
|
|
5180
|
+
if (session?.tokens !== void 0 && !isExpired(session.tokens, now))
|
|
5181
|
+
return { ...session.tokens };
|
|
5182
|
+
if (session === null && !initialGrantConsumed && initialGrant?.resource === resource && initialGrant.tokens !== void 0 && !isExpired(initialGrant.tokens, now))
|
|
5183
|
+
return { ...initialGrant.tokens };
|
|
5184
|
+
if (input.discover === void 0)
|
|
5185
|
+
return;
|
|
5186
|
+
const discovery = await input.discover();
|
|
5187
|
+
input.signal?.throwIfAborted();
|
|
5188
|
+
assertRequestMatchesResource(resource, canonicalizeResourceIndicator(discovery.resource));
|
|
5189
|
+
session = await ensureAuthorizedSession(resource, discovery, input.fetch, true, false, input.signal);
|
|
5190
|
+
if (session?.tokens === void 0 || isExpired(session.tokens, now))
|
|
5191
|
+
throw new Error("OAuth authentication did not establish a usable grant");
|
|
5192
|
+
return { ...session.tokens };
|
|
5193
|
+
},
|
|
5169
5194
|
async authorizeRequest(input) {
|
|
5170
5195
|
assertNoAccessTokenInUrl(input.requestUrl, "Protected resource request URL");
|
|
5171
5196
|
const requestUrl = canonicalizeResourceIndicator(input.requestUrl);
|
|
@@ -6782,7 +6807,8 @@ var McpClient = class {
|
|
|
6782
6807
|
async (params, context) => this.options.onElicitationRequest(params, context)
|
|
6783
6808
|
);
|
|
6784
6809
|
}
|
|
6785
|
-
messageLayer.sendNotification("notifications/initialized");
|
|
6810
|
+
if (transport.completeInitialization === void 0) messageLayer.sendNotification("notifications/initialized");
|
|
6811
|
+
else await transport.completeInitialization({ signal: options.signal, timeoutMs: this.options.requestTimeoutMs ?? 3e4 });
|
|
6786
6812
|
this.currentState = "ready";
|
|
6787
6813
|
return initializeResult;
|
|
6788
6814
|
} catch (error) {
|
|
@@ -7282,14 +7308,16 @@ async function createTestPair(server, createClient) {
|
|
|
7282
7308
|
return { client, cleanup };
|
|
7283
7309
|
}
|
|
7284
7310
|
var HttpTransportError = class extends Error {
|
|
7285
|
-
constructor(message, status, method) {
|
|
7311
|
+
constructor(message, status, method, rpcMethod) {
|
|
7286
7312
|
super(message);
|
|
7287
7313
|
this.status = status;
|
|
7288
7314
|
this.method = method;
|
|
7315
|
+
this.rpcMethod = rpcMethod;
|
|
7289
7316
|
this.name = "HttpTransportError";
|
|
7290
7317
|
}
|
|
7291
7318
|
status;
|
|
7292
7319
|
method;
|
|
7320
|
+
rpcMethod;
|
|
7293
7321
|
};
|
|
7294
7322
|
function defaultStdioSpawn(command, args, options) {
|
|
7295
7323
|
return spawn2(command, args, options);
|
|
@@ -7464,6 +7492,21 @@ var HttpTransport = class {
|
|
|
7464
7492
|
this.dispose(error instanceof Error ? error : new Error(String(error)));
|
|
7465
7493
|
});
|
|
7466
7494
|
}
|
|
7495
|
+
async completeInitialization(options) {
|
|
7496
|
+
const deadline = options.timeoutMs > 0 ? AbortSignal.timeout(Math.ceil(options.timeoutMs)) : void 0;
|
|
7497
|
+
const signals = [options.signal, deadline].filter((signal2) => signal2 !== void 0);
|
|
7498
|
+
const signal = signals.length === 0 ? new AbortController().signal : AbortSignal.any(signals);
|
|
7499
|
+
signal.throwIfAborted();
|
|
7500
|
+
try {
|
|
7501
|
+
await this.sendPost(serializeJsonRpcMessage({ jsonrpc: "2.0", method: "notifications/initialized" }), signal);
|
|
7502
|
+
signal.throwIfAborted();
|
|
7503
|
+
if (this.disposed) throw (await this.closed).reason;
|
|
7504
|
+
} catch (error) {
|
|
7505
|
+
if (error instanceof HttpTransportError)
|
|
7506
|
+
throw new HttpTransportError(error.message, error.status, error.method, "notifications/initialized");
|
|
7507
|
+
throw error;
|
|
7508
|
+
}
|
|
7509
|
+
}
|
|
7467
7510
|
filterTools(tools, reset = true) {
|
|
7468
7511
|
if (reset) this.toolParameterHeaders.clear();
|
|
7469
7512
|
const accepted = [];
|
|
@@ -7575,7 +7618,8 @@ var HttpTransport = class {
|
|
|
7575
7618
|
}
|
|
7576
7619
|
}
|
|
7577
7620
|
}
|
|
7578
|
-
async sendPost(line) {
|
|
7621
|
+
async sendPost(line, signal) {
|
|
7622
|
+
signal?.throwIfAborted();
|
|
7579
7623
|
const parsed = parseJsonRpcMessage(line);
|
|
7580
7624
|
const message = parsed.type === "request" || parsed.type === "notification" ? parsed.message : void 0;
|
|
7581
7625
|
const metadata = isObjectRecord5(message?.params) ? message.params._meta : void 0;
|
|
@@ -7589,7 +7633,10 @@ var HttpTransport = class {
|
|
|
7589
7633
|
this.modernRequests.get(requestId)?.abort();
|
|
7590
7634
|
return;
|
|
7591
7635
|
}
|
|
7592
|
-
const controller = modern && parsed.type === "request" ? new AbortController() : void 0;
|
|
7636
|
+
const controller = modern && parsed.type === "request" || signal !== void 0 ? new AbortController() : void 0;
|
|
7637
|
+
const aborted = () => controller?.abort(signal?.reason);
|
|
7638
|
+
signal?.addEventListener("abort", aborted, { once: true });
|
|
7639
|
+
if (signal?.aborted) aborted();
|
|
7593
7640
|
const id = parsed.type === "request" ? parsed.message.id : void 0;
|
|
7594
7641
|
if (controller !== void 0 && id !== void 0) this.modernRequests.set(id, controller);
|
|
7595
7642
|
try {
|
|
@@ -7598,7 +7645,7 @@ var HttpTransport = class {
|
|
|
7598
7645
|
const response = await this.fetchWithOAuthRetry({
|
|
7599
7646
|
url: postUrl,
|
|
7600
7647
|
method: "POST",
|
|
7601
|
-
createHeaders: (
|
|
7648
|
+
createHeaders: (signal2) => this.createPostHeaders(message, modern, signal2),
|
|
7602
7649
|
body: line,
|
|
7603
7650
|
controller
|
|
7604
7651
|
});
|
|
@@ -7634,6 +7681,7 @@ var HttpTransport = class {
|
|
|
7634
7681
|
} catch (error) {
|
|
7635
7682
|
if (!controller?.signal.aborted) throw error;
|
|
7636
7683
|
} finally {
|
|
7684
|
+
signal?.removeEventListener("abort", aborted);
|
|
7637
7685
|
if (id !== void 0 && this.modernRequests.get(id) === controller)
|
|
7638
7686
|
this.modernRequests.delete(id);
|
|
7639
7687
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "toolcraft",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.319",
|
|
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.319",
|
|
162
162
|
"toolcraft-design": "*",
|
|
163
163
|
"@poe-code/frontmatter": "*",
|
|
164
164
|
"@poe-code/agent-mcp-config": "*",
|