Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit abd040f

Browse files
committed
feat: add Gitee error handling and MCP server implementation
Signed-off-by: 诺墨 <[email protected]>
1 parent 7311fe9 commit abd040f

File tree

3 files changed

+137
-0
lines changed

3 files changed

+137
-0
lines changed

common/errors.ts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
export class GiteeError extends Error {
2+
constructor(message: string) {
3+
super(message);
4+
this.name = "GiteeError";
5+
}
6+
}
7+
8+
export function isGiteeError(error: unknown): error is GiteeError {
9+
return error instanceof GiteeError;
10+
}
11+
12+
export function createGiteeError(status: number, responseBody: unknown): GiteeError {
13+
let message = "Gitee API 请求失败";
14+
let resetAt: Date | undefined;
15+
16+
if (typeof responseBody === "object" && responseBody !== null) {
17+
const body = responseBody as Record<string, unknown>;
18+
19+
if (body.message && typeof body.message === "string") {
20+
message = body.message;
21+
}
22+
23+
if (body.documentation_url && typeof body.documentation_url === "string") {
24+
message += ` - 文档: ${body.documentation_url}`;
25+
}
26+
}
27+
28+
switch (status) {
29+
case 400:
30+
return new GiteeValidationError(message, responseBody);
31+
case 401:
32+
return new GiteeAuthenticationError(message);
33+
case 403:
34+
return new GiteePermissionError(message);
35+
case 404:
36+
return new GiteeResourceNotFoundError(message);
37+
case 409:
38+
return new GiteeConflictError(message);
39+
case 429:
40+
return new GiteeRateLimitError(
41+
message,
42+
resetAt || new Date(Date.now() + 60 * 1000) // 默认 1 分钟后重置
43+
);
44+
default:
45+
return new GiteeError(message);
46+
}
47+
}

common/server.ts

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
2+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3+
import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
4+
import { z } from 'zod';
5+
import { zodToJsonSchema } from 'zod-to-json-schema';
6+
import { isGiteeError } from "./errors.js";
7+
8+
type MCPServerOptions = {
9+
name: string;
10+
version: string;
11+
};
12+
13+
type ToolDefinition = {
14+
name: string;
15+
description: string;
16+
schema: z.ZodType<any, any, any>;
17+
handler: (params: any) => Promise<any>;
18+
};
19+
20+
export class MCPServer {
21+
private server: Server;
22+
private tools: Map<string, ToolDefinition> = new Map();
23+
24+
constructor(options: MCPServerOptions) {
25+
this.server = new Server(
26+
{
27+
name: options.name,
28+
version: options.version,
29+
},
30+
{
31+
capabilities: {
32+
tools: {},
33+
},
34+
}
35+
);
36+
37+
this.setupRequestHandlers();
38+
}
39+
40+
private setupRequestHandlers() {
41+
this.server.setRequestHandler(ListToolsRequestSchema, async () => {
42+
const toolsList = Array.from(this.tools.values()).map((tool) => ({
43+
name: tool.name,
44+
description: tool.description,
45+
inputSchema: zodToJsonSchema(tool.schema),
46+
}));
47+
48+
return {
49+
tools: toolsList,
50+
};
51+
});
52+
53+
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
54+
try {
55+
if (!request.params.arguments) {
56+
throw new Error("Parameters are necessary.");
57+
}
58+
59+
const tool = this.tools.get(request.params.name);
60+
if (!tool) {
61+
throw new Error(`Unknown tool: ${request.params.name}`);
62+
}
63+
64+
const args = tool.schema.parse(request.params.arguments);
65+
const result = await tool.handler(args);
66+
67+
return {
68+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
69+
};
70+
} catch (error) {
71+
if (error instanceof z.ZodError) {
72+
throw new Error(`Invalid input: ${JSON.stringify(error.errors)}`);
73+
}
74+
if (isGiteeError(error)) {
75+
throw error;
76+
}
77+
throw error;
78+
}
79+
});
80+
}
81+
82+
public registerTool(tool: ToolDefinition) {
83+
this.tools.set(tool.name, tool);
84+
}
85+
86+
public async connect(transport: StdioServerTransport) {
87+
await this.server.connect(transport);
88+
}
89+
}

common/version.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export const VERSION = "0.1.0";

0 commit comments

Comments
 (0)