pictmcp 0.2.0 → 0.3.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 +7 -14
- package/dist/index.d.ts +1 -3
- package/dist/index.js +7 -42
- package/dist/server.d.ts +4 -0
- package/dist/server.js +86 -0
- package/package.json +26 -9
- package/dist/index.spec.d.ts +0 -1
- package/dist/index.spec.js +0 -25
package/README.md
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
# PictMCP
|
|
2
2
|
|
|
3
|
-
Pairwise Independent Combinatorial Testings for MCP
|
|
4
|
-
|
|
5
3
|
## 🚧 Work in Progress 🚧
|
|
6
4
|
|
|
7
5
|
> [!WARNING]
|
|
@@ -10,32 +8,27 @@ Pairwise Independent Combinatorial Testings for MCP
|
|
|
10
8
|
>
|
|
11
9
|
> Use in production environments is **not recommended** at this time.
|
|
12
10
|
|
|
11
|
+
## Project overview
|
|
12
|
+
|
|
13
|
+
PictMCP is an MCP (Model Context Protocol) server that provides pairwise combinatorial testing capabilities to AI assistants. It wraps the PICT (Pairwise Independent Combinatorial Testing) algorithm via WebAssembly, enabling AI clients to generate optimized test case combinations.
|
|
14
|
+
|
|
13
15
|
## Install
|
|
14
16
|
|
|
15
17
|
### Prerequisites
|
|
16
18
|
|
|
17
|
-
- [Node.js](https://nodejs.org/) (
|
|
19
|
+
- [Node.js](https://nodejs.org/) (v24 or higher)
|
|
18
20
|
- [pnpm](https://pnpm.io/) (v10 or higher)
|
|
19
21
|
|
|
20
22
|
### Commands
|
|
21
23
|
|
|
22
|
-
In your terminal
|
|
23
|
-
|
|
24
|
-
```sh
|
|
25
|
-
git clone https://github.com/takeyaqa/PictMCP.git
|
|
26
|
-
cd PictMCP
|
|
27
|
-
pnpm install
|
|
28
|
-
pnpm build
|
|
29
|
-
```
|
|
30
|
-
|
|
31
24
|
In your MCP client
|
|
32
25
|
|
|
33
26
|
```json
|
|
34
27
|
{
|
|
35
28
|
"mcpServers": {
|
|
36
29
|
"PictMCP": {
|
|
37
|
-
"command": "
|
|
38
|
-
"args": ["
|
|
30
|
+
"command": "pnpx",
|
|
31
|
+
"args": ["pictmcp"]
|
|
39
32
|
}
|
|
40
33
|
}
|
|
41
34
|
}
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,50 +1,15 @@
|
|
|
1
|
-
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
1
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
3
|
-
import {
|
|
4
|
-
import { PictRunner } from "@takeyaqa/pict-wasm";
|
|
5
|
-
// Create server instance
|
|
6
|
-
const server = new McpServer({
|
|
7
|
-
name: "PictMCP",
|
|
8
|
-
version: "0.2.0",
|
|
9
|
-
});
|
|
10
|
-
// Register pict tools
|
|
11
|
-
server.registerTool("generate-test-cases", {
|
|
12
|
-
description: "Generates test cases using pairwise combination algorithm",
|
|
13
|
-
inputSchema: {
|
|
14
|
-
parameters: z
|
|
15
|
-
.object({ name: z.string(), values: z.string() })
|
|
16
|
-
.array()
|
|
17
|
-
.describe("Parameters for the test case generation"),
|
|
18
|
-
constraints: z
|
|
19
|
-
.string()
|
|
20
|
-
.optional()
|
|
21
|
-
.describe("Constraints for the test case generation"),
|
|
22
|
-
},
|
|
23
|
-
}, async ({ parameters, constraints }) => {
|
|
24
|
-
const pictRunner = new PictRunner();
|
|
25
|
-
await pictRunner.init();
|
|
26
|
-
const output = pictRunner.run(parameters, { constraintsText: constraints });
|
|
27
|
-
const formattedOutput = output.body.map((row) => row.map((cell) => cell.trim()).join(", "));
|
|
28
|
-
const formattedHeader = output.header.map((cell) => cell.trim()).join(", ");
|
|
29
|
-
const formattedBody = formattedOutput.join("\n");
|
|
30
|
-
const formattedOutputText = `Header: ${formattedHeader}\nBody:\n${formattedBody}`;
|
|
31
|
-
return {
|
|
32
|
-
content: [
|
|
33
|
-
{
|
|
34
|
-
type: "text",
|
|
35
|
-
text: formattedOutputText,
|
|
36
|
-
},
|
|
37
|
-
],
|
|
38
|
-
};
|
|
39
|
-
});
|
|
40
|
-
// export for testing purposes
|
|
41
|
-
export { server };
|
|
2
|
+
import { PictMcpServer } from "./server.js";
|
|
42
3
|
async function main() {
|
|
4
|
+
const server = new PictMcpServer();
|
|
43
5
|
const transport = new StdioServerTransport();
|
|
44
6
|
await server.connect(transport);
|
|
45
7
|
console.error("PictMCP Server running on stdio");
|
|
46
8
|
}
|
|
47
|
-
|
|
9
|
+
try {
|
|
10
|
+
await main();
|
|
11
|
+
}
|
|
12
|
+
catch (error) {
|
|
48
13
|
console.error("Fatal error in main():", error);
|
|
49
14
|
process.exit(1);
|
|
50
|
-
}
|
|
15
|
+
}
|
package/dist/server.d.ts
ADDED
package/dist/server.js
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { PictRunner } from "@takeyaqa/pict-wasm";
|
|
4
|
+
export class PictMcpServer extends McpServer {
|
|
5
|
+
constructor() {
|
|
6
|
+
super({
|
|
7
|
+
name: "io.github.takeyaqa/PictMCP",
|
|
8
|
+
title: "PictMCP",
|
|
9
|
+
version: "0.3.0",
|
|
10
|
+
description: "Provides pairwise combinatorial testing capabilities to AI assistants.",
|
|
11
|
+
websiteUrl: "https://github.com/takeyaqa/PictMCP#readme",
|
|
12
|
+
icons: [
|
|
13
|
+
{
|
|
14
|
+
src: "https://raw.githubusercontent.com/takeyaqa/PictMCP/main/assets/PictMCP_icon@64x64.png",
|
|
15
|
+
mimeType: "image/png",
|
|
16
|
+
sizes: ["64x64"],
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
src: "https://raw.githubusercontent.com/takeyaqa/PictMCP/main/assets/PictMCP_icon.svg",
|
|
20
|
+
mimeType: "image/svg+xml",
|
|
21
|
+
sizes: ["any"],
|
|
22
|
+
},
|
|
23
|
+
],
|
|
24
|
+
});
|
|
25
|
+
// Register pict tools
|
|
26
|
+
this.registerTool("generate-test-cases", {
|
|
27
|
+
title: "Generate test cases",
|
|
28
|
+
description: "Executes PICT with the given parameters and options to generate test cases.",
|
|
29
|
+
inputSchema: {
|
|
30
|
+
parameters: z
|
|
31
|
+
.object({
|
|
32
|
+
name: z.string().describe("The name of the parameter."),
|
|
33
|
+
values: z
|
|
34
|
+
.string()
|
|
35
|
+
.describe("A comma-separated string of possible values for this parameter."),
|
|
36
|
+
})
|
|
37
|
+
.array()
|
|
38
|
+
.describe("Represents a parameter definition for PICT test case generation."),
|
|
39
|
+
constraintsText: z
|
|
40
|
+
.string()
|
|
41
|
+
.optional()
|
|
42
|
+
.describe("PICT constraint expressions to filter invalid combinations."),
|
|
43
|
+
},
|
|
44
|
+
outputSchema: {
|
|
45
|
+
result: z
|
|
46
|
+
.object({
|
|
47
|
+
header: z
|
|
48
|
+
.string()
|
|
49
|
+
.array()
|
|
50
|
+
.describe("An array of parameter names representing the column headers."),
|
|
51
|
+
body: z
|
|
52
|
+
.string()
|
|
53
|
+
.array()
|
|
54
|
+
.array()
|
|
55
|
+
.describe("A two-dimensional array where each inner array represents a test case, with values corresponding to the header columns."),
|
|
56
|
+
})
|
|
57
|
+
.describe("Represents the parsed result of PICT test case generation."),
|
|
58
|
+
modelFile: z
|
|
59
|
+
.string()
|
|
60
|
+
.describe("The complete model file content that was passed to PICT."),
|
|
61
|
+
message: z
|
|
62
|
+
.string()
|
|
63
|
+
.optional()
|
|
64
|
+
.describe("Optional message output from PICT, typically containing information."),
|
|
65
|
+
},
|
|
66
|
+
}, async ({ parameters, constraintsText }) => {
|
|
67
|
+
const pictRunner = await PictRunner.create();
|
|
68
|
+
const output = pictRunner.run(parameters, {
|
|
69
|
+
constraintsText,
|
|
70
|
+
});
|
|
71
|
+
return {
|
|
72
|
+
structuredContent: {
|
|
73
|
+
result: output.result,
|
|
74
|
+
modelFile: output.modelFile,
|
|
75
|
+
message: output.message,
|
|
76
|
+
},
|
|
77
|
+
content: [
|
|
78
|
+
{
|
|
79
|
+
type: "text",
|
|
80
|
+
text: JSON.stringify(output),
|
|
81
|
+
},
|
|
82
|
+
],
|
|
83
|
+
};
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
}
|
package/package.json
CHANGED
|
@@ -1,9 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pictmcp",
|
|
3
3
|
"mcpName": "io.github.takeyaqa/PictMCP",
|
|
4
|
-
"version": "0.
|
|
5
|
-
"description": "
|
|
6
|
-
"keywords": [
|
|
4
|
+
"version": "0.3.0",
|
|
5
|
+
"description": "MCP (Model Context Protocol) server that provides pairwise combinatorial testing capabilities to AI assistants.",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"mcp",
|
|
8
|
+
"mcp-server",
|
|
9
|
+
"ai",
|
|
10
|
+
"pict",
|
|
11
|
+
"testing",
|
|
12
|
+
"testing-tools",
|
|
13
|
+
"test-case-generation",
|
|
14
|
+
"combinatorial-testing",
|
|
15
|
+
"pairwise",
|
|
16
|
+
"pairwise-testing"
|
|
17
|
+
],
|
|
7
18
|
"homepage": "https://github.com/takeyaqa/PictMCP#readme",
|
|
8
19
|
"bugs": {
|
|
9
20
|
"url": "https://github.com/takeyaqa/PictMCP/issues"
|
|
@@ -23,21 +34,25 @@
|
|
|
23
34
|
},
|
|
24
35
|
"dependencies": {
|
|
25
36
|
"@modelcontextprotocol/sdk": "^1.25.2",
|
|
26
|
-
"@takeyaqa/pict-wasm": "3.7.4-wasm.
|
|
37
|
+
"@takeyaqa/pict-wasm": "3.7.4-wasm.12",
|
|
27
38
|
"zod": "^4.3.5"
|
|
28
39
|
},
|
|
29
40
|
"devDependencies": {
|
|
30
41
|
"@eslint/js": "^9.39.2",
|
|
42
|
+
"@tsconfig/node-ts": "^23.6.2",
|
|
31
43
|
"@tsconfig/node24": "^24.0.4",
|
|
32
44
|
"@types/node": "^25.0.9",
|
|
45
|
+
"@vitest/eslint-plugin": "^1.6.6",
|
|
33
46
|
"eslint": "^9.39.2",
|
|
34
47
|
"eslint-config-prettier": "^10.1.8",
|
|
35
|
-
"globals": "^17.0.0",
|
|
36
48
|
"prettier": "^3.8.0",
|
|
37
49
|
"typescript": "~5.9.3",
|
|
38
|
-
"typescript-eslint": "^8.
|
|
50
|
+
"typescript-eslint": "^8.54.0",
|
|
39
51
|
"vitest": "^4.0.17"
|
|
40
52
|
},
|
|
53
|
+
"engines": {
|
|
54
|
+
"node": ">=24"
|
|
55
|
+
},
|
|
41
56
|
"devEngines": {
|
|
42
57
|
"runtime": {
|
|
43
58
|
"name": "node",
|
|
@@ -53,10 +68,12 @@
|
|
|
53
68
|
"scripts": {
|
|
54
69
|
"build": "tsc && chmod 755 dist/index.js",
|
|
55
70
|
"clean": "rm -rf dist",
|
|
56
|
-
"
|
|
71
|
+
"fmt": "prettier --write .",
|
|
72
|
+
"fmt:check": "prettier --check .",
|
|
57
73
|
"lint": "eslint .",
|
|
58
|
-
"
|
|
74
|
+
"lint:fix": "eslint --fix .",
|
|
75
|
+
"typecheck": "tsc --project tsconfig.typecheck.json",
|
|
59
76
|
"test": "vitest",
|
|
60
|
-
"test:
|
|
77
|
+
"test:run": "vitest run"
|
|
61
78
|
}
|
|
62
79
|
}
|
package/dist/index.spec.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
package/dist/index.spec.js
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, beforeEach, afterEach } from "vitest";
|
|
2
|
-
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
3
|
-
import { InMemoryTransport } from "@modelcontextprotocol/sdk/inMemory.js";
|
|
4
|
-
import packageJson from "../package.json" with { type: "json" };
|
|
5
|
-
import serverJson from "../server.json" with { type: "json" };
|
|
6
|
-
import { server } from "./index.js";
|
|
7
|
-
describe("PictMCP Server", () => {
|
|
8
|
-
let client;
|
|
9
|
-
beforeEach(async () => {
|
|
10
|
-
const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
|
|
11
|
-
client = new Client({ name: "test-client", version: "1.0.0" });
|
|
12
|
-
await server.connect(serverTransport);
|
|
13
|
-
await client.connect(clientTransport);
|
|
14
|
-
});
|
|
15
|
-
afterEach(async () => {
|
|
16
|
-
await client.close();
|
|
17
|
-
await server.close();
|
|
18
|
-
});
|
|
19
|
-
it("should return version matching package configuration", async () => {
|
|
20
|
-
const serverVersion = client.getServerVersion();
|
|
21
|
-
expect(serverVersion?.version).toBe(packageJson.version);
|
|
22
|
-
expect(serverVersion?.version).toBe(serverJson.version);
|
|
23
|
-
expect(serverVersion?.version).toBe(serverJson.packages[0].version);
|
|
24
|
-
});
|
|
25
|
-
});
|