@mjquinlan2000/practicepanther-mcp 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/server.js ADDED
@@ -0,0 +1,1779 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ getAccessToken
4
+ } from "./chunk-A6QUURB5.js";
5
+
6
+ // src/server.ts
7
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
8
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
9
+ import { z as z2 } from "zod";
10
+
11
+ // src/client/core/bodySerializer.gen.ts
12
+ var jsonBodySerializer = {
13
+ bodySerializer: (body) => JSON.stringify(body, (_key, value) => typeof value === "bigint" ? value.toString() : value)
14
+ };
15
+
16
+ // src/client/core/params.gen.ts
17
+ var extraPrefixesMap = {
18
+ $body_: "body",
19
+ $headers_: "headers",
20
+ $path_: "path",
21
+ $query_: "query"
22
+ };
23
+ var extraPrefixes = Object.entries(extraPrefixesMap);
24
+
25
+ // src/client/core/serverSentEvents.gen.ts
26
+ var createSseClient = ({
27
+ onRequest,
28
+ onSseError,
29
+ onSseEvent,
30
+ responseTransformer,
31
+ responseValidator,
32
+ sseDefaultRetryDelay,
33
+ sseMaxRetryAttempts,
34
+ sseMaxRetryDelay,
35
+ sseSleepFn,
36
+ url,
37
+ ...options
38
+ }) => {
39
+ let lastEventId;
40
+ const sleep = sseSleepFn ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
41
+ const createStream = async function* () {
42
+ let retryDelay = sseDefaultRetryDelay ?? 3e3;
43
+ let attempt = 0;
44
+ const signal = options.signal ?? new AbortController().signal;
45
+ while (true) {
46
+ if (signal.aborted) break;
47
+ attempt++;
48
+ const headers = options.headers instanceof Headers ? options.headers : new Headers(options.headers);
49
+ if (lastEventId !== void 0) {
50
+ headers.set("Last-Event-ID", lastEventId);
51
+ }
52
+ try {
53
+ const requestInit = {
54
+ redirect: "follow",
55
+ ...options,
56
+ body: options.serializedBody,
57
+ headers,
58
+ signal
59
+ };
60
+ let request = new Request(url, requestInit);
61
+ if (onRequest) {
62
+ request = await onRequest(url, requestInit);
63
+ }
64
+ const _fetch = options.fetch ?? globalThis.fetch;
65
+ const response = await _fetch(request);
66
+ if (!response.ok) throw new Error(`SSE failed: ${response.status} ${response.statusText}`);
67
+ if (!response.body) throw new Error("No body in SSE response");
68
+ const reader = response.body.pipeThrough(new TextDecoderStream()).getReader();
69
+ let buffer = "";
70
+ const abortHandler = () => {
71
+ try {
72
+ reader.cancel();
73
+ } catch {
74
+ }
75
+ };
76
+ signal.addEventListener("abort", abortHandler);
77
+ try {
78
+ while (true) {
79
+ const { done, value } = await reader.read();
80
+ if (done) break;
81
+ buffer += value;
82
+ buffer = buffer.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
83
+ const chunks = buffer.split("\n\n");
84
+ buffer = chunks.pop() ?? "";
85
+ for (const chunk of chunks) {
86
+ const lines = chunk.split("\n");
87
+ const dataLines = [];
88
+ let eventName;
89
+ for (const line of lines) {
90
+ if (line.startsWith("data:")) {
91
+ dataLines.push(line.replace(/^data:\s*/, ""));
92
+ } else if (line.startsWith("event:")) {
93
+ eventName = line.replace(/^event:\s*/, "");
94
+ } else if (line.startsWith("id:")) {
95
+ lastEventId = line.replace(/^id:\s*/, "");
96
+ } else if (line.startsWith("retry:")) {
97
+ const parsed = Number.parseInt(line.replace(/^retry:\s*/, ""), 10);
98
+ if (!Number.isNaN(parsed)) {
99
+ retryDelay = parsed;
100
+ }
101
+ }
102
+ }
103
+ let data;
104
+ let parsedJson = false;
105
+ if (dataLines.length) {
106
+ const rawData = dataLines.join("\n");
107
+ try {
108
+ data = JSON.parse(rawData);
109
+ parsedJson = true;
110
+ } catch {
111
+ data = rawData;
112
+ }
113
+ }
114
+ if (parsedJson) {
115
+ if (responseValidator) {
116
+ await responseValidator(data);
117
+ }
118
+ if (responseTransformer) {
119
+ data = await responseTransformer(data);
120
+ }
121
+ }
122
+ onSseEvent?.({
123
+ data,
124
+ event: eventName,
125
+ id: lastEventId,
126
+ retry: retryDelay
127
+ });
128
+ if (dataLines.length) {
129
+ yield data;
130
+ }
131
+ }
132
+ }
133
+ } finally {
134
+ signal.removeEventListener("abort", abortHandler);
135
+ reader.releaseLock();
136
+ }
137
+ break;
138
+ } catch (error) {
139
+ onSseError?.(error);
140
+ if (sseMaxRetryAttempts !== void 0 && attempt >= sseMaxRetryAttempts) {
141
+ break;
142
+ }
143
+ const backoff = Math.min(retryDelay * 2 ** (attempt - 1), sseMaxRetryDelay ?? 3e4);
144
+ await sleep(backoff);
145
+ }
146
+ }
147
+ };
148
+ const stream = createStream();
149
+ return { stream };
150
+ };
151
+
152
+ // src/client/core/pathSerializer.gen.ts
153
+ var separatorArrayExplode = (style) => {
154
+ switch (style) {
155
+ case "label":
156
+ return ".";
157
+ case "matrix":
158
+ return ";";
159
+ case "simple":
160
+ return ",";
161
+ default:
162
+ return "&";
163
+ }
164
+ };
165
+ var separatorArrayNoExplode = (style) => {
166
+ switch (style) {
167
+ case "form":
168
+ return ",";
169
+ case "pipeDelimited":
170
+ return "|";
171
+ case "spaceDelimited":
172
+ return "%20";
173
+ default:
174
+ return ",";
175
+ }
176
+ };
177
+ var separatorObjectExplode = (style) => {
178
+ switch (style) {
179
+ case "label":
180
+ return ".";
181
+ case "matrix":
182
+ return ";";
183
+ case "simple":
184
+ return ",";
185
+ default:
186
+ return "&";
187
+ }
188
+ };
189
+ var serializeArrayParam = ({
190
+ allowReserved,
191
+ explode,
192
+ name,
193
+ style,
194
+ value
195
+ }) => {
196
+ if (!explode) {
197
+ const joinedValues2 = (allowReserved ? value : value.map((v) => encodeURIComponent(v))).join(separatorArrayNoExplode(style));
198
+ switch (style) {
199
+ case "label":
200
+ return `.${joinedValues2}`;
201
+ case "matrix":
202
+ return `;${name}=${joinedValues2}`;
203
+ case "simple":
204
+ return joinedValues2;
205
+ default:
206
+ return `${name}=${joinedValues2}`;
207
+ }
208
+ }
209
+ const separator = separatorArrayExplode(style);
210
+ const joinedValues = value.map((v) => {
211
+ if (style === "label" || style === "simple") {
212
+ return allowReserved ? v : encodeURIComponent(v);
213
+ }
214
+ return serializePrimitiveParam({
215
+ allowReserved,
216
+ name,
217
+ value: v
218
+ });
219
+ }).join(separator);
220
+ return style === "label" || style === "matrix" ? separator + joinedValues : joinedValues;
221
+ };
222
+ var serializePrimitiveParam = ({
223
+ allowReserved,
224
+ name,
225
+ value
226
+ }) => {
227
+ if (value === void 0 || value === null) {
228
+ return "";
229
+ }
230
+ if (typeof value === "object") {
231
+ throw new Error(
232
+ "Deeply-nested arrays/objects aren\u2019t supported. Provide your own `querySerializer()` to handle these."
233
+ );
234
+ }
235
+ return `${name}=${allowReserved ? value : encodeURIComponent(value)}`;
236
+ };
237
+ var serializeObjectParam = ({
238
+ allowReserved,
239
+ explode,
240
+ name,
241
+ style,
242
+ value,
243
+ valueOnly
244
+ }) => {
245
+ if (value instanceof Date) {
246
+ return valueOnly ? value.toISOString() : `${name}=${value.toISOString()}`;
247
+ }
248
+ if (style !== "deepObject" && !explode) {
249
+ let values = [];
250
+ Object.entries(value).forEach(([key, v]) => {
251
+ values = [...values, key, allowReserved ? v : encodeURIComponent(v)];
252
+ });
253
+ const joinedValues2 = values.join(",");
254
+ switch (style) {
255
+ case "form":
256
+ return `${name}=${joinedValues2}`;
257
+ case "label":
258
+ return `.${joinedValues2}`;
259
+ case "matrix":
260
+ return `;${name}=${joinedValues2}`;
261
+ default:
262
+ return joinedValues2;
263
+ }
264
+ }
265
+ const separator = separatorObjectExplode(style);
266
+ const joinedValues = Object.entries(value).map(
267
+ ([key, v]) => serializePrimitiveParam({
268
+ allowReserved,
269
+ name: style === "deepObject" ? `${name}[${key}]` : key,
270
+ value: v
271
+ })
272
+ ).join(separator);
273
+ return style === "label" || style === "matrix" ? separator + joinedValues : joinedValues;
274
+ };
275
+
276
+ // src/client/core/utils.gen.ts
277
+ var PATH_PARAM_RE = /\{[^{}]+\}/g;
278
+ var defaultPathSerializer = ({ path, url: _url }) => {
279
+ let url = _url;
280
+ const matches = _url.match(PATH_PARAM_RE);
281
+ if (matches) {
282
+ for (const match of matches) {
283
+ let explode = false;
284
+ let name = match.substring(1, match.length - 1);
285
+ let style = "simple";
286
+ if (name.endsWith("*")) {
287
+ explode = true;
288
+ name = name.substring(0, name.length - 1);
289
+ }
290
+ if (name.startsWith(".")) {
291
+ name = name.substring(1);
292
+ style = "label";
293
+ } else if (name.startsWith(";")) {
294
+ name = name.substring(1);
295
+ style = "matrix";
296
+ }
297
+ const value = path[name];
298
+ if (value === void 0 || value === null) {
299
+ continue;
300
+ }
301
+ if (Array.isArray(value)) {
302
+ url = url.replace(match, serializeArrayParam({ explode, name, style, value }));
303
+ continue;
304
+ }
305
+ if (typeof value === "object") {
306
+ url = url.replace(
307
+ match,
308
+ serializeObjectParam({
309
+ explode,
310
+ name,
311
+ style,
312
+ value,
313
+ valueOnly: true
314
+ })
315
+ );
316
+ continue;
317
+ }
318
+ if (style === "matrix") {
319
+ url = url.replace(
320
+ match,
321
+ `;${serializePrimitiveParam({
322
+ name,
323
+ value
324
+ })}`
325
+ );
326
+ continue;
327
+ }
328
+ const replaceValue = encodeURIComponent(
329
+ style === "label" ? `.${value}` : value
330
+ );
331
+ url = url.replace(match, replaceValue);
332
+ }
333
+ }
334
+ return url;
335
+ };
336
+ var getUrl = ({
337
+ baseUrl,
338
+ path,
339
+ query,
340
+ querySerializer,
341
+ url: _url
342
+ }) => {
343
+ const pathUrl = _url.startsWith("/") ? _url : `/${_url}`;
344
+ let url = (baseUrl ?? "") + pathUrl;
345
+ if (path) {
346
+ url = defaultPathSerializer({ path, url });
347
+ }
348
+ let search = query ? querySerializer(query) : "";
349
+ if (search.startsWith("?")) {
350
+ search = search.substring(1);
351
+ }
352
+ if (search) {
353
+ url += `?${search}`;
354
+ }
355
+ return url;
356
+ };
357
+ function getValidRequestBody(options) {
358
+ const hasBody = options.body !== void 0;
359
+ const isSerializedBody = hasBody && options.bodySerializer;
360
+ if (isSerializedBody) {
361
+ if ("serializedBody" in options) {
362
+ const hasSerializedBody = options.serializedBody !== void 0 && options.serializedBody !== "";
363
+ return hasSerializedBody ? options.serializedBody : null;
364
+ }
365
+ return options.body !== "" ? options.body : null;
366
+ }
367
+ if (hasBody) {
368
+ return options.body;
369
+ }
370
+ return void 0;
371
+ }
372
+
373
+ // src/client/core/auth.gen.ts
374
+ var getAuthToken = async (auth, callback) => {
375
+ const token = typeof callback === "function" ? await callback(auth) : callback;
376
+ if (!token) {
377
+ return;
378
+ }
379
+ if (auth.scheme === "bearer") {
380
+ return `Bearer ${token}`;
381
+ }
382
+ if (auth.scheme === "basic") {
383
+ return `Basic ${btoa(token)}`;
384
+ }
385
+ return token;
386
+ };
387
+
388
+ // src/client/client/utils.gen.ts
389
+ var createQuerySerializer = ({
390
+ parameters = {},
391
+ ...args
392
+ } = {}) => {
393
+ const querySerializer = (queryParams) => {
394
+ const search = [];
395
+ if (queryParams && typeof queryParams === "object") {
396
+ for (const name in queryParams) {
397
+ const value = queryParams[name];
398
+ if (value === void 0 || value === null) {
399
+ continue;
400
+ }
401
+ const options = parameters[name] || args;
402
+ if (Array.isArray(value)) {
403
+ const serializedArray = serializeArrayParam({
404
+ allowReserved: options.allowReserved,
405
+ explode: true,
406
+ name,
407
+ style: "form",
408
+ value,
409
+ ...options.array
410
+ });
411
+ if (serializedArray) search.push(serializedArray);
412
+ } else if (typeof value === "object") {
413
+ const serializedObject = serializeObjectParam({
414
+ allowReserved: options.allowReserved,
415
+ explode: true,
416
+ name,
417
+ style: "deepObject",
418
+ value,
419
+ ...options.object
420
+ });
421
+ if (serializedObject) search.push(serializedObject);
422
+ } else {
423
+ const serializedPrimitive = serializePrimitiveParam({
424
+ allowReserved: options.allowReserved,
425
+ name,
426
+ value
427
+ });
428
+ if (serializedPrimitive) search.push(serializedPrimitive);
429
+ }
430
+ }
431
+ }
432
+ return search.join("&");
433
+ };
434
+ return querySerializer;
435
+ };
436
+ var getParseAs = (contentType) => {
437
+ if (!contentType) {
438
+ return "stream";
439
+ }
440
+ const cleanContent = contentType.split(";")[0]?.trim();
441
+ if (!cleanContent) {
442
+ return;
443
+ }
444
+ if (cleanContent.startsWith("application/json") || cleanContent.endsWith("+json")) {
445
+ return "json";
446
+ }
447
+ if (cleanContent === "multipart/form-data") {
448
+ return "formData";
449
+ }
450
+ if (["application/", "audio/", "image/", "video/"].some((type) => cleanContent.startsWith(type))) {
451
+ return "blob";
452
+ }
453
+ if (cleanContent.startsWith("text/")) {
454
+ return "text";
455
+ }
456
+ return;
457
+ };
458
+ var checkForExistence = (options, name) => {
459
+ if (!name) {
460
+ return false;
461
+ }
462
+ if (options.headers.has(name) || options.query?.[name] || options.headers.get("Cookie")?.includes(`${name}=`)) {
463
+ return true;
464
+ }
465
+ return false;
466
+ };
467
+ var setAuthParams = async ({
468
+ security,
469
+ ...options
470
+ }) => {
471
+ for (const auth of security) {
472
+ if (checkForExistence(options, auth.name)) {
473
+ continue;
474
+ }
475
+ const token = await getAuthToken(auth, options.auth);
476
+ if (!token) {
477
+ continue;
478
+ }
479
+ const name = auth.name ?? "Authorization";
480
+ switch (auth.in) {
481
+ case "query":
482
+ if (!options.query) {
483
+ options.query = {};
484
+ }
485
+ options.query[name] = token;
486
+ break;
487
+ case "cookie":
488
+ options.headers.append("Cookie", `${name}=${token}`);
489
+ break;
490
+ case "header":
491
+ default:
492
+ options.headers.set(name, token);
493
+ break;
494
+ }
495
+ }
496
+ };
497
+ var buildUrl = (options) => getUrl({
498
+ baseUrl: options.baseUrl,
499
+ path: options.path,
500
+ query: options.query,
501
+ querySerializer: typeof options.querySerializer === "function" ? options.querySerializer : createQuerySerializer(options.querySerializer),
502
+ url: options.url
503
+ });
504
+ var mergeConfigs = (a, b) => {
505
+ const config = { ...a, ...b };
506
+ if (config.baseUrl?.endsWith("/")) {
507
+ config.baseUrl = config.baseUrl.substring(0, config.baseUrl.length - 1);
508
+ }
509
+ config.headers = mergeHeaders(a.headers, b.headers);
510
+ return config;
511
+ };
512
+ var headersEntries = (headers) => {
513
+ const entries = [];
514
+ headers.forEach((value, key) => {
515
+ entries.push([key, value]);
516
+ });
517
+ return entries;
518
+ };
519
+ var mergeHeaders = (...headers) => {
520
+ const mergedHeaders = new Headers();
521
+ for (const header of headers) {
522
+ if (!header) {
523
+ continue;
524
+ }
525
+ const iterator = header instanceof Headers ? headersEntries(header) : Object.entries(header);
526
+ for (const [key, value] of iterator) {
527
+ if (value === null) {
528
+ mergedHeaders.delete(key);
529
+ } else if (Array.isArray(value)) {
530
+ for (const v of value) {
531
+ mergedHeaders.append(key, v);
532
+ }
533
+ } else if (value !== void 0) {
534
+ mergedHeaders.set(
535
+ key,
536
+ typeof value === "object" ? JSON.stringify(value) : value
537
+ );
538
+ }
539
+ }
540
+ }
541
+ return mergedHeaders;
542
+ };
543
+ var Interceptors = class {
544
+ fns = [];
545
+ clear() {
546
+ this.fns = [];
547
+ }
548
+ eject(id) {
549
+ const index = this.getInterceptorIndex(id);
550
+ if (this.fns[index]) {
551
+ this.fns[index] = null;
552
+ }
553
+ }
554
+ exists(id) {
555
+ const index = this.getInterceptorIndex(id);
556
+ return Boolean(this.fns[index]);
557
+ }
558
+ getInterceptorIndex(id) {
559
+ if (typeof id === "number") {
560
+ return this.fns[id] ? id : -1;
561
+ }
562
+ return this.fns.indexOf(id);
563
+ }
564
+ update(id, fn) {
565
+ const index = this.getInterceptorIndex(id);
566
+ if (this.fns[index]) {
567
+ this.fns[index] = fn;
568
+ return id;
569
+ }
570
+ return false;
571
+ }
572
+ use(fn) {
573
+ this.fns.push(fn);
574
+ return this.fns.length - 1;
575
+ }
576
+ };
577
+ var createInterceptors = () => ({
578
+ error: new Interceptors(),
579
+ request: new Interceptors(),
580
+ response: new Interceptors()
581
+ });
582
+ var defaultQuerySerializer = createQuerySerializer({
583
+ allowReserved: false,
584
+ array: {
585
+ explode: true,
586
+ style: "form"
587
+ },
588
+ object: {
589
+ explode: true,
590
+ style: "deepObject"
591
+ }
592
+ });
593
+ var defaultHeaders = {
594
+ "Content-Type": "application/json"
595
+ };
596
+ var createConfig = (override = {}) => ({
597
+ ...jsonBodySerializer,
598
+ headers: defaultHeaders,
599
+ parseAs: "auto",
600
+ querySerializer: defaultQuerySerializer,
601
+ ...override
602
+ });
603
+
604
+ // src/client/client/client.gen.ts
605
+ var createClient = (config = {}) => {
606
+ let _config = mergeConfigs(createConfig(), config);
607
+ const getConfig = () => ({ ..._config });
608
+ const setConfig = (config2) => {
609
+ _config = mergeConfigs(_config, config2);
610
+ return getConfig();
611
+ };
612
+ const interceptors = createInterceptors();
613
+ const beforeRequest = async (options) => {
614
+ const opts = {
615
+ ..._config,
616
+ ...options,
617
+ fetch: options.fetch ?? _config.fetch ?? globalThis.fetch,
618
+ headers: mergeHeaders(_config.headers, options.headers),
619
+ serializedBody: void 0
620
+ };
621
+ if (opts.security) {
622
+ await setAuthParams({
623
+ ...opts,
624
+ security: opts.security
625
+ });
626
+ }
627
+ if (opts.requestValidator) {
628
+ await opts.requestValidator(opts);
629
+ }
630
+ if (opts.body !== void 0 && opts.bodySerializer) {
631
+ opts.serializedBody = opts.bodySerializer(opts.body);
632
+ }
633
+ if (opts.body === void 0 || opts.serializedBody === "") {
634
+ opts.headers.delete("Content-Type");
635
+ }
636
+ const url = buildUrl(opts);
637
+ return { opts, url };
638
+ };
639
+ const request = async (options) => {
640
+ const { opts, url } = await beforeRequest(options);
641
+ const requestInit = {
642
+ redirect: "follow",
643
+ ...opts,
644
+ body: getValidRequestBody(opts)
645
+ };
646
+ let request2 = new Request(url, requestInit);
647
+ for (const fn of interceptors.request.fns) {
648
+ if (fn) {
649
+ request2 = await fn(request2, opts);
650
+ }
651
+ }
652
+ const _fetch = opts.fetch;
653
+ let response;
654
+ try {
655
+ response = await _fetch(request2);
656
+ } catch (error2) {
657
+ let finalError2 = error2;
658
+ for (const fn of interceptors.error.fns) {
659
+ if (fn) {
660
+ finalError2 = await fn(error2, void 0, request2, opts);
661
+ }
662
+ }
663
+ finalError2 = finalError2 || {};
664
+ if (opts.throwOnError) {
665
+ throw finalError2;
666
+ }
667
+ return opts.responseStyle === "data" ? void 0 : {
668
+ error: finalError2,
669
+ request: request2,
670
+ response: void 0
671
+ };
672
+ }
673
+ for (const fn of interceptors.response.fns) {
674
+ if (fn) {
675
+ response = await fn(response, request2, opts);
676
+ }
677
+ }
678
+ const result = {
679
+ request: request2,
680
+ response
681
+ };
682
+ if (response.ok) {
683
+ const parseAs = (opts.parseAs === "auto" ? getParseAs(response.headers.get("Content-Type")) : opts.parseAs) ?? "json";
684
+ if (response.status === 204 || response.headers.get("Content-Length") === "0") {
685
+ let emptyData;
686
+ switch (parseAs) {
687
+ case "arrayBuffer":
688
+ case "blob":
689
+ case "text":
690
+ emptyData = await response[parseAs]();
691
+ break;
692
+ case "formData":
693
+ emptyData = new FormData();
694
+ break;
695
+ case "stream":
696
+ emptyData = response.body;
697
+ break;
698
+ case "json":
699
+ default:
700
+ emptyData = {};
701
+ break;
702
+ }
703
+ return opts.responseStyle === "data" ? emptyData : {
704
+ data: emptyData,
705
+ ...result
706
+ };
707
+ }
708
+ let data;
709
+ switch (parseAs) {
710
+ case "arrayBuffer":
711
+ case "blob":
712
+ case "formData":
713
+ case "text":
714
+ data = await response[parseAs]();
715
+ break;
716
+ case "json": {
717
+ const text = await response.text();
718
+ data = text ? JSON.parse(text) : {};
719
+ break;
720
+ }
721
+ case "stream":
722
+ return opts.responseStyle === "data" ? response.body : {
723
+ data: response.body,
724
+ ...result
725
+ };
726
+ }
727
+ if (parseAs === "json") {
728
+ if (opts.responseValidator) {
729
+ await opts.responseValidator(data);
730
+ }
731
+ if (opts.responseTransformer) {
732
+ data = await opts.responseTransformer(data);
733
+ }
734
+ }
735
+ return opts.responseStyle === "data" ? data : {
736
+ data,
737
+ ...result
738
+ };
739
+ }
740
+ const textError = await response.text();
741
+ let jsonError;
742
+ try {
743
+ jsonError = JSON.parse(textError);
744
+ } catch {
745
+ }
746
+ const error = jsonError ?? textError;
747
+ let finalError = error;
748
+ for (const fn of interceptors.error.fns) {
749
+ if (fn) {
750
+ finalError = await fn(error, response, request2, opts);
751
+ }
752
+ }
753
+ finalError = finalError || {};
754
+ if (opts.throwOnError) {
755
+ throw finalError;
756
+ }
757
+ return opts.responseStyle === "data" ? void 0 : {
758
+ error: finalError,
759
+ ...result
760
+ };
761
+ };
762
+ const makeMethodFn = (method) => (options) => request({ ...options, method });
763
+ const makeSseFn = (method) => async (options) => {
764
+ const { opts, url } = await beforeRequest(options);
765
+ return createSseClient({
766
+ ...opts,
767
+ body: opts.body,
768
+ headers: opts.headers,
769
+ method,
770
+ onRequest: async (url2, init) => {
771
+ let request2 = new Request(url2, init);
772
+ for (const fn of interceptors.request.fns) {
773
+ if (fn) {
774
+ request2 = await fn(request2, opts);
775
+ }
776
+ }
777
+ return request2;
778
+ },
779
+ serializedBody: getValidRequestBody(opts),
780
+ url
781
+ });
782
+ };
783
+ const _buildUrl = (options) => buildUrl({ ..._config, ...options });
784
+ return {
785
+ buildUrl: _buildUrl,
786
+ connect: makeMethodFn("CONNECT"),
787
+ delete: makeMethodFn("DELETE"),
788
+ get: makeMethodFn("GET"),
789
+ getConfig,
790
+ head: makeMethodFn("HEAD"),
791
+ interceptors,
792
+ options: makeMethodFn("OPTIONS"),
793
+ patch: makeMethodFn("PATCH"),
794
+ post: makeMethodFn("POST"),
795
+ put: makeMethodFn("PUT"),
796
+ request,
797
+ setConfig,
798
+ sse: {
799
+ connect: makeSseFn("CONNECT"),
800
+ delete: makeSseFn("DELETE"),
801
+ get: makeSseFn("GET"),
802
+ head: makeSseFn("HEAD"),
803
+ options: makeSseFn("OPTIONS"),
804
+ patch: makeSseFn("PATCH"),
805
+ post: makeSseFn("POST"),
806
+ put: makeSseFn("PUT"),
807
+ trace: makeSseFn("TRACE")
808
+ },
809
+ trace: makeMethodFn("TRACE")
810
+ };
811
+ };
812
+
813
+ // src/client/client.gen.ts
814
+ var client = createClient(createConfig({ baseUrl: "https://app.practicepanther.com" }));
815
+
816
+ // src/pp.ts
817
+ client.setConfig({
818
+ baseUrl: "https://app.practicepanther.com",
819
+ auth: async () => getAccessToken()
820
+ });
821
+
822
+ // src/client/sdk.gen.ts
823
+ var accountsGetAccount = (options) => (options.client ?? client).get({
824
+ security: [{ scheme: "bearer", type: "http" }],
825
+ url: "/api/v2/accounts/{id}",
826
+ ...options
827
+ });
828
+ var accountsGetAccounts = (options) => (options?.client ?? client).get({
829
+ security: [{ scheme: "bearer", type: "http" }],
830
+ url: "/api/v2/accounts",
831
+ ...options
832
+ });
833
+ var bankAccountsGetBankAccount = (options) => (options.client ?? client).get({
834
+ security: [{ scheme: "bearer", type: "http" }],
835
+ url: "/api/v2/bankaccounts/{id}",
836
+ ...options
837
+ });
838
+ var bankAccountsGetBankAccounts = (options) => (options?.client ?? client).get({
839
+ security: [{ scheme: "bearer", type: "http" }],
840
+ url: "/api/v2/bankaccounts",
841
+ ...options
842
+ });
843
+ var callLogsGetCallLog = (options) => (options.client ?? client).get({
844
+ security: [{ scheme: "bearer", type: "http" }],
845
+ url: "/api/v2/calllogs/{id}",
846
+ ...options
847
+ });
848
+ var callLogsGetCallLogs = (options) => (options?.client ?? client).get({
849
+ security: [{ scheme: "bearer", type: "http" }],
850
+ url: "/api/v2/calllogs",
851
+ ...options
852
+ });
853
+ var contactsGetContact = (options) => (options.client ?? client).get({
854
+ security: [{ scheme: "bearer", type: "http" }],
855
+ url: "/api/v2/contacts/{id}",
856
+ ...options
857
+ });
858
+ var contactsGetContacts = (options) => (options?.client ?? client).get({
859
+ security: [{ scheme: "bearer", type: "http" }],
860
+ url: "/api/v2/contacts",
861
+ ...options
862
+ });
863
+ var customFieldsGetCustomFieldsForAccount = (options) => (options?.client ?? client).get({
864
+ security: [{ scheme: "bearer", type: "http" }],
865
+ url: "/api/v2/customfields/company",
866
+ ...options
867
+ });
868
+ var customFieldsGetCustomFieldsForMatter = (options) => (options?.client ?? client).get({
869
+ security: [{ scheme: "bearer", type: "http" }],
870
+ url: "/api/v2/customfields/matter",
871
+ ...options
872
+ });
873
+ var customFieldsGetCustomFieldsForContact = (options) => (options?.client ?? client).get({
874
+ security: [{ scheme: "bearer", type: "http" }],
875
+ url: "/api/v2/customfields/contact",
876
+ ...options
877
+ });
878
+ var customFieldsGetCustomField = (options) => (options.client ?? client).get({
879
+ security: [{ scheme: "bearer", type: "http" }],
880
+ url: "/api/v2/customfields/{id}",
881
+ ...options
882
+ });
883
+ var emailsGetEmail = (options) => (options.client ?? client).get({
884
+ security: [{ scheme: "bearer", type: "http" }],
885
+ url: "/api/v2/emails/{id}",
886
+ ...options
887
+ });
888
+ var emailsGetEmails = (options) => (options?.client ?? client).get({
889
+ security: [{ scheme: "bearer", type: "http" }],
890
+ url: "/api/v2/emails",
891
+ ...options
892
+ });
893
+ var eventsGetEvent = (options) => (options.client ?? client).get({
894
+ security: [{ scheme: "bearer", type: "http" }],
895
+ url: "/api/v2/events/{id}",
896
+ ...options
897
+ });
898
+ var eventsGetEvents = (options) => (options?.client ?? client).get({
899
+ security: [{ scheme: "bearer", type: "http" }],
900
+ url: "/api/v2/events",
901
+ ...options
902
+ });
903
+ var expenseCategoriesGetExpenseCategory = (options) => (options.client ?? client).get({
904
+ security: [{ scheme: "bearer", type: "http" }],
905
+ url: "/api/v2/ExpenseCategories/{id}",
906
+ ...options
907
+ });
908
+ var expenseCategoriesGetExpenseCategories = (options) => (options?.client ?? client).get({
909
+ security: [{ scheme: "bearer", type: "http" }],
910
+ url: "/api/v2/ExpenseCategories",
911
+ ...options
912
+ });
913
+ var expensesGetExpense = (options) => (options.client ?? client).get({
914
+ security: [{ scheme: "bearer", type: "http" }],
915
+ url: "/api/v2/Expenses/{id}",
916
+ ...options
917
+ });
918
+ var expensesGetExpensess = (options) => (options?.client ?? client).get({
919
+ security: [{ scheme: "bearer", type: "http" }],
920
+ url: "/api/v2/Expenses",
921
+ ...options
922
+ });
923
+ var filesGetFile = (options) => (options.client ?? client).get({
924
+ security: [{ scheme: "bearer", type: "http" }],
925
+ url: "/api/v2/files/{id}",
926
+ ...options
927
+ });
928
+ var filesDownloadFile = (options) => (options.client ?? client).get({
929
+ security: [{ scheme: "bearer", type: "http" }],
930
+ url: "/api/v2/files/download/{id}",
931
+ ...options
932
+ });
933
+ var filesGetFiles = (options) => (options?.client ?? client).get({
934
+ security: [{ scheme: "bearer", type: "http" }],
935
+ url: "/api/v2/files",
936
+ ...options
937
+ });
938
+ var flatFeesGetFlatFee = (options) => (options.client ?? client).get({
939
+ security: [{ scheme: "bearer", type: "http" }],
940
+ url: "/api/v2/flatfees/{id}",
941
+ ...options
942
+ });
943
+ var flatFeesGetFlatFees = (options) => (options?.client ?? client).get({
944
+ security: [{ scheme: "bearer", type: "http" }],
945
+ url: "/api/v2/flatfees",
946
+ ...options
947
+ });
948
+ var invoicesGetInvoice = (options) => (options.client ?? client).get({
949
+ security: [{ scheme: "bearer", type: "http" }],
950
+ url: "/api/v2/invoices/{id}",
951
+ ...options
952
+ });
953
+ var invoicesGetInvoices = (options) => (options?.client ?? client).get({
954
+ security: [{ scheme: "bearer", type: "http" }],
955
+ url: "/api/v2/invoices",
956
+ ...options
957
+ });
958
+ var itemsGetItem = (options) => (options.client ?? client).get({
959
+ security: [{ scheme: "bearer", type: "http" }],
960
+ url: "/api/v2/Items/{id}",
961
+ ...options
962
+ });
963
+ var itemsGetItems = (options) => (options?.client ?? client).get({
964
+ security: [{ scheme: "bearer", type: "http" }],
965
+ url: "/api/v2/Items",
966
+ ...options
967
+ });
968
+ var mattersGetMatter = (options) => (options.client ?? client).get({
969
+ security: [{ scheme: "bearer", type: "http" }],
970
+ url: "/api/v2/matters/{id}",
971
+ ...options
972
+ });
973
+ var mattersGetMatters = (options) => (options?.client ?? client).get({
974
+ security: [{ scheme: "bearer", type: "http" }],
975
+ url: "/api/v2/matters",
976
+ ...options
977
+ });
978
+ var messagesGetMessagesAsync = (options) => (options?.client ?? client).get({
979
+ security: [{ scheme: "bearer", type: "http" }],
980
+ url: "/api/v2/messages",
981
+ ...options
982
+ });
983
+ var notesGetNote = (options) => (options.client ?? client).get({
984
+ security: [{ scheme: "bearer", type: "http" }],
985
+ url: "/api/v2/notes/{id}",
986
+ ...options
987
+ });
988
+ var notesGetNotes = (options) => (options?.client ?? client).get({
989
+ security: [{ scheme: "bearer", type: "http" }],
990
+ url: "/api/v2/notes",
991
+ ...options
992
+ });
993
+ var paymentsGetPayment = (options) => (options.client ?? client).get({
994
+ security: [{ scheme: "bearer", type: "http" }],
995
+ url: "/api/v2/payments/{id}",
996
+ ...options
997
+ });
998
+ var paymentsGetPayments = (options) => (options?.client ?? client).get({
999
+ security: [{ scheme: "bearer", type: "http" }],
1000
+ url: "/api/v2/payments",
1001
+ ...options
1002
+ });
1003
+ var relationshipsGetRelationship = (options) => (options.client ?? client).get({
1004
+ security: [{ scheme: "bearer", type: "http" }],
1005
+ url: "/api/v2/relationships/{id}",
1006
+ ...options
1007
+ });
1008
+ var relationshipsGetRelationships = (options) => (options?.client ?? client).get({
1009
+ security: [{ scheme: "bearer", type: "http" }],
1010
+ url: "/api/v2/relationships",
1011
+ ...options
1012
+ });
1013
+ var tagsGetTagsForAccounts = (options) => (options?.client ?? client).get({
1014
+ security: [{ scheme: "bearer", type: "http" }],
1015
+ url: "/api/v2/tags/account",
1016
+ ...options
1017
+ });
1018
+ var tagsGetTagsForProjects = (options) => (options?.client ?? client).get({
1019
+ security: [{ scheme: "bearer", type: "http" }],
1020
+ url: "/api/v2/tags/matter",
1021
+ ...options
1022
+ });
1023
+ var tagsGetTagsForActivities = (options) => (options?.client ?? client).get({
1024
+ security: [{ scheme: "bearer", type: "http" }],
1025
+ url: "/api/v2/tags/activity",
1026
+ ...options
1027
+ });
1028
+ var tasksGetTask = (options) => (options.client ?? client).get({
1029
+ security: [{ scheme: "bearer", type: "http" }],
1030
+ url: "/api/v2/tasks/{id}",
1031
+ ...options
1032
+ });
1033
+ var tasksGetTasks = (options) => (options?.client ?? client).get({
1034
+ security: [{ scheme: "bearer", type: "http" }],
1035
+ url: "/api/v2/tasks",
1036
+ ...options
1037
+ });
1038
+ var timeEntriesGetTimeEntry = (options) => (options.client ?? client).get({
1039
+ security: [{ scheme: "bearer", type: "http" }],
1040
+ url: "/api/v2/timeentries/{id}",
1041
+ ...options
1042
+ });
1043
+ var timeEntriesGetTimeEntrys = (options) => (options?.client ?? client).get({
1044
+ security: [{ scheme: "bearer", type: "http" }],
1045
+ url: "/api/v2/timeentries",
1046
+ ...options
1047
+ });
1048
+ var usersMe = (options) => (options?.client ?? client).get({
1049
+ security: [{ scheme: "bearer", type: "http" }],
1050
+ url: "/api/v2/users/me",
1051
+ ...options
1052
+ });
1053
+ var usersGetUser = (options) => (options.client ?? client).get({
1054
+ security: [{ scheme: "bearer", type: "http" }],
1055
+ url: "/api/v2/users/{id}",
1056
+ ...options
1057
+ });
1058
+ var usersGetUsers = (options) => (options?.client ?? client).get({
1059
+ security: [{ scheme: "bearer", type: "http" }],
1060
+ url: "/api/v2/users",
1061
+ ...options
1062
+ });
1063
+
1064
+ // src/schemas.ts
1065
+ import { readFileSync } from "fs";
1066
+ import { dirname, join } from "path";
1067
+ import { fileURLToPath } from "url";
1068
+ import { z } from "zod";
1069
+ var __dirname = dirname(fileURLToPath(import.meta.url));
1070
+ var spec = JSON.parse(
1071
+ readFileSync(join(__dirname, "..", "openapi.json"), "utf8")
1072
+ );
1073
+ var defs = spec.components.schemas;
1074
+ var cache = /* @__PURE__ */ new Map();
1075
+ function buildProp(prop) {
1076
+ if (prop.$ref) {
1077
+ const name = prop.$ref.split("/").pop();
1078
+ if (name) return buildSchema(name);
1079
+ }
1080
+ if (prop.type === "array" && prop.items) {
1081
+ return z.array(buildProp(prop.items));
1082
+ }
1083
+ if (prop.type === "integer" || prop.type === "number") return z.number();
1084
+ if (prop.type === "boolean") return z.boolean();
1085
+ return z.string();
1086
+ }
1087
+ function buildSchema(name) {
1088
+ const cached = cache.get(name);
1089
+ if (cached) return cached;
1090
+ const def = defs[name];
1091
+ const shape = {};
1092
+ for (const [key, prop] of Object.entries(def?.properties ?? {})) {
1093
+ shape[key] = buildProp(prop).nullable().optional();
1094
+ }
1095
+ const schema = z.looseObject(shape);
1096
+ cache.set(name, schema);
1097
+ return schema;
1098
+ }
1099
+ for (const name of Object.keys(defs)) buildSchema(name);
1100
+ function get(name) {
1101
+ const s = cache.get(name);
1102
+ if (!s) throw new Error(`Schema ${name} not found`);
1103
+ return s;
1104
+ }
1105
+ var AccountSchema = get("Account");
1106
+ var AccountReferenceSchema = get("AccountReference");
1107
+ var ActivityReferenceSchema = get("ActivityReference");
1108
+ var BankAccountSchema = get("BankAccount");
1109
+ var CallLogSchema = get("CallLog");
1110
+ var ContactSchema = get("Contact");
1111
+ var ContactReferenceSchema = get("ContactReference");
1112
+ var CustomFieldSchema = get("CustomField");
1113
+ var CustomFieldRefSchema = get("CustomFieldRef");
1114
+ var CustomFieldValueSchema = get("CustomFieldValue");
1115
+ var EmailSchema = get("Email");
1116
+ var EmailAddressSchema = get("EmailAddress");
1117
+ var EventSchema = get("Event");
1118
+ var ExpenseCategorySchema = get("ExpenseCategory");
1119
+ var ExpenseSchema = get("Expense");
1120
+ var FileSchema = get("File");
1121
+ var FileReferenceSchema = get("FileReference");
1122
+ var FlatFeeSchema = get("FlatFee");
1123
+ var InvoiceSchema = get("Invoice");
1124
+ var InvoiceLineItemSchema = get("InvoiceLineItem");
1125
+ var ItemSchema = get("Item");
1126
+ var ItemReferenceSchema = get("ItemReference");
1127
+ var MatterSchema = get("Matter");
1128
+ var MatterReferenceSchema = get("MatterReference");
1129
+ var MessageSchema = get("Message");
1130
+ var NoteSchema = get("Note");
1131
+ var PaymentSchema = get("Payment");
1132
+ var PaymentDetailSchema = get("Payment_Detail");
1133
+ var RelationshipSchema = get("Relationship");
1134
+ var TagSchema = get("Tag");
1135
+ var TaskSchema = get("Task");
1136
+ var TimeEntrySchema = get("TimeEntry");
1137
+ var UserSchema = get("User");
1138
+ var UserReferenceSchema = get("UserReference");
1139
+ function listOf(schema) {
1140
+ return z.looseObject({ items: z.array(schema) });
1141
+ }
1142
+
1143
+ // src/server.ts
1144
+ var server = new McpServer(
1145
+ {
1146
+ name: "practicepanther",
1147
+ version: "1.0.0"
1148
+ },
1149
+ {
1150
+ instructions: [
1151
+ "PracticePanther is a legal practice management system.",
1152
+ "IMPORTANT: The API does not support pagination.",
1153
+ "List endpoints return ALL matching records, which can be very large.",
1154
+ "Always constrain list calls with filters (date ranges, account/matter IDs, tags, etc.) to avoid returning excessive data.",
1155
+ "Prefer using created_since/updated_since or date_from/date_to to narrow results.",
1156
+ "If looking for a specific record, use a get-by-id tool instead of listing and filtering client-side."
1157
+ ].join(" ")
1158
+ }
1159
+ );
1160
+ function cleanQuery(q) {
1161
+ return Object.fromEntries(
1162
+ Object.entries(q).filter(([, v]) => v !== void 0)
1163
+ );
1164
+ }
1165
+ function err(e) {
1166
+ const msg = e instanceof Error ? e.message : String(e);
1167
+ return {
1168
+ content: [{ type: "text", text: `Error: ${msg}` }],
1169
+ isError: true
1170
+ };
1171
+ }
1172
+ var tools = [
1173
+ // ── Accounts ──
1174
+ {
1175
+ name: "get_account",
1176
+ description: "Get a single account (company or individual) by ID. Returns contacts, tags, custom fields, and assigned users.",
1177
+ sdkFn: accountsGetAccount,
1178
+ schema: AccountSchema,
1179
+ pathParams: { id: "Account ID" }
1180
+ },
1181
+ {
1182
+ name: "list_accounts",
1183
+ description: "List accounts with optional filters. An account represents one or more contacts (e.g. a company).",
1184
+ sdkFn: accountsGetAccounts,
1185
+ schema: AccountSchema,
1186
+ isList: true,
1187
+ queryParams: {
1188
+ assigned_to_user_id: z2.string().optional().describe("Filter by assigned user ID"),
1189
+ created_since: z2.string().optional().describe("ISO date \u2014 return records created after this date"),
1190
+ updated_since: z2.string().optional().describe("ISO date \u2014 return records updated after this date"),
1191
+ search_text: z2.string().optional().describe("Search text"),
1192
+ account_tag: z2.string().optional().describe("Filter by account tag")
1193
+ }
1194
+ },
1195
+ // ── Bank Accounts ──
1196
+ {
1197
+ name: "get_bank_account",
1198
+ description: "Get a single bank account (operating, trust, or credit card) by ID.",
1199
+ sdkFn: bankAccountsGetBankAccount,
1200
+ schema: BankAccountSchema,
1201
+ pathParams: { id: "Bank Account ID" }
1202
+ },
1203
+ {
1204
+ name: "list_bank_accounts",
1205
+ description: "List all bank accounts.",
1206
+ sdkFn: bankAccountsGetBankAccounts,
1207
+ schema: BankAccountSchema,
1208
+ isList: true,
1209
+ queryParams: {
1210
+ created_since: z2.string().optional().describe("ISO date \u2014 return records created after this date"),
1211
+ updated_since: z2.string().optional().describe("ISO date \u2014 return records updated after this date")
1212
+ }
1213
+ },
1214
+ // ── Call Logs ──
1215
+ {
1216
+ name: "get_call_log",
1217
+ description: "Get a single call log entry by ID.",
1218
+ sdkFn: callLogsGetCallLog,
1219
+ schema: CallLogSchema,
1220
+ pathParams: { id: "Call Log ID" }
1221
+ },
1222
+ {
1223
+ name: "list_call_logs",
1224
+ description: "List call log entries with optional filters by account, matter, user, date range, or tag.",
1225
+ sdkFn: callLogsGetCallLogs,
1226
+ schema: CallLogSchema,
1227
+ isList: true,
1228
+ queryParams: {
1229
+ assigned_to_user_id: z2.string().optional().describe("Filter by assigned user ID"),
1230
+ account_id: z2.string().optional().describe("Filter by account ID"),
1231
+ matter_id: z2.string().optional().describe("Filter by matter ID"),
1232
+ created_since: z2.string().optional().describe("ISO date \u2014 return records created after this date"),
1233
+ updated_since: z2.string().optional().describe("ISO date \u2014 return records updated after this date"),
1234
+ date_from: z2.string().optional().describe("ISO date \u2014 filter from this date"),
1235
+ date_to: z2.string().optional().describe("ISO date \u2014 filter to this date"),
1236
+ activity_tag: z2.string().optional().describe("Filter by activity tag")
1237
+ }
1238
+ },
1239
+ // ── Contacts ──
1240
+ {
1241
+ name: "get_contact",
1242
+ description: "Get a single contact by ID. Each account can have multiple contacts; one is the primary.",
1243
+ sdkFn: contactsGetContact,
1244
+ schema: ContactSchema,
1245
+ pathParams: { id: "Contact ID" }
1246
+ },
1247
+ {
1248
+ name: "list_contacts",
1249
+ description: "List contacts with optional filters by account, status, user, search text, or company.",
1250
+ sdkFn: contactsGetContacts,
1251
+ schema: ContactSchema,
1252
+ isList: true,
1253
+ queryParams: {
1254
+ assigned_to_user_id: z2.string().optional().describe("Filter by assigned user ID"),
1255
+ account_id: z2.string().optional().describe("Filter by account ID"),
1256
+ status: z2.enum(["Active", "Archived"]).optional().describe("Filter by status"),
1257
+ created_since: z2.string().optional().describe("ISO date \u2014 return records created after this date"),
1258
+ updated_since: z2.string().optional().describe("ISO date \u2014 return records updated after this date"),
1259
+ search_text: z2.string().optional().describe("Search text"),
1260
+ account_tag: z2.string().optional().describe("Filter by account tag"),
1261
+ company_name: z2.string().optional().describe("Filter by company name")
1262
+ }
1263
+ },
1264
+ // ── Custom Fields ──
1265
+ {
1266
+ name: "get_custom_field",
1267
+ description: "Get a single custom field definition by ID.",
1268
+ sdkFn: customFieldsGetCustomField,
1269
+ schema: CustomFieldSchema,
1270
+ pathParams: { id: "Custom Field ID" }
1271
+ },
1272
+ {
1273
+ name: "list_custom_fields_for_company",
1274
+ description: "List custom field definitions for companies (accounts).",
1275
+ sdkFn: customFieldsGetCustomFieldsForAccount,
1276
+ schema: CustomFieldSchema,
1277
+ isList: true,
1278
+ queryParams: {
1279
+ created_since: z2.string().optional().describe("ISO date \u2014 return records created after this date"),
1280
+ updated_since: z2.string().optional().describe("ISO date \u2014 return records updated after this date")
1281
+ }
1282
+ },
1283
+ {
1284
+ name: "list_custom_fields_for_matter",
1285
+ description: "List custom field definitions for matters.",
1286
+ sdkFn: customFieldsGetCustomFieldsForMatter,
1287
+ schema: CustomFieldSchema,
1288
+ isList: true,
1289
+ queryParams: {
1290
+ created_since: z2.string().optional().describe("ISO date \u2014 return records created after this date"),
1291
+ updated_since: z2.string().optional().describe("ISO date \u2014 return records updated after this date")
1292
+ }
1293
+ },
1294
+ {
1295
+ name: "list_custom_fields_for_contact",
1296
+ description: "List custom field definitions for contacts.",
1297
+ sdkFn: customFieldsGetCustomFieldsForContact,
1298
+ schema: CustomFieldSchema,
1299
+ isList: true,
1300
+ queryParams: {
1301
+ created_since: z2.string().optional().describe("ISO date \u2014 return records created after this date"),
1302
+ updated_since: z2.string().optional().describe("ISO date \u2014 return records updated after this date")
1303
+ }
1304
+ },
1305
+ // ── Emails ──
1306
+ {
1307
+ name: "get_email",
1308
+ description: "Get a single email by ID. Returns full HTML body when fetched individually.",
1309
+ sdkFn: emailsGetEmail,
1310
+ schema: EmailSchema,
1311
+ pathParams: { id: "Email ID" }
1312
+ },
1313
+ {
1314
+ name: "list_emails",
1315
+ description: "List emails with optional filters by account, matter, user, tag, or external message ID.",
1316
+ sdkFn: emailsGetEmails,
1317
+ schema: EmailSchema,
1318
+ isList: true,
1319
+ queryParams: {
1320
+ assigned_to_user_id: z2.string().optional().describe("Filter by assigned user ID"),
1321
+ account_id: z2.string().optional().describe("Filter by account ID"),
1322
+ matter_id: z2.string().optional().describe("Filter by matter ID"),
1323
+ created_since: z2.string().optional().describe("ISO date \u2014 return records created after this date"),
1324
+ updated_since: z2.string().optional().describe("ISO date \u2014 return records updated after this date"),
1325
+ activity_tag: z2.string().optional().describe("Filter by activity tag"),
1326
+ external_message_id: z2.string().optional().describe("Filter by external message ID")
1327
+ }
1328
+ },
1329
+ // ── Events ──
1330
+ {
1331
+ name: "get_event",
1332
+ description: "Get a single calendar event by ID.",
1333
+ sdkFn: eventsGetEvent,
1334
+ schema: EventSchema,
1335
+ pathParams: { id: "Event ID" }
1336
+ },
1337
+ {
1338
+ name: "list_events",
1339
+ description: "List calendar events with optional filters by account, matter, user, date range, or tag.",
1340
+ sdkFn: eventsGetEvents,
1341
+ schema: EventSchema,
1342
+ isList: true,
1343
+ queryParams: {
1344
+ assigned_to_user_id: z2.string().optional().describe("Filter by assigned user ID"),
1345
+ account_id: z2.string().optional().describe("Filter by account ID"),
1346
+ matter_id: z2.string().optional().describe("Filter by matter ID"),
1347
+ created_since: z2.string().optional().describe("ISO date \u2014 return records created after this date"),
1348
+ updated_since: z2.string().optional().describe("ISO date \u2014 return records updated after this date"),
1349
+ date_from: z2.string().optional().describe("ISO date \u2014 filter from this date"),
1350
+ date_to: z2.string().optional().describe("ISO date \u2014 filter to this date"),
1351
+ activity_tag: z2.string().optional().describe("Filter by activity tag")
1352
+ }
1353
+ },
1354
+ // ── Expense Categories ──
1355
+ {
1356
+ name: "get_expense_category",
1357
+ description: "Get a single expense category by ID.",
1358
+ sdkFn: expenseCategoriesGetExpenseCategory,
1359
+ schema: ExpenseCategorySchema,
1360
+ pathParams: { id: "Expense Category ID" }
1361
+ },
1362
+ {
1363
+ name: "list_expense_categories",
1364
+ description: "List all expense categories.",
1365
+ sdkFn: expenseCategoriesGetExpenseCategories,
1366
+ schema: ExpenseCategorySchema,
1367
+ isList: true,
1368
+ queryParams: {
1369
+ created_since: z2.string().optional().describe("ISO date \u2014 return records created after this date"),
1370
+ updated_since: z2.string().optional().describe("ISO date \u2014 return records updated after this date")
1371
+ }
1372
+ },
1373
+ // ── Expenses ──
1374
+ {
1375
+ name: "get_expense",
1376
+ description: "Get a single expense by ID. Includes billable status, amount, and category.",
1377
+ sdkFn: expensesGetExpense,
1378
+ schema: ExpenseSchema,
1379
+ pathParams: { id: "Expense ID" }
1380
+ },
1381
+ {
1382
+ name: "list_expenses",
1383
+ description: "List expenses with optional filters by account, matter, billing user, category, or date range.",
1384
+ sdkFn: expensesGetExpensess,
1385
+ schema: ExpenseSchema,
1386
+ isList: true,
1387
+ queryParams: {
1388
+ account_id: z2.string().optional().describe("Filter by account ID"),
1389
+ matter_id: z2.string().optional().describe("Filter by matter ID"),
1390
+ billed_by_user_id: z2.string().optional().describe("Filter by billing user ID"),
1391
+ expense_category_id: z2.string().optional().describe("Filter by expense category ID"),
1392
+ created_since: z2.string().optional().describe("ISO date \u2014 return records created after this date"),
1393
+ updated_since: z2.string().optional().describe("ISO date \u2014 return records updated after this date"),
1394
+ date_from: z2.string().optional().describe("ISO date \u2014 filter from this date"),
1395
+ date_to: z2.string().optional().describe("ISO date \u2014 filter to this date")
1396
+ }
1397
+ },
1398
+ // ── Files ──
1399
+ {
1400
+ name: "get_file",
1401
+ description: "Get file metadata by ID (name, size, content type).",
1402
+ sdkFn: filesGetFile,
1403
+ schema: FileSchema,
1404
+ pathParams: { id: "File ID" }
1405
+ },
1406
+ {
1407
+ name: "download_file",
1408
+ description: "Download a file's contents by ID.",
1409
+ sdkFn: filesDownloadFile,
1410
+ pathParams: { id: "File ID to download" },
1411
+ rawContent: true
1412
+ },
1413
+ {
1414
+ name: "list_files",
1415
+ description: "List files with optional filters by account, matter, activity, creator, or search text.",
1416
+ sdkFn: filesGetFiles,
1417
+ schema: FileSchema,
1418
+ isList: true,
1419
+ queryParams: {
1420
+ created_since: z2.string().optional().describe("ISO date \u2014 return records created after this date"),
1421
+ updated_since: z2.string().optional().describe("ISO date \u2014 return records updated after this date"),
1422
+ search_text: z2.string().optional().describe("Search text"),
1423
+ account_id: z2.string().optional().describe("Filter by account ID"),
1424
+ matter_id: z2.string().optional().describe("Filter by matter ID"),
1425
+ activity_id: z2.string().optional().describe("Filter by activity ID"),
1426
+ created_by_user_id: z2.string().optional().describe("Filter by creating user ID")
1427
+ }
1428
+ },
1429
+ // ── Flat Fees ──
1430
+ {
1431
+ name: "get_flat_fee",
1432
+ description: "Get a single flat fee entry by ID.",
1433
+ sdkFn: flatFeesGetFlatFee,
1434
+ schema: FlatFeeSchema,
1435
+ pathParams: { id: "Flat Fee ID" }
1436
+ },
1437
+ {
1438
+ name: "list_flat_fees",
1439
+ description: "List flat fees with optional filters by account, matter, user, item, or date range.",
1440
+ sdkFn: flatFeesGetFlatFees,
1441
+ schema: FlatFeeSchema,
1442
+ isList: true,
1443
+ queryParams: {
1444
+ account_id: z2.string().optional().describe("Filter by account ID"),
1445
+ matter_id: z2.string().optional().describe("Filter by matter ID"),
1446
+ user_id: z2.string().optional().describe("Filter by user ID"),
1447
+ item_id: z2.string().optional().describe("Filter by item ID"),
1448
+ created_since: z2.string().optional().describe("ISO date \u2014 return records created after this date"),
1449
+ updated_since: z2.string().optional().describe("ISO date \u2014 return records updated after this date"),
1450
+ date_from: z2.string().optional().describe("ISO date \u2014 filter from this date"),
1451
+ date_to: z2.string().optional().describe("ISO date \u2014 filter to this date")
1452
+ }
1453
+ },
1454
+ // ── Invoices ──
1455
+ {
1456
+ name: "get_invoice",
1457
+ description: "Get a single invoice by ID with line items (time entries, expenses, flat fees).",
1458
+ sdkFn: invoicesGetInvoice,
1459
+ schema: InvoiceSchema,
1460
+ pathParams: { id: "Invoice ID" }
1461
+ },
1462
+ {
1463
+ name: "list_invoices",
1464
+ description: "List invoices with optional filters by account, matter, or date range.",
1465
+ sdkFn: invoicesGetInvoices,
1466
+ schema: InvoiceSchema,
1467
+ isList: true,
1468
+ queryParams: {
1469
+ account_id: z2.string().optional().describe("Filter by account ID"),
1470
+ matter_id: z2.string().optional().describe("Filter by matter ID"),
1471
+ created_since: z2.string().optional().describe("ISO date \u2014 return records created after this date"),
1472
+ updated_since: z2.string().optional().describe("ISO date \u2014 return records updated after this date"),
1473
+ date_from: z2.string().optional().describe("ISO date \u2014 filter from this date"),
1474
+ date_to: z2.string().optional().describe("ISO date \u2014 filter to this date")
1475
+ }
1476
+ },
1477
+ // ── Items ──
1478
+ {
1479
+ name: "get_item",
1480
+ description: "Get a single billing item/service by ID.",
1481
+ sdkFn: itemsGetItem,
1482
+ schema: ItemSchema,
1483
+ pathParams: { id: "Item ID" }
1484
+ },
1485
+ {
1486
+ name: "list_items",
1487
+ description: "List all billing items/services.",
1488
+ sdkFn: itemsGetItems,
1489
+ schema: ItemSchema,
1490
+ isList: true,
1491
+ queryParams: {
1492
+ created_since: z2.string().optional().describe("ISO date \u2014 return records created after this date"),
1493
+ updated_since: z2.string().optional().describe("ISO date \u2014 return records updated after this date")
1494
+ }
1495
+ },
1496
+ // ── Matters ──
1497
+ {
1498
+ name: "get_matter",
1499
+ description: "Get a single matter (case/project) by ID. Returns status, assigned users, tags, and custom fields.",
1500
+ sdkFn: mattersGetMatter,
1501
+ schema: MatterSchema,
1502
+ pathParams: { id: "Matter ID" }
1503
+ },
1504
+ {
1505
+ name: "list_matters",
1506
+ description: "List matters with optional filters by account, status (Open/Closed/Pending/Archived), user, search text, or tags.",
1507
+ sdkFn: mattersGetMatters,
1508
+ schema: MatterSchema,
1509
+ isList: true,
1510
+ queryParams: {
1511
+ assigned_to_user_id: z2.string().optional().describe("Filter by assigned user ID"),
1512
+ account_id: z2.string().optional().describe("Filter by account ID"),
1513
+ status: z2.enum(["Closed", "Pending", "Open", "Archived"]).optional().describe("Filter by matter status"),
1514
+ created_since: z2.string().optional().describe("ISO date \u2014 return records created after this date"),
1515
+ updated_since: z2.string().optional().describe("ISO date \u2014 return records updated after this date"),
1516
+ search_text: z2.string().optional().describe("Search text"),
1517
+ account_tag: z2.string().optional().describe("Filter by account tag"),
1518
+ matter_tag: z2.string().optional().describe("Filter by matter tag")
1519
+ }
1520
+ },
1521
+ // ── Messages ──
1522
+ {
1523
+ name: "list_messages",
1524
+ description: "List all messages.",
1525
+ sdkFn: messagesGetMessagesAsync,
1526
+ schema: MessageSchema,
1527
+ isList: true
1528
+ },
1529
+ // ── Notes ──
1530
+ {
1531
+ name: "get_note",
1532
+ description: "Get a single note by ID.",
1533
+ sdkFn: notesGetNote,
1534
+ schema: NoteSchema,
1535
+ pathParams: { id: "Note ID" }
1536
+ },
1537
+ {
1538
+ name: "list_notes",
1539
+ description: "List notes with optional filters by account, matter, user, date range, or tag.",
1540
+ sdkFn: notesGetNotes,
1541
+ schema: NoteSchema,
1542
+ isList: true,
1543
+ queryParams: {
1544
+ assigned_to_user_id: z2.string().optional().describe("Filter by assigned user ID"),
1545
+ account_id: z2.string().optional().describe("Filter by account ID"),
1546
+ matter_id: z2.string().optional().describe("Filter by matter ID"),
1547
+ created_since: z2.string().optional().describe("ISO date \u2014 return records created after this date"),
1548
+ updated_since: z2.string().optional().describe("ISO date \u2014 return records updated after this date"),
1549
+ date_from: z2.string().optional().describe("ISO date \u2014 filter from this date"),
1550
+ date_to: z2.string().optional().describe("ISO date \u2014 filter to this date"),
1551
+ activity_tag: z2.string().optional().describe("Filter by activity tag")
1552
+ }
1553
+ },
1554
+ // ── Payments ──
1555
+ {
1556
+ name: "get_payment",
1557
+ description: "Get a single payment by ID with full details including status.",
1558
+ sdkFn: paymentsGetPayment,
1559
+ schema: PaymentDetailSchema,
1560
+ pathParams: { id: "Payment ID" }
1561
+ },
1562
+ {
1563
+ name: "list_payments",
1564
+ description: "List payments with optional filters by account, matter, bank account, type, or date range.",
1565
+ sdkFn: paymentsGetPayments,
1566
+ schema: PaymentSchema,
1567
+ isList: true,
1568
+ queryParams: {
1569
+ account_id: z2.string().optional().describe("Filter by account ID"),
1570
+ matter_id: z2.string().optional().describe("Filter by matter ID"),
1571
+ bank_account_id: z2.string().optional().describe("Filter by bank account ID"),
1572
+ bank_account_type: z2.enum(["Operating", "Trust", "CreditCard"]).optional().describe("Filter by bank account type"),
1573
+ created_since: z2.string().optional().describe("ISO date \u2014 return records created after this date"),
1574
+ updated_since: z2.string().optional().describe("ISO date \u2014 return records updated after this date"),
1575
+ date_from: z2.string().optional().describe("ISO date \u2014 filter from this date"),
1576
+ date_to: z2.string().optional().describe("ISO date \u2014 filter to this date")
1577
+ }
1578
+ },
1579
+ // ── Relationships ──
1580
+ {
1581
+ name: "get_relationship",
1582
+ description: "Get a single matter-contact relationship by ID.",
1583
+ sdkFn: relationshipsGetRelationship,
1584
+ schema: RelationshipSchema,
1585
+ pathParams: { id: "Relationship ID" }
1586
+ },
1587
+ {
1588
+ name: "list_relationships",
1589
+ description: "List relationships between contacts and matters with optional filters.",
1590
+ sdkFn: relationshipsGetRelationships,
1591
+ schema: RelationshipSchema,
1592
+ isList: true,
1593
+ queryParams: {
1594
+ contact_id: z2.string().optional().describe("Filter by contact ID"),
1595
+ matter_id: z2.string().optional().describe("Filter by matter ID"),
1596
+ account_id: z2.string().optional().describe("Filter by account ID"),
1597
+ created_since: z2.string().optional().describe("ISO date \u2014 return records created after this date"),
1598
+ updated_since: z2.string().optional().describe("ISO date \u2014 return records updated after this date")
1599
+ }
1600
+ },
1601
+ // ── Tags ──
1602
+ {
1603
+ name: "list_account_tags",
1604
+ description: "List all tags available for accounts.",
1605
+ sdkFn: tagsGetTagsForAccounts,
1606
+ schema: TagSchema,
1607
+ isList: true
1608
+ },
1609
+ {
1610
+ name: "list_matter_tags",
1611
+ description: "List all tags available for matters.",
1612
+ sdkFn: tagsGetTagsForProjects,
1613
+ schema: TagSchema,
1614
+ isList: true
1615
+ },
1616
+ {
1617
+ name: "list_activity_tags",
1618
+ description: "List all tags available for activities (call logs, events, notes, etc.).",
1619
+ sdkFn: tagsGetTagsForActivities,
1620
+ schema: TagSchema,
1621
+ isList: true
1622
+ },
1623
+ // ── Tasks ──
1624
+ {
1625
+ name: "get_task",
1626
+ description: "Get a single task by ID.",
1627
+ sdkFn: tasksGetTask,
1628
+ schema: TaskSchema,
1629
+ pathParams: { id: "Task ID" }
1630
+ },
1631
+ {
1632
+ name: "list_tasks",
1633
+ description: "List tasks with optional filters by account, matter, user, status, due date range, or tag.",
1634
+ sdkFn: tasksGetTasks,
1635
+ schema: TaskSchema,
1636
+ isList: true,
1637
+ queryParams: {
1638
+ assigned_to_user_id: z2.string().optional().describe("Filter by assigned user ID"),
1639
+ account_id: z2.string().optional().describe("Filter by account ID"),
1640
+ matter_id: z2.string().optional().describe("Filter by matter ID"),
1641
+ created_since: z2.string().optional().describe("ISO date \u2014 return records created after this date"),
1642
+ updated_since: z2.string().optional().describe("ISO date \u2014 return records updated after this date"),
1643
+ status: z2.enum(["NotCompleted", "InProgress", "Completed", "Conditional"]).optional().describe("Filter by task status"),
1644
+ due_date_from: z2.string().optional().describe("ISO date \u2014 filter by due date from"),
1645
+ due_date_to: z2.string().optional().describe("ISO date \u2014 filter by due date to"),
1646
+ activity_tag: z2.string().optional().describe("Filter by activity tag")
1647
+ }
1648
+ },
1649
+ // ── Time Entries ──
1650
+ {
1651
+ name: "get_time_entry",
1652
+ description: "Get a single time entry by ID. Hours are decimal (e.g. 1.5 = 1h30m).",
1653
+ sdkFn: timeEntriesGetTimeEntry,
1654
+ schema: TimeEntrySchema,
1655
+ pathParams: { id: "Time Entry ID" }
1656
+ },
1657
+ {
1658
+ name: "list_time_entries",
1659
+ description: "List time entries with optional filters by account, matter, user, item, or date range.",
1660
+ sdkFn: timeEntriesGetTimeEntrys,
1661
+ schema: TimeEntrySchema,
1662
+ isList: true,
1663
+ queryParams: {
1664
+ account_id: z2.string().optional().describe("Filter by account ID"),
1665
+ matter_id: z2.string().optional().describe("Filter by matter ID"),
1666
+ user_id: z2.string().optional().describe("Filter by user ID"),
1667
+ item_id: z2.string().optional().describe("Filter by item ID"),
1668
+ created_since: z2.string().optional().describe("ISO date \u2014 return records created after this date"),
1669
+ updated_since: z2.string().optional().describe("ISO date \u2014 return records updated after this date"),
1670
+ date_from: z2.string().optional().describe("ISO date \u2014 filter from this date"),
1671
+ date_to: z2.string().optional().describe("ISO date \u2014 filter to this date")
1672
+ }
1673
+ },
1674
+ // ── Users ──
1675
+ {
1676
+ name: "get_me",
1677
+ description: "Get the currently authenticated user's profile.",
1678
+ sdkFn: usersMe,
1679
+ schema: UserSchema
1680
+ },
1681
+ {
1682
+ name: "get_user",
1683
+ description: "Get a single user by ID.",
1684
+ sdkFn: usersGetUser,
1685
+ schema: UserSchema,
1686
+ pathParams: { id: "User ID" }
1687
+ },
1688
+ {
1689
+ name: "list_users",
1690
+ description: "List users with optional filters by creation date, update date, or email address.",
1691
+ sdkFn: usersGetUsers,
1692
+ schema: UserSchema,
1693
+ isList: true,
1694
+ queryParams: {
1695
+ created_since: z2.string().optional().describe("ISO date \u2014 return records created after this date"),
1696
+ updated_since: z2.string().optional().describe("ISO date \u2014 return records updated after this date"),
1697
+ email_address: z2.string().optional().describe("Filter by email address")
1698
+ }
1699
+ }
1700
+ ];
1701
+ for (const tool of tools) {
1702
+ const inputSchema = {};
1703
+ if (tool.pathParams) {
1704
+ for (const [paramName, description] of Object.entries(tool.pathParams)) {
1705
+ inputSchema[paramName] = z2.string().describe(description);
1706
+ }
1707
+ }
1708
+ if (tool.queryParams) {
1709
+ for (const [paramName, zodType] of Object.entries(tool.queryParams)) {
1710
+ inputSchema[paramName] = zodType;
1711
+ }
1712
+ }
1713
+ const outputSchema = tool.schema ? tool.isList ? listOf(tool.schema) : tool.schema : void 0;
1714
+ server.registerTool(
1715
+ tool.name,
1716
+ {
1717
+ description: tool.description,
1718
+ inputSchema: Object.keys(inputSchema).length > 0 ? inputSchema : void 0,
1719
+ outputSchema
1720
+ },
1721
+ async (params) => {
1722
+ try {
1723
+ const options = {};
1724
+ if (tool.pathParams) {
1725
+ const path = {};
1726
+ for (const paramName of Object.keys(tool.pathParams)) {
1727
+ path[paramName] = params[paramName];
1728
+ }
1729
+ options.path = path;
1730
+ }
1731
+ if (tool.queryParams) {
1732
+ const query = {};
1733
+ for (const paramName of Object.keys(tool.queryParams)) {
1734
+ if (params[paramName] !== void 0) {
1735
+ query[paramName] = params[paramName];
1736
+ }
1737
+ }
1738
+ if (Object.keys(query).length > 0) {
1739
+ options.query = cleanQuery(query);
1740
+ }
1741
+ }
1742
+ const res = await tool.sdkFn(
1743
+ Object.keys(options).length > 0 ? options : void 0
1744
+ );
1745
+ if (tool.rawContent) {
1746
+ return {
1747
+ content: [
1748
+ {
1749
+ type: "text",
1750
+ text: JSON.stringify(res.data, null, 2)
1751
+ }
1752
+ ]
1753
+ };
1754
+ }
1755
+ if (tool.isList) {
1756
+ return {
1757
+ content: [],
1758
+ structuredContent: { items: res.data }
1759
+ };
1760
+ }
1761
+ return {
1762
+ content: [],
1763
+ structuredContent: res.data
1764
+ };
1765
+ } catch (e) {
1766
+ return err(e);
1767
+ }
1768
+ }
1769
+ );
1770
+ }
1771
+ var command = process.argv[2];
1772
+ if (command === "auth") {
1773
+ const { runCli } = await import("./auth.js");
1774
+ runCli(process.argv[3]);
1775
+ } else {
1776
+ const transport = new StdioServerTransport();
1777
+ await server.connect(transport);
1778
+ }
1779
+ //# sourceMappingURL=server.js.map