@raiseinfo/smartorder-stdio-mcp 1.0.0 → 1.0.1
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/dist/tools/file-upload.js +45 -14
- package/dist/utils/http-client.d.ts +1 -1
- package/dist/utils/http-client.js +24 -7
- package/package.json +1 -1
- package/src/tools/file-upload.ts +45 -15
- package/src/utils/http-client.ts +27 -8
|
@@ -42,33 +42,63 @@ export async function handleUpload(args) {
|
|
|
42
42
|
await fileReader.validate(file_path);
|
|
43
43
|
let apiUrl;
|
|
44
44
|
let cache = await cacheManager.load();
|
|
45
|
+
const baseUrl = process.env.SMARTORDER_API_BASE || 'https://smart-order.raiseinfo.cn';
|
|
45
46
|
if (cache && !cacheManager.isExpired(cache)) {
|
|
47
|
+
console.log('[Upload] Using cached config');
|
|
46
48
|
apiUrl = cache.apiUrl;
|
|
47
49
|
}
|
|
48
50
|
else {
|
|
49
51
|
try {
|
|
52
|
+
console.log('[Upload] Fetching new config from backend...');
|
|
50
53
|
const config = await httpClient.getConfig();
|
|
51
|
-
|
|
54
|
+
if (config?.data?.apiUrl) {
|
|
55
|
+
apiUrl = config.data.apiUrl;
|
|
56
|
+
console.log('[Upload] Got config from backend:', apiUrl);
|
|
57
|
+
await cacheManager.save({
|
|
58
|
+
version: 1,
|
|
59
|
+
apiUrl: config.data.apiUrl,
|
|
60
|
+
folder: config.data.folder,
|
|
61
|
+
prefix: config.data.prefix,
|
|
62
|
+
tenantCode: process.env.TENANT_CODE || '',
|
|
63
|
+
expiresIn: config.data.expiresIn,
|
|
64
|
+
obtainedAt: Date.now(),
|
|
65
|
+
expiresAt: Date.now() + config.data.expiresIn * 1000,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
console.log('[Upload] Backend config invalid, using fallback');
|
|
70
|
+
apiUrl = baseUrl + '/api/mcp/upload';
|
|
71
|
+
await cacheManager.save({
|
|
72
|
+
version: 1,
|
|
73
|
+
apiUrl: apiUrl,
|
|
74
|
+
folder: 'smart-order/',
|
|
75
|
+
prefix: 'smart-order/',
|
|
76
|
+
tenantCode: process.env.TENANT_CODE || '',
|
|
77
|
+
expiresIn: 28800,
|
|
78
|
+
obtainedAt: Date.now(),
|
|
79
|
+
expiresAt: Date.now() + 28800 * 1000,
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
console.log('[Upload] Failed to get config, using fallback URL');
|
|
85
|
+
console.log('[Upload] Error:', error.message);
|
|
86
|
+
apiUrl = baseUrl + '/api/mcp/upload';
|
|
52
87
|
await cacheManager.save({
|
|
53
88
|
version: 1,
|
|
54
|
-
apiUrl:
|
|
55
|
-
folder:
|
|
56
|
-
prefix:
|
|
89
|
+
apiUrl: apiUrl,
|
|
90
|
+
folder: 'smart-order/',
|
|
91
|
+
prefix: 'smart-order/',
|
|
57
92
|
tenantCode: process.env.TENANT_CODE || '',
|
|
58
|
-
expiresIn:
|
|
93
|
+
expiresIn: 28800,
|
|
59
94
|
obtainedAt: Date.now(),
|
|
60
|
-
expiresAt: Date.now() +
|
|
95
|
+
expiresAt: Date.now() + 28800 * 1000,
|
|
61
96
|
});
|
|
62
97
|
}
|
|
63
|
-
catch (error) {
|
|
64
|
-
return {
|
|
65
|
-
content: [{ type: 'text', text: `获取配置失败:${error.message}` }],
|
|
66
|
-
isError: true,
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
98
|
}
|
|
70
99
|
try {
|
|
71
|
-
|
|
100
|
+
console.log('[Upload] Uploading to:', apiUrl);
|
|
101
|
+
const result = await httpClient.uploadFile(file_path, folder, apiUrl);
|
|
72
102
|
return {
|
|
73
103
|
content: [
|
|
74
104
|
{
|
|
@@ -87,7 +117,8 @@ export async function handleUpload(args) {
|
|
|
87
117
|
}
|
|
88
118
|
if (error.message.includes('5xx') || error.message.includes('网络')) {
|
|
89
119
|
try {
|
|
90
|
-
|
|
120
|
+
console.log('[Upload] Retrying upload...');
|
|
121
|
+
const result = await httpClient.uploadFile(file_path, folder, apiUrl);
|
|
91
122
|
return {
|
|
92
123
|
content: [{ type: 'text', text: JSON.stringify(result.data, null, 2) }],
|
|
93
124
|
};
|
|
@@ -5,6 +5,6 @@ export declare class HttpClient {
|
|
|
5
5
|
private mcpToken;
|
|
6
6
|
constructor();
|
|
7
7
|
getConfig(): Promise<McpConfigResponse>;
|
|
8
|
-
uploadFile(filePath: string, folder: string): Promise<McpUploadResponse>;
|
|
8
|
+
uploadFile(filePath: string, folder: string, apiUrl?: string): Promise<McpUploadResponse>;
|
|
9
9
|
private request;
|
|
10
10
|
}
|
|
@@ -14,16 +14,27 @@ export class HttpClient {
|
|
|
14
14
|
}
|
|
15
15
|
async getConfig() {
|
|
16
16
|
const url = `${this.baseUrl}/api/mcp/config`;
|
|
17
|
-
|
|
17
|
+
console.log('[HTTP] GET config from:', url);
|
|
18
|
+
console.log('[HTTP] Headers:', {
|
|
19
|
+
'X-Tenant-Code': this.tenantCode ? '***' : 'EMPTY',
|
|
20
|
+
'X-Mcp-Token': this.mcpToken ? '***' : 'EMPTY'
|
|
21
|
+
});
|
|
22
|
+
const result = await this.request('GET', url);
|
|
23
|
+
console.log('[HTTP] GET config response:', JSON.stringify(result, null, 2));
|
|
24
|
+
return result;
|
|
18
25
|
}
|
|
19
|
-
async uploadFile(filePath, folder) {
|
|
20
|
-
const url = `${this.baseUrl}/api/mcp/upload`;
|
|
26
|
+
async uploadFile(filePath, folder, apiUrl) {
|
|
27
|
+
const url = apiUrl || `${this.baseUrl}/api/mcp/upload`;
|
|
28
|
+
console.log('[HTTP] POST upload to:', url);
|
|
29
|
+
console.log('[HTTP] File:', filePath, 'Folder:', folder);
|
|
21
30
|
const form = new FormData();
|
|
22
31
|
const fileStream = fs.createReadStream(filePath);
|
|
23
32
|
const fileName = path.basename(filePath);
|
|
24
33
|
form.append('file', fileStream, { filename: fileName });
|
|
25
34
|
form.append('folder', folder);
|
|
26
|
-
|
|
35
|
+
const result = await this.request('POST', url, form, true);
|
|
36
|
+
console.log('[HTTP] Upload response:', JSON.stringify(result, null, 2));
|
|
37
|
+
return result;
|
|
27
38
|
}
|
|
28
39
|
request(method, url, body, isFormData = false) {
|
|
29
40
|
return new Promise((resolve, reject) => {
|
|
@@ -40,13 +51,16 @@ export class HttpClient {
|
|
|
40
51
|
...(isFormData ? body.getHeaders() : { 'Content-Type': 'application/json' }),
|
|
41
52
|
},
|
|
42
53
|
};
|
|
54
|
+
console.log('[HTTP] Request:', method, url);
|
|
43
55
|
const req = client.request(options, (res) => {
|
|
44
56
|
let data = '';
|
|
57
|
+
console.log('[HTTP] Response status:', res.statusCode);
|
|
45
58
|
res.on('data', (chunk) => (data += chunk));
|
|
46
59
|
res.on('end', () => {
|
|
60
|
+
console.log('[HTTP] Raw response:', data);
|
|
47
61
|
try {
|
|
48
62
|
const json = JSON.parse(data);
|
|
49
|
-
if (res.statusCode
|
|
63
|
+
if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) {
|
|
50
64
|
resolve(json);
|
|
51
65
|
}
|
|
52
66
|
else if (res.statusCode === 401 || res.statusCode === 403) {
|
|
@@ -59,12 +73,15 @@ export class HttpClient {
|
|
|
59
73
|
reject(new Error(`服务返回错误:${res.statusCode}`));
|
|
60
74
|
}
|
|
61
75
|
}
|
|
62
|
-
catch {
|
|
63
|
-
|
|
76
|
+
catch (e) {
|
|
77
|
+
console.error('[HTTP] Parse error:', e);
|
|
78
|
+
console.error('[HTTP] Raw data:', data);
|
|
79
|
+
reject(new Error('响应解析失败: ' + data));
|
|
64
80
|
}
|
|
65
81
|
});
|
|
66
82
|
});
|
|
67
83
|
req.on('error', (err) => {
|
|
84
|
+
console.error('[HTTP] Request error:', err);
|
|
68
85
|
reject(new Error(`网络错误:${err.message}`));
|
|
69
86
|
});
|
|
70
87
|
if (body) {
|
package/package.json
CHANGED
package/src/tools/file-upload.ts
CHANGED
|
@@ -49,34 +49,63 @@ export async function handleUpload(args: { file_path: string; folder?: string })
|
|
|
49
49
|
|
|
50
50
|
let apiUrl: string;
|
|
51
51
|
let cache = await cacheManager.load();
|
|
52
|
+
const baseUrl = process.env.SMARTORDER_API_BASE || 'https://smart-order.raiseinfo.cn';
|
|
52
53
|
|
|
53
54
|
if (cache && !cacheManager.isExpired(cache)) {
|
|
55
|
+
console.log('[Upload] Using cached config');
|
|
54
56
|
apiUrl = cache.apiUrl;
|
|
55
57
|
} else {
|
|
56
58
|
try {
|
|
59
|
+
console.log('[Upload] Fetching new config from backend...');
|
|
57
60
|
const config = await httpClient.getConfig();
|
|
58
|
-
|
|
59
|
-
|
|
61
|
+
|
|
62
|
+
if (config?.data?.apiUrl) {
|
|
63
|
+
apiUrl = config.data.apiUrl;
|
|
64
|
+
console.log('[Upload] Got config from backend:', apiUrl);
|
|
65
|
+
await cacheManager.save({
|
|
66
|
+
version: 1,
|
|
67
|
+
apiUrl: config.data.apiUrl,
|
|
68
|
+
folder: config.data.folder,
|
|
69
|
+
prefix: config.data.prefix,
|
|
70
|
+
tenantCode: process.env.TENANT_CODE || '',
|
|
71
|
+
expiresIn: config.data.expiresIn,
|
|
72
|
+
obtainedAt: Date.now(),
|
|
73
|
+
expiresAt: Date.now() + config.data.expiresIn * 1000,
|
|
74
|
+
});
|
|
75
|
+
} else {
|
|
76
|
+
console.log('[Upload] Backend config invalid, using fallback');
|
|
77
|
+
apiUrl = baseUrl + '/api/mcp/upload';
|
|
78
|
+
await cacheManager.save({
|
|
79
|
+
version: 1,
|
|
80
|
+
apiUrl: apiUrl,
|
|
81
|
+
folder: 'smart-order/',
|
|
82
|
+
prefix: 'smart-order/',
|
|
83
|
+
tenantCode: process.env.TENANT_CODE || '',
|
|
84
|
+
expiresIn: 28800,
|
|
85
|
+
obtainedAt: Date.now(),
|
|
86
|
+
expiresAt: Date.now() + 28800 * 1000,
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
} catch (error: any) {
|
|
90
|
+
console.log('[Upload] Failed to get config, using fallback URL');
|
|
91
|
+
console.log('[Upload] Error:', error.message);
|
|
92
|
+
apiUrl = baseUrl + '/api/mcp/upload';
|
|
60
93
|
await cacheManager.save({
|
|
61
94
|
version: 1,
|
|
62
|
-
apiUrl:
|
|
63
|
-
folder:
|
|
64
|
-
prefix:
|
|
95
|
+
apiUrl: apiUrl,
|
|
96
|
+
folder: 'smart-order/',
|
|
97
|
+
prefix: 'smart-order/',
|
|
65
98
|
tenantCode: process.env.TENANT_CODE || '',
|
|
66
|
-
expiresIn:
|
|
99
|
+
expiresIn: 28800,
|
|
67
100
|
obtainedAt: Date.now(),
|
|
68
|
-
expiresAt: Date.now() +
|
|
101
|
+
expiresAt: Date.now() + 28800 * 1000,
|
|
69
102
|
});
|
|
70
|
-
} catch (error: any) {
|
|
71
|
-
return {
|
|
72
|
-
content: [{ type: 'text', text: `获取配置失败:${error.message}` }],
|
|
73
|
-
isError: true,
|
|
74
|
-
};
|
|
75
103
|
}
|
|
76
104
|
}
|
|
77
105
|
|
|
78
106
|
try {
|
|
79
|
-
|
|
107
|
+
console.log('[Upload] Uploading to:', apiUrl);
|
|
108
|
+
const result = await httpClient.uploadFile(file_path, folder, apiUrl);
|
|
80
109
|
return {
|
|
81
110
|
content: [
|
|
82
111
|
{
|
|
@@ -95,7 +124,8 @@ export async function handleUpload(args: { file_path: string; folder?: string })
|
|
|
95
124
|
|
|
96
125
|
if (error.message.includes('5xx') || error.message.includes('网络')) {
|
|
97
126
|
try {
|
|
98
|
-
|
|
127
|
+
console.log('[Upload] Retrying upload...');
|
|
128
|
+
const result = await httpClient.uploadFile(file_path, folder, apiUrl);
|
|
99
129
|
return {
|
|
100
130
|
content: [{ type: 'text', text: JSON.stringify(result.data, null, 2) }],
|
|
101
131
|
};
|
|
@@ -112,4 +142,4 @@ export async function handleUpload(args: { file_path: string; folder?: string })
|
|
|
112
142
|
isError: true,
|
|
113
143
|
};
|
|
114
144
|
}
|
|
115
|
-
}
|
|
145
|
+
}
|
package/src/utils/http-client.ts
CHANGED
|
@@ -18,11 +18,20 @@ export class HttpClient {
|
|
|
18
18
|
|
|
19
19
|
async getConfig(): Promise<McpConfigResponse> {
|
|
20
20
|
const url = `${this.baseUrl}/api/mcp/config`;
|
|
21
|
-
|
|
21
|
+
console.log('[HTTP] GET config from:', url);
|
|
22
|
+
console.log('[HTTP] Headers:', {
|
|
23
|
+
'X-Tenant-Code': this.tenantCode ? '***' : 'EMPTY',
|
|
24
|
+
'X-Mcp-Token': this.mcpToken ? '***' : 'EMPTY'
|
|
25
|
+
});
|
|
26
|
+
const result = await this.request('GET', url);
|
|
27
|
+
console.log('[HTTP] GET config response:', JSON.stringify(result, null, 2));
|
|
28
|
+
return result as McpConfigResponse;
|
|
22
29
|
}
|
|
23
30
|
|
|
24
|
-
async uploadFile(filePath: string, folder: string): Promise<McpUploadResponse> {
|
|
25
|
-
const url = `${this.baseUrl}/api/mcp/upload`;
|
|
31
|
+
async uploadFile(filePath: string, folder: string, apiUrl?: string): Promise<McpUploadResponse> {
|
|
32
|
+
const url = apiUrl || `${this.baseUrl}/api/mcp/upload`;
|
|
33
|
+
console.log('[HTTP] POST upload to:', url);
|
|
34
|
+
console.log('[HTTP] File:', filePath, 'Folder:', folder);
|
|
26
35
|
const form = new FormData();
|
|
27
36
|
|
|
28
37
|
const fileStream = fs.createReadStream(filePath);
|
|
@@ -31,7 +40,9 @@ export class HttpClient {
|
|
|
31
40
|
form.append('file', fileStream, { filename: fileName });
|
|
32
41
|
form.append('folder', folder);
|
|
33
42
|
|
|
34
|
-
|
|
43
|
+
const result = await this.request('POST', url, form, true);
|
|
44
|
+
console.log('[HTTP] Upload response:', JSON.stringify(result, null, 2));
|
|
45
|
+
return result as McpUploadResponse;
|
|
35
46
|
}
|
|
36
47
|
|
|
37
48
|
private request(
|
|
@@ -56,13 +67,18 @@ export class HttpClient {
|
|
|
56
67
|
},
|
|
57
68
|
};
|
|
58
69
|
|
|
70
|
+
console.log('[HTTP] Request:', method, url);
|
|
71
|
+
|
|
59
72
|
const req = client.request(options, (res) => {
|
|
60
73
|
let data = '';
|
|
74
|
+
console.log('[HTTP] Response status:', res.statusCode);
|
|
75
|
+
|
|
61
76
|
res.on('data', (chunk) => (data += chunk));
|
|
62
77
|
res.on('end', () => {
|
|
78
|
+
console.log('[HTTP] Raw response:', data);
|
|
63
79
|
try {
|
|
64
80
|
const json = JSON.parse(data);
|
|
65
|
-
if (res.statusCode
|
|
81
|
+
if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) {
|
|
66
82
|
resolve(json);
|
|
67
83
|
} else if (res.statusCode === 401 || res.statusCode === 403) {
|
|
68
84
|
reject(new Error('认证失败,请检查租户Token配置'));
|
|
@@ -71,13 +87,16 @@ export class HttpClient {
|
|
|
71
87
|
} else {
|
|
72
88
|
reject(new Error(`服务返回错误:${res.statusCode}`));
|
|
73
89
|
}
|
|
74
|
-
} catch {
|
|
75
|
-
|
|
90
|
+
} catch (e) {
|
|
91
|
+
console.error('[HTTP] Parse error:', e);
|
|
92
|
+
console.error('[HTTP] Raw data:', data);
|
|
93
|
+
reject(new Error('响应解析失败: ' + data));
|
|
76
94
|
}
|
|
77
95
|
});
|
|
78
96
|
});
|
|
79
97
|
|
|
80
98
|
req.on('error', (err) => {
|
|
99
|
+
console.error('[HTTP] Request error:', err);
|
|
81
100
|
reject(new Error(`网络错误:${err.message}`));
|
|
82
101
|
});
|
|
83
102
|
|
|
@@ -92,4 +111,4 @@ export class HttpClient {
|
|
|
92
111
|
req.end();
|
|
93
112
|
});
|
|
94
113
|
}
|
|
95
|
-
}
|
|
114
|
+
}
|