@mokoconsulting/mcp-mokosuite 1.0.0 → 1.1.0-dev.372

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mokoconsulting/mcp-mokosuite",
3
- "version": "1.0.0",
3
+ "version": "1.1.0-dev.372",
4
4
  "description": "MCP server for MokoSuite (Joomla) REST API v1 operations",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
package/src/index.ts CHANGED
@@ -25,6 +25,9 @@ import type { ApiConfig, ApiResponse } from './types.js';
25
25
  /** Base path for MokoSuiteClient Web Services (appended after /api/index.php). */
26
26
  const MSC = '/v1/mokosuiteclient';
27
27
 
28
+ /** Base path for MokoSuiteExtensions (store) Web Services (appended after /api/index.php). */
29
+ const MSE = '/v1/mokosuiteextensions';
30
+
28
31
  let config: ApiConfig;
29
32
 
30
33
  function clientFor(connection?: string): ApiClient {
@@ -64,7 +67,7 @@ function requireConfirm(confirm: boolean): { content: Array<{ type: 'text'; text
64
67
 
65
68
  const server = new McpServer({
66
69
  name: 'mcp-mokosuite',
67
- version: '1.0.0',
70
+ version: '1.1.0',
68
71
  });
69
72
 
70
73
  // ════════════════════════════════════════════════════════════════════════
@@ -322,6 +325,61 @@ server.tool(
322
325
  },
323
326
  );
324
327
 
328
+ // ════════════════════════════════════════════════════════════════════════
329
+ // LAYER 1 — Extensions Store (MokoSuiteExtensions)
330
+ // ════════════════════════════════════════════════════════════════════════
331
+
332
+ server.tool(
333
+ 'store_catalog_list',
334
+ 'List the products available in the MokoSuite Extensions store catalog for a site.',
335
+ { ...ConnectionParam },
336
+ async ({ connection }) => formatResponse(await clientFor(connection).get(`${MSE}/catalog`)),
337
+ );
338
+
339
+ server.tool(
340
+ 'store_catalog_get',
341
+ 'Get a single MokoSuite Extensions store product by its catalog id.',
342
+ {
343
+ id: z.number().describe('Catalog product id'),
344
+ ...ConnectionParam,
345
+ },
346
+ async ({ id, connection }) => formatResponse(await clientFor(connection).get(`${MSE}/catalog/${id}`)),
347
+ );
348
+
349
+ server.tool(
350
+ 'store_install',
351
+ 'Install a MokoSuite Extensions store product on a site by its catalog id.',
352
+ {
353
+ id: z.number().describe('Catalog product id to install'),
354
+ ...ConnectionParam,
355
+ },
356
+ async ({ id, connection }) => formatResponse(await clientFor(connection).post(`${MSE}/catalog/${id}/install`)),
357
+ );
358
+
359
+ server.tool(
360
+ 'store_update',
361
+ 'Update an installed MokoSuite Extensions store product on a site by its catalog id.',
362
+ {
363
+ id: z.number().describe('Catalog product id to update'),
364
+ ...ConnectionParam,
365
+ },
366
+ async ({ id, connection }) => formatResponse(await clientFor(connection).post(`${MSE}/catalog/${id}/update`)),
367
+ );
368
+
369
+ server.tool(
370
+ 'store_uninstall',
371
+ 'Uninstall a MokoSuite Extensions store product from a site by its catalog id. Destructive — requires `confirm: true`.',
372
+ {
373
+ id: z.number().describe('Catalog product id to uninstall'),
374
+ confirm: z.boolean().describe('Must be true — uninstalling removes the product from the target site'),
375
+ ...ConnectionParam,
376
+ },
377
+ async ({ id, confirm, connection }) => {
378
+ if (!confirm) return text('Refused: set `confirm: true` to uninstall this store product.');
379
+ return formatResponse(await clientFor(connection).post(`${MSE}/catalog/${id}/uninstall`));
380
+ },
381
+ );
382
+
325
383
  // ── Start Server ────────────────────────────────────────────────────────
326
384
 
327
385
  async function main(): Promise<void> {
@@ -1,203 +0,0 @@
1
- # Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
2
- #
3
- # SPDX-License-Identifier: GPL-3.0-or-later
4
- #
5
- # FILE INFORMATION
6
- # DEFGROUP: MokoGIT.Workflow
7
- # INGROUP: MokoCLI.CI
8
- # REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
9
- # PATH: /.mokogit/workflows/ci-generic.yml
10
- # VERSION: 01.00.00
11
- # BRIEF: CI pipeline — lint, validate, and test for generic projects (PHP + Node.js)
12
-
13
- name: "Generic: Project CI"
14
-
15
- on:
16
- pull_request:
17
- branches:
18
- - main
19
- - dev
20
- - dev/**
21
- - rc/**
22
- workflow_dispatch:
23
-
24
- permissions:
25
- contents: read
26
-
27
- env:
28
- FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
29
-
30
- jobs:
31
- # ── Lint & Validate ───────────────────────────────────────────────────
32
- lint:
33
- name: Lint & Validate
34
- runs-on: ubuntu-latest
35
- # Skip on template repos (Template-*) — they hold placeholder scaffolding, not buildable source.
36
- if: ${{ !startsWith(github.event.repository.name, 'Template-') }}
37
-
38
- steps:
39
- - name: Checkout
40
- uses: actions/checkout@v4
41
-
42
- - name: Detect toolchain
43
- id: detect
44
- run: |
45
- HAS_PHP=false
46
- HAS_NODE=false
47
- [ -f "composer.json" ] && HAS_PHP=true
48
- [ -f "package.json" ] && HAS_NODE=true
49
- echo "has_php=$HAS_PHP" >> "$GITHUB_OUTPUT"
50
- echo "has_node=$HAS_NODE" >> "$GITHUB_OUTPUT"
51
- echo "Toolchain: PHP=$HAS_PHP Node=$HAS_NODE"
52
-
53
- - name: Setup PHP
54
- if: steps.detect.outputs.has_php == 'true'
55
- run: |
56
- if ! command -v php &> /dev/null; then
57
- sudo apt-get update -qq
58
- sudo apt-get install -y -qq php-cli php-mbstring php-xml >/dev/null 2>&1
59
- fi
60
- php -v
61
-
62
- - name: Setup Node.js
63
- if: steps.detect.outputs.has_node == 'true'
64
- uses: actions/setup-node@v4
65
- with:
66
- node-version: '20'
67
-
68
- - name: Install PHP dependencies
69
- if: steps.detect.outputs.has_php == 'true'
70
- run: |
71
- if [ -f "composer.json" ]; then
72
- composer install --no-interaction --prefer-dist --quiet 2>/dev/null || true
73
- fi
74
-
75
- - name: Install Node.js dependencies
76
- if: steps.detect.outputs.has_node == 'true'
77
- run: |
78
- if [ -f "package.json" ]; then
79
- npm ci --quiet 2>/dev/null || npm install --quiet 2>/dev/null || true
80
- fi
81
-
82
- - name: PHP syntax check
83
- if: steps.detect.outputs.has_php == 'true'
84
- run: |
85
- ERRORS=0
86
- while IFS= read -r -d '' file; do
87
- if ! php -l "$file" 2>&1 | grep -q "No syntax errors"; then
88
- echo "::error file=${file}::PHP syntax error"
89
- ERRORS=$((ERRORS + 1))
90
- fi
91
- done < <(find . -name "*.php" -not -path "./.git/*" -not -path "./vendor/*" -not -path "./node_modules/*" -print0)
92
-
93
- echo "## PHP Lint" >> $GITHUB_STEP_SUMMARY
94
- if [ "$ERRORS" -eq 0 ]; then
95
- echo "All PHP files passed syntax check." >> $GITHUB_STEP_SUMMARY
96
- else
97
- echo "${ERRORS} file(s) with syntax errors." >> $GITHUB_STEP_SUMMARY
98
- exit 1
99
- fi
100
-
101
- - name: TypeScript/JavaScript lint
102
- if: steps.detect.outputs.has_node == 'true'
103
- run: |
104
- if [ -f "node_modules/.bin/eslint" ]; then
105
- npx eslint src/ --quiet 2>&1 || { echo "::error::ESLint errors found"; exit 1; }
106
- echo "## ESLint" >> $GITHUB_STEP_SUMMARY
107
- echo "All files passed ESLint." >> $GITHUB_STEP_SUMMARY
108
- elif [ -f ".eslintrc.json" ] || [ -f ".eslintrc.js" ] || [ -f "eslint.config.js" ]; then
109
- echo "::warning::ESLint config found but eslint not installed"
110
- else
111
- echo "No ESLint configured — skipping"
112
- fi
113
-
114
- - name: TypeScript compile check
115
- if: steps.detect.outputs.has_node == 'true'
116
- run: |
117
- if [ -f "tsconfig.json" ] && [ -f "node_modules/.bin/tsc" ]; then
118
- npx tsc --noEmit 2>&1 || { echo "::error::TypeScript compilation errors"; exit 1; }
119
- echo "## TypeScript" >> $GITHUB_STEP_SUMMARY
120
- echo "TypeScript compilation passed." >> $GITHUB_STEP_SUMMARY
121
- fi
122
-
123
- - name: PHPStan static analysis
124
- if: steps.detect.outputs.has_php == 'true'
125
- run: |
126
- if [ -f "phpstan.neon" ] && [ -f "vendor/bin/phpstan" ]; then
127
- vendor/bin/phpstan analyse --no-progress 2>&1 || { echo "::warning::PHPStan found issues"; }
128
- fi
129
-
130
- # ── Tests ─────────────────────────────────────────────────────────────
131
- test:
132
- name: Tests
133
- runs-on: ubuntu-latest
134
- # Independent job (no `needs: lint`): the MokoGIT Actions scheduler does not
135
- # offer the dependent 2nd job of a needs-chain to runners, so it stalls in
136
- # "waiting" and is reaped by ABANDONED_JOB_TIMEOUT. Guard template repos
137
- # directly (same condition lint uses) instead of gating on lint's result.
138
- if: ${{ !startsWith(github.event.repository.name, 'Template-') }}
139
-
140
- steps:
141
- - name: Checkout
142
- uses: actions/checkout@v4
143
-
144
- - name: Detect toolchain
145
- id: detect
146
- run: |
147
- HAS_PHP=false
148
- HAS_NODE=false
149
- [ -f "composer.json" ] && HAS_PHP=true
150
- [ -f "package.json" ] && HAS_NODE=true
151
- echo "has_php=$HAS_PHP" >> "$GITHUB_OUTPUT"
152
- echo "has_node=$HAS_NODE" >> "$GITHUB_OUTPUT"
153
-
154
- - name: Setup PHP
155
- if: steps.detect.outputs.has_php == 'true'
156
- run: |
157
- if ! command -v php &> /dev/null; then
158
- sudo apt-get update -qq
159
- sudo apt-get install -y -qq php-cli php-mbstring php-xml >/dev/null 2>&1
160
- fi
161
-
162
- - name: Setup Node.js
163
- if: steps.detect.outputs.has_node == 'true'
164
- uses: actions/setup-node@v4
165
- with:
166
- node-version: '20'
167
-
168
- - name: Install dependencies
169
- run: |
170
- [ -f "composer.json" ] && composer install --no-interaction --prefer-dist --quiet 2>/dev/null || true
171
- [ -f "package.json" ] && { npm ci --quiet 2>/dev/null || npm install --quiet 2>/dev/null || true; } || true
172
-
173
- - name: Run PHP tests
174
- if: steps.detect.outputs.has_php == 'true'
175
- run: |
176
- if [ -f "vendor/bin/phpunit" ]; then
177
- vendor/bin/phpunit --testdox 2>&1
178
- echo "## PHPUnit" >> $GITHUB_STEP_SUMMARY
179
- echo "Tests passed." >> $GITHUB_STEP_SUMMARY
180
- elif [ -f "phpunit.xml" ] || [ -f "phpunit.xml.dist" ]; then
181
- echo "::warning::PHPUnit config found but phpunit not installed"
182
- else
183
- echo "No PHPUnit configured — skipping"
184
- fi
185
-
186
- - name: Run Node.js tests
187
- if: steps.detect.outputs.has_node == 'true'
188
- run: |
189
- if jq -e '.scripts.test' package.json > /dev/null 2>&1; then
190
- npm test 2>&1
191
- echo "## Node.js Tests" >> $GITHUB_STEP_SUMMARY
192
- echo "Tests passed." >> $GITHUB_STEP_SUMMARY
193
- else
194
- echo "No test script in package.json — skipping"
195
- fi
196
-
197
- - name: Build check
198
- run: |
199
- if [ -f "Makefile" ]; then
200
- make build 2>&1 || echo "::warning::Build failed or not configured"
201
- elif [ -f "package.json" ] && jq -e '.scripts.build' package.json > /dev/null 2>&1; then
202
- npm run build 2>&1 || echo "::warning::Build failed"
203
- fi