@rockhopper-co/mcp-server 0.2.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 (92) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/LICENSE +21 -0
  3. package/README.md +157 -0
  4. package/dist/api-client.d.ts +54 -0
  5. package/dist/api-client.d.ts.map +1 -0
  6. package/dist/api-client.js +120 -0
  7. package/dist/api-client.js.map +1 -0
  8. package/dist/index.d.ts +3 -0
  9. package/dist/index.d.ts.map +1 -0
  10. package/dist/index.js +19 -0
  11. package/dist/index.js.map +1 -0
  12. package/dist/prompts/index.d.ts +4 -0
  13. package/dist/prompts/index.d.ts.map +1 -0
  14. package/dist/prompts/index.js +156 -0
  15. package/dist/prompts/index.js.map +1 -0
  16. package/dist/resources/changes.d.ts +4 -0
  17. package/dist/resources/changes.d.ts.map +1 -0
  18. package/dist/resources/changes.js +33 -0
  19. package/dist/resources/changes.js.map +1 -0
  20. package/dist/resources/comments.d.ts +4 -0
  21. package/dist/resources/comments.d.ts.map +1 -0
  22. package/dist/resources/comments.js +31 -0
  23. package/dist/resources/comments.js.map +1 -0
  24. package/dist/resources/files.d.ts +4 -0
  25. package/dist/resources/files.d.ts.map +1 -0
  26. package/dist/resources/files.js +48 -0
  27. package/dist/resources/files.js.map +1 -0
  28. package/dist/resources/index.d.ts +4 -0
  29. package/dist/resources/index.d.ts.map +1 -0
  30. package/dist/resources/index.js +15 -0
  31. package/dist/resources/index.js.map +1 -0
  32. package/dist/resources/reviews.d.ts +4 -0
  33. package/dist/resources/reviews.d.ts.map +1 -0
  34. package/dist/resources/reviews.js +40 -0
  35. package/dist/resources/reviews.js.map +1 -0
  36. package/dist/resources/teams.d.ts +4 -0
  37. package/dist/resources/teams.d.ts.map +1 -0
  38. package/dist/resources/teams.js +22 -0
  39. package/dist/resources/teams.js.map +1 -0
  40. package/dist/resources/versions.d.ts +4 -0
  41. package/dist/resources/versions.d.ts.map +1 -0
  42. package/dist/resources/versions.js +49 -0
  43. package/dist/resources/versions.js.map +1 -0
  44. package/dist/server.d.ts +4 -0
  45. package/dist/server.d.ts.map +1 -0
  46. package/dist/server.js +22 -0
  47. package/dist/server.js.map +1 -0
  48. package/dist/tools/get-cell-history.d.ts +4 -0
  49. package/dist/tools/get-cell-history.d.ts.map +1 -0
  50. package/dist/tools/get-cell-history.js +50 -0
  51. package/dist/tools/get-cell-history.js.map +1 -0
  52. package/dist/tools/get-comments.d.ts +4 -0
  53. package/dist/tools/get-comments.d.ts.map +1 -0
  54. package/dist/tools/get-comments.js +53 -0
  55. package/dist/tools/get-comments.js.map +1 -0
  56. package/dist/tools/get-reviews.d.ts +4 -0
  57. package/dist/tools/get-reviews.d.ts.map +1 -0
  58. package/dist/tools/get-reviews.js +71 -0
  59. package/dist/tools/get-reviews.js.map +1 -0
  60. package/dist/tools/get-versions.d.ts +4 -0
  61. package/dist/tools/get-versions.d.ts.map +1 -0
  62. package/dist/tools/get-versions.js +56 -0
  63. package/dist/tools/get-versions.js.map +1 -0
  64. package/dist/tools/index.d.ts +4 -0
  65. package/dist/tools/index.d.ts.map +1 -0
  66. package/dist/tools/index.js +23 -0
  67. package/dist/tools/index.js.map +1 -0
  68. package/dist/tools/list-files.d.ts +4 -0
  69. package/dist/tools/list-files.d.ts.map +1 -0
  70. package/dist/tools/list-files.js +45 -0
  71. package/dist/tools/list-files.js.map +1 -0
  72. package/dist/tools/search.d.ts +4 -0
  73. package/dist/tools/search.d.ts.map +1 -0
  74. package/dist/tools/search.js +94 -0
  75. package/dist/tools/search.js.map +1 -0
  76. package/dist/tools/write-comments.d.ts +4 -0
  77. package/dist/tools/write-comments.d.ts.map +1 -0
  78. package/dist/tools/write-comments.js +142 -0
  79. package/dist/tools/write-comments.js.map +1 -0
  80. package/dist/tools/write-files.d.ts +4 -0
  81. package/dist/tools/write-files.d.ts.map +1 -0
  82. package/dist/tools/write-files.js +40 -0
  83. package/dist/tools/write-files.js.map +1 -0
  84. package/dist/tools/write-reviews.d.ts +4 -0
  85. package/dist/tools/write-reviews.d.ts.map +1 -0
  86. package/dist/tools/write-reviews.js +107 -0
  87. package/dist/tools/write-reviews.js.map +1 -0
  88. package/dist/types.d.ts +106 -0
  89. package/dist/types.d.ts.map +1 -0
  90. package/dist/types.js +2 -0
  91. package/dist/types.js.map +1 -0
  92. package/package.json +72 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,41 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented here. Follows
