@zeroheight/mcp-server 2.1.0 → 2.1.1
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/CHANGELOG.md +4 -0
- package/README.md +12 -4
- package/dist/api/api.js +31 -6
- package/dist/api/api.js.map +1 -1
- package/dist/api/page.js +8 -11
- package/dist/api/page.js.map +1 -1
- package/dist/api/styleguide.js +6 -6
- package/dist/api/styleguide.js.map +1 -1
- package/dist/api/token.js +15 -0
- package/dist/api/token.js.map +1 -0
- package/dist/api/types/token.js +5 -0
- package/dist/api/types/token.js.map +1 -0
- package/dist/auth/introspection.js +36 -0
- package/dist/auth/introspection.js.map +1 -0
- package/dist/common/credentials.js +27 -9
- package/dist/common/credentials.js.map +1 -1
- package/dist/common/formatters/token.js +10 -0
- package/dist/common/formatters/token.js.map +1 -0
- package/dist/lint/color.js +43 -0
- package/dist/lint/color.js.map +1 -0
- package/dist/lint/dimension.js +90 -0
- package/dist/lint/dimension.js.map +1 -0
- package/dist/lint/index.js +122 -0
- package/dist/lint/index.js.map +1 -0
- package/dist/lint/parser.js +462 -0
- package/dist/lint/parser.js.map +1 -0
- package/dist/lint/tokens.js +33 -0
- package/dist/lint/tokens.js.map +1 -0
- package/dist/logging.js +129 -0
- package/dist/logging.js.map +1 -0
- package/dist/mcp-server.js +9 -4
- package/dist/mcp-server.js.map +1 -1
- package/dist/tools/lint.js +74 -0
- package/dist/tools/lint.js.map +1 -0
- package/dist/tools/page.js +56 -25
- package/dist/tools/page.js.map +1 -1
- package/dist/tools/styleguide.js +22 -11
- package/dist/tools/styleguide.js.map +1 -1
- package/dist/tools/token.js +73 -0
- package/dist/tools/token.js.map +1 -0
- package/dist/types/server.js +5 -0
- package/dist/types/server.js.map +1 -0
- package/package.json +10 -3
package/dist/logging.js
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
|
|
2
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="de5a1ebe-3d68-5029-910b-6ef417fd9863")}catch(e){}}();
|
|
3
|
+
import * as amplitude from "@amplitude/analytics-node";
|
|
4
|
+
import { ApiType, internalRequest, request } from "./api/api.js";
|
|
5
|
+
import { getCredentials, isLocalMCP } from "./common/credentials.js";
|
|
6
|
+
import packageJson from "../package.json" with { type: "json" };
|
|
7
|
+
let enabled = false;
|
|
8
|
+
export function initAmplitude() {
|
|
9
|
+
const key = process.env["AMPLITUDE_API_KEY"];
|
|
10
|
+
if (!key)
|
|
11
|
+
return;
|
|
12
|
+
if (process.env["NODE_ENV"] !== "dev") {
|
|
13
|
+
amplitude.init(key);
|
|
14
|
+
}
|
|
15
|
+
enabled = true;
|
|
16
|
+
}
|
|
17
|
+
const track = (...args) => {
|
|
18
|
+
if (!enabled)
|
|
19
|
+
return;
|
|
20
|
+
if (process.env["NODE_ENV"] === "dev") {
|
|
21
|
+
console.log("Amplitude track:", ...args);
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
amplitude.track(...args);
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
function sendMcpLog(payload, credentials) {
|
|
28
|
+
const promise = isLocalMCP(credentials)
|
|
29
|
+
? request("/mcp/log", credentials, { method: "POST", body: JSON.stringify(payload) }, undefined, ApiType.Internal)
|
|
30
|
+
: internalRequest("/mcp/log", "POST", payload);
|
|
31
|
+
promise.catch((err) => console.error("Failed to send MCP log:", err));
|
|
32
|
+
}
|
|
33
|
+
function buildLogPayload(toolName, toolParameters, credentials, clientUserAgent, serverVersion, durationMs, success, errorMessage) {
|
|
34
|
+
const base = {
|
|
35
|
+
tool_name: toolName,
|
|
36
|
+
tool_parameters: toolParameters,
|
|
37
|
+
success,
|
|
38
|
+
transport: isLocalMCP(credentials) ? "local" : "remote",
|
|
39
|
+
mcp_client_user_agent: clientUserAgent,
|
|
40
|
+
mcp_server_version: serverVersion,
|
|
41
|
+
duration_ms: durationMs,
|
|
42
|
+
};
|
|
43
|
+
if (errorMessage !== undefined) {
|
|
44
|
+
base.error_message = errorMessage;
|
|
45
|
+
}
|
|
46
|
+
if (credentials.type === "jwt") {
|
|
47
|
+
base.team_id = credentials.teamId;
|
|
48
|
+
base.user_id = credentials.userId;
|
|
49
|
+
base.styleguide_id = credentials.styleguideId;
|
|
50
|
+
base.mcp_auth_id = credentials.mcpAuthId;
|
|
51
|
+
base.viewer_id = credentials.viewerId;
|
|
52
|
+
}
|
|
53
|
+
else if (credentials.type === "oauth_jwt") {
|
|
54
|
+
base.team_id = credentials.teamId;
|
|
55
|
+
base.user_id = credentials.userId;
|
|
56
|
+
base.oauth_client_id = credentials.clientId;
|
|
57
|
+
}
|
|
58
|
+
else if (isLocalMCP(credentials)) {
|
|
59
|
+
base.client_id = credentials.client;
|
|
60
|
+
}
|
|
61
|
+
return base;
|
|
62
|
+
}
|
|
63
|
+
function sanitizeToolParams(toolName, params) {
|
|
64
|
+
const sanitized = { ...params };
|
|
65
|
+
if (toolName === "lint-code") {
|
|
66
|
+
delete sanitized.code;
|
|
67
|
+
}
|
|
68
|
+
return sanitized;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Wraps a tool handler to track tool calls via Amplitude and DB logging.
|
|
72
|
+
* Resolves the client user agent centrally and passes it to the handler.
|
|
73
|
+
*/
|
|
74
|
+
export function registerTrackedToolCall(server, name, config, handler) {
|
|
75
|
+
server.registerTool(name, config, (async (args, context) => {
|
|
76
|
+
const clientVersion = server.server.getClientVersion();
|
|
77
|
+
const fallbackUserAgent = clientVersion
|
|
78
|
+
? `${clientVersion.name}/${clientVersion.version}`
|
|
79
|
+
: undefined;
|
|
80
|
+
const userAgent = getUserAgent(context.requestInfo?.headers, fallbackUserAgent);
|
|
81
|
+
const startTime = Date.now();
|
|
82
|
+
// args is loosely typed by the SDK callback; the schema guarantees correctness
|
|
83
|
+
const result = await handler(args, context, userAgent);
|
|
84
|
+
const durationMs = Date.now() - startTime;
|
|
85
|
+
const isError = result.isError ?? false;
|
|
86
|
+
const errorMessage = isError
|
|
87
|
+
? result.content.filter((item) => item.type === "text").map((item) => item.text).join("\n")
|
|
88
|
+
: undefined;
|
|
89
|
+
const credentials = await getCredentials(context.authInfo);
|
|
90
|
+
if (enabled) {
|
|
91
|
+
const eventProperties = {
|
|
92
|
+
tool_name: name,
|
|
93
|
+
tool_parameters: sanitizeToolParams(name, args),
|
|
94
|
+
success: !isError,
|
|
95
|
+
progress_token: context._meta?.progressToken,
|
|
96
|
+
mcp_client_user_agent: userAgent,
|
|
97
|
+
duration_ms: durationMs,
|
|
98
|
+
};
|
|
99
|
+
if (credentials.type === "jwt") {
|
|
100
|
+
track({
|
|
101
|
+
event_type: "mcp:tool_call",
|
|
102
|
+
event_properties: eventProperties,
|
|
103
|
+
user_properties: {
|
|
104
|
+
team_id: credentials.teamId,
|
|
105
|
+
viewer_id: credentials.viewerId,
|
|
106
|
+
styleguide_id: credentials.styleguideId,
|
|
107
|
+
},
|
|
108
|
+
user_agent: userAgent,
|
|
109
|
+
user_id: credentials.userId ? `${credentials.userId}` : undefined,
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
sendMcpLog(buildLogPayload(name, sanitizeToolParams(name, args), credentials, userAgent, packageJson.version, durationMs, !isError, errorMessage), credentials);
|
|
114
|
+
return result;
|
|
115
|
+
}));
|
|
116
|
+
}
|
|
117
|
+
const getUserAgent = (headers, fallback) => {
|
|
118
|
+
if (headers) {
|
|
119
|
+
if (Array.isArray(headers["user-agent"])) {
|
|
120
|
+
return headers["user-agent"].join(" ");
|
|
121
|
+
}
|
|
122
|
+
if (typeof headers["user-agent"] === "string") {
|
|
123
|
+
return headers["user-agent"];
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return fallback;
|
|
127
|
+
};
|
|
128
|
+
//# sourceMappingURL=logging.js.map
|
|
129
|
+
//# debugId=de5a1ebe-3d68-5029-910b-6ef417fd9863
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logging.js","sources":["logging.ts"],"sourceRoot":"/","sourcesContent":["import * as amplitude from \"@amplitude/analytics-node\";\nimport {\n McpServer,\n ToolCallback,\n} from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { RequestHandlerExtra } from \"@modelcontextprotocol/sdk/shared/protocol.js\";\nimport {\n CallToolResult,\n ServerNotification,\n ServerRequest,\n ToolAnnotations,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport z, { ZodRawShape } from \"zod\";\nimport { ApiType, internalRequest, request } from \"./api/api.js\";\nimport { Credentials, getCredentials, isLocalMCP } from \"./common/credentials.js\";\nimport packageJson from \"../package.json\" with { type: \"json\" };\n\nlet enabled = false;\nexport function initAmplitude() {\n const key = process.env[\"AMPLITUDE_API_KEY\"];\n if (!key) return;\n\n if (process.env[\"NODE_ENV\"] !== \"dev\") {\n amplitude.init(key);\n }\n enabled = true;\n}\n\nconst track = (...args: Parameters<typeof amplitude.track>) => {\n if (!enabled) return;\n\n if (process.env[\"NODE_ENV\"] === \"dev\") {\n console.log(\"Amplitude track:\", ...args);\n } else {\n amplitude.track(...args);\n }\n};\n\ninterface EventProperties {\n tool_name: string;\n tool_parameters: Record<string, unknown>;\n success: boolean;\n error_message?: string;\n progress_token?: string | number | undefined;\n mcp_client_user_agent?: string;\n duration_ms?: number;\n}\n\ninterface UserProperties {\n team_id?: number;\n viewer_id?: string;\n styleguide_id?: number;\n token?: string;\n}\n\ninterface McpLogPayload {\n tool_name: string;\n tool_parameters: Record<string, unknown>;\n success: boolean;\n error_message?: string;\n mcp_client_user_agent?: string;\n mcp_server_version?: string;\n transport: string;\n duration_ms?: number;\n team_id?: number;\n user_id?: number;\n styleguide_id?: number;\n mcp_auth_id?: number;\n viewer_id?: string;\n oauth_client_id?: string;\n client_id?: string;\n}\n\nfunction sendMcpLog(payload: McpLogPayload, credentials: Credentials): void {\n const promise =\n isLocalMCP(credentials)\n ? request(\"/mcp/log\", credentials, { method: \"POST\", body: JSON.stringify(payload) }, undefined, ApiType.Internal)\n : internalRequest(\"/mcp/log\", \"POST\", payload);\n\n promise.catch((err) => console.error(\"Failed to send MCP log:\", err));\n}\n\nfunction buildLogPayload(\n toolName: string,\n toolParameters: Record<string, unknown>,\n credentials: Credentials,\n clientUserAgent: string | undefined,\n serverVersion: string,\n durationMs: number,\n success: boolean,\n errorMessage?: string,\n): McpLogPayload {\n const base: McpLogPayload = {\n tool_name: toolName,\n tool_parameters: toolParameters,\n success,\n transport: isLocalMCP(credentials) ? \"local\" : \"remote\",\n mcp_client_user_agent: clientUserAgent,\n mcp_server_version: serverVersion,\n duration_ms: durationMs,\n };\n\n if (errorMessage !== undefined) {\n base.error_message = errorMessage;\n }\n\n if (credentials.type === \"jwt\") {\n base.team_id = credentials.teamId;\n base.user_id = credentials.userId;\n base.styleguide_id = credentials.styleguideId;\n base.mcp_auth_id = credentials.mcpAuthId;\n base.viewer_id = credentials.viewerId;\n } else if (credentials.type === \"oauth_jwt\") {\n base.team_id = credentials.teamId;\n base.user_id = credentials.userId;\n base.oauth_client_id = credentials.clientId;\n } else if (isLocalMCP(credentials)) {\n base.client_id = credentials.client;\n }\n\n return base;\n}\n\nfunction sanitizeToolParams(\n toolName: string,\n params: Record<string, unknown>,\n): Record<string, unknown> {\n const sanitized = { ...params };\n if (toolName === \"lint-code\") {\n delete sanitized.code;\n }\n return sanitized;\n}\n\nexport type TrackedToolCallback<Args extends ZodRawShape> = (\n args: z.objectOutputType<Args, z.ZodTypeAny>,\n context: RequestHandlerExtra<ServerRequest, ServerNotification>,\n clientUserAgent: string | undefined,\n) => CallToolResult | Promise<CallToolResult>;\n\n/**\n * Wraps a tool handler to track tool calls via Amplitude and DB logging.\n * Resolves the client user agent centrally and passes it to the handler.\n */\nexport function registerTrackedToolCall<\n InputArgs extends ZodRawShape,\n OutputArgs extends ZodRawShape,\n>(\n server: McpServer,\n name: string,\n config: {\n title?: string;\n description?: string;\n inputSchema?: InputArgs;\n outputSchema?: OutputArgs;\n annotations?: ToolAnnotations;\n },\n handler: TrackedToolCallback<InputArgs>,\n) {\n server.registerTool<InputArgs, OutputArgs>(name, config, (async (\n args,\n context,\n ) => {\n const clientVersion = server.server.getClientVersion();\n const fallbackUserAgent = clientVersion\n ? `${clientVersion.name}/${clientVersion.version}`\n : undefined;\n const userAgent = getUserAgent(context.requestInfo?.headers, fallbackUserAgent);\n\n const startTime = Date.now();\n // args is loosely typed by the SDK callback; the schema guarantees correctness\n const result = await handler(args as any, context, userAgent);\n const durationMs = Date.now() - startTime;\n\n const isError = result.isError ?? false;\n const errorMessage = isError\n ? result.content.filter((item) => item.type === \"text\").map((item) => item.text).join(\"\\n\")\n : undefined;\n\n const credentials = await getCredentials(context.authInfo);\n\n if (enabled) {\n const eventProperties: EventProperties = {\n tool_name: name,\n tool_parameters: sanitizeToolParams(name, args),\n success: !isError,\n progress_token: context._meta?.progressToken,\n mcp_client_user_agent: userAgent,\n duration_ms: durationMs,\n };\n\n if (credentials.type === \"jwt\") {\n track({\n event_type: \"mcp:tool_call\",\n event_properties: eventProperties,\n user_properties: {\n team_id: credentials.teamId,\n viewer_id: credentials.viewerId,\n styleguide_id: credentials.styleguideId,\n } satisfies UserProperties,\n user_agent: userAgent,\n user_id: credentials.userId ? `${credentials.userId}` : undefined,\n });\n }\n }\n\n sendMcpLog(\n buildLogPayload(\n name,\n sanitizeToolParams(name, args),\n credentials,\n userAgent,\n packageJson.version,\n durationMs,\n !isError,\n errorMessage,\n ),\n credentials,\n );\n\n return result;\n }) as ToolCallback<InputArgs>);\n}\n\nconst getUserAgent = (\n headers: Record<string, string | string[] | undefined> | undefined,\n fallback?: string,\n) => {\n if (headers) {\n if (Array.isArray(headers[\"user-agent\"])) {\n return headers[\"user-agent\"].join(\" \");\n }\n if (typeof headers[\"user-agent\"] === \"string\") {\n return headers[\"user-agent\"];\n }\n }\n return fallback;\n};\n"],"names":[],"mappings":"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","debug_id":"de5a1ebe-3d68-5029-910b-6ef417fd9863"}
|
package/dist/mcp-server.js
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
|
|
2
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
2
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="763e812a-ba2d-538d-b58f-673629728a81")}catch(e){}}();
|
|
3
3
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
4
4
|
import packageJson from "../package.json" with { type: "json" };
|
|
5
5
|
import { registerGetStyleguideTreeTool, registerListStyleguidesTool, } from "./tools/styleguide.js";
|
|
6
6
|
import { registerGetPageTool, registerListPagesTool, registerSearchPagesTool, } from "./tools/page.js";
|
|
7
|
+
import { registerGetTokensTool, registerListTokenSetsTool, } from "./tools/token.js";
|
|
8
|
+
import { registerLintCodeTool } from "./tools/lint.js";
|
|
7
9
|
import { recommendSummarizePagePrompt } from "./prompts/page.js";
|
|
8
10
|
import { registerRecommendPagesPrompt } from "./prompts/styleguide.js";
|
|
9
|
-
export function createServer(
|
|
11
|
+
export function createServer(context = { features: {} }) {
|
|
10
12
|
const server = new McpServer({
|
|
11
13
|
name: "zeroheight",
|
|
12
14
|
version: packageJson.version,
|
|
@@ -22,10 +24,13 @@ export function createServer(features = {}) {
|
|
|
22
24
|
registerListStyleguidesTool,
|
|
23
25
|
registerGetStyleguideTreeTool,
|
|
24
26
|
registerSearchPagesTool,
|
|
25
|
-
|
|
27
|
+
registerListTokenSetsTool,
|
|
28
|
+
registerGetTokensTool,
|
|
29
|
+
registerLintCodeTool,
|
|
30
|
+
].forEach((fn) => fn(server, context));
|
|
26
31
|
// Register all prompts
|
|
27
32
|
[registerRecommendPagesPrompt, recommendSummarizePagePrompt].forEach((fn) => fn(server));
|
|
28
33
|
return server;
|
|
29
34
|
}
|
|
30
35
|
//# sourceMappingURL=mcp-server.js.map
|
|
31
|
-
//# debugId=
|
|
36
|
+
//# debugId=763e812a-ba2d-538d-b58f-673629728a81
|
package/dist/mcp-server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-server.js","sources":["mcp-server.ts"],"sourceRoot":"/","sourcesContent":["import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\n\nimport packageJson from \"../package.json\" with { type: \"json\" };\nimport {\n registerGetStyleguideTreeTool,\n registerListStyleguidesTool,\n} from \"./tools/styleguide.js\";\nimport {\n registerGetPageTool,\n registerListPagesTool,\n registerSearchPagesTool,\n} from \"./tools/page.js\";\nimport { recommendSummarizePagePrompt } from \"./prompts/page.js\";\nimport { registerRecommendPagesPrompt } from \"./prompts/styleguide.js\";\n\nexport function createServer(
|
|
1
|
+
{"version":3,"file":"mcp-server.js","sources":["mcp-server.ts"],"sourceRoot":"/","sourcesContent":["import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\n\nimport packageJson from \"../package.json\" with { type: \"json\" };\nimport {\n registerGetStyleguideTreeTool,\n registerListStyleguidesTool,\n} from \"./tools/styleguide.js\";\nimport {\n registerGetPageTool,\n registerListPagesTool,\n registerSearchPagesTool,\n} from \"./tools/page.js\";\nimport {\n registerGetTokensTool,\n registerListTokenSetsTool,\n} from \"./tools/token.js\";\nimport { registerLintCodeTool } from \"./tools/lint.js\";\nimport { recommendSummarizePagePrompt } from \"./prompts/page.js\";\nimport { registerRecommendPagesPrompt } from \"./prompts/styleguide.js\";\nimport { ServerContext } from \"./types/server.js\";\n\nexport function createServer(context: ServerContext = { features: {} }) {\n const server = new McpServer({\n name: \"zeroheight\",\n version: packageJson.version,\n capabilities: {\n resources: {},\n tools: {},\n },\n });\n\n // Register tools\n [\n registerListPagesTool,\n registerGetPageTool,\n registerListStyleguidesTool,\n registerGetStyleguideTreeTool,\n registerSearchPagesTool,\n registerListTokenSetsTool,\n registerGetTokensTool,\n registerLintCodeTool,\n ].forEach((fn) => fn(server, context));\n\n // Register all prompts\n [registerRecommendPagesPrompt, recommendSummarizePagePrompt].forEach((fn) =>\n fn(server),\n );\n\n return server;\n}\n"],"names":[],"mappings":";;AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,WAAW,MAAM,iBAAiB,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AAChE,OAAO,EACL,6BAA6B,EAC7B,2BAA2B,GAC5B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,mBAAmB,EACnB,qBAAqB,EACrB,uBAAuB,GACxB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,qBAAqB,EACrB,yBAAyB,GAC1B,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,EAAE,4BAA4B,EAAE,MAAM,mBAAmB,CAAC;AACjE,OAAO,EAAE,4BAA4B,EAAE,MAAM,yBAAyB,CAAC;AAGvE,MAAM,UAAU,YAAY,CAAC,UAAyB,EAAE,QAAQ,EAAE,EAAE,EAAE;IACpE,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;QAC3B,IAAI,EAAE,YAAY;QAClB,OAAO,EAAE,WAAW,CAAC,OAAO;QAC5B,YAAY,EAAE;YACZ,SAAS,EAAE,EAAE;YACb,KAAK,EAAE,EAAE;SACV;KACF,CAAC,CAAC;IAEH,iBAAiB;IACjB;QACE,qBAAqB;QACrB,mBAAmB;QACnB,2BAA2B;QAC3B,6BAA6B;QAC7B,uBAAuB;QACvB,yBAAyB;QACzB,qBAAqB;QACrB,oBAAoB;KACrB,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAEvC,uBAAuB;IACvB,CAAC,4BAA4B,EAAE,4BAA4B,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,CAC1E,EAAE,CAAC,MAAM,CAAC,CACX,CAAC;IAEF,OAAO,MAAM,CAAC;AAChB,CAAC","debug_id":"763e812a-ba2d-538d-b58f-673629728a81"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lint Tool - lint-code MCP tool
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="ef58d605-4a30-5d61-ac2e-8edd07ea3adf")}catch(e){}}();
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
import { getTokenSetExport } from "../api/token.js";
|
|
8
|
+
import { getCredentials } from "../common/credentials.js";
|
|
9
|
+
import { registerTrackedToolCall } from "../logging.js";
|
|
10
|
+
import { lint } from "../lint/index.js";
|
|
11
|
+
export function registerLintCodeTool(server, context) {
|
|
12
|
+
if (!context.features["TREE-2686_mcp_experimental_tools"]) {
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
registerTrackedToolCall(server, "lint-code", {
|
|
16
|
+
title: "Lint code against design tokens",
|
|
17
|
+
description: "Lint CSS, SCSS, TSX, TS, JS, or JSX code against design tokens to find hardcoded values that should use tokens. IMPORTANT: Always use this tool to validate code AFTER generating CSS/SCSS/TSX/TS/JS/JSX. When violations are found, you MUST fix them by replacing hardcoded values with the suggested design tokens from the violation results before returning the code to the user. Replace only the literal value (e.g. the color hex or dimension) with the suggested token value or variable; do not add any inline comments or labels.",
|
|
18
|
+
inputSchema: {
|
|
19
|
+
code: z.string().describe("Source code to lint"),
|
|
20
|
+
language: z
|
|
21
|
+
.enum(["css", "scss", "tsx", "ts", "js", "jsx"])
|
|
22
|
+
.describe("Language of the source code"),
|
|
23
|
+
tokenSetId: z
|
|
24
|
+
.number()
|
|
25
|
+
.int()
|
|
26
|
+
.positive()
|
|
27
|
+
.describe("Token set ID to validate against"),
|
|
28
|
+
colorDistanceThreshold: z
|
|
29
|
+
.number()
|
|
30
|
+
.min(0)
|
|
31
|
+
.max(100)
|
|
32
|
+
.default(10)
|
|
33
|
+
.describe("Color distance threshold for suggestions (0-100, default 10)"),
|
|
34
|
+
},
|
|
35
|
+
}, async ({ code, language, tokenSetId, colorDistanceThreshold }, { authInfo }, clientUserAgent) => {
|
|
36
|
+
const credentials = await getCredentials(authInfo);
|
|
37
|
+
const tokens = await getTokenSetExport(credentials, tokenSetId, clientUserAgent);
|
|
38
|
+
if (tokens === null) {
|
|
39
|
+
return {
|
|
40
|
+
isError: true,
|
|
41
|
+
content: [
|
|
42
|
+
{
|
|
43
|
+
type: "text",
|
|
44
|
+
text: "Could not fetch tokens for this token set. Check that the token set ID is valid.",
|
|
45
|
+
},
|
|
46
|
+
],
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
const violations = lint(code, language, tokens, colorDistanceThreshold);
|
|
50
|
+
const byType = violations.reduce((acc, v) => {
|
|
51
|
+
acc[v.type] = (acc[v.type] || 0) + 1;
|
|
52
|
+
return acc;
|
|
53
|
+
}, {});
|
|
54
|
+
const result = {
|
|
55
|
+
violations,
|
|
56
|
+
tokenSetId,
|
|
57
|
+
summary: {
|
|
58
|
+
total: violations.length,
|
|
59
|
+
byType,
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
return {
|
|
63
|
+
content: [
|
|
64
|
+
{
|
|
65
|
+
type: "text",
|
|
66
|
+
text: JSON.stringify(result, null, 2),
|
|
67
|
+
mimeType: "application/json",
|
|
68
|
+
},
|
|
69
|
+
],
|
|
70
|
+
};
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=lint.js.map
|
|
74
|
+
//# debugId=ef58d605-4a30-5d61-ac2e-8edd07ea3adf
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lint.js","sources":["tools/lint.ts"],"sourceRoot":"/","sourcesContent":["/**\n * Lint Tool - lint-code MCP tool\n */\n\nimport { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\n\nimport { getTokenSetExport } from \"../api/token.js\";\nimport { getCredentials } from \"../common/credentials.js\";\nimport { registerTrackedToolCall } from \"../logging.js\";\nimport { lint, type Language } from \"../lint/index.js\";\nimport { ServerContext } from \"../types/server.js\";\n\nexport function registerLintCodeTool(\n server: McpServer,\n context: ServerContext,\n) {\n if (!context.features[\"TREE-2686_mcp_experimental_tools\"]) {\n return;\n }\n\n registerTrackedToolCall(\n server,\n \"lint-code\",\n {\n title: \"Lint code against design tokens\",\n description:\n \"Lint CSS, SCSS, TSX, TS, JS, or JSX code against design tokens to find hardcoded values that should use tokens. IMPORTANT: Always use this tool to validate code AFTER generating CSS/SCSS/TSX/TS/JS/JSX. When violations are found, you MUST fix them by replacing hardcoded values with the suggested design tokens from the violation results before returning the code to the user. Replace only the literal value (e.g. the color hex or dimension) with the suggested token value or variable; do not add any inline comments or labels.\",\n inputSchema: {\n code: z.string().describe(\"Source code to lint\"),\n language: z\n .enum([\"css\", \"scss\", \"tsx\", \"ts\", \"js\", \"jsx\"])\n .describe(\"Language of the source code\"),\n tokenSetId: z\n .number()\n .int()\n .positive()\n .describe(\"Token set ID to validate against\"),\n colorDistanceThreshold: z\n .number()\n .min(0)\n .max(100)\n .default(10)\n .describe(\n \"Color distance threshold for suggestions (0-100, default 10)\",\n ),\n },\n },\n async (\n { code, language, tokenSetId, colorDistanceThreshold },\n { authInfo },\n clientUserAgent,\n ) => {\n const credentials = await getCredentials(authInfo);\n const tokens = await getTokenSetExport(credentials, tokenSetId, clientUserAgent);\n\n if (tokens === null) {\n return {\n isError: true,\n content: [\n {\n type: \"text\",\n text: \"Could not fetch tokens for this token set. Check that the token set ID is valid.\",\n },\n ],\n };\n }\n\n const violations = lint(\n code,\n language as Language,\n tokens,\n colorDistanceThreshold,\n );\n\n const byType = violations.reduce(\n (acc, v) => {\n acc[v.type] = (acc[v.type] || 0) + 1;\n return acc;\n },\n {} as Record<string, number>,\n );\n\n const result = {\n violations,\n tokenSetId,\n summary: {\n total: violations.length,\n byType,\n },\n };\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(result, null, 2),\n mimeType: \"application/json\",\n },\n ],\n };\n },\n );\n}\n"],"names":[],"mappings":"AAAA;;GAEG;;;AAGH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,EAAE,IAAI,EAAiB,MAAM,kBAAkB,CAAC;AAGvD,MAAM,UAAU,oBAAoB,CAClC,MAAiB,EACjB,OAAsB;IAEtB,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,kCAAkC,CAAC,EAAE,CAAC;QAC1D,OAAO;IACT,CAAC;IAED,uBAAuB,CACrB,MAAM,EACN,WAAW,EACX;QACE,KAAK,EAAE,iCAAiC;QACxC,WAAW,EACT,ghBAAghB;QAClhB,WAAW,EAAE;YACX,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,qBAAqB,CAAC;YAChD,QAAQ,EAAE,CAAC;iBACR,IAAI,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;iBAC/C,QAAQ,CAAC,6BAA6B,CAAC;YAC1C,UAAU,EAAE,CAAC;iBACV,MAAM,EAAE;iBACR,GAAG,EAAE;iBACL,QAAQ,EAAE;iBACV,QAAQ,CAAC,kCAAkC,CAAC;YAC/C,sBAAsB,EAAE,CAAC;iBACtB,MAAM,EAAE;iBACR,GAAG,CAAC,CAAC,CAAC;iBACN,GAAG,CAAC,GAAG,CAAC;iBACR,OAAO,CAAC,EAAE,CAAC;iBACX,QAAQ,CACP,8DAA8D,CAC/D;SACJ;KACF,EACD,KAAK,EACH,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,sBAAsB,EAAE,EACtD,EAAE,QAAQ,EAAE,EACZ,eAAe,EACf,EAAE;QACF,MAAM,WAAW,GAAG,MAAM,cAAc,CAAC,QAAQ,CAAC,CAAC;QACnD,MAAM,MAAM,GAAG,MAAM,iBAAiB,CAAC,WAAW,EAAE,UAAU,EAAE,eAAe,CAAC,CAAC;QAEjF,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;YACpB,OAAO;gBACL,OAAO,EAAE,IAAI;gBACb,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,kFAAkF;qBACzF;iBACF;aACF,CAAC;QACJ,CAAC;QAED,MAAM,UAAU,GAAG,IAAI,CACrB,IAAI,EACJ,QAAoB,EACpB,MAAM,EACN,sBAAsB,CACvB,CAAC;QAEF,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,CAC9B,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE;YACT,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;YACrC,OAAO,GAAG,CAAC;QACb,CAAC,EACD,EAA4B,CAC7B,CAAC;QAEF,MAAM,MAAM,GAAG;YACb,UAAU;YACV,UAAU;YACV,OAAO,EAAE;gBACP,KAAK,EAAE,UAAU,CAAC,MAAM;gBACxB,MAAM;aACP;SACF,CAAC;QAEF,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;oBACrC,QAAQ,EAAE,kBAAkB;iBAC7B;aACF;SACF,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC","debug_id":"ef58d605-4a30-5d61-ac2e-8edd07ea3adf"}
|
package/dist/tools/page.js
CHANGED
|
@@ -2,21 +2,37 @@
|
|
|
2
2
|
* Page Tools
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
5
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="2ab3f4ac-1c8c-55d1-a9ba-f8cdbfa3c8dd")}catch(e){}}();
|
|
6
6
|
import z from "zod";
|
|
7
7
|
import { getPage, listPages, searchPages } from "../api/page.js";
|
|
8
8
|
import { formatPageAsMarkdown, formatPageListItemsAsMarkdown, } from "../common/formatters/page.js";
|
|
9
9
|
import { getCredentials } from "../common/credentials.js";
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
import { registerTrackedToolCall } from "../logging.js";
|
|
11
|
+
export function registerListPagesTool(server, _context) {
|
|
12
|
+
registerTrackedToolCall(server, "list-pages", {
|
|
12
13
|
title: "List pages for a styleguide",
|
|
13
|
-
description: "
|
|
14
|
+
description: "Explore the pages within a design system to find guidance relevant to the task.\n\n*Useful when generating UI that should align with documented component usage, patterns, or interaction recommendations rather than inferred solutions.*",
|
|
14
15
|
inputSchema: {
|
|
15
|
-
styleguideId: z
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
styleguideId: z
|
|
17
|
+
.number()
|
|
18
|
+
.int()
|
|
19
|
+
.min(1)
|
|
20
|
+
.describe("The design system to reference. Use `list-styleguides` to discover available systems"),
|
|
21
|
+
releaseId: z
|
|
22
|
+
.number()
|
|
23
|
+
.int()
|
|
24
|
+
.min(1)
|
|
25
|
+
.describe("Optional. Returns guidelines for the default release if omitted. User can specify when a particular release is relevant.")
|
|
26
|
+
.optional(),
|
|
27
|
+
searchTerm: z
|
|
28
|
+
.string()
|
|
29
|
+
.describe("Optional. Filters pages by name and is helpful when looking for guidance related to a specific component, pattern, or concept.")
|
|
30
|
+
.optional(),
|
|
18
31
|
},
|
|
19
|
-
|
|
32
|
+
annotations: {
|
|
33
|
+
readOnlyHint: true,
|
|
34
|
+
},
|
|
35
|
+
}, async ({ styleguideId, releaseId, searchTerm }, { authInfo }, clientUserAgent) => {
|
|
20
36
|
const credentials = await getCredentials(authInfo);
|
|
21
37
|
if (credentials.type === "jwt" &&
|
|
22
38
|
credentials.styleguideId !== styleguideId) {
|
|
@@ -33,7 +49,7 @@ export function registerListPagesTool(server, _features) {
|
|
|
33
49
|
const pages = await listPages(credentials, styleguideId, {
|
|
34
50
|
releaseId,
|
|
35
51
|
searchTerm,
|
|
36
|
-
});
|
|
52
|
+
}, clientUserAgent);
|
|
37
53
|
if (pages.length === 0) {
|
|
38
54
|
return {
|
|
39
55
|
isError: true,
|
|
@@ -56,18 +72,30 @@ export function registerListPagesTool(server, _features) {
|
|
|
56
72
|
};
|
|
57
73
|
});
|
|
58
74
|
}
|
|
59
|
-
export function registerGetPageTool(server,
|
|
60
|
-
server
|
|
75
|
+
export function registerGetPageTool(server, _context) {
|
|
76
|
+
registerTrackedToolCall(server, "get-page", {
|
|
61
77
|
title: "Get a styleguide page",
|
|
62
|
-
description: "
|
|
78
|
+
description: "Fetch guidance from a specific design system page, including usage notes, recommendations, and supporting context.\n\n*Particularly helpful ahead of UI generation to increase the likelihood that outputs reflect the intent of the design system.*",
|
|
63
79
|
inputSchema: {
|
|
64
|
-
pageId: z
|
|
65
|
-
|
|
66
|
-
|
|
80
|
+
pageId: z
|
|
81
|
+
.string()
|
|
82
|
+
.describe("Identifies the page containing relevant guidance. Use `list-pages` or `get-styleguide-tree` to locate it."),
|
|
83
|
+
releaseId: z
|
|
84
|
+
.number()
|
|
85
|
+
.int()
|
|
86
|
+
.describe("Optional. Returns guidelines for the default release if omitted. User can specify when a particular release is relevant.")
|
|
87
|
+
.optional(),
|
|
88
|
+
responseFormat: z
|
|
89
|
+
.enum(["markdown", "json"])
|
|
90
|
+
.describe("Choose the format best suited to the task — markdown is often easier for reasoning, while JSON supports structured workflows.")
|
|
91
|
+
.default("json"),
|
|
67
92
|
},
|
|
68
|
-
|
|
93
|
+
annotations: {
|
|
94
|
+
readOnlyHint: true,
|
|
95
|
+
},
|
|
96
|
+
}, async ({ pageId, releaseId, responseFormat }, { authInfo }, clientUserAgent) => {
|
|
69
97
|
const credentials = await getCredentials(authInfo);
|
|
70
|
-
const page = await getPage(credentials, pageId);
|
|
98
|
+
const page = await getPage(credentials, pageId, { releaseId }, clientUserAgent);
|
|
71
99
|
if (!page) {
|
|
72
100
|
return {
|
|
73
101
|
isError: true,
|
|
@@ -101,20 +129,23 @@ export function registerGetPageTool(server, _features) {
|
|
|
101
129
|
};
|
|
102
130
|
});
|
|
103
131
|
}
|
|
104
|
-
export function registerSearchPagesTool(server,
|
|
105
|
-
if (features["SKI_2466_bedrock_indexing"] !== true) {
|
|
132
|
+
export function registerSearchPagesTool(server, context) {
|
|
133
|
+
if (context.features["SKI_2466_bedrock_indexing"] !== true) {
|
|
106
134
|
return;
|
|
107
135
|
}
|
|
108
|
-
server
|
|
136
|
+
registerTrackedToolCall(server, "search-pages", {
|
|
109
137
|
title: "Search pages in a styleguide",
|
|
110
138
|
description: "Search for pages in a styleguide by a search term",
|
|
111
139
|
inputSchema: {
|
|
112
|
-
styleguideId: z.number().int().
|
|
113
|
-
releaseId: z.number().int().
|
|
140
|
+
styleguideId: z.number().int().min(1),
|
|
141
|
+
releaseId: z.number().int().min(1).optional(),
|
|
114
142
|
searchTerm: z.string(),
|
|
115
143
|
responseFormat: z.enum(["markdown", "json"]).default("json"),
|
|
116
144
|
},
|
|
117
|
-
|
|
145
|
+
annotations: {
|
|
146
|
+
readOnlyHint: true,
|
|
147
|
+
},
|
|
148
|
+
}, async ({ styleguideId, searchTerm, releaseId, responseFormat }, { authInfo }, clientUserAgent) => {
|
|
118
149
|
const credentials = await getCredentials(authInfo);
|
|
119
150
|
if (credentials.type === "jwt" &&
|
|
120
151
|
credentials.styleguideId !== styleguideId) {
|
|
@@ -128,7 +159,7 @@ export function registerSearchPagesTool(server, features) {
|
|
|
128
159
|
],
|
|
129
160
|
};
|
|
130
161
|
}
|
|
131
|
-
const results = await searchPages(credentials, styleguideId, searchTerm, releaseId);
|
|
162
|
+
const results = await searchPages(credentials, styleguideId, searchTerm, releaseId, clientUserAgent);
|
|
132
163
|
if (results.length === 0) {
|
|
133
164
|
return {
|
|
134
165
|
isError: true,
|
|
@@ -163,4 +194,4 @@ export function registerSearchPagesTool(server, features) {
|
|
|
163
194
|
});
|
|
164
195
|
}
|
|
165
196
|
//# sourceMappingURL=page.js.map
|
|
166
|
-
//# debugId=
|
|
197
|
+
//# debugId=2ab3f4ac-1c8c-55d1-a9ba-f8cdbfa3c8dd
|
package/dist/tools/page.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"page.js","sources":["tools/page.ts"],"sourceRoot":"/","sourcesContent":["/**\n * Page Tools\n */\n\nimport { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport z from \"zod\";\n\nimport { getPage, listPages, searchPages } from \"../api/page.js\";\nimport {\n formatPageAsMarkdown,\n formatPageListItemsAsMarkdown,\n} from \"../common/formatters/page.js\";\nimport { getCredentials } from \"../common/credentials.js\";\n\nexport function registerListPagesTool(\n server: McpServer,\n _features: Record<string, boolean>\n) {\n server.registerTool(\n \"list-pages\",\n {\n title: \"List pages for a styleguide\",\n description: \"List all accessible pages in a styleguide\",\n inputSchema: {\n styleguideId: z.number().int().positive(),\n releaseId: z.number().int().positive().optional(),\n searchTerm: z.string().optional(),\n },\n },\n async ({ styleguideId, releaseId, searchTerm }, { authInfo }) => {\n const credentials = await getCredentials(authInfo);\n if (\n credentials.type === \"jwt\" &&\n credentials.styleguideId !== styleguideId\n ) {\n return {\n isError: true,\n content: [\n {\n type: \"text\",\n text: \"You do not have access to this styleguide\",\n },\n ],\n };\n }\n\n const pages = await listPages(credentials, styleguideId, {\n releaseId,\n searchTerm,\n });\n\n if (pages.length === 0) {\n return {\n isError: true,\n content: [\n {\n type: \"text\",\n text: \"There are no pages in this styleguide, check you have the correct styleguide ID\",\n },\n ],\n };\n }\n\n return {\n content: [\n {\n type: \"text\",\n text: formatPageListItemsAsMarkdown(pages),\n mimeType: \"text/markdown\",\n },\n ],\n };\n }\n );\n}\n\nexport function registerGetPageTool(\n server: McpServer,\n _features: Record<string, boolean>\n) {\n server.registerTool(\n \"get-page\",\n {\n title: \"Get a styleguide page\",\n description: \"Get a page in the requested format\",\n inputSchema: {\n pageId: z.string(),\n releaseId: z.number().int().optional(),\n responseFormat: z.enum([\"markdown\", \"json\"]).default(\"json\"),\n },\n },\n async ({ pageId, responseFormat }, { authInfo }) => {\n const credentials = await getCredentials(authInfo);\n const page = await getPage(credentials, pageId);\n\n if (!page) {\n return {\n isError: true,\n content: [\n {\n type: \"text\",\n text: \"Could not find the page, check you have the correct page ID and release ID.\",\n },\n ],\n };\n }\n\n if (responseFormat === \"markdown\") {\n return {\n content: [\n {\n type: \"text\",\n text: formatPageAsMarkdown(page),\n mimeType: \"text/markdown\",\n },\n ],\n };\n }\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(page, null, 2),\n mimeType: \"application/json\",\n },\n ],\n };\n }\n );\n}\n\nexport function registerSearchPagesTool(\n server: McpServer,\n features: Record<string, boolean>\n) {\n if (features[\"SKI_2466_bedrock_indexing\"] !== true) {\n return;\n }\n server.registerTool(\n \"search-pages\",\n {\n title: \"Search pages in a styleguide\",\n description: \"Search for pages in a styleguide by a search term\",\n inputSchema: {\n styleguideId: z.number().int().positive(),\n releaseId: z.number().int().positive().optional(),\n searchTerm: z.string(),\n responseFormat: z.enum([\"markdown\", \"json\"]).default(\"json\"),\n },\n },\n async (\n { styleguideId, searchTerm, releaseId, responseFormat },\n { authInfo }\n ) => {\n const credentials = await getCredentials(authInfo);\n if (\n credentials.type === \"jwt\" &&\n credentials.styleguideId !== styleguideId\n ) {\n return {\n isError: true,\n content: [\n {\n type: \"text\",\n text: \"You do not have access to this styleguide\",\n },\n ],\n };\n }\n\n const results = await searchPages(\n credentials,\n styleguideId,\n searchTerm,\n releaseId\n );\n\n if (results.length === 0) {\n return {\n isError: true,\n content: [\n {\n type: \"text\",\n text: \"No pages match that search term, try something else.\",\n },\n ],\n };\n }\n\n if (responseFormat === \"markdown\") {\n return {\n content: [\n {\n type: \"text\",\n text: formatPageListItemsAsMarkdown(results),\n mimeType: \"text/markdown\",\n },\n ],\n };\n }\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(results, null, 2),\n mimeType: \"application/json\",\n },\n ],\n };\n }\n );\n}\n"],"names":[],"mappings":"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","debug_id":"dcf209c1-22ae-5f43-8f9e-0a88d093d5f0"}
|
|
1
|
+
{"version":3,"file":"page.js","sources":["tools/page.ts"],"sourceRoot":"/","sourcesContent":["/**\n * Page Tools\n */\n\nimport { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport z from \"zod\";\n\nimport { getPage, listPages, searchPages } from \"../api/page.js\";\nimport {\n formatPageAsMarkdown,\n formatPageListItemsAsMarkdown,\n} from \"../common/formatters/page.js\";\nimport { getCredentials } from \"../common/credentials.js\";\nimport { registerTrackedToolCall } from \"../logging.js\";\nimport { ServerContext } from \"../types/server.js\";\n\nexport function registerListPagesTool(\n server: McpServer,\n _context: ServerContext,\n) {\n registerTrackedToolCall(\n server,\n \"list-pages\",\n {\n title: \"List pages for a styleguide\",\n description:\n \"Explore the pages within a design system to find guidance relevant to the task.\\n\\n*Useful when generating UI that should align with documented component usage, patterns, or interaction recommendations rather than inferred solutions.*\",\n inputSchema: {\n styleguideId: z\n .number()\n .int()\n .min(1)\n .describe(\n \"The design system to reference. Use `list-styleguides` to discover available systems\",\n ),\n releaseId: z\n .number()\n .int()\n .min(1)\n .describe(\n \"Optional. Returns guidelines for the default release if omitted. User can specify when a particular release is relevant.\",\n )\n .optional(),\n searchTerm: z\n .string()\n .describe(\n \"Optional. Filters pages by name and is helpful when looking for guidance related to a specific component, pattern, or concept.\",\n )\n .optional(),\n },\n annotations: {\n readOnlyHint: true,\n },\n },\n async ({ styleguideId, releaseId, searchTerm }, { authInfo }, clientUserAgent) => {\n const credentials = await getCredentials(authInfo);\n if (\n credentials.type === \"jwt\" &&\n credentials.styleguideId !== styleguideId\n ) {\n return {\n isError: true,\n content: [\n {\n type: \"text\",\n text: \"You do not have access to this styleguide\",\n },\n ],\n };\n }\n\n const pages = await listPages(credentials, styleguideId, {\n releaseId,\n searchTerm,\n }, clientUserAgent);\n\n if (pages.length === 0) {\n return {\n isError: true,\n content: [\n {\n type: \"text\",\n text: \"There are no pages in this styleguide, check you have the correct styleguide ID\",\n },\n ],\n };\n }\n\n return {\n content: [\n {\n type: \"text\",\n text: formatPageListItemsAsMarkdown(pages),\n mimeType: \"text/markdown\",\n },\n ],\n };\n },\n );\n}\n\nexport function registerGetPageTool(\n server: McpServer,\n _context: ServerContext,\n) {\n registerTrackedToolCall(\n server,\n \"get-page\",\n {\n title: \"Get a styleguide page\",\n description:\n \"Fetch guidance from a specific design system page, including usage notes, recommendations, and supporting context.\\n\\n*Particularly helpful ahead of UI generation to increase the likelihood that outputs reflect the intent of the design system.*\",\n inputSchema: {\n pageId: z\n .string()\n .describe(\n \"Identifies the page containing relevant guidance. Use `list-pages` or `get-styleguide-tree` to locate it.\",\n ),\n releaseId: z\n .number()\n .int()\n .describe(\n \"Optional. Returns guidelines for the default release if omitted. User can specify when a particular release is relevant.\",\n )\n .optional(),\n responseFormat: z\n .enum([\"markdown\", \"json\"])\n .describe(\n \"Choose the format best suited to the task — markdown is often easier for reasoning, while JSON supports structured workflows.\",\n )\n .default(\"json\"),\n },\n annotations: {\n readOnlyHint: true,\n },\n },\n async ({ pageId, releaseId, responseFormat }, { authInfo }, clientUserAgent) => {\n const credentials = await getCredentials(authInfo);\n const page = await getPage(credentials, pageId, { releaseId }, clientUserAgent);\n\n if (!page) {\n return {\n isError: true,\n content: [\n {\n type: \"text\",\n text: \"Could not find the page, check you have the correct page ID and release ID.\",\n },\n ],\n };\n }\n\n if (responseFormat === \"markdown\") {\n return {\n content: [\n {\n type: \"text\",\n text: formatPageAsMarkdown(page),\n mimeType: \"text/markdown\",\n },\n ],\n };\n }\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(page, null, 2),\n mimeType: \"application/json\",\n },\n ],\n };\n },\n );\n}\n\nexport function registerSearchPagesTool(\n server: McpServer,\n context: ServerContext,\n) {\n if (context.features[\"SKI_2466_bedrock_indexing\"] !== true) {\n return;\n }\n registerTrackedToolCall(\n server,\n \"search-pages\",\n {\n title: \"Search pages in a styleguide\",\n description: \"Search for pages in a styleguide by a search term\",\n inputSchema: {\n styleguideId: z.number().int().min(1),\n releaseId: z.number().int().min(1).optional(),\n searchTerm: z.string(),\n responseFormat: z.enum([\"markdown\", \"json\"]).default(\"json\"),\n },\n annotations: {\n readOnlyHint: true,\n },\n },\n async (\n { styleguideId, searchTerm, releaseId, responseFormat },\n { authInfo },\n clientUserAgent,\n ) => {\n const credentials = await getCredentials(authInfo);\n if (\n credentials.type === \"jwt\" &&\n credentials.styleguideId !== styleguideId\n ) {\n return {\n isError: true,\n content: [\n {\n type: \"text\",\n text: \"You do not have access to this styleguide\",\n },\n ],\n };\n }\n\n const results = await searchPages(\n credentials,\n styleguideId,\n searchTerm,\n releaseId,\n clientUserAgent,\n );\n\n if (results.length === 0) {\n return {\n isError: true,\n content: [\n {\n type: \"text\",\n text: \"No pages match that search term, try something else.\",\n },\n ],\n };\n }\n\n if (responseFormat === \"markdown\") {\n return {\n content: [\n {\n type: \"text\",\n text: formatPageListItemsAsMarkdown(results),\n mimeType: \"text/markdown\",\n },\n ],\n };\n }\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(results, null, 2),\n mimeType: \"application/json\",\n },\n ],\n };\n },\n );\n}\n"],"names":[],"mappings":"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","debug_id":"2ab3f4ac-1c8c-55d1-a9ba-f8cdbfa3c8dd"}
|
package/dist/tools/styleguide.js
CHANGED
|
@@ -2,19 +2,23 @@
|
|
|
2
2
|
* Styleguide Tools
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
5
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="ac7b3567-e927-57fc-9ca1-250c0ff89baa")}catch(e){}}();
|
|
6
6
|
import z from "zod";
|
|
7
7
|
import { getStyleguideTree, listStyleguides } from "../api/styleguide.js";
|
|
8
8
|
import { formatStyleguideListAsMarkdown, formatTreeAsJson, } from "../common/formatters/styleguide.js";
|
|
9
9
|
import { getCredentials } from "../common/credentials.js";
|
|
10
|
+
import { registerTrackedToolCall } from "../logging.js";
|
|
10
11
|
export function registerListStyleguidesTool(server) {
|
|
11
|
-
server
|
|
12
|
+
registerTrackedToolCall(server, "list-styleguides", {
|
|
12
13
|
title: "List styleguides",
|
|
13
|
-
description: "
|
|
14
|
+
description: "Discover available design systems that provide documented guidance for components, patterns, and styles. If multiple systems are available, confirm with the user which should be used.\n\n*Helpful to reference before generating UI so decisions can reflect established design approaches.*",
|
|
14
15
|
inputSchema: {},
|
|
15
|
-
|
|
16
|
+
annotations: {
|
|
17
|
+
readOnlyHint: true,
|
|
18
|
+
},
|
|
19
|
+
}, async (_, { authInfo }, clientUserAgent) => {
|
|
16
20
|
const credentials = await getCredentials(authInfo);
|
|
17
|
-
const styleguides = await listStyleguides(credentials);
|
|
21
|
+
const styleguides = await listStyleguides(credentials, clientUserAgent);
|
|
18
22
|
if (styleguides.length === 0) {
|
|
19
23
|
return {
|
|
20
24
|
isError: true,
|
|
@@ -38,16 +42,23 @@ export function registerListStyleguidesTool(server) {
|
|
|
38
42
|
});
|
|
39
43
|
}
|
|
40
44
|
export function registerGetStyleguideTreeTool(server) {
|
|
41
|
-
server
|
|
45
|
+
registerTrackedToolCall(server, "get-styleguide-tree", {
|
|
42
46
|
title: "Get styleguide tree",
|
|
43
|
-
description: "
|
|
47
|
+
description: "View the navigation hierarchy of a design system — including categories, pages, and tabs — to better understand how guidance is organized.\n\n*Helpful when determining where to look for component or pattern documentation before generating UI.*",
|
|
44
48
|
inputSchema: {
|
|
45
|
-
styleguideId: z
|
|
49
|
+
styleguideId: z
|
|
50
|
+
.number()
|
|
51
|
+
.int()
|
|
52
|
+
.min(1)
|
|
53
|
+
.describe("The design system to reference. Use `list-styleguides` to discover available systems."),
|
|
54
|
+
},
|
|
55
|
+
annotations: {
|
|
56
|
+
readOnlyHint: true,
|
|
46
57
|
},
|
|
47
|
-
}, async ({ styleguideId }, { authInfo }) => {
|
|
58
|
+
}, async ({ styleguideId }, { authInfo }, clientUserAgent) => {
|
|
48
59
|
try {
|
|
49
60
|
const credentials = await getCredentials(authInfo);
|
|
50
|
-
const tree = await getStyleguideTree(credentials, styleguideId);
|
|
61
|
+
const tree = await getStyleguideTree(credentials, styleguideId, clientUserAgent);
|
|
51
62
|
const formattedTree = formatTreeAsJson(tree);
|
|
52
63
|
return {
|
|
53
64
|
content: [
|
|
@@ -72,4 +83,4 @@ export function registerGetStyleguideTreeTool(server) {
|
|
|
72
83
|
});
|
|
73
84
|
}
|
|
74
85
|
//# sourceMappingURL=styleguide.js.map
|
|
75
|
-
//# debugId=
|
|
86
|
+
//# debugId=ac7b3567-e927-57fc-9ca1-250c0ff89baa
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"styleguide.js","sources":["tools/styleguide.ts"],"sourceRoot":"/","sourcesContent":["/**\n * Styleguide Tools\n */\n\nimport { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport z from \"zod\";\n\nimport { getStyleguideTree, listStyleguides } from \"../api/styleguide.js\";\nimport {\n DEFAULT_NAME,\n formatStyleguideListAsMarkdown,\n formatTreeAsJson,\n} from \"../common/formatters/styleguide.js\";\nimport { getCredentials } from \"../common/credentials.js\";\n\nexport function registerListStyleguidesTool(server: McpServer) {\n
|
|
1
|
+
{"version":3,"file":"styleguide.js","sources":["tools/styleguide.ts"],"sourceRoot":"/","sourcesContent":["/**\n * Styleguide Tools\n */\n\nimport { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport z from \"zod\";\n\nimport { getStyleguideTree, listStyleguides } from \"../api/styleguide.js\";\nimport {\n DEFAULT_NAME,\n formatStyleguideListAsMarkdown,\n formatTreeAsJson,\n} from \"../common/formatters/styleguide.js\";\nimport { getCredentials } from \"../common/credentials.js\";\nimport { registerTrackedToolCall } from \"../logging.js\";\n\nexport function registerListStyleguidesTool(server: McpServer) {\n registerTrackedToolCall(\n server,\n \"list-styleguides\",\n {\n title: \"List styleguides\",\n description:\n \"Discover available design systems that provide documented guidance for components, patterns, and styles. If multiple systems are available, confirm with the user which should be used.\\n\\n*Helpful to reference before generating UI so decisions can reflect established design approaches.*\",\n inputSchema: {},\n annotations: {\n readOnlyHint: true,\n },\n },\n async (_, { authInfo }, clientUserAgent) => {\n const credentials = await getCredentials(authInfo);\n const styleguides = await listStyleguides(credentials, clientUserAgent);\n\n if (styleguides.length === 0) {\n return {\n isError: true,\n content: [\n {\n type: \"text\",\n text: \"There are no accessible styleguides. Check your auth credentials and make sure you have at least one styleguide in zeroheight.\",\n },\n ],\n };\n }\n\n return {\n content: [\n {\n type: \"text\",\n text: formatStyleguideListAsMarkdown(styleguides),\n mimeType: \"text/markdown\",\n },\n ],\n };\n }\n );\n}\n\nexport function registerGetStyleguideTreeTool(server: McpServer) {\n registerTrackedToolCall(\n server,\n \"get-styleguide-tree\",\n {\n title: \"Get styleguide tree\",\n description:\n \"View the navigation hierarchy of a design system — including categories, pages, and tabs — to better understand how guidance is organized.\\n\\n*Helpful when determining where to look for component or pattern documentation before generating UI.*\",\n inputSchema: {\n styleguideId: z\n .number()\n .int()\n .min(1)\n .describe(\n \"The design system to reference. Use `list-styleguides` to discover available systems.\",\n ),\n },\n annotations: {\n readOnlyHint: true,\n },\n },\n async ({ styleguideId }, { authInfo }, clientUserAgent) => {\n try {\n const credentials = await getCredentials(authInfo);\n const tree = await getStyleguideTree(credentials, styleguideId, clientUserAgent);\n const formattedTree = formatTreeAsJson(tree);\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(formattedTree, null, 2),\n },\n ],\n };\n } catch {\n return {\n isError: true,\n content: [\n {\n type: \"text\",\n text: \"Could not get the navigation tree for this styleguide.\",\n },\n ],\n };\n }\n },\n );\n}\n"],"names":[],"mappings":"AAAA;;GAEG;;;AAGH,OAAO,CAAC,MAAM,KAAK,CAAC;AAEpB,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC1E,OAAO,EAEL,8BAA8B,EAC9B,gBAAgB,GACjB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAExD,MAAM,UAAU,2BAA2B,CAAC,MAAiB;IAC3D,uBAAuB,CACrB,MAAM,EACN,kBAAkB,EAClB;QACE,KAAK,EAAE,kBAAkB;QACzB,WAAW,EACT,gSAAgS;QAClS,WAAW,EAAE,EAAE;QACf,WAAW,EAAE;YACX,YAAY,EAAE,IAAI;SACnB;KACF,EACD,KAAK,EAAE,CAAC,EAAE,EAAE,QAAQ,EAAE,EAAE,eAAe,EAAE,EAAE;QACzC,MAAM,WAAW,GAAG,MAAM,cAAc,CAAC,QAAQ,CAAC,CAAC;QACnD,MAAM,WAAW,GAAG,MAAM,eAAe,CAAC,WAAW,EAAE,eAAe,CAAC,CAAC;QAExE,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC7B,OAAO;gBACL,OAAO,EAAE,IAAI;gBACb,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,gIAAgI;qBACvI;iBACF;aACF,CAAC;QACJ,CAAC;QAED,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,8BAA8B,CAAC,WAAW,CAAC;oBACjD,QAAQ,EAAE,eAAe;iBAC1B;aACF;SACF,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,6BAA6B,CAAC,MAAiB;IAC7D,uBAAuB,CACrB,MAAM,EACN,qBAAqB,EACrB;QACE,KAAK,EAAE,qBAAqB;QAC5B,WAAW,EACT,qPAAqP;QACvP,WAAW,EAAE;YACX,YAAY,EAAE,CAAC;iBACZ,MAAM,EAAE;iBACR,GAAG,EAAE;iBACL,GAAG,CAAC,CAAC,CAAC;iBACN,QAAQ,CACP,uFAAuF,CACxF;SACJ;QACD,WAAW,EAAE;YACX,YAAY,EAAE,IAAI;SACnB;KACF,EACD,KAAK,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,eAAe,EAAE,EAAE;QACxD,IAAI,CAAC;YACH,MAAM,WAAW,GAAG,MAAM,cAAc,CAAC,QAAQ,CAAC,CAAC;YACnD,MAAM,IAAI,GAAG,MAAM,iBAAiB,CAAC,WAAW,EAAE,YAAY,EAAE,eAAe,CAAC,CAAC;YACjF,MAAM,aAAa,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;YAE7C,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;qBAC7C;iBACF;aACF,CAAC;QACJ,CAAC;QAAC,MAAM,CAAC;YACP,OAAO;gBACL,OAAO,EAAE,IAAI;gBACb,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,wDAAwD;qBAC/D;iBACF;aACF,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC","debug_id":"ac7b3567-e927-57fc-9ca1-250c0ff89baa"}
|