@feedmob/github-issues 0.0.2 → 0.0.3
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/README.md +64 -103
- package/dist/common/version.js +1 -1
- package/dist/index.js +156 -147
- package/dist/operations/issues.js +14 -4
- package/package.json +3 -1
package/README.md
CHANGED
|
@@ -1,125 +1,86 @@
|
|
|
1
|
-
# GitHub MCP Server
|
|
1
|
+
# FeedMob GitHub Issues MCP Server
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
## Features
|
|
6
|
-
|
|
7
|
-
The GitHub MCP Server provides the following capabilities:
|
|
8
|
-
- Create and manage GitHub issues
|
|
9
|
-
- Search for issues across repositories
|
|
10
|
-
- List and filter repository issues
|
|
11
|
-
- Update existing issues
|
|
12
|
-
- Get details of specific issues
|
|
3
|
+
A GitHub Issues MCP server customized for the FeedMob team
|
|
13
4
|
|
|
14
5
|
## Tools
|
|
15
6
|
|
|
7
|
+
### `search_issues`
|
|
8
|
+
- Search GitHub Issues through FeedMob API
|
|
9
|
+
- Input parameters:
|
|
10
|
+
- `scheam` (string, required): Get from system resource `issues/search_schema`
|
|
11
|
+
- `start_date` (string): Issue creation start date, defaults to 6 days ago
|
|
12
|
+
- `end_date` (string): Issue creation end date, defaults to today
|
|
13
|
+
- `status` (optional string): Issue status, e.g., 'open', 'closed'
|
|
14
|
+
- `repo` (optional string)
|
|
15
|
+
- `users` (optional string[]): List of users
|
|
16
|
+
- `team` (optional string): Team name, e.g., 'Star', 'Mighty'
|
|
17
|
+
- Returns: Search results
|
|
18
|
+
|
|
16
19
|
### `create_issue`
|
|
17
|
-
- Create a new
|
|
18
|
-
-
|
|
19
|
-
- `owner` (string): Repository owner
|
|
20
|
-
- `repo` (string): Repository name
|
|
21
|
-
- `title` (string): Issue title
|
|
20
|
+
- Create a new Issue in a GitHub repository
|
|
21
|
+
- Input parameters:
|
|
22
|
+
- `owner` (optional string): Repository owner, can use environment variable default
|
|
23
|
+
- `repo` (string, required): Repository name
|
|
24
|
+
- `title` (string, required): Issue title
|
|
22
25
|
- `body` (optional string): Issue description
|
|
23
|
-
- `assignees` (optional string[]): Usernames to assign
|
|
26
|
+
- `assignees` (optional string[]): Usernames to assign to
|
|
24
27
|
- `labels` (optional string[]): Labels to add
|
|
25
28
|
- `milestone` (optional number): Milestone number
|
|
26
|
-
- Returns: Created
|
|
27
|
-
|
|
28
|
-
### `list_issues`
|
|
29
|
-
- List and filter repository issues
|
|
30
|
-
- Inputs:
|
|
31
|
-
- `owner` (string): Repository owner
|
|
32
|
-
- `repo` (string): Repository name
|
|
33
|
-
- `state` (optional string): Filter by state ('open', 'closed', 'all')
|
|
34
|
-
- `labels` (optional string[]): Filter by labels
|
|
35
|
-
- `sort` (optional string): Sort by ('created', 'updated', 'comments')
|
|
36
|
-
- `direction` (optional string): Sort direction ('asc', 'desc')
|
|
37
|
-
- `since` (optional string): Filter by date (ISO 8601 timestamp)
|
|
38
|
-
- `page` (optional number): Page number
|
|
39
|
-
- `per_page` (optional number): Results per page
|
|
40
|
-
- Returns: Array of issue details
|
|
29
|
+
- Returns: Created Issue details
|
|
41
30
|
|
|
42
31
|
### `update_issue`
|
|
43
|
-
- Update an existing
|
|
44
|
-
-
|
|
45
|
-
- `owner` (string): Repository owner
|
|
46
|
-
- `repo` (string): Repository name
|
|
47
|
-
- `issue_number` (number): Issue number to update
|
|
32
|
+
- Update an existing Issue
|
|
33
|
+
- Input parameters:
|
|
34
|
+
- `owner` (string, required): Repository owner
|
|
35
|
+
- `repo` (string, required): Repository name
|
|
36
|
+
- `issue_number` (number, required): Issue number to update
|
|
48
37
|
- `title` (optional string): New title
|
|
49
38
|
- `body` (optional string): New description
|
|
50
39
|
- `state` (optional string): New state ('open' or 'closed')
|
|
51
40
|
- `labels` (optional string[]): New labels
|
|
52
41
|
- `assignees` (optional string[]): New assignees
|
|
53
42
|
- `milestone` (optional number): New milestone number
|
|
54
|
-
- Returns: Updated
|
|
55
|
-
|
|
56
|
-
### `search_issues`
|
|
57
|
-
- Search for issues and pull requests across GitHub repositories
|
|
58
|
-
- Inputs:
|
|
59
|
-
- `q` (string): Search query using GitHub issues search syntax
|
|
60
|
-
- `sort` (optional string): Sort field (comments, reactions, created, etc.)
|
|
61
|
-
- `order` (optional string): Sort order ('asc' or 'desc')
|
|
62
|
-
- `per_page` (optional number): Results per page (max 100)
|
|
63
|
-
- `page` (optional number): Page number
|
|
64
|
-
- Returns: Issue and pull request search results
|
|
43
|
+
- Returns: Updated Issue details
|
|
65
44
|
|
|
66
45
|
### `get_issue`
|
|
67
|
-
-
|
|
68
|
-
-
|
|
69
|
-
- `owner` (string): Repository owner
|
|
70
|
-
- `repo` (string):
|
|
71
|
-
- `issue_number` (number): Issue number to retrieve
|
|
72
|
-
- Returns: GitHub Issue object
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
- `
|
|
78
|
-
- `
|
|
79
|
-
- `
|
|
80
|
-
- `
|
|
81
|
-
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
```json
|
|
105
|
-
{
|
|
106
|
-
"mcpServers": {
|
|
107
|
-
"github": {
|
|
108
|
-
"command": "npx",
|
|
109
|
-
"args": [
|
|
110
|
-
"-y",
|
|
111
|
-
"@feedmob/github-issues"
|
|
112
|
-
],
|
|
113
|
-
"env": {
|
|
114
|
-
"GITHUB_PERSONAL_ACCESS_TOKEN": "<YOUR_TOKEN>",
|
|
115
|
-
"GITHUB_DEFAULT_OWNER": "optional-default-owner",
|
|
116
|
-
"GITHUB_DEFAULT_REPO": "optional-default-repo"
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
}
|
|
46
|
+
- Get details of a specific Issue in a repository
|
|
47
|
+
- Input parameters:
|
|
48
|
+
- `owner` (string, required): Repository owner
|
|
49
|
+
- `repo` (string, required):
|
|
50
|
+
- `issue_number` (number, required): Issue number to retrieve
|
|
51
|
+
- Returns: GitHub Issue object and details
|
|
52
|
+
|
|
53
|
+
### `add_issue_comment`
|
|
54
|
+
- Add a comment to an existing Issue
|
|
55
|
+
- Input parameters:
|
|
56
|
+
- `owner` (string, required): Repository owner
|
|
57
|
+
- `repo` (string, required):
|
|
58
|
+
- `issue_number` (number, required): Issue number
|
|
59
|
+
- `body` (string, required): Comment content
|
|
60
|
+
- Returns: Created comment details
|
|
61
|
+
|
|
62
|
+
### `sync_latest_issues`
|
|
63
|
+
- Sync GitHub Issues Latest Data By FeedMob API
|
|
64
|
+
|
|
65
|
+
## Resources
|
|
66
|
+
|
|
67
|
+
### `issues/search_schema`
|
|
68
|
+
- Provides schema definition for Issues search
|
|
69
|
+
|
|
70
|
+
### Local Development
|
|
71
|
+
For local development, you can run the server using the following commands:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
# Install dependencies
|
|
75
|
+
npm install
|
|
76
|
+
|
|
77
|
+
# Build project
|
|
78
|
+
npm run build
|
|
79
|
+
|
|
80
|
+
# Run server
|
|
81
|
+
npx tsx src/github-issues/index.ts
|
|
121
82
|
```
|
|
122
83
|
|
|
123
84
|
## License
|
|
124
85
|
|
|
125
|
-
This MCP server is licensed under the MIT License. This means you
|
|
86
|
+
This MCP server is licensed under the MIT License. This means you can freely use, modify, and distribute this software, but must comply with the terms and conditions of the MIT License. For more details, please refer to the LICENSE file in the project repository.
|
package/dist/common/version.js
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,28 +1,20 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
-
import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
|
|
5
|
-
import { z } from 'zod';
|
|
6
|
-
import { zodToJsonSchema } from 'zod-to-json-schema';
|
|
2
|
+
import { FastMCP } from "fastmcp";
|
|
7
3
|
import fetch from 'node-fetch';
|
|
8
4
|
import * as issues from './operations/issues.js';
|
|
9
|
-
import
|
|
10
|
-
import { GitHubValidationError, GitHubResourceNotFoundError, GitHubAuthenticationError, GitHubPermissionError, GitHubRateLimitError, GitHubConflictError, isGitHubError, } from './common/errors.js';
|
|
5
|
+
import { GitHubValidationError, GitHubResourceNotFoundError, GitHubAuthenticationError, GitHubPermissionError, GitHubRateLimitError, GitHubConflictError, } from './common/errors.js';
|
|
11
6
|
import { VERSION } from "./common/version.js";
|
|
12
7
|
// If fetch doesn't exist in global scope, add it
|
|
13
8
|
if (!globalThis.fetch) {
|
|
14
9
|
globalThis.fetch = fetch;
|
|
15
10
|
}
|
|
16
11
|
// Default values from environment variables
|
|
17
|
-
const DEFAULT_OWNER = process.env.GITHUB_DEFAULT_OWNER
|
|
18
|
-
const
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
capabilities: {
|
|
24
|
-
tools: {},
|
|
25
|
-
},
|
|
12
|
+
const DEFAULT_OWNER = process.env.GITHUB_DEFAULT_OWNER;
|
|
13
|
+
const AI_API_URL = process.env.AI_API_URL;
|
|
14
|
+
const AI_API_TOKEN = process.env.AI_API_TOKEN;
|
|
15
|
+
const server = new FastMCP({
|
|
16
|
+
name: "feedmob-github-mcp-server",
|
|
17
|
+
version: VERSION
|
|
26
18
|
});
|
|
27
19
|
function formatGitHubError(error) {
|
|
28
20
|
let message = `GitHub API Error: ${error.message}`;
|
|
@@ -49,147 +41,164 @@ function formatGitHubError(error) {
|
|
|
49
41
|
}
|
|
50
42
|
return message;
|
|
51
43
|
}
|
|
52
|
-
server.
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
name: "list_issues",
|
|
62
|
-
description: "List issues in a GitHub repository with filtering options",
|
|
63
|
-
inputSchema: zodToJsonSchema(issues.ListIssuesOptionsSchema)
|
|
64
|
-
},
|
|
65
|
-
{
|
|
66
|
-
name: "update_issue",
|
|
67
|
-
description: "Update an existing issue in a GitHub repository",
|
|
68
|
-
inputSchema: zodToJsonSchema(issues.UpdateIssueOptionsSchema)
|
|
69
|
-
},
|
|
70
|
-
{
|
|
71
|
-
name: "search_issues",
|
|
72
|
-
description: "Search for issues and pull requests across GitHub repositories",
|
|
73
|
-
inputSchema: zodToJsonSchema(search.SearchIssuesSchema),
|
|
74
|
-
},
|
|
75
|
-
{
|
|
76
|
-
name: "get_issue",
|
|
77
|
-
description: "Get details of a specific issue in a GitHub repository.",
|
|
78
|
-
inputSchema: zodToJsonSchema(issues.GetIssueSchema)
|
|
44
|
+
server.addResource({
|
|
45
|
+
uri: "issues/search_schema",
|
|
46
|
+
name: "search issues schema",
|
|
47
|
+
mimeType: "text/markdown",
|
|
48
|
+
async load() {
|
|
49
|
+
const response = await fetch(AI_API_URL + "/issues/scheam", {
|
|
50
|
+
method: 'GET',
|
|
51
|
+
headers: {
|
|
52
|
+
'Authorization': "Bearer " + AI_API_TOKEN,
|
|
79
53
|
}
|
|
80
|
-
|
|
81
|
-
|
|
54
|
+
});
|
|
55
|
+
return {
|
|
56
|
+
text: await response.text(),
|
|
57
|
+
};
|
|
58
|
+
},
|
|
82
59
|
});
|
|
83
|
-
server.
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
if (!owner || !repo) {
|
|
96
|
-
throw new Error("Repository owner and name are required. Either provide them directly or set GITHUB_DEFAULT_OWNER and GITHUB_DEFAULT_REPO environment variables.");
|
|
97
|
-
}
|
|
98
|
-
try {
|
|
99
|
-
console.error(`[DEBUG] Attempting to create issue in ${owner}/${repo}`);
|
|
100
|
-
console.error(`[DEBUG] Issue options:`, JSON.stringify(options, null, 2));
|
|
101
|
-
const issue = await issues.createIssue(owner, repo, options);
|
|
102
|
-
console.error(`[DEBUG] Issue created successfully`);
|
|
103
|
-
return {
|
|
104
|
-
content: [{ type: "text", text: JSON.stringify(issue, null, 2) }],
|
|
105
|
-
};
|
|
106
|
-
}
|
|
107
|
-
catch (err) {
|
|
108
|
-
// Type guard for Error objects
|
|
109
|
-
const error = err instanceof Error ? err : new Error(String(err));
|
|
110
|
-
console.error(`[ERROR] Failed to create issue:`, error);
|
|
111
|
-
if (error instanceof GitHubResourceNotFoundError) {
|
|
112
|
-
throw new Error(`Repository '${owner}/${repo}' not found. Please verify:\n` +
|
|
113
|
-
`1. The repository exists\n` +
|
|
114
|
-
`2. You have correct access permissions\n` +
|
|
115
|
-
`3. The owner and repository names are spelled correctly`);
|
|
116
|
-
}
|
|
117
|
-
// Safely access error properties
|
|
118
|
-
throw new Error(`Failed to create issue: ${error.message}${error.stack ? `\nStack: ${error.stack}` : ''}`);
|
|
119
|
-
}
|
|
60
|
+
server.addTool({
|
|
61
|
+
name: "search_issues",
|
|
62
|
+
description: "Search GitHub Issues",
|
|
63
|
+
parameters: issues.FeedmobSearchOptions,
|
|
64
|
+
execute: async (args) => {
|
|
65
|
+
try {
|
|
66
|
+
let params = new URLSearchParams();
|
|
67
|
+
params.set('start_date', args.start_date);
|
|
68
|
+
params.set('end_date', args.end_date);
|
|
69
|
+
// 添加可选参数
|
|
70
|
+
if (args.status !== undefined) {
|
|
71
|
+
params.set('status', args.status);
|
|
120
72
|
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
const results = await search.searchIssues(args);
|
|
124
|
-
return {
|
|
125
|
-
content: [{ type: "text", text: JSON.stringify(results, null, 2) }],
|
|
126
|
-
};
|
|
73
|
+
if (args.repo !== undefined) {
|
|
74
|
+
params.set('repo', args.repo);
|
|
127
75
|
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
// Use default values from environment variables if not provided
|
|
131
|
-
const owner = args.owner || DEFAULT_OWNER;
|
|
132
|
-
const repo = args.repo || DEFAULT_REPO;
|
|
133
|
-
const { ...options } = args;
|
|
134
|
-
if (!owner || !repo) {
|
|
135
|
-
throw new Error("Repository owner and name are required. Either provide them directly or set GITHUB_DEFAULT_OWNER and GITHUB_DEFAULT_REPO environment variables.");
|
|
136
|
-
}
|
|
137
|
-
const result = await issues.listIssues(owner, repo, options);
|
|
138
|
-
return {
|
|
139
|
-
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
140
|
-
};
|
|
76
|
+
if (args.users !== undefined) {
|
|
77
|
+
args.users.forEach(user => params.append('users[]', user));
|
|
141
78
|
}
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
// Use default values from environment variables if not provided
|
|
145
|
-
const owner = args.owner || DEFAULT_OWNER;
|
|
146
|
-
const repo = args.repo || DEFAULT_REPO;
|
|
147
|
-
const { issue_number, ...options } = args;
|
|
148
|
-
if (!owner || !repo) {
|
|
149
|
-
throw new Error("Repository owner and name are required. Either provide them directly or set GITHUB_DEFAULT_OWNER and GITHUB_DEFAULT_REPO environment variables.");
|
|
150
|
-
}
|
|
151
|
-
const result = await issues.updateIssue(owner, repo, issue_number, options);
|
|
152
|
-
return {
|
|
153
|
-
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
154
|
-
};
|
|
79
|
+
if (args.team !== undefined) {
|
|
80
|
+
params.set('team', args.team);
|
|
155
81
|
}
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
const repo = args.repo || DEFAULT_REPO;
|
|
161
|
-
const { issue_number } = args;
|
|
162
|
-
if (!owner || !repo) {
|
|
163
|
-
throw new Error("Repository owner and name are required. Either provide them directly or set GITHUB_DEFAULT_OWNER and GITHUB_DEFAULT_REPO environment variables.");
|
|
82
|
+
const response = await fetch(`${AI_API_URL}/issues?${params}`, {
|
|
83
|
+
method: 'GET',
|
|
84
|
+
headers: {
|
|
85
|
+
'Authorization': "Bearer " + AI_API_TOKEN
|
|
164
86
|
}
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
87
|
+
});
|
|
88
|
+
return {
|
|
89
|
+
content: [{ type: "text", text: await response.text() }],
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
return {
|
|
94
|
+
content: [{ type: "text", text: `API ERROR: ${error instanceof Error ? error.message : String(error)}` }],
|
|
95
|
+
};
|
|
172
96
|
}
|
|
173
97
|
}
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
98
|
+
});
|
|
99
|
+
server.addTool({
|
|
100
|
+
name: "create_issue",
|
|
101
|
+
description: "Create a new issue in a GitHub repository",
|
|
102
|
+
parameters: issues.CreateIssueSchema,
|
|
103
|
+
execute: async (args) => {
|
|
104
|
+
const owner = args.owner || DEFAULT_OWNER;
|
|
105
|
+
const repo = args.repo;
|
|
106
|
+
const { ...options } = args;
|
|
107
|
+
if (!owner || !repo) {
|
|
108
|
+
throw new Error("Repository owner and name are required. Either provide them directly or set GITHUB_DEFAULT_OWNER environment variables.");
|
|
177
109
|
}
|
|
178
|
-
|
|
179
|
-
|
|
110
|
+
try {
|
|
111
|
+
console.error(`[DEBUG] Attempting to create issue in ${owner}/${repo}`);
|
|
112
|
+
console.error(`[DEBUG] Issue options:`, JSON.stringify(options, null, 2));
|
|
113
|
+
const issue = await issues.createIssue(owner, repo, options);
|
|
114
|
+
console.error(`[DEBUG] Issue created successfully`);
|
|
115
|
+
return {
|
|
116
|
+
content: [{ type: "text", text: JSON.stringify(issue, null, 2) }],
|
|
117
|
+
};
|
|
180
118
|
}
|
|
181
|
-
|
|
182
|
-
|
|
119
|
+
catch (err) {
|
|
120
|
+
// Type guard for Error objects
|
|
121
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
122
|
+
console.error(`[ERROR] Failed to create issue:`, error);
|
|
123
|
+
if (error instanceof GitHubResourceNotFoundError) {
|
|
124
|
+
throw new Error(`Repository '${owner}/${repo}' not found. Please verify:\n` +
|
|
125
|
+
`1. The repository exists\n` +
|
|
126
|
+
`2. You have correct access permissions\n` +
|
|
127
|
+
`3. The owner and repository names are spelled correctly`);
|
|
128
|
+
}
|
|
129
|
+
// Safely access error properties
|
|
130
|
+
throw new Error(`Failed to create issue: ${error.message}${error.stack ? `\nStack: ${error.stack}` : ''}`);
|
|
131
|
+
}
|
|
132
|
+
},
|
|
183
133
|
});
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
134
|
+
server.addTool({
|
|
135
|
+
name: "update_issue",
|
|
136
|
+
description: "Update an existing issue in a GitHub repository",
|
|
137
|
+
parameters: issues.UpdateIssueOptionsSchema,
|
|
138
|
+
execute: async (args) => {
|
|
139
|
+
const owner = args.owner || DEFAULT_OWNER;
|
|
140
|
+
const repo = args.repo;
|
|
141
|
+
const { issue_number, ...options } = args;
|
|
142
|
+
if (!owner || !repo) {
|
|
143
|
+
throw new Error("Repository owner and name are required. Either provide them directly or set GITHUB_DEFAULT_OWNER environment variables.");
|
|
144
|
+
}
|
|
145
|
+
const result = await issues.updateIssue(owner, repo, issue_number, options);
|
|
146
|
+
return {
|
|
147
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
148
|
+
};
|
|
149
|
+
},
|
|
150
|
+
});
|
|
151
|
+
server.addTool({
|
|
152
|
+
name: "get_issue",
|
|
153
|
+
description: "Get details of a specific issue in a GitHub repository.",
|
|
154
|
+
parameters: issues.GetIssueSchema,
|
|
155
|
+
execute: async (args) => {
|
|
156
|
+
const owner = args.owner || DEFAULT_OWNER;
|
|
157
|
+
const repo = args.repo;
|
|
158
|
+
const { issue_number } = args;
|
|
159
|
+
if (!owner || !repo) {
|
|
160
|
+
throw new Error("Repository owner and name are required. Either provide them directly or set GITHUB_DEFAULT_OWNER environment variables.");
|
|
161
|
+
}
|
|
162
|
+
const issue = await issues.getIssue(owner, repo, issue_number);
|
|
163
|
+
return {
|
|
164
|
+
content: [{ type: "text", text: JSON.stringify(issue, null, 2) }],
|
|
165
|
+
};
|
|
166
|
+
},
|
|
167
|
+
});
|
|
168
|
+
server.addTool({
|
|
169
|
+
name: "add_issue_comment",
|
|
170
|
+
description: "Add a comment to an existing issue",
|
|
171
|
+
parameters: issues.IssueCommentSchema,
|
|
172
|
+
execute: async (args) => {
|
|
173
|
+
const { owner, repo, issue_number, body } = args;
|
|
174
|
+
const result = await issues.addIssueComment(owner, repo, issue_number, body);
|
|
175
|
+
return {
|
|
176
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
177
|
+
};
|
|
178
|
+
},
|
|
179
|
+
});
|
|
180
|
+
server.addTool({
|
|
181
|
+
name: "sync_latest_issues",
|
|
182
|
+
description: "sync latest issues from Api",
|
|
183
|
+
execute: async () => {
|
|
184
|
+
try {
|
|
185
|
+
const response = await fetch(AI_API_URL + "/issues/sync_latest", {
|
|
186
|
+
method: 'GET',
|
|
187
|
+
headers: {
|
|
188
|
+
'Authorization': "Bearer " + AI_API_TOKEN,
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
return {
|
|
192
|
+
content: [{ type: "text", text: await response.text() }],
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
catch (error) {
|
|
196
|
+
return {
|
|
197
|
+
content: [{ type: "text", text: `API ERROR: ${error instanceof Error ? error.message : String(error)}` }],
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
},
|
|
201
|
+
});
|
|
202
|
+
server.start({
|
|
203
|
+
transportType: "stdio"
|
|
195
204
|
});
|
|
@@ -1,13 +1,23 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { githubRequest, buildUrl } from "../common/utils.js";
|
|
3
|
+
import { subDays, format } from 'date-fns';
|
|
4
|
+
export const FeedmobSearchOptions = z.object({
|
|
5
|
+
scheam: z.string().describe("get from system resources issues/search_schema"),
|
|
6
|
+
start_date: z.string().default(format(subDays(new Date(), 6), 'yyyy-MM-dd')).describe("The creation start date of the issue"),
|
|
7
|
+
end_date: z.string().default(format(new Date(), 'yyyy-MM-dd')).describe("The creation end date of the issue"),
|
|
8
|
+
status: z.string().optional().describe("The status of the issue, e.g., 'open', 'closed'"),
|
|
9
|
+
repo: z.string().optional().describe("The repository name, e.g., 'feedmob', 'tracking_admin', If the user does not specify otherwise, this parameter can be omitted and all repos will be searched by default."),
|
|
10
|
+
users: z.array(z.string()).optional().optional(),
|
|
11
|
+
team: z.string().optional().describe("The team name, e.g., 'Star', 'Mighty'"),
|
|
12
|
+
});
|
|
3
13
|
export const GetIssueSchema = z.object({
|
|
4
14
|
owner: z.string(),
|
|
5
|
-
repo: z.string(),
|
|
15
|
+
repo: z.string().describe("The repository name, e.g., 'feedmob', 'tracking_admin'"),
|
|
6
16
|
issue_number: z.number(),
|
|
7
17
|
});
|
|
8
18
|
export const IssueCommentSchema = z.object({
|
|
9
19
|
owner: z.string(),
|
|
10
|
-
repo: z.string(),
|
|
20
|
+
repo: z.string().describe("The repository name, e.g., 'feedmob', 'tracking_admin'"),
|
|
11
21
|
issue_number: z.number(),
|
|
12
22
|
body: z.string(),
|
|
13
23
|
});
|
|
@@ -20,7 +30,7 @@ export const CreateIssueOptionsSchema = z.object({
|
|
|
20
30
|
});
|
|
21
31
|
export const CreateIssueSchema = z.object({
|
|
22
32
|
owner: z.string().optional(),
|
|
23
|
-
repo: z.string().
|
|
33
|
+
repo: z.string().describe("The repository name, e.g., 'feedmob', 'tracking_admin'"),
|
|
24
34
|
...CreateIssueOptionsSchema.shape,
|
|
25
35
|
});
|
|
26
36
|
export const ListIssuesOptionsSchema = z.object({
|
|
@@ -36,7 +46,7 @@ export const ListIssuesOptionsSchema = z.object({
|
|
|
36
46
|
});
|
|
37
47
|
export const UpdateIssueOptionsSchema = z.object({
|
|
38
48
|
owner: z.string(),
|
|
39
|
-
repo: z.string(),
|
|
49
|
+
repo: z.string().describe("The repository name, e.g., 'feedmob', 'tracking_admin'"),
|
|
40
50
|
issue_number: z.number(),
|
|
41
51
|
title: z.string().optional(),
|
|
42
52
|
body: z.string().optional(),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@feedmob/github-issues",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
4
4
|
"description": "MCP server for using the GitHub API",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "FeedMob",
|
|
@@ -19,6 +19,8 @@
|
|
|
19
19
|
"watch": "tsc --watch"
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
|
+
"date-fns": "^4.1.0",
|
|
23
|
+
"fastmcp": "2.1.0",
|
|
22
24
|
"@modelcontextprotocol/sdk": "1.0.1",
|
|
23
25
|
"@types/node": "^22",
|
|
24
26
|
"@types/node-fetch": "^2.6.12",
|