ios-vibe-mcp01 0.1.3 → 0.1.5

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
@@ -1,17 +1,21 @@
1
- #!/usr/bin/env node
2
1
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
2
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
3
  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
4
  async function main() {
5
+ // MCP server metadata (Cursor’da da görünür)
6
+ const server = new McpServer({
7
+ name: "ios-vibe-factory",
8
+ version: "0.1.5",
9
+ });
10
+ // ✅ Tool’ları register et
11
+ registerIosVibeTool(server);
12
+ // ✅ MCP server’ı başlat (Cursor bununla tool listesini alır)
11
13
  const transport = new StdioServerTransport();
12
14
  await server.connect(transport);
15
+ // (opsiyonel) log
16
+ console.log("ios-vibe-mcp01 running (MCP server started)");
13
17
  }
14
18
  main().catch((err) => {
15
- console.error("Fatal MCP server error:", err);
19
+ console.error("Failed to start ios-vibe-mcp01:", 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.3",
3
+ "version": "0.1.5",
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",