accessflow-mcp-server 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/TOOL_REFERENCE.md +126 -0
- package/bin/flow-mcp +4 -0
- package/build/index.d.ts +3 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +95 -0
- package/build/index.js.map +1 -0
- package/build/prompts/formatUrgentIssues.d.ts +4 -0
- package/build/prompts/formatUrgentIssues.d.ts.map +1 -0
- package/build/prompts/formatUrgentIssues.js +78 -0
- package/build/prompts/formatUrgentIssues.js.map +1 -0
- package/build/prompts/index.d.ts +4 -0
- package/build/prompts/index.d.ts.map +1 -0
- package/build/prompts/index.js +12 -0
- package/build/prompts/index.js.map +1 -0
- package/build/prompts/types.d.ts +22 -0
- package/build/prompts/types.d.ts.map +1 -0
- package/build/prompts/types.js +2 -0
- package/build/prompts/types.js.map +1 -0
- package/build/rules.json +4591 -0
- package/build/services/accessflow.d.ts +6 -0
- package/build/services/accessflow.d.ts.map +1 -0
- package/build/services/accessflow.js +8 -0
- package/build/services/accessflow.js.map +1 -0
- package/build/tools/getIssueRemediation.d.ts +4 -0
- package/build/tools/getIssueRemediation.d.ts.map +1 -0
- package/build/tools/getIssueRemediation.js +165 -0
- package/build/tools/getIssueRemediation.js.map +1 -0
- package/build/tools/getMostUrgentIssues.d.ts +4 -0
- package/build/tools/getMostUrgentIssues.d.ts.map +1 -0
- package/build/tools/getMostUrgentIssues.js +106 -0
- package/build/tools/getMostUrgentIssues.js.map +1 -0
- package/build/tools/index.d.ts +9 -0
- package/build/tools/index.d.ts.map +1 -0
- package/build/tools/index.js +19 -0
- package/build/tools/index.js.map +1 -0
- package/build/tools/types.d.ts +19 -0
- package/build/tools/types.d.ts.map +1 -0
- package/build/tools/types.js +2 -0
- package/build/tools/types.js.map +1 -0
- package/build/utils/config.d.ts +8 -0
- package/build/utils/config.d.ts.map +1 -0
- package/build/utils/config.js +26 -0
- package/build/utils/config.js.map +1 -0
- package/build/utils/database.d.ts +13 -0
- package/build/utils/database.d.ts.map +1 -0
- package/build/utils/database.js +64 -0
- package/build/utils/database.js.map +1 -0
- package/build/utils/domain.d.ts +2 -0
- package/build/utils/domain.d.ts.map +1 -0
- package/build/utils/domain.js +11 -0
- package/build/utils/domain.js.map +1 -0
- package/build/utils/logger.d.ts +18 -0
- package/build/utils/logger.d.ts.map +1 -0
- package/build/utils/logger.js +51 -0
- package/build/utils/logger.js.map +1 -0
- package/build/utils/responses.d.ts +19 -0
- package/build/utils/responses.d.ts.map +1 -0
- package/build/utils/responses.js +41 -0
- package/build/utils/responses.js.map +1 -0
- package/build/utils/validation.d.ts +7 -0
- package/build/utils/validation.d.ts.map +1 -0
- package/build/utils/validation.js +47 -0
- package/build/utils/validation.js.map +1 -0
- package/mcp-config.json +11 -0
- package/package.json +33 -0
- package/src/index.ts +125 -0
- package/src/rules.json +4591 -0
- package/src/services/accessflow.ts +9 -0
- package/src/tools/getIssueRemediation.ts +218 -0
- package/src/tools/getMostUrgentIssues.ts +144 -0
- package/src/tools/index.ts +33 -0
- package/src/tools/types.ts +20 -0
- package/src/utils/domain.ts +13 -0
- package/test.mjs +63 -0
- package/tsconfig.json +20 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA,MAAM,CAAN,IAAY,QAKX;AALD,WAAY,QAAQ;IAClB,yCAAS,CAAA;IACT,uCAAQ,CAAA;IACR,uCAAQ,CAAA;IACR,yCAAS,CAAA;AACX,CAAC,EALW,QAAQ,KAAR,QAAQ,QAKnB;AAED,MAAM,OAAO,MAAM;IACT,KAAK,CAAW;IAExB,YAAY,QAAgB,MAAM;QAChC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IACzC,CAAC;IAEO,aAAa,CAAC,KAAa;QACjC,QAAQ,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;YAC5B,KAAK,OAAO,CAAC,CAAC,OAAO,QAAQ,CAAC,KAAK,CAAC;YACpC,KAAK,MAAM,CAAC,CAAC,OAAO,QAAQ,CAAC,IAAI,CAAC;YAClC,KAAK,MAAM,CAAC,CAAC,OAAO,QAAQ,CAAC,IAAI,CAAC;YAClC,KAAK,OAAO,CAAC,CAAC,OAAO,QAAQ,CAAC,KAAK,CAAC;YACpC,OAAO,CAAC,CAAC,OAAO,QAAQ,CAAC,IAAI,CAAC;QAChC,CAAC;IACH,CAAC;IAEO,SAAS,CAAC,KAAe;QAC/B,OAAO,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC;IAC7B,CAAC;IAEO,aAAa,CAAC,KAAa,EAAE,OAAe,EAAE,IAAU;QAC9D,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAC3C,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACvD,OAAO,IAAI,SAAS,KAAK,KAAK,KAAK,OAAO,GAAG,OAAO,EAAE,CAAC;IACzD,CAAC;IAED,KAAK,CAAC,OAAe,EAAE,IAAU;QAC/B,IAAI,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YACnC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;QAC5D,CAAC;IACH,CAAC;IAED,IAAI,CAAC,OAAe,EAAE,IAAU;QAC9B,IAAI,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YAClC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;QAC1D,CAAC;IACH,CAAC;IAED,IAAI,CAAC,OAAe,EAAE,IAAU;QAC9B,IAAI,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YAClC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;QACzD,CAAC;IACH,CAAC;IAED,KAAK,CAAC,OAAe,EAAE,IAAU;QAC/B,IAAI,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YACnC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;QAC1D,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export interface McpResponse {
|
|
2
|
+
content: Array<{
|
|
3
|
+
type: "text";
|
|
4
|
+
text: string;
|
|
5
|
+
}>;
|
|
6
|
+
}
|
|
7
|
+
export interface ErrorResponse {
|
|
8
|
+
error: string;
|
|
9
|
+
code: string;
|
|
10
|
+
details?: any;
|
|
11
|
+
}
|
|
12
|
+
export declare class ResponseFormatter {
|
|
13
|
+
static success(text: string): McpResponse;
|
|
14
|
+
static error(message: string, code?: string, details?: any): McpResponse;
|
|
15
|
+
static notFound(resource: string, identifier: string): McpResponse;
|
|
16
|
+
static validationError(message: string, field?: string): McpResponse;
|
|
17
|
+
static websiteMismatch(issueId: string, expectedWebsite: string, actualWebsite: string): McpResponse;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=responses.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"responses.d.ts","sourceRoot":"","sources":["../../src/utils/responses.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,KAAK,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;KACd,CAAC,CAAC;CACJ;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,GAAG,CAAC;CACf;AAED,qBAAa,iBAAiB;IAC5B,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW;IAWzC,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,GAAE,MAAyB,EAAE,OAAO,CAAC,EAAE,GAAG,GAAG,WAAW;IAiB1F,MAAM,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,WAAW;IAQlE,MAAM,CAAC,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,WAAW;IAQpE,MAAM,CAAC,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,WAAW;CAWrG"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export class ResponseFormatter {
|
|
2
|
+
static success(text) {
|
|
3
|
+
return {
|
|
4
|
+
content: [
|
|
5
|
+
{
|
|
6
|
+
type: "text",
|
|
7
|
+
text
|
|
8
|
+
}
|
|
9
|
+
]
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
static error(message, code = "INTERNAL_ERROR", details) {
|
|
13
|
+
const errorResponse = {
|
|
14
|
+
error: message,
|
|
15
|
+
code,
|
|
16
|
+
...(details && { details })
|
|
17
|
+
};
|
|
18
|
+
return {
|
|
19
|
+
content: [
|
|
20
|
+
{
|
|
21
|
+
type: "text",
|
|
22
|
+
text: `**Error (${code})**\n\n${message}${details ? `\n\n**Details:**\n\`\`\`json\n${JSON.stringify(details, null, 2)}\n\`\`\`` : ""}`
|
|
23
|
+
}
|
|
24
|
+
]
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
static notFound(resource, identifier) {
|
|
28
|
+
return this.error(`${resource} not found: ${identifier}`, "NOT_FOUND", { resource, identifier });
|
|
29
|
+
}
|
|
30
|
+
static validationError(message, field) {
|
|
31
|
+
return this.error(`Validation error: ${message}`, "VALIDATION_ERROR", { field });
|
|
32
|
+
}
|
|
33
|
+
static websiteMismatch(issueId, expectedWebsite, actualWebsite) {
|
|
34
|
+
return this.error(`Issue "${issueId}" belongs to website "${actualWebsite}" but expected website "${expectedWebsite}"`, "WEBSITE_MISMATCH", {
|
|
35
|
+
issueId,
|
|
36
|
+
expectedWebsite,
|
|
37
|
+
actualWebsite
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=responses.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"responses.js","sourceRoot":"","sources":["../../src/utils/responses.ts"],"names":[],"mappings":"AAaA,MAAM,OAAO,iBAAiB;IAC5B,MAAM,CAAC,OAAO,CAAC,IAAY;QACzB,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAM;oBACZ,IAAI;iBACL;aACF;SACF,CAAC;IACJ,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,OAAe,EAAE,OAAe,gBAAgB,EAAE,OAAa;QAC1E,MAAM,aAAa,GAAkB;YACnC,KAAK,EAAE,OAAO;YACd,IAAI;YACJ,GAAG,CAAC,OAAO,IAAI,EAAE,OAAO,EAAE,CAAC;SAC5B,CAAC;QAEF,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,YAAY,IAAI,UAAU,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,iCAAiC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,EAAE;iBACvI;aACF;SACF,CAAC;IACJ,CAAC;IAED,MAAM,CAAC,QAAQ,CAAC,QAAgB,EAAE,UAAkB;QAClD,OAAO,IAAI,CAAC,KAAK,CACf,GAAG,QAAQ,eAAe,UAAU,EAAE,EACtC,WAAW,EACX,EAAE,QAAQ,EAAE,UAAU,EAAE,CACzB,CAAC;IACJ,CAAC;IAED,MAAM,CAAC,eAAe,CAAC,OAAe,EAAE,KAAc;QACpD,OAAO,IAAI,CAAC,KAAK,CACf,qBAAqB,OAAO,EAAE,EAC9B,kBAAkB,EAClB,EAAE,KAAK,EAAE,CACV,CAAC;IACJ,CAAC;IAED,MAAM,CAAC,eAAe,CAAC,OAAe,EAAE,eAAuB,EAAE,aAAqB;QACpF,OAAO,IAAI,CAAC,KAAK,CACf,UAAU,OAAO,yBAAyB,aAAa,2BAA2B,eAAe,GAAG,EACpG,kBAAkB,EAClB;YACE,OAAO;YACP,eAAe;YACf,aAAa;SACd,CACF,CAAC;IACJ,CAAC;CACF"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare class ValidationError extends Error {
|
|
2
|
+
constructor(message: string);
|
|
3
|
+
}
|
|
4
|
+
export declare function validateIssueDisplayName(displayName: string): void;
|
|
5
|
+
export declare function validateObjectId(id: string): void;
|
|
6
|
+
export declare function sanitizeMongoQuery(query: any): any;
|
|
7
|
+
//# sourceMappingURL=validation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/utils/validation.ts"],"names":[],"mappings":"AAGA,qBAAa,eAAgB,SAAQ,KAAK;gBAC5B,OAAO,EAAE,MAAM;CAI5B;AAED,wBAAgB,wBAAwB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAalE;AAED,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAIjD;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,GAAG,GAAG,GAAG,CAwBlD"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { ObjectId } from "mongodb";
|
|
2
|
+
import { McpError, ErrorCode } from "@modelcontextprotocol/sdk/types.js";
|
|
3
|
+
export class ValidationError extends Error {
|
|
4
|
+
constructor(message) {
|
|
5
|
+
super(message);
|
|
6
|
+
this.name = "ValidationError";
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
export function validateIssueDisplayName(displayName) {
|
|
10
|
+
if (!displayName || typeof displayName !== "string") {
|
|
11
|
+
throw new McpError(ErrorCode.InvalidParams, "Issue display name must be a non-empty string");
|
|
12
|
+
}
|
|
13
|
+
// Sanitize input - remove potentially dangerous characters
|
|
14
|
+
if (!/^[a-zA-Z0-9\-_]+$/.test(displayName)) {
|
|
15
|
+
throw new McpError(ErrorCode.InvalidParams, "Issue display name contains invalid characters");
|
|
16
|
+
}
|
|
17
|
+
if (displayName.length > 100) {
|
|
18
|
+
throw new McpError(ErrorCode.InvalidParams, "Issue display name too long (max 100 characters)");
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export function validateObjectId(id) {
|
|
22
|
+
if (!ObjectId.isValid(id)) {
|
|
23
|
+
throw new McpError(ErrorCode.InvalidParams, `Invalid ObjectId format: ${id}`);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export function sanitizeMongoQuery(query) {
|
|
27
|
+
// Remove any potential MongoDB injection operators
|
|
28
|
+
const sanitized = JSON.parse(JSON.stringify(query));
|
|
29
|
+
function removeOperators(obj) {
|
|
30
|
+
if (Array.isArray(obj)) {
|
|
31
|
+
return obj.map(removeOperators);
|
|
32
|
+
}
|
|
33
|
+
if (obj && typeof obj === "object") {
|
|
34
|
+
const cleaned = {};
|
|
35
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
36
|
+
// Remove keys that start with $ (MongoDB operators)
|
|
37
|
+
if (!key.startsWith("$")) {
|
|
38
|
+
cleaned[key] = removeOperators(value);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return cleaned;
|
|
42
|
+
}
|
|
43
|
+
return obj;
|
|
44
|
+
}
|
|
45
|
+
return removeOperators(sanitized);
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=validation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/utils/validation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,oCAAoC,CAAC;AAEzE,MAAM,OAAO,eAAgB,SAAQ,KAAK;IACxC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;IAChC,CAAC;CACF;AAED,MAAM,UAAU,wBAAwB,CAAC,WAAmB;IAC1D,IAAI,CAAC,WAAW,IAAI,OAAO,WAAW,KAAK,QAAQ,EAAE,CAAC;QACpD,MAAM,IAAI,QAAQ,CAAC,SAAS,CAAC,aAAa,EAAE,+CAA+C,CAAC,CAAC;IAC/F,CAAC;IAED,2DAA2D;IAC3D,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;QAC3C,MAAM,IAAI,QAAQ,CAAC,SAAS,CAAC,aAAa,EAAE,gDAAgD,CAAC,CAAC;IAChG,CAAC;IAED,IAAI,WAAW,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;QAC7B,MAAM,IAAI,QAAQ,CAAC,SAAS,CAAC,aAAa,EAAE,kDAAkD,CAAC,CAAC;IAClG,CAAC;AACH,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,EAAU;IACzC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,QAAQ,CAAC,SAAS,CAAC,aAAa,EAAE,4BAA4B,EAAE,EAAE,CAAC,CAAC;IAChF,CAAC;AACH,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,KAAU;IAC3C,mDAAmD;IACnD,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;IAEpD,SAAS,eAAe,CAAC,GAAQ;QAC/B,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;YACvB,OAAO,GAAG,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;QAClC,CAAC;QAED,IAAI,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;YACnC,MAAM,OAAO,GAAQ,EAAE,CAAC;YACxB,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC/C,oDAAoD;gBACpD,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;oBACzB,OAAO,CAAC,GAAG,CAAC,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;gBACxC,CAAC;YACH,CAAC;YACD,OAAO,OAAO,CAAC;QACjB,CAAC;QAED,OAAO,GAAG,CAAC;IACb,CAAC;IAED,OAAO,eAAe,CAAC,SAAS,CAAC,CAAC;AACpC,CAAC"}
|
package/mcp-config.json
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "accessflow-mcp-server",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "AccessFlow MCP Server for accessibility issue remediation",
|
|
5
|
+
"main": "build/index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"flow-mcp": "./bin/flow-mcp"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"build": "tsc",
|
|
11
|
+
"start": "node build/index.js",
|
|
12
|
+
"dev": "tsc && node build/index.js",
|
|
13
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"mcp",
|
|
17
|
+
"accessibility",
|
|
18
|
+
"wcag",
|
|
19
|
+
"remediation"
|
|
20
|
+
],
|
|
21
|
+
"author": "AccessFlow",
|
|
22
|
+
"license": "ISC",
|
|
23
|
+
"type": "module",
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"@modelcontextprotocol/sdk": "^1.15.1",
|
|
26
|
+
"@types/mongodb": "^4.0.6",
|
|
27
|
+
"mongodb": "^6.17.0"
|
|
28
|
+
},
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"@types/node": "^24.0.14",
|
|
31
|
+
"typescript": "^5.8.3"
|
|
32
|
+
}
|
|
33
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
4
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
5
|
+
import {
|
|
6
|
+
CallToolRequestSchema,
|
|
7
|
+
ErrorCode,
|
|
8
|
+
ListToolsRequestSchema,
|
|
9
|
+
McpError,
|
|
10
|
+
} from "@modelcontextprotocol/sdk/types.js";
|
|
11
|
+
import rulesData from "./rules.json" with { type: "json" };
|
|
12
|
+
import { getToolDefinitions, getToolHandler } from "./tools/index.js";
|
|
13
|
+
import { ToolContext } from "./tools/types.js";
|
|
14
|
+
import { sanitizeDomain } from "./utils/domain.js";
|
|
15
|
+
|
|
16
|
+
class AccessFlowMCPServer {
|
|
17
|
+
private server: Server;
|
|
18
|
+
private environment: string;
|
|
19
|
+
private domain: string;
|
|
20
|
+
private apiKey: string;
|
|
21
|
+
private rules: any[] = rulesData;
|
|
22
|
+
|
|
23
|
+
constructor() {
|
|
24
|
+
this.server = new Server(
|
|
25
|
+
{
|
|
26
|
+
name: "flow-mcp",
|
|
27
|
+
version: "1.0.0",
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
capabilities: {
|
|
31
|
+
tools: {},
|
|
32
|
+
},
|
|
33
|
+
}
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
this.environment = process.env.ENVIRONMENT || "accessflow.accessibe.com";
|
|
37
|
+
|
|
38
|
+
// Get DOMAIN Key from environment variable
|
|
39
|
+
this.domain = sanitizeDomain(process.env.DOMAIN || "");
|
|
40
|
+
if (!this.domain) {
|
|
41
|
+
console.error("DOMAIN environment variable is required");
|
|
42
|
+
process.exit(1);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
// Get API Key from environment variable
|
|
47
|
+
this.apiKey = process.env.API_KEY || "";
|
|
48
|
+
if (!this.apiKey) {
|
|
49
|
+
console.error("API_KEY environment variable is required");
|
|
50
|
+
process.exit(1);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
this.setupToolHandlers();
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
private setupToolHandlers(): void {
|
|
57
|
+
this.server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
58
|
+
return {
|
|
59
|
+
tools: getToolDefinitions(),
|
|
60
|
+
};
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
64
|
+
const { name, arguments: args } = request.params;
|
|
65
|
+
|
|
66
|
+
try {
|
|
67
|
+
const handler = getToolHandler(name);
|
|
68
|
+
if (!handler) {
|
|
69
|
+
throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const headers: Record<string, string> = {
|
|
73
|
+
"x-api-key": this.apiKey,
|
|
74
|
+
"x-accessflow-domain": this.domain,
|
|
75
|
+
"Content-Type": "application/json",
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
if (this.environment.toLowerCase().includes("test")) {
|
|
79
|
+
const basicAuth = Buffer.from("test:acsb123").toString("base64");
|
|
80
|
+
headers["Authorization"] = `Basic ${basicAuth}`;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const context: ToolContext = {
|
|
84
|
+
rules: this.rules,
|
|
85
|
+
environment: this.environment,
|
|
86
|
+
apiKey: this.apiKey,
|
|
87
|
+
headers: headers,
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
return await handler(args || {}, context);
|
|
91
|
+
} catch (error) {
|
|
92
|
+
if (error instanceof McpError) {
|
|
93
|
+
throw error;
|
|
94
|
+
}
|
|
95
|
+
const errorMessage =
|
|
96
|
+
error instanceof Error ? error.message : String(error);
|
|
97
|
+
throw new McpError(
|
|
98
|
+
ErrorCode.InternalError,
|
|
99
|
+
`Tool execution failed: ${errorMessage}`
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
async run(): Promise<void> {
|
|
106
|
+
const transport = new StdioServerTransport();
|
|
107
|
+
await this.server.connect(transport);
|
|
108
|
+
console.error("AccessFlow MCP Server running on stdio");
|
|
109
|
+
|
|
110
|
+
// Handle graceful shutdown
|
|
111
|
+
process.on("SIGINT", async () => {
|
|
112
|
+
console.error("Shutting down AccessFlow MCP Server...");
|
|
113
|
+
process.exit(0);
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
process.on("SIGTERM", async () => {
|
|
117
|
+
console.error("Shutting down AccessFlow MCP Server...");
|
|
118
|
+
process.exit(0);
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Start the server
|
|
124
|
+
const server = new AccessFlowMCPServer();
|
|
125
|
+
server.run().catch(console.error);
|