@happykiller/sunny-mcp 0.1.1 → 0.2.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/README.md ADDED
@@ -0,0 +1,8 @@
1
+
2
+ ## Note sur les tests
3
+
4
+ `npm test` passe `--test-force-exit` : le transport HTTP du SDK garde des
5
+ ressources que la fermeture du serveur n'emporte pas toutes, et le lanceur ne
6
+ rendait jamais la main alors que tous les cas passaient. Le drapeau est prévu
7
+ pour cela. Les assertions, elles, ne sont pas affaiblies : les cas de
8
+ `transport.test.ts` exercent de vraies requêtes HTTP.
@@ -10,6 +10,15 @@ export interface SessionOptions {
10
10
  password?: string;
11
11
  /** Jeton fixé d'avance : court-circuite toute connexion. */
12
12
  token?: string;
13
+ /**
14
+ * Fournit le jeton à la demande, au lieu de le négocier par login.
15
+ *
16
+ * C'est ce que le transport HTTP emploie : le jeton s'obtient alors par
17
+ * échange (RFC 8693) à partir de celui de l'appelant, et non par un couple
18
+ * login/mot de passe. Le serveur MCP ne détient ainsi aucun identifiant
19
+ * d'utilisateur, et chaque action reste attribuée à qui l'a demandée.
20
+ */
21
+ obtenirJeton?: () => Promise<string>;
13
22
  cache?: TokenCache;
14
23
  /** En-tête par lequel le serveur réémet un jeton frais à chaque requête
15
24
  * authentifiée (`seguri-refresh-token` chez Siguri). L'adopter évite de
@@ -1 +1 @@
1
- {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/graphql/session.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAG3C,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ;qEACiE;IACjE,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,MAAM,GAAG,SAAS,CAAC;IACjD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4DAA4D;IAC5D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB;;wDAEoD;IACpD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CAC1B;AAED,qBAAa,cAAc;IAKb,OAAO,CAAC,QAAQ,CAAC,IAAI;IAJjC,OAAO,CAAC,KAAK,CAAC,CAAS;IACvB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAe;gBAER,IAAI,EAAE,cAAc;IAM3C,OAAO,CAAC,CAAC,GAAG,GAAG,EACnB,QAAQ,EAAE,MAAM,EAChB,SAAS,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GACtC,OAAO,CAAC,CAAC,CAAC;IAoBb,2EAA2E;IACrE,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC;IAYxB,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC;YA0BpB,OAAO;IA6CrB,OAAO,CAAC,uBAAuB;CAQhC"}
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/graphql/session.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAG3C,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ;qEACiE;IACjE,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,MAAM,GAAG,SAAS,CAAC;IACjD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4DAA4D;IAC5D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;;;OAOG;IACH,YAAY,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IACrC,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB;;wDAEoD;IACpD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CAC1B;AAED,qBAAa,cAAc;IAKb,OAAO,CAAC,QAAQ,CAAC,IAAI;IAJjC,OAAO,CAAC,KAAK,CAAC,CAAS;IACvB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAe;gBAER,IAAI,EAAE,cAAc;IAM3C,OAAO,CAAC,CAAC,GAAG,GAAG,EACnB,QAAQ,EAAE,MAAM,EAChB,SAAS,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GACtC,OAAO,CAAC,CAAC,CAAC;IAoBb,2EAA2E;IACrE,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC;IAiBxB,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC;YA8BpB,OAAO;IA6CrB,OAAO,CAAC,uBAAuB;CAQhC"}
@@ -40,6 +40,10 @@ export class GraphQLSession {
40
40
  return this.opts.token;
41
41
  if (this.token)
42
42
  return this.token;
43
+ if (this.opts.obtenirJeton) {
44
+ this.token = await this.opts.obtenirJeton();
45
+ return this.token;
46
+ }
43
47
  const encache = this.opts.cache?.lire();
44
48
  if (encache) {
45
49
  this.token = encache;
@@ -48,6 +52,10 @@ export class GraphQLSession {
48
52
  return this.connexion();
49
53
  }
50
54
  async connexion() {
55
+ if (this.opts.obtenirJeton) {
56
+ this.token = await this.opts.obtenirJeton();
57
+ return this.token;
58
+ }
51
59
  if (!this.opts.login || !this.opts.password) {
52
60
  throw new GraphQLCallError('MISSING_CREDENTIALS', {
53
61
  hint: "Ni jeton fixé ni couple login/mot de passe n'a été fourni.",
@@ -1 +1 @@
1
- {"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/graphql/session.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/graphql/session.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,10 +1,10 @@
1
1
  export { ok, fail } from './server/contract.js';
2
2
  export { createMcpServer } from './server/createMcpServer.js';
3
- export type { CreateServerOptions } from './server/createMcpServer.js';
3
+ export type { CreateServerOptions, FabriqueContexte, } from './server/createMcpServer.js';
4
4
  export { startTransport } from './server/transport.js';
5
5
  export type { StartOptions, TransportKind } from './server/transport.js';
6
6
  export { defineTool } from './tools/defineTool.js';
7
- export type { ToolCatalog, ToolContext, ToolDefinition, } from './tools/defineTool.js';
7
+ export type { Appelant, ToolCatalog, ToolContext, ToolDefinition, } from './tools/defineTool.js';
8
8
  export { GraphQLSession } from './graphql/session.js';
9
9
  export type { SessionOptions } from './graphql/session.js';
10
10
  export { GraphQLCallError, estErreurAuth, mapGraphQLErrors, } from './graphql/errors.js';
@@ -14,4 +14,8 @@ export { AVEU_PROD, TargetRefusedError, resolveTarget, } from './safety/target.j
14
14
  export type { Target } from './safety/target.js';
15
15
  export { silentLogger, stderrLogger } from './logger.js';
16
16
  export type { Logger } from './logger.js';
17
+ export { creerVerificateurJwks } from './resource/verifier.js';
18
+ export type { OptionsVerificateur } from './resource/verifier.js';
19
+ export { CHEMIN_METADONNEES, metadonneesRessource, } from './resource/metadata.js';
20
+ export type { OptionsMetadonnees } from './resource/metadata.js';
17
21
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAC9D,YAAY,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AACvE,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAEzE,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,YAAY,EACV,WAAW,EACX,WAAW,EACX,cAAc,GACf,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,YAAY,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EACL,gBAAgB,EAChB,aAAa,EACb,gBAAgB,GACjB,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EACL,UAAU,EACV,WAAW,EACX,aAAa,EACb,iBAAiB,GAClB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EACL,SAAS,EACT,kBAAkB,EAClB,aAAa,GACd,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAEjD,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACzD,YAAY,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAC9D,YAAY,EACV,mBAAmB,EACnB,gBAAgB,GACjB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAEzE,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,YAAY,EACV,QAAQ,EACR,WAAW,EACX,WAAW,EACX,cAAc,GACf,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,YAAY,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EACL,gBAAgB,EAChB,aAAa,EACb,gBAAgB,GACjB,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EACL,UAAU,EACV,WAAW,EACX,aAAa,EACb,iBAAiB,GAClB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EACL,SAAS,EACT,kBAAkB,EAClB,aAAa,GACd,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAEjD,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACzD,YAAY,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,YAAY,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EACL,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,wBAAwB,CAAC;AAChC,YAAY,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC"}
package/dist/index.js CHANGED
@@ -8,4 +8,6 @@ export { GraphQLCallError, estErreurAuth, mapGraphQLErrors, } from './graphql/er
8
8
  export { TokenCache, cheminCache, jwtExpiration, tokenEncoreValide, } from './graphql/tokenCache.js';
9
9
  export { AVEU_PROD, TargetRefusedError, resolveTarget, } from './safety/target.js';
10
10
  export { silentLogger, stderrLogger } from './logger.js';
11
+ export { creerVerificateurJwks } from './resource/verifier.js';
12
+ export { CHEMIN_METADONNEES, metadonneesRessource, } from './resource/metadata.js';
11
13
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,4CAA4C;AAC5C,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAE9D,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAGvD,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAOnD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,OAAO,EACL,gBAAgB,EAChB,aAAa,EACb,gBAAgB,GACjB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,UAAU,EACV,WAAW,EACX,aAAa,EACb,iBAAiB,GAClB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EACL,SAAS,EACT,kBAAkB,EAClB,aAAa,GACd,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,4CAA4C;AAC5C,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAK9D,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAGvD,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAQnD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,OAAO,EACL,gBAAgB,EAChB,aAAa,EACb,gBAAgB,GACjB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,UAAU,EACV,WAAW,EACX,aAAa,EACb,iBAAiB,GAClB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EACL,SAAS,EACT,kBAAkB,EAClB,aAAa,GACd,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAGzD,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAE/D,OAAO,EACL,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,wBAAwB,CAAC"}
@@ -0,0 +1,14 @@
1
+ import type { OAuthProtectedResourceMetadata } from '@modelcontextprotocol/sdk/shared/auth.js';
2
+ export interface OptionsMetadonnees {
3
+ /** URI canonique de ce serveur — l'audience que porteront ses jetons. */
4
+ resource: string;
5
+ /** Serveurs d'autorisation habilités à émettre pour cette ressource. */
6
+ authorizationServers: string[];
7
+ /** Scopes minimaux nécessaires au fonctionnement de base. */
8
+ scopesSupported: string[];
9
+ resourceName?: string;
10
+ }
11
+ export declare function metadonneesRessource(opts: OptionsMetadonnees): OAuthProtectedResourceMetadata;
12
+ /** Chemin normalisé du document, tel que le cherchent les clients. */
13
+ export declare const CHEMIN_METADONNEES = "/.well-known/oauth-protected-resource";
14
+ //# sourceMappingURL=metadata.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metadata.d.ts","sourceRoot":"","sources":["../../src/resource/metadata.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,0CAA0C,CAAC;AAE/F,MAAM,WAAW,kBAAkB;IACjC,yEAAyE;IACzE,QAAQ,EAAE,MAAM,CAAC;IACjB,wEAAwE;IACxE,oBAAoB,EAAE,MAAM,EAAE,CAAC;IAC/B,6DAA6D;IAC7D,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,kBAAkB,GACvB,8BAA8B,CAQhC;AAED,sEAAsE;AACtE,eAAO,MAAM,kBAAkB,0CAA0C,CAAC"}
@@ -0,0 +1,12 @@
1
+ export function metadonneesRessource(opts) {
2
+ return {
3
+ resource: opts.resource,
4
+ authorization_servers: opts.authorizationServers,
5
+ scopes_supported: opts.scopesSupported,
6
+ bearer_methods_supported: ['header'],
7
+ resource_name: opts.resourceName,
8
+ };
9
+ }
10
+ /** Chemin normalisé du document, tel que le cherchent les clients. */
11
+ export const CHEMIN_METADONNEES = '/.well-known/oauth-protected-resource';
12
+ //# sourceMappingURL=metadata.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metadata.js","sourceRoot":"","sources":["../../src/resource/metadata.ts"],"names":[],"mappings":"AAqBA,MAAM,UAAU,oBAAoB,CAClC,IAAwB;IAExB,OAAO;QACL,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,qBAAqB,EAAE,IAAI,CAAC,oBAAoB;QAChD,gBAAgB,EAAE,IAAI,CAAC,eAAe;QACtC,wBAAwB,EAAE,CAAC,QAAQ,CAAC;QACpC,aAAa,EAAE,IAAI,CAAC,YAAY;KACjC,CAAC;AACJ,CAAC;AAED,sEAAsE;AACtE,MAAM,CAAC,MAAM,kBAAkB,GAAG,uCAAuC,CAAC"}
@@ -0,0 +1,21 @@
1
+ import type { OAuthTokenVerifier } from '@modelcontextprotocol/sdk/server/auth/provider.js';
2
+ import type { Logger } from '../logger.js';
3
+ export interface OptionsVerificateur {
4
+ /** Où le serveur d'autorisation publie ses clés publiques. */
5
+ jwksUri: string;
6
+ /** Émetteur attendu — le claim `iss`. */
7
+ issuer: string;
8
+ /** URI canonique de CE serveur, attendue en audience (RFC 8707). */
9
+ resource: string;
10
+ logger?: Logger;
11
+ }
12
+ /**
13
+ * Vérificateur adossé au JWKS du serveur d'autorisation.
14
+ *
15
+ * Les clés sont récupérées à distance et mises en cache par `jose`, qui gère
16
+ * aussi leur rotation : une clé inconnue déclenche une nouvelle récupération.
17
+ * C'est ce qui permet au serveur d'autorisation de faire tourner ses clés sans
18
+ * qu'on ait à redéployer ici quoi que ce soit.
19
+ */
20
+ export declare function creerVerificateurJwks(opts: OptionsVerificateur): OAuthTokenVerifier;
21
+ //# sourceMappingURL=verifier.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verifier.d.ts","sourceRoot":"","sources":["../../src/resource/verifier.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mDAAmD,CAAC;AAE5F,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAG3C,MAAM,WAAW,mBAAmB;IAClC,8DAA8D;IAC9D,OAAO,EAAE,MAAM,CAAC;IAChB,yCAAyC;IACzC,MAAM,EAAE,MAAM,CAAC;IACf,oEAAoE;IACpE,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,mBAAmB,GACxB,kBAAkB,CAiCpB"}
@@ -0,0 +1,46 @@
1
+ // src/resource/verifier.ts
2
+ // Vérification des jetons présentés au serveur MCP.
3
+ //
4
+ // La spécification MCP est explicite : un serveur MCP est un Resource Server
5
+ // OAuth 2.1, et il « MUST validate that access tokens were issued specifically
6
+ // for them as the intended audience ». Sans ce contrôle, un jeton obtenu pour
7
+ // n'importe quel autre service ouvrirait celui-ci.
8
+ import { createRemoteJWKSet, jwtVerify } from 'jose';
9
+ import { silentLogger } from '../logger.js';
10
+ /**
11
+ * Vérificateur adossé au JWKS du serveur d'autorisation.
12
+ *
13
+ * Les clés sont récupérées à distance et mises en cache par `jose`, qui gère
14
+ * aussi leur rotation : une clé inconnue déclenche une nouvelle récupération.
15
+ * C'est ce qui permet au serveur d'autorisation de faire tourner ses clés sans
16
+ * qu'on ait à redéployer ici quoi que ce soit.
17
+ */
18
+ export function creerVerificateurJwks(opts) {
19
+ const logger = opts.logger ?? silentLogger;
20
+ const jwks = createRemoteJWKSet(new URL(opts.jwksUri));
21
+ return {
22
+ async verifyAccessToken(token) {
23
+ const { payload } = await jwtVerify(token, jwks, {
24
+ issuer: opts.issuer,
25
+ // C'est LE contrôle qui compte. `jose` rejette le jeton si son `aud` ne
26
+ // contient pas cette valeur — donc si le jeton était destiné ailleurs.
27
+ audience: opts.resource,
28
+ });
29
+ const scopes = String(payload.scope ?? '')
30
+ .split(' ')
31
+ .filter(Boolean);
32
+ logger.info(`jeton accepté — sub=${payload.sub} scopes=${scopes.join(',') || 'aucun'}`);
33
+ return {
34
+ token,
35
+ clientId: String(payload.client_id ?? payload.azp ?? ''),
36
+ scopes,
37
+ expiresAt: typeof payload.exp === 'number' ? payload.exp : undefined,
38
+ resource: new URL(opts.resource),
39
+ // Le sujet voyage jusqu'aux outils : c'est lui qui dit AU NOM DE QUI
40
+ // l'action est faite, et c'est ce qui rend l'attribution exacte.
41
+ extra: { sub: payload.sub },
42
+ };
43
+ },
44
+ };
45
+ }
46
+ //# sourceMappingURL=verifier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verifier.js","sourceRoot":"","sources":["../../src/resource/verifier.ts"],"names":[],"mappings":"AAAA,2BAA2B;AAC3B,oDAAoD;AACpD,EAAE;AACF,6EAA6E;AAC7E,+EAA+E;AAC/E,8EAA8E;AAC9E,mDAAmD;AACnD,OAAO,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,MAAM,CAAC;AAKrD,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAY5C;;;;;;;GAOG;AACH,MAAM,UAAU,qBAAqB,CACnC,IAAyB;IAEzB,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,YAAY,CAAC;IAC3C,MAAM,IAAI,GAAG,kBAAkB,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;IAEvD,OAAO;QACL,KAAK,CAAC,iBAAiB,CAAC,KAAa;YACnC,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE;gBAC/C,MAAM,EAAE,IAAI,CAAC,MAAM;gBACnB,wEAAwE;gBACxE,uEAAuE;gBACvE,QAAQ,EAAE,IAAI,CAAC,QAAQ;aACxB,CAAC,CAAC;YAEH,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC;iBACvC,KAAK,CAAC,GAAG,CAAC;iBACV,MAAM,CAAC,OAAO,CAAC,CAAC;YAEnB,MAAM,CAAC,IAAI,CACT,uBAAuB,OAAO,CAAC,GAAG,WAAW,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,OAAO,EAAE,CAC3E,CAAC;YAEF,OAAO;gBACL,KAAK;gBACL,QAAQ,EAAE,MAAM,CAAC,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC,GAAG,IAAI,EAAE,CAAC;gBACxD,MAAM;gBACN,SAAS,EAAE,OAAO,OAAO,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS;gBACpE,QAAQ,EAAE,IAAI,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC;gBAChC,qEAAqE;gBACrE,iEAAiE;gBACjE,KAAK,EAAE,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE;aAC5B,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -1,10 +1,19 @@
1
1
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
- import type { ToolCatalog, ToolContext } from '../tools/defineTool.js';
2
+ import type { Appelant, ToolCatalog, ToolContext } from '../tools/defineTool.js';
3
+ /**
4
+ * Contexte des outils : une valeur fixe, ou une fabrique appelée à CHAQUE
5
+ * requête.
6
+ *
7
+ * La fabrique existe pour le transport HTTP, où l'identité varie d'un appel à
8
+ * l'autre : un contexte figé y ferait agir tout le monde sous la même identité.
9
+ * En stdio, la valeur fixe suffit.
10
+ */
11
+ export type FabriqueContexte = (appelant: Appelant | undefined) => ToolContext | Promise<ToolContext>;
3
12
  export interface CreateServerOptions {
4
13
  name: string;
5
14
  version: string;
6
15
  catalog: ToolCatalog;
7
- ctx: ToolContext;
16
+ ctx: ToolContext | FabriqueContexte;
8
17
  }
