@smartbear/mcp 0.27.1 → 0.28.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/common/initialize.js +22 -0
- package/dist/common/server.js +7 -0
- package/dist/common/transport-http.js +2 -13
- package/dist/common/transport-stdio.js +2 -13
- package/dist/package.json.js +1 -1
- package/dist/pactflow/client.js +10 -3
- package/dist/swagger/client/api.js +5 -4
- package/dist/swagger/client/functional-testing-api.js +25 -0
- package/dist/swagger/client/functional-testing-tools.js +8 -0
- package/dist/swagger/client/portal-types.js +4 -1
- package/dist/swagger/client.js +3 -0
- package/dist/zephyr/common/rest-api-schemas.js +2199 -102
- package/package.json +1 -1
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
function handleInitializeMessage(server, message) {
|
|
2
|
+
if (typeof message !== "object" || message === null || !("method" in message) || message.method !== "initialize") {
|
|
3
|
+
return;
|
|
4
|
+
}
|
|
5
|
+
const params = message.params;
|
|
6
|
+
const clientInfo = params?.clientInfo;
|
|
7
|
+
if (clientInfo) {
|
|
8
|
+
server.setClientInfo(clientInfo);
|
|
9
|
+
}
|
|
10
|
+
if (params?.protocolVersion === "2025-11-25") {
|
|
11
|
+
const clientCapabilities = params.capabilities ?? {};
|
|
12
|
+
if (Object.hasOwn(clientCapabilities, "sampling")) {
|
|
13
|
+
server.setSamplingSupported(true);
|
|
14
|
+
}
|
|
15
|
+
if (Object.hasOwn(clientCapabilities, "elicitation")) {
|
|
16
|
+
server.setElicitationSupported(true);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
export {
|
|
21
|
+
handleInitializeMessage
|
|
22
|
+
};
|
package/dist/common/server.js
CHANGED
|
@@ -10,6 +10,7 @@ class SmartBearMcpServer extends McpServer {
|
|
|
10
10
|
cache;
|
|
11
11
|
samplingSupported = false;
|
|
12
12
|
elicitationSupported = false;
|
|
13
|
+
clientInfo;
|
|
13
14
|
clients = [];
|
|
14
15
|
enabledToolsets;
|
|
15
16
|
constructor(enabledToolsets) {
|
|
@@ -48,6 +49,12 @@ class SmartBearMcpServer extends McpServer {
|
|
|
48
49
|
isElicitationSupported() {
|
|
49
50
|
return this.elicitationSupported;
|
|
50
51
|
}
|
|
52
|
+
setClientInfo(info) {
|
|
53
|
+
this.clientInfo = info;
|
|
54
|
+
}
|
|
55
|
+
getClientInfo() {
|
|
56
|
+
return this.clientInfo;
|
|
57
|
+
}
|
|
51
58
|
getClients() {
|
|
52
59
|
return this.clients;
|
|
53
60
|
}
|
|
@@ -5,6 +5,7 @@ import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
|
|
|
5
5
|
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
6
6
|
import { isInitializeRequest } from "@modelcontextprotocol/sdk/types.js";
|
|
7
7
|
import { clientRegistry } from "./client-registry.js";
|
|
8
|
+
import { handleInitializeMessage } from "./initialize.js";
|
|
8
9
|
import { withRequestContext } from "./request-context.js";
|
|
9
10
|
import { SmartBearMcpServer } from "./server.js";
|
|
10
11
|
import { isDraining, registerShutdownHandler } from "./shutdown.js";
|
|
@@ -211,19 +212,7 @@ async function createNewTransport(req, res, transports) {
|
|
|
211
212
|
transports.set(newSessionId, { server, transport });
|
|
212
213
|
}
|
|
213
214
|
});
|
|
214
|
-
transport.onmessage = (message) =>
|
|
215
|
-
if ("method" in message && message.method === "initialize") {
|
|
216
|
-
if (message.params?.protocolVersion === "2025-11-25") {
|
|
217
|
-
const clientCapabilities = message.params?.capabilities;
|
|
218
|
-
if (Object.hasOwn(clientCapabilities, "sampling")) {
|
|
219
|
-
server.setSamplingSupported(true);
|
|
220
|
-
}
|
|
221
|
-
if (Object.hasOwn(clientCapabilities, "elicitation")) {
|
|
222
|
-
server.setElicitationSupported(true);
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
};
|
|
215
|
+
transport.onmessage = (message) => handleInitializeMessage(server, message);
|
|
227
216
|
transport.onclose = () => {
|
|
228
217
|
if (transport.sessionId) {
|
|
229
218
|
console.log(`[MCP] Session closed: ${transport.sessionId}`);
|
|
@@ -2,6 +2,7 @@ import { enableCompileCache } from "node:module";
|
|
|
2
2
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
3
3
|
import { clientRegistry } from "./client-registry.js";
|
|
4
4
|
import { USER_AGENT } from "./info.js";
|
|
5
|
+
import { handleInitializeMessage } from "./initialize.js";
|
|
5
6
|
import { SmartBearMcpServer } from "./server.js";
|
|
6
7
|
import { registerShutdownHandler } from "./shutdown.js";
|
|
7
8
|
import { isOptionalType, getTypeDescription } from "./zod-utils.js";
|
|
@@ -57,19 +58,7 @@ ${message.join("\n")}` : "No clients support environment variable configuration.
|
|
|
57
58
|
console.error("[MCP][shutdown] Error closing stdio transport:", err);
|
|
58
59
|
}
|
|
59
60
|
});
|
|
60
|
-
transport.onmessage = (message) =>
|
|
61
|
-
if ("method" in message && message.method === "initialize") {
|
|
62
|
-
if (message.params?.protocolVersion === "2025-11-25") {
|
|
63
|
-
const clientCapabilities = message.params?.capabilities;
|
|
64
|
-
if (Object.hasOwn(clientCapabilities, "sampling")) {
|
|
65
|
-
server.setSamplingSupported(true);
|
|
66
|
-
}
|
|
67
|
-
if (Object.hasOwn(clientCapabilities, "elicitation")) {
|
|
68
|
-
server.setElicitationSupported(true);
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
};
|
|
61
|
+
transport.onmessage = (message) => handleInitializeMessage(server, message);
|
|
73
62
|
await server.connect(transport);
|
|
74
63
|
}
|
|
75
64
|
function getEnvVarName(clientPrefix, key) {
|
package/dist/package.json.js
CHANGED
package/dist/pactflow/client.js
CHANGED
|
@@ -170,6 +170,10 @@ class PactflowClient {
|
|
|
170
170
|
if (Array.isArray(contextToken)) {
|
|
171
171
|
contextToken = contextToken[0];
|
|
172
172
|
}
|
|
173
|
+
const clientInfo = this._server?.getClientInfo();
|
|
174
|
+
const sourceApplicationHeader = {
|
|
175
|
+
SOURCE_APPLICATION: clientInfo ? `${clientInfo.name}/${clientInfo.version}` : "unknown"
|
|
176
|
+
};
|
|
173
177
|
if (contextToken) {
|
|
174
178
|
let authHeader = contextToken;
|
|
175
179
|
if (!contextToken.startsWith("Basic ") && !contextToken.startsWith("Bearer ")) {
|
|
@@ -178,7 +182,8 @@ class PactflowClient {
|
|
|
178
182
|
return {
|
|
179
183
|
Authorization: authHeader,
|
|
180
184
|
"Content-Type": "application/json",
|
|
181
|
-
"User-Agent": USER_AGENT
|
|
185
|
+
"User-Agent": USER_AGENT,
|
|
186
|
+
...sourceApplicationHeader
|
|
182
187
|
};
|
|
183
188
|
}
|
|
184
189
|
if (this.token) {
|
|
@@ -189,14 +194,16 @@ class PactflowClient {
|
|
|
189
194
|
return {
|
|
190
195
|
Authorization: authHeader,
|
|
191
196
|
"Content-Type": "application/json",
|
|
192
|
-
"User-Agent": USER_AGENT
|
|
197
|
+
"User-Agent": USER_AGENT,
|
|
198
|
+
...sourceApplicationHeader
|
|
193
199
|
};
|
|
194
200
|
} else if (this.username && this.password) {
|
|
195
201
|
const authString = `${this.username}:${this.password}`;
|
|
196
202
|
return {
|
|
197
203
|
Authorization: `Basic ${Buffer.from(authString).toString("base64")}`,
|
|
198
204
|
"Content-Type": "application/json",
|
|
199
|
-
"User-Agent": USER_AGENT
|
|
205
|
+
"User-Agent": USER_AGENT,
|
|
206
|
+
...sourceApplicationHeader
|
|
200
207
|
};
|
|
201
208
|
}
|
|
202
209
|
return void 0;
|
|
@@ -677,7 +677,8 @@ class SwaggerAPI {
|
|
|
677
677
|
contentType = "markdown",
|
|
678
678
|
source = "internal",
|
|
679
679
|
order = 0,
|
|
680
|
-
parentId = null
|
|
680
|
+
parentId = null,
|
|
681
|
+
pageSlug
|
|
681
682
|
} = args;
|
|
682
683
|
if (contentType === "html" && source === "internal" && pageContent !== void 0) {
|
|
683
684
|
throw new ToolError(
|
|
@@ -694,12 +695,12 @@ class SwaggerAPI {
|
|
|
694
695
|
);
|
|
695
696
|
}
|
|
696
697
|
const section = sections.items[0];
|
|
697
|
-
const
|
|
698
|
+
const resolvedPageSlug = pageSlug || normalizeSlug(pageTitle);
|
|
698
699
|
const normalizedTitle = pageTitle.slice(0, 255);
|
|
699
700
|
const tocItem = await this.createTableOfContents(section.id, {
|
|
700
701
|
type: "new",
|
|
701
702
|
title: normalizedTitle,
|
|
702
|
-
slug:
|
|
703
|
+
slug: resolvedPageSlug,
|
|
703
704
|
order,
|
|
704
705
|
parentId,
|
|
705
706
|
content: {
|
|
@@ -724,7 +725,7 @@ class SwaggerAPI {
|
|
|
724
725
|
sectionSlug: section.slug,
|
|
725
726
|
pageDetails: {
|
|
726
727
|
tableOfContentsId: tocItem.id,
|
|
727
|
-
slug:
|
|
728
|
+
slug: resolvedPageSlug,
|
|
728
729
|
title: normalizedTitle,
|
|
729
730
|
content: {
|
|
730
731
|
type: contentType,
|
|
@@ -65,6 +65,31 @@ class FunctionalTestingAPI {
|
|
|
65
65
|
}
|
|
66
66
|
return response.json();
|
|
67
67
|
}
|
|
68
|
+
async listSuites() {
|
|
69
|
+
const headers = this.getFtHeaders();
|
|
70
|
+
let response;
|
|
71
|
+
try {
|
|
72
|
+
response = await fetch(`${this.baseUrl}/suites`, {
|
|
73
|
+
method: "GET",
|
|
74
|
+
headers
|
|
75
|
+
});
|
|
76
|
+
} catch {
|
|
77
|
+
throw new ToolError(
|
|
78
|
+
"Swagger Functional Testing service is currently unreachable. Retry after a moment."
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
if (response.status === 401 || response.status === 403) {
|
|
82
|
+
throw new ToolError(
|
|
83
|
+
"Authentication failed. Verify your API token is valid and has not expired."
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
if (!response.ok) {
|
|
87
|
+
throw new ToolError(
|
|
88
|
+
`Failed to list Functional Testing suites: ${response.status} ${response.statusText}`
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
return response.json();
|
|
92
|
+
}
|
|
68
93
|
}
|
|
69
94
|
export {
|
|
70
95
|
FUNCTIONAL_TESTING_API_KEY_HEADER,
|
|
@@ -22,6 +22,14 @@ const FUNCTIONAL_TESTING_TOOLS = [
|
|
|
22
22
|
inputSchema: GetFunctionalTestingExecutionTestSchema,
|
|
23
23
|
handler: "getFunctionalTestingExecution",
|
|
24
24
|
idempotent: false
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
title: "List Suites",
|
|
28
|
+
toolset: "Functional Testing",
|
|
29
|
+
summary: "Lists all test suites available in your Swagger Functional Testing workspace. Use this tool when you need to discover available suites before running them or checking their execution history. Do not use this tool to retrieve individual tests or test suite execution results.",
|
|
30
|
+
handler: "listFunctionalTestingSuites",
|
|
31
|
+
idempotent: true,
|
|
32
|
+
readOnly: true
|
|
25
33
|
}
|
|
26
34
|
];
|
|
27
35
|
export {
|
|
@@ -216,7 +216,10 @@ const CreateDocumentationPageArgsSchema = z.object({
|
|
|
216
216
|
portalId: z.string().describe("Portal UUID or subdomain - unique identifier for the portal"),
|
|
217
217
|
productId: z.string().uuid().describe("Product UUID - unique identifier for the product"),
|
|
218
218
|
pageTitle: z.string().describe(
|
|
219
|
-
"Title of the documentation page - will be displayed in navigation (3-255 characters
|
|
219
|
+
"Title of the documentation page - will be displayed in navigation (3-255 characters)"
|
|
220
|
+
),
|
|
221
|
+
pageSlug: z.string().optional().describe(
|
|
222
|
+
"URL slug for the documentation page. 3-255 characters, lowercase, alphanumeric with hyphens, underscores, or dots (e.g. 'my-page'). If not provided, the slug is generated from the page title."
|
|
220
223
|
),
|
|
221
224
|
pageContent: z.string().optional().describe(
|
|
222
225
|
"Content of the documentation page. Provide HTML when contentType is 'html', Markdown when contentType is 'markdown'."
|
package/dist/swagger/client.js
CHANGED
|
@@ -191,6 +191,9 @@ class SwaggerClient {
|
|
|
191
191
|
}
|
|
192
192
|
return fn(this.ftApi);
|
|
193
193
|
}
|
|
194
|
+
async listFunctionalTestingSuites() {
|
|
195
|
+
return this.withFunctionalTesting((ftApi) => ftApi.listSuites());
|
|
196
|
+
}
|
|
194
197
|
async registerTools(register, _getInput) {
|
|
195
198
|
TOOLS.forEach((tool) => {
|
|
196
199
|
if (tool.toolset === "Functional Testing" && !this.ftApi) {
|