
# MCP Tools

The AI SDK supports Model Context Protocol (MCP) tools by offering a lightweight client that exposes a `tools` method for retrieving tools from a MCP server. After use, the client should always be closed to release resources.

## Server

Let's create a route handler for `/api/completion` that will generate text based on the input prompt and MCP tools that can be called at any time during a generation. The route will call the `streamText` function from the `ai` module, which will then generate text based on the input prompt and stream it to the client.

To use the `StreamableHTTPClientTransport`, you will need to install the official Typescript SDK for Model Context Protocol:

<Snippet text="pnpm install @modelcontextprotocol/sdk" />

```ts filename="app/api/completion/route.ts"
import { experimental_createMCPClient, streamText } from 'ai';
import { Experimental_StdioMCPTransport } from 'ai/mcp-stdio';
import { openai } from '@ai-sdk/openai';
import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp';

export async function POST(req: Request) {
  const { prompt }: { prompt: string } = await req.json();

  try {
    // Initialize an MCP client to connect to a `stdio` MCP server:
    const transport = new Experimental_StdioMCPTransport({
      command: 'node',
      args: ['src/stdio/dist/server.js'],
    });
    const stdioClient = await experimental_createMCPClient({
      transport,
    });

    // Alternatively, you can connect to a Server-Sent Events (SSE) MCP server:
    const sseClient = await experimental_createMCPClient({
      transport: {
        type: 'sse',
        url: 'https://actions.zapier.com/mcp/[YOUR_KEY]/sse',
      },
    });

    // Similarly to the stdio example, you can pass in your own custom transport as long as it implements the `MCPTransport` interface (e.g. `StreamableHTTPClientTransport`):
    const transport = new StreamableHTTPClientTransport(
      new URL('http://localhost:3000/mcp'),
    );
    const customClient = await experimental_createMCPClient({
      transport,
    });

    const toolSetOne = await stdioClient.tools();
    const toolSetTwo = await sseClient.tools();
    const toolSetThree = await customClient.tools();
    const tools = {
      ...toolSetOne,
      ...toolSetTwo,
      ...toolSetThree, // note: this approach causes subsequent tool sets to override tools with the same name
    };

    const response = await streamText({
      model: openai('gpt-4o'),
      tools,
      prompt,
      // When streaming, the client should be closed after the response is finished:
      onFinish: async () => {
        await stdioClient.close();
        await sseClient.close();
        await customClient.close();
      },
      // Closing clients onError is optional
      // - Closing: Immediately frees resources, prevents hanging connections
      // - Not closing: Keeps connection open for retries
      onError: async error => {
        await stdioClient.close();
        await sseClient.close();
        await customClient.close();
      },
    });

    return response.toDataStreamResponse();
  } catch (error) {
    return new Response('Internal Server Error', { status: 500 });
  }
}
```

## Client

Let's create a simple React component that imports the `useCompletion` hook from the `@ai-sdk/react` module. The `useCompletion` hook will call the `/api/completion` endpoint when a button is clicked. The endpoint will generate text based on the input prompt and stream it to the client.

```tsx filename="app/page.tsx"
'use client';

import { useCompletion } from '@ai-sdk/react';

export default function Page() {
  const { completion, complete } = useCompletion({
    api: '/api/completion',
  });

  return (
    <div>
      <div
        onClick={async () => {
          await complete(
            'Please schedule a call with Sonny and Robby for tomorrow at 10am ET for me!',
          );
        }}
      >
        Schedule a call
      </div>

      {completion}
    </div>
  );
}
```


## Navigation

- [Generate Text](/v4/cookbook/next/generate-text)
- [Generate Text with Chat Prompt](/v4/cookbook/next/generate-text-with-chat-prompt)
- [Generate Image with Chat Prompt](/v4/cookbook/next/generate-image-with-chat-prompt)
- [Stream Assistant Response](/v4/cookbook/next/stream-assistant-response)
- [Stream Assistant Response with Tools](/v4/cookbook/next/stream-assistant-response-with-tools)
- [Caching Middleware](/v4/cookbook/next/caching-middleware)
- [Stream Text](/v4/cookbook/next/stream-text)
- [Stream Text with Chat Prompt](/v4/cookbook/next/stream-text-with-chat-prompt)
- [Stream Text with Image Prompt](/v4/cookbook/next/stream-text-with-image-prompt)
- [Chat with PDFs](/v4/cookbook/next/chat-with-pdf)
- [streamText Multi-Step Cookbook](/v4/cookbook/next/stream-text-multistep)
- [Markdown Chatbot with Memoization](/v4/cookbook/next/markdown-chatbot-with-memoization)
- [Generate Object](/v4/cookbook/next/generate-object)
- [Generate Object with File Prompt through Form Submission](/v4/cookbook/next/generate-object-with-file-prompt)
- [Stream Object](/v4/cookbook/next/stream-object)
- [Call Tools](/v4/cookbook/next/call-tools)
- [Call Tools in Parallel](/v4/cookbook/next/call-tools-in-parallel)
- [Call Tools in Multiple Steps](/v4/cookbook/next/call-tools-multiple-steps)
- [Model Context Protocol (MCP) Tools](/v4/cookbook/next/mcp-tools)
- [Human-in-the-Loop with Next.js](/v4/cookbook/next/human-in-the-loop)
- [Send Custom Body from useChat](/v4/cookbook/next/send-custom-body-from-use-chat)
- [Render Visual Interface in Chat](/v4/cookbook/next/render-visual-interface-in-chat)


[Full Sitemap](/sitemap.md)
