Skip to content

Commit a70745a

Browse files
committed
feat: add MCP tools section for organizers in the dashboard with setup link and descriptive content
1 parent d7e7d66 commit a70745a

2 files changed

Lines changed: 299 additions & 0 deletions

File tree

Lines changed: 265 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,265 @@
1+
'use client'
2+
3+
import { ArrowLeft, KeyRound, Sparkles, Terminal } from 'lucide-react'
4+
import Link from 'next/link'
5+
import { useEffect, useState } from 'react'
6+
import { Button } from '@/components/ui/button'
7+
import {
8+
Card,
9+
CardContent,
10+
CardDescription,
11+
CardHeader,
12+
CardTitle
13+
} from '@/components/ui/card'
14+
import { SidebarTrigger } from '@/components/ui/sidebar'
15+
16+
function McpUrlHint() {
17+
const [origin, setOrigin] = useState<string | null>(null)
18+
useEffect(() => {
19+
setOrigin(window.location.origin)
20+
}, [])
21+
const url = origin ? `${origin}/mcp` : 'https://cl.neuland.ing/mcp'
22+
return (
23+
<code className="text-xs sm:text-sm bg-muted px-2 py-1 rounded break-all">
24+
{url}
25+
</code>
26+
)
27+
}
28+
29+
export default function McpSetupPage() {
30+
return (
31+
<div className="flex flex-col min-h-screen">
32+
<header className="sticky top-0 z-50 flex h-16 shrink-0 items-center gap-2 border-b bg-background/95 backdrop-blur-sm px-4">
33+
<SidebarTrigger className="-ml-1" />
34+
<div className="flex items-center gap-2 min-w-0">
35+
<h1 className="text-lg font-semibold truncate">MCP Setup</h1>
36+
</div>
37+
</header>
38+
39+
<div className="flex-1 space-y-8 p-4 md:p-8 pt-6 mb-12 max-w-3xl">
40+
<Link
41+
href="/"
42+
className="inline-flex items-center gap-2 text-sm text-muted-foreground hover:text-foreground transition-colors"
43+
>
44+
<ArrowLeft className="size-4" />
45+
Dashboard
46+
</Link>
47+
48+
<div className="space-y-2">
49+
<div className="flex items-center gap-2">
50+
<Sparkles className="size-8 text-violet-500 shrink-0" />
51+
<h2 className="text-3xl font-bold tracking-tight">
52+
Events &amp; Verein per KI verwalten
53+
</h2>
54+
</div>
55+
<p className="text-muted-foreground text-pretty">
56+
Über das{' '}
57+
<a
58+
href="https://modelcontextprotocol.io"
59+
target="_blank"
60+
rel="noopener noreferrer"
61+
className="underline underline-offset-4 hover:text-foreground"
62+
>
63+
Model Context Protocol (MCP)
64+
</a>{' '}
65+
kannst du in unterstützten KI-Clients (z.&nbsp;B. Cursor oder
66+
Claude) Tools nutzen: Events anlegen und bearbeiten, Vereinsprofil
67+
pflegen, Newsletter-Daten abrufen und mehr. Verbindung und
68+
Authentifizierung laufen über HTTPS und einen persönlichen
69+
API-Token.
70+
</p>
71+
</div>
72+
73+
<Card>
74+
<CardHeader>
75+
<CardTitle className="flex items-center gap-2 text-xl">
76+
<KeyRound className="size-5" />
77+
1. API-Token erzeugen
78+
</CardTitle>
79+
<CardDescription>
80+
Nur Vereinskonten (Organizer) können MCP mit diesen Tokens nutzen.
81+
</CardDescription>
82+
</CardHeader>
83+
<CardContent className="space-y-4 text-sm text-pretty">
84+
<ol className="list-decimal pl-5 space-y-2">
85+
<li>
86+
Öffne{' '}
87+
<Link
88+
href="/settings"
89+
className="font-medium text-primary underline underline-offset-4"
90+
>
91+
Einstellungen
92+
</Link>
93+
.
94+
</li>
95+
<li>
96+
Unter <strong>API-Token</strong> auf{' '}
97+
<strong>Neues Token</strong> klicken, optional eine Bezeichnung
98+
eintragen (z.&nbsp;B. &quot;Cursor Laptop&quot;).
99+
</li>
100+
<li>
101+
Den angezeigten Klartext{' '}
102+
<strong>sofort kopieren und sicher aufbewahren</strong> — er
103+
wird nur einmal angezeigt. Gültigkeit: 30&nbsp;Tage ab
104+
Erstellung; widerrufen kannst du Token in derselben Ansicht.
105+
</li>
106+
</ol>
107+
<p className="text-muted-foreground">
108+
Bei jedem MCP-Aufruf sendet der Client den Header{' '}
109+
<code className="text-xs bg-muted px-1.5 py-0.5 rounded">
110+
Authorization: Bearer DEIN_TOKEN
111+
</code>
112+
.
113+
</p>
114+
</CardContent>
115+
</Card>
116+
117+
<Card>
118+
<CardHeader>
119+
<CardTitle className="flex items-center gap-2 text-xl">
120+
<Terminal className="size-5" />
121+
2. MCP-Endpunkt
122+
</CardTitle>
123+
<CardDescription>
124+
JSON-RPC über HTTPS POST — typisch dieselbe Basis-URL wie das
125+
Dashboard, Pfad{' '}
126+
<code className="text-xs bg-muted px-1 rounded">/mcp</code>.
127+
</CardDescription>
128+
</CardHeader>
129+
<CardContent className="space-y-3 text-sm">
130+
<p className="text-muted-foreground">
131+
Aktuelle Basis-URL (aus diesem Browser):
132+
</p>
133+
<div className="rounded-lg border bg-muted/30 p-3">
134+
<McpUrlHint />
135+
</div>
136+
<p className="text-muted-foreground">
137+
Öffentlich z.&nbsp;B.{' '}
138+
<code className="text-xs bg-muted px-1.5 py-0.5 rounded break-all">
139+
https://cl.neuland.ing/mcp
140+
</code>{' '}
141+
oder{' '}
142+
<code className="text-xs bg-muted px-1.5 py-0.5 rounded break-all">
143+
https://cl.neuland-ingolstadt.de/mcp
144+
</code>
145+
. Reines lokales Backend ohne HTTPS-Proxy:{' '}
146+
<code className="text-xs bg-muted px-1.5 py-0.5 rounded">
147+
http://localhost:8080/mcp
148+
</code>
149+
.
150+
</p>
151+
</CardContent>
152+
</Card>
153+
154+
<Card>
155+
<CardHeader>
156+
<CardTitle className="text-xl">3. Cursor</CardTitle>
157+
<CardDescription>
158+
Projektdatei{' '}
159+
<code className="text-xs bg-muted px-1 rounded">
160+
.cursor/mcp.json
161+
</code>{' '}
162+
oder MCP-Eintrag in den Cursor Settings.
163+
</CardDescription>
164+
</CardHeader>
165+
<CardContent className="space-y-4 text-sm text-pretty">
166+
<ol className="list-decimal pl-5 space-y-2">
167+
<li>
168+
<code className="text-xs bg-muted px-1.5 py-0.5 rounded">
169+
url
170+
</code>{' '}
171+
auf deinen MCP-Endpunkt setzen,
172+
<code className="text-xs bg-muted px-1.5 py-0.5 rounded mx-1">
173+
headers.Authorization
174+
</code>
175+
auf{' '}
176+
<code className="text-xs bg-muted px-1.5 py-0.5 rounded">
177+
Bearer …
178+
</code>{' '}
179+
mit dem kopierten Token.
180+
</li>
181+
<li>
182+
<code className="text-xs bg-muted px-1.5 py-0.5 rounded">
183+
Accept
184+
</code>{' '}
185+
und{' '}
186+
<code className="text-xs bg-muted px-1.5 py-0.5 rounded">
187+
MCP-Protocol-Version
188+
</code>{' '}
189+
wie im Beispiel — damit ist das Verhalten dasselbe wie bei einem
190+
Standard-MCP-over-HTTP-Client.
191+
</li>
192+
<li>Cursor neu laden bzw. MCP-Server aktivieren.</li>
193+
</ol>
194+
<p className="text-muted-foreground">
195+
Beispiel (Server-Name und URL anpassen, Token einsetzen):
196+
</p>
197+
<pre className="text-xs bg-muted p-4 rounded-lg overflow-x-auto border leading-relaxed">
198+
{`{
199+
"mcpServers": {
200+
"campus-life-events-local": {
201+
"url": "https://cl.neuland.ing/mcp",
202+
"headers": {
203+
"Authorization": "Bearer DEIN_API_TOKEN",
204+
"Accept": "application/json, text/event-stream",
205+
"MCP-Protocol-Version": "2025-03-26"
206+
}
207+
}
208+
}
209+
}`}
210+
</pre>
211+
</CardContent>
212+
</Card>
213+
214+
<Card>
215+
<CardHeader>
216+
<CardTitle className="text-xl">
217+
4. Claude &amp; andere Clients
218+
</CardTitle>
219+
<CardDescription>
220+
Je nach Produkt (Claude Desktop, Claude Code, API) unterscheidet
221+
sich die Konfiguration.
222+
</CardDescription>
223+
</CardHeader>
224+
<CardContent className="space-y-3 text-sm text-pretty text-muted-foreground">
225+
<p>
226+
Wenn dein Setup{' '}
227+
<strong className="text-foreground font-medium">
228+
HTTP-basierte MCP-Server
229+
</strong>{' '}
230+
unterstützt, dieselbe{' '}
231+
<code className="text-xs bg-muted px-1.5 py-0.5 rounded">
232+
url
233+
</code>{' '}
234+
und dieselben{' '}
235+
<code className="text-xs bg-muted px-1.5 py-0.5 rounded">
236+
headers
237+
</code>{' '}
238+
wie oben verwenden.
239+
</p>
240+
<p>
241+
Token nicht committen;{' '}
242+
<code className="text-xs bg-muted px-1.5 py-0.5 rounded">
243+
.cursor/mcp.json
244+
</code>{' '}
245+
gehört in die{' '}
246+
<code className="text-xs bg-muted px-1.5 py-0.5 rounded">
247+
.gitignore
248+
</code>
249+
, wenn sie Secrets enthält.
250+
</p>
251+
</CardContent>
252+
</Card>
253+
254+
<div className="flex flex-wrap gap-3">
255+
<Button asChild>
256+
<Link href="/settings">API-Token</Link>
257+
</Button>
258+
<Button variant="outline" asChild>
259+
<Link href="/">Dashboard</Link>
260+
</Button>
261+
</div>
262+
</div>
263+
</div>
264+
)
265+
}

