Files
gh-jezweb-claude-skills-ski…/templates/custom-mcp-server.ts
2025-11-30 08:23:58 +08:00

162 lines
4.2 KiB
TypeScript

import { query, createSdkMcpServer, tool } from "@anthropic-ai/claude-agent-sdk";
import { z } from "zod";
/**
* Custom MCP Server Template
*
* Demonstrates:
* - Creating in-process MCP server
* - Defining tools with Zod schemas
* - Multiple tools in one server
* - Error handling in tools
*/
// Define a custom MCP server with multiple tools
const weatherServer = createSdkMcpServer({
name: "weather-service",
version: "1.0.0",
tools: [
tool(
"get_weather",
"Get current weather for a location",
{
location: z.string().describe("City name or coordinates"),
units: z.enum(["celsius", "fahrenheit"]).default("celsius")
},
async (args) => {
try {
// Simulate API call
const response = await fetch(
`https://api.weather.com/v1/current?location=${args.location}&units=${args.units}`
);
const data = await response.json();
return {
content: [{
type: "text",
text: `Temperature: ${data.temp}° ${args.units}\nConditions: ${data.conditions}\nHumidity: ${data.humidity}%`
}]
};
} catch (error) {
return {
content: [{
type: "text",
text: `Error fetching weather: ${error.message}`
}],
isError: true
};
}
}
),
tool(
"get_forecast",
"Get weather forecast for next 7 days",
{
location: z.string(),
days: z.number().min(1).max(7).default(7)
},
async (args) => {
// Simulated forecast data
return {
content: [{
type: "text",
text: `7-day forecast for ${args.location}: Mostly sunny with temperatures ranging from 15-25°C`
}]
};
}
)
]
});
// Database tools server
const databaseServer = createSdkMcpServer({
name: "database",
version: "1.0.0",
tools: [
tool(
"query_users",
"Query user records from the database",
{
email: z.string().email().optional(),
limit: z.number().min(1).max(100).default(10),
offset: z.number().min(0).default(0)
},
async (args) => {
// Simulated database query
const results = [
{ id: 1, email: "user1@example.com", name: "User 1" },
{ id: 2, email: "user2@example.com", name: "User 2" }
];
return {
content: [{
type: "text",
text: JSON.stringify(results, null, 2)
}]
};
}
),
tool(
"calculate",
"Perform mathematical calculations",
{
expression: z.string().describe("Mathematical expression to evaluate"),
precision: z.number().min(0).max(10).default(2)
},
async (args) => {
try {
// In production, use a proper math parser (e.g., mathjs)
const result = eval(args.expression);
const rounded = Number(result.toFixed(args.precision));
return {
content: [{
type: "text",
text: `Result: ${rounded}`
}]
};
} catch (error) {
return {
content: [{
type: "text",
text: `Invalid expression: ${error.message}`
}],
isError: true
};
}
}
)
]
});
// Use custom tools in query
async function useCustomTools() {
const response = query({
prompt: "What's the weather in San Francisco? Also query users with gmail addresses and calculate 15% tip on $85.50",
options: {
model: "claude-sonnet-4-5",
mcpServers: {
"weather-service": weatherServer,
"database": databaseServer
},
allowedTools: [
"mcp__weather-service__get_weather",
"mcp__weather-service__get_forecast",
"mcp__database__query_users",
"mcp__database__calculate"
]
}
});
for await (const message of response) {
if (message.type === 'assistant') {
console.log('Assistant:', message.content);
} else if (message.type === 'tool_call') {
console.log(`\n🔧 ${message.tool_name}:`, message.input);
}
}
}
// Run
useCustomTools().catch(console.error);