Host Configuration
By the Syncfusion DevTutorials team · Last updated
Connecting MCP servers to hosts: stdio and HTTP entries, VS Code mcp.json with inputs and dev mode, Visual Studio config locations, servers vs mcpServers, keeping secrets out, and start-up checks.
When you set up a new printer, you tell your computer how to find it: what it is called, how it connects, and whether it needs a password. Once that is configured, your apps can use it without redoing the setup every time.
The same pattern applies to MCP servers. A host needs a small entry for each server: its name, how to reach it, and any needed settings or keys. Once the host has that information, it can start the server, connect to it, discover its tools, and let the model use them.
The main idea: host config is just the setup layer for MCP. A stdio server entry tells the host what command to run. An HTTP server entry tells it which URL to call. Secrets should come from prompts or environment variables, not from the config file itself. After that, the host must verify that the server starts and lists its tools correctly.
A Real-World Example
Ravi wants the Brightgrid returns server inside VS Code so he can try it with the editor's AI chat.
- He adds
.vscode/mcp.jsonto the project with two entries: a local build over stdio and the company cloud server over HTTP. - The API key is not stored in the file. VS Code asks for it once and stores it safely.
- He runs MCP: List Servers, starts the local server, and checks the output log to confirm it launched and listed its tools.
- He commits the config file so teammates get the same setup, while each person supplies their own key.
In simple words: describe each server once, keep secrets out of the file, and prove the server starts before depending on it.
What You Will Learn
In this lesson, you will learn:
- What a host config contains for stdio and HTTP servers.
- How to configure VS Code.
- How to configure Visual Studio.
- How to keep secrets out of config files.
- How to check that a server starts, connects, and lists its tools.
The MCP Lab is also a kind of host, but it is set up in code to talk to a specific in-browser server. This lesson is about real hosts running on your machine, where the file-based config matters.
A host reads its config, starts stdio servers or calls HTTP servers, resolves secret values, then discovers each server and reads its tool list.
What a Config Contains
The host needs enough information to either start a local process or contact a remote server. The exact fields depend on which type of server you are configuring.
stdio Entries
For a local server, the host starts a program. A stdio entry usually includes:
type:"stdio"command: the executable to run, such asnode,python, ornpxargs: the arguments passed to that command, such as["build/index.js"]env: any environment variables the server needs- sometimes
cwdorenvFilefor more control over the startup environment
HTTP Entries
For a remote server, the host calls a URL instead of running a local process. The entry usually includes:
type:"http"url: the server endpoint, such ashttps://mcp.brightgrid.example/mcpheaders: extra HTTP headers, such as anAuthorizationheader with a token
VS Code
The File
VS Code reads MCP servers from a few places:
.vscode/mcp.jsonin a workspace, with the top-level keyservers. Commit this file when you want the team to share the same server setup.- Your user-level configuration, opened with MCP: Open User Configuration, for servers you want in every project.
- A portable
.mcp.jsonat the project root, which uses the keymcpServers. Many other hosts use the same shape.
A .vscode/mcp.json file
const config = {
inputs: [
{
type: "promptString",
id: "brightgrid-key",
description: "Brightgrid API key",
password: true,
},
],
servers: {
"brightgrid-local": {
type: "stdio",
command: "node",
args: ["build/index.js"],
env: { BRIGHTGRID_API_KEY: "${input:brightgrid-key}" },
dev: { watch: "build/**/*.js" },
},
"brightgrid-cloud": {
type: "http",
url: "https://mcp.brightgrid.example/mcp",
headers: { Authorization: "Bearer ${input:brightgrid-key}" },
},
},
};
console.log(JSON.stringify(config, null, 2));
Expected output:
{
"inputs": [
{
"type": "promptString",
"id": "brightgrid-key",
"description": "Brightgrid API key",
"password": true
}
],
"servers": {
"brightgrid-local": {
"type": "stdio",
"command": "node",
"args": [
"build/index.js"
],
"env": {
"BRIGHTGRID_API_KEY": "${input:brightgrid-key}"
},
"dev": {
"watch": "build/**/*.js"
}
},
"brightgrid-cloud": {
"type": "http",
"url": "https://mcp.brightgrid.example/mcp",
"headers": {
"Authorization": "Bearer ${input:brightgrid-key}"
}
}
}
}
Inputs for Secrets
The inputs list tells the host which values to ask for. "type": "promptString" shows a prompt box, and "password": true hides what the user types. A reference like ${input:brightgrid-key} then gets replaced at runtime. VS Code asks the first time the server starts and stores the answer for later use.
How input placeholders are filled
const answers = { "brightgrid-key": "sk-live-9f2c" };
function resolve(value) {
return value.replace(
/\$\{input:([\w-]+)\}/g,
(_, id) => answers[id] ?? `<ask user for ${id}>`,
);
}
const env = { BRIGHTGRID_API_KEY: "${input:brightgrid-key}", REGION: "eu" };
const resolved = Object.fromEntries(Object.entries(env).map(([k, v]) => [k, resolve(v)]));
console.log("in the file: ", JSON.stringify(env));
console.log(
"at start-up: BRIGHTGRID_API_KEY is",
resolved.BRIGHTGRID_API_KEY ? "set" : "missing",
"| REGION =",
resolved.REGION,
);
console.log("unknown input:", resolve("${input:other-key}"));
Expected output:
in the file: {"BRIGHTGRID_API_KEY":"${input:brightgrid-key}","REGION":"eu"}
at start-up: BRIGHTGRID_API_KEY is set | REGION = eu
unknown input: <ask user for other-key>
This is a common pattern because it keeps secrets out of source control while still making the value available to the server at runtime.
Running and Debugging
- MCP: List Servers in the Command Palette lists configured servers and lets you start, stop, or restart them.
- The output log is the first place to check when a server fails to start.
- A
devsection can enable watch mode;dev.watchcan restart the server when matching files change, and VS Code can attach a debugger for Node.js or Python stdio servers.
Visual Studio
Like VS Code, Visual Studio acts as the MCP host. The main difference is where each host stores its configuration files.
Versions and Files
Visual Studio 2022 version 17.14 and Visual Studio 2026 support MCP servers for GitHub Copilot. Visual Studio looks for config files in several places, including:
%USERPROFILE%\.mcp.json: personal config for all repositories<solution>\.mcp.json: repository-shared config<solution>\.vs\mcp.json: solution-local config for the current user.vscode\mcp.jsonunder the solution folder
The file uses a top-level servers object, just like VS Code's. Editing it inside Visual Studio gives you validation and auto-completion, and saving the file reloads the server list.
Formats Across Hosts
servers vs mcpServers
Most hosts agree on the entries, but they do not always agree on the top-level key. VS Code and Visual Studio use servers, while the portable .mcp.json format uses mcpServers. Moving between them is usually just a matter of renaming the key.
Convert between the two shapes
const vscode = {
servers: {
brightgrid: { type: "stdio", command: "node", args: ["build/index.js"] },
docs: { type: "http", url: "https://mcp.brightgrid.example/mcp" },
},
};
function toPortable(cfg) {
return { mcpServers: cfg.servers };
}
const portable = toPortable(vscode);
console.log("VS Code (.vscode/mcp.json): top key =", Object.keys(vscode)[0]);
console.log("Portable (.mcp.json): top key =", Object.keys(portable)[0]);
console.log("servers:", Object.keys(portable.mcpServers).join(", "));
Expected output:
VS Code (.vscode/mcp.json): top key = servers
Portable (.mcp.json): top key = mcpServers
servers: brightgrid, docs
Check each host's documentation for the exact file name, location, and fields. Those details change faster than the protocol itself, and small differences, like .mcp.json versus mcp.json, matter.
Keeping Secrets Out
Rules
- Never write a key or token directly in a config file, especially if that file is committed to git.
- Use
${input:...}prompts, environment variables, or anenvFilethat is not committed. - Use
https://for remote servers. Plainhttp://is fine only for local, trusted servers such ashttp://127.0.0.1:3001/mcp.
Lint a config
function lint(name, s) {
const issues = [];
if (s.type === "stdio" && !s.command) {
issues.push("stdio needs a command");
}
if (s.type === "http") {
if (!s.url) {
issues.push("http needs a url");
} else if (
s.url.startsWith("http://") &&
!/^http:\/\/(127\.0\.0\.1|localhost)/.test(s.url)
) {
issues.push("use https for remote servers");
}
}
const values = JSON.stringify({ env: s.env, headers: s.headers });
if (/sk-[a-z]+-\w+|Bearer [A-Za-z0-9]{8,}/.test(values)) {
issues.push("secret written in the file: use ${input:...}");
}
return `${name}: ${issues.length ? issues.join("; ") : "ok"}`;
}
console.log(lint("local", { type: "stdio", command: "node", args: ["build/index.js"] }));
console.log(lint("cloud", { type: "http", url: "http://mcp.brightgrid.example/mcp" }));
console.log(
lint("leaky", { type: "stdio", command: "node", env: { KEY: "sk-live-9f2c" } }),
);
console.log(lint("dev", { type: "http", url: "http://127.0.0.1:3001/mcp" }));
Expected output:
local: ok
cloud: use https for remote servers
leaky: secret written in the file: use ${input:...}
dev: ok
A config entry can start a command with your privileges. Only add servers from sources you trust, and read the command before starting it. A shared repository can add a server you never meant to run, so changes to an MCP config deserve the same review as code changes.
Start-Up Checks
Spawn, Connect, Discover
When a server is enabled, the host does a few basic checks in order:
- Start it if it is a stdio server, or prepare the URL if it is an HTTP server.
- Connect by sending a discovery request such as
server/discoveror, for older servers,initialize. - Check the versions and capabilities reported by the server.
- List tools, resources, and prompts.
If a server fails at any step, the output log usually tells you why. For stdio servers, common problems are a wrong command, a missing environment variable, or a server that writes logs to stdout instead of stderr.
A start-up checklist
const steps = [
["start", "stdio: run the command | http: nothing to start", true],
["connect", "first request: server/discover (or initialize for older servers)", true],
["versions", "server supports 2026-07-28?", true],
["capabilities", "tools present?", true],
["tools/list", "expected tools: lookup_order, book_return", false],
];
for (const [step, check, ok] of steps) {
console.log(`${ok ? "ok " : "FAIL"} ${step.padEnd(13)} ${check}`);
if (!ok) {
console.log(
" -> open the server's output log; for stdio, read what it wrote to stderr",
);
break;
}
}
Expected output:
ok start stdio: run the command | http: nothing to start
ok connect first request: server/discover (or initialize for older servers)
ok versions server supports 2026-07-28?
ok capabilities tools present?
FAIL tools/list expected tools: lookup_order, book_return
-> open the server's output log; for stdio, read what it wrote to stderr
The pattern is the same everywhere: if the server does not show tools, the first place to look is the startup log.
Common mistakes
- Wrong top-level key. Some hosts use
servers, others usemcpServers. A wrong key means the host never sees the list. - Relative paths from the wrong folder. Set
cwdor use paths relative to the workspace. - Missing environment variables. The server stops during startup. Read the log.
- Using
http://for a remote server. Tokens go over the network in plain text. Usehttpsinstead. - Enabling too many servers at once. Each server adds tools to the host's tool list. Only enable what the task needs.
Exercises
Each exercise ends with a value on the last line. Press Check to compare it with the expected answer.
What to Remember
- A host config lists servers. stdio entries use a command and usually arguments; HTTP entries use a URL and optional headers.
- VS Code uses
.vscode/mcp.jsonwith a top-levelserverskey, while the portable format usesmcpServers. - Secrets should come from
${input:...}prompts or environment variables, not from committed config files. - Start-up checks are simple: start or connect, verify discovery, ensure the server advertises its capabilities, and inspect the output log when it fails.
- Review config changes as you would review code changes, because they can start commands with real privileges.
The pattern is simple: configure once, keep secrets safe, verify startup, then let the model use the tools.
Next: Building Servers with SDKs, where you learn how to write and test a complete MCP server from scratch.