toolcraft 0.0.312 → 0.0.314
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 +20 -1
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/client/auth-store-session-store.d.ts +3 -2
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/client/auth-store-session-store.js +22 -15
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/client/default-oauth-client-provider.js +30 -10
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/client/scope.d.ts +2 -0
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/client/scope.js +9 -0
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/client/token-endpoint.js +4 -1
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/client/types.d.ts +4 -0
- package/node_modules/tiny-http-mcp-server/package.json +1 -1
- package/node_modules/tiny-mcp-client/dist/index.d.ts +4 -0
- package/node_modules/tiny-mcp-client/dist/index.js +62 -25
- 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.33",
|
|
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.314",
|
|
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.314",
|
|
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.33",
|
|
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.314",
|
|
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.314",
|
|
127
127
|
"license": "MIT"
|
|
128
128
|
},
|
|
129
129
|
{
|
|
@@ -42,6 +42,7 @@ const verifier = createJwksTokenVerifier({
|
|
|
42
42
|
- `mode: "static"` with `clientId`, optional `clientSecret`, optional `metadata`
|
|
43
43
|
- `allowInteractive: false` prevents interactive login while retaining cached tokens and silent refresh
|
|
44
44
|
- `sessionLockTimeoutMs` limits acquisition waits for a session transaction lock (default 30,000 ms; integer from 1 to 2147483647)
|
|
45
|
+
- `persistenceNamespace` isolates native sessions and registrations for a named profile (nonempty string, at most 1024 UTF-8 bytes)
|
|
45
46
|
- `initialGrant: { resource, tokens }` optionally imports an existing Bearer grant for one HTTP resource; requires the original client ID
|
|
46
47
|
- `browser.openBrowser(url)` optional
|
|
47
48
|
- `browser.readLine()` optional
|
|
@@ -95,7 +96,14 @@ on 401 even when the server omits `error="invalid_token"`. Invalid provenance
|
|
|
95
96
|
fails without quoting token values.
|
|
96
97
|
|
|
97
98
|
Configure `client.metadata.scope` to request a precise scope set; broader
|
|
98
|
-
discovery metadata does not override it.
|
|
99
|
+
discovery metadata does not override it. Explicit scopes must match the cached
|
|
100
|
+
or imported grant's scope set; ordering, repeated spaces and duplicates are
|
|
101
|
+
normalized. An imported grant must declare its scope when a scope is configured.
|
|
102
|
+
Authorization records the requested set when the endpoint omits scope, and
|
|
103
|
+
refresh retains the previous granted set. Mismatched responses never activate
|
|
104
|
+
credentials; an unusable refresh response retains the pending refresh record.
|
|
105
|
+
Select a separate persistence namespace for another scope profile. No scope is
|
|
106
|
+
invented when the client does not configure one.
|
|
99
107
|
|
|
100
108
|
Imported `initialGrant.tokens` use `accessToken`, optional `refreshToken`,
|
|
101
109
|
`tokenType: "Bearer"`, `expiresAt` (Unix epoch milliseconds or `null` if unknown),
|
|
@@ -104,6 +112,17 @@ Discovery binds an expired or explicitly rejected grant before silent refresh,
|
|
|
104
112
|
using the original configured client. Persisted sessions take precedence,
|
|
105
113
|
including sessions whose tokens have been cleared; an import cannot revive them.
|
|
106
114
|
Input tokens are copied and invalid expiry values fail before authorization.
|
|
115
|
+
Static clients and dynamic initial-grant imports require cached grants to match
|
|
116
|
+
the original normalized client ID and secret. A different client configuration
|
|
117
|
+
fails before attaching or refreshing credentials and retains the stored record;
|
|
118
|
+
select separate persistence or explicitly reset the session to change apps.
|
|
119
|
+
Use `persistenceNamespace: "personal"` or `"work"` to keep separate native
|
|
120
|
+
profiles for the same resource/issuer. `createAuthStoreSessionStore(options,
|
|
121
|
+
namespace)` addresses the same profile when seeding or inspecting credentials.
|
|
122
|
+
Namespaces are hashed into file/Keychain identities and transaction locks;
|
|
123
|
+
omitting one preserves the default storage keys. Switching namespaces selects a
|
|
124
|
+
different record and does not migrate or reset the previous profile. Host-owned
|
|
125
|
+
`sessionStore` implementations remain responsible for their own profile keys.
|
|
107
126
|
|
|
108
127
|
`createAuthStoreSessionStore(options)` accepts the standard `auth-store` config.
|
|
109
128
|
|
|
@@ -9,6 +9,7 @@ export interface OAuthClientStore {
|
|
|
9
9
|
save(issuer: string, client: StoredOAuthClient): Promise<void>;
|
|
10
10
|
clear(issuer: string): Promise<void>;
|
|
11
11
|
}
|
|
12
|
-
export declare function createAuthStoreSessionStore(options?: CreateSecretStoreInput): OAuthSessionStore;
|
|
13
|
-
export declare function createAuthStoreClientStore(options: CreateSecretStoreInput): OAuthClientStore;
|
|
12
|
+
export declare function createAuthStoreSessionStore(options?: CreateSecretStoreInput, namespace?: string): OAuthSessionStore;
|
|
13
|
+
export declare function createAuthStoreClientStore(options: CreateSecretStoreInput, namespace?: string): OAuthClientStore;
|
|
14
|
+
export declare function assertPersistenceNamespace(namespace: string | undefined): void;
|
|
14
15
|
export {};
|
|
@@ -9,16 +9,17 @@ const DEFAULT_CLIENT_FILE_SALT = "poe-code:mcp-oauth:clients:v1";
|
|
|
9
9
|
const DEFAULT_CLIENT_FILE_DIRECTORY = ".poe-code/mcp-oauth/clients";
|
|
10
10
|
const DEFAULT_CLIENT_KEYCHAIN_SERVICE = "poe-code-mcp-oauth-clients";
|
|
11
11
|
const MAX_JS_DATE_MS = 8_640_000_000_000_000;
|
|
12
|
-
export function createAuthStoreSessionStore(options = {}) {
|
|
12
|
+
export function createAuthStoreSessionStore(options = {}, namespace) {
|
|
13
|
+
assertPersistenceNamespace(namespace);
|
|
13
14
|
return {
|
|
14
15
|
async withLock(resource, operation, lockOptions) {
|
|
15
|
-
const store = createResourceSecretStore(resource, options);
|
|
16
|
+
const store = createResourceSecretStore(resource, options, namespace);
|
|
16
17
|
if (store.withLock === undefined)
|
|
17
18
|
throw new Error("OAuth secret-store backend does not support transaction locks");
|
|
18
19
|
return store.withLock(operation, lockOptions);
|
|
19
20
|
},
|
|
20
21
|
async load(resource) {
|
|
21
|
-
const store = createResourceSecretStore(resource, options);
|
|
22
|
+
const store = createResourceSecretStore(resource, options, namespace);
|
|
22
23
|
const value = await store.get();
|
|
23
24
|
if (value === null) {
|
|
24
25
|
return null;
|
|
@@ -36,19 +37,20 @@ export function createAuthStoreSessionStore(options = {}) {
|
|
|
36
37
|
throw new Error("Stored OAuth session must match the expected shape");
|
|
37
38
|
},
|
|
38
39
|
async save(resource, session) {
|
|
39
|
-
const store = createResourceSecretStore(resource, options);
|
|
40
|
+
const store = createResourceSecretStore(resource, options, namespace);
|
|
40
41
|
await store.set(JSON.stringify(session));
|
|
41
42
|
},
|
|
42
43
|
async clear(resource) {
|
|
43
|
-
const store = createResourceSecretStore(resource, options);
|
|
44
|
+
const store = createResourceSecretStore(resource, options, namespace);
|
|
44
45
|
await store.delete();
|
|
45
46
|
}
|
|
46
47
|
};
|
|
47
48
|
}
|
|
48
|
-
export function createAuthStoreClientStore(options) {
|
|
49
|
+
export function createAuthStoreClientStore(options, namespace) {
|
|
50
|
+
assertPersistenceNamespace(namespace);
|
|
49
51
|
return {
|
|
50
52
|
async load(issuer) {
|
|
51
|
-
const store = createIssuerSecretStore(issuer, options);
|
|
53
|
+
const store = createIssuerSecretStore(issuer, options, namespace);
|
|
52
54
|
const value = await store.get();
|
|
53
55
|
if (value === null) {
|
|
54
56
|
return null;
|
|
@@ -72,17 +74,17 @@ export function createAuthStoreClientStore(options) {
|
|
|
72
74
|
throw new Error("Stored OAuth client must be a JSON object with clientId");
|
|
73
75
|
},
|
|
74
76
|
async save(issuer, client) {
|
|
75
|
-
const store = createIssuerSecretStore(issuer, options);
|
|
77
|
+
const store = createIssuerSecretStore(issuer, options, namespace);
|
|
76
78
|
await store.set(JSON.stringify(client));
|
|
77
79
|
},
|
|
78
80
|
async clear(issuer) {
|
|
79
|
-
const store = createIssuerSecretStore(issuer, options);
|
|
81
|
+
const store = createIssuerSecretStore(issuer, options, namespace);
|
|
80
82
|
await store.delete();
|
|
81
83
|
}
|
|
82
84
|
};
|
|
83
85
|
}
|
|
84
|
-
function createNamedSecretStore(key, options, defaults) {
|
|
85
|
-
const hash = crypto.createHash("sha256").update(key).digest("hex");
|
|
86
|
+
function createNamedSecretStore(key, options, defaults, namespace) {
|
|
87
|
+
const hash = crypto.createHash("sha256").update(namespace === undefined ? key : JSON.stringify([namespace, key])).digest("hex");
|
|
86
88
|
const configuredFilePath = options.fileStore?.filePath;
|
|
87
89
|
const parsedFilePath = configuredFilePath === undefined ? null : path.parse(configuredFilePath);
|
|
88
90
|
const fileStore = {
|
|
@@ -104,21 +106,25 @@ function createNamedSecretStore(key, options, defaults) {
|
|
|
104
106
|
};
|
|
105
107
|
return createSecretStore({ ...options, fileStore, keychainStore }).store;
|
|
106
108
|
}
|
|
107
|
-
function createResourceSecretStore(resource, options) {
|
|
109
|
+
function createResourceSecretStore(resource, options, namespace) {
|
|
108
110
|
return createNamedSecretStore(canonicalizeResourceIndicator(resource), options, {
|
|
109
111
|
salt: DEFAULT_FILE_SALT,
|
|
110
112
|
directory: DEFAULT_FILE_DIRECTORY,
|
|
111
113
|
service: DEFAULT_KEYCHAIN_SERVICE,
|
|
112
114
|
accountPrefix: "provider"
|
|
113
|
-
});
|
|
115
|
+
}, namespace);
|
|
114
116
|
}
|
|
115
|
-
function createIssuerSecretStore(issuer, options) {
|
|
117
|
+
function createIssuerSecretStore(issuer, options, namespace) {
|
|
116
118
|
return createNamedSecretStore(issuer, options, {
|
|
117
119
|
salt: DEFAULT_CLIENT_FILE_SALT,
|
|
118
120
|
directory: DEFAULT_CLIENT_FILE_DIRECTORY,
|
|
119
121
|
service: DEFAULT_CLIENT_KEYCHAIN_SERVICE,
|
|
120
122
|
accountPrefix: "issuer"
|
|
121
|
-
});
|
|
123
|
+
}, namespace);
|
|
124
|
+
}
|
|
125
|
+
export function assertPersistenceNamespace(namespace) {
|
|
126
|
+
if (namespace !== undefined && (typeof namespace !== "string" || namespace.trim() === "" || Buffer.byteLength(namespace, "utf8") > 1024))
|
|
127
|
+
throw new Error("OAuth persistence namespace must be a nonempty string within 1024 bytes");
|
|
122
128
|
}
|
|
123
129
|
function isObjectRecord(value) {
|
|
124
130
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -138,6 +144,7 @@ function isStoredOAuthSession(value) {
|
|
|
138
144
|
isNonBlankOwnString(value, "authorizationServer") &&
|
|
139
145
|
isStoredOAuthClient(getOwnEntry(value, "client")) &&
|
|
140
146
|
isStoredOAuthDiscovery(getOwnEntry(value, "discovery")) &&
|
|
147
|
+
(getOwnEntry(value, "requestedScope") === undefined || isNonBlankOwnString(value, "requestedScope")) &&
|
|
141
148
|
(getOwnEntry(value, "refreshState") === undefined ||
|
|
142
149
|
(getOwnEntry(value, "refreshState") === "pending" && getOwnEntry(value, "tokens") === undefined)) &&
|
|
143
150
|
isStoredOAuthTokensOrMissing(getOwnEntry(value, "tokens")));
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import { normalizeOAuthScope } from "./scope.js";
|
|
1
2
|
import { isIP } from "node:net";
|
|
2
3
|
import { fetchMcpResponse } from "../http-fetch.js";
|
|
3
4
|
import { URL } from "node:url";
|
|
4
|
-
import { createAuthStoreClientStore, createAuthStoreSessionStore } from "./auth-store-session-store.js";
|
|
5
|
+
import { createAuthStoreClientStore, createAuthStoreSessionStore, assertPersistenceNamespace } from "./auth-store-session-store.js";
|
|
5
6
|
import { createLoopbackAuthorizationSession, loopbackTarget } from "./loopback-authorization.js";
|
|
6
7
|
import { createAuthorizationState } from "./authorization-state.js";
|
|
7
8
|
import { generateCodeChallenge, generateCodeVerifier } from "./pkce.js";
|
|
@@ -17,8 +18,11 @@ export function createOAuthClientProvider(options) {
|
|
|
17
18
|
}
|
|
18
19
|
export function createDefaultOAuthClientProvider(options) {
|
|
19
20
|
loopbackTarget(options.browser);
|
|
20
|
-
|
|
21
|
-
const
|
|
21
|
+
assertPersistenceNamespace(options.persistenceNamespace);
|
|
22
|
+
const clientMetadata = getClientMetadata(options.client);
|
|
23
|
+
const requestedScope = clientMetadata?.scope;
|
|
24
|
+
const sessionStore = options.sessionStore ?? createAuthStoreSessionStore(options.authStore, options.persistenceNamespace);
|
|
25
|
+
const clientStore = options.authStore === undefined ? null : createAuthStoreClientStore(options.authStore, options.persistenceNamespace);
|
|
22
26
|
const now = options.now ?? Date.now;
|
|
23
27
|
const registeredClients = new Map();
|
|
24
28
|
if (options.initialGrant !== undefined) {
|
|
@@ -40,6 +44,8 @@ export function createDefaultOAuthClientProvider(options) {
|
|
|
40
44
|
if (initialGrant !== undefined && (initialGrant.tokens === undefined || initialGrant.client === null))
|
|
41
45
|
throw new Error("OAuth initial grant requires valid tokens and the original client ID");
|
|
42
46
|
if (initialGrant?.tokens !== undefined) {
|
|
47
|
+
if (requestedScope !== undefined && initialGrant.tokens.scope !== requestedScope)
|
|
48
|
+
throw new Error("OAuth initial grant does not match the requested OAuth scope");
|
|
43
49
|
try {
|
|
44
50
|
new Headers({ Authorization: `Bearer ${initialGrant.tokens.accessToken}` });
|
|
45
51
|
}
|
|
@@ -132,7 +138,8 @@ export function createDefaultOAuthClientProvider(options) {
|
|
|
132
138
|
initialGrant.tokens !== undefined && initialGrant.client !== null) {
|
|
133
139
|
assertSecureOAuthFlowEndpoints(discovery.authorizationServerMetadata);
|
|
134
140
|
session = { resource: canonicalResource, authorizationServer: discovery.authorizationServer,
|
|
135
|
-
client: initialGrant.client, tokens: initialGrant.tokens,
|
|
141
|
+
client: initialGrant.client, tokens: initialGrant.tokens,
|
|
142
|
+
...(requestedScope === undefined ? {} : { requestedScope }), discovery: toStoredDiscovery(discovery) };
|
|
136
143
|
await saveSession(canonicalResource, session);
|
|
137
144
|
initialGrantConsumed = true;
|
|
138
145
|
signal?.throwIfAborted();
|
|
@@ -140,6 +147,13 @@ export function createDefaultOAuthClientProvider(options) {
|
|
|
140
147
|
if (forceRefresh && rejectedTokens !== undefined && (rejectedTokens === null || session?.tokens === undefined || !sameTokenGrant(session.tokens, rejectedTokens)))
|
|
141
148
|
forceRefresh = false;
|
|
142
149
|
const sessionDiscovery = resolveDiscovery(discovery, session);
|
|
150
|
+
if ((options.client.mode === "static" || initialGrant !== undefined) && session !== null && (session.tokens !== undefined || session.refreshState === "pending")) {
|
|
151
|
+
const configured = normalizeConfiguredClient(options.client);
|
|
152
|
+
if (configured === null || configured.clientId !== session.client.clientId || configured.clientSecret !== session.client.clientSecret)
|
|
153
|
+
throw new Error("Stored session belongs to a different OAuth client; use separate persistence or explicitly reset it");
|
|
154
|
+
}
|
|
155
|
+
if (requestedScope !== undefined && session?.tokens !== undefined && normalizeOAuthScope(session.tokens.scope ?? session.requestedScope) !== requestedScope)
|
|
156
|
+
throw new Error("Stored session does not match the requested OAuth scope; authorize again or select separate persistence");
|
|
143
157
|
if (session?.refreshState === "pending") {
|
|
144
158
|
if (!allowInteractive || options.allowInteractive === false || sessionDiscovery === undefined)
|
|
145
159
|
throw new Error("OAuth refresh outcome is unknown; authorize again before using this resource");
|
|
@@ -220,10 +234,13 @@ export function createDefaultOAuthClientProvider(options) {
|
|
|
220
234
|
...session,
|
|
221
235
|
tokens: {
|
|
222
236
|
...refreshedTokens,
|
|
223
|
-
refreshToken: refreshedTokens.refreshToken ?? session.tokens.refreshToken
|
|
237
|
+
refreshToken: refreshedTokens.refreshToken ?? session.tokens.refreshToken,
|
|
238
|
+
scope: refreshedTokens.scope ?? session.tokens.scope
|
|
224
239
|
},
|
|
225
240
|
discovery: toStoredDiscovery(discovery)
|
|
226
241
|
};
|
|
242
|
+
if (requestedScope !== undefined && normalizeOAuthScope(updatedSession.tokens?.scope ?? session.requestedScope) !== requestedScope)
|
|
243
|
+
throw new Error("OAuth refresh response does not match the requested OAuth scope; authorize again");
|
|
227
244
|
await saveSession(resource, updatedSession);
|
|
228
245
|
return updatedSession;
|
|
229
246
|
}
|
|
@@ -251,6 +268,7 @@ export function createDefaultOAuthClientProvider(options) {
|
|
|
251
268
|
resource,
|
|
252
269
|
authorizationServer: discovery.authorizationServer,
|
|
253
270
|
client: resolvedClient.client,
|
|
271
|
+
...(requestedScope === undefined ? {} : { requestedScope }),
|
|
254
272
|
discovery: toStoredDiscovery(discovery)
|
|
255
273
|
};
|
|
256
274
|
await saveSession(resource, sessionWithoutTokens);
|
|
@@ -262,7 +280,7 @@ export function createDefaultOAuthClientProvider(options) {
|
|
|
262
280
|
clientId: resolvedClient.client.clientId,
|
|
263
281
|
redirectUri: loopback.redirectUri,
|
|
264
282
|
codeChallenge: challenge,
|
|
265
|
-
clientMetadata
|
|
283
|
+
clientMetadata
|
|
266
284
|
});
|
|
267
285
|
const code = await loopback.waitForCode(authorizationUrl);
|
|
268
286
|
const tokens = await exchangeAuthorizationCode({
|
|
@@ -276,6 +294,8 @@ export function createDefaultOAuthClientProvider(options) {
|
|
|
276
294
|
fetch, signal,
|
|
277
295
|
now
|
|
278
296
|
});
|
|
297
|
+
if (requestedScope !== undefined && tokens.scope !== undefined && normalizeOAuthScope(tokens.scope) !== requestedScope)
|
|
298
|
+
throw new Error("OAuth authorization response does not match the requested OAuth scope");
|
|
279
299
|
const session = {
|
|
280
300
|
...sessionWithoutTokens,
|
|
281
301
|
tokens
|
|
@@ -357,7 +377,7 @@ export function createDefaultOAuthClientProvider(options) {
|
|
|
357
377
|
};
|
|
358
378
|
}
|
|
359
379
|
}
|
|
360
|
-
const registrationBody = buildClientRegistrationBody(
|
|
380
|
+
const registrationBody = buildClientRegistrationBody(clientMetadata, redirectUri);
|
|
361
381
|
const deadline = AbortSignal.timeout(30_000);
|
|
362
382
|
const signal = parentSignal === undefined ? deadline : AbortSignal.any([parentSignal, deadline]);
|
|
363
383
|
const response = await fetchMcpResponse(fetch, registrationEndpoint, {
|
|
@@ -520,10 +540,10 @@ function normalizeStoredTokens(value) {
|
|
|
520
540
|
const tokenType = getOwnString(value, "tokenType");
|
|
521
541
|
const expiresAt = getOwnEntry(value, "expiresAt");
|
|
522
542
|
const refreshToken = getOwnEntry(value, "refreshToken");
|
|
523
|
-
const scope =
|
|
543
|
+
const scope = getOwnEntry(value, "scope");
|
|
524
544
|
const normalizedAccessToken = accessToken?.trim();
|
|
525
545
|
const normalizedRefreshToken = typeof refreshToken === "string" ? refreshToken.trim() : undefined;
|
|
526
|
-
const normalizedScope = scope
|
|
546
|
+
const normalizedScope = normalizeOAuthScope(scope);
|
|
527
547
|
if (accessToken === undefined ||
|
|
528
548
|
normalizedAccessToken === undefined ||
|
|
529
549
|
normalizedAccessToken.length === 0 ||
|
|
@@ -555,7 +575,7 @@ function getClientMetadata(client) {
|
|
|
555
575
|
}
|
|
556
576
|
return {
|
|
557
577
|
clientName: normalizeOptionalOAuthString(client.metadata.clientName),
|
|
558
|
-
scope:
|
|
578
|
+
scope: normalizeOAuthScope(client.metadata.scope),
|
|
559
579
|
softwareId: normalizeOptionalOAuthString(client.metadata.softwareId),
|
|
560
580
|
softwareVersion: normalizeOptionalOAuthString(client.metadata.softwareVersion)
|
|
561
581
|
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** Compare OAuth scope sets without accepting controls or changing token case. */
|
|
2
|
+
export function normalizeOAuthScope(scope) {
|
|
3
|
+
if (scope === undefined)
|
|
4
|
+
return undefined;
|
|
5
|
+
if (typeof scope !== "string" || [...scope].some(char => char.charCodeAt(0) < 32 || char.charCodeAt(0) > 126 || char === '"' || char === "\\"))
|
|
6
|
+
throw new Error("Invalid OAuth scope syntax");
|
|
7
|
+
const normalized = [...new Set(scope.split(" ").filter(Boolean))].sort().join(" ");
|
|
8
|
+
return normalized || undefined;
|
|
9
|
+
}
|
package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/client/token-endpoint.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { canonicalizeResourceIndicator } from "../resource-indicator.js";
|
|
2
2
|
import { readBoundedResponseText } from "../http-response.js";
|
|
3
3
|
import { fetchMcpResponse } from "../http-fetch.js";
|
|
4
|
+
import { normalizeOAuthScope } from "./scope.js";
|
|
4
5
|
const MAX_JS_DATE_MS = 8_640_000_000_000_000;
|
|
5
6
|
export class OAuthError extends Error {
|
|
6
7
|
error;
|
|
@@ -117,7 +118,9 @@ async function requestTokens(input) {
|
|
|
117
118
|
const normalizedRefreshToken = typeof refreshToken === "string" && refreshToken.trim().length > 0
|
|
118
119
|
? refreshToken.trim()
|
|
119
120
|
: undefined;
|
|
120
|
-
const normalizedScope =
|
|
121
|
+
const normalizedScope = normalizeOAuthScope(scope);
|
|
122
|
+
if (scope !== undefined && normalizedScope === undefined)
|
|
123
|
+
throw new Error("Invalid OAuth scope syntax in token response");
|
|
121
124
|
return {
|
|
122
125
|
accessToken: normalizedAccessToken,
|
|
123
126
|
refreshToken: normalizedRefreshToken === undefined ? undefined : normalizedRefreshToken,
|
|
@@ -80,6 +80,8 @@ export interface StoredOAuthSession {
|
|
|
80
80
|
tokens?: StoredOAuthTokens;
|
|
81
81
|
/** A refresh was begun; its winning response may not have been persisted. */
|
|
82
82
|
refreshState?: "pending";
|
|
83
|
+
/** Canonical explicitly requested scope set when the server omits token scope. */
|
|
84
|
+
requestedScope?: string;
|
|
83
85
|
discovery: {
|
|
84
86
|
resourceMetadataUrl: string;
|
|
85
87
|
resourceMetadata: Record<string, unknown>;
|
|
@@ -112,6 +114,8 @@ export interface DefaultOAuthClientProviderOptions {
|
|
|
112
114
|
allowInteractive?: boolean;
|
|
113
115
|
/** Maximum wait to acquire a session transaction lock (default 30,000 ms). */
|
|
114
116
|
sessionLockTimeoutMs?: number;
|
|
117
|
+
/** Isolate native persisted sessions and registrations for a named profile. */
|
|
118
|
+
persistenceNamespace?: string;
|
|
115
119
|
/** Import an existing grant for one resource. Persisted sessions take precedence. */
|
|
116
120
|
initialGrant?: {
|
|
117
121
|
resource: string;
|
|
@@ -183,6 +183,8 @@ interface StoredOAuthSession {
|
|
|
183
183
|
tokens?: StoredOAuthTokens;
|
|
184
184
|
/** A refresh was begun; its winning response may not have been persisted. */
|
|
185
185
|
refreshState?: "pending";
|
|
186
|
+
/** Canonical explicitly requested scope set when the server omits token scope. */
|
|
187
|
+
requestedScope?: string;
|
|
186
188
|
discovery: {
|
|
187
189
|
resourceMetadataUrl: string;
|
|
188
190
|
resourceMetadata: Record<string, unknown>;
|
|
@@ -215,6 +217,8 @@ interface DefaultOAuthClientProviderOptions {
|
|
|
215
217
|
allowInteractive?: boolean;
|
|
216
218
|
/** Maximum wait to acquire a session transaction lock (default 30,000 ms). */
|
|
217
219
|
sessionLockTimeoutMs?: number;
|
|
220
|
+
/** Isolate native persisted sessions and registrations for a named profile. */
|
|
221
|
+
persistenceNamespace?: string;
|
|
218
222
|
/** Import an existing grant for one resource. Persisted sessions take precedence. */
|
|
219
223
|
initialGrant?: {
|
|
220
224
|
resource: string;
|
|
@@ -4077,16 +4077,17 @@ var DEFAULT_CLIENT_FILE_SALT = "poe-code:mcp-oauth:clients:v1";
|
|
|
4077
4077
|
var DEFAULT_CLIENT_FILE_DIRECTORY = ".poe-code/mcp-oauth/clients";
|
|
4078
4078
|
var DEFAULT_CLIENT_KEYCHAIN_SERVICE = "poe-code-mcp-oauth-clients";
|
|
4079
4079
|
var MAX_JS_DATE_MS = 864e13;
|
|
4080
|
-
function createAuthStoreSessionStore(options = {}) {
|
|
4080
|
+
function createAuthStoreSessionStore(options = {}, namespace) {
|
|
4081
|
+
assertPersistenceNamespace(namespace);
|
|
4081
4082
|
return {
|
|
4082
4083
|
async withLock(resource, operation, lockOptions) {
|
|
4083
|
-
const store = createResourceSecretStore(resource, options);
|
|
4084
|
+
const store = createResourceSecretStore(resource, options, namespace);
|
|
4084
4085
|
if (store.withLock === void 0)
|
|
4085
4086
|
throw new Error("OAuth secret-store backend does not support transaction locks");
|
|
4086
4087
|
return store.withLock(operation, lockOptions);
|
|
4087
4088
|
},
|
|
4088
4089
|
async load(resource) {
|
|
4089
|
-
const store = createResourceSecretStore(resource, options);
|
|
4090
|
+
const store = createResourceSecretStore(resource, options, namespace);
|
|
4090
4091
|
const value = await store.get();
|
|
4091
4092
|
if (value === null) {
|
|
4092
4093
|
return null;
|
|
@@ -4103,19 +4104,20 @@ function createAuthStoreSessionStore(options = {}) {
|
|
|
4103
4104
|
throw new Error("Stored OAuth session must match the expected shape");
|
|
4104
4105
|
},
|
|
4105
4106
|
async save(resource, session) {
|
|
4106
|
-
const store = createResourceSecretStore(resource, options);
|
|
4107
|
+
const store = createResourceSecretStore(resource, options, namespace);
|
|
4107
4108
|
await store.set(JSON.stringify(session));
|
|
4108
4109
|
},
|
|
4109
4110
|
async clear(resource) {
|
|
4110
|
-
const store = createResourceSecretStore(resource, options);
|
|
4111
|
+
const store = createResourceSecretStore(resource, options, namespace);
|
|
4111
4112
|
await store.delete();
|
|
4112
4113
|
}
|
|
4113
4114
|
};
|
|
4114
4115
|
}
|
|
4115
|
-
function createAuthStoreClientStore(options) {
|
|
4116
|
+
function createAuthStoreClientStore(options, namespace) {
|
|
4117
|
+
assertPersistenceNamespace(namespace);
|
|
4116
4118
|
return {
|
|
4117
4119
|
async load(issuer) {
|
|
4118
|
-
const store = createIssuerSecretStore(issuer, options);
|
|
4120
|
+
const store = createIssuerSecretStore(issuer, options, namespace);
|
|
4119
4121
|
const value = await store.get();
|
|
4120
4122
|
if (value === null) {
|
|
4121
4123
|
return null;
|
|
@@ -4137,17 +4139,17 @@ function createAuthStoreClientStore(options) {
|
|
|
4137
4139
|
throw new Error("Stored OAuth client must be a JSON object with clientId");
|
|
4138
4140
|
},
|
|
4139
4141
|
async save(issuer, client) {
|
|
4140
|
-
const store = createIssuerSecretStore(issuer, options);
|
|
4142
|
+
const store = createIssuerSecretStore(issuer, options, namespace);
|
|
4141
4143
|
await store.set(JSON.stringify(client));
|
|
4142
4144
|
},
|
|
4143
4145
|
async clear(issuer) {
|
|
4144
|
-
const store = createIssuerSecretStore(issuer, options);
|
|
4146
|
+
const store = createIssuerSecretStore(issuer, options, namespace);
|
|
4145
4147
|
await store.delete();
|
|
4146
4148
|
}
|
|
4147
4149
|
};
|
|
4148
4150
|
}
|
|
4149
|
-
function createNamedSecretStore(key2, options, defaults) {
|
|
4150
|
-
const hash = crypto.createHash("sha256").update(key2).digest("hex");
|
|
4151
|
+
function createNamedSecretStore(key2, options, defaults, namespace) {
|
|
4152
|
+
const hash = crypto.createHash("sha256").update(namespace === void 0 ? key2 : JSON.stringify([namespace, key2])).digest("hex");
|
|
4151
4153
|
const configuredFilePath = options.fileStore?.filePath;
|
|
4152
4154
|
const parsedFilePath = configuredFilePath === void 0 ? null : path4.parse(configuredFilePath);
|
|
4153
4155
|
const fileStore = {
|
|
@@ -4165,21 +4167,25 @@ function createNamedSecretStore(key2, options, defaults) {
|
|
|
4165
4167
|
};
|
|
4166
4168
|
return createSecretStore({ ...options, fileStore, keychainStore }).store;
|
|
4167
4169
|
}
|
|
4168
|
-
function createResourceSecretStore(resource, options) {
|
|
4170
|
+
function createResourceSecretStore(resource, options, namespace) {
|
|
4169
4171
|
return createNamedSecretStore(canonicalizeResourceIndicator(resource), options, {
|
|
4170
4172
|
salt: DEFAULT_FILE_SALT,
|
|
4171
4173
|
directory: DEFAULT_FILE_DIRECTORY,
|
|
4172
4174
|
service: DEFAULT_KEYCHAIN_SERVICE,
|
|
4173
4175
|
accountPrefix: "provider"
|
|
4174
|
-
});
|
|
4176
|
+
}, namespace);
|
|
4175
4177
|
}
|
|
4176
|
-
function createIssuerSecretStore(issuer, options) {
|
|
4178
|
+
function createIssuerSecretStore(issuer, options, namespace) {
|
|
4177
4179
|
return createNamedSecretStore(issuer, options, {
|
|
4178
4180
|
salt: DEFAULT_CLIENT_FILE_SALT,
|
|
4179
4181
|
directory: DEFAULT_CLIENT_FILE_DIRECTORY,
|
|
4180
4182
|
service: DEFAULT_CLIENT_KEYCHAIN_SERVICE,
|
|
4181
4183
|
accountPrefix: "issuer"
|
|
4182
|
-
});
|
|
4184
|
+
}, namespace);
|
|
4185
|
+
}
|
|
4186
|
+
function assertPersistenceNamespace(namespace) {
|
|
4187
|
+
if (namespace !== void 0 && (typeof namespace !== "string" || namespace.trim() === "" || Buffer.byteLength(namespace, "utf8") > 1024))
|
|
4188
|
+
throw new Error("OAuth persistence namespace must be a nonempty string within 1024 bytes");
|
|
4183
4189
|
}
|
|
4184
4190
|
function isObjectRecord(value) {
|
|
4185
4191
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -4195,7 +4201,7 @@ function isStoredOAuthSession(value) {
|
|
|
4195
4201
|
if (!isObjectRecord(value)) {
|
|
4196
4202
|
return false;
|
|
4197
4203
|
}
|
|
4198
|
-
return isNonBlankOwnString(value, "resource") && isNonBlankOwnString(value, "authorizationServer") && isStoredOAuthClient(getOwnEntry3(value, "client")) && isStoredOAuthDiscovery(getOwnEntry3(value, "discovery")) && (getOwnEntry3(value, "refreshState") === void 0 || getOwnEntry3(value, "refreshState") === "pending" && getOwnEntry3(value, "tokens") === void 0) && isStoredOAuthTokensOrMissing(getOwnEntry3(value, "tokens"));
|
|
4204
|
+
return isNonBlankOwnString(value, "resource") && isNonBlankOwnString(value, "authorizationServer") && isStoredOAuthClient(getOwnEntry3(value, "client")) && isStoredOAuthDiscovery(getOwnEntry3(value, "discovery")) && (getOwnEntry3(value, "requestedScope") === void 0 || isNonBlankOwnString(value, "requestedScope")) && (getOwnEntry3(value, "refreshState") === void 0 || getOwnEntry3(value, "refreshState") === "pending" && getOwnEntry3(value, "tokens") === void 0) && isStoredOAuthTokensOrMissing(getOwnEntry3(value, "tokens"));
|
|
4199
4205
|
}
|
|
4200
4206
|
function isStoredOAuthClient(value) {
|
|
4201
4207
|
if (!isObjectRecord(value) || !isNonBlankOwnString(value, "clientId")) {
|
|
@@ -4236,6 +4242,16 @@ function isNonBlankOwnString(record2, key2) {
|
|
|
4236
4242
|
return value !== void 0 && value.trim().length > 0;
|
|
4237
4243
|
}
|
|
4238
4244
|
|
|
4245
|
+
// ../mcp-oauth/dist/client/scope.js
|
|
4246
|
+
function normalizeOAuthScope(scope) {
|
|
4247
|
+
if (scope === void 0)
|
|
4248
|
+
return void 0;
|
|
4249
|
+
if (typeof scope !== "string" || [...scope].some((char) => char.charCodeAt(0) < 32 || char.charCodeAt(0) > 126 || char === '"' || char === "\\"))
|
|
4250
|
+
throw new Error("Invalid OAuth scope syntax");
|
|
4251
|
+
const normalized = [...new Set(scope.split(" ").filter(Boolean))].sort().join(" ");
|
|
4252
|
+
return normalized || void 0;
|
|
4253
|
+
}
|
|
4254
|
+
|
|
4239
4255
|
// ../mcp-oauth/dist/client/default-oauth-client-provider.js
|
|
4240
4256
|
import { isIP } from "node:net";
|
|
4241
4257
|
|
|
@@ -4720,7 +4736,9 @@ async function requestTokens(input) {
|
|
|
4720
4736
|
const refreshToken = getOwnEntry5(payload, "refresh_token");
|
|
4721
4737
|
const scope = getOwnEntry5(payload, "scope");
|
|
4722
4738
|
const normalizedRefreshToken = typeof refreshToken === "string" && refreshToken.trim().length > 0 ? refreshToken.trim() : void 0;
|
|
4723
|
-
const normalizedScope =
|
|
4739
|
+
const normalizedScope = normalizeOAuthScope(scope);
|
|
4740
|
+
if (scope !== void 0 && normalizedScope === void 0)
|
|
4741
|
+
throw new Error("Invalid OAuth scope syntax in token response");
|
|
4724
4742
|
return {
|
|
4725
4743
|
accessToken: normalizedAccessToken,
|
|
4726
4744
|
refreshToken: normalizedRefreshToken === void 0 ? void 0 : normalizedRefreshToken,
|
|
@@ -4840,8 +4858,11 @@ function createOAuthClientProvider(options) {
|
|
|
4840
4858
|
}
|
|
4841
4859
|
function createDefaultOAuthClientProvider(options) {
|
|
4842
4860
|
loopbackTarget(options.browser);
|
|
4843
|
-
|
|
4844
|
-
const
|
|
4861
|
+
assertPersistenceNamespace(options.persistenceNamespace);
|
|
4862
|
+
const clientMetadata = getClientMetadata(options.client);
|
|
4863
|
+
const requestedScope = clientMetadata?.scope;
|
|
4864
|
+
const sessionStore = options.sessionStore ?? createAuthStoreSessionStore(options.authStore, options.persistenceNamespace);
|
|
4865
|
+
const clientStore = options.authStore === void 0 ? null : createAuthStoreClientStore(options.authStore, options.persistenceNamespace);
|
|
4845
4866
|
const now = options.now ?? Date.now;
|
|
4846
4867
|
const registeredClients = /* @__PURE__ */ new Map();
|
|
4847
4868
|
if (options.initialGrant !== void 0) {
|
|
@@ -4862,6 +4883,8 @@ function createDefaultOAuthClientProvider(options) {
|
|
|
4862
4883
|
if (initialGrant !== void 0 && (initialGrant.tokens === void 0 || initialGrant.client === null))
|
|
4863
4884
|
throw new Error("OAuth initial grant requires valid tokens and the original client ID");
|
|
4864
4885
|
if (initialGrant?.tokens !== void 0) {
|
|
4886
|
+
if (requestedScope !== void 0 && initialGrant.tokens.scope !== requestedScope)
|
|
4887
|
+
throw new Error("OAuth initial grant does not match the requested OAuth scope");
|
|
4865
4888
|
try {
|
|
4866
4889
|
new Headers({ Authorization: `Bearer ${initialGrant.tokens.accessToken}` });
|
|
4867
4890
|
} catch {
|
|
@@ -4949,6 +4972,7 @@ function createDefaultOAuthClientProvider(options) {
|
|
|
4949
4972
|
authorizationServer: discovery.authorizationServer,
|
|
4950
4973
|
client: initialGrant.client,
|
|
4951
4974
|
tokens: initialGrant.tokens,
|
|
4975
|
+
...requestedScope === void 0 ? {} : { requestedScope },
|
|
4952
4976
|
discovery: toStoredDiscovery(discovery)
|
|
4953
4977
|
};
|
|
4954
4978
|
await saveSession(canonicalResource, session);
|
|
@@ -4958,6 +4982,13 @@ function createDefaultOAuthClientProvider(options) {
|
|
|
4958
4982
|
if (forceRefresh && rejectedTokens !== void 0 && (rejectedTokens === null || session?.tokens === void 0 || !sameTokenGrant(session.tokens, rejectedTokens)))
|
|
4959
4983
|
forceRefresh = false;
|
|
4960
4984
|
const sessionDiscovery = resolveDiscovery(discovery, session);
|
|
4985
|
+
if ((options.client.mode === "static" || initialGrant !== void 0) && session !== null && (session.tokens !== void 0 || session.refreshState === "pending")) {
|
|
4986
|
+
const configured = normalizeConfiguredClient(options.client);
|
|
4987
|
+
if (configured === null || configured.clientId !== session.client.clientId || configured.clientSecret !== session.client.clientSecret)
|
|
4988
|
+
throw new Error("Stored session belongs to a different OAuth client; use separate persistence or explicitly reset it");
|
|
4989
|
+
}
|
|
4990
|
+
if (requestedScope !== void 0 && session?.tokens !== void 0 && normalizeOAuthScope(session.tokens.scope ?? session.requestedScope) !== requestedScope)
|
|
4991
|
+
throw new Error("Stored session does not match the requested OAuth scope; authorize again or select separate persistence");
|
|
4961
4992
|
if (session?.refreshState === "pending") {
|
|
4962
4993
|
if (!allowInteractive || options.allowInteractive === false || sessionDiscovery === void 0)
|
|
4963
4994
|
throw new Error("OAuth refresh outcome is unknown; authorize again before using this resource");
|
|
@@ -5034,10 +5065,13 @@ function createDefaultOAuthClientProvider(options) {
|
|
|
5034
5065
|
...session,
|
|
5035
5066
|
tokens: {
|
|
5036
5067
|
...refreshedTokens,
|
|
5037
|
-
refreshToken: refreshedTokens.refreshToken ?? session.tokens.refreshToken
|
|
5068
|
+
refreshToken: refreshedTokens.refreshToken ?? session.tokens.refreshToken,
|
|
5069
|
+
scope: refreshedTokens.scope ?? session.tokens.scope
|
|
5038
5070
|
},
|
|
5039
5071
|
discovery: toStoredDiscovery(discovery)
|
|
5040
5072
|
};
|
|
5073
|
+
if (requestedScope !== void 0 && normalizeOAuthScope(updatedSession.tokens?.scope ?? session.requestedScope) !== requestedScope)
|
|
5074
|
+
throw new Error("OAuth refresh response does not match the requested OAuth scope; authorize again");
|
|
5041
5075
|
await saveSession(resource, updatedSession);
|
|
5042
5076
|
return updatedSession;
|
|
5043
5077
|
}
|
|
@@ -5065,6 +5099,7 @@ function createDefaultOAuthClientProvider(options) {
|
|
|
5065
5099
|
resource,
|
|
5066
5100
|
authorizationServer: discovery.authorizationServer,
|
|
5067
5101
|
client: resolvedClient.client,
|
|
5102
|
+
...requestedScope === void 0 ? {} : { requestedScope },
|
|
5068
5103
|
discovery: toStoredDiscovery(discovery)
|
|
5069
5104
|
};
|
|
5070
5105
|
await saveSession(resource, sessionWithoutTokens);
|
|
@@ -5076,7 +5111,7 @@ function createDefaultOAuthClientProvider(options) {
|
|
|
5076
5111
|
clientId: resolvedClient.client.clientId,
|
|
5077
5112
|
redirectUri: loopback.redirectUri,
|
|
5078
5113
|
codeChallenge: challenge,
|
|
5079
|
-
clientMetadata
|
|
5114
|
+
clientMetadata
|
|
5080
5115
|
});
|
|
5081
5116
|
const code = await loopback.waitForCode(authorizationUrl);
|
|
5082
5117
|
const tokens = await exchangeAuthorizationCode({
|
|
@@ -5091,6 +5126,8 @@ function createDefaultOAuthClientProvider(options) {
|
|
|
5091
5126
|
signal,
|
|
5092
5127
|
now
|
|
5093
5128
|
});
|
|
5129
|
+
if (requestedScope !== void 0 && tokens.scope !== void 0 && normalizeOAuthScope(tokens.scope) !== requestedScope)
|
|
5130
|
+
throw new Error("OAuth authorization response does not match the requested OAuth scope");
|
|
5094
5131
|
const session = {
|
|
5095
5132
|
...sessionWithoutTokens,
|
|
5096
5133
|
tokens
|
|
@@ -5168,7 +5205,7 @@ function createDefaultOAuthClientProvider(options) {
|
|
|
5168
5205
|
};
|
|
5169
5206
|
}
|
|
5170
5207
|
}
|
|
5171
|
-
const registrationBody = buildClientRegistrationBody(
|
|
5208
|
+
const registrationBody = buildClientRegistrationBody(clientMetadata, redirectUri);
|
|
5172
5209
|
const deadline = AbortSignal.timeout(3e4);
|
|
5173
5210
|
const signal = parentSignal === void 0 ? deadline : AbortSignal.any([parentSignal, deadline]);
|
|
5174
5211
|
const response = await fetchMcpResponse(fetch2, registrationEndpoint, {
|
|
@@ -5323,10 +5360,10 @@ function normalizeStoredTokens(value) {
|
|
|
5323
5360
|
const tokenType = getOwnString2(value, "tokenType");
|
|
5324
5361
|
const expiresAt = getOwnEntry6(value, "expiresAt");
|
|
5325
5362
|
const refreshToken = getOwnEntry6(value, "refreshToken");
|
|
5326
|
-
const scope =
|
|
5363
|
+
const scope = getOwnEntry6(value, "scope");
|
|
5327
5364
|
const normalizedAccessToken = accessToken?.trim();
|
|
5328
5365
|
const normalizedRefreshToken = typeof refreshToken === "string" ? refreshToken.trim() : void 0;
|
|
5329
|
-
const normalizedScope = scope
|
|
5366
|
+
const normalizedScope = normalizeOAuthScope(scope);
|
|
5330
5367
|
if (accessToken === void 0 || normalizedAccessToken === void 0 || normalizedAccessToken.length === 0 || tokenType !== "Bearer" || !(expiresAt === null || typeof expiresAt === "number" && Number.isSafeInteger(expiresAt) && expiresAt <= MAX_JS_DATE_MS3 && Number.isFinite(new Date(expiresAt).getTime())) || refreshToken !== void 0 && (typeof refreshToken !== "string" || normalizedRefreshToken === void 0 || normalizedRefreshToken.length === 0)) {
|
|
5331
5368
|
return void 0;
|
|
5332
5369
|
}
|
|
@@ -5344,7 +5381,7 @@ function getClientMetadata(client) {
|
|
|
5344
5381
|
}
|
|
5345
5382
|
return {
|
|
5346
5383
|
clientName: normalizeOptionalOAuthString(client.metadata.clientName),
|
|
5347
|
-
scope:
|
|
5384
|
+
scope: normalizeOAuthScope(client.metadata.scope),
|
|
5348
5385
|
softwareId: normalizeOptionalOAuthString(client.metadata.softwareId),
|
|
5349
5386
|
softwareVersion: normalizeOptionalOAuthString(client.metadata.softwareVersion)
|
|
5350
5387
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "toolcraft",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.314",
|
|
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.314",
|
|
162
162
|
"toolcraft-design": "*",
|
|
163
163
|
"@poe-code/frontmatter": "*",
|
|
164
164
|
"@poe-code/agent-mcp-config": "*",
|