thedotmack/claude-mem · error · ServerClientError
transport
transport
Error message
${toolName} requires CLAUDE_MEM_RUNTIME=server. Current runtime is "worker"; use the existing search/timeline/get_observations tools for worker-mode memory access. What it means
Thrown by requireServerForObservationTool() when selectRuntime() returns a runtime other than 'server' (i.e. the install is in 'worker' runtime). The observation_* server-backed tools (observation_add, observation_record_event, observation_search, observation_context, observation_generation_status) only exist on the server /v1 surface, so they refuse to run against the worker. The error tells the caller which worker-mode equivalents to use instead.
Source
Thrown at src/servers/mcp-server.ts:206
text: `Tool error: ${error instanceof Error ? error.message : String(error)}`,
}],
isError: true as const,
};
}
function formatJsonResult(payload: unknown): { content: Array<{ type: 'text'; text: string }> } {
return {
content: [{
type: 'text' as const,
text: JSON.stringify(payload, null, 2),
}],
};
}
function requireServerForObservationTool(toolName: string): ServerAvailable {
const resolution = resolveServerToolContext();
if (!resolution) {
throw new ServerClientError(
'transport',
`${toolName} requires CLAUDE_MEM_RUNTIME=server. Current runtime is "worker"; use the existing search/timeline/get_observations tools for worker-mode memory access.`,
);
}
if (!resolution.available) {
throw new ServerClientError('missing_api_key', `${toolName}: ${resolution.reason}`);
}
return resolution;
}
function wrapHandler<Args>(
toolName: string,
execute: (args: Args) => Promise<{ content: Array<{ type: 'text'; text: string }> }>,
): (args: Args) => Promise<{ content: Array<{ type: 'text'; text: string }>; isError?: boolean }> {
return async (args: Args) => {
try {
return await execute(args);
} catch (error) {View on GitHub (pinned to d768ba3643)
Solutions
- Set the runtime to server: put CLAUDE_MEM_RUNTIME=server in your settings/env, then restart the MCP server (runtime is re-resolved per call, so no rebuild needed).
- If you cannot run the server runtime, stop calling the observation_* tools and use the worker-mode equivalents the message names: search, timeline, get_observations.
- Verify the switch took effect by checking selectRuntime()'s return or the debug log line from resolveServerToolContext().
Example fix
// before
// settings: { "runtime": "worker" }
// → observation_add throws 'requires CLAUDE_MEM_RUNTIME=server'
// after
// settings.json
{ "runtime": "server", "serverBaseUrl": "https://...", "apiKey": "cmem_..." }
// or env
export CLAUDE_MEM_RUNTIME=server Defensive patterns
Strategy: validation
Validate before calling
// Resolve runtime before calling observation_* tools.
import { selectRuntime } from '<runtime-module>';
if (selectRuntime() !== 'server') {
// do not call observation_*; use search/timeline/get_observations instead
} Type guard
function isServerRuntime(): boolean {
// mirrors resolveServerToolContext()'s null branch
try { return selectRuntime() === 'server'; } catch { return false; }
} Try / catch
try {
await tools.observation_add({ content });
} catch (e) {
if (e instanceof ServerClientError && e.kind === 'transport' && /requires CLAUDE_MEM_RUNTIME=server/.test(e.message)) {
// wrong runtime — fall back to worker-mode tools
await tools.search({ query: content });
} else throw e;
} Prevention
- Only advertise observation_* tools when selectRuntime() === 'server' (filter the tools list by runtime).
- Document in each tool description that it is server-only so LLM clients avoid calling it in worker mode.
- Re-resolve runtime per call (already cheap) so flipping CLAUDE_MEM_RUNTIME takes effect without restart.
When it happens
Trigger: Calling any observation_* tool while CLAUDE_MEM_RUNTIME=worker (or unset and resolving to worker). selectRuntime() returns 'worker', resolveServerToolContext() returns null, and the guard throws a ServerClientError of kind 'transport'.
Common situations: User upgraded to a version that introduced server-mode tools but never switched CLAUDE_MEM_RUNTIME to 'server' in settings/env; an MCP client auto-discovers advertised tools and calls one in a worker-only install; settings file has a typo in the runtime value so it falls back to worker.
Related errors
- missing_api_key
- `server ${commandLabel}` is a server runtime command, but CL
- Cannot bootstrap server API key: CLAUDE_MEM_SERVER_DATABASE_
- Found mcpServers/claude-mem markers but could not locate a r
- SSE stream response has no body
AI-assisted analysis of thedotmack/claude-mem@d768ba3643 (2026-08-12).
Data as JSON: /api/errors/68c7930e49b855fb.
Report an issue: GitHub.