feat: support SSE for MCP tools adapter (#1882)

This commit is contained in:
Huu Le
2025-04-23 15:54:37 +07:00
committed by GitHub
parent 056594452c
commit 294f502441
4 changed files with 82 additions and 9 deletions
+5
View File
@@ -0,0 +1,5 @@
---
"@llamaindex/tools": patch
---
Support SSE for MCP tools adapter
@@ -57,6 +57,41 @@ const researchAgent = agent({
});
```
## MCP tools
If you have a MCP server running, you can fetch tools from the server and use them in your agents.
```ts
// 1. Import MCP tools adapter
import { mcp } from "@llamaindex/tools";
import { agent } from "llamaindex";
// 2. Initialize a MCP client
// by npx
const server = mcp({
command: "npx",
args: ["-y", "@modelcontextprotocol/server-filesystem", "."],
verbose: true,
});
// or by SSE
const server = mcp({
url: "http://localhost:8000/mcp",
verbose: true,
});
// 3. Get tools from MCP server
const tools = await server.tools();
// Now you can create an agent with the tools
const agent = agent({
name: "My Agent",
systemPrompt: "You are a helpful assistant that can use the provided tools to answer questions.",
llm: openai({ model: "gpt-4o" }),
tools: tools,
});
```
## Function tool
You can still use the `FunctionTool` class to define a tool.
+7 -3
View File
@@ -9,6 +9,12 @@ async function main() {
args: ["-y", "@modelcontextprotocol/server-filesystem", "."],
verbose: true,
});
// You can also connect to the MCP server using SSE
// See: https://modelcontextprotocol.io/docs/concepts/transports#server-sent-events-sse
// const server = mcp({
// url: "http://localhost:8000/mcp",
// verbose: true,
// });
try {
// Create an agent that uses the MCP tools
@@ -21,9 +27,7 @@ async function main() {
});
// Run a task
const response = await myAgent.run(
"what are the files in the current directory?",
);
const response = await myAgent.run("What are the available tools?");
console.log("Agent response:", response.data);
} finally {
+35 -6
View File
@@ -2,6 +2,10 @@ import type { JSONValue } from "@llamaindex/core/global";
import type { BaseToolWithCall } from "@llamaindex/core/llms";
import { FunctionTool } from "@llamaindex/core/tools";
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import {
SSEClientTransport,
type SSEClientTransportOptions,
} from "@modelcontextprotocol/sdk/client/sse.js";
import {
StdioClientTransport,
type StdioServerParameters,
@@ -13,7 +17,7 @@ interface ToolInput {
[key: string]: unknown;
}
type MCPClientOptions = StdioServerParameters & {
type MCPCommonOptions = {
/**
* The prefix to add to the tool name
*/
@@ -32,11 +36,20 @@ type MCPClientOptions = StdioServerParameters & {
verbose?: boolean;
};
type StdioMCPClientOptions = StdioServerParameters & MCPCommonOptions;
type SSEMCPClientOptions = SSEClientTransportOptions &
MCPCommonOptions & {
url: string;
};
type MCPClientOptions = StdioMCPClientOptions | SSEMCPClientOptions;
class MCPClient {
private mcp: Client;
private transport: StdioClientTransport | null = null;
private transport: StdioClientTransport | SSEClientTransport | null = null;
private verbose: boolean;
private toolNamePrefix?: string | undefined;
private connected: boolean = false;
constructor(options: MCPClientOptions) {
this.mcp = new Client({
@@ -46,18 +59,34 @@ class MCPClient {
this.verbose = options.verbose ?? false;
this.toolNamePrefix = options.toolNamePrefix;
this.connectToSever(options);
if ("url" in options) {
this.transport = new SSEClientTransport(
new URL(options.url),
options as SSEClientTransportOptions,
);
} else {
this.transport = new StdioClientTransport(
options as StdioServerParameters,
);
}
this.connected = false;
}
async connectToSever(options: StdioServerParameters) {
async connectToSever() {
if (this.verbose) {
console.log("Connecting to MCP server...");
}
this.transport = new StdioClientTransport(options);
if (!this.transport) {
throw new Error("Initialized with invalid options");
}
await this.mcp.connect(this.transport);
this.connected = true;
}
async listTools(): Promise<Tool[]> {
private async listTools(): Promise<Tool[]> {
if (!this.connected) {
await this.connectToSever();
}
const tools = await this.mcp.listTools();
return tools.tools;
}