MCP SSE 通信流程实战

97 阅读1分钟

创建 webmvc-mcp-server 项目

maven 依赖

    <properties>
        <java.version>17</java.version>
        <spring-ai.version>1.0.0</spring-ai.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-starter-mcp-server-webmvc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.ai</groupId>
                <artifactId>spring-ai-bom</artifactId>
                <version>${spring-ai.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

创建 WeatherService 类

@Service
public class WeatherService {
    @Tool(description = "Get weather forecast for a specific latitude/longitude")
    public String getWeatherForecastByLocation(double latitude, double longitude) {
        System.out.println("latitude:" + latitude + ",longitude:" + longitude);
        return "ok";
    }
}

注册方法回调

@SpringBootApplication
public class WebmvcMcpServerApplication {

	public static void main(String[] args) {
		SpringApplication.run(WebmvcMcpServerApplication.class, args);
	}
   // 注册方法回调
	@Bean
	public ToolCallbackProvider weatherTools(WeatherService weatherService) {
		return MethodToolCallbackProvider.builder().toolObjects(weatherService).build();
	}
}

application.yaml 配置

# Using spring-ai-starter-mcp-server-webmvc
spring:
  ai:
    mcp:
      server:
        name: webmvc-mcp-server
        version: 1.0.0
        type: SYNC
        instructions: "This server provides weather information tools and resources"
        sse-message-endpoint: /mcp/messages
        capabilities:
          tool: true
          resource: true
          prompt: true
          completion: true

运行 mcp-server

mvn spring-boot:run

创建 mcp-client 项目

maven 依赖

<properties>
		<java.version>17</java.version>
		<spring-ai.version>1.0.0</spring-ai.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.ai</groupId>
			<artifactId>spring-ai-starter-mcp-client</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>
	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.ai</groupId>
				<artifactId>spring-ai-bom</artifactId>
				<version>${spring-ai.version}</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>

注入 mcpSyncClients 调用 mcp-server 方法

@SpringBootApplication
public class McpClientApplication implements ApplicationRunner {
	public static void main(String[] args) {
		SpringApplication.run(McpClientApplication.class, args);
	}

	@Autowired
	private List<McpSyncClient> mcpSyncClients;
	@Override
	public void run(ApplicationArguments args) throws Exception {
		for(McpSyncClient mcpSyncClient : mcpSyncClients) {
			McpSchema.CallToolResult result = mcpSyncClient.callTool(new McpSchema.CallToolRequest(
					"getWeatherForecastByLocation",
					Map.of("latitude", "47.6062", "longitude", "-122.3321")));
			System.out.println(result);
		}
	}
}

交互过程

sequenceDiagram

autonumber

participant Client
participant Server


Client ->> Server: Open SSE Connection
activate Server
Server -->> Client: Endpoint Event

loop Message Exchange
Client ->> Server: POST /mcp/message?sessionId=xxx
Server -->> Client: Message Event
end
Client ->> Server: Close SSE Connection
deactivate Server

curl 操作

// 建立连接,注意不能关闭命令行窗口,后面的 curl 操作在新的命令行执行
curl -v http://localhost:8080/sse

// 
curl -v post "http://localhost:8080/mcp/messages?sessionId=bda664ee-6577-428b-af84-0f7e5d006395" \ 
-H 'Content-Type: application/json' \ 
-d '{"jsonrpc":"2.0","method":"initialize","id":"4d7c8c63-0","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"my-mcp-client - server1","version":"1.0.0"}}}'


curl -v post "http://localhost:8080/mcp/messages?sessionId=bda664ee-6577-428b-af84-0f7e5d006395" \ 
-H 'Content-Type: application/json' \ 
-d '{"jsonrpc":"2.0","method":"notifications/initialized"}'

// 调用方法
curl -v post "http://localhost:8080/mcp/messages?sessionId=bda664ee-6577-428b-af84-0f7e5d006395" \ 
-H 'Content-Type: application/json' \ 
-d '{"jsonrpc":"2.0","method":"tools/call","id":"35b2167d-1","params":{"name":"getWeatherForecastByLocation","arguments":{"longitude":"-122.3321","latitude":"47.6062"}}}'