谢亚昕 1 month ago
parent
commit
03669e9b5b
  1. 31
      client.js
  2. 5
      package.json
  3. 5
      pnpm-lock.yaml
  4. 26
      readme.md
  5. 58
      server-sse.js
  6. 29
      weather/client.js
  7. 47
      weather/server-sse.js
  8. 76
      weather/server.js
  9. 4
      weather/test.js
  10. 28
      weather/util.js

31
client.js

@ -28,8 +28,11 @@ try {
// const prompts = await client.listPrompts();
// console.log(prompts);
// const prompt = await client.getPrompt("example-prompt", {
// arg1: "value",
// const prompt = await client.getPrompt({
// name: "echo",
// arguments: {
// message: "aaac",
// },
// });
// console.log(prompt);
@ -46,26 +49,10 @@ try {
// console.log(resources);
// Read a resource
const resource = await client.readResource("echo://example.txt");
console.log(resource);
// const resource = await client.readResource({
// uri: "echo://asa",
// });
// console.log(resource);
} catch (error) {
console.error("Failed to connect:", error);
}
// // List prompts
// const prompts = await client.listPrompts();
// console.log(prompts);
// Get a prompt
// const prompt = await client.getPrompt("example-prompt", {
// arg1: "value"
// });
// console.log(11);
// console.log(prompt);
// List resources
// const resources = await client.listResources();
// console.log(resources);
// Read a resource
// const resource = await client.readResource("file:///example.txt");

5
package.json

@ -5,7 +5,9 @@
"description": "",
"main": "index.js",
"scripts": {
"test": "mcp-inspector node server.js"
"start": "node client.js",
"test": "mcp-inspector node server.js",
"sse": "node server-sse.js"
},
"keywords": [],
"author": "",
@ -14,6 +16,7 @@
"dependencies": {
"@modelcontextprotocol/inspector": "^0.6.0",
"@modelcontextprotocol/sdk": "^1.7.0",
"express": "^4.21.2",
"zod": "^3.24.2"
}
}

5
pnpm-lock.yaml

@ -14,6 +14,9 @@ importers:
'@modelcontextprotocol/sdk':
specifier: ^1.7.0
version: 1.7.0
express:
specifier: ^4.21.2
version: 4.21.2
zod:
specifier: ^3.24.2
version: 3.24.2
@ -2119,7 +2122,7 @@ snapshots:
send@1.1.0:
dependencies:
debug: 4.3.6
debug: 4.4.0
destroy: 1.2.0
encodeurl: 2.0.0
escape-html: 1.0.3

26
readme.md

@ -4,3 +4,29 @@
- https://github.com/modelcontextprotocol/servers
- https://mcpcn.com/docs/quickstart/client/
- https://www.npmjs.com/package/@modelcontextprotocol/sdk#writing-mcp-clients
- https://mcpcn.com/docs/examples/
- https://zhuanlan.zhihu.com/p/16934783594
- https://mcpcn.com/tools/inspector/
- https://modelcontextprotocol.io/sdk/java/mcp-client
- https://github1s.com/modelcontextprotocol/servers/blob/main/src/sentry/src/mcp_server_sentry/server.py#L233
- https://mcpservers.org/
- https://www.npmjs.com/package/@modelcontextprotocol/sdk#server-capabilities
{
"mcpServers": {
"天气": {
"url": "http://localhost:3001/sse",
"env": {}
},
"filesystem": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"D:/@code/demo/x6-demo",
"D:/@code/demo/x6-demo"
]
}
}
}

58
server-sse.js

@ -0,0 +1,58 @@
import express from "express";
import {
ResourceTemplate,
McpServer,
} from "@modelcontextprotocol/sdk/server/mcp.js";
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
import { z } from "zod";
const server = new McpServer({
name: "Echo",
version: "1.0.0",
});
server.resource(
"echo",
new ResourceTemplate("echo://{message}", { list: undefined }),
async (uri, { message }) => ({
contents: [
{
uri: uri.href,
text: `Resource echo: ${message}`,
},
],
})
);
server.tool("echo", { message: z.string() }, async ({ message }) => ({
content: [{ type: "text", text: `Tool echo: ${message}` }],
}));
server.prompt("echo", { message: z.string() }, ({ message }) => ({
messages: [
{
role: "user",
content: {
type: "text",
text: `Please process this message: ${message}`,
},
},
],
}));
const app = express();
let transport
app.get("/sse", async (req, res) => {
transport = new SSEServerTransport("/messages", res);
await server.connect(transport);
});
app.post("/messages", async (req, res) => {
// Note: to support multiple simultaneous connections, these messages will
// need to be routed to a specific matching transport. (This logic isn't
// implemented here, for simplicity.)
await transport.handlePostMessage(req, res);
});
app.listen(3001);
console.log("Server running on http://localhost:3001");

