@rockhopper-co/mcp-server 0.4.0 → 0.6.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/CHANGELOG.md CHANGED
@@ -4,6 +4,42 @@ All notable changes to this project are documented here. Follows
4
4
  [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and
5
5
  [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## [0.5.0] — 2026-05-12
8
+
9
+ ### Changed
10
+ - **`resources/list` no longer enumerates per-file instances.** The 4
11
+ per-file resource templates (`enrolled-file`, `file-versions`,
12
+ `file-comments`, `unattributed-changes`) previously expanded into one
13
+ concrete resource per enrolled file via their `list:` callbacks,
14
+ bloating the response to 44+ entries at single-digit file counts and
15
+ ~400 at 100 files. They now appear in `resources/templates/list`
16
+ semantics instead — AI clients learn the URI pattern and construct
17
+ concrete URIs on demand. `resources/list` stays at a small static set
18
+ regardless of workspace size. Closes KI-078 / ENG-1381.
19
+
20
+ ### Added
21
+ - **`rockhopper://orchestration-guide` resource.** Static markdown
22
+ resource that documents tool sequencing, identity disambiguation
23
+ (`fileMsId` vs `versionId` vs `versionInternalId`), the comment and
24
+ review lifecycles, versioning rules, and cross-cloud (Microsoft vs
25
+ Google Sheets) differences. AI clients can read it once at session
26
+ start to avoid common tool-sequencing errors. Backed by
27
+ `src/resources/orchestration-guide.md`. Closes KI-079 / ENG-1382.
28
+
29
+ ### Internal
30
+ - Build step now copies `src/**/*.md` into `dist/` so non-`.ts` assets
31
+ ship with the package (`scripts/copy-non-ts-assets.mjs`).
32
+ - Unit and e2e test updates: assert `resources/list` returns exactly 2
33
+ static entries and `resources/templates/list` returns the 8 URI
34
+ templates; new test reads the orchestration-guide content.
35
+ - Regenerated Postman collection (16 tools, 10 resources, 4 prompts).
36
+
37
+ ### Breaking changes
38
+ - Behavior change in `resources/list` response shape. Downstream
39
+ consumers that cached the previous per-file enumeration must refresh
40
+ their resource lists. No tool, prompt, or resource-read semantics
41
+ changed — only the `resources/list` response.
42
+
7
43
  ## [0.4.0] — 2026-05-03
8
44
 
9
45
  ### Added
@@ -1 +1 @@
1
- {"version":3,"file":"changes.d.ts","sourceRoot":"","sources":["../../src/resources/changes.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAElD,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,SAAS,EACjB,GAAG,EAAE,SAAS,GACb,IAAI,CAoCN"}
1
+ {"version":3,"file":"changes.d.ts","sourceRoot":"","sources":["../../src/resources/changes.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAElD,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,SAAS,EACjB,GAAG,EAAE,SAAS,GACb,IAAI,CA4BN"}
@@ -1,18 +1,10 @@
1
1
  import { ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js';
2
2
  export function registerChangeResources(server, api) {
3
+ // KI-078 (ENG-1381): template only, no per-file expansion into resources/list.
4
+ // Previously this enumerated only files with `hasUncommittedChanges === true` —
5
+ // a per-call API request that scaled linearly with file count.
3
6
  server.registerResource('unattributed-changes', new ResourceTemplate('rockhopper://files/{fileMsId}/changes', {
4
- list: async () => {
5
- const files = await api.listEnrolledFiles();
6
- return {
7
- resources: files
8
- .filter((f) => f.hasUncommittedChanges)
9
- .map((f) => ({
10
- uri: `rockhopper://files/${f.platformId}/changes`,
11
- name: `Unattributed changes in ${f.name}`,
12
- mimeType: 'application/json',
13
- })),
14
- };
15
- },
7
+ list: undefined,
16
8
  }), {
17
9
  title: 'Unattributed Changes',
18
10
  description: 'Pending cell-level changes not yet attributed to a version for a file',
@@ -1 +1 @@
1
- {"version":3,"file":"changes.js","sourceRoot":"","sources":["../../src/resources/changes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,yCAAyC,CAAC;AAI3E,MAAM,UAAU,uBAAuB,CACrC,MAAiB,EACjB,GAAc;IAEd,MAAM,CAAC,gBAAgB,CACrB,sBAAsB,EACtB,IAAI,gBAAgB,CAAC,uCAAuC,EAAE;QAC5D,IAAI,EAAE,KAAK,IAAI,EAAE;YACf,MAAM,KAAK,GAAG,MAAM,GAAG,CAAC,iBAAiB,EAAE,CAAC;YAC5C,OAAO;gBACL,SAAS,EAAE,KAAK;qBACb,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,qBAAqB,CAAC;qBACtC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;oBACX,GAAG,EAAE,sBAAsB,CAAC,CAAC,UAAU,UAAU;oBACjD,IAAI,EAAE,2BAA2B,CAAC,CAAC,IAAI,EAAE;oBACzC,QAAQ,EAAE,kBAAkB;iBAC7B,CAAC,CAAC;aACN,CAAC;QACJ,CAAC;KACF,CAAC,EACF;QACE,KAAK,EAAE,sBAAsB;QAC7B,WAAW,EACT,uEAAuE;QACzE,QAAQ,EAAE,kBAAkB;KAC7B,EACD,KAAK,EAAE,GAAG,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE;QAC1B,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,sBAAsB,CAAC,QAAkB,CAAC,CAAC;QACrE,OAAO;YACL,QAAQ,EAAE;gBACR;oBACE,GAAG,EAAE,GAAG,CAAC,IAAI;oBACb,QAAQ,EAAE,kBAAkB;oBAC5B,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;iBACvC;aACF;SACF,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"changes.js","sourceRoot":"","sources":["../../src/resources/changes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,yCAAyC,CAAC;AAI3E,MAAM,UAAU,uBAAuB,CACrC,MAAiB,EACjB,GAAc;IAEd,+EAA+E;IAC/E,gFAAgF;IAChF,+DAA+D;IAC/D,MAAM,CAAC,gBAAgB,CACrB,sBAAsB,EACtB,IAAI,gBAAgB,CAAC,uCAAuC,EAAE;QAC5D,IAAI,EAAE,SAAS;KAChB,CAAC,EACF;QACE,KAAK,EAAE,sBAAsB;QAC7B,WAAW,EACT,uEAAuE;QACzE,QAAQ,EAAE,kBAAkB;KAC7B,EACD,KAAK,EAAE,GAAG,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE;QAC1B,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,sBAAsB,CAAC,QAAkB,CAAC,CAAC;QACrE,OAAO;YACL,QAAQ,EAAE;gBACR;oBACE,GAAG,EAAE,GAAG,CAAC,IAAI;oBACb,QAAQ,EAAE,kBAAkB;oBAC5B,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;iBACvC;aACF;SACF,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"comments.d.ts","sourceRoot":"","sources":["../../src/resources/comments.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAElD,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,SAAS,EACjB,GAAG,EAAE,SAAS,GACb,IAAI,CAkCN"}
1
+ {"version":3,"file":"comments.d.ts","sourceRoot":"","sources":["../../src/resources/comments.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAElD,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,SAAS,EACjB,GAAG,EAAE,SAAS,GACb,IAAI,CA0BN"}
@@ -1,16 +1,8 @@
1
1
  import { ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js';
2
2
  export function registerCommentResources(server, api) {
3
+ // KI-078 (ENG-1381): template only, no per-file expansion into resources/list.
3
4
  server.registerResource('file-comments', new ResourceTemplate('rockhopper://files/{fileMsId}/comments', {
4
- list: async () => {
5
- const files = await api.listEnrolledFiles();
6
- return {
7
- resources: files.map((f) => ({
8
- uri: `rockhopper://files/${f.platformId}/comments`,
9
- name: `Comments on ${f.name}`,
10
- mimeType: 'application/json',
11
- })),
12
- };
13
- },
5
+ list: undefined,
14
6
  }), {
15
7
  title: 'File Comments',
16
8
  description: 'All comments and chat threads on a specific enrolled file',
@@ -1 +1 @@
1
- {"version":3,"file":"comments.js","sourceRoot":"","sources":["../../src/resources/comments.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,yCAAyC,CAAC;AAI3E,MAAM,UAAU,wBAAwB,CACtC,MAAiB,EACjB,GAAc;IAEd,MAAM,CAAC,gBAAgB,CACrB,eAAe,EACf,IAAI,gBAAgB,CAAC,wCAAwC,EAAE;QAC7D,IAAI,EAAE,KAAK,IAAI,EAAE;YACf,MAAM,KAAK,GAAG,MAAM,GAAG,CAAC,iBAAiB,EAAE,CAAC;YAC5C,OAAO;gBACL,SAAS,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;oBAC3B,GAAG,EAAE,sBAAsB,CAAC,CAAC,UAAU,WAAW;oBAClD,IAAI,EAAE,eAAe,CAAC,CAAC,IAAI,EAAE;oBAC7B,QAAQ,EAAE,kBAAkB;iBAC7B,CAAC,CAAC;aACJ,CAAC;QACJ,CAAC;KACF,CAAC,EACF;QACE,KAAK,EAAE,eAAe;QACtB,WAAW,EACT,2DAA2D;QAC7D,QAAQ,EAAE,kBAAkB;KAC7B,EACD,KAAK,EAAE,GAAG,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE;QAC1B,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,eAAe,CAAC,QAAkB,CAAC,CAAC;QAC/D,OAAO;YACL,QAAQ,EAAE;gBACR;oBACE,GAAG,EAAE,GAAG,CAAC,IAAI;oBACb,QAAQ,EAAE,kBAAkB;oBAC5B,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;iBACxC;aACF;SACF,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"comments.js","sourceRoot":"","sources":["../../src/resources/comments.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,yCAAyC,CAAC;AAI3E,MAAM,UAAU,wBAAwB,CACtC,MAAiB,EACjB,GAAc;IAEd,+EAA+E;IAC/E,MAAM,CAAC,gBAAgB,CACrB,eAAe,EACf,IAAI,gBAAgB,CAAC,wCAAwC,EAAE;QAC7D,IAAI,EAAE,SAAS;KAChB,CAAC,EACF;QACE,KAAK,EAAE,eAAe;QACtB,WAAW,EACT,2DAA2D;QAC7D,QAAQ,EAAE,kBAAkB;KAC7B,EACD,KAAK,EAAE,GAAG,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE;QAC1B,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,eAAe,CAAC,QAAkB,CAAC,CAAC;QAC/D,OAAO;YACL,QAAQ,EAAE;gBACR;oBACE,GAAG,EAAE,GAAG,CAAC,IAAI;oBACb,QAAQ,EAAE,kBAAkB;oBAC5B,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;iBACxC;aACF;SACF,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"files.d.ts","sourceRoot":"","sources":["../../src/resources/files.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAElD,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,SAAS,EACjB,GAAG,EAAE,SAAS,GACb,IAAI,CAyDN"}
1
+ {"version":3,"file":"files.d.ts","sourceRoot":"","sources":["../../src/resources/files.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAElD,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,SAAS,EACjB,GAAG,EAAE,SAAS,GACb,IAAI,CAmDN"}
@@ -16,18 +16,12 @@ export function registerFileResources(server, api) {
16
16
  ],
17
17
  };
18
18
  });
19
+ // KI-078 (ENG-1381): the per-file template no longer enumerates `resources/list`.
20
+ // It is exposed via `resources/templates/list` so AI clients learn the URI pattern;
21
+ // concrete instances are read by URI on demand (e.g. `rockhopper://files/abc123`).
22
+ // The workspace-level `rockhopper://files` listing above is the discovery entry point.
19
23
  server.registerResource('enrolled-file', new ResourceTemplate('rockhopper://files/{fileMsId}', {
20
- list: async () => {
21
- const files = await api.listEnrolledFiles();
22
- return {
23
- resources: files.map((f) => ({
24
- uri: `rockhopper://files/${f.platformId}`,
25
- name: f.name,
26
- description: `${f.name} (${f.fileType})`,
27
- mimeType: 'application/json',
28
- })),
29
- };
30
- },
24
+ list: undefined,
31
25
  }), {
32
26
  title: 'Enrolled File Details',
33
27
  description: 'Details for a specific enrolled file by its platform ID',
@@ -1 +1 @@
1
- {"version":3,"file":"files.js","sourceRoot":"","sources":["../../src/resources/files.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,yCAAyC,CAAC;AAI3E,MAAM,UAAU,qBAAqB,CACnC,MAAiB,EACjB,GAAc;IAEd,MAAM,CAAC,gBAAgB,CACrB,gBAAgB,EAChB,oBAAoB,EACpB;QACE,KAAK,EAAE,gBAAgB;QACvB,WAAW,EACT,sEAAsE;QACxE,QAAQ,EAAE,kBAAkB;KAC7B,EACD,KAAK,EAAE,GAAG,EAAE,EAAE;QACZ,MAAM,KAAK,GAAG,MAAM,GAAG,CAAC,iBAAiB,EAAE,CAAC;QAC5C,OAAO;YACL,QAAQ,EAAE;gBACR;oBACE,GAAG,EAAE,GAAG,CAAC,IAAI;oBACb,QAAQ,EAAE,kBAAkB;oBAC5B,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;iBACrC;aACF;SACF,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,gBAAgB,CACrB,eAAe,EACf,IAAI,gBAAgB,CAAC,+BAA+B,EAAE;QACpD,IAAI,EAAE,KAAK,IAAI,EAAE;YACf,MAAM,KAAK,GAAG,MAAM,GAAG,CAAC,iBAAiB,EAAE,CAAC;YAC5C,OAAO;gBACL,SAAS,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;oBAC3B,GAAG,EAAE,sBAAsB,CAAC,CAAC,UAAU,EAAE;oBACzC,IAAI,EAAE,CAAC,CAAC,IAAI;oBACZ,WAAW,EAAE,GAAG,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,QAAQ,GAAG;oBACxC,QAAQ,EAAE,kBAAkB;iBAC7B,CAAC,CAAC;aACJ,CAAC;QACJ,CAAC;KACF,CAAC,EACF;QACE,KAAK,EAAE,uBAAuB;QAC9B,WAAW,EAAE,yDAAyD;QACtE,QAAQ,EAAE,kBAAkB;KAC7B,EACD,KAAK,EAAE,GAAG,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE;QAC1B,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,eAAe,CAAC,QAAkB,CAAC,CAAC;QAC3D,OAAO;YACL,QAAQ,EAAE;gBACR;oBACE,GAAG,EAAE,GAAG,CAAC,IAAI;oBACb,QAAQ,EAAE,kBAAkB;oBAC5B,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;iBACpC;aACF;SACF,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"files.js","sourceRoot":"","sources":["../../src/resources/files.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,yCAAyC,CAAC;AAI3E,MAAM,UAAU,qBAAqB,CACnC,MAAiB,EACjB,GAAc;IAEd,MAAM,CAAC,gBAAgB,CACrB,gBAAgB,EAChB,oBAAoB,EACpB;QACE,KAAK,EAAE,gBAAgB;QACvB,WAAW,EACT,sEAAsE;QACxE,QAAQ,EAAE,kBAAkB;KAC7B,EACD,KAAK,EAAE,GAAG,EAAE,EAAE;QACZ,MAAM,KAAK,GAAG,MAAM,GAAG,CAAC,iBAAiB,EAAE,CAAC;QAC5C,OAAO;YACL,QAAQ,EAAE;gBACR;oBACE,GAAG,EAAE,GAAG,CAAC,IAAI;oBACb,QAAQ,EAAE,kBAAkB;oBAC5B,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;iBACrC;aACF;SACF,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,kFAAkF;IAClF,oFAAoF;IACpF,mFAAmF;IACnF,uFAAuF;IACvF,MAAM,CAAC,gBAAgB,CACrB,eAAe,EACf,IAAI,gBAAgB,CAAC,+BAA+B,EAAE;QACpD,IAAI,EAAE,SAAS;KAChB,CAAC,EACF;QACE,KAAK,EAAE,uBAAuB;QAC9B,WAAW,EAAE,yDAAyD;QACtE,QAAQ,EAAE,kBAAkB;KAC7B,EACD,KAAK,EAAE,GAAG,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE;QAC1B,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,eAAe,CAAC,QAAkB,CAAC,CAAC;QAC3D,OAAO;YACL,QAAQ,EAAE;gBACR;oBACE,GAAG,EAAE,GAAG,CAAC,IAAI;oBACb,QAAQ,EAAE,kBAAkB;oBAC5B,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;iBACpC;aACF;SACF,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/resources/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAQlD,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,SAAS,EACjB,GAAG,EAAE,SAAS,GACb,IAAI,CAON"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/resources/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AASlD,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,SAAS,EACjB,GAAG,EAAE,SAAS,GACb,IAAI,CAQN"}
@@ -4,6 +4,7 @@ import { registerCommentResources } from './comments.js';
4
4
  import { registerReviewResources } from './reviews.js';
5
5
  import { registerTeamResources } from './teams.js';
6
6
  import { registerChangeResources } from './changes.js';
7
+ import { registerOrchestrationGuideResource } from './orchestration-guide.js';
7
8
  export function registerResources(server, api) {
8
9
  registerFileResources(server, api);
9
10
  registerVersionResources(server, api);
@@ -11,5 +12,6 @@ export function registerResources(server, api) {
11
12
  registerReviewResources(server, api);
12
13
  registerTeamResources(server, api);
13
14
  registerChangeResources(server, api);
15
+ registerOrchestrationGuideResource(server);
14
16
  }
15
17
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/resources/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;AACvD,OAAO,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;AAEvD,MAAM,UAAU,iBAAiB,CAC/B,MAAiB,EACjB,GAAc;IAEd,qBAAqB,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACnC,wBAAwB,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACtC,wBAAwB,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACtC,uBAAuB,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACrC,qBAAqB,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACnC,uBAAuB,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AACvC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/resources/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;AACvD,OAAO,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;AACvD,OAAO,EAAE,kCAAkC,EAAE,MAAM,0BAA0B,CAAC;AAE9E,MAAM,UAAU,iBAAiB,CAC/B,MAAiB,EACjB,GAAc;IAEd,qBAAqB,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACnC,wBAAwB,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACtC,wBAAwB,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACtC,uBAAuB,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACrC,qBAAqB,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACnC,uBAAuB,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACrC,kCAAkC,CAAC,MAAM,CAAC,CAAC;AAC7C,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ export declare function registerOrchestrationGuideResource(server: McpServer): void;
3
+ //# sourceMappingURL=orchestration-guide.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orchestration-guide.d.ts","sourceRoot":"","sources":["../../src/resources/orchestration-guide.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAczE,wBAAgB,kCAAkC,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAoB1E"}
@@ -0,0 +1,26 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { dirname, join } from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+ const ORCHESTRATION_GUIDE_URI = 'rockhopper://orchestration-guide';
5
+ // KI-079 (ENG-1382): static narrative resource that documents tool sequencing,
6
+ // identity disambiguation (`fileMsId` vs `versionId` vs `versionInternalId`),
7
+ // and lifecycle rules. Loaded once at module init from the sibling .md file;
8
+ // the build copies the .md into `dist/resources/` so it ships with the package.
9
+ const moduleDir = dirname(fileURLToPath(import.meta.url));
10
+ const guideContent = readFileSync(join(moduleDir, 'orchestration-guide.md'), 'utf8');
11
+ export function registerOrchestrationGuideResource(server) {
12
+ server.registerResource('orchestration-guide', ORCHESTRATION_GUIDE_URI, {
13
+ title: 'Orchestration Guide',
14
+ description: 'Narrative reference for sequencing Rockhopper MCP tools correctly — identity types, workflows, review lifecycle, versioning rules, cross-cloud differences.',
15
+ mimeType: 'text/markdown',
16
+ }, async (uri) => ({
17
+ contents: [
18
+ {
19
+ uri: uri.href,
20
+ mimeType: 'text/markdown',
21
+ text: guideContent,
22
+ },
23
+ ],
24
+ }));
25
+ }
26
+ //# sourceMappingURL=orchestration-guide.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orchestration-guide.js","sourceRoot":"","sources":["../../src/resources/orchestration-guide.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAGzC,MAAM,uBAAuB,GAAG,kCAAkC,CAAC;AAEnE,+EAA+E;AAC/E,8EAA8E;AAC9E,6EAA6E;AAC7E,gFAAgF;AAChF,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC1D,MAAM,YAAY,GAAG,YAAY,CAC/B,IAAI,CAAC,SAAS,EAAE,wBAAwB,CAAC,EACzC,MAAM,CACP,CAAC;AAEF,MAAM,UAAU,kCAAkC,CAAC,MAAiB;IAClE,MAAM,CAAC,gBAAgB,CACrB,qBAAqB,EACrB,uBAAuB,EACvB;QACE,KAAK,EAAE,qBAAqB;QAC5B,WAAW,EACT,6JAA6J;QAC/J,QAAQ,EAAE,eAAe;KAC1B,EACD,KAAK,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;QACd,QAAQ,EAAE;YACR;gBACE,GAAG,EAAE,GAAG,CAAC,IAAI;gBACb,QAAQ,EAAE,eAAe;gBACzB,IAAI,EAAE,YAAY;aACnB;SACF;KACF,CAAC,CACH,CAAC;AACJ,CAAC"}
@@ -0,0 +1,120 @@
1
+ # Rockhopper MCP — orchestration guide
2
+
3
+ This guide explains how to combine Rockhopper's MCP tools and resources correctly. Read it before sequencing multiple tool calls — it documents the prerequisites, identity types, and lifecycle rules that the individual tool descriptions cannot show in isolation.
4
+
5
+ ## 1. Identity and IDs
6
+
7
+ Rockhopper uses three distinct identifiers. Mixing them is the most common cause of tool-call errors.
8
+
9
+ | ID | Type | Where it comes from | Where it goes |
10
+ |----|------|---------------------|---------------|
11
+ | `fileMsId` | string | `list_files` response, `rockhopper://files` resource | Tools that act on a file: `get_file_versions`, `get_file_comments`, `add_comment`, `create_version`, `discard_changes`, `get_cell_history`, `get_unattributed_changes`, `update_file_description` |
12
+ | `versionId` | number | `get_file_versions` response (`internalId` field), `create_version` response | Tools that act on a specific version snapshot: `get_reviews`, `create_review_request`, `approve_review`, `cancel_review` |
13
+ | `versionInternalId` | number | `get_file_comments` response (comments scope to a version) | Comment-thread tools: `add_comment`, `reply_to_comment`, `resolve_comment` |
14
+
15
+ Decision tree:
16
+
17
+ - **Reading file metadata** → `fileMsId`.
18
+ - **Writing a comment** → `fileMsId` (the server auto-resolves the latest version) OR `versionInternalId` if commenting on a historical version.
19
+ - **Acting on a review** → `versionId`.
20
+
21
+ If a tool returns an error like "expected versionId but received fileMsId", you used the wrong identifier — check the tool description for which type it accepts.
22
+
23
+ ## 2. Reading workflow
24
+
25
+ Standard sequence to inspect a file:
26
+
27
+ 1. `list_files` — discover enrolled files. Returns `fileMsId`, `name`, `fileType`, `hasUncommittedChanges`.
28
+ 2. `get_file_versions(fileMsId)` — version history. Each entry has `internalId` (this is the `versionId`).
29
+ 3. Branch:
30
+ - File contents at a specific version → `get_cell_history(fileMsId, sheet, cellAddress)`.
31
+ - Comments → `get_file_comments(fileMsId)`. Filters to the latest live version by default.
32
+ - Reviews → `get_reviews(versionId)`. Pass a `versionId` from step 2.
33
+ - Uncommitted changes → `get_unattributed_changes(fileMsId)` (only useful if `hasUncommittedChanges === true`).
34
+
35
+ ## 3. Commenting workflow
36
+
37
+ Comments are scoped to a version. The default version is the latest **committed** one.
38
+
39
+ 1. `add_comment({ fileMsId, message, cellReference })` — creates a top-level comment on the latest version.
40
+ 2. `reply_to_comment({ parentCommentId, message })` — `parentCommentId` is the `internalId` from `get_file_comments`, **not** a substring or message match.
41
+ 3. `resolve_comment({ commentId })` — closes a thread. Idempotent — calling on an already-resolved comment is a no-op (returns the existing record).
42
+
43
+ Comments on historical versions:
44
+
45
+ - Pass `versionInternalId` explicitly to `add_comment` to comment on a historical version snapshot.
46
+ - `get_file_comments` accepts `versionInternalId` if you want to read historical-version comments rather than the current set.
47
+
48
+ ## 4. Review lifecycle
49
+
50
+ Reviews follow a strict state machine: **`pending` → `approved`** or **`pending` → `cancelled`**. No other transitions are valid.
51
+
52
+ 1. `create_review_request({ versionId, reviewerEmails, subject, description? })` — creates a `pending` review. Only the file owner / workspace member with edit rights can create.
53
+ 2. `approve_review({ reviewId })` — moves `pending` → `approved`. **Only** assigned reviewers can approve.
54
+ 3. `cancel_review({ reviewId })` — moves `pending` → `cancelled`. **Only** the requester can cancel.
55
+
56
+ Calling `approve_review` before `create_review_request` returns a 404 — there is no review to approve. Calling `approve_review` on an already-approved or cancelled review returns a 409 conflict.
57
+
58
+ ## 5. Versioning
59
+
60
+ `create_version` snapshots the file's current uncommitted state as a new version.
61
+
62
+ Rules:
63
+
64
+ - **Requires uncommitted changes.** If `get_unattributed_changes(fileMsId)` returns an empty list, `create_version` will fail with "no changes to commit".
65
+ - **Auto-bumps semver** from the latest committed version. Defaults to patch (`1.0.0` → `1.0.1`). Pass `bumpType: 'minor' | 'major'` to override.
66
+ - **Optional `description`** — a one-line changelog entry. Recommended for any non-trivial version.
67
+
68
+ `discard_changes(fileMsId)` is the **destructive** alternative: it wipes uncommitted edits without creating a snapshot. Use only when the user explicitly asks to throw away unsaved work — call `get_unattributed_changes(fileMsId)` first and confirm with the user before discarding anything substantive.
69
+
70
+ ## 6. Uncommitted changes vs. committed history
71
+
72
+ Two distinct concepts. Tools work with one or the other; do not mix.
73
+
74
+ - **Committed history** — version snapshots created by `create_version`. Surfaced by `get_file_versions`, `get_cell_history`. Immutable.
75
+ - **Uncommitted changes** — cell edits the user has made since the last `create_version`. Surfaced by `get_unattributed_changes`. Mutable; consumed by the next `create_version` or `discard_changes` call.
76
+
77
+ Common mistake: calling `get_cell_history` to inspect a recent edit before it has been committed. `get_cell_history` only returns committed values — use `get_unattributed_changes` for pending edits.
78
+
79
+ ## 7. Cross-cloud differences
80
+
81
+ Rockhopper supports both Microsoft Excel files (M365 / OneDrive) and Google Sheets. Tool calls work transparently across both, but the identifiers carry different meanings:
82
+
83
+ | Field | Microsoft Excel | Google Sheets |
84
+ |-------|------------------|----------------|
85
+ | `fileType` | `microsoft_xlsx` | `google_sheets` |
86
+ | `driveMsId` | OneDrive / SharePoint drive ID | Google Drive file ID (yes, the field name is misleading for the Google case) |
87
+ | `platformId` (= `fileMsId`) | Microsoft graph file ID | Google Drive file ID |
88
+
89
+ If a tool description references "drive ID" or "platform ID", it works identically across both clouds. If you need to know the platform, inspect `fileType`.
90
+
91
+ ## 8. Error handling
92
+
93
+ Tool failures return structured responses with `isError: true` and a human-readable message in `content`. Common patterns:
94
+
95
+ - **404 / "not found"** — usually a wrong-identifier-type error. Re-check the IDs section above.
96
+ - **409 / "conflict"** — state-machine violation (e.g. approving an already-approved review).
97
+ - **403 / "forbidden"** — permission error (e.g. non-reviewer calling `approve_review`).
98
+ - **5xx** — server-side error. Retry once; if it persists, surface the error to the user — don't loop.
99
+
100
+ When a tool returns `isError: true`, do not silently retry with the same arguments. Either correct the arguments based on the error message or surface the failure.
101
+
102
+ ## 9. Resources
103
+
104
+ The MCP server exposes two static resources via `resources/list`:
105
+
106
+ - `rockhopper://files` — workspace-level enrolled files listing. Same data as `list_files` tool.
107
+ - `rockhopper://orchestration-guide` — this document.
108
+
109
+ Eight URI templates via `resources/templates/list` — read these by constructing a concrete URI from the template pattern:
110
+
111
+ - `rockhopper://files/{fileMsId}` — file details
112
+ - `rockhopper://files/{fileMsId}/versions` — version history
113
+ - `rockhopper://files/{fileMsId}/comments` — all comments
114
+ - `rockhopper://files/{fileMsId}/changes` — uncommitted changes
115
+ - `rockhopper://versions/{versionId}` — version details
116
+ - `rockhopper://versions/{versionId}/reviews` — reviews on a version
117
+ - `rockhopper://reviews/{reviewId}` — review details
118
+ - `rockhopper://teams/{teamId}` — team details
119
+
120
+ Resources and tools return the same data for the same identifiers. Tools are preferable when you need argument shaping (filters, search); resources are preferable when you have a known URI and want the canonical representation.
@@ -1 +1 @@
1
- {"version":3,"file":"versions.d.ts","sourceRoot":"","sources":["../../src/resources/versions.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAElD,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,SAAS,EACjB,GAAG,EAAE,SAAS,GACb,IAAI,CAyDN"}
1
+ {"version":3,"file":"versions.d.ts","sourceRoot":"","sources":["../../src/resources/versions.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAElD,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,SAAS,EACjB,GAAG,EAAE,SAAS,GACb,IAAI,CAiDN"}
@@ -1,16 +1,8 @@
1
1
  import { ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js';
2
2
  export function registerVersionResources(server, api) {
3
+ // KI-078 (ENG-1381): template only, no per-file expansion into resources/list.
3
4
  server.registerResource('file-versions', new ResourceTemplate('rockhopper://files/{fileMsId}/versions', {
4
- list: async () => {
5
- const files = await api.listEnrolledFiles();
6
- return {
7
- resources: files.map((f) => ({
8
- uri: `rockhopper://files/${f.platformId}/versions`,
9
- name: `Versions of ${f.name}`,
10
- mimeType: 'application/json',
11
- })),
12
- };
13
- },
5
+ list: undefined,
14
6
  }), {
15
7
  title: 'File Version History',
16
8
  description: 'All version snapshots for a specific enrolled file',
@@ -1 +1 @@
1
- {"version":3,"file":"versions.js","sourceRoot":"","sources":["../../src/resources/versions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,yCAAyC,CAAC;AAI3E,MAAM,UAAU,wBAAwB,CACtC,MAAiB,EACjB,GAAc;IAEd,MAAM,CAAC,gBAAgB,CACrB,eAAe,EACf,IAAI,gBAAgB,CAAC,wCAAwC,EAAE;QAC7D,IAAI,EAAE,KAAK,IAAI,EAAE;YACf,MAAM,KAAK,GAAG,MAAM,GAAG,CAAC,iBAAiB,EAAE,CAAC;YAC5C,OAAO;gBACL,SAAS,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;oBAC3B,GAAG,EAAE,sBAAsB,CAAC,CAAC,UAAU,WAAW;oBAClD,IAAI,EAAE,eAAe,CAAC,CAAC,IAAI,EAAE;oBAC7B,QAAQ,EAAE,kBAAkB;iBAC7B,CAAC,CAAC;aACJ,CAAC;QACJ,CAAC;KACF,CAAC,EACF;QACE,KAAK,EAAE,sBAAsB;QAC7B,WAAW,EAAE,oDAAoD;QACjE,QAAQ,EAAE,kBAAkB;KAC7B,EACD,KAAK,EAAE,GAAG,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE;QAC1B,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,eAAe,CAAC,QAAkB,CAAC,CAAC;QAC/D,OAAO;YACL,QAAQ,EAAE;gBACR;oBACE,GAAG,EAAE,GAAG,CAAC,IAAI;oBACb,QAAQ,EAAE,kBAAkB;oBAC5B,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;iBACxC;aACF;SACF,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,gBAAgB,CACrB,cAAc,EACd,IAAI,gBAAgB,CAAC,mCAAmC,EAAE;QACxD,IAAI,EAAE,SAAS;KAChB,CAAC,EACF;QACE,KAAK,EAAE,iBAAiB;QACxB,WAAW,EAAE,oDAAoD;QACjE,QAAQ,EAAE,kBAAkB;KAC7B,EACD,KAAK,EAAE,GAAG,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE;QAC3B,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,cAAc,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC;QAC5D,OAAO;YACL,QAAQ,EAAE;gBACR;oBACE,GAAG,EAAE,GAAG,CAAC,IAAI;oBACb,QAAQ,EAAE,kBAAkB;oBAC5B,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;iBACvC;aACF;SACF,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"versions.js","sourceRoot":"","sources":["../../src/resources/versions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,yCAAyC,CAAC;AAI3E,MAAM,UAAU,wBAAwB,CACtC,MAAiB,EACjB,GAAc;IAEd,+EAA+E;IAC/E,MAAM,CAAC,gBAAgB,CACrB,eAAe,EACf,IAAI,gBAAgB,CAAC,wCAAwC,EAAE;QAC7D,IAAI,EAAE,SAAS;KAChB,CAAC,EACF;QACE,KAAK,EAAE,sBAAsB;QAC7B,WAAW,EAAE,oDAAoD;QACjE,QAAQ,EAAE,kBAAkB;KAC7B,EACD,KAAK,EAAE,GAAG,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE;QAC1B,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,eAAe,CAAC,QAAkB,CAAC,CAAC;QAC/D,OAAO;YACL,QAAQ,EAAE;gBACR;oBACE,GAAG,EAAE,GAAG,CAAC,IAAI;oBACb,QAAQ,EAAE,kBAAkB;oBAC5B,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;iBACxC;aACF;SACF,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,gBAAgB,CACrB,cAAc,EACd,IAAI,gBAAgB,CAAC,mCAAmC,EAAE;QACxD,IAAI,EAAE,SAAS;KAChB,CAAC,EACF;QACE,KAAK,EAAE,iBAAiB;QACxB,WAAW,EAAE,oDAAoD;QACjE,QAAQ,EAAE,kBAAkB;KAC7B,EACD,KAAK,EAAE,GAAG,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE;QAC3B,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,cAAc,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC;QAC5D,OAAO;YACL,QAAQ,EAAE;gBACR;oBACE,GAAG,EAAE,GAAG,CAAC,IAAI;oBACb,QAAQ,EAAE,kBAAkB;oBAC5B,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;iBACvC;aACF;SACF,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rockhopper-co/mcp-server",
3
- "version": "0.4.0",
3
+ "version": "0.6.0",
4
4
  "description": "Rockhopper MCP server — expose file metadata, versions, reviews, and comments to AI tools",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -22,7 +22,7 @@
22
22
  "CHANGELOG.md"
23
23
  ],
24
24
  "scripts": {
25
- "build": "tsc -p tsconfig.build.json",
25
+ "build": "tsc -p tsconfig.build.json && node scripts/copy-non-ts-assets.mjs",
26
26
  "start": "node dist/cli.js",
27
27
  "dev": "tsx watch src/cli.ts",
28
28
  "lint": "eslint src/",