@creezio/mcp-facade 0.22.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 (174) hide show
  1. package/README.md +420 -0
  2. package/dist/.creezio-src-hash.json +4 -0
  3. package/dist/admin/adapters.d.ts +10 -0
  4. package/dist/admin/adapters.d.ts.map +1 -0
  5. package/dist/admin/adapters.js +21 -0
  6. package/dist/admin/adapters.js.map +1 -0
  7. package/dist/admin/http-routes.d.ts +11 -0
  8. package/dist/admin/http-routes.d.ts.map +1 -0
  9. package/dist/admin/http-routes.js +66 -0
  10. package/dist/admin/http-routes.js.map +1 -0
  11. package/dist/admin/index.d.ts +12 -0
  12. package/dist/admin/index.d.ts.map +1 -0
  13. package/dist/admin/index.js +8 -0
  14. package/dist/admin/index.js.map +1 -0
  15. package/dist/admin/mcp-admin.d.ts +165 -0
  16. package/dist/admin/mcp-admin.d.ts.map +1 -0
  17. package/dist/admin/mcp-admin.js +419 -0
  18. package/dist/admin/mcp-admin.js.map +1 -0
  19. package/dist/admin/tool-policy-guard.d.ts +106 -0
  20. package/dist/admin/tool-policy-guard.d.ts.map +1 -0
  21. package/dist/admin/tool-policy-guard.js +187 -0
  22. package/dist/admin/tool-policy-guard.js.map +1 -0
  23. package/dist/admin/types.d.ts +62 -0
  24. package/dist/admin/types.d.ts.map +1 -0
  25. package/dist/admin/types.js +6 -0
  26. package/dist/admin/types.js.map +1 -0
  27. package/dist/brand-facade.d.ts +41 -0
  28. package/dist/brand-facade.d.ts.map +1 -0
  29. package/dist/brand-facade.js +67 -0
  30. package/dist/brand-facade.js.map +1 -0
  31. package/dist/core-tools.d.ts +22 -0
  32. package/dist/core-tools.d.ts.map +1 -0
  33. package/dist/core-tools.js +93 -0
  34. package/dist/core-tools.js.map +1 -0
  35. package/dist/dyn-import.d.ts +13 -0
  36. package/dist/dyn-import.d.ts.map +1 -0
  37. package/dist/dyn-import.js +2 -0
  38. package/dist/dyn-import.js.map +1 -0
  39. package/dist/facade.d.ts +40 -0
  40. package/dist/facade.d.ts.map +1 -0
  41. package/dist/facade.js +334 -0
  42. package/dist/facade.js.map +1 -0
  43. package/dist/hono-bind.d.ts +48 -0
  44. package/dist/hono-bind.d.ts.map +1 -0
  45. package/dist/hono-bind.js +70 -0
  46. package/dist/hono-bind.js.map +1 -0
  47. package/dist/hono-proxy.d.ts +63 -0
  48. package/dist/hono-proxy.d.ts.map +1 -0
  49. package/dist/hono-proxy.js +185 -0
  50. package/dist/hono-proxy.js.map +1 -0
  51. package/dist/index.d.ts +32 -0
  52. package/dist/index.d.ts.map +1 -0
  53. package/dist/index.js +23 -0
  54. package/dist/index.js.map +1 -0
  55. package/dist/jwt.d.ts +20 -0
  56. package/dist/jwt.d.ts.map +1 -0
  57. package/dist/jwt.js +84 -0
  58. package/dist/jwt.js.map +1 -0
  59. package/dist/module-ops-tools.d.ts +43 -0
  60. package/dist/module-ops-tools.d.ts.map +1 -0
  61. package/dist/module-ops-tools.js +301 -0
  62. package/dist/module-ops-tools.js.map +1 -0
  63. package/dist/namespace.d.ts +23 -0
  64. package/dist/namespace.d.ts.map +1 -0
  65. package/dist/namespace.js +51 -0
  66. package/dist/namespace.js.map +1 -0
  67. package/dist/oauth/cors-policy.d.ts +3 -0
  68. package/dist/oauth/cors-policy.d.ts.map +1 -0
  69. package/dist/oauth/cors-policy.js +25 -0
  70. package/dist/oauth/cors-policy.js.map +1 -0
  71. package/dist/oauth/hono-app.d.ts +18 -0
  72. package/dist/oauth/hono-app.d.ts.map +1 -0
  73. package/dist/oauth/hono-app.js +175 -0
  74. package/dist/oauth/hono-app.js.map +1 -0
  75. package/dist/oauth/index.d.ts +9 -0
  76. package/dist/oauth/index.d.ts.map +1 -0
  77. package/dist/oauth/index.js +6 -0
  78. package/dist/oauth/index.js.map +1 -0
  79. package/dist/oauth/rate-limit.d.ts +11 -0
  80. package/dist/oauth/rate-limit.d.ts.map +1 -0
  81. package/dist/oauth/rate-limit.js +32 -0
  82. package/dist/oauth/rate-limit.js.map +1 -0
  83. package/dist/oauth/routes.d.ts +8 -0
  84. package/dist/oauth/routes.d.ts.map +1 -0
  85. package/dist/oauth/routes.js +671 -0
  86. package/dist/oauth/routes.js.map +1 -0
  87. package/dist/oauth/store.d.ts +113 -0
  88. package/dist/oauth/store.d.ts.map +1 -0
  89. package/dist/oauth/store.js +390 -0
  90. package/dist/oauth/store.js.map +1 -0
  91. package/dist/oauth/types.d.ts +97 -0
  92. package/dist/oauth/types.d.ts.map +1 -0
  93. package/dist/oauth/types.js +5 -0
  94. package/dist/oauth/types.js.map +1 -0
  95. package/dist/open-external-tab-host-tools.d.ts +67 -0
  96. package/dist/open-external-tab-host-tools.d.ts.map +1 -0
  97. package/dist/open-external-tab-host-tools.js +92 -0
  98. package/dist/open-external-tab-host-tools.js.map +1 -0
  99. package/dist/policy.d.ts +59 -0
  100. package/dist/policy.d.ts.map +1 -0
  101. package/dist/policy.js +88 -0
  102. package/dist/policy.js.map +1 -0
  103. package/dist/runtime.d.ts +22 -0
  104. package/dist/runtime.d.ts.map +1 -0
  105. package/dist/runtime.js +20 -0
  106. package/dist/runtime.js.map +1 -0
  107. package/dist/types.d.ts +163 -0
  108. package/dist/types.d.ts.map +1 -0
  109. package/dist/types.js +2 -0
  110. package/dist/types.js.map +1 -0
  111. package/dist-cjs/admin/adapters.js +27 -0
  112. package/dist-cjs/admin/adapters.js.map +1 -0
  113. package/dist-cjs/admin/http-routes.js +69 -0
  114. package/dist-cjs/admin/http-routes.js.map +1 -0
  115. package/dist-cjs/admin/index.js +40 -0
  116. package/dist-cjs/admin/index.js.map +1 -0
  117. package/dist-cjs/admin/mcp-admin.js +441 -0
  118. package/dist-cjs/admin/mcp-admin.js.map +1 -0
  119. package/dist-cjs/admin/tool-policy-guard.js +193 -0
  120. package/dist-cjs/admin/tool-policy-guard.js.map +1 -0
  121. package/dist-cjs/admin/types.js +7 -0
  122. package/dist-cjs/admin/types.js.map +1 -0
  123. package/dist-cjs/brand-facade.js +70 -0
  124. package/dist-cjs/brand-facade.js.map +1 -0
  125. package/dist-cjs/core-tools.js +97 -0
  126. package/dist-cjs/core-tools.js.map +1 -0
  127. package/dist-cjs/dyn-import.js +5 -0
  128. package/dist-cjs/dyn-import.js.map +1 -0
  129. package/dist-cjs/facade.js +337 -0
  130. package/dist-cjs/facade.js.map +1 -0
  131. package/dist-cjs/hono-bind.js +74 -0
  132. package/dist-cjs/hono-bind.js.map +1 -0
  133. package/dist-cjs/hono-proxy.js +189 -0
  134. package/dist-cjs/hono-proxy.js.map +1 -0
  135. package/dist-cjs/index.js +120 -0
  136. package/dist-cjs/index.js.map +1 -0
  137. package/dist-cjs/jwt.js +91 -0
  138. package/dist-cjs/jwt.js.map +1 -0
  139. package/dist-cjs/module-ops-tools.js +308 -0
  140. package/dist-cjs/module-ops-tools.js.map +1 -0
  141. package/dist-cjs/namespace.js +56 -0
  142. package/dist-cjs/namespace.js.map +1 -0
  143. package/dist-cjs/oauth/cors-policy.js +29 -0
  144. package/dist-cjs/oauth/cors-policy.js.map +1 -0
  145. package/dist-cjs/oauth/hono-app.js +178 -0
  146. package/dist-cjs/oauth/hono-app.js.map +1 -0
  147. package/dist-cjs/oauth/index.js +48 -0
  148. package/dist-cjs/oauth/index.js.map +1 -0
  149. package/dist-cjs/oauth/rate-limit.js +37 -0
  150. package/dist-cjs/oauth/rate-limit.js.map +1 -0
  151. package/dist-cjs/oauth/routes.js +674 -0
  152. package/dist-cjs/oauth/routes.js.map +1 -0
  153. package/dist-cjs/oauth/store.js +418 -0
  154. package/dist-cjs/oauth/store.js.map +1 -0
  155. package/dist-cjs/oauth/types.js +6 -0
  156. package/dist-cjs/oauth/types.js.map +1 -0
  157. package/dist-cjs/open-external-tab-host-tools.js +96 -0
  158. package/dist-cjs/open-external-tab-host-tools.js.map +1 -0
  159. package/dist-cjs/package.json +3 -0
  160. package/dist-cjs/policy.js +93 -0
  161. package/dist-cjs/policy.js.map +1 -0
  162. package/dist-cjs/runtime.js +24 -0
  163. package/dist-cjs/runtime.js.map +1 -0
  164. package/dist-cjs/types.js +3 -0
  165. package/dist-cjs/types.js.map +1 -0
  166. package/package.json +92 -0
  167. package/ui/index.ts +5 -0
  168. package/ui/mcp-admin-client.tsx +270 -0
  169. package/ui/primitives/badge.tsx +37 -0
  170. package/ui/primitives/button.tsx +44 -0
  171. package/ui/primitives/card.tsx +44 -0
  172. package/ui/primitives/cn.ts +6 -0
  173. package/ui/primitives/input.tsx +19 -0
  174. package/ui/primitives/tabs.tsx +51 -0
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Types OAuth MCP + transport Hono — adapters injectés (zéro hardcode marque).
3
+ */
4
+ import type { Context, MiddlewareHandler } from "hono";
5
+ import type { McpAdminSqliteDatabase } from "../admin/types.js";
6
+ export type McpOAuthSqliteDatabase = McpAdminSqliteDatabase;
7
+ /** Injection host pour le store OAuth (tables v22/v25/v27). */
8
+ export type McpOAuthAdapters = {
9
+ getWriteDb: () => McpOAuthSqliteDatabase;
10
+ tableExists: (name: string) => boolean;
11
+ /** Secret JWT (défaut : process.env.MCP_JWT_SECRET). */
12
+ getJwtSecret?: () => string;
13
+ /** Resolver URL publique (défaut : MCP_PUBLIC_URL → APP_PUBLIC_URL → APP_BASE_URL). */
14
+ resolvePublicUrl?: () => string | null;
15
+ };
16
+ export type McpOAuthSessionUser = {
17
+ id: string;
18
+ username: string;
19
+ };
20
+ export type McpOAuthSession = {
21
+ email?: string | null;
22
+ sub?: string | null;
23
+ };
24
+ /**
25
+ * Pont session/credentials marque — ne pas hardcoder le cookie CRM.
26
+ */
27
+ export type McpOAuthSessionBridge = {
28
+ getSessionFromContext: (c: Context) => Promise<McpOAuthSession | null | undefined>;
29
+ authenticateUser: (username: string, password: string) => McpOAuthSessionUser | null | Promise<McpOAuthSessionUser | null>;
30
+ /** Credentials legacy (setup desktop) — optionnel. */
31
+ validateCredentials?: (username: string, password: string) => boolean;
32
+ getOwnerId: () => string | null;
33
+ /** Pose cookie session après login consent (optionnel). */
34
+ createSessionCookie?: (c: Context, user: {
35
+ id?: string | null;
36
+ username: string;
37
+ }) => Promise<void>;
38
+ };
39
+ export type McpOAuthRoutesConfig = {
40
+ /** Titre produit pages consent (ex. « TempoFlow2 CRM »). */
41
+ productName: string;
42
+ /** resource_name metadata (défaut : `${productName} MCP`). */
43
+ resourceName?: string;
44
+ /** HTML `<li>…</li>` pour la liste de scopes consent. */
45
+ consentScopesHtml?: string;
46
+ session: McpOAuthSessionBridge;
47
+ /** Cookie Secure derrière tunnel (injectable ; défaut heuristique env). */
48
+ resolveCookieSecure?: (c: Context) => boolean;
49
+ /** Documentation URL path (défaut `/developers`). */
50
+ documentationPath?: string;
51
+ dcrRateLimit?: {
52
+ limit: number;
53
+ windowMs: number;
54
+ };
55
+ };
56
+ export type McpServerAuthContext = {
57
+ userId: string | null;
58
+ clientId?: string;
59
+ scopes?: string;
60
+ };
61
+ export type McpStreamableTransport = {
62
+ handleRequest: (c: Context) => Promise<Response> | Response;
63
+ close: () => Promise<void>;
64
+ };
65
+ export type McpConnectedServer = {
66
+ connect: (transport: McpStreamableTransport) => Promise<void>;
67
+ close: () => Promise<void>;
68
+ };
69
+ export type McpApiKeyRecord = {
70
+ id: string;
71
+ user_id?: string | null;
72
+ scopes?: string;
73
+ };
74
+ export type CreateMcpHonoAppOptions = {
75
+ /** Routes OAuth (createMcpOAuthRoutes). */
76
+ oauthRoutes: {
77
+ fetch: unknown;
78
+ } | import("hono").Hono;
79
+ buildMcpServer: (ctx: McpServerAuthContext) => Promise<McpConnectedServer>;
80
+ /** Factory transport Streamable HTTP (ex. `() => new StreamableHTTPTransport(...)`). */
81
+ createTransport: () => McpStreamableTransport;
82
+ /** Auth clé API locale (Hermes) — optionnel. */
83
+ apiKeyAuth?: {
84
+ prefix: string;
85
+ verify: (token: string) => McpApiKeyRecord | null;
86
+ resolveUserId?: (key: McpApiKeyRecord) => string | null;
87
+ };
88
+ ensureSchema?: () => void;
89
+ /** Middleware /mcp (ex. requestLogMcpMiddleware). */
90
+ mcpMiddleware?: MiddlewareHandler;
91
+ resolveCorsOrigin?: (origin: string) => string;
92
+ mcpRateLimit?: {
93
+ limit: number;
94
+ windowMs: number;
95
+ };
96
+ };
97
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/oauth/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Types OAuth MCP + transport Hono — adapters injectés (zéro hardcode marque).
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/oauth/types.ts"],"names":[],"mappings":"AAAA;;GAEG"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * D-P18 — tool MCP host-only `open_external_tab` (desktop).
3
+ * SoT kit partagée TF / CV / Fidu. Métier résolution URL reste injecté.
4
+ */
5
+ import { z } from "zod";
6
+ export declare const CREEZIO_OPEN_EXTERNAL_TAB_MCP_TOOL_NAME: "open_external_tab";
7
+ export type OpenExternalTabResolved = {
8
+ url: string;
9
+ fournisseurId: number;
10
+ title: string;
11
+ source: string;
12
+ };
13
+ export type OpenExternalTabResolveResult = ({
14
+ ok: true;
15
+ } & OpenExternalTabResolved) | ({
16
+ ok: false;
17
+ error: string;
18
+ } & Record<string, unknown>);
19
+ export type OpenExternalTabHostMcpToolConfig = {
20
+ title: string;
21
+ description: string;
22
+ inputSchema: Record<string, z.ZodType>;
23
+ };
24
+ export type OpenExternalTabHostMcpRegisterFn = (name: string, config: OpenExternalTabHostMcpToolConfig, handler: (input: any) => Promise<unknown> | unknown) => void;
25
+ export type OpenExternalTabUser = {
26
+ id: string;
27
+ role?: string;
28
+ };
29
+ export type CreateOpenExternalTabHostMcpToolsOptions = {
30
+ /** Enregistrement marque (`registerMcpTool` ou `server.registerTool`). */
31
+ registerTool: OpenExternalTabHostMcpRegisterFn;
32
+ /** `userId` du token MCP (Bearer / API key). */
33
+ getActorUserId: () => string | null | undefined;
34
+ /** Métier marque — résolution URL / catalogue. */
35
+ resolveOpenTabRequest: (input: {
36
+ url?: string;
37
+ outil_slug?: string;
38
+ fournisseur_id?: number;
39
+ title?: string;
40
+ }) => OpenExternalTabResolveResult;
41
+ /** Params IPC desktop (alias marque de `toSupplierOpenTabParams`). */
42
+ toOpenTabParams: (resolved: OpenExternalTabResolved) => Record<string, unknown>;
43
+ /**
44
+ * Dispatch action desktop (typiquement `dispatchSupplierAction`
45
+ * avec `"supplier_open_tab"`).
46
+ */
47
+ dispatchOpenTabAction: (params: Record<string, unknown>, opts: {
48
+ targetUserId: string;
49
+ requireTargetOnline: boolean;
50
+ }) => Promise<Record<string, unknown>>;
51
+ getUserById: (id: string) => OpenExternalTabUser | null | undefined;
52
+ getOwner: () => {
53
+ id: string;
54
+ } | null | undefined;
55
+ /** Titre tool MCP (défaut neutre). */
56
+ title?: string;
57
+ /** Description tool MCP (défaut neutre). */
58
+ description?: string;
59
+ /** Fidu : expose `outil_slug` dans le schéma. Défaut false. */
60
+ includeOutilSlug?: boolean;
61
+ };
62
+ /**
63
+ * Enregistre le tool MCP host `open_external_tab` (SoT kit).
64
+ * Retourne la liste des noms enregistrés (`["open_external_tab"]`).
65
+ */
66
+ export declare function createOpenExternalTabHostMcpTools(options: CreateOpenExternalTabHostMcpToolsOptions): readonly string[];
67
+ //# sourceMappingURL=open-external-tab-host-tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"open-external-tab-host-tools.d.ts","sourceRoot":"","sources":["../src/open-external-tab-host-tools.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,uCAAuC,EAClD,mBAA4B,CAAC;AAE/B,MAAM,MAAM,uBAAuB,GAAG;IACpC,GAAG,EAAE,MAAM,CAAC;IACZ,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,4BAA4B,GACpC,CAAC;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GAAG,uBAAuB,CAAC,GACxC,CAAC;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAE7D,MAAM,MAAM,gCAAgC,GAAG;IAC7C,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC;CACxC,CAAC;AAEF,MAAM,MAAM,gCAAgC,GAAG,CAC7C,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,gCAAgC,EACxC,OAAO,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,KAChD,IAAI,CAAC;AAEV,MAAM,MAAM,mBAAmB,GAAG;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,wCAAwC,GAAG;IACrD,0EAA0E;IAC1E,YAAY,EAAE,gCAAgC,CAAC;IAC/C,gDAAgD;IAChD,cAAc,EAAE,MAAM,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAChD,kDAAkD;IAClD,qBAAqB,EAAE,CAAC,KAAK,EAAE;QAC7B,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,KAAK,4BAA4B,CAAC;IACnC,sEAAsE;IACtE,eAAe,EAAE,CACf,QAAQ,EAAE,uBAAuB,KAC9B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC7B;;;OAGG;IACH,qBAAqB,EAAE,CACrB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,IAAI,EAAE;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,mBAAmB,EAAE,OAAO,CAAA;KAAE,KACzD,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACtC,WAAW,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,mBAAmB,GAAG,IAAI,GAAG,SAAS,CAAC;IACpE,QAAQ,EAAE,MAAM;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,GAAG,SAAS,CAAC;IAClD,sCAAsC;IACtC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,4CAA4C;IAC5C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,+DAA+D;IAC/D,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B,CAAC;AAoBF;;;GAGG;AACH,wBAAgB,iCAAiC,CAC/C,OAAO,EAAE,wCAAwC,GAChD,SAAS,MAAM,EAAE,CA0FnB"}
@@ -0,0 +1,92 @@
1
+ /**
2
+ * D-P18 — tool MCP host-only `open_external_tab` (desktop).
3
+ * SoT kit partagée TF / CV / Fidu. Métier résolution URL reste injecté.
4
+ */
5
+ import { z } from "zod";
6
+ export const CREEZIO_OPEN_EXTERNAL_TAB_MCP_TOOL_NAME = "open_external_tab";
7
+ function jsonResult(data) {
8
+ return {
9
+ content: [{ type: "text", text: JSON.stringify(data, null, 1) }],
10
+ };
11
+ }
12
+ function errorResult(message) {
13
+ return {
14
+ content: [
15
+ {
16
+ type: "text",
17
+ text: JSON.stringify({ error: message }),
18
+ },
19
+ ],
20
+ isError: true,
21
+ };
22
+ }
23
+ /**
24
+ * Enregistre le tool MCP host `open_external_tab` (SoT kit).
25
+ * Retourne la liste des noms enregistrés (`["open_external_tab"]`).
26
+ */
27
+ export function createOpenExternalTabHostMcpTools(options) {
28
+ const { registerTool, getActorUserId, resolveOpenTabRequest, toOpenTabParams, dispatchOpenTabAction, getUserById, getOwner, title = "Ouvrir un onglet externe", description = "Ouvre un onglet externe dans le desktop de l'utilisateur lié au token OAuth.", includeOutilSlug = false, } = options;
29
+ const inputSchema = {
30
+ url: z.string().optional().describe("URL ou domaine"),
31
+ fournisseur_id: z
32
+ .number()
33
+ .int()
34
+ .optional()
35
+ .describe("ID catalogue (0 ou omis = URL libre)"),
36
+ title: z.string().optional().describe("Titre d'onglet"),
37
+ target_user_id: z
38
+ .string()
39
+ .optional()
40
+ .describe("Compte principal uniquement : autre utilisateur cible"),
41
+ };
42
+ if (includeOutilSlug) {
43
+ inputSchema.outil_slug = z
44
+ .string()
45
+ .optional()
46
+ .describe("Slug catalogue");
47
+ }
48
+ registerTool(CREEZIO_OPEN_EXTERNAL_TAB_MCP_TOOL_NAME, { title, description, inputSchema }, async (input) => {
49
+ try {
50
+ const actorId = getActorUserId();
51
+ if (!actorId) {
52
+ return errorResult("token MCP sans user_id — reconnectez le client MCP");
53
+ }
54
+ let targetUserId = actorId;
55
+ if (input.target_user_id && input.target_user_id !== actorId) {
56
+ const actor = getUserById(actorId);
57
+ const owner = getOwner();
58
+ if (!actor || actor.role !== "owner" || actor.id !== owner?.id) {
59
+ return errorResult("Seul le compte principal peut cibler un autre utilisateur");
60
+ }
61
+ if (!getUserById(input.target_user_id)) {
62
+ return errorResult("Utilisateur cible introuvable");
63
+ }
64
+ targetUserId = input.target_user_id;
65
+ }
66
+ const resolved = resolveOpenTabRequest({
67
+ url: input.url,
68
+ outil_slug: input.outil_slug,
69
+ fournisseur_id: input.fournisseur_id,
70
+ title: input.title,
71
+ });
72
+ if (!resolved.ok)
73
+ return jsonResult(resolved);
74
+ const result = await dispatchOpenTabAction(toOpenTabParams(resolved), { targetUserId, requireTargetOnline: true });
75
+ return jsonResult({
76
+ ...result,
77
+ resolved: {
78
+ url: resolved.url,
79
+ fournisseur_id: resolved.fournisseurId,
80
+ title: resolved.title,
81
+ source: resolved.source,
82
+ },
83
+ target_user_id: targetUserId,
84
+ });
85
+ }
86
+ catch (error) {
87
+ return errorResult(error instanceof Error ? error.message : String(error));
88
+ }
89
+ });
90
+ return [CREEZIO_OPEN_EXTERNAL_TAB_MCP_TOOL_NAME];
91
+ }
92
+ //# sourceMappingURL=open-external-tab-host-tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"open-external-tab-host-tools.js","sourceRoot":"","sources":["../src/open-external-tab-host-tools.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Policies MCP H4 — deny cross-layer cohérent api-kernel H2.
3
+ * H5 — plugin ACL (see/execute) alignée Product Hub.
4
+ */
5
+ import type { McpAuthorizeContext, McpToolPolicyDecision } from "./types.js";
6
+ export type PluginAclPolicyResolver = (pluginId: string) => {
7
+ allowedOrgIds: string[];
8
+ allowedUserIds: string[];
9
+ ownerOrgId?: string | null;
10
+ capabilitiesBySubject?: Record<string, Array<"see" | "install" | "execute">>;
11
+ failClosed?: boolean;
12
+ pluginId: string;
13
+ } | undefined;
14
+ export type PluginAclActorResolver = (ctx: McpAuthorizeContext) => {
15
+ orgId?: string | null;
16
+ userId?: string | null;
17
+ isOwner?: boolean;
18
+ isServiceKey?: boolean;
19
+ isImpersonating?: boolean;
20
+ };
21
+ export type DecidePluginAccessFn = (policy: {
22
+ pluginId: string;
23
+ allowedOrgIds: string[];
24
+ allowedUserIds: string[];
25
+ ownerOrgId?: string | null;
26
+ capabilitiesBySubject?: Record<string, Array<"see" | "install" | "execute">>;
27
+ failClosed?: boolean;
28
+ } | undefined, actor: {
29
+ orgId?: string | null;
30
+ userId?: string | null;
31
+ isOwner?: boolean;
32
+ isServiceKey?: boolean;
33
+ isImpersonating?: boolean;
34
+ }, action: "see" | "install" | "execute") => {
35
+ allow: true;
36
+ } | {
37
+ allow: false;
38
+ reason: string;
39
+ };
40
+ /**
41
+ * Deny-by-default si la charge utile tente un échappement cross-layer
42
+ * (même sémantique que api-kernel `__cross/` / `core/` escaping).
43
+ */
44
+ export declare function denyCrossLayerToolCall(ctx: McpAuthorizeContext): McpToolPolicyDecision;
45
+ /**
46
+ * Compose plusieurs policies (premier deny gagne).
47
+ */
48
+ export declare function composeToolPolicies(...policies: Array<(ctx: McpAuthorizeContext) => McpToolPolicyDecision | Promise<McpToolPolicyDecision>>): (ctx: McpAuthorizeContext) => Promise<McpToolPolicyDecision>;
49
+ /**
50
+ * H5 — deny tools `plugin.<id>.*` si l'acteur n'a pas `execute`.
51
+ * Injecter `decidePluginAccess` depuis `@creezio/product-hub` pour
52
+ * une décision identique à l'API / control-plane.
53
+ */
54
+ export declare function createDenyUnauthorizedPluginToolPolicy(opts: {
55
+ getPolicy: PluginAclPolicyResolver;
56
+ resolveActor?: PluginAclActorResolver;
57
+ decide: DecidePluginAccessFn;
58
+ }): (ctx: McpAuthorizeContext) => McpToolPolicyDecision;
59
+ //# sourceMappingURL=policy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policy.d.ts","sourceRoot":"","sources":["../src/policy.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EACV,mBAAmB,EACnB,qBAAqB,EACtB,MAAM,YAAY,CAAC;AAEpB,MAAM,MAAM,uBAAuB,GAAG,CAAC,QAAQ,EAAE,MAAM,KACnD;IACE,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,qBAAqB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,KAAK,GAAG,SAAS,GAAG,SAAS,CAAC,CAAC,CAAC;IAC7E,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;CAClB,GACD,SAAS,CAAC;AAEd,MAAM,MAAM,sBAAsB,GAAG,CAAC,GAAG,EAAE,mBAAmB,KAAK;IACjE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG,CACjC,MAAM,EACF;IACE,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,qBAAqB,CAAC,EAAE,MAAM,CAC5B,MAAM,EACN,KAAK,CAAC,KAAK,GAAG,SAAS,GAAG,SAAS,CAAC,CACrC,CAAC;IACF,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,GACD,SAAS,EACb,KAAK,EAAE;IACL,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B,EACD,MAAM,EAAE,KAAK,GAAG,SAAS,GAAG,SAAS,KAClC;IAAE,KAAK,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,KAAK,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAExD;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,mBAAmB,GACvB,qBAAqB,CAiCvB;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,GAAG,QAAQ,EAAE,KAAK,CAChB,CAAC,GAAG,EAAE,mBAAmB,KAAK,qBAAqB,GAAG,OAAO,CAAC,qBAAqB,CAAC,CACrF,GACA,CAAC,GAAG,EAAE,mBAAmB,KAAK,OAAO,CAAC,qBAAqB,CAAC,CAQ9D;AAED;;;;GAIG;AACH,wBAAgB,sCAAsC,CAAC,IAAI,EAAE;IAC3D,SAAS,EAAE,uBAAuB,CAAC;IACnC,YAAY,CAAC,EAAE,sBAAsB,CAAC;IACtC,MAAM,EAAE,oBAAoB,CAAC;CAC9B,GAAG,CAAC,GAAG,EAAE,mBAAmB,KAAK,qBAAqB,CAqBtD"}
package/dist/policy.js ADDED
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Policies MCP H4 — deny cross-layer cohérent api-kernel H2.
3
+ * H5 — plugin ACL (see/execute) alignée Product Hub.
4
+ */
5
+ /**
6
+ * Deny-by-default si la charge utile tente un échappement cross-layer
7
+ * (même sémantique que api-kernel `__cross/` / `core/` escaping).
8
+ */
9
+ export function denyCrossLayerToolCall(ctx) {
10
+ const args = ctx.args || {};
11
+ for (const [key, value] of Object.entries(args)) {
12
+ const blob = `${key}=${stringifyArg(value)}`.toLowerCase();
13
+ if (blob.includes("__cross/") ||
14
+ blob.includes("__cross") ||
15
+ /(^|[=\s/])core\//.test(blob) ||
16
+ blob.includes("/../") ||
17
+ blob.includes("..\\")) {
18
+ return { allow: false, reason: "cross_layer_denied" };
19
+ }
20
+ }
21
+ // Un tool module/plugin ne peut pas se faire passer pour core via alias.
22
+ if (ctx.isAlias && ctx.space === "core") {
23
+ return { allow: false, reason: "alias_to_core_denied" };
24
+ }
25
+ // Spoof explicite de couche cible.
26
+ const targetSpace = args.targetSpace ?? args.target_space ?? args.space;
27
+ if (typeof targetSpace === "string" &&
28
+ targetSpace !== ctx.space &&
29
+ (targetSpace === "core" ||
30
+ targetSpace === "module" ||
31
+ targetSpace === "plugin")) {
32
+ return { allow: false, reason: "cross_layer_space_spoof" };
33
+ }
34
+ return { allow: true };
35
+ }
36
+ /**
37
+ * Compose plusieurs policies (premier deny gagne).
38
+ */
39
+ export function composeToolPolicies(...policies) {
40
+ return async (ctx) => {
41
+ for (const p of policies) {
42
+ const d = await p(ctx);
43
+ if (!d.allow)
44
+ return d;
45
+ }
46
+ return { allow: true };
47
+ };
48
+ }
49
+ /**
50
+ * H5 — deny tools `plugin.<id>.*` si l'acteur n'a pas `execute`.
51
+ * Injecter `decidePluginAccess` depuis `@creezio/product-hub` pour
52
+ * une décision identique à l'API / control-plane.
53
+ */
54
+ export function createDenyUnauthorizedPluginToolPolicy(opts) {
55
+ const resolveActor = opts.resolveActor ||
56
+ ((ctx) => ({
57
+ orgId: ctx.orgId ?? ctx.claims?.orgId ?? null,
58
+ userId: ctx.subject || null,
59
+ isOwner: Boolean(ctx.claims?.isOwner),
60
+ isServiceKey: ctx.subject === "opaque-token" || ctx.subject === "anonymous",
61
+ }));
62
+ return (ctx) => {
63
+ if (ctx.space !== "plugin")
64
+ return { allow: true };
65
+ const pluginId = ctx.ownerId;
66
+ if (!pluginId) {
67
+ return { allow: false, reason: "acl_plugin_owner_missing" };
68
+ }
69
+ const actor = resolveActor(ctx);
70
+ const decision = opts.decide(opts.getPolicy(pluginId), actor, "execute");
71
+ if (!decision.allow)
72
+ return { allow: false, reason: decision.reason };
73
+ return { allow: true };
74
+ };
75
+ }
76
+ function stringifyArg(value) {
77
+ if (value == null)
78
+ return "";
79
+ if (typeof value === "string")
80
+ return value;
81
+ try {
82
+ return JSON.stringify(value);
83
+ }
84
+ catch {
85
+ return String(value);
86
+ }
87
+ }
88
+ //# sourceMappingURL=policy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policy.js","sourceRoot":"","sources":["../src/policy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Contrat MCP produit (D1/C2 → M9) — une seule stack.
3
+ *
4
+ * - Exécuteur HTTP public : **Hono** `GET|POST /mcp`.
5
+ * - Façade Electron `@creezio/mcp-facade` : adaptateur brand-mounts (tests /
6
+ * offline) **ou** proxy vers Hono dès qu'un upstream local est annoncé.
7
+ *
8
+ * Hermes / Cursor / ChatGPT → toujours `{base}/mcp`, jamais un 2ᵉ serveur
9
+ * MCP dans le process Electron.
10
+ */
11
+ export declare const MCP_PRODUCT_EXECUTOR: "hono";
12
+ export type McpProductExecutor = typeof MCP_PRODUCT_EXECUTOR;
13
+ /** Rôle de la façade Electron (pas un 2ᵉ exécuteur produit). */
14
+ export type McpFacadeRole = "local-brand-adapter" | "hono-proxy";
15
+ export type McpFacadeMode = "local-adapter" | "hono-proxy" | "hono-preferred";
16
+ export type McpUpstreamRef = {
17
+ /** Base URL Next locale, ex. http://127.0.0.1:3920 — sans slash final. */
18
+ getBaseUrl: () => string | null;
19
+ getApiKey: () => string | null;
20
+ };
21
+ export declare function resolveMcpFacadeRole(mode: McpFacadeMode, upstream: string | null): McpFacadeRole;
22
+ //# sourceMappingURL=runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,eAAO,MAAM,oBAAoB,EAAG,MAAe,CAAC;AAEpD,MAAM,MAAM,kBAAkB,GAAG,OAAO,oBAAoB,CAAC;AAE7D,gEAAgE;AAChE,MAAM,MAAM,aAAa,GAAG,qBAAqB,GAAG,YAAY,CAAC;AAEjE,MAAM,MAAM,aAAa,GAAG,eAAe,GAAG,YAAY,GAAG,gBAAgB,CAAC;AAE9E,MAAM,MAAM,cAAc,GAAG;IAC3B,0EAA0E;IAC1E,UAAU,EAAE,MAAM,MAAM,GAAG,IAAI,CAAC;IAChC,SAAS,EAAE,MAAM,MAAM,GAAG,IAAI,CAAC;CAChC,CAAC;AAEF,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,aAAa,EACnB,QAAQ,EAAE,MAAM,GAAG,IAAI,GACtB,aAAa,CAKf"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Contrat MCP produit (D1/C2 → M9) — une seule stack.
3
+ *
4
+ * - Exécuteur HTTP public : **Hono** `GET|POST /mcp`.
5
+ * - Façade Electron `@creezio/mcp-facade` : adaptateur brand-mounts (tests /
6
+ * offline) **ou** proxy vers Hono dès qu'un upstream local est annoncé.
7
+ *
8
+ * Hermes / Cursor / ChatGPT → toujours `{base}/mcp`, jamais un 2ᵉ serveur
9
+ * MCP dans le process Electron.
10
+ */
11
+ export const MCP_PRODUCT_EXECUTOR = "hono";
12
+ export function resolveMcpFacadeRole(mode, upstream) {
13
+ if (mode === "local-adapter")
14
+ return "local-brand-adapter";
15
+ if (mode === "hono-proxy")
16
+ return "hono-proxy";
17
+ // hono-preferred
18
+ return upstream ? "hono-proxy" : "local-brand-adapter";
19
+ }
20
+ //# sourceMappingURL=runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.js","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,MAAM,CAAC,MAAM,oBAAoB,GAAG,MAAe,CAAC;AAepD,MAAM,UAAU,oBAAoB,CAClC,IAAmB,EACnB,QAAuB;IAEvB,IAAI,IAAI,KAAK,eAAe;QAAE,OAAO,qBAAqB,CAAC;IAC3D,IAAI,IAAI,KAAK,YAAY;QAAE,OAAO,YAAY,CAAC;IAC/C,iBAAiB;IACjB,OAAO,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,qBAAqB,CAAC;AACzD,CAAC"}
@@ -0,0 +1,163 @@
1
+ export type McpToolSpace = "core" | "module" | "plugin";
2
+ /**
3
+ * Surface publique listTools :
4
+ * - `canonical` — noms namespacés uniquement (module.panier.get)
5
+ * - `legacy-preferred` — si un alias legacy existe, masquer le canonique
6
+ * - `both` — alias + canonique (déconseillé — double exposition)
7
+ */
8
+ export type McpPublicSurfaceMode = "canonical" | "legacy-preferred" | "both";
9
+ export type McpToolDefinition = {
10
+ name: string;
11
+ description: string;
12
+ space: McpToolSpace;
13
+ /** Id module/plugin si space !== core. */
14
+ ownerId?: string;
15
+ inputSchema?: Record<string, unknown>;
16
+ /** Nom canonique si cette entrée est un alias legacy exposé. */
17
+ aliasOf?: string;
18
+ /** Rôles seedés dans `mcp_tool_policies` (ops de module). */
19
+ defaultRoles?: string[];
20
+ /**
21
+ * Seed policy `enabled` — false = à activer dans `/admin/mcp`.
22
+ * Absent = comportement historique (enabled).
23
+ */
24
+ mcpPublishDefault?: boolean;
25
+ requiredScope?: string;
26
+ };
27
+ export type McpToolCallResult = {
28
+ ok: boolean;
29
+ content?: unknown;
30
+ error?: string;
31
+ };
32
+ /**
33
+ * Acteur du call courant, transmis aux handlers (2ᵉ argument optionnel —
34
+ * rétro-compatible : les handlers existants à un argument restent valides).
35
+ */
36
+ export type McpToolCallActor = {
37
+ subject?: string;
38
+ orgId?: string;
39
+ claims?: Record<string, unknown>;
40
+ /**
41
+ * Bearer (JWT session ou clé service) du call — à poser sur la requête
42
+ * synthétique `module.*` pour que `requireSession` / cookie+Authorization
43
+ * voient le même acteur que le chat OS.
44
+ */
45
+ bearerToken?: string | null;
46
+ /** Headers HTTP d'origine (Cookie, Authorization) à propager. */
47
+ headers?: Record<string, string>;
48
+ };
49
+ /** Options de `callTool` — Bearer + headers de la requête chat. */
50
+ export type McpCallToolOpts = {
51
+ bearerToken?: string | null;
52
+ headers?: Record<string, string>;
53
+ };
54
+ export type McpToolHandler = (args: Record<string, unknown>, actor?: McpToolCallActor) => McpToolCallResult | Promise<McpToolCallResult>;
55
+ /**
56
+ * Acteur résolu depuis un Bearer opaque (ex. clé API service vérifiée par
57
+ * l'app contre sa table `api_keys`). `null` = token inconnu → fallback JWT.
58
+ */
59
+ export type McpBearerActor = {
60
+ subject: string;
61
+ orgId?: string;
62
+ claims?: Record<string, unknown>;
63
+ };
64
+ export type McpResolveBearerActorFn = (token: string) => McpBearerActor | null | Promise<McpBearerActor | null>;
65
+ export type McpRegisteredTool = McpToolDefinition & {
66
+ handler: McpToolHandler;
67
+ };
68
+ export type DiscoverToolsFn = () => McpRegisteredTool[] | Promise<McpRegisteredTool[]>;
69
+ /** Discovery scindée par couche (H2.3) — préférée à une liste plate. */
70
+ export type DiscoverToolsBySpaceFn = () => Partial<Record<"module" | "plugin", McpRegisteredTool[]>> | Promise<Partial<Record<"module" | "plugin", McpRegisteredTool[]>>>;
71
+ export type McpAuthorizeContext = {
72
+ name: string;
73
+ canonicalName: string;
74
+ space: McpToolSpace;
75
+ ownerId?: string;
76
+ subject?: string;
77
+ /** H5 — org claim JWT / opaque actor. */
78
+ orgId?: string;
79
+ /** Claims JWT bruts (orgId, isOwner, …). */
80
+ claims?: Record<string, unknown>;
81
+ args: Record<string, unknown>;
82
+ isAlias: boolean;
83
+ };
84
+ export type McpToolPolicyDecision = {
85
+ allow: true;
86
+ } | {
87
+ allow: false;
88
+ reason: string;
89
+ };
90
+ export type McpAuthorizeToolCallFn = (ctx: McpAuthorizeContext) => McpToolPolicyDecision | Promise<McpToolPolicyDecision>;
91
+ export type McpFacadeOptions = {
92
+ /** Secret JWT (local-config `mcpJwtSecret` / env MCP_JWT_SECRET). */
93
+ jwtSecret?: string | null;
94
+ /** Si true, auth JWT optionnelle (dev/sandbox). Défaut false en prod. */
95
+ allowUnauthenticated?: boolean;
96
+ /**
97
+ * Résolution d'acteur pour Bearer OPAQUE (non-JWT) — consultée AVANT la
98
+ * vérification JWT (ex. clé API service Hermes → owner). `null`/throw =
99
+ * fallback JWT inchangé. Ne jamais y mettre de métier marque.
100
+ */
101
+ resolveBearerActor?: McpResolveBearerActorFn;
102
+ /** Discoverer plat (H1 compat). */
103
+ discoverTools?: DiscoverToolsFn;
104
+ /**
105
+ * Discoverer scindé (H2) — tools modules vs plugins.
106
+ * Si fourni, fusionné avec `discoverTools` (plat).
107
+ */
108
+ discoverToolsBySpace?: DiscoverToolsBySpaceFn;
109
+ architectureVersion?: string;
110
+ brandId?: string;
111
+ /** Liste mounts api-kernel (optionnel, pour tool admin). */
112
+ listApiMounts?: () => Array<{
113
+ space: string;
114
+ id: string;
115
+ }>;
116
+ /**
117
+ * H4 — impose préfixes `core.*` / `creezio.*` · `module.<id>.*` · `plugin.<id>.*`
118
+ * Défaut true.
119
+ */
120
+ enforceNamespaces?: boolean;
121
+ /**
122
+ * H4 — aliases legacy → nom canonique namespacé
123
+ * (ex. get_panier → module.panier.get).
124
+ */
125
+ aliases?: Record<string, string>;
126
+ /**
127
+ * H4 — surface listTools (défaut `legacy-preferred` pour éviter
128
+ * la double exposition panier historique ↔ module.*).
129
+ */
130
+ publicSurface?: McpPublicSurfaceMode;
131
+ /** H4 — policy avant callTool (deny cross-layer par défaut). */
132
+ authorizeToolCall?: McpAuthorizeToolCallFn;
133
+ /**
134
+ * H4 — si false, ne pas installer denyCrossLayerToolCall par défaut.
135
+ * Défaut true.
136
+ */
137
+ defaultCrossLayerDeny?: boolean;
138
+ /**
139
+ * H5 — filtre listTools space=plugin selon ACL (optionnel).
140
+ * Si fourni, les tools plugin non visibles sont masqués.
141
+ */
142
+ filterPluginToolsForActor?: (tools: McpToolDefinition[], ctx: {
143
+ subject?: string;
144
+ orgId?: string;
145
+ claims?: Record<string, unknown>;
146
+ }) => McpToolDefinition[] | Promise<McpToolDefinition[]>;
147
+ };
148
+ export type McpListToolsResult = {
149
+ tools: McpToolDefinition[];
150
+ };
151
+ export type McpToolsBySpace = Record<McpToolSpace, McpToolDefinition[]>;
152
+ export type McpAuthResult = {
153
+ ok: true;
154
+ subject?: string;
155
+ /** H5 — orgId depuis claim JWT `orgId` / `org_id`. */
156
+ orgId?: string;
157
+ claims?: Record<string, unknown>;
158
+ } | {
159
+ ok: false;
160
+ error: string;
161
+ status: number;
162
+ };
163
+ //# sourceMappingURL=types.d.ts.map