29
weather/client.js

@ -0,0 +1,29 @@
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
const transport = new StdioClientTransport({
command: "node",
args: ["./server.js"],
cwd: process.cwd(),
});
const client = new Client(
{
name: "weather-client",
version: "0.0.1",
},
{
capabilities: {
prompts: {},
resources: {},
tools: {},
},
}
);
try {
await client.connect(transport);
console.log("Connected successfully");
} catch (error) {
console.error("Failed to connect:", error);
}

47
weather/server-sse.js

@ -0,0 +1,47 @@
import express from "express";
import {
ResourceTemplate,
McpServer,
} from "@modelcontextprotocol/sdk/server/mcp.js";
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
import { z } from "zod";
const server = new McpServer(
{
name: "天气工具包",
version: "1.0.0",
},
{
capabilities: {
tools: {},
},
}
);
server.tool("get-weather", { state: z.string() }, async ({ state }) => {
const url = `https://cn.apihz.cn/api/tianqi/tqyb.php?id=88888888&key=88888888&sheng=四川&place=绵阳`;
const data = await fetch(url).then((res) => res.json());
if (!data) {
return "无法获取天气";
}
return data;
});
const app = express();
let transport;
app.get("/sse", async (req, res) => {
transport = new SSEServerTransport("/messages", res);
await server.connect(transport);
});
app.post("/messages", async (req, res) => {
// Note: to support multiple simultaneous connections, these messages will
// need to be routed to a specific matching transport. (This logic isn't
// implemented here, for simplicity.)
await transport.handlePostMessage(req, res);
});
app.listen(3001);
console.log("Server running on http://localhost:3001");

76
weather/server.js

@ -0,0 +1,76 @@
import {
McpServer,
ResourceTemplate,
} from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
makeNWSRequest,
formatAlert,
NWS_API_BASE,
USER_AGENT,
} from "./util.js";
import { z } from "zod";
const server = new McpServer({
name: "天气工具包",
version: "0.0.1",
});
server.tool("获取天气", { state: z.string() }, async ({ state }) => {
const url = `https://cn.apihz.cn/api/tianqi/tqyb.php?id=88888888&key=88888888&sheng=四川&place=绵阳`;
const data = await fetch(url).then(res => res.json());
if (!data) {
return "无法获取天气";
}
return data;
});
// server.tool({
// name: "get-forecast",
// description: "获取位置的天气预报",
// parameters: {
// latitude: {
// type: "number",
// description: "位置的纬度",
// },
// longitude: {
// type: "number",
// description: "位置的经度",
// },
// },
// async execute({ latitude, longitude }) {
// // 首先获取预报网格端点
// const pointsUrl = `${NWS_API_BASE}/points/${latitude},${longitude}`;
// const pointsData = await makeNWSRequest(pointsUrl);
// if (!pointsData) {
// return "无法为此位置获取预报数据。";
// }
// // 从点响应中获取预报URL
// const forecastUrl = pointsData.properties.forecast;
// const forecastData = await makeNWSRequest(forecastUrl);
// if (!forecastData) {
// return "无法获取详细预报。";
// }
// // 将时段格式化为可读预报
// const periods = forecastData.properties.periods;
// const forecasts = periods.slice(0, 5).map(
// (period) => `
// ${period.name}:
// Temperature: ${period.temperature}°${period.temperatureUnit}
// Wind: ${period.windSpeed} ${period.windDirection}
// Forecast: ${period.detailedForecast}
// `
// );
// return forecasts.join("\n---\n");
// },
// });
const transport = new StdioServerTransport();
await server.connect(transport);

4
weather/test.js

@ -0,0 +1,4 @@
fetch("https://cn.apihz.cn/api/tianqi/tqyb.php?id=88888888&key=88888888&sheng=四川&place=绵阳").then(res => res.json()).then(data => {
console.log(data)
})

28
weather/util.js

@ -0,0 +1,28 @@
// 常量
export const NWS_API_BASE = "https://api.weather.gov";
export const USER_AGENT = "weather-app/1.0";
export async function makeNWSRequest(url) {
const headers = {
// "User-Agent": USER_AGENT,
// Accept: "application/geo+json",
};
try {
const response = await fetch(url);
if (!response.ok) throw new Error("API request failed");
return await response.json();
} catch (error) {
return null;
}
}
export function formatAlert(feature) {
const props = feature.properties;
return `
Event: ${props.event || "Unknown"}
Area: ${props.areaDesc || "Unknown"}
Severity: ${props.severity || "Unknown"}
Description: ${props.description || "No description available"}
Instructions: ${props.instruction || "No specific instructions provided"}
`;
}
Loading…
Cancel
Save