@nimbus-dev/connectors 0.2.1 → 0.2.2

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 (215) hide show
  1. package/README.md +14 -4
  2. package/connectors/airflow/src/search-filter.ts +2 -15
  3. package/connectors/airflow/src/server.ts +2 -87
  4. package/connectors/airflow/src/tools.ts +74 -0
  5. package/connectors/apple/src/adapters.ts +326 -0
  6. package/connectors/apple/src/apple-mail-core.ts +4 -8
  7. package/connectors/apple/src/calendar-tools.ts +28 -8
  8. package/connectors/apple/src/server.ts +23 -512
  9. package/connectors/apple/src/tools.ts +18 -44
  10. package/connectors/argocd/src/server.ts +25 -38
  11. package/connectors/athena/src/tools.ts +15 -34
  12. package/connectors/aws/src/server.ts +2 -183
  13. package/connectors/aws/src/tools.ts +197 -0
  14. package/connectors/azure/src/server.ts +2 -131
  15. package/connectors/azure/src/tools.ts +133 -0
  16. package/connectors/bigeye/src/search-filter.ts +4 -15
  17. package/connectors/bigeye/src/server.ts +38 -38
  18. package/connectors/bigquery/src/tools.ts +1 -26
  19. package/connectors/bitbucket/src/server.ts +2 -244
  20. package/connectors/bitbucket/src/tools.ts +241 -0
  21. package/connectors/bitrise/src/server.ts +2 -79
  22. package/connectors/bitrise/src/tools.ts +76 -0
  23. package/connectors/canva/src/search-filter.ts +2 -11
  24. package/connectors/canva/src/server.ts +2 -73
  25. package/connectors/canva/src/tools.ts +66 -0
  26. package/connectors/circleci/src/server.ts +2 -176
  27. package/connectors/circleci/src/tools.ts +193 -0
  28. package/connectors/cloud-logging/src/tools.ts +14 -27
  29. package/connectors/cloudwatch/src/tools.ts +15 -34
  30. package/connectors/codemagic/src/server.ts +2 -70
  31. package/connectors/codemagic/src/tools.ts +71 -0
  32. package/connectors/confluence/src/server.ts +2 -301
  33. package/connectors/confluence/src/tools.ts +320 -0
  34. package/connectors/dagster/src/server.ts +2 -214
  35. package/connectors/dagster/src/tools.ts +187 -0
  36. package/connectors/databricks/src/search-filter.ts +7 -7
  37. package/connectors/databricks/src/server.ts +2 -77
  38. package/connectors/databricks/src/tools.ts +66 -0
  39. package/connectors/datadog/src/server.ts +2 -48
  40. package/connectors/datadog/src/tools.ts +48 -0
  41. package/connectors/dataprofile/src/profile.ts +16 -46
  42. package/connectors/dbt/src/server.ts +2 -92
  43. package/connectors/dbt/src/tools.ts +80 -0
  44. package/connectors/dependencytrack/src/server.ts +2 -76
  45. package/connectors/dependencytrack/src/tools.ts +65 -0
  46. package/connectors/discord/src/server.ts +2 -85
  47. package/connectors/discord/src/tools.ts +82 -0
  48. package/connectors/elasticsearch/src/tools.ts +7 -37
  49. package/connectors/fastmail/src/jmap-client.ts +202 -0
  50. package/connectors/fastmail/src/jmap-core.ts +8 -21
  51. package/connectors/fastmail/src/server.ts +2 -187
  52. package/connectors/fastmail/src/tools.ts +4 -23
  53. package/connectors/figma/src/search-filter.ts +2 -11
  54. package/connectors/figma/src/server.ts +2 -113
  55. package/connectors/figma/src/tools.ts +99 -0
  56. package/connectors/firebase/src/server.ts +2 -90
  57. package/connectors/firebase/src/token.ts +2 -5
  58. package/connectors/firebase/src/tools.ts +106 -0
  59. package/connectors/flagsmith/src/server.ts +2 -98
  60. package/connectors/flagsmith/src/tools.ts +95 -0
  61. package/connectors/flux/src/server.ts +52 -53
  62. package/connectors/gcp/src/server.ts +2 -132
  63. package/connectors/gcp/src/tools.ts +123 -0
  64. package/connectors/github/src/server.ts +2 -328
  65. package/connectors/github/src/tools.ts +311 -0
  66. package/connectors/github-actions/src/server.ts +2 -205
  67. package/connectors/github-actions/src/tools.ts +209 -0
  68. package/connectors/gitlab/src/server.ts +2 -384
  69. package/connectors/gitlab/src/tools.ts +392 -0
  70. package/connectors/gmail/src/server.ts +2 -270
  71. package/connectors/gmail/src/tools.ts +209 -0
  72. package/connectors/google-drive/src/server.ts +2 -524
  73. package/connectors/google-drive/src/tools.ts +529 -0
  74. package/connectors/google-meet/src/server.ts +2 -82
  75. package/connectors/google-meet/src/tools.ts +87 -0
  76. package/connectors/google-photos/src/server.ts +2 -132
  77. package/connectors/google-photos/src/tools.ts +138 -0
  78. package/connectors/grafana/src/server.ts +2 -53
  79. package/connectors/grafana/src/tools.ts +53 -0
  80. package/connectors/great-expectations/src/gx-parse.ts +14 -45
  81. package/connectors/greenhouse/src/server.ts +2 -63
  82. package/connectors/greenhouse/src/tools.ts +68 -0
  83. package/connectors/hubspot/src/server.ts +2 -77
  84. package/connectors/hubspot/src/tools.ts +70 -0
  85. package/connectors/iac/src/server.ts +2 -137
  86. package/connectors/iac/src/tools.ts +152 -0
  87. package/connectors/imap/src/imap-core.ts +29 -82
  88. package/connectors/imap/src/server.ts +33 -220
  89. package/connectors/intercom/src/server.ts +2 -61
  90. package/connectors/intercom/src/tools.ts +58 -0
  91. package/connectors/jenkins/src/jenkins-api.ts +2 -6
  92. package/connectors/jenkins/src/server.ts +2 -215
  93. package/connectors/jenkins/src/tools.ts +240 -0
  94. package/connectors/jira/src/server.ts +2 -301
  95. package/connectors/jira/src/tools.ts +325 -0
  96. package/connectors/kubernetes/src/server.ts +2 -155
  97. package/connectors/kubernetes/src/tools.ts +159 -0
  98. package/connectors/launchdarkly/src/server.ts +2 -75
  99. package/connectors/launchdarkly/src/tools.ts +72 -0
  100. package/connectors/lever/src/search-filter.ts +4 -12
  101. package/connectors/lever/src/server.ts +2 -60
  102. package/connectors/lever/src/tools.ts +61 -0
  103. package/connectors/linear/src/server.ts +2 -459
  104. package/connectors/linear/src/tools.ts +482 -0
  105. package/connectors/localdb/src/sql-scan.ts +13 -41
  106. package/connectors/localdb/src/tools.ts +1 -1
  107. package/connectors/looker/src/search-filter.ts +2 -15
  108. package/connectors/looker/src/server.ts +35 -70
  109. package/connectors/mendeley/src/server.ts +2 -55
  110. package/connectors/mendeley/src/tools.ts +54 -0
  111. package/connectors/mercury/src/server.ts +2 -57
  112. package/connectors/mercury/src/tools.ts +50 -0
  113. package/connectors/metabase/src/search-filter.ts +4 -15
  114. package/connectors/metabase/src/server.ts +2 -79
  115. package/connectors/metabase/src/tools.ts +64 -0
  116. package/connectors/miro/src/server.ts +2 -72
  117. package/connectors/miro/src/tools.ts +65 -0
  118. package/connectors/mlflow/src/search-filter.ts +3 -7
  119. package/connectors/mlflow/src/server.ts +20 -40
  120. package/connectors/monte-carlo/src/server.ts +50 -57
  121. package/connectors/netlify/src/search-filter.ts +6 -14
  122. package/connectors/netlify/src/server.ts +2 -60
  123. package/connectors/netlify/src/tools.ts +53 -0
  124. package/connectors/newrelic/src/server.ts +2 -40
  125. package/connectors/newrelic/src/tools.ts +37 -0
  126. package/connectors/notion/src/server.ts +2 -335
  127. package/connectors/notion/src/tools.ts +344 -0
  128. package/connectors/obsidian/src/server.ts +2 -425
  129. package/connectors/obsidian/src/tools.ts +466 -0
  130. package/connectors/onedrive/src/server.ts +2 -249
  131. package/connectors/onedrive/src/tools.ts +253 -0
  132. package/connectors/outlook/src/server.ts +2 -351
  133. package/connectors/outlook/src/tools.ts +357 -0
  134. package/connectors/pagerduty/src/server.ts +2 -132
  135. package/connectors/pagerduty/src/tools.ts +126 -0
  136. package/connectors/pipedrive/src/server.ts +2 -58
  137. package/connectors/pipedrive/src/tools.ts +63 -0
  138. package/connectors/powerbi/src/search-filter.ts +2 -15
  139. package/connectors/powerbi/src/server.ts +43 -68
  140. package/connectors/prefect/src/search-filter.ts +3 -16
  141. package/connectors/prefect/src/server.ts +2 -90
  142. package/connectors/prefect/src/tools.ts +83 -0
  143. package/connectors/protonmail/src/mail-core.ts +16 -75
  144. package/connectors/protonmail/src/server.ts +34 -214
  145. package/connectors/raindrop/src/server.ts +2 -103
  146. package/connectors/raindrop/src/tools.ts +103 -0
  147. package/connectors/ramp/src/server.ts +2 -105
  148. package/connectors/ramp/src/tools.ts +98 -0
  149. package/connectors/readwise/src/server.ts +2 -88
  150. package/connectors/readwise/src/tools.ts +81 -0
  151. package/connectors/sagemaker/src/tools.ts +19 -38
  152. package/connectors/salesforce/src/search-filter.ts +4 -11
  153. package/connectors/salesforce/src/server.ts +2 -90
  154. package/connectors/salesforce/src/tools.ts +75 -0
  155. package/connectors/semgrep/src/search-filter.ts +3 -10
  156. package/connectors/semgrep/src/server.ts +2 -104
  157. package/connectors/semgrep/src/tools.ts +92 -0
  158. package/connectors/sentry/src/server.ts +2 -58
  159. package/connectors/sentry/src/tools.ts +53 -0
  160. package/connectors/slack/src/server.ts +2 -352
  161. package/connectors/slack/src/tools.ts +376 -0
  162. package/connectors/snowflake/src/search-filter.ts +4 -19
  163. package/connectors/snowflake/src/server.ts +6 -25
  164. package/connectors/snyk/src/server.ts +2 -140
  165. package/connectors/snyk/src/tools.ts +136 -0
  166. package/connectors/sonarqube/src/server.ts +2 -111
  167. package/connectors/sonarqube/src/tools.ts +98 -0
  168. package/connectors/stackoverflow/src/server.ts +2 -77
  169. package/connectors/stackoverflow/src/tools.ts +66 -0
  170. package/connectors/storybook/src/storybook-parse.ts +3 -6
  171. package/connectors/stripe/src/server.ts +2 -61
  172. package/connectors/stripe/src/tools.ts +54 -0
  173. package/connectors/superset/src/search-filter.ts +4 -15
  174. package/connectors/superset/src/server.ts +2 -115
  175. package/connectors/superset/src/tools.ts +98 -0
  176. package/connectors/tableau/src/search-filter.ts +2 -15
  177. package/connectors/tableau/src/server.ts +13 -65
  178. package/connectors/teams/src/server.ts +2 -249
  179. package/connectors/teams/src/tools.ts +283 -0
  180. package/connectors/testflight/src/server.ts +2 -70
  181. package/connectors/testflight/src/tools.ts +79 -0
  182. package/connectors/vercel/src/search-filter.ts +2 -10
  183. package/connectors/vercel/src/server.ts +2 -75
  184. package/connectors/vercel/src/tools.ts +73 -0
  185. package/connectors/vertex-ai/src/tools.ts +23 -33
  186. package/connectors/wiz/src/search-filter.ts +6 -30
  187. package/connectors/wiz/src/server.ts +2 -188
  188. package/connectors/wiz/src/tools.ts +168 -0
  189. package/connectors/zendesk/src/server.ts +2 -73
  190. package/connectors/zendesk/src/tools.ts +60 -0
  191. package/connectors/zoom/src/search-filter.ts +1 -7
  192. package/connectors/zoom/src/server.ts +2 -94
  193. package/connectors/zoom/src/tools.ts +93 -0
  194. package/connectors/zotero/src/server.ts +2 -78
  195. package/connectors/zotero/src/tools.ts +67 -0
  196. package/package.json +14 -12
  197. package/shared/access-token-cache.ts +123 -0
  198. package/shared/atlassian-json-fetch.ts +6 -16
  199. package/shared/audit-chain.ts +13 -6
  200. package/shared/cli-json-kit.ts +150 -0
  201. package/shared/collection-tool-kit.ts +143 -0
  202. package/shared/connector-mode.ts +3 -2
  203. package/shared/cursor-list-tool.ts +29 -0
  204. package/shared/env-json-api.ts +209 -0
  205. package/shared/fetch-json-text.ts +27 -0
  206. package/shared/github-rest.ts +62 -0
  207. package/shared/graphql-json.ts +60 -0
  208. package/shared/imap-mail-core.ts +91 -0
  209. package/shared/imap-tool-kit.ts +57 -23
  210. package/shared/imapflow-adapter.ts +417 -0
  211. package/shared/rest-tool-kit.ts +77 -7
  212. package/shared/run-cli-json.ts +38 -16
  213. package/shared/search-filter.ts +58 -18
  214. package/shared/walk-files.ts +118 -0
  215. package/standalone/src/launcher.ts +19 -7
