@mcp-z/client 1.0.0

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 (211) hide show
  1. package/AGENTS.md +159 -0
  2. package/LICENSE +21 -0
  3. package/README.md +90 -0
  4. package/dist/cjs/auth/capability-discovery.d.cts +25 -0
  5. package/dist/cjs/auth/capability-discovery.d.ts +25 -0
  6. package/dist/cjs/auth/capability-discovery.js +280 -0
  7. package/dist/cjs/auth/capability-discovery.js.map +1 -0
  8. package/dist/cjs/auth/index.d.cts +9 -0
  9. package/dist/cjs/auth/index.d.ts +9 -0
  10. package/dist/cjs/auth/index.js +28 -0
  11. package/dist/cjs/auth/index.js.map +1 -0
  12. package/dist/cjs/auth/interactive-oauth-flow.d.cts +58 -0
  13. package/dist/cjs/auth/interactive-oauth-flow.d.ts +58 -0
  14. package/dist/cjs/auth/interactive-oauth-flow.js +537 -0
  15. package/dist/cjs/auth/interactive-oauth-flow.js.map +1 -0
  16. package/dist/cjs/auth/oauth-callback-listener.d.cts +56 -0
  17. package/dist/cjs/auth/oauth-callback-listener.d.ts +56 -0
  18. package/dist/cjs/auth/oauth-callback-listener.js +333 -0
  19. package/dist/cjs/auth/oauth-callback-listener.js.map +1 -0
  20. package/dist/cjs/auth/pkce.d.cts +17 -0
  21. package/dist/cjs/auth/pkce.d.ts +17 -0
  22. package/dist/cjs/auth/pkce.js +192 -0
  23. package/dist/cjs/auth/pkce.js.map +1 -0
  24. package/dist/cjs/auth/rfc9728-discovery.d.cts +34 -0
  25. package/dist/cjs/auth/rfc9728-discovery.d.ts +34 -0
  26. package/dist/cjs/auth/rfc9728-discovery.js +436 -0
  27. package/dist/cjs/auth/rfc9728-discovery.js.map +1 -0
  28. package/dist/cjs/auth/types.d.cts +137 -0
  29. package/dist/cjs/auth/types.d.ts +137 -0
  30. package/dist/cjs/auth/types.js +9 -0
  31. package/dist/cjs/auth/types.js.map +1 -0
  32. package/dist/cjs/client-helpers.d.cts +55 -0
  33. package/dist/cjs/client-helpers.d.ts +55 -0
  34. package/dist/cjs/client-helpers.js +128 -0
  35. package/dist/cjs/client-helpers.js.map +1 -0
  36. package/dist/cjs/config/server-loader.d.cts +27 -0
  37. package/dist/cjs/config/server-loader.d.ts +27 -0
  38. package/dist/cjs/config/server-loader.js +111 -0
  39. package/dist/cjs/config/server-loader.js.map +1 -0
  40. package/dist/cjs/config/validate-config.d.cts +15 -0
  41. package/dist/cjs/config/validate-config.d.ts +15 -0
  42. package/dist/cjs/config/validate-config.js +128 -0
  43. package/dist/cjs/config/validate-config.js.map +1 -0
  44. package/dist/cjs/connection/connect-client.d.cts +59 -0
  45. package/dist/cjs/connection/connect-client.d.ts +59 -0
  46. package/dist/cjs/connection/connect-client.js +536 -0
  47. package/dist/cjs/connection/connect-client.js.map +1 -0
  48. package/dist/cjs/connection/existing-process-transport.d.cts +40 -0
  49. package/dist/cjs/connection/existing-process-transport.d.ts +40 -0
  50. package/dist/cjs/connection/existing-process-transport.js +274 -0
  51. package/dist/cjs/connection/existing-process-transport.js.map +1 -0
  52. package/dist/cjs/connection/types.d.cts +61 -0
  53. package/dist/cjs/connection/types.d.ts +61 -0
  54. package/dist/cjs/connection/types.js +53 -0
  55. package/dist/cjs/connection/types.js.map +1 -0
  56. package/dist/cjs/connection/wait-for-http-ready.d.cts +15 -0
  57. package/dist/cjs/connection/wait-for-http-ready.d.ts +15 -0
  58. package/dist/cjs/connection/wait-for-http-ready.js +232 -0
  59. package/dist/cjs/connection/wait-for-http-ready.js.map +1 -0
  60. package/dist/cjs/dcr/dcr-authenticator.d.cts +73 -0
  61. package/dist/cjs/dcr/dcr-authenticator.d.ts +73 -0
  62. package/dist/cjs/dcr/dcr-authenticator.js +655 -0
  63. package/dist/cjs/dcr/dcr-authenticator.js.map +1 -0
  64. package/dist/cjs/dcr/dynamic-client-registrar.d.cts +28 -0
  65. package/dist/cjs/dcr/dynamic-client-registrar.d.ts +28 -0
  66. package/dist/cjs/dcr/dynamic-client-registrar.js +245 -0
  67. package/dist/cjs/dcr/dynamic-client-registrar.js.map +1 -0
  68. package/dist/cjs/dcr/index.d.cts +8 -0
  69. package/dist/cjs/dcr/index.d.ts +8 -0
  70. package/dist/cjs/dcr/index.js +24 -0
  71. package/dist/cjs/dcr/index.js.map +1 -0
  72. package/dist/cjs/index.d.cts +21 -0
  73. package/dist/cjs/index.d.ts +21 -0
  74. package/dist/cjs/index.js +94 -0
  75. package/dist/cjs/index.js.map +1 -0
  76. package/dist/cjs/monkey-patches.d.cts +6 -0
  77. package/dist/cjs/monkey-patches.d.ts +6 -0
  78. package/dist/cjs/monkey-patches.js +236 -0
  79. package/dist/cjs/monkey-patches.js.map +1 -0
  80. package/dist/cjs/package.json +1 -0
  81. package/dist/cjs/response-wrappers.d.cts +41 -0
  82. package/dist/cjs/response-wrappers.d.ts +41 -0
  83. package/dist/cjs/response-wrappers.js +443 -0
  84. package/dist/cjs/response-wrappers.js.map +1 -0
  85. package/dist/cjs/search/index.d.cts +6 -0
  86. package/dist/cjs/search/index.d.ts +6 -0
  87. package/dist/cjs/search/index.js +25 -0
  88. package/dist/cjs/search/index.js.map +1 -0
  89. package/dist/cjs/search/search.d.cts +22 -0
  90. package/dist/cjs/search/search.d.ts +22 -0
  91. package/dist/cjs/search/search.js +630 -0
  92. package/dist/cjs/search/search.js.map +1 -0
  93. package/dist/cjs/search/types.d.cts +122 -0
  94. package/dist/cjs/search/types.d.ts +122 -0
  95. package/dist/cjs/search/types.js +10 -0
  96. package/dist/cjs/search/types.js.map +1 -0
  97. package/dist/cjs/spawn/spawn-server.d.cts +83 -0
  98. package/dist/cjs/spawn/spawn-server.d.ts +83 -0
  99. package/dist/cjs/spawn/spawn-server.js +410 -0
  100. package/dist/cjs/spawn/spawn-server.js.map +1 -0
  101. package/dist/cjs/spawn/spawn-servers.d.cts +151 -0
  102. package/dist/cjs/spawn/spawn-servers.d.ts +151 -0
  103. package/dist/cjs/spawn/spawn-servers.js +911 -0
  104. package/dist/cjs/spawn/spawn-servers.js.map +1 -0
  105. package/dist/cjs/types.d.cts +11 -0
  106. package/dist/cjs/types.d.ts +11 -0
  107. package/dist/cjs/types.js +10 -0
  108. package/dist/cjs/types.js.map +1 -0
  109. package/dist/cjs/utils/logger.d.cts +24 -0
  110. package/dist/cjs/utils/logger.d.ts +24 -0
  111. package/dist/cjs/utils/logger.js +80 -0
  112. package/dist/cjs/utils/logger.js.map +1 -0
  113. package/dist/cjs/utils/path-utils.d.cts +45 -0
  114. package/dist/cjs/utils/path-utils.d.ts +45 -0
  115. package/dist/cjs/utils/path-utils.js +158 -0
  116. package/dist/cjs/utils/path-utils.js.map +1 -0
  117. package/dist/cjs/utils/sanitizer.d.cts +30 -0
  118. package/dist/cjs/utils/sanitizer.d.ts +30 -0
  119. package/dist/cjs/utils/sanitizer.js +124 -0
  120. package/dist/cjs/utils/sanitizer.js.map +1 -0
  121. package/dist/esm/auth/capability-discovery.d.ts +25 -0
  122. package/dist/esm/auth/capability-discovery.js +110 -0
  123. package/dist/esm/auth/capability-discovery.js.map +1 -0
  124. package/dist/esm/auth/index.d.ts +9 -0
  125. package/dist/esm/auth/index.js +6 -0
  126. package/dist/esm/auth/index.js.map +1 -0
  127. package/dist/esm/auth/interactive-oauth-flow.d.ts +58 -0
  128. package/dist/esm/auth/interactive-oauth-flow.js +217 -0
  129. package/dist/esm/auth/interactive-oauth-flow.js.map +1 -0
  130. package/dist/esm/auth/oauth-callback-listener.d.ts +56 -0
  131. package/dist/esm/auth/oauth-callback-listener.js +166 -0
  132. package/dist/esm/auth/oauth-callback-listener.js.map +1 -0
  133. package/dist/esm/auth/pkce.d.ts +17 -0
  134. package/dist/esm/auth/pkce.js +41 -0
  135. package/dist/esm/auth/pkce.js.map +1 -0
  136. package/dist/esm/auth/rfc9728-discovery.d.ts +34 -0
  137. package/dist/esm/auth/rfc9728-discovery.js +157 -0
  138. package/dist/esm/auth/rfc9728-discovery.js.map +1 -0
  139. package/dist/esm/auth/types.d.ts +137 -0
  140. package/dist/esm/auth/types.js +7 -0
  141. package/dist/esm/auth/types.js.map +1 -0
  142. package/dist/esm/client-helpers.d.ts +55 -0
  143. package/dist/esm/client-helpers.js +81 -0
  144. package/dist/esm/client-helpers.js.map +1 -0
  145. package/dist/esm/config/server-loader.d.ts +27 -0
  146. package/dist/esm/config/server-loader.js +49 -0
  147. package/dist/esm/config/server-loader.js.map +1 -0
  148. package/dist/esm/config/validate-config.d.ts +15 -0
  149. package/dist/esm/config/validate-config.js +76 -0
  150. package/dist/esm/config/validate-config.js.map +1 -0
  151. package/dist/esm/connection/connect-client.d.ts +59 -0
  152. package/dist/esm/connection/connect-client.js +272 -0
  153. package/dist/esm/connection/connect-client.js.map +1 -0
  154. package/dist/esm/connection/existing-process-transport.d.ts +40 -0
  155. package/dist/esm/connection/existing-process-transport.js +103 -0
  156. package/dist/esm/connection/existing-process-transport.js.map +1 -0
  157. package/dist/esm/connection/types.d.ts +61 -0
  158. package/dist/esm/connection/types.js +34 -0
  159. package/dist/esm/connection/types.js.map +1 -0
  160. package/dist/esm/connection/wait-for-http-ready.d.ts +15 -0
  161. package/dist/esm/connection/wait-for-http-ready.js +43 -0
  162. package/dist/esm/connection/wait-for-http-ready.js.map +1 -0
  163. package/dist/esm/dcr/dcr-authenticator.d.ts +73 -0
  164. package/dist/esm/dcr/dcr-authenticator.js +235 -0
  165. package/dist/esm/dcr/dcr-authenticator.js.map +1 -0
  166. package/dist/esm/dcr/dynamic-client-registrar.d.ts +28 -0
  167. package/dist/esm/dcr/dynamic-client-registrar.js +66 -0
  168. package/dist/esm/dcr/dynamic-client-registrar.js.map +1 -0
  169. package/dist/esm/dcr/index.d.ts +8 -0
  170. package/dist/esm/dcr/index.js +5 -0
  171. package/dist/esm/dcr/index.js.map +1 -0
  172. package/dist/esm/index.d.ts +21 -0
  173. package/dist/esm/index.js +22 -0
  174. package/dist/esm/index.js.map +1 -0
  175. package/dist/esm/monkey-patches.d.ts +6 -0
  176. package/dist/esm/monkey-patches.js +32 -0
  177. package/dist/esm/monkey-patches.js.map +1 -0
  178. package/dist/esm/package.json +1 -0
  179. package/dist/esm/response-wrappers.d.ts +41 -0
  180. package/dist/esm/response-wrappers.js +201 -0
  181. package/dist/esm/response-wrappers.js.map +1 -0
  182. package/dist/esm/search/index.d.ts +6 -0
  183. package/dist/esm/search/index.js +3 -0
  184. package/dist/esm/search/index.js.map +1 -0
  185. package/dist/esm/search/search.d.ts +22 -0
  186. package/dist/esm/search/search.js +236 -0
  187. package/dist/esm/search/search.js.map +1 -0
  188. package/dist/esm/search/types.d.ts +122 -0
  189. package/dist/esm/search/types.js +8 -0
  190. package/dist/esm/search/types.js.map +1 -0
  191. package/dist/esm/spawn/spawn-server.d.ts +83 -0
  192. package/dist/esm/spawn/spawn-server.js +145 -0
  193. package/dist/esm/spawn/spawn-server.js.map +1 -0
  194. package/dist/esm/spawn/spawn-servers.d.ts +151 -0
  195. package/dist/esm/spawn/spawn-servers.js +406 -0
  196. package/dist/esm/spawn/spawn-servers.js.map +1 -0
  197. package/dist/esm/types.d.ts +11 -0
  198. package/dist/esm/types.js +9 -0
  199. package/dist/esm/types.js.map +1 -0
  200. package/dist/esm/utils/logger.d.ts +24 -0
  201. package/dist/esm/utils/logger.js +59 -0
  202. package/dist/esm/utils/logger.js.map +1 -0
  203. package/dist/esm/utils/path-utils.d.ts +45 -0
  204. package/dist/esm/utils/path-utils.js +89 -0
  205. package/dist/esm/utils/path-utils.js.map +1 -0
  206. package/dist/esm/utils/sanitizer.d.ts +30 -0
  207. package/dist/esm/utils/sanitizer.js +43 -0
  208. package/dist/esm/utils/sanitizer.js.map +1 -0
  209. package/package.json +92 -0
  210. package/schemas/servers.d.ts +90 -0
  211. package/schemas/servers.schema.json +104 -0
