@ric_/forgejo-mcp 0.1.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.
Files changed (55) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +302 -0
  3. package/dist/client.d.ts +35 -0
  4. package/dist/client.d.ts.map +1 -0
  5. package/dist/client.js +107 -0
  6. package/dist/client.js.map +1 -0
  7. package/dist/config.d.ts +10 -0
  8. package/dist/config.d.ts.map +1 -0
  9. package/dist/config.js +86 -0
  10. package/dist/config.js.map +1 -0
  11. package/dist/http.d.ts +3 -0
  12. package/dist/http.d.ts.map +1 -0
  13. package/dist/http.js +108 -0
  14. package/dist/http.js.map +1 -0
  15. package/dist/index.d.ts +3 -0
  16. package/dist/index.d.ts.map +1 -0
  17. package/dist/index.js +16 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/server.d.ts +4 -0
  20. package/dist/server.d.ts.map +1 -0
  21. package/dist/server.js +27 -0
  22. package/dist/server.js.map +1 -0
  23. package/dist/tools/admin.d.ts +4 -0
  24. package/dist/tools/admin.d.ts.map +1 -0
  25. package/dist/tools/admin.js +261 -0
  26. package/dist/tools/admin.js.map +1 -0
  27. package/dist/tools/helpers.d.ts +16 -0
  28. package/dist/tools/helpers.d.ts.map +1 -0
  29. package/dist/tools/helpers.js +30 -0
  30. package/dist/tools/helpers.js.map +1 -0
  31. package/dist/tools/issues.d.ts +4 -0
  32. package/dist/tools/issues.d.ts.map +1 -0
  33. package/dist/tools/issues.js +337 -0
  34. package/dist/tools/issues.js.map +1 -0
  35. package/dist/tools/organizations.d.ts +4 -0
  36. package/dist/tools/organizations.d.ts.map +1 -0
  37. package/dist/tools/organizations.js +232 -0
  38. package/dist/tools/organizations.js.map +1 -0
  39. package/dist/tools/pullrequests.d.ts +4 -0
  40. package/dist/tools/pullrequests.d.ts.map +1 -0
  41. package/dist/tools/pullrequests.js +251 -0
  42. package/dist/tools/pullrequests.js.map +1 -0
  43. package/dist/tools/repository.d.ts +4 -0
  44. package/dist/tools/repository.d.ts.map +1 -0
  45. package/dist/tools/repository.js +437 -0
  46. package/dist/tools/repository.js.map +1 -0
  47. package/dist/tools/users.d.ts +4 -0
  48. package/dist/tools/users.d.ts.map +1 -0
  49. package/dist/tools/users.js +204 -0
  50. package/dist/tools/users.js.map +1 -0
  51. package/dist/validation.d.ts +35 -0
  52. package/dist/validation.d.ts.map +1 -0
  53. package/dist/validation.js +68 -0
  54. package/dist/validation.js.map +1 -0
  55. package/package.json +49 -0
