MCP integration across the Koder Stack

draft

stackRFC002 — MCP integration across the Koder Stack

Abstract

Model Context Protocol (MCP) is Anthropic's JSONRPC2.0-based standard for LLMs to talk to *ools*(callable functions), *esources*(readable contexts), and *rompts*(parametric templates). Originally stdioonly; the 20250618 spec revision added the `streamablehttp` transport (a.k.a. WebMCP) which is the production-relevant variant for distributed deployments.

This RFC defines how MCP fits into the Koder Stack across *lient*and *erver*roles, and opens the first 4 implementation tickets (KMCP001..004) against the highestimpact components. It does NOT mandate every component become MCP-capable — only the ones where MCP unlocks a use case the user already wants but can't satisfy today.

Why MCP

The user's recurring pattern in 2026-Q2 has been "I want my chat in Kruze / my data in kdb / my repos in Flow to talk to LLMs without me copying and pasting context". Today each integration is bespoke: ai-gateway calls Koder Flow's Gitea API directly; kdb has a custom streaming-JSON channel for AI exports; Kruze's AI panel has no way to consume tools outside its own conversation buffer.

MCP collapses these into *ne wire format*that any LLM host (Claude Desktop, Cursor, internal Koder AI panel, third-party agents) can speak. Concretely:

  • The user adds an MCP server URL in Kruze's AI panel settings and

    the chat gains slack.send, linear.create_issue, notion.search tools without ai-gateway shipping any new code.

  • An external Claude Desktop attaches to https://kdb.koder.dev/mcp/

    with the user's Koder ID OAuth token and can kdb.query + read kdb://tables/users as a resource — same wire format as accessing Slack or GitHub MCP servers.

  • Koder Flow exposes repos.list, issues.create, prs.review as

    MCP tools at https://flow.koder.dev/mcp/ so coding agents (Aider, Cursor, our own future Koder Aider) drive Flow uniformly.

Roles

MCP client

A component that *onsumes*toolsresourcesprompts from external MCP servers. The classic UX is "user pastes a server URL in settings; the LLM-driven chat in the app can now call that server's tools".

Koder components with a natural MCP-client surface today:

  • *ruze AI panel*(KMCP-001) — the chat sidebar in the desktop

    browser. Highest value: zero aigateway changes needed; user installed tools land in the chat immediately.

  • *ek*(deferred) — once services/ai/chat-adapter standardises

    the LLM-host shape used by Dek's editor.

MCP server

A component that *xposes*its own functions as tools / its own data as resources. The host LLM (anyone with a compatible client) calls them via JSON-RPC.

Koder components with a natural MCP-server surface today:

  • *ruze browser surface*(KMCP-002) — open_tab, read_active_tab,

    screenshot, click, eval_js, print_pdf, start_debug_mode. Reuses the existing webview_cef + capture pipeline; new code is the JSONRPC + KoderID-auth layer.

  • *dbnext*(KMCP003) — list_tables, describe_table,

    query(sql), sample(table, n) as tools; large tables as MCP resources readonly. Casa com stackRFC-001.

  • *oder Flow*(KMCP-004) — list_repos, list_issues,

    comment_pr, create_issue, git_log, get_file(repo, path). Forkar github-mcp-server-style implementations and swap the REST backend for Gitea API.

Deferred but plausible v2 candidates: servicesaitrace (traces as MCP resources for LLM debugging incidents), Hub (search/install apps), servicesfoundationid (whoami, list_workspaces).

Architectural decisions

Transport: streamable-http (WebMCP)

stdio works for single-process LLM hosts (Claude Desktop launching a local Python server). For Koder we need crossmachine + crossproduct: Kruze on the laptop talking to kdb in the LXC cluster. The 20250618 spec's streamable-http transport uses HTTP POST for client→server and SSE (or chunked HTTP) for server→client streaming. Every Koder MCP server lives behind a Koder Jet vhost (<service>.koder.dev/mcp/).

stdio support stays available where it's cheap (e.g. a local CLI companion), but it's not the canonical transport.

Auth: Koder ID OAuth bearer tokens

