@theyahia/megaplan-mcp 1.1.1 → 4.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/LICENSE +21 -21
- package/README.md +134 -10
- package/dist/client.d.ts +3 -1
- package/dist/client.js +210 -26
- package/dist/client.js.map +1 -1
- package/dist/format.d.ts +12 -0
- package/dist/format.js +148 -0
- package/dist/format.js.map +1 -0
- package/dist/http.d.ts +3 -0
- package/dist/http.js +152 -0
- package/dist/http.js.map +1 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +94 -16
- package/dist/index.js.map +1 -1
- package/dist/meta.d.ts +2 -0
- package/dist/meta.js +5 -0
- package/dist/meta.js.map +1 -0
- package/dist/prompts.d.ts +7 -0
- package/dist/prompts.js +22 -0
- package/dist/prompts.js.map +1 -0
- package/dist/query.d.ts +32 -0
- package/dist/query.js +61 -0
- package/dist/query.js.map +1 -0
- package/dist/tools/comments.d.ts +35 -0
- package/dist/tools/comments.js +31 -0
- package/dist/tools/comments.js.map +1 -0
- package/dist/tools/contractors.d.ts +35 -0
- package/dist/tools/contractors.js +39 -0
- package/dist/tools/contractors.js.map +1 -0
- package/dist/tools/deals.d.ts +76 -7
- package/dist/tools/deals.js +89 -16
- package/dist/tools/deals.js.map +1 -1
- package/dist/tools/employees.d.ts +21 -0
- package/dist/tools/employees.js +25 -0
- package/dist/tools/employees.js.map +1 -0
- package/dist/tools/me.d.ts +9 -0
- package/dist/tools/me.js +26 -0
- package/dist/tools/me.js.map +1 -0
- package/dist/tools/programs.d.ts +26 -0
- package/dist/tools/programs.js +25 -0
- package/dist/tools/programs.js.map +1 -0
- package/dist/tools/projects.d.ts +32 -0
- package/dist/tools/projects.js +34 -0
- package/dist/tools/projects.js.map +1 -0
- package/dist/tools/tasks.d.ts +49 -9
- package/dist/tools/tasks.js +62 -20
- package/dist/tools/tasks.js.map +1 -1
- package/dist/types.d.ts +54 -32
- package/dist/types.js +4 -0
- package/dist/types.js.map +1 -1
- package/package.json +69 -57
package/dist/format.js
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
// Maps raw, verbose Megaplan v3 entities into the compact shapes in types.ts.
|
|
2
|
+
//
|
|
3
|
+
// All accessors are defensive (optional chaining + fallbacks): the exact v3
|
|
4
|
+
// field set varies by account, so an unknown/renamed field yields null rather
|
|
5
|
+
// than throwing. Every tool also exposes a `raw` escape hatch to bypass this.
|
|
6
|
+
function rec(v) {
|
|
7
|
+
return v && typeof v === "object" ? v : {};
|
|
8
|
+
}
|
|
9
|
+
function str(v) {
|
|
10
|
+
return v == null ? undefined : String(v);
|
|
11
|
+
}
|
|
12
|
+
/** A Megaplan reference object {id, contentType, name?} -> display string. */
|
|
13
|
+
function refName(v) {
|
|
14
|
+
if (v == null)
|
|
15
|
+
return null;
|
|
16
|
+
if (typeof v === "string" || typeof v === "number")
|
|
17
|
+
return String(v);
|
|
18
|
+
const r = rec(v);
|
|
19
|
+
return r.name ?? (r.id != null ? String(r.id) : null);
|
|
20
|
+
}
|
|
21
|
+
/** An enum/status value (string code or {name|value|code}) -> display string. */
|
|
22
|
+
function enumName(v) {
|
|
23
|
+
if (v == null)
|
|
24
|
+
return null;
|
|
25
|
+
if (typeof v === "string" || typeof v === "number")
|
|
26
|
+
return String(v);
|
|
27
|
+
const r = rec(v);
|
|
28
|
+
return r.name ?? r.value ?? r.code ?? null;
|
|
29
|
+
}
|
|
30
|
+
/** A DateTime/DateOnly object {value} (or a bare string) -> string. */
|
|
31
|
+
function dateVal(v) {
|
|
32
|
+
if (v == null)
|
|
33
|
+
return null;
|
|
34
|
+
if (typeof v === "string")
|
|
35
|
+
return v;
|
|
36
|
+
const r = rec(v);
|
|
37
|
+
return r.value ?? null;
|
|
38
|
+
}
|
|
39
|
+
/** A Money object {value, currency} (or a bare number) -> display string. */
|
|
40
|
+
function money(v) {
|
|
41
|
+
if (v == null)
|
|
42
|
+
return null;
|
|
43
|
+
if (typeof v === "number")
|
|
44
|
+
return String(v);
|
|
45
|
+
const r = rec(v);
|
|
46
|
+
if (r.value == null)
|
|
47
|
+
return null;
|
|
48
|
+
return r.currency ? `${r.value} ${r.currency}` : String(r.value);
|
|
49
|
+
}
|
|
50
|
+
export function formatTask(e) {
|
|
51
|
+
const t = rec(e);
|
|
52
|
+
return {
|
|
53
|
+
id: str(t.id) ?? "",
|
|
54
|
+
name: t.name,
|
|
55
|
+
status: enumName(t.status),
|
|
56
|
+
responsible: refName(t.responsible),
|
|
57
|
+
deadline: dateVal(t.deadline),
|
|
58
|
+
priority: enumName(t.priority),
|
|
59
|
+
created: dateVal(t.timeCreated ?? t.created),
|
|
60
|
+
modified: dateVal(t.timeUpdated ?? t.modified),
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
export function formatDeal(e) {
|
|
64
|
+
const d = rec(e);
|
|
65
|
+
return {
|
|
66
|
+
id: str(d.id) ?? "",
|
|
67
|
+
name: d.name,
|
|
68
|
+
status: enumName(d.status ?? d.state),
|
|
69
|
+
price: money(d.price),
|
|
70
|
+
cost: money(d.cost),
|
|
71
|
+
responsible: refName(d.responsible),
|
|
72
|
+
contact: refName(d.contact),
|
|
73
|
+
contractor: refName(d.contractor),
|
|
74
|
+
created: dateVal(d.timeCreated ?? d.created),
|
|
75
|
+
modified: dateVal(d.timeUpdated ?? d.modified),
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
export function formatProject(e) {
|
|
79
|
+
const p = rec(e);
|
|
80
|
+
return {
|
|
81
|
+
id: str(p.id) ?? "",
|
|
82
|
+
name: p.name,
|
|
83
|
+
status: enumName(p.status),
|
|
84
|
+
responsible: refName(p.responsible),
|
|
85
|
+
created: dateVal(p.timeCreated ?? p.created),
|
|
86
|
+
modified: dateVal(p.timeUpdated ?? p.modified),
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
export function formatEmployee(e) {
|
|
90
|
+
const m = rec(e);
|
|
91
|
+
return {
|
|
92
|
+
id: str(m.id) ?? "",
|
|
93
|
+
name: m.name ?? refName(m),
|
|
94
|
+
email: m.email ?? null,
|
|
95
|
+
department: refName(m.department),
|
|
96
|
+
position: enumName(m.position),
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
export function formatComment(e) {
|
|
100
|
+
const c = rec(e);
|
|
101
|
+
return {
|
|
102
|
+
id: str(c.id) ?? "",
|
|
103
|
+
content: c.content ?? c.text ?? null,
|
|
104
|
+
author: refName(c.author),
|
|
105
|
+
created: dateVal(c.timeCreated ?? c.created),
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
export function formatProgram(e) {
|
|
109
|
+
const p = rec(e);
|
|
110
|
+
return { id: str(p.id) ?? "", name: p.name };
|
|
111
|
+
}
|
|
112
|
+
export function formatClient(e) {
|
|
113
|
+
const c = rec(e);
|
|
114
|
+
return {
|
|
115
|
+
id: str(c.id) ?? "",
|
|
116
|
+
name: c.name ?? refName(c),
|
|
117
|
+
email: c.email ?? null,
|
|
118
|
+
phone: enumName(c.phone) ?? null,
|
|
119
|
+
type: c.contentType ?? null,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
/** Unwrap a v3 `{meta, data}` list envelope into a compact summary string. */
|
|
123
|
+
export function formatList(result, formatter, raw) {
|
|
124
|
+
if (raw)
|
|
125
|
+
return JSON.stringify(result, null, 2);
|
|
126
|
+
const r = rec(result);
|
|
127
|
+
const data = Array.isArray(r.data) ? r.data : [];
|
|
128
|
+
const meta = rec(r.meta);
|
|
129
|
+
const pagination = rec(meta.pagination);
|
|
130
|
+
const items = data.map(formatter);
|
|
131
|
+
const last = rec(data[data.length - 1]);
|
|
132
|
+
const summary = {
|
|
133
|
+
total: meta.totalCount ?? pagination.count ?? items.length,
|
|
134
|
+
count: items.length,
|
|
135
|
+
items,
|
|
136
|
+
nextPageAfter: last.id != null ? String(last.id) : null,
|
|
137
|
+
};
|
|
138
|
+
return JSON.stringify(summary, null, 2);
|
|
139
|
+
}
|
|
140
|
+
/** Unwrap a v3 `{data: {...}}` single-entity envelope and format it. */
|
|
141
|
+
export function formatEntity(result, formatter, raw) {
|
|
142
|
+
if (raw)
|
|
143
|
+
return JSON.stringify(result, null, 2);
|
|
144
|
+
const r = rec(result);
|
|
145
|
+
const data = r.data !== undefined ? r.data : r;
|
|
146
|
+
return JSON.stringify(formatter(data), null, 2);
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=format.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.js","sourceRoot":"","sources":["../src/format.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,EAAE;AACF,4EAA4E;AAC5E,8EAA8E;AAC9E,8EAA8E;AAe9E,SAAS,GAAG,CAAC,CAAU;IACrB,OAAO,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAE,CAAS,CAAC,CAAC,CAAC,EAAE,CAAC;AACtD,CAAC;AACD,SAAS,GAAG,CAAC,CAAU;IACrB,OAAO,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AAC3C,CAAC;AACD,8EAA8E;AAC9E,SAAS,OAAO,CAAC,CAAU;IACzB,IAAI,CAAC,IAAI,IAAI;QAAE,OAAO,IAAI,CAAC;IAC3B,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,OAAO,CAAC,KAAK,QAAQ;QAAE,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC;IACrE,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;IACjB,OAAO,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AACxD,CAAC;AACD,iFAAiF;AACjF,SAAS,QAAQ,CAAC,CAAU;IAC1B,IAAI,CAAC,IAAI,IAAI;QAAE,OAAO,IAAI,CAAC;IAC3B,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,OAAO,CAAC,KAAK,QAAQ;QAAE,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC;IACrE,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;IACjB,OAAO,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,IAAI,IAAI,IAAI,CAAC;AAC7C,CAAC;AACD,uEAAuE;AACvE,SAAS,OAAO,CAAC,CAAU;IACzB,IAAI,CAAC,IAAI,IAAI;QAAE,OAAO,IAAI,CAAC;IAC3B,IAAI,OAAO,CAAC,KAAK,QAAQ;QAAE,OAAO,CAAC,CAAC;IACpC,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;IACjB,OAAO,CAAC,CAAC,KAAK,IAAI,IAAI,CAAC;AACzB,CAAC;AACD,6EAA6E;AAC7E,SAAS,KAAK,CAAC,CAAU;IACvB,IAAI,CAAC,IAAI,IAAI;QAAE,OAAO,IAAI,CAAC;IAC3B,IAAI,OAAO,CAAC,KAAK,QAAQ;QAAE,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC;IAC5C,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;IACjB,IAAI,CAAC,CAAC,KAAK,IAAI,IAAI;QAAE,OAAO,IAAI,CAAC;IACjC,OAAO,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;AACnE,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,CAAU;IACnC,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;IACjB,OAAO;QACL,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,EAAE;QACnB,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC;QAC1B,WAAW,EAAE,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC;QACnC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC;QAC7B,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC;QAC9B,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,WAAW,IAAI,CAAC,CAAC,OAAO,CAAC;QAC5C,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC,WAAW,IAAI,CAAC,CAAC,QAAQ,CAAC;KAC/C,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,CAAU;IACnC,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;IACjB,OAAO;QACL,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,EAAE;QACnB,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,KAAK,CAAC;QACrC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC;QACrB,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;QACnB,WAAW,EAAE,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC;QACnC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC;QAC3B,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC;QACjC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,WAAW,IAAI,CAAC,CAAC,OAAO,CAAC;QAC5C,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC,WAAW,IAAI,CAAC,CAAC,QAAQ,CAAC;KAC/C,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,CAAU;IACtC,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;IACjB,OAAO;QACL,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,EAAE;QACnB,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC;QAC1B,WAAW,EAAE,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC;QACnC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,WAAW,IAAI,CAAC,CAAC,OAAO,CAAC;QAC5C,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC,WAAW,IAAI,CAAC,CAAC,QAAQ,CAAC;KAC/C,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,CAAU;IACvC,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;IACjB,OAAO;QACL,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,EAAE;QACnB,IAAI,EAAE,CAAC,CAAC,IAAI,IAAI,OAAO,CAAC,CAAC,CAAC;QAC1B,KAAK,EAAE,CAAC,CAAC,KAAK,IAAI,IAAI;QACtB,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC;QACjC,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC;KAC/B,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,CAAU;IACtC,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;IACjB,OAAO;QACL,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,EAAE;QACnB,OAAO,EAAE,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,IAAI,IAAI,IAAI;QACpC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC;QACzB,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,WAAW,IAAI,CAAC,CAAC,OAAO,CAAC;KAC7C,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,CAAU;IACtC,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;IACjB,OAAO,EAAE,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,CAAU;IACrC,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;IACjB,OAAO;QACL,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,EAAE;QACnB,IAAI,EAAE,CAAC,CAAC,IAAI,IAAI,OAAO,CAAC,CAAC,CAAC;QAC1B,KAAK,EAAE,CAAC,CAAC,KAAK,IAAI,IAAI;QACtB,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,IAAI;QAChC,IAAI,EAAE,CAAC,CAAC,WAAW,IAAI,IAAI;KAC5B,CAAC;AACJ,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,UAAU,CACxB,MAAe,EACf,SAA4B,EAC5B,GAAa;IAEb,IAAI,GAAG;QAAE,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAChD,MAAM,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC;IACtB,MAAM,IAAI,GAAc,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;IAC5D,MAAM,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IACzB,MAAM,UAAU,GAAG,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACxC,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IAClC,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;IACxC,MAAM,OAAO,GAA2B;QACtC,KAAK,EAAE,IAAI,CAAC,UAAU,IAAI,UAAU,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM;QAC1D,KAAK,EAAE,KAAK,CAAC,MAAM;QACnB,KAAK;QACL,aAAa,EAAE,IAAI,CAAC,EAAE,IAAI,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI;KACxD,CAAC;IACF,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AAC1C,CAAC;AAED,wEAAwE;AACxE,MAAM,UAAU,YAAY,CAC1B,MAAe,EACf,SAA4B,EAC5B,GAAa;IAEb,IAAI,GAAG;QAAE,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAChD,MAAM,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC;IACtB,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/C,OAAO,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AAClD,CAAC"}
|
package/dist/http.d.ts
ADDED
package/dist/http.js
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
2
|
+
import express from "express";
|
|
3
|
+
import { randomUUID } from "node:crypto";
|
|
4
|
+
import { TOOL_COUNT, PROMPT_COUNT } from "./meta.js";
|
|
5
|
+
/** Close a transport without caring about the result (sync throw or async rejection). */
|
|
6
|
+
function closeQuietly(transport) {
|
|
7
|
+
void Promise.resolve()
|
|
8
|
+
.then(() => transport.close())
|
|
9
|
+
.catch(() => {
|
|
10
|
+
/* ignore */
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
export async function startHttpServer(createMcpServer, port) {
|
|
14
|
+
const host = process.env.HOST ?? "127.0.0.1";
|
|
15
|
+
// Fail closed: this server proxies live Megaplan credentials, so refuse to
|
|
16
|
+
// start --http without an auth token rather than expose tools unauthenticated.
|
|
17
|
+
const httpToken = process.env.MCP_HTTP_TOKEN;
|
|
18
|
+
if (!httpToken) {
|
|
19
|
+
throw new Error("MCP_HTTP_TOKEN must be set for --http mode (refusing to expose Megaplan tools without authentication).");
|
|
20
|
+
}
|
|
21
|
+
const allowedHosts = (process.env.MCP_HTTP_ALLOWED_HOSTS ?? `127.0.0.1:${port},localhost:${port}`)
|
|
22
|
+
.split(",")
|
|
23
|
+
.map((s) => s.trim())
|
|
24
|
+
.filter(Boolean);
|
|
25
|
+
const maxSessions = Number(process.env.MCP_HTTP_MAX_SESSIONS ?? 100);
|
|
26
|
+
const idleMs = Number(process.env.MCP_HTTP_SESSION_TTL_MS ?? 30 * 60 * 1000);
|
|
27
|
+
const app = express();
|
|
28
|
+
app.use(express.json({ limit: process.env.MCP_HTTP_BODY_LIMIT ?? "1mb" }));
|
|
29
|
+
// Bearer auth in front of every /mcp route.
|
|
30
|
+
app.use("/mcp", (req, res, next) => {
|
|
31
|
+
if (req.headers.authorization !== `Bearer ${httpToken}`) {
|
|
32
|
+
res.status(401).json({ error: "unauthorized" });
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
next();
|
|
36
|
+
});
|
|
37
|
+
const transports = new Map();
|
|
38
|
+
// Evict idle/abandoned sessions so the map (and its live transports) can't grow without bound.
|
|
39
|
+
const sweep = setInterval(() => {
|
|
40
|
+
const now = Date.now();
|
|
41
|
+
for (const [id, session] of transports) {
|
|
42
|
+
if (now - session.lastSeen > idleMs) {
|
|
43
|
+
closeQuietly(session.transport);
|
|
44
|
+
transports.delete(id);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}, 60_000);
|
|
48
|
+
sweep.unref?.();
|
|
49
|
+
app.post("/mcp", async (req, res) => {
|
|
50
|
+
try {
|
|
51
|
+
const sessionId = req.headers["mcp-session-id"];
|
|
52
|
+
if (sessionId && transports.has(sessionId)) {
|
|
53
|
+
const session = transports.get(sessionId);
|
|
54
|
+
session.lastSeen = Date.now();
|
|
55
|
+
await session.transport.handleRequest(req, res, req.body);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
if (transports.size >= maxSessions) {
|
|
59
|
+
res.status(503).json({ error: "too many sessions" });
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
const newSessionId = randomUUID();
|
|
63
|
+
const transport = new StreamableHTTPServerTransport({
|
|
64
|
+
sessionIdGenerator: () => newSessionId,
|
|
65
|
+
enableDnsRebindingProtection: true,
|
|
66
|
+
allowedHosts,
|
|
67
|
+
allowedOrigins: [],
|
|
68
|
+
});
|
|
69
|
+
transport.onclose = () => transports.delete(newSessionId);
|
|
70
|
+
// A fresh McpServer per session (an McpServer is 1:1 with a transport).
|
|
71
|
+
await createMcpServer().connect(transport);
|
|
72
|
+
transports.set(newSessionId, { transport, lastSeen: Date.now() });
|
|
73
|
+
try {
|
|
74
|
+
await transport.handleRequest(req, res, req.body);
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
// Roll back the session we just created if the first request failed.
|
|
78
|
+
transports.delete(newSessionId);
|
|
79
|
+
closeQuietly(transport);
|
|
80
|
+
throw error;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
console.error("[megaplan-mcp] POST /mcp error:", error);
|
|
85
|
+
if (!res.headersSent)
|
|
86
|
+
res.status(500).json({ error: "internal error" });
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
app.get("/mcp", async (req, res) => {
|
|
90
|
+
try {
|
|
91
|
+
const sessionId = req.headers["mcp-session-id"];
|
|
92
|
+
if (!sessionId || !transports.has(sessionId)) {
|
|
93
|
+
res.status(400).json({ error: "No valid session. POST /mcp first." });
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
const session = transports.get(sessionId);
|
|
97
|
+
session.lastSeen = Date.now();
|
|
98
|
+
await session.transport.handleRequest(req, res);
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
console.error("[megaplan-mcp] GET /mcp error:", error);
|
|
102
|
+
if (!res.headersSent)
|
|
103
|
+
res.status(500).json({ error: "internal error" });
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
app.delete("/mcp", async (req, res) => {
|
|
107
|
+
const sessionId = req.headers["mcp-session-id"];
|
|
108
|
+
const session = sessionId ? transports.get(sessionId) : undefined;
|
|
109
|
+
if (!session) {
|
|
110
|
+
res.status(200).end();
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
try {
|
|
114
|
+
await session.transport.handleRequest(req, res);
|
|
115
|
+
}
|
|
116
|
+
catch (error) {
|
|
117
|
+
console.error("[megaplan-mcp] DELETE /mcp error:", error);
|
|
118
|
+
if (!res.headersSent)
|
|
119
|
+
res.status(500).json({ error: "internal error" });
|
|
120
|
+
}
|
|
121
|
+
finally {
|
|
122
|
+
// Always tear down the session, even if handleRequest threw.
|
|
123
|
+
closeQuietly(session.transport);
|
|
124
|
+
transports.delete(sessionId);
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
app.get("/health", (_req, res) => {
|
|
128
|
+
res.json({ status: "ok", tools: TOOL_COUNT, prompts: PROMPT_COUNT, sessions: transports.size });
|
|
129
|
+
});
|
|
130
|
+
// Body-parser / payload-size error handler (must be last, 4-arg signature).
|
|
131
|
+
app.use((err, _req, res, next) => {
|
|
132
|
+
if (!err) {
|
|
133
|
+
next();
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
const tooLarge = err.type === "entity.too.large";
|
|
137
|
+
console.error("[megaplan-mcp] request error:", err);
|
|
138
|
+
if (!res.headersSent)
|
|
139
|
+
res.status(tooLarge ? 413 : 400).json({ error: "bad request" });
|
|
140
|
+
});
|
|
141
|
+
return new Promise((resolve) => {
|
|
142
|
+
const httpServer = app.listen(port, host, () => {
|
|
143
|
+
const bound = httpServer.address();
|
|
144
|
+
const shownPort = typeof bound === "object" && bound ? bound.port : port;
|
|
145
|
+
console.error(`[megaplan-mcp] HTTP server on http://${host}:${shownPort}/mcp (Streamable HTTP, auth required)`);
|
|
146
|
+
console.error(`[megaplan-mcp] Health: http://${host}:${shownPort}/health`);
|
|
147
|
+
resolve(httpServer);
|
|
148
|
+
});
|
|
149
|
+
httpServer.on("close", () => clearInterval(sweep));
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
//# sourceMappingURL=http.js.map
|
package/dist/http.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,22 +1,100 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
3
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { realpathSync } from "node:fs";
|
|
6
|
+
import { TOOL_COUNT, PROMPT_COUNT } from "./meta.js";
|
|
7
|
+
import { getTasksSchema, handleGetTasks, getTaskSchema, handleGetTask, createTaskSchema, handleCreateTask, updateTaskSchema, handleUpdateTask, } from "./tools/tasks.js";
|
|
8
|
+
import { getDealsSchema, handleGetDeals, getDealSchema, handleGetDeal, createDealSchema, handleCreateDeal, updateDealSchema, handleUpdateDeal, } from "./tools/deals.js";
|
|
9
|
+
import { getProjectsSchema, handleGetProjects, getProjectSchema, handleGetProject } from "./tools/projects.js";
|
|
10
|
+
import { getEmployeesSchema, handleGetEmployees } from "./tools/employees.js";
|
|
11
|
+
import { getCommentsSchema, handleGetComments, createCommentSchema, handleCreateComment } from "./tools/comments.js";
|
|
12
|
+
import { getDealProgramsSchema, handleGetDealPrograms, getDealProgramSchema, handleGetDealProgram, } from "./tools/programs.js";
|
|
13
|
+
import { listClientsSchema, handleListClients, getClientSchema, handleGetClient, } from "./tools/contractors.js";
|
|
14
|
+
import { getCurrentUserSchema, handleGetCurrentUser } from "./tools/me.js";
|
|
15
|
+
import { MY_TASKS_TODAY, CREATE_DEAL_WIZARD } from "./prompts.js";
|
|
16
|
+
/** Wrap a tool handler so thrown errors become a clean isError result, not a transport error. */
|
|
17
|
+
function wrapTool(handler) {
|
|
18
|
+
return async (params) => {
|
|
19
|
+
try {
|
|
20
|
+
return { content: [{ type: "text", text: await handler(params) }] };
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
24
|
+
console.error("[megaplan-mcp] tool error:", error);
|
|
25
|
+
return { content: [{ type: "text", text: `Error: ${message}` }], isError: true };
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
export function createServer() {
|
|
30
|
+
const server = new McpServer({
|
|
31
|
+
name: "megaplan-mcp",
|
|
32
|
+
version: "4.0.0",
|
|
33
|
+
});
|
|
34
|
+
// ── Tasks ──
|
|
35
|
+
server.tool("get_tasks", "List tasks from Megaplan, filtered by status code(s), responsible user, and free-text search.", getTasksSchema.shape, wrapTool(handleGetTasks));
|
|
36
|
+
server.tool("get_task", "Get a single Megaplan task by ID with full details.", getTaskSchema.shape, wrapTool(handleGetTask));
|
|
37
|
+
server.tool("create_task", "Create a task in Megaplan with name, description, responsible user, and deadline.", createTaskSchema.shape, wrapTool(handleCreateTask));
|
|
38
|
+
server.tool("update_task", "Update an existing Megaplan task (name, description, responsible, deadline, status).", updateTaskSchema.shape, wrapTool(handleUpdateTask));
|
|
39
|
+
// ── Deals ──
|
|
40
|
+
server.tool("get_deals", "List deals from Megaplan, filtered by status code(s), responsible user, and free-text search.", getDealsSchema.shape, wrapTool(handleGetDeals));
|
|
41
|
+
server.tool("get_deal", "Get a single Megaplan deal by ID with full details.", getDealSchema.shape, wrapTool(handleGetDeal));
|
|
42
|
+
server.tool("create_deal", "Create a deal in Megaplan. Requires a program (pipeline) ID — discover it via get_deal_programs.", createDealSchema.shape, wrapTool(handleCreateDeal));
|
|
43
|
+
server.tool("update_deal", "Update an existing Megaplan deal (name, responsible, amount, description, status).", updateDealSchema.shape, wrapTool(handleUpdateDeal));
|
|
44
|
+
// ── Projects ──
|
|
45
|
+
server.tool("get_projects", "List projects from Megaplan, filtered by status code(s) and free-text search.", getProjectsSchema.shape, wrapTool(handleGetProjects));
|
|
46
|
+
server.tool("get_project", "Get a single Megaplan project by ID with full details.", getProjectSchema.shape, wrapTool(handleGetProject));
|
|
47
|
+
// ── Employees ──
|
|
48
|
+
server.tool("get_employees", "List employees from Megaplan with free-text search and department filter.", getEmployeesSchema.shape, wrapTool(handleGetEmployees));
|
|
49
|
+
// ── Deal programs (pipelines) ──
|
|
50
|
+
server.tool("get_deal_programs", "List deal programs (pipelines). Use this to find the program_id required by create_deal.", getDealProgramsSchema.shape, wrapTool(handleGetDealPrograms));
|
|
51
|
+
server.tool("get_deal_program", "Get a single deal program (pipeline) by ID.", getDealProgramSchema.shape, wrapTool(handleGetDealProgram));
|
|
52
|
+
// ── Clients (CRM contractors) ──
|
|
53
|
+
server.tool("list_clients", "List clients (CRM contractors): people (human) or organizations (company).", listClientsSchema.shape, wrapTool(handleListClients));
|
|
54
|
+
server.tool("get_client", "Get a single client (contractor) by type and ID.", getClientSchema.shape, wrapTool(handleGetClient));
|
|
55
|
+
// ── Current user ──
|
|
56
|
+
server.tool("get_current_user", "Get the authenticated user's employee record (experimental). Use it to scope 'my tasks'.", getCurrentUserSchema.shape, wrapTool(handleGetCurrentUser));
|
|
57
|
+
// ── Comments ──
|
|
58
|
+
server.tool("get_comments", "List comments for a task, deal, or project in Megaplan.", getCommentsSchema.shape, wrapTool(handleGetComments));
|
|
59
|
+
server.tool("create_comment", "Add a comment to a task, deal, or project in Megaplan.", createCommentSchema.shape, wrapTool(handleCreateComment));
|
|
60
|
+
// ── Skills (prompts) ──
|
|
61
|
+
const registerPrompt = (p) => server.prompt(p.name, p.description, {}, async () => ({
|
|
62
|
+
messages: [{ role: "user", content: { type: "text", text: p.text } }],
|
|
63
|
+
}));
|
|
64
|
+
registerPrompt(MY_TASKS_TODAY);
|
|
65
|
+
registerPrompt(CREATE_DEAL_WIZARD);
|
|
66
|
+
return server;
|
|
67
|
+
}
|
|
13
68
|
async function main() {
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
69
|
+
const args = process.argv.slice(2);
|
|
70
|
+
if (args.includes("--http")) {
|
|
71
|
+
const { startHttpServer } = await import("./http.js");
|
|
72
|
+
const port = parseInt(process.env.PORT ?? "3000", 10);
|
|
73
|
+
await startHttpServer(createServer, port);
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
const server = createServer();
|
|
77
|
+
const transport = new StdioServerTransport();
|
|
78
|
+
await server.connect(transport);
|
|
79
|
+
console.error(`[megaplan-mcp] Server started via stdio. ${TOOL_COUNT} tools, ${PROMPT_COUNT} skills available.`);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/** True when this file is being executed directly (not imported, e.g. by tests). */
|
|
83
|
+
function isEntrypoint() {
|
|
84
|
+
const entry = process.argv[1];
|
|
85
|
+
if (!entry)
|
|
86
|
+
return false;
|
|
87
|
+
try {
|
|
88
|
+
return realpathSync(entry) === realpathSync(fileURLToPath(import.meta.url));
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
if (isEntrypoint()) {
|
|
95
|
+
main().catch((error) => {
|
|
96
|
+
console.error("[megaplan-mcp] Error:", error);
|
|
97
|
+
process.exit(1);
|
|
98
|
+
});
|
|
17
99
|
}
|
|
18
|
-
main().catch((error) => {
|
|
19
|
-
console.error("[megaplan-mcp] Error:", error);
|
|
20
|
-
process.exit(1);
|
|
21
|
-
});
|
|
22
100
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACrD,OAAO,EACL,cAAc,EAAE,cAAc,EAC9B,aAAa,EAAE,aAAa,EAC5B,gBAAgB,EAAE,gBAAgB,EAClC,gBAAgB,EAAE,gBAAgB,GACnC,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,cAAc,EAAE,cAAc,EAC9B,aAAa,EAAE,aAAa,EAC5B,gBAAgB,EAAE,gBAAgB,EAClC,gBAAgB,EAAE,gBAAgB,GACnC,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC/G,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC9E,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AACrH,OAAO,EACL,qBAAqB,EAAE,qBAAqB,EAC5C,oBAAoB,EAAE,oBAAoB,GAC3C,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,iBAAiB,EAAE,iBAAiB,EACpC,eAAe,EAAE,eAAe,GACjC,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAC3E,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAkB,MAAM,cAAc,CAAC;AAOlF,iGAAiG;AACjG,SAAS,QAAQ,CAAI,OAAuC;IAC1D,OAAO,KAAK,EAAE,MAAS,EAAuB,EAAE;QAC9C,IAAI,CAAC;YACH,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC;QACtE,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACvE,OAAO,CAAC,KAAK,CAAC,4BAA4B,EAAE,KAAK,CAAC,CAAC;YACnD,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,OAAO,EAAE,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QACnF,CAAC;IACH,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;QAC3B,IAAI,EAAE,cAAc;QACpB,OAAO,EAAE,OAAO;KACjB,CAAC,CAAC;IAEH,cAAc;IACd,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,+FAA+F,EAAE,cAAc,CAAC,KAAK,EAAE,QAAQ,CAAC,cAAc,CAAC,CAAC,CAAC;IAC1K,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,qDAAqD,EAAE,aAAa,CAAC,KAAK,EAAE,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC;IAC7H,MAAM,CAAC,IAAI,CAAC,aAAa,EAAE,mFAAmF,EAAE,gBAAgB,CAAC,KAAK,EAAE,QAAQ,CAAC,gBAAgB,CAAC,CAAC,CAAC;IACpK,MAAM,CAAC,IAAI,CAAC,aAAa,EAAE,sFAAsF,EAAE,gBAAgB,CAAC,KAAK,EAAE,QAAQ,CAAC,gBAAgB,CAAC,CAAC,CAAC;IAEvK,cAAc;IACd,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,+FAA+F,EAAE,cAAc,CAAC,KAAK,EAAE,QAAQ,CAAC,cAAc,CAAC,CAAC,CAAC;IAC1K,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,qDAAqD,EAAE,aAAa,CAAC,KAAK,EAAE,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC;IAC7H,MAAM,CAAC,IAAI,CAAC,aAAa,EAAE,kGAAkG,EAAE,gBAAgB,CAAC,KAAK,EAAE,QAAQ,CAAC,gBAAgB,CAAC,CAAC,CAAC;IACnL,MAAM,CAAC,IAAI,CAAC,aAAa,EAAE,oFAAoF,EAAE,gBAAgB,CAAC,KAAK,EAAE,QAAQ,CAAC,gBAAgB,CAAC,CAAC,CAAC;IAErK,iBAAiB;IACjB,MAAM,CAAC,IAAI,CAAC,cAAc,EAAE,+EAA+E,EAAE,iBAAiB,CAAC,KAAK,EAAE,QAAQ,CAAC,iBAAiB,CAAC,CAAC,CAAC;IACnK,MAAM,CAAC,IAAI,CAAC,aAAa,EAAE,wDAAwD,EAAE,gBAAgB,CAAC,KAAK,EAAE,QAAQ,CAAC,gBAAgB,CAAC,CAAC,CAAC;IAEzI,kBAAkB;IAClB,MAAM,CAAC,IAAI,CAAC,eAAe,EAAE,2EAA2E,EAAE,kBAAkB,CAAC,KAAK,EAAE,QAAQ,CAAC,kBAAkB,CAAC,CAAC,CAAC;IAElK,kCAAkC;IAClC,MAAM,CAAC,IAAI,CAAC,mBAAmB,EAAE,0FAA0F,EAAE,qBAAqB,CAAC,KAAK,EAAE,QAAQ,CAAC,qBAAqB,CAAC,CAAC,CAAC;IAC3L,MAAM,CAAC,IAAI,CAAC,kBAAkB,EAAE,6CAA6C,EAAE,oBAAoB,CAAC,KAAK,EAAE,QAAQ,CAAC,oBAAoB,CAAC,CAAC,CAAC;IAE3I,kCAAkC;IAClC,MAAM,CAAC,IAAI,CAAC,cAAc,EAAE,4EAA4E,EAAE,iBAAiB,CAAC,KAAK,EAAE,QAAQ,CAAC,iBAAiB,CAAC,CAAC,CAAC;IAChK,MAAM,CAAC,IAAI,CAAC,YAAY,EAAE,kDAAkD,EAAE,eAAe,CAAC,KAAK,EAAE,QAAQ,CAAC,eAAe,CAAC,CAAC,CAAC;IAEhI,qBAAqB;IACrB,MAAM,CAAC,IAAI,CAAC,kBAAkB,EAAE,0FAA0F,EAAE,oBAAoB,CAAC,KAAK,EAAE,QAAQ,CAAC,oBAAoB,CAAC,CAAC,CAAC;IAExL,iBAAiB;IACjB,MAAM,CAAC,IAAI,CAAC,cAAc,EAAE,yDAAyD,EAAE,iBAAiB,CAAC,KAAK,EAAE,QAAQ,CAAC,iBAAiB,CAAC,CAAC,CAAC;IAC7I,MAAM,CAAC,IAAI,CAAC,gBAAgB,EAAE,wDAAwD,EAAE,mBAAmB,CAAC,KAAK,EAAE,QAAQ,CAAC,mBAAmB,CAAC,CAAC,CAAC;IAElJ,yBAAyB;IACzB,MAAM,cAAc,GAAG,CAAC,CAAY,EAAE,EAAE,CACtC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,EAAE,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;QACpD,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;KACxF,CAAC,CAAC,CAAC;IACN,cAAc,CAAC,cAAc,CAAC,CAAC;IAC/B,cAAc,CAAC,kBAAkB,CAAC,CAAC;IAEnC,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAEnC,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC5B,MAAM,EAAE,eAAe,EAAE,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,CAAC;QACtD,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,MAAM,EAAE,EAAE,CAAC,CAAC;QACtD,MAAM,eAAe,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;IAC5C,CAAC;SAAM,CAAC;QACN,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;QAC9B,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;QAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAChC,OAAO,CAAC,KAAK,CAAC,4CAA4C,UAAU,WAAW,YAAY,oBAAoB,CAAC,CAAC;IACnH,CAAC;AACH,CAAC;AAED,oFAAoF;AACpF,SAAS,YAAY;IACnB,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC9B,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IACzB,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,KAAK,CAAC,KAAK,YAAY,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IAC9E,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,IAAI,YAAY,EAAE,EAAE,CAAC;IACnB,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;QACrB,OAAO,CAAC,KAAK,CAAC,uBAAuB,EAAE,KAAK,CAAC,CAAC;QAC9C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC"}
|
package/dist/meta.d.ts
ADDED
package/dist/meta.js
ADDED
package/dist/meta.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"meta.js","sourceRoot":"","sources":["../src/meta.ts"],"names":[],"mappings":"AAAA,iFAAiF;AACjF,mEAAmE;AACnE,MAAM,CAAC,MAAM,UAAU,GAAG,EAAE,CAAC;AAC7B,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAC"}
|
package/dist/prompts.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// Prompt ("skill") definitions, kept separate so their contract (which tools
|
|
2
|
+
// and filters they steer the model toward) can be unit-tested.
|
|
3
|
+
export const MY_TASKS_TODAY = {
|
|
4
|
+
name: "my-tasks-today",
|
|
5
|
+
description: "Мои задачи на сегодня — your tasks due today or overdue",
|
|
6
|
+
text: "Сначала вызови get_current_user, чтобы узнать мой employee id. Если он недоступен " +
|
|
7
|
+
"(experimental endpoint вернул ошибку) — попроси меня указать мой employee id (его можно " +
|
|
8
|
+
"найти через get_employees). Затем вызови get_tasks с filter_responsible_id=<мой id> и " +
|
|
9
|
+
"подходящим filter_status, чтобы получить именно МОИ активные задачи. Покажи список с " +
|
|
10
|
+
"дедлайнами, отсортируй по срочности, просроченные пометь. Формат: компактная таблица с " +
|
|
11
|
+
"колонками Задача, Дедлайн, Статус, Приоритет.",
|
|
12
|
+
};
|
|
13
|
+
export const CREATE_DEAL_WIZARD = {
|
|
14
|
+
name: "create-deal-wizard",
|
|
15
|
+
description: "Создай сделку — guided deal creation wizard",
|
|
16
|
+
text: "Помоги создать новую сделку в Мегаплане. Сначала вызови get_deal_programs и покажи мне " +
|
|
17
|
+
"список доступных программ (pipelines) с их id, чтобы я выбрал нужную. Затем спроси: " +
|
|
18
|
+
"1) Название сделки, 2) Ответственный (опционально — найди через get_employees), 3) Сумма и " +
|
|
19
|
+
"валюта (опционально), 4) Контакт/клиент и его тип human/company (опционально — найди через " +
|
|
20
|
+
"list_clients), 5) Описание (опционально). После сбора данных вызови create_deal.",
|
|
21
|
+
};
|
|
22
|
+
//# sourceMappingURL=prompts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompts.js","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,+DAA+D;AAQ/D,MAAM,CAAC,MAAM,cAAc,GAAc;IACvC,IAAI,EAAE,gBAAgB;IACtB,WAAW,EAAE,yDAAyD;IACtE,IAAI,EACF,oFAAoF;QACpF,0FAA0F;QAC1F,wFAAwF;QACxF,uFAAuF;QACvF,yFAAyF;QACzF,+CAA+C;CAClD,CAAC;AAEF,MAAM,CAAC,MAAM,kBAAkB,GAAc;IAC3C,IAAI,EAAE,oBAAoB;IAC1B,WAAW,EAAE,6CAA6C;IAC1D,IAAI,EACF,yFAAyF;QACzF,sFAAsF;QACtF,6FAA6F;QAC7F,6FAA6F;QAC7F,kFAAkF;CACrF,CAAC"}
|
package/dist/query.d.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const idSchema: z.ZodString;
|
|
3
|
+
export interface RefSpec {
|
|
4
|
+
/** Entity field to filter on, e.g. "responsible" or "department". */
|
|
5
|
+
field: string;
|
|
6
|
+
/** Referenced entity contentType, e.g. "Employee" or "Department". */
|
|
7
|
+
contentType: string;
|
|
8
|
+
id: string;
|
|
9
|
+
}
|
|
10
|
+
export interface ListQueryOpts {
|
|
11
|
+
/** Entity contentType base, used for the filter type and the cursor, e.g. "Task". */
|
|
12
|
+
entity: string;
|
|
13
|
+
limit: number;
|
|
14
|
+
/** Cursor: id of the last item from the previous page. */
|
|
15
|
+
pageAfter?: string;
|
|
16
|
+
/** Status enum code(s), e.g. ["filter_any"]. Account-specific. */
|
|
17
|
+
status?: string | string[];
|
|
18
|
+
/** Reference filters (responsible, department, ...). */
|
|
19
|
+
refs?: RefSpec[];
|
|
20
|
+
/** Free-text search. */
|
|
21
|
+
search?: string;
|
|
22
|
+
/** Override for the filter contentType (defaults to `${entity}Filter`). */
|
|
23
|
+
filterContentType?: string;
|
|
24
|
+
}
|
|
25
|
+
type Json = Record<string, unknown>;
|
|
26
|
+
/** Build the v3 list-query object (limit + filter + cursor). */
|
|
27
|
+
export declare function buildListQuery(opts: ListQueryOpts): Json;
|
|
28
|
+
/** v3 date+time value object (deadlines etc. are entity objects, not bare strings). */
|
|
29
|
+
export declare function toDateTime(iso: string): Json;
|
|
30
|
+
/** v3 Money value object (money fields are complex objects, not bare numbers). */
|
|
31
|
+
export declare function toMoney(value: number, currency?: string): Json;
|
|
32
|
+
export {};
|
package/dist/query.js
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
// A Megaplan entity id. Constrained so a value interpolated into a request URL
|
|
3
|
+
// path (e.g. /task/{id}, /{type}/{subject_id}/comments) can't smuggle in path
|
|
4
|
+
// traversal — the callers here are LLM agents, so ids are an untrusted boundary.
|
|
5
|
+
export const idSchema = z
|
|
6
|
+
.string()
|
|
7
|
+
.regex(/^[A-Za-z0-9_-]+$/, "Invalid Megaplan id (letters, digits, _ or - only)");
|
|
8
|
+
/** Build the v3 list-query object (limit + filter + cursor). */
|
|
9
|
+
export function buildListQuery(opts) {
|
|
10
|
+
const query = { limit: opts.limit };
|
|
11
|
+
const terms = [];
|
|
12
|
+
const status = opts.status == null ? [] : Array.isArray(opts.status) ? opts.status : [opts.status];
|
|
13
|
+
if (status.length > 0) {
|
|
14
|
+
terms.push({
|
|
15
|
+
contentType: "FilterTermEnum",
|
|
16
|
+
field: "status",
|
|
17
|
+
comparison: "equals",
|
|
18
|
+
value: status,
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
for (const ref of opts.refs ?? []) {
|
|
22
|
+
if (!ref.id)
|
|
23
|
+
continue;
|
|
24
|
+
terms.push({
|
|
25
|
+
contentType: "FilterTermRef",
|
|
26
|
+
field: ref.field,
|
|
27
|
+
comparison: "equals",
|
|
28
|
+
value: [{ id: ref.id, contentType: ref.contentType }],
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
if (terms.length > 0) {
|
|
32
|
+
query.filter = {
|
|
33
|
+
// TODO(live-verify): per-entity filter contentType (e.g. Deal may be
|
|
34
|
+
// "TradeFilter" rather than "DealFilter") — confirm against the account RAML.
|
|
35
|
+
contentType: opts.filterContentType ?? `${opts.entity}Filter`,
|
|
36
|
+
id: null,
|
|
37
|
+
config: {
|
|
38
|
+
contentType: "FilterConfig",
|
|
39
|
+
termGroup: { contentType: "FilterTermGroup", join: "and", terms },
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
// TODO(live-verify): free-text search param name (q vs search vs a string
|
|
44
|
+
// filter term). `q` is the documented-likely candidate.
|
|
45
|
+
if (opts.search)
|
|
46
|
+
query.q = opts.search;
|
|
47
|
+
if (opts.pageAfter) {
|
|
48
|
+
query.pageAfter = { contentType: opts.entity, id: opts.pageAfter };
|
|
49
|
+
}
|
|
50
|
+
return query;
|
|
51
|
+
}
|
|
52
|
+
/** v3 date+time value object (deadlines etc. are entity objects, not bare strings). */
|
|
53
|
+
export function toDateTime(iso) {
|
|
54
|
+
return { contentType: "DateTime", value: iso };
|
|
55
|
+
}
|
|
56
|
+
/** v3 Money value object (money fields are complex objects, not bare numbers). */
|
|
57
|
+
export function toMoney(value, currency = "RUB") {
|
|
58
|
+
// TODO(live-verify): the API may also require `valueInMain`.
|
|
59
|
+
return { contentType: "Money", value, currency };
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=query.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query.js","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,+EAA+E;AAC/E,8EAA8E;AAC9E,iFAAiF;AACjF,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC;KACtB,MAAM,EAAE;KACR,KAAK,CAAC,kBAAkB,EAAE,oDAAoD,CAAC,CAAC;AAqCnF,gEAAgE;AAChE,MAAM,UAAU,cAAc,CAAC,IAAmB;IAChD,MAAM,KAAK,GAAS,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC;IAE1C,MAAM,KAAK,GAAW,EAAE,CAAC;IACzB,MAAM,MAAM,GACV,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACtF,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtB,KAAK,CAAC,IAAI,CAAC;YACT,WAAW,EAAE,gBAAgB;YAC7B,KAAK,EAAE,QAAQ;YACf,UAAU,EAAE,QAAQ;YACpB,KAAK,EAAE,MAAM;SACd,CAAC,CAAC;IACL,CAAC;IACD,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC;QAClC,IAAI,CAAC,GAAG,CAAC,EAAE;YAAE,SAAS;QACtB,KAAK,CAAC,IAAI,CAAC;YACT,WAAW,EAAE,eAAe;YAC5B,KAAK,EAAE,GAAG,CAAC,KAAK;YAChB,UAAU,EAAE,QAAQ;YACpB,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,WAAW,EAAE,GAAG,CAAC,WAAW,EAAE,CAAC;SACtD,CAAC,CAAC;IACL,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrB,KAAK,CAAC,MAAM,GAAG;YACb,qEAAqE;YACrE,8EAA8E;YAC9E,WAAW,EAAE,IAAI,CAAC,iBAAiB,IAAI,GAAG,IAAI,CAAC,MAAM,QAAQ;YAC7D,EAAE,EAAE,IAAI;YACR,MAAM,EAAE;gBACN,WAAW,EAAE,cAAc;gBAC3B,SAAS,EAAE,EAAE,WAAW,EAAE,iBAAiB,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE;aAClE;SACF,CAAC;IACJ,CAAC;IAED,0EAA0E;IAC1E,wDAAwD;IACxD,IAAI,IAAI,CAAC,MAAM;QAAE,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC;IAEvC,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;QACnB,KAAK,CAAC,SAAS,GAAG,EAAE,WAAW,EAAE,IAAI,CAAC,MAAM,EAAE,EAAE,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC;IACrE,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED,uFAAuF;AACvF,MAAM,UAAU,UAAU,CAAC,GAAW;IACpC,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;AACjD,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,OAAO,CAAC,KAAa,EAAE,QAAQ,GAAG,KAAK;IACrD,6DAA6D;IAC7D,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;AACnD,CAAC"}
|