@@ -1,467 +1,10 @@
1
1
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
2
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
- import { z } from "zod";
4
-
5
- import {
6
- createRegisterSimpleTool,
7
- createZodToolRegistrar,
8
- mcpJsonResult as jsonResult,
9
- requireProcessEnv,
10
- } from "../../../shared/mcp-tool-kit.ts";
11
-
12
- const LINEAR_GQL = "https://api.linear.app/graphql";
13
-
14
- type LinearGqlResponse<T> = {
15
- data?: T;
16
- errors?: ReadonlyArray<{ message: string }>;
17
- };
18
-
19
- async function linearGraphql<T>(
20
- apiKey: string,
21
- query: string,
22
- variables?: Record<string, unknown>,
23
- ): Promise<{ ok: true; data: T; text: string } | { ok: false; status: number; text: string }> {
24
- const res = await fetch(LINEAR_GQL, {
25
- method: "POST",
26
- headers: {
27
- "Content-Type": "application/json",
28
- Authorization: apiKey,
29
- },
30
- body: JSON.stringify({ query, variables }),
31
- });
32
- const text = await res.text();
33
- if (!res.ok) {
34
- return { ok: false, status: res.status, text };
35
- }
36
- let parsed: unknown;
37
- try {
38
- parsed = JSON.parse(text) as unknown;
39
- } catch {
40
- return { ok: false, status: res.status, text: "invalid JSON" };
41
- }
42
- const body = parsed as LinearGqlResponse<T>;
43
- if (body.errors !== undefined && body.errors.length > 0) {
44
- const msg = body.errors.map((e) => e.message).join("; ");
45
- throw new Error(`Linear GraphQL: ${msg.slice(0, 400)}`);
46
- }
47
- if (body.data === undefined) {
48
- throw new Error("Linear GraphQL: missing data");
49
- }
50
- return { ok: true, data: body.data, text };
51
- }
52
-
53
- function linearGqlData<T>(
54
- res: { ok: true; data: T; text: string } | { ok: false; status: number; text: string },
55
- ): T {
56
- if (!res.ok) {
57
- throw new Error(`Linear ${String(res.status)}: ${res.text.slice(0, 300)}`);
58
- }
59
- return res.data;
60
- }
3
+ import { registerLinearTools } from "./tools.ts";
61
4
 
