@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/CHANGELOG.md
CHANGED
package/README.md
CHANGED
|
@@ -43,16 +43,24 @@ To help improve the experience this MCP server uses Sentry for error tracking. I
|
|
|
43
43
|
The server provides these MCP tools:
|
|
44
44
|
|
|
45
45
|
**list-styleguides**
|
|
46
|
-
|
|
46
|
+
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.
|
|
47
|
+
|
|
48
|
+
*Helpful to reference before generating UI so decisions can reflect established design approaches.*
|
|
47
49
|
|
|
48
50
|
**get-styleguide-tree**
|
|
49
|
-
|
|
51
|
+
View the navigation hierarchy of a design system — including categories, pages, and tabs — to better understand how guidance is organized.
|
|
52
|
+
|
|
53
|
+
*Helpful when determining where to look for component or pattern documentation before generating UI.*
|
|
50
54
|
|
|
51
55
|
**list-pages**
|
|
52
|
-
|
|
56
|
+
Explore the pages within a design system to find guidance relevant to the task.
|
|
57
|
+
|
|
58
|
+
*Useful when generating UI that should align with documented component usage, patterns, or interaction recommendations rather than inferred solutions.*
|
|
53
59
|
|
|
54
60
|
**get-page**
|
|
55
|
-
|
|
61
|
+
Fetch guidance from a specific design system page, including usage notes, recommendations, and supporting context.
|
|
62
|
+
|
|
63
|
+
*Particularly helpful ahead of UI generation to increase the likelihood that outputs reflect the intent of the design system.*
|
|
56
64
|
|
|
57
65
|
### Setup Examples
|
|
58
66
|
|
package/dist/api/api.js
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
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]="4a8750ba-4616-5bb8-aadc-1a6c400d4bd6")}catch(e){}}();
|
|
3
3
|
import * as Sentry from "@sentry/node";
|
|
4
4
|
import { IncorrectScopeError, MaxRetriesError, UnauthorizedError, UnknownError, } from "./errors.js";
|
|
5
5
|
import packageJson from "../../package.json" with { type: "json" };
|
|
6
6
|
const API_PATH = "/open_api/v2";
|
|
7
7
|
const USER_AGENT = `zeroheight-mcp-server/${packageJson.version}`;
|
|
8
|
+
export var ApiType;
|
|
9
|
+
(function (ApiType) {
|
|
10
|
+
ApiType["OpenApi"] = "open_api";
|
|
11
|
+
ApiType["Internal"] = "internal";
|
|
12
|
+
})(ApiType || (ApiType = {}));
|
|
8
13
|
export var ResponseStatus;
|
|
9
14
|
(function (ResponseStatus) {
|
|
10
15
|
ResponseStatus["Success"] = "success";
|
|
@@ -15,6 +20,10 @@ export var ResponseStatus;
|
|
|
15
20
|
* Get the correct URL for production of development depending on the environment variable
|
|
16
21
|
*/
|
|
17
22
|
export function getZeroheightURL() {
|
|
23
|
+
const zeroheightURL = process.env["ZEROHEIGHT_URL"];
|
|
24
|
+
if (zeroheightURL) {
|
|
25
|
+
return new URL(zeroheightURL);
|
|
26
|
+
}
|
|
18
27
|
if (process.env["NODE_ENV"] === "dev") {
|
|
19
28
|
return new URL("https://zeroheight.dev");
|
|
20
29
|
}
|
|
@@ -25,9 +34,9 @@ export function getZeroheightURL() {
|
|
|
25
34
|
async function sleep(ms) {
|
|
26
35
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
27
36
|
}
|
|
28
|
-
export async function request(path, credentials, init, search) {
|
|
37
|
+
export async function request(path, credentials, init, search, apiType = ApiType.OpenApi, metadata = {}) {
|
|
29
38
|
const url = getZeroheightURL();
|
|
30
|
-
url.pathname = API_PATH + path;
|
|
39
|
+
url.pathname = (apiType === ApiType.OpenApi ? API_PATH : "/api") + path;
|
|
31
40
|
if (search) {
|
|
32
41
|
url.search = "?" + search.toString();
|
|
33
42
|
}
|
|
@@ -43,9 +52,19 @@ export async function request(path, credentials, init, search) {
|
|
|
43
52
|
"Content-Type": "application/json",
|
|
44
53
|
Accept: "application/json",
|
|
45
54
|
};
|
|
55
|
+
if (metadata.clientUserAgent) {
|
|
56
|
+
headers["X-MCP-Client-User-Agent"] = metadata.clientUserAgent;
|
|
57
|
+
}
|
|
46
58
|
if (credentials.type === "jwt") {
|
|
47
59
|
headers["Authorization"] = `Bearer ${credentials.jwt}`;
|
|
48
60
|
headers["X-API-CLIENT-NAME"] = "remote-mcp-server";
|
|
61
|
+
if (credentials.mcpAuthId) {
|
|
62
|
+
headers["X-MCP-Auth-ID"] = String(credentials.mcpAuthId);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
else if (credentials.type === "oauth_jwt") {
|
|
66
|
+
headers["Authorization"] = `Bearer ${credentials.jwt}`;
|
|
67
|
+
headers["X-API-CLIENT-NAME"] = `remote-mcp-server:${credentials.clientId}`;
|
|
49
68
|
}
|
|
50
69
|
else {
|
|
51
70
|
headers["X-API-CLIENT"] = credentials.client;
|
|
@@ -64,8 +83,14 @@ export async function request(path, credentials, init, search) {
|
|
|
64
83
|
}
|
|
65
84
|
else if (response.status === 429) {
|
|
66
85
|
retries++;
|
|
67
|
-
|
|
68
|
-
|
|
86
|
+
let waitTime;
|
|
87
|
+
if (apiType === ApiType.OpenApi) {
|
|
88
|
+
const responseData = await response.json();
|
|
89
|
+
waitTime = responseData.data.reset_time * 1000 - Date.now();
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
waitTime = 2 ** retries * 1000;
|
|
93
|
+
}
|
|
69
94
|
await sleep(waitTime);
|
|
70
95
|
continue;
|
|
71
96
|
}
|
|
@@ -118,4 +143,4 @@ export async function internalRequest(path, method, body) {
|
|
|
118
143
|
return responseJson;
|
|
119
144
|
}
|
|
120
145
|
//# sourceMappingURL=api.js.map
|
|
121
|
-
//# debugId=
|
|
146
|
+
//# debugId=4a8750ba-4616-5bb8-aadc-1a6c400d4bd6
|
package/dist/api/api.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.js","sources":["api/api.ts"],"sourceRoot":"/","sourcesContent":["import * as Sentry from \"@sentry/node\";\nimport {\n IncorrectScopeError,\n MaxRetriesError,\n UnauthorizedError,\n UnknownError,\n} from \"./errors.js\";\n\nimport packageJson from \"../../package.json\" with { type: \"json\" };\n\nimport { Credentials } from \"../common/credentials.js\";\n\nconst API_PATH = \"/open_api/v2\";\nconst USER_AGENT = `zeroheight-mcp-server/${packageJson.version}`;\n\nexport enum ResponseStatus {\n Success = \"success\",\n Error = \"error\",\n Fail = \"fail\",\n}\n\n/**\n * Open API V2 Response format\n */\n\ninterface BaseResponse<T> {\n status: ResponseStatus;\n message: string;\n data: T;\n}\n\ninterface SuccessResponse<T> extends BaseResponse<T> {\n status: ResponseStatus.Success;\n}\n\ninterface FailResponse<T> extends BaseResponse<T> {\n status: ResponseStatus.Fail;\n}\n\ninterface ErrorResponse<T> extends BaseResponse<T> {\n status: ResponseStatus.Error;\n}\n\nexport type APIResponse<S = {}, F = {}, E = {}> =\n | SuccessResponse<S>\n | FailResponse<F>\n | ErrorResponse<E>;\n\n/**\n * Get the correct URL for production of development depending on the environment variable\n */\nexport function getZeroheightURL() {\n if (process.env[\"NODE_ENV\"] === \"dev\") {\n return new URL(\"https://zeroheight.dev\");\n } else {\n return new URL(\"https://zeroheight.com\");\n }\n}\n\nasync function sleep(ms: number) {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport async function request<R>(\n path: string,\n credentials: Credentials,\n init: RequestInit,\n search?: URLSearchParams,\n): Promise<R> {\n const url = getZeroheightURL();\n url.pathname = API_PATH + path;\n if (search) {\n url.search = \"?\" + search.toString();\n }\n\n if (process.env[\"NODE_ENV\"] === \"dev\") {\n process.env[\"NODE_TLS_REJECT_UNAUTHORIZED\"] = \"0\";\n }\n\n const maxRetries = 3;\n let retries = 0;\n\n const headers: Record<string, string> = {\n \"X-API-CLIENT-NAME\": \"mcp-server\",\n \"X-API-CLIENT-VERSION\": packageJson.version,\n \"User-Agent\": USER_AGENT,\n \"Content-Type\": \"application/json\",\n Accept: \"application/json\",\n };\n\n if (credentials.type === \"jwt\") {\n headers[\"Authorization\"] = `Bearer ${credentials.jwt}`;\n headers[\"X-API-CLIENT-NAME\"] = \"remote-mcp-server\";\n } else {\n headers[\"X-API-CLIENT\"] = credentials.client;\n headers[\"X-API-KEY\"] = credentials.token;\n }\n\n while (retries < maxRetries) {\n const response = await fetch(url, {\n ...init,\n headers,\n });\n\n if (response.status === 401) {\n console.error(\"Unauthorized response from API\", {\n response: { status: response.status, body: await response.text() },\n });\n throw new UnauthorizedError();\n } else if (response.status === 429) {\n retries++;\n const responseData = await response.json();\n const waitTime = responseData.data.reset_time * 1000 - Date.now();\n await sleep(waitTime);\n continue;\n } else if (response.status < 200 || response.status >= 300) {\n console.error(\"API request failed\", {\n response: { status: response.status, body: await response.text() },\n });\n\n if (response.status === 403) {\n throw new IncorrectScopeError();\n } else {\n Sentry.captureMessage(\n `Unknown error occurred making request to: ${url}`,\n );\n throw new UnknownError();\n }\n }\n\n const responseJson = await response.json();\n return responseJson;\n }\n\n throw new MaxRetriesError();\n}\n\nexport async function internalRequest<R>(\n path: string,\n method: \"GET\" | \"POST\" | \"PUT\" | \"DELETE\",\n body: any,\n): Promise<R> {\n const url = getZeroheightURL();\n url.pathname = \"/api\" + path;\n\n if (process.env[\"NODE_ENV\"] === \"dev\") {\n process.env[\"NODE_TLS_REJECT_UNAUTHORIZED\"] = \"0\";\n }\n\n const response = await fetch(url, {\n method,\n headers: {\n \"Content-Type\": \"application/json\",\n Accept: \"application/json\",\n \"User-Agent\": USER_AGENT,\n \"X-API-KEY\": process.env[\"INTERNAL_API_KEY\"] || \"\",\n },\n body: JSON.stringify(body),\n });\n\n if (response.status < 200 || response.status >= 300) {\n console.error(\"Internal API request failed\", {\n response: { status: response.status, body: await response.text() },\n });\n\n if (response.status === 401) {\n throw new UnauthorizedError();\n } else {\n Sentry.captureMessage(\n `Unknown error occurred making internal request to: ${url}`,\n );\n throw new UnknownError();\n }\n }\n\n const responseJson = await response.json();\n return responseJson;\n}\n"],"names":[],"mappings":"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","debug_id":"84ff6650-a8f8-5c0b-9cd9-6a6cd07211cf"}
|
|
1
|
+
{"version":3,"file":"api.js","sources":["api/api.ts"],"sourceRoot":"/","sourcesContent":["import * as Sentry from \"@sentry/node\";\nimport {\n IncorrectScopeError,\n MaxRetriesError,\n UnauthorizedError,\n UnknownError,\n} from \"./errors.js\";\n\nimport packageJson from \"../../package.json\" with { type: \"json\" };\n\nimport { Credentials } from \"../common/credentials.js\";\n\nconst API_PATH = \"/open_api/v2\";\nconst USER_AGENT = `zeroheight-mcp-server/${packageJson.version}`;\n\nexport enum ApiType {\n OpenApi = \"open_api\", // /open_api/v2\n Internal = \"internal\", // /api\n}\n\nexport enum ResponseStatus {\n Success = \"success\",\n Error = \"error\",\n Fail = \"fail\",\n}\n\n/**\n * Open API V2 Response format\n */\n\ninterface BaseResponse<T> {\n status: ResponseStatus;\n message: string;\n data: T;\n}\n\ninterface SuccessResponse<T> extends BaseResponse<T> {\n status: ResponseStatus.Success;\n}\n\ninterface FailResponse<T> extends BaseResponse<T> {\n status: ResponseStatus.Fail;\n}\n\ninterface ErrorResponse<T> extends BaseResponse<T> {\n status: ResponseStatus.Error;\n}\n\nexport type APIResponse<S = {}, F = {}, E = {}> =\n | SuccessResponse<S>\n | FailResponse<F>\n | ErrorResponse<E>;\n\n/**\n * Get the correct URL for production of development depending on the environment variable\n */\nexport function getZeroheightURL() {\n const zeroheightURL = process.env[\"ZEROHEIGHT_URL\"];\n if (zeroheightURL) {\n return new URL(zeroheightURL);\n }\n\n if (process.env[\"NODE_ENV\"] === \"dev\") {\n return new URL(\"https://zeroheight.dev\");\n } else {\n return new URL(\"https://zeroheight.com\");\n }\n}\n\nasync function sleep(ms: number) {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport async function request<R>(\n path: string,\n credentials: Credentials,\n init: RequestInit,\n search?: URLSearchParams,\n apiType: ApiType = ApiType.OpenApi,\n metadata: { clientUserAgent?: string } = {},\n): Promise<R> {\n const url = getZeroheightURL();\n url.pathname = (apiType === ApiType.OpenApi ? API_PATH : \"/api\") + path;\n if (search) {\n url.search = \"?\" + search.toString();\n }\n\n if (process.env[\"NODE_ENV\"] === \"dev\") {\n process.env[\"NODE_TLS_REJECT_UNAUTHORIZED\"] = \"0\";\n }\n\n const maxRetries = 3;\n let retries = 0;\n\n const headers: Record<string, string> = {\n \"X-API-CLIENT-NAME\": \"mcp-server\",\n \"X-API-CLIENT-VERSION\": packageJson.version,\n \"User-Agent\": USER_AGENT,\n \"Content-Type\": \"application/json\",\n Accept: \"application/json\",\n };\n\n if (metadata.clientUserAgent) {\n headers[\"X-MCP-Client-User-Agent\"] = metadata.clientUserAgent;\n }\n\n if (credentials.type === \"jwt\") {\n headers[\"Authorization\"] = `Bearer ${credentials.jwt}`;\n headers[\"X-API-CLIENT-NAME\"] = \"remote-mcp-server\";\n if (credentials.mcpAuthId) {\n headers[\"X-MCP-Auth-ID\"] = String(credentials.mcpAuthId);\n }\n } else if (credentials.type === \"oauth_jwt\") {\n headers[\"Authorization\"] = `Bearer ${credentials.jwt}`;\n headers[\"X-API-CLIENT-NAME\"] = `remote-mcp-server:${credentials.clientId}`;\n } else {\n headers[\"X-API-CLIENT\"] = credentials.client;\n headers[\"X-API-KEY\"] = credentials.token;\n }\n\n while (retries < maxRetries) {\n const response = await fetch(url, {\n ...init,\n headers,\n });\n\n if (response.status === 401) {\n console.error(\"Unauthorized response from API\", {\n response: { status: response.status, body: await response.text() },\n });\n throw new UnauthorizedError();\n } else if (response.status === 429) {\n retries++;\n let waitTime: number;\n if (apiType === ApiType.OpenApi) {\n const responseData = await response.json();\n waitTime = responseData.data.reset_time * 1000 - Date.now();\n } else {\n waitTime = 2 ** retries * 1000;\n }\n await sleep(waitTime);\n continue;\n } else if (response.status < 200 || response.status >= 300) {\n console.error(\"API request failed\", {\n response: { status: response.status, body: await response.text() },\n });\n\n if (response.status === 403) {\n throw new IncorrectScopeError();\n } else {\n Sentry.captureMessage(\n `Unknown error occurred making request to: ${url}`,\n );\n throw new UnknownError();\n }\n }\n\n const responseJson = await response.json();\n return responseJson;\n }\n\n throw new MaxRetriesError();\n}\n\nexport async function internalRequest<R>(\n path: string,\n method: \"GET\" | \"POST\" | \"PUT\" | \"DELETE\",\n body: any,\n): Promise<R> {\n const url = getZeroheightURL();\n url.pathname = \"/api\" + path;\n\n if (process.env[\"NODE_ENV\"] === \"dev\") {\n process.env[\"NODE_TLS_REJECT_UNAUTHORIZED\"] = \"0\";\n }\n\n const response = await fetch(url, {\n method,\n headers: {\n \"Content-Type\": \"application/json\",\n Accept: \"application/json\",\n \"User-Agent\": USER_AGENT,\n \"X-API-KEY\": process.env[\"INTERNAL_API_KEY\"] || \"\",\n },\n body: JSON.stringify(body),\n });\n\n if (response.status < 200 || response.status >= 300) {\n console.error(\"Internal API request failed\", {\n response: { status: response.status, body: await response.text() },\n });\n\n if (response.status === 401) {\n throw new UnauthorizedError();\n } else {\n Sentry.captureMessage(\n `Unknown error occurred making internal request to: ${url}`,\n );\n throw new UnknownError();\n }\n }\n\n const responseJson = await response.json();\n return responseJson;\n}\n"],"names":[],"mappings":"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","debug_id":"4a8750ba-4616-5bb8-aadc-1a6c400d4bd6"}
|
package/dist/api/page.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
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]="4cc32259-80f6-5153-bf7c-7e2ca8c7578d")}catch(e){}}();
|
|
3
3
|
import { request } from "./api.js";
|
|
4
4
|
import { UnknownError } from "./errors.js";
|
|
5
5
|
import { captureException } from "../common/errors.js";
|
|
6
|
-
export async function listPages(credentials, styleguideId, optionalParams = {}) {
|
|
6
|
+
export async function listPages(credentials, styleguideId, optionalParams = {}, clientUserAgent) {
|
|
7
7
|
try {
|
|
8
8
|
const searchParams = new URLSearchParams({
|
|
9
9
|
show_hidden: "false",
|
|
@@ -16,7 +16,7 @@ export async function listPages(credentials, styleguideId, optionalParams = {})
|
|
|
16
16
|
}
|
|
17
17
|
const response = await request(`/styleguides/${styleguideId}/pages`, credentials, {
|
|
18
18
|
method: "GET",
|
|
19
|
-
}, searchParams);
|
|
19
|
+
}, searchParams, undefined, { clientUserAgent });
|
|
20
20
|
if ("pages" in response.data) {
|
|
21
21
|
return response.data.pages;
|
|
22
22
|
}
|
|
@@ -27,7 +27,7 @@ export async function listPages(credentials, styleguideId, optionalParams = {})
|
|
|
27
27
|
return [];
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
|
-
export async function getPage(credentials, pageId, optionalParams = {}) {
|
|
30
|
+
export async function getPage(credentials, pageId, optionalParams = {}, clientUserAgent) {
|
|
31
31
|
try {
|
|
32
32
|
const searchParams = new URLSearchParams();
|
|
33
33
|
if (optionalParams.releaseId) {
|
|
@@ -35,7 +35,7 @@ export async function getPage(credentials, pageId, optionalParams = {}) {
|
|
|
35
35
|
}
|
|
36
36
|
const response = await request(`/pages/${pageId}`, credentials, {
|
|
37
37
|
method: "GET",
|
|
38
|
-
}, searchParams);
|
|
38
|
+
}, searchParams, undefined, { clientUserAgent });
|
|
39
39
|
if ("page" in response.data) {
|
|
40
40
|
return response.data.page;
|
|
41
41
|
}
|
|
@@ -46,7 +46,7 @@ export async function getPage(credentials, pageId, optionalParams = {}) {
|
|
|
46
46
|
return null;
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
|
-
export async function searchPages(credentials, styleguideId, query, releaseId) {
|
|
49
|
+
export async function searchPages(credentials, styleguideId, query, releaseId, clientUserAgent) {
|
|
50
50
|
try {
|
|
51
51
|
const filters = {
|
|
52
52
|
type: "page",
|
|
@@ -57,14 +57,11 @@ export async function searchPages(credentials, styleguideId, query, releaseId) {
|
|
|
57
57
|
}
|
|
58
58
|
const response = await request(`/search`, credentials, {
|
|
59
59
|
method: "POST",
|
|
60
|
-
headers: {
|
|
61
|
-
"Content-Type": "application/json",
|
|
62
|
-
},
|
|
63
60
|
body: JSON.stringify({
|
|
64
61
|
query,
|
|
65
62
|
filters,
|
|
66
63
|
}),
|
|
67
|
-
});
|
|
64
|
+
}, undefined, undefined, { clientUserAgent });
|
|
68
65
|
if ("results" in response.data) {
|
|
69
66
|
return response.data.results;
|
|
70
67
|
}
|
|
@@ -76,4 +73,4 @@ export async function searchPages(credentials, styleguideId, query, releaseId) {
|
|
|
76
73
|
}
|
|
77
74
|
}
|
|
78
75
|
//# sourceMappingURL=page.js.map
|
|
79
|
-
//# debugId=
|
|
76
|
+
//# debugId=4cc32259-80f6-5153-bf7c-7e2ca8c7578d
|
package/dist/api/page.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"page.js","sources":["api/page.ts"],"sourceRoot":"/","sourcesContent":["import { Credentials } from \"../common/credentials.js\";\nimport { APIResponse, request } from \"./api.js\";\nimport { UnknownError } from \"./errors.js\";\nimport { Page, PageListItem, PageSearchResultItem } from \"./types/page.js\";\nimport { captureException } from \"../common/errors.js\";\n\ninterface PageListSuccessResponse {\n pages: PageListItem[];\n}\n\ninterface PageListOptionalParams {\n searchTerm: string;\n releaseId: number;\n}\n\nexport async function listPages(\n credentials: Credentials,\n styleguideId: number,\n optionalParams: Partial<PageListOptionalParams> = {}
|
|
1
|
+
{"version":3,"file":"page.js","sources":["api/page.ts"],"sourceRoot":"/","sourcesContent":["import { Credentials } from \"../common/credentials.js\";\nimport { APIResponse, request } from \"./api.js\";\nimport { UnknownError } from \"./errors.js\";\nimport { Page, PageListItem, PageSearchResultItem } from \"./types/page.js\";\nimport { captureException } from \"../common/errors.js\";\n\ninterface PageListSuccessResponse {\n pages: PageListItem[];\n}\n\ninterface PageListOptionalParams {\n searchTerm: string;\n releaseId: number;\n}\n\nexport async function listPages(\n credentials: Credentials,\n styleguideId: number,\n optionalParams: Partial<PageListOptionalParams> = {},\n clientUserAgent?: string,\n) {\n try {\n const searchParams = new URLSearchParams({\n show_hidden: \"false\",\n });\n\n if (optionalParams.releaseId) {\n searchParams.set(\"release_id\", optionalParams.releaseId.toString());\n }\n\n if (optionalParams.searchTerm) {\n searchParams.set(\"search\", optionalParams.searchTerm);\n }\n\n const response = await request<\n APIResponse<PageListSuccessResponse, {}, {}>\n >(\n `/styleguides/${styleguideId}/pages`,\n credentials,\n {\n method: \"GET\",\n },\n searchParams,\n undefined,\n { clientUserAgent },\n );\n\n if (\"pages\" in response.data) {\n return response.data.pages;\n }\n\n throw new UnknownError();\n } catch (e) {\n captureException(e);\n return [];\n }\n}\n\ninterface PageSuccessResponse {\n page: Page;\n}\n\ninterface PageOptionalParams {\n releaseId: number;\n}\n\nexport async function getPage(\n credentials: Credentials,\n pageId: number | string,\n optionalParams: Partial<PageOptionalParams> = {},\n clientUserAgent?: string,\n) {\n try {\n const searchParams = new URLSearchParams();\n\n if (optionalParams.releaseId) {\n searchParams.set(\"release_id\", optionalParams.releaseId.toString());\n }\n\n const response = await request<APIResponse<PageSuccessResponse, {}, {}>>(\n `/pages/${pageId}`,\n credentials,\n {\n method: \"GET\",\n },\n searchParams,\n undefined,\n { clientUserAgent },\n );\n\n if (\"page\" in response.data) {\n return response.data.page;\n }\n\n throw new UnknownError();\n } catch (e) {\n captureException(e);\n return null;\n }\n}\n\ninterface SearchSuccessResponse {\n results: PageSearchResultItem[];\n}\n\nexport async function searchPages(\n credentials: Credentials,\n styleguideId: number,\n query: string,\n releaseId?: number,\n clientUserAgent?: string,\n) {\n try {\n const filters: Record<string, number | string> = {\n type: \"page\",\n styleguide_id: styleguideId,\n };\n\n if (typeof releaseId === \"number\") {\n filters[\"styleguide_version_id\"] = releaseId;\n }\n\n const response = await request<APIResponse<SearchSuccessResponse, {}, {}>>(\n `/search`,\n credentials,\n {\n method: \"POST\",\n body: JSON.stringify({\n query,\n filters,\n }),\n },\n undefined,\n undefined,\n { clientUserAgent },\n );\n\n if (\"results\" in response.data) {\n return response.data.results;\n }\n\n throw new UnknownError();\n } catch (e) {\n captureException(e);\n return [];\n }\n}\n"],"names":[],"mappings":"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","debug_id":"4cc32259-80f6-5153-bf7c-7e2ca8c7578d"}
|
package/dist/api/styleguide.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
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]="3d4cd722-6043-5c3e-a421-a6f2511a55b0")}catch(e){}}();
|
|
3
3
|
import { request } from "./api.js";
|
|
4
4
|
import { UnknownError } from "./errors.js";
|
|
5
5
|
import { captureException } from "../common/errors.js";
|
|
6
|
-
export async function listStyleguides(credentials) {
|
|
6
|
+
export async function listStyleguides(credentials, clientUserAgent) {
|
|
7
7
|
try {
|
|
8
8
|
const response = await request("/styleguides", credentials, {
|
|
9
9
|
method: "GET",
|
|
10
|
-
});
|
|
10
|
+
}, undefined, undefined, { clientUserAgent });
|
|
11
11
|
if ("styleguides" in response.data) {
|
|
12
12
|
if (credentials.type === "jwt") {
|
|
13
13
|
return response.data.styleguides.filter((sg) => sg.id === credentials.styleguideId);
|
|
@@ -21,14 +21,14 @@ export async function listStyleguides(credentials) {
|
|
|
21
21
|
return [];
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
|
-
export async function getStyleguideTree(credentials, id) {
|
|
24
|
+
export async function getStyleguideTree(credentials, id, clientUserAgent) {
|
|
25
25
|
try {
|
|
26
26
|
const searchParams = new URLSearchParams({
|
|
27
27
|
show_hidden: "false",
|
|
28
28
|
});
|
|
29
29
|
const response = await request(`/styleguides/${id}/tree`, credentials, {
|
|
30
30
|
method: "GET",
|
|
31
|
-
}, searchParams);
|
|
31
|
+
}, searchParams, undefined, { clientUserAgent });
|
|
32
32
|
if ("tree" in response.data) {
|
|
33
33
|
return response.data.tree;
|
|
34
34
|
}
|
|
@@ -41,4 +41,4 @@ export async function getStyleguideTree(credentials, id) {
|
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
43
|
//# sourceMappingURL=styleguide.js.map
|
|
44
|
-
//# debugId=
|
|
44
|
+
//# debugId=3d4cd722-6043-5c3e-a421-a6f2511a55b0
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"styleguide.js","sources":["api/styleguide.ts"],"sourceRoot":"/","sourcesContent":["import { APIResponse, request } from \"./api.js\";\nimport { UnknownError } from \"./errors.js\";\nimport { Credentials } from \"../common/credentials.js\";\nimport {\n CategoryNode,\n NavigationNode,\n PageNode,\n Styleguide,\n} from \"./types/styleguide.js\";\nimport { captureException } from \"../common/errors.js\";\n\ninterface StyleguideListSuccessResponse {\n styleguides: Styleguide[];\n}\n\nexport async function listStyleguides(credentials: Credentials) {\n try {\n const response = await request<\n APIResponse<StyleguideListSuccessResponse, {}, {}>\n >(\"/styleguides\", credentials, {\n method: \"GET\",\n });\n\n if (\"styleguides\" in response.data) {\n if (credentials.type === \"jwt\") {\n return response.data.styleguides.filter(\n (sg) => sg.id === credentials.styleguideId,\n );\n }\n\n return response.data.styleguides;\n }\n\n throw new UnknownError();\n } catch (e) {\n captureException(e);\n return [];\n }\n}\n\ninterface SyleguideTreeSuccessResponse {\n tree: (PageNode | CategoryNode | NavigationNode)[];\n}\n\nexport async function getStyleguideTree(credentials: Credentials, id: number) {\n try {\n const searchParams = new URLSearchParams({\n show_hidden: \"false\",\n });\n\n const response = await request<\n APIResponse<SyleguideTreeSuccessResponse, {}, {}>\n >(\n `/styleguides/${id}/tree`,\n credentials,\n {\n method: \"GET\",\n },\n searchParams,\n );\n\n if (\"tree\" in response.data) {\n return response.data.tree;\n }\n\n console.error(response);\n\n throw new UnknownError();\n } catch (e) {\n captureException(e);\n return [];\n }\n}\n"],"names":[],"mappings":";;AAAA,OAAO,EAAe,OAAO,EAAE,MAAM,UAAU,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAQ3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAMvD,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,WAAwB;
|
|
1
|
+
{"version":3,"file":"styleguide.js","sources":["api/styleguide.ts"],"sourceRoot":"/","sourcesContent":["import { APIResponse, request } from \"./api.js\";\nimport { UnknownError } from \"./errors.js\";\nimport { Credentials } from \"../common/credentials.js\";\nimport {\n CategoryNode,\n NavigationNode,\n PageNode,\n Styleguide,\n} from \"./types/styleguide.js\";\nimport { captureException } from \"../common/errors.js\";\n\ninterface StyleguideListSuccessResponse {\n styleguides: Styleguide[];\n}\n\nexport async function listStyleguides(credentials: Credentials, clientUserAgent?: string) {\n try {\n const response = await request<\n APIResponse<StyleguideListSuccessResponse, {}, {}>\n >(\"/styleguides\", credentials, {\n method: \"GET\",\n }, undefined, undefined, { clientUserAgent });\n\n if (\"styleguides\" in response.data) {\n if (credentials.type === \"jwt\") {\n return response.data.styleguides.filter(\n (sg) => sg.id === credentials.styleguideId,\n );\n }\n\n return response.data.styleguides;\n }\n\n throw new UnknownError();\n } catch (e) {\n captureException(e);\n return [];\n }\n}\n\ninterface SyleguideTreeSuccessResponse {\n tree: (PageNode | CategoryNode | NavigationNode)[];\n}\n\nexport async function getStyleguideTree(credentials: Credentials, id: number, clientUserAgent?: string) {\n try {\n const searchParams = new URLSearchParams({\n show_hidden: \"false\",\n });\n\n const response = await request<\n APIResponse<SyleguideTreeSuccessResponse, {}, {}>\n >(\n `/styleguides/${id}/tree`,\n credentials,\n {\n method: \"GET\",\n },\n searchParams,\n undefined,\n { clientUserAgent },\n );\n\n if (\"tree\" in response.data) {\n return response.data.tree;\n }\n\n console.error(response);\n\n throw new UnknownError();\n } catch (e) {\n captureException(e);\n return [];\n }\n}\n"],"names":[],"mappings":";;AAAA,OAAO,EAAe,OAAO,EAAE,MAAM,UAAU,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAQ3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAMvD,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,WAAwB,EAAE,eAAwB;IACtF,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,OAAO,CAE5B,cAAc,EAAE,WAAW,EAAE;YAC7B,MAAM,EAAE,KAAK;SACd,EAAE,SAAS,EAAE,SAAS,EAAE,EAAE,eAAe,EAAE,CAAC,CAAC;QAE9C,IAAI,aAAa,IAAI,QAAQ,CAAC,IAAI,EAAE,CAAC;YACnC,IAAI,WAAW,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;gBAC/B,OAAO,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CACrC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,WAAW,CAAC,YAAY,CAC3C,CAAC;YACJ,CAAC;YAED,OAAO,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC;QACnC,CAAC;QAED,MAAM,IAAI,YAAY,EAAE,CAAC;IAC3B,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,gBAAgB,CAAC,CAAC,CAAC,CAAC;QACpB,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAMD,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,WAAwB,EAAE,EAAU,EAAE,eAAwB;IACpG,IAAI,CAAC;QACH,MAAM,YAAY,GAAG,IAAI,eAAe,CAAC;YACvC,WAAW,EAAE,OAAO;SACrB,CAAC,CAAC;QAEH,MAAM,QAAQ,GAAG,MAAM,OAAO,CAG5B,gBAAgB,EAAE,OAAO,EACzB,WAAW,EACX;YACE,MAAM,EAAE,KAAK;SACd,EACD,YAAY,EACZ,SAAS,EACT,EAAE,eAAe,EAAE,CACpB,CAAC;QAEF,IAAI,MAAM,IAAI,QAAQ,CAAC,IAAI,EAAE,CAAC;YAC5B,OAAO,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC;QAC5B,CAAC;QAED,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QAExB,MAAM,IAAI,YAAY,EAAE,CAAC;IAC3B,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,gBAAgB,CAAC,CAAC,CAAC,CAAC;QACpB,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC","debug_id":"3d4cd722-6043-5c3e-a421-a6f2511a55b0"}
|
|
@@ -0,0 +1,15 @@
|
|
|
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]="6a5a51a2-6a32-54bd-9e0a-63ef812eb566")}catch(e){}}();
|
|
3
|
+
import { ApiType, request } from "./api.js";
|
|
4
|
+
import { captureException } from "../common/errors.js";
|
|
5
|
+
export async function getTokenSetExport(credentials, tokenSetId, clientUserAgent) {
|
|
6
|
+
try {
|
|
7
|
+
return await request(`/token_management/token_set/${tokenSetId}/export`, credentials, { method: "GET" }, new URLSearchParams({ format: "w3c" }), ApiType.Internal, { clientUserAgent });
|
|
8
|
+
}
|
|
9
|
+
catch (e) {
|
|
10
|
+
captureException(e);
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=token.js.map
|
|
15
|
+
//# debugId=6a5a51a2-6a32-54bd-9e0a-63ef812eb566
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token.js","sources":["api/token.ts"],"sourceRoot":"/","sourcesContent":["import { Credentials } from \"../common/credentials.js\";\nimport { ApiType, request } from \"./api.js\";\nimport { TokenGroup } from \"./types/token.js\";\nimport { captureException } from \"../common/errors.js\";\n\nexport async function getTokenSetExport(\n credentials: Credentials,\n tokenSetId: number,\n clientUserAgent?: string,\n): Promise<TokenGroup | null> {\n try {\n return await request<TokenGroup>(\n `/token_management/token_set/${tokenSetId}/export`,\n credentials,\n { method: \"GET\" },\n new URLSearchParams({ format: \"w3c\" }),\n ApiType.Internal,\n { clientUserAgent },\n );\n } catch (e) {\n captureException(e);\n return null;\n }\n}\n"],"names":[],"mappings":";;AACA,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAE5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAEvD,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,WAAwB,EACxB,UAAkB,EAClB,eAAwB;IAExB,IAAI,CAAC;QACH,OAAO,MAAM,OAAO,CAClB,+BAA+B,UAAU,SAAS,EAClD,WAAW,EACX,EAAE,MAAM,EAAE,KAAK,EAAE,EACjB,IAAI,eAAe,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EACtC,OAAO,CAAC,QAAQ,EAChB,EAAE,eAAe,EAAE,CACpB,CAAC;IACJ,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,gBAAgB,CAAC,CAAC,CAAC,CAAC;QACpB,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC","debug_id":"6a5a51a2-6a32-54bd-9e0a-63ef812eb566"}
|
|
@@ -0,0 +1,5 @@
|
|
|
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]="176de3fd-0981-5940-a815-50166cce2f8b")}catch(e){}}();
|
|
3
|
+
export {};
|
|
4
|
+
//# sourceMappingURL=token.js.map
|
|
5
|
+
//# debugId=176de3fd-0981-5940-a815-50166cce2f8b
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token.js","sources":["api/types/token.ts"],"sourceRoot":"/","sourcesContent":["export interface TokenSet {\n id: number;\n name: string;\n source: string;\n created_at: string;\n updated_at: string;\n}\n\nexport interface TokenValue {\n $value: string | number | Record<string, unknown>;\n $type?: string;\n $description?: string;\n}\n\nexport interface TokenGroup {\n $type?: string;\n $description?: string;\n [key: string]: string | TokenValue | TokenGroup | undefined;\n}\n"],"names":[],"mappings":"","debug_id":"176de3fd-0981-5940-a815-50166cce2f8b"}
|
|
@@ -0,0 +1,36 @@
|
|
|
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]="00a53473-e975-58f2-96d3-02166ee7d41a")}catch(e){}}();
|
|
3
|
+
import { InvalidTokenError, } from "@modelcontextprotocol/sdk/server/auth/errors.js";
|
|
4
|
+
import { internalRequest } from "../api/api.js";
|
|
5
|
+
function parseScopes(scope) {
|
|
6
|
+
if (!scope) {
|
|
7
|
+
return [];
|
|
8
|
+
}
|
|
9
|
+
if (Array.isArray(scope)) {
|
|
10
|
+
return scope.filter((item) => typeof item === "string");
|
|
11
|
+
}
|
|
12
|
+
return scope
|
|
13
|
+
.split(" ")
|
|
14
|
+
.map((item) => item.trim())
|
|
15
|
+
.filter(Boolean);
|
|
16
|
+
}
|
|
17
|
+
export async function verifyAccessToken(token, _req) {
|
|
18
|
+
const exchange = await internalRequest("/mcp/exchange_oauth_token", "POST", {
|
|
19
|
+
access_token: token,
|
|
20
|
+
});
|
|
21
|
+
if (!exchange.active) {
|
|
22
|
+
throw new InvalidTokenError("Token is inactive");
|
|
23
|
+
}
|
|
24
|
+
if (typeof exchange.exp !== "number") {
|
|
25
|
+
throw new InvalidTokenError("Token has no expiration time");
|
|
26
|
+
}
|
|
27
|
+
return {
|
|
28
|
+
token: exchange.extra.jwt,
|
|
29
|
+
clientId: exchange.client_id ?? "unknown-client",
|
|
30
|
+
scopes: parseScopes(exchange.scope),
|
|
31
|
+
expiresAt: exchange.exp,
|
|
32
|
+
extra: exchange.extra,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=introspection.js.map
|
|
36
|
+
//# debugId=00a53473-e975-58f2-96d3-02166ee7d41a
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"introspection.js","sources":["auth/introspection.ts"],"sourceRoot":"/","sourcesContent":["import { Request } from \"express\";\nimport { AuthInfo } from \"@modelcontextprotocol/sdk/server/auth/types.js\";\nimport {\n InvalidTokenError,\n ServerError,\n} from \"@modelcontextprotocol/sdk/server/auth/errors.js\";\nimport { internalRequest } from \"../api/api.js\";\n\ninterface ExchangeResponse {\n active: boolean;\n scope?: string | string[];\n client_id?: string;\n exp?: number;\n extra: {\n features: Record<string, unknown>;\n jwt: string;\n user_id: number;\n team_id: number;\n };\n}\n\nfunction parseScopes(scope?: string | string[]): string[] {\n if (!scope) {\n return [];\n }\n if (Array.isArray(scope)) {\n return scope.filter((item): item is string => typeof item === \"string\");\n }\n return scope\n .split(\" \")\n .map((item) => item.trim())\n .filter(Boolean);\n}\n\nexport async function verifyAccessToken(\n token: string,\n _req: Request,\n): Promise<AuthInfo> {\n const exchange = await internalRequest<ExchangeResponse>(\n \"/mcp/exchange_oauth_token\",\n \"POST\",\n {\n access_token: token,\n },\n );\n\n if (!exchange.active) {\n throw new InvalidTokenError(\"Token is inactive\");\n }\n\n if (typeof exchange.exp !== \"number\") {\n throw new InvalidTokenError(\"Token has no expiration time\");\n }\n\n return {\n token: exchange.extra.jwt,\n clientId: exchange.client_id ?? \"unknown-client\",\n scopes: parseScopes(exchange.scope),\n expiresAt: exchange.exp,\n extra: exchange.extra,\n };\n}\n"],"names":[],"mappings":";;AAEA,OAAO,EACL,iBAAiB,GAElB,MAAM,iDAAiD,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAehD,SAAS,WAAW,CAAC,KAAyB;IAC5C,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAkB,EAAE,CAAC,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC;IAC1E,CAAC;IACD,OAAO,KAAK;SACT,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;SAC1B,MAAM,CAAC,OAAO,CAAC,CAAC;AACrB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,KAAa,EACb,IAAa;IAEb,MAAM,QAAQ,GAAG,MAAM,eAAe,CACpC,2BAA2B,EAC3B,MAAM,EACN;QACE,YAAY,EAAE,KAAK;KACpB,CACF,CAAC;IAEF,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;QACrB,MAAM,IAAI,iBAAiB,CAAC,mBAAmB,CAAC,CAAC;IACnD,CAAC;IAED,IAAI,OAAO,QAAQ,CAAC,GAAG,KAAK,QAAQ,EAAE,CAAC;QACrC,MAAM,IAAI,iBAAiB,CAAC,8BAA8B,CAAC,CAAC;IAC9D,CAAC;IAED,OAAO;QACL,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC,GAAG;QACzB,QAAQ,EAAE,QAAQ,CAAC,SAAS,IAAI,gBAAgB;QAChD,MAAM,EAAE,WAAW,CAAC,QAAQ,CAAC,KAAK,CAAC;QACnC,SAAS,EAAE,QAAQ,CAAC,GAAG;QACvB,KAAK,EAAE,QAAQ,CAAC,KAAK;KACtB,CAAC;AACJ,CAAC","debug_id":"00a53473-e975-58f2-96d3-02166ee7d41a"}
|
|
@@ -1,7 +1,10 @@
|
|
|
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]="11c203a2-35a9-5524-af57-bf3c016a0056")}catch(e){}}();
|
|
3
3
|
import { MissingCredentialsError } from "./errors.js";
|
|
4
4
|
import { internalRequest } from "../api/api.js";
|
|
5
|
+
export function isLocalMCP(credentials) {
|
|
6
|
+
return credentials.type === "client_token";
|
|
7
|
+
}
|
|
5
8
|
export function getCredentialsFromEnvironment() {
|
|
6
9
|
const token = process.env["ZEROHEIGHT_ACCESS_TOKEN"];
|
|
7
10
|
const client = process.env["ZEROHEIGHT_CLIENT_ID"];
|
|
@@ -18,15 +21,30 @@ export async function getCredentials(authInfo) {
|
|
|
18
21
|
if (!authInfo) {
|
|
19
22
|
return getCredentialsFromEnvironment();
|
|
20
23
|
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
+
if (authInfo.clientId === "http-client") {
|
|
25
|
+
const res = await internalRequest("/mcp_url/exchange_token", "POST", {
|
|
26
|
+
token: authInfo.token,
|
|
27
|
+
});
|
|
28
|
+
return {
|
|
29
|
+
type: "jwt",
|
|
30
|
+
jwt: res.jwt,
|
|
31
|
+
styleguideId: res.styleguide_id,
|
|
32
|
+
features: res.features ?? {},
|
|
33
|
+
userId: res.user_id,
|
|
34
|
+
viewerId: res.viewer_id,
|
|
35
|
+
teamId: res.team_id,
|
|
36
|
+
mcpAuthId: res.mcp_auth_id,
|
|
37
|
+
tokenSets: res.token_sets,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
24
40
|
return {
|
|
25
|
-
type: "
|
|
26
|
-
jwt:
|
|
27
|
-
|
|
28
|
-
|
|
41
|
+
type: "oauth_jwt",
|
|
42
|
+
jwt: authInfo.token,
|
|
43
|
+
features: authInfo.extra.features,
|
|
44
|
+
userId: authInfo.extra.user_id,
|
|
45
|
+
teamId: authInfo.extra.team_id,
|
|
46
|
+
clientId: authInfo.clientId,
|
|
29
47
|
};
|
|
30
48
|
}
|
|
31
49
|
//# sourceMappingURL=credentials.js.map
|
|
32
|
-
//# debugId=
|
|
50
|
+
//# debugId=11c203a2-35a9-5524-af57-bf3c016a0056
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"credentials.js","sources":["common/credentials.ts"],"sourceRoot":"/","sourcesContent":["import { AuthInfo } from \"@modelcontextprotocol/sdk/server/auth/types.js\";\nimport { MissingCredentialsError } from \"./errors.js\";\nimport { internalRequest } from \"../api/api.js\";\n\nexport type Credentials =\n | {\n type: \"client_token\";\n token: string;\n client: string;\n }\n | {\n type: \"jwt\";\n jwt: string;\n styleguideId: number;\n features: Record<string, boolean>;\n };\n\nexport function getCredentialsFromEnvironment(): Credentials {\n const token = process.env[\"ZEROHEIGHT_ACCESS_TOKEN\"];\n const client = process.env[\"ZEROHEIGHT_CLIENT_ID\"];\n if (!token || !client) {\n throw new MissingCredentialsError();\n }\n\n return {\n type: \"client_token\",\n token,\n client,\n };\n}\n\ninterface JwtResponse {\n jwt: string;\n styleguide_id: number;\n features: Record<string, boolean>;\n}\n\nexport async function getCredentials(\n authInfo?: AuthInfo
|
|
1
|
+
{"version":3,"file":"credentials.js","sources":["common/credentials.ts"],"sourceRoot":"/","sourcesContent":["import { AuthInfo } from \"@modelcontextprotocol/sdk/server/auth/types.js\";\nimport { MissingCredentialsError } from \"./errors.js\";\nimport { internalRequest } from \"../api/api.js\";\n\nexport type Credentials =\n | {\n type: \"client_token\";\n token: string;\n client: string;\n }\n | {\n type: \"jwt\";\n jwt: string;\n styleguideId: number;\n features: Record<string, boolean>;\n viewerId?: string;\n userId?: number;\n teamId?: number;\n mcpAuthId?: number;\n tokenSets?: Array<{ id: number; name: string }>;\n }\n | {\n type: \"oauth_jwt\";\n jwt: string;\n clientId: string;\n features: Record<string, boolean>;\n userId: number;\n teamId: number;\n };\n\nexport function isLocalMCP(\n credentials: Credentials,\n): credentials is Extract<Credentials, { type: \"client_token\" }> {\n return credentials.type === \"client_token\";\n}\n\nexport function getCredentialsFromEnvironment(): Credentials {\n const token = process.env[\"ZEROHEIGHT_ACCESS_TOKEN\"];\n const client = process.env[\"ZEROHEIGHT_CLIENT_ID\"];\n if (!token || !client) {\n throw new MissingCredentialsError();\n }\n\n return {\n type: \"client_token\",\n token,\n client,\n };\n}\n\ninterface JwtResponse {\n jwt: string;\n styleguide_id: number;\n features: Record<string, boolean>;\n user_id?: number;\n viewer_id?: string;\n team_id?: number;\n mcp_auth_id?: number;\n token_sets?: Array<{ id: number; name: string }>;\n}\n\nexport async function getCredentials(\n authInfo?: AuthInfo,\n): Promise<Credentials> {\n if (!authInfo) {\n return getCredentialsFromEnvironment();\n }\n if (authInfo.clientId === \"http-client\") {\n const res = await internalRequest<JwtResponse>(\n \"/mcp_url/exchange_token\",\n \"POST\",\n {\n token: authInfo.token,\n },\n );\n\n return {\n type: \"jwt\",\n jwt: res.jwt,\n styleguideId: res.styleguide_id,\n features: res.features ?? {},\n userId: res.user_id,\n viewerId: res.viewer_id,\n teamId: res.team_id,\n mcpAuthId: res.mcp_auth_id,\n tokenSets: res.token_sets,\n };\n }\n return {\n type: \"oauth_jwt\",\n jwt: authInfo.token,\n features: authInfo.extra!.features as Record<string, boolean>,\n userId: authInfo.extra!.user_id as number,\n teamId: authInfo.extra!.team_id as number,\n clientId: authInfo.clientId,\n };\n}\n"],"names":[],"mappings":";;AACA,OAAO,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AA4BhD,MAAM,UAAU,UAAU,CACxB,WAAwB;IAExB,OAAO,WAAW,CAAC,IAAI,KAAK,cAAc,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,6BAA6B;IAC3C,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;IACrD,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;IACnD,IAAI,CAAC,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC;QACtB,MAAM,IAAI,uBAAuB,EAAE,CAAC;IACtC,CAAC;IAED,OAAO;QACL,IAAI,EAAE,cAAc;QACpB,KAAK;QACL,MAAM;KACP,CAAC;AACJ,CAAC;AAaD,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,QAAmB;IAEnB,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,6BAA6B,EAAE,CAAC;IACzC,CAAC;IACD,IAAI,QAAQ,CAAC,QAAQ,KAAK,aAAa,EAAE,CAAC;QACxC,MAAM,GAAG,GAAG,MAAM,eAAe,CAC/B,yBAAyB,EACzB,MAAM,EACN;YACE,KAAK,EAAE,QAAQ,CAAC,KAAK;SACtB,CACF,CAAC;QAEF,OAAO;YACL,IAAI,EAAE,KAAK;YACX,GAAG,EAAE,GAAG,CAAC,GAAG;YACZ,YAAY,EAAE,GAAG,CAAC,aAAa;YAC/B,QAAQ,EAAE,GAAG,CAAC,QAAQ,IAAI,EAAE;YAC5B,MAAM,EAAE,GAAG,CAAC,OAAO;YACnB,QAAQ,EAAE,GAAG,CAAC,SAAS;YACvB,MAAM,EAAE,GAAG,CAAC,OAAO;YACnB,SAAS,EAAE,GAAG,CAAC,WAAW;YAC1B,SAAS,EAAE,GAAG,CAAC,UAAU;SAC1B,CAAC;IACJ,CAAC;IACD,OAAO;QACL,IAAI,EAAE,WAAW;QACjB,GAAG,EAAE,QAAQ,CAAC,KAAK;QACnB,QAAQ,EAAE,QAAQ,CAAC,KAAM,CAAC,QAAmC;QAC7D,MAAM,EAAE,QAAQ,CAAC,KAAM,CAAC,OAAiB;QACzC,MAAM,EAAE,QAAQ,CAAC,KAAM,CAAC,OAAiB;QACzC,QAAQ,EAAE,QAAQ,CAAC,QAAQ;KAC5B,CAAC;AACJ,CAAC","debug_id":"11c203a2-35a9-5524-af57-bf3c016a0056"}
|
|
@@ -0,0 +1,10 @@
|
|
|
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]="4c5c6e2e-3416-5b29-a1eb-011b1b114173")}catch(e){}}();
|
|
3
|
+
export function formatTokenSetsAsMarkdown(tokenSets) {
|
|
4
|
+
if (tokenSets.length === 0) {
|
|
5
|
+
return "No token sets available. You can link token sets in your styleguide's AI settings.";
|
|
6
|
+
}
|
|
7
|
+
return tokenSets.map((ts) => `- ${ts.name} (ID: ${ts.id})`).join("\n");
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=token.js.map
|
|
10
|
+
//# debugId=4c5c6e2e-3416-5b29-a1eb-011b1b114173
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token.js","sources":["common/formatters/token.ts"],"sourceRoot":"/","sourcesContent":["import { LinkedTokenSet } from \"../../types/server.js\";\n\nexport function formatTokenSetsAsMarkdown(tokenSets: LinkedTokenSet[]): string {\n if (tokenSets.length === 0) {\n return \"No token sets available. You can link token sets in your styleguide's AI settings.\";\n }\n return tokenSets.map((ts) => `- ${ts.name} (ID: ${ts.id})`).join(\"\\n\");\n}\n"],"names":[],"mappings":";;AAEA,MAAM,UAAU,yBAAyB,CAAC,SAA2B;IACnE,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3B,OAAO,oFAAoF,CAAC;IAC9F,CAAC;IACD,OAAO,SAAS,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,KAAK,EAAE,CAAC,IAAI,SAAS,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACzE,CAAC","debug_id":"4c5c6e2e-3416-5b29-a1eb-011b1b114173"}
|
|
@@ -0,0 +1,43 @@
|
|
|
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]="c0a4d1e9-2a97-5cc7-8056-fb540bb525a7")}catch(e){}}();
|
|
3
|
+
import { parse, differenceCiede2000 } from "culori";
|
|
4
|
+
import { flattenTokensByType } from "./tokens.js";
|
|
5
|
+
export function parseColor(value) {
|
|
6
|
+
const parsed = parse(value);
|
|
7
|
+
return parsed ?? null;
|
|
8
|
+
}
|
|
9
|
+
/** CIEDE2000 perceptual distance. 0 = identical, higher = more different. */
|
|
10
|
+
export function colorDistance(color1, color2) {
|
|
11
|
+
const c1 = parse(color1);
|
|
12
|
+
const c2 = parse(color2);
|
|
13
|
+
if (!c1 || !c2)
|
|
14
|
+
return null;
|
|
15
|
+
const diff = differenceCiede2000();
|
|
16
|
+
return diff(c1, c2);
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Find the closest color token within a CIEDE2000 threshold.
|
|
20
|
+
* Default threshold is 10 (perceptually similar).
|
|
21
|
+
*/
|
|
22
|
+
export function findClosestColorToken(color, tokens, threshold = 10) {
|
|
23
|
+
const parsedColor = parse(color);
|
|
24
|
+
if (!parsedColor)
|
|
25
|
+
return null;
|
|
26
|
+
const colorTokens = flattenTokensByType(tokens, "color");
|
|
27
|
+
const diff = differenceCiede2000();
|
|
28
|
+
let closest = null;
|
|
29
|
+
for (const [name, tokenValue] of colorTokens) {
|
|
30
|
+
const tokenColor = parse(tokenValue);
|
|
31
|
+
if (!tokenColor)
|
|
32
|
+
continue;
|
|
33
|
+
const distance = diff(parsedColor, tokenColor);
|
|
34
|
+
if (distance <= threshold) {
|
|
35
|
+
if (!closest || distance < closest.distance) {
|
|
36
|
+
closest = { name, value: tokenValue, distance };
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return closest;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=color.js.map
|
|
43
|
+
//# debugId=c0a4d1e9-2a97-5cc7-8056-fb540bb525a7
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"color.js","sources":["lint/color.ts"],"sourceRoot":"/","sourcesContent":["import { parse, differenceCiede2000, type Color } from \"culori\";\nimport type { TokenGroup } from \"../api/types/token.js\";\nimport { flattenTokensByType } from \"./tokens.js\";\n\nexport function parseColor(value: string): Color | null {\n const parsed = parse(value);\n return parsed ?? null;\n}\n\n/** CIEDE2000 perceptual distance. 0 = identical, higher = more different. */\nexport function colorDistance(color1: string, color2: string): number | null {\n const c1 = parse(color1);\n const c2 = parse(color2);\n if (!c1 || !c2) return null;\n\n const diff = differenceCiede2000();\n return diff(c1, c2);\n}\n\nexport interface ColorTokenMatch {\n name: string;\n value: string;\n distance: number;\n}\n\n/**\n * Find the closest color token within a CIEDE2000 threshold.\n * Default threshold is 10 (perceptually similar).\n */\nexport function findClosestColorToken(\n color: string,\n tokens: TokenGroup,\n threshold: number = 10,\n): ColorTokenMatch | null {\n const parsedColor = parse(color);\n if (!parsedColor) return null;\n\n const colorTokens = flattenTokensByType(tokens, \"color\");\n const diff = differenceCiede2000();\n\n let closest: ColorTokenMatch | null = null;\n\n for (const [name, tokenValue] of colorTokens) {\n const tokenColor = parse(tokenValue);\n if (!tokenColor) continue;\n\n const distance = diff(parsedColor, tokenColor);\n\n if (distance <= threshold) {\n if (!closest || distance < closest.distance) {\n closest = { name, value: tokenValue, distance };\n }\n }\n }\n\n return closest;\n}\n"],"names":[],"mappings":";;AAAA,OAAO,EAAE,KAAK,EAAE,mBAAmB,EAAc,MAAM,QAAQ,CAAC;AAEhE,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAElD,MAAM,UAAU,UAAU,CAAC,KAAa;IACtC,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;IAC5B,OAAO,MAAM,IAAI,IAAI,CAAC;AACxB,CAAC;AAED,6EAA6E;AAC7E,MAAM,UAAU,aAAa,CAAC,MAAc,EAAE,MAAc;IAC1D,MAAM,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;IACzB,MAAM,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;IACzB,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE;QAAE,OAAO,IAAI,CAAC;IAE5B,MAAM,IAAI,GAAG,mBAAmB,EAAE,CAAC;IACnC,OAAO,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;AACtB,CAAC;AAQD;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CACnC,KAAa,EACb,MAAkB,EAClB,YAAoB,EAAE;IAEtB,MAAM,WAAW,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;IACjC,IAAI,CAAC,WAAW;QAAE,OAAO,IAAI,CAAC;IAE9B,MAAM,WAAW,GAAG,mBAAmB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACzD,MAAM,IAAI,GAAG,mBAAmB,EAAE,CAAC;IAEnC,IAAI,OAAO,GAA2B,IAAI,CAAC;IAE3C,KAAK,MAAM,CAAC,IAAI,EAAE,UAAU,CAAC,IAAI,WAAW,EAAE,CAAC;QAC7C,MAAM,UAAU,GAAG,KAAK,CAAC,UAAU,CAAC,CAAC;QACrC,IAAI,CAAC,UAAU;YAAE,SAAS;QAE1B,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;QAE/C,IAAI,QAAQ,IAAI,SAAS,EAAE,CAAC;YAC1B,IAAI,CAAC,OAAO,IAAI,QAAQ,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;gBAC5C,OAAO,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAC;YAClD,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC","debug_id":"c0a4d1e9-2a97-5cc7-8056-fb540bb525a7"}
|