@mokoconsulting/mcp-mokogitea-api 1.4.0 → 1.4.1

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/dist/index.js CHANGED
@@ -1114,14 +1114,22 @@ server.tool('gitea_metadata_update', 'Update repo metadata settings (merges with
1114
1114
  repo: z.string().describe('Repository name'),
1115
1115
  name: z.string().optional().describe('Project name'),
1116
1116
  org: z.string().optional().describe('Organization'),
1117
+ description: z.string().optional().describe('Project description'),
1117
1118
  version: z.string().optional().describe('Version string (e.g. 06.00.00)'),
1118
1119
  version_prefix: z.string().optional().describe('Tag prefix for version display (e.g. v1.26.1-moko.)'),
1119
1120
  license_spdx: z.string().optional().describe('SPDX license identifier'),
1121
+ license_name: z.string().optional().describe('Human-readable license name (e.g. GNU General Public License v3)'),
1122
+ element_name: z.string().optional().describe('Extension element name (e.g. pkg_mokosuitecrm, mod_mokojoomhero)'),
1120
1123
  platform: z.string().optional().describe('Platform (joomla, wordpress, dolibarr, go, mcp, platform, generic)'),
1124
+ standards_version: z.string().optional().describe('mokoplatform standards version (e.g. 05.01.00)'),
1125
+ standards_source: z.string().optional().describe('URL to standards repo'),
1126
+ maintainer: z.string().optional().describe('Maintainer name (e.g. Moko Consulting)'),
1127
+ maintainer_url: z.string().optional().describe('Maintainer website URL'),
1121
1128
  info_url: z.string().optional().describe('Extension info/product page URL'),
1122
- target_version: z.string().optional().describe('Target platform version regex (e.g. (5|6)\\.*)'),
1129
+ target_version: z.string().optional().describe('Target platform version regex (e.g. 6..*)'),
1123
1130
  php_minimum: z.string().optional().describe('Minimum PHP version (e.g. 8.1)'),
1124
- package_type: z.string().optional().describe('Extension type (component, module, plugin, package, template, library, file)'),
1131
+ language: z.string().optional().describe('Primary language (e.g. PHP, Go, TypeScript)'),
1132
+ extension_type: z.string().optional().describe('Extension type (component, module, plugin, package, template, library, file)'),
1125
1133
  entry_point: z.string().optional().describe('Build entry point path'),
1126
1134
  ...ConnectionParam,
1127
1135
  }, async ({ owner, repo, connection, ...fields }) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mokoconsulting/mcp-mokogitea-api",
3
- "version": "1.4.0",
3
+ "version": "1.4.1",
4
4
  "description": "MCP server for Gitea REST API v1 operations",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
package/src/client.ts CHANGED
@@ -52,7 +52,21 @@ export class GiteaClient {
52
52
  }
53
53
 
54
54
  async delete(endpoint: string, body?: unknown): Promise<ApiResponse> {
55
- return this.request(this.buildUrl(endpoint), 'DELETE', body);
55
+ if (body === undefined) {
56
+ return this.request(this.buildUrl(endpoint), 'DELETE');
57
+ }
58
+ // Use fetch for DELETE+body — node:https drops the body on some
59
+ // proxy/TLS configurations, causing the server to see an empty request.
60
+ const url = this.buildUrl(endpoint);
61
+ const resp = await fetch(url, {
62
+ method: 'DELETE',
63
+ headers: { ...this.headers },
64
+ body: JSON.stringify(body),
65
+ });
66
+ const raw = await resp.text();
67
+ let data: unknown;
68
+ try { data = JSON.parse(raw); } catch { data = raw; }
69
+ return { status: resp.status, data };
56
70
  }
57
71
 
