236 lines
6.7 KiB
TypeScript
236 lines
6.7 KiB
TypeScript
import { McpServer, ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js'
|
|
import { StreamableHTTPTransport } from '@hono/mcp'
|
|
import { Hono } from 'hono'
|
|
import { z } from 'zod'
|
|
import { cors } from 'hono/cors'
|
|
|
|
const app = new Hono()
|
|
|
|
app.use(
|
|
'/*',
|
|
cors({
|
|
origin: '*',
|
|
allowHeaders: ['content-type', 'mcp-session-id', 'mcp-protocol-version'],
|
|
exposeHeaders: ['mcp-session-id'],
|
|
}),
|
|
)
|
|
|
|
// Your MCP server implementation
|
|
const mcpServer = new McpServer({
|
|
name: 'vengabus-mcp-server',
|
|
version: '1.0.0',
|
|
})
|
|
|
|
mcpServer.registerTool(
|
|
'calculate_party_capacity',
|
|
{
|
|
title: 'Party Bus Capacity Calculator',
|
|
description: 'Calculate how many people can fit on the Vengabus',
|
|
inputSchema: {
|
|
busCount: z.number().describe('Number of Vengabuses'),
|
|
peoplePerBus: z.number().describe('People per bus'),
|
|
},
|
|
},
|
|
async ({ busCount, peoplePerBus }) => ({
|
|
content: [
|
|
{
|
|
type: 'text',
|
|
text: `🚌 ${busCount} Vengabuses can transport ${busCount * peoplePerBus} party people! The wheels of steel are turning! 🎉`,
|
|
},
|
|
],
|
|
}),
|
|
)
|
|
|
|
mcpServer.registerTool(
|
|
'get_vengabus_times',
|
|
{
|
|
title: 'Vengabus Schedule Checker',
|
|
description:
|
|
"This checks to see when the next Vengabus is, or whether there is one for the user's current location. Please display all the information to the user in a tabulated form.",
|
|
inputSchema: {},
|
|
},
|
|
async () => {
|
|
// Simulate some async work
|
|
await new Promise((resolve) => setTimeout(resolve, 100 + Math.random() * 100))
|
|
return {
|
|
content: [
|
|
{
|
|
type: 'text',
|
|
text: `🚌 BOOM BOOM BOOM BOOM! Next Vengabus: IMMINENT! 🎉
|
|
|
|
Current Route: "Intercity Disco Express"
|
|
From: New York
|
|
To: IBIZA - THE MAGIC ISLAND! ✨
|
|
|
|
Schedule:
|
|
- Departure: When the beat drops
|
|
- Via: San Francisco (quick party stop)
|
|
- Arrival: When the sun comes up
|
|
|
|
Status: The party bus is jumping!
|
|
Passengers: Maximum capacity!
|
|
BPM: 142 and rising!
|
|
|
|
We're going to Ibiza! Back to the island! 🏝️`,
|
|
},
|
|
],
|
|
}
|
|
},
|
|
)
|
|
|
|
// Register sample resources
|
|
mcpServer.registerResource(
|
|
'config',
|
|
'config://vengabus',
|
|
{
|
|
title: 'Vengabus Fleet Configuration',
|
|
description: 'Current Vengabus fleet settings and party parameters',
|
|
mimeType: 'application/json',
|
|
},
|
|
async (uri: URL) => {
|
|
const normalizedUri = uri.href.replace(/\/$/, '')
|
|
return {
|
|
contents: [
|
|
{
|
|
uri: normalizedUri,
|
|
mimeType: 'application/json',
|
|
text: JSON.stringify(
|
|
{
|
|
version: '1.0.0',
|
|
fleet: 'intercity-disco',
|
|
features: {
|
|
bassBoost: true,
|
|
strobeEnabled: true,
|
|
maxBPM: 160,
|
|
wheelsOfSteel: 'turning',
|
|
},
|
|
routes: ['New York to Ibiza', 'Back to the Magic Island', 'Like an Intercity Disco', 'The place to be'],
|
|
},
|
|
null,
|
|
2,
|
|
),
|
|
},
|
|
],
|
|
}
|
|
},
|
|
)
|
|
|
|
mcpServer.registerResource(
|
|
'readme',
|
|
'docs://party-manual.md',
|
|
{
|
|
title: 'Vengabus Party Manual',
|
|
description: 'Official guide to the Vengabus experience',
|
|
mimeType: 'text/markdown',
|
|
},
|
|
() => ({
|
|
contents: [
|
|
{
|
|
uri: 'docs://party-manual.md',
|
|
mimeType: 'text/markdown',
|
|
text: "# 🚌 Vengabus MCP Server\n\nBOOM BOOM BOOM BOOM! Welcome aboard the Vengabus! We like to party!\n\n## Features\n- 🎉 Party capacity calculator - How many can we take to Ibiza?\n- 🕐 Vengabus schedule checker - Next stop: The Magic Island!\n- 🎵 Fleet configuration with maximum bass boost\n- 🌟 Party statistics tracker (BPM, passengers, energy levels)\n\n## Routes\n- New York to Ibiza (via San Francisco)\n- Back to the Magic Island\n- Like an Intercity Disco\n- The place to be\n\n## Current Status\nThe wheels of steel are turning, and traffic lights are burning!\nWe're going to Ibiza! Woah! We're going to Ibiza!\n\n*Up, up and away we go!*",
|
|
},
|
|
],
|
|
}),
|
|
)
|
|
|
|
// Register a resource template
|
|
mcpServer.registerResource(
|
|
'stats',
|
|
new ResourceTemplate('party://stats/{metric}', { list: undefined }),
|
|
{
|
|
title: 'Vengabus Party Statistics',
|
|
description: 'Get party metrics (bpm, passengers, energy)',
|
|
mimeType: 'application/json',
|
|
},
|
|
async (uri: URL, { metric }) => {
|
|
return {
|
|
contents: [
|
|
{
|
|
uri: uri.href,
|
|
mimeType: 'application/json',
|
|
text: JSON.stringify(
|
|
{
|
|
metric: metric,
|
|
value:
|
|
metric === 'bpm'
|
|
? 140 + Math.floor(Math.random() * 20)
|
|
: metric === 'passengers'
|
|
? Math.floor(Math.random() * 50) + 20
|
|
: metric === 'energy'
|
|
? Math.floor(Math.random() * 100)
|
|
: 0,
|
|
unit:
|
|
metric === 'bpm'
|
|
? 'beats per minute'
|
|
: metric === 'passengers'
|
|
? 'party people'
|
|
: metric === 'energy'
|
|
? 'party power %'
|
|
: 'unknown',
|
|
status: 'The party is jumping!',
|
|
lastUpdated: new Date().toISOString(),
|
|
},
|
|
null,
|
|
2,
|
|
),
|
|
},
|
|
],
|
|
}
|
|
},
|
|
)
|
|
|
|
// Register sample prompts
|
|
mcpServer.registerPrompt(
|
|
'party_invitation',
|
|
{
|
|
title: 'Vengabus Party Invitation',
|
|
description: 'Generate a party invitation for the Vengabus',
|
|
argsSchema: {
|
|
name: z.string().describe('Name of the party person'),
|
|
destination: z.string().optional().describe('Where the Vengabus is heading'),
|
|
},
|
|
},
|
|
({ name, destination }) => ({
|
|
messages: [
|
|
{
|
|
role: 'user',
|
|
content: {
|
|
type: 'text',
|
|
text: `Create a party invitation for ${name} to join the Vengabus${destination ? ` heading to ${destination}` : ''}`,
|
|
},
|
|
},
|
|
],
|
|
}),
|
|
)
|
|
|
|
mcpServer.registerPrompt(
|
|
'party_announcement',
|
|
{
|
|
title: 'Party Bus Announcement',
|
|
description: 'Generate party-themed announcements for various occasions',
|
|
argsSchema: {
|
|
event: z.string().describe('Type of event (deployment, release, milestone, etc.)'),
|
|
details: z.string().optional().describe('Additional details about the event'),
|
|
},
|
|
},
|
|
({ event, details }) => ({
|
|
messages: [
|
|
{
|
|
role: 'user',
|
|
content: {
|
|
type: 'text',
|
|
text: `Create a party bus announcement for a ${event}${details ? `: ${details}` : ''}`,
|
|
},
|
|
},
|
|
],
|
|
}),
|
|
)
|
|
|
|
app.post('/mcp', async (c) => {
|
|
const transport = new StreamableHTTPTransport()
|
|
await mcpServer.connect(transport)
|
|
return transport.handleRequest(c)
|
|
})
|
|
|
|
export default app
|