multica-ai/multica · error

remote server missing required field `url`

Error message

remote server missing required field `url`

What it means

Returned when a mcp_config entry declares "type": "remote" but the strict-decoded object has an empty `url` field. Remote servers are addressed purely by URL, so it is mandatory. If `url` is present, the same branch also validates `timeout` (must be positive when set) and `oauth` (validated by validateOpenCodeOAuth), so those errors come from the same code path.

Source

Thrown at server/pkg/agent/opencode_mcp.go:241

	switch typeStr {
	case "local":
		var entry opencodeMCPLocal
		if err := strictDecode(raw, &entry); err != nil {
			return nil, wrap(err)
		}
		if len(entry.Command) == 0 {
			return nil, wrap(errors.New("local server missing required field `command`"))
		}
		if entry.Timeout != nil && *entry.Timeout <= 0 {
			return nil, wrap(fmt.Errorf("`timeout` must be a positive integer, got %d", *entry.Timeout))
		}
	case "remote":
		var entry opencodeMCPRemote
		if err := strictDecode(raw, &entry); err != nil {
			return nil, wrap(err)
		}
		if entry.URL == "" {
			return nil, wrap(errors.New("remote server missing required field `url`"))
		}
		if entry.Timeout != nil && *entry.Timeout <= 0 {
			return nil, wrap(fmt.Errorf("`timeout` must be a positive integer, got %d", *entry.Timeout))
		}
		if len(entry.OAuth) > 0 {
			if err := validateOpenCodeOAuth(entry.OAuth); err != nil {
				return nil, wrap(fmt.Errorf("`oauth`: %w", err))
			}
		}
	case "":
		// No `type` field. The bare `{"enabled": bool}` override shape
		// is OpenCode's third native variant; anything else without a
		// type is a malformed local/remote attempt. Surface a single
		// friendly "missing type" error instead of the strict-decode
		// "json: unknown field" leak — the user usually didn't realise
		// they were mis-using the override shape.
		var entry opencodeMCPEnabledOnly
		if err := strictDecode(raw, &entry); err != nil || entry.Enabled == nil {

View on GitHub (pinned to 2c0912b6ec)

Solutions

  1. Add "url": "https://your-mcp-host/sse" (non-empty string) to the remote entry.
  2. Confirm the key is exactly `url` and the value is a full URL string.
  3. If the server is actually a local stdio process, switch to "type": "local" with a `command` array instead.

Example fix

// before
"mcp_config": { "github": { "type": "remote", "endpoint": "https://mcp.github.com/sse" } }

// after
"mcp_config": { "github": { "type": "remote", "url": "https://mcp.github.com/sse" } }
Defensive patterns

Strategy: validation

Validate before calling

function validateRemoteEntry(e: { type: string; url?: unknown }): string | null {
  if (e.type === 'remote' && (typeof e.url !== 'string' || e.url === '')) {
    return 'remote MCP server requires a non-empty `url`';
  }
  return null;
}

Type guard

function isRemoteMCPEntry(e: Record<string, unknown>): e is { type: 'remote'; url: string; timeout?: number; oauth?: Record<string, unknown> } {
  return e.type === 'remote' && typeof e.url === 'string' && e.url.length > 0;
}

Prevention

When it happens

Trigger: Setting {"type": "remote"} (or with "url": "") for a server in mcp_config; putting the URL under a misspelled key such as "endpoint" or "uri" that strict decoding would reject, or omitting it entirely.

Common situations: Copy-pasting a remote MCP server config that uses a different key name; a templating step that renders an empty URL; intending a local stdio server but selecting "remote" by mistake.

Related errors


AI-assisted analysis of multica-ai/multica@2c0912b6ec (2026-08-15). Data as JSON: /api/errors/5807cb2f4b9bc6be. Report an issue: GitHub.