Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ Run `devspace init` to create both files. `devspace config set publicBaseUrl
"server": {
"host": "127.0.0.1",
"port": 7676,
"maxMcpSessions": 256,
// Use the public origin only; do not append /mcp.
"publicBaseUrl": "https://devspace.example.com",
"allowedHosts": [],
Expand Down Expand Up @@ -77,6 +78,11 @@ Omitted sections and keys use the defaults shown above. An empty
`workspaces.allowedRoots` uses the current working directory. Unknown keys are
rejected so spelling mistakes cannot silently alter behavior.

`server.maxMcpSessions` limits how many stateful MCP sessions DevSpace keeps in
memory. When the limit is reached, DevSpace closes the least-recently-used idle
session first. Active sessions are not evicted. If all retained sessions are
active, new initialize requests return `503` until a slot is free.

## Tool modes and UI

`tools.mode` accepts two values:
Expand Down
6 changes: 6 additions & 0 deletions schema/v1/devspace.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@
"minimum": 1,
"maximum": 65535
},
"maxMcpSessions": {
"default": 256,
"type": "integer",
"exclusiveMinimum": 0,
"maximum": 9007199254740991
},
"publicBaseUrl": {
"default": null,
"anyOf": [
Expand Down
1 change: 1 addition & 0 deletions src/config-schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export const DEVSPACE_CONFIG_SCHEMA_URL =
const serverConfigSchema = z.object({
host: z.string().trim().min(1).default("127.0.0.1"),
port: z.number().int().min(1).max(65_535).default(7676),
maxMcpSessions: z.number().int().positive().default(256),
publicBaseUrl: z.string().url().nullable().default(null),
allowedHosts: z.array(z.string().trim().min(1)).default([]),
trustProxy: z.boolean().default(false),
Expand Down
3 changes: 3 additions & 0 deletions src/config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ try {
const defaults = loadConfig(env);
assert.equal(defaults.host, "127.0.0.1");
assert.equal(defaults.port, 7676);
assert.equal(defaults.maxMcpSessions, 256);
assert.equal(defaults.publicBaseUrl, "http://127.0.0.1:7676");
assert.deepEqual(defaults.allowedRoots, [process.cwd()]);
assert.deepEqual(defaults.allowedHosts, ["localhost", "127.0.0.1", "::1"]);
Expand All @@ -38,6 +39,7 @@ try {
server: {
host: "0.0.0.0",
port: 8787,
maxMcpSessions: 32,
publicBaseUrl: "https://devspace.example.com/",
allowedHosts: ["example.internal"],
trustProxy: true,
Expand Down Expand Up @@ -76,6 +78,7 @@ try {
assert.equal(configured.configDir, configDir);
assert.equal(configured.host, "0.0.0.0");
assert.equal(configured.port, 8787);
assert.equal(configured.maxMcpSessions, 32);
assert.equal(configured.publicBaseUrl, "https://devspace.example.com");
assert.deepEqual(configured.allowedRoots, [resolve("~/work".replace("~", process.env.HOME!))]);
assert.deepEqual(configured.allowedHosts, [
Expand Down
3 changes: 3 additions & 0 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export interface ServerConfig {
configDir: string;
host: string;
port: number;
maxMcpSessions: number;
oauth: OAuthConfig;
allowedRoots: string[];
allowedHosts: string[];
Expand All @@ -31,6 +32,7 @@ export interface ServerConfig {
logging: LoggingConfig;
}

/** Load and normalize the persisted DevSpace server configuration. */
export function loadConfig(env: NodeJS.ProcessEnv = process.env): ServerConfig {
const files = loadDevspaceFiles(env);
const stored = files.config;
Expand All @@ -52,6 +54,7 @@ export function loadConfig(env: NodeJS.ProcessEnv = process.env): ServerConfig {
configDir: files.dir,
host,
port,
maxMcpSessions: stored.server.maxMcpSessions,
oauth: {
ownerToken: parseRequiredSecret(
env.DEVSPACE_OAUTH_OWNER_TOKEN ?? files.auth.ownerToken,
Expand Down
Loading
Loading