@atxp/server 0.2.5

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 (107) hide show
  1. package/README.md +148 -0
  2. package/dist/atxpContext.d.ts +6 -0
  3. package/dist/atxpContext.d.ts.map +1 -0
  4. package/dist/atxpContext.js +41 -0
  5. package/dist/atxpContext.js.map +1 -0
  6. package/dist/atxpServer.d.ts +12 -0
  7. package/dist/atxpServer.d.ts.map +1 -0
  8. package/dist/atxpServer.js +101 -0
  9. package/dist/atxpServer.js.map +1 -0
  10. package/dist/getResource.d.ts +4 -0
  11. package/dist/getResource.d.ts.map +1 -0
  12. package/dist/getResource.js +17 -0
  13. package/dist/getResource.js.map +1 -0
  14. package/dist/http.d.ts +7 -0
  15. package/dist/http.d.ts.map +1 -0
  16. package/dist/http.js +51 -0
  17. package/dist/http.js.map +1 -0
  18. package/dist/index.d.ts +5 -0
  19. package/dist/index.d.ts.map +1 -0
  20. package/dist/index.js +5 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/oAuthChallenge.d.ts +4 -0
  23. package/dist/oAuthChallenge.d.ts.map +1 -0
  24. package/dist/oAuthChallenge.js +39 -0
  25. package/dist/oAuthChallenge.js.map +1 -0
  26. package/dist/oAuthMetadata.d.ts +6 -0
  27. package/dist/oAuthMetadata.d.ts.map +1 -0
  28. package/dist/oAuthMetadata.js +41 -0
  29. package/dist/oAuthMetadata.js.map +1 -0
  30. package/dist/paymentServer.d.ts +68 -0
  31. package/dist/paymentServer.d.ts.map +1 -0
  32. package/dist/paymentServer.js +97 -0
  33. package/dist/paymentServer.js.map +1 -0
  34. package/dist/protectedResourceMetadata.d.ts +5 -0
  35. package/dist/protectedResourceMetadata.d.ts.map +1 -0
  36. package/dist/protectedResourceMetadata.js +40 -0
  37. package/dist/protectedResourceMetadata.js.map +1 -0
  38. package/dist/requirePayment.d.ts +3 -0
  39. package/dist/requirePayment.d.ts.map +1 -0
  40. package/dist/requirePayment.js +35 -0
  41. package/dist/requirePayment.js.map +1 -0
  42. package/dist/serverTestHelpers.d.ts +55 -0
  43. package/dist/serverTestHelpers.d.ts.map +1 -0
  44. package/dist/serverTestHelpers.js +88 -0
  45. package/dist/serverTestHelpers.js.map +1 -0
  46. package/dist/src/atxpContext.d.ts +6 -0
  47. package/dist/src/atxpContext.d.ts.map +1 -0
  48. package/dist/src/atxpContext.js +41 -0
  49. package/dist/src/atxpContext.js.map +1 -0
  50. package/dist/src/atxpServer.d.ts +12 -0
  51. package/dist/src/atxpServer.d.ts.map +1 -0
  52. package/dist/src/atxpServer.js +95 -0
  53. package/dist/src/atxpServer.js.map +1 -0
  54. package/dist/src/getResource.d.ts +4 -0
  55. package/dist/src/getResource.d.ts.map +1 -0
  56. package/dist/src/getResource.js +17 -0
  57. package/dist/src/getResource.js.map +1 -0
  58. package/dist/src/http.d.ts +7 -0
  59. package/dist/src/http.d.ts.map +1 -0
  60. package/dist/src/http.js +51 -0
  61. package/dist/src/http.js.map +1 -0
  62. package/dist/src/index.d.ts +5 -0
  63. package/dist/src/index.d.ts.map +1 -0
  64. package/dist/src/index.js +5 -0
  65. package/dist/src/index.js.map +1 -0
  66. package/dist/src/oAuthChallenge.d.ts +4 -0
  67. package/dist/src/oAuthChallenge.d.ts.map +1 -0
  68. package/dist/src/oAuthChallenge.js +39 -0
  69. package/dist/src/oAuthChallenge.js.map +1 -0
  70. package/dist/src/oAuthMetadata.d.ts +6 -0
  71. package/dist/src/oAuthMetadata.d.ts.map +1 -0
  72. package/dist/src/oAuthMetadata.js +41 -0
  73. package/dist/src/oAuthMetadata.js.map +1 -0
  74. package/dist/src/paymentServer.d.ts +68 -0
  75. package/dist/src/paymentServer.d.ts.map +1 -0
  76. package/dist/src/paymentServer.js +97 -0
  77. package/dist/src/paymentServer.js.map +1 -0
  78. package/dist/src/protectedResourceMetadata.d.ts +5 -0
  79. package/dist/src/protectedResourceMetadata.d.ts.map +1 -0
  80. package/dist/src/protectedResourceMetadata.js +40 -0
  81. package/dist/src/protectedResourceMetadata.js.map +1 -0
  82. package/dist/src/requirePayment.d.ts +3 -0
  83. package/dist/src/requirePayment.d.ts.map +1 -0
  84. package/dist/src/requirePayment.js +35 -0
  85. package/dist/src/requirePayment.js.map +1 -0
  86. package/dist/src/serverTestHelpers.d.ts +55 -0
  87. package/dist/src/serverTestHelpers.d.ts.map +1 -0
  88. package/dist/src/serverTestHelpers.js +88 -0
  89. package/dist/src/serverTestHelpers.js.map +1 -0
  90. package/dist/src/token.d.ts +4 -0
  91. package/dist/src/token.d.ts.map +1 -0
  92. package/dist/src/token.js +36 -0
  93. package/dist/src/token.js.map +1 -0
  94. package/dist/src/types.d.ts +60 -0
  95. package/dist/src/types.d.ts.map +1 -0
  96. package/dist/src/types.js +10 -0
  97. package/dist/src/types.js.map +1 -0
  98. package/dist/token.d.ts +4 -0
  99. package/dist/token.d.ts.map +1 -0
  100. package/dist/token.js +36 -0
  101. package/dist/token.js.map +1 -0
  102. package/dist/tsconfig.tsbuildinfo +1 -0
  103. package/dist/types.d.ts +60 -0
  104. package/dist/types.d.ts.map +1 -0
  105. package/dist/types.js +10 -0
  106. package/dist/types.js.map +1 -0
  107. package/package.json +44 -0
