wflow-mcp 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,52 @@
1
+ # wflow MCP Server
2
+
3
+ MCP server for AI assistants — extensible tool platform for the wflow ecosystem.
4
+
5
+ ## Quick Start
6
+
7
+ ### 1. Get your API key
8
+
9
+ Ask your team for the `WFLOW_MCP_API_KEY` (matches the `MASTER_KEY` in the wflow Convex ecosystem).
10
+
11
+ ### 2. Add to Claude Code
12
+
13
+ ```bash
14
+ claude mcp add -s user -e WFLOW_MCP_API_KEY=your-secret-key wflow-product-mcp -- npx -y wflow-mcp
15
+ ```
16
+
17
+ That's it. Tools are loaded dynamically from the backend — no config needed.
18
+
19
+ ### 3. Verify
20
+
21
+ ```bash
22
+ claude mcp list
23
+ ```
24
+
25
+ You should see `wflow-product-mcp` in the list.
26
+
27
+ ## Available Tools
28
+
29
+ Tools are fetched dynamically from the backend at startup. Currently available:
30
+
31
+ ### `productboard_check_existence`
32
+
33
+ Semantic duplicate search across features, insights, tasks, and bugs. Uses vector search + LLM validation.
34
+
35
+ **Parameters:**
36
+ - `description` (string) — What you're searching for
37
+ - `type` (enum) — `feature`, `insight`, `jira_task`, or `jira_bug`
38
+
39
+ **Example usage in Claude Code:**
40
+ > "Check if there's already a feature for invoice approval on line items"
41
+
42
+ ## Architecture
43
+
44
+ This package is a thin pass-through client. It contains no business logic or internal API URLs. All tool definitions and routing logic live on the backend — adding new tools requires no package update.
45
+
46
+ ## Development
47
+
48
+ ```bash
49
+ git clone https://github.com/wflowcom/product_mcp.git
50
+ cd product_mcp/mcp-server
51
+ npm install && npm run build
52
+ ```
package/dist/auth.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Authentication for the MCP server.
3
+ * Validates WFLOW_MCP_API_KEY env var on startup.
4
+ * Also used as Authorization header when calling Convex HTTP Actions.
5
+ */
6
+ export declare function getApiKey(): string;
package/dist/auth.js ADDED
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Authentication for the MCP server.
3
+ * Validates WFLOW_MCP_API_KEY env var on startup.
4
+ * Also used as Authorization header when calling Convex HTTP Actions.
5
+ */
6
+ export function getApiKey() {
7
+ const key = process.env.WFLOW_MCP_API_KEY;
8
+ if (!key) {
9
+ console.error("ERROR: WFLOW_MCP_API_KEY environment variable is required.\n" +
10
+ "Set it before running the MCP server:\n" +
11
+ ' export WFLOW_MCP_API_KEY="your-secret-key"');
12
+ process.exit(1);
13
+ }
14
+ return key;
15
+ }
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Thin gateway client — communicates with the product_mcp Convex backend.
3
+ * The MCP client only knows this one URL; all routing happens server-side.
4
+ */
5
+ export interface ToolDefinition {
6
+ name: string;
7
+ description: string;
8
+ inputSchema: Record<string, unknown>;
9
+ }
10
+ interface InvokeResult {
11
+ content: Array<{
12
+ type: string;
13
+ text: string;
14
+ }>;
15
+ }
16
+ /**
17
+ * Fetch available tool definitions from the gateway.
18
+ */
19
+ export declare function fetchTools(gatewayUrl: string): Promise<ToolDefinition[]>;
20
+ /**
21
+ * Invoke a tool on the gateway.
22
+ */
23
+ export declare function invokeTool(gatewayUrl: string, apiKey: string, toolName: string, args: Record<string, unknown>): Promise<InvokeResult>;
24
+ export {};
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Thin gateway client — communicates with the product_mcp Convex backend.
3
+ * The MCP client only knows this one URL; all routing happens server-side.
4
+ */
5
+ /**
6
+ * Fetch available tool definitions from the gateway.
7
+ */
8
+ export async function fetchTools(gatewayUrl) {
9
+ const response = await fetch(`${gatewayUrl}/api/mcp/tools`, {
10
+ method: "GET",
11
+ headers: { "Content-Type": "application/json" },
12
+ });
13
+ if (!response.ok) {
14
+ throw new Error(`Gateway returned ${response.status} ${response.statusText}`);
15
+ }
16
+ const result = await response.json();
17
+ if (!result.success || !Array.isArray(result.data)) {
18
+ throw new Error(result.error || "Invalid response from gateway");
19
+ }
20
+ return result.data;
21
+ }
22
+ /**
23
+ * Invoke a tool on the gateway.
24
+ */
25
+ export async function invokeTool(gatewayUrl, apiKey, toolName, args) {
26
+ const response = await fetch(`${gatewayUrl}/api/mcp/invoke`, {
27
+ method: "POST",
28
+ headers: {
29
+ "Content-Type": "application/json",
30
+ Authorization: apiKey,
31
+ },
32
+ body: JSON.stringify({ tool: toolName, arguments: args }),
33
+ });
34
+ if (!response.ok) {
35
+ throw new Error(`Gateway returned ${response.status} ${response.statusText}`);
36
+ }
37
+ const result = await response.json();
38
+ if (!result.content) {
39
+ throw new Error(result.error || "Unknown error from gateway");
40
+ }
41
+ return { content: result.content };
42
+ }
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * wflow MCP server — thin pass-through client.
4
+ *
5
+ * Fetches tool definitions from the Convex gateway at startup,
6
+ * registers them dynamically, and forwards all invocations.
7
+ * Contains no business logic or internal API URLs.
8
+ */
9
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,65 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * wflow MCP server — thin pass-through client.
4
+ *
5
+ * Fetches tool definitions from the Convex gateway at startup,
6
+ * registers them dynamically, and forwards all invocations.
7
+ * Contains no business logic or internal API URLs.
8
+ */
9
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
10
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
11
+ import { ListToolsRequestSchema, CallToolRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
12
+ import { getApiKey } from "./auth.js";
13
+ import { fetchTools, invokeTool, } from "./gateway.js";
14
+ const GATEWAY_URL = "https://zealous-rhinoceros-886.eu-west-1.convex.site";
15
+ const apiKey = getApiKey();
16
+ // Fetch tool definitions from the gateway at startup
17
+ let tools = [];
18
+ try {
19
+ tools = await fetchTools(GATEWAY_URL);
20
+ }
21
+ catch (error) {
22
+ // stderr only — stdout is reserved for MCP protocol
23
+ console.error(`Warning: Failed to fetch tools from gateway: ${error instanceof Error ? error.message : String(error)}`);
24
+ console.error("MCP server starting with no tools available.");
25
+ }
26
+ const server = new Server({ name: "wflow-mcp", version: "1.1.0" }, { capabilities: { tools: { listChanged: false } } });
27
+ // tools/list — return definitions fetched from gateway
28
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({
29
+ tools: tools.map((t) => ({
30
+ name: t.name,
31
+ description: t.description,
32
+ inputSchema: t.inputSchema,
33
+ })),
34
+ }));
35
+ // tools/call — forward invocation to gateway
36
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
37
+ const { name, arguments: args } = request.params;
38
+ const knownTool = tools.find((t) => t.name === name);
39
+ if (!knownTool) {
40
+ return {
41
+ content: [
42
+ { type: "text", text: `Error: Unknown tool "${name}"` },
43
+ ],
44
+ isError: true,
45
+ };
46
+ }
47
+ try {
48
+ const result = await invokeTool(GATEWAY_URL, apiKey, name, args ?? {});
49
+ return { content: result.content };
50
+ }
51
+ catch (error) {
52
+ return {
53
+ content: [
54
+ {
55
+ type: "text",
56
+ text: `Error invoking tool: ${error instanceof Error ? error.message : String(error)}`,
57
+ },
58
+ ],
59
+ isError: true,
60
+ };
61
+ }
62
+ });
63
+ // Start stdio transport
64
+ const transport = new StdioServerTransport();
65
+ await server.connect(transport);
package/package.json ADDED
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "wflow-mcp",
3
+ "version": "1.1.0",
4
+ "description": "wflow MCP server for AI assistants — extensible tool platform",
5
+ "type": "module",
6
+ "bin": {
7
+ "wflow-mcp": "./dist/index.js"
8
+ },
9
+ "files": [
10
+ "dist"
11
+ ],
12
+ "scripts": {
13
+ "build": "tsc",
14
+ "dev": "tsc --watch",
15
+ "start": "node dist/index.js",
16
+ "prepare": "npm run build"
17
+ },
18
+ "dependencies": {
19
+ "@modelcontextprotocol/sdk": "^1.12.1"
20
+ },
21
+ "devDependencies": {
22
+ "@types/node": "^22.15.0",
23
+ "typescript": "^5.9.3"
24
+ },
25
+ "engines": {
26
+ "node": ">=20"
27
+ },
28
+ "publishConfig": {
29
+ "access": "public"
30
+ },
31
+ "private": false
32
+ }