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:
parent
e0743c35e4
commit
6a42f9dc93
1 changed files with 124 additions and 84 deletions
|
|
@ -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}` : ''}`,
|
||||
},
|
||||
},
|
||||
],
|
||||
|
|
|
|||
Loading…
Reference in a new issue