How to Create Custom LLM API Configurations in Chat MCP: A Complete Guide

To create custom LLM API configurations in Chat MCP, add an env object containing your API key and URL to the server entry in src/main/config.json, which the Electron main process injects into the MCP server's environment variables at runtime.

The ai-ql/chat-mcp repository provides an Electron-based frontend for Model Context Protocol (MCP) servers. Because the application delegates LLM interactions to external MCP servers rather than implementing them directly, you configure custom API endpoints and authentication keys via environment variables defined in the server's JSON configuration.

Understanding the Configuration Architecture

The configuration flow follows a strict pipeline from JSON definition to process execution. When the Electron application starts, src/main/main.ts reads src/main/config.json and constructs ServerConfig objects for each entry. These configurations pass to src/main/client.ts, where initializeClient creates a StdioClientTransport instance that spawns the MCP server as a child process. The transport merges the env object from your configuration into the child process environment, making variables like LLM_API_URL and LLM_API_KEY available to the server implementation.

Step-by-Step Configuration Guide

Step 1: Define Environment Variables in config.json

Locate src/main/config.json and add an env object under your target server entry. This object must contain the URL and API key variables expected by your specific MCP server implementation.

{
  "mcpServers": {
    "custom-llm": {
      "command": "npx",
      "args": [
        "-y",
        "@modelcontextprotocol/server-everything"
      ],
      "env": {
        "LLM_API_URL": "https://api.custom-model.com/v1",
        "LLM_API_KEY": "sk-your-secret-key-here"
      }
    }
  }
}

The Electron main process passes these values to child_process.spawn via the StdioClientTransport constructor, ensuring the variables exist in the server's process environment before it initializes.

Step 2: Match Variable Names to Server Requirements

Different MCP server implementations expect different environment variable names. If your server requires CUSTOM_ENDPOINT instead of LLM_API_URL, adjust the env keys accordingly:

{
  "mcpServers": {
    "myModel": {
      "command": "npx",
      "args": ["-y", "@myorg/custom-mcp-server"],
      "env": {
        "CUSTOM_ENDPOINT": "https://my-custom-model.com/v1",
        "CUSTOM_TOKEN": "sk-your-token-here"
      }
    }
  }
}

Step 3: (Optional) Expose Configuration to the UI

If you want the renderer process to dynamically specify model parameters, modify the request handler in src/main/client.ts. The setRequestHandler method for CreateMessageRequestSchema can read environment variables or request parameters to determine which endpoint to target:

// src/main/client.ts
client.setRequestHandler(CreateMessageRequestSchema, async (request) => {
  // Use model from request or fall back to environment variable
  const model = request?.model ?? process.env.LLM_API_URL;
  
  return {
    model,
    stopReason: "endTurn",
    role: "assistant",
    content: {
      type: "text",
      text: "Custom LLM response placeholder"
    }
  };
});

Accessing Custom LLMs from the Renderer

Once configured, the renderer process accesses the custom LLM through the preload bridge defined in src/preload/preload.ts. The window.mcpServers object exposes methods to call tools, prompts, and resources from the configured server:

// Renderer process (e.g., React component or vanilla JS)
window.mcpServers['custom-llm'].tools.call('myTool', { query: "Hello" })
  .then(result => console.log('Response:', result))
  .catch(err => console.error('Error:', err));

Key Implementation Files

Understanding these source files helps troubleshoot configuration issues:

  • src/main/config.json: Defines MCP server commands, arguments, and environment variables. This is the only file you must edit to configure a custom API endpoint.
  • src/main/main.ts: Reads the configuration and initializes the Electron window. Calls readConfig to parse the JSON into ServerConfig objects.
  • src/main/client.ts: Creates StdioClientTransport instances and manages the Client lifecycle. Contains initializeClient where you can modify request handlers.
  • src/preload/preload.ts: Exposes the MCP API to the renderer via contextBridge, creating the window.mcpServers interface.

Summary

  • Chat MCP configures custom LLM endpoints via environment variables in src/main/config.json, not hardcoded frontend values.
  • Add an env object to your server configuration containing LLM_API_URL and LLM_API_KEY (or server-specific equivalents).
  • The Electron main process injects these variables when spawning the MCP server through StdioClientTransport.
  • For dynamic model selection, extend the CreateMessageRequestSchema handler in src/main/client.ts.
  • Access configured servers from the renderer using window.mcpServers.<name>.tools.call().

Frequently Asked Questions

Where do I store the API key securely?

Store the API key in the env object within src/main/config.json. Because this file resides in the main process and is read at runtime, the key never ships in the renderer bundle. For production, consider loading sensitive values from the host environment or a secrets manager rather than committing them to version control.

Can I use multiple custom LLM providers simultaneously?

Yes. Define multiple entries in the mcpServers object, each with distinct env configurations. For example, configure one server with OpenAI credentials and another with Azure OpenAI credentials. Each runs as a separate process with isolated environment variables.

Why does my server not recognize the environment variables?

Verify that your MCP server implementation actually reads the variable names you configured. The Chat MCP repository passes variables exactly as defined in the JSON env object, but the server code must explicitly access them via process.env.LLM_API_URL (Node.js) or equivalent. Check your server's documentation for the expected variable names.

Do I need to rebuild the Electron app after changing config.json?

No. Because src/main/config.json is read at runtime by src/main/main.ts, you only need to restart the Electron application. Changes take effect immediately on the next launch without recompiling the TypeScript or rebuilding the bundle.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →