@toolsdk.ai/registry 1.0.131 → 1.0.133

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.
Files changed (41) hide show
  1. package/README.md +11 -10
  2. package/dist/api/index.js +4 -0
  3. package/dist/domains/executor/executor-types.d.ts +3 -1
  4. package/dist/domains/executor/local-executor.d.ts +1 -1
  5. package/dist/domains/executor/local-executor.js +3 -3
  6. package/dist/domains/executor/sandbox-executor.d.ts +1 -1
  7. package/dist/domains/executor/sandbox-executor.js +3 -3
  8. package/dist/domains/oauth/__tests__/oauth-session.test.d.ts +1 -0
  9. package/dist/domains/oauth/__tests__/oauth-session.test.js +272 -0
  10. package/dist/domains/oauth/__tests__/oauth-utils.test.d.ts +1 -0
  11. package/dist/domains/oauth/__tests__/oauth-utils.test.js +284 -0
  12. package/dist/domains/oauth/index.d.ts +9 -0
  13. package/dist/domains/oauth/index.js +9 -0
  14. package/dist/domains/oauth/oauth-handler.d.ts +65 -0
  15. package/dist/domains/oauth/oauth-handler.js +355 -0
  16. package/dist/domains/oauth/oauth-route.d.ts +11 -0
  17. package/dist/domains/oauth/oauth-route.js +138 -0
  18. package/dist/domains/oauth/oauth-schema.d.ts +257 -0
  19. package/dist/domains/oauth/oauth-schema.js +119 -0
  20. package/dist/domains/oauth/oauth-session.d.ts +54 -0
  21. package/dist/domains/oauth/oauth-session.js +116 -0
  22. package/dist/domains/oauth/oauth-types.d.ts +148 -0
  23. package/dist/domains/oauth/oauth-types.js +9 -0
  24. package/dist/domains/oauth/oauth-utils.d.ts +99 -0
  25. package/dist/domains/oauth/oauth-utils.js +267 -0
  26. package/dist/domains/package/package-handler.d.ts +2 -2
  27. package/dist/domains/package/package-handler.js +4 -4
  28. package/dist/domains/package/package-route.js +5 -5
  29. package/dist/domains/package/package-schema.d.ts +81 -4
  30. package/dist/domains/package/package-schema.js +17 -0
  31. package/dist/domains/package/package-so.d.ts +11 -3
  32. package/dist/domains/package/package-so.js +4 -3
  33. package/dist/shared/schemas/common-schema.d.ts +92 -4
  34. package/dist/shared/schemas/common-schema.js +13 -0
  35. package/dist/shared/scripts-helpers/index.d.ts +9 -1
  36. package/dist/shared/utils/mcp-client-util.d.ts +3 -3
  37. package/dist/shared/utils/mcp-client-util.js +22 -1
  38. package/indexes/categories-list.json +1 -0
  39. package/indexes/packages-list.json +15 -0
  40. package/package.json +2 -1
  41. package/packages/developer-tools/github-mcp.json +19 -0
