acf-mcp 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.
Files changed (75) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +87 -0
  3. package/content/fiches/.gitkeep +0 -0
  4. package/content/fiches/ACF-00.en.md +59 -0
  5. package/content/fiches/ACF-00.fr.md +59 -0
  6. package/content/fiches/ACF-01.en.md +32 -0
  7. package/content/fiches/ACF-01.fr.md +32 -0
  8. package/content/fiches/ACF-02.en.md +32 -0
  9. package/content/fiches/ACF-02.fr.md +32 -0
  10. package/content/fiches/ACF-03.en.md +78 -0
  11. package/content/fiches/ACF-03.fr.md +78 -0
  12. package/content/fiches/ACF-04.en.md +32 -0
  13. package/content/fiches/ACF-04.fr.md +32 -0
  14. package/content/fiches/ACF-05.en.md +32 -0
  15. package/content/fiches/ACF-05.fr.md +32 -0
  16. package/content/fiches/ACF-06.en.md +32 -0
  17. package/content/fiches/ACF-06.fr.md +32 -0
  18. package/content/fiches/ACF-07.en.md +32 -0
  19. package/content/fiches/ACF-07.fr.md +32 -0
  20. package/content/fiches/ACF-08.en.md +32 -0
  21. package/content/fiches/ACF-08.fr.md +32 -0
  22. package/content/fiches/ACF-09.en.md +32 -0
  23. package/content/fiches/ACF-09.fr.md +32 -0
  24. package/content/fiches/ACF-10.en.md +32 -0
  25. package/content/fiches/ACF-10.fr.md +32 -0
  26. package/content/fiches/ACF-11.en.md +32 -0
  27. package/content/fiches/ACF-11.fr.md +32 -0
  28. package/content/fiches/ACF-12.en.md +32 -0
  29. package/content/fiches/ACF-12.fr.md +32 -0
  30. package/content/fiches/ACF-13.en.md +32 -0
  31. package/content/fiches/ACF-13.fr.md +32 -0
  32. package/content/fiches/ACF-14.en.md +32 -0
  33. package/content/fiches/ACF-14.fr.md +32 -0
  34. package/content/fiches/ACF-15.en.md +32 -0
  35. package/content/fiches/ACF-15.fr.md +32 -0
  36. package/content/fiches/ACF-16.en.md +32 -0
  37. package/content/fiches/ACF-16.fr.md +32 -0
  38. package/content/framework/.gitkeep +0 -0
  39. package/content/framework/autonomy-levels.json +73 -0
  40. package/content/framework/ddao.json +16 -0
  41. package/content/framework/dimensions.json +83 -0
  42. package/content/framework/principles.json +77 -0
  43. package/content/glossary/.gitkeep +0 -0
  44. package/content/glossary/en.json +96 -0
  45. package/content/glossary/fr.json +96 -0
  46. package/content/guides/.gitkeep +0 -0
  47. package/content/manual/.gitkeep +0 -0
  48. package/content/meta.json +23 -0
  49. package/content/rules/.gitkeep +0 -0
  50. package/content/rules/ai-act-annex-i.json +54 -0
  51. package/content/rules/ai-act-annex-iii.json +165 -0
  52. package/content/rules/ai-act-roles.json +52 -0
  53. package/content/rules/autonomy-inference.json +38 -0
  54. package/content/rules/criticality-matrix.json +83 -0
  55. package/content/rules/ddao-controls-mapping.json +148 -0
  56. package/content/rules/gdpr-qualification.json +58 -0
  57. package/content/rules/gpai-triggers.json +41 -0
  58. package/content/rules/rules-meta.json +5 -0
  59. package/content/rules/sign-off-matrix.json +84 -0
  60. package/content/whitepaper/.gitkeep +0 -0
  61. package/dist/index.d.ts +30 -0
  62. package/dist/index.js +2898 -0
  63. package/dist/index.js.map +1 -0
  64. package/dist/lib/rate-limit.d.ts +24 -0
  65. package/dist/lib/rate-limit.js +89 -0
  66. package/dist/lib/rate-limit.js.map +1 -0
  67. package/dist/search-index.json +1 -0
  68. package/dist/server-DxztThU5.d.ts +931 -0
  69. package/dist/transport/http.d.ts +27 -0
  70. package/dist/transport/http.js +2908 -0
  71. package/dist/transport/http.js.map +1 -0
  72. package/dist/transport/stdio.d.ts +1 -0
  73. package/dist/transport/stdio.js +2907 -0
  74. package/dist/transport/stdio.js.map +1 -0
  75. package/package.json +81 -0
