@fre4x/github 1.0.30 → 1.0.40
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 +69 -58
- package/dist/api.d.ts +10 -0
- package/dist/api.d.ts.map +1 -0
- package/{src/api.ts → dist/api.js} +103 -175
- package/dist/api.js.map +1 -0
- package/dist/index.d.ts +37 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +26839 -0
- package/dist/index.js.map +1 -0
- package/dist/index.test.d.ts +2 -0
- package/dist/index.test.d.ts.map +1 -0
- package/dist/index.test.js +160 -0
- package/dist/index.test.js.map +1 -0
- package/dist/mock.d.ts +13 -0
- package/dist/mock.d.ts.map +1 -0
- package/{src/mock.ts → dist/mock.js} +11 -24
- package/dist/mock.js.map +1 -0
- package/{src/types.ts → dist/types.d.ts} +4 -16
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +32 -30
- package/CHANGELOG.md +0 -68
- package/bun.lock +0 -25
- package/src/index.test.ts +0 -246
- package/src/index.ts +0 -421
- package/tsconfig.json +0 -11
package/src/index.test.ts
DELETED
|
@@ -1,246 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, beforeAll } from 'vitest';
|
|
2
|
-
import {
|
|
3
|
-
ListToolsResultSchema,
|
|
4
|
-
CallToolResultSchema,
|
|
5
|
-
type TextContent,
|
|
6
|
-
} from '@modelcontextprotocol/sdk/types.js';
|
|
7
|
-
import { server } from './index.js';
|
|
8
|
-
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
|
9
|
-
import { InMemoryTransport } from '@modelcontextprotocol/sdk/inMemory.js';
|
|
10
|
-
|
|
11
|
-
// Ensure mock mode is enabled for tests
|
|
12
|
-
process.env.MOCK = 'true';
|
|
13
|
-
|
|
14
|
-
describe('GitHub MCP Server', () => {
|
|
15
|
-
let client: Client;
|
|
16
|
-
let transport: ReturnType<typeof InMemoryTransport.createLinkedPair>[0];
|
|
17
|
-
|
|
18
|
-
beforeAll(async () => {
|
|
19
|
-
const [_clientTransport, serverTransport] =
|
|
20
|
-
InMemoryTransport.createLinkedPair();
|
|
21
|
-
transport = _clientTransport;
|
|
22
|
-
|
|
23
|
-
await server.connect(serverTransport);
|
|
24
|
-
|
|
25
|
-
client = new Client({
|
|
26
|
-
name: 'test-client',
|
|
27
|
-
version: '1.0.0',
|
|
28
|
-
});
|
|
29
|
-
await client.connect(transport);
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
describe('Tools', () => {
|
|
33
|
-
it('should list all available tools', async () => {
|
|
34
|
-
const response = await client.request(
|
|
35
|
-
{ method: 'tools/list' },
|
|
36
|
-
ListToolsResultSchema,
|
|
37
|
-
);
|
|
38
|
-
expect(response.tools).toBeDefined();
|
|
39
|
-
expect(response.tools.length).toBe(8);
|
|
40
|
-
|
|
41
|
-
const toolNames = response.tools.map((t) => t.name);
|
|
42
|
-
expect(toolNames).toContain('github_search_repositories');
|
|
43
|
-
expect(toolNames).toContain('github_search_code');
|
|
44
|
-
expect(toolNames).toContain('github_search_issues_and_prs');
|
|
45
|
-
expect(toolNames).toContain('github_get_repository');
|
|
46
|
-
expect(toolNames).toContain('github_list_issues');
|
|
47
|
-
expect(toolNames).toContain('github_create_issue');
|
|
48
|
-
expect(toolNames).toContain('github_get_pull_request');
|
|
49
|
-
expect(toolNames).toContain('github_list_pull_requests');
|
|
50
|
-
});
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
describe('Handlers (Mock Mode)', () => {
|
|
54
|
-
it('handles github_search_repositories', async () => {
|
|
55
|
-
const response = await client.request(
|
|
56
|
-
{
|
|
57
|
-
method: 'tools/call',
|
|
58
|
-
params: {
|
|
59
|
-
name: 'github_search_repositories',
|
|
60
|
-
arguments: { query: 'mcp-server', limit: 5 },
|
|
61
|
-
},
|
|
62
|
-
},
|
|
63
|
-
CallToolResultSchema,
|
|
64
|
-
);
|
|
65
|
-
|
|
66
|
-
expect(response.isError).toBeUndefined();
|
|
67
|
-
expect((response.content[0] as TextContent).text).toContain(
|
|
68
|
-
'fre4x/mcp-server',
|
|
69
|
-
);
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
it('handles github_search_code', async () => {
|
|
73
|
-
const response = await client.request(
|
|
74
|
-
{
|
|
75
|
-
method: 'tools/call',
|
|
76
|
-
params: {
|
|
77
|
-
name: 'github_search_code',
|
|
78
|
-
arguments: { query: 'index.ts', limit: 5 },
|
|
79
|
-
},
|
|
80
|
-
},
|
|
81
|
-
CallToolResultSchema,
|
|
82
|
-
);
|
|
83
|
-
|
|
84
|
-
expect(response.isError).toBeUndefined();
|
|
85
|
-
expect((response.content[0] as TextContent).text).toContain(
|
|
86
|
-
'index.ts',
|
|
87
|
-
);
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
it('handles github_search_issues_and_prs', async () => {
|
|
91
|
-
const response = await client.request(
|
|
92
|
-
{
|
|
93
|
-
method: 'tools/call',
|
|
94
|
-
params: {
|
|
95
|
-
name: 'github_search_issues_and_prs',
|
|
96
|
-
arguments: { query: 'mock issue', limit: 5 },
|
|
97
|
-
},
|
|
98
|
-
},
|
|
99
|
-
CallToolResultSchema,
|
|
100
|
-
);
|
|
101
|
-
|
|
102
|
-
expect(response.isError).toBeUndefined();
|
|
103
|
-
expect((response.content[0] as TextContent).text).toContain(
|
|
104
|
-
'Mock issue title',
|
|
105
|
-
);
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
it('handles github_get_repository', async () => {
|
|
109
|
-
const response = await client.request(
|
|
110
|
-
{
|
|
111
|
-
method: 'tools/call',
|
|
112
|
-
params: {
|
|
113
|
-
name: 'github_get_repository',
|
|
114
|
-
arguments: { owner: 'fre4x', repo: 'mcp-server' },
|
|
115
|
-
},
|
|
116
|
-
},
|
|
117
|
-
CallToolResultSchema,
|
|
118
|
-
);
|
|
119
|
-
|
|
120
|
-
expect(response.isError).toBeUndefined();
|
|
121
|
-
expect((response.content[0] as TextContent).text).toContain(
|
|
122
|
-
'fre4x/mcp-server',
|
|
123
|
-
);
|
|
124
|
-
expect((response.content[0] as TextContent).text).toContain(
|
|
125
|
-
'Mock repository.',
|
|
126
|
-
);
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
it('handles github_list_issues', async () => {
|
|
130
|
-
const response = await client.request(
|
|
131
|
-
{
|
|
132
|
-
method: 'tools/call',
|
|
133
|
-
params: {
|
|
134
|
-
name: 'github_list_issues',
|
|
135
|
-
arguments: { owner: 'fre4x', repo: 'mcp-server' },
|
|
136
|
-
},
|
|
137
|
-
},
|
|
138
|
-
CallToolResultSchema,
|
|
139
|
-
);
|
|
140
|
-
|
|
141
|
-
expect(response.isError).toBeUndefined();
|
|
142
|
-
expect((response.content[0] as TextContent).text).toContain(
|
|
143
|
-
'Fix bug in handler',
|
|
144
|
-
);
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
it('handles github_create_issue', async () => {
|
|
148
|
-
const response = await client.request(
|
|
149
|
-
{
|
|
150
|
-
method: 'tools/call',
|
|
151
|
-
params: {
|
|
152
|
-
name: 'github_create_issue',
|
|
153
|
-
arguments: {
|
|
154
|
-
owner: 'fre4x',
|
|
155
|
-
repo: 'mcp-server',
|
|
156
|
-
title: 'New mocked issue',
|
|
157
|
-
body: 'test',
|
|
158
|
-
},
|
|
159
|
-
},
|
|
160
|
-
},
|
|
161
|
-
CallToolResultSchema,
|
|
162
|
-
);
|
|
163
|
-
|
|
164
|
-
expect(response.isError).toBeUndefined();
|
|
165
|
-
expect((response.content[0] as TextContent).text).toContain(
|
|
166
|
-
'New mocked issue',
|
|
167
|
-
);
|
|
168
|
-
});
|
|
169
|
-
|
|
170
|
-
it('handles github_get_pull_request', async () => {
|
|
171
|
-
const response = await client.request(
|
|
172
|
-
{
|
|
173
|
-
method: 'tools/call',
|
|
174
|
-
params: {
|
|
175
|
-
name: 'github_get_pull_request',
|
|
176
|
-
arguments: {
|
|
177
|
-
owner: 'fre4x',
|
|
178
|
-
repo: 'mcp-server',
|
|
179
|
-
pull_number: 4,
|
|
180
|
-
},
|
|
181
|
-
},
|
|
182
|
-
},
|
|
183
|
-
CallToolResultSchema,
|
|
184
|
-
);
|
|
185
|
-
|
|
186
|
-
expect(response.isError).toBeUndefined();
|
|
187
|
-
expect((response.content[0] as TextContent).text).toContain(
|
|
188
|
-
'Mock PR title',
|
|
189
|
-
);
|
|
190
|
-
});
|
|
191
|
-
|
|
192
|
-
it('handles github_list_pull_requests', async () => {
|
|
193
|
-
const response = await client.request(
|
|
194
|
-
{
|
|
195
|
-
method: 'tools/call',
|
|
196
|
-
params: {
|
|
197
|
-
name: 'github_list_pull_requests',
|
|
198
|
-
arguments: { owner: 'fre4x', repo: 'mcp-server' },
|
|
199
|
-
},
|
|
200
|
-
},
|
|
201
|
-
CallToolResultSchema,
|
|
202
|
-
);
|
|
203
|
-
|
|
204
|
-
expect(response.isError).toBeUndefined();
|
|
205
|
-
expect((response.content[0] as TextContent).text).toContain(
|
|
206
|
-
'Update dependencies',
|
|
207
|
-
);
|
|
208
|
-
});
|
|
209
|
-
|
|
210
|
-
it('returns validation error for missing required arguments', async () => {
|
|
211
|
-
const response = await client.request(
|
|
212
|
-
{
|
|
213
|
-
method: 'tools/call',
|
|
214
|
-
params: {
|
|
215
|
-
name: 'github_get_repository',
|
|
216
|
-
arguments: { owner: 'fre4x' }, // Missing repo
|
|
217
|
-
},
|
|
218
|
-
},
|
|
219
|
-
CallToolResultSchema,
|
|
220
|
-
);
|
|
221
|
-
|
|
222
|
-
expect(response.isError).toBe(true);
|
|
223
|
-
expect((response.content[0] as TextContent).text).toContain(
|
|
224
|
-
'Validation Error',
|
|
225
|
-
);
|
|
226
|
-
});
|
|
227
|
-
|
|
228
|
-
it('returns error for unknown tool', async () => {
|
|
229
|
-
const response = await client.request(
|
|
230
|
-
{
|
|
231
|
-
method: 'tools/call',
|
|
232
|
-
params: {
|
|
233
|
-
name: 'unknown_tool',
|
|
234
|
-
arguments: {},
|
|
235
|
-
},
|
|
236
|
-
},
|
|
237
|
-
CallToolResultSchema,
|
|
238
|
-
);
|
|
239
|
-
|
|
240
|
-
expect(response.isError).toBe(true);
|
|
241
|
-
expect((response.content[0] as TextContent).text).toContain(
|
|
242
|
-
'Unknown tool',
|
|
243
|
-
);
|
|
244
|
-
});
|
|
245
|
-
});
|
|
246
|
-
});
|
package/src/index.ts
DELETED
|
@@ -1,421 +0,0 @@
|
|
|
1
|
-
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
2
|
-
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
3
|
-
import {
|
|
4
|
-
CallToolRequestSchema,
|
|
5
|
-
ListToolsRequestSchema,
|
|
6
|
-
type Tool,
|
|
7
|
-
type CallToolResult,
|
|
8
|
-
} from '@modelcontextprotocol/sdk/types.js';
|
|
9
|
-
import * as zod from 'zod';
|
|
10
|
-
// biome-ignore lint/suspicious/noExplicitAny: compatibility pattern
|
|
11
|
-
const z = zod.z || (zod as any).default || zod;
|
|
12
|
-
import { pathToFileURL } from 'node:url';
|
|
13
|
-
import {
|
|
14
|
-
truncateToLimit,
|
|
15
|
-
createInternalError,
|
|
16
|
-
createValidationError,
|
|
17
|
-
formatMarkdownSection,
|
|
18
|
-
} from '@fre4x/mcp-shared';
|
|
19
|
-
|
|
20
|
-
import {
|
|
21
|
-
searchRepositories,
|
|
22
|
-
searchCode,
|
|
23
|
-
searchIssuesAndPrs,
|
|
24
|
-
getRepository,
|
|
25
|
-
listIssues,
|
|
26
|
-
createIssue,
|
|
27
|
-
getPullRequest,
|
|
28
|
-
listPullRequests,
|
|
29
|
-
} from './api.js';
|
|
30
|
-
|
|
31
|
-
const server = new Server(
|
|
32
|
-
{
|
|
33
|
-
name: '@fre4x/github',
|
|
34
|
-
version: '1.0.0',
|
|
35
|
-
},
|
|
36
|
-
{
|
|
37
|
-
capabilities: {
|
|
38
|
-
tools: {},
|
|
39
|
-
},
|
|
40
|
-
},
|
|
41
|
-
);
|
|
42
|
-
|
|
43
|
-
const paginationShape = {
|
|
44
|
-
limit: z
|
|
45
|
-
.number()
|
|
46
|
-
.int()
|
|
47
|
-
.min(1)
|
|
48
|
-
.max(100)
|
|
49
|
-
.default(20)
|
|
50
|
-
.describe('Maximum number of results to return (1–100, default 20)'),
|
|
51
|
-
offset: z
|
|
52
|
-
.number()
|
|
53
|
-
.int()
|
|
54
|
-
.min(0)
|
|
55
|
-
.default(0)
|
|
56
|
-
.describe('Number of results to skip for pagination (default 0)'),
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
const searchRepositoriesSchema = z.object({
|
|
60
|
-
query: z.string().describe('Query to search repositories'),
|
|
61
|
-
...paginationShape,
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
const searchCodeSchema = z.object({
|
|
65
|
-
query: z.string().describe('Query to search code'),
|
|
66
|
-
...paginationShape,
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
const searchIssuesAndPrsSchema = z.object({
|
|
70
|
-
query: z.string().describe('Query to search issues and PRs'),
|
|
71
|
-
...paginationShape,
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
const getRepositorySchema = z.object({
|
|
75
|
-
owner: z.string().describe('Repository owner'),
|
|
76
|
-
repo: z.string().describe('Repository name'),
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
const listIssuesSchema = z.object({
|
|
80
|
-
owner: z.string().describe('Repository owner'),
|
|
81
|
-
repo: z.string().describe('Repository name'),
|
|
82
|
-
state: z
|
|
83
|
-
.enum(['open', 'closed', 'all'])
|
|
84
|
-
.optional()
|
|
85
|
-
.describe('State of issues to list'),
|
|
86
|
-
...paginationShape,
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
const createIssueSchema = z.object({
|
|
90
|
-
owner: z.string().describe('Repository owner'),
|
|
91
|
-
repo: z.string().describe('Repository name'),
|
|
92
|
-
title: z.string().describe('Title of the new issue'),
|
|
93
|
-
body: z.string().optional().describe('Body of the new issue'),
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
const getPullRequestSchema = z.object({
|
|
97
|
-
owner: z.string().describe('Repository owner'),
|
|
98
|
-
repo: z.string().describe('Repository name'),
|
|
99
|
-
pull_number: z.number().describe('Pull request number'),
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
const listPullRequestsSchema = z.object({
|
|
103
|
-
owner: z.string().describe('Repository owner'),
|
|
104
|
-
repo: z.string().describe('Repository name'),
|
|
105
|
-
state: z
|
|
106
|
-
.enum(['open', 'closed', 'all'])
|
|
107
|
-
.optional()
|
|
108
|
-
.describe('State of PRs to list'),
|
|
109
|
-
...paginationShape,
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
// --- Tools ---
|
|
113
|
-
const tools: Tool[] = [
|
|
114
|
-
{
|
|
115
|
-
name: 'github_search_repositories',
|
|
116
|
-
description: 'Search for GitHub repositories',
|
|
117
|
-
inputSchema: {
|
|
118
|
-
type: 'object',
|
|
119
|
-
properties: {
|
|
120
|
-
query: { type: 'string' },
|
|
121
|
-
limit: { type: 'number' },
|
|
122
|
-
offset: { type: 'number' },
|
|
123
|
-
},
|
|
124
|
-
required: ['query'],
|
|
125
|
-
},
|
|
126
|
-
},
|
|
127
|
-
{
|
|
128
|
-
name: 'github_search_code',
|
|
129
|
-
description: 'Search for code within GitHub repositories',
|
|
130
|
-
inputSchema: {
|
|
131
|
-
type: 'object',
|
|
132
|
-
properties: {
|
|
133
|
-
query: { type: 'string' },
|
|
134
|
-
limit: { type: 'number' },
|
|
135
|
-
offset: { type: 'number' },
|
|
136
|
-
},
|
|
137
|
-
required: ['query'],
|
|
138
|
-
},
|
|
139
|
-
},
|
|
140
|
-
{
|
|
141
|
-
name: 'github_search_issues_and_prs',
|
|
142
|
-
description: 'Search for issues and pull requests',
|
|
143
|
-
inputSchema: {
|
|
144
|
-
type: 'object',
|
|
145
|
-
properties: {
|
|
146
|
-
query: { type: 'string' },
|
|
147
|
-
limit: { type: 'number' },
|
|
148
|
-
offset: { type: 'number' },
|
|
149
|
-
},
|
|
150
|
-
required: ['query'],
|
|
151
|
-
},
|
|
152
|
-
},
|
|
153
|
-
{
|
|
154
|
-
name: 'github_get_repository',
|
|
155
|
-
description: 'Get details for a specific repository',
|
|
156
|
-
inputSchema: {
|
|
157
|
-
type: 'object',
|
|
158
|
-
properties: {
|
|
159
|
-
owner: { type: 'string' },
|
|
160
|
-
repo: { type: 'string' },
|
|
161
|
-
},
|
|
162
|
-
required: ['owner', 'repo'],
|
|
163
|
-
},
|
|
164
|
-
},
|
|
165
|
-
{
|
|
166
|
-
name: 'github_list_issues',
|
|
167
|
-
description: 'List issues in a specific repository',
|
|
168
|
-
inputSchema: {
|
|
169
|
-
type: 'object',
|
|
170
|
-
properties: {
|
|
171
|
-
owner: { type: 'string' },
|
|
172
|
-
repo: { type: 'string' },
|
|
173
|
-
state: { type: 'string', enum: ['open', 'closed', 'all'] },
|
|
174
|
-
limit: { type: 'number' },
|
|
175
|
-
offset: { type: 'number' },
|
|
176
|
-
},
|
|
177
|
-
required: ['owner', 'repo'],
|
|
178
|
-
},
|
|
179
|
-
},
|
|
180
|
-
{
|
|
181
|
-
name: 'github_create_issue',
|
|
182
|
-
description: 'Create an issue in a repository',
|
|
183
|
-
inputSchema: {
|
|
184
|
-
type: 'object',
|
|
185
|
-
properties: {
|
|
186
|
-
owner: { type: 'string' },
|
|
187
|
-
repo: { type: 'string' },
|
|
188
|
-
title: { type: 'string' },
|
|
189
|
-
body: { type: 'string' },
|
|
190
|
-
},
|
|
191
|
-
required: ['owner', 'repo', 'title'],
|
|
192
|
-
},
|
|
193
|
-
},
|
|
194
|
-
{
|
|
195
|
-
name: 'github_get_pull_request',
|
|
196
|
-
description: 'Get details for a specific pull request',
|
|
197
|
-
inputSchema: {
|
|
198
|
-
type: 'object',
|
|
199
|
-
properties: {
|
|
200
|
-
owner: { type: 'string' },
|
|
201
|
-
repo: { type: 'string' },
|
|
202
|
-
pull_number: { type: 'number' },
|
|
203
|
-
},
|
|
204
|
-
required: ['owner', 'repo', 'pull_number'],
|
|
205
|
-
},
|
|
206
|
-
},
|
|
207
|
-
{
|
|
208
|
-
name: 'github_list_pull_requests',
|
|
209
|
-
description: 'List pull requests in a specific repository',
|
|
210
|
-
inputSchema: {
|
|
211
|
-
type: 'object',
|
|
212
|
-
properties: {
|
|
213
|
-
owner: { type: 'string' },
|
|
214
|
-
repo: { type: 'string' },
|
|
215
|
-
state: { type: 'string', enum: ['open', 'closed', 'all'] },
|
|
216
|
-
limit: { type: 'number' },
|
|
217
|
-
offset: { type: 'number' },
|
|
218
|
-
},
|
|
219
|
-
required: ['owner', 'repo'],
|
|
220
|
-
},
|
|
221
|
-
},
|
|
222
|
-
];
|
|
223
|
-
|
|
224
|
-
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
225
|
-
return { tools };
|
|
226
|
-
});
|
|
227
|
-
|
|
228
|
-
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
229
|
-
try {
|
|
230
|
-
switch (request.params.name) {
|
|
231
|
-
case 'github_search_repositories': {
|
|
232
|
-
const rawArgs = request.params.arguments ?? {};
|
|
233
|
-
const args = searchRepositoriesSchema.parse(rawArgs);
|
|
234
|
-
const limit = args.limit;
|
|
235
|
-
const offset = args.offset;
|
|
236
|
-
const result = await searchRepositories({
|
|
237
|
-
query: args.query,
|
|
238
|
-
limit,
|
|
239
|
-
offset,
|
|
240
|
-
});
|
|
241
|
-
return {
|
|
242
|
-
content: [
|
|
243
|
-
{
|
|
244
|
-
type: 'text',
|
|
245
|
-
text: truncateToLimit(
|
|
246
|
-
JSON.stringify(result, null, 2),
|
|
247
|
-
),
|
|
248
|
-
},
|
|
249
|
-
],
|
|
250
|
-
};
|
|
251
|
-
}
|
|
252
|
-
case 'github_search_code': {
|
|
253
|
-
const rawArgs = request.params.arguments ?? {};
|
|
254
|
-
const args = searchCodeSchema.parse(rawArgs);
|
|
255
|
-
const limit = args.limit;
|
|
256
|
-
const offset = args.offset;
|
|
257
|
-
const result = await searchCode({
|
|
258
|
-
query: args.query,
|
|
259
|
-
limit,
|
|
260
|
-
offset,
|
|
261
|
-
});
|
|
262
|
-
return {
|
|
263
|
-
content: [
|
|
264
|
-
{
|
|
265
|
-
type: 'text',
|
|
266
|
-
text: truncateToLimit(
|
|
267
|
-
JSON.stringify(result, null, 2),
|
|
268
|
-
),
|
|
269
|
-
},
|
|
270
|
-
],
|
|
271
|
-
};
|
|
272
|
-
}
|
|
273
|
-
case 'github_search_issues_and_prs': {
|
|
274
|
-
const rawArgs = request.params.arguments ?? {};
|
|
275
|
-
const args = searchIssuesAndPrsSchema.parse(rawArgs);
|
|
276
|
-
const limit = args.limit;
|
|
277
|
-
const offset = args.offset;
|
|
278
|
-
const result = await searchIssuesAndPrs({
|
|
279
|
-
query: args.query,
|
|
280
|
-
limit,
|
|
281
|
-
offset,
|
|
282
|
-
});
|
|
283
|
-
return {
|
|
284
|
-
content: [
|
|
285
|
-
{
|
|
286
|
-
type: 'text',
|
|
287
|
-
text: truncateToLimit(
|
|
288
|
-
JSON.stringify(result, null, 2),
|
|
289
|
-
),
|
|
290
|
-
},
|
|
291
|
-
],
|
|
292
|
-
};
|
|
293
|
-
}
|
|
294
|
-
case 'github_get_repository': {
|
|
295
|
-
const rawArgs = request.params.arguments ?? {};
|
|
296
|
-
const args = getRepositorySchema.parse(rawArgs);
|
|
297
|
-
const result = await getRepository(args);
|
|
298
|
-
return {
|
|
299
|
-
content: [
|
|
300
|
-
{
|
|
301
|
-
type: 'text',
|
|
302
|
-
text: formatMarkdownSection(
|
|
303
|
-
result.full_name,
|
|
304
|
-
JSON.stringify(result, null, 2),
|
|
305
|
-
),
|
|
306
|
-
},
|
|
307
|
-
],
|
|
308
|
-
};
|
|
309
|
-
}
|
|
310
|
-
case 'github_list_issues': {
|
|
311
|
-
const rawArgs = request.params.arguments ?? {};
|
|
312
|
-
const args = listIssuesSchema.parse(rawArgs);
|
|
313
|
-
const limit = args.limit;
|
|
314
|
-
const offset = args.offset;
|
|
315
|
-
const result = await listIssues({
|
|
316
|
-
owner: args.owner,
|
|
317
|
-
repo: args.repo,
|
|
318
|
-
state: args.state,
|
|
319
|
-
limit,
|
|
320
|
-
offset,
|
|
321
|
-
});
|
|
322
|
-
return {
|
|
323
|
-
content: [
|
|
324
|
-
{
|
|
325
|
-
type: 'text',
|
|
326
|
-
text: truncateToLimit(
|
|
327
|
-
JSON.stringify(result, null, 2),
|
|
328
|
-
),
|
|
329
|
-
},
|
|
330
|
-
],
|
|
331
|
-
};
|
|
332
|
-
}
|
|
333
|
-
case 'github_create_issue': {
|
|
334
|
-
const rawArgs = request.params.arguments ?? {};
|
|
335
|
-
const args = createIssueSchema.parse(rawArgs);
|
|
336
|
-
const result = await createIssue(args);
|
|
337
|
-
return {
|
|
338
|
-
content: [
|
|
339
|
-
{
|
|
340
|
-
type: 'text',
|
|
341
|
-
text: formatMarkdownSection(
|
|
342
|
-
result.title,
|
|
343
|
-
JSON.stringify(result, null, 2),
|
|
344
|
-
),
|
|
345
|
-
},
|
|
346
|
-
],
|
|
347
|
-
};
|
|
348
|
-
}
|
|
349
|
-
case 'github_get_pull_request': {
|
|
350
|
-
const rawArgs = request.params.arguments ?? {};
|
|
351
|
-
const args = getPullRequestSchema.parse(rawArgs);
|
|
352
|
-
const result = await getPullRequest(args);
|
|
353
|
-
return {
|
|
354
|
-
content: [
|
|
355
|
-
{
|
|
356
|
-
type: 'text',
|
|
357
|
-
text: formatMarkdownSection(
|
|
358
|
-
result.title,
|
|
359
|
-
JSON.stringify(result, null, 2),
|
|
360
|
-
),
|
|
361
|
-
},
|
|
362
|
-
],
|
|
363
|
-
};
|
|
364
|
-
}
|
|
365
|
-
case 'github_list_pull_requests': {
|
|
366
|
-
const rawArgs = request.params.arguments ?? {};
|
|
367
|
-
const args = listPullRequestsSchema.parse(rawArgs);
|
|
368
|
-
const limit = args.limit;
|
|
369
|
-
const offset = args.offset;
|
|
370
|
-
const result = await listPullRequests({
|
|
371
|
-
owner: args.owner,
|
|
372
|
-
repo: args.repo,
|
|
373
|
-
state: args.state,
|
|
374
|
-
limit,
|
|
375
|
-
offset,
|
|
376
|
-
});
|
|
377
|
-
return {
|
|
378
|
-
content: [
|
|
379
|
-
{
|
|
380
|
-
type: 'text',
|
|
381
|
-
text: truncateToLimit(
|
|
382
|
-
JSON.stringify(result, null, 2),
|
|
383
|
-
),
|
|
384
|
-
},
|
|
385
|
-
],
|
|
386
|
-
};
|
|
387
|
-
}
|
|
388
|
-
default:
|
|
389
|
-
throw new Error(`Unknown tool: ${request.params.name}`);
|
|
390
|
-
}
|
|
391
|
-
} catch (error: unknown) {
|
|
392
|
-
if (error instanceof z.ZodError) {
|
|
393
|
-
return createValidationError('Arguments', error.message);
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
const isMcpError = (err: unknown): err is CallToolResult =>
|
|
397
|
-
!!err &&
|
|
398
|
-
typeof err === 'object' &&
|
|
399
|
-
'isError' in err &&
|
|
400
|
-
(err as Record<string, unknown>).isError === true &&
|
|
401
|
-
'content' in err &&
|
|
402
|
-
Array.isArray((err as Record<string, unknown>).content);
|
|
403
|
-
|
|
404
|
-
if (isMcpError(error)) {
|
|
405
|
-
return error;
|
|
406
|
-
}
|
|
407
|
-
return createInternalError(error);
|
|
408
|
-
}
|
|
409
|
-
});
|
|
410
|
-
|
|
411
|
-
async function run() {
|
|
412
|
-
const transport = new StdioServerTransport();
|
|
413
|
-
await server.connect(transport);
|
|
414
|
-
console.error('GitHub MCP server running on stdio');
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
if (import.meta.url === pathToFileURL(process.argv[1]).href) {
|
|
418
|
-
run().catch(console.error);
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
export { server };
|
package/tsconfig.json
DELETED