@stubbedev/trimit-mcp 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +230 -0
- package/dist/categories/customers.js +187 -0
- package/dist/categories/exported.js +105 -0
- package/dist/categories/index.js +9 -0
- package/dist/categories/inventory.js +63 -0
- package/dist/categories/masterdata.js +246 -0
- package/dist/categories/metadata.js +27 -0
- package/dist/categories/postedsales.js +155 -0
- package/dist/categories/products.js +176 -0
- package/dist/categories/salesdocs.js +395 -0
- package/dist/categories/standard.js +228 -0
- package/dist/common.js +91 -0
- package/dist/index.js +10 -0
- package/dist/registry.js +27 -0
- package/dist/server.js +706 -0
- package/package.json +56 -0
package/dist/common.js
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
// Shared constants and helpers for TRIMIT API tool handlers.
|
|
2
|
+
//
|
|
3
|
+
// All TRIMIT endpoints are hosted by Microsoft Dynamics 365 Business Central
|
|
4
|
+
// at api.businesscentral.dynamics.com. There are three logical base URLs:
|
|
5
|
+
//
|
|
6
|
+
// trimit → /api/trimit/integration/v1.1/companies({companyId}) (TRIMIT custom extension)
|
|
7
|
+
// std → /api/v2.0/companies({companyId}) (Microsoft standard BC API)
|
|
8
|
+
// odata → /ODataV4 (BC OData v4 endpoint)
|
|
9
|
+
//
|
|
10
|
+
// Placeholders that the caller must substitute before issuing the request:
|
|
11
|
+
// {tenant} — Azure AD / Microsoft Entra tenant GUID (OAUTH_TENANT)
|
|
12
|
+
// {environment} — BC environment name (e.g. "Production", "Sandbox")
|
|
13
|
+
// {companyId} — BC company GUID (returned by GET /companies)
|
|
14
|
+
export const HOST = "https://api.businesscentral.dynamics.com/v2.0";
|
|
15
|
+
export const TRIMIT_API_PATH = "api/trimit/integration/v1.1";
|
|
16
|
+
export const STD_API_PATH = "api/v2.0";
|
|
17
|
+
export function trimitBase() {
|
|
18
|
+
return `${HOST}/{tenant}/{environment}/${TRIMIT_API_PATH}/companies({companyId})`;
|
|
19
|
+
}
|
|
20
|
+
export function stdBase() {
|
|
21
|
+
return `${HOST}/{tenant}/{environment}/${STD_API_PATH}/companies({companyId})`;
|
|
22
|
+
}
|
|
23
|
+
export function stdRoot() {
|
|
24
|
+
return `${HOST}/{tenant}/{environment}/${STD_API_PATH}`;
|
|
25
|
+
}
|
|
26
|
+
export function odataBase() {
|
|
27
|
+
return `${HOST}/{tenant}/{environment}/ODataV4`;
|
|
28
|
+
}
|
|
29
|
+
export function tenantRoot() {
|
|
30
|
+
return `${HOST}/{tenant}/{environment}`;
|
|
31
|
+
}
|
|
32
|
+
export function buildOdataQuery(q) {
|
|
33
|
+
const params = {};
|
|
34
|
+
const segments = [];
|
|
35
|
+
if (q.filter) {
|
|
36
|
+
params["$filter"] = q.filter;
|
|
37
|
+
segments.push(`$filter=${encodeURIComponent(q.filter)}`);
|
|
38
|
+
}
|
|
39
|
+
if (q.select?.length) {
|
|
40
|
+
const v = q.select.join(",");
|
|
41
|
+
params["$select"] = v;
|
|
42
|
+
segments.push(`$select=${v}`);
|
|
43
|
+
}
|
|
44
|
+
if (q.expand) {
|
|
45
|
+
params["$expand"] = q.expand;
|
|
46
|
+
segments.push(`$expand=${encodeURIComponent(q.expand)}`);
|
|
47
|
+
}
|
|
48
|
+
if (q.top !== undefined) {
|
|
49
|
+
params["$top"] = String(q.top);
|
|
50
|
+
segments.push(`$top=${q.top}`);
|
|
51
|
+
}
|
|
52
|
+
if (q.skip !== undefined) {
|
|
53
|
+
params["$skip"] = String(q.skip);
|
|
54
|
+
segments.push(`$skip=${q.skip}`);
|
|
55
|
+
}
|
|
56
|
+
if (q.orderby) {
|
|
57
|
+
params["$orderby"] = q.orderby;
|
|
58
|
+
segments.push(`$orderby=${encodeURIComponent(q.orderby)}`);
|
|
59
|
+
}
|
|
60
|
+
if (q.count !== undefined) {
|
|
61
|
+
params["$count"] = String(q.count);
|
|
62
|
+
segments.push(`$count=${q.count}`);
|
|
63
|
+
}
|
|
64
|
+
return { qs: segments.length ? `?${segments.join("&")}` : "", params };
|
|
65
|
+
}
|
|
66
|
+
export function buildHeaders(extra) {
|
|
67
|
+
return {
|
|
68
|
+
Authorization: "Bearer {token}",
|
|
69
|
+
"Content-Type": "application/json",
|
|
70
|
+
Accept: "application/json",
|
|
71
|
+
...(extra ?? {}),
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
export const TRIMIT_AUTH = {
|
|
75
|
+
type: "OAuth 2.0 — Microsoft Entra (Azure AD) client credentials",
|
|
76
|
+
tokenEndpoint: "https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token",
|
|
77
|
+
scope: "https://api.businesscentral.dynamics.com/.default",
|
|
78
|
+
notes: "Customer-tenant Entra app registration with Business Central / TRIMIT integration consent. Send bearer token in Authorization header.",
|
|
79
|
+
};
|
|
80
|
+
export function fetchExample(endpoint, method, body, extraHeaders) {
|
|
81
|
+
const headers = {
|
|
82
|
+
Authorization: "Bearer {token}",
|
|
83
|
+
...(body !== null && body !== undefined ? { "Content-Type": "application/json" } : {}),
|
|
84
|
+
...(extraHeaders ?? {}),
|
|
85
|
+
};
|
|
86
|
+
const headerLines = JSON.stringify(headers);
|
|
87
|
+
if (body === null || body === undefined) {
|
|
88
|
+
return `const response = await fetch('${endpoint}', {\n method: '${method}',\n headers: ${headerLines}\n});\nconst data = await response.json();`;
|
|
89
|
+
}
|
|
90
|
+
return `const response = await fetch('${endpoint}', {\n method: '${method}',\n headers: ${headerLines},\n body: JSON.stringify(${JSON.stringify(body, null, 2)})\n});\nconst data = await response.json();`;
|
|
91
|
+
}
|
package/dist/index.js
ADDED
package/dist/registry.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export class ToolRegistry {
|
|
2
|
+
tools = new Map();
|
|
3
|
+
loadedCategories = new Set();
|
|
4
|
+
registerCategory(categoryName, categoryTools) {
|
|
5
|
+
const newToolNames = [];
|
|
6
|
+
for (const tool of categoryTools) {
|
|
7
|
+
this.tools.set(tool.name, tool);
|
|
8
|
+
newToolNames.push(tool.name);
|
|
9
|
+
}
|
|
10
|
+
this.loadedCategories.add(categoryName);
|
|
11
|
+
return newToolNames;
|
|
12
|
+
}
|
|
13
|
+
unregisterCategory(categoryName) {
|
|
14
|
+
for (const [name, tool] of this.tools.entries()) {
|
|
15
|
+
if (tool.category === categoryName) {
|
|
16
|
+
this.tools.delete(name);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
this.loadedCategories.delete(categoryName);
|
|
20
|
+
}
|
|
21
|
+
getAll() {
|
|
22
|
+
return Array.from(this.tools.values());
|
|
23
|
+
}
|
|
24
|
+
get(name) {
|
|
25
|
+
return this.tools.get(name);
|
|
26
|
+
}
|
|
27
|
+
}
|