showcase/shell-docs/src/content/docs/agentic-protocols/mcp.mdx
The Model Context Protocol is an open standard that enables developers to build secure, two-way connections between their data sources and AI-powered tools. With MCP, you can:
For further reading, check out the Model Context Protocol website.
<Callout type="info" title="Looking for MCP Apps?"> If you want MCP servers to return **interactive UI components** that render directly in the chat, check out [MCP Apps](/generative-ui/mcp-apps). </Callout><Image src="/images/any-agentic-backend-light.png" alt="CopilotKit with Agentic Protocols" width={4096} height={2304} className="block dark:hidden w-full mx-auto" /> <Image src="/images/any-agentic-backend-dark.png" alt="CopilotKit with Agentic Protocols" width={4096} height={2304} className="hidden dark:block w-full mx-auto" />
<div className="text-center text-sm text-muted-foreground mt-2 mb-8 w-3/5 mx-auto"> MCP is one of three prominent [agentic protocols](/agentic-protocols) CopilotKit supports to connect agents to user-facing frontends </div><Accordions className="shadow-lg ring-1 ring-indigo-400 selected bg-gradient-to-r from-indigo-100/80 to-purple-200 dark:from-indigo-900/30 dark:to-purple-900/50">
<Accordion title="Get an MCP Server from Composio">
Composio provides a registry of ready-to-use MCP servers with simple authentication and setup.
To get started, go to [Composio](https://mcp.composio.dev/), find a server that suits your needs and copy the SSE URL before continuing here.
</Accordion>
</Accordions>
<Accordions>
<Accordion title="Don't have a Next.js application?">
No problem! Just use `create-next-app` to make one quickly.
```bash
npx create-next-app@latest
```
</Accordion>
</Accordions>
```bash
npx copilotkit@latest init -m MCP
```
</Step>
</TailoredContentOption>
<TailoredContentOption
id="do-it-manually"
title="Code along"
description="I want to deeply understand what's happening under the hood or don't have a Next.js application."
icon={<SquareChartGantt />}
>
<Step>
#### Set up the CopilotKit Provider
Wrap your application with the `CopilotKit` provider:
```tsx
"use client";
import { CopilotKit } from "@copilotkit/react-core/v2";
export default function App() {
return (
<CopilotKit publicApiKey="<replace_with_your_own>">
</CopilotKit>
);
}
```
</Step>
<Step>
#### Connect to MCP Servers
Create a component to manage MCP server connections:
```tsx
"use client";
import { useEffect } from "react";
import { useCopilotKit } from "@copilotkit/react-core/v2";
function McpServerManager() {
const { setMcpServers } = useCopilotKit();
useEffect(() => {
setMcpServers([
{
// Try a sample MCP server at https://mcp.composio.dev/
endpoint: "your_mcp_sse_url",
},
]);
}, [setMcpServers]);
return null;
}
export default McpServerManager;
```
</Step>
<Step>
#### Add the Chat Interface
Add the `CopilotChat` component to your page:
```tsx
"use client";
import { CopilotChat } from "@copilotkit/react-core/v2";
export default function ChatInterface() {
return (
<div className="flex h-screen p-4">
<McpServerManager />
<CopilotChat
className="flex-grow rounded-lg w-full"
/>
</div>
);
}
```
</Step>
<Step>
#### Visualize MCP Tool Calls (Optional)
Create a component to display MCP tool calls in your UI:
```tsx
"use client";
import {
useFrontendTool,
CatchAllActionRenderProps,
} from "@copilotkit/react-core/v2";
export function ToolRenderer() {
useFrontendTool({
/**
* The asterisk (*) matches all tool calls
*/
name: "*",
render: ({ name, status, args, result }: CatchAllActionRenderProps<[]>) => (
<McpToolCall status={status} name={name} args={args} result={result} />
),
});
return null;
}
```
</Step>
<Step>
#### Complete Implementation
Combine all components together:
```tsx
"use client";
import { CopilotKit, CopilotChat } from "@copilotkit/react-core/v2";
export default function Page() {
return (
<CopilotKit publicApiKey="<replace_with_your_own>">
<div className="flex h-screen p-4">
<McpServerManager />
<CopilotChat
className="flex-grow rounded-lg w-full"
/>
<ToolRenderer />
</div>
</CopilotKit>
);
}
```
</Step>
</TailoredContentOption>
"use client";
interface ToolCallProps {
status: "complete" | "inProgress" | "executing";
name?: string;
args?: any;
result?: any;
}
export default function MCPToolCall({
status,
name = "",
args,
result,
}: ToolCallProps) {
const [isOpen, setIsOpen] = React.useState(false);
// Format content for display
const format = (content: any): string => {
if (!content) return "";
const text =
typeof content === "object"
? JSON.stringify(content, null, 2)
: String(content);
return text
.replace(/\\n/g, "\n")
.replace(/\\t/g, "\t")
.replace(/\\"/g, '"')
.replace(/\\\\/g, "\\");
};
return (
<div className="bg-[#1e2738] rounded-lg overflow-hidden w-full">
<div
className="p-3 flex items-center cursor-pointer"
onClick={() => setIsOpen(!isOpen)}
>
<span className="text-white text-sm overflow-hidden text-ellipsis">
{name || "MCP Tool Call"}
</span>
<div className="ml-auto">
<div
className={`w-2 h-2 rounded-full ${
status === "complete"
? "bg-gray-300"
: status === "inProgress" || status === "executing"
? "bg-gray-500 animate-pulse"
: "bg-gray-700"
}`}
/>
</div>
</div>
{isOpen && (
<div className="px-4 pb-4 text-gray-300 font-mono text-xs">
{args && (
<div className="mb-4">
<div className="text-gray-400 mb-2">Parameters:</div>
<pre className="whitespace-pre-wrap max-h-[200px] overflow-auto">
{format(args)}
</pre>
</div>
)}
{status === "complete" && result && (
<div>
<div className="text-gray-400 mb-2">Result:</div>
<pre className="whitespace-pre-wrap max-h-[200px] overflow-auto">
{format(result)}
</pre>
</div>
)}
</div>
)}
</div>
);
}
To configure your self-hosted runtime with MCP servers, you'll need to implement the createMCPClient function that matches this interface:
type CreateMCPClientFunction = (
config: MCPEndpointConfig,
) => Promise<MCPClient>;
For detailed implementation guidance, refer to the official MCP SDK documentation.
Here's a basic example of configuring the runtime:
import {
CopilotRuntime,
OpenAIAdapter,
copilotRuntimeNextJSAppRouterEndpoint,
} from "@copilotkit/runtime";
import { NextRequest } from "next/server";
const serviceAdapter = new OpenAIAdapter();
const runtime = new CopilotRuntime({
createMCPClient: async (config) => {
// Implement your MCP client creation logic here
// See the MCP SDK docs for implementation details
},
});
export const POST = async (req: NextRequest) => {
const { handleRequest } = copilotRuntimeNextJSAppRouterEndpoint({
runtime,
serviceAdapter,
endpoint: "/api/copilotkit",
});
return handleRequest(req);
};