@morphixai/mcp-server 0.3.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.
@@ -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,323 @@
1
+ #!/usr/bin/env node
2
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
3
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import { CallToolRequestSchema, ListToolsRequestSchema, ErrorCode, McpError, } from "@modelcontextprotocol/sdk/types.js";
5
+ import { MorphixClient, GitHubClient, GitLabClient, JiraClient, OfficeGitHubSchema, OfficeGitLabSchema, OfficeJiraSchema, } from "@morphixai/core";
6
+ // --- Helpers ---
7
+ const API_KEY_GUIDE_URL = "https://morphix.app/api-keys";
8
+ const CONNECTIONS_URL = "https://morphix.app/connections";
9
+ class AppNotConnectedError extends Error {
10
+ appSlug;
11
+ constructor(appSlug) {
12
+ super(`No ${appSlug} account connected. Visit ${CONNECTIONS_URL} to link your ${appSlug} account.`);
13
+ this.appSlug = appSlug;
14
+ this.name = "AppNotConnectedError";
15
+ }
16
+ }
17
+ async function resolveAppAccount(client, appSlug, accountId) {
18
+ if (accountId)
19
+ return accountId;
20
+ const accounts = await client.listAccounts(appSlug, true);
21
+ if (accounts.length === 0) {
22
+ throw new AppNotConnectedError(appSlug);
23
+ }
24
+ const active = accounts.find((a) => a.isActive) || accounts[0];
25
+ return active.accountId;
26
+ }
27
+ // --- Server Setup ---
28
+ const server = new Server({
29
+ name: "morphixai-mcp",
30
+ version: "0.1.0",
31
+ }, {
32
+ capabilities: {
33
+ tools: {},
34
+ },
35
+ });
36
+ const API_KEY = process.env.MORPHIXAI_API_KEY;
37
+ if (!API_KEY) {
38
+ console.error("MORPHIXAI_API_KEY environment variable is required.");
39
+ console.error(`Visit ${API_KEY_GUIDE_URL} to get your API Key.`);
40
+ process.exit(1);
41
+ }
42
+ const morphixClient = new MorphixClient({ apiKey: API_KEY, baseUrl: process.env.MORPHIXAI_BASE_URL });
43
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
44
+ return {
45
+ tools: [
46
+ {
47
+ name: "mx_github",
48
+ description: "GitHub integration: list repos, issues, pull requests, workflow runs. Create issues/PRs, update issues, trigger workflows.",
49
+ inputSchema: OfficeGitHubSchema,
50
+ },
51
+ {
52
+ name: "mx_gitlab",
53
+ description: "GitLab integration: manage projects, MRs, issues, and pipelines. Use format 'group/project' for project_id.",
54
+ inputSchema: OfficeGitLabSchema,
55
+ },
56
+ {
57
+ name: "mx_jira",
58
+ description: "Jira integration: list projects, search issues (JQL), create/update issues, transition issues, add comments.",
59
+ inputSchema: OfficeJiraSchema,
60
+ },
61
+ ],
62
+ };
63
+ });
64
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
65
+ const { name, arguments: args } = request.params;
66
+ try {
67
+ switch (name) {
68
+ case "mx_github": {
69
+ const p = args;
70
+ const accountId = await resolveAppAccount(morphixClient, "github", p.account_id);
71
+ const github = new GitHubClient(morphixClient, accountId);
72
+ let result;
73
+ switch (p.action) {
74
+ case "get_user":
75
+ result = await github.getCurrentUser();
76
+ break;
77
+ case "list_repos":
78
+ result = await github.listRepos({
79
+ sort: p.sort,
80
+ type: p.type,
81
+ perPage: p.per_page,
82
+ page: p.page,
83
+ });
84
+ break;
85
+ case "get_repo":
86
+ result = await github.getRepo(p.repo);
87
+ break;
88
+ case "list_issues":
89
+ result = await github.listIssues(p.repo, {
90
+ state: p.state,
91
+ labels: p.labels,
92
+ perPage: p.per_page,
93
+ page: p.page,
94
+ });
95
+ break;
96
+ case "create_issue":
97
+ result = await github.createIssue(p.repo, {
98
+ title: p.title,
99
+ body: p.body,
100
+ labels: p.labels,
101
+ assignees: p.assignees,
102
+ });
103
+ break;
104
+ case "update_issue":
105
+ result = await github.updateIssue(p.repo, p.issue_number, {
106
+ title: p.title,
107
+ body: p.body,
108
+ state: p.state,
109
+ labels: p.labels,
110
+ });
111
+ break;
112
+ case "list_pulls":
113
+ result = await github.listPulls(p.repo, {
114
+ state: p.state,
115
+ perPage: p.per_page,
116
+ page: p.page,
117
+ });
118
+ break;
119
+ case "create_pull":
120
+ result = await github.createPull(p.repo, {
121
+ title: p.title,
122
+ head: p.head,
123
+ base: p.base,
124
+ body: p.body,
125
+ });
126
+ break;
127
+ case "list_workflow_runs":
128
+ result = await github.listWorkflowRuns(p.repo, {
129
+ status: p.status,
130
+ perPage: p.per_page,
131
+ });
132
+ break;
133
+ case "trigger_workflow":
134
+ await github.triggerWorkflow(p.repo, p.workflow_id, p.ref, p.inputs);
135
+ result = { success: true, repo: p.repo, workflow_id: p.workflow_id, ref: p.ref };
136
+ break;
137
+ default:
138
+ throw new McpError(ErrorCode.InvalidParams, `Unknown GitHub action: ${args.action}`);
139
+ }
140
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
141
+ }
142
+ case "mx_gitlab": {
143
+ const p = args;
144
+ const accountId = await resolveAppAccount(morphixClient, "gitlab", p.account_id);
145
+ const gitlab = new GitLabClient(morphixClient, accountId);
146
+ let result;
147
+ switch (p.action) {
148
+ case "get_user":
149
+ result = await gitlab.getCurrentUser();
150
+ break;
151
+ case "list_projects":
152
+ result = await gitlab.listProjects({
153
+ search: p.search,
154
+ perPage: p.per_page,
155
+ page: p.page,
156
+ orderBy: p.order_by,
157
+ sort: p.sort,
158
+ });
159
+ break;
160
+ case "get_project":
161
+ result = await gitlab.getProject(p.project);
162
+ break;
163
+ case "get_merge_request":
164
+ result = await gitlab.getMergeRequest(p.project, p.mr_iid);
165
+ break;
166
+ case "list_merge_requests":
167
+ result = await gitlab.listMergeRequests(p.project, {
168
+ state: p.state,
169
+ perPage: p.per_page,
170
+ page: p.page,
171
+ });
172
+ break;
173
+ case "create_merge_request":
174
+ result = await gitlab.createMergeRequest(p.project, {
175
+ sourceBranch: p.source_branch,
176
+ targetBranch: p.target_branch,
177
+ title: p.title,
178
+ description: p.description,
179
+ });
180
+ break;
181
+ case "approve_merge_request":
182
+ await gitlab.approveMergeRequest(p.project, p.mr_iid);
183
+ result = { success: true, project: p.project, mr_iid: p.mr_iid };
184
+ break;
185
+ case "merge_merge_request":
186
+ result = await gitlab.mergeMergeRequest(p.project, p.mr_iid);
187
+ break;
188
+ case "list_issues":
189
+ result = await gitlab.listIssues(p.project, {
190
+ state: p.state,
191
+ labels: p.labels,
192
+ perPage: p.per_page,
193
+ page: p.page,
194
+ });
195
+ break;
196
+ case "create_issue":
197
+ result = await gitlab.createIssue(p.project, {
198
+ title: p.title,
199
+ description: p.description,
200
+ labels: p.labels,
201
+ assigneeIds: p.assignee_ids,
202
+ });
203
+ break;
204
+ case "list_pipelines":
205
+ result = await gitlab.listPipelines(p.project, {
206
+ status: p.status,
207
+ ref: p.ref,
208
+ perPage: p.per_page,
209
+ });
210
+ break;
211
+ case "retry_pipeline":
212
+ result = await gitlab.retryPipeline(p.project, p.pipeline_id);
213
+ break;
214
+ case "update_merge_request":
215
+ result = await gitlab.updateMergeRequest(p.project, p.mr_iid, {
216
+ title: p.title,
217
+ description: p.description,
218
+ targetBranch: p.target_branch,
219
+ reviewerIds: p.reviewer_ids,
220
+ assigneeIds: p.assignee_ids,
221
+ labels: p.labels,
222
+ });
223
+ break;
224
+ case "search_users":
225
+ result = await gitlab.searchUsers({ search: p.search, perPage: p.per_page });
226
+ break;
227
+ case "list_branches":
228
+ result = await gitlab.listBranches(p.project, {
229
+ search: p.search,
230
+ perPage: p.per_page,
231
+ });
232
+ break;
233
+ default:
234
+ throw new McpError(ErrorCode.InvalidParams, `Unknown GitLab action: ${args.action}`);
235
+ }
236
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
237
+ }
238
+ case "mx_jira": {
239
+ const p = args;
240
+ const accountId = await resolveAppAccount(morphixClient, "jira", p.account_id);
241
+ const jira = new JiraClient(morphixClient, accountId);
242
+ let result;
243
+ switch (p.action) {
244
+ case "get_myself":
245
+ result = await jira.getMyself();
246
+ break;
247
+ case "list_projects":
248
+ result = await jira.listProjects({
249
+ query: p.query,
250
+ maxResults: p.max_results,
251
+ });
252
+ break;
253
+ case "search_issues":
254
+ result = await jira.searchIssues(p.jql, {
255
+ maxResults: p.max_results,
256
+ fields: p.fields,
257
+ });
258
+ break;
259
+ case "get_issue":
260
+ result = await jira.getIssue(p.issue_key, p.fields);
261
+ break;
262
+ case "create_issue":
263
+ result = await jira.createIssue({
264
+ project: p.project,
265
+ summary: p.summary,
266
+ issueType: p.issue_type,
267
+ description: p.description,
268
+ assigneeAccountId: p.assignee_account_id,
269
+ priority: p.priority,
270
+ labels: p.labels,
271
+ duedate: p.duedate,
272
+ });
273
+ break;
274
+ case "update_issue":
275
+ await jira.updateIssue(p.issue_key, p.fields);
276
+ result = { success: true, issue_key: p.issue_key };
277
+ break;
278
+ case "transition_issue":
279
+ await jira.transitionIssue(p.issue_key, p.target_status);
280
+ result = {
281
+ success: true,
282
+ issue_key: p.issue_key,
283
+ target_status: p.target_status,
284
+ };
285
+ break;
286
+ case "get_transitions":
287
+ result = await jira.getTransitions(p.issue_key);
288
+ break;
289
+ case "add_comment":
290
+ result = await jira.addComment(p.issue_key, p.body);
291
+ break;
292
+ default:
293
+ throw new McpError(ErrorCode.InvalidParams, `Unknown Jira action: ${args.action}`);
294
+ }
295
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
296
+ }
297
+ default:
298
+ throw new McpError(ErrorCode.MethodNotFound, `Tool not found: ${name}`);
299
+ }
300
+ }
301
+ catch (err) {
302
+ if (err instanceof AppNotConnectedError) {
303
+ return {
304
+ content: [{ type: "text", text: `Error: ${err.message}\nAction required: Connect your account at ${CONNECTIONS_URL}` }],
305
+ isError: true,
306
+ };
307
+ }
308
+ return {
309
+ content: [{ type: "text", text: `Error: ${err instanceof Error ? err.message : String(err)}` }],
310
+ isError: true,
311
+ };
312
+ }
313
+ });
314
+ async function main() {
315
+ const transport = new StdioServerTransport();
316
+ await server.connect(transport);
317
+ console.error("MorphixAI MCP Server running on stdio");
318
+ }
319
+ main().catch((err) => {
320
+ console.error("Server error:", err);
321
+ process.exit(1);
322
+ });
323
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,22 @@
1
+ {
2
+ "name": "@morphixai/mcp-server",
3
+ "version": "0.3.0",
4
+ "type": "module",
5
+ "description": "MorphixAI MCP Server (for Claude Code, Cursor, etc.)",
6
+ "main": "./dist/index.js",
7
+ "bin": {
8
+ "morphix-mcp": "./dist/index.js"
9
+ },
10
+ "scripts": {
11
+ "build": "tsc",
12
+ "start": "node dist/index.js"
13
+ },
14
+ "dependencies": {
15
+ "@modelcontextprotocol/sdk": "^1.0.0",
16
+ "@morphixai/core": "workspace:*"
17
+ },
18
+ "devDependencies": {
19
+ "@types/node": "^25.3.5",
20
+ "typescript": "^5.3.0"
21
+ }
22
+ }
package/src/index.ts ADDED
@@ -0,0 +1,366 @@
1
+ #!/usr/bin/env node
2
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
3
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import {
5
+ CallToolRequestSchema,
6
+ ListToolsRequestSchema,
7
+ ErrorCode,
8
+ McpError,
9
+ } from "@modelcontextprotocol/sdk/types.js";
10
+
11
+ import {
12
+ MorphixClient,
13
+ GitHubClient,
14
+ GitLabClient,
15
+ JiraClient,
16
+ OfficeGitHubSchema,
17
+ OfficeGitLabSchema,
18
+ OfficeJiraSchema,
19
+ type OfficeGitHubParams,
20
+ type OfficeGitLabParams,
21
+ type OfficeJiraParams,
22
+ } from "@morphixai/core";
23
+
24
+ // --- Helpers ---
25
+ const API_KEY_GUIDE_URL = "https://morphix.app/api-keys";
26
+ const CONNECTIONS_URL = "https://morphix.app/connections";
27
+
28
+ class AppNotConnectedError extends Error {
29
+ constructor(public readonly appSlug: string) {
30
+ super(
31
+ `No ${appSlug} account connected. Visit ${CONNECTIONS_URL} to link your ${appSlug} account.`,
32
+ );
33
+ this.name = "AppNotConnectedError";
34
+ }
35
+ }
36
+
37
+ async function resolveAppAccount(
38
+ client: MorphixClient,
39
+ appSlug: string,
40
+ accountId?: string,
41
+ ): Promise<string> {
42
+ if (accountId) return accountId;
43
+
44
+ const accounts = await client.listAccounts(appSlug, true);
45
+ if (accounts.length === 0) {
46
+ throw new AppNotConnectedError(appSlug);
47
+ }
48
+ const active = accounts.find((a) => a.isActive) || accounts[0];
49
+ return active.accountId;
50
+ }
51
+
52
+ // --- Server Setup ---
53
+ const server = new Server(
54
+ {
55
+ name: "morphixai-mcp",
56
+ version: "0.1.0",
57
+ },
58
+ {
59
+ capabilities: {
60
+ tools: {},
61
+ },
62
+ },
63
+ );
64
+
65
+ const API_KEY = process.env.MORPHIXAI_API_KEY;
66
+
67
+ if (!API_KEY) {
68
+ console.error("MORPHIXAI_API_KEY environment variable is required.");
69
+ console.error(`Visit ${API_KEY_GUIDE_URL} to get your API Key.`);
70
+ process.exit(1);
71
+ }
72
+
73
+ const morphixClient = new MorphixClient({ apiKey: API_KEY, baseUrl: process.env.MORPHIXAI_BASE_URL });
74
+
75
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
76
+ return {
77
+ tools: [
78
+ {
79
+ name: "mx_github",
80
+ description:
81
+ "GitHub integration: list repos, issues, pull requests, workflow runs. Create issues/PRs, update issues, trigger workflows.",
82
+ inputSchema: OfficeGitHubSchema as never,
83
+ },
84
+ {
85
+ name: "mx_gitlab",
86
+ description:
87
+ "GitLab integration: manage projects, MRs, issues, and pipelines. Use format 'group/project' for project_id.",
88
+ inputSchema: OfficeGitLabSchema as never,
89
+ },
90
+ {
91
+ name: "mx_jira",
92
+ description:
93
+ "Jira integration: list projects, search issues (JQL), create/update issues, transition issues, add comments.",
94
+ inputSchema: OfficeJiraSchema as never,
95
+ },
96
+ ],
97
+ };
98
+ });
99
+
100
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
101
+ const { name, arguments: args } = request.params;
102
+
103
+ try {
104
+ switch (name) {
105
+ case "mx_github": {
106
+ const p = args as unknown as OfficeGitHubParams;
107
+ const accountId = await resolveAppAccount(morphixClient, "github", p.account_id);
108
+ const github = new GitHubClient(morphixClient, accountId);
109
+
110
+ let result;
111
+ switch (p.action) {
112
+ case "get_user":
113
+ result = await github.getCurrentUser();
114
+ break;
115
+ case "list_repos":
116
+ result = await github.listRepos({
117
+ sort: p.sort,
118
+ type: p.type,
119
+ perPage: p.per_page,
120
+ page: p.page,
121
+ });
122
+ break;
123
+ case "get_repo":
124
+ result = await github.getRepo(p.repo);
125
+ break;
126
+ case "list_issues":
127
+ result = await github.listIssues(p.repo, {
128
+ state: p.state,
129
+ labels: p.labels,
130
+ perPage: p.per_page,
131
+ page: p.page,
132
+ });
133
+ break;
134
+ case "create_issue":
135
+ result = await github.createIssue(p.repo, {
136
+ title: p.title,
137
+ body: p.body,
138
+ labels: p.labels,
139
+ assignees: p.assignees,
140
+ });
141
+ break;
142
+ case "update_issue":
143
+ result = await github.updateIssue(p.repo, p.issue_number, {
144
+ title: p.title,
145
+ body: p.body,
146
+ state: p.state,
147
+ labels: p.labels,
148
+ });
149
+ break;
150
+ case "list_pulls":
151
+ result = await github.listPulls(p.repo, {
152
+ state: p.state,
153
+ perPage: p.per_page,
154
+ page: p.page,
155
+ });
156
+ break;
157
+ case "create_pull":
158
+ result = await github.createPull(p.repo, {
159
+ title: p.title,
160
+ head: p.head,
161
+ base: p.base,
162
+ body: p.body,
163
+ });
164
+ break;
165
+ case "list_workflow_runs":
166
+ result = await github.listWorkflowRuns(p.repo, {
167
+ status: p.status,
168
+ perPage: p.per_page,
169
+ });
170
+ break;
171
+ case "trigger_workflow":
172
+ await github.triggerWorkflow(p.repo, p.workflow_id, p.ref, p.inputs);
173
+ result = { success: true, repo: p.repo, workflow_id: p.workflow_id, ref: p.ref };
174
+ break;
175
+ default:
176
+ throw new McpError(ErrorCode.InvalidParams, `Unknown GitHub action: ${(args as { action?: string }).action}`);
177
+ }
178
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
179
+ }
180
+
181
+ case "mx_gitlab": {
182
+ const p = args as unknown as OfficeGitLabParams;
183
+ const accountId = await resolveAppAccount(morphixClient, "gitlab", p.account_id);
184
+ const gitlab = new GitLabClient(morphixClient, accountId);
185
+
186
+ let result;
187
+ switch (p.action) {
188
+ case "get_user":
189
+ result = await gitlab.getCurrentUser();
190
+ break;
191
+ case "list_projects":
192
+ result = await gitlab.listProjects({
193
+ search: p.search,
194
+ perPage: p.per_page,
195
+ page: p.page,
196
+ orderBy: p.order_by,
197
+ sort: p.sort,
198
+ });
199
+ break;
200
+ case "get_project":
201
+ result = await gitlab.getProject(p.project);
202
+ break;
203
+ case "get_merge_request":
204
+ result = await gitlab.getMergeRequest(p.project, p.mr_iid);
205
+ break;
206
+ case "list_merge_requests":
207
+ result = await gitlab.listMergeRequests(p.project, {
208
+ state: p.state,
209
+ perPage: p.per_page,
210
+ page: p.page,
211
+ });
212
+ break;
213
+ case "create_merge_request":
214
+ result = await gitlab.createMergeRequest(p.project, {
215
+ sourceBranch: p.source_branch,
216
+ targetBranch: p.target_branch,
217
+ title: p.title,
218
+ description: p.description,
219
+ });
220
+ break;
221
+ case "approve_merge_request":
222
+ await gitlab.approveMergeRequest(p.project, p.mr_iid);
223
+ result = { success: true, project: p.project, mr_iid: p.mr_iid };
224
+ break;
225
+ case "merge_merge_request":
226
+ result = await gitlab.mergeMergeRequest(p.project, p.mr_iid);
227
+ break;
228
+ case "list_issues":
229
+ result = await gitlab.listIssues(p.project, {
230
+ state: p.state,
231
+ labels: p.labels,
232
+ perPage: p.per_page,
233
+ page: p.page,
234
+ });
235
+ break;
236
+ case "create_issue":
237
+ result = await gitlab.createIssue(p.project, {
238
+ title: p.title,
239
+ description: p.description,
240
+ labels: p.labels,
241
+ assigneeIds: p.assignee_ids,
242
+ });
243
+ break;
244
+ case "list_pipelines":
245
+ result = await gitlab.listPipelines(p.project, {
246
+ status: p.status,
247
+ ref: p.ref,
248
+ perPage: p.per_page,
249
+ });
250
+ break;
251
+ case "retry_pipeline":
252
+ result = await gitlab.retryPipeline(p.project, p.pipeline_id);
253
+ break;
254
+ case "update_merge_request":
255
+ result = await gitlab.updateMergeRequest(p.project, p.mr_iid, {
256
+ title: p.title,
257
+ description: p.description,
258
+ targetBranch: p.target_branch,
259
+ reviewerIds: p.reviewer_ids,
260
+ assigneeIds: p.assignee_ids,
261
+ labels: p.labels,
262
+ });
263
+ break;
264
+ case "search_users":
265
+ result = await gitlab.searchUsers({ search: p.search, perPage: p.per_page });
266
+ break;
267
+ case "list_branches":
268
+ result = await gitlab.listBranches(p.project, {
269
+ search: p.search,
270
+ perPage: p.per_page,
271
+ });
272
+ break;
273
+ default:
274
+ throw new McpError(ErrorCode.InvalidParams, `Unknown GitLab action: ${(args as { action?: string }).action}`);
275
+ }
276
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
277
+ }
278
+
279
+ case "mx_jira": {
280
+ const p = args as unknown as OfficeJiraParams;
281
+ const accountId = await resolveAppAccount(morphixClient, "jira", p.account_id);
282
+ const jira = new JiraClient(morphixClient, accountId);
283
+
284
+ let result;
285
+ switch (p.action) {
286
+ case "get_myself":
287
+ result = await jira.getMyself();
288
+ break;
289
+ case "list_projects":
290
+ result = await jira.listProjects({
291
+ query: p.query,
292
+ maxResults: p.max_results,
293
+ });
294
+ break;
295
+ case "search_issues":
296
+ result = await jira.searchIssues(p.jql, {
297
+ maxResults: p.max_results,
298
+ fields: p.fields,
299
+ });
300
+ break;
301
+ case "get_issue":
302
+ result = await jira.getIssue(p.issue_key, p.fields);
303
+ break;
304
+ case "create_issue":
305
+ result = await jira.createIssue({
306
+ project: p.project,
307
+ summary: p.summary,
308
+ issueType: p.issue_type,
309
+ description: p.description,
310
+ assigneeAccountId: p.assignee_account_id,
311
+ priority: p.priority,
312
+ labels: p.labels,
313
+ duedate: p.duedate,
314
+ });
315
+ break;
316
+ case "update_issue":
317
+ await jira.updateIssue(p.issue_key, p.fields);
318
+ result = { success: true, issue_key: p.issue_key };
319
+ break;
320
+ case "transition_issue":
321
+ await jira.transitionIssue(p.issue_key, p.target_status);
322
+ result = {
323
+ success: true,
324
+ issue_key: p.issue_key,
325
+ target_status: p.target_status,
326
+ };
327
+ break;
328
+ case "get_transitions":
329
+ result = await jira.getTransitions(p.issue_key);
330
+ break;
331
+ case "add_comment":
332
+ result = await jira.addComment(p.issue_key, p.body);
333
+ break;
334
+ default:
335
+ throw new McpError(ErrorCode.InvalidParams, `Unknown Jira action: ${(args as { action?: string }).action}`);
336
+ }
337
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
338
+ }
339
+
340
+ default:
341
+ throw new McpError(ErrorCode.MethodNotFound, `Tool not found: ${name}`);
342
+ }
343
+ } catch (err: unknown) {
344
+ if (err instanceof AppNotConnectedError) {
345
+ return {
346
+ content: [{ type: "text", text: `Error: ${err.message}\nAction required: Connect your account at ${CONNECTIONS_URL}` }],
347
+ isError: true,
348
+ };
349
+ }
350
+ return {
351
+ content: [{ type: "text", text: `Error: ${err instanceof Error ? err.message : String(err)}` }],
352
+ isError: true,
353
+ };
354
+ }
355
+ });
356
+
357
+ async function main() {
358
+ const transport = new StdioServerTransport();
359
+ await server.connect(transport);
360
+ console.error("MorphixAI MCP Server running on stdio");
361
+ }
362
+
363
+ main().catch((err) => {
364
+ console.error("Server error:", err);
365
+ process.exit(1);
366
+ });
package/tsconfig.json ADDED
@@ -0,0 +1,28 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ES2022",
5
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
6
+ "types": ["node"],
7
+ "moduleResolution": "bundler",
8
+ "declaration": true,
9
+ "declarationMap": true,
10
+ "sourceMap": true,
11
+ "outDir": "./dist",
12
+ "rootDir": "./src",
13
+ "strict": false,
14
+ "noImplicitAny": false,
15
+ "esModuleInterop": true,
16
+ "skipLibCheck": true,
17
+ "forceConsistentCasingInFileNames": true,
18
+ "resolveJsonModule": true,
19
+ "allowSyntheticDefaultImports": true
20
+ },
21
+ "include": [
22
+ "src/**/*"
23
+ ],
24
+ "exclude": [
25
+ "node_modules",
26
+ "dist"
27
+ ]
28
+ }