toolcraft 0.0.340 → 0.0.342
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/auth-store/README.md +3 -1
- package/node_modules/auth-store/dist/encrypted-file-store.js +1 -0
- package/node_modules/auth-store/dist/transaction-lock.js +1 -0
- 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 +19 -3
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/client/auth-store-session-store.js +4 -2
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/client/default-oauth-client-provider.js +23 -9
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/client/resource-bound-store.js +2 -0
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/client/token-endpoint.js +6 -0
- package/node_modules/tiny-http-mcp-server/package.json +1 -1
- package/node_modules/tiny-mcp-client/dist/index.js +39 -13
- 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.65",
|
|
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.342",
|
|
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.342",
|
|
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.65",
|
|
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.342",
|
|
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.342",
|
|
127
127
|
"license": "MIT"
|
|
128
128
|
},
|
|
129
129
|
{
|
|
@@ -34,7 +34,9 @@ for transactions spanning a read, external operation and write. Independent
|
|
|
34
34
|
instances and processes serialize the same encrypted file or Keychain
|
|
35
35
|
service/account; unrelated identities proceed independently. The default
|
|
36
36
|
acquisition timeout is 30 seconds. Cancellation during acquisition does not
|
|
37
|
-
release the active owner's lock.
|
|
37
|
+
release the active owner's lock. Each acquisition retains its original signal
|
|
38
|
+
and timeout before path checks wait; replacing the caller's option handles cannot
|
|
39
|
+
bypass original cancellation or introduce another signal's cancellation. Individual `get`, `set` and `delete` calls do
|
|
38
40
|
not implicitly acquire it.
|
|
39
41
|
|
|
40
42
|
Locks use private filesystem claim directories, containing PID/random names
|
|
@@ -81,6 +81,7 @@ export class EncryptedFileStore {
|
|
|
81
81
|
}
|
|
82
82
|
}
|
|
83
83
|
async withLock(operation, options = {}) {
|
|
84
|
+
options = { ...options };
|
|
84
85
|
await this.assertCredentialPathHasNoSymbolicLinks(`${this.filePath}.lock`);
|
|
85
86
|
if (this.fs.readdir === undefined)
|
|
86
87
|
throw new Error("Secret-store transaction locks require filesystem readdir support");
|
|
@@ -3,6 +3,7 @@ import path from "node:path";
|
|
|
3
3
|
import { hasOwnErrorCode } from "./error-codes.js";
|
|
4
4
|
/** Filesystem bakery lock: unique claims allow dead-owner cleanup without deleting a replacement owner's lock. */
|
|
5
5
|
export async function withSecretStoreFileLock(fs, lockDirectory, operation, options = {}) {
|
|
6
|
+
options = { ...options };
|
|
6
7
|
const timeoutMs = options.timeoutMs ?? 30_000;
|
|
7
8
|
if (!Number.isFinite(timeoutMs) || timeoutMs < 0 || timeoutMs > 2_147_483_647)
|
|
8
9
|
throw new Error("Invalid secret-store transaction lock timeout");
|
|
@@ -64,7 +64,8 @@ aborting the original signal still cancels authorization.
|
|
|
64
64
|
Native session and client persistence factories also capture file paths, salts,
|
|
65
65
|
Keychain identities, lock locations and selected filesystem/command handles.
|
|
66
66
|
Mutating these settings cannot redirect a later read or write.
|
|
67
|
-
The factories
|
|
67
|
+
The factories copy these settings before reading the selected backend environment
|
|
68
|
+
variable, so its getter cannot replace them. They resolve that variable once at creation;
|
|
68
69
|
later environment changes cannot move a transaction between file and Keychain.
|
|
69
70
|
|
|
70
71
|
`createJwksTokenVerifier(options)` accepts:
|
|
@@ -93,6 +94,13 @@ accept the same `redirectUri`, `signal` and `timeoutMs` options. Cancellation,
|
|
|
93
94
|
timeout and explicit close settle pending code waits and release listeners.
|
|
94
95
|
Always close a successful standalone session in `finally`.
|
|
95
96
|
|
|
97
|
+
Native provider calls capture request option handles before host work. Unauthorized
|
|
98
|
+
handling also owns complete discovery metadata, presented grant values, rejected
|
|
99
|
+
request headers and the selected challenge error before reading persistence.
|
|
100
|
+
A browser callback cannot redirect a later code exchange by changing caller
|
|
101
|
+
metadata. Explicit authentication owns metadata when lazy discovery returns;
|
|
102
|
+
the selected discovery method retains its original receiver and live host state.
|
|
103
|
+
|
|
96
104
|
Provider request inputs accept an optional `signal`. It reaches callback waits,
|
|
97
105
|
registration, token requests and bounded token-body reads. Cancellation retains
|
|
98
106
|
its original reason and does not retry authorization. Native provider calls
|
|
@@ -125,7 +133,11 @@ timeoutMs })`. Reset acquires the raw identity backend lock, so it can recover
|
|
|
125
133
|
corrupt or undecryptable records without reading their old contents. It atomically
|
|
126
134
|
retires the identity's grant and registrations and writes a marker that suppresses
|
|
127
135
|
stale initial grants. The default lock wait is 30 seconds. Other names/profiles
|
|
128
|
-
are untouched, and symlink paths are still refused.
|
|
136
|
+
are untouched, and symlink paths are still refused. Native reset, import and
|
|
137
|
+
transaction callbacks retain their original signal while locks or reconciliation
|
|
138
|
+
wait; replacing a caller handle cannot change subsequent cancellation checks.
|
|
139
|
+
Cancellation after a completed identity write prevents the transaction callback
|
|
140
|
+
from running and retains that already persisted identity.
|
|
129
141
|
|
|
130
142
|
Configure `client.metadata.scope` to request a precise scope set; broader
|
|
131
143
|
discovery metadata does not override it. Explicit scopes must match the cached
|
|
@@ -255,7 +267,11 @@ transient retry or restoration of the original grant. Gateway error pages do not
|
|
|
255
267
|
Native persisted OAuth reads always reject corrupt encrypted documents and
|
|
256
268
|
invalid stored JSON, with diagnostics that omit decrypted contents. They retain
|
|
257
269
|
the existing record for explicit reset rather than interpreting corruption as
|
|
258
|
-
an absent session and reviving an initial grant.
|
|
270
|
+
an absent session and reviving an initial grant. Persisted access tokens that
|
|
271
|
+
cannot be sent as HTTP headers fail with diagnostics that omit token contents;
|
|
272
|
+
the original record remains available for explicit recovery. Token responses are
|
|
273
|
+
checked before activation or persistence. An unusable rotated access token keeps
|
|
274
|
+
refresh intent pending, preventing rotating-token replay. Caller file-backend settings
|
|
259
275
|
cannot disable this policy.
|
|
260
276
|
|
|
261
277
|
## Environment Variables
|
|
@@ -82,12 +82,14 @@ export function createAuthStoreClientStore(options, namespace) {
|
|
|
82
82
|
};
|
|
83
83
|
}
|
|
84
84
|
function snapshotPersistenceOptions(options) {
|
|
85
|
-
|
|
86
|
-
...options,
|
|
85
|
+
const snapshot = {
|
|
86
|
+
...options,
|
|
87
87
|
...(options.fileStore === undefined ? {} : { fileStore: { ...options.fileStore } }),
|
|
88
88
|
...(options.keychainStore === undefined ? {} : { keychainStore: { ...options.keychainStore,
|
|
89
89
|
...(options.keychainStore.lock === undefined ? {} : { lock: { ...options.keychainStore.lock } }) } })
|
|
90
90
|
};
|
|
91
|
+
snapshot.backend = resolveSecretStoreBackend(snapshot);
|
|
92
|
+
return snapshot;
|
|
91
93
|
}
|
|
92
94
|
export function createNamedSecretStore(key, options, defaults, namespace) {
|
|
93
95
|
const hash = crypto.createHash("sha256").update(namespace === undefined ? key : JSON.stringify([namespace, key])).digest("hex");
|
|
@@ -73,6 +73,7 @@ export function createDefaultOAuthClientProvider(options) {
|
|
|
73
73
|
let initialGrantConsumed = false;
|
|
74
74
|
return {
|
|
75
75
|
async authenticate(input) {
|
|
76
|
+
input = { ...input, ...(input.discover === undefined ? {} : { discover: input.discover.bind(input) }) };
|
|
76
77
|
input.signal?.throwIfAborted();
|
|
77
78
|
assertNoAccessTokenInUrl(input.requestUrl, "Protected resource request URL");
|
|
78
79
|
const resource = canonicalizeResourceIndicator(input.requestUrl);
|
|
@@ -84,7 +85,7 @@ export function createDefaultOAuthClientProvider(options) {
|
|
|
84
85
|
return { ...initialGrant.tokens };
|
|
85
86
|
if (input.discover === undefined)
|
|
86
87
|
return;
|
|
87
|
-
const discovery = await waitForOAuthOperation(input.discover(), input.signal);
|
|
88
|
+
const discovery = structuredClone(await waitForOAuthOperation(input.discover(), input.signal));
|
|
88
89
|
input.signal?.throwIfAborted();
|
|
89
90
|
assertRequestMatchesResource(resource, canonicalizeResourceIndicator(discovery.resource));
|
|
90
91
|
session = await ensureAuthorizedSession(resource, discovery, input.fetch, true, false, input.signal);
|
|
@@ -93,6 +94,7 @@ export function createDefaultOAuthClientProvider(options) {
|
|
|
93
94
|
return { ...session.tokens };
|
|
94
95
|
},
|
|
95
96
|
async authorizeRequest(input) {
|
|
97
|
+
input = { ...input };
|
|
96
98
|
assertNoAccessTokenInUrl(input.requestUrl, "Protected resource request URL");
|
|
97
99
|
const requestUrl = canonicalizeResourceIndicator(input.requestUrl);
|
|
98
100
|
const session = await ensureAuthorizedSession(requestUrl, undefined, input.fetch, false, false, input.signal);
|
|
@@ -113,8 +115,16 @@ export function createDefaultOAuthClientProvider(options) {
|
|
|
113
115
|
return { ...session.tokens };
|
|
114
116
|
},
|
|
115
117
|
async handleUnauthorized(input) {
|
|
118
|
+
input = { ...input };
|
|
116
119
|
try {
|
|
117
120
|
input.signal?.throwIfAborted();
|
|
121
|
+
const presented = input.presentedTokens == null ? input.presentedTokens : normalizeStoredTokens(input.presentedTokens);
|
|
122
|
+
if (input.presentedTokens != null && presented === undefined)
|
|
123
|
+
throw new Error("OAuth rejected-request provenance does not match its authorization header");
|
|
124
|
+
const challengeError = input.challenge?.params.error;
|
|
125
|
+
input = { ...input, discovery: structuredClone(input.discovery),
|
|
126
|
+
...(input.requestHeaders === undefined ? {} : { requestHeaders: new Headers(input.requestHeaders) }),
|
|
127
|
+
...(presented === undefined ? {} : { presentedTokens: presented }) };
|
|
118
128
|
assertNoAccessTokenInUrl(input.requestUrl, "Protected resource request URL");
|
|
119
129
|
const requestUrl = canonicalizeResourceIndicator(input.requestUrl);
|
|
120
130
|
const resource = canonicalizeResourceIndicator(input.discovery.resource);
|
|
@@ -126,16 +136,15 @@ export function createDefaultOAuthClientProvider(options) {
|
|
|
126
136
|
if (input.presentedTokens !== undefined) {
|
|
127
137
|
rejectedCurrentGrant = false;
|
|
128
138
|
if (input.presentedTokens !== null) {
|
|
129
|
-
const presented =
|
|
139
|
+
const presented = input.presentedTokens;
|
|
130
140
|
const header = input.requestHeaders?.get("Authorization") ?? "";
|
|
131
141
|
const separator = header.indexOf(" ");
|
|
132
|
-
if (
|
|
142
|
+
if (header.slice(0, separator).toLowerCase() !== "bearer" || header.slice(separator + 1).trim() !== presented.accessToken)
|
|
133
143
|
throw new Error("OAuth rejected-request provenance does not match its authorization header");
|
|
134
144
|
presentedTokens = presented;
|
|
135
145
|
rejectedCurrentGrant = currentTokens !== undefined && sameTokenGrant(currentTokens, presented);
|
|
136
146
|
}
|
|
137
147
|
}
|
|
138
|
-
const challengeError = input.challenge?.params.error;
|
|
139
148
|
const forceRefresh = rejectedCurrentGrant && (challengeError === "invalid_token" || (input.presentedTokens !== undefined && challengeError === undefined));
|
|
140
149
|
const session = await ensureAuthorizedSession(resource, {
|
|
141
150
|
...input.discovery,
|
|
@@ -591,11 +600,16 @@ function normalizeLoadedSession(session) {
|
|
|
591
600
|
if (client === null) {
|
|
592
601
|
return { ...session, client: { clientId: "" }, tokens: undefined };
|
|
593
602
|
}
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
603
|
+
const tokens = normalizeStoredTokens(getOwnEntry(session, "tokens"));
|
|
604
|
+
if (tokens !== undefined) {
|
|
605
|
+
try {
|
|
606
|
+
new Headers({ Authorization: `Bearer ${tokens.accessToken}` });
|
|
607
|
+
}
|
|
608
|
+
catch {
|
|
609
|
+
throw new Error("Stored OAuth access token is not a valid HTTP header value");
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
return { ...session, client, tokens };
|
|
599
613
|
}
|
|
600
614
|
function normalizeImportedTokens(value, now) {
|
|
601
615
|
if (!isObjectRecord(value))
|
package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/client/resource-bound-store.js
CHANGED
|
@@ -51,6 +51,7 @@ export function createResourceBoundOAuthStores(options, namespace, identity) {
|
|
|
51
51
|
}
|
|
52
52
|
};
|
|
53
53
|
async function replace(record, options) {
|
|
54
|
+
options = { ...options };
|
|
54
55
|
options.signal?.throwIfAborted();
|
|
55
56
|
const timeoutMs = options.timeoutMs ?? 30_000;
|
|
56
57
|
if (!Number.isSafeInteger(timeoutMs) || timeoutMs < 1 || timeoutMs > 2_147_483_647)
|
|
@@ -124,6 +125,7 @@ export function createResourceBoundOAuthStores(options, namespace, identity) {
|
|
|
124
125
|
}
|
|
125
126
|
result.sessionStore = {
|
|
126
127
|
async withLock(resource, operation, options) {
|
|
128
|
+
options = { ...options };
|
|
127
129
|
if (store.withLock === undefined)
|
|
128
130
|
throw new Error("OAuth resource identity backend must support transaction locks");
|
|
129
131
|
return store.withLock(async () => {
|
package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/client/token-endpoint.js
CHANGED
|
@@ -105,6 +105,12 @@ async function requestTokens(input) {
|
|
|
105
105
|
throw new Error("OAuth token response missing access_token");
|
|
106
106
|
}
|
|
107
107
|
const normalizedAccessToken = accessToken.trim();
|
|
108
|
+
try {
|
|
109
|
+
new Headers({ Authorization: `Bearer ${normalizedAccessToken}` });
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
throw new Error("OAuth token response access_token is not a valid HTTP header value");
|
|
113
|
+
}
|
|
108
114
|
const tokenType = normalizeBearerTokenType(getOwnEntry(payload, "token_type"));
|
|
109
115
|
if (tokenType === null) {
|
|
110
116
|
throw new Error("OAuth token response missing token_type=Bearer");
|
|
@@ -3907,6 +3907,7 @@ function hasOwnErrorCode(error, code) {
|
|
|
3907
3907
|
import { randomUUID } from "node:crypto";
|
|
3908
3908
|
import path from "node:path";
|
|
3909
3909
|
async function withSecretStoreFileLock(fs2, lockDirectory, operation, options = {}) {
|
|
3910
|
+
options = { ...options };
|
|
3910
3911
|
const timeoutMs = options.timeoutMs ?? 3e4;
|
|
3911
3912
|
if (!Number.isFinite(timeoutMs) || timeoutMs < 0 || timeoutMs > 2147483647)
|
|
3912
3913
|
throw new Error("Invalid secret-store transaction lock timeout");
|
|
@@ -4126,6 +4127,7 @@ var EncryptedFileStore = class {
|
|
|
4126
4127
|
}
|
|
4127
4128
|
}
|
|
4128
4129
|
async withLock(operation, options = {}) {
|
|
4130
|
+
options = { ...options };
|
|
4129
4131
|
await this.assertCredentialPathHasNoSymbolicLinks(`${this.filePath}.lock`);
|
|
4130
4132
|
if (this.fs.readdir === void 0)
|
|
4131
4133
|
throw new Error("Secret-store transaction locks require filesystem readdir support");
|
|
@@ -4638,15 +4640,16 @@ function createAuthStoreClientStore(options, namespace) {
|
|
|
4638
4640
|
};
|
|
4639
4641
|
}
|
|
4640
4642
|
function snapshotPersistenceOptions(options) {
|
|
4641
|
-
|
|
4643
|
+
const snapshot = {
|
|
4642
4644
|
...options,
|
|
4643
|
-
backend: resolveSecretStoreBackend(options),
|
|
4644
4645
|
...options.fileStore === void 0 ? {} : { fileStore: { ...options.fileStore } },
|
|
4645
4646
|
...options.keychainStore === void 0 ? {} : { keychainStore: {
|
|
4646
4647
|
...options.keychainStore,
|
|
4647
4648
|
...options.keychainStore.lock === void 0 ? {} : { lock: { ...options.keychainStore.lock } }
|
|
4648
4649
|
} }
|
|
4649
4650
|
};
|
|
4651
|
+
snapshot.backend = resolveSecretStoreBackend(snapshot);
|
|
4652
|
+
return snapshot;
|
|
4650
4653
|
}
|
|
4651
4654
|
function createNamedSecretStore(key2, options, defaults, namespace) {
|
|
4652
4655
|
const hash = crypto2.createHash("sha256").update(namespace === void 0 ? key2 : JSON.stringify([namespace, key2])).digest("hex");
|
|
@@ -4790,6 +4793,7 @@ function createResourceBoundOAuthStores(options, namespace, identity) {
|
|
|
4790
4793
|
}
|
|
4791
4794
|
};
|
|
4792
4795
|
async function replace(record2, options2) {
|
|
4796
|
+
options2 = { ...options2 };
|
|
4793
4797
|
options2.signal?.throwIfAborted();
|
|
4794
4798
|
const timeoutMs = options2.timeoutMs ?? 3e4;
|
|
4795
4799
|
if (!Number.isSafeInteger(timeoutMs) || timeoutMs < 1 || timeoutMs > 2147483647)
|
|
@@ -4855,6 +4859,7 @@ function createResourceBoundOAuthStores(options, namespace, identity) {
|
|
|
4855
4859
|
}
|
|
4856
4860
|
result.sessionStore = {
|
|
4857
4861
|
async withLock(resource, operation, options2) {
|
|
4862
|
+
options2 = { ...options2 };
|
|
4858
4863
|
if (store.withLock === void 0)
|
|
4859
4864
|
throw new Error("OAuth resource identity backend must support transaction locks");
|
|
4860
4865
|
return store.withLock(async () => {
|
|
@@ -5111,6 +5116,11 @@ async function requestTokens(input) {
|
|
|
5111
5116
|
throw new Error("OAuth token response missing access_token");
|
|
5112
5117
|
}
|
|
5113
5118
|
const normalizedAccessToken = accessToken.trim();
|
|
5119
|
+
try {
|
|
5120
|
+
new Headers({ Authorization: `Bearer ${normalizedAccessToken}` });
|
|
5121
|
+
} catch {
|
|
5122
|
+
throw new Error("OAuth token response access_token is not a valid HTTP header value");
|
|
5123
|
+
}
|
|
5114
5124
|
const tokenType = normalizeBearerTokenType(getOwnEntry5(payload, "token_type"));
|
|
5115
5125
|
if (tokenType === null) {
|
|
5116
5126
|
throw new Error("OAuth token response missing token_type=Bearer");
|
|
@@ -5325,6 +5335,7 @@ function createDefaultOAuthClientProvider(options) {
|
|
|
5325
5335
|
let initialGrantConsumed = false;
|
|
5326
5336
|
return {
|
|
5327
5337
|
async authenticate(input) {
|
|
5338
|
+
input = { ...input, ...input.discover === void 0 ? {} : { discover: input.discover.bind(input) } };
|
|
5328
5339
|
input.signal?.throwIfAborted();
|
|
5329
5340
|
assertNoAccessTokenInUrl(input.requestUrl, "Protected resource request URL");
|
|
5330
5341
|
const resource = canonicalizeResourceIndicator(input.requestUrl);
|
|
@@ -5335,7 +5346,7 @@ function createDefaultOAuthClientProvider(options) {
|
|
|
5335
5346
|
return { ...initialGrant.tokens };
|
|
5336
5347
|
if (input.discover === void 0)
|
|
5337
5348
|
return;
|
|
5338
|
-
const discovery = await waitForOAuthOperation(input.discover(), input.signal);
|
|
5349
|
+
const discovery = structuredClone(await waitForOAuthOperation(input.discover(), input.signal));
|
|
5339
5350
|
input.signal?.throwIfAborted();
|
|
5340
5351
|
assertRequestMatchesResource(resource, canonicalizeResourceIndicator(discovery.resource));
|
|
5341
5352
|
session = await ensureAuthorizedSession(resource, discovery, input.fetch, true, false, input.signal);
|
|
@@ -5344,6 +5355,7 @@ function createDefaultOAuthClientProvider(options) {
|
|
|
5344
5355
|
return { ...session.tokens };
|
|
5345
5356
|
},
|
|
5346
5357
|
async authorizeRequest(input) {
|
|
5358
|
+
input = { ...input };
|
|
5347
5359
|
assertNoAccessTokenInUrl(input.requestUrl, "Protected resource request URL");
|
|
5348
5360
|
const requestUrl = canonicalizeResourceIndicator(input.requestUrl);
|
|
5349
5361
|
const session = await ensureAuthorizedSession(requestUrl, void 0, input.fetch, false, false, input.signal);
|
|
@@ -5360,8 +5372,19 @@ function createDefaultOAuthClientProvider(options) {
|
|
|
5360
5372
|
return { ...session.tokens };
|
|
5361
5373
|
},
|
|
5362
5374
|
async handleUnauthorized(input) {
|
|
5375
|
+
input = { ...input };
|
|
5363
5376
|
try {
|
|
5364
5377
|
input.signal?.throwIfAborted();
|
|
5378
|
+
const presented = input.presentedTokens == null ? input.presentedTokens : normalizeStoredTokens(input.presentedTokens);
|
|
5379
|
+
if (input.presentedTokens != null && presented === void 0)
|
|
5380
|
+
throw new Error("OAuth rejected-request provenance does not match its authorization header");
|
|
5381
|
+
const challengeError = input.challenge?.params.error;
|
|
5382
|
+
input = {
|
|
5383
|
+
...input,
|
|
5384
|
+
discovery: structuredClone(input.discovery),
|
|
5385
|
+
...input.requestHeaders === void 0 ? {} : { requestHeaders: new Headers(input.requestHeaders) },
|
|
5386
|
+
...presented === void 0 ? {} : { presentedTokens: presented }
|
|
5387
|
+
};
|
|
5365
5388
|
assertNoAccessTokenInUrl(input.requestUrl, "Protected resource request URL");
|
|
5366
5389
|
const requestUrl = canonicalizeResourceIndicator(input.requestUrl);
|
|
5367
5390
|
const resource = canonicalizeResourceIndicator(input.discovery.resource);
|
|
@@ -5373,16 +5396,15 @@ function createDefaultOAuthClientProvider(options) {
|
|
|
5373
5396
|
if (input.presentedTokens !== void 0) {
|
|
5374
5397
|
rejectedCurrentGrant = false;
|
|
5375
5398
|
if (input.presentedTokens !== null) {
|
|
5376
|
-
const
|
|
5399
|
+
const presented2 = input.presentedTokens;
|
|
5377
5400
|
const header = input.requestHeaders?.get("Authorization") ?? "";
|
|
5378
5401
|
const separator = header.indexOf(" ");
|
|
5379
|
-
if (
|
|
5402
|
+
if (header.slice(0, separator).toLowerCase() !== "bearer" || header.slice(separator + 1).trim() !== presented2.accessToken)
|
|
5380
5403
|
throw new Error("OAuth rejected-request provenance does not match its authorization header");
|
|
5381
|
-
presentedTokens =
|
|
5382
|
-
rejectedCurrentGrant = currentTokens !== void 0 && sameTokenGrant(currentTokens,
|
|
5404
|
+
presentedTokens = presented2;
|
|
5405
|
+
rejectedCurrentGrant = currentTokens !== void 0 && sameTokenGrant(currentTokens, presented2);
|
|
5383
5406
|
}
|
|
5384
5407
|
}
|
|
5385
|
-
const challengeError = input.challenge?.params.error;
|
|
5386
5408
|
const forceRefresh = rejectedCurrentGrant && (challengeError === "invalid_token" || input.presentedTokens !== void 0 && challengeError === void 0);
|
|
5387
5409
|
const session = await ensureAuthorizedSession(resource, {
|
|
5388
5410
|
...input.discovery,
|
|
@@ -5822,11 +5844,15 @@ function normalizeLoadedSession(session) {
|
|
|
5822
5844
|
if (client === null) {
|
|
5823
5845
|
return { ...session, client: { clientId: "" }, tokens: void 0 };
|
|
5824
5846
|
}
|
|
5825
|
-
|
|
5826
|
-
|
|
5827
|
-
|
|
5828
|
-
|
|
5829
|
-
|
|
5847
|
+
const tokens = normalizeStoredTokens(getOwnEntry6(session, "tokens"));
|
|
5848
|
+
if (tokens !== void 0) {
|
|
5849
|
+
try {
|
|
5850
|
+
new Headers({ Authorization: `Bearer ${tokens.accessToken}` });
|
|
5851
|
+
} catch {
|
|
5852
|
+
throw new Error("Stored OAuth access token is not a valid HTTP header value");
|
|
5853
|
+
}
|
|
5854
|
+
}
|
|
5855
|
+
return { ...session, client, tokens };
|
|
5830
5856
|
}
|
|
5831
5857
|
function normalizeImportedTokens(value, now) {
|
|
5832
5858
|
if (!isObjectRecord3(value))
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "toolcraft",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.342",
|
|
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.342",
|
|
162
162
|
"toolcraft-design": "*",
|
|
163
163
|
"@poe-code/frontmatter": "*",
|
|
164
164
|
"@poe-code/agent-mcp-config": "*",
|