@happykiller/sunny-mcp 0.2.0 → 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.
@@ -1,3 +1,4 @@
1
+ import type { Server } from 'node:http';
1
2
  import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
3
  import type { OAuthTokenVerifier } from '@modelcontextprotocol/sdk/server/auth/provider.js';
3
4
  import type { Logger } from '../logger.js';
@@ -21,5 +22,11 @@ export interface StartOptions {
21
22
  metadata: OptionsMetadonnees;
22
23
  };
23
24
  }
24
- 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>;
25
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;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,wBAAsB,cAAc,CAClC,MAAM,EAAE,SAAS,EACjB,IAAI,GAAE,YAAiB,GACtB,OAAO,CAAC,IAAI,CAAC,CA6Df"}
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"}
@@ -9,13 +9,19 @@ import { metadataHandler } from '@modelcontextprotocol/sdk/server/auth/handlers/
9
9
  import { requireBearerAuth } from '@modelcontextprotocol/sdk/server/auth/middleware/bearerAuth.js';
10
10
  import { silentLogger } from '../logger.js';
11
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
+ */
12
18
  export async function startTransport(server, opts = {}) {
13
19
  const logger = opts.logger ?? silentLogger;
14
20
  const kind = opts.transport ?? 'stdio';
15
21
  if (kind === 'stdio') {
16
22
  await server.connect(new StdioServerTransport());
17
23
  logger.info('transport stdio prêt');
18
- return;
24
+ return undefined;
19
25
  }
20
26
  const app = express();
21
27
  app.use(express.json({ limit: '4mb' }));
@@ -24,7 +30,11 @@ export async function startTransport(server, opts = {}) {
24
30
  // Le document de découverte reste PUBLIC : c'est par lui qu'un client non
25
31
  // authentifié apprend où aller s'authentifier. L'exiger authentifié
26
32
  // rendrait la découverte impossible.
27
- app.get(CHEMIN_METADONNEES, metadataHandler(metadonneesRessource(protection.metadata)));
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)));
28
38
  logger.info(`métadonnées de ressource sur ${CHEMIN_METADONNEES}`);
29
39
  }
30
40
  // `sessionIdGenerator: undefined` = mode sans état : aucune session à tenir
@@ -53,10 +63,17 @@ export async function startTransport(server, opts = {}) {
53
63
  app.get('/mcp', ...garde, relais);
54
64
  app.delete('/mcp', ...garde, relais);
55
65
  const port = opts.port ?? 3000;
56
- await new Promise((resolve) => {
57
- app.listen(port, () => {
66
+ return new Promise((resolve) => {
67
+ const httpServer = app.listen(port, () => {
58
68
  logger.info(`transport http prêt sur :${port}/mcp`);
59
- 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();
60
77
  });
61
78
  });
62
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;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,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,MAAM,UAAU,GAAG,IAAI,CAAC,cAAc,CAAC;IACvC,IAAI,UAAU,EAAE,CAAC;QACf,0EAA0E;QAC1E,oEAAoE;QACpE,qCAAqC;QACrC,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,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":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@happykiller/sunny-mcp",
3
- "version": "0.2.0",
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
6
  "repository": {
@@ -22,7 +22,7 @@
22
22
  },
23
23
  "scripts": {
24
24
  "build": "rm -rf dist && tsc -p tsconfig.json",
25
- "test": "tsx --test $(find src -name '*.test.ts' | sort)",
25
+ "test": "tsx --test --test-force-exit $(find src -name '*.test.ts' | sort)",
26
26
  "check": "tsc --noEmit -p tsconfig.json && npm test"
27
27
  },
28
28
  "dependencies": {