You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
7.0 KiB
7.0 KiB
| name | description |
|---|---|
| mcp-builder | Build MCP (Model Context Protocol) servers that give Claude new capabilities. Use when user wants to create an MCP server, add tools to Claude, or integrate external services. |
MCP Server Building Skill
You now have expertise in building MCP (Model Context Protocol) servers. MCP enables Claude to interact with external services through a standardized protocol.
What is MCP?
MCP servers expose:
- Tools: Functions Claude can call (like API endpoints)
- Resources: Data Claude can read (like files or database records)
- Prompts: Pre-built prompt templates
Quick Start: Java/Spring AI MCP Server
1. Project Setup
# 使用 Spring Initializr 创建项目
# 或通过 Maven 手动创建
mkdir my-mcp-server && cd my-mcp-server
mvn archetype:generate -DgroupId=com.example -DartifactId=my-mcp-server \
-DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
在 pom.xml 中添加依赖:
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-mcp-server-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
</dependencies>
2. Basic Server Template
// src/main/java/com/example/McpServerApplication.java
package com.example;
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.ai.tool.annotation.ToolParam;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
public class McpServerApplication {
public static void main(String[] args) {
SpringApplication.run(McpServerApplication.class, args);
}
@Bean
public MyTools myTools() {
return new MyTools();
}
}
// 定义工具类
class MyTools {
@Tool(description = "Say hello to someone")
public String hello(@ToolParam(description = "The name to greet") String name) {
return "Hello, " + name + "!";
}
@Tool(description = "Add two numbers together")
public String addNumbers(
@ToolParam(description = "First number") int a,
@ToolParam(description = "Second number") int b) {
return String.valueOf(a + b);
}
}
配置 application.properties:
spring.ai.mcp.server.name=my-server
spring.ai.mcp.server.version=1.0.0
spring.ai.mcp.server.type=SYNC
spring.main.web-application-type=none
spring.main.banner-mode=off
spring.ai.mcp.server.stdio=true
3. Register with Claude
Add to ~/.claude/mcp.json:
{
"mcpServers": {
"my-server": {
"command": "java",
"args": ["-jar", "/path/to/my-mcp-server/target/my-mcp-server.jar"]
}
}
}
TypeScript MCP Server
1. Setup
mkdir my-mcp-server && cd my-mcp-server
npm init -y
npm install @modelcontextprotocol/sdk
2. Template
// src/index.ts
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
const server = new Server({
name: "my-server",
version: "1.0.0",
});
// Define tools
server.setRequestHandler("tools/list", async () => ({
tools: [
{
name: "hello",
description: "Say hello to someone",
inputSchema: {
type: "object",
properties: {
name: { type: "string", description: "Name to greet" },
},
required: ["name"],
},
},
],
}));
server.setRequestHandler("tools/call", async (request) => {
if (request.params.name === "hello") {
const name = request.params.arguments.name;
return { content: [{ type: "text", text: `Hello, ${name}!` }] };
}
throw new Error("Unknown tool");
});
// Start server
const transport = new StdioServerTransport();
server.connect(transport);
Advanced Patterns
External API Integration
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.ai.tool.annotation.ToolParam;
import org.springframework.web.client.RestTemplate;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
public class WeatherTools {
private final RestTemplate restTemplate = new RestTemplate();
private final ObjectMapper objectMapper = new ObjectMapper();
@Tool(description = "Get current weather for a city")
public String getWeather(@ToolParam(description = "City name") String city) {
String url = "https://api.weatherapi.com/v1/current.json?key=YOUR_API_KEY&q=" + city;
String response = restTemplate.getForObject(url, String.class);
JsonNode data = objectMapper.readTree(response);
JsonNode current = data.get("current");
return String.format("%s: %s°C, %s",
city, current.get("temp_c"), current.get("condition").get("text").asText());
}
}
Database Access
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.ai.tool.annotation.ToolParam;
import org.springframework.jdbc.core.JdbcTemplate;
public class DatabaseTools {
private final JdbcTemplate jdbcTemplate;
public DatabaseTools(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
@Tool(description = "Execute a read-only SQL query")
public String queryDb(@ToolParam(description = "SQL query to execute") String sql) {
if (!sql.trim().toUpperCase().startsWith("SELECT")) {
return "Error: Only SELECT queries allowed";
}
var rows = jdbcTemplate.queryForList(sql);
return rows.toString();
}
}
Resources (Read-only Data)
import org.springframework.ai.tool.annotation.Tool;
import java.nio.file.Files;
import java.nio.file.Path;
public class ResourceTools {
@Tool(description = "Read application settings")
public String getSettings() throws Exception {
return Files.readString(Path.of("settings.json"));
}
@Tool(description = "Read a file from the workspace")
public String readFile(@ToolParam(description = "Path to the file") String path) throws Exception {
return Files.readString(Path.of(path));
}
}
Testing
# Build the project
mvn clean package -DskipTests
# Test with MCP Inspector
npx @anthropics/mcp-inspector java -jar target/my-mcp-server.jar
# Or send test messages directly
echo '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' | java -jar target/my-mcp-server.jar
Best Practices
- Clear tool descriptions: Claude uses
@Tool(description=...)to decide when to call tools - Input validation: Always validate and sanitize inputs in tool methods
- Error handling: Return meaningful error messages, use proper exception handling
- Use Spring DI: Leverage Spring's dependency injection for service wiring
- Security: Never expose sensitive operations without auth
- Idempotency: Tools should be safe to retry