feat(examples): transform hono-mcp server to Vengabus party theme

Transform the generic example server into a fun Vengabus-themed MCP server with:
- Replace generic tools with party-themed tools (party capacity calculator, vengabus schedule)
- Update resources to use party-themed URIs and content
- Replace generic prompts with party invitations and announcements
- Fix resource URI handling to strip trailing slashes
- Fix TypeScript errors with proper resource template typing
- Use docs:// protocol for party manual resource

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Jem 2025-07-02 18:24:03 -07:00
commit 6a42f9dc93

View file

@ -1,4 +1,4 @@
import { McpServer, type ReadResourceTemplateCallback, ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js'
import { McpServer, ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js'
import { StreamableHTTPTransport } from '@hono/mcp'
import { Hono } from 'hono'
import { z } from 'zod'
@ -17,19 +17,27 @@ app.use(
// Your MCP server implementation
const mcpServer = new McpServer({
name: 'my-mcp-server',
name: 'vengabus-mcp-server',
version: '1.0.0',
})
mcpServer.registerTool(
'add',
'calculate_party_capacity',
{
title: 'Addition Tool',
description: 'Add two numbers',
inputSchema: { a: z.number(), b: z.number() },
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 ({ a, b }) => ({
content: [{ type: 'text', text: String(a + b) }],
async ({ busCount, peoplePerBus }) => ({
content: [
{
type: 'text',
text: `🚌 ${busCount} Vengabuses can transport ${busCount * peoplePerBus} party people! The wheels of steel are turning! 🎉`,
},
],
}),
)
@ -48,7 +56,22 @@ mcpServer.registerTool(
content: [
{
type: 'text',
text: `Next Vengabus: imminent. Current user's route: New York to San Francisco. Route name: "Intercity Disco".`,
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! 🏝️`,
},
],
}
@ -58,107 +81,124 @@ mcpServer.registerTool(
// Register sample resources
mcpServer.registerResource(
'config',
'config://app',
'config://vengabus',
{
title: 'Application Configuration',
description: 'Current application configuration settings',
title: 'Vengabus Fleet Configuration',
description: 'Current Vengabus fleet settings and party parameters',
mimeType: 'application/json',
},
async (uri: URL) => ({
contents: [
{
uri: uri.href,
mimeType: 'application/json',
text: JSON.stringify(
{
version: '1.0.0',
environment: 'test',
features: {
vengabus: true,
calculator: true,
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,
),
},
],
}),
null,
2,
),
},
],
}
},
)
mcpServer.registerResource(
'readme',
'file://readme.md',
'docs://party-manual.md',
{
title: 'README',
description: 'Server documentation',
title: 'Vengabus Party Manual',
description: 'Official guide to the Vengabus experience',
mimeType: 'text/markdown',
},
async (uri: URL) => ({
contents: [
{
uri: uri.href,
mimeType: 'text/markdown',
text: '# Test MCP Server\n\nThis is a test server for the use-mcp integration tests.\n\n## Features\n- Addition tool\n- Vengabus schedule checker\n- Sample resources\n- Sample prompts',
},
],
() => ({
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('data://stats/{type}', { list: undefined }),
new ResourceTemplate('party://stats/{metric}', { list: undefined }),
{
title: 'Statistics Data',
description: 'Get statistics for different types',
title: 'Vengabus Party Statistics',
description: 'Get party metrics (bpm, passengers, energy)',
mimeType: 'application/json',
},
// @ts-expect-error - type is missing in the callback
async (uri: URL, { type }) => ({
contents: [
{
uri: uri.href,
mimeType: 'application/json',
text: JSON.stringify(
{
type: type,
count: Math.floor(Math.random() * 100),
lastUpdated: new Date().toISOString(),
},
null,
2,
),
},
],
}),
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(
'greeting',
'party_invitation',
{
title: 'Generate Greeting',
description: 'Generate a greeting message',
title: 'Vengabus Party Invitation',
description: 'Generate a party invitation for the Vengabus',
argsSchema: {
name: z.string().describe('Name of the person to greet'),
style: z.string().optional().describe('Style of greeting (formal/casual)'),
name: z.string().describe('Name of the party person'),
destination: z.string().optional().describe('Where the Vengabus is heading'),
},
},
({ name, style }) => ({
({ name, destination }) => ({
messages: [
{
role: 'user',
content: {
type: 'text',
text: `Generate a ${style || 'casual'} greeting for ${name}`,
},
},
{
role: 'assistant',
content: {
type: 'text',
text: style === 'formal' ? `Good day, ${name}. I hope this message finds you well.` : `Hey ${name}! How's it going?`,
text: `Create a party invitation for ${name} to join the Vengabus${destination ? ` heading to ${destination}` : ''}`,
},
},
],
@ -166,22 +206,22 @@ mcpServer.registerPrompt(
)
mcpServer.registerPrompt(
'code_review',
'party_announcement',
{
title: 'Code Review Template',
description: 'Template for code review requests',
title: 'Party Bus Announcement',
description: 'Generate party-themed announcements for various occasions',
argsSchema: {
language: z.string().describe('Programming language'),
focus: z.string().optional().describe('What to focus on (performance/security/style)'),
event: z.string().describe('Type of event (deployment, release, milestone, etc.)'),
details: z.string().optional().describe('Additional details about the event'),
},
},
({ language, focus }) => ({
({ event, details }) => ({
messages: [
{
role: 'user',
content: {
type: 'text',
text: `Please review the following ${language} code${focus ? ` with a focus on ${focus}` : ''}:`,
text: `Create a party bus announcement for a ${event}${details ? `: ${details}` : ''}`,
},
},
],