zudoku 0.83.0 → 0.84.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/dist/cli/cli.js +77 -19
- package/dist/cli/worker.js +1 -0
- package/dist/declarations/app/notFoundRoute.d.ts +2 -0
- package/dist/declarations/config/validators/ZudokuConfig.d.ts +8 -0
- package/dist/declarations/lib/components/Search.d.ts +2 -0
- package/dist/declarations/lib/components/context/RenderContext.d.ts +3 -0
- package/dist/declarations/lib/core/plugins.d.ts +1 -0
- package/dist/declarations/lib/plugins/api-catalog/index.d.ts +1 -0
- package/dist/declarations/lib/plugins/openapi/MCPEndpoint.d.ts +2 -1
- package/dist/declarations/lib/plugins/openapi/McpCatalog.d.ts +5 -0
- package/dist/declarations/lib/plugins/openapi/components/SelectOnClick.d.ts +2 -1
- package/dist/declarations/lib/plugins/openapi/graphql/gql.d.ts +2 -1
- package/dist/declarations/lib/plugins/openapi/graphql/graphql.d.ts +27 -0
- package/dist/declarations/lib/plugins/openapi/index.d.ts +1 -1
- package/dist/declarations/lib/plugins/openapi/interfaces.d.ts +5 -0
- package/dist/declarations/lib/plugins/openapi/mcp-configs.d.ts +15 -1
- package/dist/declarations/lib/plugins/openapi/util/documentType.d.ts +8 -0
- package/dist/declarations/lib/plugins/openapi/util/getRoutes.d.ts +1 -1
- package/dist/declarations/lib/plugins/openapi/util/sanitizeMarkdownForMetatag.d.ts +1 -0
- package/dist/flat-config.d.ts +1 -0
- package/docs/configuration/api-reference.md +7 -0
- package/docs/configuration/search.md +5 -0
- package/docs/guides/mcp-servers.md +48 -0
- package/docs/openapi-extensions/x-mcp-server.md +39 -0
- package/docs/openapi-extensions/x-zudoku-type.md +80 -0
- package/package.json +1 -1
- package/src/app/main.tsx +2 -1
- package/src/app/notFoundRoute.tsx +21 -0
- package/src/config/validators/ZudokuConfig.ts +1 -0
- package/src/lib/components/Header.tsx +93 -89
- package/src/lib/components/Search.tsx +53 -15
- package/src/lib/components/context/RenderContext.ts +10 -0
- package/src/lib/core/RouteGuard.tsx +6 -3
- package/src/lib/core/plugins.ts +1 -0
- package/src/lib/oas/graphql/index.ts +6 -0
- package/src/lib/plugins/api-catalog/Catalog.tsx +1 -1
- package/src/lib/plugins/api-catalog/index.tsx +3 -0
- package/src/lib/plugins/openapi/MCPEndpoint.tsx +7 -5
- package/src/lib/plugins/openapi/McpCatalog.tsx +467 -0
- package/src/lib/plugins/openapi/OperationListItem.tsx +5 -1
- package/src/lib/plugins/openapi/components/SelectOnClick.tsx +16 -0
- package/src/lib/plugins/openapi/graphql/gql.ts +12 -3
- package/src/lib/plugins/openapi/graphql/graphql.ts +53 -0
- package/src/lib/plugins/openapi/index.tsx +7 -1
- package/src/lib/plugins/openapi/interfaces.ts +14 -0
- package/src/lib/plugins/openapi/mcp-configs.ts +105 -2
- package/src/lib/plugins/openapi/util/createNavigationCategory.tsx +10 -6
- package/src/lib/plugins/openapi/util/documentType.ts +59 -0
- package/src/lib/plugins/openapi/util/getRoutes.tsx +29 -1
- package/src/lib/plugins/openapi/util/sanitizeMarkdownForMetatag.tsx +18 -6
- package/src/lib/plugins/search-inkeep/index.tsx +51 -19
- package/src/lib/plugins/search-inkeep/inkeep.ts +5 -1
- package/src/vite/plugin-api.ts +100 -23
package/dist/cli/cli.js
CHANGED
|
@@ -3152,6 +3152,7 @@ var ApiOptionsSchema = z7.object({
|
|
|
3152
3152
|
expandAllTags: z7.boolean(),
|
|
3153
3153
|
showInfoPage: z7.boolean(),
|
|
3154
3154
|
disableSecurity: z7.boolean(),
|
|
3155
|
+
disableMcpAuthInstructions: z7.boolean(),
|
|
3155
3156
|
schemaDownload: z7.object({
|
|
3156
3157
|
enabled: z7.boolean(),
|
|
3157
3158
|
fileName: z7.string().regex(/^[A-Za-z0-9_-]+$/).optional()
|
|
@@ -4178,6 +4179,7 @@ import fs2 from "node:fs/promises";
|
|
|
4178
4179
|
import path12 from "node:path";
|
|
4179
4180
|
import { deepEqual as deepEqual2 } from "fast-equals";
|
|
4180
4181
|
import { runnerImport as runnerImport3 } from "vite";
|
|
4182
|
+
import { parse as parseYaml } from "yaml";
|
|
4181
4183
|
|
|
4182
4184
|
// src/config/validators/BuildSchema.ts
|
|
4183
4185
|
import path7 from "node:path";
|
|
@@ -5104,6 +5106,11 @@ var OperationItem = builder.objectRef("OperationItem").implement({
|
|
|
5104
5106
|
operationId: t.exposeString("operationId", { nullable: true }),
|
|
5105
5107
|
summary: t.exposeString("summary", { nullable: true }),
|
|
5106
5108
|
description: t.exposeString("description", { nullable: true }),
|
|
5109
|
+
// Lean flag so consumers (e.g. the sidebar) can tell an MCP server
|
|
5110
|
+
// endpoint apart without pulling in the whole `x-mcp-server` extension.
|
|
5111
|
+
isMcpServer: t.boolean({
|
|
5112
|
+
resolve: (parent) => resolveExtensions(parent)["x-mcp-server"] !== void 0
|
|
5113
|
+
}),
|
|
5107
5114
|
contentTypes: t.stringList({
|
|
5108
5115
|
resolve: (parent) => Object.keys(parent.requestBody?.content ?? {})
|
|
5109
5116
|
}),
|
|
@@ -5360,6 +5367,34 @@ builder.queryType({
|
|
|
5360
5367
|
var schema = builder.toSchema();
|
|
5361
5368
|
var createGraphQLServer = (options) => createYoga({ schema, batching: true, ...options });
|
|
5362
5369
|
|
|
5370
|
+
// src/lib/plugins/openapi/interfaces.ts
|
|
5371
|
+
var DOCUMENT_TYPE_EXTENSION = "x-zudoku-type";
|
|
5372
|
+
var MCP_CATALOG = "mcp-catalog";
|
|
5373
|
+
|
|
5374
|
+
// src/lib/plugins/openapi/util/documentType.ts
|
|
5375
|
+
var MCP_SERVER_EXTENSION = "x-mcp-server";
|
|
5376
|
+
var HTTP_METHODS = [
|
|
5377
|
+
"get",
|
|
5378
|
+
"post",
|
|
5379
|
+
"put",
|
|
5380
|
+
"patch",
|
|
5381
|
+
"delete",
|
|
5382
|
+
"options",
|
|
5383
|
+
"head",
|
|
5384
|
+
"trace"
|
|
5385
|
+
];
|
|
5386
|
+
var httpMethods = new Set(HTTP_METHODS);
|
|
5387
|
+
var KNOWN_DOCUMENT_TYPES = [MCP_CATALOG];
|
|
5388
|
+
var readDocumentType = (schema2) => schema2[DOCUMENT_TYPE_EXTENSION];
|
|
5389
|
+
var isKnownDocumentType = (value) => typeof value === "string" && KNOWN_DOCUMENT_TYPES.includes(value);
|
|
5390
|
+
var operationsOf = (schema2) => Object.values(schema2.paths ?? {}).flatMap(
|
|
5391
|
+
(pathItem) => pathItem && typeof pathItem === "object" ? Object.entries(pathItem).filter(([method]) => httpMethods.has(method.toLowerCase())).map(([, operation]) => operation) : []
|
|
5392
|
+
);
|
|
5393
|
+
var countOperations = (schema2) => operationsOf(schema2).length;
|
|
5394
|
+
var countMcpServers = (schema2) => operationsOf(schema2).filter(
|
|
5395
|
+
(operation) => !!operation && typeof operation === "object" && MCP_SERVER_EXTENSION in operation
|
|
5396
|
+
).length;
|
|
5397
|
+
|
|
5363
5398
|
// src/lib/util/ensureArray.ts
|
|
5364
5399
|
var ensureArray = (value) => Array.isArray(value) ? value : [value];
|
|
5365
5400
|
|
|
@@ -6062,6 +6097,25 @@ var viteConfigReloadPlugin = () => ({
|
|
|
6062
6097
|
|
|
6063
6098
|
// src/vite/plugin-api.ts
|
|
6064
6099
|
var PROCESSED_STORE_SUBPATH = "node_modules/.zudoku/processed";
|
|
6100
|
+
var warn = (message) => {
|
|
6101
|
+
console.warn(`[zudoku] ${message}`);
|
|
6102
|
+
};
|
|
6103
|
+
var resolveDocumentType = (schema2, apiPath = "<unknown>") => {
|
|
6104
|
+
const value = readDocumentType(schema2);
|
|
6105
|
+
if (value === void 0) return void 0;
|
|
6106
|
+
if (isKnownDocumentType(value)) return value;
|
|
6107
|
+
warn(
|
|
6108
|
+
`Unknown "x-zudoku-type" value ${JSON.stringify(value)} in "${apiPath}". Rendering the default API view.`
|
|
6109
|
+
);
|
|
6110
|
+
return void 0;
|
|
6111
|
+
};
|
|
6112
|
+
var resolveRawDocumentType = (input, apiPath = "<unknown>") => {
|
|
6113
|
+
try {
|
|
6114
|
+
return resolveDocumentType(parseYaml(input), apiPath);
|
|
6115
|
+
} catch {
|
|
6116
|
+
return void 0;
|
|
6117
|
+
}
|
|
6118
|
+
};
|
|
6065
6119
|
var viteApiPlugin = async () => {
|
|
6066
6120
|
const virtualModuleId4 = "virtual:zudoku-api-plugins";
|
|
6067
6121
|
const resolvedVirtualModuleId4 = `\0${virtualModuleId4}`;
|
|
@@ -6162,28 +6216,12 @@ var viteApiPlugin = async () => {
|
|
|
6162
6216
|
);
|
|
6163
6217
|
const apis = ensureArray(config.apis);
|
|
6164
6218
|
const apiMetadata = [];
|
|
6165
|
-
const httpMethods = /* @__PURE__ */ new Set([
|
|
6166
|
-
"get",
|
|
6167
|
-
"post",
|
|
6168
|
-
"put",
|
|
6169
|
-
"patch",
|
|
6170
|
-
"delete",
|
|
6171
|
-
"options",
|
|
6172
|
-
"head",
|
|
6173
|
-
"trace"
|
|
6174
|
-
]);
|
|
6175
6219
|
for (const apiConfig of apis) {
|
|
6176
6220
|
if (apiConfig.type === "file" && apiConfig.path) {
|
|
6177
6221
|
const latestSchema = schemaManager.getLatestSchema(apiConfig.path);
|
|
6178
6222
|
if (!latestSchema?.schema.info) continue;
|
|
6179
|
-
const
|
|
6180
|
-
|
|
6181
|
-
).reduce((sum, pathItem) => {
|
|
6182
|
-
if (!pathItem || typeof pathItem !== "object") return sum;
|
|
6183
|
-
return sum + Object.keys(pathItem).filter(
|
|
6184
|
-
(m) => httpMethods.has(m.toLowerCase())
|
|
6185
|
-
).length;
|
|
6186
|
-
}, 0);
|
|
6223
|
+
const isCatalog = resolveDocumentType(latestSchema.schema, apiConfig.path) === MCP_CATALOG;
|
|
6224
|
+
const operationCount = isCatalog ? countMcpServers(latestSchema.schema) : countOperations(latestSchema.schema);
|
|
6187
6225
|
const rawVersion = latestSchema.schema.info.version;
|
|
6188
6226
|
const version = rawVersion ? rawVersion.startsWith("v") || rawVersion.startsWith("V") ? rawVersion : `v${rawVersion}` : void 0;
|
|
6189
6227
|
apiMetadata.push({
|
|
@@ -6192,7 +6230,8 @@ var viteApiPlugin = async () => {
|
|
|
6192
6230
|
description: latestSchema.schema.info.description ?? "",
|
|
6193
6231
|
categories: apiConfig.categories ?? [],
|
|
6194
6232
|
version,
|
|
6195
|
-
operationCount
|
|
6233
|
+
operationCount,
|
|
6234
|
+
countLabel: isCatalog ? operationCount === 1 ? "server" : "servers" : void 0
|
|
6196
6235
|
});
|
|
6197
6236
|
}
|
|
6198
6237
|
}
|
|
@@ -6223,18 +6262,34 @@ var viteApiPlugin = async () => {
|
|
|
6223
6262
|
});
|
|
6224
6263
|
const tags = Array.from(allSlugs);
|
|
6225
6264
|
const schemaImports = schemaManager.getSchemaImports();
|
|
6265
|
+
const latest = schemas.at(0);
|
|
6266
|
+
const documentType = latest ? resolveDocumentType(latest.schema, apiConfig.path) : void 0;
|
|
6267
|
+
if (documentType === MCP_CATALOG) {
|
|
6268
|
+
if (schemas.length > 1) {
|
|
6269
|
+
warn(
|
|
6270
|
+
`"${apiConfig.path}" is an MCP catalog with ${schemas.length} versions. Only the latest is rendered; catalog documents do not support version switching.`
|
|
6271
|
+
);
|
|
6272
|
+
}
|
|
6273
|
+
if (latest && countMcpServers(latest.schema) === 0) {
|
|
6274
|
+
warn(
|
|
6275
|
+
`"${apiConfig.path}" is marked as an MCP catalog but has no operations with "x-mcp-server". The catalog will render empty.`
|
|
6276
|
+
);
|
|
6277
|
+
}
|
|
6278
|
+
}
|
|
6226
6279
|
code.push(
|
|
6227
6280
|
"configuredApiPlugins.push(openApiPlugin({",
|
|
6228
6281
|
` type: "file",`,
|
|
6229
6282
|
` input: ${JSON.stringify(versionedInput)},`,
|
|
6230
6283
|
` path: ${JSON.stringify(apiConfig.path)},`,
|
|
6231
6284
|
` tagPages: ${JSON.stringify(tags)},`,
|
|
6285
|
+
...documentType ? [` documentType: ${JSON.stringify(documentType)},`] : [],
|
|
6232
6286
|
` options: {`,
|
|
6233
6287
|
` examplesLanguage: config.defaults?.apis?.examplesLanguage ?? config.defaults?.examplesLanguage,`,
|
|
6234
6288
|
` supportedLanguages: config.defaults?.apis?.supportedLanguages,`,
|
|
6235
6289
|
` disablePlayground: config.defaults?.apis?.disablePlayground,`,
|
|
6236
6290
|
` disableSidecar: config.defaults?.apis?.disableSidecar,`,
|
|
6237
6291
|
` disableSecurity: config.defaults?.apis?.disableSecurity ?? true,`,
|
|
6292
|
+
` disableMcpAuthInstructions: config.defaults?.apis?.disableMcpAuthInstructions,`,
|
|
6238
6293
|
` showVersionSelect: config.defaults?.apis?.showVersionSelect ?? "if-available",`,
|
|
6239
6294
|
` expandAllTags: config.defaults?.apis?.expandAllTags ?? true,`,
|
|
6240
6295
|
` showInfoPage: config.defaults?.apis?.showInfoPage,`,
|
|
@@ -6251,15 +6306,18 @@ var viteApiPlugin = async () => {
|
|
|
6251
6306
|
"}));"
|
|
6252
6307
|
);
|
|
6253
6308
|
} else {
|
|
6309
|
+
const documentType = apiConfig.type === "raw" ? resolveRawDocumentType(apiConfig.input, apiConfig.path) : void 0;
|
|
6254
6310
|
code.push(
|
|
6255
6311
|
"configuredApiPlugins.push(openApiPlugin({",
|
|
6256
6312
|
` ...${JSON.stringify(apiConfig)},`,
|
|
6313
|
+
...documentType ? [` documentType: ${JSON.stringify(documentType)},`] : [],
|
|
6257
6314
|
" options: {",
|
|
6258
6315
|
` examplesLanguage: config.defaults?.apis?.examplesLanguage ?? config.defaults?.examplesLanguage,`,
|
|
6259
6316
|
` supportedLanguages: config.defaults?.apis?.supportedLanguages,`,
|
|
6260
6317
|
` disablePlayground: config.defaults?.apis?.disablePlayground,`,
|
|
6261
6318
|
` disableSidecar: config.defaults?.apis?.disableSidecar,`,
|
|
6262
6319
|
` disableSecurity: config.defaults?.apis?.disableSecurity ?? true,`,
|
|
6320
|
+
` disableMcpAuthInstructions: config.defaults?.apis?.disableMcpAuthInstructions,`,
|
|
6263
6321
|
` showVersionSelect: config.defaults?.apis?.showVersionSelect ?? "if-available",`,
|
|
6264
6322
|
` expandAllTags: config.defaults?.apis?.expandAllTags ?? false,`,
|
|
6265
6323
|
` showInfoPage: config.defaults?.apis?.showInfoPage,`,
|
package/dist/cli/worker.js
CHANGED
|
@@ -2386,6 +2386,7 @@ var ApiOptionsSchema = z4.object({
|
|
|
2386
2386
|
expandAllTags: z4.boolean(),
|
|
2387
2387
|
showInfoPage: z4.boolean(),
|
|
2388
2388
|
disableSecurity: z4.boolean(),
|
|
2389
|
+
disableMcpAuthInstructions: z4.boolean(),
|
|
2389
2390
|
schemaDownload: z4.object({
|
|
2390
2391
|
enabled: z4.boolean(),
|
|
2391
2392
|
fileName: z4.string().regex(/^[A-Za-z0-9_-]+$/).optional()
|
|
@@ -57,6 +57,7 @@ declare const ApiOptionsSchema: z.ZodObject<{
|
|
|
57
57
|
expandAllTags: z.ZodOptional<z.ZodBoolean>;
|
|
58
58
|
showInfoPage: z.ZodOptional<z.ZodBoolean>;
|
|
59
59
|
disableSecurity: z.ZodOptional<z.ZodBoolean>;
|
|
60
|
+
disableMcpAuthInstructions: z.ZodOptional<z.ZodBoolean>;
|
|
60
61
|
schemaDownload: z.ZodOptional<z.ZodObject<{
|
|
61
62
|
enabled: z.ZodOptional<z.ZodBoolean>;
|
|
62
63
|
fileName: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
@@ -7297,6 +7298,7 @@ export declare const ZudokuConfig: z.ZodObject<{
|
|
|
7297
7298
|
expandAllTags: z.ZodOptional<z.ZodBoolean>;
|
|
7298
7299
|
showInfoPage: z.ZodOptional<z.ZodBoolean>;
|
|
7299
7300
|
disableSecurity: z.ZodOptional<z.ZodBoolean>;
|
|
7301
|
+
disableMcpAuthInstructions: z.ZodOptional<z.ZodBoolean>;
|
|
7300
7302
|
schemaDownload: z.ZodOptional<z.ZodObject<{
|
|
7301
7303
|
enabled: z.ZodOptional<z.ZodBoolean>;
|
|
7302
7304
|
fileName: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
@@ -7333,6 +7335,7 @@ export declare const ZudokuConfig: z.ZodObject<{
|
|
|
7333
7335
|
expandAllTags: z.ZodOptional<z.ZodBoolean>;
|
|
7334
7336
|
showInfoPage: z.ZodOptional<z.ZodBoolean>;
|
|
7335
7337
|
disableSecurity: z.ZodOptional<z.ZodBoolean>;
|
|
7338
|
+
disableMcpAuthInstructions: z.ZodOptional<z.ZodBoolean>;
|
|
7336
7339
|
schemaDownload: z.ZodOptional<z.ZodObject<{
|
|
7337
7340
|
enabled: z.ZodOptional<z.ZodBoolean>;
|
|
7338
7341
|
fileName: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
@@ -7369,6 +7372,7 @@ export declare const ZudokuConfig: z.ZodObject<{
|
|
|
7369
7372
|
expandAllTags: z.ZodOptional<z.ZodBoolean>;
|
|
7370
7373
|
showInfoPage: z.ZodOptional<z.ZodBoolean>;
|
|
7371
7374
|
disableSecurity: z.ZodOptional<z.ZodBoolean>;
|
|
7375
|
+
disableMcpAuthInstructions: z.ZodOptional<z.ZodBoolean>;
|
|
7372
7376
|
schemaDownload: z.ZodOptional<z.ZodObject<{
|
|
7373
7377
|
enabled: z.ZodOptional<z.ZodBoolean>;
|
|
7374
7378
|
fileName: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
@@ -7401,6 +7405,7 @@ export declare const ZudokuConfig: z.ZodObject<{
|
|
|
7401
7405
|
expandAllTags: z.ZodOptional<z.ZodBoolean>;
|
|
7402
7406
|
showInfoPage: z.ZodOptional<z.ZodBoolean>;
|
|
7403
7407
|
disableSecurity: z.ZodOptional<z.ZodBoolean>;
|
|
7408
|
+
disableMcpAuthInstructions: z.ZodOptional<z.ZodBoolean>;
|
|
7404
7409
|
schemaDownload: z.ZodOptional<z.ZodObject<{
|
|
7405
7410
|
enabled: z.ZodOptional<z.ZodBoolean>;
|
|
7406
7411
|
fileName: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
@@ -7437,6 +7442,7 @@ export declare const ZudokuConfig: z.ZodObject<{
|
|
|
7437
7442
|
expandAllTags: z.ZodOptional<z.ZodBoolean>;
|
|
7438
7443
|
showInfoPage: z.ZodOptional<z.ZodBoolean>;
|
|
7439
7444
|
disableSecurity: z.ZodOptional<z.ZodBoolean>;
|
|
7445
|
+
disableMcpAuthInstructions: z.ZodOptional<z.ZodBoolean>;
|
|
7440
7446
|
schemaDownload: z.ZodOptional<z.ZodObject<{
|
|
7441
7447
|
enabled: z.ZodOptional<z.ZodBoolean>;
|
|
7442
7448
|
fileName: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
@@ -7473,6 +7479,7 @@ export declare const ZudokuConfig: z.ZodObject<{
|
|
|
7473
7479
|
expandAllTags: z.ZodOptional<z.ZodBoolean>;
|
|
7474
7480
|
showInfoPage: z.ZodOptional<z.ZodBoolean>;
|
|
7475
7481
|
disableSecurity: z.ZodOptional<z.ZodBoolean>;
|
|
7482
|
+
disableMcpAuthInstructions: z.ZodOptional<z.ZodBoolean>;
|
|
7476
7483
|
schemaDownload: z.ZodOptional<z.ZodObject<{
|
|
7477
7484
|
enabled: z.ZodOptional<z.ZodBoolean>;
|
|
7478
7485
|
fileName: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
@@ -7574,6 +7581,7 @@ export declare const ZudokuConfig: z.ZodObject<{
|
|
|
7574
7581
|
expandAllTags: z.ZodOptional<z.ZodBoolean>;
|
|
7575
7582
|
showInfoPage: z.ZodOptional<z.ZodBoolean>;
|
|
7576
7583
|
disableSecurity: z.ZodOptional<z.ZodBoolean>;
|
|
7584
|
+
disableMcpAuthInstructions: z.ZodOptional<z.ZodBoolean>;
|
|
7577
7585
|
schemaDownload: z.ZodOptional<z.ZodObject<{
|
|
7578
7586
|
enabled: z.ZodOptional<z.ZodBoolean>;
|
|
7579
7587
|
fileName: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
@@ -9,3 +9,6 @@ export type RenderContextValue = {
|
|
|
9
9
|
ssrAuth?: SSRAuthState;
|
|
10
10
|
};
|
|
11
11
|
export declare const RenderContext: import("react").Context<RenderContextValue>;
|
|
12
|
+
export declare const setSsrStatus: (renderContext: RenderContextValue, status: number, { onlyIfUnset }?: {
|
|
13
|
+
onlyIfUnset?: boolean;
|
|
14
|
+
}) => void;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { type McpServerData } from "./mcp-configs.js";
|
|
2
|
-
export declare const MCPEndpoint: ({ serverUrl, operationPath, summary, data, }: {
|
|
2
|
+
export declare const MCPEndpoint: ({ serverUrl, operationPath, summary, data, disableAuthInstructions, }: {
|
|
3
3
|
serverUrl?: string;
|
|
4
4
|
operationPath?: string;
|
|
5
5
|
data?: McpServerData;
|
|
6
6
|
summary?: string;
|
|
7
|
+
disableAuthInstructions?: boolean;
|
|
7
8
|
}) => import("react").JSX.Element;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare const GetMcpCatalogQuery: import("./graphql/graphql.js").TypedDocumentString<import("./graphql/graphql.js").GetMcpCatalogQuery, {
|
|
2
|
+
input: any;
|
|
3
|
+
type: import("./graphql/graphql.js").SchemaType;
|
|
4
|
+
}>;
|
|
5
|
+
export declare const McpCatalog: () => import("react").JSX.Element;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type SlotProps } from "@radix-ui/react-slot";
|
|
2
|
-
export declare const SelectOnClick: ({ asChild, onClick, enabled, ...props }: {
|
|
2
|
+
export declare const SelectOnClick: ({ asChild, onClick, copyValue, enabled, ...props }: {
|
|
3
3
|
asChild?: boolean;
|
|
4
4
|
enabled?: boolean;
|
|
5
|
+
copyValue?: string;
|
|
5
6
|
} & SlotProps) => import("react").JSX.Element;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
export declare function graphql(source: "\n query ServersQuery($input: JSON!, $type: SchemaType!) {\n schema(input: $input, type: $type) {\n url\n servers {\n url\n }\n }\n }\n"): typeof import("./graphql.js").ServersQueryDocument;
|
|
2
|
+
export declare function graphql(source: "\n query GetMcpCatalog($input: JSON!, $type: SchemaType!) {\n schema(input: $input, type: $type) {\n title\n description\n tags {\n name\n slug\n operations {\n slug\n summary\n description\n operationId\n path\n extensions\n servers {\n url\n }\n }\n }\n }\n }\n"): typeof import("./graphql.js").GetMcpCatalogDocument;
|
|
2
3
|
export declare function graphql(source: "\n fragment OperationsFragment on OperationItem {\n slug\n summary\n method\n description\n operationId\n contentTypes\n path\n deprecated\n extensions\n servers {\n url\n description\n }\n parameters {\n name\n in\n description\n required\n schema\n style\n explode\n allowReserved\n examples {\n name\n description\n externalValue\n value\n summary\n }\n }\n security {\n schemes {\n scopes\n scheme {\n name\n type\n description\n in\n paramName\n scheme\n bearerFormat\n openIdConnectUrl\n flows {\n implicit {\n authorizationUrl\n scopes {\n name\n description\n }\n }\n password {\n tokenUrl\n scopes {\n name\n description\n }\n }\n clientCredentials {\n tokenUrl\n scopes {\n name\n description\n }\n }\n authorizationCode {\n authorizationUrl\n tokenUrl\n scopes {\n name\n description\n }\n }\n }\n }\n }\n }\n requestBody {\n content {\n mediaType\n encoding {\n name\n }\n examples {\n name\n description\n externalValue\n value\n summary\n }\n schema\n }\n description\n required\n }\n responses {\n statusCode\n links\n description\n content {\n examples {\n name\n description\n externalValue\n value\n summary\n }\n mediaType\n encoding {\n name\n }\n schema\n }\n }\n }\n"): typeof import("./graphql.js").OperationsFragmentFragmentDoc;
|
|
3
4
|
export declare function graphql(source: "\n query OperationsForTag(\n $input: JSON!\n $type: SchemaType!\n $tag: String\n $untagged: Boolean\n ) {\n schema(input: $input, type: $type) {\n servers {\n url\n }\n description\n summary\n title\n url\n version\n tag(slug: $tag, untagged: $untagged) {\n name\n description\n operations {\n slug\n ...OperationsFragment\n }\n extensions\n next {\n name\n slug\n extensions\n }\n prev {\n name\n slug\n extensions\n }\n }\n }\n }\n"): typeof import("./graphql.js").OperationsForTagDocument;
|
|
4
5
|
export declare function graphql(source: "\n query SchemaInfo($input: JSON!, $type: SchemaType!) {\n schema(input: $input, type: $type) {\n servers {\n url\n description\n }\n license {\n name\n url\n identifier\n }\n termsOfService\n externalDocs {\n description\n url\n }\n contact {\n name\n url\n email\n }\n description\n summary\n title\n url\n version\n tags {\n name\n description\n extensions\n }\n components {\n securitySchemes {\n name\n type\n description\n in\n paramName\n scheme\n bearerFormat\n openIdConnectUrl\n flows {\n implicit {\n authorizationUrl\n scopes {\n name\n description\n }\n }\n password {\n tokenUrl\n scopes {\n name\n description\n }\n }\n clientCredentials {\n tokenUrl\n scopes {\n name\n description\n }\n }\n authorizationCode {\n authorizationUrl\n tokenUrl\n scopes {\n name\n description\n }\n }\n }\n }\n }\n webhooks {\n name\n method\n summary\n description\n }\n }\n }\n"): typeof import("./graphql.js").SchemaInfoDocument;
|
|
5
6
|
export declare function graphql(source: "\n query GetSchemas($input: JSON!, $type: SchemaType!) {\n schema(input: $input, type: $type) {\n title\n description\n summary\n components {\n schemas {\n name\n schema\n extensions\n }\n }\n }\n }\n"): typeof import("./graphql.js").GetSchemasDocument;
|
|
6
7
|
export declare function graphql(source: "\n query getServerQuery($input: JSON!, $type: SchemaType!) {\n schema(input: $input, type: $type) {\n url\n servers {\n url\n }\n }\n }\n"): typeof import("./graphql.js").GetServerQueryDocument;
|
|
7
|
-
export declare function graphql(source: "\n query GetNavigationOperations($input: JSON!, $type: SchemaType!) {\n schema(input: $input, type: $type) {\n extensions\n description\n tags {\n slug\n name\n extensions\n operations {\n summary\n slug\n method\n operationId\n path\n }\n }\n components {\n schemas {\n __typename\n }\n }\n }\n }\n"): typeof import("./graphql.js").GetNavigationOperationsDocument;
|
|
8
|
+
export declare function graphql(source: "\n query GetNavigationOperations($input: JSON!, $type: SchemaType!) {\n schema(input: $input, type: $type) {\n extensions\n description\n tags {\n slug\n name\n extensions\n operations {\n summary\n slug\n method\n operationId\n path\n isMcpServer\n }\n }\n components {\n schemas {\n __typename\n }\n }\n }\n }\n"): typeof import("./graphql.js").GetNavigationOperationsDocument;
|
|
8
9
|
export declare function graphql(source: "\n query SchemaWarmup($input: JSON!, $type: SchemaType!) {\n schema(input: $input, type: $type) {\n openapi\n }\n }\n"): typeof import("./graphql.js").SchemaWarmupDocument;
|
|
@@ -23,6 +23,31 @@ export type ServersQueryQuery = {
|
|
|
23
23
|
}>;
|
|
24
24
|
};
|
|
25
25
|
};
|
|
26
|
+
export type GetMcpCatalogQueryVariables = Exact<{
|
|
27
|
+
input: any;
|
|
28
|
+
type: SchemaType;
|
|
29
|
+
}>;
|
|
30
|
+
export type GetMcpCatalogQuery = {
|
|
31
|
+
schema: {
|
|
32
|
+
title: string;
|
|
33
|
+
description: string | null;
|
|
34
|
+
tags: Array<{
|
|
35
|
+
name: string | null;
|
|
36
|
+
slug: string | null;
|
|
37
|
+
operations: Array<{
|
|
38
|
+
slug: string;
|
|
39
|
+
summary: string | null;
|
|
40
|
+
description: string | null;
|
|
41
|
+
operationId: string | null;
|
|
42
|
+
path: string;
|
|
43
|
+
extensions: any;
|
|
44
|
+
servers: Array<{
|
|
45
|
+
url: string;
|
|
46
|
+
}>;
|
|
47
|
+
}>;
|
|
48
|
+
}>;
|
|
49
|
+
};
|
|
50
|
+
};
|
|
26
51
|
export type OperationsFragmentFragment = {
|
|
27
52
|
slug: string;
|
|
28
53
|
summary: string | null;
|
|
@@ -314,6 +339,7 @@ export type GetNavigationOperationsQuery = {
|
|
|
314
339
|
method: string;
|
|
315
340
|
operationId: string | null;
|
|
316
341
|
path: string;
|
|
342
|
+
isMcpServer: boolean;
|
|
317
343
|
}>;
|
|
318
344
|
}>;
|
|
319
345
|
components: {
|
|
@@ -341,6 +367,7 @@ export declare class TypedDocumentString<TResult, TVariables> extends String imp
|
|
|
341
367
|
}
|
|
342
368
|
export declare const OperationsFragmentFragmentDoc: TypedDocumentString<OperationsFragmentFragment, unknown>;
|
|
343
369
|
export declare const ServersQueryDocument: TypedDocumentString<ServersQueryQuery, ServersQueryQueryVariables>;
|
|
370
|
+
export declare const GetMcpCatalogDocument: TypedDocumentString<GetMcpCatalogQuery, GetMcpCatalogQueryVariables>;
|
|
344
371
|
export declare const OperationsForTagDocument: TypedDocumentString<OperationsForTagQuery, OperationsForTagQueryVariables>;
|
|
345
372
|
export declare const SchemaInfoDocument: TypedDocumentString<SchemaInfoQuery, SchemaInfoQueryVariables>;
|
|
346
373
|
export declare const GetSchemasDocument: TypedDocumentString<GetSchemasQuery, GetSchemasQueryVariables>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ZudokuPlugin } from "../../core/plugins.js";
|
|
2
2
|
import type { GetNavigationOperationsQuery as GetNavigationOperationsQueryResult } from "./graphql/graphql.js";
|
|
3
|
-
import type
|
|
3
|
+
import { type OasPluginConfig } from "./interfaces.js";
|
|
4
4
|
export declare const GetNavigationOperationsQuery: import("./graphql/graphql.js").TypedDocumentString<GetNavigationOperationsQueryResult, {
|
|
5
5
|
input: any;
|
|
6
6
|
type: import("./graphql/graphql.js").SchemaType;
|
|
@@ -58,12 +58,16 @@ export type GenerateCodeSnippetFn = (options: {
|
|
|
58
58
|
example?: any | null;
|
|
59
59
|
resolvedAuth?: ResolvedAuth;
|
|
60
60
|
}) => string | false;
|
|
61
|
+
export declare const DOCUMENT_TYPE_EXTENSION = "x-zudoku-type";
|
|
62
|
+
export declare const MCP_CATALOG = "mcp-catalog";
|
|
63
|
+
export type OasDocumentType = typeof MCP_CATALOG;
|
|
61
64
|
type BaseOasConfig = {
|
|
62
65
|
server?: string;
|
|
63
66
|
path?: string;
|
|
64
67
|
skipPreload?: boolean;
|
|
65
68
|
tagPages?: Array<string>;
|
|
66
69
|
schemaImports?: SchemaImports;
|
|
70
|
+
documentType?: OasDocumentType;
|
|
67
71
|
options?: {
|
|
68
72
|
examplesLanguage?: string;
|
|
69
73
|
supportedLanguages?: {
|
|
@@ -73,6 +77,7 @@ type BaseOasConfig = {
|
|
|
73
77
|
disablePlayground?: boolean;
|
|
74
78
|
disableSidecar?: boolean;
|
|
75
79
|
disableSecurity?: boolean;
|
|
80
|
+
disableMcpAuthInstructions?: boolean;
|
|
76
81
|
showVersionSelect?: "always" | "if-available" | "hide";
|
|
77
82
|
expandAllTags?: boolean;
|
|
78
83
|
showInfoPage?: boolean;
|
|
@@ -6,6 +6,12 @@ export interface AuthHeader {
|
|
|
6
6
|
export type AuthType = "none" | "apiKey" | "oauth";
|
|
7
7
|
export declare const getAuthType: (data?: McpServerData) => AuthType;
|
|
8
8
|
export declare const getAuthHeader: (data?: McpServerData) => AuthHeader | undefined;
|
|
9
|
+
export declare const resolveMcpAuth: (data?: McpServerData, options?: {
|
|
10
|
+
disableAuthInstructions?: boolean;
|
|
11
|
+
}) => {
|
|
12
|
+
authType: AuthType;
|
|
13
|
+
auth?: AuthHeader;
|
|
14
|
+
};
|
|
9
15
|
export interface McpSubApp {
|
|
10
16
|
id: string;
|
|
11
17
|
label: string;
|
|
@@ -19,7 +25,15 @@ export interface McpApp {
|
|
|
19
25
|
export declare const MCP_APPS: McpApp[];
|
|
20
26
|
export declare const getVisibleApps: (authType: AuthType) => McpApp[];
|
|
21
27
|
export declare const getMcpServerName: (data?: McpServerData, summary?: string) => string;
|
|
22
|
-
export
|
|
28
|
+
export type McpTool = {
|
|
29
|
+
name: string;
|
|
30
|
+
description?: string;
|
|
31
|
+
};
|
|
32
|
+
export declare const isMcpServerObject: (data?: McpServerData) => data is Record<string, unknown>;
|
|
33
|
+
export declare const isMcpServerData: (value: unknown) => value is McpServerData;
|
|
34
|
+
export declare const getMcpServerTitle: (data?: McpServerData, summary?: string | null, operationId?: string | null) => string;
|
|
35
|
+
export declare const getMcpTools: (data?: McpServerData) => McpTool[];
|
|
36
|
+
export declare const getMcpUrl: (serverUrl?: string, operationPath?: string, data?: McpServerData) => string;
|
|
23
37
|
export declare const getClaudeCodeCommand: (name: string, mcpUrl: string, auth?: AuthHeader) => string;
|
|
24
38
|
export declare const getCodexCliCommand: (name: string, mcpUrl: string, auth?: AuthHeader) => string;
|
|
25
39
|
export declare const getCursorConfig: (name: string, mcpUrl: string, auth?: AuthHeader) => string;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { OpenAPIDocument } from "../../../oas/parser/index.js";
|
|
2
|
+
import { type OasDocumentType } from "../interfaces.js";
|
|
3
|
+
export declare const MCP_SERVER_EXTENSION = "x-mcp-server";
|
|
4
|
+
export declare const HTTP_METHODS: readonly ["get", "post", "put", "patch", "delete", "options", "head", "trace"];
|
|
5
|
+
export declare const readDocumentType: (schema: OpenAPIDocument) => unknown;
|
|
6
|
+
export declare const isKnownDocumentType: (value: unknown) => value is OasDocumentType;
|
|
7
|
+
export declare const countOperations: (schema: OpenAPIDocument) => number;
|
|
8
|
+
export declare const countMcpServers: (schema: OpenAPIDocument) => number;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type RouteObject } from "react-router";
|
|
2
2
|
import type { GraphQLClient } from "../client/GraphQLClient.js";
|
|
3
3
|
import { type OpenApiPluginOptions } from "../index.js";
|
|
4
|
-
import type
|
|
4
|
+
import { type OasPluginConfig, type VersionEntry } from "../interfaces.js";
|
|
5
5
|
export declare const getVersionMetadata: (config: OasPluginConfig) => {
|
|
6
6
|
versions: string[];
|
|
7
7
|
versionMap: Record<string, {
|
package/dist/flat-config.d.ts
CHANGED
|
@@ -207,6 +207,7 @@ const config = {
|
|
|
207
207
|
disablePlayground: false, // Disable the interactive API playground
|
|
208
208
|
disableSidecar: false, // Disable the sidecar completely
|
|
209
209
|
disableSecurity: true, // Disable security scheme display and playground auth (default)
|
|
210
|
+
disableMcpAuthInstructions: false, // Hide auth steps in the MCP server card
|
|
210
211
|
showVersionSelect: "if-available", // Control version selector visibility
|
|
211
212
|
expandAllTags: true, // Control initial expanded state of tag categories
|
|
212
213
|
showInfoPage: true, // Always show the info page (unset = show only if a description is set)
|
|
@@ -229,6 +230,11 @@ Available options:
|
|
|
229
230
|
- `disableSecurity`: Disable OpenAPI security scheme display (auth badges on operations, security
|
|
230
231
|
schemes section on the info page, and the Authorize dialog in the playground). Disabled by default
|
|
231
232
|
(`true`). Set to `false` to enable security scheme support
|
|
233
|
+
- `disableMcpAuthInstructions`: Hide the authentication instructions on
|
|
234
|
+
[MCP server](../guides/mcp-servers.md) endpoints. The MCP card normally derives a credential
|
|
235
|
+
header from the operation's security scheme and shows it in every install snippet. Set to `true`
|
|
236
|
+
to render the server as unauthenticated instead — no header snippets and no "replace
|
|
237
|
+
`YOUR_API_KEY`" steps
|
|
232
238
|
- `showVersionSelect`: Control version selector visibility
|
|
233
239
|
- `"if-available"`: Show version selector only when multiple versions exist (default)
|
|
234
240
|
- `"always"`: Always show version selector (disabled if only one version)
|
|
@@ -260,6 +266,7 @@ const config = {
|
|
|
260
266
|
disablePlayground: false, // Disable the interactive API playground
|
|
261
267
|
disableSidecar: false, // Disable the sidecar completely
|
|
262
268
|
disableSecurity: true, // Disable security scheme display and playground auth (default)
|
|
269
|
+
disableMcpAuthInstructions: false, // Hide auth steps in the MCP server card
|
|
263
270
|
showVersionSelect: "if-available", // Control version selector visibility
|
|
264
271
|
expandAllTags: false, // Control initial expanded state of tag categories
|
|
265
272
|
showInfoPage: true, // Always show the info page (unset = show only if a description is set)
|
|
@@ -182,6 +182,11 @@ You can also pass
|
|
|
182
182
|
Zudoku's defaults and passed through to Inkeep as-is, so any option Inkeep supports can be used —
|
|
183
183
|
including ones added after this Zudoku version was released.
|
|
184
184
|
|
|
185
|
+
Zudoku owns the search modal's open state, so `modalSettings.isOpen` is managed for you. The
|
|
186
|
+
<kbd>⌘</kbd>+<kbd>K</kbd> / <kbd>Ctrl</kbd>+<kbd>K</kbd> shortcut is handled by Zudoku's search
|
|
187
|
+
button as well, which is why Inkeep's own `shortcutKey` is disabled by default. Setting it adds an
|
|
188
|
+
additional shortcut rather than replacing it.
|
|
189
|
+
|
|
185
190
|
For example, to categorize results into tabs based on their URL:
|
|
186
191
|
|
|
187
192
|
```typescript
|
|
@@ -59,6 +59,7 @@ metadata. In this case, the operation's `summary` is used as the server name.
|
|
|
59
59
|
| --------- | -------- | -------- | ---------------------------------------------------------------------------------------------------------------------------- |
|
|
60
60
|
| `name` | `string` | No | Display name used in the generated client configuration snippets. Falls back to the operation `summary`, then `"mcp-server"` |
|
|
61
61
|
| `version` | `string` | No | Version metadata (included for completeness; not currently rendered in UI) |
|
|
62
|
+
| `url` | `string` | No | Overrides the endpoint URL shown in the card and install snippets |
|
|
62
63
|
| `tools` | `array` | No | Tools metadata (used by Zuplo enrichment; not currently rendered in UI) |
|
|
63
64
|
|
|
64
65
|
Each tool in the `tools` array has:
|
|
@@ -92,6 +93,53 @@ For example, with this configuration:
|
|
|
92
93
|
|
|
93
94
|
The displayed MCP URL will be `https://api.example.com/mcp/docs`.
|
|
94
95
|
|
|
96
|
+
If your MCP server lives on its own hostname, set `url` on the extension to override the derived
|
|
97
|
+
endpoint:
|
|
98
|
+
|
|
99
|
+
```json
|
|
100
|
+
{
|
|
101
|
+
"x-mcp-server": { "name": "docs-mcp", "url": "https://mcp.example.com/mcp" }
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
An absolute URL is used verbatim everywhere the endpoint appears, and takes precedence over the
|
|
106
|
+
server dropdown. A value without a scheme (such as `/v2/mcp`) is treated as a path on the server URL
|
|
107
|
+
instead. See the
|
|
108
|
+
[`x-mcp-server` reference](/docs/openapi-extensions/x-mcp-server#overriding-the-url) for details.
|
|
109
|
+
|
|
110
|
+
## Authentication instructions
|
|
111
|
+
|
|
112
|
+
When the `x-mcp-server` extension carries `security` and `securitySchemes` (Zuplo adds these
|
|
113
|
+
automatically for authenticated routes), the card derives the credential header from the first
|
|
114
|
+
scheme and threads it through every install snippet — for example an
|
|
115
|
+
`Authorization: Bearer YOUR_API_KEY` header in the `mcp.json` samples, plus a step telling users to
|
|
116
|
+
replace the placeholder with their key. API key auth also hides the clients that cannot send custom
|
|
117
|
+
headers (Claude Desktop and ChatGPT), and the one-click install buttons for Cursor and VS Code,
|
|
118
|
+
since those links cannot carry a secret.
|
|
119
|
+
|
|
120
|
+
If your users get their credentials some other way — the key is injected by a proxy, handled by your
|
|
121
|
+
own login flow, or simply documented elsewhere — turn the authentication instructions off in your
|
|
122
|
+
Zudoku config:
|
|
123
|
+
|
|
124
|
+
```tsx title="zudoku.config.tsx"
|
|
125
|
+
const config: ZudokuConfig = {
|
|
126
|
+
apis: [
|
|
127
|
+
{
|
|
128
|
+
type: "file",
|
|
129
|
+
input: "./mcp-api.json",
|
|
130
|
+
path: "mcp",
|
|
131
|
+
options: {
|
|
132
|
+
disableMcpAuthInstructions: true,
|
|
133
|
+
},
|
|
134
|
+
},
|
|
135
|
+
],
|
|
136
|
+
};
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
The card then renders the server as if it were unauthenticated, whatever its security says: no
|
|
140
|
+
header in the snippets, no placeholder step, and every client available again. Set it under
|
|
141
|
+
`defaults.apis` instead to apply it to all APIs.
|
|
142
|
+
|
|
95
143
|
## Complete example
|
|
96
144
|
|
|
97
145
|
This is a minimal but complete OpenAPI spec that produces an MCP endpoint page:
|