@vjeko.com/al-object-id-ninja-mcp 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.
Files changed (65) hide show
  1. package/README.md +115 -0
  2. package/dist/src/al-app/ALApp.d.ts +52 -0
  3. package/dist/src/al-app/ALApp.js +130 -0
  4. package/dist/src/al-app/ALApp.js.map +1 -0
  5. package/dist/src/al-app/ALAppManifest.d.ts +39 -0
  6. package/dist/src/al-app/ALAppManifest.js +114 -0
  7. package/dist/src/al-app/ALAppManifest.js.map +1 -0
  8. package/dist/src/al-app/AppResolver.d.ts +24 -0
  9. package/dist/src/al-app/AppResolver.js +100 -0
  10. package/dist/src/al-app/AppResolver.js.map +1 -0
  11. package/dist/src/al-app/ObjIdConfig.d.ts +23 -0
  12. package/dist/src/al-app/ObjIdConfig.js +84 -0
  13. package/dist/src/al-app/ObjIdConfig.js.map +1 -0
  14. package/dist/src/al-app/index.d.ts +4 -0
  15. package/dist/src/al-app/index.js +12 -0
  16. package/dist/src/al-app/index.js.map +1 -0
  17. package/dist/src/backend/BackendClient.d.ts +35 -0
  18. package/dist/src/backend/BackendClient.js +129 -0
  19. package/dist/src/backend/BackendClient.js.map +1 -0
  20. package/dist/src/backend/index.d.ts +1 -0
  21. package/dist/src/backend/index.js +6 -0
  22. package/dist/src/backend/index.js.map +1 -0
  23. package/dist/src/index.d.ts +2 -0
  24. package/dist/src/index.js +9 -0
  25. package/dist/src/index.js.map +1 -0
  26. package/dist/src/server.d.ts +3 -0
  27. package/dist/src/server.js +108 -0
  28. package/dist/src/server.js.map +1 -0
  29. package/dist/src/tools/AssignObjectIdTool.d.ts +16 -0
  30. package/dist/src/tools/AssignObjectIdTool.js +83 -0
  31. package/dist/src/tools/AssignObjectIdTool.js.map +1 -0
  32. package/dist/src/tools/UnassignObjectIdTool.d.ts +16 -0
  33. package/dist/src/tools/UnassignObjectIdTool.js +50 -0
  34. package/dist/src/tools/UnassignObjectIdTool.js.map +1 -0
  35. package/dist/src/tools/index.d.ts +3 -0
  36. package/dist/src/tools/index.js +8 -0
  37. package/dist/src/tools/index.js.map +1 -0
  38. package/dist/src/types/ALObjectType.d.ts +15 -0
  39. package/dist/src/types/ALObjectType.js +20 -0
  40. package/dist/src/types/ALObjectType.js.map +1 -0
  41. package/dist/src/types/ALRange.d.ts +7 -0
  42. package/dist/src/types/ALRange.js +3 -0
  43. package/dist/src/types/ALRange.js.map +1 -0
  44. package/dist/src/types/NextObjectIdInfo.d.ts +9 -0
  45. package/dist/src/types/NextObjectIdInfo.js +3 -0
  46. package/dist/src/types/NextObjectIdInfo.js.map +1 -0
  47. package/dist/src/types/NinjaALRange.d.ts +4 -0
  48. package/dist/src/types/NinjaALRange.js +3 -0
  49. package/dist/src/types/NinjaALRange.js.map +1 -0
  50. package/dist/src/types/PropertyBag.d.ts +3 -0
  51. package/dist/src/types/PropertyBag.js +3 -0
  52. package/dist/src/types/PropertyBag.js.map +1 -0
  53. package/dist/src/types/index.d.ts +5 -0
  54. package/dist/src/types/index.js +6 -0
  55. package/dist/src/types/index.js.map +1 -0
  56. package/dist/src/utils/getSha256.d.ts +1 -0
  57. package/dist/src/utils/getSha256.js +43 -0
  58. package/dist/src/utils/getSha256.js.map +1 -0
  59. package/dist/src/utils/index.d.ts +2 -0
  60. package/dist/src/utils/index.js +9 -0
  61. package/dist/src/utils/index.js.map +1 -0
  62. package/dist/src/utils/validation.d.ts +2 -0
  63. package/dist/src/utils/validation.js +20 -0
  64. package/dist/src/utils/validation.js.map +1 -0
  65. package/package.json +59 -0
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.ObjIdConfig = void 0;
37
+ const fs = __importStar(require("fs"));
38
+ const comment_json_1 = require("comment-json");
39
+ /**
40
+ * Read-only representation of the .objidconfig file.
41
+ */
42
+ class ObjIdConfig {
43
+ _path;
44
+ _config;
45
+ constructor(configPath) {
46
+ this._path = configPath;
47
+ this._config = this.read();
48
+ }
49
+ read() {
50
+ try {
51
+ const content = fs.readFileSync(this._path).toString() || "{}";
52
+ return (0, comment_json_1.parse)(content);
53
+ }
54
+ catch {
55
+ return {};
56
+ }
57
+ }
58
+ get path() {
59
+ return this._path;
60
+ }
61
+ get authKey() {
62
+ return this._config.authKey || "";
63
+ }
64
+ get appPoolId() {
65
+ return this._config.appPoolId || "";
66
+ }
67
+ get idRanges() {
68
+ return [...(this._config.idRanges || [])];
69
+ }
70
+ get objectRanges() {
71
+ return this._config.objectRanges || {};
72
+ }
73
+ /**
74
+ * Gets ranges for the specified object type.
75
+ * Falls back to idRanges if no object-specific ranges are defined.
76
+ * @param objectType Object type for which to get ranges
77
+ * @returns Ranges for the specified object type
78
+ */
79
+ getObjectTypeRanges(objectType) {
80
+ return this.objectRanges[objectType] || this.idRanges;
81
+ }
82
+ }
83
+ exports.ObjIdConfig = ObjIdConfig;
84
+ //# sourceMappingURL=ObjIdConfig.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ObjIdConfig.js","sourceRoot":"","sources":["../../../src/al-app/ObjIdConfig.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,uCAAyB;AACzB,+CAAqC;AAWrC;;GAEG;AACH,MAAa,WAAW;IACH,KAAK,CAAS;IACd,OAAO,CAAkB;IAE1C,YAAmB,UAAkB;QACjC,IAAI,CAAC,KAAK,GAAG,UAAU,CAAC;QACxB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IAC/B,CAAC;IAEO,IAAI;QACR,IAAI,CAAC;YACD,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,QAAQ,EAAE,IAAI,IAAI,CAAC;YAC/D,OAAO,IAAA,oBAAK,EAAC,OAAO,CAA+B,CAAC;QACxD,CAAC;QAAC,MAAM,CAAC;YACL,OAAO,EAAqB,CAAC;QACjC,CAAC;IACL,CAAC;IAED,IAAW,IAAI;QACX,OAAO,IAAI,CAAC,KAAK,CAAC;IACtB,CAAC;IAED,IAAW,OAAO;QACd,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC;IACtC,CAAC;IAED,IAAW,SAAS;QAChB,OAAO,IAAI,CAAC,OAAO,CAAC,SAAS,IAAI,EAAE,CAAC;IACxC,CAAC;IAED,IAAW,QAAQ;QACf,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,CAAC;IAC9C,CAAC;IAED,IAAW,YAAY;QACnB,OAAO,IAAI,CAAC,OAAO,CAAC,YAAY,IAAI,EAAE,CAAC;IAC3C,CAAC;IAED;;;;;OAKG;IACH,mBAAmB,CAAC,UAAkB;QAClC,OAAO,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC;IAC1D,CAAC;CACJ;AA/CD,kCA+CC"}
@@ -0,0 +1,4 @@
1
+ export { ALApp } from "./ALApp";
2
+ export { ALAppManifest } from "./ALAppManifest";
3
+ export { ObjIdConfig } from "./ObjIdConfig";
4
+ export { AppResolver } from "./AppResolver";
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AppResolver = exports.ObjIdConfig = exports.ALAppManifest = exports.ALApp = void 0;
4
+ var ALApp_1 = require("./ALApp");
5
+ Object.defineProperty(exports, "ALApp", { enumerable: true, get: function () { return ALApp_1.ALApp; } });
6
+ var ALAppManifest_1 = require("./ALAppManifest");
7
+ Object.defineProperty(exports, "ALAppManifest", { enumerable: true, get: function () { return ALAppManifest_1.ALAppManifest; } });
8
+ var ObjIdConfig_1 = require("./ObjIdConfig");
9
+ Object.defineProperty(exports, "ObjIdConfig", { enumerable: true, get: function () { return ObjIdConfig_1.ObjIdConfig; } });
10
+ var AppResolver_1 = require("./AppResolver");
11
+ Object.defineProperty(exports, "AppResolver", { enumerable: true, get: function () { return AppResolver_1.AppResolver; } });
12
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/al-app/index.ts"],"names":[],"mappings":";;;AAAA,iCAAgC;AAAvB,8FAAA,KAAK,OAAA;AACd,iDAAgD;AAAvC,8GAAA,aAAa,OAAA;AACtB,6CAA4C;AAAnC,0GAAA,WAAW,OAAA;AACpB,6CAA4C;AAAnC,0GAAA,WAAW,OAAA"}
@@ -0,0 +1,35 @@
1
+ import { ALApp } from "../al-app/ALApp";
2
+ import { NinjaALRange } from "../types/NinjaALRange";
3
+ import { NextObjectIdInfo } from "../types/NextObjectIdInfo";
4
+ /**
5
+ * HTTP client for communicating with the AL Object ID Ninja backend API.
6
+ */
7
+ export declare class BackendClient {
8
+ /**
9
+ * Gets the next available object ID from the backend.
10
+ * @param app The AL app
11
+ * @param type Object type (e.g., "table", "codeunit")
12
+ * @param ranges Ranges to allocate from
13
+ * @param commit Whether to commit the allocation
14
+ * @param require Optional specific range starting ID to require
15
+ * @returns NextObjectIdInfo or undefined on failure
16
+ */
17
+ static getNextNo(app: ALApp, type: string, ranges: NinjaALRange[], commit: boolean, require?: number): Promise<NextObjectIdInfo | undefined>;
18
+ /**
19
+ * Removes (unassigns) an object ID assignment.
20
+ * @param app The AL app
21
+ * @param type Object type
22
+ * @param id Object ID to unassign
23
+ * @returns true if the assignment was removed, false otherwise
24
+ */
25
+ static removeAssignment(app: ALApp, type: string, id: number): Promise<boolean>;
26
+ /**
27
+ * Sends a request to the backend API.
28
+ * @param path API endpoint path
29
+ * @param method HTTP method
30
+ * @param data Request body
31
+ * @param app ALApp for auth key and manifest info
32
+ * @returns Response data or undefined on error
33
+ */
34
+ private static sendRequest;
35
+ }
@@ -0,0 +1,129 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BackendClient = void 0;
4
+ const child_process_1 = require("child_process");
5
+ const BACKEND_URL = "https://backend.alid.ninja";
6
+ // Must be >= 3.1.0 to pass backend version check
7
+ const MCP_VERSION = "3.1.0";
8
+ /**
9
+ * Executes a git command and returns the output.
10
+ */
11
+ function execGitCommand(command, cwd) {
12
+ return new Promise((resolve) => {
13
+ (0, child_process_1.exec)(`git ${command}`, { cwd, windowsHide: true }, (error, stdout) => {
14
+ if (error) {
15
+ resolve("");
16
+ return;
17
+ }
18
+ resolve(stdout.trim());
19
+ });
20
+ });
21
+ }
22
+ /**
23
+ * Gets git user info (name and email) for the given directory.
24
+ * Always reads fresh from git config - no caching.
25
+ */
26
+ async function getGitUserInfo(cwd) {
27
+ const [name, email] = await Promise.all([
28
+ execGitCommand("config user.name", cwd),
29
+ execGitCommand("config user.email", cwd),
30
+ ]);
31
+ return {
32
+ name,
33
+ email: email.toLowerCase(),
34
+ };
35
+ }
36
+ /**
37
+ * HTTP client for communicating with the AL Object ID Ninja backend API.
38
+ */
39
+ class BackendClient {
40
+ /**
41
+ * Gets the next available object ID from the backend.
42
+ * @param app The AL app
43
+ * @param type Object type (e.g., "table", "codeunit")
44
+ * @param ranges Ranges to allocate from
45
+ * @param commit Whether to commit the allocation
46
+ * @param require Optional specific range starting ID to require
47
+ * @returns NextObjectIdInfo or undefined on failure
48
+ */
49
+ static async getNextNo(app, type, ranges, commit, require) {
50
+ const appId = app.config.appPoolId || app.hash;
51
+ const body = {
52
+ appId,
53
+ type,
54
+ ranges,
55
+ commit,
56
+ perRange: true,
57
+ };
58
+ if (commit && require) {
59
+ body.require = require;
60
+ }
61
+ const response = await this.sendRequest(`/api/v3/getNext/${appId}`, "POST", body, app);
62
+ return response;
63
+ }
64
+ /**
65
+ * Removes (unassigns) an object ID assignment.
66
+ * @param app The AL app
67
+ * @param type Object type
68
+ * @param id Object ID to unassign
69
+ * @returns true if the assignment was removed, false otherwise
70
+ */
71
+ static async removeAssignment(app, type, id) {
72
+ const appId = app.config.appPoolId || app.hash;
73
+ const response = await this.sendRequest(`/api/v3/storeAssignment/${appId}/${type}/${id}/delete`, "POST", { appId }, app);
74
+ return !!response?.updated;
75
+ }
76
+ /**
77
+ * Sends a request to the backend API.
78
+ * @param path API endpoint path
79
+ * @param method HTTP method
80
+ * @param data Request body
81
+ * @param app ALApp for auth key and manifest info
82
+ * @returns Response data or undefined on error
83
+ */
84
+ static async sendRequest(path, method, data, app) {
85
+ const url = `${BACKEND_URL}${path}`;
86
+ const headers = {
87
+ "Content-Type": "application/json",
88
+ };
89
+ // Add auth key if available
90
+ if (app.authKey) {
91
+ headers["Ninja-Auth-Key"] = app.authKey;
92
+ }
93
+ // Add app ID header
94
+ if (app.manifest.id) {
95
+ headers["Ninja-App-Id"] = app.manifest.id;
96
+ }
97
+ // Get git user info fresh for every request
98
+ const gitUser = await getGitUserInfo(app.rootPath);
99
+ // Build header payload (must include ninjaVersion >= 3.1.0)
100
+ const headerPayload = {
101
+ gitUserName: gitUser.name || undefined,
102
+ gitUserEmail: gitUser.email || undefined,
103
+ appPublisher: app.manifest.publisher,
104
+ appName: app.manifest.name,
105
+ appVersion: app.manifest.version,
106
+ ninjaVersion: MCP_VERSION,
107
+ source: "mcp",
108
+ };
109
+ headers["Ninja-Header-Payload"] = Buffer.from(JSON.stringify(headerPayload)).toString("base64");
110
+ try {
111
+ const response = await fetch(url, {
112
+ method,
113
+ headers,
114
+ body: data ? JSON.stringify(data) : undefined,
115
+ });
116
+ if (!response.ok) {
117
+ const body = await response.text();
118
+ throw new Error(`HTTP ${response.status}: ${response.statusText} - ${body}`);
119
+ }
120
+ return await response.json();
121
+ }
122
+ catch (error) {
123
+ const message = error instanceof Error ? error.message : String(error);
124
+ throw new Error(`Backend request failed: ${message}`);
125
+ }
126
+ }
127
+ }
128
+ exports.BackendClient = BackendClient;
129
+ //# sourceMappingURL=BackendClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BackendClient.js","sourceRoot":"","sources":["../../../src/backend/BackendClient.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export { BackendClient } from "./BackendClient";
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BackendClient = void 0;
4
+ var BackendClient_1 = require("./BackendClient");
5
+ Object.defineProperty(exports, "BackendClient", { enumerable: true, get: function () { return BackendClient_1.BackendClient; } });
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/backend/index.ts"],"names":[],"mappings":";;;AAAA,iDAAgD;AAAvC,8GAAA,aAAa,OAAA"}
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const server_1 = require("./server");
5
+ (0, server_1.runServer)().catch((error) => {
6
+ console.error("Failed to start MCP server:", error);
7
+ process.exit(1);
8
+ });
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;AAEA,qCAAqC;AAErC,IAAA,kBAAS,GAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACxB,OAAO,CAAC,KAAK,CAAC,6BAA6B,EAAE,KAAK,CAAC,CAAC;IACpD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACpB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
2
+ export declare function createServer(): Server;
3
+ export declare function runServer(): Promise<void>;
@@ -0,0 +1,108 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createServer = createServer;
4
+ exports.runServer = runServer;
5
+ const index_js_1 = require("@modelcontextprotocol/sdk/server/index.js");
6
+ const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
7
+ const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
8
+ const tools_1 = require("./tools");
9
+ function toCallToolResult(result) {
10
+ return {
11
+ content: result.content,
12
+ isError: result.isError,
13
+ };
14
+ }
15
+ const TOOL_DEFINITIONS = [
16
+ {
17
+ name: "ninja_assignObjectId",
18
+ description: "Assigns and commits the next available AL object ID. " +
19
+ "The ID is reserved immediately and can be used in the AL object file. " +
20
+ "Use this when creating new AL objects that require IDs (tables, pages, codeunits, etc.).",
21
+ inputSchema: {
22
+ type: "object",
23
+ properties: {
24
+ objectType: {
25
+ type: "string",
26
+ description: "The AL object type. Valid types: codeunit, enum, enumextension, page, pageextension, " +
27
+ "permissionset, permissionsetextension, query, report, reportextension, table, " +
28
+ "tableextension, xmlport. For table fields use table_{tableId}, for enum values use enum_{enumId}.",
29
+ },
30
+ targetFilePath: {
31
+ type: "string",
32
+ description: "Absolute path to a file within the AL app. Used to identify which AL app to assign the ID for.",
33
+ },
34
+ rangeName: {
35
+ type: "string",
36
+ description: "Optional. Name of the logical range to use when multiple ranges are configured. " +
37
+ "Required when the app has multiple ranges defined for the object type.",
38
+ },
39
+ },
40
+ required: ["objectType", "targetFilePath"],
41
+ },
42
+ },
43
+ {
44
+ name: "ninja_unassignObjectId",
45
+ description: "Unassigns (releases) a previously assigned AL object ID, making it available for future assignments. " +
46
+ "Use this when deleting an AL object or when an ID was assigned by mistake.",
47
+ inputSchema: {
48
+ type: "object",
49
+ properties: {
50
+ objectType: {
51
+ type: "string",
52
+ description: "The AL object type. Valid types: codeunit, enum, enumextension, page, pageextension, " +
53
+ "permissionset, permissionsetextension, query, report, reportextension, table, " +
54
+ "tableextension, xmlport. For table fields use table_{tableId}, for enum values use enum_{enumId}.",
55
+ },
56
+ objectId: {
57
+ type: "number",
58
+ description: "The object ID to unassign. Must be a positive number.",
59
+ },
60
+ targetFilePath: {
61
+ type: "string",
62
+ description: "Absolute path to a file within the AL app. Used to identify which AL app to unassign the ID from.",
63
+ },
64
+ },
65
+ required: ["objectType", "objectId", "targetFilePath"],
66
+ },
67
+ },
68
+ ];
69
+ function createServer() {
70
+ const server = new index_js_1.Server({
71
+ name: "AL Object ID Ninja",
72
+ version: "3.1.5",
73
+ }, {
74
+ capabilities: {
75
+ tools: {},
76
+ },
77
+ });
78
+ // List available tools
79
+ server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => {
80
+ return { tools: TOOL_DEFINITIONS };
81
+ });
82
+ // Handle tool calls
83
+ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
84
+ const { name, arguments: args } = request.params;
85
+ switch (name) {
86
+ case "ninja_assignObjectId": {
87
+ const input = args;
88
+ return toCallToolResult(await (0, tools_1.assignObjectId)(input));
89
+ }
90
+ case "ninja_unassignObjectId": {
91
+ const input = args;
92
+ return toCallToolResult(await (0, tools_1.unassignObjectId)(input));
93
+ }
94
+ default:
95
+ return {
96
+ content: [{ type: "text", text: `Unknown tool: ${name}` }],
97
+ isError: true,
98
+ };
99
+ }
100
+ });
101
+ return server;
102
+ }
103
+ async function runServer() {
104
+ const server = createServer();
105
+ const transport = new stdio_js_1.StdioServerTransport();
106
+ await server.connect(transport);
107
+ }
108
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ export interface AssignObjectIdInput {
2
+ objectType: string;
3
+ targetFilePath: string;
4
+ rangeName?: string;
5
+ }
6
+ export interface McpToolResult {
7
+ content: Array<{
8
+ type: "text";
9
+ text: string;
10
+ }>;
11
+ isError?: boolean;
12
+ }
13
+ /**
14
+ * Assigns and commits the next available AL object ID.
15
+ */
16
+ export declare function assignObjectId(input: AssignObjectIdInput): Promise<McpToolResult>;
@@ -0,0 +1,83 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.assignObjectId = assignObjectId;
4
+ const AppResolver_1 = require("../al-app/AppResolver");
5
+ const BackendClient_1 = require("../backend/BackendClient");
6
+ const validation_1 = require("../utils/validation");
7
+ function makeResult(text, isError = false) {
8
+ return {
9
+ content: [{ type: "text", text }],
10
+ isError,
11
+ };
12
+ }
13
+ /**
14
+ * Assigns and commits the next available AL object ID.
15
+ */
16
+ async function assignObjectId(input) {
17
+ const { objectType, targetFilePath, rangeName } = input;
18
+ const type = objectType.toLowerCase();
19
+ // Validate object type
20
+ if (!(0, validation_1.isValidObjectType)(type)) {
21
+ return makeResult(`Error: Invalid object type "${objectType}". ${(0, validation_1.getValidTypesMessage)()}`, true);
22
+ }
23
+ // Resolve AL app from file path
24
+ const app = AppResolver_1.AppResolver.resolveFromPath(targetFilePath);
25
+ if (!app) {
26
+ return makeResult(`Error: No AL app found for path "${targetFilePath}". ` +
27
+ `The path must be within an AL app folder (a folder containing app.json).`, true);
28
+ }
29
+ // Get ranges for the object type
30
+ const ranges = app.getObjectTypeRanges(type);
31
+ if (ranges.length === 0) {
32
+ return makeResult(`Error: No ID ranges found for ${type}. ` +
33
+ `Configure ranges in app.json (idRanges property) or .objidconfig.`, true);
34
+ }
35
+ // Check if we need range selection
36
+ if (ranges.length > 1 && !rangeName) {
37
+ const rangeList = ranges
38
+ .map(r => `- "${r.description}": ${r.from}-${r.to}`)
39
+ .join("\n");
40
+ return makeResult(`Error: Multiple ranges available for ${type}. You must specify which range to use via the rangeName parameter.\n\n` +
41
+ `Available ranges:\n${rangeList}\n\n` +
42
+ `Either decide based on the object's purpose (e.g., "Temporary Tables" for temp tables) ` +
43
+ `or ask the user which range to use.`, true);
44
+ }
45
+ // Find the target range
46
+ let targetRange;
47
+ if (rangeName) {
48
+ const found = ranges.find(r => r.description?.toLowerCase() === rangeName.toLowerCase());
49
+ if (!found) {
50
+ const available = ranges.map(r => `"${r.description}"`).join(", ");
51
+ return makeResult(`Error: Range "${rangeName}" not found for ${type}. Available ranges: ${available}`, true);
52
+ }
53
+ targetRange = found;
54
+ }
55
+ else {
56
+ targetRange = ranges[0];
57
+ }
58
+ try {
59
+ // Send request to backend with the target range
60
+ const singleRange = [targetRange];
61
+ const result = await BackendClient_1.BackendClient.getNextNo(app, type, singleRange, true, targetRange.from);
62
+ if (!result) {
63
+ return makeResult(`Error: Failed to get next ${type} ID. The backend did not return a result.`, true);
64
+ }
65
+ if (!result.available) {
66
+ return makeResult(`Error: No ${type} IDs available in range "${targetRange.description}" (${targetRange.from}-${targetRange.to}). ` +
67
+ `All IDs in this range have been consumed.`, true);
68
+ }
69
+ const id = Array.isArray(result.id) ? result.id[0] : result.id;
70
+ const rangeDisplay = targetRange.description
71
+ ? `${targetRange.description} (${targetRange.from}-${targetRange.to})`
72
+ : `${targetRange.from}-${targetRange.to}`;
73
+ return makeResult(`Successfully committed ${type} ID: ${id}\n` +
74
+ `App: ${app.manifest.name}\n` +
75
+ `Range: ${rangeDisplay}\n` +
76
+ `This ID has been reserved and can be used immediately.`);
77
+ }
78
+ catch (error) {
79
+ const errorMessage = error instanceof Error ? error.message : String(error);
80
+ return makeResult(`Error: Failed to commit ${type} ID: ${errorMessage}`, true);
81
+ }
82
+ }
83
+ //# sourceMappingURL=AssignObjectIdTool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AssignObjectIdTool.js","sourceRoot":"","sources":["../../../src/tools/AssignObjectIdTool.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ export interface UnassignObjectIdInput {
2
+ objectType: string;
3
+ objectId: number;
4
+ targetFilePath: string;
5
+ }
6
+ export interface McpToolResult {
7
+ content: Array<{
8
+ type: "text";
9
+ text: string;
10
+ }>;
11
+ isError?: boolean;
12
+ }
13
+ /**
14
+ * Unassigns (releases) a previously assigned AL object ID.
15
+ */
16
+ export declare function unassignObjectId(input: UnassignObjectIdInput): Promise<McpToolResult>;
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.unassignObjectId = unassignObjectId;
4
+ const AppResolver_1 = require("../al-app/AppResolver");
5
+ const BackendClient_1 = require("../backend/BackendClient");
6
+ const validation_1 = require("../utils/validation");
7
+ function makeResult(text, isError = false) {
8
+ return {
9
+ content: [{ type: "text", text }],
10
+ isError,
11
+ };
12
+ }
13
+ /**
14
+ * Unassigns (releases) a previously assigned AL object ID.
15
+ */
16
+ async function unassignObjectId(input) {
17
+ const { objectType, objectId, targetFilePath } = input;
18
+ const type = objectType.toLowerCase();
19
+ // Validate object type
20
+ if (!(0, validation_1.isValidObjectType)(type)) {
21
+ return makeResult(`Error: Invalid object type "${objectType}". ${(0, validation_1.getValidTypesMessage)()}`, true);
22
+ }
23
+ // Validate object ID
24
+ if (typeof objectId !== "number" || objectId <= 0) {
25
+ return makeResult(`Error: Invalid object ID "${objectId}". Must be a positive number.`, true);
26
+ }
27
+ // Resolve AL app from file path
28
+ const app = AppResolver_1.AppResolver.resolveFromPath(targetFilePath);
29
+ if (!app) {
30
+ return makeResult(`Error: No AL app found for path "${targetFilePath}". ` +
31
+ `The path must be within an AL app folder (a folder containing app.json).`, true);
32
+ }
33
+ try {
34
+ const success = await BackendClient_1.BackendClient.removeAssignment(app, type, objectId);
35
+ if (success) {
36
+ return makeResult(`Successfully unassigned ${type} ID: ${objectId}\n` +
37
+ `App: ${app.manifest.name}\n` +
38
+ `The ID has been released and is now available for future assignments.`);
39
+ }
40
+ else {
41
+ return makeResult(`Warning: Unassign request for ${type} ID ${objectId} completed but no changes were made. ` +
42
+ `The ID may not have been assigned or was already unassigned.`);
43
+ }
44
+ }
45
+ catch (error) {
46
+ const errorMessage = error instanceof Error ? error.message : String(error);
47
+ return makeResult(`Error: Failed to unassign ${type} ID ${objectId}: ${errorMessage}`, true);
48
+ }
49
+ }
50
+ //# sourceMappingURL=UnassignObjectIdTool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UnassignObjectIdTool.js","sourceRoot":"","sources":["../../../src/tools/UnassignObjectIdTool.ts"],"names":[],"mappings":";;AAyBA,4CAoDC;AA7ED,uDAAoD;AACpD,4DAAyD;AACzD,oDAA8E;AAa9E,SAAS,UAAU,CAAC,IAAY,EAAE,OAAO,GAAG,KAAK;IAC7C,OAAO;QACH,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;QACjC,OAAO;KACV,CAAC;AACN,CAAC;AAED;;GAEG;AACI,KAAK,UAAU,gBAAgB,CAAC,KAA4B;IAC/D,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,cAAc,EAAE,GAAG,KAAK,CAAC;IACvD,MAAM,IAAI,GAAG,UAAU,CAAC,WAAW,EAAE,CAAC;IAEtC,uBAAuB;IACvB,IAAI,CAAC,IAAA,8BAAiB,EAAC,IAAI,CAAC,EAAE,CAAC;QAC3B,OAAO,UAAU,CACb,+BAA+B,UAAU,MAAM,IAAA,iCAAoB,GAAE,EAAE,EACvE,IAAI,CACP,CAAC;IACN,CAAC;IAED,qBAAqB;IACrB,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,IAAI,CAAC,EAAE,CAAC;QAChD,OAAO,UAAU,CACb,6BAA6B,QAAQ,+BAA+B,EACpE,IAAI,CACP,CAAC;IACN,CAAC;IAED,gCAAgC;IAChC,MAAM,GAAG,GAAG,yBAAW,CAAC,eAAe,CAAC,cAAc,CAAC,CAAC;IACxD,IAAI,CAAC,GAAG,EAAE,CAAC;QACP,OAAO,UAAU,CACb,oCAAoC,cAAc,KAAK;YACvD,0EAA0E,EAC1E,IAAI,CACP,CAAC;IACN,CAAC;IAED,IAAI,CAAC;QACD,MAAM,OAAO,GAAG,MAAM,6BAAa,CAAC,gBAAgB,CAAC,GAAG,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;QAE1E,IAAI,OAAO,EAAE,CAAC;YACV,OAAO,UAAU,CACb,2BAA2B,IAAI,QAAQ,QAAQ,IAAI;gBACnD,QAAQ,GAAG,CAAC,QAAQ,CAAC,IAAI,IAAI;gBAC7B,uEAAuE,CAC1E,CAAC;QACN,CAAC;aAAM,CAAC;YACJ,OAAO,UAAU,CACb,iCAAiC,IAAI,OAAO,QAAQ,uCAAuC;gBAC3F,8DAA8D,CACjE,CAAC;QACN,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,MAAM,YAAY,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC5E,OAAO,UAAU,CACb,6BAA6B,IAAI,OAAO,QAAQ,KAAK,YAAY,EAAE,EACnE,IAAI,CACP,CAAC;IACN,CAAC;AACL,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { assignObjectId, AssignObjectIdInput } from "./AssignObjectIdTool";
2
+ export { unassignObjectId, UnassignObjectIdInput } from "./UnassignObjectIdTool";
3
+ export { McpToolResult } from "./AssignObjectIdTool";
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.unassignObjectId = exports.assignObjectId = void 0;
4
+ var AssignObjectIdTool_1 = require("./AssignObjectIdTool");
5
+ Object.defineProperty(exports, "assignObjectId", { enumerable: true, get: function () { return AssignObjectIdTool_1.assignObjectId; } });
6
+ var UnassignObjectIdTool_1 = require("./UnassignObjectIdTool");
7
+ Object.defineProperty(exports, "unassignObjectId", { enumerable: true, get: function () { return UnassignObjectIdTool_1.unassignObjectId; } });
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/tools/index.ts"],"names":[],"mappings":";;;AAAA,2DAA2E;AAAlE,oHAAA,cAAc,OAAA;AACvB,+DAAiF;AAAxE,wHAAA,gBAAgB,OAAA"}