@ameno/pi-minimax-mcp 1.0.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/LICENSE +21 -0
- package/README.md +207 -0
- package/bin/pi-minimax-mcp.js +163 -0
- package/dist/client.d.ts +30 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +189 -0
- package/dist/client.js.map +1 -0
- package/dist/config.d.ts +12 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +84 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +49 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +13 -0
- package/dist/types.js.map +1 -0
- package/dist/utils.d.ts +38 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +118 -0
- package/dist/utils.js.map +1 -0
- package/extensions/index.ts +271 -0
- package/package.json +67 -0
- package/skill/SKILL.md +63 -0
package/dist/config.js
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MiniMax MCP Configuration
|
|
3
|
+
*
|
|
4
|
+
* Handles configuration loading from files and environment variables
|
|
5
|
+
*/
|
|
6
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
7
|
+
import { homedir } from "node:os";
|
|
8
|
+
import { dirname, join } from "node:path";
|
|
9
|
+
import { DEFAULT_CONFIG } from "./types.js";
|
|
10
|
+
const CONFIG_PATHS = [
|
|
11
|
+
join(process.cwd(), ".pi", "extensions", "minimax-mcp.json"),
|
|
12
|
+
join(homedir(), ".pi", "agent", "extensions", "minimax-mcp.json"),
|
|
13
|
+
];
|
|
14
|
+
export function resolveConfigPath(customPath) {
|
|
15
|
+
if (customPath) {
|
|
16
|
+
return customPath.startsWith("~")
|
|
17
|
+
? join(homedir(), customPath.slice(1))
|
|
18
|
+
: customPath;
|
|
19
|
+
}
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
export function loadConfig(customPath) {
|
|
23
|
+
const paths = customPath
|
|
24
|
+
? [resolveConfigPath(customPath)]
|
|
25
|
+
: CONFIG_PATHS;
|
|
26
|
+
for (const path of paths) {
|
|
27
|
+
if (existsSync(path)) {
|
|
28
|
+
try {
|
|
29
|
+
const raw = readFileSync(path, "utf-8");
|
|
30
|
+
const parsed = JSON.parse(raw);
|
|
31
|
+
return mergeConfig(parsed);
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
console.warn(`[pi-minimax-mcp] Failed to load config from ${path}:`, error);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return mergeConfig({});
|
|
39
|
+
}
|
|
40
|
+
export function mergeConfig(overrides) {
|
|
41
|
+
const parseEnvInt = (val, fallback) => {
|
|
42
|
+
if (!val)
|
|
43
|
+
return fallback;
|
|
44
|
+
const parsed = parseInt(val, 10);
|
|
45
|
+
return Number.isNaN(parsed) ? fallback : parsed;
|
|
46
|
+
};
|
|
47
|
+
return {
|
|
48
|
+
apiKey: overrides.apiKey ?? process.env.MINIMAX_API_KEY ?? DEFAULT_CONFIG.apiKey,
|
|
49
|
+
apiHost: overrides.apiHost ?? process.env.MINIMAX_API_HOST ?? DEFAULT_CONFIG.apiHost,
|
|
50
|
+
basePath: overrides.basePath ?? process.env.MINIMAX_MCP_BASE_PATH ?? DEFAULT_CONFIG.basePath,
|
|
51
|
+
resourceMode: (overrides.resourceMode ?? process.env.MINIMAX_API_RESOURCE_MODE ?? DEFAULT_CONFIG.resourceMode),
|
|
52
|
+
timeoutMs: overrides.timeoutMs ?? parseEnvInt(process.env.MINIMAX_MCP_TIMEOUT_MS, DEFAULT_CONFIG.timeoutMs),
|
|
53
|
+
maxBytes: overrides.maxBytes ?? parseEnvInt(process.env.MINIMAX_MCP_MAX_BYTES, DEFAULT_CONFIG.maxBytes),
|
|
54
|
+
maxLines: overrides.maxLines ?? parseEnvInt(process.env.MINIMAX_MCP_MAX_LINES, DEFAULT_CONFIG.maxLines),
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
export function ensureDefaultConfig() {
|
|
58
|
+
const globalPath = CONFIG_PATHS[1];
|
|
59
|
+
if (existsSync(globalPath))
|
|
60
|
+
return;
|
|
61
|
+
try {
|
|
62
|
+
mkdirSync(dirname(globalPath), { recursive: true });
|
|
63
|
+
writeFileSync(globalPath, JSON.stringify({
|
|
64
|
+
apiKey: null,
|
|
65
|
+
apiHost: "https://api.minimax.io",
|
|
66
|
+
basePath: null,
|
|
67
|
+
resourceMode: "url",
|
|
68
|
+
timeoutMs: 60000,
|
|
69
|
+
maxBytes: 51200,
|
|
70
|
+
maxLines: 2000,
|
|
71
|
+
}, null, 2) + "\n", "utf-8");
|
|
72
|
+
console.log(`[pi-minimax-mcp] Created default config at ${globalPath}`);
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
console.warn(`[pi-minimax-mcp] Failed to create default config:`, error);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
export function validateConfig(config) {
|
|
79
|
+
if (!config.apiKey) {
|
|
80
|
+
throw new Error("MiniMax API key is required. Set MINIMAX_API_KEY environment variable or add to config file.\n" +
|
|
81
|
+
"Get your key at: https://platform.minimax.io/subscribe/coding-plan");
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* pi-minimax-mcp
|
|
3
|
+
*
|
|
4
|
+
* MiniMax MCP integration for Pi coding agent
|
|
5
|
+
* Provides web search and image understanding capabilities
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* // As Pi extension
|
|
9
|
+
* import minimaxMcp from "ameno-/pi-minimax-mcp/extensions";
|
|
10
|
+
*
|
|
11
|
+
* // As library
|
|
12
|
+
* import { MiniMaxMcpClient } from "ameno-/pi-minimax-mcp";
|
|
13
|
+
* const client = new MiniMaxMcpClient({ apiKey: "..." });
|
|
14
|
+
* const results = await client.webSearch({ query: "..." });
|
|
15
|
+
*/
|
|
16
|
+
export { MiniMaxMcpClient } from "./client.js";
|
|
17
|
+
export { loadConfig, mergeConfig, validateConfig, ensureDefaultConfig } from "./config.js";
|
|
18
|
+
export { formatToolOutput, formatBytes, redactSensitiveData, truncateHead } from "./utils.js";
|
|
19
|
+
export type { JsonRpcRequest, JsonRpcResponse, McpToolResult, MiniMaxMcpConfig, WebSearchParams, UnderstandImageParams, } from "./types.js";
|
|
20
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAC3F,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC9F,YAAY,EACV,cAAc,EACd,eAAe,EACf,aAAa,EACb,gBAAgB,EAChB,eAAe,EACf,qBAAqB,GACtB,MAAM,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* pi-minimax-mcp
|
|
3
|
+
*
|
|
4
|
+
* MiniMax MCP integration for Pi coding agent
|
|
5
|
+
* Provides web search and image understanding capabilities
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* // As Pi extension
|
|
9
|
+
* import minimaxMcp from "ameno-/pi-minimax-mcp/extensions";
|
|
10
|
+
*
|
|
11
|
+
* // As library
|
|
12
|
+
* import { MiniMaxMcpClient } from "ameno-/pi-minimax-mcp";
|
|
13
|
+
* const client = new MiniMaxMcpClient({ apiKey: "..." });
|
|
14
|
+
* const results = await client.webSearch({ query: "..." });
|
|
15
|
+
*/
|
|
16
|
+
export { MiniMaxMcpClient } from "./client.js";
|
|
17
|
+
export { loadConfig, mergeConfig, validateConfig, ensureDefaultConfig } from "./config.js";
|
|
18
|
+
export { formatToolOutput, formatBytes, redactSensitiveData, truncateHead } from "./utils.js";
|
|
19
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAC3F,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MiniMax MCP Types
|
|
3
|
+
*
|
|
4
|
+
* Type definitions for MiniMax MCP protocol
|
|
5
|
+
*/
|
|
6
|
+
export interface JsonRpcRequest {
|
|
7
|
+
jsonrpc: "2.0";
|
|
8
|
+
id: string | number;
|
|
9
|
+
method: string;
|
|
10
|
+
params?: Record<string, unknown>;
|
|
11
|
+
}
|
|
12
|
+
export interface JsonRpcResponse {
|
|
13
|
+
jsonrpc: "2.0";
|
|
14
|
+
id?: string | number | null;
|
|
15
|
+
result?: unknown;
|
|
16
|
+
error?: {
|
|
17
|
+
code: number;
|
|
18
|
+
message: string;
|
|
19
|
+
data?: unknown;
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
export interface McpToolResult {
|
|
23
|
+
content?: Array<{
|
|
24
|
+
type: string;
|
|
25
|
+
text?: string;
|
|
26
|
+
[key: string]: unknown;
|
|
27
|
+
}>;
|
|
28
|
+
isError?: boolean;
|
|
29
|
+
}
|
|
30
|
+
export interface MiniMaxMcpConfig {
|
|
31
|
+
apiKey?: string;
|
|
32
|
+
apiHost?: string;
|
|
33
|
+
basePath?: string;
|
|
34
|
+
resourceMode?: "url" | "local";
|
|
35
|
+
timeoutMs?: number;
|
|
36
|
+
maxBytes?: number;
|
|
37
|
+
maxLines?: number;
|
|
38
|
+
}
|
|
39
|
+
export interface WebSearchParams {
|
|
40
|
+
query: string;
|
|
41
|
+
numResults?: number;
|
|
42
|
+
recencyDays?: number;
|
|
43
|
+
}
|
|
44
|
+
export interface UnderstandImageParams {
|
|
45
|
+
imagePath: string;
|
|
46
|
+
prompt?: string;
|
|
47
|
+
}
|
|
48
|
+
export declare const DEFAULT_CONFIG: MiniMaxMcpConfig;
|
|
49
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,KAAK,CAAC;IACf,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,KAAK,CAAC;IACf,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAC5B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE;QACN,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,CAAC,EAAE,OAAO,CAAC;KAChB,CAAC;CACH;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,EAAE,KAAK,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;KACxB,CAAC,CAAC;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,KAAK,GAAG,OAAO,CAAC;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,eAAO,MAAM,cAAc,EAAE,gBAM5B,CAAC"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MiniMax MCP Types
|
|
3
|
+
*
|
|
4
|
+
* Type definitions for MiniMax MCP protocol
|
|
5
|
+
*/
|
|
6
|
+
export const DEFAULT_CONFIG = {
|
|
7
|
+
apiHost: "https://api.minimax.io",
|
|
8
|
+
resourceMode: "url",
|
|
9
|
+
timeoutMs: 60000,
|
|
10
|
+
maxBytes: 51200,
|
|
11
|
+
maxLines: 2000,
|
|
12
|
+
};
|
|
13
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAkDH,MAAM,CAAC,MAAM,cAAc,GAAqB;IAC9C,OAAO,EAAE,wBAAwB;IACjC,YAAY,EAAE,KAAK;IACnB,SAAS,EAAE,KAAK;IAChB,QAAQ,EAAE,KAAK;IACf,QAAQ,EAAE,IAAI;CACf,CAAC"}
|
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MiniMax MCP Utilities
|
|
3
|
+
*
|
|
4
|
+
* Output formatting, truncation, and helper functions
|
|
5
|
+
*/
|
|
6
|
+
import type { McpToolResult, MiniMaxMcpConfig } from "./types.js";
|
|
7
|
+
export interface FormatOptions {
|
|
8
|
+
maxBytes?: number;
|
|
9
|
+
maxLines?: number;
|
|
10
|
+
}
|
|
11
|
+
export interface FormattedOutput {
|
|
12
|
+
text: string;
|
|
13
|
+
details: {
|
|
14
|
+
truncated: boolean;
|
|
15
|
+
totalLines: number;
|
|
16
|
+
totalBytes: number;
|
|
17
|
+
outputLines: number;
|
|
18
|
+
outputBytes: number;
|
|
19
|
+
tempFile?: string;
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
export declare function formatToolOutput(result: McpToolResult, options?: FormatOptions): FormattedOutput;
|
|
23
|
+
export declare function writeTempFile(content: string): string;
|
|
24
|
+
export declare function formatBytes(bytes: number): string;
|
|
25
|
+
export declare function redactSensitiveData(config: MiniMaxMcpConfig): Partial<MiniMaxMcpConfig>;
|
|
26
|
+
export declare function truncateHead(text: string, options: {
|
|
27
|
+
maxBytes?: number;
|
|
28
|
+
maxLines?: number;
|
|
29
|
+
}): {
|
|
30
|
+
content: string;
|
|
31
|
+
truncated: boolean;
|
|
32
|
+
outputLines: number;
|
|
33
|
+
outputBytes: number;
|
|
34
|
+
totalLines: number;
|
|
35
|
+
totalBytes: number;
|
|
36
|
+
firstLineExceedsLimit: boolean;
|
|
37
|
+
};
|
|
38
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAElE,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE;QACP,SAAS,EAAE,OAAO,CAAC;QACnB,UAAU,EAAE,MAAM,CAAC;QACnB,UAAU,EAAE,MAAM,CAAC;QACnB,WAAW,EAAE,MAAM,CAAC;QACpB,WAAW,EAAE,MAAM,CAAC;QACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC;CACH;AAED,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,aAAa,EACrB,OAAO,GAAE,aAAkB,GAC1B,eAAe,CAwDjB;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAMrD;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAIjD;AAED,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,gBAAgB,GACvB,OAAO,CAAC,gBAAgB,CAAC,CAK3B;AAED,wBAAgB,YAAY,CAC1B,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAChD;IACD,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,qBAAqB,EAAE,OAAO,CAAC;CAChC,CA+CA"}
|
package/dist/utils.js
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MiniMax MCP Utilities
|
|
3
|
+
*
|
|
4
|
+
* Output formatting, truncation, and helper functions
|
|
5
|
+
*/
|
|
6
|
+
import { tmpdir } from "node:os";
|
|
7
|
+
import { join } from "node:path";
|
|
8
|
+
import { writeFileSync } from "node:fs";
|
|
9
|
+
export function formatToolOutput(result, options = {}) {
|
|
10
|
+
const { maxBytes = 51200, maxLines = 2000 } = options;
|
|
11
|
+
const contentBlocks = Array.isArray(result.content) ? result.content : [];
|
|
12
|
+
const textBlocks = contentBlocks
|
|
13
|
+
.filter((b) => b.type === "text" && typeof b.text === "string")
|
|
14
|
+
.map((b) => b.text);
|
|
15
|
+
const rawText = textBlocks.join("\n\n") || JSON.stringify(result, null, 2);
|
|
16
|
+
const lines = rawText.split("\n");
|
|
17
|
+
const totalLines = lines.length;
|
|
18
|
+
const totalBytes = Buffer.byteLength(rawText, "utf-8");
|
|
19
|
+
// Check if truncation needed
|
|
20
|
+
const truncateByLines = totalLines > maxLines;
|
|
21
|
+
const truncateByBytes = totalBytes > maxBytes;
|
|
22
|
+
let outputText = rawText;
|
|
23
|
+
let tempFile;
|
|
24
|
+
if (truncateByLines || truncateByBytes) {
|
|
25
|
+
// Determine truncation strategy
|
|
26
|
+
if (truncateByBytes && totalBytes > maxBytes) {
|
|
27
|
+
// Truncate by bytes (keep from end)
|
|
28
|
+
const buffer = Buffer.from(rawText, "utf-8");
|
|
29
|
+
const truncated = buffer.slice(-maxBytes).toString("utf-8");
|
|
30
|
+
// Clean up partial UTF-8 character at start
|
|
31
|
+
outputText = truncated.replace(/^[^\n]*\n/, "");
|
|
32
|
+
}
|
|
33
|
+
if (truncateByLines) {
|
|
34
|
+
outputText = lines.slice(-maxLines).join("\n");
|
|
35
|
+
}
|
|
36
|
+
// Write full output to temp file
|
|
37
|
+
tempFile = writeTempFile(rawText);
|
|
38
|
+
const truncationInfo = `\n\n[Output truncated: ${Math.min(totalLines, maxLines)} of ${totalLines} lines (${formatBytes(Math.min(totalBytes, maxBytes))} of ${formatBytes(totalBytes)}). Full output: ${tempFile}]`;
|
|
39
|
+
outputText += truncationInfo;
|
|
40
|
+
}
|
|
41
|
+
const outputLines = outputText.split("\n").length;
|
|
42
|
+
const outputBytes = Buffer.byteLength(outputText, "utf-8");
|
|
43
|
+
return {
|
|
44
|
+
text: outputText,
|
|
45
|
+
details: {
|
|
46
|
+
truncated: truncateByLines || truncateByBytes,
|
|
47
|
+
totalLines,
|
|
48
|
+
totalBytes,
|
|
49
|
+
outputLines,
|
|
50
|
+
outputBytes,
|
|
51
|
+
tempFile,
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
export function writeTempFile(content) {
|
|
56
|
+
const timestamp = Date.now();
|
|
57
|
+
const filename = `pi-minimax-mcp-${timestamp}.txt`;
|
|
58
|
+
const filepath = join(tmpdir(), filename);
|
|
59
|
+
writeFileSync(filepath, content, "utf-8");
|
|
60
|
+
return filepath;
|
|
61
|
+
}
|
|
62
|
+
export function formatBytes(bytes) {
|
|
63
|
+
if (bytes < 1024)
|
|
64
|
+
return `${bytes}B`;
|
|
65
|
+
if (bytes < 1024 * 1024)
|
|
66
|
+
return `${(bytes / 1024).toFixed(1)}KB`;
|
|
67
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
|
|
68
|
+
}
|
|
69
|
+
export function redactSensitiveData(config) {
|
|
70
|
+
return {
|
|
71
|
+
...config,
|
|
72
|
+
apiKey: config.apiKey ? "***REDACTED***" : undefined,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
export function truncateHead(text, options) {
|
|
76
|
+
const maxBytes = options.maxBytes ?? 51200;
|
|
77
|
+
const maxLines = options.maxLines ?? 2000;
|
|
78
|
+
const totalBytes = Buffer.byteLength(text, "utf-8");
|
|
79
|
+
const lines = text.split("\n");
|
|
80
|
+
const totalLines = lines.length;
|
|
81
|
+
let content = text;
|
|
82
|
+
let truncated = false;
|
|
83
|
+
let firstLineExceedsLimit = false;
|
|
84
|
+
// Check if first line alone exceeds byte limit
|
|
85
|
+
if (lines[0] && Buffer.byteLength(lines[0], "utf-8") > maxBytes) {
|
|
86
|
+
firstLineExceedsLimit = true;
|
|
87
|
+
content = lines[0].slice(0, maxBytes) + "... [truncated]";
|
|
88
|
+
truncated = true;
|
|
89
|
+
}
|
|
90
|
+
else if (totalLines > maxLines || totalBytes > maxBytes) {
|
|
91
|
+
truncated = true;
|
|
92
|
+
// Keep from the end (most recent content)
|
|
93
|
+
if (totalLines > maxLines) {
|
|
94
|
+
content = lines.slice(-maxLines).join("\n");
|
|
95
|
+
}
|
|
96
|
+
// Apply byte limit if still over
|
|
97
|
+
const contentBytes = Buffer.byteLength(content, "utf-8");
|
|
98
|
+
if (contentBytes > maxBytes) {
|
|
99
|
+
const buffer = Buffer.from(content, "utf-8");
|
|
100
|
+
content = buffer.slice(-maxBytes).toString("utf-8");
|
|
101
|
+
// Remove potential partial line at start
|
|
102
|
+
const newlineIdx = content.indexOf("\n");
|
|
103
|
+
if (newlineIdx > 0) {
|
|
104
|
+
content = content.slice(newlineIdx + 1);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return {
|
|
109
|
+
content,
|
|
110
|
+
truncated,
|
|
111
|
+
outputLines: content.split("\n").length,
|
|
112
|
+
outputBytes: Buffer.byteLength(content, "utf-8"),
|
|
113
|
+
totalLines,
|
|
114
|
+
totalBytes,
|
|
115
|
+
firstLineExceedsLimit,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MiniMax MCP Pi Extension
|
|
3
|
+
*
|
|
4
|
+
* Provides MiniMax MCP tools via Pi's ExtensionAPI:
|
|
5
|
+
* - web_search: Real-time web search
|
|
6
|
+
* - understand_image: Image analysis and description
|
|
7
|
+
*
|
|
8
|
+
* Setup:
|
|
9
|
+
* 1. Install: pi install npm:@ameno/pi-minimax-mcp
|
|
10
|
+
* 2. Get API key: https://platform.minimax.io/subscribe/coding-plan
|
|
11
|
+
* 3. Set env: MINIMAX_API_KEY=your-key
|
|
12
|
+
*
|
|
13
|
+
* Or use config file: ~/.pi/agent/extensions/minimax-mcp.json
|
|
14
|
+
*
|
|
15
|
+
* Usage:
|
|
16
|
+
* "Search the web for quantum computing breakthroughs"
|
|
17
|
+
* "What does this image show? ./screenshot.png"
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import { Type } from "@sinclair/typebox";
|
|
21
|
+
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
|
22
|
+
import { MiniMaxMcpClient } from "../src/client.js";
|
|
23
|
+
import { ensureDefaultConfig, loadConfig, mergeConfig, validateConfig } from "../src/config.js";
|
|
24
|
+
import { formatToolOutput, redactSensitiveData } from "../src/utils.js";
|
|
25
|
+
|
|
26
|
+
// =============================================================================
|
|
27
|
+
// Extension Entry Point
|
|
28
|
+
// =============================================================================
|
|
29
|
+
|
|
30
|
+
export default function minimaxMcp(pi: ExtensionAPI) {
|
|
31
|
+
// Register CLI flags
|
|
32
|
+
pi.registerFlag("--minimax-api-key", {
|
|
33
|
+
description: "MiniMax API key (overrides env/config)",
|
|
34
|
+
type: "string",
|
|
35
|
+
});
|
|
36
|
+
pi.registerFlag("--minimax-api-host", {
|
|
37
|
+
description: "MiniMax API host (default: https://api.minimax.io)",
|
|
38
|
+
type: "string",
|
|
39
|
+
});
|
|
40
|
+
pi.registerFlag("--minimax-mcp-config", {
|
|
41
|
+
description: "Path to JSON config file",
|
|
42
|
+
type: "string",
|
|
43
|
+
});
|
|
44
|
+
pi.registerFlag("--minimax-mcp-max-bytes", {
|
|
45
|
+
description: "Max bytes to keep from tool output (default: 51200)",
|
|
46
|
+
type: "string",
|
|
47
|
+
});
|
|
48
|
+
pi.registerFlag("--minimax-mcp-max-lines", {
|
|
49
|
+
description: "Max lines to keep from tool output (default: 2000)",
|
|
50
|
+
type: "string",
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
// Ensure default config exists
|
|
54
|
+
ensureDefaultConfig();
|
|
55
|
+
|
|
56
|
+
// Get effective configuration
|
|
57
|
+
const getConfig = () => {
|
|
58
|
+
const configFlag = pi.getFlag("--minimax-mcp-config");
|
|
59
|
+
const baseConfig = loadConfig(
|
|
60
|
+
typeof configFlag === "string" ? configFlag : undefined
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
const apiKeyFlag = pi.getFlag("--minimax-api-key");
|
|
64
|
+
const hostFlag = pi.getFlag("--minimax-api-host");
|
|
65
|
+
const maxBytesFlag = pi.getFlag("--minimax-mcp-max-bytes");
|
|
66
|
+
const maxLinesFlag = pi.getFlag("--minimax-mcp-max-lines");
|
|
67
|
+
|
|
68
|
+
return mergeConfig({
|
|
69
|
+
apiKey: typeof apiKeyFlag === "string" ? apiKeyFlag : baseConfig.apiKey,
|
|
70
|
+
apiHost: typeof hostFlag === "string" ? hostFlag : baseConfig.apiHost,
|
|
71
|
+
maxBytes:
|
|
72
|
+
typeof maxBytesFlag === "string"
|
|
73
|
+
? parseInt(maxBytesFlag, 10)
|
|
74
|
+
: baseConfig.maxBytes,
|
|
75
|
+
maxLines:
|
|
76
|
+
typeof maxLinesFlag === "string"
|
|
77
|
+
? parseInt(maxLinesFlag, 10)
|
|
78
|
+
: baseConfig.maxLines,
|
|
79
|
+
});
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
// Tool parameter schemas
|
|
83
|
+
const webSearchParams = Type.Object(
|
|
84
|
+
{
|
|
85
|
+
query: Type.String({ description: "Search query" }),
|
|
86
|
+
numResults: Type.Optional(
|
|
87
|
+
Type.Integer({
|
|
88
|
+
description: "Number of results to return (default: 5)",
|
|
89
|
+
minimum: 1,
|
|
90
|
+
maximum: 10,
|
|
91
|
+
})
|
|
92
|
+
),
|
|
93
|
+
recencyDays: Type.Optional(
|
|
94
|
+
Type.Integer({
|
|
95
|
+
description: "Limit results to recent days",
|
|
96
|
+
minimum: 1,
|
|
97
|
+
})
|
|
98
|
+
),
|
|
99
|
+
},
|
|
100
|
+
{ additionalProperties: false }
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
const understandImageParams = Type.Object(
|
|
104
|
+
{
|
|
105
|
+
imagePath: Type.String({
|
|
106
|
+
description: "Path to image file (relative or absolute)",
|
|
107
|
+
}),
|
|
108
|
+
prompt: Type.Optional(
|
|
109
|
+
Type.String({
|
|
110
|
+
description: "Optional prompt to guide image understanding",
|
|
111
|
+
})
|
|
112
|
+
),
|
|
113
|
+
},
|
|
114
|
+
{ additionalProperties: false }
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
// Register web_search tool
|
|
118
|
+
pi.registerTool({
|
|
119
|
+
name: "web_search",
|
|
120
|
+
label: "MiniMax Web Search",
|
|
121
|
+
description:
|
|
122
|
+
"Real-time web search via MiniMax. Best for current information, news, documentation, and facts.",
|
|
123
|
+
parameters: webSearchParams,
|
|
124
|
+
async execute(_toolCallId, params, onUpdate, _ctx, signal) {
|
|
125
|
+
const config = getConfig();
|
|
126
|
+
|
|
127
|
+
try {
|
|
128
|
+
validateConfig(config);
|
|
129
|
+
} catch (err) {
|
|
130
|
+
return {
|
|
131
|
+
content: [
|
|
132
|
+
{
|
|
133
|
+
type: "text",
|
|
134
|
+
text:
|
|
135
|
+
err instanceof Error
|
|
136
|
+
? err.message
|
|
137
|
+
: "MiniMax configuration error",
|
|
138
|
+
},
|
|
139
|
+
],
|
|
140
|
+
isError: true,
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if (signal?.aborted) {
|
|
145
|
+
return { content: [{ type: "text", text: "Cancelled" }] };
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
onUpdate?.({
|
|
149
|
+
content: [{ type: "text", text: `Searching: "${params.query}"...` }],
|
|
150
|
+
details: { status: "pending" },
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
const client = new MiniMaxMcpClient(config);
|
|
154
|
+
|
|
155
|
+
try {
|
|
156
|
+
const result = await client.webSearch({
|
|
157
|
+
query: params.query,
|
|
158
|
+
numResults: params.numResults,
|
|
159
|
+
recencyDays: params.recencyDays,
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
if (signal?.aborted) {
|
|
163
|
+
return { content: [{ type: "text", text: "Cancelled" }] };
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const formatted = formatToolOutput(result, {
|
|
167
|
+
maxBytes: config.maxBytes,
|
|
168
|
+
maxLines: config.maxLines,
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
return {
|
|
172
|
+
content: [{ type: "text", text: formatted.text }],
|
|
173
|
+
details: {
|
|
174
|
+
...formatted.details,
|
|
175
|
+
config: redactSensitiveData(config),
|
|
176
|
+
},
|
|
177
|
+
isError: result.isError,
|
|
178
|
+
};
|
|
179
|
+
} catch (error) {
|
|
180
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
181
|
+
return {
|
|
182
|
+
content: [{ type: "text", text: `MiniMax MCP error: ${message}` }],
|
|
183
|
+
isError: true,
|
|
184
|
+
details: {
|
|
185
|
+
error: message,
|
|
186
|
+
config: redactSensitiveData(config),
|
|
187
|
+
},
|
|
188
|
+
};
|
|
189
|
+
} finally {
|
|
190
|
+
client.disconnect();
|
|
191
|
+
}
|
|
192
|
+
},
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
// Register understand_image tool
|
|
196
|
+
pi.registerTool({
|
|
197
|
+
name: "understand_image",
|
|
198
|
+
label: "MiniMax Image Understanding",
|
|
199
|
+
description:
|
|
200
|
+
"Analyze and describe image content via MiniMax. Best for screenshots, diagrams, photos, and visual analysis.",
|
|
201
|
+
parameters: understandImageParams,
|
|
202
|
+
async execute(_toolCallId, params, onUpdate, _ctx, signal) {
|
|
203
|
+
const config = getConfig();
|
|
204
|
+
|
|
205
|
+
try {
|
|
206
|
+
validateConfig(config);
|
|
207
|
+
} catch (err) {
|
|
208
|
+
return {
|
|
209
|
+
content: [
|
|
210
|
+
{
|
|
211
|
+
type: "text",
|
|
212
|
+
text:
|
|
213
|
+
err instanceof Error
|
|
214
|
+
? err.message
|
|
215
|
+
: "MiniMax configuration error",
|
|
216
|
+
},
|
|
217
|
+
],
|
|
218
|
+
isError: true,
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
if (signal?.aborted) {
|
|
223
|
+
return { content: [{ type: "text", text: "Cancelled" }] };
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
onUpdate?.({
|
|
227
|
+
content: [{ type: "text", text: "Analyzing image..." }],
|
|
228
|
+
details: { status: "pending" },
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
const client = new MiniMaxMcpClient(config);
|
|
232
|
+
|
|
233
|
+
try {
|
|
234
|
+
const result = await client.understandImage({
|
|
235
|
+
imagePath: params.imagePath,
|
|
236
|
+
prompt: params.prompt,
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
if (signal?.aborted) {
|
|
240
|
+
return { content: [{ type: "text", text: "Cancelled" }] };
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
const formatted = formatToolOutput(result, {
|
|
244
|
+
maxBytes: config.maxBytes,
|
|
245
|
+
maxLines: config.maxLines,
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
return {
|
|
249
|
+
content: [{ type: "text", text: formatted.text }],
|
|
250
|
+
details: {
|
|
251
|
+
...formatted.details,
|
|
252
|
+
config: redactSensitiveData(config),
|
|
253
|
+
},
|
|
254
|
+
isError: result.isError,
|
|
255
|
+
};
|
|
256
|
+
} catch (error) {
|
|
257
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
258
|
+
return {
|
|
259
|
+
content: [{ type: "text", text: `MiniMax MCP error: ${message}` }],
|
|
260
|
+
isError: true,
|
|
261
|
+
details: {
|
|
262
|
+
error: message,
|
|
263
|
+
config: redactSensitiveData(config),
|
|
264
|
+
},
|
|
265
|
+
};
|
|
266
|
+
} finally {
|
|
267
|
+
client.disconnect();
|
|
268
|
+
}
|
|
269
|
+
},
|
|
270
|
+
});
|
|
271
|
+
}
|