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 +21 -0
- package/README.md +159 -0
- package/dist/core/HostProfiles.d.ts +56 -0
- package/dist/core/HostProfiles.d.ts.map +1 -0
- package/dist/core/HostProfiles.js +132 -0
- package/dist/core/HostProfiles.js.map +1 -0
- package/dist/core/MockMCPHost.d.ts +108 -0
- package/dist/core/MockMCPHost.d.ts.map +1 -0
- package/dist/core/MockMCPHost.js +265 -0
- package/dist/core/MockMCPHost.js.map +1 -0
- package/dist/core/TransportInterceptor.d.ts +72 -0
- package/dist/core/TransportInterceptor.d.ts.map +1 -0
- package/dist/core/TransportInterceptor.js +135 -0
- package/dist/core/TransportInterceptor.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +69 -0
- package/dist/index.js.map +1 -0
- package/dist/types/index.d.ts +95 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +6 -0
- package/dist/types/index.js.map +1 -0
- package/package.json +56 -0
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
|
+

|
|
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
|
+

|
|
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
|
+

|
|
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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"}
|
package/dist/index.d.ts
ADDED
|
@@ -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 @@
|
|
|
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
|
+
}
|