@warlok-net/mcp-server 0.1.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.
package/dist/index.js ADDED
@@ -0,0 +1,706 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ createServer: () => createServer,
34
+ runServer: () => runServer
35
+ });
36
+ module.exports = __toCommonJS(index_exports);
37
+ var import_server = require("@modelcontextprotocol/sdk/server/index.js");
38
+ var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
39
+ var import_types = require("@modelcontextprotocol/sdk/types.js");
40
+ var import_sdk = require("@warlok-net/sdk");
41
+
42
+ // src/screenshot.ts
43
+ var import_promises = __toESM(require("fs/promises"));
44
+ var import_node_path = __toESM(require("path"));
45
+ async function loadChromium() {
46
+ try {
47
+ const playwright = await import("playwright");
48
+ return playwright.chromium;
49
+ } catch {
50
+ throw new Error(
51
+ "capture_ui_screenshot requires Playwright. Install it with: npm i playwright && npx playwright install chromium"
52
+ );
53
+ }
54
+ }
55
+ var DEFAULT_VIEWPORT_WIDTH = 1440;
56
+ var DEFAULT_VIEWPORT_HEIGHT = 900;
57
+ var DEFAULT_TIMEOUT_MS = 3e4;
58
+ var DEFAULT_WAIT_MS = 250;
59
+ var DEFAULT_FORMAT = "png";
60
+ async function captureUiScreenshot(input) {
61
+ const startedAt = Date.now();
62
+ const url = parseHttpUrl(input.url);
63
+ const width = clampInteger(input.viewportWidth, 320, 7680, DEFAULT_VIEWPORT_WIDTH);
64
+ const height = clampInteger(
65
+ input.viewportHeight,
66
+ 240,
67
+ 4320,
68
+ DEFAULT_VIEWPORT_HEIGHT
69
+ );
70
+ const timeoutMs = clampInteger(input.timeoutMs, 5e3, 12e4, DEFAULT_TIMEOUT_MS);
71
+ const waitForMs = clampInteger(input.waitForMs, 0, 3e4, DEFAULT_WAIT_MS);
72
+ const fullPage = input.fullPage ?? true;
73
+ const colorScheme = input.colorScheme ?? "dark";
74
+ const format = input.format ?? inferFormatFromOutputPath(input.outputPath);
75
+ const outputPath = resolveOutputPath(url, input.outputPath, format);
76
+ await import_promises.default.mkdir(import_node_path.default.dirname(outputPath), { recursive: true });
77
+ const chromium = await loadChromium();
78
+ const browser = await chromium.launch({ headless: true });
79
+ try {
80
+ const context = await browser.newContext({
81
+ viewport: { width, height },
82
+ colorScheme,
83
+ deviceScaleFactor: 1
84
+ });
85
+ const page = await context.newPage();
86
+ page.setDefaultTimeout(timeoutMs);
87
+ await page.goto(url.toString(), { waitUntil: "networkidle", timeout: timeoutMs });
88
+ if (input.waitForSelector) {
89
+ await page.waitForSelector(input.waitForSelector, {
90
+ state: "visible",
91
+ timeout: timeoutMs
92
+ });
93
+ }
94
+ if (waitForMs > 0) {
95
+ await page.waitForTimeout(waitForMs);
96
+ }
97
+ if (input.selector) {
98
+ const locator = page.locator(input.selector).first();
99
+ await locator.waitFor({ state: "visible", timeout: timeoutMs });
100
+ await locator.screenshot({
101
+ path: outputPath,
102
+ type: format
103
+ });
104
+ } else {
105
+ await page.screenshot({
106
+ path: outputPath,
107
+ fullPage,
108
+ type: format
109
+ });
110
+ }
111
+ await context.close();
112
+ } finally {
113
+ await browser.close();
114
+ }
115
+ const stat = await import_promises.default.stat(outputPath);
116
+ return {
117
+ outputPath,
118
+ bytes: stat.size,
119
+ width,
120
+ height,
121
+ url: url.toString(),
122
+ selector: input.selector ?? null,
123
+ fullPage,
124
+ colorScheme,
125
+ format,
126
+ durationMs: Date.now() - startedAt
127
+ };
128
+ }
129
+ function parseHttpUrl(value) {
130
+ let parsed;
131
+ try {
132
+ parsed = new URL(value);
133
+ } catch {
134
+ throw new Error("Invalid URL. Expected a valid absolute URL.");
135
+ }
136
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
137
+ throw new Error("Invalid URL protocol. Only http/https URLs are supported.");
138
+ }
139
+ return parsed;
140
+ }
141
+ function resolveOutputPath(url, requestedPath, format) {
142
+ if (requestedPath) {
143
+ const absolute = import_node_path.default.isAbsolute(requestedPath) ? requestedPath : import_node_path.default.resolve(outputRoot(), requestedPath);
144
+ return ensureExt(absolute, format);
145
+ }
146
+ const now = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
147
+ const host = sanitizeSegment(url.host);
148
+ const pathname = sanitizeSegment(url.pathname.replace(/\//g, "_") || "root");
149
+ const filename = `${now}-${host}-${pathname}.${format}`;
150
+ return import_node_path.default.join(outputRoot(), filename);
151
+ }
152
+ function outputRoot() {
153
+ const configured = process.env.WARLOK_SCREENSHOT_DIR;
154
+ if (configured && configured.trim()) {
155
+ return import_node_path.default.resolve(configured.trim());
156
+ }
157
+ return import_node_path.default.resolve(process.cwd(), "tmp", "mcp-screenshots");
158
+ }
159
+ function ensureExt(value, format) {
160
+ const ext = import_node_path.default.extname(value).toLowerCase();
161
+ if (ext === ".png" || ext === ".jpg" || ext === ".jpeg" || ext === ".webp") {
162
+ return value;
163
+ }
164
+ return `${value}.${format}`;
165
+ }
166
+ function sanitizeSegment(value) {
167
+ return value.toLowerCase().replace(/[^a-z0-9._-]/g, "-").replace(/-+/g, "-").replace(/^-+|-+$/g, "").slice(0, 120) || "capture";
168
+ }
169
+ function inferFormatFromOutputPath(pathname) {
170
+ if (!pathname) return DEFAULT_FORMAT;
171
+ const ext = import_node_path.default.extname(pathname).toLowerCase();
172
+ if (ext === ".jpg" || ext === ".jpeg") return "jpeg";
173
+ return "png";
174
+ }
175
+ function clampInteger(value, min, max, fallback) {
176
+ if (typeof value !== "number" || !Number.isFinite(value)) return fallback;
177
+ const rounded = Math.round(value);
178
+ if (rounded < min) return min;
179
+ if (rounded > max) return max;
180
+ return rounded;
181
+ }
182
+
183
+ // src/index.ts
184
+ var TOOLS = [
185
+ {
186
+ name: "generate_3d_model",
187
+ description: "Generate a 3D model from text description or image. Returns an asset_id to track status.",
188
+ inputSchema: {
189
+ type: "object",
190
+ properties: {
191
+ name: {
192
+ type: "string",
193
+ description: "Name for the generation (max 100 characters)"
194
+ },
195
+ type: {
196
+ type: "string",
197
+ enum: [
198
+ "character",
199
+ "creature",
200
+ "environment",
201
+ "prop",
202
+ "weapon",
203
+ "vehicle",
204
+ "material",
205
+ "noun",
206
+ "person",
207
+ "place",
208
+ "thing"
209
+ ],
210
+ description: "Entity or legacy asset type"
211
+ },
212
+ prompt: {
213
+ type: "string",
214
+ description: "Text prompt describing what to generate"
215
+ },
216
+ image_url: {
217
+ type: "string",
218
+ description: "Optional URL to a reference image"
219
+ },
220
+ auto_rig: {
221
+ type: "boolean",
222
+ description: "Whether to rig for Mixamo when generating a person",
223
+ default: true
224
+ }
225
+ },
226
+ required: ["type"]
227
+ }
228
+ },
229
+ {
230
+ name: "get_model_status",
231
+ description: "Check generation status by asset_id.",
232
+ inputSchema: {
233
+ type: "object",
234
+ properties: {
235
+ asset_id: {
236
+ type: "string",
237
+ description: "The generation ID"
238
+ }
239
+ },
240
+ required: ["asset_id"]
241
+ }
242
+ },
243
+ {
244
+ name: "list_models",
245
+ description: "List generations for the current account.",
246
+ inputSchema: {
247
+ type: "object",
248
+ properties: {
249
+ limit: {
250
+ type: "number",
251
+ description: "Maximum rows to return (default: 20)",
252
+ default: 20
253
+ },
254
+ type: {
255
+ type: "string",
256
+ enum: [
257
+ "character",
258
+ "creature",
259
+ "environment",
260
+ "prop",
261
+ "weapon",
262
+ "vehicle",
263
+ "material",
264
+ "noun",
265
+ "person",
266
+ "place",
267
+ "thing"
268
+ ],
269
+ description: "Filter by entity/legacy type"
270
+ },
271
+ status: {
272
+ type: "string",
273
+ enum: [
274
+ "pending",
275
+ "preprocessing",
276
+ "generating",
277
+ "rigging",
278
+ "complete",
279
+ "failed"
280
+ ],
281
+ description: "Filter by generation status"
282
+ }
283
+ }
284
+ }
285
+ },
286
+ {
287
+ name: "get_model_download_url",
288
+ description: "Get the best available download URL for a completed generation.",
289
+ inputSchema: {
290
+ type: "object",
291
+ properties: {
292
+ asset_id: {
293
+ type: "string",
294
+ description: "The generation ID"
295
+ },
296
+ format: {
297
+ type: "string",
298
+ enum: ["model", "rigged"],
299
+ description: "Preferred format (default: best available)"
300
+ }
301
+ },
302
+ required: ["asset_id"]
303
+ }
304
+ },
305
+ {
306
+ name: "delete_model",
307
+ description: "Delete a generation.",
308
+ inputSchema: {
309
+ type: "object",
310
+ properties: {
311
+ asset_id: {
312
+ type: "string",
313
+ description: "The generation ID to delete"
314
+ }
315
+ },
316
+ required: ["asset_id"]
317
+ }
318
+ },
319
+ {
320
+ name: "capture_ui_screenshot",
321
+ description: "Capture a deterministic Playwright screenshot for UI/design iteration.",
322
+ inputSchema: {
323
+ type: "object",
324
+ properties: {
325
+ url: {
326
+ type: "string",
327
+ description: "HTTP/HTTPS URL to capture"
328
+ },
329
+ output_path: {
330
+ type: "string",
331
+ description: "Optional output file path. Relative paths are resolved in tmp/mcp-screenshots."
332
+ },
333
+ selector: {
334
+ type: "string",
335
+ description: "Optional CSS selector to capture only a specific element."
336
+ },
337
+ wait_for_selector: {
338
+ type: "string",
339
+ description: "Optional selector to wait for before capture (useful for async UI)."
340
+ },
341
+ wait_for_ms: {
342
+ type: "number",
343
+ description: "Extra delay before capture in milliseconds (default: 250).",
344
+ default: 250
345
+ },
346
+ timeout_ms: {
347
+ type: "number",
348
+ description: "Navigation and selector timeout in milliseconds (default: 30000).",
349
+ default: 3e4
350
+ },
351
+ full_page: {
352
+ type: "boolean",
353
+ description: "Capture full page when selector is not set (default: true).",
354
+ default: true
355
+ },
356
+ viewport_width: {
357
+ type: "number",
358
+ description: "Viewport width in px (default: 1440).",
359
+ default: 1440
360
+ },
361
+ viewport_height: {
362
+ type: "number",
363
+ description: "Viewport height in px (default: 900).",
364
+ default: 900
365
+ },
366
+ color_scheme: {
367
+ type: "string",
368
+ enum: ["light", "dark", "no-preference"],
369
+ description: "Preferred color scheme (default: dark).",
370
+ default: "dark"
371
+ },
372
+ format: {
373
+ type: "string",
374
+ enum: ["png", "jpeg"],
375
+ description: "Screenshot format (default inferred from output_path, else png)."
376
+ }
377
+ },
378
+ required: ["url"]
379
+ }
380
+ }
381
+ ];
382
+ function createServer(apiKey, baseUrl) {
383
+ const client = new import_sdk.WarlokClient({ apiKey, baseUrl });
384
+ const server = new import_server.Server(
385
+ {
386
+ name: "warlok-mcp",
387
+ version: "0.1.0"
388
+ },
389
+ {
390
+ capabilities: {
391
+ tools: {}
392
+ }
393
+ }
394
+ );
395
+ server.setRequestHandler(import_types.ListToolsRequestSchema, async () => ({
396
+ tools: TOOLS
397
+ }));
398
+ server.setRequestHandler(import_types.CallToolRequestSchema, async (request) => {
399
+ const { name, arguments: args } = request.params;
400
+ try {
401
+ switch (name) {
402
+ case "generate_3d_model": {
403
+ const generation = await client.generate({
404
+ name: stringOrUndefined(args, "name"),
405
+ type: requiredType(args),
406
+ prompt: stringOrUndefined(args, "prompt"),
407
+ imageUrl: stringOrUndefined(args, "image_url"),
408
+ options: {
409
+ autoRig: booleanOrUndefined(args, "auto_rig")
410
+ }
411
+ });
412
+ return {
413
+ content: [
414
+ {
415
+ type: "text",
416
+ text: JSON.stringify(
417
+ {
418
+ success: true,
419
+ asset_id: generation.id,
420
+ name: generation.name,
421
+ entity_type: generation.entityType,
422
+ status: generation.status,
423
+ message: `Generation started. Use get_model_status with asset_id "${generation.id}".`
424
+ },
425
+ null,
426
+ 2
427
+ )
428
+ }
429
+ ]
430
+ };
431
+ }
432
+ case "get_model_status": {
433
+ const generation = await client.getGeneration(requiredAssetId(args));
434
+ return {
435
+ content: [
436
+ {
437
+ type: "text",
438
+ text: JSON.stringify(formatGenerationStatus(generation), null, 2)
439
+ }
440
+ ]
441
+ };
442
+ }
443
+ case "list_models": {
444
+ const generations = await client.listGenerations({
445
+ limit: numberOrUndefined(args, "limit") || 20,
446
+ type: typeOrUndefined(args),
447
+ status: statusOrUndefined(args)
448
+ });
449
+ return {
450
+ content: [
451
+ {
452
+ type: "text",
453
+ text: JSON.stringify(
454
+ {
455
+ total: generations.length,
456
+ models: generations.map((generation) => ({
457
+ id: generation.id,
458
+ name: generation.name,
459
+ entity_type: generation.entityType,
460
+ status: generation.status,
461
+ created_at: generation.createdAt
462
+ }))
463
+ },
464
+ null,
465
+ 2
466
+ )
467
+ }
468
+ ]
469
+ };
470
+ }
471
+ case "get_model_download_url": {
472
+ const generation = await client.getGeneration(requiredAssetId(args));
473
+ if (generation.status !== "complete") {
474
+ return {
475
+ content: [
476
+ {
477
+ type: "text",
478
+ text: JSON.stringify({
479
+ success: false,
480
+ error: `Generation is not complete. Current status: ${generation.status}`
481
+ })
482
+ }
483
+ ]
484
+ };
485
+ }
486
+ const format = downloadFormatOrUndefined(args);
487
+ const url = format === "model" ? generation.outputs.modelUrl : format === "rigged" ? generation.outputs.riggedModelUrl : generation.outputs.riggedModelUrl || generation.outputs.modelUrl;
488
+ if (!url) {
489
+ return {
490
+ content: [
491
+ {
492
+ type: "text",
493
+ text: JSON.stringify({
494
+ success: false,
495
+ error: "No download URL available for this generation"
496
+ })
497
+ }
498
+ ]
499
+ };
500
+ }
501
+ return {
502
+ content: [
503
+ {
504
+ type: "text",
505
+ text: JSON.stringify(
506
+ {
507
+ success: true,
508
+ asset_id: generation.id,
509
+ name: generation.name,
510
+ download_url: url,
511
+ format: format || "best_available",
512
+ prompt: generation.input.prompt || null,
513
+ preview_png_url: generation.outputs.previewPngUrl || null,
514
+ nanobanana_png_url: generation.outputs.promptImageUrl || generation.provenance?.preprocessPromptImageUrl || null
515
+ },
516
+ null,
517
+ 2
518
+ )
519
+ }
520
+ ]
521
+ };
522
+ }
523
+ case "delete_model": {
524
+ const assetId = requiredAssetId(args);
525
+ await client.deleteGeneration(assetId);
526
+ return {
527
+ content: [
528
+ {
529
+ type: "text",
530
+ text: JSON.stringify({
531
+ success: true,
532
+ message: `Generation ${assetId} deleted successfully`
533
+ })
534
+ }
535
+ ]
536
+ };
537
+ }
538
+ case "capture_ui_screenshot": {
539
+ const screenshot = await captureUiScreenshot({
540
+ url: requiredUrl(args),
541
+ outputPath: stringOrUndefined(args, "output_path"),
542
+ selector: stringOrUndefined(args, "selector"),
543
+ waitForSelector: stringOrUndefined(args, "wait_for_selector"),
544
+ waitForMs: numberOrUndefined(args, "wait_for_ms"),
545
+ timeoutMs: numberOrUndefined(args, "timeout_ms"),
546
+ fullPage: booleanOrUndefined(args, "full_page"),
547
+ viewportWidth: numberOrUndefined(args, "viewport_width"),
548
+ viewportHeight: numberOrUndefined(args, "viewport_height"),
549
+ colorScheme: colorSchemeOrUndefined(args),
550
+ format: screenshotFormatOrUndefined(args)
551
+ });
552
+ return {
553
+ content: [
554
+ {
555
+ type: "text",
556
+ text: JSON.stringify(
557
+ {
558
+ success: true,
559
+ ...screenshot
560
+ },
561
+ null,
562
+ 2
563
+ )
564
+ }
565
+ ]
566
+ };
567
+ }
568
+ default:
569
+ throw new import_types.McpError(import_types.ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
570
+ }
571
+ } catch (error) {
572
+ if (error instanceof import_types.McpError) {
573
+ throw error;
574
+ }
575
+ const message = error instanceof Error ? error.message : "Unknown error";
576
+ return {
577
+ content: [
578
+ {
579
+ type: "text",
580
+ text: JSON.stringify({ success: false, error: message })
581
+ }
582
+ ],
583
+ isError: true
584
+ };
585
+ }
586
+ });
587
+ return server;
588
+ }
589
+ function requiredAssetId(args) {
590
+ const value = stringOrUndefined(args, "asset_id");
591
+ if (!value) {
592
+ throw new import_types.McpError(import_types.ErrorCode.InvalidParams, "asset_id is required");
593
+ }
594
+ return value;
595
+ }
596
+ function requiredType(args) {
597
+ const value = stringOrUndefined(args, "type");
598
+ if (!value) {
599
+ throw new import_types.McpError(import_types.ErrorCode.InvalidParams, "type is required");
600
+ }
601
+ return value;
602
+ }
603
+ function requiredUrl(args) {
604
+ const value = stringOrUndefined(args, "url");
605
+ if (!value) {
606
+ throw new import_types.McpError(import_types.ErrorCode.InvalidParams, "url is required");
607
+ }
608
+ return value;
609
+ }
610
+ function typeOrUndefined(args) {
611
+ const value = stringOrUndefined(args, "type");
612
+ return value;
613
+ }
614
+ function statusOrUndefined(args) {
615
+ const value = stringOrUndefined(args, "status");
616
+ return value;
617
+ }
618
+ function downloadFormatOrUndefined(args) {
619
+ const value = stringOrUndefined(args, "format");
620
+ if (value === "model" || value === "rigged") {
621
+ return value;
622
+ }
623
+ return void 0;
624
+ }
625
+ function stringOrUndefined(args, key) {
626
+ const value = args?.[key];
627
+ return typeof value === "string" && value.trim() ? value.trim() : void 0;
628
+ }
629
+ function booleanOrUndefined(args, key) {
630
+ const value = args?.[key];
631
+ return typeof value === "boolean" ? value : void 0;
632
+ }
633
+ function numberOrUndefined(args, key) {
634
+ const value = args?.[key];
635
+ return typeof value === "number" ? value : void 0;
636
+ }
637
+ function colorSchemeOrUndefined(args) {
638
+ const value = stringOrUndefined(args, "color_scheme");
639
+ if (value === "light" || value === "dark" || value === "no-preference") {
640
+ return value;
641
+ }
642
+ return void 0;
643
+ }
644
+ function screenshotFormatOrUndefined(args) {
645
+ const value = stringOrUndefined(args, "format");
646
+ if (value === "png" || value === "jpeg") {
647
+ return value;
648
+ }
649
+ return void 0;
650
+ }
651
+ function formatGenerationStatus(generation) {
652
+ const base = {
653
+ success: true,
654
+ asset_id: generation.id,
655
+ name: generation.name,
656
+ entity_type: generation.entityType,
657
+ status: generation.status,
658
+ progress: generation.progress,
659
+ prompt: generation.input.prompt || null,
660
+ preview_png_url: generation.outputs.previewPngUrl || null,
661
+ nanobanana_png_url: generation.outputs.promptImageUrl || generation.provenance?.preprocessPromptImageUrl || null,
662
+ created_at: generation.createdAt,
663
+ updated_at: generation.updatedAt
664
+ };
665
+ if (generation.status === "complete") {
666
+ return {
667
+ ...base,
668
+ model_url: generation.outputs.modelUrl,
669
+ rigged_model_url: generation.outputs.riggedModelUrl,
670
+ mixamo_ready: generation.outputs.mixamoReady
671
+ };
672
+ }
673
+ if (generation.status === "failed") {
674
+ return {
675
+ ...base,
676
+ error: generation.error
677
+ };
678
+ }
679
+ return {
680
+ ...base,
681
+ message: getStatusMessage(generation.status, generation.progress)
682
+ };
683
+ }
684
+ function getStatusMessage(status, progress) {
685
+ const messages = {
686
+ pending: "Queued for processing",
687
+ preprocessing: "Preparing specialized PNG",
688
+ generating: "Generating 3D mesh",
689
+ rigging: "Rigging for Mixamo"
690
+ };
691
+ return `${messages[status] || "Processing"} (${progress}% complete)`;
692
+ }
693
+ async function runServer(apiKey, baseUrl) {
694
+ const server = createServer(apiKey, baseUrl);
695
+ const transport = new import_stdio.StdioServerTransport();
696
+ await server.connect(transport);
697
+ process.on("SIGINT", async () => {
698
+ await server.close();
699
+ process.exit(0);
700
+ });
701
+ }
702
+ // Annotate the CommonJS export names for ESM import in node:
703
+ 0 && (module.exports = {
704
+ createServer,
705
+ runServer
706
+ });
package/dist/index.mjs ADDED
@@ -0,0 +1,8 @@
1
+ import {
2
+ createServer,
3
+ runServer
4
+ } from "./chunk-HTA6LITF.mjs";
5
+ export {
6
+ createServer,
7
+ runServer
8
+ };