@hasna/microservices 0.0.3 → 0.0.5

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.
Files changed (68) hide show
  1. package/bin/index.js +63 -0
  2. package/bin/mcp.js +63 -0
  3. package/dist/index.js +63 -0
  4. package/microservices/microservice-ads/package.json +27 -0
  5. package/microservices/microservice-ads/src/cli/index.ts +605 -0
  6. package/microservices/microservice-ads/src/db/campaigns.ts +797 -0
  7. package/microservices/microservice-ads/src/db/database.ts +93 -0
  8. package/microservices/microservice-ads/src/db/migrations.ts +60 -0
  9. package/microservices/microservice-ads/src/index.ts +39 -0
  10. package/microservices/microservice-ads/src/mcp/index.ts +480 -0
  11. package/microservices/microservice-contracts/package.json +27 -0
  12. package/microservices/microservice-contracts/src/cli/index.ts +770 -0
  13. package/microservices/microservice-contracts/src/db/contracts.ts +925 -0
  14. package/microservices/microservice-contracts/src/db/database.ts +93 -0
  15. package/microservices/microservice-contracts/src/db/migrations.ts +141 -0
  16. package/microservices/microservice-contracts/src/index.ts +43 -0
  17. package/microservices/microservice-contracts/src/mcp/index.ts +617 -0
  18. package/microservices/microservice-domains/package.json +27 -0
  19. package/microservices/microservice-domains/src/cli/index.ts +691 -0
  20. package/microservices/microservice-domains/src/db/database.ts +93 -0
  21. package/microservices/microservice-domains/src/db/domains.ts +1164 -0
  22. package/microservices/microservice-domains/src/db/migrations.ts +60 -0
  23. package/microservices/microservice-domains/src/index.ts +65 -0
  24. package/microservices/microservice-domains/src/mcp/index.ts +536 -0
  25. package/microservices/microservice-hiring/package.json +27 -0
  26. package/microservices/microservice-hiring/src/cli/index.ts +741 -0
  27. package/microservices/microservice-hiring/src/db/database.ts +93 -0
  28. package/microservices/microservice-hiring/src/db/hiring.ts +1085 -0
  29. package/microservices/microservice-hiring/src/db/migrations.ts +89 -0
  30. package/microservices/microservice-hiring/src/index.ts +80 -0
  31. package/microservices/microservice-hiring/src/lib/scoring.ts +206 -0
  32. package/microservices/microservice-hiring/src/mcp/index.ts +709 -0
  33. package/microservices/microservice-payments/package.json +27 -0
  34. package/microservices/microservice-payments/src/cli/index.ts +609 -0
  35. package/microservices/microservice-payments/src/db/database.ts +93 -0
  36. package/microservices/microservice-payments/src/db/migrations.ts +81 -0
  37. package/microservices/microservice-payments/src/db/payments.ts +1204 -0
  38. package/microservices/microservice-payments/src/index.ts +51 -0
  39. package/microservices/microservice-payments/src/mcp/index.ts +683 -0
  40. package/microservices/microservice-payroll/package.json +27 -0
  41. package/microservices/microservice-payroll/src/cli/index.ts +643 -0
  42. package/microservices/microservice-payroll/src/db/database.ts +93 -0
  43. package/microservices/microservice-payroll/src/db/migrations.ts +95 -0
  44. package/microservices/microservice-payroll/src/db/payroll.ts +1377 -0
  45. package/microservices/microservice-payroll/src/index.ts +48 -0
  46. package/microservices/microservice-payroll/src/mcp/index.ts +666 -0
  47. package/microservices/microservice-shipping/package.json +27 -0
  48. package/microservices/microservice-shipping/src/cli/index.ts +606 -0
  49. package/microservices/microservice-shipping/src/db/database.ts +93 -0
  50. package/microservices/microservice-shipping/src/db/migrations.ts +69 -0
  51. package/microservices/microservice-shipping/src/db/shipping.ts +1093 -0
  52. package/microservices/microservice-shipping/src/index.ts +53 -0
  53. package/microservices/microservice-shipping/src/mcp/index.ts +533 -0
  54. package/microservices/microservice-social/package.json +27 -0
  55. package/microservices/microservice-social/src/cli/index.ts +689 -0
  56. package/microservices/microservice-social/src/db/database.ts +93 -0
  57. package/microservices/microservice-social/src/db/migrations.ts +88 -0
  58. package/microservices/microservice-social/src/db/social.ts +1046 -0
  59. package/microservices/microservice-social/src/index.ts +46 -0
  60. package/microservices/microservice-social/src/mcp/index.ts +655 -0
  61. package/microservices/microservice-subscriptions/package.json +27 -0
  62. package/microservices/microservice-subscriptions/src/cli/index.ts +715 -0
  63. package/microservices/microservice-subscriptions/src/db/database.ts +93 -0
  64. package/microservices/microservice-subscriptions/src/db/migrations.ts +125 -0
  65. package/microservices/microservice-subscriptions/src/db/subscriptions.ts +1256 -0
  66. package/microservices/microservice-subscriptions/src/index.ts +41 -0
  67. package/microservices/microservice-subscriptions/src/mcp/index.ts +631 -0
  68. package/package.json +1 -1
