yupno-mcp-server 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.
- package/README.md +61 -0
- package/index.js +166 -0
- package/package.json +28 -0
package/README.md
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# Yupno MCP Server
|
|
2
|
+
|
|
3
|
+
MCP server for creating and managing events on [Yupno](https://yupno.io).
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npx yupno-mcp-server
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Configuration
|
|
12
|
+
|
|
13
|
+
Add to your Claude settings:
|
|
14
|
+
|
|
15
|
+
```json
|
|
16
|
+
{
|
|
17
|
+
"mcpServers": {
|
|
18
|
+
"yupno": {
|
|
19
|
+
"command": "npx",
|
|
20
|
+
"args": ["-y", "yupno-mcp-server"]
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Available Tools
|
|
27
|
+
|
|
28
|
+
### create_event
|
|
29
|
+
|
|
30
|
+
Create a new event with optional theming.
|
|
31
|
+
|
|
32
|
+
**Example prompt:** "Create an 80s party event for tomorrow at 7pm with a neon theme"
|
|
33
|
+
|
|
34
|
+
### get_event
|
|
35
|
+
|
|
36
|
+
Get details of an existing event.
|
|
37
|
+
|
|
38
|
+
### update_event
|
|
39
|
+
|
|
40
|
+
Update an event (requires admin token).
|
|
41
|
+
|
|
42
|
+
### delete_event
|
|
43
|
+
|
|
44
|
+
Delete an event (requires admin token).
|
|
45
|
+
|
|
46
|
+
## Theme Options
|
|
47
|
+
|
|
48
|
+
When creating events, you can specify visual themes:
|
|
49
|
+
|
|
50
|
+
- `primaryColor` - Hex color for buttons/accents
|
|
51
|
+
- `accentColor` - Secondary color
|
|
52
|
+
- `backgroundColor` - Page background
|
|
53
|
+
- `textColor` - Text color (for dark backgrounds)
|
|
54
|
+
- `fontFamily` - Google Font name
|
|
55
|
+
- `backgroundUrl` - HTTPS image URL
|
|
56
|
+
- `backgroundOverlay` - Overlay opacity (0-1)
|
|
57
|
+
|
|
58
|
+
### Suggested Fonts
|
|
59
|
+
|
|
60
|
+
Press Start 2P, Monoton, Righteous, Bangers, Lobster, Pacifico,
|
|
61
|
+
Playfair Display, Oswald, Bebas Neue, Space Grotesk
|
package/index.js
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
4
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
|
|
7
|
+
const YUPNO_API = process.env.YUPNO_API_URL || "https://yupno.io";
|
|
8
|
+
|
|
9
|
+
// Create server
|
|
10
|
+
const server = new McpServer({
|
|
11
|
+
name: "yupno",
|
|
12
|
+
version: "1.0.0",
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
// Create event tool
|
|
16
|
+
server.tool(
|
|
17
|
+
"create_event",
|
|
18
|
+
`Create a new event on Yupno. Returns admin URL (for managing) and guest URL (for sharing).
|
|
19
|
+
|
|
20
|
+
DESIGN RULES (follow these for professional results):
|
|
21
|
+
- Title: Keep SHORT (2-4 words). NO emojis in title. Examples: "Game Night", "Sarah's Birthday"
|
|
22
|
+
- Fonts: Use Poppins, Inter, Playfair Display, or Montserrat. AVOID Lobster/Pacifico (wrap badly)
|
|
23
|
+
- Colors: Dark bg (#1a1a2e) needs light text (#ffffff). Light bg (#faf7f2) needs dark text (#2d3436)
|
|
24
|
+
- Description: Brief (2-3 sentences), emojis OK but sparingly`,
|
|
25
|
+
{
|
|
26
|
+
title: z.string().describe("Event title - keep SHORT (2-4 words), NO emojis. Good: 'Game Night', 'Emma's 30th'"),
|
|
27
|
+
eventDate: z.string().describe("Start date/time in ISO 8601 format"),
|
|
28
|
+
endDate: z.string().optional().describe("End date/time in ISO 8601 format"),
|
|
29
|
+
timezone: z.string().optional().describe("IANA timezone (e.g., America/New_York)"),
|
|
30
|
+
location: z.string().optional().describe("Physical address or venue name"),
|
|
31
|
+
description: z.string().optional().describe("Brief description (2-3 sentences). Emojis OK sparingly. Don't repeat date/location."),
|
|
32
|
+
theme: z.object({
|
|
33
|
+
primaryColor: z.string().optional().describe("Hex color for buttons. Should contrast with backgroundColor"),
|
|
34
|
+
accentColor: z.string().optional().describe("Hex color for secondary elements"),
|
|
35
|
+
backgroundColor: z.string().optional().describe("Hex color for page background. Dark (#1a1a2e) or light (#faf7f2)"),
|
|
36
|
+
textColor: z.string().optional().describe("Hex color for text. Use #ffffff on dark bg, #1a1a1a on light bg"),
|
|
37
|
+
fontFamily: z.string().optional().describe("Google Font. Recommended: Poppins, Inter, Playfair Display, Montserrat. AVOID: Lobster, Pacifico"),
|
|
38
|
+
backgroundUrl: z.string().optional().describe("HTTPS URL for background image (use Unsplash)"),
|
|
39
|
+
backgroundOverlay: z.number().min(0).max(1).optional().describe("Dark overlay 0.5-0.7 for readability with background images"),
|
|
40
|
+
}).optional().describe("Visual theme - see design rules above"),
|
|
41
|
+
},
|
|
42
|
+
async (args) => {
|
|
43
|
+
try {
|
|
44
|
+
const res = await fetch(`${YUPNO_API}/api/v1/events`, {
|
|
45
|
+
method: "POST",
|
|
46
|
+
headers: { "Content-Type": "application/json" },
|
|
47
|
+
body: JSON.stringify(args),
|
|
48
|
+
});
|
|
49
|
+
const data = await res.json();
|
|
50
|
+
|
|
51
|
+
if (!res.ok) {
|
|
52
|
+
return { content: [{ type: "text", text: `Error: ${data.error || JSON.stringify(data)}` }] };
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return {
|
|
56
|
+
content: [{
|
|
57
|
+
type: "text",
|
|
58
|
+
text: `Event created successfully!
|
|
59
|
+
|
|
60
|
+
Admin URL (save this - for managing RSVPs): ${data.links.admin}
|
|
61
|
+
Guest URL (share this): ${data.links.guest}
|
|
62
|
+
|
|
63
|
+
Admin Token: ${data.adminToken}
|
|
64
|
+
Event Token: ${data.eventToken}`,
|
|
65
|
+
}],
|
|
66
|
+
};
|
|
67
|
+
} catch (error) {
|
|
68
|
+
return { content: [{ type: "text", text: `Error: ${error.message}` }] };
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
// Get event tool
|
|
74
|
+
server.tool(
|
|
75
|
+
"get_event",
|
|
76
|
+
"Get public details of an event by its event token.",
|
|
77
|
+
{
|
|
78
|
+
eventToken: z.string().describe("The event token from the guest URL"),
|
|
79
|
+
},
|
|
80
|
+
async ({ eventToken }) => {
|
|
81
|
+
try {
|
|
82
|
+
const res = await fetch(`${YUPNO_API}/api/v1/events/${eventToken}`);
|
|
83
|
+
const data = await res.json();
|
|
84
|
+
|
|
85
|
+
if (!res.ok) {
|
|
86
|
+
return { content: [{ type: "text", text: `Error: ${data.error || 'Event not found'}` }] };
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
|
|
90
|
+
} catch (error) {
|
|
91
|
+
return { content: [{ type: "text", text: `Error: ${error.message}` }] };
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
// Update event tool
|
|
97
|
+
server.tool(
|
|
98
|
+
"update_event",
|
|
99
|
+
"Update an existing event. Requires the admin token.",
|
|
100
|
+
{
|
|
101
|
+
adminToken: z.string().describe("The admin token for the event"),
|
|
102
|
+
title: z.string().optional(),
|
|
103
|
+
eventDate: z.string().optional(),
|
|
104
|
+
endDate: z.string().optional(),
|
|
105
|
+
timezone: z.string().optional(),
|
|
106
|
+
location: z.string().optional(),
|
|
107
|
+
description: z.string().optional(),
|
|
108
|
+
theme: z.object({
|
|
109
|
+
primaryColor: z.string().optional(),
|
|
110
|
+
accentColor: z.string().optional(),
|
|
111
|
+
backgroundColor: z.string().optional(),
|
|
112
|
+
textColor: z.string().optional(),
|
|
113
|
+
fontFamily: z.string().optional(),
|
|
114
|
+
backgroundUrl: z.string().optional(),
|
|
115
|
+
backgroundOverlay: z.number().optional(),
|
|
116
|
+
}).optional(),
|
|
117
|
+
},
|
|
118
|
+
async ({ adminToken, ...updateData }) => {
|
|
119
|
+
try {
|
|
120
|
+
const res = await fetch(`${YUPNO_API}/api/v1/events/${adminToken}`, {
|
|
121
|
+
method: "PUT",
|
|
122
|
+
headers: { "Content-Type": "application/json" },
|
|
123
|
+
body: JSON.stringify(updateData),
|
|
124
|
+
});
|
|
125
|
+
const data = await res.json();
|
|
126
|
+
|
|
127
|
+
if (!res.ok) {
|
|
128
|
+
return { content: [{ type: "text", text: `Error: ${data.error || JSON.stringify(data)}` }] };
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return { content: [{ type: "text", text: "Event updated successfully!" }] };
|
|
132
|
+
} catch (error) {
|
|
133
|
+
return { content: [{ type: "text", text: `Error: ${error.message}` }] };
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
);
|
|
137
|
+
|
|
138
|
+
// Delete event tool
|
|
139
|
+
server.tool(
|
|
140
|
+
"delete_event",
|
|
141
|
+
"Delete an event. Requires the admin token. This action cannot be undone.",
|
|
142
|
+
{
|
|
143
|
+
adminToken: z.string().describe("The admin token for the event"),
|
|
144
|
+
},
|
|
145
|
+
async ({ adminToken }) => {
|
|
146
|
+
try {
|
|
147
|
+
const res = await fetch(`${YUPNO_API}/api/v1/events/${adminToken}`, {
|
|
148
|
+
method: "DELETE",
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
if (!res.ok) {
|
|
152
|
+
const data = await res.json();
|
|
153
|
+
return { content: [{ type: "text", text: `Error: ${data.error || 'Failed to delete'}` }] };
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return { content: [{ type: "text", text: "Event deleted successfully." }] };
|
|
157
|
+
} catch (error) {
|
|
158
|
+
return { content: [{ type: "text", text: `Error: ${error.message}` }] };
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
);
|
|
162
|
+
|
|
163
|
+
// Start server with stdio transport
|
|
164
|
+
const transport = new StdioServerTransport();
|
|
165
|
+
await server.connect(transport);
|
|
166
|
+
console.error("Yupno MCP server running");
|
package/package.json
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "yupno-mcp-server",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "MCP server for creating and managing Yupno events with Claude Desktop",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"bin": {
|
|
8
|
+
"yupno-mcp-server": "./index.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"index.js"
|
|
12
|
+
],
|
|
13
|
+
"scripts": {
|
|
14
|
+
"start": "node index.js"
|
|
15
|
+
},
|
|
16
|
+
"keywords": ["mcp", "yupno", "events", "rsvp", "claude", "anthropic", "model-context-protocol"],
|
|
17
|
+
"author": "Yupno",
|
|
18
|
+
"license": "MIT",
|
|
19
|
+
"repository": {
|
|
20
|
+
"type": "git",
|
|
21
|
+
"url": "https://github.com/yupno/yupno"
|
|
22
|
+
},
|
|
23
|
+
"homepage": "https://yupno.io/docs.html",
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"@modelcontextprotocol/sdk": "^1.12.0",
|
|
26
|
+
"zod": "^3.24.0"
|
|
27
|
+
}
|
|
28
|
+
}
|