62
5
  const server = new McpServer({ name: "nimbus-linear", version: "0.1.0" });
63
6
 
64
- const registerSimpleTool = createRegisterSimpleTool(server);
65
-
66
- import { createWriteToolRegistrar } from "../../../shared/consent-kit.ts";
67
-
68
- const reg = createZodToolRegistrar(registerSimpleTool);
69
-
70
- /**
71
- * Every MUTATING linear tool goes through here. Outside the gateway this adds the
72
- * consent gate, the write-scope allow-list, the mutation budget and the audit record; inside
73
- * the gateway it is a pass-through, because executor.ts (I2) is the gate there.
74
- */
75
- const registerWriteTool = createWriteToolRegistrar(server, {
76
- connector: "linear",
77
- scopeEnv: "NIMBUS_MCP_LINEAR_WRITE_SCOPE",
78
- scopeKinds: ["team", "issue"],
79
- });
80
-
81
- const linearIssueListSchema = z.object({
82
- first: z.number().int().min(1).max(100).optional(),
83
- teamId: z.string().min(1).optional(),
84
- stateName: z.string().min(1).optional(),
85
- assigneeId: z.string().min(1).optional(),
86
- });
87
-
88
- reg(
89
- "linear_issue_list",
90
- "List Linear issues with optional filters (team id, state name, assignee id).",
91
- linearIssueListSchema,
92
- async (parsed) => {
93
- const apiKey = requireProcessEnv("LINEAR_API_KEY");
94
- const filter: Record<string, unknown> = {};
95
- if (parsed.teamId !== undefined) {
96
- filter["team"] = { id: { eq: parsed.teamId } };
97
- }
98
- if (parsed.stateName !== undefined) {
99
- filter["state"] = { name: { eq: parsed.stateName } };
100
- }
101
- if (parsed.assigneeId !== undefined) {
102
- filter["assignee"] = { id: { eq: parsed.assigneeId } };
103
- }
104
- const hasFilter = Object.keys(filter).length > 0;
105
- const q = hasFilter
106
- ? `
107
- query IssueList($first: Int!, $filter: IssueFilter!) {
108
- issues(first: $first, filter: $filter, orderBy: updatedAt) {
109
- nodes {
110
- id
111
- identifier
112
- title
113
- updatedAt
114
- url
115
- state { id name type }
116
- team { id name key }
117
- }
118
- }
119
- }
120
- `
121
- : `
122
- query IssueList($first: Int!) {
123
- issues(first: $first, orderBy: updatedAt) {
124
- nodes {
125
- id
126
- identifier
127
- title
128
- updatedAt
129
- url
130
- state { id name type }
131
- team { id name key }
132
- }
133
- }
134
- }
135
- `;
136
- type Out = {
137
- issues: {
138
- nodes: ReadonlyArray<Record<string, unknown>>;
139
- };
140
- };
141
- const vars: Record<string, unknown> = { first: parsed.first ?? 50 };
142
- if (hasFilter) {
143
- vars["filter"] = filter;
144
- }
145
- const res = await linearGraphql<Out>(apiKey, q, vars);
146
- return jsonResult(linearGqlData(res));
147
- },
148
- );
149
-
150
- const linearIssueIdSchema = z.object({ issueId: z.string().min(1) });
151
-
152
- reg(
153
- "linear_issue_get",
154
- "Get a single Linear issue by UUID id.",
155
- linearIssueIdSchema,
156
- async (parsed) => {
157
- const apiKey = requireProcessEnv("LINEAR_API_KEY");
158
- const q = `
159
- query IssueGet($id: String!) {
160
- issue(id: $id) {
161
- id
162
- identifier
163
- title
164
- description
165
- updatedAt
166
- createdAt
167
- url
168
- priority
169
- state { id name type }
170
- team { id name key }
171
- assignee { id name displayName }
172
- }
173
- }
174
- `;
175
- type Out = { issue: Record<string, unknown> | null };
176
- const res = await linearGraphql<Out>(apiKey, q, { id: parsed.issueId });
177
- return jsonResult(linearGqlData(res));
178
- },
179
- );
180
-
181
- const linearIssueCreateSchema = z.object({
182
- teamId: z.string().min(1),
183
- title: z.string().min(1),
184
- description: z.string().optional(),
185
- priority: z.number().int().min(0).max(4).optional(),
186
- stateId: z.string().min(1).optional(),
187
- assigneeId: z.string().min(1).optional(),
188
- });
189
-
190
- registerWriteTool(
191
- "linear_issue_create",
192
- {
193
- mutates: "linear.issue.create",
194
- recoverable: true,
195
- scopeTargetOf: (p) => ({ kind: "team", value: p.teamId }),
196
- },
197
- "Create a Linear issue (requires teamId and title).",
198
- linearIssueCreateSchema,
199
- async (parsed) => {
200
- const apiKey = requireProcessEnv("LINEAR_API_KEY");
201
- const input: Record<string, unknown> = {
202
- teamId: parsed.teamId,
203
- title: parsed.title,
204
- };
205
- if (parsed.description !== undefined) {
206
- input["description"] = parsed.description;
207
- }
208
- if (parsed.priority !== undefined) {
209
- input["priority"] = parsed.priority;
210
- }
211
- if (parsed.stateId !== undefined) {
212
- input["stateId"] = parsed.stateId;
213
- }
214
- if (parsed.assigneeId !== undefined) {
215
- input["assigneeId"] = parsed.assigneeId;
216
- }
217
- const q = `
218
- mutation IssueCreate($input: IssueCreateInput!) {
219
- issueCreate(input: $input) {
220
- success
221
- issue { id identifier url title }
222
- }
223
- }
224
- `;
225
- type Out = { issueCreate: { success: boolean; issue: Record<string, unknown> | null } };
226
- const res = await linearGraphql<Out>(apiKey, q, { input });
227
- return jsonResult(linearGqlData(res));
228
- },
229
- );
230
-
231
- const linearIssueUpdateSchema = z.object({
232
- issueId: z.string().min(1),
233
- title: z.string().min(1).optional(),
234
- description: z.string().optional(),
235
- stateId: z.string().min(1).optional(),
236
- priority: z.number().int().min(0).max(4).optional(),
237
- assigneeId: z.string().min(1).optional(),
238
- });
239
-
240
- registerWriteTool(
241
- "linear_issue_update",
242
- {
243
- mutates: "linear.issue.update",
244
- recoverable: true,
245
- scopeTargetOf: (p) => ({ kind: "issue", value: p.issueId }),
246
- },
247
- "Update a Linear issue by id.",
248
- linearIssueUpdateSchema,
249
- async (parsed) => {
250
- const apiKey = requireProcessEnv("LINEAR_API_KEY");
251
- const input: Record<string, unknown> = {};
252
- if (parsed.title !== undefined) {
253
- input["title"] = parsed.title;
254
- }
255
- if (parsed.description !== undefined) {
256
- input["description"] = parsed.description;
257
- }
258
- if (parsed.stateId !== undefined) {
259
- input["stateId"] = parsed.stateId;
260
- }
261
- if (parsed.priority !== undefined) {
262
- input["priority"] = parsed.priority;
263
- }
264
- if (parsed.assigneeId !== undefined) {
265
- input["assigneeId"] = parsed.assigneeId;
266
- }
267
- const q = `
268
- mutation IssueUpdate($id: String!, $input: IssueUpdateInput!) {
269
- issueUpdate(id: $id, input: $input) {
270
- success
271
- issue { id identifier url title updatedAt }
272
- }
273
- }
274
- `;
275
- type Out = {
276
- issueUpdate: { success: boolean; issue: Record<string, unknown> | null };
277
- };
278
- const res = await linearGraphql<Out>(apiKey, q, {
279
- id: parsed.issueId,
280
- input,
281
- });
282
- return jsonResult(linearGqlData(res));
283
- },
284
- );
285
-
286
- const linearCommentCreateSchema = z.object({
287
- issueId: z.string().min(1),
288
- body: z.string().min(1),
289
- });
290
-
291
- registerWriteTool(
292
- "linear_comment_create",
293
- {
294
- mutates: "linear.comment.create",
295
- recoverable: true,
296
- scopeTargetOf: (p) => ({ kind: "issue", value: p.issueId }),
297
- },
298
- "Add a comment to a Linear issue.",
299
- linearCommentCreateSchema,
300
- async (parsed) => {
301
- const apiKey = requireProcessEnv("LINEAR_API_KEY");
302
- const q = `
303
- mutation CommentCreate($input: CommentCreateInput!) {
304
- commentCreate(input: $input) {
305
- success
306
- comment { id body createdAt }
307
- }
308
- }
309
- `;
310
- type Out = {
311
- commentCreate: { success: boolean; comment: Record<string, unknown> | null };
312
- };
313
- const res = await linearGraphql<Out>(apiKey, q, {
314
- input: { issueId: parsed.issueId, body: parsed.body },
315
- });
316
- return jsonResult(linearGqlData(res));
317
- },
318
- );
319
-
320
- const linearFirstOptionalSchema = z.object({
321
- first: z.number().int().min(1).max(100).optional(),
322
- });
323
-
324
- reg("linear_project_list", "List Linear projects.", linearFirstOptionalSchema, async (parsed) => {
325
- const apiKey = requireProcessEnv("LINEAR_API_KEY");
326
- const q = `
327
- query ProjectList($first: Int!) {
328
- projects(first: $first) {
329
- nodes {
330
- id
331
- name
332
- description
333
- slugId
334
- url
335
- updatedAt
336
- state
337
- }
338
- }
339
- }
340
- `;
341
- type Out = { projects: { nodes: ReadonlyArray<Record<string, unknown>> } };
342
- const res = await linearGraphql<Out>(apiKey, q, { first: parsed.first ?? 50 });
343
- return jsonResult(linearGqlData(res));
344
- });
345
-
346
- const linearProjectIdSchema = z.object({ projectId: z.string().min(1) });
347
-
348
- reg("linear_project_get", "Get a Linear project by id.", linearProjectIdSchema, async (parsed) => {
349
- const apiKey = requireProcessEnv("LINEAR_API_KEY");
350
- const q = `
351
- query ProjectGet($id: String!) {
352
- project(id: $id) {
353
- id
354
- name
355
- description
356
- slugId
357
- url
358
- updatedAt
359
- state
360
- lead { id displayName }
361
- }
362
- }
363
- `;
364
- type Out = { project: Record<string, unknown> | null };
365
- const res = await linearGraphql<Out>(apiKey, q, { id: parsed.projectId });
366
- return jsonResult(linearGqlData(res));
367
- });
368
-
369
- const linearCycleListSchema = z.object({
370
- teamId: z.string().min(1),
371
- first: z.number().int().min(1).max(50).optional(),
372
- });
373
-
374
- reg(
375
- "linear_cycle_list",
376
- "List Linear cycles for a team.",
377
- linearCycleListSchema,
378
- async (parsed) => {
379
- const apiKey = requireProcessEnv("LINEAR_API_KEY");
380
- const q = `
381
- query CycleList($teamId: ID!, $first: Int!) {
382
- team(id: $teamId) {
383
- id
384
- cycles(first: $first) {
385
- nodes {
386
- id
387
- name
388
- number
389
- startsAt
390
- endsAt
391
- completedAt
392
- }
393
- }
394
- }
395
- }
396
- `;
397
- type Out = {
398
- team: {
399
- id: string;
400
- cycles: { nodes: ReadonlyArray<Record<string, unknown>> };
401
- } | null;
402
- };
403
- const res = await linearGraphql<Out>(apiKey, q, {
404
- teamId: parsed.teamId,
405
- first: parsed.first ?? 20,
406
- });
407
- return jsonResult(linearGqlData(res));
408
- },
409
- );
410
-
411
- const linearRoadmapFirstSchema = z.object({
412
- first: z.number().int().min(1).max(50).optional(),
413
- });
414
-
415
- reg(
416
- "linear_roadmap_list",
417
- "List Linear initiatives (roadmap).",
418
- linearRoadmapFirstSchema,
419
- async (parsed) => {
420
- const apiKey = requireProcessEnv("LINEAR_API_KEY");
421
- const q = `
422
- query InitiativeList($first: Int!) {
423
- initiatives(first: $first) {
424
- nodes {
425
- id
426
- name
427
- description
428
- targetDate
429
- updatedAt
430
- url
431
- }
432
- }
433
- }
434
- `;
435
- type Out = { initiatives: { nodes: ReadonlyArray<Record<string, unknown>> } };
436
- const res = await linearGraphql<Out>(apiKey, q, { first: parsed.first ?? 30 });
437
- return jsonResult(linearGqlData(res));
438
- },
439
- );
440
-
441
- reg(
442
- "linear_member_list",
443
- "List users in the workspace.",
444
- linearFirstOptionalSchema,
445
- async (parsed) => {
446
- const apiKey = requireProcessEnv("LINEAR_API_KEY");
447
- const q = `
448
- query Users($first: Int!) {
449
- users(first: $first) {
450
- nodes {
451
- id
452
- name
453
- displayName
454
- email
455
- active
456
- }
457
- }
458
- }
459
- `;
460
- type Out = { users: { nodes: ReadonlyArray<Record<string, unknown>> } };
461
- const res = await linearGraphql<Out>(apiKey, q, { first: parsed.first ?? 50 });
462
- return jsonResult(linearGqlData(res));
463
- },
464
- );
7
+ registerLinearTools(server);
465
8
 
466
9
  const transport = new StdioServerTransport();
467
10
  await server.connect(transport);