Añadido el modo producción / test
This commit is contained in:
@@ -2,17 +2,16 @@
|
||||
* Acai Code MCP Server - Stdio Entry Point
|
||||
*
|
||||
* Used when Claude Code launches the MCP server directly via .mcp.json.
|
||||
* Reads credentials from .acai file on each tool call (auto-refresh on token renewal).
|
||||
* Reads credentials from the local Python server on each tool call.
|
||||
*/
|
||||
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
||||
import { createMcpServer } from "./server.js";
|
||||
import { registerPrompts } from "./prompts/index.js";
|
||||
import { registerTools } from "./tools/index.js";
|
||||
import { registerResources } from "./resources/index.js";
|
||||
import { sessionCredentials } from "./auth/credentials.js";
|
||||
import { fetchProjectInfo } from "./auth/localClient.js";
|
||||
|
||||
// Create server instance
|
||||
const server = createMcpServer();
|
||||
@@ -20,75 +19,71 @@ registerPrompts(server);
|
||||
registerTools(server);
|
||||
registerResources(server);
|
||||
|
||||
// Static env vars (web_url and website don't change, token does)
|
||||
const projectDir = process.env.ACAI_PROJECT_DIR || "";
|
||||
const acaiFilePath = projectDir ? path.join(projectDir, ".acai") : "";
|
||||
|
||||
// Read .acai once at startup for URL fallbacks
|
||||
let acaiFileData = {};
|
||||
if (acaiFilePath) {
|
||||
try {
|
||||
acaiFileData = JSON.parse(fs.readFileSync(acaiFilePath, "utf-8"));
|
||||
} catch { /* ignore - fall back to env vars */ }
|
||||
// Aplica vars de override de entorno (usado por cronjobs para forzar el
|
||||
// entorno objetivo sin tocar el .acai del proyecto). Modifica creds in-place.
|
||||
function applyEnvironmentOverride(creds) {
|
||||
const modeOverride = process.env.ACAI_MODE_OVERRIDE;
|
||||
if (!modeOverride) return creds;
|
||||
creds.mode = modeOverride;
|
||||
if (process.env.ACAI_WEB_URL_OVERRIDE) creds.web_url = process.env.ACAI_WEB_URL_OVERRIDE;
|
||||
if (process.env.ACAI_API_WEB_URL_OVERRIDE) creds.api_web_url = process.env.ACAI_API_WEB_URL_OVERRIDE;
|
||||
if (process.env.ACAI_FORGE_HOST_OVERRIDE !== undefined) {
|
||||
creds.forge_host = process.env.ACAI_FORGE_HOST_OVERRIDE;
|
||||
}
|
||||
return creds;
|
||||
}
|
||||
|
||||
const website = process.env.ACAI_WEBSITE || acaiFileData.domain || "";
|
||||
const webUrl = process.env.ACAI_WEB_URL || acaiFileData.local_web_url || "";
|
||||
const derivedForgeHost = (() => {
|
||||
// First check .acai for explicit forge host
|
||||
if (acaiFileData.local_forge_host) return acaiFileData.local_forge_host;
|
||||
if (!webUrl) return "";
|
||||
try {
|
||||
const parsed = new URL(webUrl);
|
||||
return parsed.hostname.includes("forge.acaisuite.com") ? parsed.host : "";
|
||||
} catch {
|
||||
return "";
|
||||
}
|
||||
})();
|
||||
const apiWebUrl = process.env.ACAI_API_WEB_URL || (derivedForgeHost ? "http://web:80/" : webUrl);
|
||||
const forgeHost = process.env.ACAI_FORGE_HOST || derivedForgeHost;
|
||||
|
||||
// Read fresh credentials from .acai file
|
||||
function readFreshCredentials() {
|
||||
let token = process.env.ACAI_TOKEN || "";
|
||||
let tokenHash = process.env.ACAI_TOKEN_HASH || "";
|
||||
|
||||
// If .acai file exists, read fresh token from disk (renewed by Python server)
|
||||
if (acaiFilePath) {
|
||||
async function readFreshCredentials() {
|
||||
if (projectDir) {
|
||||
try {
|
||||
const data = JSON.parse(fs.readFileSync(acaiFilePath, "utf-8"));
|
||||
if (data.token) token = data.token;
|
||||
if (data.tokenHash) tokenHash = data.tokenHash;
|
||||
} catch {
|
||||
// Fall back to env vars if .acai can't be read
|
||||
const data = await fetchProjectInfo({ project_dir: projectDir });
|
||||
if (data?.success) {
|
||||
return applyEnvironmentOverride({
|
||||
token: data.token || "",
|
||||
tokenHash: data.tokenHash || "",
|
||||
website: data.domain || "",
|
||||
web_url: data.web_url || "",
|
||||
api_web_url: data.api_web_url || data.web_url || "",
|
||||
forge_host: data.forge_host || "",
|
||||
mode: data.mode || "local",
|
||||
profileName: "stdio",
|
||||
role: "developer",
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`[MCP stdio] Failed to resolve project-info: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
token,
|
||||
tokenHash,
|
||||
website,
|
||||
web_url: webUrl,
|
||||
api_web_url: apiWebUrl,
|
||||
forge_host: forgeHost,
|
||||
profileName: "stdio",
|
||||
return applyEnvironmentOverride({
|
||||
token: process.env.ACAI_TOKEN || "",
|
||||
tokenHash: process.env.ACAI_TOKEN_HASH || "",
|
||||
website: process.env.ACAI_WEBSITE || "",
|
||||
web_url: process.env.ACAI_WEB_URL || "",
|
||||
api_web_url: process.env.ACAI_API_WEB_URL || "",
|
||||
forge_host: process.env.ACAI_FORGE_HOST || "",
|
||||
mode: process.env.ACAI_MODE || "local",
|
||||
profileName: "stdio-fallback",
|
||||
role: "developer",
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
if (!webUrl) {
|
||||
const initialCreds = await readFreshCredentials();
|
||||
|
||||
if (!initialCreds.web_url) {
|
||||
console.error("[MCP stdio] WARNING: No ACAI_WEB_URL in environment. Tools will fail.");
|
||||
}
|
||||
|
||||
// Set initial credentials
|
||||
sessionCredentials.set("_default", readFreshCredentials());
|
||||
sessionCredentials.set("_default", initialCreds);
|
||||
|
||||
// Intercept tool calls to refresh credentials from .acai before each call
|
||||
// Intercept tool calls to refresh credentials from the Python server before each call
|
||||
const _origSetHandler = server.server.setRequestHandler;
|
||||
server.server.setRequestHandler = (schema, handler) => {
|
||||
return _origSetHandler.call(server.server, schema, async (request, extra) => {
|
||||
// Re-read .acai on every tool call to pick up renewed tokens
|
||||
const freshCreds = readFreshCredentials();
|
||||
const freshCreds = await readFreshCredentials();
|
||||
sessionCredentials.set("_default", freshCreds);
|
||||
if (extra?.sessionId) {
|
||||
sessionCredentials.set(extra.sessionId, freshCreds);
|
||||
@@ -100,4 +95,4 @@ server.server.setRequestHandler = (schema, handler) => {
|
||||
// Connect via stdio transport
|
||||
const transport = new StdioServerTransport();
|
||||
await server.connect(transport);
|
||||
console.error(`[MCP stdio] Connected — ${website} → ${webUrl} (project: ${projectDir})`);
|
||||
console.error(`[MCP stdio] Connected — ${initialCreds.website} → ${initialCreds.web_url} (project: ${projectDir})`);
|
||||
|
||||
Reference in New Issue
Block a user