@@ -0,0 +1,284 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { buildAuthorizationUrl, generatePKCE, generateSessionId, generateState, getCanonicalResourceUri, parseWWWAuthenticate, verifyPKCESupport, } from "../oauth-utils";
3
+ describe("oauth-utils", () => {
4
+ describe("generatePKCE", () => {
5
+ it("should generate valid PKCE parameters", () => {
6
+ // Act
7
+ const pkce = generatePKCE();
8
+ // Assert
9
+ expect(pkce).toHaveProperty("codeVerifier");
10
+ expect(pkce).toHaveProperty("codeChallenge");
11
+ expect(pkce).toHaveProperty("codeChallengeMethod");
12
+ expect(pkce.codeChallengeMethod).toBe("S256");
13
+ });
14
+ it("should generate code verifier with correct length (43 chars base64url)", () => {
15
+ // Act
16
+ const pkce = generatePKCE();
17
+ // Assert - 32 bytes base64url encoded = 43 characters
18
+ expect(pkce.codeVerifier.length).toBe(43);
19
+ });
20
+ it("should generate code challenge with correct length", () => {
21
+ // Act
22
+ const pkce = generatePKCE();
23
+ // Assert - SHA256 hash (32 bytes) base64url encoded = 43 characters
24
+ expect(pkce.codeChallenge.length).toBe(43);
25
+ });
26
+ it("should generate different values each time", () => {
27
+ // Act
28
+ const pkce1 = generatePKCE();
29
+ const pkce2 = generatePKCE();
30
+ // Assert
31
+ expect(pkce1.codeVerifier).not.toBe(pkce2.codeVerifier);
32
+ expect(pkce1.codeChallenge).not.toBe(pkce2.codeChallenge);
33
+ });
34
+ it("should generate base64url encoded values (no +, /, =)", () => {
35
+ // Act
36
+ const pkce = generatePKCE();
37
+ // Assert - base64url should not contain +, /, or =
38
+ expect(pkce.codeVerifier).not.toMatch(/[+/=]/);
39
+ expect(pkce.codeChallenge).not.toMatch(/[+/=]/);
40
+ });
41
+ });
42
+ describe("generateState", () => {
43
+ it("should generate a valid UUID", () => {
44
+ // Act
45
+ const state = generateState();
46
+ // Assert - UUID format: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
47
+ expect(state).toMatch(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i);
48
+ });
49
+ it("should generate different values each time", () => {
50
+ // Act
51
+ const state1 = generateState();
52
+ const state2 = generateState();
53
+ // Assert
54
+ expect(state1).not.toBe(state2);
55
+ });
56
+ });
57
+ describe("generateSessionId", () => {
58
+ it("should generate a valid UUID", () => {
59
+ // Act
60
+ const sessionId = generateSessionId();
61
+ // Assert
62
+ expect(sessionId).toMatch(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i);
63
+ });
64
+ it("should generate different values each time", () => {
65
+ // Act
66
+ const id1 = generateSessionId();
67
+ const id2 = generateSessionId();
68
+ // Assert
69
+ expect(id1).not.toBe(id2);
70
+ });
71
+ });
72
+ describe("parseWWWAuthenticate", () => {
73
+ it("should parse complete WWW-Authenticate header", () => {
74
+ // Arrange
75
+ const header = 'Bearer realm="mcp", resource_metadata="http://localhost:3001/.well-known/oauth-protected-resource", scope="read write"';
76
+ // Act
77
+ const result = parseWWWAuthenticate(header);
78
+ // Assert
79
+ expect(result).toEqual({
80
+ realm: "mcp",
81
+ resourceMetadataUrl: "http://localhost:3001/.well-known/oauth-protected-resource",
82
+ scope: "read write",
83
+ });
84
+ });
85
+ it("should parse header with only realm", () => {
86
+ // Arrange
87
+ const header = 'Bearer realm="example"';
88
+ // Act
89
+ const result = parseWWWAuthenticate(header);
90
+ // Assert
91
+ expect(result).toEqual({
92
+ realm: "example",
93
+ });
94
+ });
95
+ it("should parse header with only resource_metadata", () => {
96
+ // Arrange
97
+ const header = 'Bearer resource_metadata="http://example.com/.well-known/oauth-protected-resource"';
98
+ // Act
99
+ const result = parseWWWAuthenticate(header);
100
+ // Assert
101
+ expect(result).toEqual({
102
+ resourceMetadataUrl: "http://example.com/.well-known/oauth-protected-resource",
103
+ });
104
+ });
105
+ it("should return empty object for empty header", () => {
106
+ // Arrange
107
+ const header = "Bearer";
108
+ // Act
109
+ const result = parseWWWAuthenticate(header);
110
+ // Assert
111
+ expect(result).toEqual({});
112
+ });
113
+ });
114
+ describe("verifyPKCESupport", () => {
115
+ it("should return supported=true when S256 is in supported methods", () => {
116
+ // Arrange
117
+ const metadata = {
118
+ issuer: "http://localhost:3001",
119
+ authorization_endpoint: "http://localhost:3001/authorize",
120
+ token_endpoint: "http://localhost:3001/token",
121
+ code_challenge_methods_supported: ["S256", "plain"],
122
+ };
123
+ // Act
124
+ const result = verifyPKCESupport(metadata);
125
+ // Assert
126
+ expect(result).toEqual({ supported: true, advertised: true });
127
+ });
128
+ it("should return supported=false when S256 is not in supported methods", () => {
129
+ // Arrange
130
+ const metadata = {
131
+ issuer: "http://localhost:3001",
132
+ authorization_endpoint: "http://localhost:3001/authorize",
133
+ token_endpoint: "http://localhost:3001/token",
134
+ code_challenge_methods_supported: ["plain"],
135
+ };
136
+ // Act
137
+ const result = verifyPKCESupport(metadata);
138
+ // Assert
139
+ expect(result).toEqual({ supported: false, advertised: true });
140
+ });
141
+ it("should return supported=true, advertised=false when code_challenge_methods_supported is missing", () => {
142
+ // Arrange
143
+ const metadata = {
144
+ issuer: "http://localhost:3001",
145
+ authorization_endpoint: "http://localhost:3001/authorize",
146
+ token_endpoint: "http://localhost:3001/token",
147
+ };
148
+ // Act
149
+ const result = verifyPKCESupport(metadata);
150
+ // Assert
151
+ expect(result).toEqual({ supported: true, advertised: false });
152
+ });
153
+ it("should return supported=true, advertised=false when code_challenge_methods_supported is empty", () => {
154
+ // Arrange
155
+ const metadata = {
156
+ issuer: "http://localhost:3001",
157
+ authorization_endpoint: "http://localhost:3001/authorize",
158
+ token_endpoint: "http://localhost:3001/token",
159
+ code_challenge_methods_supported: [],
160
+ };
161
+ // Act
162
+ const result = verifyPKCESupport(metadata);
163
+ // Assert
164
+ expect(result).toEqual({ supported: true, advertised: false });
165
+ });
166
+ });
167
+ describe("buildAuthorizationUrl", () => {
168
+ it("should build URL with all required parameters", () => {
169
+ // Arrange
170
+ const params = {
171
+ authorizationEndpoint: "http://localhost:3001/authorize",
172
+ clientId: "test-client",
173
+ redirectUri: "http://localhost:3003/callback",
174
+ state: "random-state",
175
+ codeChallenge: "test-challenge",
176
+ codeChallengeMethod: "S256",
177
+ };
178
+ // Act
179
+ const result = buildAuthorizationUrl(params);
180
+ // Assert
181
+ const url = new URL(result);
182
+ expect(url.origin).toBe("http://localhost:3001");
183
+ expect(url.pathname).toBe("/authorize");
184
+ expect(url.searchParams.get("response_type")).toBe("code");
185
+ expect(url.searchParams.get("client_id")).toBe("test-client");
186
+ expect(url.searchParams.get("redirect_uri")).toBe("http://localhost:3003/callback");
187
+ expect(url.searchParams.get("state")).toBe("random-state");
188
+ expect(url.searchParams.get("code_challenge")).toBe("test-challenge");
189
+ expect(url.searchParams.get("code_challenge_method")).toBe("S256");
190
+ });
191
+ it("should include scope when provided", () => {
192
+ // Arrange
193
+ const params = {
194
+ authorizationEndpoint: "http://localhost:3001/authorize",
195
+ clientId: "test-client",
196
+ redirectUri: "http://localhost:3003/callback",
197
+ state: "random-state",
198
+ codeChallenge: "test-challenge",
199
+ codeChallengeMethod: "S256",
200
+ scope: "read write",
201
+ };
202
+ // Act
203
+ const result = buildAuthorizationUrl(params);
204
+ // Assert
205
+ const url = new URL(result);
206
+ expect(url.searchParams.get("scope")).toBe("read write");
207
+ });
208
+ it("should include resource when provided", () => {
209
+ // Arrange
210
+ const params = {
211
+ authorizationEndpoint: "http://localhost:3001/authorize",
212
+ clientId: "test-client",
213
+ redirectUri: "http://localhost:3003/callback",
214
+ state: "random-state",
215
+ codeChallenge: "test-challenge",
216
+ codeChallengeMethod: "S256",
217
+ resource: "http://localhost:3001/mcp",
218
+ };
219
+ // Act
220
+ const result = buildAuthorizationUrl(params);
221
+ // Assert
222
+ const url = new URL(result);
223
+ expect(url.searchParams.get("resource")).toBe("http://localhost:3001/mcp");
224
+ });
225
+ it("should not include scope when not provided", () => {
226
+ // Arrange
227
+ const params = {
228
+ authorizationEndpoint: "http://localhost:3001/authorize",
229
+ clientId: "test-client",
230
+ redirectUri: "http://localhost:3003/callback",
231
+ state: "random-state",
232
+ codeChallenge: "test-challenge",
233
+ codeChallengeMethod: "S256",
234
+ };
235
+ // Act
236
+ const result = buildAuthorizationUrl(params);
237
+ // Assert
238
+ const url = new URL(result);
239
+ expect(url.searchParams.has("scope")).toBe(false);
240
+ });
241
+ });
242
+ describe("getCanonicalResourceUri", () => {
243
+ it("should return URL without trailing slash", () => {
244
+ // Arrange
245
+ const mcpServerUrl = "http://localhost:3001/mcp/";
246
+ // Act
247
+ const result = getCanonicalResourceUri(mcpServerUrl);
248
+ // Assert
249
+ expect(result).toBe("http://localhost:3001/mcp");
250
+ });
251
+ it("should keep URL without trailing slash unchanged", () => {
252
+ // Arrange
253
+ const mcpServerUrl = "http://localhost:3001/mcp";
254
+ // Act
255
+ const result = getCanonicalResourceUri(mcpServerUrl);
256
+ // Assert
257
+ expect(result).toBe("http://localhost:3001/mcp");
258
+ });
259
+ it("should handle root URL correctly", () => {
260
+ // Arrange
261
+ const mcpServerUrl = "http://localhost:3001/";
262
+ // Act
263
+ const result = getCanonicalResourceUri(mcpServerUrl);
264
+ // Assert
265
+ expect(result).toBe("http://localhost:3001/");
266
+ });
267
+ it("should strip query parameters", () => {
268
+ // Arrange
269
+ const mcpServerUrl = "http://localhost:3001/mcp?param=value";
270
+ // Act
271
+ const result = getCanonicalResourceUri(mcpServerUrl);
272
+ // Assert
273
+ expect(result).toBe("http://localhost:3001/mcp");
274
+ });
275
+ it("should strip fragment", () => {
276
+ // Arrange
277
+ const mcpServerUrl = "http://localhost:3001/mcp#section";
278
+ // Act
279
+ const result = getCanonicalResourceUri(mcpServerUrl);
280
+ // Assert
281
+ expect(result).toBe("http://localhost:3001/mcp");
282
+ });
283
+ });
284
+ });
@@ -0,0 +1,9 @@
1
+ /**
2
+ * OAuth Domain Exports
3
+ */
4
+ export * from "./oauth-handler";
5
+ export * from "./oauth-route";
6
+ export * from "./oauth-schema";
7
+ export * from "./oauth-session";
8
+ export * from "./oauth-types";
9
+ export * from "./oauth-utils";
@@ -0,0 +1,9 @@
1
+ /**
2
+ * OAuth Domain Exports
3
+ */
4
+ export * from "./oauth-handler";
5
+ export * from "./oauth-route";
6
+ export * from "./oauth-schema";
7
+ export * from "./oauth-session";
8
+ export * from "./oauth-types";
9
+ export * from "./oauth-utils";
@@ -0,0 +1,65 @@
1
+ /**
2
+ * OAuth Handler
3
+ *
4
+ * Business logic for OAuth flow:
5
+ * 1. Prepare: Discovery + Registration + Build Auth URL
6
+ * 2. Callback: Exchange code for tokens + Notify caller
7
+ * 3. Refresh: Refresh access token
8
+ */
9
+ import type { OAuthPrepareRequest, OAuthRefreshRequest } from "./oauth-types";
10
+ /**
11
+ * Prepare OAuth flow
12
+ *
13
+ * 1. Get MCP Server URL from package config
14
+ * 2. Discover Protected Resource Metadata
15
+ * 3. Discover Authorization Server Metadata
16
+ * 4. Verify PKCE support
17
+ * 5. Register client (Dynamic Client Registration)
18
+ * 6. Generate PKCE + state + session
19
+ * 7. Build authorization URL
20
+ */
21
+ export declare function prepareOAuth(request: OAuthPrepareRequest): Promise<{
22
+ success: boolean;
23
+ code: number;
24
+ message: string;
25
+ }>;
26
+ /**
27
+ * Handle OAuth callback
28
+ *
29
+ * 1. Find session by state
30
+ * 2. Exchange code for tokens
31
+ * 3. POST tokens + clientInfo to callbackBaseUrl
32
+ * 4. Delete session
33
+ * 5. Return HTML to close popup
34
+ */
35
+ export declare function handleCallback(params: {
36
+ code?: string;
37
+ state?: string;
38
+ error?: string;
39
+ error_description?: string;
40
+ }): Promise<{
41
+ success: boolean;
42
+ error: string;
43
+ error_description: string | undefined;
44
+ html: string;
45
+ sessionId?: undefined;
46
+ } | {
47
+ success: boolean;
48
+ sessionId: string;
49
+ html: string;
50
+ error?: undefined;
51
+ error_description?: undefined;
52
+ }>;
53
+ /**
54
+ * Refresh access token
55
+ */
56
+ export declare function handleRefresh(request: OAuthRefreshRequest): Promise<{
57
+ success: boolean;
58
+ code: number;
59
+ message: string;
60
+ }>;
61
+ export declare const oauthHandler: {
62
+ prepareOAuth: typeof prepareOAuth;
63
+ handleCallback: typeof handleCallback;
64
+ handleRefresh: typeof handleRefresh;
65
+ };