Back to Smithery

Session Configuration

docs-build-session-config.md

latest7.0 KB
Original Source

Overview

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 TypeHow Users Provide Config
Remote (HTTP)Query parameters or HTTP headers
Local (stdio)Command-line arguments

When you define a configuration schema, Smithery automatically:

  • Generates an OAuth UI form for remote servers
  • Passes values to your server in the appropriate format
  • Validates inputs and applies defaults

Configuration schemas are limited to 20 fields and 1KB total size. Keep schemas focused on essential settings.

Defining Your Schema

TypeScript

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.

Config Transport (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 config

Specifies 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 upstream

Specifies 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:

  • Your upstream server expects an Authorization header, but you can’t use authorization as x-from (it’s reserved for Smithery OAuth)
  • You want to rename headers for compatibility with existing APIs
  • You need to map user-friendly parameter names to technical header names

Default: If no x-to is specified, values are forwarded using the same location as x-from.

Example: PostHog API Key

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:

  • Clients connect with header posthog-api-key: sk-xxx
  • Your server receives header Authorization: sk-xxx

Type Support

Only simple types support x-from:

  • string
  • number
  • boolean

Nested objects and arrays are not supported — only flat schemas are allowed.

Reserved Headers

The following headers cannot be used as x-from sources:

  • authorization — Used for Smithery OAuth
  • cookie — Reserved for session management
  • cf-* — Cloudflare infrastructure headers
  • smithery-* — Internal service headers

These restrictions only apply to x-from. You can use any header name (including Authorization) in x-to to forward values to your upstream server.

How Configuration Reaches Your Server

URL

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.

Type Coercion

Since query parameters, headers, and CLI arguments are strings, Smithery automatically coerces values:

Schema TypeCoercion
stringNo coercion
numberNumber(value) — fails if non-numeric
boolean"true" / "1"true, "false" / "0"false

Best Practices

Schema Design

  • Use clear descriptions — These become form labels and help text
  • Set sensible defaults — Minimize required fields
  • Use enums for fixed options — Creates dropdown menus in the UI
  • Keep required fields minimal — Only require what’s essential

Security

  • Use headers for secrets — Configure "x-from": { header: "x-api-key" } for API keys
  • Never log sensitive values — Treat keys and tokens as secrets
  • Validate server-side — Don’t rely solely on client validation

Troubleshooting

Configuration not detected?

  • Export configSchema from the same file as createServer
  • Ensure schema is a valid Zod object

Type errors?

  • Accept { config } in your createServer function
  • Use z.infer<typeof configSchema> for typing

Common Questions

Can 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.

See Also

  • Publish — Publish your MCP on Smithery

Was this page helpful?

YesNo

⌘I