soajs.controller 4.3.22 → 4.3.23

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.
@@ -0,0 +1,157 @@
1
+ "use strict";
2
+
3
+ const assert = require('assert');
4
+ const request = require('request');
5
+ const helper = require("../../helper.js");
6
+ let Controller = helper.requireModule('./server/controller');
7
+ let localConfig = helper.requireModule('./config.js');
8
+
9
+ let mock = require('../UC2-http-methods/service-mock/index.js');
10
+
11
+ //NOTE: the mock service answers GET /mcp/tools on its maintenance port with tools for /myroute;
12
+ // the gateway custom registry has mcp.enabled
13
+ describe("Integration for Usecase 8 - MCP endpoint /soajs/mcp", function () {
14
+ let extKey = "3d90163cf9d6b3076ad26aa5ed58556348069258e5c6c941ee0f18448b570ad1c5c790e2d2a1989680c55f4904e2005ff5f8e71606e4aa641e67882f4210ebbc5460ff305dcb36e6ec2a2299cf0448ef60b9e38f41950ec251c1cf41f05f3ce9";
15
+ let ownerToken = "cfb209a91b23896820f510aadbf1f4284b512123";
16
+
17
+ let c = new Controller({
18
+ "serviceName": localConfig.serviceName,
19
+ "serviceVersion": localConfig.serviceVersion,
20
+ "serviceGroup": localConfig.serviceGroup,
21
+ "servicePort": localConfig.servicePort,
22
+ "maintenance": localConfig.maintenance
23
+ });
24
+ let registry = null;
25
+ let log = null;
26
+ let service = null;
27
+ let server = null;
28
+ let serverMaintenance = null;
29
+ let httpmethods = null;
30
+
31
+ function mcp(body, opts, cb) {
32
+ opts = opts || {};
33
+ let headers = {key: extKey};
34
+ if (opts.token !== false) {
35
+ headers.authorization = "Bearer " + (opts.token || ownerToken);
36
+ }
37
+ request({
38
+ "method": opts.method || "POST",
39
+ "uri": 'http://127.0.0.1:' + localConfig.servicePort + '/soajs/mcp',
40
+ "headers": headers,
41
+ "body": (typeof body === "string") ? body : JSON.stringify(body)
42
+ }, (error, response, text) => {
43
+ assert.ifError(error);
44
+ let json = null;
45
+ try {
46
+ json = text ? JSON.parse(text) : null;
47
+ } catch (e) {
48
+ json = text;
49
+ }
50
+ return cb(response.statusCode, json);
51
+ });
52
+ }
53
+
54
+ before((done) => {
55
+ mock.startServer(null, function (servers) {
56
+ httpmethods = servers;
57
+ });
58
+ c.init((_registry, _log, _service, _server, _serverMaintenance) => {
59
+ registry = _registry;
60
+ log = _log;
61
+ service = _service;
62
+ server = _server;
63
+ serverMaintenance = _serverMaintenance;
64
+ c.start(registry, log, service, server, serverMaintenance, () => {
65
+ setTimeout(function () {
66
+ done();
67
+ }, 5000);
68
+ });
69
+ });
70
+ });
71
+
72
+ it("initialize", function (done) {
73
+ mcp({jsonrpc: "2.0", id: 1, method: "initialize", params: {protocolVersion: "2025-06-18", capabilities: {}, clientInfo: {name: "test", version: "1"}}}, {}, (status, body) => {
74
+ assert.strictEqual(status, 200);
75
+ assert.strictEqual(body.id, 1);
76
+ assert.strictEqual(body.result.protocolVersion, "2025-06-18");
77
+ assert.deepStrictEqual(body.result.capabilities, {"tools": {"listChanged": false}});
78
+ assert.strictEqual(body.result.serverInfo.name, "soajs-gateway");
79
+ done();
80
+ });
81
+ });
82
+
83
+ it("notifications/initialized is accepted", function (done) {
84
+ mcp({jsonrpc: "2.0", method: "notifications/initialized"}, {}, (status, body) => {
85
+ assert.strictEqual(status, 202);
86
+ assert.strictEqual(body, null);
87
+ done();
88
+ });
89
+ });
90
+
91
+ it("tools/list has the tools of the services the caller may use", function (done) {
92
+ mcp({jsonrpc: "2.0", id: 2, method: "tools/list"}, {}, (status, body) => {
93
+ assert.strictEqual(status, 200);
94
+ let names = body.result.tools.map((t) => t.name);
95
+ assert.ok(names.indexOf("httpmethods_get_myroute") !== -1, JSON.stringify(names));
96
+ assert.ok(names.indexOf("httpmethods_post_myroute") !== -1);
97
+ assert.ok(names.indexOf("httpmethods_delete_myroute") !== -1);
98
+ let get = body.result.tools.find((t) => t.name === "httpmethods_get_myroute");
99
+ assert.deepStrictEqual(get.inputSchema, {"type": "object", "properties": {"name": {"type": "string"}}, "required": ["name"]});
100
+ assert.strictEqual(get.annotations.readOnlyHint, true);
101
+ done();
102
+ });
103
+ });
104
+
105
+ it("tools/call runs the api through the gateway", function (done) {
106
+ mcp({jsonrpc: "2.0", id: 3, method: "tools/call", params: {name: "httpmethods_get_myroute", arguments: {name: "ann"}}}, {}, (status, body) => {
107
+ assert.strictEqual(status, 200);
108
+ assert.strictEqual(body.result.isError, false, JSON.stringify(body));
109
+ assert.strictEqual(body.result.structuredContent.method, "GET");
110
+ assert.strictEqual(body.result.structuredContent.url, "/myroute?name=ann");
111
+ assert.strictEqual(body.result.structuredContent.firstname, "antoine");
112
+ mcp({jsonrpc: "2.0", id: 4, method: "tools/call", params: {name: "httpmethods_post_myroute", arguments: {title: "t"}}}, {}, (status, body) => {
113
+ assert.strictEqual(body.result.isError, false, JSON.stringify(body));
114
+ assert.strictEqual(body.result.structuredContent.method, "POST");
115
+ done();
116
+ });
117
+ });
118
+ });
119
+
120
+ it("tools/call of an unknown tool", function (done) {
121
+ mcp({jsonrpc: "2.0", id: 5, method: "tools/call", params: {name: "httpmethods_get_nope", arguments: {}}}, {}, (status, body) => {
122
+ assert.deepStrictEqual(body.error, {"code": -32602, "message": "Unknown tool: httpmethods_get_nope"});
123
+ done();
124
+ });
125
+ });
126
+
127
+ it("no signed-in user is refused, like /soajs/acl", function (done) {
128
+ mcp({jsonrpc: "2.0", id: 6, method: "tools/list"}, {token: false}, (status, body) => {
129
+ assert.strictEqual(body.result, false);
130
+ assert.ok(body.errors, JSON.stringify(body));
131
+ done();
132
+ });
133
+ });
134
+
135
+ it("GET is not allowed", function (done) {
136
+ mcp("", {method: "GET"}, (status, body) => {
137
+ assert.strictEqual(status, 405);
138
+ assert.strictEqual(body.error.code, -32600);
139
+ done();
140
+ });
141
+ });
142
+
143
+ it("a body that is not JSON", function (done) {
144
+ mcp("{nope", {}, (status, body) => {
145
+ assert.strictEqual(status, 400);
146
+ assert.strictEqual(body.error.code, -32700);
147
+ done();
148
+ });
149
+ });
150
+
151
+ after((done) => {
152
+ mock.killServer(httpmethods);
153
+ c.stop(registry, log, service, server, serverMaintenance, () => {
154
+ done();
155
+ });
156
+ });
157
+ });
@@ -48,6 +48,10 @@ describe("starting integration tests", () => {
48
48
  // to test cache invalidation with the mongo model
49
49
  require("./UC7-cache-invalidate/index.js");
50
50
 
51
+
52
+ // to test the MCP endpoint /soajs/mcp
53
+ require("./UC8-mcp/index.js");
54
+
51
55
  done();
52
56
  });
53
57
  });
@@ -37,6 +37,7 @@ describe("Starting Gateway Unit test", () => {
37
37
  require("./mw/response/index.js");
38
38
  require("./mw/soajs/index.js");
39
39
  require("./mw/soajsRoutes/keyACL.js");
40
+ require("./mw/soajsRoutes/mcp.js");
40
41
  require("./mw/traffic/index.js");
41
42
  require("./mw/idempotency/index.js");
42
43
  require("./mw/idempotency/memory.js");