hostinger-api-mcp 1.61.0 → 1.61.2
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 +14 -0
- package/gemini-extension.json +1 -1
- package/package.json +1 -1
- package/server.json +2 -2
- package/src/core/runtime.js +61 -9
- package/src/core/runtime.ts +65 -9
- package/src/servers/agency-hosting.js +1 -1
- package/src/servers/agency-hosting.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/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,20 @@ Generated at release time from the diff between the previous and current
|
|
|
4
4
|
build. Tool changes are listed individually; everything else is summarised
|
|
5
5
|
by area.
|
|
6
6
|
|
|
7
|
+
## v1.61.2 — 2026-09-21
|
|
8
|
+
|
|
9
|
+
### Also in this release
|
|
10
|
+
|
|
11
|
+
- Dependencies: `package-lock.json`
|
|
12
|
+
- Request handling and authentication: `src/core/runtime.js`, `src/core/runtime.ts`
|
|
13
|
+
- Other files: `.gitignore`
|
|
14
|
+
|
|
15
|
+
## v1.61.1 — 2026-09-17
|
|
16
|
+
|
|
17
|
+
### Also in this release
|
|
18
|
+
|
|
19
|
+
- Request handling and authentication: `src/core/runtime.js`, `src/core/runtime.ts`
|
|
20
|
+
|
|
7
21
|
## v1.61.0 — 2026-09-16
|
|
8
22
|
|
|
9
23
|
### Tools
|
package/gemini-extension.json
CHANGED
package/package.json
CHANGED
package/server.json
CHANGED
|
@@ -6,12 +6,12 @@
|
|
|
6
6
|
"url": "https://github.com/hostinger/api-mcp-server",
|
|
7
7
|
"source": "github"
|
|
8
8
|
},
|
|
9
|
-
"version": "1.61.
|
|
9
|
+
"version": "1.61.2",
|
|
10
10
|
"packages": [
|
|
11
11
|
{
|
|
12
12
|
"registryType": "npm",
|
|
13
13
|
"identifier": "@hostinger/mcp",
|
|
14
|
-
"version": "1.61.
|
|
14
|
+
"version": "1.61.2",
|
|
15
15
|
"transport": {
|
|
16
16
|
"type": "stdio"
|
|
17
17
|
},
|
package/src/core/runtime.js
CHANGED
|
@@ -10,6 +10,8 @@ import { config as dotenvConfig } from "dotenv";
|
|
|
10
10
|
import {
|
|
11
11
|
ListToolsRequestSchema,
|
|
12
12
|
CallToolRequestSchema,
|
|
13
|
+
ErrorCode,
|
|
14
|
+
McpError,
|
|
13
15
|
} from "@modelcontextprotocol/sdk/types.js";
|
|
14
16
|
import { OAuthProvider, getEnvToken } from "./oauth.js";
|
|
15
17
|
import * as tus from "tus-js-client";
|
|
@@ -19,6 +21,19 @@ import path from "path";
|
|
|
19
21
|
// Load environment variables
|
|
20
22
|
dotenvConfig({ quiet: true });
|
|
21
23
|
|
|
24
|
+
/**
|
|
25
|
+
* An upstream API call that came back as a failure. Carries the status and the
|
|
26
|
+
* API's own response body so the CallTool handler can hand both to the model.
|
|
27
|
+
*/
|
|
28
|
+
class ApiExecutionError extends Error {
|
|
29
|
+
constructor(status, data, message) {
|
|
30
|
+
super(message || `API request failed with status ${status}`);
|
|
31
|
+
this.name = 'ApiExecutionError';
|
|
32
|
+
this.status = status;
|
|
33
|
+
this.responseData = data;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
22
37
|
const SECURITY_SCHEMES = {
|
|
23
38
|
"apiToken": {
|
|
24
39
|
"type": "http",
|
|
@@ -29,7 +44,7 @@ const SECURITY_SCHEMES = {
|
|
|
29
44
|
|
|
30
45
|
/**
|
|
31
46
|
* MCP Server for Hostinger API
|
|
32
|
-
* Generated from OpenAPI spec version 1.53.
|
|
47
|
+
* Generated from OpenAPI spec version 1.53.1
|
|
33
48
|
*/
|
|
34
49
|
class MCPServer {
|
|
35
50
|
constructor({ name, version, tools }) {
|
|
@@ -157,13 +172,17 @@ class MCPServer {
|
|
|
157
172
|
}
|
|
158
173
|
}
|
|
159
174
|
|
|
175
|
+
// An unknown tool is a protocol error, not a tool execution error: the
|
|
176
|
+
// model cannot self-correct its way out of a name the server does not
|
|
177
|
+
// have. -32602 is what the spec's example and the SDK's own McpServer
|
|
178
|
+
// use; a plain Error would go out as -32603 instead.
|
|
160
179
|
if (!toolName) {
|
|
161
|
-
throw new
|
|
180
|
+
throw new McpError(ErrorCode.InvalidParams, `Tool not found: ${name}`);
|
|
162
181
|
}
|
|
163
182
|
|
|
164
183
|
toolDetails = this.toolList.find(t => t.name === toolName);
|
|
165
184
|
if (!toolDetails) {
|
|
166
|
-
throw new
|
|
185
|
+
throw new McpError(ErrorCode.InternalError, `Tool details not found for ID: ${toolName}`);
|
|
167
186
|
}
|
|
168
187
|
|
|
169
188
|
try {
|
|
@@ -189,10 +208,32 @@ class MCPServer {
|
|
|
189
208
|
|
|
190
209
|
} catch (error) {
|
|
191
210
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
192
|
-
const response = error.response;
|
|
193
211
|
this.log('error', `Error executing tool ${name}: ${errorMessage}`);
|
|
194
212
|
|
|
195
|
-
|
|
213
|
+
// MCP reports tool execution failures (API errors, bad input, business
|
|
214
|
+
// logic) inside the result with isError: true. Throwing here would turn
|
|
215
|
+
// them into JSON-RPC protocol errors instead, which the spec reserves
|
|
216
|
+
// for unknown tools and malformed requests — those are still thrown,
|
|
217
|
+
// above, before this try. The status stays in the text so the model can
|
|
218
|
+
// tell a retryable 429/503 from a 403 it should not retry.
|
|
219
|
+
let errorText = errorMessage;
|
|
220
|
+
if (error instanceof ApiExecutionError) {
|
|
221
|
+
const payload = error.responseData;
|
|
222
|
+
const body = payload === null || payload === undefined || payload === ''
|
|
223
|
+
? errorMessage
|
|
224
|
+
: typeof payload === 'object' ? JSON.stringify(payload) : String(payload);
|
|
225
|
+
errorText = error.status ? `HTTP ${error.status}: ${body}` : body;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
return {
|
|
229
|
+
isError: true,
|
|
230
|
+
content: [
|
|
231
|
+
{
|
|
232
|
+
type: "text",
|
|
233
|
+
text: errorText
|
|
234
|
+
}
|
|
235
|
+
]
|
|
236
|
+
};
|
|
196
237
|
}
|
|
197
238
|
});
|
|
198
239
|
}
|
|
@@ -2474,6 +2515,13 @@ class MCPServer {
|
|
|
2474
2515
|
this.log('debug', `Retry response status: ${response.status}`);
|
|
2475
2516
|
}
|
|
2476
2517
|
|
|
2518
|
+
// validateStatus resolves everything under 500, so a 4xx arrives here as
|
|
2519
|
+
// an ordinary response. Without this it would be returned to the model as
|
|
2520
|
+
// a successful tool result whose body happens to be the API's error.
|
|
2521
|
+
if (response.status >= 400) {
|
|
2522
|
+
throw new ApiExecutionError(response.status, response.data);
|
|
2523
|
+
}
|
|
2524
|
+
|
|
2477
2525
|
return response.data;
|
|
2478
2526
|
|
|
2479
2527
|
} catch (error) {
|
|
@@ -2489,10 +2537,14 @@ class MCPServer {
|
|
|
2489
2537
|
data: typeof responseData === 'object' ? JSON.stringify(responseData) : responseData
|
|
2490
2538
|
});
|
|
2491
2539
|
|
|
2492
|
-
//
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
throw
|
|
2540
|
+
// Structured so the CallTool handler can report this as an MCP tool
|
|
2541
|
+
// execution error carrying the API's own payload. Status is 0 for a
|
|
2542
|
+
// transport failure (DNS, ECONNREFUSED, timeout) — there is no response.
|
|
2543
|
+
throw new ApiExecutionError(
|
|
2544
|
+
responseStatus ?? 0,
|
|
2545
|
+
responseData,
|
|
2546
|
+
`API request failed with status ${responseStatus}: ${errorMessage}`
|
|
2547
|
+
);
|
|
2496
2548
|
}
|
|
2497
2549
|
|
|
2498
2550
|
throw error;
|
package/src/core/runtime.ts
CHANGED
|
@@ -10,6 +10,8 @@ import { config as dotenvConfig } from "dotenv";
|
|
|
10
10
|
import {
|
|
11
11
|
ListToolsRequestSchema,
|
|
12
12
|
CallToolRequestSchema,
|
|
13
|
+
ErrorCode,
|
|
14
|
+
McpError,
|
|
13
15
|
Tool,
|
|
14
16
|
} from "@modelcontextprotocol/sdk/types.js";
|
|
15
17
|
import { OAuthProvider, getEnvToken } from "./oauth.js";
|
|
@@ -42,6 +44,22 @@ interface SecurityScheme {
|
|
|
42
44
|
scheme?: string;
|
|
43
45
|
}
|
|
44
46
|
|
|
47
|
+
/**
|
|
48
|
+
* An upstream API call that came back as a failure. Carries the status and the
|
|
49
|
+
* API's own response body so the CallTool handler can hand both to the model.
|
|
50
|
+
*/
|
|
51
|
+
class ApiExecutionError extends Error {
|
|
52
|
+
public readonly status: number;
|
|
53
|
+
public readonly responseData: any;
|
|
54
|
+
|
|
55
|
+
constructor(status: number, data: any, message?: string) {
|
|
56
|
+
super(message || `API request failed with status ${status}`);
|
|
57
|
+
this.name = 'ApiExecutionError';
|
|
58
|
+
this.status = status;
|
|
59
|
+
this.responseData = data;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
45
63
|
const SECURITY_SCHEMES: Record<string, SecurityScheme> = {
|
|
46
64
|
"apiToken": {
|
|
47
65
|
"type": "http",
|
|
@@ -52,7 +70,7 @@ const SECURITY_SCHEMES: Record<string, SecurityScheme> = {
|
|
|
52
70
|
|
|
53
71
|
/**
|
|
54
72
|
* MCP Server for Hostinger API
|
|
55
|
-
* Generated from OpenAPI spec version 1.53.
|
|
73
|
+
* Generated from OpenAPI spec version 1.53.1
|
|
56
74
|
*/
|
|
57
75
|
class MCPServer {
|
|
58
76
|
private readonly name: string;
|
|
@@ -188,13 +206,17 @@ class MCPServer {
|
|
|
188
206
|
}
|
|
189
207
|
}
|
|
190
208
|
|
|
209
|
+
// An unknown tool is a protocol error, not a tool execution error: the
|
|
210
|
+
// model cannot self-correct its way out of a name the server does not
|
|
211
|
+
// have. -32602 is what the spec's example and the SDK's own McpServer
|
|
212
|
+
// use; a plain Error would go out as -32603 instead.
|
|
191
213
|
if (!toolName) {
|
|
192
|
-
throw new
|
|
214
|
+
throw new McpError(ErrorCode.InvalidParams, `Tool not found: ${name}`);
|
|
193
215
|
}
|
|
194
216
|
|
|
195
217
|
toolDetails = this.toolList.find(t => t.name === toolName);
|
|
196
218
|
if (!toolDetails) {
|
|
197
|
-
throw new
|
|
219
|
+
throw new McpError(ErrorCode.InternalError, `Tool details not found for ID: ${toolName}`);
|
|
198
220
|
}
|
|
199
221
|
|
|
200
222
|
try {
|
|
@@ -221,8 +243,31 @@ class MCPServer {
|
|
|
221
243
|
} catch (error) {
|
|
222
244
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
223
245
|
this.log('error', `Error executing tool ${toolName}: ${errorMessage}`);
|
|
224
|
-
|
|
225
|
-
|
|
246
|
+
|
|
247
|
+
// MCP reports tool execution failures (API errors, bad input, business
|
|
248
|
+
// logic) inside the result with isError: true. Throwing here would turn
|
|
249
|
+
// them into JSON-RPC protocol errors instead, which the spec reserves
|
|
250
|
+
// for unknown tools and malformed requests — those are still thrown,
|
|
251
|
+
// above, before this try. The status stays in the text so the model can
|
|
252
|
+
// tell a retryable 429/503 from a 403 it should not retry.
|
|
253
|
+
let errorText: string = errorMessage;
|
|
254
|
+
if (error instanceof ApiExecutionError) {
|
|
255
|
+
const payload = error.responseData;
|
|
256
|
+
const body = payload === null || payload === undefined || payload === ''
|
|
257
|
+
? errorMessage
|
|
258
|
+
: typeof payload === 'object' ? JSON.stringify(payload) : String(payload);
|
|
259
|
+
errorText = error.status ? `HTTP ${error.status}: ${body}` : body;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
return {
|
|
263
|
+
isError: true,
|
|
264
|
+
content: [
|
|
265
|
+
{
|
|
266
|
+
type: "text",
|
|
267
|
+
text: errorText
|
|
268
|
+
}
|
|
269
|
+
]
|
|
270
|
+
};
|
|
226
271
|
}
|
|
227
272
|
});
|
|
228
273
|
}
|
|
@@ -2524,6 +2569,13 @@ class MCPServer {
|
|
|
2524
2569
|
this.log('debug', `Retry response status: ${response.status}`);
|
|
2525
2570
|
}
|
|
2526
2571
|
|
|
2572
|
+
// validateStatus resolves everything under 500, so a 4xx arrives here as
|
|
2573
|
+
// an ordinary response. Without this it would be returned to the model as
|
|
2574
|
+
// a successful tool result whose body happens to be the API's error.
|
|
2575
|
+
if (response.status >= 400) {
|
|
2576
|
+
throw new ApiExecutionError(response.status, response.data);
|
|
2577
|
+
}
|
|
2578
|
+
|
|
2527
2579
|
return response.data;
|
|
2528
2580
|
|
|
2529
2581
|
} catch (error) {
|
|
@@ -2540,10 +2592,14 @@ class MCPServer {
|
|
|
2540
2592
|
data: typeof responseData === 'object' ? JSON.stringify(responseData) : String(responseData)
|
|
2541
2593
|
});
|
|
2542
2594
|
|
|
2543
|
-
//
|
|
2544
|
-
|
|
2545
|
-
(
|
|
2546
|
-
throw
|
|
2595
|
+
// Structured so the CallTool handler can report this as an MCP tool
|
|
2596
|
+
// execution error carrying the API's own payload. Status is 0 for a
|
|
2597
|
+
// transport failure (DNS, ECONNREFUSED, timeout) — there is no response.
|
|
2598
|
+
throw new ApiExecutionError(
|
|
2599
|
+
responseStatus ?? 0,
|
|
2600
|
+
responseData,
|
|
2601
|
+
`API request failed with status ${responseStatus}: ${errorMessage}`
|
|
2602
|
+
);
|
|
2547
2603
|
}
|
|
2548
2604
|
|
|
2549
2605
|
throw error;
|
|
@@ -3,4 +3,4 @@
|
|
|
3
3
|
import { startServer } from '../core/runtime.js';
|
|
4
4
|
import tools from '../core/tools/agency-hosting.js';
|
|
5
5
|
|
|
6
|
-
startServer({ name: 'hostinger-agency-hosting-mcp', version: '1.61.
|
|
6
|
+
startServer({ name: 'hostinger-agency-hosting-mcp', version: '1.61.2', tools });
|
|
@@ -3,4 +3,4 @@
|
|
|
3
3
|
import { startServer } from '../core/runtime.js';
|
|
4
4
|
import tools from '../core/tools/agency-hosting.js';
|
|
5
5
|
|
|
6
|
-
startServer({ name: 'hostinger-agency-hosting-mcp', version: '1.61.
|
|
6
|
+
startServer({ name: 'hostinger-agency-hosting-mcp', version: '1.61.2', tools });
|
package/src/servers/all.js
CHANGED
package/src/servers/all.ts
CHANGED
package/src/servers/billing.js
CHANGED
package/src/servers/billing.ts
CHANGED
package/src/servers/dns.js
CHANGED
package/src/servers/dns.ts
CHANGED
package/src/servers/domains.js
CHANGED
package/src/servers/domains.ts
CHANGED
package/src/servers/ecommerce.js
CHANGED
package/src/servers/ecommerce.ts
CHANGED
package/src/servers/horizons.js
CHANGED
package/src/servers/horizons.ts
CHANGED
package/src/servers/hosting.js
CHANGED
package/src/servers/hosting.ts
CHANGED
package/src/servers/mail.js
CHANGED
package/src/servers/mail.ts
CHANGED
package/src/servers/reach.js
CHANGED
package/src/servers/reach.ts
CHANGED
package/src/servers/vps.js
CHANGED
package/src/servers/vps.ts
CHANGED
package/src/servers/wordpress.js
CHANGED
package/src/servers/wordpress.ts
CHANGED