@cubis/foundry 0.3.68 → 0.3.70
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/dist/cli/core.js +95 -2
- package/dist/cli/core.js.map +1 -1
- package/dist/cli/init/execute.js +6 -4
- package/dist/cli/init/execute.js.map +1 -1
- package/dist/cli/init/prompts.js +5 -0
- package/dist/cli/init/prompts.js.map +1 -1
- package/mcp/dist/index.js +37 -8
- package/mcp/src/cbxConfig/index.ts +6 -1
- package/mcp/src/cbxConfig/serviceConfig.ts +38 -3
- package/mcp/src/cbxConfig/types.ts +6 -0
- package/mcp/src/gateway/config.ts +69 -8
- package/mcp/src/gateway/manager.ts +17 -6
- package/mcp/src/gateway/types.ts +1 -1
- package/mcp/src/server.ts +18 -13
- package/mcp/src/tools/playwrightGetStatus.ts +60 -0
- package/mcp/src/tools/registry.test.ts +26 -8
- package/mcp/src/tools/registry.ts +29 -2
- package/mcp/src/tools/routeResolve.ts +1 -1
- package/mcp/src/upstream/passthrough.ts +69 -8
- package/package.json +1 -1
- package/src/cli/core.ts +100 -5
- package/src/cli/init/execute.ts +14 -5
- package/src/cli/init/prompts.ts +5 -0
- package/src/cli/init/types.ts +1 -1
- package/workflows/skills/generated/skill-catalog.json +806 -103
- package/workflows/skills/playwright-e2e/SKILL.md +21 -5
- package/workflows/skills/playwright-e2e/references/locator-trace-flake-checklist.md +28 -0
- package/workflows/skills/skills_index.json +802 -99
- package/workflows/workflows/agent-environment-setup/manifest.json +65 -9
- package/workflows/workflows/agent-environment-setup/platforms/antigravity/agents/backend-specialist.md +6 -0
- package/workflows/workflows/agent-environment-setup/platforms/antigravity/agents/code-archaeologist.md +7 -0
- package/workflows/workflows/agent-environment-setup/platforms/antigravity/agents/database-architect.md +6 -0
- package/workflows/workflows/agent-environment-setup/platforms/antigravity/agents/debugger.md +7 -0
- package/workflows/workflows/agent-environment-setup/platforms/antigravity/agents/devops-engineer.md +6 -0
- package/workflows/workflows/agent-environment-setup/platforms/antigravity/agents/documentation-writer.md +4 -0
- package/workflows/workflows/agent-environment-setup/platforms/antigravity/agents/frontend-specialist.md +6 -0
- package/workflows/workflows/agent-environment-setup/platforms/antigravity/agents/game-developer.md +1 -0
- package/workflows/workflows/agent-environment-setup/platforms/antigravity/agents/mobile-developer.md +6 -0
- package/workflows/workflows/agent-environment-setup/platforms/antigravity/agents/orchestrator.md +8 -0
- package/workflows/workflows/agent-environment-setup/platforms/antigravity/agents/penetration-tester.md +4 -0
- package/workflows/workflows/agent-environment-setup/platforms/antigravity/agents/performance-optimizer.md +4 -0
- package/workflows/workflows/agent-environment-setup/platforms/antigravity/agents/product-manager.md +1 -0
- package/workflows/workflows/agent-environment-setup/platforms/antigravity/agents/project-planner.md +8 -0
- package/workflows/workflows/agent-environment-setup/platforms/antigravity/agents/qa-automation-engineer.md +1 -0
- package/workflows/workflows/agent-environment-setup/platforms/antigravity/agents/researcher.md +5 -0
- package/workflows/workflows/agent-environment-setup/platforms/antigravity/agents/security-auditor.md +6 -0
- package/workflows/workflows/agent-environment-setup/platforms/antigravity/agents/seo-specialist.md +1 -0
- package/workflows/workflows/agent-environment-setup/platforms/antigravity/agents/sre-engineer.md +6 -0
- package/workflows/workflows/agent-environment-setup/platforms/antigravity/agents/test-engineer.md +5 -0
- package/workflows/workflows/agent-environment-setup/platforms/antigravity/agents/validator.md +1 -0
- package/workflows/workflows/agent-environment-setup/platforms/antigravity/agents/vercel-expert.md +1 -0
- package/workflows/workflows/agent-environment-setup/platforms/antigravity/rules/GEMINI.md +1 -1
- package/workflows/workflows/agent-environment-setup/platforms/claude/agents/backend-specialist.md +6 -0
- package/workflows/workflows/agent-environment-setup/platforms/claude/agents/code-archaeologist.md +7 -0
- package/workflows/workflows/agent-environment-setup/platforms/claude/agents/database-architect.md +6 -0
- package/workflows/workflows/agent-environment-setup/platforms/claude/agents/debugger.md +7 -0
- package/workflows/workflows/agent-environment-setup/platforms/claude/agents/devops-engineer.md +6 -0
- package/workflows/workflows/agent-environment-setup/platforms/claude/agents/documentation-writer.md +4 -0
- package/workflows/workflows/agent-environment-setup/platforms/claude/agents/frontend-specialist.md +6 -0
- package/workflows/workflows/agent-environment-setup/platforms/claude/agents/game-developer.md +1 -0
- package/workflows/workflows/agent-environment-setup/platforms/claude/agents/mobile-developer.md +6 -0
- package/workflows/workflows/agent-environment-setup/platforms/claude/agents/orchestrator.md +8 -0
- package/workflows/workflows/agent-environment-setup/platforms/claude/agents/penetration-tester.md +4 -0
- package/workflows/workflows/agent-environment-setup/platforms/claude/agents/performance-optimizer.md +4 -0
- package/workflows/workflows/agent-environment-setup/platforms/claude/agents/product-manager.md +1 -0
- package/workflows/workflows/agent-environment-setup/platforms/claude/agents/project-planner.md +8 -0
- package/workflows/workflows/agent-environment-setup/platforms/claude/agents/qa-automation-engineer.md +1 -0
- package/workflows/workflows/agent-environment-setup/platforms/claude/agents/researcher.md +5 -0
- package/workflows/workflows/agent-environment-setup/platforms/claude/agents/security-auditor.md +6 -0
- package/workflows/workflows/agent-environment-setup/platforms/claude/agents/seo-specialist.md +1 -0
- package/workflows/workflows/agent-environment-setup/platforms/claude/agents/sre-engineer.md +6 -0
- package/workflows/workflows/agent-environment-setup/platforms/claude/agents/test-engineer.md +5 -0
- package/workflows/workflows/agent-environment-setup/platforms/claude/agents/validator.md +1 -0
- package/workflows/workflows/agent-environment-setup/platforms/claude/agents/vercel-expert.md +1 -0
- package/workflows/workflows/agent-environment-setup/platforms/claude/rules/CLAUDE.md +77 -63
- package/workflows/workflows/agent-environment-setup/platforms/claude/skills/playwright-e2e/SKILL.md +21 -5
- package/workflows/workflows/agent-environment-setup/platforms/claude/skills/playwright-e2e/references/locator-trace-flake-checklist.md +28 -0
- package/workflows/workflows/agent-environment-setup/platforms/claude/skills/skills_index.json +802 -99
- package/workflows/workflows/agent-environment-setup/platforms/codex/agents/backend-specialist.md +6 -0
- package/workflows/workflows/agent-environment-setup/platforms/codex/agents/code-archaeologist.md +7 -0
- package/workflows/workflows/agent-environment-setup/platforms/codex/agents/database-architect.md +6 -0
- package/workflows/workflows/agent-environment-setup/platforms/codex/agents/debugger.md +7 -0
- package/workflows/workflows/agent-environment-setup/platforms/codex/agents/devops-engineer.md +6 -0
- package/workflows/workflows/agent-environment-setup/platforms/codex/agents/documentation-writer.md +4 -0
- package/workflows/workflows/agent-environment-setup/platforms/codex/agents/frontend-specialist.md +6 -0
- package/workflows/workflows/agent-environment-setup/platforms/codex/agents/game-developer.md +1 -0
- package/workflows/workflows/agent-environment-setup/platforms/codex/agents/mobile-developer.md +6 -0
- package/workflows/workflows/agent-environment-setup/platforms/codex/agents/orchestrator.md +8 -0
- package/workflows/workflows/agent-environment-setup/platforms/codex/agents/penetration-tester.md +4 -0
- package/workflows/workflows/agent-environment-setup/platforms/codex/agents/performance-optimizer.md +4 -0
- package/workflows/workflows/agent-environment-setup/platforms/codex/agents/product-manager.md +1 -0
- package/workflows/workflows/agent-environment-setup/platforms/codex/agents/project-planner.md +8 -0
- package/workflows/workflows/agent-environment-setup/platforms/codex/agents/qa-automation-engineer.md +1 -0
- package/workflows/workflows/agent-environment-setup/platforms/codex/agents/researcher.md +5 -0
- package/workflows/workflows/agent-environment-setup/platforms/codex/agents/security-auditor.md +6 -0
- package/workflows/workflows/agent-environment-setup/platforms/codex/agents/seo-specialist.md +1 -0
- package/workflows/workflows/agent-environment-setup/platforms/codex/agents/sre-engineer.md +6 -0
- package/workflows/workflows/agent-environment-setup/platforms/codex/agents/test-engineer.md +5 -0
- package/workflows/workflows/agent-environment-setup/platforms/codex/agents/validator.md +1 -0
- package/workflows/workflows/agent-environment-setup/platforms/codex/agents/vercel-expert.md +1 -0
- package/workflows/workflows/agent-environment-setup/platforms/codex/rules/AGENTS.md +1 -1
- package/workflows/workflows/agent-environment-setup/platforms/copilot/agents/backend-specialist.md +5 -0
- package/workflows/workflows/agent-environment-setup/platforms/copilot/agents/code-archaeologist.md +5 -0
- package/workflows/workflows/agent-environment-setup/platforms/copilot/agents/database-architect.md +5 -0
- package/workflows/workflows/agent-environment-setup/platforms/copilot/agents/debugger.md +5 -0
- package/workflows/workflows/agent-environment-setup/platforms/copilot/agents/devops-engineer.md +5 -0
- package/workflows/workflows/agent-environment-setup/platforms/copilot/agents/documentation-writer.md +3 -0
- package/workflows/workflows/agent-environment-setup/platforms/copilot/agents/frontend-specialist.md +5 -0
- package/workflows/workflows/agent-environment-setup/platforms/copilot/agents/mobile-developer.md +5 -0
- package/workflows/workflows/agent-environment-setup/platforms/copilot/agents/orchestrator.md +6 -0
- package/workflows/workflows/agent-environment-setup/platforms/copilot/agents/penetration-tester.md +3 -0
- package/workflows/workflows/agent-environment-setup/platforms/copilot/agents/performance-optimizer.md +3 -0
- package/workflows/workflows/agent-environment-setup/platforms/copilot/agents/project-planner.md +6 -0
- package/workflows/workflows/agent-environment-setup/platforms/copilot/agents/researcher.md +3 -0
- package/workflows/workflows/agent-environment-setup/platforms/copilot/agents/security-auditor.md +5 -0
- package/workflows/workflows/agent-environment-setup/platforms/copilot/agents/sre-engineer.md +5 -0
- package/workflows/workflows/agent-environment-setup/platforms/copilot/agents/test-engineer.md +3 -0
- package/workflows/workflows/agent-environment-setup/platforms/copilot/rules/copilot-instructions.md +87 -82
- package/workflows/workflows/agent-environment-setup/platforms/copilot/skills/playwright-e2e/SKILL.md +21 -5
- package/workflows/workflows/agent-environment-setup/platforms/copilot/skills/playwright-e2e/references/locator-trace-flake-checklist.md +28 -0
- package/workflows/workflows/agent-environment-setup/platforms/copilot/skills/skills_index.json +802 -99
- package/workflows/workflows/agent-environment-setup/shared/agents/backend-specialist.md +6 -0
- package/workflows/workflows/agent-environment-setup/shared/agents/code-archaeologist.md +7 -0
- package/workflows/workflows/agent-environment-setup/shared/agents/database-architect.md +6 -0
- package/workflows/workflows/agent-environment-setup/shared/agents/debugger.md +7 -0
- package/workflows/workflows/agent-environment-setup/shared/agents/devops-engineer.md +6 -0
- package/workflows/workflows/agent-environment-setup/shared/agents/documentation-writer.md +4 -0
- package/workflows/workflows/agent-environment-setup/shared/agents/frontend-specialist.md +6 -0
- package/workflows/workflows/agent-environment-setup/shared/agents/game-developer.md +1 -0
- package/workflows/workflows/agent-environment-setup/shared/agents/mobile-developer.md +6 -0
- package/workflows/workflows/agent-environment-setup/shared/agents/orchestrator.md +8 -0
- package/workflows/workflows/agent-environment-setup/shared/agents/penetration-tester.md +4 -0
- package/workflows/workflows/agent-environment-setup/shared/agents/performance-optimizer.md +4 -0
- package/workflows/workflows/agent-environment-setup/shared/agents/product-manager.md +1 -0
- package/workflows/workflows/agent-environment-setup/shared/agents/project-planner.md +8 -0
- package/workflows/workflows/agent-environment-setup/shared/agents/qa-automation-engineer.md +1 -0
- package/workflows/workflows/agent-environment-setup/shared/agents/researcher.md +5 -0
- package/workflows/workflows/agent-environment-setup/shared/agents/security-auditor.md +6 -0
- package/workflows/workflows/agent-environment-setup/shared/agents/seo-specialist.md +1 -0
- package/workflows/workflows/agent-environment-setup/shared/agents/sre-engineer.md +6 -0
- package/workflows/workflows/agent-environment-setup/shared/agents/test-engineer.md +5 -0
- package/workflows/workflows/agent-environment-setup/shared/agents/validator.md +1 -0
- package/workflows/workflows/agent-environment-setup/shared/agents/vercel-expert.md +1 -0
- package/workflows/workflows/agent-environment-setup/shared/rules/STEERING.md +27 -4
- package/workflows/workflows/agent-environment-setup/shared/rules/overrides/antigravity.md +18 -3
- package/workflows/workflows/agent-environment-setup/shared/rules/overrides/claude.md +12 -4
- package/workflows/workflows/agent-environment-setup/shared/rules/overrides/codex.md +12 -2
- package/workflows/workflows/agent-environment-setup/shared/rules/overrides/copilot.md +13 -3
- package/workflows/skills/react-best-practices/docs/AGENTS.md +0 -2934
- package/workflows/workflows/agent-environment-setup/platforms/claude/skills/react-best-practices/docs/AGENTS.md +0 -2934
- package/workflows/workflows/agent-environment-setup/platforms/copilot/rules/AGENTS.md +0 -25
- package/workflows/workflows/agent-environment-setup/platforms/copilot/skills/react-best-practices/docs/AGENTS.md +0 -2934
|
@@ -42,9 +42,18 @@ function createTestContext(): ToolRuntimeContext {
|
|
|
42
42
|
primarySkills: ["flutter-expert"],
|
|
43
43
|
supportingSkills: [],
|
|
44
44
|
artifacts: {
|
|
45
|
-
codex: {
|
|
46
|
-
|
|
47
|
-
|
|
45
|
+
codex: {
|
|
46
|
+
workflowFile: "mobile.md",
|
|
47
|
+
compatibilityAlias: "$workflow-mobile",
|
|
48
|
+
},
|
|
49
|
+
copilot: {
|
|
50
|
+
workflowFile: "mobile.md",
|
|
51
|
+
promptFile: "workflow-mobile.prompt.md",
|
|
52
|
+
},
|
|
53
|
+
antigravity: {
|
|
54
|
+
workflowFile: "mobile.md",
|
|
55
|
+
commandFile: "mobile.toml",
|
|
56
|
+
},
|
|
48
57
|
claude: { workflowFile: "mobile.md" },
|
|
49
58
|
},
|
|
50
59
|
},
|
|
@@ -77,10 +86,11 @@ describe("tool registry", () => {
|
|
|
77
86
|
expect(names).toContain("stitch_get_mode");
|
|
78
87
|
expect(names).toContain("stitch_set_profile");
|
|
79
88
|
expect(names).toContain("stitch_get_status");
|
|
89
|
+
expect(names).toContain("playwright_get_status");
|
|
80
90
|
});
|
|
81
91
|
|
|
82
|
-
it("has exactly
|
|
83
|
-
expect(TOOL_REGISTRY).toHaveLength(
|
|
92
|
+
it("has exactly 15 built-in tools", () => {
|
|
93
|
+
expect(TOOL_REGISTRY).toHaveLength(15);
|
|
84
94
|
});
|
|
85
95
|
|
|
86
96
|
it("has no duplicate tool names", () => {
|
|
@@ -94,7 +104,9 @@ describe("tool registry", () => {
|
|
|
94
104
|
expect(entry.name).toBeTruthy();
|
|
95
105
|
expect(entry.description).toBeTruthy();
|
|
96
106
|
expect(entry.schema).toBeTruthy();
|
|
97
|
-
expect(entry.category).toMatch(
|
|
107
|
+
expect(entry.category).toMatch(
|
|
108
|
+
/^(skill|route|postman|stitch|playwright)$/,
|
|
109
|
+
);
|
|
98
110
|
expect(typeof entry.createHandler).toBe("function");
|
|
99
111
|
}
|
|
100
112
|
});
|
|
@@ -128,7 +140,11 @@ describe("tool registry", () => {
|
|
|
128
140
|
(t) => t.name === "skill_list_categories",
|
|
129
141
|
)!;
|
|
130
142
|
const handler = entry.createHandler(ctx);
|
|
131
|
-
const result = (await
|
|
143
|
+
const result = (await (
|
|
144
|
+
handler as unknown as (
|
|
145
|
+
args: Record<string, never>,
|
|
146
|
+
) => Promise<{ content: Array<{ text: string }> }>
|
|
147
|
+
)({})) as {
|
|
132
148
|
content: Array<{ text: string }>;
|
|
133
149
|
};
|
|
134
150
|
const data = JSON.parse(result.content[0].text);
|
|
@@ -137,15 +153,17 @@ describe("tool registry", () => {
|
|
|
137
153
|
|
|
138
154
|
it("buildRegistrySummary produces correct structure", () => {
|
|
139
155
|
const summary = buildRegistrySummary();
|
|
140
|
-
expect(summary.totalTools).toBe(
|
|
156
|
+
expect(summary.totalTools).toBe(15);
|
|
141
157
|
expect(summary.categories).toHaveProperty("route");
|
|
142
158
|
expect(summary.categories).toHaveProperty("skill");
|
|
143
159
|
expect(summary.categories).toHaveProperty("postman");
|
|
144
160
|
expect(summary.categories).toHaveProperty("stitch");
|
|
161
|
+
expect(summary.categories).toHaveProperty("playwright");
|
|
145
162
|
expect(summary.categories.route.tools).toHaveLength(1);
|
|
146
163
|
expect(summary.categories.skill.tools).toHaveLength(7);
|
|
147
164
|
expect(summary.categories.postman.tools).toHaveLength(3);
|
|
148
165
|
expect(summary.categories.stitch.tools).toHaveLength(3);
|
|
166
|
+
expect(summary.categories.playwright.tools).toHaveLength(1);
|
|
149
167
|
});
|
|
150
168
|
|
|
151
169
|
it("each schema has a valid .shape property", () => {
|
|
@@ -12,13 +12,19 @@
|
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
14
|
import { z } from "zod";
|
|
15
|
+
import type { ToolCallback } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
15
16
|
import type { VaultManifest } from "../vault/types.js";
|
|
16
17
|
import type { RouteManifest } from "../routes/types.js";
|
|
17
18
|
import type { ConfigScope } from "../cbxConfig/types.js";
|
|
18
19
|
|
|
19
20
|
// ─── Core types ─────────────────────────────────────────────
|
|
20
21
|
|
|
21
|
-
export type ToolCategory =
|
|
22
|
+
export type ToolCategory =
|
|
23
|
+
| "skill"
|
|
24
|
+
| "route"
|
|
25
|
+
| "postman"
|
|
26
|
+
| "stitch"
|
|
27
|
+
| "playwright";
|
|
22
28
|
|
|
23
29
|
export interface ToolRegistryEntry {
|
|
24
30
|
/** Tool name exposed to MCP clients. */
|
|
@@ -35,7 +41,7 @@ export interface ToolRegistryEntry {
|
|
|
35
41
|
*/
|
|
36
42
|
createHandler: (
|
|
37
43
|
ctx: ToolRuntimeContext,
|
|
38
|
-
) =>
|
|
44
|
+
) => ToolCallback<z.ZodObject<z.ZodRawShape>>;
|
|
39
45
|
}
|
|
40
46
|
|
|
41
47
|
export interface ToolRuntimeContext {
|
|
@@ -146,6 +152,13 @@ import {
|
|
|
146
152
|
handleStitchGetStatus,
|
|
147
153
|
} from "./stitchGetStatus.js";
|
|
148
154
|
|
|
155
|
+
import {
|
|
156
|
+
playwrightGetStatusName,
|
|
157
|
+
playwrightGetStatusDescription,
|
|
158
|
+
playwrightGetStatusSchema,
|
|
159
|
+
handlePlaywrightGetStatus,
|
|
160
|
+
} from "./playwrightGetStatus.js";
|
|
161
|
+
|
|
149
162
|
// ─── Scope helper ───────────────────────────────────────────
|
|
150
163
|
|
|
151
164
|
function withDefaultScope(
|
|
@@ -335,6 +348,20 @@ export const TOOL_REGISTRY: readonly ToolRegistryEntry[] = [
|
|
|
335
348
|
>,
|
|
336
349
|
),
|
|
337
350
|
},
|
|
351
|
+
|
|
352
|
+
// ── Playwright tools ──────────────────────────────────────
|
|
353
|
+
{
|
|
354
|
+
name: playwrightGetStatusName,
|
|
355
|
+
description: playwrightGetStatusDescription,
|
|
356
|
+
schema: playwrightGetStatusSchema,
|
|
357
|
+
category: "playwright",
|
|
358
|
+
createHandler: (ctx) => async (args) =>
|
|
359
|
+
handlePlaywrightGetStatus(
|
|
360
|
+
withDefaultScope(args, ctx.defaultConfigScope) as z.infer<
|
|
361
|
+
typeof playwrightGetStatusSchema
|
|
362
|
+
>,
|
|
363
|
+
),
|
|
364
|
+
},
|
|
338
365
|
];
|
|
339
366
|
|
|
340
367
|
// ─── Helpers ────────────────────────────────────────────────
|
|
@@ -359,7 +359,7 @@ async function fileExists(target: string) {
|
|
|
359
359
|
|
|
360
360
|
async function detectLanguageSkillHint() {
|
|
361
361
|
const cwd = process.cwd();
|
|
362
|
-
const candidates = await fs.readdir(cwd).catch(() => []);
|
|
362
|
+
const candidates: string[] = await fs.readdir(cwd).catch(() => []);
|
|
363
363
|
const has = (fileName: string) => candidates.includes(fileName);
|
|
364
364
|
|
|
365
365
|
for (const entry of LANGUAGE_SIGNAL_FILES) {
|
|
@@ -6,14 +6,16 @@ import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
|
6
6
|
import path from "node:path";
|
|
7
7
|
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
8
8
|
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
|
9
|
+
import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
|
9
10
|
import {
|
|
10
11
|
parsePostmanState,
|
|
11
12
|
parseStitchState,
|
|
13
|
+
parsePlaywrightState,
|
|
12
14
|
readEffectiveConfig,
|
|
13
15
|
} from "../cbxConfig/index.js";
|
|
14
16
|
import type { CbxConfig, ConfigScope } from "../cbxConfig/types.js";
|
|
15
17
|
|
|
16
|
-
type ServiceId = "postman" | "stitch";
|
|
18
|
+
type ServiceId = "postman" | "stitch" | "playwright";
|
|
17
19
|
|
|
18
20
|
export interface UpstreamToolInfo {
|
|
19
21
|
name: string;
|
|
@@ -125,7 +127,10 @@ async function loadCachedCatalogTools({
|
|
|
125
127
|
}
|
|
126
128
|
}
|
|
127
129
|
|
|
128
|
-
function getServiceAuth(
|
|
130
|
+
function getServiceAuth(
|
|
131
|
+
config: CbxConfig,
|
|
132
|
+
service: ServiceId,
|
|
133
|
+
): {
|
|
129
134
|
mcpUrl: string | null;
|
|
130
135
|
activeProfileName: string | null;
|
|
131
136
|
envVar: string | null;
|
|
@@ -133,6 +138,17 @@ function getServiceAuth(config: CbxConfig, service: ServiceId): {
|
|
|
133
138
|
configured: boolean;
|
|
134
139
|
error?: string;
|
|
135
140
|
} {
|
|
141
|
+
if (service === "playwright") {
|
|
142
|
+
const state = parsePlaywrightState(config);
|
|
143
|
+
return {
|
|
144
|
+
mcpUrl: state.mcpUrl,
|
|
145
|
+
activeProfileName: null,
|
|
146
|
+
envVar: null,
|
|
147
|
+
headers: {},
|
|
148
|
+
configured: Boolean(state.mcpUrl),
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
|
|
136
152
|
if (service === "postman") {
|
|
137
153
|
const state = parsePostmanState(config);
|
|
138
154
|
const activeProfile = state.activeProfile;
|
|
@@ -209,6 +225,42 @@ async function withUpstreamClient<T>({
|
|
|
209
225
|
}
|
|
210
226
|
}
|
|
211
227
|
|
|
228
|
+
function isCallToolResult(
|
|
229
|
+
result: Awaited<ReturnType<Client["callTool"]>>,
|
|
230
|
+
): result is CallToolResult {
|
|
231
|
+
return Array.isArray(
|
|
232
|
+
(
|
|
233
|
+
result as {
|
|
234
|
+
content?: unknown;
|
|
235
|
+
}
|
|
236
|
+
).content,
|
|
237
|
+
);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
function normalizeUpstreamToolResult(
|
|
241
|
+
result: Awaited<ReturnType<Client["callTool"]>>,
|
|
242
|
+
): CallToolResult {
|
|
243
|
+
if (isCallToolResult(result)) {
|
|
244
|
+
return result;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
return {
|
|
248
|
+
content: [
|
|
249
|
+
{
|
|
250
|
+
type: "text",
|
|
251
|
+
text: JSON.stringify(
|
|
252
|
+
{
|
|
253
|
+
toolResult: result.toolResult,
|
|
254
|
+
},
|
|
255
|
+
null,
|
|
256
|
+
2,
|
|
257
|
+
),
|
|
258
|
+
},
|
|
259
|
+
],
|
|
260
|
+
_meta: result._meta,
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
|
|
212
264
|
async function persistCatalog(catalog: UpstreamCatalog): Promise<void> {
|
|
213
265
|
if (!catalog.configPath) return;
|
|
214
266
|
const catalogDir = resolveCatalogDir(catalog.configPath);
|
|
@@ -240,6 +292,7 @@ export async function discoverUpstreamCatalogs(
|
|
|
240
292
|
): Promise<{
|
|
241
293
|
postman: UpstreamCatalog;
|
|
242
294
|
stitch: UpstreamCatalog;
|
|
295
|
+
playwright: UpstreamCatalog;
|
|
243
296
|
}> {
|
|
244
297
|
const effective = readEffectiveConfig(scope);
|
|
245
298
|
if (!effective) {
|
|
@@ -256,9 +309,14 @@ export async function discoverUpstreamCatalogs(
|
|
|
256
309
|
discoveryError: "cbx_config.json not found",
|
|
257
310
|
};
|
|
258
311
|
const missingStitch: UpstreamCatalog = { ...missing, service: "stitch" };
|
|
312
|
+
const missingPlaywright: UpstreamCatalog = {
|
|
313
|
+
...missing,
|
|
314
|
+
service: "playwright",
|
|
315
|
+
};
|
|
259
316
|
return {
|
|
260
317
|
postman: missing,
|
|
261
318
|
stitch: missingStitch,
|
|
319
|
+
playwright: missingPlaywright,
|
|
262
320
|
};
|
|
263
321
|
}
|
|
264
322
|
|
|
@@ -331,6 +389,7 @@ export async function discoverUpstreamCatalogs(
|
|
|
331
389
|
return {
|
|
332
390
|
postman: await discoverOne("postman"),
|
|
333
391
|
stitch: await discoverOne("stitch"),
|
|
392
|
+
playwright: await discoverOne("playwright"),
|
|
334
393
|
};
|
|
335
394
|
}
|
|
336
395
|
|
|
@@ -344,7 +403,7 @@ export async function callUpstreamTool({
|
|
|
344
403
|
name: string;
|
|
345
404
|
argumentsValue: Record<string, unknown>;
|
|
346
405
|
scope?: ConfigScope | "auto";
|
|
347
|
-
}) {
|
|
406
|
+
}): Promise<CallToolResult> {
|
|
348
407
|
const effective = readEffectiveConfig(scope);
|
|
349
408
|
if (!effective) {
|
|
350
409
|
throw new Error("cbx_config.json not found");
|
|
@@ -360,10 +419,12 @@ export async function callUpstreamTool({
|
|
|
360
419
|
return withUpstreamClient({
|
|
361
420
|
url: auth.mcpUrl,
|
|
362
421
|
headers: auth.headers,
|
|
363
|
-
fn: async (client) =>
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
422
|
+
fn: async (client): Promise<CallToolResult> =>
|
|
423
|
+
normalizeUpstreamToolResult(
|
|
424
|
+
await client.callTool({
|
|
425
|
+
name,
|
|
426
|
+
arguments: argumentsValue,
|
|
427
|
+
}),
|
|
428
|
+
),
|
|
368
429
|
});
|
|
369
430
|
}
|
package/package.json
CHANGED
package/src/cli/core.ts
CHANGED
|
@@ -217,6 +217,10 @@ const STITCH_SKILL_ID = "stitch";
|
|
|
217
217
|
const STITCH_MCP_SERVER_ID = "StitchMCP";
|
|
218
218
|
const STITCH_API_KEY_ENV_VAR = "STITCH_API_KEY_DEFAULT";
|
|
219
219
|
const STITCH_MCP_URL = "https://stitch.googleapis.com/mcp";
|
|
220
|
+
const PLAYWRIGHT_SKILL_ID = "playwright";
|
|
221
|
+
const PLAYWRIGHT_MCP_SERVER_ID = "PlaywrightMCP";
|
|
222
|
+
const PLAYWRIGHT_DEFAULT_PORT = 8931;
|
|
223
|
+
const PLAYWRIGHT_MCP_URL = `http://localhost:${PLAYWRIGHT_DEFAULT_PORT}/mcp`;
|
|
220
224
|
const POSTMAN_WORKSPACE_MANUAL_CHOICE = "__postman_workspace_manual__";
|
|
221
225
|
const CBX_CONFIG_FILENAME = "cbx_config.json";
|
|
222
226
|
const CBX_CREDENTIALS_ENV_FILENAME = "credentials.env";
|
|
@@ -4719,6 +4723,30 @@ function buildGeminiStitchServer({
|
|
|
4719
4723
|
};
|
|
4720
4724
|
}
|
|
4721
4725
|
|
|
4726
|
+
function buildVsCodePlaywrightServer({ mcpUrl = PLAYWRIGHT_MCP_URL } = {}) {
|
|
4727
|
+
return {
|
|
4728
|
+
type: "http",
|
|
4729
|
+
url: mcpUrl,
|
|
4730
|
+
headers: {},
|
|
4731
|
+
};
|
|
4732
|
+
}
|
|
4733
|
+
|
|
4734
|
+
function buildCopilotCliPlaywrightServer({ mcpUrl = PLAYWRIGHT_MCP_URL } = {}) {
|
|
4735
|
+
return {
|
|
4736
|
+
type: "http",
|
|
4737
|
+
url: mcpUrl,
|
|
4738
|
+
headers: {},
|
|
4739
|
+
tools: ["*"],
|
|
4740
|
+
};
|
|
4741
|
+
}
|
|
4742
|
+
|
|
4743
|
+
function buildGeminiPlaywrightServer({ mcpUrl = PLAYWRIGHT_MCP_URL } = {}) {
|
|
4744
|
+
return {
|
|
4745
|
+
httpUrl: mcpUrl,
|
|
4746
|
+
headers: {},
|
|
4747
|
+
};
|
|
4748
|
+
}
|
|
4749
|
+
|
|
4722
4750
|
function getPostmanApiKeySource({ apiKey, envApiKey }) {
|
|
4723
4751
|
if (apiKey) return "inline";
|
|
4724
4752
|
if (envApiKey) return "env";
|
|
@@ -5210,6 +5238,7 @@ async function applyPostmanMcpForPlatform({
|
|
|
5210
5238
|
stitchMcpUrl,
|
|
5211
5239
|
includeStitchMcp = false,
|
|
5212
5240
|
includeFoundryMcp = true,
|
|
5241
|
+
includePlaywrightMcp = false,
|
|
5213
5242
|
foundryRuntime = "local",
|
|
5214
5243
|
dryRun = false,
|
|
5215
5244
|
cwd = process.cwd(),
|
|
@@ -5278,6 +5307,9 @@ async function applyPostmanMcpForPlatform({
|
|
|
5278
5307
|
mcpUrl: stitchMcpUrl,
|
|
5279
5308
|
});
|
|
5280
5309
|
}
|
|
5310
|
+
if (includePlaywrightMcp) {
|
|
5311
|
+
mcpServers[PLAYWRIGHT_MCP_SERVER_ID] = buildGeminiPlaywrightServer();
|
|
5312
|
+
}
|
|
5281
5313
|
next.mcpServers = mcpServers;
|
|
5282
5314
|
return next;
|
|
5283
5315
|
},
|
|
@@ -5324,6 +5356,10 @@ async function applyPostmanMcpForPlatform({
|
|
|
5324
5356
|
} else {
|
|
5325
5357
|
delete mcpServers[FOUNDRY_MCP_SERVER_ID];
|
|
5326
5358
|
}
|
|
5359
|
+
if (includePlaywrightMcp) {
|
|
5360
|
+
mcpServers[PLAYWRIGHT_MCP_SERVER_ID] =
|
|
5361
|
+
buildCopilotCliPlaywrightServer();
|
|
5362
|
+
}
|
|
5327
5363
|
next.mcpServers = mcpServers;
|
|
5328
5364
|
return next;
|
|
5329
5365
|
}
|
|
@@ -5350,6 +5386,9 @@ async function applyPostmanMcpForPlatform({
|
|
|
5350
5386
|
} else {
|
|
5351
5387
|
delete servers[FOUNDRY_MCP_SERVER_ID];
|
|
5352
5388
|
}
|
|
5389
|
+
if (includePlaywrightMcp) {
|
|
5390
|
+
servers[PLAYWRIGHT_MCP_SERVER_ID] = buildVsCodePlaywrightServer();
|
|
5391
|
+
}
|
|
5353
5392
|
next.servers = servers;
|
|
5354
5393
|
return next;
|
|
5355
5394
|
},
|
|
@@ -5401,6 +5440,9 @@ async function applyPostmanMcpForPlatform({
|
|
|
5401
5440
|
} else {
|
|
5402
5441
|
delete servers[FOUNDRY_MCP_SERVER_ID];
|
|
5403
5442
|
}
|
|
5443
|
+
if (includePlaywrightMcp) {
|
|
5444
|
+
servers[PLAYWRIGHT_MCP_SERVER_ID] = buildVsCodePlaywrightServer();
|
|
5445
|
+
}
|
|
5404
5446
|
next.servers = servers;
|
|
5405
5447
|
return next;
|
|
5406
5448
|
},
|
|
@@ -5529,6 +5571,57 @@ async function applyPostmanMcpForPlatform({
|
|
|
5529
5571
|
};
|
|
5530
5572
|
}
|
|
5531
5573
|
|
|
5574
|
+
if (platform === "claude") {
|
|
5575
|
+
const claudeConfigPath =
|
|
5576
|
+
mcpScope === "global"
|
|
5577
|
+
? path.join(os.homedir(), ".claude", "mcp.json")
|
|
5578
|
+
: path.join(workspaceRoot, ".mcp.json");
|
|
5579
|
+
const result = await upsertJsonObjectFile({
|
|
5580
|
+
targetPath: claudeConfigPath,
|
|
5581
|
+
updater: (existing) => {
|
|
5582
|
+
const next = { ...existing };
|
|
5583
|
+
const mcpServers =
|
|
5584
|
+
next.mcpServers &&
|
|
5585
|
+
typeof next.mcpServers === "object" &&
|
|
5586
|
+
!Array.isArray(next.mcpServers)
|
|
5587
|
+
? { ...next.mcpServers }
|
|
5588
|
+
: {};
|
|
5589
|
+
if (includeFoundryMcp) {
|
|
5590
|
+
if (normalizedFoundryRuntime === "docker") {
|
|
5591
|
+
mcpServers[FOUNDRY_MCP_SERVER_ID] = {
|
|
5592
|
+
type: "url",
|
|
5593
|
+
url: buildFoundryDockerUrl({ port: foundryDockerPort }),
|
|
5594
|
+
};
|
|
5595
|
+
} else {
|
|
5596
|
+
mcpServers[FOUNDRY_MCP_SERVER_ID] = {
|
|
5597
|
+
type: "stdio",
|
|
5598
|
+
command: FOUNDRY_MCP_COMMAND,
|
|
5599
|
+
args: buildFoundryServeArgs({ scope: foundryScope }),
|
|
5600
|
+
};
|
|
5601
|
+
}
|
|
5602
|
+
} else {
|
|
5603
|
+
delete mcpServers[FOUNDRY_MCP_SERVER_ID];
|
|
5604
|
+
}
|
|
5605
|
+
if (includePlaywrightMcp) {
|
|
5606
|
+
mcpServers[PLAYWRIGHT_MCP_SERVER_ID] = {
|
|
5607
|
+
type: "url",
|
|
5608
|
+
url: PLAYWRIGHT_MCP_URL,
|
|
5609
|
+
};
|
|
5610
|
+
}
|
|
5611
|
+
next.mcpServers = mcpServers;
|
|
5612
|
+
return next;
|
|
5613
|
+
},
|
|
5614
|
+
dryRun,
|
|
5615
|
+
});
|
|
5616
|
+
return {
|
|
5617
|
+
kind: "claude-mcp",
|
|
5618
|
+
scope: mcpScope,
|
|
5619
|
+
path: claudeConfigPath,
|
|
5620
|
+
action: result.action,
|
|
5621
|
+
warnings: [...warnings, ...result.warnings],
|
|
5622
|
+
};
|
|
5623
|
+
}
|
|
5624
|
+
|
|
5532
5625
|
return {
|
|
5533
5626
|
kind: "unknown",
|
|
5534
5627
|
scope: mcpScope,
|
|
@@ -5606,10 +5699,7 @@ async function resolvePostmanInstallSelection({
|
|
|
5606
5699
|
: null;
|
|
5607
5700
|
let workspaceSelectionSource = hasWorkspaceOption ? "option" : "none";
|
|
5608
5701
|
const requestedMcpScope = options.mcpScope
|
|
5609
|
-
? coerceWorkspaceOnlyMcpScope(
|
|
5610
|
-
options.mcpScope,
|
|
5611
|
-
"--mcp-scope",
|
|
5612
|
-
)
|
|
5702
|
+
? coerceWorkspaceOnlyMcpScope(options.mcpScope, "--mcp-scope")
|
|
5613
5703
|
: null;
|
|
5614
5704
|
let mcpScope = requestedMcpScope?.scope || "project";
|
|
5615
5705
|
const warnings = [];
|
|
@@ -6057,6 +6147,7 @@ async function configurePostmanInstallArtifacts({
|
|
|
6057
6147
|
stitchMcpUrl: effectiveStitchMcpUrl,
|
|
6058
6148
|
includeStitchMcp: shouldInstallStitch,
|
|
6059
6149
|
includeFoundryMcp: postmanSelection.foundryMcpEnabled,
|
|
6150
|
+
includePlaywrightMcp: postmanSelection.playwrightEnabled ?? false,
|
|
6060
6151
|
foundryRuntime: postmanSelection.effectiveMcpRuntime || "local",
|
|
6061
6152
|
dryRun,
|
|
6062
6153
|
cwd,
|
|
@@ -6167,6 +6258,7 @@ async function applyPostmanConfigArtifacts({
|
|
|
6167
6258
|
POSTMAN_API_KEY_ENV_VAR;
|
|
6168
6259
|
const postmanMcpUrl = postmanState.mcpUrl || POSTMAN_MCP_URL;
|
|
6169
6260
|
const stitchEnabled = Boolean(stitchState);
|
|
6261
|
+
const playwrightEnabled = Boolean(configValue?.playwright);
|
|
6170
6262
|
const stitchApiKeyEnvVar =
|
|
6171
6263
|
normalizePostmanApiKey(stitchState?.apiKeyEnvVar) || STITCH_API_KEY_ENV_VAR;
|
|
6172
6264
|
const stitchMcpUrl = stitchState?.mcpUrl || STITCH_MCP_URL;
|
|
@@ -6239,6 +6331,7 @@ async function applyPostmanConfigArtifacts({
|
|
|
6239
6331
|
stitchMcpUrl,
|
|
6240
6332
|
includeStitchMcp: stitchEnabled,
|
|
6241
6333
|
includeFoundryMcp: true,
|
|
6334
|
+
includePlaywrightMcp: playwrightEnabled ?? false,
|
|
6242
6335
|
foundryRuntime,
|
|
6243
6336
|
dryRun,
|
|
6244
6337
|
cwd,
|
|
@@ -8239,7 +8332,9 @@ async function performWorkflowInstall(
|
|
|
8239
8332
|
cancelled: false,
|
|
8240
8333
|
cwd,
|
|
8241
8334
|
scope,
|
|
8242
|
-
warnings: requestedInstallScope.warning
|
|
8335
|
+
warnings: requestedInstallScope.warning
|
|
8336
|
+
? [requestedInstallScope.warning]
|
|
8337
|
+
: [],
|
|
8243
8338
|
ruleScope,
|
|
8244
8339
|
dryRun,
|
|
8245
8340
|
platform,
|
package/src/cli/init/execute.ts
CHANGED
|
@@ -23,12 +23,20 @@ export function buildInitExecutionPlan({
|
|
|
23
23
|
const planItems: InitExecutionPlanItem[] = [];
|
|
24
24
|
const wantsPostman = hasMcpSelection(selections.selectedMcps, "postman");
|
|
25
25
|
const wantsStitch = hasMcpSelection(selections.selectedMcps, "stitch");
|
|
26
|
-
const wantsFoundry = hasMcpSelection(
|
|
26
|
+
const wantsFoundry = hasMcpSelection(
|
|
27
|
+
selections.selectedMcps,
|
|
28
|
+
"cubis-foundry",
|
|
29
|
+
);
|
|
30
|
+
const wantsPlaywright = hasMcpSelection(
|
|
31
|
+
selections.selectedMcps,
|
|
32
|
+
"playwright",
|
|
33
|
+
);
|
|
27
34
|
|
|
28
35
|
for (const platform of selections.platforms) {
|
|
29
36
|
const stitchSupported = platform === "antigravity";
|
|
30
37
|
const stitchEnabled = wantsStitch && stitchSupported;
|
|
31
|
-
const hasAnyMcp =
|
|
38
|
+
const hasAnyMcp =
|
|
39
|
+
wantsPostman || stitchEnabled || wantsFoundry || wantsPlaywright;
|
|
32
40
|
const warnings: string[] = [];
|
|
33
41
|
if (wantsStitch && !stitchSupported) {
|
|
34
42
|
warnings.push(
|
|
@@ -48,10 +56,11 @@ export function buildInitExecutionPlan({
|
|
|
48
56
|
target,
|
|
49
57
|
postman: wantsPostman,
|
|
50
58
|
stitch: stitchEnabled,
|
|
59
|
+
playwright: wantsPlaywright,
|
|
51
60
|
stitchDefaultForAntigravity: false,
|
|
52
61
|
mcpScope: selections.mcpScope,
|
|
53
62
|
foundryMcp: wantsFoundry,
|
|
54
|
-
mcpToolSync: wantsPostman || stitchEnabled,
|
|
63
|
+
mcpToolSync: wantsPostman || stitchEnabled || wantsPlaywright,
|
|
55
64
|
mcpRuntime: hasAnyMcp ? selections.mcpRuntime : "local",
|
|
56
65
|
mcpFallback: "local",
|
|
57
66
|
mcpBuildLocal: hasAnyMcp ? selections.mcpBuildLocal : false,
|
|
@@ -83,9 +92,9 @@ export function formatInitSummary(selections: InitWizardSelections) {
|
|
|
83
92
|
`- Skill profile: ${selections.skillProfile}`,
|
|
84
93
|
`- Skills scope: ${selections.skillsScope}`,
|
|
85
94
|
`- MCP scope: ${selections.mcpScope}`,
|
|
86
|
-
`- MCP runtime: ${selections.mcpRuntime}${selections.mcpRuntime === "docker" ? selections.mcpBuildLocal ? " (build local image)" : " (pull image)" : ""}`,
|
|
95
|
+
`- MCP runtime: ${selections.mcpRuntime}${selections.mcpRuntime === "docker" ? (selections.mcpBuildLocal ? " (build local image)" : " (pull image)") : ""}`,
|
|
87
96
|
`- MCP selections: ${selections.selectedMcps.length > 0 ? selections.selectedMcps.join(", ") : "(none)"}`,
|
|
88
97
|
`- Postman mode: ${postmanSelected ? selections.postmanMode : "(not selected)"}`,
|
|
89
|
-
`- Postman workspace: ${postmanSelected ? selections.postmanWorkspaceId === null ? "null" : selections.postmanWorkspaceId : "(not selected)"}`,
|
|
98
|
+
`- Postman workspace: ${postmanSelected ? (selections.postmanWorkspaceId === null ? "null" : selections.postmanWorkspaceId) : "(not selected)"}`,
|
|
90
99
|
].join("\n");
|
|
91
100
|
}
|
package/src/cli/init/prompts.ts
CHANGED
|
@@ -90,6 +90,11 @@ export async function promptInitMcpSelection(defaultMcps: InitMcpId[]) {
|
|
|
90
90
|
value: "stitch",
|
|
91
91
|
checked: defaultMcps.includes("stitch"),
|
|
92
92
|
},
|
|
93
|
+
{
|
|
94
|
+
name: "Playwright",
|
|
95
|
+
value: "playwright",
|
|
96
|
+
checked: defaultMcps.includes("playwright"),
|
|
97
|
+
},
|
|
93
98
|
],
|
|
94
99
|
});
|
|
95
100
|
}
|
package/src/cli/init/types.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export type InitScope = "project" | "global";
|
|
2
2
|
export type InitSkillProfile = "core" | "web-backend" | "full";
|
|
3
|
-
export type InitMcpId = "cubis-foundry" | "postman" | "stitch";
|
|
3
|
+
export type InitMcpId = "cubis-foundry" | "postman" | "stitch" | "playwright";
|
|
4
4
|
export type InitPostmanMode = "full" | "minimal";
|
|
5
5
|
export type InitPlatformId = "codex" | "antigravity" | "copilot" | "claude";
|
|
6
6
|
export type InitMcpRuntime = "local" | "docker";
|