Every MCP server MUST require a Authorization: Bearer <token> header and validate it against Koder ID. The bearer token IS the tenant discriminator — policies/multi-tenant-by-default.kmd applies: every tool's response set is scoped to the caller's koder_user_id. Cross- tenant attempts return 404 (per the multi-tenancy contract — never 403, to avoid existence-leak side channels).

For local stdio MCP servers, auth is the OS-process boundary (already trusted).

Tool naming: <server-slug>.<verb>_<noun>

Per the MCP spec, tools are namespaced by the server they live on. We add the convention that tool names within a server use <verb>_<noun> (snake_case), so the fully-qualified name in the client's tool list reads as kdb.list_tables, flow.create_issue, kruze.open_tab. This matches the OpenAPI verb/noun convention already in use across Koder backends.

SDK extraction (reuse-first.kmd trigger)

The MCP server boilerplate (JSON-RPC dispatcher + transport handshake + Koder ID auth middleware + multi-tenant scoping + standard error shapes) repeats across all 3+ planned serverside components (KMCP002, 003, -004). Per `policies/reusefirst.kmd §"create SDK ≥3 consumers", this triggers an SDK: **enginessdkkoder_mcp` (Go)*with a Dart binding to follow when Flutter components need MCP-client behaviour beyond what the chat adapter abstracts.

Open question for sub-tickets: should we adopt the existing mark3labs/mcp-go library wholesale (BSD-licensed, lightweight) versus rolling our own. Default direction: adopt + wrap with Koder-specific middleware (auth + tenant scoping); revisit if upstream proves limiting.

Sub-tickets

ID Title Component Effort
KMCP-001 Kruze AI panel — MCP client wiring (settings + chat tool-call routing) products/horizontal/kruze 2-3 days
KMCP-002 Kruze browser surface — MCP server (open_tabscreenshotpdf/debug_mode) products/horizontal/kruze 3-5 days
KMCP-003 kdb-next — MCP server (list_tablesquerysample) infra/data/kdb 2-3 days
KMCP-004 Koder Flow — MCP server (list_reposissuesprs/git_log) products/dev/flow 12 days (fork githubmcp-server)

Each subticket has its own `KMCPNNN-*.md under the relevant component's backlogpending`, opened in the same commit that lands this RFC.

Out of scope

  • *CP server registry / discovery*— users paste URLs manually

    in v1. A central "koder/mcp-registry" listing the canonical Koder servers + community ones lands as a future ticket.

  • *oolcall sandboxing*— beyond pertenant scoping, we don't

    ratelimit or audit individual tool invocations in v1. Aud lands when KMCP-* components have real traffic.

  • *CP prompts*— the third primitive (after tools + resources)

    is parameterised prompt templates. Useful but no clear v1 use case; defer until a component asks for it.

  • *CP roots*— file-system root negotiation. Useful for desktop

    agents; v1 doesn't need it (server-side tools encode their own paths).

  • *ampling*— MCP servers can request the client's LLM to run

    completions on their behalf. Powerful but a security cliff (server-controlled prompts). Off by default in every Koder MCP server; revisit when a real use case shows up.

Migration path

No existing functionality changes — MCP capability is additive on every component. Existing ai-gateway integrations with Flow/kdb stay as-is; the MCP server is a parallel endpoint that other LLM hosts can attach to.

Acceptance

A user with a fresh Koder ID account can:

  1. Install Kruze (released via the kruze-release.yml pipeline now

    that KSHIP-001002003 are fixed).

  2. Add https://flow.koder.dev/mcp/ to the Kruze AI panel's MCP

    server list, sign in via Koder ID OAuth.

  3. Type "list my open PRs in the koder-tools repo" in the chat.
  4. Watch the LLM call `flow.list_prs(repo: "koder-tools",

    state: "open")` via MCP, receive the result, and produce a structured answer with PR titles + URLs.

That roundtrip — without any custom aigateway integration code — demonstrates the full client + server + auth + multi-tenant chain.

Source: ../home/koder/dev/koder/meta/docs/stack/rfcs/stack-RFC-002-mcp-integration.kmd