@wilnertech/halopsa-mcp-server 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +19 -0
- package/LICENSE +21 -0
- package/README.md +270 -0
- package/dist/api/client.d.ts +85 -0
- package/dist/api/client.d.ts.map +1 -0
- package/dist/api/client.js +297 -0
- package/dist/api/client.js.map +1 -0
- package/dist/api/errors.d.ts +60 -0
- package/dist/api/errors.d.ts.map +1 -0
- package/dist/api/errors.js +188 -0
- package/dist/api/errors.js.map +1 -0
- package/dist/cache/memory-cache.d.ts +89 -0
- package/dist/cache/memory-cache.d.ts.map +1 -0
- package/dist/cache/memory-cache.js +175 -0
- package/dist/cache/memory-cache.js.map +1 -0
- package/dist/cache/prewarm.d.ts +12 -0
- package/dist/cache/prewarm.d.ts.map +1 -0
- package/dist/cache/prewarm.js +55 -0
- package/dist/cache/prewarm.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +141 -0
- package/dist/index.js.map +1 -0
- package/dist/schemas/common.d.ts +212 -0
- package/dist/schemas/common.d.ts.map +1 -0
- package/dist/schemas/common.js +127 -0
- package/dist/schemas/common.js.map +1 -0
- package/dist/tools/assets.d.ts +482 -0
- package/dist/tools/assets.d.ts.map +1 -0
- package/dist/tools/assets.js +732 -0
- package/dist/tools/assets.js.map +1 -0
- package/dist/tools/batch-operations.d.ts +125 -0
- package/dist/tools/batch-operations.d.ts.map +1 -0
- package/dist/tools/batch-operations.js +207 -0
- package/dist/tools/batch-operations.js.map +1 -0
- package/dist/tools/clients.d.ts +145 -0
- package/dist/tools/clients.d.ts.map +1 -0
- package/dist/tools/clients.js +148 -0
- package/dist/tools/clients.js.map +1 -0
- package/dist/tools/reference-data.d.ts +118 -0
- package/dist/tools/reference-data.d.ts.map +1 -0
- package/dist/tools/reference-data.js +103 -0
- package/dist/tools/reference-data.js.map +1 -0
- package/dist/tools/registrations.d.ts +7 -0
- package/dist/tools/registrations.d.ts.map +1 -0
- package/dist/tools/registrations.js +61 -0
- package/dist/tools/registrations.js.map +1 -0
- package/dist/tools/registry.d.ts +67 -0
- package/dist/tools/registry.d.ts.map +1 -0
- package/dist/tools/registry.js +71 -0
- package/dist/tools/registry.js.map +1 -0
- package/dist/tools/sites.d.ts +188 -0
- package/dist/tools/sites.d.ts.map +1 -0
- package/dist/tools/sites.js +258 -0
- package/dist/tools/sites.js.map +1 -0
- package/dist/tools/users.d.ts +317 -0
- package/dist/tools/users.d.ts.map +1 -0
- package/dist/tools/users.js +489 -0
- package/dist/tools/users.js.map +1 -0
- package/dist/types/halopsa.d.ts +212 -0
- package/dist/types/halopsa.d.ts.map +1 -0
- package/dist/types/halopsa.js +8 -0
- package/dist/types/halopsa.js.map +1 -0
- package/dist/utils/formatter.d.ts +18 -0
- package/dist/utils/formatter.d.ts.map +1 -0
- package/dist/utils/formatter.js +178 -0
- package/dist/utils/formatter.js.map +1 -0
- package/dist/utils/similarity.d.ts +25 -0
- package/dist/utils/similarity.d.ts.map +1 -0
- package/dist/utils/similarity.js +90 -0
- package/dist/utils/similarity.js.map +1 -0
- package/dist/utils/zod-to-schema.d.ts +29 -0
- package/dist/utils/zod-to-schema.d.ts.map +1 -0
- package/dist/utils/zod-to-schema.js +182 -0
- package/dist/utils/zod-to-schema.js.map +1 -0
- package/package.json +61 -0
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TypeScript type definitions for HaloPSA API objects
|
|
3
|
+
* Based on HaloPSA API documentation and WilnerTech requirements
|
|
4
|
+
*
|
|
5
|
+
* CRITICAL: These types support billing automation - accuracy is essential
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* HaloPSA Asset (Configuration Item)
|
|
9
|
+
* Primary entity for billing - asset counts determine client charges
|
|
10
|
+
*/
|
|
11
|
+
export interface HaloPSAAsset {
|
|
12
|
+
id: number;
|
|
13
|
+
inventory_number: string;
|
|
14
|
+
key_field: string;
|
|
15
|
+
key_field2: string;
|
|
16
|
+
assettype_id: number;
|
|
17
|
+
assettype_name: string;
|
|
18
|
+
status_id: number;
|
|
19
|
+
status_name: string;
|
|
20
|
+
site_id: number;
|
|
21
|
+
site_name: string;
|
|
22
|
+
client_id: number;
|
|
23
|
+
client_name: string;
|
|
24
|
+
warranty_end?: string;
|
|
25
|
+
last_seen?: string;
|
|
26
|
+
notes?: string;
|
|
27
|
+
fields: HaloPSACustomField[];
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Custom field in HaloPSA
|
|
31
|
+
* Used for extended asset/user data
|
|
32
|
+
*/
|
|
33
|
+
export interface HaloPSACustomField {
|
|
34
|
+
id: number;
|
|
35
|
+
name: string;
|
|
36
|
+
value: string | number | boolean | null;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* HaloPSA User
|
|
40
|
+
* Secondary billing entity - user counts contribute to billing
|
|
41
|
+
*/
|
|
42
|
+
export interface HaloPSAUser {
|
|
43
|
+
id: number;
|
|
44
|
+
name: string;
|
|
45
|
+
emailaddress: string;
|
|
46
|
+
username: string;
|
|
47
|
+
site_id: number;
|
|
48
|
+
site_name: string;
|
|
49
|
+
client_id: number;
|
|
50
|
+
client_name: string;
|
|
51
|
+
inactive: boolean;
|
|
52
|
+
user_customfields: HaloPSAUserCustomField[];
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* User custom field
|
|
56
|
+
* Important: UPN (User Principal Name) stored here for Entra sync
|
|
57
|
+
*/
|
|
58
|
+
export interface HaloPSAUserCustomField {
|
|
59
|
+
id: number;
|
|
60
|
+
name: string;
|
|
61
|
+
value: string;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* HaloPSA Site (Location)
|
|
65
|
+
* Organizational unit within a client
|
|
66
|
+
*/
|
|
67
|
+
export interface HaloPSASite {
|
|
68
|
+
id: number;
|
|
69
|
+
name: string;
|
|
70
|
+
client_id: number;
|
|
71
|
+
maincontact_name?: string;
|
|
72
|
+
phonenumber?: string;
|
|
73
|
+
notes?: string;
|
|
74
|
+
address?: HaloPSAAddress;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Address object for sites
|
|
78
|
+
*/
|
|
79
|
+
export interface HaloPSAAddress {
|
|
80
|
+
addressline1?: string;
|
|
81
|
+
addressline2?: string;
|
|
82
|
+
city?: string;
|
|
83
|
+
state?: string;
|
|
84
|
+
postalcode?: string;
|
|
85
|
+
country?: string;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* HaloPSA Client (Top-level organization)
|
|
89
|
+
*/
|
|
90
|
+
export interface HaloPSAClient {
|
|
91
|
+
id: number;
|
|
92
|
+
name: string;
|
|
93
|
+
inactive: boolean;
|
|
94
|
+
website?: string;
|
|
95
|
+
notes?: string;
|
|
96
|
+
phonenumber?: string;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* HaloPSA Asset Type (Reference data)
|
|
100
|
+
*/
|
|
101
|
+
export interface HaloPSAAssetType {
|
|
102
|
+
id: number;
|
|
103
|
+
name: string;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* HaloPSA Asset Status (Reference data)
|
|
107
|
+
* CRITICAL: status_id=1 (Active) determines billing eligibility
|
|
108
|
+
*/
|
|
109
|
+
export interface HaloPSAAssetStatus {
|
|
110
|
+
id: number;
|
|
111
|
+
name: string;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* HaloPSA Contact Type (Reference data)
|
|
115
|
+
*/
|
|
116
|
+
export interface HaloPSAContactType {
|
|
117
|
+
id: number;
|
|
118
|
+
name: string;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* API Response wrapper for list endpoints
|
|
122
|
+
* Note: HaloPSA returns named arrays (assets, users, sites, clients) depending on endpoint
|
|
123
|
+
*/
|
|
124
|
+
export interface HaloPSAListResponse<T> {
|
|
125
|
+
data: T[];
|
|
126
|
+
record_count: number;
|
|
127
|
+
page_count?: number;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Typed list response for assets
|
|
131
|
+
*/
|
|
132
|
+
export interface HaloPSAAssetListResponse {
|
|
133
|
+
assets: HaloPSAAsset[];
|
|
134
|
+
record_count: number;
|
|
135
|
+
page_count?: number;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Typed list response for users
|
|
139
|
+
*/
|
|
140
|
+
export interface HaloPSAUserListResponse {
|
|
141
|
+
users: HaloPSAUser[];
|
|
142
|
+
record_count: number;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Typed list response for sites
|
|
146
|
+
*/
|
|
147
|
+
export interface HaloPSASiteListResponse {
|
|
148
|
+
sites: HaloPSASite[];
|
|
149
|
+
record_count: number;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Typed list response for clients
|
|
153
|
+
*/
|
|
154
|
+
export interface HaloPSAClientListResponse {
|
|
155
|
+
clients: HaloPSAClient[];
|
|
156
|
+
record_count: number;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Query parameters for HaloPSA API requests
|
|
160
|
+
*/
|
|
161
|
+
export interface HaloPSAQueryParams {
|
|
162
|
+
count?: number;
|
|
163
|
+
page_no?: number;
|
|
164
|
+
pageinate?: boolean;
|
|
165
|
+
order?: string;
|
|
166
|
+
orderdesc?: boolean;
|
|
167
|
+
search?: string;
|
|
168
|
+
client_id?: number;
|
|
169
|
+
site_id?: number;
|
|
170
|
+
assettype_id?: number;
|
|
171
|
+
status_id?: number;
|
|
172
|
+
includeactive?: boolean;
|
|
173
|
+
includeinactive?: boolean;
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Deduplication result with confidence scoring
|
|
177
|
+
* Used for asset/user/site matching operations
|
|
178
|
+
*/
|
|
179
|
+
export interface DeduplicationResult {
|
|
180
|
+
match: HaloPSAAsset | HaloPSAUser | HaloPSASite | null;
|
|
181
|
+
confidence: number;
|
|
182
|
+
matchField: string;
|
|
183
|
+
action: 'Update' | 'CreateNew' | 'ManualReview';
|
|
184
|
+
warning?: string;
|
|
185
|
+
matches?: Array<HaloPSAAsset | HaloPSAUser | HaloPSASite>;
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Duplicate group for scan results
|
|
189
|
+
*/
|
|
190
|
+
export interface DuplicateGroup {
|
|
191
|
+
type: 'asset' | 'user' | 'site';
|
|
192
|
+
matchField: string;
|
|
193
|
+
matchValue: string;
|
|
194
|
+
confidence: 'High' | 'Medium';
|
|
195
|
+
asset_count: number;
|
|
196
|
+
entities: Array<{
|
|
197
|
+
id: number;
|
|
198
|
+
name: string;
|
|
199
|
+
[key: string]: unknown;
|
|
200
|
+
}>;
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Asset field schema for custom field inspection
|
|
204
|
+
*/
|
|
205
|
+
export interface AssetFieldSchema {
|
|
206
|
+
field_id: number;
|
|
207
|
+
name: string;
|
|
208
|
+
sample_values: Array<string | number | boolean | null>;
|
|
209
|
+
value_type: 'string' | 'number' | 'boolean' | 'null' | 'mixed';
|
|
210
|
+
usage_count: number;
|
|
211
|
+
}
|
|
212
|
+
//# sourceMappingURL=halopsa.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"halopsa.d.ts","sourceRoot":"","sources":["../../src/types/halopsa.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"halopsa.js","sourceRoot":"","sources":["../../src/types/halopsa.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Response formatting utilities for token optimization
|
|
3
|
+
* Provides compact, standard, and detailed output modes for HaloPSA responses
|
|
4
|
+
*/
|
|
5
|
+
export interface FormatOptions {
|
|
6
|
+
format?: 'compact' | 'standard' | 'detailed';
|
|
7
|
+
fields?: string[];
|
|
8
|
+
omit_empty?: boolean;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Format a response object based on options
|
|
12
|
+
* @param data - The data to format (single object or array)
|
|
13
|
+
* @param options - Formatting options
|
|
14
|
+
* @param meta - Optional metadata (pagination, counts)
|
|
15
|
+
* @returns JSON string formatted according to options
|
|
16
|
+
*/
|
|
17
|
+
export declare function formatResponse<T>(data: T | T[], options?: FormatOptions, meta?: Record<string, unknown>): string;
|
|
18
|
+
//# sourceMappingURL=formatter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatter.d.ts","sourceRoot":"","sources":["../../src/utils/formatter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,EAAE,SAAS,GAAG,UAAU,GAAG,UAAU,CAAC;IAC7C,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAC9B,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE,EACb,OAAO,GAAE,aAAkB,EAC3B,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,MAAM,CA0CR"}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Response formatting utilities for token optimization
|
|
3
|
+
* Provides compact, standard, and detailed output modes for HaloPSA responses
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Format a response object based on options
|
|
7
|
+
* @param data - The data to format (single object or array)
|
|
8
|
+
* @param options - Formatting options
|
|
9
|
+
* @param meta - Optional metadata (pagination, counts)
|
|
10
|
+
* @returns JSON string formatted according to options
|
|
11
|
+
*/
|
|
12
|
+
export function formatResponse(data, options = {}, meta) {
|
|
13
|
+
const { format = 'standard', fields, omit_empty = false, } = options;
|
|
14
|
+
// Process data
|
|
15
|
+
let processedData;
|
|
16
|
+
if (Array.isArray(data)) {
|
|
17
|
+
processedData = data.map((item) => processItem(item, fields, omit_empty, format));
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
processedData = processItem(data, fields, omit_empty, format);
|
|
21
|
+
}
|
|
22
|
+
// Build result object
|
|
23
|
+
const result = Array.isArray(data)
|
|
24
|
+
? { data: processedData }
|
|
25
|
+
: processedData;
|
|
26
|
+
// Add metadata if provided and data is array
|
|
27
|
+
if (meta && Array.isArray(data)) {
|
|
28
|
+
result.meta = meta;
|
|
29
|
+
}
|
|
30
|
+
// Return with appropriate formatting
|
|
31
|
+
switch (format) {
|
|
32
|
+
case 'compact':
|
|
33
|
+
// No pretty printing, minimal whitespace
|
|
34
|
+
return JSON.stringify(result);
|
|
35
|
+
case 'standard':
|
|
36
|
+
// No pretty printing but clean structure
|
|
37
|
+
return JSON.stringify(result);
|
|
38
|
+
case 'detailed':
|
|
39
|
+
// Pretty printed with indentation
|
|
40
|
+
return JSON.stringify(result, null, 2);
|
|
41
|
+
default:
|
|
42
|
+
return JSON.stringify(result);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Process a single item based on formatting options
|
|
47
|
+
*/
|
|
48
|
+
function processItem(item, fields, omitEmpty, format) {
|
|
49
|
+
// Guard against null/undefined items
|
|
50
|
+
if (item === null || item === undefined || typeof item !== 'object') {
|
|
51
|
+
return item;
|
|
52
|
+
}
|
|
53
|
+
let processed = { ...item };
|
|
54
|
+
// Apply field filtering
|
|
55
|
+
if (fields && fields.length > 0) {
|
|
56
|
+
processed = filterFields(processed, fields);
|
|
57
|
+
}
|
|
58
|
+
// Remove empty fields if requested
|
|
59
|
+
if (omitEmpty) {
|
|
60
|
+
processed = removeEmptyFields(processed);
|
|
61
|
+
}
|
|
62
|
+
// For compact mode, further reduce data
|
|
63
|
+
if (format === 'compact') {
|
|
64
|
+
processed = compactItem(processed);
|
|
65
|
+
}
|
|
66
|
+
return processed;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Filter object to only include specified fields
|
|
70
|
+
*/
|
|
71
|
+
function filterFields(obj, fields) {
|
|
72
|
+
const filtered = {};
|
|
73
|
+
for (const field of fields) {
|
|
74
|
+
// Support nested field access with dot notation
|
|
75
|
+
if (field.includes('.')) {
|
|
76
|
+
const parts = field.split('.');
|
|
77
|
+
const value = getNestedValue(obj, parts);
|
|
78
|
+
if (value !== undefined) {
|
|
79
|
+
setNestedValue(filtered, parts, value);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
if (field in obj) {
|
|
84
|
+
filtered[field] = obj[field];
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return filtered;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Remove fields with null, undefined, or empty string values
|
|
92
|
+
*/
|
|
93
|
+
function removeEmptyFields(obj) {
|
|
94
|
+
const cleaned = {};
|
|
95
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
96
|
+
if (value !== null && value !== undefined && value !== '') {
|
|
97
|
+
// Recursively clean nested objects
|
|
98
|
+
if (typeof value === 'object' && !Array.isArray(value)) {
|
|
99
|
+
const cleanedNested = removeEmptyFields(value);
|
|
100
|
+
if (Object.keys(cleanedNested).length > 0) {
|
|
101
|
+
cleaned[key] = cleanedNested;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
cleaned[key] = value;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return cleaned;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Create compact representation of an item
|
|
113
|
+
* Removes verbose fields, keeps only essentials
|
|
114
|
+
*/
|
|
115
|
+
function compactItem(item) {
|
|
116
|
+
const compact = {};
|
|
117
|
+
// Always include id and name if present
|
|
118
|
+
if ('id' in item)
|
|
119
|
+
compact.id = item.id;
|
|
120
|
+
if ('name' in item)
|
|
121
|
+
compact.name = item.name;
|
|
122
|
+
// Include status fields if present (billing critical)
|
|
123
|
+
if ('status_id' in item)
|
|
124
|
+
compact.status_id = item.status_id;
|
|
125
|
+
if ('status_name' in item)
|
|
126
|
+
compact.status_name = item.status_name;
|
|
127
|
+
if ('inactive' in item)
|
|
128
|
+
compact.inactive = item.inactive;
|
|
129
|
+
// Include key identifiers for HaloPSA
|
|
130
|
+
if ('key_field' in item && item.key_field) {
|
|
131
|
+
compact.serial_number = item.key_field;
|
|
132
|
+
}
|
|
133
|
+
if ('key_field2' in item && item.key_field2) {
|
|
134
|
+
compact.hostname = item.key_field2;
|
|
135
|
+
}
|
|
136
|
+
if ('emailaddress' in item && item.emailaddress) {
|
|
137
|
+
compact.email = item.emailaddress;
|
|
138
|
+
}
|
|
139
|
+
if ('inventory_number' in item && item.inventory_number) {
|
|
140
|
+
compact.inventory_number = item.inventory_number;
|
|
141
|
+
}
|
|
142
|
+
// Include client/site references
|
|
143
|
+
if ('client_id' in item)
|
|
144
|
+
compact.client_id = item.client_id;
|
|
145
|
+
if ('client_name' in item)
|
|
146
|
+
compact.client_name = item.client_name;
|
|
147
|
+
return compact;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Get nested value from object using path parts
|
|
151
|
+
*/
|
|
152
|
+
function getNestedValue(obj, parts) {
|
|
153
|
+
let current = obj;
|
|
154
|
+
for (const part of parts) {
|
|
155
|
+
if (current && typeof current === 'object' && part in current) {
|
|
156
|
+
current = current[part];
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
return undefined;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return current;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Set nested value in object using path parts
|
|
166
|
+
*/
|
|
167
|
+
function setNestedValue(obj, parts, value) {
|
|
168
|
+
let current = obj;
|
|
169
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
170
|
+
const part = parts[i];
|
|
171
|
+
if (!(part in current)) {
|
|
172
|
+
current[part] = {};
|
|
173
|
+
}
|
|
174
|
+
current = current[part];
|
|
175
|
+
}
|
|
176
|
+
current[parts[parts.length - 1]] = value;
|
|
177
|
+
}
|
|
178
|
+
//# sourceMappingURL=formatter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatter.js","sourceRoot":"","sources":["../../src/utils/formatter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* String similarity algorithms for deduplication
|
|
3
|
+
* Used for fuzzy matching in site/organization name comparisons
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Calculate Levenshtein distance between two strings
|
|
7
|
+
* Returns the minimum number of single-character edits required to change one string into another
|
|
8
|
+
*/
|
|
9
|
+
export declare function getLevenshteinDistance(str1: string, str2: string): number;
|
|
10
|
+
/**
|
|
11
|
+
* Calculate similarity percentage between two strings using Levenshtein distance
|
|
12
|
+
* Returns a value between 0 (completely different) and 1 (identical)
|
|
13
|
+
*/
|
|
14
|
+
export declare function getStringSimilarity(str1: string, str2: string): number;
|
|
15
|
+
/**
|
|
16
|
+
* Normalize an address string for comparison
|
|
17
|
+
* Removes common variations to improve matching
|
|
18
|
+
*/
|
|
19
|
+
export declare function normalizeAddress(address: string): string;
|
|
20
|
+
/**
|
|
21
|
+
* Compare two addresses with normalization
|
|
22
|
+
* Returns similarity score between 0 and 1
|
|
23
|
+
*/
|
|
24
|
+
export declare function getAddressSimilarity(addr1: string, addr2: string): number;
|
|
25
|
+
//# sourceMappingURL=similarity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"similarity.d.ts","sourceRoot":"","sources":["../../src/utils/similarity.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CA8BzE;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAoBtE;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAqBxD;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAKzE"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* String similarity algorithms for deduplication
|
|
3
|
+
* Used for fuzzy matching in site/organization name comparisons
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Calculate Levenshtein distance between two strings
|
|
7
|
+
* Returns the minimum number of single-character edits required to change one string into another
|
|
8
|
+
*/
|
|
9
|
+
export function getLevenshteinDistance(str1, str2) {
|
|
10
|
+
const len1 = str1.length;
|
|
11
|
+
const len2 = str2.length;
|
|
12
|
+
// Create distance matrix
|
|
13
|
+
const matrix = Array(len1 + 1)
|
|
14
|
+
.fill(null)
|
|
15
|
+
.map(() => Array(len2 + 1).fill(0));
|
|
16
|
+
// Initialize first row and column
|
|
17
|
+
for (let i = 0; i <= len1; i++) {
|
|
18
|
+
matrix[i][0] = i;
|
|
19
|
+
}
|
|
20
|
+
for (let j = 0; j <= len2; j++) {
|
|
21
|
+
matrix[0][j] = j;
|
|
22
|
+
}
|
|
23
|
+
// Calculate distance
|
|
24
|
+
for (let i = 1; i <= len1; i++) {
|
|
25
|
+
for (let j = 1; j <= len2; j++) {
|
|
26
|
+
const cost = str1[i - 1] === str2[j - 1] ? 0 : 1;
|
|
27
|
+
matrix[i][j] = Math.min(matrix[i - 1][j] + 1, // deletion
|
|
28
|
+
matrix[i][j - 1] + 1, // insertion
|
|
29
|
+
matrix[i - 1][j - 1] + cost // substitution
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return matrix[len1][len2];
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Calculate similarity percentage between two strings using Levenshtein distance
|
|
37
|
+
* Returns a value between 0 (completely different) and 1 (identical)
|
|
38
|
+
*/
|
|
39
|
+
export function getStringSimilarity(str1, str2) {
|
|
40
|
+
if (!str1 || !str2) {
|
|
41
|
+
return 0;
|
|
42
|
+
}
|
|
43
|
+
// Normalize: lowercase, trim whitespace
|
|
44
|
+
const normalized1 = str1.toLowerCase().trim();
|
|
45
|
+
const normalized2 = str2.toLowerCase().trim();
|
|
46
|
+
if (normalized1 === normalized2) {
|
|
47
|
+
return 1;
|
|
48
|
+
}
|
|
49
|
+
const maxLength = Math.max(normalized1.length, normalized2.length);
|
|
50
|
+
const distance = getLevenshteinDistance(normalized1, normalized2);
|
|
51
|
+
// Convert distance to similarity percentage
|
|
52
|
+
const similarity = 1 - distance / maxLength;
|
|
53
|
+
return Math.round(similarity * 100) / 100; // Round to 2 decimal places
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Normalize an address string for comparison
|
|
57
|
+
* Removes common variations to improve matching
|
|
58
|
+
*/
|
|
59
|
+
export function normalizeAddress(address) {
|
|
60
|
+
if (!address)
|
|
61
|
+
return '';
|
|
62
|
+
return address
|
|
63
|
+
.toLowerCase()
|
|
64
|
+
.trim()
|
|
65
|
+
// Normalize common abbreviations
|
|
66
|
+
.replace(/\bstreet\b/g, 'st')
|
|
67
|
+
.replace(/\bavenue\b/g, 'ave')
|
|
68
|
+
.replace(/\bboulevard\b/g, 'blvd')
|
|
69
|
+
.replace(/\bdrive\b/g, 'dr')
|
|
70
|
+
.replace(/\broad\b/g, 'rd')
|
|
71
|
+
.replace(/\blane\b/g, 'ln')
|
|
72
|
+
.replace(/\bcourt\b/g, 'ct')
|
|
73
|
+
.replace(/\bapartment\b/g, 'apt')
|
|
74
|
+
.replace(/\bsuite\b/g, 'ste')
|
|
75
|
+
.replace(/\bbuilding\b/g, 'bldg')
|
|
76
|
+
// Remove punctuation
|
|
77
|
+
.replace(/[.,#]/g, '')
|
|
78
|
+
// Normalize whitespace
|
|
79
|
+
.replace(/\s+/g, ' ');
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Compare two addresses with normalization
|
|
83
|
+
* Returns similarity score between 0 and 1
|
|
84
|
+
*/
|
|
85
|
+
export function getAddressSimilarity(addr1, addr2) {
|
|
86
|
+
const normalized1 = normalizeAddress(addr1);
|
|
87
|
+
const normalized2 = normalizeAddress(addr2);
|
|
88
|
+
return getStringSimilarity(normalized1, normalized2);
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=similarity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"similarity.js","sourceRoot":"","sources":["../../src/utils/similarity.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Converts Zod schemas to MCP-compatible JSON Schema objects.
|
|
3
|
+
*
|
|
4
|
+
* The MCP SDK expects inputSchema as:
|
|
5
|
+
* { type: 'object', properties: Record<string, unknown>, required?: string[] }
|
|
6
|
+
*
|
|
7
|
+
* This utility traverses Zod's internal _def structure to produce that shape,
|
|
8
|
+
* handling the types used across ITGlue MCP tool schemas: string, number,
|
|
9
|
+
* boolean, array, object, enum, literal, optional, default, and effects
|
|
10
|
+
* (z.coerce). Descriptions and numeric min/max checks are preserved.
|
|
11
|
+
*/
|
|
12
|
+
import { z } from 'zod';
|
|
13
|
+
/**
|
|
14
|
+
* MCP-compatible JSON Schema for a tool's inputSchema.
|
|
15
|
+
*/
|
|
16
|
+
interface McpInputSchema {
|
|
17
|
+
type: 'object';
|
|
18
|
+
properties: Record<string, unknown>;
|
|
19
|
+
required?: string[];
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Convert a top-level Zod object schema to an MCP-compatible inputSchema.
|
|
23
|
+
*
|
|
24
|
+
* The input is expected to be a z.ZodObject (possibly wrapped in optional/effects).
|
|
25
|
+
* Returns { type: 'object', properties: {...}, required?: [...] }.
|
|
26
|
+
*/
|
|
27
|
+
export declare function zodToJsonSchema(schema: z.ZodType): McpInputSchema;
|
|
28
|
+
export {};
|
|
29
|
+
//# sourceMappingURL=zod-to-schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"zod-to-schema.d.ts","sourceRoot":"","sources":["../../src/utils/zod-to-schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;GAEG;AACH,UAAU,cAAc;IACtB,IAAI,EAAE,QAAQ,CAAC;IACf,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAkLD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,GAAG,cAAc,CASjE"}
|