58
72
  private buildUrl(endpoint: string, params?: Record<string, string>): string {
package/src/index.ts CHANGED
@@ -1720,14 +1720,22 @@ server.tool(
1720
1720
  repo: z.string().describe('Repository name'),
1721
1721
  name: z.string().optional().describe('Project name'),
1722
1722
  org: z.string().optional().describe('Organization'),
1723
+ description: z.string().optional().describe('Project description'),
1723
1724
  version: z.string().optional().describe('Version string (e.g. 06.00.00)'),
1724
1725
  version_prefix: z.string().optional().describe('Tag prefix for version display (e.g. v1.26.1-moko.)'),
1725
1726
  license_spdx: z.string().optional().describe('SPDX license identifier'),
1727
+ license_name: z.string().optional().describe('Human-readable license name (e.g. GNU General Public License v3)'),
1728
+ element_name: z.string().optional().describe('Extension element name (e.g. pkg_mokosuitecrm, mod_mokojoomhero)'),
1726
1729
  platform: z.string().optional().describe('Platform (joomla, wordpress, dolibarr, go, mcp, platform, generic)'),
1730
+ standards_version: z.string().optional().describe('mokoplatform standards version (e.g. 05.01.00)'),
1731
+ standards_source: z.string().optional().describe('URL to standards repo'),
1732
+ maintainer: z.string().optional().describe('Maintainer name (e.g. Moko Consulting)'),
1733
+ maintainer_url: z.string().optional().describe('Maintainer website URL'),
1727
1734
  info_url: z.string().optional().describe('Extension info/product page URL'),
1728
- target_version: z.string().optional().describe('Target platform version regex (e.g. (5|6)\\.*)'),
1735
+ target_version: z.string().optional().describe('Target platform version regex (e.g. 6..*)'),
1729
1736
  php_minimum: z.string().optional().describe('Minimum PHP version (e.g. 8.1)'),
1730
- package_type: z.string().optional().describe('Extension type (component, module, plugin, package, template, library, file)'),
1737
+ language: z.string().optional().describe('Primary language (e.g. PHP, Go, TypeScript)'),
1738
+ extension_type: z.string().optional().describe('Extension type (component, module, plugin, package, template, library, file)'),
1731
1739
  entry_point: z.string().optional().describe('Build entry point path'),
1732
1740
  ...ConnectionParam,
1733
1741
  },
package/Dockerfile DELETED
@@ -1,18 +0,0 @@
1
- FROM node:20-alpine
2
-
3
- WORKDIR /app
4
-
5
- COPY package.json package-lock.json ./
6
- RUN npm ci --production=false
7
-
8
- COPY tsconfig.json ./
9
- COPY src/ ./src/
10
- RUN npx tsc && npm prune --production
11
-
12
- EXPOSE 3100
13
-
14
- ENV PORT=3100
15
- ENV NODE_ENV=production
16
-
17
- # SSE mode by default for Docker deployments
18
- CMD ["node", "dist/sse.js"]
package/dist/server.d.ts DELETED
@@ -1,4 +0,0 @@
1
- import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
- import type { GiteaConfig } from './types.js';
3
- export declare function createMcpServer(cfg: GiteaConfig): McpServer;
4
- //# sourceMappingURL=server.d.ts.map
package/dist/server.js DELETED
@@ -1,12 +0,0 @@
1
- // Copyright 2026 Moko Consulting <hello@mokoconsulting.tech>
2
- // SPDX-License-Identifier: GPL-3.0-or-later
3
- //
4
- // Creates a configured MCP server instance for use by both stdio and SSE transports.
5
- // Import index.ts to register all tools on its exported `server` singleton,
6
- // then re-export a factory that initializes config and returns the server.
7
- import { server, initConfig } from './index.js';
8
- export function createMcpServer(cfg) {
9
- initConfig(cfg);
10
- return server;
11
- }
12
- //# sourceMappingURL=server.js.map
package/dist/sse.d.ts DELETED
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=sse.d.ts.map
package/dist/sse.js DELETED
@@ -1,87 +0,0 @@
1
- // Copyright 2026 Moko Consulting <hello@mokoconsulting.tech>
2
- // SPDX-License-Identifier: GPL-3.0-or-later
3
- //
4
- // SSE transport entry point for MokoGitea MCP server.
5
- // Run with: node dist/sse.js
6
- // Or: GITEA_URL=https://gitea.example.com GITEA_TOKEN=xxx node dist/sse.js
7
- //
8
- // Listens on PORT (default 3100) and serves SSE at /sse with POST at /message.
9
- import { createServer } from 'node:http';
10
- import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';
11
- import { createMcpServer } from './server.js';
12
- import { loadConfig } from './config.js';
13
- const PORT = parseInt(process.env.PORT ?? '3100', 10);
14
- async function main() {
15
- const config = await loadConfig();
16
- const transports = new Map();
17
- const httpServer = createServer(async (req, res) => {
18
- // CORS headers for browser clients
19
- res.setHeader('Access-Control-Allow-Origin', '*');
20
- res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
21
- res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
22
- if (req.method === 'OPTIONS') {
23
- res.writeHead(204);
24
- res.end();
25
- return;
26
- }
27
- // Health check
28
- if (req.url === '/health') {
29
- res.writeHead(200, { 'Content-Type': 'application/json' });
30
- res.end(JSON.stringify({ status: 'ok', tools: 120 }));
31
- return;
32
- }
33
- // SSE endpoint - client connects here
34
- if (req.url === '/sse' && req.method === 'GET') {
35
- const transport = new SSEServerTransport('/message', res);
36
- const sessionId = transport.sessionId;
37
- transports.set(sessionId, transport);
38
- const server = createMcpServer(config);
39
- await server.connect(transport);
40
- req.on('close', () => {
41
- transports.delete(sessionId);
42
- });
43
- return;
44
- }
45
- // Message endpoint - client sends tool calls here
46
- if (req.url?.startsWith('/message') && req.method === 'POST') {
47
- const url = new URL(req.url, `http://${req.headers.host}`);
48
- const sessionId = url.searchParams.get('sessionId');
49
- if (!sessionId || !transports.has(sessionId)) {
50
- res.writeHead(400, { 'Content-Type': 'application/json' });
51
- res.end(JSON.stringify({ error: 'Invalid or missing sessionId' }));
52
- return;
53
- }
54
- const transport = transports.get(sessionId);
55
- await transport.handlePostMessage(req, res);
56
- return;
57
- }
58
- // Root - info page
59
- if (req.url === '/' || req.url === '') {
60
- res.writeHead(200, { 'Content-Type': 'application/json' });
61
- res.end(JSON.stringify({
62
- name: '@mokoconsulting/mokogitea-mcp',
63
- version: '1.1.0',
64
- description: 'MCP server for Gitea and MokoGitea - 120+ tools',
65
- endpoints: {
66
- sse: '/sse',
67
- message: '/message',
68
- health: '/health',
69
- },
70
- docs: 'https://git.mokoconsulting.tech/MokoConsulting/mcp_mokogitea_api',
71
- }));
72
- return;
73
- }
74
- res.writeHead(404);
75
- res.end('Not found');
76
- });
77
- httpServer.listen(PORT, () => {
78
- process.stderr.write(`MokoGitea MCP SSE server listening on port ${PORT}\n`);
79
- process.stderr.write(` SSE: http://localhost:${PORT}/sse\n`);
80
- process.stderr.write(` Health: http://localhost:${PORT}/health\n`);
81
- });
82
- }
83
- main().catch((err) => {
84
- process.stderr.write(`Fatal: ${err}\n`);
85
- process.exit(1);
86
- });
87
- //# sourceMappingURL=sse.js.map
package/src/server.ts DELETED
@@ -1,16 +0,0 @@
1
- // Copyright 2026 Moko Consulting <hello@mokoconsulting.tech>
2
- // SPDX-License-Identifier: GPL-3.0-or-later
3
- //
4
- // Creates a configured MCP server instance for use by both stdio and SSE transports.
5
-
6
- import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
7
- import type { GiteaConfig } from './types.js';
8
-
9
- // Import index.ts to register all tools on its exported `server` singleton,
10
- // then re-export a factory that initializes config and returns the server.
11
- import { server, initConfig } from './index.js';
12
-
13
- export function createMcpServer(cfg: GiteaConfig): McpServer {
14
- initConfig(cfg);
15
- return server;
16
- }
package/src/sse.ts DELETED
@@ -1,100 +0,0 @@
1
- // Copyright 2026 Moko Consulting <hello@mokoconsulting.tech>
2
- // SPDX-License-Identifier: GPL-3.0-or-later
3
- //
4
- // SSE transport entry point for MokoGitea MCP server.
5
- // Run with: node dist/sse.js
6
- // Or: GITEA_URL=https://gitea.example.com GITEA_TOKEN=xxx node dist/sse.js
7
- //
8
- // Listens on PORT (default 3100) and serves SSE at /sse with POST at /message.
9
-
10
- import { createServer } from 'node:http';
11
- import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';
12
- import { createMcpServer } from './server.js';
13
- import { loadConfig } from './config.js';
14
-
15
- const PORT = parseInt(process.env.PORT ?? '3100', 10);
16
-
17
- async function main(): Promise<void> {
18
- const config = await loadConfig();
19
- const transports = new Map<string, SSEServerTransport>();
20
-
21
- const httpServer = createServer(async (req, res) => {
22
- // CORS headers for browser clients
23
- res.setHeader('Access-Control-Allow-Origin', '*');
24
- res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
25
- res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
26
-
27
- if (req.method === 'OPTIONS') {
28
- res.writeHead(204);
29
- res.end();
30
- return;
31
- }
32
-
33
- // Health check
34
- if (req.url === '/health') {
35
- res.writeHead(200, { 'Content-Type': 'application/json' });
36
- res.end(JSON.stringify({ status: 'ok', tools: 120 }));
37
- return;
38
- }
39
-
40
- // SSE endpoint - client connects here
41
- if (req.url === '/sse' && req.method === 'GET') {
42
- const transport = new SSEServerTransport('/message', res);
43
- const sessionId = transport.sessionId;
44
- transports.set(sessionId, transport);
45
-
46
- const server = createMcpServer(config);
47
- await server.connect(transport);
48
-
49
- req.on('close', () => {
50
- transports.delete(sessionId);
51
- });
52
- return;
53
- }
54
-
55
- // Message endpoint - client sends tool calls here
56
- if (req.url?.startsWith('/message') && req.method === 'POST') {
57
- const url = new URL(req.url, `http://${req.headers.host}`);
58
- const sessionId = url.searchParams.get('sessionId');
59
- if (!sessionId || !transports.has(sessionId)) {
60
- res.writeHead(400, { 'Content-Type': 'application/json' });
61
- res.end(JSON.stringify({ error: 'Invalid or missing sessionId' }));
62
- return;
63
- }
64
- const transport = transports.get(sessionId)!;
65
- await transport.handlePostMessage(req, res);
66
- return;
67
- }
68
-
69
- // Root - info page
70
- if (req.url === '/' || req.url === '') {
71
- res.writeHead(200, { 'Content-Type': 'application/json' });
72
- res.end(JSON.stringify({
73
- name: '@mokoconsulting/mokogitea-mcp',
74
- version: '1.1.0',
75
- description: 'MCP server for Gitea and MokoGitea - 120+ tools',
76
- endpoints: {
77
- sse: '/sse',
78
- message: '/message',
79
- health: '/health',
80
- },
81
- docs: 'https://git.mokoconsulting.tech/MokoConsulting/mcp_mokogitea_api',
82
- }));
83
- return;
84
- }
85
-
86
- res.writeHead(404);
87
- res.end('Not found');
88
- });
89
-
90
- httpServer.listen(PORT, () => {
91
- process.stderr.write(`MokoGitea MCP SSE server listening on port ${PORT}\n`);
92
- process.stderr.write(` SSE: http://localhost:${PORT}/sse\n`);
93
- process.stderr.write(` Health: http://localhost:${PORT}/health\n`);
94
- });
95
- }
96
-
97
- main().catch((err) => {
98
- process.stderr.write(`Fatal: ${err}\n`);
99
- process.exit(1);
100
- });
@@ -1,144 +0,0 @@
1
- ← [Home](Home)
2
-
3
- # Architecture
4
-
5
- ## Component Overview
6
-
7
- ```
8
- src/
9
- index.ts -- MCP server entry point, tool registrations (61 tools)
10
- client.ts -- HTTP client for Gitea REST API v1
11
- config.ts -- Configuration loader (multi-connection support)
12
- types.ts -- TypeScript type definitions
13
- ```
14
-
15
- ### index.ts -- Server Entry Point
16
-
17
- The main module that:
18
-
19
- - Creates the `McpServer` instance with stdio transport
20
- - Loads configuration on startup via `loadConfig()`
21
- - Registers all 61 tools organized by category
22
- - Provides shared parameter schemas (`OwnerRepo`, `PaginationParams`, `ConnectionParam`)
23
- - Routes tool calls through `clientFor(connection)` to resolve the target Gitea instance
24
- - Formats all API responses through `formatResponse()` for consistent MCP output
25
-
26
- ### client.ts -- HTTP Client
27
-
28
- `GiteaClient` is a zero-dependency HTTP client built on `node:https` and `node:http`:
29
-
30
- - Prepends `/api/v1` to all endpoint paths
31
- - Sets `Authorization: token <token>` header on every request (Gitea's native auth format)
32
- - Supports `GET`, `POST`, `PUT`, `PATCH`, `DELETE` methods
33
- - Handles query parameter construction via `URL.searchParams`
34
- - Parses JSON responses automatically
35
- - 30-second request timeout
36
- - Optional TLS certificate verification bypass (`insecure` flag)
37
-
38
- ### config.ts -- Configuration Loader
39
-
40
- Loads the connection configuration from disk:
41
-
42
- - Default path: `~/.gitea-api-mcp.json`
43
- - Override via `GITEA_API_MCP_CONFIG` environment variable
44
- - Validates that at least one connection exists
45
- - Sets `defaultConnection` to the first connection if not explicitly specified
46
- - `getConnection()` resolves a named connection or falls back to the default
47
-
48
- ### types.ts -- Type Definitions
49
-
50
- Three core interfaces:
51
-
52
- - `GiteaConnection` -- Single connection config (`baseUrl`, `token`, `insecure?`)
53
- - `GiteaConfig` -- Full config with named connections map and default
54
- - `ApiResponse` -- Standardized response wrapper (`status`, `data`)
55
-
56
- ## Design Decisions
57
-
58
- ### Token Authentication
59
-
60
- Gitea uses `Authorization: token <access-token>` as its native authentication header format, unlike GitHub's `Bearer` token format. This server uses the native Gitea format directly, ensuring compatibility with all Gitea versions without requiring OAuth2 setup.
61
-
62
- ### Multi-Connection Architecture
63
-
64
- Every tool accepts an optional `connection` parameter. This enables:
65
-
66
- - Managing multiple Gitea instances from a single MCP server
67
- - Switching between production, staging, and development instances
68
- - Cross-instance operations within a single Claude Code session
69
-
70
- The connection is resolved at call time, not at startup, so different tool calls can target different instances.
71
-
72
- ### node:https (Zero HTTP Dependencies)
73
-
74
- The HTTP client uses Node.js built-in `node:https` and `node:http` modules instead of third-party libraries (e.g., axios, node-fetch). This decision:
75
-
76
- - Eliminates supply-chain risk from HTTP client dependencies
77
- - Reduces `node_modules` size
78
- - Avoids compatibility issues across Node.js versions
79
- - Provides full control over TLS configuration (needed for `insecure` flag)
80
-
81
- ### Stdio Transport
82
-
83
- The MCP server uses stdio transport (stdin/stdout) rather than HTTP/SSE. This means:
84
-
85
- - No network ports are opened by the server
86
- - Tokens are never exposed through HTTP endpoints
87
- - The server runs as a child process of the MCP client
88
- - Communication is process-local, reducing attack surface
89
-
90
- ### Shared Parameter Objects
91
-
92
- Common parameter patterns are defined as reusable objects:
93
-
94
- - `OwnerRepo` -- `{ owner, repo }` for all repository-scoped operations
95
- - `PaginationParams` -- `{ page, limit }` for all list endpoints
96
- - `ConnectionParam` -- `{ connection }` for multi-connection routing
97
-
98
- This ensures consistency across all 61 tools and simplifies adding new tools.
99
-
100
- ## Data Flow
101
-
102
- ```
103
- +-----------------+
104
- | Claude Code / |
105
- | MCP Client |
106
- +--------+--------+
107
- |
108
- stdio (JSON-RPC)
109
- |
110
- +--------v--------+
111
- | index.ts |
112
- | McpServer |
113
- | (tool router) |
114
- +--------+--------+
115
- |
116
- +-----------+-----------+
117
- | |
118
- +------v------+ +-------v-------+
119
- | config.ts | | client.ts |
120
- | loadConfig | | GiteaClient |
121
- | getConn | | (HTTP calls) |
122
- +------+------+ +-------+-------+
123
- | |
124
- +------v------+ HTTPS / HTTP
125
- | ~/.gitea- | |
126
- | api-mcp.json| +--------v--------+
127
- +-------------+ | Gitea Instance |
128
- | /api/v1/* |
129
- +-----------------+
130
- ```
131
-
132
- 1. Claude Code sends a JSON-RPC tool call over stdio
133
- 2. `McpServer` routes the call to the registered tool handler
134
- 3. The handler calls `clientFor(connection)` which resolves the connection from config
135
- 4. `GiteaClient` constructs the HTTP request and sends it to the Gitea API
136
- 5. The JSON response is wrapped in `formatResponse()` and returned to the MCP client
137
-
138
- ---
139
-
140
- *Repo: [gitea-api-mcp](https://git.mokoconsulting.tech/MokoConsulting/gitea-api-mcp) . [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/mokoplatform/wiki/Home)*
141
-
142
- | Revision | Date | Author | Description |
143
- |---|---|---|---|
144
- | 1.0 | 2026-05-09 | Moko Consulting | Initial version |
package/wiki/Home.md DELETED
@@ -1,35 +0,0 @@
1
- # gitea-api-mcp
2
-
3
- MCP server for Gitea REST API v1 operations — 61 tools for repos, issues, PRs, releases, branches, actions, orgs, wiki, webhooks, and more
4
-
5
- | Field | Value |
6
- |---|---|
7
- | **Language** | Markdown |
8
- | **License** | GPL-3.0-or-later |
9
- | **Platform** | [Gitea](https://git.mokoconsulting.tech/MokoConsulting/gitea-api-mcp) |
10
-
11
- ---
12
-
13
- ## Guides
14
-
15
- | Page | Description |
16
- |---|---|
17
- | [INSTALLATION](INSTALLATION) | - **Node.js** >= 20.0.0 ([download](https://nodejs.org)) |
18
-
19
- ## Reference
20
-
21
- | Page | Description |
22
- |---|---|
23
- | [ARCHITECTURE](ARCHITECTURE) | index.ts -- MCP server entry point, tool registrations (61 tools) |
24
-
25
- ---
26
-
27
- > [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/mokoplatform/wiki/Home)
28
-
29
- ---
30
-
31
- *Repo: [gitea-api-mcp](https://git.mokoconsulting.tech/MokoConsulting/gitea-api-mcp) . [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/mokoplatform/wiki/Home)*
32
-
33
- | Revision | Date | Author | Description |
34
- |---|---|---|---|
35
- | 1.0 | 2026-05-09 | Moko Consulting | Initial version |