mcp-apps-testing 0.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Aviv Eldan
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,159 @@
1
+ # mcp-apps-testing
2
+
3
+ **The first UI testing framework built specifically for Model Context Protocol applications.** Test your MCP apps exactly how users experience them—with real browser rendering, simulated IDE environments, and complete JSON-RPC message control.
4
+
5
+ ![Hello World App](docs/images/hello-world-result.png)
6
+
7
+ ## Why mcp-apps-testing?
8
+
9
+ Building MCP applications? You need to test more than just the protocol—you need to verify UI rendering, sandboxing behavior, and real-world interactions across different host environments (Claude, VS Code, etc.). **This is the framework that does all three.**
10
+
11
+ **Zero-Config Testing**
12
+ ```typescript
13
+ const host = new MockMCPHost({ hostProfile: 'Claude' });
14
+ await host.callTool('greet', { name: 'World' });
15
+ ```
16
+
17
+ **What Makes It Unique**
18
+ - **Host Simulation**: Test against Claude, VS Code, or custom IDE profiles with different capabilities and themes
19
+ - **Full Control**: Mock, intercept, and assert on every JSON-RPC message
20
+ - **UI + Protocol**: Tests both UI rendering AND protocol interactions in a single framework
21
+ - **Fluent API**: Human-readable test code with auto-retry and intelligent defaults
22
+
23
+ ## Quick Start
24
+
25
+ ### Installation
26
+
27
+ Install the package along with its peer dependency:
28
+
29
+ ```bash
30
+ npm install mcp-apps-testing @playwright/test --save-dev
31
+ npx playwright install chromium
32
+ ```
33
+
34
+ **Write Your First Test**
35
+ ```typescript
36
+ import { test, expect } from '@playwright/test';
37
+ import { MockMCPHost } from 'mcp-apps-testing';
38
+
39
+ test('MCP app responds to tool calls', async () => {
40
+ const host = new MockMCPHost({ hostProfile: 'Claude' });
41
+
42
+ // Mock the tool response
43
+ host.getInterceptor().mockResponse('tools/call', (req) => ({
44
+ jsonrpc: '2.0',
45
+ id: req.id,
46
+ result: { content: [{ type: 'text', text: 'Hello, World!' }] }
47
+ }));
48
+
49
+ // Call the tool with fluent API
50
+ const response = await host.callTool('greet', { name: 'World' });
51
+ expect(response.result.content[0].text).toBe('Hello, World!');
52
+
53
+ await host.cleanup();
54
+ });
55
+ ```
56
+
57
+ **Run tests**: `npm test`
58
+
59
+ ## Key Features
60
+
61
+ ### Simulate Real IDE Environments
62
+ Test your MCP app against different host profiles with specific capabilities, themes, and constraints:
63
+ ```typescript
64
+ new MockMCPHost({ hostProfile: 'Claude' }) // Full MCP capabilities
65
+ new MockMCPHost({ hostProfile: 'VSCode' }) // Editor-specific constraints
66
+ ```
67
+
68
+ ### Complete Message Control
69
+ Mock, intercept, and record every JSON-RPC interaction:
70
+ ```typescript
71
+ // Mock responses
72
+ host.getInterceptor().mockResponse('tools/call', yourHandler);
73
+
74
+ // Record and assert
75
+ const requests = host.getInterceptor().getRecordedRequests();
76
+ expect(requests[0].method).toBe('initialize');
77
+ ```
78
+
79
+ ### Test UI + Protocol Together
80
+ Validate both visual rendering AND protocol behavior in the same test:
81
+ ```typescript
82
+ // Test UI rendering
83
+ await page.goto('your-mcp-app.html');
84
+ await expect(page.locator('h1')).toBeVisible();
85
+
86
+ // Test protocol interaction
87
+ const response = await host.callTool('greet', { name: 'Test' });
88
+ ```
89
+
90
+ ## Architecture
91
+
92
+ ![Architecture Diagram](docs/images/architecture.svg)
93
+
94
+ **Core Components**
95
+ - **MockMCPHost**: Simulates IDE hosting environment with auto-response to common protocol messages
96
+ - **TransportInterceptor**: Mocks and records JSON-RPC messages for testing and assertions
97
+ - **Host Profiles**: Pre-configured environments (Claude, VS Code, Generic) with capabilities and themes
98
+
99
+ ## Examples
100
+
101
+ See the [examples/](examples/) directory for complete working examples:
102
+ - **hello-world.spec.ts**: Full UI testing with theme switching and tool calls
103
+ - **basic-test.spec.ts**: Protocol-focused testing with message mocking
104
+
105
+ ![Test Results](docs/images/test-results.svg)
106
+
107
+ ## Documentation
108
+
109
+ - [Getting Started Guide](docs/getting-started.md) - Detailed setup and first steps
110
+ - [API Reference](docs/api-reference.md) - Complete API documentation
111
+ - [Example App](examples/hello-world-app.html) - Sample MCP application
112
+
113
+ ## Commands
114
+
115
+ ```bash
116
+ npm test # Run all tests
117
+ npm run test:ui # Run with Playwright UI
118
+ npm run build # Build the framework
119
+ npm run dev # Development mode with watch
120
+ ```
121
+
122
+ ## Publishing
123
+
124
+ This package is automatically published to npm via GitHub Actions when a new release is created.
125
+
126
+ ### Publishing a New Version
127
+
128
+ 1. Update the version in `package.json` following [semantic versioning](https://semver.org/)
129
+ 2. Commit and push the version change
130
+ 3. Create a new GitHub release with a tag matching the version (e.g., `v0.1.0`)
131
+ 4. The GitHub Actions workflow will automatically:
132
+ - Build the package
133
+ - Run tests
134
+ - Publish to npm using the `NPM_PAT` secret from the `npm-publish` environment
135
+
136
+ ### Manual Publishing (if needed)
137
+
138
+ To publish manually:
139
+ ```bash
140
+ npm run build
141
+ npm test
142
+ npm publish
143
+ ```
144
+
145
+ The `prepublishOnly` script ensures a clean build is created before publishing.
146
+
147
+ ## Contributing
148
+
149
+ This framework is designed for professional MCP UI application testing. Contributions should maintain the modular architecture and focus on core testing capabilities.
150
+
151
+ ## License
152
+
153
+ MIT
154
+
155
+ ---
156
+
157
+ **Built with:** TypeScript • Playwright • [@modelcontextprotocol/sdk](https://github.com/modelcontextprotocol/typescript-sdk)
158
+
159
+ **Learn more:** [Model Context Protocol](https://modelcontextprotocol.io/) • [Playwright](https://playwright.dev/)
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Host Profiles - Simulates different MCP host environments
3
+ *
4
+ * This module provides pre-configured profiles for different AI host environments
5
+ * like Claude, VS Code, etc., including their specific capabilities, theme variables,
6
+ * and constraints.
7
+ */
8
+ export interface HostProfile {
9
+ name: string;
10
+ capabilities: {
11
+ tools?: {
12
+ listChanged?: boolean;
13
+ };
14
+ resources?: {
15
+ subscribe?: boolean;
16
+ listChanged?: boolean;
17
+ };
18
+ prompts?: {
19
+ listChanged?: boolean;
20
+ };
21
+ };
22
+ theme: {
23
+ light: Record<string, string>;
24
+ dark: Record<string, string>;
25
+ };
26
+ constraints?: {
27
+ maxViewportWidth?: number;
28
+ maxViewportHeight?: number;
29
+ allowedProtocols?: string[];
30
+ };
31
+ }
32
+ /**
33
+ * Claude AI host profile
34
+ */
35
+ export declare const ClaudeProfile: HostProfile;
36
+ /**
37
+ * VS Code host profile
38
+ */
39
+ export declare const VSCodeProfile: HostProfile;
40
+ /**
41
+ * Generic host profile (default)
42
+ */
43
+ export declare const GenericProfile: HostProfile;
44
+ /**
45
+ * Available host profiles
46
+ */
47
+ export declare const HostProfiles: {
48
+ readonly Claude: HostProfile;
49
+ readonly VSCode: HostProfile;
50
+ readonly Generic: HostProfile;
51
+ };
52
+ /**
53
+ * Apply theme CSS variables to a page or element
54
+ */
55
+ export declare function applyTheme(profile: HostProfile, mode?: 'light' | 'dark'): string;
56
+ //# sourceMappingURL=HostProfiles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HostProfiles.d.ts","sourceRoot":"","sources":["../../src/core/HostProfiles.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE;QACZ,KAAK,CAAC,EAAE;YAAE,WAAW,CAAC,EAAE,OAAO,CAAA;SAAE,CAAC;QAClC,SAAS,CAAC,EAAE;YAAE,SAAS,CAAC,EAAE,OAAO,CAAC;YAAC,WAAW,CAAC,EAAE,OAAO,CAAA;SAAE,CAAC;QAC3D,OAAO,CAAC,EAAE;YAAE,WAAW,CAAC,EAAE,OAAO,CAAA;SAAE,CAAC;KACrC,CAAC;IACF,KAAK,EAAE;QACL,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC9B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KAC9B,CAAC;IACF,WAAW,CAAC,EAAE;QACZ,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,iBAAiB,CAAC,EAAE,MAAM,CAAC;QAC3B,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;KAC7B,CAAC;CACH;AAED;;GAEG;AACH,eAAO,MAAM,aAAa,EAAE,WAgC3B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,aAAa,EAAE,WAgC3B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,cAAc,EAAE,WA2B5B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,YAAY;;;;CAIf,CAAC;AAEX;;GAEG;AACH,wBAAgB,UAAU,CACxB,OAAO,EAAE,WAAW,EACpB,IAAI,GAAE,OAAO,GAAG,MAAgB,GAC/B,MAAM,CAKR"}
@@ -0,0 +1,132 @@
1
+ "use strict";
2
+ /**
3
+ * Host Profiles - Simulates different MCP host environments
4
+ *
5
+ * This module provides pre-configured profiles for different AI host environments
6
+ * like Claude, VS Code, etc., including their specific capabilities, theme variables,
7
+ * and constraints.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.HostProfiles = exports.GenericProfile = exports.VSCodeProfile = exports.ClaudeProfile = void 0;
11
+ exports.applyTheme = applyTheme;
12
+ /**
13
+ * Claude AI host profile
14
+ */
15
+ exports.ClaudeProfile = {
16
+ name: 'Claude',
17
+ capabilities: {
18
+ tools: { listChanged: true },
19
+ resources: { subscribe: true, listChanged: true },
20
+ prompts: { listChanged: true },
21
+ },
22
+ theme: {
23
+ light: {
24
+ '--background': '#ffffff',
25
+ '--foreground': '#1a1a1a',
26
+ '--primary': '#6366f1',
27
+ '--secondary': '#8b5cf6',
28
+ '--accent': '#ec4899',
29
+ '--muted': '#f3f4f6',
30
+ '--border': '#e5e7eb',
31
+ },
32
+ dark: {
33
+ '--background': '#1a1a1a',
34
+ '--foreground': '#ffffff',
35
+ '--primary': '#818cf8',
36
+ '--secondary': '#a78bfa',
37
+ '--accent': '#f472b6',
38
+ '--muted': '#374151',
39
+ '--border': '#4b5563',
40
+ },
41
+ },
42
+ constraints: {
43
+ maxViewportWidth: 1920,
44
+ maxViewportHeight: 1080,
45
+ allowedProtocols: ['http', 'https', 'data'],
46
+ },
47
+ };
48
+ /**
49
+ * VS Code host profile
50
+ */
51
+ exports.VSCodeProfile = {
52
+ name: 'VS Code',
53
+ capabilities: {
54
+ tools: { listChanged: true },
55
+ resources: { subscribe: false, listChanged: true },
56
+ prompts: { listChanged: false },
57
+ },
58
+ theme: {
59
+ light: {
60
+ '--background': '#ffffff',
61
+ '--foreground': '#333333',
62
+ '--primary': '#007acc',
63
+ '--secondary': '#68217a',
64
+ '--accent': '#0098ff',
65
+ '--muted': '#f3f3f3',
66
+ '--border': '#cccccc',
67
+ },
68
+ dark: {
69
+ '--background': '#1e1e1e',
70
+ '--foreground': '#cccccc',
71
+ '--primary': '#0098ff',
72
+ '--secondary': '#c586c0',
73
+ '--accent': '#4fc1ff',
74
+ '--muted': '#2d2d2d',
75
+ '--border': '#3e3e3e',
76
+ },
77
+ },
78
+ constraints: {
79
+ maxViewportWidth: 1600,
80
+ maxViewportHeight: 900,
81
+ allowedProtocols: ['http', 'https', 'vscode', 'data'],
82
+ },
83
+ };
84
+ /**
85
+ * Generic host profile (default)
86
+ */
87
+ exports.GenericProfile = {
88
+ name: 'Generic',
89
+ capabilities: {
90
+ tools: { listChanged: true },
91
+ resources: { subscribe: true, listChanged: true },
92
+ prompts: { listChanged: true },
93
+ },
94
+ theme: {
95
+ light: {
96
+ '--background': '#ffffff',
97
+ '--foreground': '#000000',
98
+ '--primary': '#0066cc',
99
+ '--secondary': '#6600cc',
100
+ '--accent': '#cc0066',
101
+ '--muted': '#f5f5f5',
102
+ '--border': '#dddddd',
103
+ },
104
+ dark: {
105
+ '--background': '#000000',
106
+ '--foreground': '#ffffff',
107
+ '--primary': '#3399ff',
108
+ '--secondary': '#9933ff',
109
+ '--accent': '#ff3399',
110
+ '--muted': '#333333',
111
+ '--border': '#555555',
112
+ },
113
+ },
114
+ };
115
+ /**
116
+ * Available host profiles
117
+ */
118
+ exports.HostProfiles = {
119
+ Claude: exports.ClaudeProfile,
120
+ VSCode: exports.VSCodeProfile,
121
+ Generic: exports.GenericProfile,
122
+ };
123
+ /**
124
+ * Apply theme CSS variables to a page or element
125
+ */
126
+ function applyTheme(profile, mode = 'light') {
127
+ const themeVars = profile.theme[mode];
128
+ return Object.entries(themeVars)
129
+ .map(([key, value]) => `${key}: ${value};`)
130
+ .join('\n');
131
+ }
132
+ //# sourceMappingURL=HostProfiles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HostProfiles.js","sourceRoot":"","sources":["../../src/core/HostProfiles.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,108 @@
1
+ import { TransportInterceptor } from './TransportInterceptor';
2
+ import { MockMCPHostConfig, MCPCapabilities, JSONRPCRequest, JSONRPCResponse } from '../types';
3
+ import { HostProfile } from './HostProfiles';
4
+ /**
5
+ * MockMCPHost - Simulates an IDE environment hosting an MCP server
6
+ *
7
+ * This class provides:
8
+ * - A simulated MCP host environment for testing
9
+ * - Automatic handling of common MCP protocol messages
10
+ * - Integration with TransportInterceptor for request/response mocking
11
+ * - Capability simulation (tools, resources, prompts)
12
+ * - Host profile simulation (Claude, VS Code, etc.)
13
+ */
14
+ export declare class MockMCPHost {
15
+ private interceptor;
16
+ private config;
17
+ private capabilities;
18
+ private initialized;
19
+ private requestIdCounter;
20
+ private hostProfile;
21
+ constructor(config?: MockMCPHostConfig);
22
+ /**
23
+ * Load a host profile
24
+ */
25
+ private loadHostProfile;
26
+ /**
27
+ * Get the current host profile
28
+ */
29
+ getHostProfile(): HostProfile | null;
30
+ /**
31
+ * Get the transport interceptor
32
+ */
33
+ getInterceptor(): TransportInterceptor;
34
+ /**
35
+ * Set up automatic responses for common MCP protocol messages
36
+ */
37
+ private setupAutoResponders;
38
+ /**
39
+ * Set capabilities that this host supports
40
+ */
41
+ setCapabilities(capabilities: MCPCapabilities): void;
42
+ /**
43
+ * Send a request to the server (simulate client -> server)
44
+ */
45
+ sendRequest(method: string, params?: unknown): Promise<JSONRPCResponse>;
46
+ /**
47
+ * Initialize the MCP connection
48
+ */
49
+ initialize(clientInfo?: {
50
+ name: string;
51
+ version: string;
52
+ }): Promise<JSONRPCResponse>;
53
+ /**
54
+ * Check if the host is initialized
55
+ */
56
+ isInitialized(): boolean;
57
+ /**
58
+ * Cleanup and reset the host
59
+ */
60
+ cleanup(): Promise<void>;
61
+ /**
62
+ * Get all recorded messages from the interceptor
63
+ */
64
+ getRecordedMessages(): (JSONRPCRequest | JSONRPCResponse | import("../types").JSONRPCNotification)[];
65
+ /**
66
+ * Clear recorded messages
67
+ */
68
+ clearRecordedMessages(): void;
69
+ /**
70
+ * Fluent DSL: Call a tool with automatic response handling
71
+ * @param name Tool name
72
+ * @param args Tool arguments
73
+ * @param options Optional retry and timeout settings
74
+ */
75
+ callTool(name: string, args?: Record<string, unknown>, options?: {
76
+ timeout?: number;
77
+ retries?: number;
78
+ }): Promise<JSONRPCResponse>;
79
+ /**
80
+ * Fluent DSL: List available tools
81
+ */
82
+ listTools(): Promise<JSONRPCResponse>;
83
+ /**
84
+ * Fluent DSL: Read a resource
85
+ * @param uri Resource URI
86
+ */
87
+ readResource(uri: string): Promise<JSONRPCResponse>;
88
+ /**
89
+ * Fluent DSL: List available resources
90
+ */
91
+ listResources(): Promise<JSONRPCResponse>;
92
+ /**
93
+ * Fluent DSL: Get a prompt
94
+ * @param name Prompt name
95
+ * @param args Prompt arguments
96
+ */
97
+ getPrompt(name: string, args?: Record<string, unknown>): Promise<JSONRPCResponse>;
98
+ /**
99
+ * Fluent DSL: List available prompts
100
+ */
101
+ listPrompts(): Promise<JSONRPCResponse>;
102
+ /**
103
+ * Enable protocol logging for debugging
104
+ */
105
+ private protocolLoggingEnabled;
106
+ enableProtocolLogging(): void;
107
+ }
108
+ //# sourceMappingURL=MockMCPHost.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MockMCPHost.d.ts","sourceRoot":"","sources":["../../src/core/MockMCPHost.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAC/F,OAAO,EAAgB,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE3D;;;;;;;;;GASG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,WAAW,CAAuB;IAC1C,OAAO,CAAC,MAAM,CAAoB;IAClC,OAAO,CAAC,YAAY,CAAkB;IACtC,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,gBAAgB,CAAK;IAC7B,OAAO,CAAC,WAAW,CAA4B;gBAEnC,MAAM,GAAE,iBAAsB;IAoB1C;;OAEG;IACH,OAAO,CAAC,eAAe;IAQvB;;OAEG;IACH,cAAc,IAAI,WAAW,GAAG,IAAI;IAIpC;;OAEG;IACH,cAAc,IAAI,oBAAoB;IAItC;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAqD3B;;OAEG;IACH,eAAe,CAAC,YAAY,EAAE,eAAe,GAAG,IAAI;IAIpD;;OAEG;IACG,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,eAAe,CAAC;IA8B7E;;OAEG;IACG,UAAU,CAAC,UAAU,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,eAAe,CAAC;IAW1F;;OAEG;IACH,aAAa,IAAI,OAAO;IAIxB;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAM9B;;OAEG;IACH,mBAAmB;IAInB;;OAEG;IACH,qBAAqB,IAAI,IAAI;IAI7B;;;;;OAKG;IACG,QAAQ,CACZ,IAAI,EAAE,MAAM,EACZ,IAAI,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,EAClC,OAAO,GAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAO,GACnD,OAAO,CAAC,eAAe,CAAC;IA6B3B;;OAEG;IACG,SAAS,IAAI,OAAO,CAAC,eAAe,CAAC;IAI3C;;;OAGG;IACG,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAIzD;;OAEG;IACG,aAAa,IAAI,OAAO,CAAC,eAAe,CAAC;IAI/C;;;;OAIG;IACG,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAI3F;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,eAAe,CAAC;IAI7C;;OAEG;IACH,OAAO,CAAC,sBAAsB,CAAS;IAEvC,qBAAqB,IAAI,IAAI;CAkB9B"}
@@ -0,0 +1,265 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MockMCPHost = void 0;
4
+ const TransportInterceptor_1 = require("./TransportInterceptor");
5
+ const HostProfiles_1 = require("./HostProfiles");
6
+ /**
7
+ * MockMCPHost - Simulates an IDE environment hosting an MCP server
8
+ *
9
+ * This class provides:
10
+ * - A simulated MCP host environment for testing
11
+ * - Automatic handling of common MCP protocol messages
12
+ * - Integration with TransportInterceptor for request/response mocking
13
+ * - Capability simulation (tools, resources, prompts)
14
+ * - Host profile simulation (Claude, VS Code, etc.)
15
+ */
16
+ class MockMCPHost {
17
+ constructor(config = {}) {
18
+ this.initialized = false;
19
+ this.requestIdCounter = 0;
20
+ this.hostProfile = null;
21
+ /**
22
+ * Enable protocol logging for debugging
23
+ */
24
+ this.protocolLoggingEnabled = false;
25
+ this.config = {
26
+ autoRespond: true,
27
+ debug: false,
28
+ ...config,
29
+ };
30
+ this.interceptor = new TransportInterceptor_1.TransportInterceptor(this.config.debug);
31
+ this.capabilities = {};
32
+ // Load host profile if specified
33
+ if (this.config.hostProfile) {
34
+ this.loadHostProfile(this.config.hostProfile);
35
+ }
36
+ if (this.config.autoRespond) {
37
+ this.setupAutoResponders();
38
+ }
39
+ }
40
+ /**
41
+ * Load a host profile
42
+ */
43
+ loadHostProfile(profileName) {
44
+ const profile = HostProfiles_1.HostProfiles[profileName];
45
+ if (profile) {
46
+ this.hostProfile = profile;
47
+ this.capabilities = profile.capabilities;
48
+ }
49
+ }
50
+ /**
51
+ * Get the current host profile
52
+ */
53
+ getHostProfile() {
54
+ return this.hostProfile;
55
+ }
56
+ /**
57
+ * Get the transport interceptor
58
+ */
59
+ getInterceptor() {
60
+ return this.interceptor;
61
+ }
62
+ /**
63
+ * Set up automatic responses for common MCP protocol messages
64
+ */
65
+ setupAutoResponders() {
66
+ // Auto-respond to initialize requests
67
+ this.interceptor.mockResponse('initialize', (request) => {
68
+ this.initialized = true;
69
+ return {
70
+ jsonrpc: '2.0',
71
+ id: request.id,
72
+ result: {
73
+ protocolVersion: '2024-11-05',
74
+ capabilities: this.capabilities,
75
+ serverInfo: {
76
+ name: 'mock-mcp-server',
77
+ version: '0.1.0',
78
+ },
79
+ },
80
+ };
81
+ });
82
+ // Auto-respond to ping requests
83
+ this.interceptor.mockResponse('ping', (request) => ({
84
+ jsonrpc: '2.0',
85
+ id: request.id,
86
+ result: {},
87
+ }));
88
+ // Auto-respond to tools/list requests
89
+ this.interceptor.mockResponse('tools/list', (request) => ({
90
+ jsonrpc: '2.0',
91
+ id: request.id,
92
+ result: {
93
+ tools: [],
94
+ },
95
+ }));
96
+ // Auto-respond to resources/list requests
97
+ this.interceptor.mockResponse('resources/list', (request) => ({
98
+ jsonrpc: '2.0',
99
+ id: request.id,
100
+ result: {
101
+ resources: [],
102
+ },
103
+ }));
104
+ // Auto-respond to prompts/list requests
105
+ this.interceptor.mockResponse('prompts/list', (request) => ({
106
+ jsonrpc: '2.0',
107
+ id: request.id,
108
+ result: {
109
+ prompts: [],
110
+ },
111
+ }));
112
+ }
113
+ /**
114
+ * Set capabilities that this host supports
115
+ */
116
+ setCapabilities(capabilities) {
117
+ this.capabilities = capabilities;
118
+ }
119
+ /**
120
+ * Send a request to the server (simulate client -> server)
121
+ */
122
+ async sendRequest(method, params) {
123
+ const request = {
124
+ jsonrpc: '2.0',
125
+ id: ++this.requestIdCounter,
126
+ method,
127
+ params,
128
+ };
129
+ // Intercept the request
130
+ const interceptedRequest = await this.interceptor.interceptRequest(request);
131
+ // Check if we should mock the response
132
+ const mockResponse = await this.interceptor.shouldMock(interceptedRequest);
133
+ if (mockResponse) {
134
+ return await this.interceptor.interceptResponse(mockResponse);
135
+ }
136
+ // If no mock, return an error
137
+ const errorResponse = {
138
+ jsonrpc: '2.0',
139
+ id: interceptedRequest.id,
140
+ error: {
141
+ code: -32601,
142
+ message: `Method not found: ${method}`,
143
+ },
144
+ };
145
+ return await this.interceptor.interceptResponse(errorResponse);
146
+ }
147
+ /**
148
+ * Initialize the MCP connection
149
+ */
150
+ async initialize(clientInfo) {
151
+ return await this.sendRequest('initialize', {
152
+ protocolVersion: '2024-11-05',
153
+ capabilities: {},
154
+ clientInfo: clientInfo || {
155
+ name: 'mock-client',
156
+ version: '0.1.0',
157
+ },
158
+ });
159
+ }
160
+ /**
161
+ * Check if the host is initialized
162
+ */
163
+ isInitialized() {
164
+ return this.initialized;
165
+ }
166
+ /**
167
+ * Cleanup and reset the host
168
+ */
169
+ async cleanup() {
170
+ this.interceptor.reset();
171
+ this.initialized = false;
172
+ this.requestIdCounter = 0;
173
+ }
174
+ /**
175
+ * Get all recorded messages from the interceptor
176
+ */
177
+ getRecordedMessages() {
178
+ return this.interceptor.getRecordedMessages();
179
+ }
180
+ /**
181
+ * Clear recorded messages
182
+ */
183
+ clearRecordedMessages() {
184
+ this.interceptor.clearRecordedMessages();
185
+ }
186
+ /**
187
+ * Fluent DSL: Call a tool with automatic response handling
188
+ * @param name Tool name
189
+ * @param args Tool arguments
190
+ * @param options Optional retry and timeout settings
191
+ */
192
+ async callTool(name, args = {}, options = {}) {
193
+ const { timeout = 5000, retries = 3 } = options;
194
+ let lastError = null;
195
+ for (let attempt = 0; attempt <= retries; attempt++) {
196
+ try {
197
+ const response = await Promise.race([
198
+ this.sendRequest('tools/call', { name, arguments: args }),
199
+ new Promise((_, reject) => setTimeout(() => reject(new Error('Tool call timeout')), timeout)),
200
+ ]);
201
+ if (response.error) {
202
+ throw new Error(response.error.message);
203
+ }
204
+ return response;
205
+ }
206
+ catch (error) {
207
+ lastError = error;
208
+ if (attempt < retries) {
209
+ await new Promise(resolve => setTimeout(resolve, 100 * (attempt + 1)));
210
+ }
211
+ }
212
+ }
213
+ throw new Error(`Tool call failed after ${retries + 1} attempts: ${lastError?.message}`);
214
+ }
215
+ /**
216
+ * Fluent DSL: List available tools
217
+ */
218
+ async listTools() {
219
+ return await this.sendRequest('tools/list');
220
+ }
221
+ /**
222
+ * Fluent DSL: Read a resource
223
+ * @param uri Resource URI
224
+ */
225
+ async readResource(uri) {
226
+ return await this.sendRequest('resources/read', { uri });
227
+ }
228
+ /**
229
+ * Fluent DSL: List available resources
230
+ */
231
+ async listResources() {
232
+ return await this.sendRequest('resources/list');
233
+ }
234
+ /**
235
+ * Fluent DSL: Get a prompt
236
+ * @param name Prompt name
237
+ * @param args Prompt arguments
238
+ */
239
+ async getPrompt(name, args = {}) {
240
+ return await this.sendRequest('prompts/get', { name, arguments: args });
241
+ }
242
+ /**
243
+ * Fluent DSL: List available prompts
244
+ */
245
+ async listPrompts() {
246
+ return await this.sendRequest('prompts/list');
247
+ }
248
+ enableProtocolLogging() {
249
+ // Prevent duplicate logging interceptors
250
+ if (this.protocolLoggingEnabled) {
251
+ return;
252
+ }
253
+ this.protocolLoggingEnabled = true;
254
+ this.interceptor.onRequest(async (request) => {
255
+ console.log('[MCP Request]', JSON.stringify(request, null, 2));
256
+ return request;
257
+ });
258
+ this.interceptor.onResponse(async (response) => {
259
+ console.log('[MCP Response]', JSON.stringify(response, null, 2));
260
+ return response;
261
+ });
262
+ }
263
+ }
264
+ exports.MockMCPHost = MockMCPHost;
265
+ //# sourceMappingURL=MockMCPHost.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MockMCPHost.js","sourceRoot":"","sources":["../../src/core/MockMCPHost.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,72 @@
1
+ import { JSONRPCRequest, JSONRPCResponse, JSONRPCNotification, MessageHandler, RequestInterceptor, ResponseInterceptor } from '../types';
2
+ /**
3
+ * TransportInterceptor - Intercepts and mocks JSON-RPC messages
4
+ *
5
+ * This class allows you to:
6
+ * - Intercept outgoing requests and modify them
7
+ * - Intercept incoming responses and modify them
8
+ * - Mock responses to specific requests
9
+ * - Record all messages for testing assertions
10
+ */
11
+ export declare class TransportInterceptor {
12
+ private requestInterceptors;
13
+ private responseInterceptors;
14
+ private messageHandlers;
15
+ private requestMocks;
16
+ private recordedMessages;
17
+ private debug;
18
+ constructor(debug?: boolean);
19
+ /**
20
+ * Add a request interceptor
21
+ */
22
+ onRequest(interceptor: RequestInterceptor): void;
23
+ /**
24
+ * Add a response interceptor
25
+ */
26
+ onResponse(interceptor: ResponseInterceptor): void;
27
+ /**
28
+ * Add a message handler (for all messages)
29
+ */
30
+ onMessage(handler: MessageHandler): void;
31
+ /**
32
+ * Mock a response for a specific method
33
+ */
34
+ mockResponse(method: string, handler: (request: JSONRPCRequest) => JSONRPCResponse | Promise<JSONRPCResponse>): void;
35
+ /**
36
+ * Process an outgoing request
37
+ */
38
+ interceptRequest(request: JSONRPCRequest): Promise<JSONRPCRequest>;
39
+ /**
40
+ * Process an incoming response
41
+ */
42
+ interceptResponse(response: JSONRPCResponse): Promise<JSONRPCResponse>;
43
+ /**
44
+ * Check if a request should be mocked
45
+ */
46
+ shouldMock(request: JSONRPCRequest): Promise<JSONRPCResponse | null>;
47
+ /**
48
+ * Get all recorded messages
49
+ */
50
+ getRecordedMessages(): Array<JSONRPCRequest | JSONRPCResponse | JSONRPCNotification>;
51
+ /**
52
+ * Get recorded requests only
53
+ */
54
+ getRecordedRequests(): JSONRPCRequest[];
55
+ /**
56
+ * Get recorded responses only
57
+ */
58
+ getRecordedResponses(): JSONRPCResponse[];
59
+ /**
60
+ * Find requests by method name
61
+ */
62
+ findRequestsByMethod(method: string): JSONRPCRequest[];
63
+ /**
64
+ * Clear all recorded messages
65
+ */
66
+ clearRecordedMessages(): void;
67
+ /**
68
+ * Clear all interceptors and mocks
69
+ */
70
+ reset(): void;
71
+ }
72
+ //# sourceMappingURL=TransportInterceptor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TransportInterceptor.d.ts","sourceRoot":"","sources":["../../src/core/TransportInterceptor.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,eAAe,EACf,mBAAmB,EACnB,cAAc,EACd,kBAAkB,EAClB,mBAAmB,EACpB,MAAM,UAAU,CAAC;AAElB;;;;;;;;GAQG;AACH,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,mBAAmB,CAA4B;IACvD,OAAO,CAAC,oBAAoB,CAA6B;IACzD,OAAO,CAAC,eAAe,CAAwB;IAC/C,OAAO,CAAC,YAAY,CAAmG;IACvH,OAAO,CAAC,gBAAgB,CAAqE;IAC7F,OAAO,CAAC,KAAK,CAAU;gBAEX,KAAK,UAAQ;IAIzB;;OAEG;IACH,SAAS,CAAC,WAAW,EAAE,kBAAkB,GAAG,IAAI;IAIhD;;OAEG;IACH,UAAU,CAAC,WAAW,EAAE,mBAAmB,GAAG,IAAI;IAIlD;;OAEG;IACH,SAAS,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI;IAIxC;;OAEG;IACH,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC,GAAG,IAAI;IAIpH;;OAEG;IACG,gBAAgB,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC;IAmBxE;;OAEG;IACG,iBAAiB,CAAC,QAAQ,EAAE,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC;IAmB5E;;OAEG;IACG,UAAU,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC;IAW1E;;OAEG;IACH,mBAAmB,IAAI,KAAK,CAAC,cAAc,GAAG,eAAe,GAAG,mBAAmB,CAAC;IAIpF;;OAEG;IACH,mBAAmB,IAAI,cAAc,EAAE;IAIvC;;OAEG;IACH,oBAAoB,IAAI,eAAe,EAAE;IAIzC;;OAEG;IACH,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,EAAE;IAItD;;OAEG;IACH,qBAAqB,IAAI,IAAI;IAI7B;;OAEG;IACH,KAAK,IAAI,IAAI;CAOd"}
@@ -0,0 +1,135 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TransportInterceptor = void 0;
4
+ /**
5
+ * TransportInterceptor - Intercepts and mocks JSON-RPC messages
6
+ *
7
+ * This class allows you to:
8
+ * - Intercept outgoing requests and modify them
9
+ * - Intercept incoming responses and modify them
10
+ * - Mock responses to specific requests
11
+ * - Record all messages for testing assertions
12
+ */
13
+ class TransportInterceptor {
14
+ constructor(debug = false) {
15
+ this.requestInterceptors = [];
16
+ this.responseInterceptors = [];
17
+ this.messageHandlers = [];
18
+ this.requestMocks = new Map();
19
+ this.recordedMessages = [];
20
+ this.debug = debug;
21
+ }
22
+ /**
23
+ * Add a request interceptor
24
+ */
25
+ onRequest(interceptor) {
26
+ this.requestInterceptors.push(interceptor);
27
+ }
28
+ /**
29
+ * Add a response interceptor
30
+ */
31
+ onResponse(interceptor) {
32
+ this.responseInterceptors.push(interceptor);
33
+ }
34
+ /**
35
+ * Add a message handler (for all messages)
36
+ */
37
+ onMessage(handler) {
38
+ this.messageHandlers.push(handler);
39
+ }
40
+ /**
41
+ * Mock a response for a specific method
42
+ */
43
+ mockResponse(method, handler) {
44
+ this.requestMocks.set(method, handler);
45
+ }
46
+ /**
47
+ * Process an outgoing request
48
+ */
49
+ async interceptRequest(request) {
50
+ if (this.debug) {
51
+ console.log('[TransportInterceptor] Outgoing request:', JSON.stringify(request, null, 2));
52
+ }
53
+ this.recordedMessages.push(request);
54
+ let modifiedRequest = request;
55
+ for (const interceptor of this.requestInterceptors) {
56
+ modifiedRequest = await interceptor(modifiedRequest);
57
+ }
58
+ for (const handler of this.messageHandlers) {
59
+ await handler(modifiedRequest);
60
+ }
61
+ return modifiedRequest;
62
+ }
63
+ /**
64
+ * Process an incoming response
65
+ */
66
+ async interceptResponse(response) {
67
+ if (this.debug) {
68
+ console.log('[TransportInterceptor] Incoming response:', JSON.stringify(response, null, 2));
69
+ }
70
+ this.recordedMessages.push(response);
71
+ let modifiedResponse = response;
72
+ for (const interceptor of this.responseInterceptors) {
73
+ modifiedResponse = await interceptor(modifiedResponse);
74
+ }
75
+ for (const handler of this.messageHandlers) {
76
+ await handler(modifiedResponse);
77
+ }
78
+ return modifiedResponse;
79
+ }
80
+ /**
81
+ * Check if a request should be mocked
82
+ */
83
+ async shouldMock(request) {
84
+ const mockHandler = this.requestMocks.get(request.method);
85
+ if (mockHandler) {
86
+ if (this.debug) {
87
+ console.log(`[TransportInterceptor] Mocking response for method: ${request.method}`);
88
+ }
89
+ return await mockHandler(request);
90
+ }
91
+ return null;
92
+ }
93
+ /**
94
+ * Get all recorded messages
95
+ */
96
+ getRecordedMessages() {
97
+ return [...this.recordedMessages];
98
+ }
99
+ /**
100
+ * Get recorded requests only
101
+ */
102
+ getRecordedRequests() {
103
+ return this.recordedMessages.filter(msg => 'method' in msg && 'id' in msg);
104
+ }
105
+ /**
106
+ * Get recorded responses only
107
+ */
108
+ getRecordedResponses() {
109
+ return this.recordedMessages.filter(msg => 'id' in msg && !('method' in msg));
110
+ }
111
+ /**
112
+ * Find requests by method name
113
+ */
114
+ findRequestsByMethod(method) {
115
+ return this.getRecordedRequests().filter(req => req.method === method);
116
+ }
117
+ /**
118
+ * Clear all recorded messages
119
+ */
120
+ clearRecordedMessages() {
121
+ this.recordedMessages = [];
122
+ }
123
+ /**
124
+ * Clear all interceptors and mocks
125
+ */
126
+ reset() {
127
+ this.requestInterceptors = [];
128
+ this.responseInterceptors = [];
129
+ this.messageHandlers = [];
130
+ this.requestMocks.clear();
131
+ this.recordedMessages = [];
132
+ }
133
+ }
134
+ exports.TransportInterceptor = TransportInterceptor;
135
+ //# sourceMappingURL=TransportInterceptor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TransportInterceptor.js","sourceRoot":"","sources":["../../src/core/TransportInterceptor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * MCP Apps Testing Framework
3
+ *
4
+ * A professional framework for testing Model Context Protocol (MCP) UI applications
5
+ * with Playwright. Bridge the gap between MCP protocol testing and UI rendering/iframe sandboxing.
6
+ */
7
+ export { MockMCPHost } from './core/MockMCPHost';
8
+ export { TransportInterceptor } from './core/TransportInterceptor';
9
+ export { HostProfiles, ClaudeProfile, VSCodeProfile, GenericProfile, applyTheme } from './core/HostProfiles';
10
+ export type { HostProfile } from './core/HostProfiles';
11
+ export type { JSONRPCRequest, JSONRPCResponse, JSONRPCNotification, JSONRPCError, MessageHandler, RequestInterceptor, ResponseInterceptor, MockMCPHostConfig, MCPCapabilities, MCPTestContext, MCPTransport, } from './types';
12
+ import type { MockMCPHostConfig, MCPTestContext } from './types';
13
+ /**
14
+ * Create a test context with a mock MCP host
15
+ */
16
+ export declare function createMCPTestContext(config?: MockMCPHostConfig): Promise<MCPTestContext>;
17
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAC7G,YAAY,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAEvD,YAAY,EACV,cAAc,EACd,eAAe,EACf,mBAAmB,EACnB,YAAY,EACZ,cAAc,EACd,kBAAkB,EAClB,mBAAmB,EACnB,iBAAiB,EACjB,eAAe,EACf,cAAc,EACd,YAAY,GACb,MAAM,SAAS,CAAC;AAEjB,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAEjE;;GAEG;AACH,wBAAsB,oBAAoB,CAAC,MAAM,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,cAAc,CAAC,CAY9F"}
package/dist/index.js ADDED
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ /**
3
+ * MCP Apps Testing Framework
4
+ *
5
+ * A professional framework for testing Model Context Protocol (MCP) UI applications
6
+ * with Playwright. Bridge the gap between MCP protocol testing and UI rendering/iframe sandboxing.
7
+ */
8
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
9
+ if (k2 === undefined) k2 = k;
10
+ var desc = Object.getOwnPropertyDescriptor(m, k);
11
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
12
+ desc = { enumerable: true, get: function() { return m[k]; } };
13
+ }
14
+ Object.defineProperty(o, k2, desc);
15
+ }) : (function(o, m, k, k2) {
16
+ if (k2 === undefined) k2 = k;
17
+ o[k2] = m[k];
18
+ }));
19
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
20
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
21
+ }) : function(o, v) {
22
+ o["default"] = v;
23
+ });
24
+ var __importStar = (this && this.__importStar) || (function () {
25
+ var ownKeys = function(o) {
26
+ ownKeys = Object.getOwnPropertyNames || function (o) {
27
+ var ar = [];
28
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
29
+ return ar;
30
+ };
31
+ return ownKeys(o);
32
+ };
33
+ return function (mod) {
34
+ if (mod && mod.__esModule) return mod;
35
+ var result = {};
36
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
37
+ __setModuleDefault(result, mod);
38
+ return result;
39
+ };
40
+ })();
41
+ Object.defineProperty(exports, "__esModule", { value: true });
42
+ exports.applyTheme = exports.GenericProfile = exports.VSCodeProfile = exports.ClaudeProfile = exports.HostProfiles = exports.TransportInterceptor = exports.MockMCPHost = void 0;
43
+ exports.createMCPTestContext = createMCPTestContext;
44
+ var MockMCPHost_1 = require("./core/MockMCPHost");
45
+ Object.defineProperty(exports, "MockMCPHost", { enumerable: true, get: function () { return MockMCPHost_1.MockMCPHost; } });
46
+ var TransportInterceptor_1 = require("./core/TransportInterceptor");
47
+ Object.defineProperty(exports, "TransportInterceptor", { enumerable: true, get: function () { return TransportInterceptor_1.TransportInterceptor; } });
48
+ var HostProfiles_1 = require("./core/HostProfiles");
49
+ Object.defineProperty(exports, "HostProfiles", { enumerable: true, get: function () { return HostProfiles_1.HostProfiles; } });
50
+ Object.defineProperty(exports, "ClaudeProfile", { enumerable: true, get: function () { return HostProfiles_1.ClaudeProfile; } });
51
+ Object.defineProperty(exports, "VSCodeProfile", { enumerable: true, get: function () { return HostProfiles_1.VSCodeProfile; } });
52
+ Object.defineProperty(exports, "GenericProfile", { enumerable: true, get: function () { return HostProfiles_1.GenericProfile; } });
53
+ Object.defineProperty(exports, "applyTheme", { enumerable: true, get: function () { return HostProfiles_1.applyTheme; } });
54
+ /**
55
+ * Create a test context with a mock MCP host
56
+ */
57
+ async function createMCPTestContext(config) {
58
+ const { MockMCPHost } = await Promise.resolve().then(() => __importStar(require('./core/MockMCPHost')));
59
+ const host = new MockMCPHost(config);
60
+ const interceptor = host.getInterceptor();
61
+ return {
62
+ host,
63
+ interceptor,
64
+ cleanup: async () => {
65
+ await host.cleanup();
66
+ },
67
+ };
68
+ }
69
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0BH,oDAYC;AApCD,kDAAiD;AAAxC,0GAAA,WAAW,OAAA;AACpB,oEAAmE;AAA1D,4HAAA,oBAAoB,OAAA;AAC7B,oDAA6G;AAApG,4GAAA,YAAY,OAAA;AAAE,6GAAA,aAAa,OAAA;AAAE,6GAAA,aAAa,OAAA;AAAE,8GAAA,cAAc,OAAA;AAAE,0GAAA,UAAU,OAAA;AAmB/E;;GAEG;AACI,KAAK,UAAU,oBAAoB,CAAC,MAA0B;IACnE,MAAM,EAAE,WAAW,EAAE,GAAG,wDAAa,oBAAoB,GAAC,CAAC;IAC3D,MAAM,IAAI,GAAG,IAAI,WAAW,CAAC,MAAM,CAAC,CAAC;IACrC,MAAM,WAAW,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;IAE1C,OAAO;QACL,IAAI;QACJ,WAAW;QACX,OAAO,EAAE,KAAK,IAAI,EAAE;YAClB,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;QACvB,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Types for MCP Apps Testing Framework
3
+ */
4
+ /**
5
+ * JSON-RPC 2.0 message types
6
+ */
7
+ export interface JSONRPCRequest {
8
+ jsonrpc: '2.0';
9
+ id: string | number;
10
+ method: string;
11
+ params?: unknown;
12
+ }
13
+ export interface JSONRPCResponse {
14
+ jsonrpc: '2.0';
15
+ id: string | number;
16
+ result?: unknown;
17
+ error?: JSONRPCError;
18
+ }
19
+ export interface JSONRPCNotification {
20
+ jsonrpc: '2.0';
21
+ method: string;
22
+ params?: unknown;
23
+ }
24
+ export interface JSONRPCError {
25
+ code: number;
26
+ message: string;
27
+ data?: unknown;
28
+ }
29
+ /**
30
+ * Transport interceptor handler types
31
+ */
32
+ export type MessageHandler = (message: JSONRPCRequest | JSONRPCResponse | JSONRPCNotification) => void | Promise<void>;
33
+ export type RequestInterceptor = (request: JSONRPCRequest) => JSONRPCRequest | Promise<JSONRPCRequest>;
34
+ export type ResponseInterceptor = (response: JSONRPCResponse) => JSONRPCResponse | Promise<JSONRPCResponse>;
35
+ /**
36
+ * Transport interface for MCP communication
37
+ */
38
+ export interface MCPTransport {
39
+ send?: (message: unknown) => void | Promise<void>;
40
+ close?: () => void | Promise<void>;
41
+ }
42
+ /**
43
+ * Mock MCP Host configuration
44
+ */
45
+ export interface MockMCPHostConfig {
46
+ /**
47
+ * Whether to automatically respond to common MCP protocol messages
48
+ */
49
+ autoRespond?: boolean;
50
+ /**
51
+ * Custom transport implementation
52
+ */
53
+ transport?: MCPTransport;
54
+ /**
55
+ * Enable verbose logging
56
+ */
57
+ debug?: boolean;
58
+ /**
59
+ * Host profile to simulate (e.g., 'Claude', 'VSCode', 'Generic')
60
+ */
61
+ hostProfile?: string;
62
+ }
63
+ /**
64
+ * MCP capabilities that can be simulated
65
+ */
66
+ export interface MCPCapabilities {
67
+ tools?: {
68
+ listChanged?: boolean;
69
+ };
70
+ resources?: {
71
+ subscribe?: boolean;
72
+ listChanged?: boolean;
73
+ };
74
+ prompts?: {
75
+ listChanged?: boolean;
76
+ };
77
+ }
78
+ /**
79
+ * Test context for MCP applications
80
+ */
81
+ export interface MCPTestContext {
82
+ /**
83
+ * Mock host instance
84
+ */
85
+ host: import('../core/MockMCPHost').MockMCPHost;
86
+ /**
87
+ * Transport interceptor
88
+ */
89
+ interceptor: import('../core/TransportInterceptor').TransportInterceptor;
90
+ /**
91
+ * Cleanup function
92
+ */
93
+ cleanup: () => Promise<void>;
94
+ }
95
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,KAAK,CAAC;IACf,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,KAAK,CAAC;IACf,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,YAAY,CAAC;CACtB;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,KAAK,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,EAAE,cAAc,GAAG,eAAe,GAAG,mBAAmB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAEvH,MAAM,MAAM,kBAAkB,GAAG,CAAC,OAAO,EAAE,cAAc,KAAK,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;AAEvG,MAAM,MAAM,mBAAmB,GAAG,CAAC,QAAQ,EAAE,eAAe,KAAK,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;AAE5G;;GAEG;AACH,MAAM,WAAW,YAAY;IAE3B,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClD,KAAK,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACpC;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC;;OAEG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB;;OAEG;IACH,SAAS,CAAC,EAAE,YAAY,CAAC;IAEzB;;OAEG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAEhB;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,EAAE;QACN,WAAW,CAAC,EAAE,OAAO,CAAC;KACvB,CAAC;IACF,SAAS,CAAC,EAAE;QACV,SAAS,CAAC,EAAE,OAAO,CAAC;QACpB,WAAW,CAAC,EAAE,OAAO,CAAC;KACvB,CAAC;IACF,OAAO,CAAC,EAAE;QACR,WAAW,CAAC,EAAE,OAAO,CAAC;KACvB,CAAC;CACH;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B;;OAEG;IACH,IAAI,EAAE,OAAO,qBAAqB,EAAE,WAAW,CAAC;IAEhD;;OAEG;IACH,WAAW,EAAE,OAAO,8BAA8B,EAAE,oBAAoB,CAAC;IAEzE;;OAEG;IACH,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B"}
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ /**
3
+ * Types for MCP Apps Testing Framework
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":";AAAA;;GAEG"}
package/package.json ADDED
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "mcp-apps-testing",
3
+ "version": "0.1.0",
4
+ "description": "A professional framework for testing Model Context Protocol (MCP) UI applications with Playwright",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "scripts": {
8
+ "build": "tsc",
9
+ "dev": "tsc --watch",
10
+ "test": "playwright test",
11
+ "test:ui": "playwright test --ui",
12
+ "lint": "eslint src --ext .ts",
13
+ "clean": "rm -rf dist",
14
+ "prepublishOnly": "npm run clean && npm run build"
15
+ },
16
+ "keywords": [
17
+ "mcp",
18
+ "model-context-protocol",
19
+ "testing",
20
+ "playwright",
21
+ "ui-testing",
22
+ "json-rpc"
23
+ ],
24
+ "author": "Aviv Eldan",
25
+ "license": "MIT",
26
+ "repository": {
27
+ "type": "git",
28
+ "url": "git+https://github.com/aviveldan/mcp-apps-testing.git"
29
+ },
30
+ "bugs": {
31
+ "url": "https://github.com/aviveldan/mcp-apps-testing/issues"
32
+ },
33
+ "homepage": "https://github.com/aviveldan/mcp-apps-testing#readme",
34
+ "files": [
35
+ "dist",
36
+ "README.md",
37
+ "LICENSE"
38
+ ],
39
+ "devDependencies": {
40
+ "@playwright/test": "^1.40.0",
41
+ "@types/node": "^20.10.0",
42
+ "typescript": "^5.3.0"
43
+ },
44
+ "dependencies": {
45
+ "@modelcontextprotocol/sdk": "^1.26.0"
46
+ },
47
+ "peerDependencies": {
48
+ "@playwright/test": "^1.40.0"
49
+ },
50
+ "publishConfig": {
51
+ "access": "public"
52
+ },
53
+ "engines": {
54
+ "node": ">=18.0.0"
55
+ }
56
+ }