@o3r/mcp 13.3.0-prerelease.2 → 13.3.0-prerelease.22

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 (38) hide show
  1. package/README.md +3 -0
  2. package/package.json +13 -11
  3. package/src/best-practices/index.d.ts +8 -0
  4. package/src/best-practices/index.d.ts.map +1 -0
  5. package/src/best-practices/index.js +52 -0
  6. package/src/best-practices/index.js.map +1 -0
  7. package/src/cli/index.js +4 -3
  8. package/src/cli/index.js.map +1 -1
  9. package/src/{tools/create-monorepo-with-app.d.ts → create-monorepo-with-app/index.d.ts} +1 -1
  10. package/src/create-monorepo-with-app/index.d.ts.map +1 -0
  11. package/src/{tools/create-monorepo-with-app.js → create-monorepo-with-app/index.js} +1 -1
  12. package/src/create-monorepo-with-app/index.js.map +1 -0
  13. package/src/mcp-server.d.ts +3 -1
  14. package/src/mcp-server.d.ts.map +1 -1
  15. package/src/mcp-server.js +38 -9
  16. package/src/mcp-server.js.map +1 -1
  17. package/src/utils/otter.d.ts +21 -0
  18. package/src/utils/otter.d.ts.map +1 -0
  19. package/src/utils/otter.js +30 -0
  20. package/src/utils/otter.js.map +1 -0
  21. package/src/instructions/best-practices.d.ts +0 -8
  22. package/src/instructions/best-practices.d.ts.map +0 -1
  23. package/src/instructions/best-practices.js +0 -24
  24. package/src/instructions/best-practices.js.map +0 -1
  25. package/src/tools/best-practices.d.ts +0 -8
  26. package/src/tools/best-practices.d.ts.map +0 -1
  27. package/src/tools/best-practices.js +0 -27
  28. package/src/tools/best-practices.js.map +0 -1
  29. package/src/tools/create-monorepo-with-app.d.ts.map +0 -1
  30. package/src/tools/create-monorepo-with-app.js.map +0 -1
  31. package/src/tools/find-repositories-using-otter.d.ts +0 -7
  32. package/src/tools/find-repositories-using-otter.d.ts.map +0 -1
  33. package/src/tools/find-repositories-using-otter.js +0 -169
  34. package/src/tools/find-repositories-using-otter.js.map +0 -1
  35. package/src/utils/logger.d.ts +0 -10
  36. package/src/utils/logger.d.ts.map +0 -1
  37. package/src/utils/logger.js +0 -24
  38. package/src/utils/logger.js.map +0 -1
package/README.md CHANGED
@@ -6,6 +6,9 @@
6
6
  <br />
7
7
  <br />
8
8
 
9
+ > [!WARNING]
10
+ > [Experimental](https://github.com/AmadeusITGroup/otter/blob/main/README.md#experimental)
11
+
9
12
  ## Description
10
13
 
11
14
  A small example of an MCP server.
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@o3r/mcp",
3
- "version": "13.3.0-prerelease.2",
3
+ "version": "13.3.0-prerelease.22",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
7
- "description": "This module provides a MCP Server",
7
+ "description": "Experimental package — This module provides a MCP Server",
8
8
  "keywords": [
9
9
  "mcp",
10
10
  "otter",
@@ -22,8 +22,10 @@
22
22
  "compile": "tsc -b ./tsconfig.build.json && yarn copy:resources && yarn cpy package.json dist && patch-package-json-main"
23
23
  },
24
24
  "dependencies": {
25
- "@modelcontextprotocol/sdk": "~1.19.0",
26
- "@octokit/rest": "^22.0.0",
25
+ "@ama-mcp/core": "^13.3.0-prerelease.22",
26
+ "@ama-mcp/github": "^13.3.0-prerelease.22",
27
+ "@modelcontextprotocol/sdk": "~1.20.0",
28
+ "@octokit/rest": "~22.0.0",
27
29
  "tslib": "^2.6.2",
28
30
  "zod": "~3.25.76"
29
31
  },
@@ -39,15 +41,15 @@
39
41
  "@nx/eslint-plugin": "~21.6.0",
40
42
  "@nx/jest": "~21.6.0",
41
43
  "@nx/js": "~21.6.0",
42
- "@o3r/build-helpers": "^13.3.0-prerelease.2",
43
- "@o3r/eslint-config": "^13.3.0-prerelease.2",
44
- "@o3r/eslint-plugin": "^13.3.0-prerelease.2",
45
- "@o3r/test-helpers": "^13.3.0-prerelease.2",
44
+ "@o3r/build-helpers": "^13.3.0-prerelease.22",
45
+ "@o3r/eslint-config": "^13.3.0-prerelease.22",
46
+ "@o3r/eslint-plugin": "^13.3.0-prerelease.22",
47
+ "@o3r/test-helpers": "^13.3.0-prerelease.22",
46
48
  "@stylistic/eslint-plugin": "~5.4.0",
47
49
  "@types/jest": "~29.5.2",
48
50
  "@types/node": "~22.18.0",
49
- "@typescript-eslint/parser": "~8.45.0",
50
- "angular-eslint": "~20.3.0",
51
+ "@typescript-eslint/parser": "~8.46.0",
52
+ "angular-eslint": "~20.4.0",
51
53
  "cpy-cli": "^6.0.0",
52
54
  "eslint": "~9.37.0",
53
55
  "eslint-import-resolver-node": "~0.3.9",
@@ -72,7 +74,7 @@
72
74
  "ts-node": "~10.9.2",
73
75
  "type-fest": "^4.30.1",
74
76
  "typescript": "~5.9.2",
75
- "typescript-eslint": "~8.45.0",
77
+ "typescript-eslint": "~8.46.0",
76
78
  "zone.js": "~0.15.0"
77
79
  },
