@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/LICENSE +21 -0
- package/README.md +130 -0
- package/dist/auth.d.ts +4 -0
- package/dist/auth.js +9 -0
- package/dist/auth.js.map +1 -0
- package/dist/chunk-A6QUURB5.js +234 -0
- package/dist/chunk-A6QUURB5.js.map +1 -0
- package/dist/server.d.ts +1 -0
- package/dist/server.js +1779 -0
- package/dist/server.js.map +1 -0
- package/openapi.json +11493 -0
- package/package.json +34 -0
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
|