campus-security-mcp 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,101 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.apiClient = exports.ApiClient = void 0;
4
+ const mockData_1 = require("../data/mockData");
5
+ // 默认配置
6
+ const defaultConfig = {
7
+ baseUrl: 'https://api.example.com',
8
+ apiKey: '',
9
+ useMock: true // 默认使用Mock数据
10
+ };
11
+ // API客户端类
12
+ class ApiClient {
13
+ constructor(config = {}) {
14
+ this.config = { ...defaultConfig, ...config };
15
+ }
16
+ // 获取所有区域
17
+ async getAreas() {
18
+ if (this.config.useMock) {
19
+ // 使用Mock数据
20
+ return Promise.resolve(mockData_1.mockData.areas);
21
+ }
22
+ // 真实API调用(预留)
23
+ try {
24
+ const response = await fetch(`${this.config.baseUrl}/api/areas`, {
25
+ headers: {
26
+ 'Authorization': `Bearer ${this.config.apiKey}`,
27
+ 'Content-Type': 'application/json'
28
+ }
29
+ });
30
+ const data = await response.json();
31
+ return data.areas;
32
+ }
33
+ catch (error) {
34
+ console.error('Error fetching areas:', error);
35
+ throw error;
36
+ }
37
+ }
38
+ // 获取所有街道
39
+ async getStreets() {
40
+ if (this.config.useMock) {
41
+ // 使用Mock数据
42
+ return Promise.resolve(mockData_1.mockData.streets);
43
+ }
44
+ // 真实API调用(预留)
45
+ try {
46
+ const response = await fetch(`${this.config.baseUrl}/api/streets`, {
47
+ headers: {
48
+ 'Authorization': `Bearer ${this.config.apiKey}`,
49
+ 'Content-Type': 'application/json'
50
+ }
51
+ });
52
+ const data = await response.json();
53
+ return data.streets;
54
+ }
55
+ catch (error) {
56
+ console.error('Error fetching streets:', error);
57
+ throw error;
58
+ }
59
+ }
60
+ // 查询警告数量
61
+ async getWarnings(input) {
62
+ if (this.config.useMock) {
63
+ // 使用Mock数据(这里简化处理,实际应该使用与工具相同的过滤逻辑)
64
+ // 注意:这里只是预留结构,实际工具中已经直接使用了mockData
65
+ return Promise.resolve({
66
+ totalCount: mockData_1.mockData.warnings.length,
67
+ dailyData: [],
68
+ areaBreakdown: [],
69
+ streetBreakdown: []
70
+ });
71
+ }
72
+ // 真实API调用(预留)
73
+ try {
74
+ const response = await fetch(`${this.config.baseUrl}/api/warnings`, {
75
+ method: 'POST',
76
+ headers: {
77
+ 'Authorization': `Bearer ${this.config.apiKey}`,
78
+ 'Content-Type': 'application/json'
79
+ },
80
+ body: JSON.stringify(input)
81
+ });
82
+ const data = await response.json();
83
+ return data;
84
+ }
85
+ catch (error) {
86
+ console.error('Error fetching warnings:', error);
87
+ throw error;
88
+ }
89
+ }
90
+ // 更新配置
91
+ updateConfig(config) {
92
+ this.config = { ...this.config, ...config };
93
+ }
94
+ // 获取当前配置
95
+ getConfig() {
96
+ return { ...this.config };
97
+ }
98
+ }
99
+ exports.ApiClient = ApiClient;
100
+ // 导出默认实例
101
+ exports.apiClient = new ApiClient();
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.mockData = exports.warnings = exports.warningTypes = exports.streets = exports.areas = void 0;
4
+ const dateUtils_1 = require("../utils/dateUtils");
5
+ // 区域数据
6
+ exports.areas = ['东', '西', '南', '北'];
7
+ // 街道数据
8
+ exports.streets = [
9
+ '春晖路',
10
+ '洋房路',
11
+ '经一路',
12
+ '经二路',
13
+ '经三路',
14
+ '经四路',
15
+ '八里庄街道',
16
+ '紫竹院街道',
17
+ '北新桥街道'
18
+ ];
19
+ // 警告类型
20
+ exports.warningTypes = ['安全隐患', '人员聚集', '设备故障', '其他'];
21
+ // 区域权重(东区权重较高)
22
+ const areaWeights = {
23
+ '东': 1.5,
24
+ '西': 1.0,
25
+ '南': 1.0,
26
+ '北': 1.0
27
+ };
28
+ // 街道权重(主干道权重较高)
29
+ const streetWeights = {
30
+ '春晖路': 1.5,
31
+ '洋房路': 1.2,
32
+ '经一路': 1.3,
33
+ '经二路': 1.1,
34
+ '经三路': 1.1,
35
+ '经四路': 1.0,
36
+ '八里庄街道': 1.2,
37
+ '紫竹院街道': 1.1,
38
+ '北新桥街道': 1.0
39
+ };
40
+ // 生成随机时间(当天内的随机时间)
41
+ function generateRandomTime(dateStr) {
42
+ const date = new Date(dateStr);
43
+ const hours = Math.floor(Math.random() * 24);
44
+ const minutes = Math.floor(Math.random() * 60);
45
+ date.setHours(hours, minutes, 0, 0);
46
+ return (0, dateUtils_1.formatDateTime)(date);
47
+ }
48
+ // 生成随机警告类型
49
+ function generateRandomWarningType() {
50
+ const index = Math.floor(Math.random() * exports.warningTypes.length);
51
+ return exports.warningTypes[index];
52
+ }
53
+ // 生成警告数据
54
+ function generateWarnings() {
55
+ const warnings = [];
56
+ const last7Days = (0, dateUtils_1.getLast7Days)();
57
+ let id = 1;
58
+ // 遍历近7天
59
+ last7Days.forEach(dateStr => {
60
+ const date = new Date(dateStr);
61
+ const dayOfWeek = date.getDay();
62
+ // 周末权重较低
63
+ const dayWeight = (dayOfWeek === 0 || dayOfWeek === 6) ? 0.7 : 1.0;
64
+ // 遍历每个区域
65
+ exports.areas.forEach(area => {
66
+ const areaWeight = areaWeights[area];
67
+ // 遍历每个街道
68
+ exports.streets.forEach(street => {
69
+ const streetWeight = streetWeights[street];
70
+ // 计算总权重
71
+ const totalWeight = areaWeight * streetWeight * dayWeight;
72
+ // 根据权重计算警告数量(0-5个)
73
+ const warningCount = Math.min(5, Math.floor(Math.random() * 3 * totalWeight));
74
+ // 生成警告
75
+ for (let i = 0; i < warningCount; i++) {
76
+ warnings.push({
77
+ id: String(id++),
78
+ timestamp: generateRandomTime(dateStr),
79
+ area,
80
+ street,
81
+ type: generateRandomWarningType()
82
+ });
83
+ }
84
+ });
85
+ });
86
+ });
87
+ return warnings;
88
+ }
89
+ // 导出警告数据
90
+ exports.warnings = generateWarnings();
91
+ // 导出所有Mock数据
92
+ exports.mockData = {
93
+ areas: exports.areas,
94
+ streets: exports.streets,
95
+ warnings: exports.warnings
96
+ };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
package/dist/index.js ADDED
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const server_1 = __importDefault(require("./server"));
7
+ require("./tools"); // 导入所有工具
8
+ // 启动服务器
9
+ server_1.default.start().then(() => {
10
+ console.log('MCP server started successfully');
11
+ console.log(`Server URL: ${server_1.default.getUrl()}`);
12
+ }).catch((error) => {
13
+ console.error('Failed to start MCP server:', error);
14
+ });
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ // 模拟MCP服务器实现
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.MCP = void 0;
5
+ // MCP服务器类
6
+ class MCP {
7
+ }
8
+ exports.MCP = MCP;
9
+ MCP.Server = class {
10
+ constructor(config) {
11
+ this.tools = [];
12
+ this.name = config.name;
13
+ this.description = config.description;
14
+ this.version = config.version;
15
+ }
16
+ // 注册工具
17
+ registerTool(tool) {
18
+ this.tools.push(tool);
19
+ console.log(`Tool registered: ${tool.name}`);
20
+ }
21
+ // 启动服务器
22
+ async start() {
23
+ console.log(`Starting MCP server: ${this.name} v${this.version}`);
24
+ console.log(`Description: ${this.description}`);
25
+ console.log(`Registered tools: ${this.tools.length}`);
26
+ this.tools.forEach(tool => {
27
+ console.log(`- ${tool.name}: ${tool.description}`);
28
+ });
29
+ console.log('MCP server started successfully');
30
+ }
31
+ // 获取服务器URL(模拟)
32
+ getUrl() {
33
+ return 'http://localhost:3000';
34
+ }
35
+ // 获取所有工具
36
+ getTools() {
37
+ return this.tools;
38
+ }
39
+ };
package/dist/server.js ADDED
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const mcp_1 = require("./mcp");
4
+ // 创建MCP服务器实例
5
+ const server = new mcp_1.MCP.Server({
6
+ name: 'campus-security-assistant',
7
+ description: '校园安防助手 MCP 服务器',
8
+ version: '1.0.0'
9
+ });
10
+ exports.default = server;
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const zod_1 = require("zod");
7
+ const server_1 = __importDefault(require("../server"));
8
+ const mockData_1 = require("../data/mockData");
9
+ // 区域查询工具输入模式(无输入)
10
+ const inputSchema = zod_1.z.object({});
11
+ // 区域查询工具输出模式
12
+ const outputSchema = zod_1.z.object({
13
+ areas: zod_1.z.array(zod_1.z.string()).describe('学校区域名称数组')
14
+ });
15
+ // 注册区域查询工具
16
+ server_1.default.registerTool({
17
+ name: 'campus_security_get_areas',
18
+ description: '返回所有学校区域名称',
19
+ inputSchema,
20
+ outputSchema,
21
+ handler: async () => {
22
+ // 返回Mock数据中的区域列表
23
+ const result = {
24
+ areas: mockData_1.areas
25
+ };
26
+ return {
27
+ content: `学校区域列表:${mockData_1.areas.join('、')}`,
28
+ structuredContent: result
29
+ };
30
+ },
31
+ hints: {
32
+ readOnlyHint: true,
33
+ idempotentHint: true
34
+ }
35
+ });
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const zod_1 = require("zod");
7
+ const server_1 = __importDefault(require("../server"));
8
+ // 定义工具输入模式
9
+ const inputSchema = zod_1.z.object({
10
+ name: zod_1.z.string().describe('The name to greet'),
11
+ age: zod_1.z.number().optional().describe('Optional age parameter')
12
+ });
13
+ // 定义工具输出模式
14
+ const outputSchema = zod_1.z.object({
15
+ message: zod_1.z.string().describe('The greeting message'),
16
+ timestamp: zod_1.z.number().describe('The current timestamp')
17
+ });
18
+ // 注册工具
19
+ server_1.default.registerTool({
20
+ name: 'example_greet',
21
+ description: 'Generate a greeting message',
22
+ inputSchema,
23
+ outputSchema,
24
+ handler: async (input) => {
25
+ const { name, age } = input;
26
+ let message = `Hello, ${name}!`;
27
+ if (age) {
28
+ message += ` You are ${age} years old.`;
29
+ }
30
+ return {
31
+ content: message,
32
+ structuredContent: {
33
+ message,
34
+ timestamp: Date.now()
35
+ }
36
+ };
37
+ },
38
+ hints: {
39
+ readOnlyHint: true,
40
+ idempotentHint: true
41
+ }
42
+ });
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ // 导入所有工具
4
+ require("./areaQuery");
5
+ require("./streetQuery");
6
+ require("./warningQuery");
7
+ // 可以在这里添加更多工具导入
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const zod_1 = require("zod");
7
+ const server_1 = __importDefault(require("../server"));
8
+ const mockData_1 = require("../data/mockData");
9
+ // 街道查询工具输入模式(无输入)
10
+ const inputSchema = zod_1.z.object({});
11
+ // 街道查询工具输出模式
12
+ const outputSchema = zod_1.z.object({
13
+ streets: zod_1.z.array(zod_1.z.string()).describe('学校街道名称数组')
14
+ });
15
+ // 注册街道查询工具
16
+ server_1.default.registerTool({
17
+ name: 'campus_security_get_streets',
18
+ description: '返回所有学校街道名称',
19
+ inputSchema,
20
+ outputSchema,
21
+ handler: async () => {
22
+ // 返回Mock数据中的街道列表
23
+ const result = {
24
+ streets: mockData_1.streets
25
+ };
26
+ return {
27
+ content: `学校街道列表:${mockData_1.streets.join('、')}`,
28
+ structuredContent: result
29
+ };
30
+ },
31
+ hints: {
32
+ readOnlyHint: true,
33
+ idempotentHint: true
34
+ }
35
+ });
@@ -0,0 +1,122 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const zod_1 = require("zod");
7
+ const server_1 = __importDefault(require("../server"));
8
+ const mockData_1 = require("../data/mockData");
9
+ const dateUtils_1 = require("../utils/dateUtils");
10
+ // 警告查询工具输入模式
11
+ const inputSchema = zod_1.z.object({
12
+ startDate: zod_1.z.string().optional().describe('开始日期 (ISO 格式)'),
13
+ endDate: zod_1.z.string().optional().describe('结束日期 (ISO 格式)'),
14
+ area: zod_1.z.string().optional().describe('区域名称'),
15
+ street: zod_1.z.string().optional().describe('街道名称')
16
+ });
17
+ // 警告查询工具输出模式
18
+ const outputSchema = zod_1.z.object({
19
+ totalCount: zod_1.z.number().describe('警告总数'),
20
+ dailyData: zod_1.z.array(zod_1.z.object({
21
+ date: zod_1.z.string().describe('日期 (YYYY-MM-DD)'),
22
+ count: zod_1.z.number().describe('警告数量')
23
+ })).describe('按日期分组的警告数据'),
24
+ areaBreakdown: zod_1.z.array(zod_1.z.object({
25
+ area: zod_1.z.string().describe('区域名称'),
26
+ count: zod_1.z.number().describe('警告数量')
27
+ })).describe('按区域分组的警告数据'),
28
+ streetBreakdown: zod_1.z.array(zod_1.z.object({
29
+ street: zod_1.z.string().describe('街道名称'),
30
+ count: zod_1.z.number().describe('警告数量')
31
+ })).describe('按街道分组的警告数据')
32
+ });
33
+ // 注册警告查询工具
34
+ server_1.default.registerTool({
35
+ name: 'campus_security_get_warnings',
36
+ description: '根据时间、区域或街道查询警告数量',
37
+ inputSchema,
38
+ outputSchema,
39
+ handler: async (input) => {
40
+ const { startDate, endDate, area, street } = input;
41
+ // 过滤警告数据
42
+ const filteredWarnings = mockData_1.warnings.filter(warning => {
43
+ // 检查日期范围
44
+ const warningDate = new Date(warning.timestamp);
45
+ if (!(0, dateUtils_1.isDateInRange)(warningDate, startDate, endDate)) {
46
+ return false;
47
+ }
48
+ // 检查区域
49
+ if (area && warning.area !== area) {
50
+ return false;
51
+ }
52
+ // 检查街道
53
+ if (street && warning.street !== street) {
54
+ return false;
55
+ }
56
+ return true;
57
+ });
58
+ // 计算警告总数
59
+ const totalCount = filteredWarnings.length;
60
+ // 按日期分组
61
+ const dailyMap = new Map();
62
+ filteredWarnings.forEach(warning => {
63
+ const date = (0, dateUtils_1.formatDate)(new Date(warning.timestamp));
64
+ dailyMap.set(date, (dailyMap.get(date) || 0) + 1);
65
+ });
66
+ const dailyData = Array.from(dailyMap.entries())
67
+ .map(([date, count]) => ({ date, count }))
68
+ .sort((a, b) => a.date.localeCompare(b.date));
69
+ // 按区域分组
70
+ const areaMap = new Map();
71
+ filteredWarnings.forEach(warning => {
72
+ areaMap.set(warning.area, (areaMap.get(warning.area) || 0) + 1);
73
+ });
74
+ const areaBreakdown = Array.from(areaMap.entries())
75
+ .map(([area, count]) => ({ area: area, count }))
76
+ .sort((a, b) => b.count - a.count);
77
+ // 按街道分组
78
+ const streetMap = new Map();
79
+ filteredWarnings.forEach(warning => {
80
+ streetMap.set(warning.street, (streetMap.get(warning.street) || 0) + 1);
81
+ });
82
+ const streetBreakdown = Array.from(streetMap.entries())
83
+ .map(([street, count]) => ({ street: street, count }))
84
+ .sort((a, b) => b.count - a.count);
85
+ // 构建结果
86
+ const result = {
87
+ totalCount,
88
+ dailyData,
89
+ areaBreakdown,
90
+ streetBreakdown
91
+ };
92
+ // 构建返回内容
93
+ let content = `警告查询结果:\n`;
94
+ content += `总警告数:${totalCount}\n`;
95
+ if (dailyData.length > 0) {
96
+ content += `\n按日期统计:\n`;
97
+ dailyData.forEach(item => {
98
+ content += `${item.date}: ${item.count}个\n`;
99
+ });
100
+ }
101
+ if (areaBreakdown.length > 0) {
102
+ content += `\n按区域统计:\n`;
103
+ areaBreakdown.forEach(item => {
104
+ content += `${item.area}区: ${item.count}个\n`;
105
+ });
106
+ }
107
+ if (streetBreakdown.length > 0) {
108
+ content += `\n按街道统计:\n`;
109
+ streetBreakdown.forEach(item => {
110
+ content += `${item.street}: ${item.count}个\n`;
111
+ });
112
+ }
113
+ return {
114
+ content,
115
+ structuredContent: result
116
+ };
117
+ },
118
+ hints: {
119
+ readOnlyHint: true,
120
+ idempotentHint: true
121
+ }
122
+ });
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getLast7Days = getLast7Days;
4
+ exports.formatDate = formatDate;
5
+ exports.formatDateTime = formatDateTime;
6
+ exports.parseDate = parseDate;
7
+ exports.isDateInRange = isDateInRange;
8
+ exports.getDateRange = getDateRange;
9
+ // 生成近7天的日期数组
10
+ // 返回格式: ['2026-04-06', '2026-04-07', ..., '2026-04-12']
11
+ function getLast7Days() {
12
+ const days = [];
13
+ const today = new Date();
14
+ for (let i = 6; i >= 0; i--) {
15
+ const date = new Date(today);
16
+ date.setDate(today.getDate() - i);
17
+ days.push(formatDate(date));
18
+ }
19
+ return days;
20
+ }
21
+ // 格式化日期为 YYYY-MM-DD 格式
22
+ function formatDate(date) {
23
+ const year = date.getFullYear();
24
+ const month = String(date.getMonth() + 1).padStart(2, '0');
25
+ const day = String(date.getDate()).padStart(2, '0');
26
+ return `${year}-${month}-${day}`;
27
+ }
28
+ // 格式化日期时间为 ISO 格式
29
+ function formatDateTime(date) {
30
+ return date.toISOString();
31
+ }
32
+ // 解析日期字符串为 Date 对象
33
+ function parseDate(dateString) {
34
+ return new Date(dateString);
35
+ }
36
+ // 检查日期是否在指定范围内
37
+ function isDateInRange(date, startDate, endDate) {
38
+ if (!startDate && !endDate) {
39
+ return true;
40
+ }
41
+ if (startDate) {
42
+ const start = parseDate(startDate);
43
+ if (date < start) {
44
+ return false;
45
+ }
46
+ }
47
+ if (endDate) {
48
+ const end = parseDate(endDate);
49
+ // 设置为当天的结束时间
50
+ end.setHours(23, 59, 59, 999);
51
+ if (date > end) {
52
+ return false;
53
+ }
54
+ }
55
+ return true;
56
+ }
57
+ // 获取指定日期范围内的所有日期
58
+ function getDateRange(startDate, endDate) {
59
+ const start = parseDate(startDate);
60
+ const end = parseDate(endDate);
61
+ const dates = [];
62
+ const current = new Date(start);
63
+ while (current <= end) {
64
+ dates.push(formatDate(current));
65
+ current.setDate(current.getDate() + 1);
66
+ }
67
+ return dates;
68
+ }
package/package.json ADDED
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "campus-security-mcp",
3
+ "version": "1.0.0",
4
+ "description": "校园安防助手 MCP 服务器",
5
+ "main": "dist/index.js",
6
+ "scripts": {
7
+ "build": "tsc",
8
+ "start": "node dist/index.js",
9
+ "dev": "ts-node src/index.ts"
10
+ },
11
+ "dependencies": {
12
+ "zod": "^3.22.4"
13
+ },
14
+ "devDependencies": {
15
+ "ts-node": "^10.9.2",
16
+ "typescript": "^5.3.3"
17
+ },
18
+ "keywords": [
19
+ "mcp",
20
+ "campus-security",
21
+ "security",
22
+ "typescript"
23
+ ],
24
+ "author": "Your Name",
25
+ "license": "MIT"
26
+ }