package/dist/http.js ADDED
@@ -0,0 +1,108 @@
1
+ #!/usr/bin/env node
2
+ import { createServer as createHttpServer } from "node:http";
3
+ import { randomUUID } from "node:crypto";
4
+ import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
5
+ import { parseCliArgs, resolveConfig } from "./config.js";
6
+ import { createServer } from "./server.js";
7
+ /** Simple in-memory rate limiter per IP */
8
+ class RateLimiter {
9
+ requests = new Map();
10
+ maxRequests;
11
+ windowMs;
12
+ constructor(maxRequests = 100, windowMs = 60_000) {
13
+ this.maxRequests = maxRequests;
14
+ this.windowMs = windowMs;
15
+ }
16
+ isAllowed(ip) {
17
+ const now = Date.now();
18
+ const entry = this.requests.get(ip);
19
+ if (!entry || now > entry.resetAt) {
20
+ this.requests.set(ip, { count: 1, resetAt: now + this.windowMs });
21
+ return true;
22
+ }
23
+ entry.count++;
24
+ return entry.count <= this.maxRequests;
25
+ }
26
+ /** Periodically clean up expired entries */
27
+ cleanup() {
28
+ const now = Date.now();
29
+ for (const [ip, entry] of this.requests) {
30
+ if (now > entry.resetAt) {
31
+ this.requests.delete(ip);
32
+ }
33
+ }
34
+ }
35
+ }
36
+ async function main() {
37
+ const cliArgs = parseCliArgs(process.argv.slice(2));
38
+ const config = resolveConfig(cliArgs);
39
+ const port = cliArgs.port || parseInt(process.env.PORT || "3000", 10);
40
+ // Optional bearer token for HTTP endpoint authentication
41
+ const apiKey = process.env.FORGEJO_MCP_API_KEY;
42
+ if (!apiKey) {
43
+ console.error("WARNING: No FORGEJO_MCP_API_KEY set. The HTTP endpoint is UNAUTHENTICATED.\n" +
44
+ " Anyone who can reach this server will have full access to your Forgejo token's permissions.\n" +
45
+ " Set FORGEJO_MCP_API_KEY to require Bearer token authentication.\n" +
46
+ " Only run unauthenticated on localhost or behind a reverse proxy with its own auth.");
47
+ }
48
+ const server = createServer(config);
49
+ const rateLimiter = new RateLimiter(parseInt(process.env.RATE_LIMIT_MAX || "100", 10), parseInt(process.env.RATE_LIMIT_WINDOW_MS || "60000", 10));
50
+ // Cleanup rate limiter every 5 minutes
51
+ setInterval(() => rateLimiter.cleanup(), 300_000).unref();
52
+ const transport = new StreamableHTTPServerTransport({
53
+ sessionIdGenerator: () => randomUUID(),
54
+ });
55
+ await server.connect(transport);
56
+ const httpServer = createHttpServer(async (req, res) => {
57
+ const url = new URL(req.url || "/", `http://localhost:${port}`);
58
+ const clientIp = req.socket.remoteAddress || "unknown";
59
+ // Rate limiting
60
+ if (!rateLimiter.isAllowed(clientIp)) {
61
+ res.writeHead(429, { "Content-Type": "application/json" });
62
+ res.end(JSON.stringify({ error: "Too many requests" }));
63
+ return;
64
+ }
65
+ // Authentication check for MCP endpoints
66
+ if (url.pathname === "/mcp" && apiKey) {
67
+ const authHeader = req.headers.authorization;
68
+ if (!authHeader || authHeader !== `Bearer ${apiKey}`) {
69
+ res.writeHead(401, { "Content-Type": "application/json" });
70
+ res.end(JSON.stringify({ error: "Unauthorized. Provide Bearer token via Authorization header." }));
71
+ return;
72
+ }
73
+ }
74
+ // Security headers
75
+ res.setHeader("X-Content-Type-Options", "nosniff");
76
+ res.setHeader("X-Frame-Options", "DENY");
77
+ if (url.pathname === "/mcp" && req.method === "POST") {
78
+ await transport.handleRequest(req, res);
79
+ }
80
+ else if (url.pathname === "/mcp" && req.method === "GET") {
81
+ await transport.handleRequest(req, res);
82
+ }
83
+ else if (url.pathname === "/mcp" && req.method === "DELETE") {
84
+ await transport.handleRequest(req, res);
85
+ }
86
+ else if (url.pathname === "/health") {
87
+ res.writeHead(200, { "Content-Type": "application/json" });
88
+ res.end(JSON.stringify({ status: "ok", version: "0.1.0" }));
89
+ }
90
+ else {
91
+ res.writeHead(404, { "Content-Type": "application/json" });
92
+ res.end(JSON.stringify({ error: "Not found" }));
93
+ }
94
+ });
95
+ httpServer.listen(port, () => {
96
+ console.error(`Forgejo MCP server (HTTP) listening on port ${port}`);
97
+ console.error(` MCP endpoint: http://localhost:${port}/mcp`);
98
+ console.error(` Health check: http://localhost:${port}/health`);
99
+ console.error(` Connected to: ${config.baseUrl}`);
100
+ console.error(` Authentication: ${apiKey ? "enabled (Bearer token)" : "DISABLED"}`);
101
+ console.error(` Rate limiting: ${process.env.RATE_LIMIT_MAX || "100"} req/min per IP`);
102
+ });
103
+ }
104
+ main().catch((error) => {
105
+ console.error("Fatal error:", error);
106
+ process.exit(1);
107
+ });
108
+ //# sourceMappingURL=http.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"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"}
@@ -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,16 @@
1
+ #!/usr/bin/env node
2
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
+ import { parseCliArgs, resolveConfig } from "./config.js";
4
+ import { createServer } from "./server.js";
5
+ async function main() {
6
+ const cliArgs = parseCliArgs(process.argv.slice(2));
7
+ const config = resolveConfig(cliArgs);
8
+ const server = createServer(config);
9
+ const transport = new StdioServerTransport();
10
+ await server.connect(transport);
11
+ }
12
+ main().catch((error) => {
13
+ console.error("Fatal error:", error);
14
+ process.exit(1);
15
+ });
16
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,KAAK,UAAU,IAAI;IACjB,MAAM,OAAO,GAAG,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACpD,MAAM,MAAM,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;IACtC,MAAM,MAAM,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;IAEpC,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AAClC,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;IACrC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import type { ForgejoConfig } from "./config.js";
3
+ export declare function createServer(config: ForgejoConfig): McpServer;
4
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAQjD,wBAAgB,YAAY,CAAC,MAAM,EAAE,aAAa,GAAG,SAAS,CAuB7D"}
package/dist/server.js ADDED
@@ -0,0 +1,27 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { ForgejoClient } from "./client.js";
3
+ import { registerRepositoryTools } from "./tools/repository.js";
4
+ import { registerIssueTools } from "./tools/issues.js";
5
+ import { registerPullRequestTools } from "./tools/pullrequests.js";
6
+ import { registerOrganizationTools } from "./tools/organizations.js";
7
+ import { registerUserTools } from "./tools/users.js";
8
+ import { registerAdminTools } from "./tools/admin.js";
9
+ export function createServer(config) {
10
+ const server = new McpServer({
11
+ name: "forgejo-mcp",
12
+ version: "0.1.0",
13
+ }, {
14
+ capabilities: {
15
+ logging: {},
16
+ },
17
+ });
18
+ const client = new ForgejoClient(config);
19
+ registerRepositoryTools(server, client);
20
+ registerIssueTools(server, client);
21
+ registerPullRequestTools(server, client);
22
+ registerOrganizationTools(server, client);
23
+ registerUserTools(server, client);
24
+ registerAdminTools(server, client);
25
+ return server;
26
+ }
27
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAC;AACrE,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAEtD,MAAM,UAAU,YAAY,CAAC,MAAqB;IAChD,MAAM,MAAM,GAAG,IAAI,SAAS,CAC1B;QACE,IAAI,EAAE,aAAa;QACnB,OAAO,EAAE,OAAO;KACjB,EACD;QACE,YAAY,EAAE;YACZ,OAAO,EAAE,EAAE;SACZ;KACF,CACF,CAAC;IAEF,MAAM,MAAM,GAAG,IAAI,aAAa,CAAC,MAAM,CAAC,CAAC;IAEzC,uBAAuB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxC,kBAAkB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,wBAAwB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,yBAAyB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1C,iBAAiB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,kBAAkB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAEnC,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { ForgejoClient } from "../client.js";
3
+ export declare function registerAdminTools(server: McpServer, client: ForgejoClient): void;
4
+ //# sourceMappingURL=admin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"admin.d.ts","sourceRoot":"","sources":["../../src/tools/admin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAI7C,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,GAAG,IAAI,CA8VjF"}
@@ -0,0 +1,261 @@
1
+ import { z } from "zod";
2
+ import { formatResponse, formatError } from "./helpers.js";
3
+ import { zOwner, zPage, zLimit, zTemplateName, zMarkdownMode } from "../validation.js";
4
+ export function registerAdminTools(server, client) {
5
+ // ── Admin tools (require admin token) ──────────────────────────────
6
+ // 1. admin_list_users
7
+ server.tool("admin_list_users", "List all users (requires admin privileges)", {
8
+ page: zPage,
9
+ limit: zLimit,
10
+ }, async (params) => {
11
+ try {
12
+ const data = await client.get("/admin/users", {
13
+ page: params.page,
14
+ limit: params.limit,
15
+ });
16
+ return formatResponse(data);
17
+ }
18
+ catch (err) {
19
+ return formatError(err);
20
+ }
21
+ });
22
+ // 2. admin_create_user
23
+ server.tool("admin_create_user", "Create a new user (requires admin privileges)", {
24
+ username: zOwner.describe("Username for the new user"),
25
+ email: z.string().email().describe("Email address for the new user"),
26
+ password: z.string().min(6).max(255).describe("Password for the new user"),
27
+ must_change_password: z.boolean().optional().describe("Whether the user must change password on first login"),
28
+ }, async (params) => {
29
+ try {
30
+ const data = await client.post("/admin/users", {
31
+ username: params.username,
32
+ email: params.email,
33
+ password: params.password,
34
+ must_change_password: params.must_change_password,
35
+ });
36
+ return formatResponse(data);
37
+ }
38
+ catch (err) {
39
+ return formatError(err);
40
+ }
41
+ });
42
+ // 3. admin_delete_user
43
+ server.tool("admin_delete_user", "Delete a user (requires admin privileges)", {
44
+ username: zOwner.describe("Username of the user to delete"),
45
+ }, async (params) => {
46
+ try {
47
+ const data = await client.delete(`/admin/users/${params.username}`);
48
+ return formatResponse(data ?? "User deleted successfully");
49
+ }
50
+ catch (err) {
51
+ return formatError(err);
52
+ }
53
+ });
54
+ // 4. admin_edit_user
55
+ server.tool("admin_edit_user", "Edit an existing user (requires admin privileges)", {
56
+ username: zOwner.describe("Username of the user to edit"),
57
+ email: z.string().email().optional().describe("New email address for the user"),
58
+ active: z.boolean().optional().describe("Whether the user account is active"),
59
+ admin: z.boolean().optional().describe("Whether the user has admin privileges"),
60
+ }, async (params) => {
61
+ try {
62
+ const body = {};
63
+ if (params.email !== undefined)
64
+ body.email = params.email;
65
+ if (params.active !== undefined)
66
+ body.active = params.active;
67
+ if (params.admin !== undefined)
68
+ body.admin = params.admin;
69
+ const data = await client.patch(`/admin/users/${params.username}`, body);
70
+ return formatResponse(data);
71
+ }
72
+ catch (err) {
73
+ return formatError(err);
74
+ }
75
+ });
76
+ // 5. admin_list_cron_jobs
77
+ server.tool("admin_list_cron_jobs", "List all cron jobs (requires admin privileges)", {}, async () => {
78
+ try {
79
+ const data = await client.get("/admin/cron");
80
+ return formatResponse(data);
81
+ }
82
+ catch (err) {
83
+ return formatError(err);
84
+ }
85
+ });
86
+ // 6. admin_run_cron_job
87
+ server.tool("admin_run_cron_job", "Run a cron task by name (requires admin privileges)", {
88
+ task: zTemplateName.describe("Name of the cron task to run"),
89
+ }, async (params) => {
90
+ try {
91
+ const data = await client.post(`/admin/cron/${params.task}`);
92
+ return formatResponse(data ?? "Cron job triggered successfully");
93
+ }
94
+ catch (err) {
95
+ return formatError(err);
96
+ }
97
+ });
98
+ // 7. admin_list_hooks
99
+ server.tool("admin_list_hooks", "List system webhooks (requires admin privileges)", {}, async () => {
100
+ try {
101
+ const data = await client.get("/admin/hooks");
102
+ return formatResponse(data);
103
+ }
104
+ catch (err) {
105
+ return formatError(err);
106
+ }
107
+ });
108
+ // ── Miscellaneous tools ────────────────────────────────────────────
109
+ // 8. get_server_version
110
+ server.tool("get_server_version", "Get the Forgejo server version", {}, async () => {
111
+ try {
112
+ const data = await client.get("/version");
113
+ return formatResponse(data);
114
+ }
115
+ catch (err) {
116
+ return formatError(err);
117
+ }
118
+ });
119
+ // 9. render_markdown
120
+ server.tool("render_markdown", "Render markdown text to HTML", {
121
+ text: z.string().max(1_000_000).describe("Markdown text to render"),
122
+ mode: zMarkdownMode.describe("Render mode: gfm, comment, or plain"),
123
+ context: z.string().max(255).optional().describe("Context for resolving relative links (e.g. owner/repo)"),
124
+ }, async (params) => {
125
+ try {
126
+ const data = await client.post("/markdown", {
127
+ Text: params.text,
128
+ Mode: params.mode,
129
+ Context: params.context,
130
+ });
131
+ return formatResponse(data);
132
+ }
133
+ catch (err) {
134
+ return formatError(err);
135
+ }
136
+ });
137
+ // 10. render_markup
138
+ server.tool("render_markup", "Render markup text to HTML", {
139
+ text: z.string().max(1_000_000).describe("Markup text to render"),
140
+ mode: z.string().max(50).optional().describe("Render mode"),
141
+ context: z.string().max(255).optional().describe("Context for resolving relative links"),
142
+ wiki: z.boolean().optional().describe("Whether the content is wiki content"),
143
+ }, async (params) => {
144
+ try {
145
+ const data = await client.post("/markup", {
146
+ Text: params.text,
147
+ Mode: params.mode,
148
+ Context: params.context,
149
+ Wiki: params.wiki,
150
+ });
151
+ return formatResponse(data);
152
+ }
153
+ catch (err) {
154
+ return formatError(err);
155
+ }
156
+ });
157
+ // 11. list_gitignore_templates
158
+ server.tool("list_gitignore_templates", "List all available gitignore templates", {}, async () => {
159
+ try {
160
+ const data = await client.get("/gitignore/templates");
161
+ return formatResponse(data);
162
+ }
163
+ catch (err) {
164
+ return formatError(err);
165
+ }
166
+ });
167
+ // 12. get_gitignore_template
168
+ server.tool("get_gitignore_template", "Get a specific gitignore template by name", {
169
+ name: zTemplateName.describe("Name of the gitignore template"),
170
+ }, async (params) => {
171
+ try {
172
+ const data = await client.get(`/gitignore/templates/${params.name}`);
173
+ return formatResponse(data);
174
+ }
175
+ catch (err) {
176
+ return formatError(err);
177
+ }
178
+ });
179
+ // 13. list_license_templates
180
+ server.tool("list_license_templates", "List all available license templates", {}, async () => {
181
+ try {
182
+ const data = await client.get("/licenses");
183
+ return formatResponse(data);
184
+ }
185
+ catch (err) {
186
+ return formatError(err);
187
+ }
188
+ });
189
+ // 14. get_license_template
190
+ server.tool("get_license_template", "Get a specific license template by name", {
191
+ name: zTemplateName.describe("Name of the license template"),
192
+ }, async (params) => {
193
+ try {
194
+ const data = await client.get(`/licenses/${params.name}`);
195
+ return formatResponse(data);
196
+ }
197
+ catch (err) {
198
+ return formatError(err);
199
+ }
200
+ });
201
+ // 15. list_label_templates
202
+ server.tool("list_label_templates", "List all available label templates", {}, async () => {
203
+ try {
204
+ const data = await client.get("/label/templates");
205
+ return formatResponse(data);
206
+ }
207
+ catch (err) {
208
+ return formatError(err);
209
+ }
210
+ });
211
+ // 16. get_label_template
212
+ server.tool("get_label_template", "Get a specific label template by name", {
213
+ name: zTemplateName.describe("Name of the label template"),
214
+ }, async (params) => {
215
+ try {
216
+ const data = await client.get(`/label/templates/${params.name}`);
217
+ return formatResponse(data);
218
+ }
219
+ catch (err) {
220
+ return formatError(err);
221
+ }
222
+ });
223
+ // 17. get_nodeinfo
224
+ server.tool("get_nodeinfo", "Get the Forgejo instance NodeInfo", {}, async () => {
225
+ try {
226
+ const data = await client.get("/nodeinfo");
227
+ return formatResponse(data);
228
+ }
229
+ catch (err) {
230
+ return formatError(err);
231
+ }
232
+ });
233
+ // ── Actions tools ──────────────────────────────────────────────────
234
+ // 18. list_action_runners_jobs
235
+ server.tool("list_action_runners_jobs", "List action runner jobs (requires admin privileges)", {
236
+ page: zPage,
237
+ limit: zLimit,
238
+ }, async (params) => {
239
+ try {
240
+ const data = await client.get("/admin/runners/jobs", {
241
+ page: params.page,
242
+ limit: params.limit,
243
+ });
244
+ return formatResponse(data);
245
+ }
246
+ catch (err) {
247
+ return formatError(err);
248
+ }
249
+ });
250
+ // 19. get_runner_registration_token
251
+ server.tool("get_runner_registration_token", "Get a runner registration token (requires admin privileges)", {}, async () => {
252
+ try {
253
+ const data = await client.get("/admin/runners/registration-token");
254
+ return formatResponse(data);
255
+ }
256
+ catch (err) {
257
+ return formatError(err);
258
+ }
259
+ });
260
+ }
261
+ //# sourceMappingURL=admin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"admin.js","sourceRoot":"","sources":["../../src/tools/admin.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import type { ForgejoClient } from "../client.js";
2
+ export type ToolHandler<TInput, TOutput> = (client: ForgejoClient, input: TInput) => Promise<TOutput>;
3
+ export declare function formatResponse(data: unknown): {
4
+ content: Array<{
5
+ type: "text";
6
+ text: string;
7
+ }>;
8
+ };
9
+ export declare function formatError(error: unknown): {
10
+ content: Array<{
11
+ type: "text";
12
+ text: string;
13
+ }>;
14
+ isError: true;
15
+ };
16
+ //# sourceMappingURL=helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/tools/helpers.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAElD,MAAM,MAAM,WAAW,CAAC,MAAM,EAAE,OAAO,IAAI,CACzC,MAAM,EAAE,aAAa,EACrB,KAAK,EAAE,MAAM,KACV,OAAO,CAAC,OAAO,CAAC,CAAC;AAEtB,wBAAgB,cAAc,CAAC,IAAI,EAAE,OAAO,GAAG;IAAE,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,CAShG;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG;IAAE,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAAC,OAAO,EAAE,IAAI,CAAA;CAAE,CAiB7G"}
@@ -0,0 +1,30 @@
1
+ import { ForgejoApiError } from "../client.js";
2
+ export function formatResponse(data) {
3
+ return {
4
+ content: [
5
+ {
6
+ type: "text",
7
+ text: typeof data === "string" ? data : JSON.stringify(data, null, 2),
8
+ },
9
+ ],
10
+ };
11
+ }
12
+ export function formatError(error) {
13
+ let message;
14
+ if (error instanceof ForgejoApiError) {
15
+ // API errors are safe to expose (status + server message, URL is already sanitized)
16
+ message = error.message;
17
+ }
18
+ else if (error instanceof Error) {
19
+ // For unexpected errors, don't leak internals
20
+ message = error.message;
21
+ }
22
+ else {
23
+ message = "An unexpected error occurred";
24
+ }
25
+ return {
26
+ content: [{ type: "text", text: `Error: ${message}` }],
27
+ isError: true,
28
+ };
29
+ }
30
+ //# sourceMappingURL=helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../src/tools/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAQ/C,MAAM,UAAU,cAAc,CAAC,IAAa;IAC1C,OAAO;QACL,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,MAAe;gBACrB,IAAI,EAAE,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;aACtE;SACF;KACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,KAAc;IACxC,IAAI,OAAe,CAAC;IAEpB,IAAI,KAAK,YAAY,eAAe,EAAE,CAAC;QACrC,oFAAoF;QACpF,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;IAC1B,CAAC;SAAM,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;QAClC,8CAA8C;QAC9C,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;IAC1B,CAAC;SAAM,CAAC;QACN,OAAO,GAAG,8BAA8B,CAAC;IAC3C,CAAC;IAED,OAAO;QACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,UAAU,OAAO,EAAE,EAAE,CAAC;QAC/D,OAAO,EAAE,IAAI;KACd,CAAC;AACJ,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { ForgejoClient } from "../client.js";
3
+ export declare function registerIssueTools(server: McpServer, client: ForgejoClient): void;
4
+ //# sourceMappingURL=issues.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"issues.d.ts","sourceRoot":"","sources":["../../src/tools/issues.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAI7C,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,GAAG,IAAI,CA+ajF"}