78
80
  "engines": {
@@ -0,0 +1,8 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ /**
3
+ * Register the best practices tool and resources.
4
+ * @param server
5
+ * @param resourcesPath
6
+ */
7
+ export declare function registerBestPracticesToolAndResources(server: McpServer, resourcesPath: string): Promise<[PromiseSettledResult<void>, PromiseSettledResult<void>]>;
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/best-practices/index.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EACV,SAAS,EACV,MAAM,yCAAyC,CAAC;AA0DjD;;;;GAIG;AACH,wBAAgB,qCAAqC,CAAC,MAAM,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,qEAM7F"}
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerBestPracticesToolAndResources = registerBestPracticesToolAndResources;
4
+ const promises_1 = require("node:fs/promises");
5
+ const node_path_1 = require("node:path");
6
+ const core_1 = require("@ama-mcp/core");
7
+ const otter_1 = require("../utils/otter");
8
+ const uri = `${otter_1.uriPrefix}://best-practices`;
9
+ async function registerBestPracticesResources(server, bestPracticesResourcesPath) {
10
+ const content = await (0, promises_1.readFile)((0, node_path_1.join)(bestPracticesResourcesPath, 'output.md'), { encoding: 'utf8' });
11
+ core_1.resourceRegistry.set(uri, content);
12
+ server.registerResource('Best Practices Guide', uri, {
13
+ title: 'Otter Best Practices and Code Generation Guide',
14
+ description: await (0, promises_1.readFile)((0, node_path_1.join)(bestPracticesResourcesPath, 'description.md'), { encoding: 'utf8' }),
15
+ mimeType: 'text/markdown'
16
+ }, () => ({ contents: [{ uri, text: content }] }));
17
+ }
18
+ async function registerBestPracticesTool(server, bestPracticesResourcesPath) {
19
+ server.registerTool('get_best_practices', {
20
+ title: 'Get Otter Coding Best Practices Guide',
21
+ description: await (0, promises_1.readFile)((0, node_path_1.join)(bestPracticesResourcesPath, 'description.md'), { encoding: 'utf8' }),
22
+ annotations: {
23
+ readOnlyHint: true,
24
+ openWorldHint: false
25
+ }
26
+ }, () => ({
27
+ content: [
28
+ {
29
+ type: 'text',
30
+ text: core_1.resourceRegistry.get(uri) || 'Not found'
31
+ },
32
+ {
33
+ type: 'resource_link',
34
+ name: 'Best practices',
35
+ uri
36
+ }
37
+ ]
38
+ }));
39
+ }
40
+ /**
41
+ * Register the best practices tool and resources.
42
+ * @param server
43
+ * @param resourcesPath
44
+ */
45
+ function registerBestPracticesToolAndResources(server, resourcesPath) {
46
+ const bestPracticesResourcesPath = (0, node_path_1.join)(resourcesPath, 'best-practices');
47
+ return Promise.allSettled([
48
+ registerBestPracticesResources(server, bestPracticesResourcesPath),
49
+ registerBestPracticesTool(server, bestPracticesResourcesPath)
50
+ ]);
51
+ }
52
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/best-practices/index.ts"],"names":[],"mappings":";;AA0EA,sFAMC;AAhFD,+CAE0B;AAC1B,yCAEmB;AACnB,wCAEuB;AAIvB,0CAEwB;AAExB,MAAM,GAAG,GAAG,GAAG,iBAAS,mBAAmB,CAAC;AAE5C,KAAK,UAAU,8BAA8B,CAAC,MAAiB,EAAE,0BAAkC;IACjG,MAAM,OAAO,GAAG,MAAM,IAAA,mBAAQ,EAC5B,IAAA,gBAAI,EAAC,0BAA0B,EAAE,WAAW,CAAC,EAC7C,EAAE,QAAQ,EAAE,MAAM,EAAE,CACrB,CAAC;IACF,uBAAgB,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IACnC,MAAM,CAAC,gBAAgB,CACrB,sBAAsB,EACtB,GAAG,EACH;QACE,KAAK,EAAE,gDAAgD;QACvD,WAAW,EAAE,MAAM,IAAA,mBAAQ,EACzB,IAAA,gBAAI,EAAC,0BAA0B,EAAE,gBAAgB,CAAC,EAClD,EAAE,QAAQ,EAAE,MAAM,EAAE,CACrB;QACD,QAAQ,EAAE,eAAe;KAC1B,EACD,GAAG,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAC/C,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,yBAAyB,CAAC,MAAiB,EAAE,0BAAkC;IAC5F,MAAM,CAAC,YAAY,CACjB,oBAAoB,EACpB;QACE,KAAK,EAAE,uCAAuC;QAC9C,WAAW,EAAE,MAAM,IAAA,mBAAQ,EACzB,IAAA,gBAAI,EAAC,0BAA0B,EAAE,gBAAgB,CAAC,EAClD,EAAE,QAAQ,EAAE,MAAM,EAAE,CACrB;QACD,WAAW,EAAE;YACX,YAAY,EAAE,IAAI;YAClB,aAAa,EAAE,KAAK;SACrB;KACF,EACD,GAAG,EAAE,CAAC,CAAC;QACL,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,uBAAgB,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,WAAW;aAC/C;YACD;gBACE,IAAI,EAAE,eAAe;gBACrB,IAAI,EAAE,gBAAgB;gBACtB,GAAG;aACJ;SACF;KACF,CAAC,CACH,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,SAAgB,qCAAqC,CAAC,MAAiB,EAAE,aAAqB;IAC5F,MAAM,0BAA0B,GAAG,IAAA,gBAAI,EAAC,aAAa,EAAE,gBAAgB,CAAC,CAAC;IACzE,OAAO,OAAO,CAAC,UAAU,CAAC;QACxB,8BAA8B,CAAC,MAAM,EAAE,0BAA0B,CAAC;QAClE,yBAAyB,CAAC,MAAM,EAAE,0BAA0B,CAAC;KAC9D,CAAC,CAAC;AACL,CAAC"}
package/src/cli/index.js CHANGED
@@ -1,14 +1,15 @@
1
1
  #!/usr/bin/env node
2
2
  "use strict";
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
+ const core_1 = require("@ama-mcp/core");
4
5
  const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
5
6
  const mcp_server_1 = require("../mcp-server");
6
- const logger_1 = require("../utils/logger");
7
7
  async function startMcpServer() {
8
- const server = await (0, mcp_server_1.createMcpServer)();
8
+ const logger = new core_1.MCPLogger('O3R MCP server', process.env.O3R_MCP_LOG_LEVEL);
9
+ const server = await (0, mcp_server_1.createMcpServer)(logger);
9
10
  const transport = new stdio_js_1.StdioServerTransport();
10
11
  await server.connect(transport);
11
- logger_1.logger.info('Server connected...');
12
+ logger.info('Server connected...');
12
13
  }
13
14
  void startMcpServer();
14
15
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/cli/index.ts"],"names":[],"mappings":";;;AACA,wEAEmD;AACnD,8CAEuB;AACvB,4CAEyB;AAEzB,KAAK,UAAU,cAAc;IAC3B,MAAM,MAAM,GAAG,MAAM,IAAA,4BAAe,GAAE,CAAC;IACvC,MAAM,SAAS,GAAG,IAAI,+BAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,eAAM,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;AACrC,CAAC;AAED,KAAK,cAAc,EAAE,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/cli/index.ts"],"names":[],"mappings":";;;AACA,wCAGuB;AACvB,wEAEmD;AACnD,8CAEuB;AAEvB,KAAK,UAAU,cAAc;IAC3B,MAAM,MAAM,GAAG,IAAI,gBAAS,CAAC,gBAAgB,EAAE,OAAO,CAAC,GAAG,CAAC,iBAA6B,CAAC,CAAC;IAC1F,MAAM,MAAM,GAAG,MAAM,IAAA,4BAAe,EAAC,MAAM,CAAC,CAAC;IAC7C,MAAM,SAAS,GAAG,IAAI,+BAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,MAAM,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;AACrC,CAAC;AAED,KAAK,cAAc,EAAE,CAAC"}
@@ -5,4 +5,4 @@ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
5
5
  * @param resourcesPath
6
6
  */
7
7
  export declare function registerCreateMonorepoWithAppTool(server: McpServer, resourcesPath: string): Promise<void>;
8
- //# sourceMappingURL=create-monorepo-with-app.d.ts.map
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/create-monorepo-with-app/index.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,SAAS,EACV,MAAM,yCAAyC,CAAC;AAKjD;;;;GAIG;AACH,wBAAsB,iCAAiC,CAAC,MAAM,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA8B/G"}
@@ -35,4 +35,4 @@ async function registerCreateMonorepoWithAppTool(server, resourcesPath) {
35
35
  };
36
36
  });