4
+ [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and
5
+ [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
+
7
+ ## [0.2.0] — 2026-04-23
8
+
9
+ First public release on npm as `@rockhopper-co/mcp-server`.
10
+
11
+ ### Added
12
+ - Public npm publishing under `@rockhopper-co/mcp-server`.
13
+ - MIT license.
14
+ - GitHub Actions `ci.yml` and `publish.yml` workflows.
15
+ - `prepublishOnly` build hook and `release:*` version scripts.
16
+ - `files` whitelist so only `dist/`, `README.md`, and `LICENSE` ship.
17
+ - npm provenance via OIDC in the publish workflow.
18
+ - `tsconfig.build.json` to exclude test files from the published
19
+ tarball; production build now ships ~22 kB packed (vs ~80 kB before).
20
+
21
+ ### Changed
22
+ - Required `versionInternalId` on `add_comment` and `reply_to_comment`
23
+ to match backend DTO contracts.
24
+ - `create_review_request` now takes `versionId: number` and
25
+ `reviewerIds: number[]` (was `fileVersionInternalId` / `reviewerMsIds`).
26
+ - Removed trailing slash from sheet-scoped unattributed-changes URL to
27
+ match the backend route.
28
+
29
+ ### Fixed
30
+ - Backend gap G1: `/file-versions/file/version/:versionInternalId` now
31
+ requires JWT/PAT auth and file-access authorization.
32
+ - Backend gap G5: `search` query on `/enrolled-files` now filters by
33
+ file name (ILIKE).
34
+ - Backend gap G8: PAT-authenticated file-chat requests now log a
35
+ warning when Excel-native OBO sync is skipped.
36
+ - Backend gap G9/G12: PAT traffic is now throttled via a dedicated
37
+ `PatThrottlerGuard` (120 req/min per user+scope).
38
+
39
+ ## [0.1.0] — 2026-04-20
40
+
41
+ Internal prototype. Private package.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Rockhopper Technologies, Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,157 @@
1
+ # Rockhopper MCP Server
2
+
3
+ MCP (Model Context Protocol) server for Rockhopper. Lets AI tools like Claude, Cursor, and Copilot interact with your Rockhopper workspace — enrolled files, version history, reviews, comments, and cell-level change tracking.
4
+
5
+ ## Prerequisites
6
+
7
+ - Node.js 18+
8
+ - A Rockhopper account with at least one enrolled file
9
+ - A Personal Access Token (PAT) from Rockhopper
10
+
11
+ ## Setup
12
+
13
+ ### 1. Create a Personal Access Token
14
+
15
+ In the Rockhopper web app, go to **Settings > Personal Access Tokens** and create a new token. Choose `read-only` scope for read access or `read-write` if you also want to add comments/reviews.
16
+
17
+ Copy the token — it's shown only once.
18
+
19
+ ### 2. Install
20
+
21
+ ```bash
22
+ npm install -g @rockhopper-co/mcp-server
23
+ ```
24
+
25
+ Or run directly with npx:
26
+
27
+ ```bash
28
+ npx @rockhopper-co/mcp-server
29
+ ```
30
+
31
+ ### 3. Configure your AI tool
32
+
33
+ #### Claude Desktop / Claude Code
34
+
35
+ Add to your MCP config (`~/.claude/mcp.json` or Claude Desktop settings):
36
+
37
+ ```json
38
+ {
39
+ "mcpServers": {
40
+ "rockhopper": {
41
+ "command": "npx",
42
+ "args": ["-y", "@rockhopper-co/mcp-server"],
43
+ "env": {
44
+ "ROCKHOPPER_TOKEN": "rh_pat_your_token_here",
45
+ "ROCKHOPPER_API_URL": "https://api.rockhopper.co"
46
+ }
47
+ }
48
+ }
49
+ }
50
+ ```
51
+
52
+ #### Cursor
53
+
54
+ Add to `.cursor/mcp.json` in your project:
55
+
56
+ ```json
57
+ {
58
+ "mcpServers": {
59
+ "rockhopper": {
60
+ "command": "npx",
61
+ "args": ["-y", "@rockhopper-co/mcp-server"],
62
+ "env": {
63
+ "ROCKHOPPER_TOKEN": "rh_pat_your_token_here",
64
+ "ROCKHOPPER_API_URL": "https://api.rockhopper.co"
65
+ }
66
+ }
67
+ }
68
+ }
69
+ ```
70
+
71
+ ## Environment Variables
72
+
73
+ | Variable | Required | Default | Description |
74
+ |----------|----------|---------|-------------|
75
+ | `ROCKHOPPER_TOKEN` | Yes | — | Personal Access Token (starts with `rh_pat_`) |
76
+ | `ROCKHOPPER_API_URL` | No | `https://api.rockhopper.co` | Rockhopper API base URL |
77
+
78
+ ## Available Tools
79
+
80
+ | Tool | Description |
81
+ |------|-------------|
82
+ | `list_files` | List enrolled Excel files with optional search filter |
83
+ | `get_file_versions` | Get version history for a specific file |
84
+ | `get_file_comments` | Get comments and threaded discussions on a file |
85
+ | `get_reviews` | Get review requests for a version or file |
86
+ | `get_cell_history` | Get change history for a specific cell across versions |
87
+ | `search_files` | Search enrolled files by name |
88
+ | `get_unattributed_changes` | Get pending cell changes not yet committed to a version |
89
+
90
+ ## Available Resources
91
+
92
+ | Resource | URI | Description |
93
+ |----------|-----|-------------|
94
+ | Enrolled Files | `rockhopper://files` | All enrolled files in workspace |
95
+ | File Detail | `rockhopper://files/{fileMsId}` | Details for a specific file |
96
+ | File Versions | `rockhopper://files/{fileMsId}/versions` | Version history for a file |
97
+ | Version Detail | `rockhopper://versions/{versionId}` | Single version details |
98
+ | File Comments | `rockhopper://files/{fileMsId}/comments` | Comments on a file |
99
+ | Version Reviews | `rockhopper://versions/{versionId}/reviews` | Reviews for a version |
100
+ | Review Detail | `rockhopper://reviews/{reviewId}` | Single review details |
101
+ | Team Detail | `rockhopper://teams/{teamId}` | Team details with members |
102
+ | Unattributed Changes | `rockhopper://files/{fileMsId}/changes` | Pending changes |
103
+
104
+ ## Available Prompts
105
+
106
+ | Prompt | Description |
107
+ |--------|-------------|
108
+ | `summarize-file-changes` | Summarize recent version changes and unattributed edits for a file |
109
+ | `pending-reviews` | Show all pending review requests for the latest version of a file |
110
+ | `unresolved-comments` | List all unresolved comments on a file for follow-up |
111
+ | `file-overview` | Comprehensive overview: versions, comments, reviews, and changes |
112
+
113
+ ## Write Tools (requires `read-write` scope)
114
+
115
+ | Tool | Description |
116
+ |------|-------------|
117
+ | `add_comment` | Add a comment to an enrolled file (optionally at a cell) |
118
+ | `reply_to_comment` | Reply to an existing comment thread |
119
+ | `resolve_comment` | Mark a comment as resolved (author only) |
120
+ | `create_review_request` | Request a review on a file version |
121
+ | `approve_review` | Approve a review request (assigned reviewer only) |
122
+ | `update_file_description` | Update the display name of an enrolled file |
123
+
124
+ ## Development
125
+
126
+ ```bash
127
+ # Install dependencies
128
+ npm install
129
+
130
+ # Run in dev mode (auto-restart on changes)
131
+ npm run dev
132
+
133
+ # Build
134
+ npm run build
135
+
136
+ # Run tests
137
+ npm test
138
+
139
+ # Type check
140
+ npm run typecheck
141
+ ```
142
+
143
+ ## Security
144
+
145
+ - Tokens are scoped to the creating user — the MCP server can only access data the user has permission to see
146
+ - `read-only` tokens cannot perform write operations (comments, reviews)
147
+ - All API calls go through Rockhopper's existing authorization guards
148
+ - Tokens can be revoked instantly from the Settings page
149
+ - The MCP server runs locally and communicates with the API over HTTPS
150
+
151
+ ## Architecture
152
+
153
+ ```
154
+ AI Tool (Claude/Cursor) <--stdio--> mcp-server <--HTTPS--> Rockhopper API <--> PostgreSQL
155
+ ```
156
+
157
+ The MCP server is a thin adapter. It translates MCP tool/resource requests into Rockhopper REST API calls, authenticated with the user's PAT. All authorization is enforced server-side — the MCP server has no direct database access.
@@ -0,0 +1,54 @@
1
+ import type { CellHistoryEntry, EnrolledFile, FileChat, FileVersion, ReviewActivity, ReviewRequest, Team, UnattributedChange, UserSummary } from './types.js';
2
+ export interface ApiClientConfig {
3
+ baseUrl: string;
4
+ token: string;
5
+ }
6
+ export declare class ApiClient {
7
+ private readonly baseUrl;
8
+ private readonly token;
9
+ constructor(config: ApiClientConfig);
10
+ private request;
11
+ getMe(): Promise<UserSummary>;
12
+ getTeam(teamId: number): Promise<Team>;
13
+ listEnrolledFiles(params?: {
14
+ search?: string;
15
+ }): Promise<EnrolledFile[]>;
16
+ getEnrolledFile(fileMsId: string): Promise<EnrolledFile>;
17
+ getFileVersions(fileMsId: string): Promise<FileVersion[]>;
18
+ getFileVersion(versionInternalId: number): Promise<FileVersion>;
19
+ getCellHistory(fileMsId: string, sheetName: string, cellAddress: string): Promise<CellHistoryEntry[]>;
20
+ getFileComments(fileMsId: string): Promise<FileChat[]>;
21
+ getComment(chatId: number): Promise<FileChat>;
22
+ createComment(body: {
23
+ fileMsId: string;
24
+ message: string;
25
+ cellReference?: string;
26
+ versionInternalId: number;
27
+ }): Promise<FileChat>;
28
+ replyToComment(chatId: number, body: {
29
+ message: string;
30
+ versionInternalId: number;
31
+ }): Promise<FileChat>;
32
+ resolveComment(chatId: number): Promise<FileChat>;
33
+ getReviewsForVersion(versionId: number): Promise<ReviewRequest[]>;
34
+ getReviewsForLatestVersion(fileMsId: string): Promise<ReviewRequest[]>;
35
+ getReview(reviewId: number): Promise<ReviewRequest>;
36
+ getReviewActivities(reviewId: number): Promise<ReviewActivity[]>;
37
+ createReviewRequest(body: {
38
+ versionId: number;
39
+ subject: string;
40
+ description?: string;
41
+ reviewerIds: number[];
42
+ }): Promise<ReviewRequest>;
43
+ approveReview(reviewId: number, body: {
44
+ notes?: string;
45
+ }): Promise<ReviewRequest>;
46
+ getUnattributedChanges(fileMsId: string, params?: {
47
+ sheetName?: string;
48
+ status?: string;
49
+ }): Promise<UnattributedChange[]>;
50
+ updateEnrolledFile(fileMsId: string, body: {
51
+ name?: string;
52
+ }): Promise<EnrolledFile>;
53
+ }
54
+ //# sourceMappingURL=api-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../src/api-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,120 @@
1
+ export class ApiClient {
2
+ baseUrl;
3
+ token;
4
+ constructor(config) {
5
+ this.baseUrl = config.baseUrl.replace(/\/+$/, '');
6
+ this.token = config.token;
7
+ }
8
+ async request(path, init) {
9
+ const url = `${this.baseUrl}${path}`;
10
+ const response = await fetch(url, {
11
+ ...init,
12
+ headers: {
13
+ Authorization: `Bearer ${this.token}`,
14
+ 'Content-Type': 'application/json',
15
+ ...init?.headers,
16
+ },
17
+ });
18
+ if (!response.ok) {
19
+ const body = await response.text().catch(() => '');
20
+ throw new Error(`Rockhopper API ${response.status}: ${response.statusText} — ${body}`);
21
+ }
22
+ return response.json();
23
+ }
24
+ // --- Users ---
25
+ async getMe() {
26
+ return this.request('/users/me');
27
+ }
28
+ // --- Teams ---
29
+ async getTeam(teamId) {
30
+ return this.request(`/teams/${teamId}`);
31
+ }
32
+ // --- Enrolled Files ---
33
+ async listEnrolledFiles(params) {
34
+ const query = new URLSearchParams();
35
+ if (params?.search)
36
+ query.set('search', params.search);
37
+ const qs = query.toString();
38
+ return this.request(`/enrolled-files${qs ? `?${qs}` : ''}`);
39
+ }
40
+ async getEnrolledFile(fileMsId) {
41
+ return this.request(`/enrolled-files/${fileMsId}`);
42
+ }
43
+ // --- File Versions ---
44
+ async getFileVersions(fileMsId) {
45
+ return this.request(`/file-versions/file/${fileMsId}`);
46
+ }
47
+ async getFileVersion(versionInternalId) {
48
+ return this.request(`/file-versions/file/version/${versionInternalId}`);
49
+ }
50
+ async getCellHistory(fileMsId, sheetName, cellAddress) {
51
+ const query = new URLSearchParams({ cell: cellAddress, sheetName });
52
+ return this.request(`/file-versions/file/${fileMsId}/cell-history?${query}`);
53
+ }
54
+ // --- File Chat (Comments) ---
55
+ async getFileComments(fileMsId) {
56
+ return this.request(`/file-chat/${fileMsId}`);
57
+ }
58
+ async getComment(chatId) {
59
+ return this.request(`/file-chat/single/${chatId}`);
60
+ }
61
+ async createComment(body) {
62
+ return this.request('/file-chat', {
63
+ method: 'POST',
64
+ body: JSON.stringify(body),
65
+ });
66
+ }
67
+ async replyToComment(chatId, body) {
68
+ return this.request(`/file-chat/${chatId}/replies`, {
69
+ method: 'POST',
70
+ body: JSON.stringify(body),
71
+ });
72
+ }
73
+ async resolveComment(chatId) {
74
+ return this.request(`/file-chat/${chatId}`, {
75
+ method: 'PATCH',
76
+ body: JSON.stringify({ resolved: true }),
77
+ });
78
+ }
79
+ // --- Reviews ---
80
+ async getReviewsForVersion(versionId) {
81
+ return this.request(`/reviews/versions/${versionId}/requests`);
82
+ }
83
+ async getReviewsForLatestVersion(fileMsId) {
84
+ return this.request(`/reviews/files/${fileMsId}/latest-version/requests`);
85
+ }
86
+ async getReview(reviewId) {
87
+ return this.request(`/reviews/requests/${reviewId}`);
88
+ }
89
+ async getReviewActivities(reviewId) {
90
+ return this.request(`/reviews/requests/${reviewId}/activities`);
91
+ }
92
+ async createReviewRequest(body) {
93
+ return this.request('/reviews/requests', {
94
+ method: 'POST',
95
+ body: JSON.stringify(body),
96
+ });
97
+ }
98
+ async approveReview(reviewId, body) {
99
+ return this.request(`/reviews/requests/${reviewId}/approve`, {
100
+ method: 'POST',
101
+ body: JSON.stringify(body),
102
+ });
103
+ }
104
+ // --- Unattributed Changes ---
105
+ async getUnattributedChanges(fileMsId, params) {
106
+ let path = `/unattributed-changes/${fileMsId}`;
107
+ if (params?.sheetName) {
108
+ path += `/${params.sheetName}`;
109
+ }
110
+ return this.request(path);
111
+ }
112
+ // --- File metadata update ---
113
+ async updateEnrolledFile(fileMsId, body) {
114
+ return this.request(`/enrolled-files/${fileMsId}`, {
115
+ method: 'PATCH',
116
+ body: JSON.stringify(body),
117
+ });
118
+ }
119
+ }
120
+ //# sourceMappingURL=api-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-client.js","sourceRoot":"","sources":["../src/api-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env node
2
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
3
+ import { ApiClient } from './api-client.js';
4
+ import { createServer } from './server.js';
5
+ const ROCKHOPPER_API_URL = process.env.ROCKHOPPER_API_URL || 'https://api.rockhopper.co';
6
+ const ROCKHOPPER_TOKEN = process.env.ROCKHOPPER_TOKEN;
7
+ if (!ROCKHOPPER_TOKEN) {
8
+ console.error('Error: ROCKHOPPER_TOKEN environment variable is required.\n' +
9
+ 'Create a Personal Access Token in Rockhopper Settings and set it as ROCKHOPPER_TOKEN.');
10
+ process.exit(1);
11
+ }
12
+ const apiClient = new ApiClient({
13
+ baseUrl: ROCKHOPPER_API_URL,
14
+ token: ROCKHOPPER_TOKEN,
15
+ });
16
+ const server = createServer(apiClient);
17
+ const transport = new StdioServerTransport();
18
+ await server.connect(transport);
19
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,MAAM,kBAAkB,GACtB,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,2BAA2B,CAAC;AAChE,MAAM,gBAAgB,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;AAEtD,IAAI,CAAC,gBAAgB,EAAE,CAAC;IACtB,OAAO,CAAC,KAAK,CACX,6DAA6D;QAC3D,uFAAuF,CAC1F,CAAC;IACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,MAAM,SAAS,GAAG,IAAI,SAAS,CAAC;IAC9B,OAAO,EAAE,kBAAkB;IAC3B,KAAK,EAAE,gBAAgB;CACxB,CAAC,CAAC;AAEH,MAAM,MAAM,GAAG,YAAY,CAAC,SAAS,CAAC,CAAC;AAEvC,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;AAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import type { ApiClient } from '../api-client.js';
3
+ export declare function registerPrompts(server: McpServer, api: ApiClient): void;
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/prompts/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAElD,wBAAgB,eAAe,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,SAAS,GAAG,IAAI,CA4MvE"}
@@ -0,0 +1,156 @@
1
+ import { z } from 'zod';
2
+ export function registerPrompts(server, api) {
3
+ server.registerPrompt('summarize-file-changes', {
4
+ title: 'Summarize Recent Changes',
5
+ description: 'Summarize recent version changes and unattributed edits for an enrolled file.',
6
+ argsSchema: {
7
+ fileMsId: z.string().describe('Platform ID of the enrolled file'),
8
+ },
9
+ }, async ({ fileMsId }) => {
10
+ const [file, versions, changes] = await Promise.all([
11
+ api.getEnrolledFile(fileMsId),
12
+ api.getFileVersions(fileMsId),
13
+ api.getUnattributedChanges(fileMsId),
14
+ ]);
15
+ const recentVersions = versions.slice(0, 5);
16
+ const versionSummary = recentVersions
17
+ .map((v) => `- v${v.majorVersion}.${v.minorVersion}.${v.patchVersion}: ${v.description || 'No description'} (${v.createdAt})`)
18
+ .join('\n');
19
+ const changeSummary = changes.length
20
+ ? changes
21
+ .slice(0, 20)
22
+ .map((c) => `- ${c.sheetName}!${c.cellAddress}: ${JSON.stringify(c.oldValue)} → ${JSON.stringify(c.newValue)}`)
23
+ .join('\n')
24
+ : 'None';
25
+ return {
26
+ messages: [
27
+ {
28
+ role: 'user',
29
+ content: {
30
+ type: 'text',
31
+ text: `Summarize the recent activity on the file "${file.name}".\n\n` +
32
+ `## Recent Versions (last ${recentVersions.length} of ${versions.length})\n${versionSummary}\n\n` +
33
+ `## Unattributed Changes (${changes.length} total)\n${changeSummary}\n\n` +
34
+ `Provide a concise summary of what has changed recently, who made changes, and any notable patterns.`,
35
+ },
36
+ },
37
+ ],
38
+ };
39
+ });
40
+ server.registerPrompt('pending-reviews', {
41
+ title: 'Pending Reviews',
42
+ description: 'Show all pending review requests for the latest version of a file.',
43
+ argsSchema: {
44
+ fileMsId: z.string().describe('Platform ID of the enrolled file'),
45
+ },
46
+ }, async ({ fileMsId }) => {
47
+ const [file, reviews] = await Promise.all([
48
+ api.getEnrolledFile(fileMsId),
49
+ api.getReviewsForLatestVersion(fileMsId),
50
+ ]);
51
+ const reviewSummary = reviews.length
52
+ ? reviews
53
+ .map((r) => `- "${r.subject}" (status: ${r.status}, id: ${r.id})` +
54
+ (r.requester
55
+ ? ` — requested by ${r.requester.firstName} ${r.requester.lastName}`
56
+ : '') +
57
+ (r.description ? `\n Description: ${r.description}` : ''))
58
+ .join('\n')
59
+ : 'No reviews found for the latest version.';
60
+ return {
61
+ messages: [
62
+ {
63
+ role: 'user',
64
+ content: {
65
+ type: 'text',
66
+ text: `Show me the status of all review requests for "${file.name}".\n\n` +
67
+ `## Reviews on Latest Version\n${reviewSummary}\n\n` +
68
+ `Summarize the review status: how many are pending, approved, or need attention?`,
69
+ },
70
+ },
71
+ ],
72
+ };
73
+ });
74
+ server.registerPrompt('unresolved-comments', {
75
+ title: 'Unresolved Comments',
76
+ description: 'List all unresolved comments on a file for follow-up.',
77
+ argsSchema: {
78
+ fileMsId: z.string().describe('Platform ID of the enrolled file'),
79
+ },
80
+ }, async ({ fileMsId }) => {
81
+ const [file, comments] = await Promise.all([
82
+ api.getEnrolledFile(fileMsId),
83
+ api.getFileComments(fileMsId),
84
+ ]);
85
+ const unresolved = comments.filter((c) => !c.resolved);
86
+ const commentSummary = unresolved.length
87
+ ? unresolved
88
+ .map((c) => {
89
+ const author = c.authorName || c.authorEmail || 'Unknown';
90
+ const cell = c.cellReference ? ` [${c.cellReference}]` : '';
91
+ const replyCount = c.replies?.length || 0;
92
+ return (`- **${author}**${cell}: "${c.message}" (${c.createdAt})` +
93
+ (replyCount ? ` — ${replyCount} replies` : ''));
94
+ })
95
+ .join('\n')
96
+ : 'All comments are resolved!';
97
+ return {
98
+ messages: [
99
+ {
100
+ role: 'user',
101
+ content: {
102
+ type: 'text',
103
+ text: `List all unresolved comments on "${file.name}" that need follow-up.\n\n` +
104
+ `## Unresolved Comments (${unresolved.length} of ${comments.length} total)\n${commentSummary}\n\n` +
105
+ `Prioritize these comments by urgency and suggest next steps for each.`,
106
+ },
107
+ },
108
+ ],
109
+ };
110
+ });
111
+ server.registerPrompt('file-overview', {
112
+ title: 'File Overview',
113
+ description: 'Get a comprehensive overview of an enrolled file — versions, comments, reviews, and changes.',
114
+ argsSchema: {
115
+ fileMsId: z.string().describe('Platform ID of the enrolled file'),
116
+ },
117
+ }, async ({ fileMsId }) => {
118
+ const [file, versions, comments, changes] = await Promise.all([
119
+ api.getEnrolledFile(fileMsId),
120
+ api.getFileVersions(fileMsId),
121
+ api.getFileComments(fileMsId),
122
+ api.getUnattributedChanges(fileMsId),
123
+ ]);
124
+ const latestVersion = versions[0];
125
+ let reviews = [];
126
+ if (latestVersion) {
127
+ reviews = await api.getReviewsForVersion(latestVersion.internalId);
128
+ }
129
+ const unresolvedComments = comments.filter((c) => !c.resolved);
130
+ const pendingReviews = reviews.filter((r) => r.status !== 'approved' && r.status !== 'rejected');
131
+ return {
132
+ messages: [
133
+ {
134
+ role: 'user',
135
+ content: {
136
+ type: 'text',
137
+ text: `Give me a comprehensive overview of "${file.name}".\n\n` +
138
+ `## File Info\n` +
139
+ `- Type: ${file.fileType}\n` +
140
+ `- Platform ID: ${file.platformId}\n` +
141
+ `- Uncommitted changes: ${file.hasUncommittedChanges ? 'Yes' : 'No'}\n\n` +
142
+ `## Versions: ${versions.length} total\n` +
143
+ (latestVersion
144
+ ? `Latest: v${latestVersion.majorVersion}.${latestVersion.minorVersion}.${latestVersion.patchVersion} (${latestVersion.createdAt})\n`
145
+ : 'No versions yet.\n') +
146
+ `\n## Comments: ${comments.length} total, ${unresolvedComments.length} unresolved\n` +
147
+ `## Reviews: ${reviews.length} total, ${pendingReviews.length} pending\n` +
148
+ `## Unattributed Changes: ${changes.length}\n\n` +
149
+ `Provide a status report highlighting anything that needs attention.`,
150
+ },
151
+ },
152
+ ],
153
+ };
154
+ });
155
+ }
156
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/prompts/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import type { ApiClient } from '../api-client.js';
3
+ export declare function registerChangeResources(server: McpServer, api: ApiClient): void;
4
+ //# sourceMappingURL=changes.d.ts.map
@@ -0,0 +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"}