@expandai/mcp-server 0.1.1 → 0.1.4

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.
@@ -0,0 +1,831 @@
1
+ 'use strict';
2
+
3
+ var effect = require('effect');
4
+ var ai = require('@effect/ai');
5
+ var platformNode = require('@effect/platform-node');
6
+ var platform = require('@effect/platform');
7
+ var HttpClientError = require('@effect/platform/HttpClientError');
8
+ var HttpClientRequest = require('@effect/platform/HttpClientRequest');
9
+ var HttpClientResponse = require('@effect/platform/HttpClientResponse');
10
+ var Data = require('effect/Data');
11
+ var Effect2 = require('effect/Effect');
12
+ var S = require('effect/Schema');
13
+
14
+ function _interopNamespace(e) {
15
+ if (e && e.__esModule) return e;
16
+ var n = Object.create(null);
17
+ if (e) {
18
+ Object.keys(e).forEach(function (k) {
19
+ if (k !== 'default') {
20
+ var d = Object.getOwnPropertyDescriptor(e, k);
21
+ Object.defineProperty(n, k, d.get ? d : {
22
+ enumerable: true,
23
+ get: function () { return e[k]; }
24
+ });
25
+ }
26
+ });
27
+ }
28
+ n.default = e;
29
+ return Object.freeze(n);
30
+ }
31
+
32
+ var HttpClientError__namespace = /*#__PURE__*/_interopNamespace(HttpClientError);
33
+ var HttpClientRequest__namespace = /*#__PURE__*/_interopNamespace(HttpClientRequest);
34
+ var HttpClientResponse__namespace = /*#__PURE__*/_interopNamespace(HttpClientResponse);
35
+ var Data__namespace = /*#__PURE__*/_interopNamespace(Data);
36
+ var Effect2__namespace = /*#__PURE__*/_interopNamespace(Effect2);
37
+ var S__namespace = /*#__PURE__*/_interopNamespace(S);
38
+
39
+ // src/Server.ts
40
+
41
+ // package.json
42
+ var package_default = {
43
+ version: "0.1.4"};
44
+ var ExpandDocs = ai.McpServer.resource({
45
+ uri: "expand://about",
46
+ name: "About expand.ai",
47
+ description: "Key links for the expand.ai platform",
48
+ content: effect.Effect.succeed(`# expand.ai
49
+
50
+ - Website: https://expand.ai
51
+ - Quickstart: https://expand.ai/docs
52
+ - Dashboard: https://expand.ai/dashboard
53
+ `)
54
+ });
55
+ (class extends S__namespace.Struct({
56
+ url: S__namespace.String
57
+ }) {
58
+ });
59
+ var IssueTag = class extends S__namespace.Literal(
60
+ "Pointer",
61
+ "Unexpected",
62
+ "Missing",
63
+ "Composite",
64
+ "Refinement",
65
+ "Transformation",
66
+ "Type",
67
+ "Forbidden"
68
+ ) {
69
+ };
70
+ var PropertyKeyEnumTag = class extends S__namespace.Literal("symbol") {
71
+ };
72
+ var PropertyKey = class extends S__namespace.Union(
73
+ S__namespace.String,
74
+ S__namespace.Number,
75
+ /**
76
+ * an object to be decoded into a globally shared symbol
77
+ */
78
+ S__namespace.Struct({
79
+ _tag: PropertyKeyEnumTag,
80
+ key: S__namespace.String
81
+ })
82
+ ) {
83
+ };
84
+ var Issue = class extends S__namespace.Class("Issue")({
85
+ /**
86
+ * The tag identifying the type of parse issue
87
+ */
88
+ _tag: IssueTag,
89
+ /**
90
+ * The path to the property where the issue occurred
91
+ */
92
+ path: S__namespace.Array(PropertyKey),
93
+ /**
94
+ * A descriptive message explaining the issue
95
+ */
96
+ message: S__namespace.String
97
+ }) {
98
+ };
99
+ var HttpApiDecodeErrorTag = class extends S__namespace.Literal("HttpApiDecodeError") {
100
+ };
101
+ var HttpApiDecodeError = class extends S__namespace.Class("HttpApiDecodeError")({
102
+ issues: S__namespace.Array(Issue),
103
+ message: S__namespace.String,
104
+ _tag: HttpApiDecodeErrorTag
105
+ }) {
106
+ };
107
+ var UnauthorizedAccessTag = class extends S__namespace.Literal("UnauthorizedAccess") {
108
+ };
109
+ var UnauthorizedAccess = class extends S__namespace.Class("UnauthorizedAccess")({
110
+ _tag: UnauthorizedAccessTag
111
+ }) {
112
+ };
113
+ var AssetNotFoundTag = class extends S__namespace.Literal("AssetNotFound") {
114
+ };
115
+ var AssetNotFound = class extends S__namespace.Class("AssetNotFound")({
116
+ browserSessionId: S__namespace.optionalWith(S__namespace.String, { nullable: true }),
117
+ filename: S__namespace.String,
118
+ _tag: AssetNotFoundTag
119
+ }) {
120
+ };
121
+ var AssetNotInWaczTag = class extends S__namespace.Literal("AssetNotInWacz") {
122
+ };
123
+ var AssetNotInWacz = class extends S__namespace.Class("AssetNotInWacz")({
124
+ url: S__namespace.String,
125
+ _tag: AssetNotInWaczTag
126
+ }) {
127
+ };
128
+ var AssetsGetByUrl404 = class extends S__namespace.Union(AssetNotFound, AssetNotInWacz) {
129
+ };
130
+ var AssetReadErrorTag = class extends S__namespace.Literal("AssetReadError") {
131
+ };
132
+ var AssetReadError = class extends S__namespace.Class("AssetReadError")({
133
+ browserSessionId: S__namespace.optionalWith(S__namespace.String, { nullable: true }),
134
+ filename: S__namespace.String,
135
+ _tag: AssetReadErrorTag
136
+ }) {
137
+ };
138
+ var InvalidWaczFormatTag = class extends S__namespace.Literal("InvalidWaczFormat") {
139
+ };
140
+ var InvalidWaczFormat = class extends S__namespace.Class("InvalidWaczFormat")({
141
+ message: S__namespace.String,
142
+ _tag: InvalidWaczFormatTag
143
+ }) {
144
+ };
145
+ var AssetRetrievalErrorTag = class extends S__namespace.Literal("AssetRetrievalError") {
146
+ };
147
+ var AssetRetrievalError = class extends S__namespace.Class("AssetRetrievalError")({
148
+ browserSessionId: S__namespace.String,
149
+ url: S__namespace.String,
150
+ _tag: AssetRetrievalErrorTag
151
+ }) {
152
+ };
153
+ var AssetsGetByUrl500 = class extends S__namespace.Union(AssetReadError, InvalidWaczFormat, AssetRetrievalError) {
154
+ };
155
+ var CurlErrorInputMethod = class extends S__namespace.Literal(
156
+ "GET",
157
+ "POST",
158
+ "HEAD",
159
+ "PUT",
160
+ "DELETE",
161
+ "CONNECT",
162
+ "OPTIONS",
163
+ "TRACE",
164
+ "PATCH"
165
+ ) {
166
+ };
167
+ var CurlErrorTag = class extends S__namespace.Literal("CurlError") {
168
+ };
169
+ var CurlError = class extends S__namespace.Class("CurlError")({
170
+ status: S__namespace.Number,
171
+ input: S__namespace.Struct({
172
+ method: CurlErrorInputMethod,
173
+ url: S__namespace.String,
174
+ body: S__namespace.optionalWith(S__namespace.String, { nullable: true }),
175
+ headers: S__namespace.optionalWith(S__namespace.Struct({}), { nullable: true }),
176
+ proxy: S__namespace.optionalWith(
177
+ S__namespace.Struct({
178
+ server: S__namespace.String,
179
+ username: S__namespace.optionalWith(S__namespace.String, { nullable: true }),
180
+ password: S__namespace.optionalWith(S__namespace.String, { nullable: true })
181
+ }),
182
+ { nullable: true }
183
+ ),
184
+ timeout: S__namespace.optionalWith(S__namespace.Number, { nullable: true }),
185
+ connectTimeout: S__namespace.optionalWith(S__namespace.Number, { nullable: true })
186
+ }),
187
+ _tag: CurlErrorTag
188
+ }) {
189
+ };
190
+ var AssetListItem = class extends S__namespace.Class("AssetListItem")({
191
+ url: S__namespace.String,
192
+ mime: S__namespace.String,
193
+ status: S__namespace.Number
194
+ }) {
195
+ };
196
+ var AssetListResponse = class extends S__namespace.Class("AssetListResponse")({
197
+ browserSessionId: S__namespace.String,
198
+ assets: S__namespace.Array(AssetListItem)
199
+ }) {
200
+ };
201
+ var AssetsList500 = class extends S__namespace.Union(AssetReadError, InvalidWaczFormat) {
202
+ };
203
+ var URL = class extends S__namespace.String {
204
+ };
205
+ var SelectHtmlConfig = class extends S__namespace.Record({ key: S__namespace.String, value: S__namespace.Unknown }) {
206
+ };
207
+ var SelectMarkdownConfig = class extends S__namespace.Record({ key: S__namespace.String, value: S__namespace.Unknown }) {
208
+ };
209
+ var SelectScreenshotConfig = class extends S__namespace.Class("SelectScreenshotConfig")({
210
+ /**
211
+ * Whether to capture the full page including content below the fold
212
+ */
213
+ fullPage: S__namespace.optionalWith(S__namespace.Boolean, { nullable: true })
214
+ }) {
215
+ };
216
+ var Trimmed = class extends S__namespace.String.pipe(S__namespace.pattern(/^\S[\s\S]*\S$|^\S$|^$/)) {
217
+ };
218
+ var Int2 = class extends S__namespace.Int {
219
+ };
220
+ (class extends S__namespace.Class("FetchRequest")({
221
+ url: URL,
222
+ /**
223
+ * Specifies which content formats to include in the response
224
+ */
225
+ select: S__namespace.optionalWith(
226
+ S__namespace.Struct({
227
+ html: S__namespace.optionalWith(
228
+ S__namespace.Union(
229
+ S__namespace.Boolean,
230
+ SelectHtmlConfig
231
+ ),
232
+ { nullable: true }
233
+ ),
234
+ /**
235
+ * Include markdown-formatted content in the response
236
+ */
237
+ markdown: S__namespace.optionalWith(
238
+ S__namespace.Union(
239
+ S__namespace.Boolean,
240
+ SelectMarkdownConfig
241
+ ),
242
+ { nullable: true }
243
+ ),
244
+ screenshot: S__namespace.optionalWith(
245
+ S__namespace.Union(
246
+ S__namespace.Boolean,
247
+ SelectScreenshotConfig
248
+ ),
249
+ { nullable: true }
250
+ ),
251
+ summary: S__namespace.optionalWith(
252
+ S__namespace.Union(
253
+ S__namespace.Boolean,
254
+ /**
255
+ * Options for AI-powered page summarization
256
+ */
257
+ S__namespace.Struct({
258
+ /**
259
+ * Custom prompt for AI summarization (max 5000 characters)
260
+ */
261
+ prompt: S__namespace.optionalWith(S__namespace.String.pipe(S__namespace.maxLength(5e3)), {
262
+ nullable: true,
263
+ default: () => "You are a helpful assistant that summarizes web page content.\nGiven the markdown content of a web page, provide a clear and concise summary.\nFocus on the main points and key information.\nKeep the summary informative but brief."
264
+ })
265
+ })
266
+ ),
267
+ { nullable: true }
268
+ ),
269
+ /**
270
+ * Options for extracting relevant snippets from page content using semantic search
271
+ */
272
+ snippets: S__namespace.optionalWith(
273
+ S__namespace.Struct({
274
+ /**
275
+ * Query to find relevant content snippets from the page (required, non-empty)
276
+ */
277
+ query: Trimmed,
278
+ /**
279
+ * Maximum number of snippets to return (1-50)
280
+ */
281
+ maxSnippets: S__namespace.optionalWith(Int2, { nullable: true, default: () => 5 }),
282
+ /**
283
+ * Minimum relevance score threshold (0-1). Snippets below this score are filtered out.
284
+ */
285
+ minScore: S__namespace.optionalWith(S__namespace.Number.pipe(S__namespace.greaterThanOrEqualTo(0), S__namespace.lessThanOrEqualTo(1)), {
286
+ nullable: true,
287
+ default: () => 0.5
288
+ }),
289
+ /**
290
+ * Target snippet size in characters (100-2000)
291
+ */
292
+ targetSnippetSize: S__namespace.optionalWith(Int2, { nullable: true, default: () => 384 })
293
+ }),
294
+ { nullable: true }
295
+ ),
296
+ /**
297
+ * Include page metadata in the response
298
+ */
299
+ meta: S__namespace.optionalWith(S__namespace.Boolean, { nullable: true, default: () => true }),
300
+ /**
301
+ * Configure response info options (headers inclusion)
302
+ */
303
+ response: S__namespace.optionalWith(
304
+ S__namespace.Struct({
305
+ /**
306
+ * Whether to include HTTP response headers
307
+ */
308
+ includeHeaders: S__namespace.optionalWith(S__namespace.Boolean, { nullable: true, default: () => false })
309
+ }),
310
+ { nullable: true }
311
+ )
312
+ }),
313
+ { nullable: true }
314
+ ),
315
+ /**
316
+ * Configuration options for browser behavior during the fetch
317
+ */
318
+ browserConfig: S__namespace.optionalWith(
319
+ S__namespace.Struct({
320
+ /**
321
+ * Whether to scroll the entire page to capture lazy-loaded content
322
+ */
323
+ scrollFullPage: S__namespace.optionalWith(S__namespace.Boolean, { nullable: true, default: () => false })
324
+ }),
325
+ { nullable: true }
326
+ )
327
+ }) {
328
+ });
329
+ var ResponseInfo = class extends S__namespace.Class("ResponseInfo")({
330
+ /**
331
+ * The URL that was fetched
332
+ */
333
+ url: S__namespace.String,
334
+ /**
335
+ * HTTP status code of the response
336
+ */
337
+ statusCode: S__namespace.Number,
338
+ /**
339
+ * Response headers from the fetch operation (keys are lower-cased HTTP header names)
340
+ */
341
+ headers: S__namespace.optionalWith(S__namespace.Struct({}), { nullable: true })
342
+ }) {
343
+ };
344
+ var IconMeta = class extends S__namespace.Class("IconMeta")({
345
+ /**
346
+ * Icon URL or path
347
+ */
348
+ href: S__namespace.String,
349
+ /**
350
+ * Link relationship type
351
+ */
352
+ rel: S__namespace.String,
353
+ /**
354
+ * MIME type of the icon
355
+ */
356
+ type: S__namespace.optionalWith(S__namespace.String, { nullable: true }),
357
+ /**
358
+ * Icon dimensions
359
+ */
360
+ sizes: S__namespace.optionalWith(S__namespace.String, { nullable: true })
361
+ }) {
362
+ };
363
+ var OgImage = class extends S__namespace.Class("OgImage")({
364
+ /**
365
+ * Image URL
366
+ */
367
+ url: S__namespace.String,
368
+ /**
369
+ * Image width in pixels
370
+ */
371
+ width: S__namespace.optionalWith(S__namespace.Number, { nullable: true }),
372
+ /**
373
+ * Image height in pixels
374
+ */
375
+ height: S__namespace.optionalWith(S__namespace.Number, { nullable: true }),
376
+ /**
377
+ * Image alt text for accessibility
378
+ */
379
+ alt: S__namespace.optionalWith(S__namespace.String, { nullable: true })
380
+ }) {
381
+ };
382
+ var OpenGraphMeta = class extends S__namespace.Class("OpenGraphMeta")({
383
+ /**
384
+ * Open Graph title (og:title)
385
+ */
386
+ title: S__namespace.optionalWith(S__namespace.String, { nullable: true }),
387
+ /**
388
+ * Open Graph description (og:description)
389
+ */
390
+ description: S__namespace.optionalWith(S__namespace.String, { nullable: true }),
391
+ /**
392
+ * Open Graph type (og:type) - website, article, product, etc.
393
+ */
394
+ type: S__namespace.optionalWith(S__namespace.String, { nullable: true }),
395
+ /**
396
+ * Canonical URL for the content (og:url)
397
+ */
398
+ url: S__namespace.optionalWith(S__namespace.String, { nullable: true }),
399
+ /**
400
+ * Site name (og:site_name)
401
+ */
402
+ siteName: S__namespace.optionalWith(S__namespace.String, { nullable: true }),
403
+ /**
404
+ * Locale in language_TERRITORY format (og:locale)
405
+ */
406
+ locale: S__namespace.optionalWith(S__namespace.String, { nullable: true }),
407
+ /**
408
+ * Open Graph images (og:image and related properties)
409
+ */
410
+ images: S__namespace.optionalWith(S__namespace.Array(OgImage), { nullable: true })
411
+ }) {
412
+ };
413
+ var TwitterCardMeta = class extends S__namespace.Class("TwitterCardMeta")({
414
+ /**
415
+ * Twitter card type (twitter:card)
416
+ */
417
+ card: S__namespace.optionalWith(S__namespace.String, { nullable: true }),
418
+ /**
419
+ * Twitter @username of the website (twitter:site)
420
+ */
421
+ site: S__namespace.optionalWith(S__namespace.String, { nullable: true }),
422
+ /**
423
+ * Twitter @username of content creator (twitter:creator)
424
+ */
425
+ creator: S__namespace.optionalWith(S__namespace.String, { nullable: true }),
426
+ /**
427
+ * Title for Twitter card (twitter:title)
428
+ */
429
+ title: S__namespace.optionalWith(S__namespace.String, { nullable: true }),
430
+ /**
431
+ * Description for Twitter card (twitter:description)
432
+ */
433
+ description: S__namespace.optionalWith(S__namespace.String, { nullable: true }),
434
+ /**
435
+ * Image URL for Twitter card (twitter:image)
436
+ */
437
+ image: S__namespace.optionalWith(S__namespace.String, { nullable: true })
438
+ }) {
439
+ };
440
+ var PageMeta = class extends S__namespace.Class("PageMeta")({
441
+ /**
442
+ * Page title from <title> tag
443
+ */
444
+ title: S__namespace.optionalWith(S__namespace.String, { nullable: true }),
445
+ /**
446
+ * Meta description from <meta name="description">
447
+ */
448
+ description: S__namespace.optionalWith(S__namespace.String, { nullable: true }),
449
+ /**
450
+ * Canonical URL from <link rel="canonical">
451
+ */
452
+ canonicalUrl: S__namespace.optionalWith(S__namespace.String, { nullable: true }),
453
+ /**
454
+ * Page language from <html lang="...">
455
+ */
456
+ language: S__namespace.optionalWith(S__namespace.String, { nullable: true }),
457
+ /**
458
+ * Character encoding from <meta charset="...">
459
+ */
460
+ charset: S__namespace.optionalWith(S__namespace.String, { nullable: true }),
461
+ /**
462
+ * Primary favicon URL (first icon found)
463
+ */
464
+ favicon: S__namespace.optionalWith(S__namespace.String, { nullable: true }),
465
+ /**
466
+ * All icon links (favicons, apple-touch-icons, etc.)
467
+ */
468
+ icons: S__namespace.optionalWith(S__namespace.Array(IconMeta), { nullable: true }),
469
+ /**
470
+ * Open Graph metadata from og:* meta tags
471
+ */
472
+ openGraph: S__namespace.optionalWith(OpenGraphMeta, { nullable: true }),
473
+ /**
474
+ * Twitter Card metadata from twitter:* meta tags
475
+ */
476
+ twitter: S__namespace.optionalWith(TwitterCardMeta, { nullable: true })
477
+ }) {
478
+ };
479
+ var FetchData = class extends S__namespace.Class("FetchData")({
480
+ response: ResponseInfo,
481
+ /**
482
+ * Page metadata extracted from HTML head (title, description, Open Graph, Twitter Card, icons)
483
+ */
484
+ meta: S__namespace.optionalWith(PageMeta, { nullable: true }),
485
+ /**
486
+ * The HTML content of the fetched page
487
+ */
488
+ html: S__namespace.optionalWith(S__namespace.String, { nullable: true }),
489
+ /**
490
+ * The markdown-formatted content extracted from the page
491
+ */
492
+ markdown: S__namespace.optionalWith(S__namespace.String, { nullable: true }),
493
+ /**
494
+ * Base64-encoded data URI of the screenshot image
495
+ */
496
+ screenshot: S__namespace.optionalWith(S__namespace.String, { nullable: true }),
497
+ /**
498
+ * AI-generated summary of the page content
499
+ */
500
+ summary: S__namespace.optionalWith(S__namespace.String, { nullable: true }),
501
+ /**
502
+ * Relevant snippets extracted from the page based on the search query
503
+ */
504
+ snippets: S__namespace.optionalWith(
505
+ S__namespace.Array(
506
+ S__namespace.Struct({
507
+ /**
508
+ * Type identifier for TextPart compatibility
509
+ */
510
+ type: S__namespace.optionalWith(S__namespace.Literal("text"), { nullable: true, default: () => "text" }),
511
+ /**
512
+ * The text content of the snippet
513
+ */
514
+ text: S__namespace.String,
515
+ /**
516
+ * Relevance score from the reranker (0-1)
517
+ */
518
+ score: S__namespace.Number,
519
+ /**
520
+ * Original chunk index
521
+ */
522
+ index: S__namespace.Number
523
+ })
524
+ ),
525
+ { nullable: true }
526
+ )
527
+ }) {
528
+ };
529
+ var FetchResult = class extends S__namespace.Class("FetchResult")({
530
+ data: FetchData
531
+ }) {
532
+ };
533
+ var FetchErrorTag = class extends S__namespace.Literal("FetchError") {
534
+ };
535
+ var FetchError = class extends S__namespace.Class("FetchError")({
536
+ _tag: FetchErrorTag
537
+ }) {
538
+ };
539
+ (class extends S__namespace.Class("MarkdownRequest")({
540
+ /**
541
+ * The URL to fetch markdown content from
542
+ */
543
+ url: S__namespace.String,
544
+ /**
545
+ * Configuration options for browser behavior during the fetch
546
+ */
547
+ browserConfig: S__namespace.optionalWith(
548
+ S__namespace.Struct({
549
+ /**
550
+ * Whether to scroll the entire page to capture lazy-loaded content
551
+ */
552
+ scrollFullPage: S__namespace.optionalWith(S__namespace.Boolean, { nullable: true, default: () => false })
553
+ }),
554
+ { nullable: true }
555
+ )
556
+ }) {
557
+ });
558
+ var InvalidAssetHashTag = class extends S__namespace.Literal("InvalidAssetHash") {
559
+ };
560
+ var InvalidAssetHash = class extends S__namespace.Class("InvalidAssetHash")({
561
+ message: S__namespace.String,
562
+ _tag: InvalidAssetHashTag
563
+ }) {
564
+ };
565
+ var AssetNotFoundInHarTag = class extends S__namespace.Literal("AssetNotFoundInHar") {
566
+ };
567
+ var AssetNotFoundInHar = class extends S__namespace.Class("AssetNotFoundInHar")({
568
+ snapshotDir: S__namespace.String,
569
+ assetUrl: S__namespace.String,
570
+ _tag: AssetNotFoundInHarTag
571
+ }) {
572
+ };
573
+ var HarNotFoundTag = class extends S__namespace.Literal("HarNotFound") {
574
+ };
575
+ var HarNotFound = class extends S__namespace.Class("HarNotFound")({
576
+ snapshotDir: S__namespace.String,
577
+ _tag: HarNotFoundTag
578
+ }) {
579
+ };
580
+ var AssetFetchErrorTag = class extends S__namespace.Literal("AssetFetchError") {
581
+ };
582
+ var AssetFetchError = class extends S__namespace.Class("AssetFetchError")({
583
+ snapshotDir: S__namespace.String,
584
+ assetUrl: S__namespace.String,
585
+ _tag: AssetFetchErrorTag
586
+ }) {
587
+ };
588
+ var LocalAssetsGetAsset500 = class extends S__namespace.Union(
589
+ InvalidAssetHash,
590
+ AssetNotFoundInHar,
591
+ HarNotFound,
592
+ AssetFetchError
593
+ ) {
594
+ };
595
+ var make = (httpClient, options = {}) => {
596
+ const unexpectedStatus = (response) => Effect2__namespace.flatMap(
597
+ Effect2__namespace.orElseSucceed(response.json, () => "Unexpected status code"),
598
+ (description) => Effect2__namespace.fail(
599
+ new HttpClientError__namespace.ResponseError({
600
+ request: response.request,
601
+ response,
602
+ reason: "StatusCode",
603
+ description: typeof description === "string" ? description : JSON.stringify(description)
604
+ })
605
+ )
606
+ );
607
+ const withResponse = options.transformClient ? (f) => (request) => Effect2__namespace.flatMap(
608
+ Effect2__namespace.flatMap(options.transformClient(httpClient), (client) => client.execute(request)),
609
+ f
610
+ ) : (f) => (request) => Effect2__namespace.flatMap(httpClient.execute(request), f);
611
+ const decodeSuccess = (schema) => (response) => HttpClientResponse__namespace.schemaBodyJson(schema)(response);
612
+ const decodeError = (tag, schema) => (response) => Effect2__namespace.flatMap(
613
+ HttpClientResponse__namespace.schemaBodyJson(schema)(response),
614
+ (cause) => Effect2__namespace.fail(ClientError(tag, cause, response))
615
+ );
616
+ return {
617
+ httpClient,
618
+ assetsGetByUrl: (browserSessionId, options2) => HttpClientRequest__namespace.get(`/v1/assets/${browserSessionId}/asset`).pipe(
619
+ HttpClientRequest__namespace.setUrlParams({ url: options2?.["url"] }),
620
+ withResponse(
621
+ HttpClientResponse__namespace.matchStatus({
622
+ "400": decodeError("HttpApiDecodeError", HttpApiDecodeError),
623
+ "401": decodeError("UnauthorizedAccess", UnauthorizedAccess),
624
+ "404": decodeError("AssetsGetByUrl404", AssetsGetByUrl404),
625
+ "500": decodeError("AssetsGetByUrl500", AssetsGetByUrl500),
626
+ "502": decodeError("CurlError", CurlError),
627
+ "429": () => Effect2__namespace.void,
628
+ orElse: unexpectedStatus
629
+ })
630
+ )
631
+ ),
632
+ assetsList: (browserSessionId) => HttpClientRequest__namespace.get(`/v1/assets/${browserSessionId}`).pipe(
633
+ withResponse(
634
+ HttpClientResponse__namespace.matchStatus({
635
+ "2xx": decodeSuccess(AssetListResponse),
636
+ "400": decodeError("HttpApiDecodeError", HttpApiDecodeError),
637
+ "401": decodeError("UnauthorizedAccess", UnauthorizedAccess),
638
+ "404": decodeError("AssetNotFound", AssetNotFound),
639
+ "500": decodeError("AssetsList500", AssetsList500),
640
+ "429": () => Effect2__namespace.void,
641
+ orElse: unexpectedStatus
642
+ })
643
+ )
644
+ ),
645
+ fetch: (options2) => HttpClientRequest__namespace.post(`/v1/fetch`).pipe(
646
+ HttpClientRequest__namespace.bodyUnsafeJson(options2),
647
+ withResponse(
648
+ HttpClientResponse__namespace.matchStatus({
649
+ "2xx": decodeSuccess(FetchResult),
650
+ "400": decodeError("HttpApiDecodeError", HttpApiDecodeError),
651
+ "401": decodeError("UnauthorizedAccess", UnauthorizedAccess),
652
+ "500": decodeError("FetchError", FetchError),
653
+ "429": () => Effect2__namespace.void,
654
+ orElse: unexpectedStatus
655
+ })
656
+ )
657
+ ),
658
+ markdown: (options2) => HttpClientRequest__namespace.post(`/v1/fetch/markdown`).pipe(
659
+ HttpClientRequest__namespace.bodyUnsafeJson(options2),
660
+ withResponse(
661
+ HttpClientResponse__namespace.matchStatus({
662
+ "400": decodeError("HttpApiDecodeError", HttpApiDecodeError),
663
+ "401": decodeError("UnauthorizedAccess", UnauthorizedAccess),
664
+ "500": decodeError("FetchError", FetchError),
665
+ "429": () => Effect2__namespace.void,
666
+ orElse: unexpectedStatus
667
+ })
668
+ )
669
+ ),
670
+ localAssetsGetAsset: (assetHash) => HttpClientRequest__namespace.get(`/local-asset/${assetHash}`).pipe(
671
+ withResponse(
672
+ HttpClientResponse__namespace.matchStatus({
673
+ "400": decodeError("HttpApiDecodeError", HttpApiDecodeError),
674
+ "500": decodeError("LocalAssetsGetAsset500", LocalAssetsGetAsset500),
675
+ "204": () => Effect2__namespace.void,
676
+ "429": () => Effect2__namespace.void,
677
+ orElse: unexpectedStatus
678
+ })
679
+ )
680
+ )
681
+ };
682
+ };
683
+ var ClientErrorImpl = class extends Data__namespace.Error {
684
+ };
685
+ var ClientError = (tag, cause, response) => new ClientErrorImpl({
686
+ _tag: tag,
687
+ cause,
688
+ response,
689
+ request: response.request
690
+ });
691
+
692
+ // src/ExpandClient.ts
693
+ var ExpandConfig = effect.Config.all({
694
+ apiKey: effect.Config.option(effect.Config.redacted("EXPAND_API_KEY")),
695
+ baseUrl: effect.Config.withDefault(effect.Config.string("EXPAND_BASE_URL"), "https://api.expand.ai")
696
+ });
697
+ var ExpandClient = class extends effect.Effect.Service()("ExpandClient", {
698
+ dependencies: [],
699
+ scoped: effect.Effect.gen(function* () {
700
+ const config = yield* ExpandConfig;
701
+ const httpClient = yield* platform.HttpClient.HttpClient;
702
+ const requestHeaders = yield* effect.Effect.serviceOption(CurrentRequestHeaders);
703
+ yield* effect.Effect.logInfo(`ExpandClient connected to ${config.baseUrl}`);
704
+ return make(httpClient, {
705
+ transformClient: (client) => effect.Effect.succeed(
706
+ client.pipe(
707
+ platform.HttpClient.mapRequest(platform.HttpClientRequest.prependUrl(config.baseUrl)),
708
+ platform.HttpClient.mapRequest((req) => {
709
+ if (effect.Option.isSome(requestHeaders)) {
710
+ const auth = requestHeaders.value["authorization"];
711
+ if (auth) {
712
+ return platform.HttpClientRequest.setHeader("authorization", auth)(req);
713
+ }
714
+ }
715
+ if (effect.Option.isSome(config.apiKey)) {
716
+ return platform.HttpClientRequest.setHeader("x-expand-api-key", effect.Redacted.value(config.apiKey.value))(req);
717
+ }
718
+ return req;
719
+ })
720
+ )
721
+ )
722
+ });
723
+ })
724
+ }) {
725
+ };
726
+ var SnippetsFormat = class extends effect.Schema.Class("SnippetsFormat")({
727
+ query: effect.Schema.String.annotations({
728
+ description: "Query to find relevant content snippets from the page"
729
+ }),
730
+ maxSnippets: effect.Schema.optional(
731
+ effect.Schema.Int.pipe(effect.Schema.greaterThanOrEqualTo(1), effect.Schema.lessThanOrEqualTo(50))
732
+ ).annotations({
733
+ description: "Maximum number of snippets to return (1-50, default: 5)"
734
+ }),
735
+ targetSnippetSize: effect.Schema.optional(
736
+ effect.Schema.Int.pipe(effect.Schema.greaterThanOrEqualTo(100), effect.Schema.lessThanOrEqualTo(2e3))
737
+ ).annotations({
738
+ description: "Target snippet size in characters (100-2000, default: 384)"
739
+ })
740
+ }) {
741
+ };
742
+ var Format = effect.Schema.Union(
743
+ effect.Schema.Literal("markdown").annotations({
744
+ description: "Return as cleaned markdown content"
745
+ }),
746
+ effect.Schema.Literal("html").annotations({
747
+ description: "Return as raw HTML content"
748
+ }),
749
+ effect.Schema.Literal("summary").annotations({
750
+ description: "Return AI-generated summary of the page content"
751
+ }),
752
+ SnippetsFormat
753
+ ).annotations({
754
+ description: "Output format for the fetched content"
755
+ });
756
+ var FetchParams = class extends effect.Schema.Class("FetchParams")({
757
+ url: effect.Schema.String.annotations({
758
+ description: "The URL to fetch content from"
759
+ }),
760
+ format: Format,
761
+ includeMeta: effect.Schema.Boolean.annotations({
762
+ description: "Whether to include page meta tags in the response"
763
+ })
764
+ }) {
765
+ };
766
+ var FetchResult2 = class extends effect.Schema.Class("FetchResult")({
767
+ content: effect.Schema.String,
768
+ url: effect.Schema.String,
769
+ meta: effect.Schema.optional(PageMeta)
770
+ }) {
771
+ };
772
+ var FetchTool = ai.Tool.make("fetch", {
773
+ description: "Fetch and extract content from any URL.",
774
+ parameters: FetchParams.fields,
775
+ success: FetchResult2
776
+ }).annotate(ai.Tool.Readonly, true).annotate(ai.Tool.Destructive, false);
777
+ var Fetch = class extends effect.Effect.Service()("Fetch", {
778
+ dependencies: [ExpandClient.Default],
779
+ scoped: effect.Effect.gen(function* () {
780
+ const client = yield* ExpandClient;
781
+ const fetch = effect.Effect.fn("Fetch.fetch")(function* ({ url, format, includeMeta }) {
782
+ const formatLabel = format instanceof SnippetsFormat ? "snippets" : format;
783
+ yield* effect.Effect.logDebug(`Fetching: ${url}`).pipe(effect.Effect.annotateLogs({ format: formatLabel, includeMeta }));
784
+ const result = yield* client.fetch({
785
+ url,
786
+ select: {
787
+ markdown: format === "markdown",
788
+ html: format === "html",
789
+ summary: format === "summary",
790
+ snippets: format instanceof SnippetsFormat ? { ...format } : void 0,
791
+ meta: includeMeta
792
+ }
793
+ });
794
+ const content = result.data.markdown ?? result.data.html ?? result.data.summary ?? result.data.snippets?.map((snippet) => `${snippet.text} (Score: ${snippet.score})`).join("\n") ?? "";
795
+ yield* effect.Effect.logDebug(`\u{1F4E4} Fetched successfully: ${result.data.response.url}`);
796
+ return new FetchResult2({
797
+ content,
798
+ url: result.data.response.url,
799
+ meta: result.data.meta
800
+ });
801
+ }, effect.Effect.orDie);
802
+ return { fetch };
803
+ })
804
+ }) {
805
+ };
806
+
807
+ // src/Toolkit.ts
808
+ var toolkit = ai.Toolkit.make(FetchTool);
809
+ var ToolkitLayer = toolkit.toLayer(
810
+ effect.Effect.gen(function* () {
811
+ yield* effect.Effect.logInfo("Registering tools: fetch");
812
+ const fetchService = yield* Fetch;
813
+ return toolkit.of({
814
+ fetch: fetchService.fetch
815
+ });
816
+ })
817
+ ).pipe(effect.Layer.provide(Fetch.Default), effect.Layer.provide(ExpandClient.Default), effect.Layer.provide(platformNode.NodeHttpClient.layerUndici));
818
+ var ExpandToolKit = ai.McpServer.toolkit(toolkit).pipe(effect.Layer.provide(ToolkitLayer));
819
+
820
+ // src/Server.ts
821
+ var ServerInfo = {
822
+ name: "expandai-mcp-server",
823
+ version: package_default.version
824
+ };
825
+ var CurrentRequestHeaders = class extends effect.Context.Tag("CurrentRequestHeaders")() {
826
+ };
827
+ var makeServerLayer = (options = {}) => options.includeDocs ? effect.Layer.mergeAll(ExpandToolKit, ExpandDocs) : ExpandToolKit;
828
+
829
+ exports.CurrentRequestHeaders = CurrentRequestHeaders;
830
+ exports.ServerInfo = ServerInfo;
831
+ exports.makeServerLayer = makeServerLayer;