@loadmill/mcp 0.1.0 → 0.2.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/README.md +47 -37
- package/dist/constants.d.ts +1 -1
- package/dist/constants.js +1 -1
- package/dist/handlers/logging.d.ts +2 -0
- package/dist/handlers/logging.js +21 -0
- package/dist/handlers/logging.js.map +1 -0
- package/dist/handlers/prompts/index.js +1 -1
- package/dist/handlers/resources/index.js +3 -2
- package/dist/handlers/resources/index.js.map +1 -1
- package/dist/handlers/shared.js +4 -4
- package/dist/handlers/shared.js.map +1 -1
- package/dist/handlers/tools/tasks.js +21 -15
- package/dist/handlers/tools/tasks.js.map +1 -1
- package/dist/http-request.js +3 -2
- package/dist/http-request.js.map +1 -1
- package/dist/index.js +6 -2
- package/dist/index.js.map +1 -1
- package/dist/logger.d.ts +18 -0
- package/dist/logger.js +56 -0
- package/dist/logger.js.map +1 -0
- package/dist/mcp-handler.js +2 -0
- package/dist/mcp-handler.js.map +1 -1
- package/dist/mcp-server.js +1 -0
- package/dist/mcp-server.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,45 +1,47 @@
|
|
|
1
1
|
# Loadmill MCP Server
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The Loadmill MCP server exposes Loadmill’s test-management APIs to any Model Context Protocol (MCP) client. Use it to search, run, write and validate Loadmill tests without leaving your MCP-enabled IDE or agent workflow.
|
|
4
4
|
|
|
5
5
|
## Use Cases
|
|
6
6
|
- Query Loadmill for information
|
|
7
7
|
- Execute Loadmill tests
|
|
8
|
-
- Write and maintain Loadmill tests
|
|
8
|
+
- Write and maintain Loadmill tests
|
|
9
9
|
|
|
10
|
-
*Note*:
|
|
10
|
+
*Note*: When working with MCPs, make sure your client runs in `Agent` mode.
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
## IDE Integration
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
### VS Code
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
*Important*: You will have to generate a Loadmill API token from your [Loadmill account settings](https://app.loadmill.com/app/user/settings/security) to authenticate the MCP server.
|
|
17
|
+
```
|
|
17
18
|
{
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
19
|
+
"servers": {
|
|
20
|
+
"loadmill": {
|
|
21
|
+
"type": "stdio",
|
|
22
|
+
"command": "npx",
|
|
23
|
+
"args": ["@loadmill/mcp"],
|
|
24
|
+
"env": {
|
|
25
|
+
"LOADMILL_API_TOKEN": "${input:loadmill-api-token}"
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"inputs": [
|
|
30
|
+
{
|
|
29
31
|
"id": "loadmill-api-token",
|
|
30
32
|
"type": "promptString",
|
|
31
33
|
"description": "Loadmill API token",
|
|
32
34
|
"password": true
|
|
33
|
-
}
|
|
35
|
+
}
|
|
36
|
+
]
|
|
34
37
|
}
|
|
35
|
-
|
|
38
|
+
```
|
|
36
39
|
|
|
37
|
-
|
|
40
|
+
### Cursor
|
|
38
41
|
|
|
39
|
-
|
|
40
|
-
|
|
42
|
+
```
|
|
43
|
+
{
|
|
41
44
|
"mcpServers": {
|
|
42
|
-
// other MCP servers...
|
|
43
45
|
"loadmill": {
|
|
44
46
|
"command": "npx",
|
|
45
47
|
"args": ["@loadmill/mcp"],
|
|
@@ -51,22 +53,30 @@ This package provides a STDIO-based MCP server. It is designed to be integrated
|
|
|
51
53
|
}
|
|
52
54
|
```
|
|
53
55
|
|
|
56
|
+
|
|
54
57
|
## MCP Capabilities
|
|
55
58
|
|
|
56
|
-
|
|
59
|
+
**Tools** – Supports `list_tools` and `call_tool`; each tool returns standard MCP text content:
|
|
60
|
+
- `search_test_suites` – Filter Loadmill test suites by text, dates, or labels.
|
|
61
|
+
- `search_test_suite_runs` – Search historical test-suite flow runs.
|
|
62
|
+
- `run_test_suite` – Trigger a test-suite execution by ID.
|
|
63
|
+
- `get_test_suite_run` – Retrieve run details (including flow run IDs).
|
|
64
|
+
- `get_test_suite_flow_run` – Inspect an individual flow run by ID.
|
|
65
|
+
- `search_test_plans` – Browse Loadmill test plans.
|
|
66
|
+
- `run_test_plans` – Start a plan with optional labels and parameter overrides.
|
|
67
|
+
- `get_test_plan_run` – Fetch plan-run status and metadata.
|
|
68
|
+
- `get_labels` – List team labels (id and description).
|
|
69
|
+
- `validate_test_suite` – Validate a local Loadmill test-suite JSON file against the official schema.
|
|
70
|
+
|
|
71
|
+
**Prompts** – Supports `list_prompts` and `get_prompt`:
|
|
72
|
+
- `investigate_failed_test` – Summarise a failed run and advise next steps.
|
|
73
|
+
- `create_test_suite` – Generate a Loadmill test-suite JSON that conforms to the schema resource.
|
|
57
74
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
- Search Loadmill test suite runs.
|
|
61
|
-
- Run a specific test suite.
|
|
62
|
-
- Fetch details of a test suite run.
|
|
63
|
-
- Fetch details of a specific suite flow run.
|
|
64
|
-
- Search Loadmill test plans.
|
|
65
|
-
- Run a specific test plan (with optional labels/overrides).
|
|
66
|
-
- Fetch details of a test plan run.
|
|
67
|
-
- List all available labels in Loadmill.
|
|
75
|
+
**Resources** – Supports `list_resources` and `read_resource`:
|
|
76
|
+
- `loadmill://schemas/test-suite@v1` – JSON Schema (draft 2020-12) for Loadmill test suites. Responses are cached locally for an hour.
|
|
68
77
|
|
|
69
|
-
|
|
70
|
-
|
|
78
|
+
## Working with the Test-Suite Schema
|
|
79
|
+
- Use `validate_test_suite` to catch schema violations in local JSON files before uploading them to Loadmill.
|
|
80
|
+
- The `create_test_suite` prompt relies on the same schema resource, ensuring generated suites are schema-compliant.
|
|
71
81
|
|
|
72
|
-
|
|
82
|
+
Once connected, your MCP client can mix these tools, prompts, and resources to automate Loadmill QA workflows end-to-end.
|
package/dist/constants.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export declare const MCP_SERVER_NAME = "loadmill-mcp-server";
|
|
2
|
-
export declare const MCP_SERVER_VERSION = "0.0.
|
|
2
|
+
export declare const MCP_SERVER_VERSION = "0.0.2";
|
|
3
3
|
export declare const LOADMILL_URL: string;
|
|
4
4
|
export declare const ASSETS_URL: string;
|
|
5
5
|
export declare const API_URL: string;
|
package/dist/constants.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.AVILABLE_RESOURCES = exports.AVILABLE_PROMPTS = exports.AVALIABLE_TOOLS = exports.SCHEMA_TYPE = exports.VALIDATE_TEST_SUITE = exports.GET_TEST_SUITE_SCHEMA = exports.GET_LABELS = exports.GET_TEST_PLAN_RUN = exports.RUN_TEST_PLAN = exports.SEARCH_TEST_PLAN = exports.GET_TEST_SUITE_FLOW_RUN = exports.GET_TEST_SUITE_RUN = exports.RUN_TEST_SUITE = exports.SEARCH_TEST_SUITE_RUNS = exports.SEARCH_TEST_SUITES = exports.API_URL = exports.ASSETS_URL = exports.LOADMILL_URL = exports.MCP_SERVER_VERSION = exports.MCP_SERVER_NAME = void 0;
|
|
4
4
|
exports.MCP_SERVER_NAME = 'loadmill-mcp-server';
|
|
5
|
-
exports.MCP_SERVER_VERSION = '0.0.
|
|
5
|
+
exports.MCP_SERVER_VERSION = '0.0.2';
|
|
6
6
|
exports.LOADMILL_URL = process.env.LOADMILL_URL || 'https://app.loadmill.com';
|
|
7
7
|
exports.ASSETS_URL = exports.LOADMILL_URL + '/assets';
|
|
8
8
|
exports.API_URL = exports.LOADMILL_URL + '/api';
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.handlers = void 0;
|
|
4
|
+
const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
|
|
5
|
+
const logger_js_1 = require("../logger.js");
|
|
6
|
+
exports.handlers = [
|
|
7
|
+
{
|
|
8
|
+
schema: types_js_1.SetLevelRequestSchema,
|
|
9
|
+
handler: async (request) => {
|
|
10
|
+
const level = request.params?.level;
|
|
11
|
+
if (level) {
|
|
12
|
+
(0, logger_js_1.setLogLevel)(level);
|
|
13
|
+
if (logger_js_1.log) {
|
|
14
|
+
logger_js_1.log.info(`Set log level to ${level}`);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
return {};
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
];
|
|
21
|
+
//# sourceMappingURL=logging.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logging.js","sourceRoot":"","sources":["../../src/handlers/logging.ts"],"names":[],"mappings":";;;AAAA,iEAA2E;AAG3E,4CAAgD;AAEnC,QAAA,QAAQ,GAAiB;IACpC;QACE,MAAM,EAAE,gCAAqB;QAC7B,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;YACzB,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,EAAE,KAAK,CAAC;YACpC,IAAI,KAAK,EAAE;gBACT,IAAA,uBAAW,EAAC,KAAK,CAAC,CAAC;gBACnB,IAAI,eAAG,EAAE;oBACP,eAAG,CAAC,IAAI,CAAC,oBAAoB,KAAK,EAAE,CAAC,CAAC;iBACvC;aACF;YACD,OAAO,EAAE,CAAC;QACZ,CAAC;KACF;CACF,CAAC"}
|
|
@@ -72,7 +72,7 @@ const prompts = [
|
|
|
72
72
|
role: 'user',
|
|
73
73
|
content: `Create a test-suite named "{{name}}" to test the following endpoints and behaviors:\n\n {{requirements}}\n\n
|
|
74
74
|
Constraints:\n- Include flows and request steps covering happy-path and key edge-cases.\n-
|
|
75
|
-
Use descriptive names for flows and steps.\n- Parameterize repeated values in suite.parameters when reasonable.\n-
|
|
75
|
+
Use descriptive names for flows and steps.\n- Parameterize repeated values in suite.parameters when reasonable. Parameterised values use the format \${parameter_name}.\n-
|
|
76
76
|
Add basic assertions for status, response time, and core fields.\n- Output only JSON.`,
|
|
77
77
|
},
|
|
78
78
|
],
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.handlers = void 0;
|
|
4
4
|
const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
|
|
5
5
|
const shared_js_1 = require("../shared.js");
|
|
6
|
+
const logger_js_1 = require("../../logger.js");
|
|
6
7
|
exports.handlers = [
|
|
7
8
|
{
|
|
8
9
|
schema: types_js_1.ListResourcesRequestSchema,
|
|
@@ -23,7 +24,7 @@ exports.handlers = [
|
|
|
23
24
|
schema: types_js_1.ReadResourceRequestSchema,
|
|
24
25
|
handler: async (request) => {
|
|
25
26
|
const uri = request?.params?.uri;
|
|
26
|
-
|
|
27
|
+
logger_js_1.log.info(`Reading resource with URI: ${uri ?? 'undefined'}`);
|
|
27
28
|
if (!uri) {
|
|
28
29
|
return {
|
|
29
30
|
contents: [
|
|
@@ -36,7 +37,7 @@ exports.handlers = [
|
|
|
36
37
|
}
|
|
37
38
|
if (uri === 'loadmill://schemas/test-suite@v1') {
|
|
38
39
|
const schema = await (0, shared_js_1.getSchema)(uri);
|
|
39
|
-
|
|
40
|
+
logger_js_1.log.info(`Fetched schema for URI: ${uri}`);
|
|
40
41
|
return {
|
|
41
42
|
contents: [
|
|
42
43
|
{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/handlers/resources/index.ts"],"names":[],"mappings":";;;AAAA,iEAG4C;AAE5C,4CAAyC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/handlers/resources/index.ts"],"names":[],"mappings":";;;AAAA,iEAG4C;AAE5C,4CAAyC;AACzC,+CAAsC;AAGzB,QAAA,QAAQ,GAAiB;IACpC;QACE,MAAM,EAAE,qCAA0B;QAClC,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE;YAC1B,MAAM,SAAS,GAAG;gBAChB;oBACE,IAAI,EAAE,4BAA4B;oBAClC,KAAK,EAAE,4BAA4B;oBACnC,GAAG,EAAE,kCAAkC;oBACvC,WAAW,EACT,wEAAwE;oBAC1E,QAAQ,EAAE,yBAAyB;iBACpC;aACF,CAAC;YAEF,OAAO,EAAE,SAAS,EAAE,CAAC;QACvB,CAAC;KACF;IACD;QACE,MAAM,EAAE,oCAAyB;QACjC,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;YACzB,MAAM,GAAG,GAAG,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC;YAEjC,eAAG,CAAC,IAAI,CAAC,8BAA8B,GAAG,IAAI,WAAW,EAAE,CAAC,CAAC;YAC7D,IAAI,CAAC,GAAG,EAAE;gBACR,OAAO;oBACL,QAAQ,EAAE;wBACR;4BACE,QAAQ,EAAE,YAAY;4BACtB,IAAI,EAAE,sBAAsB;yBAC7B;qBACF;iBACF,CAAC;aACH;YAED,IAAI,GAAG,KAAK,kCAAkC,EAAE;gBAC9C,MAAM,MAAM,GAAG,MAAM,IAAA,qBAAS,EAAC,GAAG,CAAC,CAAC;gBACpC,eAAG,CAAC,IAAI,CAAC,2BAA2B,GAAG,EAAE,CAAC,CAAC;gBAC3C,OAAO;oBACL,QAAQ,EAAE;wBACR;4BACE,GAAG;4BACH,QAAQ,EAAE,kBAAkB;4BAC5B,IAAI,EAAE,MAAM;yBACb;qBACF;iBACF,CAAC;aACH;YAED,mBAAmB;YACnB,OAAO;gBACL,QAAQ,EAAE;oBACR;wBACE,QAAQ,EAAE,YAAY;wBACtB,IAAI,EAAE,qBAAqB,GAAG,EAAE;qBACjC;iBACF;aACF,CAAC;QACJ,CAAC;KACF;CACF,CAAC"}
|
package/dist/handlers/shared.js
CHANGED
|
@@ -3,10 +3,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.schemaTypeToSchemaURL = exports.getSchema = void 0;
|
|
4
4
|
const constants_1 = require("../constants");
|
|
5
5
|
const http_request_1 = require("../http-request");
|
|
6
|
+
const logger_js_1 = require("../logger.js");
|
|
6
7
|
const schemaCache = new Map();
|
|
7
8
|
async function getSchema(schemaType) {
|
|
8
9
|
try {
|
|
9
|
-
|
|
10
|
+
logger_js_1.log.info(`Getting schema with type: ${schemaType}`);
|
|
10
11
|
const schemaUrl = getSchemaURLByType(schemaType);
|
|
11
12
|
const cached = schemaCache.get(schemaUrl);
|
|
12
13
|
if (cached) {
|
|
@@ -21,12 +22,11 @@ async function getSchema(schemaType) {
|
|
|
21
22
|
text,
|
|
22
23
|
expiresAt: Date.now() + 60 * 60 * 1000, // Cache for 60 minutes
|
|
23
24
|
};
|
|
24
|
-
console.log('Cached schema:', entry);
|
|
25
25
|
schemaCache.set(schemaUrl, entry);
|
|
26
26
|
return entry.text;
|
|
27
27
|
}
|
|
28
28
|
catch (error) {
|
|
29
|
-
|
|
29
|
+
logger_js_1.log.error(`Failed to fetch schema for ${schemaType}: ${(0, logger_js_1.formatError)(error)}`);
|
|
30
30
|
throw error;
|
|
31
31
|
}
|
|
32
32
|
}
|
|
@@ -36,7 +36,7 @@ exports.schemaTypeToSchemaURL = {
|
|
|
36
36
|
};
|
|
37
37
|
function getSchemaURLByType(schemaType) {
|
|
38
38
|
const schemaUrl = exports.schemaTypeToSchemaURL[schemaType];
|
|
39
|
-
//
|
|
39
|
+
//log.info(`Resolved schema URL: ${schemaUrl}`);
|
|
40
40
|
if (!schemaUrl) {
|
|
41
41
|
throw new Error(`Unknown schema type: ${schemaType}`);
|
|
42
42
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shared.js","sourceRoot":"","sources":["../../src/handlers/shared.ts"],"names":[],"mappings":";;;AAAA,4CAAuD;AACvD,kDAA+D;
|
|
1
|
+
{"version":3,"file":"shared.js","sourceRoot":"","sources":["../../src/handlers/shared.ts"],"names":[],"mappings":";;;AAAA,4CAAuD;AACvD,kDAA+D;AAC/D,4CAAgD;AAOhD,MAAM,WAAW,GAAG,IAAI,GAAG,EAA4B,CAAC;AAEjD,KAAK,UAAU,SAAS,CAAC,UAAkB;IAEhD,IAAI;QACF,eAAG,CAAC,IAAI,CAAC,6BAA6B,UAAU,EAAE,CAAC,CAAC;QACpD,MAAM,SAAS,GAAG,kBAAkB,CAAC,UAAU,CAAC,CAAC;QAEjD,MAAM,MAAM,GAAG,WAAW,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC1C,IAAI,MAAM,EAAE;YACV,IAAI,CAAC,MAAM,CAAC,SAAS,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,SAAS,EAAE;gBACtD,OAAO,MAAM,CAAC,IAAI,CAAC;aACpB;YACD,WAAW,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;SAC/B;QAED,MAAM,IAAI,GAAG,MAAM,IAAA,8BAAe,EAAC,EAAE,MAAM,EAAE,0BAAW,CAAC,GAAG,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC;QAChF,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;QAEvB,MAAM,KAAK,GAAqB;YAC9B,IAAI;YACJ,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,uBAAuB;SAChE,CAAC;QACF,WAAW,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;QAClC,OAAO,KAAK,CAAC,IAAI,CAAC;KACnB;IAAC,OAAO,KAAK,EAAE;QACd,eAAG,CAAC,KAAK,CAAC,8BAA8B,UAAU,KAAK,IAAA,uBAAW,EAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC7E,MAAM,KAAK,CAAC;KACb;AACH,CAAC;AA3BD,8BA2BC;AAEY,QAAA,qBAAqB,GAAG;IACnC,CAAC,uBAAW,CAAC,UAAU,CAAC,EAAE,GAAG,sBAAU,4CAA4C;CACpF,CAAC;AAEF,SAAS,kBAAkB,CAAC,UAAkB;IAC5C,MAAM,SAAS,GAAG,6BAAqB,CAAC,UAAU,CAAC,CAAC;IACpD,gDAAgD;IAChD,IAAI,CAAC,SAAS,EAAE;QACd,MAAM,IAAI,KAAK,CAAC,wBAAwB,UAAU,EAAE,CAAC,CAAC;KACvD;IACD,OAAO,SAAS,CAAC;AACnB,CAAC"}
|
|
@@ -12,12 +12,21 @@ const path_1 = __importDefault(require("path"));
|
|
|
12
12
|
const http_request_js_1 = require("../../http-request.js");
|
|
13
13
|
const constants_js_1 = require("../../constants.js");
|
|
14
14
|
const utils_js_1 = require("../../utils.js");
|
|
15
|
+
const logger_js_1 = require("../../logger.js");
|
|
15
16
|
const shared_js_1 = require("../shared.js");
|
|
17
|
+
const stringifyPayload = (payload) => {
|
|
18
|
+
try {
|
|
19
|
+
return JSON.stringify(payload, null, 2);
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return String(payload);
|
|
23
|
+
}
|
|
24
|
+
};
|
|
16
25
|
// todo make sure all return in the same allowed pattern
|
|
17
26
|
exports.toolsTasks = {
|
|
18
27
|
[constants_js_1.SEARCH_TEST_SUITES]: async (params) => {
|
|
19
28
|
const args = params.arguments;
|
|
20
|
-
|
|
29
|
+
logger_js_1.log.info(`Searching test suites with args: ${stringifyPayload(args)}`);
|
|
21
30
|
const response = await (0, http_request_js_1.sendHttpRequest)({
|
|
22
31
|
method: http_request_js_1.HttpMethods.GET,
|
|
23
32
|
url: `${constants_js_1.API_URL}/test-suites`,
|
|
@@ -38,7 +47,7 @@ exports.toolsTasks = {
|
|
|
38
47
|
},
|
|
39
48
|
[constants_js_1.SEARCH_TEST_SUITE_RUNS]: async (params) => {
|
|
40
49
|
const args = params.arguments;
|
|
41
|
-
|
|
50
|
+
logger_js_1.log.info(`Searching test suite runs with args: ${stringifyPayload(args)}`);
|
|
42
51
|
const response = await (0, http_request_js_1.sendHttpRequest)({
|
|
43
52
|
method: http_request_js_1.HttpMethods.GET,
|
|
44
53
|
url: `${constants_js_1.API_URL}/test-suites-runs/flows`,
|
|
@@ -58,7 +67,7 @@ exports.toolsTasks = {
|
|
|
58
67
|
},
|
|
59
68
|
[constants_js_1.RUN_TEST_SUITE]: async (params) => {
|
|
60
69
|
const args = params.arguments;
|
|
61
|
-
|
|
70
|
+
logger_js_1.log.info(`Running test suite with args: ${stringifyPayload(args)}`);
|
|
62
71
|
const response = await (0, http_request_js_1.sendHttpRequest)({
|
|
63
72
|
method: http_request_js_1.HttpMethods.POST,
|
|
64
73
|
url: `${constants_js_1.API_URL}/test-suites/${args.id}/run`,
|
|
@@ -72,7 +81,7 @@ exports.toolsTasks = {
|
|
|
72
81
|
},
|
|
73
82
|
[constants_js_1.GET_TEST_SUITE_RUN]: async (params) => {
|
|
74
83
|
const args = params.arguments;
|
|
75
|
-
|
|
84
|
+
logger_js_1.log.info(`Getting test suite run with args: ${stringifyPayload(args)}`);
|
|
76
85
|
const response = await (0, http_request_js_1.sendHttpRequest)({
|
|
77
86
|
method: http_request_js_1.HttpMethods.GET,
|
|
78
87
|
url: `${constants_js_1.API_URL}/test-suites-runs/${args.id}`,
|
|
@@ -86,7 +95,7 @@ exports.toolsTasks = {
|
|
|
86
95
|
},
|
|
87
96
|
[constants_js_1.GET_TEST_SUITE_FLOW_RUN]: async (params) => {
|
|
88
97
|
const args = params.arguments;
|
|
89
|
-
|
|
98
|
+
logger_js_1.log.info(`Getting test suite flow run with args: ${stringifyPayload(args)}`);
|
|
90
99
|
const response = await (0, http_request_js_1.sendHttpRequest)({
|
|
91
100
|
method: http_request_js_1.HttpMethods.GET,
|
|
92
101
|
url: `${constants_js_1.API_URL}/test-suites-runs/flows/${args.flowRunId}`,
|
|
@@ -100,7 +109,7 @@ exports.toolsTasks = {
|
|
|
100
109
|
},
|
|
101
110
|
[constants_js_1.SEARCH_TEST_PLAN]: async (params) => {
|
|
102
111
|
const args = params.arguments;
|
|
103
|
-
|
|
112
|
+
logger_js_1.log.info(`Searching test plans with args: ${stringifyPayload(args)}`);
|
|
104
113
|
const response = await (0, http_request_js_1.sendHttpRequest)({
|
|
105
114
|
method: http_request_js_1.HttpMethods.GET,
|
|
106
115
|
url: `${constants_js_1.API_URL}/test-plans`,
|
|
@@ -120,7 +129,7 @@ exports.toolsTasks = {
|
|
|
120
129
|
},
|
|
121
130
|
[constants_js_1.RUN_TEST_PLAN]: async (params) => {
|
|
122
131
|
const args = params.arguments;
|
|
123
|
-
|
|
132
|
+
logger_js_1.log.info(`Running test plan with args: ${stringifyPayload(args)}`);
|
|
124
133
|
// AI decides to use both for some reason
|
|
125
134
|
const overrideParameters = args.overrideParameters && (0, utils_js_1.toLoadmillParams)(args.overrideParameters);
|
|
126
135
|
const parameters = args.parameters && (0, utils_js_1.toLoadmillParams)(args.parameters);
|
|
@@ -141,7 +150,7 @@ exports.toolsTasks = {
|
|
|
141
150
|
},
|
|
142
151
|
[constants_js_1.GET_TEST_PLAN_RUN]: async (params) => {
|
|
143
152
|
const args = params.arguments;
|
|
144
|
-
|
|
153
|
+
logger_js_1.log.info(`Getting test plan run with args: ${stringifyPayload(args)}`);
|
|
145
154
|
const response = await (0, http_request_js_1.sendHttpRequest)({
|
|
146
155
|
method: http_request_js_1.HttpMethods.GET,
|
|
147
156
|
url: `${constants_js_1.API_URL}/test-plans-runs/${args.id}`,
|
|
@@ -155,7 +164,7 @@ exports.toolsTasks = {
|
|
|
155
164
|
},
|
|
156
165
|
[constants_js_1.GET_LABELS]: async (params) => {
|
|
157
166
|
const args = params.arguments;
|
|
158
|
-
|
|
167
|
+
logger_js_1.log.info(`Getting labels with args: ${stringifyPayload(args)}`);
|
|
159
168
|
const response = await (0, http_request_js_1.sendHttpRequest)({
|
|
160
169
|
method: http_request_js_1.HttpMethods.GET,
|
|
161
170
|
url: `${constants_js_1.API_URL}/labels`,
|
|
@@ -214,13 +223,12 @@ exports.toolsTasks = {
|
|
|
214
223
|
};
|
|
215
224
|
}
|
|
216
225
|
const schemaText = await (0, shared_js_1.getSchema)(constants_js_1.SCHEMA_TYPE.TEST_SUITE);
|
|
217
|
-
console.log('Fetched schema for test suite:', typeof schemaText);
|
|
218
226
|
let schema;
|
|
219
227
|
try {
|
|
220
228
|
schema = JSON.parse(schemaText);
|
|
221
229
|
}
|
|
222
230
|
catch (e) {
|
|
223
|
-
|
|
231
|
+
logger_js_1.log.error(`Failed parsing schema JSON: ${(0, logger_js_1.formatError)(e)}`);
|
|
224
232
|
return {
|
|
225
233
|
content: [
|
|
226
234
|
{
|
|
@@ -233,8 +241,6 @@ exports.toolsTasks = {
|
|
|
233
241
|
],
|
|
234
242
|
};
|
|
235
243
|
}
|
|
236
|
-
console.log('Compiling schema for validation');
|
|
237
|
-
console.log('Schema:', schema);
|
|
238
244
|
const ajv = new _2020_1.default({ allErrors: true, strict: false });
|
|
239
245
|
(0, ajv_formats_1.default)(ajv);
|
|
240
246
|
// IMPORTANT: call on the INSTANCE
|
|
@@ -244,7 +250,7 @@ exports.toolsTasks = {
|
|
|
244
250
|
validateFn = ajv.compile(schema);
|
|
245
251
|
}
|
|
246
252
|
catch (e) {
|
|
247
|
-
|
|
253
|
+
logger_js_1.log.error(`Failed compiling schema: ${(0, logger_js_1.formatError)(e)}`);
|
|
248
254
|
return {
|
|
249
255
|
content: [
|
|
250
256
|
{
|
|
@@ -275,7 +281,7 @@ exports.toolsTasks = {
|
|
|
275
281
|
params: err.params,
|
|
276
282
|
schemaPath: err.schemaPath,
|
|
277
283
|
}));
|
|
278
|
-
|
|
284
|
+
logger_js_1.log.info(`Validation errors found: ${stringifyPayload(errors)}`);
|
|
279
285
|
return {
|
|
280
286
|
content: [
|
|
281
287
|
{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tasks.js","sourceRoot":"","sources":["../../../src/handlers/tools/tasks.ts"],"names":[],"mappings":";;;;;;AAAA,0DAAoC;AACpC,wGAA6D;AAC7D,8DAAqC;AAGrC,4CAAoB;AACpB,gDAAwB;AAExB,2DAAqE;AACrE,qDAa4B;AAC5B,6CAAkD;AAClD,4CAAyC;
|
|
1
|
+
{"version":3,"file":"tasks.js","sourceRoot":"","sources":["../../../src/handlers/tools/tasks.ts"],"names":[],"mappings":"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"}
|
package/dist/http-request.js
CHANGED
|
@@ -5,6 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.HttpMethods = exports.sendHttpRequest = void 0;
|
|
7
7
|
const superagent_1 = __importDefault(require("superagent"));
|
|
8
|
+
const logger_js_1 = require("./logger.js");
|
|
8
9
|
const DEFAULT_TIMEOUT_MS = process.env.LOADMILL_TIMEOUT || 30000; // 30 seconds
|
|
9
10
|
const RETRY_DELAY_MS = 1000; // 1 second
|
|
10
11
|
const LOADMILL_API_TOKEN = process.env.LOADMILL_API_TOKEN;
|
|
@@ -13,9 +14,9 @@ const sendHttpRequest = async (options) => {
|
|
|
13
14
|
return await _executeRequest(options);
|
|
14
15
|
}
|
|
15
16
|
catch (err) {
|
|
16
|
-
|
|
17
|
+
logger_js_1.log.error(`Error during ${(options.method || HttpMethods.GET).toUpperCase()} request to ${options.url}: ${(0, logger_js_1.formatError)(err)}`);
|
|
17
18
|
if (_shouldRetry(err)) {
|
|
18
|
-
|
|
19
|
+
logger_js_1.log.info(`Retrying ${(options.method || HttpMethods.GET).toUpperCase()} request to ${options.url}...`);
|
|
19
20
|
await _delay(RETRY_DELAY_MS);
|
|
20
21
|
return await _executeRequest(options);
|
|
21
22
|
}
|
package/dist/http-request.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http-request.js","sourceRoot":"","sources":["../src/http-request.ts"],"names":[],"mappings":";;;;;;AAAA,4DAAoC;
|
|
1
|
+
{"version":3,"file":"http-request.js","sourceRoot":"","sources":["../src/http-request.ts"],"names":[],"mappings":";;;;;;AAAA,4DAAoC;AACpC,2CAA+C;AAE/C,MAAM,kBAAkB,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,KAAK,CAAC,CAAC,aAAa;AAC/E,MAAM,cAAc,GAAG,IAAI,CAAC,CAAC,WAAW;AACxC,MAAM,kBAAkB,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC;AAEnD,MAAM,eAAe,GAAG,KAAK,EAAE,OAA2B,EAAE,EAAE;IACnE,IAAI;QACF,OAAO,MAAM,eAAe,CAAC,OAAO,CAAC,CAAC;KACvC;IACD,OAAO,GAAG,EAAE;QACV,eAAG,CAAC,KAAK,CAAC,gBAAgB,CAAC,OAAO,CAAC,MAAM,IAAI,WAAW,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,eAAe,OAAO,CAAC,GAAG,KAAK,IAAA,uBAAW,EAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC9H,IAAI,YAAY,CAAC,GAAG,CAAC,EAAE;YACrB,eAAG,CAAC,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,MAAM,IAAI,WAAW,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,eAAe,OAAO,CAAC,GAAG,KAAK,CAAC,CAAC;YACvG,MAAM,MAAM,CAAC,cAAc,CAAC,CAAC;YAC7B,OAAO,MAAM,eAAe,CAAC,OAAO,CAAC,CAAC;SACvC;QACD,MAAM,GAAG,CAAC;KACX;AACH,CAAC,CAAC;AAbW,QAAA,eAAe,mBAa1B;AAEF,MAAM,eAAe,GAAG,KAAK,EAAE,OAA2B,EAAE,EAAE;IAC5D,MAAM,EAAE,MAAM,GAAG,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC;IAC/D,IAAI,OAAO,GAAG,oBAAU,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC;SAClC,IAAI,CAAC,kBAAkB,CAAC;SACxB,OAAO,CAAC,kBAAkB,CAAC,CAAC;IAE/B,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC;IAE/D,IAAI,IAAI,EAAE;QACR,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;KAC9B;IAED,OAAO,MAAM,OAAO,CAAC;AACvB,CAAC,CAAC;AAEF,0BAA0B;AAC1B,MAAM,YAAY,GAAG,CAAC,GAAG,EAAW,EAAE;IACpC,OAAO,GAAG,CAAC,OAAO;QAChB,GAAG,CAAC,IAAI,KAAK,cAAc;QAC3B,GAAG,CAAC,IAAI,KAAK,cAAc;QAC3B,GAAG,CAAC,IAAI,KAAK,WAAW;QACxB,GAAG,CAAC,IAAI,KAAK,YAAY,CAAC;AAC9B,CAAC,CAAC;AAEF,MAAM,MAAM,GAAG,CAAC,EAAU,EAAE,EAAE,CAAC,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AAS/E,IAAY,WAMX;AAND,WAAY,WAAW;IACrB,0BAAW,CAAA;IACX,4BAAa,CAAA;IACb,0BAAW,CAAA;IACX,gCAAiB,CAAA;IACjB,8BAAe,CAAA;AACjB,CAAC,EANW,WAAW,GAAX,mBAAW,KAAX,mBAAW,QAMtB"}
|
package/dist/index.js
CHANGED
|
@@ -2,14 +2,18 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
4
4
|
const mcp_server_1 = require("./mcp-server");
|
|
5
|
+
const logger_js_1 = require("./logger.js");
|
|
6
|
+
const logger_js_2 = require("./logger.js");
|
|
5
7
|
const transport = new stdio_js_1.StdioServerTransport();
|
|
6
8
|
transport.onmessage = async (message) => {
|
|
7
|
-
|
|
9
|
+
logger_js_2.log.info(`Loadmill MCP message: ${JSON.stringify(message)}`);
|
|
8
10
|
};
|
|
9
11
|
transport.onerror = async (error) => {
|
|
10
|
-
|
|
12
|
+
logger_js_2.log.error(`Loadmill MCP Server error: ${error?.message || String(error)}`);
|
|
11
13
|
};
|
|
12
14
|
exports.default = async () => {
|
|
13
15
|
await mcp_server_1.mcpServer.connect(transport);
|
|
16
|
+
(0, logger_js_1.getInstance)(mcp_server_1.mcpServer);
|
|
17
|
+
logger_js_2.log.info('Loadmill MCP Server connected over stdio transport');
|
|
14
18
|
};
|
|
15
19
|
//# 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":";;AACA,wEAAiF;AACjF,6CAAyC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;AACA,wEAAiF;AACjF,6CAAyC;AACzC,2CAAuD;AACvD,2CAAkC;AAElC,MAAM,SAAS,GAAG,IAAI,+BAAoB,EAAE,CAAC;AAE7C,SAAS,CAAC,SAAS,GAAG,KAAK,EAAE,OAAO,EAAE,EAAE;IACtC,eAAG,CAAC,IAAI,CAAC,yBAAyB,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;AAC/D,CAAC,CAAC;AAEF,SAAS,CAAC,OAAO,GAAG,KAAK,EAAE,KAAK,EAAE,EAAE;IAClC,eAAG,CAAC,KAAK,CAAC,8BAA8B,KAAK,EAAE,OAAO,IAAI,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;AAC7E,CAAC,CAAC;AAGF,kBAAe,KAAK,IAAI,EAAE;IACxB,MAAM,sBAAS,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IACnC,IAAA,uBAAS,EAAC,sBAAS,CAAC,CAAC;IAErB,eAAG,CAAC,IAAI,CAAC,oDAAoD,CAAC,CAAC;AACjE,CAAC,CAAC"}
|
package/dist/logger.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
2
|
+
import type { LoggingLevel } from '@modelcontextprotocol/sdk/types.js';
|
|
3
|
+
interface Logger {
|
|
4
|
+
info: (message: string) => void;
|
|
5
|
+
error: (message: string) => void;
|
|
6
|
+
}
|
|
7
|
+
declare class LoggerSingleton implements Logger {
|
|
8
|
+
private server;
|
|
9
|
+
constructor(server: Server);
|
|
10
|
+
info(data: string): void;
|
|
11
|
+
error(data: string): void;
|
|
12
|
+
}
|
|
13
|
+
export declare const getInstance: (server?: Server) => LoggerSingleton;
|
|
14
|
+
export declare let log: LoggerSingleton;
|
|
15
|
+
export declare const formatError: (error: unknown) => string;
|
|
16
|
+
export declare const setLogLevel: (level: LoggingLevel) => void;
|
|
17
|
+
export declare const getLogLevel: () => LoggingLevel;
|
|
18
|
+
export {};
|
package/dist/logger.js
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getLogLevel = exports.setLogLevel = exports.formatError = exports.log = exports.getInstance = void 0;
|
|
4
|
+
var LOG_LEVELS;
|
|
5
|
+
(function (LOG_LEVELS) {
|
|
6
|
+
LOG_LEVELS["INFO"] = "info";
|
|
7
|
+
LOG_LEVELS["ERROR"] = "error";
|
|
8
|
+
})(LOG_LEVELS || (LOG_LEVELS = {}));
|
|
9
|
+
let currentLevel = LOG_LEVELS.INFO;
|
|
10
|
+
class LoggerSingleton {
|
|
11
|
+
server;
|
|
12
|
+
constructor(server) {
|
|
13
|
+
this.server = server;
|
|
14
|
+
}
|
|
15
|
+
info(data) {
|
|
16
|
+
this.server.sendLoggingMessage({
|
|
17
|
+
level: LOG_LEVELS.INFO,
|
|
18
|
+
data,
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
error(data) {
|
|
22
|
+
this.server.sendLoggingMessage({
|
|
23
|
+
level: LOG_LEVELS.ERROR,
|
|
24
|
+
data,
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
const getInstance = (server) => {
|
|
29
|
+
if (!exports.log && server) {
|
|
30
|
+
exports.log = new LoggerSingleton(server);
|
|
31
|
+
}
|
|
32
|
+
return exports.log;
|
|
33
|
+
};
|
|
34
|
+
exports.getInstance = getInstance;
|
|
35
|
+
const formatError = (error) => {
|
|
36
|
+
if (error instanceof Error) {
|
|
37
|
+
return error.stack || error.message;
|
|
38
|
+
}
|
|
39
|
+
if (typeof error === 'string') {
|
|
40
|
+
return error;
|
|
41
|
+
}
|
|
42
|
+
try {
|
|
43
|
+
return JSON.stringify(error, null, 2);
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
return String(error);
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
exports.formatError = formatError;
|
|
50
|
+
const setLogLevel = (level) => {
|
|
51
|
+
currentLevel = level;
|
|
52
|
+
};
|
|
53
|
+
exports.setLogLevel = setLogLevel;
|
|
54
|
+
const getLogLevel = () => currentLevel;
|
|
55
|
+
exports.getLogLevel = getLogLevel;
|
|
56
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":";;;AAQA,IAAK,UAGJ;AAHD,WAAK,UAAU;IACb,2BAAa,CAAA;IACb,6BAAe,CAAA;AACjB,CAAC,EAHI,UAAU,KAAV,UAAU,QAGd;AAED,IAAI,YAAY,GAAiB,UAAU,CAAC,IAAI,CAAC;AAEjD,MAAM,eAAe;IAEC;IAApB,YAAoB,MAAc;QAAd,WAAM,GAAN,MAAM,CAAQ;IAAG,CAAC;IAEtC,IAAI,CAAC,IAAY;QACf,IAAI,CAAC,MAAM,CAAC,kBAAkB,CAAC;YAC7B,KAAK,EAAE,UAAU,CAAC,IAAI;YACtB,IAAI;SACL,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,IAAY;QAChB,IAAI,CAAC,MAAM,CAAC,kBAAkB,CAAC;YAC7B,KAAK,EAAE,UAAU,CAAC,KAAK;YACvB,IAAI;SACL,CAAC,CAAC;IACL,CAAC;CACF;AAEM,MAAM,WAAW,GAAG,CAAC,MAAe,EAAmB,EAAE;IAC9D,IAAI,CAAC,WAAG,IAAI,MAAM,EAAE;QAClB,WAAG,GAAG,IAAI,eAAe,CAAC,MAAM,CAAC,CAAC;KACnC;IACD,OAAO,WAAG,CAAC;AACb,CAAC,CAAC;AALW,QAAA,WAAW,eAKtB;AAIK,MAAM,WAAW,GAAG,CAAC,KAAc,EAAU,EAAE;IACpD,IAAI,KAAK,YAAY,KAAK,EAAE;QAC1B,OAAO,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC;KACrC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE;QAC7B,OAAO,KAAK,CAAC;KACd;IACD,IAAI;QACF,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;KACvC;IAAC,MAAM;QACN,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;KACtB;AACH,CAAC,CAAC;AAZW,QAAA,WAAW,eAYtB;AAEK,MAAM,WAAW,GAAG,CAAC,KAAmB,EAAE,EAAE;IACjD,YAAY,GAAG,KAAK,CAAC;AACvB,CAAC,CAAC;AAFW,QAAA,WAAW,eAEtB;AAEK,MAAM,WAAW,GAAG,GAAiB,EAAE,CAAC,YAAY,CAAC;AAA/C,QAAA,WAAW,eAAoC"}
|
package/dist/mcp-handler.js
CHANGED
|
@@ -4,9 +4,11 @@ exports.handlers = void 0;
|
|
|
4
4
|
const tools_1 = require("./handlers/tools");
|
|
5
5
|
const prompts_1 = require("./handlers/prompts");
|
|
6
6
|
const resources_1 = require("./handlers/resources");
|
|
7
|
+
const logging_1 = require("./handlers/logging");
|
|
7
8
|
exports.handlers = [
|
|
8
9
|
...tools_1.handlers,
|
|
9
10
|
...prompts_1.handlers,
|
|
10
11
|
...resources_1.handlers,
|
|
12
|
+
...logging_1.handlers,
|
|
11
13
|
];
|
|
12
14
|
//# sourceMappingURL=mcp-handler.js.map
|
package/dist/mcp-handler.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-handler.js","sourceRoot":"","sources":["../src/mcp-handler.ts"],"names":[],"mappings":";;;AAAA,4CAA6D;AAC7D,gDAAiE;AACjE,oDAAqE;
|
|
1
|
+
{"version":3,"file":"mcp-handler.js","sourceRoot":"","sources":["../src/mcp-handler.ts"],"names":[],"mappings":";;;AAAA,4CAA6D;AAC7D,gDAAiE;AACjE,oDAAqE;AACrE,gDAAiE;AAOpD,QAAA,QAAQ,GAAiB;IACpC,GAAG,gBAAa;IAChB,GAAG,kBAAe;IAClB,GAAG,oBAAiB;IACpB,GAAG,kBAAe;CACnB,CAAC"}
|
package/dist/mcp-server.js
CHANGED
package/dist/mcp-server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-server.js","sourceRoot":"","sources":["../src/mcp-server.ts"],"names":[],"mappings":";;;AAAA,wEAAmE;AACnE,2CAAkE;AAClE,qDAA4C;AAE5C,IAAI,MAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"mcp-server.js","sourceRoot":"","sources":["../src/mcp-server.ts"],"names":[],"mappings":";;;AAAA,wEAAmE;AACnE,2CAAkE;AAClE,qDAA4C;AAE5C,IAAI,MAAc,CAAC;AAEnB,MAAM,UAAU,GAAG,GAAG,EAAE;IACtB,IAAI,CAAC,MAAM,EAAE;QACX,MAAM,GAAG,aAAa,EAAE,CAAC;KAC1B;IACD,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC;AAEF,MAAM,aAAa,GAAG,GAAG,EAAE;IACzB,MAAM,GAAG,IAAI,iBAAM,CACjB;QACE,IAAI,EAAE,2BAAe;QACrB,OAAO,EAAE,8BAAkB;KAC5B,EACD;QACE,YAAY,EAAE;YACZ,OAAO,EAAE,EAAE;YACX,SAAS,EAAE,EAAE;YACb,KAAK,EAAE,EAAE;YACT,OAAO,EAAE,EAAE;SACZ;KACF,CACF,CAAC;IAGF,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAE1B,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,KAAK,IAAI,EAAE;QAC9B,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;IACvB,CAAC,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC;AAEF,MAAM,iBAAiB,GAAG,CAAC,MAAM,EAAE,EAAE;IACnC,yBAAQ,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC3B,MAAM,CAAC,iBAAiB,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC;AAEW,QAAA,SAAS,GAAG,UAAU,EAAE,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@loadmill/mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Loadmill mcp library",
|
|
5
5
|
"main": "dist/",
|
|
6
6
|
"module": "src/",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
},
|
|
19
19
|
"license": "Apache-2.0",
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
21
|
+
"@modelcontextprotocol/sdk": "^1.21.1",
|
|
22
22
|
"ajv": "^8.17.1",
|
|
23
23
|
"ajv-formats": "^3.0.1",
|
|
24
24
|
"superagent": "^10.0.1"
|