guides

ByteChef Embedded, Part 6: The MCP Chat

ByteChef Embedded, Part 6: The MCP Chat
5 min read
Ivica Čardić

TL;DR: In part three, your own route fetched the user's tools from ByteChef and adapted each one to the AI SDK. The MCP Chat lets a standard do that work: its backend route (/api/chat-mcp) opens an MCP client to ByteChef's embedded MCP server over streamable HTTP, calls mcpClient.tools() to discover the connected user's tools, and hands them straight to the model. It's the same Model Context Protocol that Claude and Cursor speak, consumed inside your own chat. This is part six of the series.

The ComponentKit Chat gave an assistant real tools, but your route had to know ByteChef's tools API: fetch the list, parse each schema, wrap it with tool(), and POST every call back for execution. The MCP Chat gets the same kind of toolbox through a protocol instead, so discovery and execution are standardized rather than hand-written per app.

Tools by Discovery

The chat page is the same assistant-ui thread as part three. The difference is entirely in the backend route:

import { createMCPClient } from '@ai-sdk/mcp';
import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';

const jwtToken = await getToken();

const mcpClient = await createMCPClient({
    transport: new StreamableHTTPClientTransport(new URL(BYTECHEF_MCP_SERVER_URL), {
        requestInit: {
            headers: {
                Authorization: `Bearer ${jwtToken}`,
                'X-Environment': BYTECHEF_ENVIRONMENT,
            },
        },
    }),
});

const tools = await mcpClient.tools(); // discover the connected user's tools

const result = streamText({
    model: openai.chat('gpt-5'),
    messages: await convertToModelMessages(messages),
    tools: { ...tools, ...frontendTools(clientTools ?? {}) },
    stopWhen: stepCountIs(8),
    onFinish: async () => {
        await mcpClient.close();
    },
});

Instead of enumerating and wrapping actions yourself, you open an MCP connection to ByteChef's embedded MCP server and ask it for the tools available to this connected user. The same JWT from part one rides along in the Authorization header, so the user's integrations (the ones you configured for them as a vendor) arrive as ready-to-call tools, already scoped to their connections. There's no execute function to write: when the model calls a tool, the MCP client sends the call back to the server for you.

A few details worth noticing in the route:

  • stopWhen: stepCountIs(8) lets the agent loop continue past tool calls, so the model can read a tool's result and act again (or answer) instead of stopping after one step.
  • frontendTools(...) merges in any tools the assistant-ui page registers on the client, so server tools from MCP and browser-side tools live in one toolbox.
  • mcpClient.close() runs in onFinish, so each request opens and closes its own MCP session.

Add an integration on the ByteChef side and it shows up in the chat on the next request. No client change.

Authorization on Demand

The user doesn't have to connect every app up front. If the model calls a tool whose integration isn't connected yet, the embedded MCP server doesn't fail the call. It returns a result that tells the model what to do:

{
    "error": "connection_required",
    "message": "The slack integration is not connected for this user. To connect, visit: https://your-bytechef/connect.html?token=... . Instruct the user to visit this link to connect their account.",
    "setupUrl": "https://your-bytechef/connect.html?token=..."
}

The model passes the link on in the chat. The link opens ByteChef's hosted connect page, which carries a short-lived token (valid for 10 minutes) scoped to that user and integration. The page opens the same ConnectDialog from part one: an OAuth2 popup for OAuth2 apps, or a form for API keys and other credential types. Once the user connects, nothing else is needed. The server checks for a connection on every tool call, so when the model tries the tool again, it runs on the user's new connection.

That turns onboarding into part of the conversation: the user asks for something, the assistant finds it needs Slack, hands over a link, and carries on once Slack is connected. Connections only get created for the apps people actually use.

Why the Protocol Matters

Doing this over MCP rather than through a custom adapter buys you three things:

  • One definition, many clients. The tools your MCP Chat uses are the same ones an external Claude or Cursor gets from the embedded MCP server. You define an integration's tool surface once, and every AI (yours and your customers') consumes it the same way.
  • Central governance. Which tools exist, their input schemas, and the per-connected-user identity are all resolved server-side. The chat just discovers and calls.
  • Future-proofing. MCP is the emerging standard for giving models tools. Building on it means your "AI that acts" feature speaks the same language as the rest of the industry.

Same outcome as the ComponentKit Chat (an agent that operates the user's apps), but the tools flow through an open, discoverable protocol instead of bespoke wiring.

Six Parts In

The pieces so far compose into one story about what "embedded automation" takes:

  1. Connect your users' apps (the JWT and ConnectDialog everything rests on).
  2. Act on those connected apps directly with the ComponentKit.
  3. Chat with an AI assistant that uses the ComponentKit's tools.
  4. Trigger their workflows from your product's events.
  5. Call a workflow like a synchronous API.
  6. Agent over MCP: the same tools, discovered through an open protocol (this part).

Every one of them was a component or a couple of API calls, all scoped by a single JWT and all riding the same connections. That's the promise of embedded: the integration surface is yours (your UI, your brand, your product) and the integration machinery is ByteChef's.

Following along? Connect an integration in the embedded sample app, add your OpenAI key, and open MCP Chat - your assistant now finds its tools on its own.

Subscribe to the ByteChef Newsletter

Get the latest guides on complex automation, AI agents, and visual workflow best practices delivered to your inbox.