@@ -0,0 +1,24 @@
1
+ interface RateLimitTier {
2
+ key: string;
3
+ perIpLimit: number;
4
+ globalLimit: number;
5
+ }
6
+ declare const RATE_LIMIT_TIERS: Record<string, RateLimitTier>;
7
+ interface ToolPickInput {
8
+ method: string;
9
+ toolName?: string;
10
+ uri?: string;
11
+ }
12
+ declare function pickRateLimitConfig(input: ToolPickInput): RateLimitTier;
13
+ interface RateLimitCheckInput extends RateLimitTier {
14
+ windowMs: number;
15
+ }
16
+ interface RateLimitCheckResult {
17
+ allowed: boolean;
18
+ retryAfter?: number;
19
+ reason?: "per_ip" | "global";
20
+ }
21
+ declare function checkRateLimit(ip: string, input: RateLimitCheckInput): RateLimitCheckResult;
22
+ declare function _resetForTests(): void;
23
+
24
+ export { RATE_LIMIT_TIERS, type RateLimitCheckInput, type RateLimitCheckResult, type RateLimitTier, type ToolPickInput, _resetForTests, checkRateLimit, pickRateLimitConfig };
@@ -0,0 +1,89 @@
1
+ // src/lib/rate-limit.ts
2
+ var RATE_LIMIT_TIERS = {
3
+ "mcp.search": { key: "mcp.search", perIpLimit: 60, globalLimit: 1e3 },
4
+ "mcp.fiche": { key: "mcp.fiche", perIpLimit: 60, globalLimit: 1e3 },
5
+ "mcp.reason": { key: "mcp.reason", perIpLimit: 30, globalLimit: 500 },
6
+ "mcp.heavy-read": { key: "mcp.heavy-read", perIpLimit: 15, globalLimit: 200 }
7
+ };
8
+ var REASON_TOOLS = /* @__PURE__ */ new Set([
9
+ "acf.advisor",
10
+ "acf.classify-agent",
11
+ "acf.assess-autonomy",
12
+ "acf.identify-governance-gaps",
13
+ "acf.map-ai-act-obligations",
14
+ "acf.assign-ddao-controls",
15
+ "acf.evaluate-agent-mandate"
16
+ ]);
17
+ var FICHE_TOOLS = /* @__PURE__ */ new Set([
18
+ "acf.fiche.lookup",
19
+ "acf.glossary.define",
20
+ "acf.cite",
21
+ "acf.regulation.article"
22
+ ]);
23
+ var HEAVY_READ_URI_PATTERNS = [
24
+ /^acf:\/\/whitepaper(?:\?|$)/,
25
+ // full whitepaper
26
+ /^acf:\/\/manual(?:\?|$)/,
27
+ /^acf:\/\/guide\/[a-z0-9-]+(?:\?|$)/
28
+ ];
29
+ function pickRateLimitConfig(input) {
30
+ if (input.method === "tools/call" && input.toolName) {
31
+ if (REASON_TOOLS.has(input.toolName)) return RATE_LIMIT_TIERS["mcp.reason"];
32
+ if (FICHE_TOOLS.has(input.toolName)) return RATE_LIMIT_TIERS["mcp.fiche"];
33
+ if (input.toolName === "acf.search") return RATE_LIMIT_TIERS["mcp.search"];
34
+ }
35
+ if (input.method === "resources/read" && input.uri) {
36
+ if (HEAVY_READ_URI_PATTERNS.some((p) => p.test(input.uri))) {
37
+ return RATE_LIMIT_TIERS["mcp.heavy-read"];
38
+ }
39
+ return RATE_LIMIT_TIERS["mcp.fiche"];
40
+ }
41
+ return RATE_LIMIT_TIERS["mcp.search"];
42
+ }
43
+ var perIpBuckets = /* @__PURE__ */ new Map();
44
+ var globalBuckets = /* @__PURE__ */ new Map();
45
+ function consume(bucketMap, bucketKey, limit, windowMs, now) {
46
+ const existing = bucketMap.get(bucketKey);
47
+ if (!existing || now - existing.windowStart > windowMs) {
48
+ bucketMap.set(bucketKey, { count: 1, windowStart: now });
49
+ return true;
50
+ }
51
+ if (existing.count >= limit) return false;
52
+ existing.count += 1;
53
+ return true;
54
+ }
55
+ function checkRateLimit(ip, input) {
56
+ const now = Date.now();
57
+ const ipKey = `${input.key}|${ip}`;
58
+ const ipOk = consume(perIpBuckets, ipKey, input.perIpLimit, input.windowMs, now);
59
+ if (!ipOk) {
60
+ return {
61
+ allowed: false,
62
+ retryAfter: Math.ceil(input.windowMs / 1e3),
63
+ reason: "per_ip"
64
+ };
65
+ }
66
+ const globalOk = consume(
67
+ globalBuckets,
68
+ input.key,
69
+ input.globalLimit,
70
+ input.windowMs,
71
+ now
72
+ );
73
+ if (!globalOk) {
74
+ return {
75
+ allowed: false,
76
+ retryAfter: Math.ceil(input.windowMs / 1e3),
77
+ reason: "global"
78
+ };
79
+ }
80
+ return { allowed: true };
81
+ }
82
+ function _resetForTests() {
83
+ perIpBuckets.clear();
84
+ globalBuckets.clear();
85
+ }
86
+
87
+ export { RATE_LIMIT_TIERS, _resetForTests, checkRateLimit, pickRateLimitConfig };
88
+ //# sourceMappingURL=rate-limit.js.map
89
+ //# sourceMappingURL=rate-limit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/lib/rate-limit.ts"],"names":[],"mappings":"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","file":"rate-limit.js","sourcesContent":["export interface RateLimitTier {\n key: string;\n perIpLimit: number;\n globalLimit: number;\n}\n\nexport const RATE_LIMIT_TIERS: Record<string, RateLimitTier> = {\n \"mcp.search\": { key: \"mcp.search\", perIpLimit: 60, globalLimit: 1000 },\n \"mcp.fiche\": { key: \"mcp.fiche\", perIpLimit: 60, globalLimit: 1000 },\n \"mcp.reason\": { key: \"mcp.reason\", perIpLimit: 30, globalLimit: 500 },\n \"mcp.heavy-read\": { key: \"mcp.heavy-read\", perIpLimit: 15, globalLimit: 200 },\n};\n\nconst REASON_TOOLS = new Set([\n \"acf.advisor\",\n \"acf.classify-agent\",\n \"acf.assess-autonomy\",\n \"acf.identify-governance-gaps\",\n \"acf.map-ai-act-obligations\",\n \"acf.assign-ddao-controls\",\n \"acf.evaluate-agent-mandate\",\n]);\n\nconst FICHE_TOOLS = new Set([\n \"acf.fiche.lookup\", \"acf.glossary.define\", \"acf.cite\", \"acf.regulation.article\",\n]);\n\nconst HEAVY_READ_URI_PATTERNS = [\n /^acf:\\/\\/whitepaper(?:\\?|$)/, // full whitepaper\n /^acf:\\/\\/manual(?:\\?|$)/,\n /^acf:\\/\\/guide\\/[a-z0-9-]+(?:\\?|$)/,\n];\n\nexport interface ToolPickInput {\n method: string;\n toolName?: string;\n uri?: string;\n}\n\nexport function pickRateLimitConfig(input: ToolPickInput): RateLimitTier {\n if (input.method === \"tools/call\" && input.toolName) {\n if (REASON_TOOLS.has(input.toolName)) return RATE_LIMIT_TIERS[\"mcp.reason\"]!;\n if (FICHE_TOOLS.has(input.toolName)) return RATE_LIMIT_TIERS[\"mcp.fiche\"]!;\n if (input.toolName === \"acf.search\") return RATE_LIMIT_TIERS[\"mcp.search\"]!;\n }\n if (input.method === \"resources/read\" && input.uri) {\n if (HEAVY_READ_URI_PATTERNS.some((p) => p.test(input.uri!))) {\n return RATE_LIMIT_TIERS[\"mcp.heavy-read\"]!;\n }\n return RATE_LIMIT_TIERS[\"mcp.fiche\"]!;\n }\n return RATE_LIMIT_TIERS[\"mcp.search\"]!;\n}\n\ninterface Bucket {\n count: number;\n windowStart: number;\n}\n\nconst perIpBuckets = new Map<string, Bucket>();\nconst globalBuckets = new Map<string, Bucket>();\n\nexport interface RateLimitCheckInput extends RateLimitTier {\n windowMs: number;\n}\n\nexport interface RateLimitCheckResult {\n allowed: boolean;\n retryAfter?: number;\n reason?: \"per_ip\" | \"global\";\n}\n\nfunction consume(\n bucketMap: Map<string, Bucket>,\n bucketKey: string,\n limit: number,\n windowMs: number,\n now: number,\n): boolean {\n const existing = bucketMap.get(bucketKey);\n if (!existing || now - existing.windowStart > windowMs) {\n bucketMap.set(bucketKey, { count: 1, windowStart: now });\n return true;\n }\n if (existing.count >= limit) return false;\n existing.count += 1;\n return true;\n}\n\nexport function checkRateLimit(\n ip: string,\n input: RateLimitCheckInput,\n): RateLimitCheckResult {\n const now = Date.now();\n const ipKey = `${input.key}|${ip}`;\n const ipOk = consume(perIpBuckets, ipKey, input.perIpLimit, input.windowMs, now);\n if (!ipOk) {\n return {\n allowed: false,\n retryAfter: Math.ceil(input.windowMs / 1000),\n reason: \"per_ip\",\n };\n }\n const globalOk = consume(\n globalBuckets, input.key, input.globalLimit, input.windowMs, now,\n );\n if (!globalOk) {\n return {\n allowed: false,\n retryAfter: Math.ceil(input.windowMs / 1000),\n reason: \"global\",\n };\n }\n return { allowed: true };\n}\n\nexport function _resetForTests() {\n perIpBuckets.clear();\n globalBuckets.clear();\n}\n"]}