9
18
  export declare function createMcpServer(opts: CreateServerOptions): McpServer;
10
19
  //# sourceMappingURL=createMcpServer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"createMcpServer.d.ts","sourceRoot":"","sources":["../../src/server/createMcpServer.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIpE,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAEvE,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,WAAW,CAAC;IACrB,GAAG,EAAE,WAAW,CAAC;CAClB;AAMD,wBAAgB,eAAe,CAAC,IAAI,EAAE,mBAAmB,GAAG,SAAS,CA0DpE"}
1
+ {"version":3,"file":"createMcpServer.d.ts","sourceRoot":"","sources":["../../src/server/createMcpServer.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIpE,OAAO,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAEjF;;;;;;;GAOG;AACH,MAAM,MAAM,gBAAgB,GAAG,CAC7B,QAAQ,EAAE,QAAQ,GAAG,SAAS,KAC3B,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;AAExC,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,WAAW,CAAC;IACrB,GAAG,EAAE,WAAW,GAAG,gBAAgB,CAAC;CACrC;AAMD,wBAAgB,eAAe,CAAC,IAAI,EAAE,mBAAmB,GAAG,SAAS,CAgFpE"}
@@ -6,15 +6,19 @@ import { GraphQLCallError } from '../graphql/errors.js';
6
6
  * chose que l'agent lit avant d'agir, c'est la description. */
7
7
  const PREFIXE_PROD = '[PRODUCTION] ';
8
8
  export function createMcpServer(opts) {
9
- const { catalog, ctx } = opts;
9
+ const { catalog } = opts;
10
10
  const server = new McpServer({ name: opts.name, version: opts.version });
11
+ const resoudreContexte = async (appelant) => typeof opts.ctx === 'function' ? opts.ctx(appelant) : opts.ctx;
12
+ // La cible et l'interrupteur d'écriture ne dépendent pas de l'appelant : on
13
+ // les lit une fois, pour décider des descriptions à l'enregistrement.
14
+ const ctx = typeof opts.ctx === 'function' ? undefined : opts.ctx;
11
15
  const noms = new Set();
12
16
  for (const tool of catalog) {
13
17
  if (noms.has(tool.name)) {
14
18
  throw new Error(`Outil déclaré deux fois : ${tool.name}`);
15
19
  }
16
20
  noms.add(tool.name);
17
- const description = ctx.target.isProd && tool.requiresWrite
21
+ const description = ctx?.target.isProd && tool.requiresWrite
18
22
  ? PREFIXE_PROD + tool.description
19
23
  : tool.description;
20
24
  server.registerTool(tool.name, {
@@ -22,27 +26,38 @@ export function createMcpServer(opts) {
22
26
  description,
23
27
  inputSchema: tool.inputSchema,
24
28
  annotations: tool.annotations,
25
- }, async (args) => {
26
- if (tool.requiresWrite && !ctx.allowWrites) {
29
+ }, async (args, extra) => {
30
+ // L'identité vient du transport : le middleware Bearer la dépose sur la
31
+ // requête, et le SDK la relaie jusqu'ici.
32
+ const info = extra?.authInfo;
33
+ const appelant = info
34
+ ? {
35
+ sub: info.extra?.sub ?? undefined,
36
+ scopes: info.scopes ?? [],
37
+ token: info.token,
38
+ }
39
+ : undefined;
40
+ const contexte = await resoudreContexte(appelant);
41
+ if (tool.requiresWrite && !contexte.allowWrites) {
27
42
  // Refus AVANT toute requête : rien ne part sur le réseau.
28
43
  return fail('WRITES_DISABLED', {
29
44
  tool: tool.name,
30
- target: ctx.target.url,
45
+ target: contexte.target.url,
31
46
  hint: 'Poser SUNNY_MCP_ALLOW_WRITES=true pour autoriser les écritures.',
32
47
  });
33
48
  }
34
49
  try {
35
- const resultat = await tool.execute(args, ctx);
50
+ const resultat = await tool.execute(args, contexte);
36
51
  // Chaque réponse rappelle où elle a agi : l'agent et le lecteur de la
37
52
  // transcription voient la cible sans avoir à la deviner.
38
53
  return ok({
39
54
  ...resultat,
40
- target: ctx.target.url,
41
- is_prod: ctx.target.isProd,
55
+ target: contexte.target.url,
56
+ is_prod: contexte.target.isProd,
42
57
  });
43
58
  }
44
59
  catch (e) {
45
- ctx.logger.error(`${tool.name} : ${e?.message ?? e}`);
60
+ contexte.logger.error(`${tool.name} : ${e?.message ?? e}`);
46
61
  if (e instanceof GraphQLCallError) {
47
62
  return fail(e.code, { ...e.details, tool: tool.name });
48
63
  }
@@ -1 +1 @@
1
- {"version":3,"file":"createMcpServer.js","sourceRoot":"","sources":["../../src/server/createMcpServer.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAUxD;gEACgE;AAChE,MAAM,YAAY,GAAG,eAAe,CAAC;AAErC,MAAM,UAAU,eAAe,CAAC,IAAyB;IACvD,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IAC9B,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;IAEzE,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;QAC3B,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YACxB,MAAM,IAAI,KAAK,CAAC,6BAA6B,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QAC5D,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAEpB,MAAM,WAAW,GACf,GAAG,CAAC,MAAM,CAAC,MAAM,IAAI,IAAI,CAAC,aAAa;YACrC,CAAC,CAAC,YAAY,GAAG,IAAI,CAAC,WAAW;YACjC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC;QAEvB,MAAM,CAAC,YAAY,CACjB,IAAI,CAAC,IAAI,EACT;YACE,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,WAAW;YACX,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,WAAW,EAAE,IAAI,CAAC,WAAW;SAC9B,EACD,KAAK,EAAE,IAAS,EAAE,EAAE;YAClB,IAAI,IAAI,CAAC,aAAa,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;gBAC3C,0DAA0D;gBAC1D,OAAO,IAAI,CAAC,iBAAiB,EAAE;oBAC7B,IAAI,EAAE,IAAI,CAAC,IAAI;oBACf,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG;oBACtB,IAAI,EAAE,iEAAiE;iBACxE,CAAC,CAAC;YACL,CAAC;YAED,IAAI,CAAC;gBACH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;gBAC/C,sEAAsE;gBACtE,yDAAyD;gBACzD,OAAO,EAAE,CAAC;oBACR,GAAI,QAAmB;oBACvB,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG;oBACtB,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,MAAM;iBAC3B,CAAC,CAAC;YACL,CAAC;YAAC,OAAO,CAAM,EAAE,CAAC;gBAChB,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,IAAI,MAAM,CAAC,EAAE,OAAO,IAAI,CAAC,EAAE,CAAC,CAAC;gBACtD,IAAI,CAAC,YAAY,gBAAgB,EAAE,CAAC;oBAClC,OAAO,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,GAAI,CAAC,CAAC,OAAkB,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;gBACrE,CAAC;gBACD,OAAO,IAAI,CAAC,CAAC,EAAE,IAAI,IAAI,aAAa,EAAE;oBACpC,OAAO,EAAE,CAAC,EAAE,OAAO,IAAI,MAAM,CAAC,CAAC,CAAC;oBAChC,IAAI,EAAE,IAAI,CAAC,IAAI;iBAChB,CAAC,CAAC;YACL,CAAC;QACH,CAAC,CACF,CAAC;IACJ,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
1
+ {"version":3,"file":"createMcpServer.js","sourceRoot":"","sources":["../../src/server/createMcpServer.ts"],"names":[],"mappings":"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"}
@@ -1,10 +1,32 @@
1
+ import type { Server } from 'node:http';
1
2
  import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
3
+ import type { OAuthTokenVerifier } from '@modelcontextprotocol/sdk/server/auth/provider.js';
2
4
  import type { Logger } from '../logger.js';
5
+ import type { OptionsMetadonnees } from '../resource/metadata.js';
3
6
  export type TransportKind = 'stdio' | 'http';
4
7
  export interface StartOptions {
5
8
  transport?: TransportKind;
6
9
  port?: number;
7
10
  logger?: Logger;
11
+ /**
12
+ * Protection du transport HTTP. Absente, `/mcp` est ouvert — ce qui n'est
13
+ * défendable qu'en réseau strictement privé.
14
+ *
15
+ * Sans objet en stdio : la spécification écarte explicitement ce transport du
16
+ * régime OAuth, les identifiants venant alors de l'environnement.
17
+ */
18
+ resourceServer?: {
19
+ verifier: OAuthTokenVerifier;
20
+ /** Scopes exigés sur toute requête. Un manque donne un 403, pas un 401. */
21
+ requiredScopes?: string[];
22
+ metadata: OptionsMetadonnees;
23
+ };
8
24
  }
9
- export declare function startTransport(server: McpServer, opts?: StartOptions): Promise<void>;
25
+ /**
26
+ * Démarre le transport et rend le serveur HTTP, quand il y en a un.
27
+ *
28
+ * Le rendre n'est pas une commodité : un serveur qu'on ne peut pas arrêter est
29
+ * intestable, et il empêche tout processus qui l'embarque de se terminer.
30
+ */
31
+ export declare function startTransport(server: McpServer, opts?: StartOptions): Promise<Server | undefined>;
10
32
  //# sourceMappingURL=transport.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../src/server/transport.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAG3C,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,MAAM,CAAC;AAE7C,MAAM,WAAW,YAAY;IAC3B,SAAS,CAAC,EAAE,aAAa,CAAC;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAsB,cAAc,CAClC,MAAM,EAAE,SAAS,EACjB,IAAI,GAAE,YAAiB,GACtB,OAAO,CAAC,IAAI,CAAC,CAkCf"}
1
+ {"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../src/server/transport.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAGxC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIzE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mDAAmD,CAAC;AAE5F,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAG3C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAElE,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,MAAM,CAAC;AAE7C,MAAM,WAAW,YAAY;IAC3B,SAAS,CAAC,EAAE,aAAa,CAAC;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;;OAMG;IACH,cAAc,CAAC,EAAE;QACf,QAAQ,EAAE,kBAAkB,CAAC;QAC7B,2EAA2E;QAC3E,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;QAC1B,QAAQ,EAAE,kBAAkB,CAAC;KAC9B,CAAC;CACH;AAED;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,MAAM,EAAE,SAAS,EACjB,IAAI,GAAE,YAAiB,GACtB,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAyE7B"}
@@ -5,17 +5,38 @@
5
5
  import express from 'express';
6
6
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
7
7
  import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
8
+ import { metadataHandler } from '@modelcontextprotocol/sdk/server/auth/handlers/metadata.js';
9
+ import { requireBearerAuth } from '@modelcontextprotocol/sdk/server/auth/middleware/bearerAuth.js';
8
10
  import { silentLogger } from '../logger.js';
11
+ import { CHEMIN_METADONNEES, metadonneesRessource } from '../resource/metadata.js';
12
+ /**
13
+ * Démarre le transport et rend le serveur HTTP, quand il y en a un.
14
+ *
15
+ * Le rendre n'est pas une commodité : un serveur qu'on ne peut pas arrêter est
16
+ * intestable, et il empêche tout processus qui l'embarque de se terminer.
17
+ */
9
18
  export async function startTransport(server, opts = {}) {
10
19
  const logger = opts.logger ?? silentLogger;
11
20
  const kind = opts.transport ?? 'stdio';
12
21
  if (kind === 'stdio') {
13
22
  await server.connect(new StdioServerTransport());
14
23
  logger.info('transport stdio prêt');
15
- return;
24
+ return undefined;
16
25
  }
17
26
  const app = express();
18
27
  app.use(express.json({ limit: '4mb' }));
28
+ const protection = opts.resourceServer;
29
+ if (protection) {
30
+ // Le document de découverte reste PUBLIC : c'est par lui qu'un client non
31
+ // authentifié apprend où aller s'authentifier. L'exiger authentifié
32
+ // rendrait la découverte impossible.
33
+ // `app.use` et non `app.get` : le SDK rend un Router dont la route est `/`.
34
+ // Monté en `get`, la requête lui parvient avec son chemin entier, sa route
35
+ // ne correspond jamais, et le document répond 404 — en désignant pourtant
36
+ // sa propre adresse dans l'en-tête `WWW-Authenticate` des refus.
37
+ app.use(CHEMIN_METADONNEES, metadataHandler(metadonneesRessource(protection.metadata)));
38
+ logger.info(`métadonnées de ressource sur ${CHEMIN_METADONNEES}`);
39
+ }
19
40
  // `sessionIdGenerator: undefined` = mode sans état : aucune session à tenir
20
41
  // côté serveur, donc rien à répliquer si l'on déploie plusieurs instances.
21
42
  const transport = new StreamableHTTPServerTransport({
@@ -25,14 +46,34 @@ export async function startTransport(server, opts = {}) {
25
46
  const relais = async (req, res) => {
26
47
  await transport.handleRequest(req, res, req.body);
27
48
  };
28
- app.post('/mcp', relais);
29
- app.get('/mcp', relais);
30
- app.delete('/mcp', relais);
49
+ // Le middleware du SDK produit lui-même le 401 et son en-tête
50
+ // `WWW-Authenticate`, porteur de l'adresse des métadonnées : c'est ce qui
51
+ // permet à un client de découvrir le serveur d'autorisation à partir d'un
52
+ // simple refus. Un scope manquant donne un 403 `insufficient_scope`.
53
+ const garde = protection
54
+ ? [
55
+ requireBearerAuth({
56
+ verifier: protection.verifier,
57
+ requiredScopes: protection.requiredScopes,
58
+ resourceMetadataUrl: `${protection.metadata.resource.replace(/\/mcp$/, '')}${CHEMIN_METADONNEES}`,
59
+ }),
60
+ ]
61
+ : [];
62
+ app.post('/mcp', ...garde, relais);
63
+ app.get('/mcp', ...garde, relais);
64
+ app.delete('/mcp', ...garde, relais);
31
65
  const port = opts.port ?? 3000;
32
- await new Promise((resolve) => {
33
- app.listen(port, () => {
66
+ return new Promise((resolve) => {
67
+ const httpServer = app.listen(port, () => {
34
68
  logger.info(`transport http prêt sur :${port}/mcp`);
35
- resolve();
69
+ resolve(httpServer);
70
+ });
71
+ // Fermer le serveur HTTP doit tout emporter. Sans cela, le transport et le
72
+ // serveur MCP gardent des ressources que l'appelant n'a aucun moyen
73
+ // d'atteindre — et le processus qui les embarque ne se termine jamais.
74
+ httpServer.on('close', () => {
75
+ void transport.close();
76
+ void server.close();
36
77
  });
37
78
  });
38
79
  }
@@ -1 +1 @@
1
- {"version":3,"file":"transport.js","sourceRoot":"","sources":["../../src/server/transport.ts"],"names":[],"mappings":"AAAA,0BAA0B;AAC1B,+EAA+E;AAC/E,iFAAiF;AACjF,+DAA+D;AAC/D,OAAO,OAAO,MAAM,SAAS,CAAC;AAC9B,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,6BAA6B,EAAE,MAAM,oDAAoD,CAAC;AAInG,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAU5C,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,MAAiB,EACjB,OAAqB,EAAE;IAEvB,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,YAAY,CAAC;IAC3C,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,IAAI,OAAO,CAAC;IAEvC,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;QACrB,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,oBAAoB,EAAE,CAAC,CAAC;QACjD,MAAM,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;QACpC,OAAO;IACT,CAAC;IAED,MAAM,GAAG,GAAG,OAAO,EAAE,CAAC;IACtB,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;IAExC,4EAA4E;IAC5E,2EAA2E;IAC3E,MAAM,SAAS,GAAG,IAAI,6BAA6B,CAAC;QAClD,kBAAkB,EAAE,SAAS;KAC9B,CAAC,CAAC;IACH,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAEhC,MAAM,MAAM,GAAG,KAAK,EAAE,GAAoB,EAAE,GAAqB,EAAE,EAAE;QACnE,MAAM,SAAS,CAAC,aAAa,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;IACpD,CAAC,CAAC;IACF,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzB,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxB,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAE3B,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC;IAC/B,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;QAClC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE;YACpB,MAAM,CAAC,IAAI,CAAC,4BAA4B,IAAI,MAAM,CAAC,CAAC;YACpD,OAAO,EAAE,CAAC;QACZ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"transport.js","sourceRoot":"","sources":["../../src/server/transport.ts"],"names":[],"mappings":"AAAA,0BAA0B;AAC1B,+EAA+E;AAC/E,iFAAiF;AACjF,+DAA+D;AAC/D,OAAO,OAAO,MAAM,SAAS,CAAC;AAE9B,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,6BAA6B,EAAE,MAAM,oDAAoD,CAAC;AAGnG,OAAO,EAAE,eAAe,EAAE,MAAM,4DAA4D,CAAC;AAC7F,OAAO,EAAE,iBAAiB,EAAE,MAAM,gEAAgE,CAAC;AAInG,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAwBnF;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,MAAiB,EACjB,OAAqB,EAAE;IAEvB,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,YAAY,CAAC;IAC3C,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,IAAI,OAAO,CAAC;IAEvC,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;QACrB,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,oBAAoB,EAAE,CAAC,CAAC;QACjD,MAAM,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;QACpC,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,GAAG,GAAG,OAAO,EAAE,CAAC;IACtB,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;IAExC,MAAM,UAAU,GAAG,IAAI,CAAC,cAAc,CAAC;IACvC,IAAI,UAAU,EAAE,CAAC;QACf,0EAA0E;QAC1E,oEAAoE;QACpE,qCAAqC;QACrC,4EAA4E;QAC5E,2EAA2E;QAC3E,0EAA0E;QAC1E,iEAAiE;QACjE,GAAG,CAAC,GAAG,CACL,kBAAkB,EAClB,eAAe,CAAC,oBAAoB,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAC3D,CAAC;QACF,MAAM,CAAC,IAAI,CAAC,gCAAgC,kBAAkB,EAAE,CAAC,CAAC;IACpE,CAAC;IAED,4EAA4E;IAC5E,2EAA2E;IAC3E,MAAM,SAAS,GAAG,IAAI,6BAA6B,CAAC;QAClD,kBAAkB,EAAE,SAAS;KAC9B,CAAC,CAAC;IACH,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAEhC,MAAM,MAAM,GAAG,KAAK,EAAE,GAAoB,EAAE,GAAqB,EAAE,EAAE;QACnE,MAAM,SAAS,CAAC,aAAa,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;IACpD,CAAC,CAAC;IAEF,8DAA8D;IAC9D,0EAA0E;IAC1E,0EAA0E;IAC1E,qEAAqE;IACrE,MAAM,KAAK,GAA6B,UAAU;QAChD,CAAC,CAAC;YACE,iBAAiB,CAAC;gBAChB,QAAQ,EAAE,UAAU,CAAC,QAAQ;gBAC7B,cAAc,EAAE,UAAU,CAAC,cAAc;gBACzC,mBAAmB,EAAE,GAAG,UAAU,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,GAAG,kBAAkB,EAAE;aAClG,CAAC;SACH;QACH,CAAC,CAAC,EAAE,CAAC;IAEP,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,KAAK,EAAE,MAAM,CAAC,CAAC;IACnC,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,KAAK,EAAE,MAAM,CAAC,CAAC;IAClC,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,KAAK,EAAE,MAAM,CAAC,CAAC;IAErC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC;IAC/B,OAAO,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,EAAE;QACrC,MAAM,UAAU,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE;YACvC,MAAM,CAAC,IAAI,CAAC,4BAA4B,IAAI,MAAM,CAAC,CAAC;YACpD,OAAO,CAAC,UAAU,CAAC,CAAC;QACtB,CAAC,CAAC,CAAC;QAEH,2EAA2E;QAC3E,oEAAoE;QACpE,uEAAuE;QACvE,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;YAC1B,KAAK,SAAS,CAAC,KAAK,EAAE,CAAC;YACvB,KAAK,MAAM,CAAC,KAAK,EAAE,CAAC;QACtB,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -3,9 +3,25 @@ import type { ToolAnnotations } from '@modelcontextprotocol/sdk/types.js';
3
3
  import type { Logger } from '../logger.js';
4
4
  import type { Target } from '../safety/target.js';
5
5
  import type { GraphQLSession } from '../graphql/session.js';
6
+ /**
7
+ * Identité de l'appelant, quand le transport en porte une.
8
+ *
9
+ * Absente en stdio : le serveur y agit sous une seule identité, celle de son
10
+ * environnement. Présente en HTTP, où chaque requête arrive avec son jeton —
11
+ * c'est ce qui permet d'attribuer une action à la personne qui l'a demandée
12
+ * plutôt qu'à un compte de service partagé.
13
+ */
14
+ export interface Appelant {
15
+ /** Sujet du jeton : l'identifiant du compte au nom duquel on agit. */
16
+ sub?: string;
17
+ scopes: string[];
18
+ /** Le jeton lui-même, à présenter pour en obtenir un autre en aval. */
19
+ token: string;
20
+ }
6
21
  export interface ToolContext {
7
22
  gql: GraphQLSession;
8
23
  target: Target;
24
+ appelant?: Appelant;
9
25
  /** Interrupteur d'écriture, indépendant de la cible : il faut deux erreurs
10
26
  * pour écrire en production, pas une. */
11
27
  allowWrites: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"defineTool.d.ts","sourceRoot":"","sources":["../../src/tools/defineTool.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAC7B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oCAAoC,CAAC;AAE1E,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,cAAc,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf;8CAC0C;IAC1C,WAAW,EAAE,OAAO,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,cAAc,CAAC,CAAC,SAAS,CAAC,CAAC,WAAW,GAAG,CAAC,CAAC,WAAW;IACrE,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,CAAC,CAAC;IACf,WAAW,CAAC,EAAE,eAAe,CAAC;IAC9B;kDAC8C;IAC9C,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,6EAA6E;IAC7E,OAAO,CACL,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAC7B,GAAG,EAAE,WAAW,GACf,OAAO,CAAC,OAAO,CAAC,CAAC;CACrB;AAED,eAAO,MAAM,UAAU,GAAI,CAAC,SAAS,CAAC,CAAC,WAAW,EAAE,GAAG,cAAc,CAAC,CAAC,CAAC,sBAAM,CAAC;AAE/E,MAAM,MAAM,WAAW,GAAG,aAAa,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"defineTool.d.ts","sourceRoot":"","sources":["../../src/tools/defineTool.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAC7B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oCAAoC,CAAC;AAE1E,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D;;;;;;;GAOG;AACH,MAAM,WAAW,QAAQ;IACvB,sEAAsE;IACtE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,uEAAuE;IACvE,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,cAAc,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB;8CAC0C;IAC1C,WAAW,EAAE,OAAO,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,cAAc,CAAC,CAAC,SAAS,CAAC,CAAC,WAAW,GAAG,CAAC,CAAC,WAAW;IACrE,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,CAAC,CAAC;IACf,WAAW,CAAC,EAAE,eAAe,CAAC;IAC9B;kDAC8C;IAC9C,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,6EAA6E;IAC7E,OAAO,CACL,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAC7B,GAAG,EAAE,WAAW,GACf,OAAO,CAAC,OAAO,CAAC,CAAC;CACrB;AAED,eAAO,MAAM,UAAU,GAAI,CAAC,SAAS,CAAC,CAAC,WAAW,EAAE,GAAG,cAAc,CAAC,CAAC,CAAC,sBAAM,CAAC;AAE/E,MAAM,MAAM,WAAW,GAAG,aAAa,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"defineTool.js","sourceRoot":"","sources":["../../src/tools/defineTool.ts"],"names":[],"mappings":"AAqCA,MAAM,CAAC,MAAM,UAAU,GAAG,CAA0B,CAAoB,EAAE,EAAE,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"defineTool.js","sourceRoot":"","sources":["../../src/tools/defineTool.ts"],"names":[],"mappings":"AAsDA,MAAM,CAAC,MAAM,UAAU,GAAG,CAA0B,CAAoB,EAAE,EAAE,CAAC,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,12 +1,18 @@
1
1
  {
2
2
  "name": "@happykiller/sunny-mcp",
3
- "version": "0.1.1",
3
+ "version": "0.2.1",
4
4
  "description": "Socle MCP partagé : transport, session GraphQL, registre d'outils et garde-fous, pour exposer le back-office d'un produit aux agents.",
5
5
  "license": "ISC",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/Happykiller/sunny-mcp.git"
9
+ },
6
10
  "type": "module",
7
11
  "main": "dist/index.js",
8
12
  "types": "dist/index.d.ts",
9
- "files": ["dist"],
13
+ "files": [
14
+ "dist"
15
+ ],
10
16
  "exports": {
11
17
  ".": {
12
18
  "types": "./dist/index.d.ts",
@@ -16,12 +22,13 @@
16
22
  },
17
23
  "scripts": {
18
24
  "build": "rm -rf dist && tsc -p tsconfig.json",
19
- "test": "tsx --test $(find src -name '*.test.ts' | sort)",
25
+ "test": "tsx --test --test-force-exit $(find src -name '*.test.ts' | sort)",
20
26
  "check": "tsc --noEmit -p tsconfig.json && npm test"
21
27
  },
22
28
  "dependencies": {
23
29
  "@modelcontextprotocol/sdk": "^1.29.0",
24
30
  "express": "^5.2.1",
31
+ "jose": "^6.2.10",
25
32
  "zod": "^4.3.6"
26
33
  },
27
34
  "devDependencies": {