docs-build-session-config.md
Most MCP servers need user-provided values like API keys, preferences, or settings. How these values reach your server depends on how it’s deployed:
| Server Type | How Users Provide Config |
|---|---|
| Remote (HTTP) | Query parameters or HTTP headers |
| Local (stdio) | Command-line arguments |
When you define a configuration schema, Smithery automatically:
Configuration schemas are limited to 20 fields and 1KB total size. Keep schemas focused on essential settings.
JSON Schema
Export a configSchema using Zod to declare what configuration your server accepts:
// src/index.ts
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod/v4";
import type { ServerContext } from "@smithery/sdk";
export const configSchema = z.object({
apiKey: z.string()
.meta({ "x-from": { header: "x-api-key" } })
.describe("Your API key"),
model: z.string().default("gpt-4").describe("Model to use"),
temperature: z.number().min(0).max(1).default(0.7).describe("Temperature"),
});
export default function createServer({
config,
}: ServerContext<z.infer<typeof configSchema>>) {
const server = new McpServer({
name: "My Server",
version: "1.0.0",
});
// Access user-provided values
console.log(`API Key: ${config.apiKey}`);
console.log(`Model: ${config.model}`);
return server.server;
}
Smithery extracts this schema automatically — no additional configuration needed.
For URL-published servers deployed via CLI, use JSON Schema with the x-from extension:
{
"type": "object",
"properties": {
"apiKey": {
"type": "string",
"title": "API Key",
"x-from": { "header": "x-api-key" }
},
"model": {
"type": "string",
"title": "Model",
"default": "gpt-4"
}
},
"required": ["apiKey"]
}
See Publish via CLI for how to deploy with a config schema.
x-from and x-to)The x-from and x-to extensions control how config values flow through the gateway:
x-from — Where Smithery reads configSpecifies where Smithery looks for the value when a user connects:
z.string().meta({
"x-from": { header: "x-api-key" } // Read from header
})
z.string().meta({
"x-from": { query: "model" } // Read from query param
})
Default: If no x-from is specified, defaults to { query: "<propertyName>" }.
x-to — Where Smithery sends config to upstreamSpecifies how Smithery forwards the value to your upstream server. Use this when your server expects a different header name than what clients provide:
z.string().meta({
"x-from": { header: "api-key" }, // Client sends: api-key header
"x-to": { header: "Authorization" } // Upstream receives: Authorization header
})
This is useful when:
Authorization header, but you can’t use authorization as x-from (it’s reserved for Smithery OAuth)Default: If no x-to is specified, values are forwarded using the same location as x-from.
export const configSchema = z.object({
posthogApiKey: z.string()
.meta({
"x-from": { header: "posthog-api-key" }, // Client provides this header
"x-to": { header: "Authorization" } // PostHog expects Authorization
})
.describe("Your PostHog API key"),
});
With this config:
posthog-api-key: sk-xxxAuthorization: sk-xxxOnly simple types support x-from:
stringnumberbooleanNested objects and arrays are not supported — only flat schemas are allowed.
The following headers cannot be used as x-from sources:
authorization — Used for Smithery OAuthcookie — Reserved for session managementcf-* — Cloudflare infrastructure headerssmithery-* — Internal service headersThese restrictions only apply to x-from. You can use any header name (including Authorization) in x-to to forward values to your upstream server.
Local
For URL-published servers, Smithery Gateway passes through all query parameters and headers to your upstream server.
GET /mcp?apiKey=sk-xxx&model=gpt-4
x-api-key: sk-xxx
Your server receives headers and query params directly — Smithery proxies them as-is.
For local servers, Smithery translates the configuration schema into command-line arguments:
my-server --api-key=sk-xxx --model=gpt-4 --temperature=0.7
The schema field names are converted to kebab-case flags automatically. Your createServer function receives the parsed config object.
Since query parameters, headers, and CLI arguments are strings, Smithery automatically coerces values:
| Schema Type | Coercion |
|---|---|
string | No coercion |
number | Number(value) — fails if non-numeric |
boolean | "true" / "1" → true, "false" / "0" → false |
Schema Design
Security
"x-from": { header: "x-api-key" } for API keysConfiguration not detected?
configSchema from the same file as createServerType errors?
{ config } in your createServer functionz.infer<typeof configSchema> for typingCan users change configuration mid-session?
No — configuration is bound at connection time. A new connection is needed for different settings.
Can all fields be optional?
Yes — use .optional() or provide .default() values.
Where can I see a server's configuration?
View the API tab on any server’s page on Smithery.
Was this page helpful?
YesNo
⌘I