@hostinger/mcp 3.4.2 → 3.6.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.
- package/CHANGELOG.md +19 -0
- package/README.md +1 -1
- package/gemini-extension.json +1 -1
- package/package.json +1 -1
- package/server.json +2 -2
- package/skills/headless/steps/02-refine/SKILL.md +7 -0
- package/skills/headless/steps/03-provision/wordpress/SKILL.md +63 -0
- package/skills/headless/steps/04-content-model/wordpress/SKILL.md +58 -5
- package/skills/headless/steps/04-content-model/wordpress/contact-form.md +227 -0
- package/skills/headless/steps/04-content-model/wordpress/custom-plugins.md +481 -0
- package/skills/headless/steps/06-frontend/SKILL.md +15 -0
- package/skills/headless/steps/07-validate/SKILL.md +13 -0
- package/skills/headless/steps/09-done/SKILL.md +5 -0
- package/src/core/runtime.js +32 -15
- package/src/core/runtime.ts +32 -15
- package/src/core/skills.js +32 -18
- package/src/core/skills.ts +32 -18
- package/src/core/tools/all.js +1 -5
- package/src/core/tools/all.ts +1 -5
- package/src/core/tools/hosting.js +1 -5
- package/src/core/tools/hosting.ts +1 -5
- package/src/servers/agency-hosting.js +1 -1
- package/src/servers/agency-hosting.ts +1 -1
- package/src/servers/agent-readiness.js +1 -1
- package/src/servers/agent-readiness.ts +1 -1
- package/src/servers/all.js +1 -1
- package/src/servers/all.ts +1 -1
- package/src/servers/billing.js +1 -1
- package/src/servers/billing.ts +1 -1
- package/src/servers/dns.js +1 -1
- package/src/servers/dns.ts +1 -1
- package/src/servers/domains.js +1 -1
- package/src/servers/domains.ts +1 -1
- package/src/servers/ecommerce.js +1 -1
- package/src/servers/ecommerce.ts +1 -1
- package/src/servers/horizons.js +1 -1
- package/src/servers/horizons.ts +1 -1
- package/src/servers/hosting.js +1 -1
- package/src/servers/hosting.ts +1 -1
- package/src/servers/mail.js +1 -1
- package/src/servers/mail.ts +1 -1
- package/src/servers/reach.js +1 -1
- package/src/servers/reach.ts +1 -1
- package/src/servers/vps.js +1 -1
- package/src/servers/vps.ts +1 -1
- package/src/servers/wordpress.js +1 -1
- package/src/servers/wordpress.ts +1 -1
- package/types.d.ts +1 -5
package/src/core/runtime.ts
CHANGED
|
@@ -680,9 +680,6 @@ class MCPServer {
|
|
|
680
680
|
if (resolved === 'wordpress-site' && !databaseDump) {
|
|
681
681
|
throw new Error('databaseDump (path to a .sql file) is required to import a WordPress site');
|
|
682
682
|
}
|
|
683
|
-
if (params.headless === true && resolved !== 'wordpress-plugin' && resolved !== 'wordpress-theme') {
|
|
684
|
-
throw new Error('headless is for wordpress-plugin and wordpress-theme deploys only, not ' + resolved);
|
|
685
|
-
}
|
|
686
683
|
return resolved;
|
|
687
684
|
}
|
|
688
685
|
|
|
@@ -863,12 +860,6 @@ class MCPServer {
|
|
|
863
860
|
if (params.slug !== undefined && !(typeof params.slug === 'string' && /^[a-z0-9_-]+$/.test(params.slug))) {
|
|
864
861
|
throw new Error('slug must contain only lower-case letters, digits, "-" and "_"');
|
|
865
862
|
}
|
|
866
|
-
if (params.headless !== undefined && typeof params.headless !== 'boolean') {
|
|
867
|
-
throw new Error('headless must be a boolean');
|
|
868
|
-
}
|
|
869
|
-
if (params.headless === true && git !== undefined) {
|
|
870
|
-
throw new Error('headless is for wordpress-plugin and wordpress-theme deploys only, which need a local directory, not git');
|
|
871
|
-
}
|
|
872
863
|
if (git !== undefined && (typeof git !== 'object' || git === null || typeof git.repository !== 'string' || typeof git.branch !== 'string' || git.branch === '')) {
|
|
873
864
|
throw new Error('git must be an object with repository (owner/name) and branch');
|
|
874
865
|
}
|
|
@@ -892,13 +883,39 @@ class MCPServer {
|
|
|
892
883
|
theme: '/api/hosting/v1/accounts/{username}/websites/{domain}/wordpress/themes/deploy',
|
|
893
884
|
};
|
|
894
885
|
|
|
895
|
-
// A headless WordPress is installed in this folder of the document root, not at the root itself.
|
|
896
|
-
private hosting_deploy_headlessDirectory = 'cms';
|
|
897
|
-
|
|
898
886
|
private async hosting_deploy_callWordpress(kind: string, params: Record<string, any>): Promise<any> {
|
|
899
887
|
return this.executeApiCall({ name: 'wordpress_' + kind, method: 'POST', path: this.hosting_deploy_wordpressEndpoints[kind] } as any, params);
|
|
900
888
|
}
|
|
901
889
|
|
|
890
|
+
// The folder of the document root WordPress is installed in ('' for the root, e.g. 'cms' on a headless
|
|
891
|
+
// site), from the installation directory wordpress_installations_list reports (public_html or '' for the root,
|
|
892
|
+
// public_html/<folder> or a bare <folder> otherwise). Absolute paths and .. segments are refused.
|
|
893
|
+
private async hosting_deploy_wordpressDirectory(username: string, domain: string): Promise<string> {
|
|
894
|
+
const response = await this.executeApiCall({ name: 'wordpress_installations_list', method: 'GET', path: '/api/hosting/v1/wordpress/installations' } as any, { username, domain, ownership: 'all' });
|
|
895
|
+
const list = Array.isArray(response) ? response : (response && Array.isArray(response.data) ? response.data : []);
|
|
896
|
+
const installations = list.filter((installation: any) => typeof installation.domain === 'string' && installation.domain.toLowerCase() === domain.toLowerCase());
|
|
897
|
+
if (installations.length === 0) {
|
|
898
|
+
return '';
|
|
899
|
+
}
|
|
900
|
+
if (installations.length > 1) {
|
|
901
|
+
throw new Error('Several WordPress installations found for ' + domain + ' (' + installations.map((installation: any) => installation.directory).join(', ') + '); cannot tell which one to deploy to');
|
|
902
|
+
}
|
|
903
|
+
let directory = typeof installations[0].directory === 'string' ? installations[0].directory : '';
|
|
904
|
+
if (directory.startsWith('/') || directory.split('/').includes('..')) {
|
|
905
|
+
throw new Error('Unrecognized WordPress installation directory for ' + domain + ': ' + String(installations[0].directory));
|
|
906
|
+
}
|
|
907
|
+
while (directory.endsWith('/')) {
|
|
908
|
+
directory = directory.slice(0, -1);
|
|
909
|
+
}
|
|
910
|
+
if (directory === 'public_html') {
|
|
911
|
+
return '';
|
|
912
|
+
}
|
|
913
|
+
if (directory.startsWith('public_html/')) {
|
|
914
|
+
return directory.slice('public_html/'.length);
|
|
915
|
+
}
|
|
916
|
+
return directory;
|
|
917
|
+
}
|
|
918
|
+
|
|
902
919
|
private hosting_deploy_randomSuffix(): string {
|
|
903
920
|
return Math.random().toString(36).slice(2, 10).padEnd(8, '0');
|
|
904
921
|
}
|
|
@@ -964,7 +981,6 @@ class MCPServer {
|
|
|
964
981
|
|
|
965
982
|
private async hosting_deploy_wordpressExtension(username: string, domain: string, type: string, params: Record<string, any>): Promise<any> {
|
|
966
983
|
const isPlugin = type === 'wordpress-plugin';
|
|
967
|
-
const headless = params.headless === true;
|
|
968
984
|
const directory = path.resolve(params.path);
|
|
969
985
|
const slug = params.slug !== undefined ? params.slug : this.hosting_deploy_slug(directory);
|
|
970
986
|
const { files, skipped } = this.hosting_deploy_listFiles(directory);
|
|
@@ -972,9 +988,10 @@ class MCPServer {
|
|
|
972
988
|
throw new Error('No files found in directory: ' + directory);
|
|
973
989
|
}
|
|
974
990
|
|
|
991
|
+
const wordpressDirectory = await this.hosting_deploy_wordpressDirectory(username, domain);
|
|
975
992
|
// The files land in a fresh directory; the deploy call then installs from it.
|
|
976
993
|
const uploadDirName = slug + '-' + this.hosting_deploy_randomSuffix();
|
|
977
|
-
const remoteRoot = (
|
|
994
|
+
const remoteRoot = (wordpressDirectory ? wordpressDirectory + '/' : '') + (isPlugin ? 'wp-content/plugins/' : 'wp-content/themes/') + uploadDirName;
|
|
978
995
|
await this.hosting_deploy_upload(username, domain, files.map((relativePath) => ({
|
|
979
996
|
absolutePath: path.join(directory, relativePath),
|
|
980
997
|
relativePath: remoteRoot + '/' + relativePath,
|
|
@@ -994,7 +1011,7 @@ class MCPServer {
|
|
|
994
1011
|
slug,
|
|
995
1012
|
files: files.length,
|
|
996
1013
|
...(isPlugin ? {} : { activated: params.activate === true }),
|
|
997
|
-
...(
|
|
1014
|
+
...(wordpressDirectory ? { wordpressDirectory } : {}),
|
|
998
1015
|
}, skipped);
|
|
999
1016
|
}
|
|
1000
1017
|
|