@mafdet/mcp 1.5.1 → 1.7.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/README.md +3 -3
- package/dist/client.js +48 -30
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -17,7 +17,7 @@ OpenAI API works by pointing its base URL and key at Mafdet AI.
|
|
|
17
17
|
- Base URL: `https://api.mafdet.ai/v1`
|
|
18
18
|
- Endpoints: `/chat/completions`, `/embeddings`, `/audio/speech`
|
|
19
19
|
- Providers: Google (Gemini), Kimi (Moonshot), Qwen, DeepSeek
|
|
20
|
-
-
|
|
20
|
+
- The catalogue changes; the authoritative model list
|
|
21
21
|
with current prices is [`models.json`](https://docs.mafdet.ai/models.json)
|
|
22
22
|
- Docs: <https://docs.mafdet.ai>
|
|
23
23
|
|
|
@@ -25,7 +25,7 @@ OpenAI API works by pointing its base URL and key at Mafdet AI.
|
|
|
25
25
|
|
|
26
26
|
| Tool | Needs a key | What it does |
|
|
27
27
|
| --- | --- | --- |
|
|
28
|
-
| `list_models` | no | List Mafdet AI models with provider, tier, per
|
|
28
|
+
| `list_models` | no | List Mafdet AI models with provider, tier, pricing per dimension (tokens, images, or seconds), and a `[preview]` / `[beta]` marker for models the provider has not declared generally available |
|
|
29
29
|
| `search_docs` | no | Search the Mafdet AI documentation (titles, URLs, summaries) |
|
|
30
30
|
| `get_balance` | yes | Your organization's wallet: balance, bonus, frozen, available |
|
|
31
31
|
| `get_usage_summary` | yes | Requests, tokens, and charge over the last N days (1–90) |
|
|
@@ -100,7 +100,7 @@ Omit `MAFDET_API_KEY` to use only the public tools (`list_models`,
|
|
|
100
100
|
|
|
101
101
|
## Notes
|
|
102
102
|
|
|
103
|
-
- Pin a major version (`@mafdet/mcp@
|
|
103
|
+
- Pin a major version (`@mafdet/mcp@1`) in automated setups to avoid surprise
|
|
104
104
|
upgrades.
|
|
105
105
|
- The server writes only JSON-RPC to stdout; diagnostics go to stderr and never
|
|
106
106
|
include your key.
|
package/dist/client.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { redact } from "./logger.js";
|
|
1
|
+
import { redact, logError } from "./logger.js";
|
|
2
2
|
// MCP-002B: the single HTTP client for every Mafdet call. It enforces a total
|
|
3
3
|
// timeout, a response-body size cap, and JSON validation; attaches the Bearer
|
|
4
4
|
// key ONLY on account requests; and maps every failure to a stable, actionable
|
|
@@ -16,37 +16,54 @@ export class MafdetClientError extends Error {
|
|
|
16
16
|
export async function getJson(options) {
|
|
17
17
|
const url = buildUrl(options.baseUrl, options.path, options.query);
|
|
18
18
|
const controller = new AbortController();
|
|
19
|
-
|
|
20
|
-
let
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
if (!response.ok)
|
|
33
|
-
throw mapStatus(response.status);
|
|
34
|
-
const contentType = response.headers.get("content-type") ?? "";
|
|
35
|
-
if (!contentType.includes("application/json")) {
|
|
36
|
-
throw new MafdetClientError("bad_response", "Mafdet AI returned an unexpected (non-JSON) response");
|
|
37
|
-
}
|
|
38
|
-
const text = await readBounded(response);
|
|
19
|
+
let reader;
|
|
20
|
+
let timer;
|
|
21
|
+
const deadline = new Promise((_resolve, reject) => {
|
|
22
|
+
timer = setTimeout(() => {
|
|
23
|
+
reject(new MafdetClientError("network", "could not reach Mafdet AI (timed out)"));
|
|
24
|
+
void reader
|
|
25
|
+
?.cancel()
|
|
26
|
+
.catch(() => logError("response cleanup failed after timeout"));
|
|
27
|
+
controller.abort();
|
|
28
|
+
}, options.timeoutMs ?? DEFAULT_TIMEOUT_MS);
|
|
29
|
+
});
|
|
30
|
+
const request = async () => {
|
|
31
|
+
let response;
|
|
39
32
|
try {
|
|
40
|
-
|
|
33
|
+
const headers = { Accept: "application/json" };
|
|
34
|
+
if (options.authKey) {
|
|
35
|
+
headers.Authorization = `Bearer ${options.authKey}`;
|
|
36
|
+
}
|
|
37
|
+
response = await fetch(url, {
|
|
38
|
+
method: "GET",
|
|
39
|
+
headers,
|
|
40
|
+
signal: controller.signal,
|
|
41
|
+
redirect: "error",
|
|
42
|
+
});
|
|
43
|
+
if (!response.ok)
|
|
44
|
+
throw mapStatus(response.status);
|
|
45
|
+
const contentType = response.headers.get("content-type") ?? "";
|
|
46
|
+
if (!contentType.includes("application/json")) {
|
|
47
|
+
throw new MafdetClientError("bad_response", "Mafdet AI returned an unexpected (non-JSON) response");
|
|
48
|
+
}
|
|
49
|
+
const text = await readBounded(response, (value) => {
|
|
50
|
+
reader = value;
|
|
51
|
+
});
|
|
52
|
+
try {
|
|
53
|
+
return JSON.parse(text);
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
throw new MafdetClientError("bad_response", "Mafdet AI returned malformed JSON");
|
|
57
|
+
}
|
|
41
58
|
}
|
|
42
|
-
catch {
|
|
43
|
-
|
|
59
|
+
catch (error) {
|
|
60
|
+
if (error instanceof MafdetClientError)
|
|
61
|
+
throw error;
|
|
62
|
+
throw new MafdetClientError("network", `could not reach Mafdet AI (${describeNetworkError(error)})`);
|
|
44
63
|
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
throw error;
|
|
49
|
-
throw new MafdetClientError("network", `could not reach Mafdet AI (${describeNetworkError(error)})`);
|
|
64
|
+
};
|
|
65
|
+
try {
|
|
66
|
+
return await Promise.race([request(), deadline]);
|
|
50
67
|
}
|
|
51
68
|
finally {
|
|
52
69
|
clearTimeout(timer);
|
|
@@ -76,11 +93,12 @@ function mapStatus(status) {
|
|
|
76
93
|
return new MafdetClientError("unavailable", `Mafdet AI is temporarily unavailable (HTTP ${status})`);
|
|
77
94
|
}
|
|
78
95
|
// Read the response body but never buffer more than the cap.
|
|
79
|
-
async function readBounded(response) {
|
|
96
|
+
async function readBounded(response, onReader) {
|
|
80
97
|
const reader = response.body?.getReader();
|
|
81
98
|
if (!reader) {
|
|
82
99
|
return "";
|
|
83
100
|
}
|
|
101
|
+
onReader(reader);
|
|
84
102
|
const decoder = new TextDecoder();
|
|
85
103
|
let total = 0;
|
|
86
104
|
let out = "";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mafdet/mcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.0",
|
|
4
4
|
"description": "Mafdet AI MCP server — read-only account tools (models, balance, usage, subscription, docs) for Claude Code, Cursor, Codex, OpenCode, and Claude Desktop.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|