@@ -0,0 +1,60 @@
1
+ export interface MigrationEntry {
2
+ id: number;
3
+ name: string;
4
+ sql: string;
5
+ }
6
+
7
+ export const MIGRATIONS: MigrationEntry[] = [
8
+ {
9
+ id: 1,
10
+ name: "initial_schema",
11
+ sql: `
12
+ CREATE TABLE IF NOT EXISTS domains (
13
+ id TEXT PRIMARY KEY,
14
+ name TEXT NOT NULL UNIQUE,
15
+ registrar TEXT,
16
+ status TEXT NOT NULL DEFAULT 'active' CHECK (status IN ('active', 'expired', 'transferring', 'redemption')),
17
+ registered_at TEXT,
18
+ expires_at TEXT,
19
+ auto_renew INTEGER NOT NULL DEFAULT 1,
20
+ nameservers TEXT NOT NULL DEFAULT '[]',
21
+ whois TEXT NOT NULL DEFAULT '{}',
22
+ ssl_expires_at TEXT,
23
+ ssl_issuer TEXT,
24
+ notes TEXT,
25
+ metadata TEXT NOT NULL DEFAULT '{}',
26
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
27
+ updated_at TEXT NOT NULL DEFAULT (datetime('now'))
28
+ );
29
+
30
+ CREATE TABLE IF NOT EXISTS dns_records (
31
+ id TEXT PRIMARY KEY,
32
+ domain_id TEXT NOT NULL REFERENCES domains(id) ON DELETE CASCADE,
33
+ type TEXT NOT NULL CHECK (type IN ('A', 'AAAA', 'CNAME', 'MX', 'TXT', 'NS', 'SRV')),
34
+ name TEXT NOT NULL,
35
+ value TEXT NOT NULL,
36
+ ttl INTEGER NOT NULL DEFAULT 3600,
37
+ priority INTEGER,
38
+ created_at TEXT NOT NULL DEFAULT (datetime('now'))
39
+ );
40
+
41
+ CREATE TABLE IF NOT EXISTS alerts (
42
+ id TEXT PRIMARY KEY,
43
+ domain_id TEXT NOT NULL REFERENCES domains(id) ON DELETE CASCADE,
44
+ type TEXT NOT NULL CHECK (type IN ('expiry', 'ssl_expiry', 'dns_change')),
45
+ trigger_days_before INTEGER,
46
+ sent_at TEXT,
47
+ created_at TEXT NOT NULL DEFAULT (datetime('now'))
48
+ );
49
+
50
+ CREATE INDEX IF NOT EXISTS idx_domains_name ON domains(name);
51
+ CREATE INDEX IF NOT EXISTS idx_domains_registrar ON domains(registrar);
52
+ CREATE INDEX IF NOT EXISTS idx_domains_status ON domains(status);
53
+ CREATE INDEX IF NOT EXISTS idx_domains_expires_at ON domains(expires_at);
54
+ CREATE INDEX IF NOT EXISTS idx_dns_records_domain ON dns_records(domain_id);
55
+ CREATE INDEX IF NOT EXISTS idx_dns_records_type ON dns_records(type);
56
+ CREATE INDEX IF NOT EXISTS idx_alerts_domain ON alerts(domain_id);
57
+ CREATE INDEX IF NOT EXISTS idx_alerts_type ON alerts(type);
58
+ `,
59
+ },
60
+ ];
@@ -0,0 +1,65 @@
1
+ /**
2
+ * microservice-domains — Domain portfolio and DNS management microservice
3
+ */
4
+
5
+ export {
6
+ createDomain,
7
+ getDomain,
8
+ listDomains,
9
+ updateDomain,
10
+ deleteDomain,
11
+ countDomains,
12
+ searchDomains,
13
+ getByRegistrar,
14
+ listExpiring,
15
+ listSslExpiring,
16
+ getDomainStats,
17
+ getDomainByName,
18
+ type Domain,
19
+ type CreateDomainInput,
20
+ type UpdateDomainInput,
21
+ type ListDomainsOptions,
22
+ type DomainStats,
23
+ } from "./db/domains.js";
24
+
25
+ export {
26
+ createDnsRecord,
27
+ getDnsRecord,
28
+ listDnsRecords,
29
+ updateDnsRecord,
30
+ deleteDnsRecord,
31
+ type DnsRecord,
32
+ type CreateDnsRecordInput,
33
+ type UpdateDnsRecordInput,
34
+ } from "./db/domains.js";
35
+
36
+ export {
37
+ createAlert,
38
+ getAlert,
39
+ listAlerts,
40
+ deleteAlert,
41
+ type Alert,
42
+ type CreateAlertInput,
43
+ } from "./db/domains.js";
44
+
45
+ export {
46
+ whoisLookup,
47
+ checkDnsPropagation,
48
+ checkSsl,
49
+ exportZoneFile,
50
+ importZoneFile,
51
+ discoverSubdomains,
52
+ validateDns,
53
+ exportPortfolio,
54
+ checkAllDomains,
55
+ type WhoisResult,
56
+ type DnsPropagationResult,
57
+ type SslCheckResult,
58
+ type ZoneImportResult,
59
+ type SubdomainResult,
60
+ type DnsValidationIssue,
61
+ type DnsValidationResult,
62
+ type BulkCheckResult,
63
+ } from "./db/domains.js";
64
+
65
+ export { getDatabase, closeDatabase } from "./db/database.js";
@@ -0,0 +1,536 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
4
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
5
+ import { z } from "zod";
6
+ import {
7
+ createDomain,
8
+ getDomain,
9
+ listDomains,
10
+ updateDomain,
11
+ deleteDomain,
12
+ countDomains,
13
+ searchDomains,
14
+ getByRegistrar,
15
+ listExpiring,
16
+ listSslExpiring,
17
+ getDomainStats,
18
+ createDnsRecord,
19
+ listDnsRecords,
20
+ updateDnsRecord,
21
+ deleteDnsRecord,
22
+ createAlert,
23
+ listAlerts,
24
+ deleteAlert,
25
+ whoisLookup,
26
+ checkDnsPropagation,
27
+ checkSsl,
28
+ exportZoneFile,
29
+ importZoneFile,
30
+ discoverSubdomains,
31
+ validateDns,
32
+ exportPortfolio,
33
+ checkAllDomains,
34
+ } from "../db/domains.js";
35
+
36
+ const server = new McpServer({
37
+ name: "microservice-domains",
38
+ version: "0.0.1",
39
+ });
40
+
41
+ // --- Domains ---
42
+
43
+ server.registerTool(
44
+ "create_domain",
45
+ {
46
+ title: "Create Domain",
47
+ description: "Add a new domain to the portfolio.",
48
+ inputSchema: {
49
+ name: z.string(),
50
+ registrar: z.string().optional(),
51
+ status: z.enum(["active", "expired", "transferring", "redemption"]).optional(),
52
+ registered_at: z.string().optional(),
53
+ expires_at: z.string().optional(),
54
+ auto_renew: z.boolean().optional(),
55
+ nameservers: z.array(z.string()).optional(),
56
+ ssl_expires_at: z.string().optional(),
57
+ ssl_issuer: z.string().optional(),
58
+ notes: z.string().optional(),
59
+ },
60
+ },
61
+ async (params) => {
62
+ const domain = createDomain(params);
63
+ return { content: [{ type: "text", text: JSON.stringify(domain, null, 2) }] };
64
+ }
65
+ );
66
+
67
+ server.registerTool(
68
+ "get_domain",
69
+ {
70
+ title: "Get Domain",
71
+ description: "Get a domain by ID.",
72
+ inputSchema: { id: z.string() },
73
+ },
74
+ async ({ id }) => {
75
+ const domain = getDomain(id);
76
+ if (!domain) {
77
+ return { content: [{ type: "text", text: `Domain '${id}' not found.` }], isError: true };
78
+ }
79
+ return { content: [{ type: "text", text: JSON.stringify(domain, null, 2) }] };
80
+ }
81
+ );
82
+
83
+ server.registerTool(
84
+ "list_domains",
85
+ {
86
+ title: "List Domains",
87
+ description: "List domains with optional filters.",
88
+ inputSchema: {
89
+ search: z.string().optional(),
90
+ status: z.enum(["active", "expired", "transferring", "redemption"]).optional(),
91
+ registrar: z.string().optional(),
92
+ limit: z.number().optional(),
93
+ },
94
+ },
95
+ async (params) => {
96
+ const domains = listDomains(params);
97
+ return {
98
+ content: [
99
+ { type: "text", text: JSON.stringify({ domains, count: domains.length }, null, 2) },
100
+ ],
101
+ };
102
+ }
103
+ );
104
+
105
+ server.registerTool(
106
+ "update_domain",
107
+ {
108
+ title: "Update Domain",
109
+ description: "Update an existing domain.",
110
+ inputSchema: {
111
+ id: z.string(),
112
+ name: z.string().optional(),
113
+ registrar: z.string().optional(),
114
+ status: z.enum(["active", "expired", "transferring", "redemption"]).optional(),
115
+ registered_at: z.string().optional(),
116
+ expires_at: z.string().optional(),
117
+ auto_renew: z.boolean().optional(),
118
+ nameservers: z.array(z.string()).optional(),
119
+ ssl_expires_at: z.string().optional(),
120
+ ssl_issuer: z.string().optional(),
121
+ notes: z.string().optional(),
122
+ },
123
+ },
124
+ async ({ id, ...input }) => {
125
+ const domain = updateDomain(id, input);
126
+ if (!domain) {
127
+ return { content: [{ type: "text", text: `Domain '${id}' not found.` }], isError: true };
128
+ }
129
+ return { content: [{ type: "text", text: JSON.stringify(domain, null, 2) }] };
130
+ }
131
+ );
132
+
133
+ server.registerTool(
134
+ "delete_domain",
135
+ {
136
+ title: "Delete Domain",
137
+ description: "Delete a domain by ID.",
138
+ inputSchema: { id: z.string() },
139
+ },
140
+ async ({ id }) => {
141
+ const deleted = deleteDomain(id);
142
+ return { content: [{ type: "text", text: JSON.stringify({ id, deleted }) }] };
143
+ }
144
+ );
145
+
146
+ server.registerTool(
147
+ "search_domains",
148
+ {
149
+ title: "Search Domains",
150
+ description: "Search domains by name, registrar, or notes.",
151
+ inputSchema: { query: z.string() },
152
+ },
153
+ async ({ query }) => {
154
+ const results = searchDomains(query);
155
+ return {
156
+ content: [
157
+ { type: "text", text: JSON.stringify({ results, count: results.length }, null, 2) },
158
+ ],
159
+ };
160
+ }
161
+ );
162
+
163
+ server.registerTool(
164
+ "count_domains",
165
+ {
166
+ title: "Count Domains",
167
+ description: "Get the total number of domains.",
168
+ inputSchema: {},
169
+ },
170
+ async () => {
171
+ const count = countDomains();
172
+ return { content: [{ type: "text", text: JSON.stringify({ count }) }] };
173
+ }
174
+ );
175
+
176
+ server.registerTool(
177
+ "list_expiring_domains",
178
+ {
179
+ title: "List Expiring Domains",
180
+ description: "List domains expiring within N days.",
181
+ inputSchema: { days: z.number().default(30) },
182
+ },
183
+ async ({ days }) => {
184
+ const domains = listExpiring(days);
185
+ return {
186
+ content: [
187
+ { type: "text", text: JSON.stringify({ domains, count: domains.length }, null, 2) },
188
+ ],
189
+ };
190
+ }
191
+ );
192
+
193
+ server.registerTool(
194
+ "list_ssl_expiring",
195
+ {
196
+ title: "List SSL Expiring",
197
+ description: "List domains with SSL certificates expiring within N days.",
198
+ inputSchema: { days: z.number().default(30) },
199
+ },
200
+ async ({ days }) => {
201
+ const domains = listSslExpiring(days);
202
+ return {
203
+ content: [
204
+ { type: "text", text: JSON.stringify({ domains, count: domains.length }, null, 2) },
205
+ ],
206
+ };
207
+ }
208
+ );
209
+
210
+ server.registerTool(
211
+ "get_domains_by_registrar",
212
+ {
213
+ title: "Get Domains by Registrar",
214
+ description: "List all domains from a specific registrar.",
215
+ inputSchema: { registrar: z.string() },
216
+ },
217
+ async ({ registrar }) => {
218
+ const domains = getByRegistrar(registrar);
219
+ return {
220
+ content: [
221
+ { type: "text", text: JSON.stringify({ domains, count: domains.length }, null, 2) },
222
+ ],
223
+ };
224
+ }
225
+ );
226
+
227
+ server.registerTool(
228
+ "get_domain_stats",
229
+ {
230
+ title: "Get Domain Stats",
231
+ description: "Get domain portfolio statistics.",
232
+ inputSchema: {},
233
+ },
234
+ async () => {
235
+ const stats = getDomainStats();
236
+ return { content: [{ type: "text", text: JSON.stringify(stats, null, 2) }] };
237
+ }
238
+ );
239
+
240
+ // --- DNS Records ---
241
+
242
+ server.registerTool(
243
+ "create_dns_record",
244
+ {
245
+ title: "Create DNS Record",
246
+ description: "Create a new DNS record for a domain.",
247
+ inputSchema: {
248
+ domain_id: z.string(),
249
+ type: z.enum(["A", "AAAA", "CNAME", "MX", "TXT", "NS", "SRV"]),
250
+ name: z.string(),
251
+ value: z.string(),
252
+ ttl: z.number().optional(),
253
+ priority: z.number().optional(),
254
+ },
255
+ },
256
+ async (params) => {
257
+ const record = createDnsRecord(params);
258
+ return { content: [{ type: "text", text: JSON.stringify(record, null, 2) }] };
259
+ }
260
+ );
261
+
262
+ server.registerTool(
263
+ "list_dns_records",
264
+ {
265
+ title: "List DNS Records",
266
+ description: "List DNS records for a domain.",
267
+ inputSchema: {
268
+ domain_id: z.string(),
269
+ type: z.enum(["A", "AAAA", "CNAME", "MX", "TXT", "NS", "SRV"]).optional(),
270
+ },
271
+ },
272
+ async ({ domain_id, type }) => {
273
+ const records = listDnsRecords(domain_id, type);
274
+ return {
275
+ content: [
276
+ { type: "text", text: JSON.stringify({ records, count: records.length }, null, 2) },
277
+ ],
278
+ };
279
+ }
280
+ );
281
+
282
+ server.registerTool(
283
+ "update_dns_record",
284
+ {
285
+ title: "Update DNS Record",
286
+ description: "Update a DNS record.",
287
+ inputSchema: {
288
+ id: z.string(),
289
+ type: z.enum(["A", "AAAA", "CNAME", "MX", "TXT", "NS", "SRV"]).optional(),
290
+ name: z.string().optional(),
291
+ value: z.string().optional(),
292
+ ttl: z.number().optional(),
293
+ priority: z.number().optional(),
294
+ },
295
+ },
296
+ async ({ id, ...input }) => {
297
+ const record = updateDnsRecord(id, input);
298
+ if (!record) {
299
+ return { content: [{ type: "text", text: `DNS record '${id}' not found.` }], isError: true };
300
+ }
301
+ return { content: [{ type: "text", text: JSON.stringify(record, null, 2) }] };
302
+ }
303
+ );
304
+
305
+ server.registerTool(
306
+ "delete_dns_record",
307
+ {
308
+ title: "Delete DNS Record",
309
+ description: "Delete a DNS record by ID.",
310
+ inputSchema: { id: z.string() },
311
+ },
312
+ async ({ id }) => {
313
+ const deleted = deleteDnsRecord(id);
314
+ return { content: [{ type: "text", text: JSON.stringify({ id, deleted }) }] };
315
+ }
316
+ );
317
+
318
+ // --- Alerts ---
319
+
320
+ server.registerTool(
321
+ "create_alert",
322
+ {
323
+ title: "Create Alert",
324
+ description: "Set an alert for a domain (expiry, SSL expiry, or DNS change).",
325
+ inputSchema: {
326
+ domain_id: z.string(),
327
+ type: z.enum(["expiry", "ssl_expiry", "dns_change"]),
328
+ trigger_days_before: z.number().optional(),
329
+ },
330
+ },
331
+ async (params) => {
332
+ const alert = createAlert(params);
333
+ return { content: [{ type: "text", text: JSON.stringify(alert, null, 2) }] };
334
+ }
335
+ );
336
+
337
+ server.registerTool(
338
+ "list_alerts",
339
+ {
340
+ title: "List Alerts",
341
+ description: "List alerts for a domain.",
342
+ inputSchema: { domain_id: z.string() },
343
+ },
344
+ async ({ domain_id }) => {
345
+ const alerts = listAlerts(domain_id);
346
+ return {
347
+ content: [
348
+ { type: "text", text: JSON.stringify({ alerts, count: alerts.length }, null, 2) },
349
+ ],
350
+ };
351
+ }
352
+ );
353
+
354
+ server.registerTool(
355
+ "delete_alert",
356
+ {
357
+ title: "Delete Alert",
358
+ description: "Delete an alert by ID.",
359
+ inputSchema: { id: z.string() },
360
+ },
361
+ async ({ id }) => {
362
+ const deleted = deleteAlert(id);
363
+ return { content: [{ type: "text", text: JSON.stringify({ id, deleted }) }] };
364
+ }
365
+ );
366
+
367
+ // --- WHOIS Lookup ---
368
+
369
+ server.registerTool(
370
+ "whois_lookup",
371
+ {
372
+ title: "WHOIS Lookup",
373
+ description: "Run a WHOIS lookup for a domain. Parses registrar, expiry, nameservers from output. Updates DB record if found.",
374
+ inputSchema: { domain: z.string().describe("Domain name (e.g. example.com)") },
375
+ },
376
+ async ({ domain }) => {
377
+ try {
378
+ const result = whoisLookup(domain);
379
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
380
+ } catch (error: unknown) {
381
+ return {
382
+ content: [{ type: "text", text: `WHOIS lookup failed: ${error instanceof Error ? error.message : String(error)}` }],
383
+ isError: true,
384
+ };
385
+ }
386
+ }
387
+ );
388
+
389
+ // --- DNS Propagation Check ---
390
+
391
+ server.registerTool(
392
+ "check_dns_propagation",
393
+ {
394
+ title: "Check DNS Propagation",
395
+ description: "Check DNS propagation by querying multiple DNS servers (Google, Cloudflare, Quad9, OpenDNS).",
396
+ inputSchema: {
397
+ domain: z.string().describe("Domain name to check"),
398
+ record_type: z.string().default("A").describe("DNS record type (A, AAAA, CNAME, MX, TXT, NS)"),
399
+ },
400
+ },
401
+ async ({ domain, record_type }) => {
402
+ const result = checkDnsPropagation(domain, record_type);
403
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
404
+ }
405
+ );
406
+
407
+ // --- SSL Check ---
408
+
409
+ server.registerTool(
410
+ "check_ssl",
411
+ {
412
+ title: "Check SSL Certificate",
413
+ description: "Check SSL certificate for a domain. Extracts issuer and expiry. Updates DB record if found.",
414
+ inputSchema: { domain: z.string().describe("Domain name (e.g. example.com)") },
415
+ },
416
+ async ({ domain }) => {
417
+ const result = checkSsl(domain);
418
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
419
+ }
420
+ );
421
+
422
+ // --- Zone File Export ---
423
+
424
+ server.registerTool(
425
+ "export_zone_file",
426
+ {
427
+ title: "Export Zone File",
428
+ description: "Export DNS records for a domain as a BIND-format zone file.",
429
+ inputSchema: { domain_id: z.string().describe("Domain ID") },
430
+ },
431
+ async ({ domain_id }) => {
432
+ const zone = exportZoneFile(domain_id);
433
+ if (!zone) {
434
+ return { content: [{ type: "text", text: `Domain '${domain_id}' not found.` }], isError: true };
435
+ }
436
+ return { content: [{ type: "text", text: zone }] };
437
+ }
438
+ );
439
+
440
+ // --- Zone File Import ---
441
+
442
+ server.registerTool(
443
+ "import_zone_file",
444
+ {
445
+ title: "Import Zone File",
446
+ description: "Import DNS records from BIND zone file content into a domain.",
447
+ inputSchema: {
448
+ domain_id: z.string().describe("Domain ID"),
449
+ content: z.string().describe("Zone file content"),
450
+ },
451
+ },
452
+ async ({ domain_id, content }) => {
453
+ const result = importZoneFile(domain_id, content);
454
+ if (!result) {
455
+ return { content: [{ type: "text", text: `Domain '${domain_id}' not found.` }], isError: true };
456
+ }
457
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
458
+ }
459
+ );
460
+
461
+ // --- Subdomain Discovery ---
462
+
463
+ server.registerTool(
464
+ "discover_subdomains",
465
+ {
466
+ title: "Discover Subdomains",
467
+ description: "Discover subdomains via certificate transparency logs (crt.sh).",
468
+ inputSchema: { domain: z.string().describe("Domain name") },
469
+ },
470
+ async ({ domain }) => {
471
+ const result = await discoverSubdomains(domain);
472
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
473
+ }
474
+ );
475
+
476
+ // --- DNS Validation ---
477
+
478
+ server.registerTool(
479
+ "validate_dns",
480
+ {
481
+ title: "Validate DNS",
482
+ description: "Validate DNS records for common issues (CNAME conflicts, missing MX, orphan records).",
483
+ inputSchema: { domain_id: z.string().describe("Domain ID") },
484
+ },
485
+ async ({ domain_id }) => {
486
+ const result = validateDns(domain_id);
487
+ if (!result) {
488
+ return { content: [{ type: "text", text: `Domain '${domain_id}' not found.` }], isError: true };
489
+ }
490
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
491
+ }
492
+ );
493
+
494
+ // --- Portfolio Export ---
495
+
496
+ server.registerTool(
497
+ "export_portfolio",
498
+ {
499
+ title: "Export Portfolio",
500
+ description: "Export all domains as CSV or JSON with expiry, SSL, registrar, and auto-renew info.",
501
+ inputSchema: {
502
+ format: z.enum(["csv", "json"]).default("json").describe("Export format"),
503
+ },
504
+ },
505
+ async ({ format }) => {
506
+ const output = exportPortfolio(format);
507
+ return { content: [{ type: "text", text: output }] };
508
+ }
509
+ );
510
+
511
+ // --- Bulk Domain Check ---
512
+
513
+ server.registerTool(
514
+ "check_all_domains",
515
+ {
516
+ title: "Check All Domains",
517
+ description: "Run WHOIS + SSL + DNS validation on all domains. Returns a summary of issues found.",
518
+ inputSchema: {},
519
+ },
520
+ async () => {
521
+ const results = checkAllDomains();
522
+ return { content: [{ type: "text", text: JSON.stringify(results, null, 2) }] };
523
+ }
524
+ );
525
+
526
+ // --- Start ---
527
+ async function main() {
528
+ const transport = new StdioServerTransport();
529
+ await server.connect(transport);
530
+ console.error("microservice-domains MCP server running on stdio");
531
+ }
532
+
533
+ main().catch((error) => {
534
+ console.error("Fatal error:", error);
535
+ process.exit(1);
536
+ });
@@ -0,0 +1,27 @@
1
+ {
2
+ "name": "@hasna/microservice-hiring",
3
+ "version": "0.0.1",
4
+ "description": "Applicant tracking and recruitment microservice with SQLite — manage jobs, applicants, and interviews",
5
+ "type": "module",
6
+ "bin": {
7
+ "microservice-hiring": "./src/cli/index.ts",
8
+ "microservice-hiring-mcp": "./src/mcp/index.ts"
9
+ },
10
+ "exports": {
11
+ ".": "./src/index.ts"
12
+ },
13
+ "scripts": {
14
+ "dev": "bun run ./src/cli/index.ts",
15
+ "test": "bun test"
16
+ },
17
+ "dependencies": {
18
+ "@modelcontextprotocol/sdk": "^1.26.0",
19
+ "commander": "^12.1.0",
20
+ "zod": "^3.24.0"
21
+ },
22
+ "license": "Apache-2.0",
23
+ "publishConfig": {
24
+ "registry": "https://registry.npmjs.org",
25
+ "access": "public"
26
+ }
27
+ }