@mdtidy/mcp 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.
@@ -0,0 +1,1216 @@
1
+ // ../../packages/client/src/errors.ts
2
+ function isApiErrorBody(value) {
3
+ if (typeof value !== "object" || value === null) return false;
4
+ const err = value.error;
5
+ return typeof err === "object" && err !== null && typeof err.code === "string";
6
+ }
7
+ var MdtidyApiError = class extends Error {
8
+ status;
9
+ code;
10
+ requestId;
11
+ details;
12
+ constructor(args) {
13
+ super(`mdtidy ${args.status} ${args.code}: ${args.message}`);
14
+ this.name = "MdtidyApiError";
15
+ this.status = args.status;
16
+ this.code = args.code;
17
+ this.requestId = args.requestId;
18
+ this.details = args.details;
19
+ }
20
+ };
21
+
22
+ // ../../node_modules/.pnpm/openapi-fetch@0.13.8/node_modules/openapi-fetch/dist/index.js
23
+ var PATH_PARAM_RE = /\{[^{}]+\}/g;
24
+ var supportsRequestInitExt = () => {
25
+ return typeof process === "object" && Number.parseInt(process?.versions?.node?.substring(0, 2)) >= 18 && process.versions.undici;
26
+ };
27
+ function randomID() {
28
+ return Math.random().toString(36).slice(2, 11);
29
+ }
30
+ function createClient(clientOptions) {
31
+ let {
32
+ baseUrl = "",
33
+ Request: CustomRequest = globalThis.Request,
34
+ fetch: baseFetch = globalThis.fetch,
35
+ querySerializer: globalQuerySerializer,
36
+ bodySerializer: globalBodySerializer,
37
+ headers: baseHeaders,
38
+ requestInitExt = void 0,
39
+ ...baseOptions
40
+ } = { ...clientOptions };
41
+ requestInitExt = supportsRequestInitExt() ? requestInitExt : void 0;
42
+ baseUrl = removeTrailingSlash(baseUrl);
43
+ const middlewares = [];
44
+ async function coreFetch(schemaPath, fetchOptions) {
45
+ const {
46
+ baseUrl: localBaseUrl,
47
+ fetch = baseFetch,
48
+ Request = CustomRequest,
49
+ headers,
50
+ params = {},
51
+ parseAs = "json",
52
+ querySerializer: requestQuerySerializer,
53
+ bodySerializer = globalBodySerializer ?? defaultBodySerializer,
54
+ body,
55
+ ...init
56
+ } = fetchOptions || {};
57
+ let finalBaseUrl = baseUrl;
58
+ if (localBaseUrl) {
59
+ finalBaseUrl = removeTrailingSlash(localBaseUrl) ?? baseUrl;
60
+ }
61
+ let querySerializer = typeof globalQuerySerializer === "function" ? globalQuerySerializer : createQuerySerializer(globalQuerySerializer);
62
+ if (requestQuerySerializer) {
63
+ querySerializer = typeof requestQuerySerializer === "function" ? requestQuerySerializer : createQuerySerializer({
64
+ ...typeof globalQuerySerializer === "object" ? globalQuerySerializer : {},
65
+ ...requestQuerySerializer
66
+ });
67
+ }
68
+ const serializedBody = body === void 0 ? void 0 : bodySerializer(
69
+ body,
70
+ // Note: we declare mergeHeaders() both here and below because it’s a bit of a chicken-or-egg situation:
71
+ // bodySerializer() needs all headers so we aren’t dropping ones set by the user, however,
72
+ // the result of this ALSO sets the lowest-priority content-type header. So we re-merge below,
73
+ // setting the content-type at the very beginning to be overwritten.
74
+ // Lastly, based on the way headers work, it’s not a simple “present-or-not” check becauase null intentionally un-sets headers.
75
+ mergeHeaders(baseHeaders, headers, params.header)
76
+ );
77
+ const finalHeaders = mergeHeaders(
78
+ // with no body, we should not to set Content-Type
79
+ serializedBody === void 0 || // if serialized body is FormData; browser will correctly set Content-Type & boundary expression
80
+ serializedBody instanceof FormData ? {} : {
81
+ "Content-Type": "application/json"
82
+ },
83
+ baseHeaders,
84
+ headers,
85
+ params.header
86
+ );
87
+ const requestInit = {
88
+ redirect: "follow",
89
+ ...baseOptions,
90
+ ...init,
91
+ body: serializedBody,
92
+ headers: finalHeaders
93
+ };
94
+ let id;
95
+ let options;
96
+ let request = new CustomRequest(
97
+ createFinalURL(schemaPath, { baseUrl: finalBaseUrl, params, querySerializer }),
98
+ requestInit
99
+ );
100
+ let response;
101
+ for (const key in init) {
102
+ if (!(key in request)) {
103
+ request[key] = init[key];
104
+ }
105
+ }
106
+ if (middlewares.length) {
107
+ id = randomID();
108
+ options = Object.freeze({
109
+ baseUrl: finalBaseUrl,
110
+ fetch,
111
+ parseAs,
112
+ querySerializer,
113
+ bodySerializer
114
+ });
115
+ for (const m of middlewares) {
116
+ if (m && typeof m === "object" && typeof m.onRequest === "function") {
117
+ const result2 = await m.onRequest({
118
+ request,
119
+ schemaPath,
120
+ params,
121
+ options,
122
+ id
123
+ });
124
+ if (result2) {
125
+ if (result2 instanceof CustomRequest) {
126
+ request = result2;
127
+ } else if (result2 instanceof Response) {
128
+ response = result2;
129
+ break;
130
+ } else {
131
+ throw new Error("onRequest: must return new Request() or Response() when modifying the request");
132
+ }
133
+ }
134
+ }
135
+ }
136
+ }
137
+ if (!response) {
138
+ try {
139
+ response = await fetch(request, requestInitExt);
140
+ } catch (error2) {
141
+ let errorAfterMiddleware = error2;
142
+ if (middlewares.length) {
143
+ for (let i = middlewares.length - 1; i >= 0; i--) {
144
+ const m = middlewares[i];
145
+ if (m && typeof m === "object" && typeof m.onError === "function") {
146
+ const result2 = await m.onError({
147
+ request,
148
+ error: errorAfterMiddleware,
149
+ schemaPath,
150
+ params,
151
+ options,
152
+ id
153
+ });
154
+ if (result2) {
155
+ if (result2 instanceof Response) {
156
+ errorAfterMiddleware = void 0;
157
+ response = result2;
158
+ break;
159
+ }
160
+ if (result2 instanceof Error) {
161
+ errorAfterMiddleware = result2;
162
+ continue;
163
+ }
164
+ throw new Error("onError: must return new Response() or instance of Error");
165
+ }
166
+ }
167
+ }
168
+ }
169
+ if (errorAfterMiddleware) {
170
+ throw errorAfterMiddleware;
171
+ }
172
+ }
173
+ if (middlewares.length) {
174
+ for (let i = middlewares.length - 1; i >= 0; i--) {
175
+ const m = middlewares[i];
176
+ if (m && typeof m === "object" && typeof m.onResponse === "function") {
177
+ const result2 = await m.onResponse({
178
+ request,
179
+ response,
180
+ schemaPath,
181
+ params,
182
+ options,
183
+ id
184
+ });
185
+ if (result2) {
186
+ if (!(result2 instanceof Response)) {
187
+ throw new Error("onResponse: must return new Response() when modifying the response");
188
+ }
189
+ response = result2;
190
+ }
191
+ }
192
+ }
193
+ }
194
+ }
195
+ if (response.status === 204 || request.method === "HEAD" || response.headers.get("Content-Length") === "0") {
196
+ return response.ok ? { data: void 0, response } : { error: void 0, response };
197
+ }
198
+ if (response.ok) {
199
+ if (parseAs === "stream") {
200
+ return { data: response.body, response };
201
+ }
202
+ return { data: await response[parseAs](), response };
203
+ }
204
+ let error = await response.text();
205
+ try {
206
+ error = JSON.parse(error);
207
+ } catch {
208
+ }
209
+ return { error, response };
210
+ }
211
+ return {
212
+ request(method, url, init) {
213
+ return coreFetch(url, { ...init, method: method.toUpperCase() });
214
+ },
215
+ /** Call a GET endpoint */
216
+ GET(url, init) {
217
+ return coreFetch(url, { ...init, method: "GET" });
218
+ },
219
+ /** Call a PUT endpoint */
220
+ PUT(url, init) {
221
+ return coreFetch(url, { ...init, method: "PUT" });
222
+ },
223
+ /** Call a POST endpoint */
224
+ POST(url, init) {
225
+ return coreFetch(url, { ...init, method: "POST" });
226
+ },
227
+ /** Call a DELETE endpoint */
228
+ DELETE(url, init) {
229
+ return coreFetch(url, { ...init, method: "DELETE" });
230
+ },
231
+ /** Call a OPTIONS endpoint */
232
+ OPTIONS(url, init) {
233
+ return coreFetch(url, { ...init, method: "OPTIONS" });
234
+ },
235
+ /** Call a HEAD endpoint */
236
+ HEAD(url, init) {
237
+ return coreFetch(url, { ...init, method: "HEAD" });
238
+ },
239
+ /** Call a PATCH endpoint */
240
+ PATCH(url, init) {
241
+ return coreFetch(url, { ...init, method: "PATCH" });
242
+ },
243
+ /** Call a TRACE endpoint */
244
+ TRACE(url, init) {
245
+ return coreFetch(url, { ...init, method: "TRACE" });
246
+ },
247
+ /** Register middleware */
248
+ use(...middleware) {
249
+ for (const m of middleware) {
250
+ if (!m) {
251
+ continue;
252
+ }
253
+ if (typeof m !== "object" || !("onRequest" in m || "onResponse" in m || "onError" in m)) {
254
+ throw new Error("Middleware must be an object with one of `onRequest()`, `onResponse() or `onError()`");
255
+ }
256
+ middlewares.push(m);
257
+ }
258
+ },
259
+ /** Unregister middleware */
260
+ eject(...middleware) {
261
+ for (const m of middleware) {
262
+ const i = middlewares.indexOf(m);
263
+ if (i !== -1) {
264
+ middlewares.splice(i, 1);
265
+ }
266
+ }
267
+ }
268
+ };
269
+ }
270
+ function serializePrimitiveParam(name, value, options) {
271
+ if (value === void 0 || value === null) {
272
+ return "";
273
+ }
274
+ if (typeof value === "object") {
275
+ throw new Error(
276
+ "Deeply-nested arrays/objects aren\u2019t supported. Provide your own `querySerializer()` to handle these."
277
+ );
278
+ }
279
+ return `${name}=${options?.allowReserved === true ? value : encodeURIComponent(value)}`;
280
+ }
281
+ function serializeObjectParam(name, value, options) {
282
+ if (!value || typeof value !== "object") {
283
+ return "";
284
+ }
285
+ const values = [];
286
+ const joiner = {
287
+ simple: ",",
288
+ label: ".",
289
+ matrix: ";"
290
+ }[options.style] || "&";
291
+ if (options.style !== "deepObject" && options.explode === false) {
292
+ for (const k in value) {
293
+ values.push(k, options.allowReserved === true ? value[k] : encodeURIComponent(value[k]));
294
+ }
295
+ const final2 = values.join(",");
296
+ switch (options.style) {
297
+ case "form": {
298
+ return `${name}=${final2}`;
299
+ }
300
+ case "label": {
301
+ return `.${final2}`;
302
+ }
303
+ case "matrix": {
304
+ return `;${name}=${final2}`;
305
+ }
306
+ default: {
307
+ return final2;
308
+ }
309
+ }
310
+ }
311
+ for (const k in value) {
312
+ const finalName = options.style === "deepObject" ? `${name}[${k}]` : k;
313
+ values.push(serializePrimitiveParam(finalName, value[k], options));
314
+ }
315
+ const final = values.join(joiner);
316
+ return options.style === "label" || options.style === "matrix" ? `${joiner}${final}` : final;
317
+ }
318
+ function serializeArrayParam(name, value, options) {
319
+ if (!Array.isArray(value)) {
320
+ return "";
321
+ }
322
+ if (options.explode === false) {
323
+ const joiner2 = { form: ",", spaceDelimited: "%20", pipeDelimited: "|" }[options.style] || ",";
324
+ const final = (options.allowReserved === true ? value : value.map((v) => encodeURIComponent(v))).join(joiner2);
325
+ switch (options.style) {
326
+ case "simple": {
327
+ return final;
328
+ }
329
+ case "label": {
330
+ return `.${final}`;
331
+ }
332
+ case "matrix": {
333
+ return `;${name}=${final}`;
334
+ }
335
+ // case "spaceDelimited":
336
+ // case "pipeDelimited":
337
+ default: {
338
+ return `${name}=${final}`;
339
+ }
340
+ }
341
+ }
342
+ const joiner = { simple: ",", label: ".", matrix: ";" }[options.style] || "&";
343
+ const values = [];
344
+ for (const v of value) {
345
+ if (options.style === "simple" || options.style === "label") {
346
+ values.push(options.allowReserved === true ? v : encodeURIComponent(v));
347
+ } else {
348
+ values.push(serializePrimitiveParam(name, v, options));
349
+ }
350
+ }
351
+ return options.style === "label" || options.style === "matrix" ? `${joiner}${values.join(joiner)}` : values.join(joiner);
352
+ }
353
+ function createQuerySerializer(options) {
354
+ return function querySerializer(queryParams) {
355
+ const search = [];
356
+ if (queryParams && typeof queryParams === "object") {
357
+ for (const name in queryParams) {
358
+ const value = queryParams[name];
359
+ if (value === void 0 || value === null) {
360
+ continue;
361
+ }
362
+ if (Array.isArray(value)) {
363
+ if (value.length === 0) {
364
+ continue;
365
+ }
366
+ search.push(
367
+ serializeArrayParam(name, value, {
368
+ style: "form",
369
+ explode: true,
370
+ ...options?.array,
371
+ allowReserved: options?.allowReserved || false
372
+ })
373
+ );
374
+ continue;
375
+ }
376
+ if (typeof value === "object") {
377
+ search.push(
378
+ serializeObjectParam(name, value, {
379
+ style: "deepObject",
380
+ explode: true,
381
+ ...options?.object,
382
+ allowReserved: options?.allowReserved || false
383
+ })
384
+ );
385
+ continue;
386
+ }
387
+ search.push(serializePrimitiveParam(name, value, options));
388
+ }
389
+ }
390
+ return search.join("&");
391
+ };
392
+ }
393
+ function defaultPathSerializer(pathname, pathParams) {
394
+ let nextURL = pathname;
395
+ for (const match of pathname.match(PATH_PARAM_RE) ?? []) {
396
+ let name = match.substring(1, match.length - 1);
397
+ let explode = false;
398
+ let style = "simple";
399
+ if (name.endsWith("*")) {
400
+ explode = true;
401
+ name = name.substring(0, name.length - 1);
402
+ }
403
+ if (name.startsWith(".")) {
404
+ style = "label";
405
+ name = name.substring(1);
406
+ } else if (name.startsWith(";")) {
407
+ style = "matrix";
408
+ name = name.substring(1);
409
+ }
410
+ if (!pathParams || pathParams[name] === void 0 || pathParams[name] === null) {
411
+ continue;
412
+ }
413
+ const value = pathParams[name];
414
+ if (Array.isArray(value)) {
415
+ nextURL = nextURL.replace(match, serializeArrayParam(name, value, { style, explode }));
416
+ continue;
417
+ }
418
+ if (typeof value === "object") {
419
+ nextURL = nextURL.replace(match, serializeObjectParam(name, value, { style, explode }));
420
+ continue;
421
+ }
422
+ if (style === "matrix") {
423
+ nextURL = nextURL.replace(match, `;${serializePrimitiveParam(name, value)}`);
424
+ continue;
425
+ }
426
+ nextURL = nextURL.replace(match, style === "label" ? `.${encodeURIComponent(value)}` : encodeURIComponent(value));
427
+ }
428
+ return nextURL;
429
+ }
430
+ function defaultBodySerializer(body, headers) {
431
+ if (body instanceof FormData) {
432
+ return body;
433
+ }
434
+ if (headers) {
435
+ const contentType = headers.get instanceof Function ? headers.get("Content-Type") ?? headers.get("content-type") : headers["Content-Type"] ?? headers["content-type"];
436
+ if (contentType === "application/x-www-form-urlencoded") {
437
+ return new URLSearchParams(body).toString();
438
+ }
439
+ }
440
+ return JSON.stringify(body);
441
+ }
442
+ function createFinalURL(pathname, options) {
443
+ let finalURL = `${options.baseUrl}${pathname}`;
444
+ if (options.params?.path) {
445
+ finalURL = defaultPathSerializer(finalURL, options.params.path);
446
+ }
447
+ let search = options.querySerializer(options.params.query ?? {});
448
+ if (search.startsWith("?")) {
449
+ search = search.substring(1);
450
+ }
451
+ if (search) {
452
+ finalURL += `?${search}`;
453
+ }
454
+ return finalURL;
455
+ }
456
+ function mergeHeaders(...allHeaders) {
457
+ const finalHeaders = new Headers();
458
+ for (const h of allHeaders) {
459
+ if (!h || typeof h !== "object") {
460
+ continue;
461
+ }
462
+ const iterator = h instanceof Headers ? h.entries() : Object.entries(h);
463
+ for (const [k, v] of iterator) {
464
+ if (v === null) {
465
+ finalHeaders.delete(k);
466
+ } else if (Array.isArray(v)) {
467
+ for (const v2 of v) {
468
+ finalHeaders.append(k, v2);
469
+ }
470
+ } else if (v !== void 0) {
471
+ finalHeaders.set(k, v);
472
+ }
473
+ }
474
+ }
475
+ return finalHeaders;
476
+ }
477
+ function removeTrailingSlash(url) {
478
+ if (url.endsWith("/")) {
479
+ return url.substring(0, url.length - 1);
480
+ }
481
+ return url;
482
+ }
483
+
484
+ // ../../packages/client/src/client.ts
485
+ var DEFAULT_BASE_URL = "https://mdtidy.com";
486
+ var DEFAULT_TIMEOUT_MS = 6e4;
487
+ function withTimeout(baseFetch, timeoutMs) {
488
+ return (input2, init) => {
489
+ if (init?.signal) return baseFetch(input2, init);
490
+ return baseFetch(input2, { ...init, signal: AbortSignal.timeout(timeoutMs) });
491
+ };
492
+ }
493
+ function authMiddleware(apiKey) {
494
+ return {
495
+ onRequest({ request }) {
496
+ request.headers.set("X-API-KEY", apiKey);
497
+ request.headers.set("Authorization", `Bearer ${apiKey}`);
498
+ return request;
499
+ }
500
+ };
501
+ }
502
+ var throwOnError = {
503
+ async onResponse({ response }) {
504
+ if (response.ok) return response;
505
+ let body;
506
+ try {
507
+ body = await response.clone().json();
508
+ } catch {
509
+ body = void 0;
510
+ }
511
+ const err = isApiErrorBody(body) ? body.error : void 0;
512
+ throw new MdtidyApiError({
513
+ status: response.status,
514
+ code: err?.code ?? "http_error",
515
+ message: err?.message ?? (response.statusText || "request failed"),
516
+ requestId: err?.requestId,
517
+ details: err ? { required: err.required, balance: err.balance } : void 0
518
+ });
519
+ }
520
+ };
521
+ function createMdtidyClient(opts) {
522
+ const baseUrl = (opts.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
523
+ const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
524
+ const baseFetch = opts.fetch ?? globalThis.fetch;
525
+ const client = createClient({ baseUrl, fetch: withTimeout(baseFetch, timeoutMs) });
526
+ client.use(authMiddleware(opts.apiKey), throwOnError);
527
+ return client;
528
+ }
529
+
530
+ // ../../packages/mcp-core/src/context.ts
531
+ function buildContext(opts) {
532
+ return {
533
+ client: createMdtidyClient({
534
+ apiKey: opts.apiKey,
535
+ baseUrl: opts.baseUrl,
536
+ fetch: opts.fetch,
537
+ timeoutMs: opts.timeoutMs
538
+ }),
539
+ baseUrl: opts.baseUrl,
540
+ transport: opts.transport,
541
+ logger: opts.logger
542
+ };
543
+ }
544
+
545
+ // ../../packages/tools/src/catalog.ts
546
+ var TOOL_CATALOG = [
547
+ {
548
+ name: "tidy_markdown",
549
+ group: "Convert",
550
+ operationId: "convert",
551
+ cost: 1,
552
+ title: "Tidy & convert Markdown",
553
+ description: "Clean and repair messy AI-generated Markdown and render it to HTML, plain text, PDF, DOCX, or PNG. Choose a design system (minimal-clean, executive-report, developer-docs) and optional page geometry. Costs 1 credit per successful render (auto-refunded on failure); returns the cleanup fixes applied and the remaining balance."
554
+ },
555
+ {
556
+ name: "check_usage",
557
+ group: "Read",
558
+ operationId: "usage",
559
+ cost: 0,
560
+ title: "Check credit usage",
561
+ description: "Return the caller's credit balance and recent API calls. Free \u2014 call it before a batch of conversions."
562
+ },
563
+ {
564
+ name: "get_entitlement",
565
+ group: "Read",
566
+ operationId: "credits",
567
+ cost: 0,
568
+ title: "Get plan entitlement",
569
+ description: "Return the caller's plan and workspace gates (can_save / can_share). Free."
570
+ },
571
+ {
572
+ name: "list_projects",
573
+ group: "Read",
574
+ operationId: "listProjects",
575
+ cost: 0,
576
+ title: "List projects",
577
+ description: "List the caller's projects. scope: mine | shared | archived (default mine). Free."
578
+ },
579
+ {
580
+ name: "get_project",
581
+ group: "Read",
582
+ operationId: "getProject",
583
+ cost: 0,
584
+ title: "Get a project",
585
+ description: "Return a project together with its folders and files. Free."
586
+ },
587
+ {
588
+ name: "get_file",
589
+ group: "Read",
590
+ operationId: "getFile",
591
+ cost: 0,
592
+ title: "Read a file",
593
+ description: "Return a saved file's Markdown content plus its version/ETag. Free."
594
+ },
595
+ {
596
+ name: "create_project",
597
+ group: "Write",
598
+ operationId: "createProject",
599
+ cost: 0,
600
+ title: "Create a project",
601
+ description: "Create a workspace project (a container for files). Free."
602
+ },
603
+ {
604
+ name: "save_document",
605
+ group: "Write",
606
+ operationId: ["listProjects", "createProject", "getProject", "createFile", "updateFile"],
607
+ cost: "1/0",
608
+ title: "Save a document (upsert)",
609
+ description: 'Fast path \u2014 save Markdown in one step. Finds or creates the target project (default "Drafts") and creates the file, or updates it if a same-named document already exists. 1 credit on create, 0 on update. Returns the file id, project, and a link. Use this to start fast; use the granular tools for structured workspaces.'
610
+ },
611
+ {
612
+ name: "save_file",
613
+ group: "Write",
614
+ operationId: "createFile",
615
+ cost: 1,
616
+ title: "Create a file",
617
+ description: "First-save a Markdown file into a known project (idempotent via an idempotency key). 1 credit."
618
+ },
619
+ {
620
+ name: "update_file",
621
+ group: "Write",
622
+ operationId: "updateFile",
623
+ cost: 0,
624
+ title: "Update a file",
625
+ description: "Autosave, rename, or move a file. Content writes use If-Match for safe concurrent edits. Free."
626
+ },
627
+ {
628
+ name: "get_project_share",
629
+ group: "Share",
630
+ operationId: "getProjectShare",
631
+ cost: 0,
632
+ title: "Get share state",
633
+ description: "Return a project's current share state and public URL. Free."
634
+ },
635
+ {
636
+ name: "share_project_public",
637
+ group: "Share",
638
+ operationId: "enableProjectPublicLink",
639
+ cost: 1,
640
+ title: "Share a project publicly",
641
+ description: "Turn on a project's public link and return https://mdtidy.com/p/{slug}. 1 credit (free within the 30-day slug grace)."
642
+ }
643
+ ];
644
+ function catalogMeta(name) {
645
+ const entry = TOOL_CATALOG.find((t) => t.name === name);
646
+ if (!entry) throw new Error(`No catalog entry for tool "${name}"`);
647
+ return { name: entry.name, title: entry.title, description: entry.description, cost: entry.cost };
648
+ }
649
+ var DEFERRED_TOOLS = [
650
+ { name: "update_project", operationId: "updateProject" },
651
+ { name: "delete_project", operationId: "deleteProject" },
652
+ { name: "delete_file", operationId: "deleteFile" },
653
+ { name: "copy_file", operationId: "copyFile" },
654
+ { name: "create_folder", operationId: "createFolder" },
655
+ { name: "update_folder", operationId: "updateFolder" },
656
+ { name: "delete_folder", operationId: "deleteFolder" },
657
+ { name: "regenerate_public_link", operationId: "regenerateProjectPublicLink" },
658
+ { name: "invite_viewers", operationId: "inviteProjectViewers" },
659
+ { name: "remove_invitee", operationId: "removeProjectInvitee" },
660
+ { name: "make_project_private", operationId: "makeProjectPrivate" },
661
+ { name: "disable_public_link", operationId: "disableProjectPublicLink" }
662
+ ];
663
+
664
+ // ../../packages/tools/src/tools/read.ts
665
+ import { z } from "zod";
666
+
667
+ // ../../packages/tools/src/shape.ts
668
+ function jsonText(value) {
669
+ return { type: "text", text: JSON.stringify(value, null, 2) };
670
+ }
671
+ function text(value) {
672
+ return { type: "text", text: value };
673
+ }
674
+ function result(...content) {
675
+ return { content };
676
+ }
677
+ async function shapeConvertResult(data, input2, ctx) {
678
+ const fixes = data.warnings.length > 0 ? data.warnings.map((w) => `${w.rule}\xD7${w.fixes}`).join(", ") : "no changes needed";
679
+ const summary = `Tidied \u2192 ${data.format} (${data.byteSize} bytes, design system "${data.designSystem}"). Fixes: ${fixes}. Credits charged ${data.creditsCharged}, remaining ${data.creditsRemaining}.`;
680
+ const blocks = [];
681
+ if (data.format === "html" || data.format === "text") {
682
+ blocks.push(text(data.output ?? ""));
683
+ } else if (data.format === "png") {
684
+ if (data.outputBase64)
685
+ blocks.push({ type: "image", data: data.outputBase64, mimeType: "image/png" });
686
+ } else {
687
+ if (ctx.transport === "stdio" && input2.savePath && data.outputBase64) {
688
+ const { writeFileSync } = await import("fs");
689
+ writeFileSync(input2.savePath, Buffer.from(data.outputBase64, "base64"));
690
+ blocks.push(text(`Saved ${data.format.toUpperCase()} to ${input2.savePath}`));
691
+ } else if (data.outputBase64) {
692
+ blocks.push({
693
+ type: "resource",
694
+ resource: {
695
+ uri: `mdtidy://convert/${data.requestId}.${data.format}`,
696
+ mimeType: data.contentType,
697
+ blob: data.outputBase64
698
+ }
699
+ });
700
+ }
701
+ }
702
+ blocks.push(text(summary));
703
+ return { content: blocks };
704
+ }
705
+
706
+ // ../../packages/tools/src/types.ts
707
+ function defineTool(def) {
708
+ return def;
709
+ }
710
+
711
+ // ../../packages/tools/src/tools/read.ts
712
+ var checkUsage = defineTool({
713
+ ...catalogMeta("check_usage"),
714
+ inputSchema: z.object({}),
715
+ handler: async (_i, ctx) => {
716
+ const { data } = await ctx.client.GET("/api/v1/usage", {});
717
+ const u = data;
718
+ return result(
719
+ text(
720
+ `Credits remaining: ${u.creditsRemaining} (subscription ${u.subscriptionCredits} + top-up ${u.topupCredits}). Calls this period: ${u.callsThisPeriod}.`
721
+ ),
722
+ jsonText(u)
723
+ );
724
+ }
725
+ });
726
+ var getEntitlement = defineTool({
727
+ ...catalogMeta("get_entitlement"),
728
+ inputSchema: z.object({}),
729
+ handler: async (_i, ctx) => {
730
+ const { data } = await ctx.client.GET("/api/v1/credits", {});
731
+ const e = data;
732
+ return result(
733
+ text(
734
+ `Plan: ${e.plan}. Balance: ${e.credits_balance}. can_save=${e.can_save} can_share=${e.can_share}.`
735
+ ),
736
+ jsonText(e)
737
+ );
738
+ }
739
+ });
740
+ var listProjects = defineTool({
741
+ ...catalogMeta("list_projects"),
742
+ inputSchema: z.object({
743
+ scope: z.enum(["mine", "shared", "archived"]).optional().describe("Which projects to list. Defaults to mine.")
744
+ }),
745
+ handler: async (i, ctx) => {
746
+ const { data } = await ctx.client.GET("/api/v1/projects", {
747
+ params: { query: i.scope ? { scope: i.scope } : {} }
748
+ });
749
+ const d = data;
750
+ return result(text(`${d.items.length} project(s) in scope "${d.scope}".`), jsonText(d.items));
751
+ }
752
+ });
753
+ var getProject = defineTool({
754
+ ...catalogMeta("get_project"),
755
+ inputSchema: z.object({
756
+ id: z.string().uuid().describe("Project id."),
757
+ includeArchived: z.boolean().optional().describe("Include archived files. Default false.")
758
+ }),
759
+ handler: async (i, ctx) => {
760
+ const { data } = await ctx.client.GET("/api/v1/projects/{id}", {
761
+ params: {
762
+ path: { id: i.id },
763
+ query: i.includeArchived != null ? { include_archived: i.includeArchived } : {}
764
+ }
765
+ });
766
+ return result(jsonText(data));
767
+ }
768
+ });
769
+ var getFile = defineTool({
770
+ ...catalogMeta("get_file"),
771
+ inputSchema: z.object({ id: z.string().uuid().describe("File id.") }),
772
+ handler: async (i, ctx) => {
773
+ const { data } = await ctx.client.GET("/api/v1/files/{id}", {
774
+ params: { path: { id: i.id } }
775
+ });
776
+ const f = data;
777
+ return result(text(`File "${f.name}" (v${f.version}). ETag ${f.etag}.`), text(f.content ?? ""));
778
+ }
779
+ });
780
+
781
+ // ../../packages/tools/src/tools/share.ts
782
+ import { z as z2 } from "zod";
783
+ var getProjectShare = defineTool({
784
+ ...catalogMeta("get_project_share"),
785
+ inputSchema: z2.object({ id: z2.string().uuid().describe("Project id.") }),
786
+ handler: async (i, ctx) => {
787
+ const { data } = await ctx.client.GET("/api/v1/projects/{id}/share", {
788
+ params: { path: { id: i.id } }
789
+ });
790
+ return result(jsonText(data));
791
+ }
792
+ });
793
+ var shareProjectPublic = defineTool({
794
+ ...catalogMeta("share_project_public"),
795
+ inputSchema: z2.object({
796
+ id: z2.string().uuid().describe("Project id."),
797
+ idempotencyKey: z2.string().optional()
798
+ }),
799
+ handler: async (i, ctx) => {
800
+ const { data } = await ctx.client.POST("/api/v1/projects/{id}/share/public", {
801
+ params: {
802
+ path: { id: i.id },
803
+ ...i.idempotencyKey ? { header: { "Idempotency-Key": i.idempotencyKey } } : {}
804
+ }
805
+ });
806
+ const s = data;
807
+ return result(
808
+ text(`Public link: ${s.public_url ?? s.project_url ?? "(enabled)"}`),
809
+ jsonText(s)
810
+ );
811
+ }
812
+ });
813
+
814
+ // ../../packages/tools/src/tools/tidy-markdown.ts
815
+ import { z as z3 } from "zod";
816
+ var input = z3.object({
817
+ markdown: z3.string().min(1).describe("The Markdown to clean and convert."),
818
+ format: z3.enum(["html", "text", "pdf", "docx", "png"]).describe("Output format. html/text return inline; pdf/docx/png return a file or resource."),
819
+ designSystem: z3.enum(["minimal-clean", "executive-report", "developer-docs"]).optional().describe("Visual theme. Defaults to minimal-clean."),
820
+ page: z3.object({
821
+ paperSize: z3.enum(["Letter", "A4", "A3"]).optional(),
822
+ orientation: z3.enum(["portrait", "landscape"]).optional(),
823
+ marginPreset: z3.enum(["narrow", "normal", "wide"]).optional(),
824
+ fontScale: z3.enum(["down", "normal", "up"]).optional()
825
+ }).optional().describe("Optional page geometry + font scale (render-only; no credit cost)."),
826
+ tidy: z3.object({
827
+ enable: z3.boolean().optional(),
828
+ polish: z3.boolean().optional()
829
+ }).optional().describe("Tidy pipeline toggles. Both default to true."),
830
+ savePath: z3.string().optional().describe("(stdio only) write binary output (pdf/docx/png) to this local path and return it.")
831
+ });
832
+ var tidyMarkdown = defineTool({
833
+ ...catalogMeta("tidy_markdown"),
834
+ inputSchema: input,
835
+ handler: async (i, ctx) => {
836
+ const { data } = await ctx.client.POST("/api/v1/convert", {
837
+ body: {
838
+ markdown: i.markdown,
839
+ format: i.format,
840
+ ...i.designSystem ? { designSystem: i.designSystem } : {},
841
+ ...i.page ? { page: i.page } : {},
842
+ ...i.tidy ? { settings: { tidy: i.tidy } } : {}
843
+ }
844
+ });
845
+ return shapeConvertResult(data, i, ctx);
846
+ }
847
+ });
848
+
849
+ // ../../packages/tools/src/tools/write.ts
850
+ import { z as z4 } from "zod";
851
+ var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
852
+ function deriveName(markdown) {
853
+ const heading = markdown.match(/^#\s+(.+?)\s*$/m);
854
+ return (heading?.[1] ?? "Untitled").slice(0, 200);
855
+ }
856
+ async function resolveProject(ctx, project) {
857
+ const wanted = project?.trim() || "Drafts";
858
+ if (UUID_RE.test(wanted)) {
859
+ const { data } = await ctx.client.GET("/api/v1/projects/{id}", {
860
+ params: { path: { id: wanted }, query: {} }
861
+ });
862
+ return { id: data.id, name: data.name };
863
+ }
864
+ const findByName = async () => {
865
+ const { data } = await ctx.client.GET("/api/v1/projects", {
866
+ params: { query: { scope: "mine" } }
867
+ });
868
+ const found = data.items.find((p) => p.name === wanted);
869
+ return found ? { id: found.id, name: found.name } : void 0;
870
+ };
871
+ const existing = await findByName();
872
+ if (existing) return existing;
873
+ try {
874
+ const { data } = await ctx.client.POST("/api/v1/projects", { body: { name: wanted } });
875
+ return { id: data.id, name: data.name };
876
+ } catch (err) {
877
+ if (err instanceof MdtidyApiError && err.status === 409) {
878
+ const afterRace = await findByName();
879
+ if (afterRace) return afterRace;
880
+ }
881
+ throw err;
882
+ }
883
+ }
884
+ async function patchContent(ctx, fileId, etag, content) {
885
+ const { data } = await ctx.client.PATCH("/api/v1/files/{id}", {
886
+ params: { path: { id: fileId }, header: { "If-Match": etag } },
887
+ body: { content }
888
+ });
889
+ return data;
890
+ }
891
+ var createProject = defineTool({
892
+ ...catalogMeta("create_project"),
893
+ inputSchema: z4.object({
894
+ name: z4.string().min(1).max(200).describe("Project name."),
895
+ description: z4.string().max(2e3).optional()
896
+ }),
897
+ handler: async (i, ctx) => {
898
+ const { data } = await ctx.client.POST("/api/v1/projects", {
899
+ body: { name: i.name, ...i.description ? { description: i.description } : {} }
900
+ });
901
+ return result(text(`Created project "${data.name}" (${data.id}).`), jsonText(data));
902
+ }
903
+ });
904
+ var saveFile = defineTool({
905
+ ...catalogMeta("save_file"),
906
+ inputSchema: z4.object({
907
+ project_id: z4.string().uuid().describe("Target project id."),
908
+ name: z4.string().min(1).max(200),
909
+ content: z4.string().describe("Markdown body."),
910
+ folder_id: z4.string().uuid().optional(),
911
+ idempotencyKey: z4.string().optional()
912
+ }),
913
+ handler: async (i, ctx) => {
914
+ const { data } = await ctx.client.POST("/api/v1/files", {
915
+ ...i.idempotencyKey ? { params: { header: { "Idempotency-Key": i.idempotencyKey } } } : {},
916
+ body: {
917
+ project_id: i.project_id,
918
+ name: i.name,
919
+ content: i.content,
920
+ ...i.folder_id ? { folder_id: i.folder_id } : {}
921
+ }
922
+ });
923
+ return result(
924
+ text(`Saved file "${data.name}" (${data.id}). 1 credit charged.`),
925
+ jsonText(data)
926
+ );
927
+ }
928
+ });
929
+ var updateFile = defineTool({
930
+ ...catalogMeta("update_file"),
931
+ inputSchema: z4.object({
932
+ id: z4.string().uuid(),
933
+ content: z4.string().optional(),
934
+ name: z4.string().min(1).max(200).optional(),
935
+ folder_id: z4.string().uuid().nullable().optional(),
936
+ archived: z4.boolean().optional(),
937
+ ifMatch: z4.string().optional().describe("ETag/version for safe content writes (required when changing content).")
938
+ }),
939
+ handler: async (i, ctx) => {
940
+ const { data } = await ctx.client.PATCH("/api/v1/files/{id}", {
941
+ params: {
942
+ path: { id: i.id },
943
+ ...i.ifMatch ? { header: { "If-Match": i.ifMatch } } : {}
944
+ },
945
+ body: {
946
+ ...i.content != null ? { content: i.content } : {},
947
+ ...i.name != null ? { name: i.name } : {},
948
+ ...i.folder_id !== void 0 ? { folder_id: i.folder_id } : {},
949
+ ...i.archived != null ? { archived: i.archived } : {}
950
+ }
951
+ });
952
+ return result(text(`Updated file "${data.name}" (v${data.version}).`), jsonText(data));
953
+ }
954
+ });
955
+ var saveDocument = defineTool({
956
+ ...catalogMeta("save_document"),
957
+ inputSchema: z4.object({
958
+ content: z4.string().min(1).describe("Markdown body to save."),
959
+ name: z4.string().max(200).optional().describe('Document name. Defaults to the first H1, else "Untitled".'),
960
+ project: z4.string().optional().describe('Project id, or a name to find-or-create. Defaults to "Drafts".'),
961
+ idempotencyKey: z4.string().optional()
962
+ }),
963
+ handler: async (i, ctx) => {
964
+ const name = i.name?.trim() || deriveName(i.content);
965
+ const project = await resolveProject(ctx, i.project);
966
+ const { data: full } = await ctx.client.GET("/api/v1/projects/{id}", {
967
+ params: { path: { id: project.id }, query: {} }
968
+ });
969
+ const files = full.files ?? [];
970
+ const existing = files.find((f) => f.name === name && !f.archived);
971
+ let file;
972
+ let created;
973
+ if (existing) {
974
+ try {
975
+ file = await patchContent(ctx, existing.id, existing.etag, i.content);
976
+ } catch (err) {
977
+ if (err instanceof MdtidyApiError && err.status === 409) {
978
+ const { data: fresh } = await ctx.client.GET("/api/v1/projects/{id}", {
979
+ params: { path: { id: project.id }, query: {} }
980
+ });
981
+ const again = (fresh.files ?? []).find(
982
+ (f) => f.name === name && !f.archived
983
+ );
984
+ if (!again) throw err;
985
+ file = await patchContent(ctx, again.id, again.etag, i.content);
986
+ } else {
987
+ throw err;
988
+ }
989
+ }
990
+ created = false;
991
+ } else {
992
+ const { data } = await ctx.client.POST("/api/v1/files", {
993
+ ...i.idempotencyKey ? { params: { header: { "Idempotency-Key": i.idempotencyKey } } } : {},
994
+ body: { project_id: project.id, name, content: i.content }
995
+ });
996
+ file = data;
997
+ created = true;
998
+ }
999
+ const url = `${ctx.baseUrl}/edit/${file.id}`;
1000
+ const summary = created ? `Created "${name}" in project "${project.name}". 1 credit charged.` : `Updated "${name}" in project "${project.name}". No credit (update).`;
1001
+ return result(
1002
+ text(summary),
1003
+ jsonText({
1004
+ file_id: file.id,
1005
+ name,
1006
+ project,
1007
+ version: file.version,
1008
+ etag: file.etag,
1009
+ url,
1010
+ created,
1011
+ creditsRemaining: file.credits_remaining ?? null
1012
+ })
1013
+ );
1014
+ }
1015
+ });
1016
+
1017
+ // ../../packages/tools/src/registry.ts
1018
+ var REGISTRY = [
1019
+ tidyMarkdown,
1020
+ checkUsage,
1021
+ getEntitlement,
1022
+ listProjects,
1023
+ getProject,
1024
+ getFile,
1025
+ createProject,
1026
+ saveDocument,
1027
+ saveFile,
1028
+ updateFile,
1029
+ getProjectShare,
1030
+ shareProjectPublic
1031
+ ];
1032
+
1033
+ // ../../packages/mcp-core/src/register.ts
1034
+ function registerTools(server, ctx, tools = REGISTRY) {
1035
+ for (const tool of tools) {
1036
+ server.registerTool(
1037
+ tool.name,
1038
+ {
1039
+ title: tool.title,
1040
+ description: tool.description,
1041
+ inputSchema: tool.inputSchema.shape
1042
+ },
1043
+ async (args) => {
1044
+ const res = await tool.handler(args, ctx);
1045
+ return { content: res.content, isError: res.isError };
1046
+ }
1047
+ );
1048
+ }
1049
+ }
1050
+
1051
+ // ../../packages/mcp-core/src/server-info.ts
1052
+ var SERVER_INFO = {
1053
+ name: "mdtidy",
1054
+ version: "1.0.0",
1055
+ title: "Markdown Tidy"
1056
+ };
1057
+ var PROTOCOL_VERSION = "2025-06-18";
1058
+
1059
+ // ../../packages/mcp-core/src/jsonrpc.ts
1060
+ import { zodToJsonSchema } from "zod-to-json-schema";
1061
+ function toolInputJsonSchema(tool) {
1062
+ const schema = zodToJsonSchema(tool.inputSchema, {
1063
+ target: "jsonSchema7",
1064
+ $refStrategy: "none"
1065
+ });
1066
+ delete schema.$schema;
1067
+ return schema;
1068
+ }
1069
+ async function handleJsonRpc(req, ctx, opts = {}) {
1070
+ const tools = opts.tools ?? REGISTRY;
1071
+ const id = req.id ?? null;
1072
+ const ok = (result2) => ({ jsonrpc: "2.0", id, result: result2 });
1073
+ const fail = (code, message) => ({
1074
+ jsonrpc: "2.0",
1075
+ id,
1076
+ error: { code, message }
1077
+ });
1078
+ switch (req.method) {
1079
+ case "initialize": {
1080
+ const requested = req.params?.protocolVersion;
1081
+ return ok({
1082
+ protocolVersion: typeof requested === "string" ? requested : PROTOCOL_VERSION,
1083
+ capabilities: { tools: { listChanged: false } },
1084
+ serverInfo: SERVER_INFO
1085
+ });
1086
+ }
1087
+ case "ping":
1088
+ return ok({});
1089
+ case "tools/list":
1090
+ return ok({
1091
+ tools: tools.map((t) => ({
1092
+ name: t.name,
1093
+ title: t.title,
1094
+ description: t.description,
1095
+ inputSchema: toolInputJsonSchema(t)
1096
+ }))
1097
+ });
1098
+ case "tools/call": {
1099
+ const name = req.params?.name;
1100
+ const tool = tools.find((t) => t.name === name);
1101
+ if (!tool) return fail(-32602, `Unknown tool: ${name}`);
1102
+ const parsed = tool.inputSchema.safeParse(req.params?.arguments ?? {});
1103
+ if (!parsed.success) {
1104
+ const detail = parsed.error.issues.map((iss) => `${iss.path.join(".")}: ${iss.message}`).join("; ");
1105
+ return fail(-32602, `Invalid arguments for ${name}: ${detail}`);
1106
+ }
1107
+ try {
1108
+ const res = await tool.handler(parsed.data, ctx);
1109
+ return ok({ content: res.content, isError: res.isError ?? false });
1110
+ } catch (err) {
1111
+ const message = err instanceof Error ? err.message : String(err);
1112
+ return ok({ content: [{ type: "text", text: `Error: ${message}` }], isError: true });
1113
+ }
1114
+ }
1115
+ default:
1116
+ if (req.id === void 0 || req.method.startsWith("notifications/")) return null;
1117
+ return fail(-32601, `Method not found: ${req.method}`);
1118
+ }
1119
+ }
1120
+
1121
+ // ../../packages/mcp-core/src/stdio.ts
1122
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
1123
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
1124
+ async function startStdio(opts = {}) {
1125
+ const apiKey = opts.apiKey ?? process.env.MDTIDY_API_KEY;
1126
+ if (!apiKey) {
1127
+ throw new Error(
1128
+ "MDTIDY_API_KEY is required. Create a key at https://mdtidy.com/account/api-keys and set it in your MCP client config."
1129
+ );
1130
+ }
1131
+ const baseUrl = opts.baseUrl ?? process.env.MDTIDY_BASE_URL ?? "https://mdtidy.com";
1132
+ const ctx = buildContext({ apiKey, baseUrl, transport: "stdio" });
1133
+ const server = new McpServer(
1134
+ { name: SERVER_INFO.name, version: SERVER_INFO.version },
1135
+ { capabilities: { tools: {} } }
1136
+ );
1137
+ registerTools(server, ctx);
1138
+ await server.connect(new StdioServerTransport());
1139
+ }
1140
+
1141
+ // ../../packages/mcp-core/src/http.ts
1142
+ function json(body, status) {
1143
+ return new Response(JSON.stringify(body), {
1144
+ status,
1145
+ headers: { "content-type": "application/json" }
1146
+ });
1147
+ }
1148
+ function extractApiKey(req) {
1149
+ const auth = req.headers.get("authorization");
1150
+ if (auth && auth.toLowerCase().startsWith("bearer ")) return auth.slice(7).trim();
1151
+ const xKey = req.headers.get("x-api-key");
1152
+ return xKey?.trim() || void 0;
1153
+ }
1154
+ function createMcpRouteHandler(options = {}) {
1155
+ return async function handler(req) {
1156
+ if (req.method === "GET" || req.method === "DELETE") {
1157
+ return json(
1158
+ {
1159
+ jsonrpc: "2.0",
1160
+ id: null,
1161
+ error: { code: -32e3, message: "This MCP server is stateless; use POST." }
1162
+ },
1163
+ 405
1164
+ );
1165
+ }
1166
+ if (req.method !== "POST") return new Response("Method Not Allowed", { status: 405 });
1167
+ const apiKey = extractApiKey(req);
1168
+ if (!apiKey) {
1169
+ return json(
1170
+ {
1171
+ jsonrpc: "2.0",
1172
+ id: null,
1173
+ error: {
1174
+ code: -32001,
1175
+ message: 'Missing API key. Send "Authorization: Bearer <mdtidy key>" or "X-API-KEY". Create one at https://mdtidy.com/account/api-keys.'
1176
+ }
1177
+ },
1178
+ 401
1179
+ );
1180
+ }
1181
+ let body;
1182
+ try {
1183
+ body = await req.json();
1184
+ } catch {
1185
+ return json(
1186
+ { jsonrpc: "2.0", id: null, error: { code: -32700, message: "Parse error" } },
1187
+ 400
1188
+ );
1189
+ }
1190
+ const baseUrl = options.resolveBaseUrl?.(req) ?? options.defaultBaseUrl ?? "https://mdtidy.com";
1191
+ const ctx = buildContext({ apiKey, baseUrl, transport: "http", fetch: options.fetch });
1192
+ if (Array.isArray(body)) {
1193
+ const responses = (await Promise.all(body.map((m) => handleJsonRpc(m, ctx)))).filter((r) => r !== null);
1194
+ return json(responses, 200);
1195
+ }
1196
+ const res = await handleJsonRpc(body, ctx);
1197
+ if (res === null) return new Response(null, { status: 202 });
1198
+ return json(res, 200);
1199
+ };
1200
+ }
1201
+
1202
+ export {
1203
+ MdtidyApiError,
1204
+ createMdtidyClient,
1205
+ buildContext,
1206
+ TOOL_CATALOG,
1207
+ DEFERRED_TOOLS,
1208
+ REGISTRY,
1209
+ registerTools,
1210
+ SERVER_INFO,
1211
+ PROTOCOL_VERSION,
1212
+ handleJsonRpc,
1213
+ startStdio,
1214
+ createMcpRouteHandler
1215
+ };
1216
+ //# sourceMappingURL=chunk-TABPKZQW.js.map