frontend/app/(app)/page.tsx

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
Calendar,
1010
Clock,
1111
Plus,
12+
Sparkles,
1213
TrendingUp,
1314
Users
1415
} from 'lucide-react'
@@ -168,6 +169,39 @@ export default function Dashboard() {
168169
</div>
169170
)}
170171

172+
{user?.account_type === 'ORGANIZER' && (
173+
<div className="relative overflow-hidden rounded-2xl border border-violet-200/70 bg-linear-to-br from-violet-500/7 via-background to-cyan-500/5 p-5 shadow-sm dark:border-violet-800/45 dark:from-violet-400/9 dark:to-cyan-500/4">
174+
<div
175+
className="pointer-events-none absolute -right-10 -top-10 size-36 rounded-full bg-violet-500/12 blur-2xl dark:bg-violet-400/15"
176+
aria-hidden
177+
/>
178+
<div className="relative flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">
179+
<div className="flex gap-3 min-w-0">
180+
<div className="flex size-10 shrink-0 items-center justify-center rounded-xl bg-violet-500/15 text-violet-600 dark:text-violet-400">
181+
<Sparkles className="size-5" aria-hidden />
182+
</div>
183+
<div className="min-w-0 space-y-1">
184+
<p className="text-sm font-semibold tracking-tight text-foreground">
185+
KI-Tools (MCP) für Events &amp; Vereinsprofil
186+
</p>
187+
<p className="text-sm text-muted-foreground text-pretty max-w-prose">
188+
Nutze MCP in Cursor, Claude oder anderen Clients: Events
189+
verwalten, Vereinsinfos pflegen und mehr — API-Token und
190+
Kurzsetup über einen Klick.
191+
</p>
192+
</div>
193+
</div>
194+
<Button
195+
asChild
196+
variant="secondary"
197+
className="shrink-0 border-violet-200/90 bg-background/90 shadow-sm hover:bg-background dark:border-violet-800/55"
198+
>
199+
<Link href="/mcp-setup">MCP Setup</Link>
200+
</Button>
201+
</div>
202+
</div>
203+
)}
204+
171205
{/* Quick Actions */}
172206
<div className="space-y-3">
173207
<h3 className="text-lg font-semibold">Schnellaktionen</h3>

0 commit comments

Comments
 (0)