import { z } from "zod";
const apiTokenDescription = "Personal ClickUp API token used when environment variables are not provided.";
const defaultTeamIdDescription = "Default ClickUp workspace identifier applied when requests omit a team scope.";
const primaryLanguageDescription = "Preferred language code for human-facing responses. Falls back to CLICKUP_PRIMARY_LANGUAGE.";
const baseUrlDescription = "Override for the ClickUp API base URL. Defaults to https://api.clickup.com/api/v2 when unspecified.";
const requestTimeoutDescription = "Maximum duration in milliseconds before ClickUp requests timeout. Defaults to 30000.";
const defaultHeadersDescription = "JSON-encoded map of additional HTTP headers merged into every ClickUp request.";
const authSchemeDescription = "Authentication strategy negotiated with ClickUp: auto, personal_token, or oauth.";
const allowToolsDescription = "Tool allow-list overriding environment gating. Accepts a comma string or array of tool identifiers.";
const denyToolsDescription = "Tool deny-list overriding environment gating. Accepts a comma string or array of tool identifiers.";
function optionalStringField(description: string) {
return z
.union([z.string(), z.any()])
.optional()
.transform(value => (typeof value === "string" ? value : undefined))
.describe(description);
}
function optionalNumberField(description: string) {
return z
.union([z.number(), z.string(), z.any()])
.optional()
.transform(value => {
if (typeof value === "number" && Number.isFinite(value)) {
return value;
}
if (typeof value === "string") {
const parsed = Number.parseInt(value, 10);
return Number.isFinite(parsed) ? parsed : undefined;
}
return undefined;
})
.describe(description);
}
function optionalListField(description: string) {
return z
.union([z.string(), z.array(z.string())])
.optional()
.catch(undefined)
.describe(description);
}
export const smitheryConfigSchema = z
.object({
apiToken: optionalStringField(apiTokenDescription),
defaultTeamId: optionalNumberField(defaultTeamIdDescription),
primaryLanguage: optionalStringField(primaryLanguageDescription),
baseUrl: optionalStringField(baseUrlDescription),
requestTimeoutMs: optionalNumberField(requestTimeoutDescription),
defaultHeadersJson: optionalStringField(defaultHeadersDescription),
authScheme: z
.enum(["auto", "personal_token", "oauth"])
.optional()
.catch(undefined)
.describe(authSchemeDescription),
allowTools: optionalListField(allowToolsDescription),
denyTools: optionalListField(denyToolsDescription)
})
.strip();
export type SmitheryConfig = z.infer<typeof smitheryConfigSchema>;
export const mcpConfigSchema = {
$schema: "http://json-schema.org/draft-07/schema#",
$id: "https://<replace-with-host>/.well-known/mcp-config",
title: "MCP Session Configuration",
description: "Schema describing supported query parameters for the /mcp endpoint.",
"x-query-style": "dot+bracket",
type: "object",
properties: {
apiToken: {
type: "string",
title: "ClickUp API Token",
description: apiTokenDescription
},
defaultTeamId: {
type: "integer",
title: "Default Team ID",
description: defaultTeamIdDescription
},
primaryLanguage: {
type: "string",
title: "Primary Language",
description: primaryLanguageDescription
},
baseUrl: {
type: "string",
title: "ClickUp API Base URL",
description: baseUrlDescription
},
requestTimeoutMs: {
type: "integer",
title: "Request Timeout (ms)",
description: requestTimeoutDescription,
minimum: 1
},
defaultHeadersJson: {
type: "string",
title: "Default Headers JSON",
description: defaultHeadersDescription
},
authScheme: {
type: "string",
title: "Authentication Scheme",
enum: ["auto", "personal_token", "oauth"],
description: authSchemeDescription
},
allowTools: {
anyOf: [
{ type: "string" },
{ type: "array", items: { type: "string" } }
],
title: "Allowed Tools",
description: allowToolsDescription
},
denyTools: {
anyOf: [
{ type: "string" },
{ type: "array", items: { type: "string" } }
],
title: "Denied Tools",
description: denyToolsDescription
}
},
additionalProperties: false
} as const;
export type McpConfigSchema = typeof mcpConfigSchema;