37
37
  }
38
- //# sourceMappingURL=create-monorepo-with-app.js.map
38
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/create-monorepo-with-app/index.ts"],"names":[],"mappings":";;AAkBA,8EA8BC;AAhDD,+CAE0B;AAC1B,yCAEmB;AAInB,6BAEa;AAEb;;;;GAIG;AACI,KAAK,UAAU,iCAAiC,CAAC,MAAiB,EAAE,aAAqB;IAC9F,MAAM,mBAAmB,GAAG,IAAA,gBAAI,EAAC,aAAa,EAAE,QAAQ,CAAC,CAAC;IAC1D,MAAM,iBAAiB,GAAG,MAAM,IAAA,mBAAQ,EAAC,IAAA,gBAAI,EAAC,mBAAmB,EAAE,gBAAgB,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;IAC5G,MAAM,yBAAyB,GAAG,MAAM,IAAA,mBAAQ,EAAC,IAAA,gBAAI,EAAC,mBAAmB,EAAE,QAAQ,EAAE,oBAAoB,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;IAClI,MAAM,0BAA0B,GAAG,MAAM,IAAA,mBAAQ,EAAC,IAAA,gBAAI,EAAC,mBAAmB,EAAE,QAAQ,EAAE,qBAAqB,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;IACpI,MAAM,YAAY,GAAG,MAAM,IAAA,mBAAQ,EAAC,IAAA,gBAAI,EAAC,mBAAmB,EAAE,WAAW,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;IAElG,MAAM,CAAC,YAAY,CACjB,0BAA0B,EAC1B;QACE,KAAK,EAAE,0BAA0B;QACjC,WAAW,EAAE,iBAAiB;QAC9B,WAAW,EAAE;YACX,cAAc,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,yBAAyB,CAAC;YAC9D,eAAe,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,0BAA0B,CAAC,CAAC,QAAQ,EAAE;SAC5E;KACF,EACD,CAAC,EAAE,cAAc,EAAE,eAAe,GAAG,UAAU,EAAE,EAAE,EAAE;QACnD,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,YAAY;yBACf,UAAU,CAAC,kBAAkB,EAAE,cAAc,CAAC;yBAC9C,UAAU,CAAC,mBAAmB,EAAE,eAAe,CAAC;iBACpD;aACF;SACF,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -1,6 +1,8 @@
1
+ import type { MCPLogger } from '@ama-mcp/core';
1
2
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
3
  /**
3
4
  * Create an MCP server instance.
5
+ * @param logger
4
6
  */
5
- export declare function createMcpServer(): Promise<McpServer>;
7
+ export declare function createMcpServer(logger: MCPLogger): Promise<McpServer>;
6
8
  //# sourceMappingURL=mcp-server.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-server.d.ts","sourceRoot":"","sources":["../../src/mcp-server.ts"],"names":[],"mappings":"AAMA,OAAO,EACL,SAAS,EACV,MAAM,yCAAyC,CAAC;AAcjD;;GAEG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,SAAS,CAAC,CAiB1D"}
