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.
Files changed (3) hide show
  1. package/README.md +61 -0
  2. package/index.js +166 -0
  3. 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
+ }