60 lines
1.6 KiB
TypeScript
60 lines
1.6 KiB
TypeScript
// @ts-nocheck
|
|
|
|
|
|
import { httpUrl, loadToken } from '../utils/config.js';
|
|
|
|
const TOKEN = loadToken();
|
|
|
|
export async function listTools() {
|
|
|
|
const r = await callTool('metro_list_tools', {});
|
|
if (r.ok) {
|
|
return r.result?.tools || [];
|
|
}
|
|
return [];
|
|
}
|
|
|
|
export async function callTool(name, args, opts = {}) {
|
|
const t0 = performance.now();
|
|
const headers = { 'Content-Type': 'application/json' };
|
|
if (TOKEN) headers['X-MCP-Token'] = TOKEN;
|
|
if (opts.traceId) headers['X-Trace-Id'] = opts.traceId;
|
|
|
|
let r;
|
|
let lastError;
|
|
for (let attempt = 0; attempt < 2; attempt++) {
|
|
const controller = new AbortController();
|
|
const timeout = setTimeout(() => controller.abort(), 30000);
|
|
if (opts.signal) {
|
|
opts.signal.addEventListener('abort', () => controller.abort());
|
|
}
|
|
try {
|
|
r = await fetch(httpUrl(name), {
|
|
method: 'POST',
|
|
headers,
|
|
body: JSON.stringify(args || {}),
|
|
signal: controller.signal,
|
|
});
|
|
clearTimeout(timeout);
|
|
break;
|
|
} catch (e) {
|
|
clearTimeout(timeout);
|
|
lastError = e;
|
|
if (e.name === 'AbortError' || attempt === 1) throw e;
|
|
}
|
|
}
|
|
if (!r) throw lastError || new Error('HTTP 请求失败');
|
|
|
|
const durationMs = performance.now() - t0;
|
|
const json = await r.json();
|
|
|
|
return {
|
|
ok: !!json.ok,
|
|
result: json.result,
|
|
error: json.error,
|
|
meta: json.meta,
|
|
durationMs,
|
|
protocol: 'http',
|
|
};
|
|
}
|