ios-vibe-mcp01 0.1.4 → 0.1.6

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/index.js CHANGED
@@ -2,16 +2,20 @@
2
2
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
3
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
4
  import { registerIosVibeTool } from "./iosVibe.js";
5
- const server = new McpServer({
6
- name: "iOS Vibe Factory",
7
- version: "0.1.0",
8
- });
9
- registerIosVibeTool(server);
10
5
  async function main() {
6
+ const server = new McpServer({
7
+ name: "ios-vibe-factory",
8
+ version: "0.1.2",
9
+ });
10
+ // ✅ ios_vibe tool'unu ekle
11
+ registerIosVibeTool(server);
12
+ // ✅ Cursor MCP: stdio transport ile bağlan
11
13
  const transport = new StdioServerTransport();
12
14
  await server.connect(transport);
15
+ // ⚠️ stdout'a log basma (protocol bozulur). Sadece stderr.
16
+ console.error("ios-vibe-mcp01: connected via stdio");
13
17
  }
14
18
  main().catch((err) => {
15
- console.error("Fatal MCP server error:", err);
19
+ console.error("ios-vibe-mcp01: startup failed", err);
16
20
  process.exit(1);
17
21
  });
package/dist/iosVibe.js CHANGED
@@ -3,8 +3,8 @@ import { renderFilesForCommand } from "./templates.js";
3
3
  import { validateWorkflow } from "./rules.js";
4
4
  const CommandSchema = z.enum(["plan", "architecture", "coding", "uiux", "test", "review", "ship"]);
5
5
  const InputSchema = z.object({
6
- command: CommandSchema,
7
- idea: z.string().optional(),
6
+ command: CommandSchema.describe("Which stage of the iOS app workflow to run"),
7
+ idea: z.string().optional().describe("Your app idea (required for plan)"),
8
8
  config: z
9
9
  .object({
10
10
  appName: z.string().default("MyApp"),
@@ -13,7 +13,8 @@ const InputSchema = z.object({
13
13
  tone: z.string().default("soft pink"),
14
14
  constraints: z.array(z.string()).default(["offline-first", "no firebase", "mvvm", "repository"]),
15
15
  })
16
- .optional(),
16
+ .optional()
17
+ .describe("Optional project configuration"),
17
18
  state: z
18
19
  .object({
19
20
  projectBlueprintMd: z.string().optional(),
@@ -26,14 +27,9 @@ const InputSchema = z.object({
26
27
  runbookMd: z.string().optional(),
27
28
  backlogMd: z.string().optional(),
28
29
  })
29
- .optional(),
30
+ .optional()
31
+ .describe("Previous stage outputs (auto-managed)"),
30
32
  });
31
- /**
32
- * Accepts both:
33
- * 1) JSON input (object): { command: "plan", idea: "..." }
34
- * 2) Human text input (string): "plan: ..." or "architecture" etc.
35
- * Also supports { text: "plan: ..." } shape as a convenience.
36
- */
37
33
  function normalizeInput(raw) {
38
34
  const text = typeof raw === "string"
39
35
  ? raw
@@ -43,71 +39,38 @@ function normalizeInput(raw) {
43
39
  if (!text)
44
40
  return raw;
45
41
  const t = text.trim();
46
- // plan: <idea>
47
42
  const planMatch = t.match(/^plan\s*:\s*(.+)$/i);
48
- if (planMatch) {
43
+ if (planMatch)
49
44
  return { command: "plan", idea: planMatch[1].trim() };
50
- }
51
- // Single-word commands
52
45
  const lower = t.toLowerCase();
53
46
  const allowed = ["architecture", "coding", "uiux", "test", "review", "ship"];
54
- if (allowed.includes(lower)) {
47
+ if (allowed.includes(lower))
55
48
  return { command: lower };
56
- }
57
- // If user writes just "plan" without idea, let workflow validator handle it
58
- if (/^plan$/i.test(t)) {
49
+ if (/^plan$/i.test(t))
59
50
  return { command: "plan", idea: "" };
60
- }
61
- // Fallback: keep original raw so Zod can throw a clear error
62
51
  return raw;
63
52
  }
64
53
  export function registerIosVibeTool(server) {
65
- server.tool("ios_vibe", {
66
- // Keep this permissive so the tool can accept either object inputs
67
- // or "text" wrappers depending on the client
68
- command: z.string().optional(),
69
- idea: z.string().optional(),
70
- config: z.any().optional(),
71
- state: z.any().optional(),
72
- text: z.string().optional(),
73
- }, async (raw) => {
54
+ // ✅ Use InputSchema.shape for maximum SDK compatibility
55
+ server.tool("ios_vibe", InputSchema.shape, async (raw) => {
74
56
  const normalized = normalizeInput(raw);
75
57
  const parsed = InputSchema.safeParse(normalized);
76
58
  if (!parsed.success) {
77
- return {
78
- content: [
79
- {
80
- type: "text",
81
- text: `Invalid input: ${parsed.error.message}`,
82
- },
83
- ],
84
- };
59
+ return { content: [{ type: "text", text: `Invalid input: ${parsed.error.message}` }] };
85
60
  }
86
61
  const input = parsed.data;
87
- // 1) Workflow gatekeeping
88
62
  const flow = validateWorkflow(input);
89
63
  if (!flow.ok) {
90
64
  return {
91
65
  content: [
92
66
  {
93
67
  type: "text",
94
- text: `Command blocked: ${flow.reason}\n\n` +
95
- `Fix: ${flow.fix}\n\n` +
96
- `Suggested next: ${flow.suggestedNext}`,
68
+ text: `Command blocked: ${flow.reason}\n\nFix: ${flow.fix}\n\nSuggested next: ${flow.suggestedNext}`,
97
69
  },
98
70
  ],
99
71
  };
100
72
  }
101
- // 2) Generate files
102
73
  const result = renderFilesForCommand(input);
103
- // 3) MCP output
104
- return {
105
- content: [
106
- {
107
- type: "text",
108
- text: JSON.stringify(result, null, 2),
109
- },
110
- ],
111
- };
74
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
112
75
  });
113
76
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ios-vibe-mcp01",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
4
4
  "description": "MCP server for vibe coding iOS apps with command-based workflow (plan, architecture, coding, uiux, test)",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",