1
+ {"version":3,"file":"mcp-server.d.ts","sourceRoot":"","sources":["../../src/mcp-server.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EACV,SAAS,EACV,MAAM,eAAe,CAAC;AAMvB,OAAO,EACL,SAAS,EACV,MAAM,yCAAyC,CAAC;AAejD;;;GAGG;AACH,wBAAsB,eAAe,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC,CA6C3E"}
package/src/mcp-server.js CHANGED
@@ -3,15 +3,16 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createMcpServer = createMcpServer;
4
4
  const promises_1 = require("node:fs/promises");
5
5
  const node_path_1 = require("node:path");
6
+ const github_1 = require("@ama-mcp/github");
6
7
  const mcp_js_1 = require("@modelcontextprotocol/sdk/server/mcp.js");
7
- const best_practices_1 = require("./instructions/best-practices");
8
- const best_practices_2 = require("./tools/best-practices");
9
- const create_monorepo_with_app_1 = require("./tools/create-monorepo-with-app");
10
- const find_repositories_using_otter_1 = require("./tools/find-repositories-using-otter");
8
+ const best_practices_1 = require("./best-practices");
9
+ const create_monorepo_with_app_1 = require("./create-monorepo-with-app");
10
+ const otter_1 = require("./utils/otter");
11
11
  /**
12
12
  * Create an MCP server instance.
13
+ * @param logger
13
14
  */
14
- async function createMcpServer() {
15
+ async function createMcpServer(logger) {
15
16
  const { name, version } = JSON.parse(await (0, promises_1.readFile)((0, node_path_1.join)(__dirname, '..', 'package.json'), 'utf8'));
16
17
  const server = new mcp_js_1.McpServer({
17
18
  name,
@@ -22,10 +23,38 @@ async function createMcpServer() {
22
23
  }
23
24
  });
24
25
  const resourcesPath = (0, node_path_1.join)(__dirname, '..', 'resources');
25
- await (0, best_practices_1.registerBestPracticesResources)(server, resourcesPath);
26
- await (0, best_practices_2.registerBestPracticesTool)(server, resourcesPath);
27
- await (0, create_monorepo_with_app_1.registerCreateMonorepoWithAppTool)(server, resourcesPath);
28
- (0, find_repositories_using_otter_1.registerGetRepositoriesUsingOtterTool)(server);
26
+ const githubToken = process.env.O3R_MCP_GITHUB_TOKEN;
27
+ const cacheDirPath = process.env.O3R_MCP_CACHE_PATH || '.cache/@o3r/mcp';
28
+ await Promise.allSettled([
29
+ (0, best_practices_1.registerBestPracticesToolAndResources)(server, resourcesPath),
30
+ (0, create_monorepo_with_app_1.registerCreateMonorepoWithAppTool)(server, resourcesPath),
31
+ ...(githubToken
32
+ ? [
33
+ (0, github_1.registerGetRepositoriesUsingLibraryTool)(server, {
34
+ libraryName: otter_1.libraryName,
35
+ scopes: otter_1.OTTER_SCOPES,
36
+ githubToken,
37
+ cacheFilePath: (0, node_path_1.resolve)(cacheDirPath, 'repos-using-otter.json'),
38
+ cacheEntryExpireAfterDays: Number.isNaN(process.env.O3R_MCP_CACHE_MAX_AGE) ? undefined : +(process.env.O3R_MCP_CACHE_MAX_AGE)
39
+ }),
40
+ (0, github_1.registerSupportedReleasesTool)(server, {
41
+ githubToken,
42
+ owner: otter_1.owner,
43
+ repo: otter_1.repo,
44
+ libraryName: otter_1.libraryName
45
+ }),
46
+ (0, github_1.registerReleaseNotes)(server, {
47
+ githubToken,
48
+ owner: otter_1.owner,
49
+ repo: otter_1.repo,
50
+ libraryName: otter_1.libraryName,
51
+ uriPrefix: otter_1.uriPrefix
52
+ })
53
+ ]
54
+ : [
55
+ () => logger.error('Missing O3R_MCP_GITHUB_TOKEN environment variable for github tools')
56
+ ])
57
+ ]);
29
58
  return server;
30
59
  }
31
60
  //# sourceMappingURL=mcp-server.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-server.js","sourceRoot":"","sources":["../../src/mcp-server.ts"],"names":[],"mappings":";;AAyBA,0CAiBC;AA1CD,+CAE0B;AAC1B,yCAEmB;AACnB,oEAEiD;AACjD,kEAEuC;AACvC,2DAEgC;AAChC,+EAE0C;AAC1C,yFAE+C;AAE/C;;GAEG;AACI,KAAK,UAAU,eAAe;IACnC,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,IAAA,mBAAQ,EAAC,IAAA,gBAAI,EAAC,SAAS,EAAE,IAAI,EAAE,cAAc,CAAC,EAAE,MAAM,CAAC,CAAsC,CAAC;IACzI,MAAM,MAAM,GAAG,IAAI,kBAAS,CAAC;QAC3B,IAAI;QACJ,OAAO;QACP,YAAY,EAAE;YACZ,SAAS,EAAE,EAAE;YACb,KAAK,EAAE,EAAE;SACV;KACF,CAAC,CAAC;IACH,MAAM,aAAa,GAAG,IAAA,gBAAI,EAAC,SAAS,EAAE,IAAI,EAAE,WAAW,CAAC,CAAC;IAEzD,MAAM,IAAA,+CAA8B,EAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IAC5D,MAAM,IAAA,0CAAyB,EAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IACvD,MAAM,IAAA,4DAAiC,EAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IAC/D,IAAA,qEAAqC,EAAC,MAAM,CAAC,CAAC;IAC9C,OAAO,MAAM,CAAC;AAChB,CAAC"}
1
+ {"version":3,"file":"mcp-server.js","sourceRoot":"","sources":["../../src/mcp-server.ts"],"names":[],"mappings":";;AAoCA,0CA6CC;AAjFD,+CAE0B;AAC1B,yCAGmB;AAInB,4CAIyB;AACzB,oEAEiD;AACjD,qDAE0B;AAC1B,yEAEoC;AACpC,yCAMuB;AAEvB;;;GAGG;AACI,KAAK,UAAU,eAAe,CAAC,MAAiB;IACrD,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,IAAA,mBAAQ,EAAC,IAAA,gBAAI,EAAC,SAAS,EAAE,IAAI,EAAE,cAAc,CAAC,EAAE,MAAM,CAAC,CAAsC,CAAC;IACzI,MAAM,MAAM,GAAG,IAAI,kBAAS,CAAC;QAC3B,IAAI;QACJ,OAAO;QACP,YAAY,EAAE;YACZ,SAAS,EAAE,EAAE;YACb,KAAK,EAAE,EAAE;SACV;KACF,CAAC,CAAC;IACH,MAAM,aAAa,GAAG,IAAA,gBAAI,EAAC,SAAS,EAAE,IAAI,EAAE,WAAW,CAAC,CAAC;IACzD,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC;IACrD,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,iBAAiB,CAAC;IAEzE,MAAM,OAAO,CAAC,UAAU,CAAC;QACvB,IAAA,sDAAqC,EAAC,MAAM,EAAE,aAAa,CAAC;QAC5D,IAAA,4DAAiC,EAAC,MAAM,EAAE,aAAa,CAAC;QACxD,GAAG,CAAC,WAAW;YACb,CAAC,CAAC;gBACA,IAAA,gDAAuC,EAAC,MAAM,EAAE;oBAC9C,WAAW,EAAX,mBAAW;oBACX,MAAM,EAAE,oBAAY;oBACpB,WAAW;oBACX,aAAa,EAAE,IAAA,mBAAO,EAAC,YAAY,EAAE,wBAAwB,CAAC;oBAC9D,yBAAyB,EAAE,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,qBAAsB,CAAC;iBAC/H,CAAC;gBACF,IAAA,sCAA6B,EAAC,MAAM,EAAE;oBACpC,WAAW;oBACX,KAAK,EAAL,aAAK;oBACL,IAAI,EAAJ,YAAI;oBACJ,WAAW,EAAX,mBAAW;iBACZ,CAAC;gBACF,IAAA,6BAAoB,EAAC,MAAM,EAAE;oBAC3B,WAAW;oBACX,KAAK,EAAL,aAAK;oBACL,IAAI,EAAJ,YAAI;oBACJ,WAAW,EAAX,mBAAW;oBACX,SAAS,EAAT,iBAAS;iBACV,CAAC;aACH;YACD,CAAC,CAAC;gBACA,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,oEAAoE,CAAC;aACzF,CAAC;KACL,CAAC,CAAC;IACH,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Otter repository organization
3
+ */
4
+ export declare const owner = "AmadeusITGroup";
5
+ /**
6
+ * Otter repository name
7
+ */
8
+ export declare const repo = "otter";
9
+ /**
10
+ * Otter related scopes
11
+ */
12
+ export declare const OTTER_SCOPES: string[];
13
+ /**
14
+ * Otter URI prefix
15
+ */
16
+ export declare const uriPrefix = "o3r";
17
+ /**
18
+ * Otter library name
19
+ */
20
+ export declare const libraryName = "Otter";
21
+ //# sourceMappingURL=otter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"otter.d.ts","sourceRoot":"","sources":["../../../src/utils/otter.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,eAAO,MAAM,KAAK,mBAAmB,CAAC;AAEtC;;GAEG;AACH,eAAO,MAAM,IAAI,UAAU,CAAC;AAE5B;;GAEG;AACH,eAAO,MAAM,YAAY,UAMxB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,SAAS,QAAQ,CAAC;AAE/B;;GAEG;AACH,eAAO,MAAM,WAAW,UAAU,CAAC"}
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.libraryName = exports.uriPrefix = exports.OTTER_SCOPES = exports.repo = exports.owner = void 0;
4
+ /**
5
+ * Otter repository organization
6
+ */
7
+ exports.owner = 'AmadeusITGroup';
8
+ /**
9
+ * Otter repository name
10
+ */
11
+ exports.repo = 'otter';
12
+ /**
13
+ * Otter related scopes
14
+ */
15
+ exports.OTTER_SCOPES = [
16
+ 'o3r',
17
+ 'ama-styling',
18
+ 'ama-mfe',
19
+ 'ama-sdk',
20
+ 'ama-mcp'
21
+ ];
22
+ /**
23
+ * Otter URI prefix
24
+ */
25
+ exports.uriPrefix = 'o3r';
26
+ /**
27
+ * Otter library name
28
+ */
29
+ exports.libraryName = 'Otter';
30
+ //# sourceMappingURL=otter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"otter.js","sourceRoot":"","sources":["../../../src/utils/otter.ts"],"names":[],"mappings":";;;AAAA;;GAEG;AACU,QAAA,KAAK,GAAG,gBAAgB,CAAC;AAEtC;;GAEG;AACU,QAAA,IAAI,GAAG,OAAO,CAAC;AAE5B;;GAEG;AACU,QAAA,YAAY,GAAG;IAC1B,KAAK;IACL,aAAa;IACb,SAAS;IACT,SAAS;IACT,SAAS;CACV,CAAC;AAEF;;GAEG;AACU,QAAA,SAAS,GAAG,KAAK,CAAC;AAE/B;;GAEG;AACU,QAAA,WAAW,GAAG,OAAO,CAAC"}
@@ -1,8 +0,0 @@
1
- import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
- /**
3
- * Register resources for best practices
4
- * @param server
5
- * @param resourcesPath
6
- */
7
- export declare function registerBestPracticesResources(server: McpServer, resourcesPath: string): Promise<void>;
8
- //# sourceMappingURL=best-practices.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"best-practices.d.ts","sourceRoot":"","sources":["../../../src/instructions/best-practices.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,SAAS,EACV,MAAM,yCAAyC,CAAC;AAEjD;;;;GAIG;AACH,wBAAsB,8BAA8B,CAAC,MAAM,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAwB5G"}
@@ -1,24 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.registerBestPracticesResources = registerBestPracticesResources;
4
- const promises_1 = require("node:fs/promises");
5
- const node_path_1 = require("node:path");
6
- /**
7
- * Register resources for best practices
8
- * @param server
9
- * @param resourcesPath
10
- */
11
- async function registerBestPracticesResources(server, resourcesPath) {
12
- const bestPracticesResourcesPath = (0, node_path_1.join)(resourcesPath, 'best-practices');
13
- const name = 'instructions';
14
- const uri = `${name}://best-practices`;
15
- server.registerResource(name, uri, {
16
- title: 'Otter Best Practices and Code Generation Guide',
17
- description: await (0, promises_1.readFile)((0, node_path_1.join)(bestPracticesResourcesPath, 'description.md'), { encoding: 'utf8' }),
18
- mimeType: 'text/markdown'
19
- }, async () => {
20
- const text = await (0, promises_1.readFile)((0, node_path_1.join)(bestPracticesResourcesPath, 'output.md'), { encoding: 'utf8' });
21
- return { contents: [{ uri, text }] };
22
- });
23
- }
24
- //# sourceMappingURL=best-practices.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"best-practices.js","sourceRoot":"","sources":["../../../src/instructions/best-practices.ts"],"names":[],"mappings":";;AAeA,wEAwBC;AAvCD,+CAE0B;AAC1B,yCAEmB;AAKnB;;;;GAIG;AACI,KAAK,UAAU,8BAA8B,CAAC,MAAiB,EAAE,aAAqB;IAC3F,MAAM,0BAA0B,GAAG,IAAA,gBAAI,EAAC,aAAa,EAAE,gBAAgB,CAAC,CAAC;IACzE,MAAM,IAAI,GAAG,cAAc,CAAC;IAC5B,MAAM,GAAG,GAAG,GAAG,IAAI,mBAAmB,CAAC;IACvC,MAAM,CAAC,gBAAgB,CACrB,IAAI,EACJ,GAAG,EACH;QACE,KAAK,EAAE,gDAAgD;QACvD,WAAW,EAAE,MAAM,IAAA,mBAAQ,EACzB,IAAA,gBAAI,EAAC,0BAA0B,EAAE,gBAAgB,CAAC,EAClD,EAAE,QAAQ,EAAE,MAAM,EAAE,CACrB;QACD,QAAQ,EAAE,eAAe;KAC1B,EACD,KAAK,IAAI,EAAE;QACT,MAAM,IAAI,GAAG,MAAM,IAAA,mBAAQ,EACzB,IAAA,gBAAI,EAAC,0BAA0B,EAAE,WAAW,CAAC,EAC7C,EAAE,QAAQ,EAAE,MAAM,EAAE,CACrB,CAAC;QAEF,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;IACvC,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -1,8 +0,0 @@
1
- import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
- /**
3
- * Register the best practices tool.
4
- * @param server
5
- * @param resourcesPath
6
- */
7
- export declare function registerBestPracticesTool(server: McpServer, resourcesPath: string): Promise<void>;
8
- //# sourceMappingURL=best-practices.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"best-practices.d.ts","sourceRoot":"","sources":["../../../src/tools/best-practices.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,SAAS,EACV,MAAM,yCAAyC,CAAC;AAEjD;;;;GAIG;AACH,wBAAsB,yBAAyB,CAAC,MAAM,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA+BvG"}
@@ -1,27 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.registerBestPracticesTool = registerBestPracticesTool;
4
- const promises_1 = require("node:fs/promises");
5
- const node_path_1 = require("node:path");
6
- /**
7
- * Register the best practices tool.
8
- * @param server
9
- * @param resourcesPath
10
- */
11
- async function registerBestPracticesTool(server, resourcesPath) {
12
- const bestPracticesResourcesPath = (0, node_path_1.join)(resourcesPath, 'best-practices');
13
- server.registerTool('get_best_practices', {
14
- title: 'Get Otter Coding Best Practices Guide',
15
- description: await (0, promises_1.readFile)((0, node_path_1.join)(bestPracticesResourcesPath, 'description.md'), { encoding: 'utf8' }),
16
- annotations: {
17
- readOnlyHint: true,
18
- openWorldHint: false
19
- }
20
- }, async () => {
21
- const bestPractices = await (0, promises_1.readFile)((0, node_path_1.join)(bestPracticesResourcesPath, 'output.md'), { encoding: 'utf8' });
22
- const developer = await (0, promises_1.readFile)((0, node_path_1.join)(resourcesPath, 'developer.md'), { encoding: 'utf8' });
23
- const text = [developer, bestPractices].join('\n\n');
24
- return { content: [{ type: 'text', text }] };
25
- });
26
- }
27
- //# sourceMappingURL=best-practices.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"best-practices.js","sourceRoot":"","sources":["../../../src/tools/best-practices.ts"],"names":[],"mappings":";;AAeA,8DA+BC;AA9CD,+CAE0B;AAC1B,yCAEmB;AAKnB;;;;GAIG;AACI,KAAK,UAAU,yBAAyB,CAAC,MAAiB,EAAE,aAAqB;IACtF,MAAM,0BAA0B,GAAG,IAAA,gBAAI,EAAC,aAAa,EAAE,gBAAgB,CAAC,CAAC;IAEzE,MAAM,CAAC,YAAY,CACjB,oBAAoB,EACpB;QACE,KAAK,EAAE,uCAAuC;QAC9C,WAAW,EAAE,MAAM,IAAA,mBAAQ,EACzB,IAAA,gBAAI,EAAC,0BAA0B,EAAE,gBAAgB,CAAC,EAClD,EAAE,QAAQ,EAAE,MAAM,EAAE,CACrB;QACD,WAAW,EAAE;YACX,YAAY,EAAE,IAAI;YAClB,aAAa,EAAE,KAAK;SACrB;KACF,EACD,KAAK,IAAI,EAAE;QACT,MAAM,aAAa,GAAG,MAAM,IAAA,mBAAQ,EAClC,IAAA,gBAAI,EAAC,0BAA0B,EAAE,WAAW,CAAC,EAC7C,EAAE,QAAQ,EAAE,MAAM,EAAE,CACrB,CAAC;QACF,MAAM,SAAS,GAAG,MAAM,IAAA,mBAAQ,EAC9B,IAAA,gBAAI,EAAC,aAAa,EAAE,cAAc,CAAC,EACnC,EAAE,QAAQ,EAAE,MAAM,EAAE,CACrB,CAAC;QAEF,MAAM,IAAI,GAAG,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAErD,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;IAC/C,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"create-monorepo-with-app.d.ts","sourceRoot":"","sources":["../../../src/tools/create-monorepo-with-app.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,SAAS,EACV,MAAM,yCAAyC,CAAC;AAKjD;;;;GAIG;AACH,wBAAsB,iCAAiC,CAAC,MAAM,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA8B/G"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"create-monorepo-with-app.js","sourceRoot":"","sources":["../../../src/tools/create-monorepo-with-app.ts"],"names":[],"mappings":";;AAkBA,8EA8BC;AAhDD,+CAE0B;AAC1B,yCAEmB;AAInB,6BAEa;AAEb;;;;GAIG;AACI,KAAK,UAAU,iCAAiC,CAAC,MAAiB,EAAE,aAAqB;IAC9F,MAAM,mBAAmB,GAAG,IAAA,gBAAI,EAAC,aAAa,EAAE,QAAQ,CAAC,CAAC;IAC1D,MAAM,iBAAiB,GAAG,MAAM,IAAA,mBAAQ,EAAC,IAAA,gBAAI,EAAC,mBAAmB,EAAE,gBAAgB,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;IAC5G,MAAM,yBAAyB,GAAG,MAAM,IAAA,mBAAQ,EAAC,IAAA,gBAAI,EAAC,mBAAmB,EAAE,QAAQ,EAAE,oBAAoB,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;IAClI,MAAM,0BAA0B,GAAG,MAAM,IAAA,mBAAQ,EAAC,IAAA,gBAAI,EAAC,mBAAmB,EAAE,QAAQ,EAAE,qBAAqB,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;IACpI,MAAM,YAAY,GAAG,MAAM,IAAA,mBAAQ,EAAC,IAAA,gBAAI,EAAC,mBAAmB,EAAE,WAAW,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;IAElG,MAAM,CAAC,YAAY,CACjB,0BAA0B,EAC1B;QACE,KAAK,EAAE,0BAA0B;QACjC,WAAW,EAAE,iBAAiB;QAC9B,WAAW,EAAE;YACX,cAAc,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,yBAAyB,CAAC;YAC9D,eAAe,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,0BAA0B,CAAC,CAAC,QAAQ,EAAE;SAC5E;KACF,EACD,CAAC,EAAE,cAAc,EAAE,eAAe,GAAG,UAAU,EAAE,EAAE,EAAE;QACnD,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,YAAY;yBACf,UAAU,CAAC,kBAAkB,EAAE,cAAc,CAAC;yBAC9C,UAAU,CAAC,mBAAmB,EAAE,eAAe,CAAC;iBACpD;aACF;SACF,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -1,7 +0,0 @@
1
- import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
- /**
3
- * Register the get repositories using otter tool.
4
- * @param server
5
- */
6
- export declare function registerGetRepositoriesUsingOtterTool(server: McpServer): void;
7
- //# sourceMappingURL=find-repositories-using-otter.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"find-repositories-using-otter.d.ts","sourceRoot":"","sources":["../../../src/tools/find-repositories-using-otter.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EACV,SAAS,EACV,MAAM,yCAAyC,CAAC;AAgIjD;;;GAGG;AACH,wBAAgB,qCAAqC,CAAC,MAAM,EAAE,SAAS,QA0CtE"}
@@ -1,169 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.registerGetRepositoriesUsingOtterTool = registerGetRepositoriesUsingOtterTool;
4
- const node_fs_1 = require("node:fs");
5
- const promises_1 = require("node:fs/promises");
6
- const node_path_1 = require("node:path");
7
- const rest_1 = require("@octokit/rest");
8
- const logger_1 = require("../utils/logger");
9
- async function listOrgRepos(octokit) {
10
- const repos = (await octokit.paginate(octokit.repos.listForOrg, {
11
- org: process.env.O3R_MCP_GITHUB_ORG,
12
- per_page: 100,
13
- type: 'all',
14
- sort: 'updated' // Prioritize recently updated repositories
15
- })).filter((repo) => !repo.archived && !repo.fork);
16
- logger_1.logger.info(`Found ${repos.length} repositories in the organization ${process.env.O3R_MCP_GITHUB_ORG}`);
17
- return repos;
18
- }
19
- function findPackageJsonFiles(octokit) {
20
- return async (repository) => {
21
- const owner = process.env.O3R_MCP_GITHUB_ORG;
22
- const repo = repository.name;
23
- const { data: { commit: { sha } } } = await octokit.repos.getBranch({
24
- owner,
25
- repo,
26
- branch: repository.default_branch || 'main'
27
- });
28
- const { data: { tree } } = await octokit.git.getTree({
29
- owner,
30
- repo,
31
- tree_sha: sha
32
- });
33
- return tree.filter((t) => t.type === 'blob' && t.path.endsWith('package.json'));
34
- };
35
- }
36
- const O3R_SCOPE_REGEX = /^@(o3r|ama-styling|ama-mfe|ama-sdk)\//gm;
37
- function dependsOnOtter(octokit) {
38
- return async (repository, packageJsonPath) => {
39
- const owner = process.env.O3R_MCP_GITHUB_ORG;
40
- const repo = repository.name;
41
- const { data } = await octokit.repos.getContent({
42
- owner,
43
- repo,
44
- path: packageJsonPath
45
- });
46
- if (Array.isArray(data) || data.type !== 'file') {
47
- throw new Error('Unexpected content response structure');
48
- }
49
- const content = Buffer.from(data.content, 'base64').toString('utf8');
50
- const packageJson = JSON.parse(content);
51
- return [
52
- ...Object.keys(packageJson.devDependencies || {}),
53
- ...Object.keys(packageJson.dependencies || {})
54
- ].some((dep) => O3R_SCOPE_REGEX.test(dep));
55
- };
56
- }
57
- async function findRepositoriesUsingOtter(octokit, reposUsingOtter) {
58
- const cacheFolderPath = process.env.O3R_MCP_CACHE_PATH || '.cache/o3r/mcp';
59
- const cachePath = (0, node_path_1.resolve)(cacheFolderPath, 'repos-using-otter.json');
60
- let cachedRepos = {};
61
- if (process.env.O3R_MCP_USE_CACHED_REPOS === 'false') {
62
- logger_1.logger.info('Ignoring cached repositories as O3R_MCP_USE_CACHED_REPOS is set to false');
63
- }
64
- else {
65
- try {
66
- cachedRepos = JSON.parse(await (0, promises_1.readFile)(cachePath, { encoding: 'utf8' }));
67
- reposUsingOtter.push(...Object.entries(cachedRepos).filter(([, usesOtter]) => usesOtter).map(([repo]) => repo));
68
- logger_1.logger.info(`Loaded ${Object.keys(cachedRepos).length} cached repositories, ${reposUsingOtter.length} of them using Otter dependencies.`);
69
- }
70
- catch (e) {
71
- logger_1.logger.info('No cache file found, starting fresh search for repositories using Otter dependencies.', e);
72
- }
73
- }
74
- const repositories = (await listOrgRepos(octokit)).filter((r) => !cachedRepos[r.full_name]);
75
- const findPackageJsonFilesInRepo = findPackageJsonFiles(octokit);
76
- const dependsOnOtterInRepo = dependsOnOtter(octokit);
77
- await Promise.allSettled(repositories.map(async (repository) => {
78
- logger_1.logger.debug(`Checking repository ${repository.full_name}...`);
79
- const packageJsonFiles = [];
80
- try {
81
- packageJsonFiles.push(...await findPackageJsonFilesInRepo(repository));
82
- }
83
- catch (e) {
84
- logger_1.logger.warn(`Failed to list package.json files in repository ${repository.full_name}`, e);
85
- }
86
- if (packageJsonFiles.length === 0) {
87
- logger_1.logger.info(`No package.json files found in repository ${repository.full_name}`);
88
- cachedRepos[repository.full_name] = false;
89
- return;
90
- }
91
- try {
92
- await Promise.any(packageJsonFiles.map(async (packageJsonFile) => {
93
- let depFound = false;
94
- try {
95
- depFound = await dependsOnOtterInRepo(repository, packageJsonFile.path);
96
- }
97
- catch (e) {
98
- logger_1.logger.error(`Failed to check package.json file at ${packageJsonFile.path} in repository ${repository.full_name}`, e);
99
- }
100
- if (depFound) {
101
- reposUsingOtter.push(repository.full_name);
102
- logger_1.logger.info(`Repository ${repository.full_name} uses Otter dependencies`);
103
- cachedRepos[repository.full_name] = true;
104
- }
105
- else {
106
- throw new Error('No Otter dependencies found in this package.json');
107
- }
108
- }));
109
- }
110
- catch { }
111
- cachedRepos[repository.full_name] ||= false;
112
- }));
113
- logger_1.logger.info(`Found ${reposUsingOtter.length} repositories using Otter dependencies in the organization ${process.env.O3R_MCP_GITHUB_ORG}`);
114
- if (process.env.O3R_MCP_USE_CACHED_REPOS === 'false') {
115
- logger_1.logger.info('Not updating cache as O3R_MCP_USE_CACHED_REPOS is set to false');
116
- }
117
- else {
118
- if (!(0, node_fs_1.existsSync)(cacheFolderPath)) {
119
- await (0, promises_1.mkdir)(cacheFolderPath, { recursive: true });
120
- }
121
- try {
122
- await (0, promises_1.writeFile)(cachePath, JSON.stringify(cachedRepos, Object.keys(cachedRepos).sort()));
123
- }
124
- catch (e) {
125
- logger_1.logger.error('Failed to update cache', e);
126
- }
127
- }
128
- }
129
- /**
130
- * Register the get repositories using otter tool.
131
- * @param server
132
- */
133
- function registerGetRepositoriesUsingOtterTool(server) {
134
- if (!process.env.O3R_MCP_GITHUB_TOKEN) {
135
- logger_1.logger.error('Missing O3R_MCP_GITHUB_TOKEN environment variable for search_code_example tool');
136
- return;
137
- }
138
- if (!process.env.O3R_MCP_GITHUB_ORG) {
139
- logger_1.logger.error('Missing O3R_MCP_GITHUB_ORG environment variable');
140
- return;
141
- }
142
- const octokit = new rest_1.Octokit({ auth: process.env.O3R_MCP_GITHUB_TOKEN });
143
- let isLookingForRepos = true;
144
- const reposUsingOtter = [];
145
- findRepositoriesUsingOtter(octokit, reposUsingOtter).catch((e) => {
146
- logger_1.logger.error('Error finding repositories using Otter:', e);
147
- });
148
- isLookingForRepos = false;
149
- server.registerTool('get_repositories_using_otter', {
150
- title: 'Get repositories using Otter dependencies',
151
- description: 'List all repositories in the specified GitHub organization that use Otter dependencies (@o3r/* or @ama-*/*) in their package.json files.',
152
- annotations: {
153
- readOnlyHint: true,
154
- openWorldHint: false
155
- }
156
- }, () => ({
157
- content: [
158
- {
159
- type: 'text',
160
- text: (isLookingForRepos ? 'I did not finish to look for repositories. For the moment:\n' : '')
161
- + reposUsingOtter.length
162
- ? `The following repositories in the organization ${process.env.O3R_MCP_GITHUB_ORG} use Otter dependencies:\n`
163
- + reposUsingOtter.sort().map((repo) => `- ${repo}`).join('\n')
164
- : `No repositories in the organization ${process.env.O3R_MCP_GITHUB_ORG} were found to use Otter dependencies.`
165
- }
166
- ]
167
- }));
168
- }
169
- //# sourceMappingURL=find-repositories-using-otter.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"find-repositories-using-otter.js","sourceRoot":"","sources":["../../../src/tools/find-repositories-using-otter.ts"],"names":[],"mappings":"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"}
@@ -1,10 +0,0 @@
1
- /**
2
- * Logger for MCP server
3
- */
4
- export declare const logger: {
5
- error: (m: string, meta?: any) => boolean;
6
- warn: (m: string, meta?: any) => boolean;
7
- info: (m: string, meta?: any) => boolean;
8
- debug: (m: string, meta?: any) => boolean;
9
- };
10
- //# sourceMappingURL=logger.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../../src/utils/logger.ts"],"names":[],"mappings":"AAgBA;;GAEG;AACH,eAAO,MAAM,MAAM;eACN,MAAM,SAAS,GAAG;cACnB,MAAM,SAAS,GAAG;cAClB,MAAM,SAAS,GAAG;eACjB,MAAM,SAAS,GAAG;CAC9B,CAAC"}
@@ -1,24 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.logger = void 0;
4
- /**
5
- * Logging as error as recommended by modelcontextprotocol.io (https://modelcontextprotocol.io/quickstart/server#quick-examples-2)
6
- * @param level
7
- * @param message
8
- * @param meta Should be stringifyable
9
- */
10
- const log = (level, message, meta) => process.stderr.write(JSON.stringify({
11
- level,
12
- message,
13
- meta
14
- }) + '\n');
15
- /**
16
- * Logger for MCP server
17
- */
18
- exports.logger = {
19
- error: (m, meta) => log('error', m, meta),
20
- warn: (m, meta) => log('warn', m, meta),
21
- info: (m, meta) => log('info', m, meta),
22
- debug: (m, meta) => log('debug', m, meta)
23
- };
24
- //# sourceMappingURL=logger.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../../src/utils/logger.ts"],"names":[],"mappings":";;;AAEA;;;;;GAKG;AACH,MAAM,GAAG,GAAG,CAAC,KAAY,EAAE,OAAe,EAAE,IAAS,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAC5E,IAAI,CAAC,SAAS,CAAC;IACb,KAAK;IACL,OAAO;IACP,IAAI;CACL,CAAC,GAAG,IAAI,CACV,CAAC;AAEF;;GAEG;AACU,QAAA,MAAM,GAAG;IACpB,KAAK,EAAE,CAAC,CAAS,EAAE,IAAU,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,EAAE,IAAI,CAAC;IACvD,IAAI,EAAE,CAAC,CAAS,EAAE,IAAU,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,IAAI,CAAC;IACrD,IAAI,EAAE,CAAC,CAAS,EAAE,IAAU,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,IAAI,CAAC;IACrD,KAAK,EAAE,CAAC,CAAS,EAAE,IAAU,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,EAAE,IAAI,CAAC;CACxD,CAAC"}