Proxy NDC agent MCP through AI workspace hub
This commit is contained in:
parent
4e57287b5a
commit
8154890ac9
|
|
@ -60,6 +60,8 @@ app.post("/api/ai-workspace/hub/v1/agents/:pairingCode/dispatch", requireInterna
|
||||||
res.json({ ok: true, requestId: dispatch.requestId });
|
res.json({ ok: true, requestId: dispatch.requestId });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
app.use("/api/ai-workspace/hub/v1/ndc-agent-mcp/:pairingCode", asyncRoute(proxyNdcAgentMcp));
|
||||||
|
|
||||||
app.use((error, _req, res, _next) => {
|
app.use((error, _req, res, _next) => {
|
||||||
const status = Number(error?.status || 500);
|
const status = Number(error?.status || 500);
|
||||||
res.status(status >= 400 && status < 600 ? status : 500).json({
|
res.status(status >= 400 && status < 600 ? status : 500).json({
|
||||||
|
|
@ -218,6 +220,42 @@ function dispatchAgent(pairingCodeRaw, command, payload = {}, timeoutMs = 30000,
|
||||||
return { requestId };
|
return { requestId };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function proxyNdcAgentMcp(req, res) {
|
||||||
|
if (!config.engineInternalUrl || !config.engineInternalAccessToken) {
|
||||||
|
res.status(503).json({ ok: false, error: "engine_proxy_not_configured" });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const pairingCode = cleanPairingCode(req.params.pairingCode);
|
||||||
|
const agent = agentsByCode.get(pairingCode);
|
||||||
|
if (!agent || !isAgentOnline(agent)) {
|
||||||
|
res.status(503).json({ ok: false, error: "bridge_agent_offline" });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const marker = `/api/ai-workspace/hub/v1/ndc-agent-mcp/${encodeURIComponent(req.params.pairingCode)}`;
|
||||||
|
const suffix = String(req.originalUrl || "").startsWith(marker)
|
||||||
|
? String(req.originalUrl || "").slice(marker.length)
|
||||||
|
: String(req.url || "");
|
||||||
|
const targetUrl = `${config.engineInternalUrl.replace(/\/+$/, "")}/api/ndc-agent-mcp${suffix || ""}`;
|
||||||
|
const method = String(req.method || "GET").toUpperCase();
|
||||||
|
const hasBody = !["GET", "HEAD"].includes(method);
|
||||||
|
const upstream = await fetch(targetUrl, {
|
||||||
|
method,
|
||||||
|
redirect: "manual",
|
||||||
|
headers: {
|
||||||
|
Accept: "application/json",
|
||||||
|
Authorization: `Bearer ${config.engineInternalAccessToken}`,
|
||||||
|
...(hasBody ? { "Content-Type": "application/json" } : {}),
|
||||||
|
},
|
||||||
|
...(hasBody ? { body: JSON.stringify(req.body || {}) } : {}),
|
||||||
|
});
|
||||||
|
const contentType = upstream.headers.get("content-type") || "application/json; charset=utf-8";
|
||||||
|
const text = await upstream.text();
|
||||||
|
res.status(upstream.status);
|
||||||
|
res.setHeader("content-type", contentType);
|
||||||
|
res.send(text);
|
||||||
|
}
|
||||||
|
|
||||||
function startAgentRequest(pairingCodeRaw, command, payload = {}, timeoutMs = 30000, options = {}) {
|
function startAgentRequest(pairingCodeRaw, command, payload = {}, timeoutMs = 30000, options = {}) {
|
||||||
const pairingCode = cleanPairingCode(pairingCodeRaw);
|
const pairingCode = cleanPairingCode(pairingCodeRaw);
|
||||||
const agent = agentsByCode.get(pairingCode);
|
const agent = agentsByCode.get(pairingCode);
|
||||||
|
|
@ -432,6 +470,8 @@ function readConfig() {
|
||||||
port: Number(process.env.PORT || 18081),
|
port: Number(process.env.PORT || 18081),
|
||||||
wsPath: process.env.AI_WORKSPACE_HUB_WS_PATH || DEFAULT_WS_PATH,
|
wsPath: process.env.AI_WORKSPACE_HUB_WS_PATH || DEFAULT_WS_PATH,
|
||||||
internalAccessTokens,
|
internalAccessTokens,
|
||||||
|
engineInternalUrl: cleanString(process.env.NODEDC_ENGINE_INTERNAL_URL, 1000).replace(/\/+$/, ""),
|
||||||
|
engineInternalAccessToken: cleanString(process.env.NODEDC_INTERNAL_ACCESS_TOKEN, 1000),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue