Skip to content

Commit

Permalink
Revert changes to server/src/index.ts
Browse files Browse the repository at this point in the history
  • Loading branch information
nbarraud committed Mar 4, 2025
1 parent 32c1206 commit e68c24a
Showing 1 changed file with 16 additions and 138 deletions.
154 changes: 16 additions & 138 deletions server/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,158 +1,36 @@
#!/usr/bin/env node

import cors from "cors";
import { parseArgs } from "node:util";
import { parse as shellParseArgs } from "shell-quote";

import {
SSEClientTransport,
SseError,
} from "@modelcontextprotocol/sdk/client/sse.js";
import {
getDefaultEnvironment,
StdioClientTransport,
getDefaultEnvironment,
} from "@modelcontextprotocol/sdk/client/stdio.js";
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
import cors from "cors";
import express from "express";
import fs from "node:fs";
import path from "node:path";
import { parseArgs } from "node:util";
import { parse as shellParseArgs } from "shell-quote";
import { findActualExecutable } from "spawn-rx";
import { z } from "zod";
import mcpProxy from "./mcpProxy.js";

const SSE_HEADERS_PASSTHROUGH = ["authorization"];

// Schema definitions for configuration validation
const EnvVarsSchema = z.record(z.string());

const ServerConfigSchema = z.object({
command: z.string(),
args: z.array(z.string()).optional(),
env: EnvVarsSchema.optional(),
});

const ConfigFileSchema = z.object({
mcpServers: z.record(ServerConfigSchema),
});

// Default environment with any MCP_ENV_VARS merged in
const defaultEnvironment = {
...getDefaultEnvironment(),
...(process.env.MCP_ENV_VARS ? JSON.parse(process.env.MCP_ENV_VARS) : {}),
};

/**
* Resolves the command, arguments, and environment variables from various sources
* @returns Object with resolved command, arguments, and environment variables
*/
function resolveConfiguration() {
// Parse command line arguments
const { values, positionals } = parseArgs({
args: process.argv.slice(2),

options: {
env: { type: "string", default: "" },
args: { type: "string", default: "" },
config: { type: "string", default: "" },
server: { type: "string", default: "" },
},

allowPositionals: true,
});

// Default result with empty values
let result = {
command: "",
args: "",
env: {} as Record<string, string>,
};

// Try to load config file if specified
if (values.config) {
// If config file is specified, server name is required
if (!values.server) {
console.error(
"Error: --server parameter is required when using a config file",
);
process.exit(1);
}

try {
const configPath = path.isAbsolute(values.config)
? values.config
: path.resolve(process.cwd(), values.config);

if (!fs.existsSync(configPath)) {
console.error(`Error: Config file not found: ${configPath}`);
process.exit(1);
}

const configContent = fs.readFileSync(configPath, "utf8");
const parsedConfig = JSON.parse(configContent);
const validatedConfig = ConfigFileSchema.parse(parsedConfig);
const servers = validatedConfig.mcpServers;

// Check if specified server exists
if (!servers[values.server]) {
console.error(
`Error: Server '${values.server}' not found in config file. Available servers: ${Object.keys(servers).join(", ")}`,
);
process.exit(1);
}

// Use the specified server configuration
const serverConfig = servers[values.server];
console.log(
`Using server configuration '${values.server}' from ${values.config}`,
);

return {
command: serverConfig.command,
args: serverConfig.args ? serverConfig.args.join(" ") : "",
env: serverConfig.env || {},
};
} catch (err) {
if (err instanceof z.ZodError) {
const formattedErrors = err.errors
.map((e) => `Field '${e.path.join(".")}': ${e.message}`)
.join("\n");

console.error(`Error: Invalid config file format:\n${formattedErrors}`);
} else if (err instanceof SyntaxError) {
console.error(`Error: Invalid JSON in config file: ${err.message}`);
} else {
console.error(
`Error: Processing config file: ${err instanceof Error ? err.message : String(err)}`,
);
}

process.exit(1);
}
}

// Fall back to CLI arguments if no config file
if (positionals.length > 0) {
result.command = positionals[0];
result.args = positionals.length > 1 ? positionals.slice(1).join(" ") : "";
} else {
result.command = values.env;
result.args = values.args;
}

return result;
}

// Resolve the configuration
const {
command: defaultCommand,
args: defaultArgs,
env: configEnv,
} = resolveConfiguration();

// Merge environment variables
const mergedDefaultEnvironment = {
...defaultEnvironment,
...configEnv,
};
const { values } = parseArgs({
args: process.argv.slice(2),
options: {
env: { type: "string", default: "" },
args: { type: "string", default: "" },
},
});

const app = express();
app.use(cors());
Expand All @@ -169,7 +47,7 @@ const createTransport = async (req: express.Request) => {
const command = query.command as string;
const origArgs = shellParseArgs(query.args as string) as string[];
const queryEnv = query.env ? JSON.parse(query.env as string) : {};
const env = { ...process.env, ...mergedDefaultEnvironment, ...queryEnv };
const env = { ...process.env, ...defaultEnvironment, ...queryEnv };

const { cmd, args } = findActualExecutable(command, origArgs);

Expand Down Expand Up @@ -292,9 +170,9 @@ app.post("/message", async (req, res) => {
app.get("/config", (req, res) => {
try {
res.json({
defaultEnvironment: mergedDefaultEnvironment,
defaultCommand,
defaultArgs,
defaultEnvironment,
defaultCommand: values.env,
defaultArgs: values.args,
});
} catch (error) {
console.error("Error in /config route:", error);
Expand Down

0 comments on commit e68c24a

Please sign in to comment.