@inova.dev/devspace-mcp 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/README.md +115 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +250 -0
- package/dist/index.js.map +1 -0
- package/package.json +39 -0
package/README.md
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# @inova.dev/devspace-mcp
|
|
2
|
+
|
|
3
|
+
MCP server that lets any AI client (Claude Desktop, Claude Code, Cursor, etc.) read and update DevSpace tests for a **specific codebase**, authenticated with an Unkey-issued API key.
|
|
4
|
+
|
|
5
|
+
Tools exposed:
|
|
6
|
+
|
|
7
|
+
| Tool | Maps to |
|
|
8
|
+
| --- | --- |
|
|
9
|
+
| `codebase_context` | `POST /tests/context` — returns the decrypted project + codebase names + ids |
|
|
10
|
+
| `list_tests` | `POST /tests/list` |
|
|
11
|
+
| `get_test` | `POST /tests/get` |
|
|
12
|
+
| `create_test` | `POST /tests/create` |
|
|
13
|
+
| `mark_test_status` | `POST /tests/setStatus` |
|
|
14
|
+
| `delete_test` | `POST /tests/delete` |
|
|
15
|
+
|
|
16
|
+
The bound codebase is whatever the API key was minted for — there is no codebase argument and no way to widen scope.
|
|
17
|
+
|
|
18
|
+
## Setup (one-time)
|
|
19
|
+
|
|
20
|
+
1. **In the DevSpace desktop app**, open the codebase you want the AI to manage → **API Keys** → **New key**. Give it a label like "Claude Desktop" and decide:
|
|
21
|
+
- **Permissions**: `tests:read` for read-only AI, `tests:read tests:write` for "AI can also add and update tests."
|
|
22
|
+
- **Rate limit**: e.g. 60/min — useful guardrail for runaway agents.
|
|
23
|
+
- **Expiry**: leave off, or set 30/60/90 days for rotation discipline.
|
|
24
|
+
|
|
25
|
+
Copy the key when shown (`ds_org_…`). You won't see it again.
|
|
26
|
+
|
|
27
|
+
2. **Install the MCP server**. You can `npx` it directly (the snippets below do that) or `npm i -g @inova.dev/devspace-mcp` if you want it on `PATH`.
|
|
28
|
+
|
|
29
|
+
3. **Wire it into your AI client.** The exact file varies — see below.
|
|
30
|
+
|
|
31
|
+
## Wiring it in
|
|
32
|
+
|
|
33
|
+
### Claude Desktop
|
|
34
|
+
|
|
35
|
+
Edit `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS):
|
|
36
|
+
|
|
37
|
+
```json
|
|
38
|
+
{
|
|
39
|
+
"mcpServers": {
|
|
40
|
+
"devspace": {
|
|
41
|
+
"command": "npx",
|
|
42
|
+
"args": ["-y", "@inova.dev/devspace-mcp"],
|
|
43
|
+
"env": {
|
|
44
|
+
"DEVSPACE_API_KEY": "ds_org_xxxxxxxxxxxxxxxxxxxxxxxx",
|
|
45
|
+
"DEVSPACE_API_URL": "https://YOUR-PROJECT.supabase.co/functions/v1/tests"
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Restart Claude Desktop. New "devspace" tools appear in the tool picker.
|
|
53
|
+
|
|
54
|
+
### Claude Code
|
|
55
|
+
|
|
56
|
+
`claude mcp add devspace`, then edit the entry:
|
|
57
|
+
|
|
58
|
+
```jsonc
|
|
59
|
+
{
|
|
60
|
+
"command": "npx",
|
|
61
|
+
"args": ["-y", "@inova.dev/devspace-mcp"],
|
|
62
|
+
"env": {
|
|
63
|
+
"DEVSPACE_API_KEY": "ds_org_…",
|
|
64
|
+
"DEVSPACE_API_URL": "https://YOUR-PROJECT.supabase.co/functions/v1/tests"
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Cursor / other MCP-aware clients
|
|
70
|
+
|
|
71
|
+
Same shape — stdio transport, command + args + env.
|
|
72
|
+
|
|
73
|
+
## Conventional prompts to try
|
|
74
|
+
|
|
75
|
+
Once connected, the AI can drive the codebase's tests directly:
|
|
76
|
+
|
|
77
|
+
> **"What's the test coverage status for this codebase?"**
|
|
78
|
+
> Calls `codebase_context` + `list_tests` and summarizes by status.
|
|
79
|
+
|
|
80
|
+
> **"Add a test under Auth: 'New user signs up with email' — steps: open Sign Up, enter credentials, confirm. Expected: lands on dashboard."**
|
|
81
|
+
> Calls `create_test` with structured fields.
|
|
82
|
+
|
|
83
|
+
> **"Mark `<test-id>` as passing — I tested it on iOS 26."**
|
|
84
|
+
> Calls `mark_test_status` with `runBy: "<your name>"` and the note.
|
|
85
|
+
|
|
86
|
+
> **"For every test still marked 'pending' under Billing, generate a one-paragraph steps section."**
|
|
87
|
+
> Reads via `list_tests`, then loops `mark_test_status` with notes.
|
|
88
|
+
|
|
89
|
+
## Security model
|
|
90
|
+
|
|
91
|
+
- The key authorizes **only this codebase**. It cannot see, list, or modify tests on any other codebase or org — that's enforced server-side by the Edge Function reading `meta.codebaseId` off the verified Unkey result.
|
|
92
|
+
- Each key carries its own sealed envelope so the Edge Function can return decrypted project + codebase names to the AI for `codebase_context`. The envelope can only be unsealed by holders of this specific key string.
|
|
93
|
+
- **Revoking the key in the DevSpace admin sheet immediately revokes AI access** — the next request fails with HTTP 401.
|
|
94
|
+
- **Rotating** = mint a new key, update `DEVSPACE_API_KEY` in the AI client config, restart, then revoke the old one.
|
|
95
|
+
|
|
96
|
+
## Local development
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
npm install
|
|
100
|
+
npm run build
|
|
101
|
+
DEVSPACE_API_KEY=ds_org_… \
|
|
102
|
+
DEVSPACE_API_URL=https://your-project.supabase.co/functions/v1/tests \
|
|
103
|
+
npm start
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Stdio is the transport — drop it into any MCP client that speaks stdio. For a quick poke without an AI client, the `@modelcontextprotocol/inspector` tool will let you call tools by hand.
|
|
107
|
+
|
|
108
|
+
## Adding new tools
|
|
109
|
+
|
|
110
|
+
1. Add a `Tool` entry in `src/index.ts` (`tools` array).
|
|
111
|
+
2. Add a Zod schema for the inputs.
|
|
112
|
+
3. Add a case in the `CallToolRequestSchema` handler that parses args and calls `callEdge(action, args)`.
|
|
113
|
+
4. On the Edge Function side, add a matching switch case in `supabase/functions/tests/index.ts`.
|
|
114
|
+
|
|
115
|
+
That's it — no SDK regen, no protocol negotiation.
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
//
|
|
3
|
+
// @inova.dev/devspace-mcp — MCP server that surfaces the DevSpace tests API as tools
|
|
4
|
+
// an AI client (Claude Desktop, Claude Code, Cursor, etc.) can call.
|
|
5
|
+
//
|
|
6
|
+
// All tools are scoped to the codebase the Unkey API key was minted for —
|
|
7
|
+
// there's no codebase argument and no way to widen scope. Want a different
|
|
8
|
+
// codebase? Use a different key.
|
|
9
|
+
//
|
|
10
|
+
// Required env:
|
|
11
|
+
// DEVSPACE_API_KEY — Unkey-issued bearer token (ds_org_…) from the
|
|
12
|
+
// DevSpace "API Keys" admin sheet for the codebase.
|
|
13
|
+
// DEVSPACE_API_URL — full URL of the deployed Edge Function, e.g.
|
|
14
|
+
// https://<project>.supabase.co/functions/v1/tests
|
|
15
|
+
//
|
|
16
|
+
// Optional env:
|
|
17
|
+
// DEVSPACE_TIMEOUT_MS — per-request timeout (default 15000)
|
|
18
|
+
//
|
|
19
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
20
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
21
|
+
import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
|
|
22
|
+
import { z } from "zod";
|
|
23
|
+
// -------------------- Env --------------------
|
|
24
|
+
const API_KEY = requireEnv("DEVSPACE_API_KEY");
|
|
25
|
+
const API_URL = requireEnv("DEVSPACE_API_URL").replace(/\/+$/, "");
|
|
26
|
+
const TIMEOUT_MS = Number(process.env.DEVSPACE_TIMEOUT_MS ?? "15000");
|
|
27
|
+
// -------------------- Schemas --------------------
|
|
28
|
+
const ListSchema = z.object({
|
|
29
|
+
featureId: z.string().optional(),
|
|
30
|
+
groupName: z.string().optional(),
|
|
31
|
+
status: z
|
|
32
|
+
.enum(["pending", "passing", "failing", "blocked", "skipped"])
|
|
33
|
+
.optional(),
|
|
34
|
+
});
|
|
35
|
+
const GetSchema = z.object({
|
|
36
|
+
id: z.string().min(1, "id required"),
|
|
37
|
+
});
|
|
38
|
+
const CreateSchema = z.object({
|
|
39
|
+
title: z.string().min(1),
|
|
40
|
+
groupName: z.string().optional(),
|
|
41
|
+
displayId: z.string().optional(),
|
|
42
|
+
steps: z.string().optional(),
|
|
43
|
+
expectedResult: z.string().optional(),
|
|
44
|
+
notes: z.string().optional(),
|
|
45
|
+
status: z
|
|
46
|
+
.enum(["pending", "passing", "failing", "blocked", "skipped"])
|
|
47
|
+
.optional(),
|
|
48
|
+
featureId: z.string().optional(),
|
|
49
|
+
sortOrder: z.number().int().optional(),
|
|
50
|
+
});
|
|
51
|
+
const SetStatusSchema = z.object({
|
|
52
|
+
id: z.string().min(1),
|
|
53
|
+
status: z.enum(["pending", "passing", "failing", "blocked", "skipped"]),
|
|
54
|
+
runBy: z.string().optional(),
|
|
55
|
+
notes: z.string().optional(),
|
|
56
|
+
});
|
|
57
|
+
const DeleteSchema = z.object({
|
|
58
|
+
id: z.string().min(1),
|
|
59
|
+
});
|
|
60
|
+
// -------------------- Tools --------------------
|
|
61
|
+
const tools = [
|
|
62
|
+
{
|
|
63
|
+
name: "codebase_context",
|
|
64
|
+
description: "Get the project + codebase this API key is bound to. Use at the start " +
|
|
65
|
+
"of a conversation so you know which codebase you're working with.",
|
|
66
|
+
inputSchema: { type: "object", properties: {} },
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
name: "list_tests",
|
|
70
|
+
description: "List tests for the bound codebase. Optionally filter by status, " +
|
|
71
|
+
"groupName (phase / section), or featureId. Returns id, title, group, " +
|
|
72
|
+
"status, steps, expected, notes for each.",
|
|
73
|
+
inputSchema: {
|
|
74
|
+
type: "object",
|
|
75
|
+
properties: {
|
|
76
|
+
featureId: { type: "string", description: "Filter to a single feature id" },
|
|
77
|
+
groupName: { type: "string", description: "Filter to a single phase / group" },
|
|
78
|
+
status: {
|
|
79
|
+
type: "string",
|
|
80
|
+
enum: ["pending", "passing", "failing", "blocked", "skipped"],
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
name: "get_test",
|
|
87
|
+
description: "Get the full record for a single test by id.",
|
|
88
|
+
inputSchema: {
|
|
89
|
+
type: "object",
|
|
90
|
+
properties: { id: { type: "string" } },
|
|
91
|
+
required: ["id"],
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
name: "create_test",
|
|
96
|
+
description: "Create a new test on the bound codebase. Required: title. Optional: " +
|
|
97
|
+
"groupName (phase), steps, expectedResult, notes, displayId, status " +
|
|
98
|
+
"(defaults to 'pending'), featureId, sortOrder.",
|
|
99
|
+
inputSchema: {
|
|
100
|
+
type: "object",
|
|
101
|
+
properties: {
|
|
102
|
+
title: { type: "string" },
|
|
103
|
+
groupName: { type: "string" },
|
|
104
|
+
displayId: { type: "string" },
|
|
105
|
+
steps: { type: "string" },
|
|
106
|
+
expectedResult: { type: "string" },
|
|
107
|
+
notes: { type: "string" },
|
|
108
|
+
status: {
|
|
109
|
+
type: "string",
|
|
110
|
+
enum: ["pending", "passing", "failing", "blocked", "skipped"],
|
|
111
|
+
},
|
|
112
|
+
featureId: { type: "string" },
|
|
113
|
+
sortOrder: { type: "integer" },
|
|
114
|
+
},
|
|
115
|
+
required: ["title"],
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
name: "mark_test_status",
|
|
120
|
+
description: "Update a test's status. For 'passing' / 'failing', also stamps " +
|
|
121
|
+
"last_run_at; pass runBy to attribute the run to a person or agent.",
|
|
122
|
+
inputSchema: {
|
|
123
|
+
type: "object",
|
|
124
|
+
properties: {
|
|
125
|
+
id: { type: "string" },
|
|
126
|
+
status: {
|
|
127
|
+
type: "string",
|
|
128
|
+
enum: ["pending", "passing", "failing", "blocked", "skipped"],
|
|
129
|
+
},
|
|
130
|
+
runBy: { type: "string" },
|
|
131
|
+
notes: { type: "string" },
|
|
132
|
+
},
|
|
133
|
+
required: ["id", "status"],
|
|
134
|
+
},
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
name: "delete_test",
|
|
138
|
+
description: "Permanently delete a test. Prefer mark_test_status 'skipped' if you " +
|
|
139
|
+
"just want to deprioritize it.",
|
|
140
|
+
inputSchema: {
|
|
141
|
+
type: "object",
|
|
142
|
+
properties: { id: { type: "string" } },
|
|
143
|
+
required: ["id"],
|
|
144
|
+
},
|
|
145
|
+
},
|
|
146
|
+
];
|
|
147
|
+
// -------------------- HTTP --------------------
|
|
148
|
+
async function callEdge(action, body = {}) {
|
|
149
|
+
const controller = new AbortController();
|
|
150
|
+
const timer = setTimeout(() => controller.abort(), TIMEOUT_MS);
|
|
151
|
+
try {
|
|
152
|
+
const res = await fetch(`${API_URL}/${action}`, {
|
|
153
|
+
method: "POST",
|
|
154
|
+
headers: {
|
|
155
|
+
"authorization": `Bearer ${API_KEY}`,
|
|
156
|
+
"content-type": "application/json",
|
|
157
|
+
},
|
|
158
|
+
body: JSON.stringify(body),
|
|
159
|
+
signal: controller.signal,
|
|
160
|
+
});
|
|
161
|
+
const text = await res.text();
|
|
162
|
+
let json = null;
|
|
163
|
+
try {
|
|
164
|
+
json = text ? JSON.parse(text) : null;
|
|
165
|
+
}
|
|
166
|
+
catch { /* leave as text */ }
|
|
167
|
+
if (!res.ok) {
|
|
168
|
+
const msg = json?.error ?? text ?? res.statusText;
|
|
169
|
+
throw new Error(`DevSpace API ${res.status}: ${msg}`);
|
|
170
|
+
}
|
|
171
|
+
return json;
|
|
172
|
+
}
|
|
173
|
+
finally {
|
|
174
|
+
clearTimeout(timer);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
// -------------------- Dispatch --------------------
|
|
178
|
+
const server = new Server({ name: "devspace", version: "0.1.0" }, { capabilities: { tools: {} } });
|
|
179
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools }));
|
|
180
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
181
|
+
const { name, arguments: rawArgs = {} } = request.params;
|
|
182
|
+
try {
|
|
183
|
+
switch (name) {
|
|
184
|
+
case "codebase_context": {
|
|
185
|
+
const result = await callEdge("context");
|
|
186
|
+
return ok(result);
|
|
187
|
+
}
|
|
188
|
+
case "list_tests": {
|
|
189
|
+
const args = ListSchema.parse(rawArgs);
|
|
190
|
+
const result = await callEdge("list", args);
|
|
191
|
+
return ok(result);
|
|
192
|
+
}
|
|
193
|
+
case "get_test": {
|
|
194
|
+
const args = GetSchema.parse(rawArgs);
|
|
195
|
+
const result = await callEdge("get", args);
|
|
196
|
+
return ok(result);
|
|
197
|
+
}
|
|
198
|
+
case "create_test": {
|
|
199
|
+
const args = CreateSchema.parse(rawArgs);
|
|
200
|
+
const result = await callEdge("create", args);
|
|
201
|
+
return ok(result);
|
|
202
|
+
}
|
|
203
|
+
case "mark_test_status": {
|
|
204
|
+
const args = SetStatusSchema.parse(rawArgs);
|
|
205
|
+
const result = await callEdge("setStatus", args);
|
|
206
|
+
return ok(result);
|
|
207
|
+
}
|
|
208
|
+
case "delete_test": {
|
|
209
|
+
const args = DeleteSchema.parse(rawArgs);
|
|
210
|
+
const result = await callEdge("delete", args);
|
|
211
|
+
return ok(result);
|
|
212
|
+
}
|
|
213
|
+
default:
|
|
214
|
+
return err(`Unknown tool: ${name}`);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
catch (e) {
|
|
218
|
+
return err(e.message);
|
|
219
|
+
}
|
|
220
|
+
});
|
|
221
|
+
function ok(payload) {
|
|
222
|
+
return {
|
|
223
|
+
content: [
|
|
224
|
+
{ type: "text", text: JSON.stringify(payload, null, 2) },
|
|
225
|
+
],
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
function err(message) {
|
|
229
|
+
return {
|
|
230
|
+
isError: true,
|
|
231
|
+
content: [{ type: "text", text: message }],
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
// -------------------- Boot --------------------
|
|
235
|
+
function requireEnv(name) {
|
|
236
|
+
const v = process.env[name];
|
|
237
|
+
if (!v) {
|
|
238
|
+
console.error(`Missing required env: ${name}`);
|
|
239
|
+
console.error("");
|
|
240
|
+
console.error("Required:");
|
|
241
|
+
console.error(" DEVSPACE_API_KEY — Unkey-issued bearer token (ds_org_…)");
|
|
242
|
+
console.error(" DEVSPACE_API_URL — https://<project>.supabase.co/functions/v1/tests");
|
|
243
|
+
process.exit(1);
|
|
244
|
+
}
|
|
245
|
+
return v;
|
|
246
|
+
}
|
|
247
|
+
const transport = new StdioServerTransport();
|
|
248
|
+
await server.connect(transport);
|
|
249
|
+
console.error("[devspace-mcp] ready");
|
|
250
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,EAAE;AACF,qFAAqF;AACrF,qEAAqE;AACrE,EAAE;AACF,0EAA0E;AAC1E,2EAA2E;AAC3E,iCAAiC;AACjC,EAAE;AACF,gBAAgB;AAChB,sEAAsE;AACtE,0EAA0E;AAC1E,qEAAqE;AACrE,yEAAyE;AACzE,EAAE;AACF,gBAAgB;AAChB,+DAA+D;AAC/D,EAAE;AAEF,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EACL,qBAAqB,EACrB,sBAAsB,GAEvB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,gDAAgD;AAEhD,MAAM,OAAO,GAAG,UAAU,CAAC,kBAAkB,CAAC,CAAC;AAC/C,MAAM,OAAO,GAAG,UAAU,CAAC,kBAAkB,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AACnE,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,OAAO,CAAC,CAAC;AAEtE,oDAAoD;AAEpD,MAAM,UAAU,GAAG,CAAC,CAAC,MAAM,CAAC;IAC1B,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAChC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAChC,MAAM,EAAE,CAAC;SACN,IAAI,CAAC,CAAC,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;SAC7D,QAAQ,EAAE;CACd,CAAC,CAAC;AAEH,MAAM,SAAS,GAAG,CAAC,CAAC,MAAM,CAAC;IACzB,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,aAAa,CAAC;CACrC,CAAC,CAAC;AAEH,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5B,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACxB,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAChC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAChC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC5B,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACrC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC5B,MAAM,EAAE,CAAC;SACN,IAAI,CAAC,CAAC,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;SAC7D,QAAQ,EAAE;IACb,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAChC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;CACvC,CAAC,CAAC;AAEH,MAAM,eAAe,GAAG,CAAC,CAAC,MAAM,CAAC;IAC/B,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACrB,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;IACvE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC5B,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAC7B,CAAC,CAAC;AAEH,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5B,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;CACtB,CAAC,CAAC;AAEH,kDAAkD;AAElD,MAAM,KAAK,GAAW;IACpB;QACE,IAAI,EAAE,kBAAkB;QACxB,WAAW,EACT,wEAAwE;YACxE,mEAAmE;QACrE,WAAW,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,EAAE;KAChD;IACD;QACE,IAAI,EAAE,YAAY;QAClB,WAAW,EACT,kEAAkE;YAClE,uEAAuE;YACvE,0CAA0C;QAC5C,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,SAAS,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,+BAA+B,EAAE;gBAC3E,SAAS,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,kCAAkC,EAAE;gBAC9E,MAAM,EAAE;oBACN,IAAI,EAAE,QAAQ;oBACd,IAAI,EAAE,CAAC,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,CAAC;iBAC9D;aACF;SACF;KACF;IACD;QACE,IAAI,EAAE,UAAU;QAChB,WAAW,EAAE,8CAA8C;QAC3D,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;YACtC,QAAQ,EAAE,CAAC,IAAI,CAAC;SACjB;KACF;IACD;QACE,IAAI,EAAE,aAAa;QACnB,WAAW,EACT,sEAAsE;YACtE,qEAAqE;YACrE,gDAAgD;QAClD,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;gBACzB,SAAS,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;gBAC7B,SAAS,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;gBAC7B,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;gBACzB,cAAc,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;gBAClC,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;gBACzB,MAAM,EAAE;oBACN,IAAI,EAAE,QAAQ;oBACd,IAAI,EAAE,CAAC,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,CAAC;iBAC9D;gBACD,SAAS,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;gBAC7B,SAAS,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;aAC/B;YACD,QAAQ,EAAE,CAAC,OAAO,CAAC;SACpB;KACF;IACD;QACE,IAAI,EAAE,kBAAkB;QACxB,WAAW,EACT,iEAAiE;YACjE,oEAAoE;QACtE,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;gBACtB,MAAM,EAAE;oBACN,IAAI,EAAE,QAAQ;oBACd,IAAI,EAAE,CAAC,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,CAAC;iBAC9D;gBACD,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;gBACzB,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;aAC1B;YACD,QAAQ,EAAE,CAAC,IAAI,EAAE,QAAQ,CAAC;SAC3B;KACF;IACD;QACE,IAAI,EAAE,aAAa;QACnB,WAAW,EACT,sEAAsE;YACtE,+BAA+B;QACjC,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;YACtC,QAAQ,EAAE,CAAC,IAAI,CAAC;SACjB;KACF;CACF,CAAC;AAEF,iDAAiD;AAEjD,KAAK,UAAU,QAAQ,CAAC,MAAc,EAAE,OAAgB,EAAE;IACxD,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,UAAU,CAAC,CAAC;IAC/D,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,OAAO,IAAI,MAAM,EAAE,EAAE;YAC9C,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,eAAe,EAAE,UAAU,OAAO,EAAE;gBACpC,cAAc,EAAE,kBAAkB;aACnC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;YAC1B,MAAM,EAAE,UAAU,CAAC,MAAM;SAC1B,CAAC,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;QAC9B,IAAI,IAAI,GAAY,IAAI,CAAC;QACzB,IAAI,CAAC;YAAC,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC,CAAC,mBAAmB,CAAC,CAAC;QAC5E,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,GAAG,GAAI,IAAkC,EAAE,KAAK,IAAI,IAAI,IAAI,GAAG,CAAC,UAAU,CAAC;YACjF,MAAM,IAAI,KAAK,CAAC,gBAAgB,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC,CAAC;QACxD,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;YAAS,CAAC;QACT,YAAY,CAAC,KAAK,CAAC,CAAC;IACtB,CAAC;AACH,CAAC;AAED,qDAAqD;AAErD,MAAM,MAAM,GAAG,IAAI,MAAM,CACvB,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,EAAE,EACtC,EAAE,YAAY,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,CAChC,CAAC;AAEF,MAAM,CAAC,iBAAiB,CAAC,sBAAsB,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;AAE1E,MAAM,CAAC,iBAAiB,CAAC,qBAAqB,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;IAChE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IACzD,IAAI,CAAC;QACH,QAAQ,IAAI,EAAE,CAAC;YACb,KAAK,kBAAkB,CAAC,CAAC,CAAC;gBACxB,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,SAAS,CAAC,CAAC;gBACzC,OAAO,EAAE,CAAC,MAAM,CAAC,CAAC;YACpB,CAAC;YACD,KAAK,YAAY,CAAC,CAAC,CAAC;gBAClB,MAAM,IAAI,GAAG,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;gBACvC,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;gBAC5C,OAAO,EAAE,CAAC,MAAM,CAAC,CAAC;YACpB,CAAC;YACD,KAAK,UAAU,CAAC,CAAC,CAAC;gBAChB,MAAM,IAAI,GAAG,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;gBACtC,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;gBAC3C,OAAO,EAAE,CAAC,MAAM,CAAC,CAAC;YACpB,CAAC;YACD,KAAK,aAAa,CAAC,CAAC,CAAC;gBACnB,MAAM,IAAI,GAAG,YAAY,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;gBACzC,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;gBAC9C,OAAO,EAAE,CAAC,MAAM,CAAC,CAAC;YACpB,CAAC;YACD,KAAK,kBAAkB,CAAC,CAAC,CAAC;gBACxB,MAAM,IAAI,GAAG,eAAe,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;gBAC5C,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;gBACjD,OAAO,EAAE,CAAC,MAAM,CAAC,CAAC;YACpB,CAAC;YACD,KAAK,aAAa,CAAC,CAAC,CAAC;gBACnB,MAAM,IAAI,GAAG,YAAY,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;gBACzC,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;gBAC9C,OAAO,EAAE,CAAC,MAAM,CAAC,CAAC;YACpB,CAAC;YACD;gBACE,OAAO,GAAG,CAAC,iBAAiB,IAAI,EAAE,CAAC,CAAC;QACxC,CAAC;IACH,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,GAAG,CAAE,CAAW,CAAC,OAAO,CAAC,CAAC;IACnC,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,SAAS,EAAE,CAAC,OAAgB;IAC1B,OAAO;QACL,OAAO,EAAE;YACP,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE;SACzD;KACF,CAAC;AACJ,CAAC;AAED,SAAS,GAAG,CAAC,OAAe;IAC1B,OAAO;QACL,OAAO,EAAE,IAAI;QACb,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;KAC3C,CAAC;AACJ,CAAC;AAED,iDAAiD;AAEjD,SAAS,UAAU,CAAC,IAAY;IAC9B,MAAM,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC5B,IAAI,CAAC,CAAC,EAAE,CAAC;QACP,OAAO,CAAC,KAAK,CAAC,yBAAyB,IAAI,EAAE,CAAC,CAAC;QAC/C,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAClB,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;QAC3B,OAAO,CAAC,KAAK,CAAC,4DAA4D,CAAC,CAAC;QAC5E,OAAO,CAAC,KAAK,CAAC,wEAAwE,CAAC,CAAC;QACxF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAED,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;AAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AAChC,OAAO,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@inova.dev/devspace-mcp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "MCP server that lets AI clients (Claude Desktop, Claude Code, etc.) read and update DevSpace tests for a specific codebase, scoped via an Unkey-issued API key.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"devspace-mcp": "dist/index.js"
|
|
8
|
+
},
|
|
9
|
+
"main": "dist/index.js",
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"README.md"
|
|
13
|
+
],
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "tsc",
|
|
16
|
+
"dev": "tsc --watch",
|
|
17
|
+
"start": "node dist/index.js",
|
|
18
|
+
"prepublishOnly": "npm run build"
|
|
19
|
+
},
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"@modelcontextprotocol/sdk": "^1.0.4",
|
|
22
|
+
"zod": "^3.23.8"
|
|
23
|
+
},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"@types/node": "^22.10.2",
|
|
26
|
+
"typescript": "^5.7.2"
|
|
27
|
+
},
|
|
28
|
+
"engines": {
|
|
29
|
+
"node": ">=20.0.0"
|
|
30
|
+
},
|
|
31
|
+
"keywords": [
|
|
32
|
+
"mcp",
|
|
33
|
+
"model-context-protocol",
|
|
34
|
+
"claude",
|
|
35
|
+
"devspace",
|
|
36
|
+
"tests"
|
|
37
|
+
],
|
|
38
|
+
"license": "MIT"
|
|
39
|
+
}
|