@m00nsolutions/mcp-server 1.0.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 +236 -0
- package/bin/m00n-mcp.js +28 -0
- package/dist/api-client.d.ts +48 -0
- package/dist/api-client.d.ts.map +1 -0
- package/dist/api-client.js +133 -0
- package/dist/api-client.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +55 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +36 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +85 -0
- package/dist/config.js.map +1 -0
- package/dist/server.d.ts +6 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +123 -0
- package/dist/server.js.map +1 -0
- package/dist/version.d.ts +3 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +34 -0
- package/dist/version.js.map +1 -0
- package/package.json +60 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 M00n Solutions
|
|
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,236 @@
|
|
|
1
|
+
# @m00nsolutions/mcp-server
|
|
2
|
+
|
|
3
|
+
MCP (Model Context Protocol) server for M00n Report. Enables AI assistants like **Claude** and **Cursor** to query your test analytics.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 📊 **Query test trends** - Pass rates, failing tests, flaky tests over time
|
|
8
|
+
- 📈 **Get launch statistics** - Test run summaries with filtering
|
|
9
|
+
- 📁 **List projects** - Browse accessible projects
|
|
10
|
+
- 🔒 **Secure** - Uses your MCP key with your permissions
|
|
11
|
+
- 🏢 **Self-hosted ready** - Works with self-hosted M00n Report instances
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
### 1. Get an MCP Key
|
|
16
|
+
|
|
17
|
+
1. Log in to M00n Report
|
|
18
|
+
2. Go to **Settings → MCP Keys**
|
|
19
|
+
3. Create a new MCP key
|
|
20
|
+
4. Copy the key (starts with `m00n_mcp_`)
|
|
21
|
+
|
|
22
|
+
### 2. Configure Cursor
|
|
23
|
+
|
|
24
|
+
Add to your Cursor MCP configuration (`~/.cursor/mcp.json` or workspace `.cursor/mcp.json`):
|
|
25
|
+
|
|
26
|
+
```json
|
|
27
|
+
{
|
|
28
|
+
"mcpServers": {
|
|
29
|
+
"m00n": {
|
|
30
|
+
"command": "npx",
|
|
31
|
+
"args": ["-y", "@m00nsolutions/mcp-server"],
|
|
32
|
+
"env": {
|
|
33
|
+
"M00N_API_URL": "https://app.m00nreport.com",
|
|
34
|
+
"M00N_API_KEY": "m00n_mcp_your_key_here"
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### 3. Configure Claude Desktop
|
|
42
|
+
|
|
43
|
+
Add to your Claude Desktop config (`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS):
|
|
44
|
+
|
|
45
|
+
```json
|
|
46
|
+
{
|
|
47
|
+
"mcpServers": {
|
|
48
|
+
"m00n": {
|
|
49
|
+
"command": "npx",
|
|
50
|
+
"args": ["-y", "@m00nsolutions/mcp-server"],
|
|
51
|
+
"env": {
|
|
52
|
+
"M00N_API_URL": "https://app.m00nreport.com",
|
|
53
|
+
"M00N_API_KEY": "m00n_mcp_your_key_here"
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Available Tools
|
|
61
|
+
|
|
62
|
+
### `list_projects`
|
|
63
|
+
|
|
64
|
+
List all projects accessible to your MCP key.
|
|
65
|
+
|
|
66
|
+
**Example prompt:** "What projects do I have access to in M00n Report?"
|
|
67
|
+
|
|
68
|
+
### `get_launches_trends`
|
|
69
|
+
|
|
70
|
+
Get comprehensive trend data for a project including pass rates, failing tests, flaky tests, and duration trends.
|
|
71
|
+
|
|
72
|
+
**Parameters:**
|
|
73
|
+
- `projectId` (required) - Project UUID
|
|
74
|
+
- `days` (optional) - Lookback period, 1-365 (default: 30)
|
|
75
|
+
- `tags` (optional) - Filter runs by tags
|
|
76
|
+
- `topN` (optional) - Limit for top-N lists (default: 10)
|
|
77
|
+
- `include` (optional) - Which trends to include: `passRate`, `duration`, `failing`, `flaky`, `slowest`, `testsByTags`
|
|
78
|
+
|
|
79
|
+
**Example prompt:** "Show me the test pass rate trends for project abc-123 over the last 14 days"
|
|
80
|
+
|
|
81
|
+
### `get_launches_statistics`
|
|
82
|
+
|
|
83
|
+
Get a list of test runs with aggregated statistics for a project.
|
|
84
|
+
|
|
85
|
+
**Parameters:**
|
|
86
|
+
- `projectId` (required) - Project UUID
|
|
87
|
+
- `days` (optional) - Lookback period, 1-365 (default: 30)
|
|
88
|
+
- `tags` (optional) - Filter by tags
|
|
89
|
+
- `statuses` (optional) - Filter by status: `passed`, `failed`, `running`, `interrupted`
|
|
90
|
+
- `search` (optional) - Search in launch title/ID/tags
|
|
91
|
+
- `limit` (optional) - Number of launches to return (default: 20)
|
|
92
|
+
- `offset` (optional) - Pagination offset
|
|
93
|
+
|
|
94
|
+
**Example prompt:** "What were the last 10 failed test runs in project abc-123?"
|
|
95
|
+
|
|
96
|
+
## Environment Variables
|
|
97
|
+
|
|
98
|
+
| Variable | Required | Default | Description |
|
|
99
|
+
|----------|----------|---------|-------------|
|
|
100
|
+
| `M00N_API_URL` | ✅ | - | M00n Report API URL (e.g., `https://app.m00nreport.com`) |
|
|
101
|
+
| `M00N_API_KEY` | ✅ | - | MCP key from Settings → MCP Keys |
|
|
102
|
+
| `M00N_INSECURE_SSL` | | `false` | Skip SSL verification (for self-signed certs) |
|
|
103
|
+
| `M00N_DEBUG` | | `false` | Enable verbose logging |
|
|
104
|
+
| `M00N_TIMEOUT_MS` | | `30000` | Request timeout in milliseconds |
|
|
105
|
+
|
|
106
|
+
## Self-Hosted Installation
|
|
107
|
+
|
|
108
|
+
### Standard Installation
|
|
109
|
+
|
|
110
|
+
Works with any self-hosted M00n Report instance:
|
|
111
|
+
|
|
112
|
+
```json
|
|
113
|
+
{
|
|
114
|
+
"mcpServers": {
|
|
115
|
+
"m00n": {
|
|
116
|
+
"command": "npx",
|
|
117
|
+
"args": ["-y", "@m00nsolutions/mcp-server"],
|
|
118
|
+
"env": {
|
|
119
|
+
"M00N_API_URL": "https://your-m00n-instance.company.com",
|
|
120
|
+
"M00N_API_KEY": "m00n_mcp_your_key_here"
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Self-Signed Certificates
|
|
128
|
+
|
|
129
|
+
For self-hosted instances with self-signed SSL certificates:
|
|
130
|
+
|
|
131
|
+
```json
|
|
132
|
+
{
|
|
133
|
+
"mcpServers": {
|
|
134
|
+
"m00n": {
|
|
135
|
+
"command": "npx",
|
|
136
|
+
"args": ["-y", "@m00nsolutions/mcp-server"],
|
|
137
|
+
"env": {
|
|
138
|
+
"M00N_API_URL": "https://your-m00n-instance.company.com",
|
|
139
|
+
"M00N_API_KEY": "m00n_mcp_your_key_here",
|
|
140
|
+
"M00N_INSECURE_SSL": "true"
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
⚠️ **Security Note:** Only use `M00N_INSECURE_SSL=true` for trusted internal servers with self-signed certificates.
|
|
148
|
+
|
|
149
|
+
### Offline/Air-Gapped Installation
|
|
150
|
+
|
|
151
|
+
For environments without internet access:
|
|
152
|
+
|
|
153
|
+
1. On a machine with internet, create a tarball:
|
|
154
|
+
```bash
|
|
155
|
+
npm pack @m00nsolutions/mcp-server
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
2. Transfer `m00nsolutions-mcp-server-1.0.0.tgz` to the air-gapped machine
|
|
159
|
+
|
|
160
|
+
3. Install from tarball:
|
|
161
|
+
```bash
|
|
162
|
+
npm install -g ./m00nsolutions-mcp-server-1.0.0.tgz
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
4. Configure to use the global installation:
|
|
166
|
+
```json
|
|
167
|
+
{
|
|
168
|
+
"mcpServers": {
|
|
169
|
+
"m00n": {
|
|
170
|
+
"command": "m00n-mcp",
|
|
171
|
+
"env": {
|
|
172
|
+
"M00N_API_URL": "https://your-m00n-instance.company.com",
|
|
173
|
+
"M00N_API_KEY": "m00n_mcp_your_key_here"
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
## Troubleshooting
|
|
181
|
+
|
|
182
|
+
### "Cannot connect to M00n Report API"
|
|
183
|
+
|
|
184
|
+
- Verify `M00N_API_URL` is correct and accessible
|
|
185
|
+
- Check network connectivity to the M00n Report server
|
|
186
|
+
- For self-hosted: ensure the API port (default 4000) is accessible
|
|
187
|
+
|
|
188
|
+
### "Authentication failed: Invalid or expired MCP key"
|
|
189
|
+
|
|
190
|
+
- Verify `M00N_API_KEY` starts with `m00n_mcp_`
|
|
191
|
+
- Check the key hasn't been revoked in Settings → MCP Keys
|
|
192
|
+
- Ensure you're using an MCP key, not a project API key
|
|
193
|
+
|
|
194
|
+
### "SSL certificate error"
|
|
195
|
+
|
|
196
|
+
- For self-signed certificates, set `M00N_INSECURE_SSL=true`
|
|
197
|
+
- Verify the certificate chain if using a private CA
|
|
198
|
+
|
|
199
|
+
### "No tools available"
|
|
200
|
+
|
|
201
|
+
- Check your MCP key has appropriate permissions
|
|
202
|
+
- Verify your user account has access to at least one project
|
|
203
|
+
|
|
204
|
+
### Enable Debug Logging
|
|
205
|
+
|
|
206
|
+
Set `M00N_DEBUG=true` to see detailed logs:
|
|
207
|
+
|
|
208
|
+
```json
|
|
209
|
+
{
|
|
210
|
+
"env": {
|
|
211
|
+
"M00N_API_URL": "...",
|
|
212
|
+
"M00N_API_KEY": "...",
|
|
213
|
+
"M00N_DEBUG": "true"
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
## Example Prompts
|
|
219
|
+
|
|
220
|
+
Once configured, try these prompts in Claude or Cursor:
|
|
221
|
+
|
|
222
|
+
- "List my M00n Report projects"
|
|
223
|
+
- "Show me the test pass rate trends for the last 30 days"
|
|
224
|
+
- "What are the top 10 flaky tests in project X?"
|
|
225
|
+
- "Get me the failed test runs from this week"
|
|
226
|
+
- "Which tests are taking the longest to run?"
|
|
227
|
+
|
|
228
|
+
## Support
|
|
229
|
+
|
|
230
|
+
- **Documentation:** https://m00nreport.com/docs
|
|
231
|
+
- **Issues:** https://github.com/m00nsolutions/m00nreport/issues
|
|
232
|
+
- **Email:** support@m00nreport.com
|
|
233
|
+
|
|
234
|
+
## License
|
|
235
|
+
|
|
236
|
+
MIT
|
package/bin/m00n-mcp.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// M00n Report MCP Server
|
|
4
|
+
// Enables AI assistants (Claude, Cursor) to query test analytics
|
|
5
|
+
//
|
|
6
|
+
// Usage:
|
|
7
|
+
// M00N_API_URL=https://app.m00nreport.com M00N_API_KEY=your-key npx @m00nsolutions/mcp-server
|
|
8
|
+
//
|
|
9
|
+
// For Cursor/Claude Desktop config, see README.md
|
|
10
|
+
|
|
11
|
+
import { existsSync } from 'fs';
|
|
12
|
+
import { fileURLToPath } from 'url';
|
|
13
|
+
import { dirname, join } from 'path';
|
|
14
|
+
|
|
15
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
16
|
+
const distPath = join(__dirname, '..', 'dist', 'cli.js');
|
|
17
|
+
|
|
18
|
+
// Check if the package has been built (helpful during development)
|
|
19
|
+
if (!existsSync(distPath)) {
|
|
20
|
+
console.error('Error: Package not built. Run "npm run build" first.');
|
|
21
|
+
console.error(`Expected: ${distPath}`);
|
|
22
|
+
process.exit(1);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
import('../dist/cli.js').catch((err) => {
|
|
26
|
+
console.error('Failed to start M00n MCP server:', err.message);
|
|
27
|
+
process.exit(1);
|
|
28
|
+
});
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { Config } from './config.js';
|
|
2
|
+
export interface Tool {
|
|
3
|
+
name: string;
|
|
4
|
+
description: string;
|
|
5
|
+
inputSchema: {
|
|
6
|
+
type: 'object';
|
|
7
|
+
properties: Record<string, unknown>;
|
|
8
|
+
required?: string[];
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
export interface HealthResponse {
|
|
12
|
+
status: string;
|
|
13
|
+
version?: string;
|
|
14
|
+
mode?: string;
|
|
15
|
+
}
|
|
16
|
+
export interface ToolCallResult {
|
|
17
|
+
[key: string]: any;
|
|
18
|
+
}
|
|
19
|
+
export interface ApiError {
|
|
20
|
+
error: string;
|
|
21
|
+
message: string;
|
|
22
|
+
code?: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* M00n Report API Client
|
|
26
|
+
*/
|
|
27
|
+
export declare class M00nApiClient {
|
|
28
|
+
private client;
|
|
29
|
+
private config;
|
|
30
|
+
constructor(config: Config);
|
|
31
|
+
/**
|
|
32
|
+
* Check API health and get version info
|
|
33
|
+
*/
|
|
34
|
+
checkHealth(): Promise<HealthResponse>;
|
|
35
|
+
/**
|
|
36
|
+
* Fetch available tools from API
|
|
37
|
+
*/
|
|
38
|
+
fetchTools(): Promise<Tool[]>;
|
|
39
|
+
/**
|
|
40
|
+
* Execute a tool with given arguments
|
|
41
|
+
*/
|
|
42
|
+
callTool(name: string, args: Record<string, unknown>): Promise<ToolCallResult>;
|
|
43
|
+
/**
|
|
44
|
+
* Handle API errors with meaningful messages
|
|
45
|
+
*/
|
|
46
|
+
private handleError;
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=api-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../src/api-client.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,MAAM,EAAS,MAAM,aAAa,CAAC;AAI5C,MAAM,WAAW,IAAI;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ,CAAC;QACf,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACpC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;KACrB,CAAC;CACH;AAGD,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAGD,MAAM,WAAW,cAAc;IAE7B,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAGD,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,MAAM,CAAS;gBAEX,MAAM,EAAE,MAAM;IAoB1B;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,cAAc,CAAC;IAU5C;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;IAUnC;;OAEG;IACG,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,cAAc,CAAC;IAapF;;OAEG;IACH,OAAO,CAAC,WAAW;CA2EpB"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
// api-client.ts - HTTP client for M00n Report API
|
|
2
|
+
//
|
|
3
|
+
// Handles:
|
|
4
|
+
// - Authentication via X-MCP-Key header
|
|
5
|
+
// - SSL verification bypass for self-hosted
|
|
6
|
+
// - Timeout and error handling
|
|
7
|
+
// - Tool discovery and execution
|
|
8
|
+
import axios from 'axios';
|
|
9
|
+
import https from 'https';
|
|
10
|
+
import { debug } from './config.js';
|
|
11
|
+
import { VERSION } from './version.js';
|
|
12
|
+
/**
|
|
13
|
+
* M00n Report API Client
|
|
14
|
+
*/
|
|
15
|
+
export class M00nApiClient {
|
|
16
|
+
client;
|
|
17
|
+
config;
|
|
18
|
+
constructor(config) {
|
|
19
|
+
this.config = config;
|
|
20
|
+
// Create axios instance with configuration
|
|
21
|
+
this.client = axios.create({
|
|
22
|
+
baseURL: config.apiUrl,
|
|
23
|
+
timeout: config.timeoutMs,
|
|
24
|
+
headers: {
|
|
25
|
+
'X-MCP-Key': config.apiKey,
|
|
26
|
+
'Content-Type': 'application/json',
|
|
27
|
+
'User-Agent': `m00n-mcp-server/${VERSION}`,
|
|
28
|
+
},
|
|
29
|
+
// HTTPS agent with connection reuse and optional SSL verification skip
|
|
30
|
+
httpsAgent: new https.Agent({
|
|
31
|
+
rejectUnauthorized: !config.insecureSsl,
|
|
32
|
+
keepAlive: true,
|
|
33
|
+
}),
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Check API health and get version info
|
|
38
|
+
*/
|
|
39
|
+
async checkHealth() {
|
|
40
|
+
try {
|
|
41
|
+
debug(`Checking health at ${this.config.apiUrl}/api/health`, this.config);
|
|
42
|
+
const response = await this.client.get('/api/health');
|
|
43
|
+
return response.data;
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
throw this.handleError(error, 'health check');
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Fetch available tools from API
|
|
51
|
+
*/
|
|
52
|
+
async fetchTools() {
|
|
53
|
+
try {
|
|
54
|
+
debug(`Fetching tools from ${this.config.apiUrl}/api/mcp/tools`, this.config);
|
|
55
|
+
const response = await this.client.get('/api/mcp/tools');
|
|
56
|
+
return response.data.tools;
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
throw this.handleError(error, 'fetch tools');
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Execute a tool with given arguments
|
|
64
|
+
*/
|
|
65
|
+
async callTool(name, args) {
|
|
66
|
+
try {
|
|
67
|
+
debug(`Calling tool: ${name} with args: ${JSON.stringify(args)}`, this.config);
|
|
68
|
+
const response = await this.client.post('/api/mcp/tools/call', {
|
|
69
|
+
name,
|
|
70
|
+
arguments: args,
|
|
71
|
+
});
|
|
72
|
+
return response.data;
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
throw this.handleError(error, `tool call: ${name}`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Handle API errors with meaningful messages
|
|
80
|
+
*/
|
|
81
|
+
handleError(error, context) {
|
|
82
|
+
if (axios.isAxiosError(error)) {
|
|
83
|
+
const axiosError = error;
|
|
84
|
+
// Network error (no response)
|
|
85
|
+
if (!axiosError.response) {
|
|
86
|
+
if (axiosError.code === 'ECONNREFUSED') {
|
|
87
|
+
return new Error(`Cannot connect to M00n Report API at ${this.config.apiUrl}. ` +
|
|
88
|
+
'Please verify the URL is correct and the server is running.');
|
|
89
|
+
}
|
|
90
|
+
if (axiosError.code === 'ENOTFOUND') {
|
|
91
|
+
return new Error(`Cannot resolve M00n Report API host: ${this.config.apiUrl}. ` +
|
|
92
|
+
'Please check the URL is correct.');
|
|
93
|
+
}
|
|
94
|
+
if (axiosError.code === 'ETIMEDOUT' || axiosError.code === 'ECONNABORTED') {
|
|
95
|
+
return new Error(`Request to M00n Report API timed out. ` +
|
|
96
|
+
'Try increasing M00N_TIMEOUT_MS or check network connectivity.');
|
|
97
|
+
}
|
|
98
|
+
if (axiosError.message.includes('self-signed') || axiosError.message.includes('certificate')) {
|
|
99
|
+
return new Error(`SSL certificate error connecting to ${this.config.apiUrl}. ` +
|
|
100
|
+
'For self-signed certificates, set M00N_INSECURE_SSL=true');
|
|
101
|
+
}
|
|
102
|
+
return new Error(`Network error during ${context}: ${axiosError.message}`);
|
|
103
|
+
}
|
|
104
|
+
// HTTP error response
|
|
105
|
+
const status = axiosError.response.status;
|
|
106
|
+
const data = axiosError.response.data;
|
|
107
|
+
switch (status) {
|
|
108
|
+
case 401:
|
|
109
|
+
return new Error('Authentication failed: Invalid or expired MCP key. ' +
|
|
110
|
+
'Please check M00N_API_KEY is a valid MCP key from Settings → MCP Keys.');
|
|
111
|
+
case 403:
|
|
112
|
+
return new Error(`Access denied: ${data?.message || 'You do not have permission for this operation.'}`);
|
|
113
|
+
case 404:
|
|
114
|
+
return new Error(`API endpoint not found: ${context}. ` +
|
|
115
|
+
'This may indicate an API version mismatch or incorrect URL.');
|
|
116
|
+
case 429:
|
|
117
|
+
return new Error('Rate limit exceeded. Please wait before making more requests.');
|
|
118
|
+
case 500:
|
|
119
|
+
case 502:
|
|
120
|
+
case 503:
|
|
121
|
+
return new Error(`M00n Report API server error (${status}): ${data?.message || 'Please try again later.'}`);
|
|
122
|
+
default:
|
|
123
|
+
return new Error(`API error (${status}) during ${context}: ${data?.message || axiosError.message}`);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
// Non-axios error
|
|
127
|
+
if (error instanceof Error) {
|
|
128
|
+
return error;
|
|
129
|
+
}
|
|
130
|
+
return new Error(`Unknown error during ${context}: ${String(error)}`);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=api-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-client.js","sourceRoot":"","sources":["../src/api-client.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// cli.ts - CLI entry point for M00n MCP Server
|
|
2
|
+
//
|
|
3
|
+
// This is the main entry point invoked by bin/m00n-mcp.js
|
|
4
|
+
// It loads configuration from environment variables and starts the server.
|
|
5
|
+
import { loadConfig, log } from './config.js';
|
|
6
|
+
import { createServer } from './server.js';
|
|
7
|
+
/**
|
|
8
|
+
* Main entry point
|
|
9
|
+
*/
|
|
10
|
+
async function main() {
|
|
11
|
+
try {
|
|
12
|
+
// Load and validate configuration
|
|
13
|
+
const config = loadConfig();
|
|
14
|
+
// Start the server
|
|
15
|
+
await createServer(config);
|
|
16
|
+
}
|
|
17
|
+
catch (error) {
|
|
18
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
19
|
+
log(`Fatal error: ${message}`);
|
|
20
|
+
// Print helpful message for common issues
|
|
21
|
+
if (message.includes('M00N_API_URL') || message.includes('M00N_API_KEY')) {
|
|
22
|
+
console.error('\n' +
|
|
23
|
+
'╔═══════════════════════════════════════════════════════════════╗\n' +
|
|
24
|
+
'║ CONFIGURATION REQUIRED ║\n' +
|
|
25
|
+
'╠═══════════════════════════════════════════════════════════════╣\n' +
|
|
26
|
+
'║ Set the following environment variables: ║\n' +
|
|
27
|
+
'║ ║\n' +
|
|
28
|
+
'║ M00N_API_URL - Your M00n Report URL ║\n' +
|
|
29
|
+
'║ (e.g., https://app.m00nreport.com) ║\n' +
|
|
30
|
+
'║ ║\n' +
|
|
31
|
+
'║ M00N_API_KEY - MCP key from Settings → MCP Keys ║\n' +
|
|
32
|
+
'║ (starts with m00n_mcp_) ║\n' +
|
|
33
|
+
'║ ║\n' +
|
|
34
|
+
'║ For Cursor, add to your MCP config: ║\n' +
|
|
35
|
+
'║ ║\n' +
|
|
36
|
+
'║ { ║\n' +
|
|
37
|
+
'║ "mcpServers": { ║\n' +
|
|
38
|
+
'║ "m00n": { ║\n' +
|
|
39
|
+
'║ "command": "npx", ║\n' +
|
|
40
|
+
'║ "args": ["@m00nsolutions/mcp-server"], ║\n' +
|
|
41
|
+
'║ "env": { ║\n' +
|
|
42
|
+
'║ "M00N_API_URL": "https://app.m00nreport.com", ║\n' +
|
|
43
|
+
'║ "M00N_API_KEY": "m00n_mcp_..." ║\n' +
|
|
44
|
+
'║ } ║\n' +
|
|
45
|
+
'║ } ║\n' +
|
|
46
|
+
'║ } ║\n' +
|
|
47
|
+
'║ } ║\n' +
|
|
48
|
+
'╚═══════════════════════════════════════════════════════════════╝\n');
|
|
49
|
+
}
|
|
50
|
+
process.exit(1);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
// Run the main function
|
|
54
|
+
main();
|
|
55
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA,+CAA+C;AAC/C,EAAE;AACF,0DAA0D;AAC1D,2EAA2E;AAE3E,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C;;GAEG;AACH,KAAK,UAAU,IAAI;IACjB,IAAI,CAAC;QACH,kCAAkC;QAClC,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;QAE5B,mBAAmB;QACnB,MAAM,YAAY,CAAC,MAAM,CAAC,CAAC;IAC7B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACvE,GAAG,CAAC,gBAAgB,OAAO,EAAE,CAAC,CAAC;QAE/B,0CAA0C;QAC1C,IAAI,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC;YACzE,OAAO,CAAC,KAAK,CAAC,IAAI;gBAChB,qEAAqE;gBACrE,qEAAqE;gBACrE,qEAAqE;gBACrE,qEAAqE;gBACrE,qEAAqE;gBACrE,qEAAqE;gBACrE,qEAAqE;gBACrE,qEAAqE;gBACrE,qEAAqE;gBACrE,qEAAqE;gBACrE,qEAAqE;gBACrE,qEAAqE;gBACrE,qEAAqE;gBACrE,qEAAqE;gBACrE,qEAAqE;gBACrE,qEAAqE;gBACrE,qEAAqE;gBACrE,qEAAqE;gBACrE,qEAAqE;gBACrE,qEAAqE;gBACrE,qEAAqE;gBACrE,qEAAqE;gBACrE,qEAAqE;gBACrE,qEAAqE;gBACrE,qEAAqE;gBACrE,qEAAqE,CACtE,CAAC;QACJ,CAAC;QAED,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,wBAAwB;AACxB,IAAI,EAAE,CAAC"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
declare const ConfigSchema: z.ZodObject<{
|
|
3
|
+
apiUrl: z.ZodEffects<z.ZodString, string, string>;
|
|
4
|
+
apiKey: z.ZodEffects<z.ZodString, string, string>;
|
|
5
|
+
insecureSsl: z.ZodDefault<z.ZodBoolean>;
|
|
6
|
+
debug: z.ZodDefault<z.ZodBoolean>;
|
|
7
|
+
timeoutMs: z.ZodDefault<z.ZodNumber>;
|
|
8
|
+
}, "strip", z.ZodTypeAny, {
|
|
9
|
+
apiUrl: string;
|
|
10
|
+
apiKey: string;
|
|
11
|
+
insecureSsl: boolean;
|
|
12
|
+
debug: boolean;
|
|
13
|
+
timeoutMs: number;
|
|
14
|
+
}, {
|
|
15
|
+
apiUrl: string;
|
|
16
|
+
apiKey: string;
|
|
17
|
+
insecureSsl?: boolean | undefined;
|
|
18
|
+
debug?: boolean | undefined;
|
|
19
|
+
timeoutMs?: number | undefined;
|
|
20
|
+
}>;
|
|
21
|
+
export type Config = z.infer<typeof ConfigSchema>;
|
|
22
|
+
/**
|
|
23
|
+
* Parse and validate configuration from environment variables
|
|
24
|
+
* @throws Error if required variables are missing or invalid
|
|
25
|
+
*/
|
|
26
|
+
export declare function loadConfig(): Config;
|
|
27
|
+
/**
|
|
28
|
+
* Log message to stderr (MCP uses stdout for protocol, stderr for logs)
|
|
29
|
+
*/
|
|
30
|
+
export declare function log(message: string, config?: Config): void;
|
|
31
|
+
/**
|
|
32
|
+
* Log debug message (only when M00N_DEBUG=true)
|
|
33
|
+
*/
|
|
34
|
+
export declare function debug(message: string, config: Config): void;
|
|
35
|
+
export {};
|
|
36
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,QAAA,MAAM,YAAY;;;;;;;;;;;;;;;;;;EAehB,CAAC;AAEH,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAElD;;;GAGG;AACH,wBAAgB,UAAU,IAAI,MAAM,CA2BnC;AAmBD;;GAEG;AACH,wBAAgB,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAI1D;AAED;;GAEG;AACH,wBAAgB,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAI3D"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
// config.ts - Environment variable validation and configuration
|
|
2
|
+
//
|
|
3
|
+
// Required:
|
|
4
|
+
// M00N_API_URL - M00n Report API URL (e.g., https://app.m00nreport.com)
|
|
5
|
+
// M00N_API_KEY - MCP API key from Settings → MCP Keys
|
|
6
|
+
//
|
|
7
|
+
// Optional:
|
|
8
|
+
// M00N_INSECURE_SSL - Skip SSL verification (for self-signed certs)
|
|
9
|
+
// M00N_DEBUG - Enable verbose logging
|
|
10
|
+
// M00N_TIMEOUT_MS - Request timeout in ms (default: 30000)
|
|
11
|
+
import { z } from 'zod';
|
|
12
|
+
// Configuration schema with validation
|
|
13
|
+
const ConfigSchema = z.object({
|
|
14
|
+
apiUrl: z
|
|
15
|
+
.string()
|
|
16
|
+
.url('M00N_API_URL must be a valid URL')
|
|
17
|
+
.transform((url) => url.replace(/\/+$/, '')), // Remove trailing slashes
|
|
18
|
+
apiKey: z
|
|
19
|
+
.string()
|
|
20
|
+
.min(1, 'M00N_API_KEY is required')
|
|
21
|
+
.refine((key) => key.startsWith('m00n_mcp_'), 'M00N_API_KEY should start with "m00n_mcp_" - make sure you\'re using an MCP key, not a project API key'),
|
|
22
|
+
insecureSsl: z.boolean().default(false),
|
|
23
|
+
debug: z.boolean().default(false),
|
|
24
|
+
timeoutMs: z.number().int().positive().default(30000),
|
|
25
|
+
});
|
|
26
|
+
/**
|
|
27
|
+
* Parse and validate configuration from environment variables
|
|
28
|
+
* @throws Error if required variables are missing or invalid
|
|
29
|
+
*/
|
|
30
|
+
export function loadConfig() {
|
|
31
|
+
const rawConfig = {
|
|
32
|
+
apiUrl: process.env.M00N_API_URL,
|
|
33
|
+
apiKey: process.env.M00N_API_KEY,
|
|
34
|
+
insecureSsl: parseBooleanEnv(process.env.M00N_INSECURE_SSL),
|
|
35
|
+
debug: parseBooleanEnv(process.env.M00N_DEBUG),
|
|
36
|
+
timeoutMs: parseIntEnv(process.env.M00N_TIMEOUT_MS, 30000),
|
|
37
|
+
};
|
|
38
|
+
const result = ConfigSchema.safeParse(rawConfig);
|
|
39
|
+
if (!result.success) {
|
|
40
|
+
const errors = result.error.issues
|
|
41
|
+
.map((issue) => ` - ${issue.path.join('.')}: ${issue.message}`)
|
|
42
|
+
.join('\n');
|
|
43
|
+
throw new Error(`Invalid M00n MCP configuration:\n${errors}\n\n` +
|
|
44
|
+
'Required environment variables:\n' +
|
|
45
|
+
' M00N_API_URL - Your M00n Report API URL\n' +
|
|
46
|
+
' M00N_API_KEY - MCP key from Settings → MCP Keys\n\n' +
|
|
47
|
+
'Example:\n' +
|
|
48
|
+
' M00N_API_URL=https://app.m00nreport.com M00N_API_KEY=m00n_mcp_xxx...');
|
|
49
|
+
}
|
|
50
|
+
return result.data;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Parse boolean from environment variable
|
|
54
|
+
*/
|
|
55
|
+
function parseBooleanEnv(value) {
|
|
56
|
+
if (!value)
|
|
57
|
+
return false;
|
|
58
|
+
return ['true', '1', 'yes'].includes(value.toLowerCase());
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Parse integer from environment variable with default
|
|
62
|
+
*/
|
|
63
|
+
function parseIntEnv(value, defaultValue) {
|
|
64
|
+
if (!value)
|
|
65
|
+
return defaultValue;
|
|
66
|
+
const parsed = parseInt(value, 10);
|
|
67
|
+
return isNaN(parsed) ? defaultValue : parsed;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Log message to stderr (MCP uses stdout for protocol, stderr for logs)
|
|
71
|
+
*/
|
|
72
|
+
export function log(message, config) {
|
|
73
|
+
if (config?.debug || !config) {
|
|
74
|
+
console.error(`[m00n-mcp] ${message}`);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Log debug message (only when M00N_DEBUG=true)
|
|
79
|
+
*/
|
|
80
|
+
export function debug(message, config) {
|
|
81
|
+
if (config.debug) {
|
|
82
|
+
console.error(`[m00n-mcp:debug] ${message}`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAE,MAAM,EAAc,MAAM,aAAa,CAAC;AAGjD;;GAEG;AACH,wBAAsB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA0HhE"}
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
// server.ts - MCP Server setup and tool registration
|
|
2
|
+
//
|
|
3
|
+
// This module:
|
|
4
|
+
// 1. Fetches available tools from M00n Report API
|
|
5
|
+
// 2. Registers them with the MCP SDK
|
|
6
|
+
// 3. Handles tool invocations by proxying to the API
|
|
7
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
8
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
9
|
+
import { CallToolRequestSchema, ListToolsRequestSchema, ErrorCode, McpError, } from '@modelcontextprotocol/sdk/types.js';
|
|
10
|
+
import { M00nApiClient } from './api-client.js';
|
|
11
|
+
import { log, debug } from './config.js';
|
|
12
|
+
import { VERSION, PACKAGE_NAME } from './version.js';
|
|
13
|
+
/**
|
|
14
|
+
* Create and start the MCP server
|
|
15
|
+
*/
|
|
16
|
+
export async function createServer(config) {
|
|
17
|
+
log('Starting M00n MCP Server...', config);
|
|
18
|
+
// Create API client
|
|
19
|
+
const apiClient = new M00nApiClient(config);
|
|
20
|
+
// Step 1: Check API health
|
|
21
|
+
log(`Connecting to M00n Report API at ${config.apiUrl}...`, config);
|
|
22
|
+
let healthInfo;
|
|
23
|
+
try {
|
|
24
|
+
healthInfo = await apiClient.checkHealth();
|
|
25
|
+
log(`Connected to M00n Report API (version: ${healthInfo.version || 'unknown'}, mode: ${healthInfo.mode || 'unknown'})`, config);
|
|
26
|
+
}
|
|
27
|
+
catch (error) {
|
|
28
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
29
|
+
throw new Error(`Failed to connect to M00n Report API: ${message}`);
|
|
30
|
+
}
|
|
31
|
+
// Step 2: Fetch available tools
|
|
32
|
+
log('Fetching available tools...', config);
|
|
33
|
+
let tools;
|
|
34
|
+
try {
|
|
35
|
+
tools = await apiClient.fetchTools();
|
|
36
|
+
log(`Loaded ${tools.length} tools: ${tools.map((t) => t.name).join(', ')}`, config);
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
40
|
+
throw new Error(`Failed to fetch tools from API: ${message}`);
|
|
41
|
+
}
|
|
42
|
+
if (tools.length === 0) {
|
|
43
|
+
throw new Error('No tools available from M00n Report API. Please check your API key permissions.');
|
|
44
|
+
}
|
|
45
|
+
// Step 3: Create MCP server
|
|
46
|
+
const server = new Server({
|
|
47
|
+
name: PACKAGE_NAME,
|
|
48
|
+
version: VERSION,
|
|
49
|
+
}, {
|
|
50
|
+
capabilities: {
|
|
51
|
+
tools: {},
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
// Register list_tools handler
|
|
55
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
56
|
+
debug('Handling list_tools request', config);
|
|
57
|
+
return {
|
|
58
|
+
tools: tools.map((tool) => ({
|
|
59
|
+
name: tool.name,
|
|
60
|
+
description: tool.description,
|
|
61
|
+
inputSchema: tool.inputSchema,
|
|
62
|
+
})),
|
|
63
|
+
};
|
|
64
|
+
});
|
|
65
|
+
// Register call_tool handler
|
|
66
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
67
|
+
const { name, arguments: args } = request.params;
|
|
68
|
+
debug(`Handling call_tool request: ${name}`, config);
|
|
69
|
+
// Validate tool exists
|
|
70
|
+
const tool = tools.find((t) => t.name === name);
|
|
71
|
+
if (!tool) {
|
|
72
|
+
throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
|
|
73
|
+
}
|
|
74
|
+
try {
|
|
75
|
+
// Execute tool via API
|
|
76
|
+
const result = await apiClient.callTool(name, args || {});
|
|
77
|
+
// Return result as JSON content
|
|
78
|
+
return {
|
|
79
|
+
content: [
|
|
80
|
+
{
|
|
81
|
+
type: 'text',
|
|
82
|
+
text: JSON.stringify(result, null, 2),
|
|
83
|
+
},
|
|
84
|
+
],
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
89
|
+
// Return error as content (not throwing, so Claude can see the error)
|
|
90
|
+
return {
|
|
91
|
+
content: [
|
|
92
|
+
{
|
|
93
|
+
type: 'text',
|
|
94
|
+
text: `Error executing ${name}: ${message}`,
|
|
95
|
+
},
|
|
96
|
+
],
|
|
97
|
+
isError: true,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
// Step 4: Connect via stdio transport
|
|
102
|
+
const transport = new StdioServerTransport();
|
|
103
|
+
// Handle server errors
|
|
104
|
+
server.onerror = (error) => {
|
|
105
|
+
log(`Server error: ${error.message}`, config);
|
|
106
|
+
};
|
|
107
|
+
// Handle process signals for graceful shutdown
|
|
108
|
+
process.on('SIGINT', async () => {
|
|
109
|
+
log('Received SIGINT, shutting down...', config);
|
|
110
|
+
await server.close();
|
|
111
|
+
process.exit(0);
|
|
112
|
+
});
|
|
113
|
+
process.on('SIGTERM', async () => {
|
|
114
|
+
log('Received SIGTERM, shutting down...', config);
|
|
115
|
+
await server.close();
|
|
116
|
+
process.exit(0);
|
|
117
|
+
});
|
|
118
|
+
// Connect and start serving
|
|
119
|
+
await server.connect(transport);
|
|
120
|
+
log('M00n MCP Server running (stdio transport)', config);
|
|
121
|
+
log('Ready to receive requests from Claude/Cursor', config);
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAwCA,eAAO,MAAM,OAAO,QAAc,CAAC;AACnC,eAAO,MAAM,YAAY,QAAW,CAAC"}
|
package/dist/version.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// version.ts - Package version constant
|
|
2
|
+
//
|
|
3
|
+
// Reads version from package.json to ensure consistency across:
|
|
4
|
+
// - package.json
|
|
5
|
+
// - User-Agent header
|
|
6
|
+
// - MCP server version
|
|
7
|
+
import { createRequire } from 'module';
|
|
8
|
+
import { fileURLToPath } from 'url';
|
|
9
|
+
import { dirname, join } from 'path';
|
|
10
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
11
|
+
const __dirname = dirname(__filename);
|
|
12
|
+
// Read version from package.json at runtime
|
|
13
|
+
const require = createRequire(import.meta.url);
|
|
14
|
+
// Try to load from dist/../package.json (runtime) or src/../package.json (dev)
|
|
15
|
+
function loadPackageJson() {
|
|
16
|
+
try {
|
|
17
|
+
// When running from dist/, go up one level to find package.json
|
|
18
|
+
return require(join(__dirname, '..', 'package.json'));
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
// Fallback for development
|
|
22
|
+
try {
|
|
23
|
+
return require(join(__dirname, '..', '..', 'package.json'));
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
// Ultimate fallback
|
|
27
|
+
return { name: '@m00nsolutions/mcp-server', version: '1.0.0' };
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
const pkg = loadPackageJson();
|
|
32
|
+
export const VERSION = pkg.version;
|
|
33
|
+
export const PACKAGE_NAME = pkg.name;
|
|
34
|
+
//# sourceMappingURL=version.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,wCAAwC;AACxC,EAAE;AACF,gEAAgE;AAChE,iBAAiB;AACjB,sBAAsB;AACtB,uBAAuB;AAEvB,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAErC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAEtC,4CAA4C;AAC5C,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAO/C,+EAA+E;AAC/E,SAAS,eAAe;IACtB,IAAI,CAAC;QACH,gEAAgE;QAChE,OAAO,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC;IACxD,CAAC;IAAC,MAAM,CAAC;QACP,2BAA2B;QAC3B,IAAI,CAAC;YACH,OAAO,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC;QAC9D,CAAC;QAAC,MAAM,CAAC;YACP,oBAAoB;YACpB,OAAO,EAAE,IAAI,EAAE,2BAA2B,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;QACjE,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,GAAG,GAAG,eAAe,EAAE,CAAC;AAE9B,MAAM,CAAC,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC;AACnC,MAAM,CAAC,MAAM,YAAY,GAAG,GAAG,CAAC,IAAI,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@m00nsolutions/mcp-server",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "MCP server for M00n Report - enables AI assistants like Claude and Cursor to query test analytics",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/cli.js",
|
|
7
|
+
"types": "dist/cli.d.ts",
|
|
8
|
+
"bin": {
|
|
9
|
+
"m00n-mcp": "./bin/m00n-mcp.js"
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"dist",
|
|
13
|
+
"bin",
|
|
14
|
+
"README.md",
|
|
15
|
+
"LICENSE"
|
|
16
|
+
],
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "tsc",
|
|
19
|
+
"prepublishOnly": "npm run build",
|
|
20
|
+
"clean": "rimraf dist"
|
|
21
|
+
},
|
|
22
|
+
"keywords": [
|
|
23
|
+
"mcp",
|
|
24
|
+
"model-context-protocol",
|
|
25
|
+
"m00n",
|
|
26
|
+
"m00nreport",
|
|
27
|
+
"test-reporting",
|
|
28
|
+
"ai",
|
|
29
|
+
"claude",
|
|
30
|
+
"cursor",
|
|
31
|
+
"testing",
|
|
32
|
+
"analytics",
|
|
33
|
+
"playwright",
|
|
34
|
+
"jest"
|
|
35
|
+
],
|
|
36
|
+
"author": "M00n Solutions",
|
|
37
|
+
"license": "MIT",
|
|
38
|
+
"repository": {
|
|
39
|
+
"type": "git",
|
|
40
|
+
"url": "https://github.com/m00nsolutions/m00nreport.git",
|
|
41
|
+
"directory": "packages/m00n-mcp-server"
|
|
42
|
+
},
|
|
43
|
+
"homepage": "https://m00nreport.com",
|
|
44
|
+
"bugs": {
|
|
45
|
+
"url": "https://github.com/m00nsolutions/m00nreport/issues"
|
|
46
|
+
},
|
|
47
|
+
"engines": {
|
|
48
|
+
"node": ">=18.0.0"
|
|
49
|
+
},
|
|
50
|
+
"dependencies": {
|
|
51
|
+
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
52
|
+
"axios": "^1.6.0",
|
|
53
|
+
"zod": "^3.22.0"
|
|
54
|
+
},
|
|
55
|
+
"devDependencies": {
|
|
56
|
+
"@types/node": "^20.0.0",
|
|
57
|
+
"rimraf": "^5.0.0",
|
|
58
|
+
"typescript": "^5.3.0"
|
|
59
|
+
}
|
|
60
|
+
}
|