zudoku 0.82.2 → 0.82.4
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/dist/cli/cli.js +283 -225
- package/dist/cli/worker.js +23 -0
- package/dist/declarations/app/wrapProtectedRoutes.d.ts +5 -0
- package/dist/declarations/config/config.d.ts +3 -0
- package/dist/declarations/config/plugin-versions.d.ts +5 -0
- package/dist/declarations/config/validators/ZudokuConfig.d.ts +38 -0
- package/dist/declarations/lib/authentication/providers/entra.d.ts +13 -0
- package/dist/declarations/lib/authentication/providers/openid.d.ts +4 -1
- package/dist/declarations/lib/authentication/providers/util.d.ts +4 -0
- package/dist/declarations/lib/plugins/openapi/McpClientLogos.d.ts +4 -0
- package/dist/declarations/lib/plugins/openapi/mcp-configs.d.ts +3 -0
- package/dist/declarations/vite/package-root.d.ts +1 -0
- package/dist/flat-config.d.ts +17 -0
- package/docs/components/landing-page.mdx +1 -1
- package/docs/configuration/authentication-azure-ad.md +17 -15
- package/docs/configuration/authentication.md +22 -2
- package/docs/guides/mcp-servers.md +26 -0
- package/package.json +21 -17
- package/src/app/entry.server.tsx +9 -5
- package/src/app/wrapProtectedRoutes.ts +25 -0
- package/src/config/config.ts +4 -0
- package/src/config/loader.ts +15 -0
- package/src/config/plugin-versions.ts +38 -0
- package/src/config/validators/ZudokuConfig.ts +19 -0
- package/src/lib/auth/issuer.ts +7 -1
- package/src/lib/authentication/providers/entra.tsx +97 -0
- package/src/lib/authentication/providers/openid.tsx +29 -13
- package/src/lib/authentication/providers/util.ts +7 -0
- package/src/lib/components/navigation/NavigationCategory.tsx +3 -2
- package/src/lib/components/navigation/StackRows.tsx +1 -1
- package/src/lib/plugins/openapi/MCPEndpoint.tsx +347 -228
- package/src/lib/plugins/openapi/McpClientLogos.tsx +72 -0
- package/src/lib/plugins/openapi/mcp-configs.ts +55 -0
- package/src/vite/api/SchemaManager.ts +11 -25
- package/src/vite/plugin-mdx.ts +3 -0
- package/src/vite/prerender/prerender.ts +28 -3
- package/src/vite/prerender/utils.ts +33 -0
- package/src/vite/prerender/worker.ts +8 -1
- package/src/zuplo/enrich-with-zuplo-mcp.ts +14 -2
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import {
|
|
2
|
+
ArrowUpRightIcon,
|
|
3
|
+
CheckIcon,
|
|
4
|
+
CopyIcon,
|
|
5
|
+
ExternalLinkIcon,
|
|
6
|
+
} from "lucide-react";
|
|
7
|
+
import { type ReactNode, useState } from "react";
|
|
3
8
|
import { InlineCode } from "../../components/InlineCode.js";
|
|
4
9
|
import { Typography } from "../../components/Typography.js";
|
|
5
10
|
import { Button } from "../../ui/Button.js";
|
|
6
11
|
import { Callout } from "../../ui/Callout.js";
|
|
7
12
|
import { Card } from "../../ui/Card.js";
|
|
8
|
-
import {
|
|
9
|
-
Select,
|
|
10
|
-
SelectContent,
|
|
11
|
-
SelectItem,
|
|
12
|
-
SelectTrigger,
|
|
13
|
-
SelectValue,
|
|
14
|
-
} from "../../ui/Select.js";
|
|
15
13
|
import { SyntaxHighlight } from "../../ui/SyntaxHighlight.js";
|
|
16
|
-
import {
|
|
14
|
+
import { ToggleGroup, ToggleGroupItem } from "../../ui/ToggleGroup.js";
|
|
15
|
+
import { cn } from "../../util/cn.js";
|
|
17
16
|
import {
|
|
17
|
+
CLAUDE_CONNECTORS_URL,
|
|
18
18
|
type McpApp,
|
|
19
19
|
type McpServerData,
|
|
20
20
|
getAuthHeader,
|
|
@@ -23,30 +23,62 @@ import {
|
|
|
23
23
|
getCodexCliCommand,
|
|
24
24
|
getCodexConfig,
|
|
25
25
|
getCursorConfig,
|
|
26
|
+
getCursorDeepLink,
|
|
26
27
|
getGenericConfig,
|
|
27
28
|
getMcpServerName,
|
|
28
29
|
getMcpUrl,
|
|
29
30
|
getVisibleApps,
|
|
30
31
|
getVscodeConfig,
|
|
32
|
+
getVscodeDeepLink,
|
|
31
33
|
} from "./mcp-configs.js";
|
|
34
|
+
import { McpClientLogo } from "./McpClientLogos.js";
|
|
32
35
|
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
showLabel,
|
|
36
|
+
const DocsLink = ({
|
|
37
|
+
href,
|
|
36
38
|
children,
|
|
37
39
|
}: {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
40
|
+
href: string;
|
|
41
|
+
children: ReactNode;
|
|
42
|
+
}) => (
|
|
43
|
+
<a
|
|
44
|
+
href={href}
|
|
45
|
+
target="_blank"
|
|
46
|
+
rel="noopener noreferrer"
|
|
47
|
+
className="inline-flex items-center gap-1 text-sm text-primary hover:underline"
|
|
48
|
+
>
|
|
49
|
+
{children}
|
|
50
|
+
<ExternalLinkIcon className="h-3 w-3" aria-hidden="true" />
|
|
51
|
+
</a>
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
// Wraps a list of <li> steps in the shared `.stepper` visual (numbered bullets
|
|
55
|
+
// with a connecting line, see main.css).
|
|
56
|
+
const Steps = ({ children }: { children: ReactNode }) => (
|
|
57
|
+
<div className="stepper">
|
|
58
|
+
<ol>{children}</ol>
|
|
59
|
+
</div>
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
// One-click deep link rendered as a primary button. Protocol-handler links
|
|
63
|
+
// (cursor://, vscode:) open in place; external https links open a new tab.
|
|
64
|
+
const InstallButton = ({
|
|
65
|
+
href,
|
|
66
|
+
external,
|
|
67
|
+
children,
|
|
68
|
+
}: {
|
|
69
|
+
href: string;
|
|
70
|
+
external?: boolean;
|
|
71
|
+
children: ReactNode;
|
|
72
|
+
}) => (
|
|
73
|
+
<Button asChild size="sm" className="not-prose gap-1.5">
|
|
74
|
+
<a
|
|
75
|
+
href={href}
|
|
76
|
+
{...(external ? { target: "_blank", rel: "noopener noreferrer" } : {})}
|
|
77
|
+
>
|
|
45
78
|
{children}
|
|
46
|
-
</
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
);
|
|
79
|
+
</a>
|
|
80
|
+
</Button>
|
|
81
|
+
);
|
|
50
82
|
|
|
51
83
|
export const MCPEndpoint = ({
|
|
52
84
|
serverUrl,
|
|
@@ -72,9 +104,29 @@ export const MCPEndpoint = ({
|
|
|
72
104
|
const codexConfig = getCodexConfig(name, mcpUrl, auth);
|
|
73
105
|
const genericConfig = getGenericConfig(name, mcpUrl, auth);
|
|
74
106
|
const vscodeConfig = getVscodeConfig(name, mcpUrl, auth);
|
|
107
|
+
const cursorDeepLink = getCursorDeepLink(name, mcpUrl, auth);
|
|
108
|
+
const vscodeDeepLink = getVscodeDeepLink(name, mcpUrl, auth);
|
|
109
|
+
|
|
110
|
+
const [selectedAppId, setSelectedAppId] = useState(
|
|
111
|
+
visibleApps[0]?.id ?? "generic",
|
|
112
|
+
);
|
|
113
|
+
const selectedApp =
|
|
114
|
+
visibleApps.find((app) => app.id === selectedAppId) ?? visibleApps[0];
|
|
115
|
+
|
|
116
|
+
const [selectedSubAppId, setSelectedSubAppId] = useState<string | undefined>(
|
|
117
|
+
selectedApp?.subApps[0]?.id,
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
const selectApp = (id: string) => {
|
|
121
|
+
setSelectedAppId(id);
|
|
122
|
+
const next = visibleApps.find((app) => app.id === id);
|
|
123
|
+
setSelectedSubAppId(next?.subApps[0]?.id);
|
|
124
|
+
};
|
|
75
125
|
|
|
76
|
-
|
|
77
|
-
const
|
|
126
|
+
// Keep the active sub-app consistent with the selected app.
|
|
127
|
+
const activeSubApp =
|
|
128
|
+
selectedApp?.subApps.find((sub) => sub.id === selectedSubAppId) ??
|
|
129
|
+
selectedApp?.subApps[0];
|
|
78
130
|
|
|
79
131
|
const handleCopy = () => {
|
|
80
132
|
void navigator.clipboard.writeText(mcpUrl).then(() => {
|
|
@@ -83,55 +135,75 @@ export const MCPEndpoint = ({
|
|
|
83
135
|
});
|
|
84
136
|
};
|
|
85
137
|
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
const renderAppContent = (app: McpApp) => {
|
|
90
|
-
const multiSub = app.subApps.length > 1;
|
|
138
|
+
const renderSetup = (app: McpApp) => {
|
|
139
|
+
const subAppId = activeSubApp?.id ?? app.subApps[0]?.id;
|
|
91
140
|
|
|
92
141
|
switch (app.id) {
|
|
93
142
|
case "claude":
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
<
|
|
98
|
-
<
|
|
99
|
-
<
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
143
|
+
if (subAppId === "claude-code") {
|
|
144
|
+
return (
|
|
145
|
+
<>
|
|
146
|
+
<Steps>
|
|
147
|
+
<li>
|
|
148
|
+
<p>Add {name} to Claude Code by running:</p>
|
|
149
|
+
<SyntaxHighlight
|
|
150
|
+
showLanguageIndicator
|
|
151
|
+
title="Terminal"
|
|
152
|
+
language="bash"
|
|
153
|
+
code={claudeCodeCommand}
|
|
154
|
+
/>
|
|
155
|
+
</li>
|
|
156
|
+
{auth && (
|
|
103
157
|
<li>
|
|
104
|
-
|
|
105
|
-
|
|
158
|
+
<p>
|
|
159
|
+
Replace <InlineCode>{auth.placeholder}</InlineCode> with
|
|
160
|
+
your API key.
|
|
161
|
+
</p>
|
|
106
162
|
</li>
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
163
|
+
)}
|
|
164
|
+
<li>
|
|
165
|
+
<p>
|
|
166
|
+
Restart Claude Code — the {name} tools are now available.
|
|
167
|
+
</p>
|
|
168
|
+
</li>
|
|
169
|
+
</Steps>
|
|
170
|
+
<DocsLink href="https://docs.anthropic.com/en/docs/claude-code/mcp">
|
|
171
|
+
View official docs
|
|
172
|
+
</DocsLink>
|
|
173
|
+
</>
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
return (
|
|
177
|
+
<>
|
|
178
|
+
<Steps>
|
|
179
|
+
<li>
|
|
180
|
+
<p>
|
|
181
|
+
<strong>Copy the {name} URL.</strong> Use the copy button
|
|
182
|
+
above — you'll need it in the next step.
|
|
124
183
|
</p>
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
184
|
+
</li>
|
|
185
|
+
<li>
|
|
186
|
+
<p>
|
|
187
|
+
<strong>Open Settings → Connectors.</strong> Add a custom
|
|
188
|
+
connector, name it {name}, and paste the URL.
|
|
189
|
+
</p>
|
|
190
|
+
<InstallButton href={CLAUDE_CONNECTORS_URL} external>
|
|
191
|
+
Open connector settings
|
|
192
|
+
<ArrowUpRightIcon className="size-3.5" aria-hidden="true" />
|
|
193
|
+
</InstallButton>
|
|
194
|
+
</li>
|
|
195
|
+
<li>
|
|
196
|
+
<p>
|
|
197
|
+
<strong>Connect and sign in.</strong> Click{" "}
|
|
198
|
+
<strong>Add → Connect</strong> and sign in — you're all set,
|
|
199
|
+
and the {name} tools appear in your conversations.
|
|
200
|
+
</p>
|
|
201
|
+
</li>
|
|
202
|
+
</Steps>
|
|
203
|
+
<DocsLink href="https://modelcontextprotocol.io/quickstart/user">
|
|
204
|
+
View official docs
|
|
205
|
+
</DocsLink>
|
|
206
|
+
</>
|
|
135
207
|
);
|
|
136
208
|
|
|
137
209
|
case "chatgpt":
|
|
@@ -140,118 +212,124 @@ export const MCPEndpoint = ({
|
|
|
140
212
|
<Callout type="note" title="Requirements">
|
|
141
213
|
ChatGPT Plus, Team, Enterprise, or Edu subscription.
|
|
142
214
|
</Callout>
|
|
143
|
-
<
|
|
215
|
+
<Steps>
|
|
144
216
|
<li>
|
|
145
|
-
|
|
146
|
-
|
|
217
|
+
<p>
|
|
218
|
+
<strong>Turn on Developer Mode.</strong> Go to{" "}
|
|
219
|
+
<strong>Settings → Apps → Advanced settings</strong>, enable{" "}
|
|
220
|
+
<strong>Developer Mode</strong>, then click{" "}
|
|
221
|
+
<strong>Create app</strong>.
|
|
222
|
+
</p>
|
|
147
223
|
</li>
|
|
148
224
|
<li>
|
|
149
|
-
|
|
225
|
+
<p>
|
|
226
|
+
<strong>Create the app.</strong> Name it {name} and paste the
|
|
227
|
+
MCP server URL above as the connection.
|
|
228
|
+
</p>
|
|
150
229
|
</li>
|
|
151
230
|
<li>
|
|
152
|
-
|
|
153
|
-
|
|
231
|
+
<p>
|
|
232
|
+
<strong>Connect and sign in.</strong> Click{" "}
|
|
233
|
+
<strong>Create</strong> and sign in — you're all set, and the
|
|
234
|
+
app is available in your conversations.
|
|
235
|
+
</p>
|
|
154
236
|
</li>
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
<a
|
|
158
|
-
href="https://developers.openai.com/apps-sdk/deploy/connect-chatgpt#create-a-connector"
|
|
159
|
-
target="_blank"
|
|
160
|
-
rel="noopener noreferrer"
|
|
161
|
-
className="inline-flex items-center gap-1 text-sm text-primary hover:underline"
|
|
162
|
-
>
|
|
237
|
+
</Steps>
|
|
238
|
+
<DocsLink href="https://developers.openai.com/apps-sdk/deploy/connect-chatgpt#create-a-connector">
|
|
163
239
|
View official docs
|
|
164
|
-
|
|
165
|
-
</a>
|
|
240
|
+
</DocsLink>
|
|
166
241
|
</>
|
|
167
242
|
);
|
|
168
243
|
|
|
169
244
|
case "codex":
|
|
245
|
+
if (subAppId === "codex-cli") {
|
|
246
|
+
return (
|
|
247
|
+
<>
|
|
248
|
+
<Steps>
|
|
249
|
+
<li>
|
|
250
|
+
<p>Add {name} to Codex CLI by running:</p>
|
|
251
|
+
<SyntaxHighlight
|
|
252
|
+
showLanguageIndicator
|
|
253
|
+
title="Terminal"
|
|
254
|
+
language="bash"
|
|
255
|
+
code={codexCliCommand}
|
|
256
|
+
/>
|
|
257
|
+
</li>
|
|
258
|
+
<li>
|
|
259
|
+
<p>
|
|
260
|
+
Or add it to <InlineCode>~/.codex/config.json</InlineCode>:
|
|
261
|
+
</p>
|
|
262
|
+
<SyntaxHighlight
|
|
263
|
+
showLanguageIndicator
|
|
264
|
+
title="config.json"
|
|
265
|
+
language="json"
|
|
266
|
+
code={codexConfig}
|
|
267
|
+
/>
|
|
268
|
+
</li>
|
|
269
|
+
</Steps>
|
|
270
|
+
<DocsLink href="https://openai.com/index/introducing-codex/">
|
|
271
|
+
View official docs
|
|
272
|
+
</DocsLink>
|
|
273
|
+
</>
|
|
274
|
+
);
|
|
275
|
+
}
|
|
170
276
|
return (
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
<
|
|
174
|
-
<
|
|
175
|
-
<
|
|
176
|
-
Open Codex and go to <strong>Settings</strong> →{" "}
|
|
177
|
-
<strong>MCP Servers</strong>
|
|
178
|
-
</li>
|
|
179
|
-
<li>Add a new server and paste the MCP URL</li>
|
|
180
|
-
<li>
|
|
181
|
-
Save and the server will be available in your sessions
|
|
182
|
-
</li>
|
|
183
|
-
</ol>
|
|
184
|
-
<a
|
|
185
|
-
href="https://openai.com/index/introducing-codex/"
|
|
186
|
-
target="_blank"
|
|
187
|
-
rel="noopener noreferrer"
|
|
188
|
-
className="inline-flex items-center gap-1 text-sm text-primary hover:underline"
|
|
189
|
-
>
|
|
190
|
-
View official docs
|
|
191
|
-
<ExternalLinkIcon className="h-3 w-3" />
|
|
192
|
-
</a>
|
|
193
|
-
</SubAppSection>
|
|
194
|
-
)}
|
|
195
|
-
{hasSubApp(app, "codex-cli") && (
|
|
196
|
-
<SubAppSection label="Codex CLI" showLabel={multiSub}>
|
|
197
|
-
<p className="text-xs text-muted-foreground">
|
|
198
|
-
Add it to Codex CLI by running:
|
|
199
|
-
</p>
|
|
200
|
-
<SyntaxHighlight
|
|
201
|
-
showLanguageIndicator
|
|
202
|
-
title="Terminal"
|
|
203
|
-
language="bash"
|
|
204
|
-
code={codexCliCommand}
|
|
205
|
-
className="mt-2"
|
|
206
|
-
/>
|
|
207
|
-
<p className="text-xs text-muted-foreground">
|
|
208
|
-
Or add to <InlineCode>~/.codex/config.json</InlineCode>:
|
|
277
|
+
<>
|
|
278
|
+
<Steps>
|
|
279
|
+
<li>
|
|
280
|
+
<p>
|
|
281
|
+
Open Codex and go to <strong>Settings → MCP Servers</strong>.
|
|
209
282
|
</p>
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
283
|
+
</li>
|
|
284
|
+
<li>
|
|
285
|
+
<p>Add a new server and paste the MCP server URL above.</p>
|
|
286
|
+
</li>
|
|
287
|
+
<li>
|
|
288
|
+
<p>Save — the server is available in your sessions.</p>
|
|
289
|
+
</li>
|
|
290
|
+
</Steps>
|
|
291
|
+
<DocsLink href="https://openai.com/index/introducing-codex/">
|
|
292
|
+
View official docs
|
|
293
|
+
</DocsLink>
|
|
294
|
+
</>
|
|
220
295
|
);
|
|
221
296
|
|
|
222
297
|
case "cursor":
|
|
223
298
|
return (
|
|
224
299
|
<>
|
|
225
|
-
|
|
300
|
+
{!auth && (
|
|
301
|
+
<div className="not-prose space-y-2">
|
|
302
|
+
<InstallButton href={cursorDeepLink}>
|
|
303
|
+
<McpClientLogo appId="cursor" className="size-3.5" />
|
|
304
|
+
Add to Cursor
|
|
305
|
+
</InstallButton>
|
|
306
|
+
<p className="text-xs text-muted-foreground">
|
|
307
|
+
Opens Cursor and prompts to install. Or configure it manually:
|
|
308
|
+
</p>
|
|
309
|
+
</div>
|
|
310
|
+
)}
|
|
311
|
+
<Steps>
|
|
226
312
|
<li>
|
|
227
|
-
<
|
|
228
|
-
Go to
|
|
229
|
-
<strong>Tools & MCPs</strong
|
|
230
|
-
<
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
<span> (global) or </span>
|
|
234
|
-
<InlineCode>.cursor/mcp.json</InlineCode>
|
|
235
|
-
<span> (project)</span>
|
|
313
|
+
<p>
|
|
314
|
+
Go to{" "}
|
|
315
|
+
<strong>Settings → Tools & MCPs → New MCP Server</strong>, or
|
|
316
|
+
edit <InlineCode>~/.cursor/mcp.json</InlineCode> (global) /{" "}
|
|
317
|
+
<InlineCode>.cursor/mcp.json</InlineCode> (project):
|
|
318
|
+
</p>
|
|
236
319
|
<SyntaxHighlight
|
|
237
320
|
showLanguageIndicator
|
|
238
321
|
title="mcp.json"
|
|
239
322
|
language="json"
|
|
240
323
|
code={cursorConfig}
|
|
241
|
-
className="mt-2"
|
|
242
324
|
/>
|
|
243
325
|
</li>
|
|
244
|
-
<li>
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
rel="noopener noreferrer"
|
|
250
|
-
className="inline-flex items-center gap-1 text-sm text-primary hover:underline"
|
|
251
|
-
>
|
|
326
|
+
<li>
|
|
327
|
+
<p>Restart Cursor to apply the configuration.</p>
|
|
328
|
+
</li>
|
|
329
|
+
</Steps>
|
|
330
|
+
<DocsLink href="https://cursor.com/docs/context/mcp">
|
|
252
331
|
View official docs
|
|
253
|
-
|
|
254
|
-
</a>
|
|
332
|
+
</DocsLink>
|
|
255
333
|
</>
|
|
256
334
|
);
|
|
257
335
|
|
|
@@ -259,35 +337,46 @@ export const MCPEndpoint = ({
|
|
|
259
337
|
return (
|
|
260
338
|
<>
|
|
261
339
|
<Callout type="note" title="Requirements">
|
|
262
|
-
VS Code with GitHub Copilot extension
|
|
340
|
+
VS Code with the GitHub Copilot extension.
|
|
263
341
|
</Callout>
|
|
264
|
-
|
|
342
|
+
{!auth && (
|
|
343
|
+
<div className="not-prose space-y-2">
|
|
344
|
+
<InstallButton href={vscodeDeepLink}>
|
|
345
|
+
<McpClientLogo appId="vscode" className="size-3.5" />
|
|
346
|
+
Install in VS Code
|
|
347
|
+
</InstallButton>
|
|
348
|
+
<p className="text-xs text-muted-foreground">
|
|
349
|
+
Opens VS Code and prompts to install. Or configure it
|
|
350
|
+
manually:
|
|
351
|
+
</p>
|
|
352
|
+
</div>
|
|
353
|
+
)}
|
|
354
|
+
<Steps>
|
|
265
355
|
<li>
|
|
266
|
-
<
|
|
267
|
-
|
|
268
|
-
|
|
356
|
+
<p>
|
|
357
|
+
Create <InlineCode>.vscode/mcp.json</InlineCode> in your
|
|
358
|
+
workspace (or a user-level mcp.json):
|
|
359
|
+
</p>
|
|
269
360
|
<SyntaxHighlight
|
|
270
361
|
showLanguageIndicator
|
|
271
362
|
title="mcp.json"
|
|
272
363
|
language="json"
|
|
273
364
|
code={vscodeConfig}
|
|
274
|
-
className="mt-2"
|
|
275
365
|
/>
|
|
276
366
|
</li>
|
|
277
|
-
<li>Restart VS Code to apply the configuration</li>
|
|
278
367
|
<li>
|
|
279
|
-
|
|
368
|
+
<p>Restart VS Code to apply the configuration.</p>
|
|
280
369
|
</li>
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
>
|
|
370
|
+
<li>
|
|
371
|
+
<p>
|
|
372
|
+
Use the MCP tools in GitHub Copilot Chat by selecting Agent
|
|
373
|
+
mode.
|
|
374
|
+
</p>
|
|
375
|
+
</li>
|
|
376
|
+
</Steps>
|
|
377
|
+
<DocsLink href="https://code.visualstudio.com/docs/copilot/chat/mcp-servers">
|
|
288
378
|
View official docs
|
|
289
|
-
|
|
290
|
-
</a>
|
|
379
|
+
</DocsLink>
|
|
291
380
|
</>
|
|
292
381
|
);
|
|
293
382
|
|
|
@@ -295,30 +384,23 @@ export const MCPEndpoint = ({
|
|
|
295
384
|
return (
|
|
296
385
|
<>
|
|
297
386
|
<p>
|
|
298
|
-
|
|
299
|
-
|
|
387
|
+
A generic <InlineCode>.mcp.json</InlineCode> configuration that
|
|
388
|
+
works with most MCP-compatible apps.
|
|
300
389
|
</p>
|
|
301
390
|
<SyntaxHighlight
|
|
302
391
|
showLanguageIndicator
|
|
303
392
|
title=".mcp.json"
|
|
304
393
|
language="json"
|
|
305
394
|
code={genericConfig}
|
|
306
|
-
className="mt-2"
|
|
307
395
|
/>
|
|
308
396
|
<p className="text-sm text-muted-foreground">
|
|
309
397
|
Place this file in your project root or the appropriate
|
|
310
398
|
configuration directory for your app. The exact location depends
|
|
311
399
|
on your specific tool.
|
|
312
400
|
</p>
|
|
313
|
-
<
|
|
314
|
-
href="https://modelcontextprotocol.io/"
|
|
315
|
-
target="_blank"
|
|
316
|
-
rel="noopener noreferrer"
|
|
317
|
-
className="inline-flex items-center gap-1 text-sm text-primary hover:underline"
|
|
318
|
-
>
|
|
401
|
+
<DocsLink href="https://modelcontextprotocol.io/">
|
|
319
402
|
Learn more about MCP
|
|
320
|
-
|
|
321
|
-
</a>
|
|
403
|
+
</DocsLink>
|
|
322
404
|
</>
|
|
323
405
|
);
|
|
324
406
|
|
|
@@ -329,69 +411,106 @@ export const MCPEndpoint = ({
|
|
|
329
411
|
|
|
330
412
|
return (
|
|
331
413
|
<Card className="p-6 mb-6 max-w-screen-md">
|
|
332
|
-
<div className="space-y-
|
|
414
|
+
<div className="space-y-5">
|
|
333
415
|
<div>
|
|
334
|
-
<
|
|
335
|
-
|
|
416
|
+
<h3 className="text-lg font-semibold">Connect {name}</h3>
|
|
417
|
+
<p className="text-sm text-muted-foreground">
|
|
418
|
+
Add this MCP server to your favorite AI tools in a few steps.
|
|
419
|
+
</p>
|
|
420
|
+
</div>
|
|
421
|
+
|
|
422
|
+
{/* Step 1 — the one thing every client needs: the server URL. */}
|
|
423
|
+
<div className="rounded-lg border bg-muted/30 p-3">
|
|
424
|
+
<div className="flex items-center justify-between gap-3">
|
|
425
|
+
<div className="min-w-0">
|
|
426
|
+
<div className="text-xs font-medium text-muted-foreground mb-1">
|
|
427
|
+
MCP Server URL
|
|
428
|
+
</div>
|
|
429
|
+
<code className="block truncate font-mono text-sm">{mcpUrl}</code>
|
|
430
|
+
</div>
|
|
336
431
|
<Button
|
|
337
432
|
onClick={handleCopy}
|
|
338
433
|
variant="outline"
|
|
339
434
|
size="sm"
|
|
340
|
-
className="gap-1.5"
|
|
435
|
+
className="gap-1.5 shrink-0"
|
|
341
436
|
>
|
|
342
437
|
{isCopied ? (
|
|
343
438
|
<CheckIcon className="h-3.5 w-3.5 text-green-600" />
|
|
344
439
|
) : (
|
|
345
440
|
<CopyIcon className="h-3.5 w-3.5" />
|
|
346
441
|
)}
|
|
347
|
-
{isCopied ? "Copied!" : "Copy
|
|
442
|
+
{isCopied ? "Copied!" : "Copy"}
|
|
348
443
|
</Button>
|
|
349
444
|
</div>
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
445
|
+
{auth && (
|
|
446
|
+
<p className="mt-2 text-xs text-muted-foreground">
|
|
447
|
+
Requires an <InlineCode>{auth.headerName}</InlineCode> header —
|
|
448
|
+
replace <InlineCode>{auth.placeholder}</InlineCode> with your key.
|
|
449
|
+
</p>
|
|
450
|
+
)}
|
|
451
|
+
</div>
|
|
355
452
|
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
<
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
</TabsList>
|
|
453
|
+
{/* Step 2 — pick your client. */}
|
|
454
|
+
<div className="space-y-2">
|
|
455
|
+
<div className="text-sm font-medium">Choose your client</div>
|
|
456
|
+
<div className="grid grid-cols-2 gap-2 sm:grid-cols-3">
|
|
457
|
+
{visibleApps.map((app) => {
|
|
458
|
+
const isActive = app.id === selectedApp?.id;
|
|
459
|
+
return (
|
|
460
|
+
<button
|
|
461
|
+
key={app.id}
|
|
462
|
+
type="button"
|
|
463
|
+
onClick={() => selectApp(app.id)}
|
|
464
|
+
aria-pressed={isActive}
|
|
465
|
+
data-active={isActive}
|
|
466
|
+
className={cn(
|
|
467
|
+
"flex flex-col items-center justify-center gap-2 rounded-lg border p-3 transition",
|
|
468
|
+
"hover:bg-muted/60",
|
|
469
|
+
isActive
|
|
470
|
+
? "border-primary bg-primary/5 ring-1 ring-primary text-foreground"
|
|
471
|
+
: "border-border text-muted-foreground",
|
|
472
|
+
)}
|
|
473
|
+
>
|
|
474
|
+
<McpClientLogo appId={app.id} className="size-6" />
|
|
475
|
+
<span className="text-xs font-medium">{app.label}</span>
|
|
476
|
+
</button>
|
|
477
|
+
);
|
|
478
|
+
})}
|
|
479
|
+
</div>
|
|
480
|
+
</div>
|
|
385
481
|
|
|
482
|
+
{/* Step 3 — client-specific setup walkthrough. */}
|
|
483
|
+
{selectedApp && (
|
|
484
|
+
<div className="space-y-3">
|
|
485
|
+
<div className="flex flex-wrap items-center justify-between gap-2">
|
|
486
|
+
<div className="text-sm font-medium">
|
|
487
|
+
Set up {selectedApp.label}
|
|
488
|
+
</div>
|
|
489
|
+
{selectedApp.subApps.length > 1 && (
|
|
490
|
+
<ToggleGroup
|
|
491
|
+
size="sm"
|
|
492
|
+
variant="outline"
|
|
493
|
+
spacing={2}
|
|
494
|
+
aria-label={`Set up method for ${selectedApp.label}`}
|
|
495
|
+
value={activeSubApp ? [activeSubApp.id] : []}
|
|
496
|
+
onValueChange={(value: string[]) => {
|
|
497
|
+
const next = value.at(0);
|
|
498
|
+
if (next) setSelectedSubAppId(next);
|
|
499
|
+
}}
|
|
500
|
+
>
|
|
501
|
+
{selectedApp.subApps.map((sub) => (
|
|
502
|
+
<ToggleGroupItem key={sub.id} value={sub.id}>
|
|
503
|
+
{sub.label}
|
|
504
|
+
</ToggleGroupItem>
|
|
505
|
+
))}
|
|
506
|
+
</ToggleGroup>
|
|
507
|
+
)}
|
|
508
|
+
</div>
|
|
386
509
|
<Typography className="text-sm max-w-full">
|
|
387
|
-
{
|
|
388
|
-
<TabsContent key={app.id} value={app.id} className="space-y-3">
|
|
389
|
-
{renderAppContent(app)}
|
|
390
|
-
</TabsContent>
|
|
391
|
-
))}
|
|
510
|
+
{renderSetup(selectedApp)}
|
|
392
511
|
</Typography>
|
|
393
|
-
</
|
|
394
|
-
|
|
512
|
+
</div>
|
|
513
|
+
)}
|
|
395
514
|
</div>
|
|
396
515
|
</Card>
|
|
397
516
|
);
|