@doksi/mcp 0.1.1

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 ADDED
@@ -0,0 +1,11 @@
1
+ # Doksi MCP
2
+
3
+ MCP server for using Doksi from Claude, Codex, and other MCP clients.
4
+
5
+ ```bash
6
+ npm install
7
+ npm run build
8
+ DOKSI_API_KEY=dk_live_... doksi
9
+ ```
10
+
11
+ The server exposes workspace resources, PRD/user-story prompts, and tools for creating tests, uploading artifacts, and running tests using Doksi.
package/SKILL.md ADDED
@@ -0,0 +1,15 @@
1
+ # Doksi MCP
2
+
3
+ Use Doksi MCP to inspect a Doksi workspace, create tests from product requirements, upload target apps and parameter files, and run tests.
4
+
5
+ Preferred workflow:
6
+
7
+ 1. Read `doksi://workspace/summary` or call `search_workspace`.
8
+ 2. Reuse existing target, category, account, and artifact file IDs when possible.
9
+ 3. Create tests with `create_tests`.
10
+ 4. Run tests with `run_tests`.
11
+ 5. Poll with `get_run`, then inspect failures with `get_result`.
12
+
13
+ Tool responses are natural language by default. Pass `rawJson: true` only when exact structured data is needed.
14
+
15
+ Never ask Doksi MCP to reveal account secrets. Account outputs are redacted.
@@ -0,0 +1,34 @@
1
+ import type { AddTargetInput, RunTestsInput, SearchWorkspaceInput, TestDefinition, WorkspaceItemInput } from "./types.js";
2
+ export declare class DoksiApiClient {
3
+ private readonly baseUrl;
4
+ private readonly apiKey;
5
+ private readonly cache;
6
+ private readonly cacheTtlMs;
7
+ constructor(baseUrl: string, apiKey: string);
8
+ invalidateCache(): void;
9
+ private request;
10
+ private putToUploadUrl;
11
+ searchWorkspace(input: SearchWorkspaceInput): Promise<unknown>;
12
+ getWorkspaceItem(input: WorkspaceItemInput): Promise<unknown>;
13
+ addAccount(input: {
14
+ name: string;
15
+ fieldValues: Record<string, string>;
16
+ usageContext?: string;
17
+ }): Promise<unknown>;
18
+ addCategory(input: {
19
+ name: string;
20
+ color?: string;
21
+ }): Promise<unknown>;
22
+ addTarget(input: AddTargetInput): Promise<unknown>;
23
+ uploadArtifactFile(input: {
24
+ filePath: string;
25
+ name?: string;
26
+ mimeType?: string;
27
+ }): Promise<unknown>;
28
+ createTests(tests: TestDefinition[]): Promise<unknown>;
29
+ updateTests(tests: TestDefinition[]): Promise<unknown>;
30
+ runTests(input: RunTestsInput): Promise<unknown>;
31
+ getRun(runId: string): Promise<unknown>;
32
+ getResult(resultId: string): Promise<unknown>;
33
+ stopRun(runId: string): Promise<unknown>;
34
+ }
@@ -0,0 +1,189 @@
1
+ import { readFile, stat } from "fs/promises";
2
+ import { basename, extname } from "path";
3
+ import JSZip from "jszip";
4
+ import { DoksiApiError } from "./types.js";
5
+ export class DoksiApiClient {
6
+ baseUrl;
7
+ apiKey;
8
+ cache = new Map();
9
+ cacheTtlMs = 30_000;
10
+ constructor(baseUrl, apiKey) {
11
+ this.baseUrl = `${baseUrl.replace(/\/+$/, "")}/external/doksi-mcp`;
12
+ this.apiKey = apiKey;
13
+ }
14
+ invalidateCache() {
15
+ this.cache.clear();
16
+ }
17
+ async request(method, path, body, options = {}) {
18
+ const cacheKey = `${method} ${path} ${JSON.stringify(body ?? null)}`;
19
+ if (options.cache) {
20
+ const hit = this.cache.get(cacheKey);
21
+ if (hit && hit.expiresAt > Date.now())
22
+ return hit.value;
23
+ }
24
+ const response = await fetch(`${this.baseUrl}${path}`, {
25
+ method,
26
+ headers: {
27
+ Authorization: `Bearer ${this.apiKey}`,
28
+ "Content-Type": "application/json",
29
+ },
30
+ ...(body !== undefined ? { body: JSON.stringify(body) } : {}),
31
+ });
32
+ if (!response.ok) {
33
+ throw new DoksiApiError(response.status, await response.text(), `${this.baseUrl}${path}`);
34
+ }
35
+ const value = (await response.json());
36
+ if (options.cache) {
37
+ this.cache.set(cacheKey, { value, expiresAt: Date.now() + this.cacheTtlMs });
38
+ }
39
+ return value;
40
+ }
41
+ async putToUploadUrl(uploadUrl, bytes, contentType) {
42
+ const response = await fetch(uploadUrl, {
43
+ method: "PUT",
44
+ headers: { "Content-Type": contentType },
45
+ body: bytes,
46
+ });
47
+ if (!response.ok) {
48
+ throw new Error(`Upload failed with HTTP ${response.status}.`);
49
+ }
50
+ }
51
+ async searchWorkspace(input) {
52
+ const params = new URLSearchParams();
53
+ if (input.search)
54
+ params.set("search", input.search);
55
+ if (input.limit)
56
+ params.set("limit", String(input.limit));
57
+ if (input.skip)
58
+ params.set("skip", String(input.skip));
59
+ if (input.kinds?.length)
60
+ params.set("kinds", input.kinds.join(","));
61
+ const suffix = params.toString() ? `?${params.toString()}` : "";
62
+ return this.request("GET", `/workspace${suffix}`, undefined, { cache: true });
63
+ }
64
+ async getWorkspaceItem(input) {
65
+ return this.request("GET", `/items/${encodeURIComponent(input.kind)}/${encodeURIComponent(input.id)}`, undefined, { cache: true });
66
+ }
67
+ async addAccount(input) {
68
+ const result = await this.request("POST", "/accounts", input);
69
+ this.invalidateCache();
70
+ return result;
71
+ }
72
+ async addCategory(input) {
73
+ const result = await this.request("POST", "/categories", input);
74
+ this.invalidateCache();
75
+ return result;
76
+ }
77
+ async addTarget(input) {
78
+ if (input.filePath) {
79
+ const name = input.name ?? basename(input.filePath).replace(/\.(apk|zip)$/i, "");
80
+ const prepared = await prepareAndroidUpload(input.filePath);
81
+ const upload = await this.request("POST", "/targets/upload-url", {
82
+ name,
83
+ category: "android",
84
+ type: input.platformType,
85
+ });
86
+ await this.putToUploadUrl(upload.uploadUrl, prepared.bytes, "application/zip");
87
+ const result = await this.request("POST", "/targets", {
88
+ name,
89
+ fileKey: upload.fileKey,
90
+ category: "android",
91
+ type: input.platformType,
92
+ });
93
+ this.invalidateCache();
94
+ return result;
95
+ }
96
+ if (input.url) {
97
+ const result = await this.request("POST", "/targets", {
98
+ name: input.name ?? input.url,
99
+ url: input.url,
100
+ category: input.category ?? "web",
101
+ type: input.platformType,
102
+ });
103
+ this.invalidateCache();
104
+ return result;
105
+ }
106
+ throw new Error("Provide either filePath for Android upload or url for a web target.");
107
+ }
108
+ async uploadArtifactFile(input) {
109
+ const fileName = input.name ?? basename(input.filePath);
110
+ const sizeBytes = (await stat(input.filePath)).size;
111
+ const mimeType = input.mimeType ?? mimeTypeForPath(input.filePath);
112
+ const upload = await this.request("POST", "/artifact-files/upload-url", {
113
+ fileName,
114
+ mimeType,
115
+ sizeBytes,
116
+ });
117
+ const bytes = await readFile(input.filePath);
118
+ await this.putToUploadUrl(upload.uploadUrl, bytes, mimeType);
119
+ const result = await this.request("POST", "/artifact-files", {
120
+ fileKey: upload.fileKey,
121
+ fileName,
122
+ mimeType,
123
+ sizeBytes,
124
+ source: "upload",
125
+ });
126
+ this.invalidateCache();
127
+ return result;
128
+ }
129
+ async createTests(tests) {
130
+ const result = await this.request("POST", "/tests", { tests });
131
+ this.invalidateCache();
132
+ return result;
133
+ }
134
+ async updateTests(tests) {
135
+ const result = await this.request("PATCH", "/tests", { tests });
136
+ this.invalidateCache();
137
+ return result;
138
+ }
139
+ async runTests(input) {
140
+ const result = await this.request("POST", "/runs", input);
141
+ this.invalidateCache();
142
+ return result;
143
+ }
144
+ async getRun(runId) {
145
+ return this.request("GET", `/runs/${encodeURIComponent(runId)}`, undefined, { cache: true });
146
+ }
147
+ async getResult(resultId) {
148
+ return this.request("GET", `/results/${encodeURIComponent(resultId)}`, undefined, { cache: true });
149
+ }
150
+ async stopRun(runId) {
151
+ const result = await this.request("POST", `/runs/${encodeURIComponent(runId)}/stop`);
152
+ this.invalidateCache();
153
+ return result;
154
+ }
155
+ }
156
+ async function prepareAndroidUpload(filePath) {
157
+ const extension = extname(filePath).toLowerCase();
158
+ const bytes = await readFile(filePath);
159
+ if (extension === ".zip")
160
+ return { bytes };
161
+ if (extension !== ".apk") {
162
+ throw new Error("Android target upload must be an .apk or .zip file.");
163
+ }
164
+ const zip = new JSZip();
165
+ zip.file("platform_binary.apk", bytes);
166
+ return { bytes: await zip.generateAsync({ type: "nodebuffer", compression: "DEFLATE", compressionOptions: { level: 9 } }) };
167
+ }
168
+ function mimeTypeForPath(filePath) {
169
+ switch (extname(filePath).toLowerCase()) {
170
+ case ".csv":
171
+ return "text/csv";
172
+ case ".json":
173
+ return "application/json";
174
+ case ".txt":
175
+ return "text/plain";
176
+ case ".png":
177
+ return "image/png";
178
+ case ".jpg":
179
+ case ".jpeg":
180
+ return "image/jpeg";
181
+ case ".pdf":
182
+ return "application/pdf";
183
+ case ".zip":
184
+ return "application/zip";
185
+ default:
186
+ return "application/octet-stream";
187
+ }
188
+ }
189
+ //# 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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"}
@@ -0,0 +1,31 @@
1
+ export declare function textResult(text: string): {
2
+ content: {
3
+ type: "text";
4
+ text: string;
5
+ }[];
6
+ };
7
+ export declare function errorResult(error: unknown): {
8
+ content: {
9
+ type: "text";
10
+ text: string;
11
+ }[];
12
+ isError: true;
13
+ };
14
+ export declare function rawOrProse(rawJson: boolean | undefined, data: unknown, formatter: (data: any) => string): {
15
+ content: {
16
+ type: "text";
17
+ text: string;
18
+ }[];
19
+ };
20
+ export declare function humanError(error: unknown): string;
21
+ export declare function formatWorkspace(data: any): string;
22
+ export declare function formatWorkspaceItem(data: any): string;
23
+ export declare function formatAccountCreated(data: any): string;
24
+ export declare function formatCategoryCreated(data: any): string;
25
+ export declare function formatTargetCreated(data: any): string;
26
+ export declare function formatArtifactFileUploaded(data: any): string;
27
+ export declare function formatTestsChanged(data: any, verb: "Created" | "Updated"): string;
28
+ export declare function formatRunStarted(data: any): string;
29
+ export declare function formatRun(data: any): string;
30
+ export declare function formatResult(data: any): string;
31
+ export declare function formatStopRun(data: any): string;
@@ -0,0 +1,190 @@
1
+ import { DoksiApiError } from "./types.js";
2
+ export function textResult(text) {
3
+ return { content: [{ type: "text", text }] };
4
+ }
5
+ export function errorResult(error) {
6
+ return {
7
+ content: [{ type: "text", text: humanError(error) }],
8
+ isError: true,
9
+ };
10
+ }
11
+ export function rawOrProse(rawJson, data, formatter) {
12
+ return textResult(rawJson ? JSON.stringify(data) : formatter(data));
13
+ }
14
+ export function humanError(error) {
15
+ if (error instanceof DoksiApiError) {
16
+ const parsed = parseErrorBody(error.responseBody);
17
+ return `Doksi API error (${error.statusCode}): ${parsed}`;
18
+ }
19
+ return error instanceof Error ? error.message : String(error);
20
+ }
21
+ function parseErrorBody(body) {
22
+ try {
23
+ const json = JSON.parse(body);
24
+ return json.error ?? json.message ?? body;
25
+ }
26
+ catch {
27
+ return body;
28
+ }
29
+ }
30
+ export function formatWorkspace(data) {
31
+ const sections = data?.sections ?? {};
32
+ const lines = ["Workspace context:"];
33
+ appendList(lines, "Tests", sections.tests, formatTestLine);
34
+ appendList(lines, "Runs", sections.runs, formatRunLine);
35
+ appendList(lines, "Targets", sections.targets, formatTargetLine);
36
+ appendList(lines, "Accounts", sections.accounts, formatAccountLine);
37
+ appendList(lines, "Categories", sections.categories, formatCategoryLine);
38
+ appendList(lines, "Artifact files", sections.artifactFiles, formatArtifactFileLine);
39
+ lines.push("");
40
+ lines.push(`Next: use IDs above with create_tests, run_tests, or get_workspace_item. For more, repeat search_workspace with skip=${Number(data?.skip ?? 0) + Number(data?.limit ?? 20)}.`);
41
+ return lines.join("\n");
42
+ }
43
+ export function formatWorkspaceItem(data) {
44
+ const kind = data?.kind ?? "item";
45
+ const item = data?.item ?? data;
46
+ if (kind === "tests") {
47
+ const categories = (item.categories ?? []).map((category) => category.name).join(", ") || "uncategorized";
48
+ const artifacts = item.artifacts?.length ? `${item.artifacts.length} artifact${item.artifacts.length === 1 ? "" : "s"}` : "no artifacts";
49
+ return `Test "${item.name}" - id ${item.id}.
50
+
51
+ Priority: ${item.priority ?? "medium"}.
52
+ Categories: ${categories}.
53
+ Artifacts: ${artifacts}.
54
+
55
+ Description:
56
+ ${item.description ?? ""}
57
+
58
+ Expectation:
59
+ ${item.expectation ?? ""}
60
+
61
+ Next: update with update_tests or run with run_tests.`;
62
+ }
63
+ if (kind === "accounts") {
64
+ const fields = Object.keys(item.nonSensitiveFields ?? {}).join(", ") || "only secret fields, hidden";
65
+ return `Account "${item.name}" - id ${item.id}.
66
+
67
+ Visible fields: ${fields}.
68
+ Usage context: ${item.usageContext || "none"}.
69
+ Secrets are stored by Doksi and are not returned.`;
70
+ }
71
+ if (kind === "targets") {
72
+ const detail = item.packageName ?? item.url ?? item.category ?? "no target detail";
73
+ return `Target "${item.name}" - id ${item.id}.
74
+
75
+ Type: ${item.type ?? "unknown"}.
76
+ Detail: ${detail}.
77
+
78
+ Next: use target id ${item.id} with run_tests.`;
79
+ }
80
+ if (kind === "categories") {
81
+ return `Category "${item.name}" - id ${item.id}.
82
+
83
+ Tests: ${item.testsCount ?? 0}.
84
+ Color: ${item.color ?? "not set"}.`;
85
+ }
86
+ if (kind === "artifact-files") {
87
+ return `Artifact file "${item.fileName}" - id ${item.id}.
88
+
89
+ Status: ${item.status ?? "unknown"}.
90
+ MIME type: ${item.mimeType ?? "unknown"}.
91
+ Size: ${item.sizeBytes ?? 0} bytes.
92
+
93
+ Next: use file id ${item.id} in a file parameter artifact.`;
94
+ }
95
+ return keyValueSummary(`Workspace ${kind}`, item);
96
+ }
97
+ export function formatAccountCreated(data) {
98
+ const account = data?.account;
99
+ return `Created account "${account?.name}" with id ${account?.id}.\n\nVisible fields: ${Object.keys(account?.nonSensitiveFields ?? {}).join(", ") || "none"}. Secrets are stored but not returned.\n\nNext: use account id ${account?.id} in run_tests or test artifacts when a specific account is required.`;
100
+ }
101
+ export function formatCategoryCreated(data) {
102
+ const category = data?.category;
103
+ return `Created category "${category?.name}" with id ${category?.id}.\n\nNext: use category id ${category?.id} in create_tests.`;
104
+ }
105
+ export function formatTargetCreated(data) {
106
+ const target = data?.target;
107
+ const detail = target?.packageName ? ` Package ${target.packageName}.` : target?.url ? ` URL ${target.url}.` : "";
108
+ return `Created target "${target?.name}" with id ${target?.id}.${detail}\n\nNext: use target id ${target?.id} in run_tests.`;
109
+ }
110
+ export function formatArtifactFileUploaded(data) {
111
+ const file = data?.file;
112
+ const parameter = data?.parameter;
113
+ const devicePath = parameter?.file?.devicePath;
114
+ return `Uploaded artifact file "${file?.fileName}" with id ${file?.id}.\n\nUse it as a file parameter with fileId ${file?.id} and device path ${devicePath}.`;
115
+ }
116
+ export function formatTestsChanged(data, verb) {
117
+ const tests = data?.tests ?? [];
118
+ const lines = [`${verb} ${tests.length} test${tests.length === 1 ? "" : "s"}.`];
119
+ tests.forEach((test, index) => lines.push(`${index + 1}. ${test.name} - id ${test.id} - priority ${test.priority ?? "medium"}`));
120
+ lines.push("");
121
+ lines.push("Next: call run_tests with these test IDs and a target ID.");
122
+ return lines.join("\n");
123
+ }
124
+ export function formatRunStarted(data) {
125
+ const run = data?.run;
126
+ const resultIds = run?.resultIds ?? [];
127
+ return `Started run ${run?.id} (${run?.runId ?? "no short id"}) with ${data?.requestedSessions ?? run?.sessionsCount ?? 0} requested session${(data?.requestedSessions ?? 0) === 1 ? "" : "s"}.\n\nFirst session id: ${data?.firstSessionId ?? "pending"}.\nResult ids: ${resultIds.length ? resultIds.join(", ") : "results are still being created"}.\n\nNext: poll get_run with run id ${run?.id}.`;
128
+ }
129
+ export function formatRun(data) {
130
+ const run = data?.run ?? data;
131
+ const counts = run?.resultCountsByStatus ?? {};
132
+ const countText = Object.keys(counts).length ? Object.entries(counts).map(([k, v]) => `${k}: ${v}`).join(", ") : "no results yet";
133
+ return `Run ${run?.id} (${run?.runId ?? "no short id"}): ${countText}.\n\nResult ids: ${(run?.resultIds ?? []).join(", ") || "none yet"}.\nNext: call get_result for a completed or failed result id.`;
134
+ }
135
+ export function formatResult(data) {
136
+ const result = data?.result ?? data?.item ?? data;
137
+ const summary = result?.extendedSummary?.summary ?? result?.summary ?? "No summary yet.";
138
+ return `Result ${result?.id} for test ${result?.testId}: ${result?.status}.\n\nSummary: ${summary}\n\nIssues: ${result?.issuesCount ?? 0}.\nNavigation session: ${result?.navigationSessionId ?? "none"}.`;
139
+ }
140
+ function keyValueSummary(title, item) {
141
+ if (!item || typeof item !== "object")
142
+ return `${title}: ${String(item)}`;
143
+ const lines = [`${title}:`];
144
+ for (const [key, value] of Object.entries(item)) {
145
+ if (value === undefined || value === null)
146
+ continue;
147
+ if (Array.isArray(value)) {
148
+ lines.push(`${key}: ${value.length} item${value.length === 1 ? "" : "s"}`);
149
+ }
150
+ else if (typeof value === "object") {
151
+ lines.push(`${key}: present`);
152
+ }
153
+ else {
154
+ lines.push(`${key}: ${String(value)}`);
155
+ }
156
+ }
157
+ return lines.join("\n");
158
+ }
159
+ export function formatStopRun(data) {
160
+ return `Stopped ${data?.stopped ?? 0} of ${data?.total ?? 0} active result${(data?.total ?? 0) === 1 ? "" : "s"}.\n\nFailed result ids: ${(data?.failedIds ?? []).join(", ") || "none"}.`;
161
+ }
162
+ function appendList(lines, title, items, formatter) {
163
+ if (!items?.length)
164
+ return;
165
+ lines.push("");
166
+ lines.push(`${title}:`);
167
+ items.forEach((item, index) => lines.push(formatter(item, index)));
168
+ }
169
+ function formatTestLine(test, index) {
170
+ const categories = (test.categories ?? []).map((c) => c.name).join(", ") || "uncategorized";
171
+ return `${index + 1}. ${test.name} - id ${test.id} - ${categories} - ${test.priority ?? "medium"}`;
172
+ }
173
+ function formatRunLine(run, index) {
174
+ return `${index + 1}. Run ${run.numericId ?? run.runId ?? run.id} - id ${run.id} - ${run.sessionsCount ?? 0} sessions`;
175
+ }
176
+ function formatTargetLine(target, index) {
177
+ const detail = target.packageName ?? target.url ?? target.category ?? "";
178
+ return `${index + 1}. ${target.name} - id ${target.id}${detail ? ` - ${detail}` : ""}`;
179
+ }
180
+ function formatAccountLine(account, index) {
181
+ const fields = Object.keys(account.nonSensitiveFields ?? {}).join(", ") || "secret fields hidden";
182
+ return `${index + 1}. ${account.name} - id ${account.id} - ${fields}`;
183
+ }
184
+ function formatCategoryLine(category, index) {
185
+ return `${index + 1}. ${category.name} - id ${category.id} - ${category.testsCount ?? 0} tests`;
186
+ }
187
+ function formatArtifactFileLine(file, index) {
188
+ return `${index + 1}. ${file.fileName} - id ${file.id} - ${file.status ?? "ready"} - ${file.sizeBytes ?? 0} bytes`;
189
+ }
190
+ //# sourceMappingURL=formatters.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatters.js","sourceRoot":"","sources":["../src/formatters.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env node
2
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
+ import { createServer } from "./server.js";
4
+ async function main() {
5
+ const apiKey = process.env.DOKSI_API_KEY;
6
+ if (!apiKey) {
7
+ console.error("Error: DOKSI_API_KEY environment variable is required");
8
+ process.exit(1);
9
+ }
10
+ const apiUrl = process.env.DOKSI_API_URL || "https://api.doksi.ai";
11
+ const server = createServer(apiUrl, apiKey);
12
+ const transport = new StdioServerTransport();
13
+ await server.connect(transport);
14
+ }
15
+ main().catch((error) => {
16
+ console.error("Fatal error:", error);
17
+ process.exit(1);
18
+ });
19
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,KAAK,UAAU,IAAI;IACjB,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC;IACzC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,CAAC,KAAK,CAAC,uDAAuD,CAAC,CAAC;QACvE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,sBAAsB,CAAC;IACnE,MAAM,MAAM,GAAG,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5C,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AAClC,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;IACrC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function registerPrompts(server: McpServer): void;
@@ -0,0 +1,133 @@
1
+ import { z } from "zod";
2
+ export function registerPrompts(server) {
3
+ const mcp = server;
4
+ mcp.registerPrompt("create_tests_from_prd", {
5
+ title: "Create Doksi Tests From PRD",
6
+ description: "Plan and create Doksi tests from product requirements.",
7
+ argsSchema: {
8
+ prd: z.string().describe("The PRD, feature brief, or requirements text."),
9
+ },
10
+ }, ({ prd }) => ({
11
+ messages: [{
12
+ role: "user",
13
+ content: {
14
+ type: "text",
15
+ text: `Use Doksi MCP to create focused tests from this PRD.
16
+
17
+ Workflow:
18
+ 1. Read doksi://workspace/summary or call search_workspace.
19
+ 2. Reuse existing targets, accounts, categories, and artifact files when possible.
20
+ 3. Create missing categories with add_category.
21
+ 4. Create tests with create_tests. Do not run yet unless asked.
22
+
23
+ PRD:
24
+ ${prd}`,
25
+ },
26
+ }],
27
+ }));
28
+ mcp.registerPrompt("run_tests_for_prd", {
29
+ title: "Run Doksi Tests For PRD",
30
+ description: "Find or create relevant tests for a PRD and run them on a Doksi target.",
31
+ argsSchema: {
32
+ prd: z.string(),
33
+ targetHint: z.string().optional(),
34
+ },
35
+ }, ({ prd, targetHint }) => ({
36
+ messages: [{
37
+ role: "user",
38
+ content: {
39
+ type: "text",
40
+ text: `Use Doksi MCP to run relevant coverage for this PRD.
41
+
42
+ Workflow:
43
+ 1. Read doksi://workspace/summary or call search_workspace.
44
+ 2. Find the best target${targetHint ? ` matching this hint: ${targetHint}` : ""}.
45
+ 3. Reuse existing tests when they cover the PRD.
46
+ 4. Create missing tests with create_tests.
47
+ 5. Run with run_tests.
48
+ 6. Poll with get_run and inspect failures with get_result.
49
+
50
+ PRD:
51
+ ${prd}`,
52
+ },
53
+ }],
54
+ }));
55
+ mcp.registerPrompt("create_tests_from_user_stories", {
56
+ title: "Create Doksi Tests From User Stories",
57
+ description: "Plan and create Doksi tests from user stories or acceptance criteria.",
58
+ argsSchema: {
59
+ userStories: z.string().describe("User stories, acceptance criteria, Gherkin scenarios, or requirements text."),
60
+ },
61
+ }, ({ userStories }) => ({
62
+ messages: [{
63
+ role: "user",
64
+ content: {
65
+ type: "text",
66
+ text: `Use Doksi MCP to create focused tests from these user stories.
67
+
68
+ Workflow:
69
+ 1. Read doksi://workspace/summary or call search_workspace.
70
+ 2. Identify committed, user-visible behaviors. Skip notes, implementation tasks, open questions, analytics-only goals, and duplicate intent.
71
+ 3. Split independent acceptance criteria into separate tests when they have different actors, preconditions, branches, or assertions.
72
+ 4. Reuse existing tests, categories, accounts, and artifact files when possible.
73
+ 5. Create missing categories with add_category.
74
+ 6. Create tests with create_tests. Do not run yet unless asked.
75
+
76
+ User stories:
77
+ ${userStories}`,
78
+ },
79
+ }],
80
+ }));
81
+ mcp.registerPrompt("run_tests_for_user_stories", {
82
+ title: "Run Doksi Tests For User Stories",
83
+ description: "Find or create relevant tests for user stories and run them on a Doksi target.",
84
+ argsSchema: {
85
+ userStories: z.string().describe("User stories, acceptance criteria, Gherkin scenarios, or requirements text."),
86
+ targetHint: z.string().optional(),
87
+ },
88
+ }, ({ userStories, targetHint }) => ({
89
+ messages: [{
90
+ role: "user",
91
+ content: {
92
+ type: "text",
93
+ text: `Use Doksi MCP to run relevant coverage for these user stories.
94
+
95
+ Workflow:
96
+ 1. Read doksi://workspace/summary or call search_workspace.
97
+ 2. Find the best target${targetHint ? ` matching this hint: ${targetHint}` : ""}.
98
+ 3. Reuse existing tests when they cover the same behavior and expected outcome.
99
+ 4. Create missing tests with create_tests.
100
+ 5. Run with run_tests.
101
+ 6. Poll with get_run and inspect failures with get_result.
102
+
103
+ User stories:
104
+ ${userStories}`,
105
+ },
106
+ }],
107
+ }));
108
+ mcp.registerPrompt("audit_existing_tests", {
109
+ title: "Audit Existing Doksi Tests",
110
+ description: "Compare an existing Doksi test set against requirements and suggest gaps.",
111
+ argsSchema: {
112
+ requirements: z.string(),
113
+ },
114
+ }, ({ requirements }) => ({
115
+ messages: [{
116
+ role: "user",
117
+ content: {
118
+ type: "text",
119
+ text: `Audit Doksi coverage against these requirements.
120
+
121
+ Workflow:
122
+ 1. Read doksi://workspace/summary.
123
+ 2. Use search_workspace and get_workspace_item for relevant test details.
124
+ 3. Summarize covered, partially covered, and missing requirements.
125
+ 4. Only call create_tests if explicitly asked.
126
+
127
+ Requirements:
128
+ ${requirements}`,
129
+ },
130
+ }],
131
+ }));
132
+ }
133
+ //# sourceMappingURL=prompts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.js","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { type McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { DoksiApiClient } from "./api-client.js";
3
+ export declare function registerResources(server: McpServer, client: DoksiApiClient): void;
@@ -0,0 +1,78 @@
1
+ import { ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { formatResult, formatRun, formatWorkspace, formatWorkspaceItem } from "./formatters.js";
3
+ export function registerResources(server, client) {
4
+ const mcp = server;
5
+ mcp.registerResource("workspace_summary", "doksi://workspace/summary", {
6
+ title: "Doksi Workspace Summary",
7
+ description: "Compact current workspace context. Read this before creating or running tests.",
8
+ mimeType: "text/plain",
9
+ }, async (uri) => ({
10
+ contents: [{
11
+ uri: uri.href,
12
+ mimeType: "text/plain",
13
+ text: formatWorkspace(await client.searchWorkspace({ limit: 10 })),
14
+ }],
15
+ }));
16
+ mcp.registerResource("test_definition_schema", "doksi://schema/test-definition", {
17
+ title: "Doksi Test Definition Schema",
18
+ description: "How to author tests and artifacts for create_tests/update_tests.",
19
+ mimeType: "text/markdown",
20
+ }, async (uri) => ({
21
+ contents: [{
22
+ uri: uri.href,
23
+ mimeType: "text/markdown",
24
+ text: testDefinitionSchema(),
25
+ }],
26
+ }));
27
+ registerItemResource(server, client, "test", "doksi://tests/{test_id}", "tests", formatWorkspaceItem);
28
+ registerItemResource(server, client, "run", "doksi://runs/{run_id}", "runs", (data) => formatRun({ run: data.item }));
29
+ registerItemResource(server, client, "result", "doksi://results/{result_id}", "results", (data) => formatResult({ result: data.item }));
30
+ registerItemResource(server, client, "target", "doksi://targets/{target_id}", "targets", formatWorkspaceItem);
31
+ registerItemResource(server, client, "artifact_file", "doksi://artifact-files/{file_id}", "artifact-files", formatWorkspaceItem);
32
+ }
33
+ function registerItemResource(server, client, name, template, kind, formatter) {
34
+ server.registerResource(name, new ResourceTemplate(template, { list: undefined }), {
35
+ title: `Doksi ${name.replace("_", " ")}`,
36
+ description: `Detailed Doksi ${name.replace("_", " ")} context.`,
37
+ mimeType: "text/plain",
38
+ }, async (uri, variables) => {
39
+ const id = String(Object.values(variables)[0] ?? "");
40
+ const data = await client.getWorkspaceItem({ kind, id });
41
+ return {
42
+ contents: [{
43
+ uri: uri.href,
44
+ mimeType: "text/plain",
45
+ text: formatter(data),
46
+ }],
47
+ };
48
+ });
49
+ }
50
+ function testDefinitionSchema() {
51
+ return `# Doksi Test Definition
52
+
53
+ Use \`create_tests\` with:
54
+
55
+ \`\`\`json
56
+ {
57
+ "tests": [
58
+ {
59
+ "name": "Checkout accepts a valid card",
60
+ "description": "Steps the agent should perform. Reference parameters as {{parameter:Name}}.",
61
+ "expectation": "Observable pass/fail expectation.",
62
+ "categoryIds": ["category_id"],
63
+ "priority": "medium",
64
+ "artifacts": [
65
+ { "type": "account", "strategy": "specific", "accountId": "account_id" },
66
+ { "type": "parameter", "name": "Promo Code", "kind": "text", "text": { "value": "SAVE10" } },
67
+ { "type": "parameter", "name": "contacts.csv", "kind": "file", "file": { "fileId": "file_id", "devicePath": "/sdcard/Download/contacts.csv" } }
68
+ ]
69
+ }
70
+ ]
71
+ }
72
+ \`\`\`
73
+
74
+ Do not include target artifacts on tests for normal PRD workflows. Supply target id to \`run_tests\`.
75
+
76
+ Validation is internal to \`create_tests\` and \`update_tests\`. If validation fails, repair the named field or parameter and retry.`;
77
+ }
78
+ //# sourceMappingURL=resources.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resources.js","sourceRoot":"","sources":["../src/resources.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function createServer(apiUrl: string, apiKey: string): McpServer;
package/dist/server.js ADDED
@@ -0,0 +1,24 @@
1
+ import { readFileSync } from "fs";
2
+ import { dirname, join } from "path";
3
+ import { fileURLToPath } from "url";
4
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
5
+ import { DoksiApiClient } from "./api-client.js";
6
+ import { registerTools } from "./tools.js";
7
+ import { registerResources } from "./resources.js";
8
+ import { registerPrompts } from "./prompts.js";
9
+ const __dirname = dirname(fileURLToPath(import.meta.url));
10
+ const instructions = readFileSync(join(__dirname, "../SKILL.md"), "utf-8");
11
+ export function createServer(apiUrl, apiKey) {
12
+ const server = new McpServer({
13
+ name: "Doksi MCP",
14
+ version: "0.1.0",
15
+ websiteUrl: "https://doksi.ai",
16
+ description: "Create, inspect, and run Doksi tests from an LLM.",
17
+ }, { instructions });
18
+ const client = new DoksiApiClient(apiUrl, apiKey);
19
+ registerResources(server, client);
20
+ registerPrompts(server);
21
+ registerTools(server, client);
22
+ return server;
23
+ }
24
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE/C,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC1D,MAAM,YAAY,GAAG,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC,EAAE,OAAO,CAAC,CAAC;AAE3E,MAAM,UAAU,YAAY,CAAC,MAAc,EAAE,MAAc;IACzD,MAAM,MAAM,GAAG,IAAI,SAAS,CAC1B;QACE,IAAI,EAAE,WAAW;QACjB,OAAO,EAAE,OAAO;QAChB,UAAU,EAAE,kBAAkB;QAC9B,WAAW,EAAE,mDAAmD;KACjE,EACD,EAAE,YAAY,EAAE,CACjB,CAAC;IAEF,MAAM,MAAM,GAAG,IAAI,cAAc,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClD,iBAAiB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,eAAe,CAAC,MAAM,CAAC,CAAC;IACxB,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { DoksiApiClient } from "./api-client.js";
3
+ export declare function registerTools(server: McpServer, client: DoksiApiClient): void;
package/dist/tools.js ADDED
@@ -0,0 +1,218 @@
1
+ import { z } from "zod";
2
+ import { errorResult, formatAccountCreated, formatArtifactFileUploaded, formatCategoryCreated, formatResult, formatRun, formatRunStarted, formatStopRun, formatTargetCreated, formatTestsChanged, formatWorkspace, formatWorkspaceItem, rawOrProse, } from "./formatters.js";
3
+ const rawJson = z.boolean().optional().describe("Return compact JSON text instead of the default natural-language response.");
4
+ const priority = z.string().optional().describe("Priority: low, medium, high, critical. Severity aliases like major/minor are accepted.");
5
+ const artifact = z.unknown().describe("Doksi artifact object. Use parameter/account artifacts only on tests; run_tests supplies target artifacts.");
6
+ const testDefinition = z.object({
7
+ testId: z.string().optional(),
8
+ name: z.string(),
9
+ description: z.string(),
10
+ expectation: z.string(),
11
+ categoryIds: z.array(z.string()).optional(),
12
+ priority,
13
+ artifacts: z.array(artifact).optional(),
14
+ });
15
+ export function registerTools(server, client) {
16
+ const mcp = server;
17
+ mcp.registerTool("search_workspace", {
18
+ description: "Search or list compact Doksi workspace context: tests, runs, targets, accounts, categories, and artifact files. Use this before creating or running tests so you can reuse existing IDs. Returns concise prose by default.",
19
+ inputSchema: {
20
+ kinds: z.array(z.enum(["tests", "runs", "targets", "accounts", "categories", "artifact-files"])).optional(),
21
+ search: z.string().optional(),
22
+ limit: z.number().int().min(1).max(50).optional(),
23
+ skip: z.number().int().min(0).optional(),
24
+ rawJson,
25
+ },
26
+ }, async (input) => {
27
+ try {
28
+ const data = await client.searchWorkspace(input);
29
+ return rawOrProse(input.rawJson, data, formatWorkspace);
30
+ }
31
+ catch (error) {
32
+ return errorResult(error);
33
+ }
34
+ });
35
+ mcp.registerTool("get_workspace_item", {
36
+ description: "Fetch detailed context for one workspace item by id. Use when search_workspace gives an ID but you need the full test, run, result, target, account, category, or artifact-file detail.",
37
+ inputSchema: {
38
+ kind: z.enum(["tests", "runs", "results", "targets", "accounts", "categories", "artifact-files"]),
39
+ id: z.string(),
40
+ rawJson,
41
+ },
42
+ }, async (input) => {
43
+ try {
44
+ const data = await client.getWorkspaceItem(input);
45
+ return rawOrProse(input.rawJson, data, formatWorkspaceItem);
46
+ }
47
+ catch (error) {
48
+ return errorResult(error);
49
+ }
50
+ });
51
+ mcp.registerTool("add_account", {
52
+ description: "Create a reusable Doksi account. Use this only when an existing account cannot be reused. Secrets are stored by Doksi and never returned in tool output.",
53
+ inputSchema: {
54
+ name: z.string(),
55
+ fieldValues: z.record(z.string()).describe("Authentication fields, for example {\"email\":\"pm@example.com\",\"password\":\"...\"}. Sensitive values are accepted but never echoed back."),
56
+ usageContext: z.string().optional(),
57
+ rawJson,
58
+ },
59
+ }, async (input) => {
60
+ try {
61
+ const data = await client.addAccount(input);
62
+ return rawOrProse(input.rawJson, data, formatAccountCreated);
63
+ }
64
+ catch (error) {
65
+ return errorResult(error);
66
+ }
67
+ });
68
+ mcp.registerTool("add_category", {
69
+ description: "Create a test category. Use categories to group tests generated from a PRD area or feature.",
70
+ inputSchema: {
71
+ name: z.string(),
72
+ color: z.string().optional(),
73
+ rawJson,
74
+ },
75
+ }, async (input) => {
76
+ try {
77
+ const data = await client.addCategory(input);
78
+ return rawOrProse(input.rawJson, data, formatCategoryCreated);
79
+ }
80
+ catch (error) {
81
+ return errorResult(error);
82
+ }
83
+ });
84
+ mcp.registerTool("add_target", {
85
+ description: "Create a reusable test target. For Android, pass filePath to a local .apk or .zip; the MCP uploads directly to S3 and Doksi reconciles the target. For web, pass url. Use the returned target id in run_tests.",
86
+ inputSchema: {
87
+ name: z.string().optional(),
88
+ filePath: z.string().optional(),
89
+ url: z.string().optional(),
90
+ category: z.enum(["android", "web"]).optional(),
91
+ platformType: z.string().optional(),
92
+ rawJson,
93
+ },
94
+ }, async (input) => {
95
+ try {
96
+ const data = await client.addTarget(input);
97
+ return rawOrProse(input.rawJson, data, formatTargetCreated);
98
+ }
99
+ catch (error) {
100
+ return errorResult(error);
101
+ }
102
+ });
103
+ mcp.registerTool("upload_artifact_file", {
104
+ description: "Upload a parameter file for tests, such as CSVs, images, PDFs, or fixture documents. Use the returned fileId in file parameter artifacts.",
105
+ inputSchema: {
106
+ filePath: z.string(),
107
+ name: z.string().optional(),
108
+ mimeType: z.string().optional(),
109
+ rawJson,
110
+ },
111
+ }, async (input) => {
112
+ try {
113
+ const data = await client.uploadArtifactFile(input);
114
+ return rawOrProse(input.rawJson, data, formatArtifactFileUploaded);
115
+ }
116
+ catch (error) {
117
+ return errorResult(error);
118
+ }
119
+ });
120
+ mcp.registerTool("create_tests", {
121
+ description: "Create one or many Doksi tests from LLM-authored definitions. Validation happens internally; errors are returned in natural language so you can repair the definitions and retry.",
122
+ inputSchema: {
123
+ tests: z.array(testDefinition).min(1),
124
+ rawJson,
125
+ },
126
+ }, async (input) => {
127
+ try {
128
+ const data = await client.createTests(input.tests);
129
+ return rawOrProse(input.rawJson, data, (d) => formatTestsChanged(d, "Created"));
130
+ }
131
+ catch (error) {
132
+ return errorResult(error);
133
+ }
134
+ });
135
+ mcp.registerTool("update_tests", {
136
+ description: "Update one or many existing Doksi tests. Every item requires testId. Use this to revise tests after inspecting existing coverage or validation feedback.",
137
+ inputSchema: {
138
+ tests: z.array(testDefinition.extend({ testId: z.string() })).min(1),
139
+ rawJson,
140
+ },
141
+ }, async (input) => {
142
+ try {
143
+ const data = await client.updateTests(input.tests);
144
+ return rawOrProse(input.rawJson, data, (d) => formatTestsChanged(d, "Updated"));
145
+ }
146
+ catch (error) {
147
+ return errorResult(error);
148
+ }
149
+ });
150
+ mcp.registerTool("run_tests", {
151
+ description: "Run one or many tests on a target. Target is run-level; account and parameter overrides are optional. Use get_run to poll and get_result for details.",
152
+ inputSchema: {
153
+ testIds: z.array(z.string()).min(1),
154
+ targetId: z.string(),
155
+ account: z.object({
156
+ strategy: z.enum(["none", "generated", "specific"]).optional(),
157
+ accountId: z.string().optional(),
158
+ }).optional(),
159
+ parameters: z.array(artifact).optional(),
160
+ artifacts: z.array(artifact).optional(),
161
+ rawJson,
162
+ },
163
+ }, async (input) => {
164
+ try {
165
+ const data = await client.runTests(input);
166
+ return rawOrProse(input.rawJson, data, formatRunStarted);
167
+ }
168
+ catch (error) {
169
+ return errorResult(error);
170
+ }
171
+ });
172
+ mcp.registerTool("get_run", {
173
+ description: "Poll a Doksi run by id. Use this after run_tests until results complete.",
174
+ inputSchema: {
175
+ runId: z.string(),
176
+ rawJson,
177
+ },
178
+ }, async (input) => {
179
+ try {
180
+ const data = await client.getRun(input.runId);
181
+ return rawOrProse(input.rawJson, data, formatRun);
182
+ }
183
+ catch (error) {
184
+ return errorResult(error);
185
+ }
186
+ });
187
+ mcp.registerTool("get_result", {
188
+ description: "Fetch concise details for one result. Use this for failures, incomplete sessions, or completed results that need evidence.",
189
+ inputSchema: {
190
+ resultId: z.string(),
191
+ rawJson,
192
+ },
193
+ }, async (input) => {
194
+ try {
195
+ const data = await client.getResult(input.resultId);
196
+ return rawOrProse(input.rawJson, data, formatResult);
197
+ }
198
+ catch (error) {
199
+ return errorResult(error);
200
+ }
201
+ });
202
+ mcp.registerTool("stop_run", {
203
+ description: "Stop active or queued results in a Doksi run.",
204
+ inputSchema: {
205
+ runId: z.string(),
206
+ rawJson,
207
+ },
208
+ }, async (input) => {
209
+ try {
210
+ const data = await client.stopRun(input.runId);
211
+ return rawOrProse(input.rawJson, data, formatStopRun);
212
+ }
213
+ catch (error) {
214
+ return errorResult(error);
215
+ }
216
+ });
217
+ }
218
+ //# sourceMappingURL=tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.js","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ export type WorkspaceKind = "tests" | "runs" | "targets" | "accounts" | "categories" | "artifact-files";
2
+ export interface RawJsonOption {
3
+ rawJson?: boolean;
4
+ }
5
+ export interface SearchWorkspaceInput extends RawJsonOption {
6
+ kinds?: WorkspaceKind[];
7
+ search?: string;
8
+ limit?: number;
9
+ skip?: number;
10
+ }
11
+ export interface WorkspaceItemInput extends RawJsonOption {
12
+ kind: WorkspaceKind | "results";
13
+ id: string;
14
+ }
15
+ export interface TestDefinition {
16
+ testId?: string;
17
+ name: string;
18
+ description: string;
19
+ expectation: string;
20
+ categoryIds?: string[];
21
+ priority?: "low" | "medium" | "high" | "critical" | string;
22
+ artifacts?: unknown[];
23
+ }
24
+ export interface RunTestsInput extends RawJsonOption {
25
+ testIds: string[];
26
+ targetId: string;
27
+ account?: {
28
+ strategy?: "none" | "generated" | "specific";
29
+ accountId?: string;
30
+ };
31
+ parameters?: unknown[];
32
+ artifacts?: unknown[];
33
+ }
34
+ export interface AddTargetInput extends RawJsonOption {
35
+ name?: string;
36
+ filePath?: string;
37
+ url?: string;
38
+ category?: "android" | "web";
39
+ platformType?: string;
40
+ }
41
+ export declare class DoksiApiError extends Error {
42
+ readonly statusCode: number;
43
+ readonly responseBody: string;
44
+ readonly url: string;
45
+ constructor(statusCode: number, responseBody: string, url: string);
46
+ }
package/dist/types.js ADDED
@@ -0,0 +1,13 @@
1
+ export class DoksiApiError extends Error {
2
+ statusCode;
3
+ responseBody;
4
+ url;
5
+ constructor(statusCode, responseBody, url) {
6
+ super(`API error ${statusCode}: ${responseBody}`);
7
+ this.statusCode = statusCode;
8
+ this.responseBody = responseBody;
9
+ this.url = url;
10
+ this.name = "DoksiApiError";
11
+ }
12
+ }
13
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAqDA,MAAM,OAAO,aAAc,SAAQ,KAAK;IAEpB;IACA;IACA;IAHlB,YACkB,UAAkB,EAClB,YAAoB,EACpB,GAAW;QAE3B,KAAK,CAAC,aAAa,UAAU,KAAK,YAAY,EAAE,CAAC,CAAC;QAJlC,eAAU,GAAV,UAAU,CAAQ;QAClB,iBAAY,GAAZ,YAAY,CAAQ;QACpB,QAAG,GAAH,GAAG,CAAQ;QAG3B,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;IAC9B,CAAC;CACF"}
package/package.json ADDED
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "@doksi/mcp",
3
+ "version": "0.1.1",
4
+ "description": "MCP server for creating, managing, and running Doksi tests",
5
+ "type": "module",
6
+ "bin": {
7
+ "doksi": "./dist/index.js"
8
+ },
9
+ "main": "./dist/index.js",
10
+ "scripts": {
11
+ "build": "tsc && chmod +x dist/index.js",
12
+ "dev": "tsc --watch",
13
+ "prepack": "npm run build",
14
+ "start": "node dist/index.js"
15
+ },
16
+ "files": [
17
+ "dist",
18
+ "README.md",
19
+ "SKILL.md",
20
+ "version.txt"
21
+ ],
22
+ "dependencies": {
23
+ "@modelcontextprotocol/sdk": "^1.27.1",
24
+ "jszip": "^3.10.1",
25
+ "zod": "^3.25.0"
26
+ },
27
+ "devDependencies": {
28
+ "@types/node": "^22.0.0",
29
+ "typescript": "^5.7.0"
30
+ },
31
+ "license": "MIT",
32
+ "engines": {
33
+ "node": ">=18.0.0"
34
+ }
35
+ }
package/version.txt ADDED
@@ -0,0 +1 @@
1
+ 1782840898