@@ -0,0 +1,51 @@
1
+ import getRawBody from "raw-body";
2
+ import contentType from "content-type";
3
+ import { isJSONRPCRequest } from "@modelcontextprotocol/sdk/types.js";
4
+ import { parseMcpMessages } from "@longrun/atxp-common";
5
+ // Useful reference for dealing with low-level http requests:
6
+ // https://github.com/modelcontextprotocol/typescript-sdk/blob/c6ac083b1b37b222b5bfba5563822daa5d03372e/src/server/streamableHttp.ts#L375
7
+ // Using the same value as MCP SDK
8
+ const MAXIMUM_MESSAGE_SIZE = "4mb";
9
+ export async function parseMcpRequests(config, requestUrl, req, parsedBody) {
10
+ if (!req.method) {
11
+ return [];
12
+ }
13
+ if (req.method.toLowerCase() !== 'post') {
14
+ return [];
15
+ }
16
+ // The middleware has to be mounted at the root to serve the protected resource metadata,
17
+ // but the actual MCP server it's controlling is specified by the mountPath.
18
+ const path = requestUrl.pathname.replace(/\/$/, '');
19
+ const mountPath = config.mountPath.replace(/\/$/, '');
20
+ if (path !== mountPath && path !== `${mountPath}/message`) {
21
+ config.logger.debug(`Request path (${path}) does not match the mountPath (${mountPath}), skipping MCP middleware`);
22
+ return [];
23
+ }
24
+ parsedBody = parsedBody ?? await parseBody(req, config.logger);
25
+ const messages = await parseMcpMessages(parsedBody, config.logger);
26
+ const requests = messages.filter(msg => isJSONRPCRequest(msg));
27
+ if (requests.length !== messages.length) {
28
+ config.logger.debug(`Dropped ${messages.length - requests.length} MCP messages that were not MCP requests`);
29
+ }
30
+ return requests;
31
+ }
32
+ export async function parseBody(req, logger) {
33
+ try {
34
+ const ct = req.headers["content-type"];
35
+ let encoding = "utf-8";
36
+ if (ct) {
37
+ const parsedCt = contentType.parse(ct);
38
+ encoding = parsedCt.parameters.charset ?? "utf-8";
39
+ }
40
+ const body = await getRawBody(req, {
41
+ limit: MAXIMUM_MESSAGE_SIZE,
42
+ encoding,
43
+ });
44
+ return JSON.parse(body.toString());
45
+ }
46
+ catch (error) {
47
+ logger.error(error.message);
48
+ return undefined;
49
+ }
50
+ }
51
+ //# sourceMappingURL=http.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/http.ts"],"names":[],"mappings":"AACA,OAAO,UAAU,MAAM,UAAU,CAAC;AAClC,OAAO,WAAW,MAAM,cAAc,CAAC;AACvC,OAAO,EAAkB,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAEtF,OAAO,EAAE,gBAAgB,EAAU,MAAM,sBAAsB,CAAC;AAEhE,6DAA6D;AAC7D,yIAAyI;AAEzI,kCAAkC;AAClC,MAAM,oBAAoB,GAAG,KAAK,CAAC;AAEnC,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,MAAkB,EAAE,UAAe,EAAE,GAAoB,EAAE,UAAoB;IACpH,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC;QAChB,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,IAAI,GAAG,CAAC,MAAM,CAAC,WAAW,EAAE,KAAK,MAAM,EAAE,CAAC;QACxC,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,yFAAyF;IACzF,4EAA4E;IAC5E,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACpD,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACtD,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,GAAG,SAAS,UAAU,EAAE,CAAC;QAC1D,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,iBAAiB,IAAI,mCAAmC,SAAS,4BAA4B,CAAC,CAAC;QACnH,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,UAAU,GAAG,UAAU,IAAI,MAAM,SAAS,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IAC/D,MAAM,QAAQ,GAAG,MAAM,gBAAgB,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IAEnE,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC;IAC/D,IAAI,QAAQ,CAAC,MAAM,KAAK,QAAQ,CAAC,MAAM,EAAE,CAAC;QACxC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,QAAQ,CAAC,MAAM,GAAG,QAAQ,CAAC,MAAM,0CAA0C,CAAC,CAAC;IAC9G,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,GAAoB,EAAE,MAAc;IAClE,IAAI,CAAC;QACH,MAAM,EAAE,GAAG,GAAG,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;QAEvC,IAAI,QAAQ,GAAG,OAAO,CAAC;QACvB,IAAI,EAAE,EAAE,CAAC;YACP,MAAM,QAAQ,GAAG,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YACvC,QAAQ,GAAG,QAAQ,CAAC,UAAU,CAAC,OAAO,IAAI,OAAO,CAAC;QACpD,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,GAAG,EAAE;YACjC,KAAK,EAAE,oBAAoB;YAC3B,QAAQ;SACT,CAAC,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;IACrC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAE,KAAe,CAAC,OAAO,CAAC,CAAC;QACvC,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC"}
@@ -0,0 +1,5 @@
1
+ export * from './atxpServer.js';
2
+ export * from './types.js';
3
+ export * from './atxpContext.js';
4
+ export * from './requirePayment.js';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC;AAC3B,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC"}
@@ -0,0 +1,5 @@
1
+ export * from './atxpServer.js';
2
+ export * from './types.js';
3
+ export * from './atxpContext.js';
4
+ export * from './requirePayment.js';
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC;AAC3B,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { ServerResponse } from "http";
2
+ import { TokenCheck } from "./types.js";
3
+ export declare function sendOAuthChallenge(res: ServerResponse, tokenCheck: TokenCheck): boolean;
4
+ //# sourceMappingURL=oAuthChallenge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oAuthChallenge.d.ts","sourceRoot":"","sources":["../../src/oAuthChallenge.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,MAAM,CAAC;AACtC,OAAO,EAAE,UAAU,EAAgB,MAAM,YAAY,CAAC;AAGtD,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,cAAc,EAAE,UAAU,EAAE,UAAU,GAAG,OAAO,CAsCvF"}
@@ -0,0 +1,39 @@
1
+ import { TokenProblem } from "./types.js";
2
+ import { assertNever } from "@longrun/atxp-common";
3
+ export function sendOAuthChallenge(res, tokenCheck) {
4
+ if (tokenCheck.passes) {
5
+ return false;
6
+ }
7
+ let status = 401;
8
+ let body = {};
9
+ // https://datatracker.ietf.org/doc/html/rfc6750#section-3.1
10
+ switch (tokenCheck.problem) {
11
+ case TokenProblem.NO_TOKEN:
12
+ break;
13
+ case TokenProblem.NON_BEARER_AUTH_HEADER:
14
+ status = 400;
15
+ body = { error: 'invalid_request', error_description: 'Authorization header did not include a Bearer token' };
16
+ break;
17
+ case TokenProblem.INVALID_TOKEN:
18
+ body = { error: 'invalid_token', error_description: 'Token is not active' };
19
+ break;
20
+ case TokenProblem.INVALID_AUDIENCE:
21
+ body = { error: 'invalid_token', error_description: 'Token is does not match the expected audience' };
22
+ break;
23
+ case TokenProblem.NON_SUFFICIENT_FUNDS:
24
+ status = 403;
25
+ body = { error: 'insufficient_scope', error_description: 'Non sufficient funds' };
26
+ break;
27
+ case TokenProblem.INTROSPECT_ERROR:
28
+ status = 502;
29
+ body = { error: 'server_error', error_description: 'An internal server error occurred' };
30
+ break;
31
+ default:
32
+ assertNever(tokenCheck.problem);
33
+ }
34
+ res.setHeader('WWW-Authenticate', `Bearer resource_metadata="${tokenCheck.resourceMetadataUrl}"`);
35
+ res.writeHead(status);
36
+ res.end(JSON.stringify(body));
37
+ return true;
38
+ }
39
+ //# sourceMappingURL=oAuthChallenge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oAuthChallenge.js","sourceRoot":"","sources":["../../src/oAuthChallenge.ts"],"names":[],"mappings":"AACA,OAAO,EAAc,YAAY,EAAE,MAAM,YAAY,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAEnD,MAAM,UAAU,kBAAkB,CAAC,GAAmB,EAAE,UAAsB;IAC5E,IAAI,UAAU,CAAC,MAAM,EAAE,CAAC;QACtB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,MAAM,GAAG,GAAG,CAAC;IACjB,IAAI,IAAI,GAAkE,EAAE,CAAC;IAC7E,4DAA4D;IAC5D,QAAQ,UAAU,CAAC,OAAO,EAAE,CAAC;QAC3B,KAAK,YAAY,CAAC,QAAQ;YACxB,MAAM;QACR,KAAK,YAAY,CAAC,sBAAsB;YACtC,MAAM,GAAG,GAAG,CAAC;YACb,IAAI,GAAG,EAAE,KAAK,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,qDAAqD,EAAE,CAAC;YAC9G,MAAM;QACR,KAAK,YAAY,CAAC,aAAa;YAC7B,IAAI,GAAG,EAAE,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,CAAC;YAC5E,MAAM;QACR,KAAK,YAAY,CAAC,gBAAgB;YAChC,IAAI,GAAG,EAAE,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAE,+CAA+C,EAAE,CAAC;YACtG,MAAM;QACR,KAAK,YAAY,CAAC,oBAAoB;YACpC,MAAM,GAAG,GAAG,CAAC;YACb,IAAI,GAAG,EAAE,KAAK,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,CAAC;YAClF,MAAM;QACR,KAAK,YAAY,CAAC,gBAAgB;YAChC,MAAM,GAAG,GAAG,CAAC;YACb,IAAI,GAAG,EAAE,KAAK,EAAE,cAAc,EAAE,iBAAiB,EAAE,mCAAmC,EAAE,CAAC;YACzF,MAAM;QACR;YACE,WAAW,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;IACpC,CAAC;IAED,GAAG,CAAC,SAAS,CAAC,kBAAkB,EAAE,6BAA6B,UAAU,CAAC,mBAAmB,GAAG,CAAC,CAAC;IAClG,GAAG,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IACtB,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;IAE9B,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { ATXPConfig } from "./types.js";
2
+ import * as oauth from 'oauth4webapi';
3
+ import { ServerResponse } from "http";
4
+ export declare function sendOAuthMetadata(res: ServerResponse, metadata: oauth.AuthorizationServer | null): boolean;
5
+ export declare function getOAuthMetadata(config: ATXPConfig, requestUrl: URL): Promise<oauth.AuthorizationServer | null>;
6
+ //# sourceMappingURL=oAuthMetadata.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oAuthMetadata.d.ts","sourceRoot":"","sources":["../../src/oAuthMetadata.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,cAAc,EAAE,MAAM,MAAM,CAAC;AAGtC,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,cAAc,EAAE,QAAQ,EAAE,KAAK,CAAC,mBAAmB,GAAG,IAAI,GAAG,OAAO,CAQ1G;AAED,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,GAAG,GAAG,OAAO,CAAC,KAAK,CAAC,mBAAmB,GAAG,IAAI,CAAC,CAyBrH"}
@@ -0,0 +1,41 @@
1
+ import { getPath } from "./getResource.js";
2
+ export function sendOAuthMetadata(res, metadata) {
3
+ if (!metadata) {
4
+ return false;
5
+ }
6
+ res.setHeader('Content-Type', 'application/json');
7
+ res.writeHead(200);
8
+ res.end(JSON.stringify(metadata));
9
+ return true;
10
+ }
11
+ export async function getOAuthMetadata(config, requestUrl) {
12
+ if (isOAuthMetadataRequest(config, requestUrl)) {
13
+ try {
14
+ const authServer = await config.oAuthClient.authorizationServerFromUrl(new URL(config.server));
15
+ return {
16
+ issuer: config.server,
17
+ authorization_endpoint: authServer.authorization_endpoint,
18
+ response_types_supported: authServer.response_types_supported,
19
+ grant_types_supported: authServer.grant_types_supported,
20
+ token_endpoint: authServer.token_endpoint,
21
+ token_endpoint_auth_methods_supported: authServer.token_endpoint_auth_methods_supported,
22
+ registration_endpoint: authServer.registration_endpoint,
23
+ revocation_endpoint: authServer.revocation_endpoint,
24
+ introspection_endpoint: authServer.introspection_endpoint,
25
+ introspection_endpoint_auth_methods_supported: authServer.introspection_endpoint_auth_methods_supported,
26
+ code_challenge_methods_supported: authServer.code_challenge_methods_supported,
27
+ scopes_supported: authServer.scopes_supported
28
+ };
29
+ }
30
+ catch (error) {
31
+ config.logger.error(`Error fetching authorization server configuration from ${config.server}: ${error}`);
32
+ throw error;
33
+ }
34
+ }
35
+ return null;
36
+ }
37
+ function isOAuthMetadataRequest(config, requestUrl) {
38
+ const path = getPath(requestUrl).replace(/\/$/, '');
39
+ return path === '/.well-known/oauth-authorization-server';
40
+ }
41
+ //# sourceMappingURL=oAuthMetadata.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oAuthMetadata.js","sourceRoot":"","sources":["../../src/oAuthMetadata.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAE3C,MAAM,UAAU,iBAAiB,CAAC,GAAmB,EAAE,QAA0C;IAC/F,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,KAAK,CAAC;IACf,CAAC;IACD,GAAG,CAAC,SAAS,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAC;IAClD,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;IACnB,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC;IAClC,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,MAAkB,EAAE,UAAe;IACxE,IAAI,sBAAsB,CAAC,MAAM,EAAE,UAAU,CAAC,EAAE,CAAC;QAC/C,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,0BAA0B,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;YAE/F,OAAO;gBACL,MAAM,EAAE,MAAM,CAAC,MAAM;gBACrB,sBAAsB,EAAE,UAAU,CAAC,sBAAsB;gBACzD,wBAAwB,EAAE,UAAU,CAAC,wBAAwB;gBAC7D,qBAAqB,EAAE,UAAU,CAAC,qBAAqB;gBACvD,cAAc,EAAE,UAAU,CAAC,cAAc;gBACzC,qCAAqC,EAAE,UAAU,CAAC,qCAAqC;gBACvF,qBAAqB,EAAE,UAAU,CAAC,qBAAqB;gBACvD,mBAAmB,EAAE,UAAU,CAAC,mBAAmB;gBACnD,sBAAsB,EAAE,UAAU,CAAC,sBAAsB;gBACzD,6CAA6C,EAAE,UAAU,CAAC,6CAA6C;gBACvG,gCAAgC,EAAE,UAAU,CAAC,gCAAgC;gBAC7E,gBAAgB,EAAE,UAAU,CAAC,gBAAgB;aAC9C,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,0DAA0D,MAAM,CAAC,MAAM,KAAK,KAAK,EAAE,CAAC,CAAC;YACzG,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,sBAAsB,CAAC,MAAkB,EAAE,UAAe;IACjE,MAAM,IAAI,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACpD,OAAO,IAAI,KAAK,yCAAyC,CAAC;AAC5D,CAAC"}
@@ -0,0 +1,68 @@
1
+ import { PaymentServer, ChargeResponse } from "./types.js";
2
+ import { Network, Currency, AuthorizationServerUrl, FetchLike, Logger } from "@longrun/atxp-common";
3
+ import BigNumber from "bignumber.js";
4
+ /**
5
+ * ATXP Payment Server implementation
6
+ *
7
+ * This class handles payment operations with the ATXP authorization server.
8
+ *
9
+ * **Required Environment Variable:**
10
+ * - `ATXP_AUTH_CLIENT_TOKEN`: Authentication token for the ATXP authorization server.
11
+ * This token is used to authenticate API calls to the ATXP server for payment operations.
12
+ * Must be set when using this class, otherwise an error will be thrown.
13
+ *
14
+ * @example
15
+ * ```typescript
16
+ * // Ensure ATXP_AUTH_CLIENT_TOKEN is set in your environment
17
+ * const paymentServer = new ATXPPaymentServer(
18
+ * 'https://auth.atxp.ai',
19
+ * oAuthDb,
20
+ * logger
21
+ * );
22
+ * ```
23
+ */
24
+ export declare class ATXPPaymentServer implements PaymentServer {
25
+ private readonly server;
26
+ private readonly authCredentials;
27
+ private readonly logger;
28
+ private readonly fetchFn;
29
+ constructor(server: AuthorizationServerUrl, authCredentials: string, logger: Logger, fetchFn?: FetchLike);
30
+ charge: ({ source, destination, network, currency, amount }: {
31
+ source: string;
32
+ destination: string;
33
+ network: Network;
34
+ currency: Currency;
35
+ amount: BigNumber;
36
+ }) => Promise<ChargeResponse>;
37
+ createPaymentRequest: ({ source, destination, network, currency, amount }: {
38
+ source: string;
39
+ destination: string;
40
+ network: Network;
41
+ currency: Currency;
42
+ amount: BigNumber;
43
+ }) => Promise<string>;
44
+ /**
45
+ * Makes authenticated requests to the ATXP authorization server
46
+ *
47
+ * This method automatically includes the `ATXP_AUTH_CLIENT_TOKEN` from environment variables
48
+ * in the Authorization header for all requests.
49
+ *
50
+ * @param method - HTTP method ('GET' or 'POST')
51
+ * @param path - API endpoint path
52
+ * @param body - Request body (for POST requests)
53
+ * @returns Promise<Response> - The HTTP response from the server
54
+ * @throws {Error} When `ATXP_AUTH_CLIENT_TOKEN` environment variable is not set
55
+ *
56
+ * @example
57
+ * ```typescript
58
+ * // Ensure ATXP_AUTH_CLIENT_TOKEN is set in your environment
59
+ * const response = await paymentServer.makeRequest('POST', '/charge', {
60
+ * source: 'user123',
61
+ * destination: 'merchant456',
62
+ * amount: new BigNumber('0.01')
63
+ * });
64
+ * ```
65
+ */
66
+ protected makeRequest: (method: "GET" | "POST", path: string, body: unknown) => Promise<Response>;
67
+ }
68
+ //# sourceMappingURL=paymentServer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paymentServer.d.ts","sourceRoot":"","sources":["../../src/paymentServer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC3D,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,sBAAsB,EAAE,SAAS,EAAE,MAAM,EAAsB,MAAM,sBAAsB,CAAC;AACxH,OAAO,SAAS,MAAM,cAAc,CAAC;AAErC;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,iBAAkB,YAAW,aAAa;IAEnD,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAHP,MAAM,EAAE,sBAAsB,EAC9B,eAAe,EAAE,MAAM,EACvB,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,SAAiB;IAM7C,MAAM,GAAS,oDACb;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAC;QAAC,QAAQ,EAAE,QAAQ,CAAC;QAAC,MAAM,EAAE,SAAS,CAAA;KAAC,KAAG,OAAO,CAAC,cAAc,CAAC,CAczH;IAED,oBAAoB,GAAS,oDAC3B;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAC;QAAC,QAAQ,EAAE,QAAQ,CAAC;QAAC,MAAM,EAAE,SAAS,CAAA;KAAC,KAAG,OAAO,CAAC,MAAM,CAAC,CAajH;IAED;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,SAAS,CAAC,WAAW,GAAS,QAAQ,KAAK,GAAG,MAAM,EAAE,MAAM,MAAM,EAAE,MAAM,OAAO,KAAG,OAAO,CAAC,QAAQ,CAAC,CAWpG;CACF"}
@@ -0,0 +1,97 @@
1
+ /**
2
+ * ATXP Payment Server implementation
3
+ *
4
+ * This class handles payment operations with the ATXP authorization server.
5
+ *
6
+ * **Required Environment Variable:**
7
+ * - `ATXP_AUTH_CLIENT_TOKEN`: Authentication token for the ATXP authorization server.
8
+ * This token is used to authenticate API calls to the ATXP server for payment operations.
9
+ * Must be set when using this class, otherwise an error will be thrown.
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * // Ensure ATXP_AUTH_CLIENT_TOKEN is set in your environment
14
+ * const paymentServer = new ATXPPaymentServer(
15
+ * 'https://auth.atxp.ai',
16
+ * oAuthDb,
17
+ * logger
18
+ * );
19
+ * ```
20
+ */
21
+ export class ATXPPaymentServer {
22
+ constructor(server, authCredentials, logger, fetchFn = fetch) {
23
+ this.server = server;
24
+ this.authCredentials = authCredentials;
25
+ this.logger = logger;
26
+ this.fetchFn = fetchFn;
27
+ this.charge = async ({ source, destination, network, currency, amount }) => {
28
+ const body = { source, destination, network, currency, amount };
29
+ const chargeResponse = await this.makeRequest('POST', '/charge', body);
30
+ const json = await chargeResponse.json();
31
+ if (chargeResponse.status === 200) {
32
+ return { success: true, requiredPayment: null };
33
+ }
34
+ else if (chargeResponse.status === 402) {
35
+ return { success: false, requiredPayment: json };
36
+ }
37
+ else {
38
+ const msg = `Unexpected status code ${chargeResponse.status} from payment server POST /charge endpoint`;
39
+ this.logger.warn(msg);
40
+ this.logger.debug(`Response body: ${JSON.stringify(json)}`);
41
+ throw new Error(msg);
42
+ }
43
+ };
44
+ this.createPaymentRequest = async ({ source, destination, network, currency, amount }) => {
45
+ const body = { source, destination, network, currency, amount };
46
+ const response = await this.makeRequest('POST', '/payment-request', body);
47
+ const json = await response.json();
48
+ if (response.status !== 200) {
49
+ this.logger.warn(`POST /payment-request responded with unexpected HTTP status ${response.status}`);
50
+ this.logger.debug(`Response body: ${JSON.stringify(json)}`);
51
+ throw new Error(`POST /payment-request responded with unexpected HTTP status ${response.status}`);
52
+ }
53
+ if (!json.id) {
54
+ throw new Error(`POST /payment-request response did not contain an id`);
55
+ }
56
+ return json.id;
57
+ };
58
+ /**
59
+ * Makes authenticated requests to the ATXP authorization server
60
+ *
61
+ * This method automatically includes the `ATXP_AUTH_CLIENT_TOKEN` from environment variables
62
+ * in the Authorization header for all requests.
63
+ *
64
+ * @param method - HTTP method ('GET' or 'POST')
65
+ * @param path - API endpoint path
66
+ * @param body - Request body (for POST requests)
67
+ * @returns Promise<Response> - The HTTP response from the server
68
+ * @throws {Error} When `ATXP_AUTH_CLIENT_TOKEN` environment variable is not set
69
+ *
70
+ * @example
71
+ * ```typescript
72
+ * // Ensure ATXP_AUTH_CLIENT_TOKEN is set in your environment
73
+ * const response = await paymentServer.makeRequest('POST', '/charge', {
74
+ * source: 'user123',
75
+ * destination: 'merchant456',
76
+ * amount: new BigNumber('0.01')
77
+ * });
78
+ * ```
79
+ */
80
+ this.makeRequest = async (method, path, body) => {
81
+ const url = new URL(path, this.server);
82
+ const response = await this.fetchFn(url, {
83
+ method,
84
+ headers: {
85
+ 'Authorization': `Bearer ${this.authCredentials}`,
86
+ 'Content-Type': 'application/json'
87
+ },
88
+ body: JSON.stringify(body)
89
+ });
90
+ return response;
91
+ };
92
+ if (!authCredentials || authCredentials.trim() === '') {
93
+ throw new Error('Auth credentials are required');
94
+ }
95
+ }
96
+ }
97
+ //# sourceMappingURL=paymentServer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paymentServer.js","sourceRoot":"","sources":["../../src/paymentServer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import { ATXPConfig, ProtectedResourceMetadata } from "./types.js";
2
+ import { ServerResponse } from "http";
3
+ export declare function sendProtectedResourceMetadata(res: ServerResponse, metadata: ProtectedResourceMetadata | null): boolean;
4
+ export declare function getProtectedResourceMetadata(config: ATXPConfig, requestUrl: URL): ProtectedResourceMetadata | null;
5
+ //# sourceMappingURL=protectedResourceMetadata.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protectedResourceMetadata.d.ts","sourceRoot":"","sources":["../../src/protectedResourceMetadata.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAC;AACnE,OAAO,EAAE,cAAc,EAAE,MAAM,MAAM,CAAC;AAGtC,wBAAgB,6BAA6B,CAAC,GAAG,EAAE,cAAc,EAAE,QAAQ,EAAE,yBAAyB,GAAG,IAAI,GAAG,OAAO,CAQtH;AAED,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,GAAG,GAAG,yBAAyB,GAAG,IAAI,CAYlH"}
@@ -0,0 +1,40 @@
1
+ import { getPath, getResource } from "./getResource.js";
2
+ export function sendProtectedResourceMetadata(res, metadata) {
3
+ if (!metadata) {
4
+ return false;
5
+ }
6
+ res.setHeader('Content-Type', 'application/json');
7
+ res.writeHead(200);
8
+ res.end(JSON.stringify(metadata));
9
+ return true;
10
+ }
11
+ export function getProtectedResourceMetadata(config, requestUrl) {
12
+ if (isProtectedResourceMetadataRequest(config, requestUrl)) {
13
+ const resource = getResource(config, requestUrl);
14
+ return {
15
+ resource,
16
+ resource_name: config.payeeName || resource.toString(),
17
+ authorization_servers: [config.server],
18
+ bearer_methods_supported: ['header'],
19
+ scopes_supported: ['read', 'write'],
20
+ };
21
+ }
22
+ return null;
23
+ }
24
+ function isProtectedResourceMetadataRequest(config, requestUrl) {
25
+ const path = getPath(requestUrl);
26
+ if (!path.startsWith('/.well-known/oauth-protected-resource')) {
27
+ return false;
28
+ }
29
+ const resource = getResource(config, requestUrl);
30
+ const resourcePath = getPath(resource);
31
+ const mountPath = config.mountPath.replace(/\/$/, '');
32
+ if (resourcePath === mountPath) {
33
+ return true;
34
+ }
35
+ if (resourcePath === `${mountPath}/message`) {
36
+ return true;
37
+ }
38
+ return false;
39
+ }
40
+ //# sourceMappingURL=protectedResourceMetadata.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protectedResourceMetadata.js","sourceRoot":"","sources":["../../src/protectedResourceMetadata.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAExD,MAAM,UAAU,6BAA6B,CAAC,GAAmB,EAAE,QAA0C;IAC3G,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,KAAK,CAAC;IACf,CAAC;IACD,GAAG,CAAC,SAAS,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAC;IAClD,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;IACnB,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC;IAClC,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,4BAA4B,CAAC,MAAkB,EAAE,UAAe;IAC9E,IAAI,kCAAkC,CAAC,MAAM,EAAE,UAAU,CAAC,EAAE,CAAC;QAC3D,MAAM,QAAQ,GAAG,WAAW,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;QACjD,OAAO;YACL,QAAQ;YACR,aAAa,EAAE,MAAM,CAAC,SAAS,IAAI,QAAQ,CAAC,QAAQ,EAAE;YACtD,qBAAqB,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC;YACtC,wBAAwB,EAAE,CAAC,QAAQ,CAAC;YACpC,gBAAgB,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC;SACpC,CAAC;IACJ,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,kCAAkC,CAAC,MAAkB,EAAE,UAAe;IAC7E,MAAM,IAAI,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IACjC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,uCAAuC,CAAC,EAAE,CAAC;QAC9D,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,QAAQ,GAAG,WAAW,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACjD,MAAM,YAAY,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IACvC,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACtD,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;QAC/B,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,YAAY,KAAK,GAAG,SAAS,UAAU,EAAE,CAAC;QAC5C,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { RequirePaymentConfig } from "@longrun/atxp-common";
2
+ export declare function requirePayment(paymentConfig: RequirePaymentConfig): Promise<void>;
3
+ //# sourceMappingURL=requirePayment.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"requirePayment.d.ts","sourceRoot":"","sources":["../../src/requirePayment.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAwB,MAAM,sBAAsB,CAAC;AAGlF,wBAAsB,cAAc,CAAC,aAAa,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAmCvF"}
@@ -0,0 +1,35 @@
1
+ import { paymentRequiredError } from "@longrun/atxp-common";
2
+ import { getATXPConfig, atxpAccountId } from "./atxpContext.js";
3
+ export async function requirePayment(paymentConfig) {
4
+ const config = getATXPConfig();
5
+ if (!config) {
6
+ throw new Error('No config found');
7
+ }
8
+ const user = atxpAccountId();
9
+ if (!user) {
10
+ config.logger.error('No user found');
11
+ throw new Error('No user found');
12
+ }
13
+ const charge = {
14
+ amount: paymentConfig.price,
15
+ currency: config.currency,
16
+ network: config.network,
17
+ destination: config.destination,
18
+ source: user
19
+ };
20
+ config.logger.debug(`Charging amount ${charge.amount}, destination ${charge.destination}, source ${charge.source}`);
21
+ const chargeResponse = await config.paymentServer.charge(charge);
22
+ if (chargeResponse.success) {
23
+ config.logger.info(`Charged ${charge.amount} for source ${charge.source}`);
24
+ return;
25
+ }
26
+ const existingPaymentId = await paymentConfig.getExistingPaymentId?.();
27
+ if (existingPaymentId) {
28
+ config.logger.info(`Found existing payment ID ${existingPaymentId}`);
29
+ throw paymentRequiredError(config.server, existingPaymentId);
30
+ }
31
+ const paymentId = await config.paymentServer.createPaymentRequest(charge);
32
+ config.logger.info(`Created payment request ${paymentId}`);
33
+ throw paymentRequiredError(config.server, paymentId);
34
+ }
35
+ //# sourceMappingURL=requirePayment.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"requirePayment.js","sourceRoot":"","sources":["../../src/requirePayment.ts"],"names":[],"mappings":"AAAA,OAAO,EAAwB,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAClF,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEhE,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,aAAmC;IACtE,MAAM,MAAM,GAAG,aAAa,EAAE,CAAC;IAC/B,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;IACrC,CAAC;IACD,MAAM,IAAI,GAAG,aAAa,EAAE,CAAC;IAC7B,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;QACrC,MAAM,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC;IACnC,CAAC;IAED,MAAM,MAAM,GAAG;QACb,MAAM,EAAE,aAAa,CAAC,KAAK;QAC3B,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,MAAM,EAAE,IAAI;KACb,CAAC;IAEF,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,mBAAmB,MAAM,CAAC,MAAM,iBAAiB,MAAM,CAAC,WAAW,YAAY,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;IACpH,MAAM,cAAc,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACjE,IAAI,cAAc,CAAC,OAAO,EAAE,CAAC;QAC3B,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,MAAM,CAAC,MAAM,eAAe,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;QAC3E,OAAO;IACT,CAAC;IAED,MAAM,iBAAiB,GAAG,MAAM,aAAa,CAAC,oBAAoB,EAAE,EAAE,CAAC;IACvE,IAAI,iBAAiB,EAAE,CAAC;QACtB,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,6BAA6B,iBAAiB,EAAE,CAAC,CAAC;QACrE,MAAM,oBAAoB,CAAC,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAA;IAC9D,CAAC;IAED,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC;IAC1E,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,2BAA2B,SAAS,EAAE,CAAC,CAAC;IAC3D,MAAM,oBAAoB,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;AACvD,CAAC"}
@@ -0,0 +1,55 @@
1
+ import { IncomingHttpHeaders, IncomingMessage, ServerResponse } from 'http';
2
+ import { JSONRPCRequest } from '@modelcontextprotocol/sdk/types.js';
3
+ import { OAuthResourceClient, TokenData, Logger, Currency, Network } from '@longrun/atxp-common';
4
+ import { Charge, ATXPConfig, TokenCheck, TokenProblem, McpMethod, McpName, PaymentServer } from './types.js';
5
+ import * as oauth from 'oauth4webapi';
6
+ export declare const DESTINATION = "testDestination";
7
+ export declare const SOURCE = "testSource";
8
+ export declare function charge({ amount, currency, network, destination, source }?: {
9
+ amount?: BigNumber;
10
+ currency?: Currency;
11
+ network?: Network;
12
+ destination?: string;
13
+ source?: string;
14
+ }): Charge;
15
+ export declare const oneCentCharge: Charge;
16
+ export declare const zeroCharge: Charge;
17
+ export declare function logger(): Logger;
18
+ export declare function config(args?: Partial<ATXPConfig>): ATXPConfig;
19
+ export declare function paymentServer({ charge, createPaymentRequest }?: {
20
+ charge?: import("vitest").Mock<(...args: any[]) => any> | undefined;
21
+ createPaymentRequest?: import("vitest").Mock<(...args: any[]) => any> | undefined;
22
+ }): PaymentServer;
23
+ export declare function mcpRequest({ method, params, id }?: {
24
+ method?: McpMethod;
25
+ params?: any;
26
+ id?: string;
27
+ }): JSONRPCRequest;
28
+ export declare function mcpToolRequest({ toolName, args, }?: {
29
+ toolName?: McpName;
30
+ args?: any;
31
+ }): JSONRPCRequest;
32
+ export declare function incomingMessage({ body, method, url, headers }?: {
33
+ body?: any;
34
+ method?: 'POST' | 'GET' | 'PUT' | 'DELETE' | 'PATCH' | 'OPTIONS';
35
+ url?: string;
36
+ headers?: IncomingHttpHeaders;
37
+ }): IncomingMessage;
38
+ export declare function incomingToolMessage({ authHeader, url, }?: {
39
+ authHeader?: string;
40
+ url?: string;
41
+ }): IncomingMessage;
42
+ export declare function oAuthClient({ introspectResult, authorizationServer }?: {
43
+ introspectResult?: TokenData;
44
+ authorizationServer?: oauth.AuthorizationServer;
45
+ }): OAuthResourceClient;
46
+ export declare function tokenData({ active, sub, scope, aud }?: Partial<TokenData>): TokenData;
47
+ export declare function tokenCheck({ data, token, passes, problem, resourceMetadataUrl }?: {
48
+ data?: TokenData;
49
+ token?: string | null;
50
+ passes?: boolean;
51
+ problem?: TokenProblem;
52
+ resourceMetadataUrl?: string;
53
+ }): TokenCheck;
54
+ export declare function serverResponse(): ServerResponse;
55
+ //# sourceMappingURL=serverTestHelpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serverTestHelpers.d.ts","sourceRoot":"","sources":["../../src/serverTestHelpers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,88 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any, no-console */
2
+ import { Readable } from 'stream';
3
+ import { vi } from 'vitest';
4
+ import { TokenProblem } from './types.js';
5
+ import { buildServerConfig } from './atxpServer.js';
6
+ import { BigNumber } from 'bignumber.js';
7
+ export const DESTINATION = 'testDestination';
8
+ export const SOURCE = 'testSource';
9
+ export function charge({ amount = BigNumber(0.01), currency = 'USDC', network = 'solana', destination = DESTINATION, source = SOURCE } = {}) {
10
+ return { amount, currency, network, destination, source };
11
+ }
12
+ export const oneCentCharge = charge({ amount: BigNumber(0.01) });
13
+ export const zeroCharge = charge({ amount: BigNumber(0) });
14
+ export function logger() {
15
+ return {
16
+ debug: vi.fn().mockImplementation((msg) => { console.debug(msg); }),
17
+ info: vi.fn().mockImplementation((msg) => { console.info(msg); }),
18
+ warn: vi.fn().mockImplementation((msg) => { console.warn(msg); }),
19
+ error: vi.fn().mockImplementation((msg) => { console.error(msg); }),
20
+ };
21
+ }
22
+ export function config(args = {}) {
23
+ return buildServerConfig({
24
+ ...args,
25
+ destination: args.destination ?? DESTINATION,
26
+ atxpAuthClientToken: args.atxpAuthClientToken ?? 'test-auth-token'
27
+ });
28
+ }
29
+ export function paymentServer({ charge = vi.fn().mockResolvedValue({ success: true, requiredPaymentId: null }), createPaymentRequest = vi.fn().mockResolvedValue('test-payment-request-id') } = {}) {
30
+ return {
31
+ charge,
32
+ createPaymentRequest,
33
+ };
34
+ }
35
+ export function mcpRequest({ method = 'tools/call', params = {}, id = 'call-1' } = {}) {
36
+ return { jsonrpc: "2.0", method, params, id };
37
+ }
38
+ export function mcpToolRequest({ toolName = 'testTool', args = { paramOne: 'test' }, } = {}) {
39
+ return mcpRequest({ method: 'tools/call', params: { name: toolName, arguments: args } });
40
+ }
41
+ export function incomingMessage({ body = {}, method = 'POST', url = '/', headers = { 'content-type': 'application/json' } } = {}) {
42
+ const bodyString = JSON.stringify(body);
43
+ const stream = new Readable({
44
+ read() {
45
+ this.push(bodyString);
46
+ this.push(null);
47
+ }
48
+ });
49
+ stream.method = method;
50
+ stream.url = url;
51
+ stream.headers = headers;
52
+ return stream;
53
+ }
54
+ export function incomingToolMessage({ authHeader = undefined, url = '/', } = {}) {
55
+ return incomingMessage({
56
+ body: mcpToolRequest({ toolName: 'testTool' }),
57
+ headers: { 'authorization': authHeader, 'content-type': 'application/json' },
58
+ url
59
+ });
60
+ }
61
+ export function oAuthClient({ introspectResult = tokenData(), authorizationServer = {
62
+ issuer: 'https://auth.atxp.ai',
63
+ } } = {}) {
64
+ return {
65
+ introspectToken: vi.fn().mockResolvedValue(introspectResult),
66
+ authorizationServerFromUrl: vi.fn().mockResolvedValue(authorizationServer)
67
+ };
68
+ }
69
+ export function tokenData({ active = true, sub = 'test-user', scope = 'tools:read', aud = 'https://example.com' } = {}) {
70
+ return { active, sub, scope, aud };
71
+ }
72
+ export function tokenCheck({ data = tokenData(), token = 'test-token', passes = true, problem = TokenProblem.NO_TOKEN, resourceMetadataUrl = 'https://example.com/.well-known/oauth-protected-resource' } = {}) {
73
+ if (passes) {
74
+ return { passes, token, data, };
75
+ }
76
+ else {
77
+ return { passes, token, data, problem, resourceMetadataUrl };
78
+ }
79
+ }
80
+ export function serverResponse() {
81
+ return {
82
+ getHeader: vi.fn(),
83
+ setHeader: vi.fn(),
84
+ writeHead: vi.fn(),
85
+ end: vi.fn(),
86
+ };
87
+ }
88
+ //# sourceMappingURL=serverTestHelpers.js.map