tiny-http-mcp-server 0.1.30 → 0.1.31
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/dist/composition.json +1 -1
- package/node_modules/mcp-oauth/README.md +8 -0
- package/node_modules/mcp-oauth/dist/client/auth-store-session-store.d.ts +3 -2
- package/node_modules/mcp-oauth/dist/client/auth-store-session-store.js +21 -15
- package/node_modules/mcp-oauth/dist/client/default-oauth-client-provider.js +4 -3
- package/node_modules/mcp-oauth/dist/client/types.d.ts +2 -0
- package/node_modules/tiny-mcp-client/dist/index.d.ts +2 -0
- package/node_modules/tiny-mcp-client/dist/index.js +24 -17
- package/package.json +1 -1
package/dist/composition.json
CHANGED
|
@@ -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
|
|
@@ -108,6 +109,13 @@ Static clients and dynamic initial-grant imports require cached grants to match
|
|
|
108
109
|
the original normalized client ID and secret. A different client configuration
|
|
109
110
|
fails before attaching or refreshing credentials and retains the stored record;
|
|
110
111
|
select separate persistence or explicitly reset the session to change apps.
|
|
112
|
+
Use `persistenceNamespace: "personal"` or `"work"` to keep separate native
|
|
113
|
+
profiles for the same resource/issuer. `createAuthStoreSessionStore(options,
|
|
114
|
+
namespace)` addresses the same profile when seeding or inspecting credentials.
|
|
115
|
+
Namespaces are hashed into file/Keychain identities and transaction locks;
|
|
116
|
+
omitting one preserves the default storage keys. Switching namespaces selects a
|
|
117
|
+
different record and does not migrate or reset the previous profile. Host-owned
|
|
118
|
+
`sessionStore` implementations remain responsible for their own profile keys.
|
|
111
119
|
|
|
112
120
|
`createAuthStoreSessionStore(options)` accepts the standard `auth-store` config.
|
|
113
121
|
|
|
@@ -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);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { isIP } from "node:net";
|
|
2
2
|
import { fetchMcpResponse } from "../http-fetch.js";
|
|
3
3
|
import { URL } from "node:url";
|
|
4
|
-
import { createAuthStoreClientStore, createAuthStoreSessionStore } from "./auth-store-session-store.js";
|
|
4
|
+
import { createAuthStoreClientStore, createAuthStoreSessionStore, assertPersistenceNamespace } from "./auth-store-session-store.js";
|
|
5
5
|
import { createLoopbackAuthorizationSession, loopbackTarget } from "./loopback-authorization.js";
|
|
6
6
|
import { createAuthorizationState } from "./authorization-state.js";
|
|
7
7
|
import { generateCodeChallenge, generateCodeVerifier } from "./pkce.js";
|
|
@@ -17,8 +17,9 @@ export function createOAuthClientProvider(options) {
|
|
|
17
17
|
}
|
|
18
18
|
export function createDefaultOAuthClientProvider(options) {
|
|
19
19
|
loopbackTarget(options.browser);
|
|
20
|
-
|
|
21
|
-
const
|
|
20
|
+
assertPersistenceNamespace(options.persistenceNamespace);
|
|
21
|
+
const sessionStore = options.sessionStore ?? createAuthStoreSessionStore(options.authStore, options.persistenceNamespace);
|
|
22
|
+
const clientStore = options.authStore === undefined ? null : createAuthStoreClientStore(options.authStore, options.persistenceNamespace);
|
|
22
23
|
const now = options.now ?? Date.now;
|
|
23
24
|
const registeredClients = new Map();
|
|
24
25
|
if (options.initialGrant !== undefined) {
|
|
@@ -112,6 +112,8 @@ export interface DefaultOAuthClientProviderOptions {
|
|
|
112
112
|
allowInteractive?: boolean;
|
|
113
113
|
/** Maximum wait to acquire a session transaction lock (default 30,000 ms). */
|
|
114
114
|
sessionLockTimeoutMs?: number;
|
|
115
|
+
/** Isolate native persisted sessions and registrations for a named profile. */
|
|
116
|
+
persistenceNamespace?: string;
|
|
115
117
|
/** Import an existing grant for one resource. Persisted sessions take precedence. */
|
|
116
118
|
initialGrant?: {
|
|
117
119
|
resource: string;
|
|
@@ -215,6 +215,8 @@ interface DefaultOAuthClientProviderOptions {
|
|
|
215
215
|
allowInteractive?: boolean;
|
|
216
216
|
/** Maximum wait to acquire a session transaction lock (default 30,000 ms). */
|
|
217
217
|
sessionLockTimeoutMs?: number;
|
|
218
|
+
/** Isolate native persisted sessions and registrations for a named profile. */
|
|
219
|
+
persistenceNamespace?: string;
|
|
218
220
|
/** Import an existing grant for one resource. Persisted sessions take precedence. */
|
|
219
221
|
initialGrant?: {
|
|
220
222
|
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);
|
|
@@ -4840,8 +4846,9 @@ function createOAuthClientProvider(options) {
|
|
|
4840
4846
|
}
|
|
4841
4847
|
function createDefaultOAuthClientProvider(options) {
|
|
4842
4848
|
loopbackTarget(options.browser);
|
|
4843
|
-
|
|
4844
|
-
const
|
|
4849
|
+
assertPersistenceNamespace(options.persistenceNamespace);
|
|
4850
|
+
const sessionStore = options.sessionStore ?? createAuthStoreSessionStore(options.authStore, options.persistenceNamespace);
|
|
4851
|
+
const clientStore = options.authStore === void 0 ? null : createAuthStoreClientStore(options.authStore, options.persistenceNamespace);
|
|
4845
4852
|
const now = options.now ?? Date.now;
|
|
4846
4853
|
const registeredClients = /* @__PURE__ */ new Map();
|
|
4847
4854
|
if (options.initialGrant !== void 0) {
|