@@ -0,0 +1,436 @@
1
+ /**
2
+ * RFC 9728 Protected Resource Metadata Discovery
3
+ * Probes .well-known/oauth-protected-resource endpoint
4
+ */ "use strict";
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ function _export(target, all) {
9
+ for(var name in all)Object.defineProperty(target, name, {
10
+ enumerable: true,
11
+ get: Object.getOwnPropertyDescriptor(all, name).get
12
+ });
13
+ }
14
+ _export(exports, {
15
+ get discoverAuthorizationServerMetadata () {
16
+ return discoverAuthorizationServerMetadata;
17
+ },
18
+ get discoverProtectedResourceMetadata () {
19
+ return discoverProtectedResourceMetadata;
20
+ }
21
+ });
22
+ function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
23
+ try {
24
+ var info = gen[key](arg);
25
+ var value = info.value;
26
+ } catch (error) {
27
+ reject(error);
28
+ return;
29
+ }
30
+ if (info.done) {
31
+ resolve(value);
32
+ } else {
33
+ Promise.resolve(value).then(_next, _throw);
34
+ }
35
+ }
36
+ function _async_to_generator(fn) {
37
+ return function() {
38
+ var self = this, args = arguments;
39
+ return new Promise(function(resolve, reject) {
40
+ var gen = fn.apply(self, args);
41
+ function _next(value) {
42
+ asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
43
+ }
44
+ function _throw(err) {
45
+ asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
46
+ }
47
+ _next(undefined);
48
+ });
49
+ };
50
+ }
51
+ function _ts_generator(thisArg, body) {
52
+ var f, y, t, _ = {
53
+ label: 0,
54
+ sent: function() {
55
+ if (t[0] & 1) throw t[1];
56
+ return t[1];
57
+ },
58
+ trys: [],
59
+ ops: []
60
+ }, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype), d = Object.defineProperty;
61
+ return d(g, "next", {
62
+ value: verb(0)
63
+ }), d(g, "throw", {
64
+ value: verb(1)
65
+ }), d(g, "return", {
66
+ value: verb(2)
67
+ }), typeof Symbol === "function" && d(g, Symbol.iterator, {
68
+ value: function() {
69
+ return this;
70
+ }
71
+ }), g;
72
+ function verb(n) {
73
+ return function(v) {
74
+ return step([
75
+ n,
76
+ v
77
+ ]);
78
+ };
79
+ }
80
+ function step(op) {
81
+ if (f) throw new TypeError("Generator is already executing.");
82
+ while(g && (g = 0, op[0] && (_ = 0)), _)try {
83
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
84
+ if (y = 0, t) op = [
85
+ op[0] & 2,
86
+ t.value
87
+ ];
88
+ switch(op[0]){
89
+ case 0:
90
+ case 1:
91
+ t = op;
92
+ break;
93
+ case 4:
94
+ _.label++;
95
+ return {
96
+ value: op[1],
97
+ done: false
98
+ };
99
+ case 5:
100
+ _.label++;
101
+ y = op[1];
102
+ op = [
103
+ 0
104
+ ];
105
+ continue;
106
+ case 7:
107
+ op = _.ops.pop();
108
+ _.trys.pop();
109
+ continue;
110
+ default:
111
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
112
+ _ = 0;
113
+ continue;
114
+ }
115
+ if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
116
+ _.label = op[1];
117
+ break;
118
+ }
119
+ if (op[0] === 6 && _.label < t[1]) {
120
+ _.label = t[1];
121
+ t = op;
122
+ break;
123
+ }
124
+ if (t && _.label < t[2]) {
125
+ _.label = t[2];
126
+ _.ops.push(op);
127
+ break;
128
+ }
129
+ if (t[2]) _.ops.pop();
130
+ _.trys.pop();
131
+ continue;
132
+ }
133
+ op = body.call(thisArg, _);
134
+ } catch (e) {
135
+ op = [
136
+ 6,
137
+ e
138
+ ];
139
+ y = 0;
140
+ } finally{
141
+ f = t = 0;
142
+ }
143
+ if (op[0] & 5) throw op[1];
144
+ return {
145
+ value: op[0] ? op[1] : void 0,
146
+ done: true
147
+ };
148
+ }
149
+ }
150
+ /**
151
+ * Extract origin (protocol + host) from a URL
152
+ * @param url - Full URL that may include a path
153
+ * @returns Origin (e.g., "https://example.com") or original string if invalid URL
154
+ *
155
+ * @example
156
+ * getOrigin('https://example.com/mcp') // → 'https://example.com'
157
+ * getOrigin('http://localhost:9999/api/v1/mcp') // → 'http://localhost:9999'
158
+ */ function getOrigin(url) {
159
+ try {
160
+ return new URL(url).origin;
161
+ } catch (unused) {
162
+ // Invalid URL - return as-is for graceful degradation
163
+ return url;
164
+ }
165
+ }
166
+ /**
167
+ * Extract path from a URL (without origin)
168
+ * @param url - Full URL
169
+ * @returns Path component (e.g., "/mcp", "/api/v1/mcp") or empty string if no path
170
+ */ function getPath(url) {
171
+ try {
172
+ var parsed = new URL(url);
173
+ // pathname includes leading slash, e.g., "/mcp"
174
+ return parsed.pathname === '/' ? '' : parsed.pathname;
175
+ } catch (unused) {
176
+ return '';
177
+ }
178
+ }
179
+ function discoverProtectedResourceMetadata(resourceUrl) {
180
+ return _async_to_generator(function() {
181
+ var origin, path, rootUrl, response, metadata, rootMetadata, subPathUrl, subPathResponse, unused, unused1, subPathUrl1, response1, unused2, _error;
182
+ return _ts_generator(this, function(_state) {
183
+ switch(_state.label){
184
+ case 0:
185
+ _state.trys.push([
186
+ 0,
187
+ 19,
188
+ ,
189
+ 20
190
+ ]);
191
+ origin = getOrigin(resourceUrl);
192
+ path = getPath(resourceUrl);
193
+ // Strategy 1: Try root location (REQUIRED by RFC 9728)
194
+ rootUrl = "".concat(origin, "/.well-known/oauth-protected-resource");
195
+ _state.label = 1;
196
+ case 1:
197
+ _state.trys.push([
198
+ 1,
199
+ 11,
200
+ ,
201
+ 12
202
+ ]);
203
+ return [
204
+ 4,
205
+ fetch(rootUrl, {
206
+ method: 'GET',
207
+ headers: {
208
+ Accept: 'application/json',
209
+ Connection: 'close'
210
+ }
211
+ })
212
+ ];
213
+ case 2:
214
+ response = _state.sent();
215
+ if (!response.ok) return [
216
+ 3,
217
+ 10
218
+ ];
219
+ return [
220
+ 4,
221
+ response.json()
222
+ ];
223
+ case 3:
224
+ metadata = _state.sent();
225
+ // Check if the discovered resource matches what we're looking for
226
+ if (metadata.resource === resourceUrl) {
227
+ return [
228
+ 2,
229
+ metadata
230
+ ];
231
+ }
232
+ // If there's no path component, return root metadata
233
+ // (e.g., looking for http://example.com and found it)
234
+ if (!path) {
235
+ return [
236
+ 2,
237
+ metadata
238
+ ];
239
+ }
240
+ if (!resourceUrl.startsWith(metadata.resource)) return [
241
+ 3,
242
+ 10
243
+ ];
244
+ // Still try sub-path location to see if there's more specific metadata
245
+ // But save root metadata as fallback
246
+ rootMetadata = metadata;
247
+ // Try sub-path location for more specific metadata
248
+ subPathUrl = "".concat(origin, "/.well-known/oauth-protected-resource").concat(path);
249
+ _state.label = 4;
250
+ case 4:
251
+ _state.trys.push([
252
+ 4,
253
+ 8,
254
+ ,
255
+ 9
256
+ ]);
257
+ return [
258
+ 4,
259
+ fetch(subPathUrl, {
260
+ method: 'GET',
261
+ headers: {
262
+ Accept: 'application/json',
263
+ Connection: 'close'
264
+ }
265
+ })
266
+ ];
267
+ case 5:
268
+ subPathResponse = _state.sent();
269
+ if (!subPathResponse.ok) return [
270
+ 3,
271
+ 7
272
+ ];
273
+ return [
274
+ 4,
275
+ subPathResponse.json()
276
+ ];
277
+ case 6:
278
+ return [
279
+ 2,
280
+ _state.sent()
281
+ ];
282
+ case 7:
283
+ return [
284
+ 3,
285
+ 9
286
+ ];
287
+ case 8:
288
+ unused = _state.sent();
289
+ return [
290
+ 3,
291
+ 9
292
+ ];
293
+ case 9:
294
+ // Return root metadata as it applies to this resource
295
+ return [
296
+ 2,
297
+ rootMetadata
298
+ ];
299
+ case 10:
300
+ return [
301
+ 3,
302
+ 12
303
+ ];
304
+ case 11:
305
+ unused1 = _state.sent();
306
+ return [
307
+ 3,
308
+ 12
309
+ ];
310
+ case 12:
311
+ if (!path) return [
312
+ 3,
313
+ 18
314
+ ];
315
+ subPathUrl1 = "".concat(origin, "/.well-known/oauth-protected-resource").concat(path);
316
+ _state.label = 13;
317
+ case 13:
318
+ _state.trys.push([
319
+ 13,
320
+ 17,
321
+ ,
322
+ 18
323
+ ]);
324
+ return [
325
+ 4,
326
+ fetch(subPathUrl1, {
327
+ method: 'GET',
328
+ headers: {
329
+ Accept: 'application/json',
330
+ Connection: 'close'
331
+ }
332
+ })
333
+ ];
334
+ case 14:
335
+ response1 = _state.sent();
336
+ if (!response1.ok) return [
337
+ 3,
338
+ 16
339
+ ];
340
+ return [
341
+ 4,
342
+ response1.json()
343
+ ];
344
+ case 15:
345
+ return [
346
+ 2,
347
+ _state.sent()
348
+ ];
349
+ case 16:
350
+ return [
351
+ 3,
352
+ 18
353
+ ];
354
+ case 17:
355
+ unused2 = _state.sent();
356
+ return [
357
+ 3,
358
+ 18
359
+ ];
360
+ case 18:
361
+ // Neither location found or resource didn't match
362
+ return [
363
+ 2,
364
+ null
365
+ ];
366
+ case 19:
367
+ _error = _state.sent();
368
+ // Network error, invalid URL, or other failure
369
+ return [
370
+ 2,
371
+ null
372
+ ];
373
+ case 20:
374
+ return [
375
+ 2
376
+ ];
377
+ }
378
+ });
379
+ })();
380
+ }
381
+ function discoverAuthorizationServerMetadata(authServerUrl) {
382
+ return _async_to_generator(function() {
383
+ var origin, wellKnownUrl, response, _error;
384
+ return _ts_generator(this, function(_state) {
385
+ switch(_state.label){
386
+ case 0:
387
+ _state.trys.push([
388
+ 0,
389
+ 3,
390
+ ,
391
+ 4
392
+ ]);
393
+ origin = getOrigin(authServerUrl);
394
+ wellKnownUrl = "".concat(origin, "/.well-known/oauth-authorization-server");
395
+ return [
396
+ 4,
397
+ fetch(wellKnownUrl, {
398
+ method: 'GET',
399
+ headers: {
400
+ Accept: 'application/json',
401
+ Connection: 'close'
402
+ }
403
+ })
404
+ ];
405
+ case 1:
406
+ response = _state.sent();
407
+ if (!response.ok) {
408
+ return [
409
+ 2,
410
+ null
411
+ ];
412
+ }
413
+ return [
414
+ 4,
415
+ response.json()
416
+ ];
417
+ case 2:
418
+ return [
419
+ 2,
420
+ _state.sent()
421
+ ];
422
+ case 3:
423
+ _error = _state.sent();
424
+ return [
425
+ 2,
426
+ null
427
+ ];
428
+ case 4:
429
+ return [
430
+ 2
431
+ ];
432
+ }
433
+ });
434
+ })();
435
+ }
436
+ /* CJS INTEROP */ if (exports.__esModule && exports.default) { try { Object.defineProperty(exports.default, '__esModule', { value: true }); for (var key in exports) { exports.default[key] = exports[key]; } } catch (_) {}; module.exports = exports.default; }
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/Users/kevin/Dev/Projects/ai/mcp-z/libs/client/src/auth/rfc9728-discovery.ts"],"sourcesContent":["/**\n * RFC 9728 Protected Resource Metadata Discovery\n * Probes .well-known/oauth-protected-resource endpoint\n */\n\nimport type { AuthorizationServerMetadata, ProtectedResourceMetadata } from './types.ts';\n\n/**\n * Extract origin (protocol + host) from a URL\n * @param url - Full URL that may include a path\n * @returns Origin (e.g., \"https://example.com\") or original string if invalid URL\n *\n * @example\n * getOrigin('https://example.com/mcp') // → 'https://example.com'\n * getOrigin('http://localhost:9999/api/v1/mcp') // → 'http://localhost:9999'\n */\nfunction getOrigin(url: string): string {\n try {\n return new URL(url).origin;\n } catch {\n // Invalid URL - return as-is for graceful degradation\n return url;\n }\n}\n\n/**\n * Extract path from a URL (without origin)\n * @param url - Full URL\n * @returns Path component (e.g., \"/mcp\", \"/api/v1/mcp\") or empty string if no path\n */\nfunction getPath(url: string): string {\n try {\n const parsed = new URL(url);\n // pathname includes leading slash, e.g., \"/mcp\"\n return parsed.pathname === '/' ? '' : parsed.pathname;\n } catch {\n return '';\n }\n}\n\n/**\n * Discover OAuth 2.0 Protected Resource Metadata (RFC 9728)\n * Probes .well-known/oauth-protected-resource endpoint\n *\n * Discovery Strategy:\n * 1. Try origin root: {origin}/.well-known/oauth-protected-resource\n * 2. If 404, try sub-path: {origin}/.well-known/oauth-protected-resource{path}\n *\n * @param resourceUrl - URL of the protected resource (e.g., https://ai.todoist.net/mcp)\n * @returns ProtectedResourceMetadata if discovered, null otherwise\n *\n * @example\n * // Todoist case: MCP at ai.todoist.net/mcp, OAuth at todoist.com\n * const metadata = await discoverProtectedResourceMetadata('https://ai.todoist.net/mcp');\n * // Returns: { resource: \"https://ai.todoist.net/mcp\", authorization_servers: [\"https://todoist.com\"] }\n */\nexport async function discoverProtectedResourceMetadata(resourceUrl: string): Promise<ProtectedResourceMetadata | null> {\n try {\n const origin = getOrigin(resourceUrl);\n const path = getPath(resourceUrl);\n\n // Strategy 1: Try root location (REQUIRED by RFC 9728)\n const rootUrl = `${origin}/.well-known/oauth-protected-resource`;\n\n try {\n const response = await fetch(rootUrl, {\n method: 'GET',\n headers: { Accept: 'application/json', Connection: 'close' },\n });\n\n if (response.ok) {\n const metadata = (await response.json()) as ProtectedResourceMetadata;\n // Check if the discovered resource matches what we're looking for\n if (metadata.resource === resourceUrl) {\n return metadata;\n }\n // If there's no path component, return root metadata\n // (e.g., looking for http://example.com and found it)\n if (!path) {\n return metadata;\n }\n // If requested URL starts with metadata.resource, the root metadata applies to sub-paths\n // (e.g., looking for http://example.com/api/v1/mcp, found http://example.com)\n if (resourceUrl.startsWith(metadata.resource)) {\n // Still try sub-path location to see if there's more specific metadata\n // But save root metadata as fallback\n const rootMetadata = metadata;\n\n // Try sub-path location for more specific metadata\n const subPathUrl = `${origin}/.well-known/oauth-protected-resource${path}`;\n try {\n const subPathResponse = await fetch(subPathUrl, {\n method: 'GET',\n headers: { Accept: 'application/json', Connection: 'close' },\n });\n if (subPathResponse.ok) {\n return (await subPathResponse.json()) as ProtectedResourceMetadata;\n }\n } catch {\n // Sub-path failed, use root metadata\n }\n\n // Return root metadata as it applies to this resource\n return rootMetadata;\n }\n // Otherwise, try sub-path location before giving up\n }\n } catch {\n // Continue to sub-path location\n }\n\n // Strategy 2: Try sub-path location (MCP spec extension)\n // Only try if there's a path component\n if (path) {\n const subPathUrl = `${origin}/.well-known/oauth-protected-resource${path}`;\n\n try {\n const response = await fetch(subPathUrl, {\n method: 'GET',\n headers: { Accept: 'application/json', Connection: 'close' },\n });\n\n if (response.ok) {\n return (await response.json()) as ProtectedResourceMetadata;\n }\n } catch {\n // Fall through to return null\n }\n }\n\n // Neither location found or resource didn't match\n return null;\n } catch (_error) {\n // Network error, invalid URL, or other failure\n return null;\n }\n}\n\n/**\n * Discover OAuth 2.0 Authorization Server Metadata (RFC 8414)\n * Probes .well-known/oauth-authorization-server endpoint\n *\n * @param authServerUrl - URL of the authorization server (typically from RFC 9728 discovery)\n * @returns AuthorizationServerMetadata if discovered, null otherwise\n *\n * @example\n * const metadata = await discoverAuthorizationServerMetadata('https://todoist.com');\n * // Returns: { issuer: \"https://todoist.com\", authorization_endpoint: \"...\", ... }\n */\nexport async function discoverAuthorizationServerMetadata(authServerUrl: string): Promise<AuthorizationServerMetadata | null> {\n try {\n const origin = getOrigin(authServerUrl);\n const wellKnownUrl = `${origin}/.well-known/oauth-authorization-server`;\n\n const response = await fetch(wellKnownUrl, {\n method: 'GET',\n headers: { Accept: 'application/json', Connection: 'close' },\n });\n\n if (!response.ok) {\n return null;\n }\n\n return (await response.json()) as AuthorizationServerMetadata;\n } catch (_error) {\n return null;\n }\n}\n"],"names":["discoverAuthorizationServerMetadata","discoverProtectedResourceMetadata","getOrigin","url","URL","origin","getPath","parsed","pathname","resourceUrl","path","rootUrl","response","metadata","rootMetadata","subPathUrl","subPathResponse","_error","fetch","method","headers","Accept","Connection","ok","json","resource","startsWith","authServerUrl","wellKnownUrl"],"mappings":"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"}
@@ -0,0 +1,137 @@
1
+ /**
2
+ * Shared types for OAuth and DCR authentication
3
+ */
4
+ /**
5
+ * OAuth callback result from authorization server
6
+ */
7
+ export interface CallbackResult {
8
+ /** Authorization code from OAuth server */
9
+ code: string;
10
+ /** State parameter for CSRF protection */
11
+ state?: string;
12
+ }
13
+ /**
14
+ * PKCE (Proof Key for Code Exchange) parameters (RFC 7636)
15
+ * Used to secure OAuth 2.0 authorization code flow for public clients
16
+ */
17
+ export interface PkceParams {
18
+ /** Code verifier - cryptographically random string (43-128 characters) */
19
+ codeVerifier: string;
20
+ /** Code challenge - derived from code verifier using challenge method */
21
+ codeChallenge: string;
22
+ /** Code challenge method - S256 (SHA-256) or plain */
23
+ codeChallengeMethod: 'S256' | 'plain';
24
+ }
25
+ /**
26
+ * OAuth token set with access and refresh tokens
27
+ */
28
+ export interface TokenSet {
29
+ /** Access token for API requests */
30
+ accessToken: string;
31
+ /** Refresh token for obtaining new access tokens */
32
+ refreshToken: string;
33
+ /** Timestamp when access token expires (milliseconds since epoch) */
34
+ expiresAt: number;
35
+ /** Scopes granted for this token set */
36
+ scopes?: string[];
37
+ /** Client ID used for DCR registration (stored for future use) */
38
+ clientId?: string;
39
+ /** Client secret used for DCR registration (stored for future use) */
40
+ clientSecret?: string;
41
+ }
42
+ /**
43
+ * OAuth 2.0 Protected Resource Metadata (RFC 9728)
44
+ * Response from .well-known/oauth-protected-resource endpoint
45
+ */
46
+ export interface ProtectedResourceMetadata {
47
+ /** The protected resource identifier */
48
+ resource: string;
49
+ /** List of authorization server URLs that can issue tokens for this resource */
50
+ authorization_servers: string[];
51
+ /** Optional list of scopes supported by this resource */
52
+ scopes_supported?: string[];
53
+ /** Optional list of bearer token methods supported (header, query, body) */
54
+ bearer_methods_supported?: string[];
55
+ }
56
+ /**
57
+ * OAuth 2.0 Authorization Server Metadata (RFC 8414)
58
+ * Response from .well-known/oauth-authorization-server endpoint
59
+ */
60
+ export interface AuthorizationServerMetadata {
61
+ /** The authorization server's issuer identifier */
62
+ issuer?: string;
63
+ /** URL of the authorization endpoint */
64
+ authorization_endpoint?: string;
65
+ /** URL of the token endpoint */
66
+ token_endpoint?: string;
67
+ /** URL of the client registration endpoint (DCR - RFC 7591) */
68
+ registration_endpoint?: string;
69
+ /** URL of the token introspection endpoint */
70
+ introspection_endpoint?: string;
71
+ /** List of OAuth scopes supported by the authorization server */
72
+ scopes_supported?: string[];
73
+ /** Response types supported (code, token, etc.) */
74
+ response_types_supported?: string[];
75
+ /** Grant types supported (authorization_code, refresh_token, etc.) */
76
+ grant_types_supported?: string[];
77
+ /** Token endpoint authentication methods supported */
78
+ token_endpoint_auth_methods_supported?: string[];
79
+ }
80
+ /**
81
+ * OAuth server capabilities discovered from .well-known endpoint
82
+ */
83
+ export interface AuthCapabilities {
84
+ /** Whether the server supports Dynamic Client Registration (RFC 7591) */
85
+ supportsDcr: boolean;
86
+ /** DCR client registration endpoint */
87
+ registrationEndpoint?: string;
88
+ /** OAuth authorization endpoint */
89
+ authorizationEndpoint?: string;
90
+ /** OAuth token endpoint */
91
+ tokenEndpoint?: string;
92
+ /** Token introspection endpoint */
93
+ introspectionEndpoint?: string;
94
+ /** Supported OAuth scopes */
95
+ scopes?: string[];
96
+ }
97
+ /**
98
+ * Client credentials from DCR registration
99
+ */
100
+ export interface ClientCredentials {
101
+ /** OAuth client ID */
102
+ clientId: string;
103
+ /** OAuth client secret */
104
+ clientSecret: string;
105
+ /** Timestamp when client was registered */
106
+ issuedAt?: number;
107
+ }
108
+ /**
109
+ * Options for DCR client registration
110
+ */
111
+ export interface DcrRegistrationOptions {
112
+ /** Client name to register */
113
+ clientName?: string;
114
+ /** Redirect URI for OAuth callback */
115
+ redirectUri?: string;
116
+ }
117
+ /**
118
+ * Options for OAuth authorization flow
119
+ */
120
+ export interface OAuthFlowOptions {
121
+ /** Port for OAuth callback listener (required - use get-port to find available port) */
122
+ port: number;
123
+ /** Redirect URI for OAuth callback (optional - will be built from port if not provided) */
124
+ redirectUri?: string;
125
+ /** OAuth scopes to request */
126
+ scopes?: string[];
127
+ /** Resource parameter (RFC 8707) - target resource server identifier */
128
+ resource?: string;
129
+ /** Enable PKCE (RFC 7636) - recommended for all clients, required for public clients */
130
+ pkce?: boolean;
131
+ /** Headless mode (don't open browser) */
132
+ headless?: boolean;
133
+ /** Timeout for callback (milliseconds) */
134
+ timeout?: number;
135
+ /** Optional logger for debug output (defaults to singleton logger) */
136
+ logger?: import('../utils/logger.js').Logger;
137
+ }