yszl-mcp
Version:
Scenic Area Tourist Flow Query Server with official MCP SDK
214 lines (200 loc) • 5.7 kB
JavaScript
/**
* Startup file for SSE communication protocol mode
*/
import express from 'express';
import bodyParser from 'body-parser';
import dotenv from 'dotenv';
dotenv.config();
// Import tools
import { TouristFlowTool } from '../tools/touristFlowTool.js';
import { CumulativeTouristFlowTool } from '../tools/cumulativeTouristFlowTool.js';
import { DailyTouristFlowTool } from '../tools/dailyTouristFlowTool.js';
import { ProvinceOriginTool } from '../tools/provinceOriginTool.js';
import { GenderPortraitTool } from '../tools/genderPortraitTool.js';
import { AgePortraitTool } from '../tools/agePortraitTool.js';
// Import SSE transport
import { SseTransport } from '../transport/sse.js';
// Create Express application
const app = express();
const port = process.env.PORT || 3000;
// Enable CORS
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
res.header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
if (req.method === 'OPTIONS') {
return res.sendStatus(200);
}
next();
});
// Use middleware to parse JSON
app.use(bodyParser.json());
// Create tool instances
const toolInstances = {
touristFlowTool: new TouristFlowTool(),
cumulativeTouristFlowTool: new CumulativeTouristFlowTool(),
dailyTouristFlowTool: new DailyTouristFlowTool(),
provinceOriginTool: new ProvinceOriginTool(),
genderPortraitTool: new GenderPortraitTool(),
agePortraitTool: new AgePortraitTool()
};
// MCP manifest endpoint with SSE mode
app.get('/manifest', (req, res) => {
res.json({
schema_version: "v1",
name_for_human: "Tourist Flow Query Service",
name_for_model: "touristFlowQuery",
description_for_human: "Provides real-time tourist flow and visitor profile query services for scenic areas",
description_for_model: "A service for querying real-time tourist flow, cumulative flow, daily flow statistics and visitor profiles (origin, gender, age distribution) in scenic areas",
auth: {
type: "none"
},
api: {
type: "sse",
sse: {
enabled: true
}
},
tools_endpoint: "/api/tools"
});
});
// Tool metadata endpoint
app.get('/api/tools', (req, res) => {
res.json({
tools: [
{
name: 'TouristFlow',
description: 'Get real-time tourist flow information',
inputs: {
type: 'object',
properties: {
scId: {
type: 'string',
description: 'Scenic Area ID'
}
},
required: ['scId']
}
},
{
name: 'CumulativeTouristFlow',
description: 'Get cumulative tourist flow statistics',
inputs: {
type: 'object',
properties: {
scId: {
type: 'string',
description: 'Scenic Area ID'
}
},
required: ['scId']
}
},
{
name: 'DailyTouristFlow',
description: 'Get daily tourist flow statistics',
inputs: {
type: 'object',
properties: {
scId: {
type: 'string',
description: 'Scenic Area ID'
},
day: {
type: 'string',
description: 'Date in YYYYMMDD format, e.g. 20220101'
}
},
required: ['scId', 'day']
}
},
{
name: 'ProvinceOrigin',
description: 'Get tourist province origin distribution',
inputs: {
type: 'object',
properties: {
scId: {
type: 'string',
description: 'Scenic Area ID'
},
day: {
type: 'string',
description: 'Date in YYYYMMDD format, e.g. 20220101'
}
},
required: ['scId', 'day']
}
},
{
name: 'GenderPortrait',
description: 'Get tourist gender distribution',
inputs: {
type: 'object',
properties: {
scId: {
type: 'string',
description: 'Scenic Area ID'
},
day: {
type: 'string',
description: 'Date in YYYYMMDD format, e.g. 20220101'
}
},
required: ['scId', 'day']
}
},
{
name: 'AgePortrait',
description: 'Get tourist age distribution',
inputs: {
type: 'object',
properties: {
scId: {
type: 'string',
description: 'Scenic Area ID'
},
day: {
type: 'string',
description: 'Date in YYYYMMDD format, e.g. 20220101'
}
},
required: ['scId', 'day']
}
}
]
});
});
// Root endpoint
app.get('/', (req, res) => {
res.json({
name: 'Tourist Flow Query Service (SSE Mode)',
version: '1.1.8',
status: 'running',
endpoints: [
'/manifest',
'/api/tools',
'/sse',
'/sse/execute'
]
});
});
// Health check
app.get('/health', (req, res) => {
res.json({ status: 'ok' });
});
// Error handling middleware
app.use((err, req, res, next) => {
console.error('Server error:', err);
res.status(500).json({
status: 'error',
message: 'Internal server error'
});
});
// Initialize and start the SSE transport
const sseTransport = new SseTransport(app, toolInstances);
sseTransport.start();
// Start server
const server = app.listen(port, () => {
console.log(`Tourist Flow Query Service (SSE Mode) running on port ${port}`);
});