#2405·MiMo-Code

MCP auth authenticate returns 400 when config is registered at runtime but not yet in ConfigService (Notion plugin install)

Author: chenyi720Created Sep 16, 2026Updated Sep 16, 2026

Summary

Installing the bundled Notion MCP plugin from Xiaomi MiMo Desktop fails during OAuth:

授权未完成,已撤销安装:引擎请求失败 400

registerWithEngine succeeds, then POST /mcp/notion-mcp:notion/auth/authenticate returns HTTP 400 within milliseconds, and the desktop rolls back the install.

Environment

  • Xiaomi MiMo Desktop on Windows
  • Plugin: notion-mcp → remote MCP https://mcp.notion.com/mcp
  • Engine URL: http://127.0.0.1:11787 (in-process mimocode server)
  • Observed: 2026-09-16 22:09–22:10 (local)

Repro

  1. Open Desktop → Plugins page
  2. Install Notion MCP
  3. Click OAuth confirm (“继续”)
  4. Toast “正在打开官方授权页面…” then immediate 400; plugin is uninstalled

Log excerpt

22:09:45 [info] [mcp] registerWithEngine name=notion-mcp:notion
22:09:49 [info] [mcp] registerWithEngine name=notion-mcp:notion ok
22:09:49 [log] [sess-diag] engineFetch POST /mcp/notion-mcp%3Anotion/auth/authenticate -> HTTP 400 elapsed=6ms
22:09:49 [log] [sess-diag] engineFetch DELETE /mcp/notion-mcp%3Anotion/auth -> HTTP 200
22:09:49 [info] [engine] reloadConfigOnNextSession (plugin change)

(Same pattern three times: 22:09:49, 22:10:10, 22:10:20.)

Root cause

Desktop install sequence:

  1. Plugin installer writes notion-mcp:notion into global mimocode.jsonc mcp section
  2. Desktop mcpRegister → engine POST /mcpMCP.add / createAndStore (runtime client/state only)
  3. Immediately POST /mcp/:name/auth/authenticate

Engine auth path:

typescript
// supportsOAuth
const mcpConfig = cfg.mcp?.[mcpName]
if (!mcpConfig) return false
return mcpConfig.type === remote && mcpConfig.oauth !== false

// authenticate route
if (!result.supports) {
  return c.json({ error: `MCP server ${name} does not support OAuth` }, 400)
}

supportsOAuth / getMcpConfig read ConfigService, not the runtime registry that POST /mcp just populated. Plugin MCP writes are marked reloadConfigOnNextSession; if that commit has not landed in ConfigService yet, authenticate sees a missing config and returns 400. Desktop then deletes auth and uninstalls.

So: runtime registration succeeded, ConfigService still stale → 400.

Suggested fix (engine-side, this repo)

Any of:

  1. getMcpConfig / supportsOAuth fall back to the runtime-registered MCP config from POST /mcp / MCP.add
  2. POST /mcp also upserts ConfigService (or accepts an immediate config commit)
  3. authenticate / startAuth accept config from the request body when ConfigService lacks the entry
  4. Return a distinct error (e.g. config_not_ready) instead of generic 400 does not support OAuth

Desktop-side complementary fix (if applicable in host code): force commitNewSessionConfigIfDirty() before calling authenticate after plugin install.

Workaround (verified)

Manually add to ~/.config/mimocode/mimocode.jsonc:

jsonc
notion: {
  type: remote,
  url: https://mcp.notion.com/mcp,
  enabled: true
}

Then mimo mcp auth notion. Do not use the plugin-page Install button until fixed.