syncromsp-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 +244 -0
- package/dist/api-client.d.ts +21 -0
- package/dist/api-client.d.ts.map +1 -0
- package/dist/api-client.js +117 -0
- package/dist/api-client.js.map +1 -0
- package/dist/auth.d.ts +37 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +133 -0
- package/dist/auth.js.map +1 -0
- package/dist/domains/admin.d.ts +4 -0
- package/dist/domains/admin.d.ts.map +1 -0
- package/dist/domains/admin.js +807 -0
- package/dist/domains/admin.js.map +1 -0
- package/dist/domains/appointments.d.ts +4 -0
- package/dist/domains/appointments.d.ts.map +1 -0
- package/dist/domains/appointments.js +231 -0
- package/dist/domains/appointments.js.map +1 -0
- package/dist/domains/assets.d.ts +4 -0
- package/dist/domains/assets.d.ts.map +1 -0
- package/dist/domains/assets.js +138 -0
- package/dist/domains/assets.js.map +1 -0
- package/dist/domains/contacts.d.ts +4 -0
- package/dist/domains/contacts.d.ts.map +1 -0
- package/dist/domains/contacts.js +148 -0
- package/dist/domains/contacts.js.map +1 -0
- package/dist/domains/contracts.d.ts +4 -0
- package/dist/domains/contracts.d.ts.map +1 -0
- package/dist/domains/contracts.js +125 -0
- package/dist/domains/contracts.js.map +1 -0
- package/dist/domains/customers.d.ts +4 -0
- package/dist/domains/customers.d.ts.map +1 -0
- package/dist/domains/customers.js +323 -0
- package/dist/domains/customers.js.map +1 -0
- package/dist/domains/estimates.d.ts +4 -0
- package/dist/domains/estimates.d.ts.map +1 -0
- package/dist/domains/estimates.js +262 -0
- package/dist/domains/estimates.js.map +1 -0
- package/dist/domains/index.d.ts +5 -0
- package/dist/domains/index.d.ts.map +1 -0
- package/dist/domains/index.js +34 -0
- package/dist/domains/index.js.map +1 -0
- package/dist/domains/invoices.d.ts +4 -0
- package/dist/domains/invoices.d.ts.map +1 -0
- package/dist/domains/invoices.js +292 -0
- package/dist/domains/invoices.js.map +1 -0
- package/dist/domains/leads.d.ts +4 -0
- package/dist/domains/leads.d.ts.map +1 -0
- package/dist/domains/leads.js +135 -0
- package/dist/domains/leads.js.map +1 -0
- package/dist/domains/payments.d.ts +4 -0
- package/dist/domains/payments.d.ts.map +1 -0
- package/dist/domains/payments.js +188 -0
- package/dist/domains/payments.js.map +1 -0
- package/dist/domains/products.d.ts +4 -0
- package/dist/domains/products.d.ts.map +1 -0
- package/dist/domains/products.js +350 -0
- package/dist/domains/products.js.map +1 -0
- package/dist/domains/rmm.d.ts +4 -0
- package/dist/domains/rmm.d.ts.map +1 -0
- package/dist/domains/rmm.js +100 -0
- package/dist/domains/rmm.js.map +1 -0
- package/dist/domains/scheduling.d.ts +4 -0
- package/dist/domains/scheduling.d.ts.map +1 -0
- package/dist/domains/scheduling.js +206 -0
- package/dist/domains/scheduling.js.map +1 -0
- package/dist/domains/tickets.d.ts +4 -0
- package/dist/domains/tickets.d.ts.map +1 -0
- package/dist/domains/tickets.js +533 -0
- package/dist/domains/tickets.js.map +1 -0
- package/dist/domains/time.d.ts +4 -0
- package/dist/domains/time.d.ts.map +1 -0
- package/dist/domains/time.js +93 -0
- package/dist/domains/time.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +137 -0
- package/dist/index.js.map +1 -0
- package/dist/server.d.ts +5 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +183 -0
- package/dist/server.js.map +1 -0
- package/dist/session.d.ts +12 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +31 -0
- package/dist/session.js.map +1 -0
- package/dist/types.d.ts +46 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +44 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/pagination.d.ts +12 -0
- package/dist/utils/pagination.d.ts.map +1 -0
- package/dist/utils/pagination.js +18 -0
- package/dist/utils/pagination.js.map +1 -0
- package/dist/utils/rate-limiter.d.ts +15 -0
- package/dist/utils/rate-limiter.d.ts.map +1 -0
- package/dist/utils/rate-limiter.js +63 -0
- package/dist/utils/rate-limiter.js.map +1 -0
- package/dist/utils/validators.d.ts +9 -0
- package/dist/utils/validators.d.ts.map +1 -0
- package/dist/utils/validators.js +59 -0
- package/dist/utils/validators.js.map +1 -0
- package/dist/utils/version-check.d.ts +7 -0
- package/dist/utils/version-check.d.ts.map +1 -0
- package/dist/utils/version-check.js +59 -0
- package/dist/utils/version-check.js.map +1 -0
- package/manifest.json +64 -0
- package/package.json +57 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export function addPaginationParams(params, pagination) {
|
|
2
|
+
if (pagination?.page !== undefined) {
|
|
3
|
+
params.set("page", String(pagination.page));
|
|
4
|
+
}
|
|
5
|
+
}
|
|
6
|
+
export function formatPaginationInfo(meta) {
|
|
7
|
+
if (!meta)
|
|
8
|
+
return "";
|
|
9
|
+
const parts = [];
|
|
10
|
+
if (meta.page !== undefined)
|
|
11
|
+
parts.push(`Page ${meta.page}`);
|
|
12
|
+
if (meta.total_pages !== undefined)
|
|
13
|
+
parts.push(`of ${meta.total_pages}`);
|
|
14
|
+
if (meta.total_entries !== undefined)
|
|
15
|
+
parts.push(`(${meta.total_entries} total)`);
|
|
16
|
+
return parts.length > 0 ? `\n---\n${parts.join(" ")}` : "";
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=pagination.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pagination.js","sourceRoot":"","sources":["../../src/utils/pagination.ts"],"names":[],"mappings":"AAIA,MAAM,UAAU,mBAAmB,CACjC,MAAuB,EACvB,UAA6B;IAE7B,IAAI,UAAU,EAAE,IAAI,KAAK,SAAS,EAAE,CAAC;QACnC,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;IAC9C,CAAC;AACH,CAAC;AASD,MAAM,UAAU,oBAAoB,CAAC,IAAgC;IACnE,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,CAAC;IACrB,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS;QAAE,KAAK,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IAC7D,IAAI,IAAI,CAAC,WAAW,KAAK,SAAS;QAAE,KAAK,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;IACzE,IAAI,IAAI,CAAC,aAAa,KAAK,SAAS;QAAE,KAAK,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,aAAa,SAAS,CAAC,CAAC;IAClF,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,UAAU,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;AAC7D,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export declare class RateLimiter {
|
|
2
|
+
private readonly timeoutMs;
|
|
3
|
+
private tokens;
|
|
4
|
+
private lastRefill;
|
|
5
|
+
private readonly maxTokens;
|
|
6
|
+
private readonly refillRate;
|
|
7
|
+
private readonly queue;
|
|
8
|
+
constructor(maxPerMinute?: number, timeoutMs?: number);
|
|
9
|
+
private refill;
|
|
10
|
+
acquire(): Promise<void>;
|
|
11
|
+
private processTimeout;
|
|
12
|
+
private scheduleProcess;
|
|
13
|
+
private processQueue;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=rate-limiter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-limiter.d.ts","sourceRoot":"","sources":["../../src/utils/rate-limiter.ts"],"names":[],"mappings":"AAAA,qBAAa,WAAW;IAWkB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAVlE,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAId;gBAEI,YAAY,GAAE,MAAY,EAAmB,SAAS,GAAE,MAAc;IAOlF,OAAO,CAAC,MAAM;IAQR,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAsB9B,OAAO,CAAC,cAAc,CAA8C;IAEpE,OAAO,CAAC,eAAe;IASvB,OAAO,CAAC,YAAY;CAYrB"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
export class RateLimiter {
|
|
2
|
+
timeoutMs;
|
|
3
|
+
tokens;
|
|
4
|
+
lastRefill;
|
|
5
|
+
maxTokens;
|
|
6
|
+
refillRate; // tokens per ms
|
|
7
|
+
queue = [];
|
|
8
|
+
constructor(maxPerMinute = 180, timeoutMs = 30000) {
|
|
9
|
+
this.timeoutMs = timeoutMs;
|
|
10
|
+
this.maxTokens = maxPerMinute;
|
|
11
|
+
this.tokens = maxPerMinute;
|
|
12
|
+
this.refillRate = maxPerMinute / 60000;
|
|
13
|
+
this.lastRefill = Date.now();
|
|
14
|
+
}
|
|
15
|
+
refill() {
|
|
16
|
+
const now = Date.now();
|
|
17
|
+
const elapsed = now - this.lastRefill;
|
|
18
|
+
const newTokens = elapsed * this.refillRate;
|
|
19
|
+
this.tokens = Math.min(this.maxTokens, this.tokens + newTokens);
|
|
20
|
+
this.lastRefill = now;
|
|
21
|
+
}
|
|
22
|
+
async acquire() {
|
|
23
|
+
this.refill();
|
|
24
|
+
if (this.tokens >= 1) {
|
|
25
|
+
this.tokens -= 1;
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
return new Promise((resolve, reject) => {
|
|
29
|
+
const timer = setTimeout(() => {
|
|
30
|
+
const idx = this.queue.findIndex((item) => item.resolve === resolve);
|
|
31
|
+
if (idx !== -1) {
|
|
32
|
+
this.queue.splice(idx, 1);
|
|
33
|
+
}
|
|
34
|
+
reject(new Error("Rate limit timeout: request queued for too long"));
|
|
35
|
+
}, this.timeoutMs);
|
|
36
|
+
this.queue.push({ resolve, reject, timer });
|
|
37
|
+
this.scheduleProcess();
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
processTimeout = null;
|
|
41
|
+
scheduleProcess() {
|
|
42
|
+
if (this.processTimeout !== null)
|
|
43
|
+
return;
|
|
44
|
+
const waitMs = Math.ceil(1 / this.refillRate);
|
|
45
|
+
this.processTimeout = setTimeout(() => {
|
|
46
|
+
this.processTimeout = null;
|
|
47
|
+
this.processQueue();
|
|
48
|
+
}, waitMs);
|
|
49
|
+
}
|
|
50
|
+
processQueue() {
|
|
51
|
+
this.refill();
|
|
52
|
+
while (this.queue.length > 0 && this.tokens >= 1) {
|
|
53
|
+
const item = this.queue.shift();
|
|
54
|
+
clearTimeout(item.timer);
|
|
55
|
+
this.tokens -= 1;
|
|
56
|
+
item.resolve();
|
|
57
|
+
}
|
|
58
|
+
if (this.queue.length > 0) {
|
|
59
|
+
this.scheduleProcess();
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=rate-limiter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-limiter.js","sourceRoot":"","sources":["../../src/utils/rate-limiter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare function requireNumber(value: unknown, name: string): number;
|
|
2
|
+
export declare function requireString(value: unknown, name: string): string;
|
|
3
|
+
export declare function requireId(value: unknown, name?: string): number;
|
|
4
|
+
export declare function optionalString(value: unknown): string | undefined;
|
|
5
|
+
export declare function optionalNumber(value: unknown): number | undefined;
|
|
6
|
+
export declare function optionalBoolean(value: unknown): boolean | undefined;
|
|
7
|
+
export declare function optionalId(value: unknown): number | undefined;
|
|
8
|
+
export declare function pickDefined(obj: Record<string, unknown>): Record<string, unknown>;
|
|
9
|
+
//# sourceMappingURL=validators.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validators.d.ts","sourceRoot":"","sources":["../../src/utils/validators.ts"],"names":[],"mappings":"AAAA,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAKlE;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAKlE;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,GAAE,MAAa,GAAG,MAAM,CAMrE;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAKjE;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAIjE;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,GAAG,SAAS,CAInE;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAK7D;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAQjF"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
export function requireNumber(value, name) {
|
|
2
|
+
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
3
|
+
throw new Error(`${name} must be a valid number`);
|
|
4
|
+
}
|
|
5
|
+
return value;
|
|
6
|
+
}
|
|
7
|
+
export function requireString(value, name) {
|
|
8
|
+
if (typeof value !== "string" || value.trim().length === 0) {
|
|
9
|
+
throw new Error(`${name} must be a non-empty string`);
|
|
10
|
+
}
|
|
11
|
+
return value.trim();
|
|
12
|
+
}
|
|
13
|
+
export function requireId(value, name = "id") {
|
|
14
|
+
const num = requireNumber(value, name);
|
|
15
|
+
if (!Number.isInteger(num) || num <= 0) {
|
|
16
|
+
throw new Error(`${name} must be a positive integer`);
|
|
17
|
+
}
|
|
18
|
+
return num;
|
|
19
|
+
}
|
|
20
|
+
export function optionalString(value) {
|
|
21
|
+
if (value === undefined || value === null)
|
|
22
|
+
return undefined;
|
|
23
|
+
if (typeof value !== "string")
|
|
24
|
+
return undefined;
|
|
25
|
+
const trimmed = value.trim();
|
|
26
|
+
return trimmed.length > 0 ? trimmed : undefined;
|
|
27
|
+
}
|
|
28
|
+
export function optionalNumber(value) {
|
|
29
|
+
if (value === undefined || value === null)
|
|
30
|
+
return undefined;
|
|
31
|
+
if (typeof value !== "number" || !Number.isFinite(value))
|
|
32
|
+
return undefined;
|
|
33
|
+
return value;
|
|
34
|
+
}
|
|
35
|
+
export function optionalBoolean(value) {
|
|
36
|
+
if (value === undefined || value === null)
|
|
37
|
+
return undefined;
|
|
38
|
+
if (typeof value !== "boolean")
|
|
39
|
+
return undefined;
|
|
40
|
+
return value;
|
|
41
|
+
}
|
|
42
|
+
export function optionalId(value) {
|
|
43
|
+
if (value === undefined || value === null)
|
|
44
|
+
return undefined;
|
|
45
|
+
const num = optionalNumber(value);
|
|
46
|
+
if (num !== undefined && Number.isInteger(num) && num > 0)
|
|
47
|
+
return num;
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
export function pickDefined(obj) {
|
|
51
|
+
const result = {};
|
|
52
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
53
|
+
if (value !== undefined) {
|
|
54
|
+
result[key] = value;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return result;
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=validators.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validators.js","sourceRoot":"","sources":["../../src/utils/validators.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,aAAa,CAAC,KAAc,EAAE,IAAY;IACxD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACzD,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,yBAAyB,CAAC,CAAC;IACpD,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,KAAc,EAAE,IAAY;IACxD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3D,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,6BAA6B,CAAC,CAAC;IACxD,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,EAAE,CAAC;AACtB,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,KAAc,EAAE,OAAe,IAAI;IAC3D,MAAM,GAAG,GAAG,aAAa,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IACvC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC;QACvC,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,6BAA6B,CAAC,CAAC;IACxD,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,KAAc;IAC3C,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,SAAS,CAAC;IAC5D,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC;IAChD,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAC7B,OAAO,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;AAClD,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,KAAc;IAC3C,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,SAAS,CAAC;IAC5D,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAC3E,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,KAAc;IAC5C,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,SAAS,CAAC;IAC5D,IAAI,OAAO,KAAK,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IACjD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,KAAc;IACvC,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,SAAS,CAAC;IAC5D,MAAM,GAAG,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;IAClC,IAAI,GAAG,KAAK,SAAS,IAAI,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC;QAAE,OAAO,GAAG,CAAC;IACtE,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,GAA4B;IACtD,MAAM,MAAM,GAA4B,EAAE,CAAC;IAC3C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QAC/C,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;QACtB,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Non-blocking version check on startup. Logs a warning to stderr
|
|
3
|
+
* if a newer version is available. Never throws — silently fails
|
|
4
|
+
* on network errors, timeouts, etc.
|
|
5
|
+
*/
|
|
6
|
+
export declare function checkForUpdates(): void;
|
|
7
|
+
//# sourceMappingURL=version-check.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version-check.d.ts","sourceRoot":"","sources":["../../src/utils/version-check.ts"],"names":[],"mappings":"AA+BA;;;;GAIG;AACH,wBAAgB,eAAe,IAAI,IAAI,CA+BtC"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { fileURLToPath } from "node:url";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
function getCurrentVersion() {
|
|
5
|
+
try {
|
|
6
|
+
// Try reading from package.json relative to this file
|
|
7
|
+
const dir = dirname(fileURLToPath(import.meta.url));
|
|
8
|
+
const pkgPath = join(dir, "..", "..", "package.json");
|
|
9
|
+
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
10
|
+
return pkg.version || "0.0.0";
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
return "0.0.0";
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
function compareVersions(current, latest) {
|
|
17
|
+
const c = current.replace(/^v/, "").split(".").map(Number);
|
|
18
|
+
const l = latest.replace(/^v/, "").split(".").map(Number);
|
|
19
|
+
for (let i = 0; i < 3; i++) {
|
|
20
|
+
if ((c[i] || 0) < (l[i] || 0))
|
|
21
|
+
return -1;
|
|
22
|
+
if ((c[i] || 0) > (l[i] || 0))
|
|
23
|
+
return 1;
|
|
24
|
+
}
|
|
25
|
+
return 0;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Non-blocking version check on startup. Logs a warning to stderr
|
|
29
|
+
* if a newer version is available. Never throws — silently fails
|
|
30
|
+
* on network errors, timeouts, etc.
|
|
31
|
+
*/
|
|
32
|
+
export function checkForUpdates() {
|
|
33
|
+
const currentVersion = getCurrentVersion();
|
|
34
|
+
if (currentVersion === "0.0.0")
|
|
35
|
+
return;
|
|
36
|
+
const controller = new AbortController();
|
|
37
|
+
const timeout = setTimeout(() => controller.abort(), 5000);
|
|
38
|
+
fetch("https://api.github.com/repos/advenimus/syncromsp-mcp/releases/latest", {
|
|
39
|
+
headers: { Accept: "application/vnd.github+json" },
|
|
40
|
+
signal: controller.signal,
|
|
41
|
+
})
|
|
42
|
+
.then((res) => (res.ok ? res.json() : null))
|
|
43
|
+
.then((release) => {
|
|
44
|
+
if (!release)
|
|
45
|
+
return;
|
|
46
|
+
const latestVersion = release.tag_name.replace(/^v/, "");
|
|
47
|
+
if (compareVersions(currentVersion, latestVersion) < 0) {
|
|
48
|
+
console.error(`\n⚠ SyncroMSP MCP v${latestVersion} is available (you have v${currentVersion}).` +
|
|
49
|
+
`\n Update: ${release.html_url}` +
|
|
50
|
+
`\n npx: npx syncromsp-mcp@latest` +
|
|
51
|
+
`\n Docker: docker compose pull && docker compose up -d\n`);
|
|
52
|
+
}
|
|
53
|
+
})
|
|
54
|
+
.catch(() => {
|
|
55
|
+
// Silently ignore — network errors, rate limits, etc.
|
|
56
|
+
})
|
|
57
|
+
.finally(() => clearTimeout(timeout));
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=version-check.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version-check.js","sourceRoot":"","sources":["../../src/utils/version-check.ts"],"names":[],"mappings":"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"}
|
package/manifest.json
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{
|
|
2
|
+
"manifest_version": "0.3",
|
|
3
|
+
"name": "syncromsp-mcp",
|
|
4
|
+
"display_name": "SyncroMSP MCP Server",
|
|
5
|
+
"version": "0.1.0",
|
|
6
|
+
"description": "MCP server for SyncroMSP — tickets, customers, assets, invoices, and 30+ resource types for AI assistants",
|
|
7
|
+
"long_description": "A fully-featured Model Context Protocol server for the SyncroMSP IT/MSP platform. Provides AI assistants with access to 170 API endpoints across 15 domains using a lazy-loaded navigation pattern that keeps token usage efficient. Supports full CRUD for tickets, customers, invoices, estimates, appointments, products, RMM alerts, and more.",
|
|
8
|
+
"author": {
|
|
9
|
+
"name": "Advenimus",
|
|
10
|
+
"url": "https://github.com/advenimus"
|
|
11
|
+
},
|
|
12
|
+
"repository": {
|
|
13
|
+
"type": "git",
|
|
14
|
+
"url": "https://github.com/advenimus/syncromsp-mcp"
|
|
15
|
+
},
|
|
16
|
+
"homepage": "https://github.com/advenimus/syncromsp-mcp",
|
|
17
|
+
"license": "MIT",
|
|
18
|
+
"keywords": [
|
|
19
|
+
"syncro",
|
|
20
|
+
"syncromsp",
|
|
21
|
+
"msp",
|
|
22
|
+
"rmm",
|
|
23
|
+
"psa",
|
|
24
|
+
"it-management",
|
|
25
|
+
"mcp",
|
|
26
|
+
"model-context-protocol"
|
|
27
|
+
],
|
|
28
|
+
"server": {
|
|
29
|
+
"type": "node",
|
|
30
|
+
"entry_point": "dist/index.js",
|
|
31
|
+
"mcp_config": {
|
|
32
|
+
"command": "node",
|
|
33
|
+
"args": ["${__dirname}/dist/index.js"],
|
|
34
|
+
"env": {
|
|
35
|
+
"SYNCRO_API_KEY": "${user_config.syncro_api_key}",
|
|
36
|
+
"SYNCRO_SUBDOMAIN": "${user_config.syncro_subdomain}"
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
"tools_generated": true,
|
|
41
|
+
"user_config": {
|
|
42
|
+
"syncro_api_key": {
|
|
43
|
+
"type": "string",
|
|
44
|
+
"title": "Syncro API Key",
|
|
45
|
+
"description": "Your Syncro API key (found in Admin > API Tokens)",
|
|
46
|
+
"sensitive": true,
|
|
47
|
+
"required": true
|
|
48
|
+
},
|
|
49
|
+
"syncro_subdomain": {
|
|
50
|
+
"type": "string",
|
|
51
|
+
"title": "Syncro Subdomain",
|
|
52
|
+
"description": "Your Syncro subdomain (e.g., 'mycompany' from mycompany.syncromsp.com)",
|
|
53
|
+
"sensitive": false,
|
|
54
|
+
"required": true
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
"compatibility": {
|
|
58
|
+
"platforms": ["darwin", "win32", "linux"],
|
|
59
|
+
"runtimes": {
|
|
60
|
+
"node": ">=20.0.0"
|
|
61
|
+
},
|
|
62
|
+
"claude_desktop": ">=0.10.0"
|
|
63
|
+
}
|
|
64
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "syncromsp-mcp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "MCP server for SyncroMSP — full API coverage for tickets, customers, assets, invoices, and 30+ resource types",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"syncromsp-mcp": "dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist/",
|
|
12
|
+
"manifest.json",
|
|
13
|
+
"README.md",
|
|
14
|
+
"LICENSE"
|
|
15
|
+
],
|
|
16
|
+
"scripts": {
|
|
17
|
+
"build": "tsc",
|
|
18
|
+
"dev": "tsx src/index.ts",
|
|
19
|
+
"start": "node dist/index.js",
|
|
20
|
+
"test": "vitest run",
|
|
21
|
+
"test:watch": "vitest",
|
|
22
|
+
"lint": "eslint src/",
|
|
23
|
+
"prepublishOnly": "npm run build",
|
|
24
|
+
"validate:mcpb": "mcpb validate manifest.json"
|
|
25
|
+
},
|
|
26
|
+
"keywords": [
|
|
27
|
+
"mcp",
|
|
28
|
+
"syncro",
|
|
29
|
+
"syncromsp",
|
|
30
|
+
"msp",
|
|
31
|
+
"rmm",
|
|
32
|
+
"psa",
|
|
33
|
+
"it-management",
|
|
34
|
+
"model-context-protocol"
|
|
35
|
+
],
|
|
36
|
+
"author": "Advenimus",
|
|
37
|
+
"license": "MIT",
|
|
38
|
+
"repository": {
|
|
39
|
+
"type": "git",
|
|
40
|
+
"url": "https://github.com/advenimus/syncromsp-mcp.git"
|
|
41
|
+
},
|
|
42
|
+
"engines": {
|
|
43
|
+
"node": ">=20"
|
|
44
|
+
},
|
|
45
|
+
"dependencies": {
|
|
46
|
+
"@modelcontextprotocol/sdk": "^1.12.1",
|
|
47
|
+
"express": "^5.2.1",
|
|
48
|
+
"zod": "^3.24.4"
|
|
49
|
+
},
|
|
50
|
+
"devDependencies": {
|
|
51
|
+
"@types/express": "^5.0.6",
|
|
52
|
+
"@types/node": "^22.15.2",
|
|
53
|
+
"tsx": "^4.19.4",
|
|
54
|
+
"typescript": "^5.8.3",
|
|
55
|
+
"vitest": "^3.1.2"
|
|
56
|
+
}
|
|
57
|
+
}
|