projoflow-mcp-server 1.0.5 → 1.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/index.js +76 -16
- package/package.json +5 -4
package/index.js
CHANGED
|
@@ -8,32 +8,92 @@ import {
|
|
|
8
8
|
} from "@modelcontextprotocol/sdk/types.js";
|
|
9
9
|
import { createClient } from "@supabase/supabase-js";
|
|
10
10
|
|
|
11
|
-
//
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
//
|
|
11
|
+
// =============================================================================
|
|
12
|
+
// CONFIGURATION - Supports two auth methods:
|
|
13
|
+
// 1. API Key (recommended): PROJOFLOW_API_KEY=pf_xxx
|
|
14
|
+
// 2. Email/Password: PROJOFLOW_MCP_EMAIL + PROJOFLOW_MCP_PASSWORD
|
|
15
|
+
// =============================================================================
|
|
16
|
+
|
|
17
|
+
// Supabase config
|
|
18
|
+
const SUPABASE_URL = process.env.PROJOFLOW_SUPABASE_URL || "https://bylvbbadzzznjdrymiyg.supabase.co";
|
|
19
|
+
const SUPABASE_ANON_KEY = process.env.PROJOFLOW_SUPABASE_ANON_KEY || "sb_publishable_gJQ-XaYwsWccrTxWBrQ6nA_nQAf0XDU";
|
|
20
|
+
const SUPABASE_SERVICE_KEY = process.env.PROJOFLOW_SERVICE_KEY;
|
|
21
|
+
|
|
22
|
+
// Auth options
|
|
23
|
+
const API_KEY = process.env.PROJOFLOW_API_KEY;
|
|
16
24
|
const MCP_EMAIL = process.env.PROJOFLOW_MCP_EMAIL || process.env.ZFLOW_MCP_EMAIL;
|
|
17
25
|
const MCP_PASSWORD = process.env.PROJOFLOW_MCP_PASSWORD || process.env.ZFLOW_MCP_PASSWORD;
|
|
18
26
|
|
|
19
|
-
//
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
if (!SUPABASE_ANON_KEY) missing.push("PROJOFLOW_SUPABASE_ANON_KEY");
|
|
23
|
-
if (!MCP_EMAIL) missing.push("PROJOFLOW_MCP_EMAIL");
|
|
24
|
-
if (!MCP_PASSWORD) missing.push("PROJOFLOW_MCP_PASSWORD");
|
|
27
|
+
// Determine auth method
|
|
28
|
+
const useApiKey = !!API_KEY;
|
|
29
|
+
const useEmailPassword = !!(MCP_EMAIL && MCP_PASSWORD);
|
|
25
30
|
|
|
26
|
-
if (
|
|
27
|
-
console.error(`ERROR:
|
|
28
|
-
console.error(
|
|
31
|
+
if (!useApiKey && !useEmailPassword) {
|
|
32
|
+
console.error(`ERROR: Authentication required. Provide ONE of:`);
|
|
33
|
+
console.error(` 1. PROJOFLOW_API_KEY=pf_xxx (recommended - get from ProjoFlow dashboard)`);
|
|
34
|
+
console.error(` 2. PROJOFLOW_MCP_EMAIL + PROJOFLOW_MCP_PASSWORD`);
|
|
29
35
|
process.exit(1);
|
|
30
36
|
}
|
|
31
37
|
|
|
32
|
-
// Create Supabase client
|
|
33
|
-
|
|
38
|
+
// Create Supabase client - use service key for API key validation, anon for email/password
|
|
39
|
+
let supabase;
|
|
40
|
+
let authContext = null; // Will store { user_id, workspace_id } for API key auth
|
|
34
41
|
|
|
35
42
|
// Authenticate on startup
|
|
36
43
|
async function authenticate() {
|
|
44
|
+
if (useApiKey) {
|
|
45
|
+
// API Key auth - validate token and get user context
|
|
46
|
+
console.error(`Authenticating with API key (${API_KEY.substring(0, 12)}...)`);
|
|
47
|
+
|
|
48
|
+
// Need service key to validate tokens
|
|
49
|
+
if (!SUPABASE_SERVICE_KEY) {
|
|
50
|
+
// Fall back to calling an edge function or RPC with anon key
|
|
51
|
+
supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY);
|
|
52
|
+
|
|
53
|
+
// Try to validate via RPC (requires the function to be accessible)
|
|
54
|
+
const { data, error } = await supabase.rpc('validate_mcp_token', { p_token: API_KEY });
|
|
55
|
+
|
|
56
|
+
if (error || !data || data.length === 0) {
|
|
57
|
+
console.error(`API key validation failed: ${error?.message || 'Invalid or expired token'}`);
|
|
58
|
+
process.exit(1);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
authContext = {
|
|
62
|
+
user_id: data[0].user_id,
|
|
63
|
+
workspace_id: data[0].workspace_id,
|
|
64
|
+
token_id: data[0].token_id
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
console.error(`Authenticated via API key for workspace ${authContext.workspace_id}`);
|
|
68
|
+
return authContext;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Use service key for validation
|
|
72
|
+
supabase = createClient(SUPABASE_URL, SUPABASE_SERVICE_KEY);
|
|
73
|
+
|
|
74
|
+
const { data, error } = await supabase.rpc('validate_mcp_token', { p_token: API_KEY });
|
|
75
|
+
|
|
76
|
+
if (error || !data || data.length === 0) {
|
|
77
|
+
console.error(`API key validation failed: ${error?.message || 'Invalid or expired token'}`);
|
|
78
|
+
process.exit(1);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
authContext = {
|
|
82
|
+
user_id: data[0].user_id,
|
|
83
|
+
workspace_id: data[0].workspace_id,
|
|
84
|
+
token_id: data[0].token_id
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
// Update last_used_at
|
|
88
|
+
await supabase.from('mcp_api_tokens').update({ last_used_at: new Date().toISOString() }).eq('id', authContext.token_id);
|
|
89
|
+
|
|
90
|
+
console.error(`Authenticated via API key for workspace ${authContext.workspace_id}`);
|
|
91
|
+
return authContext;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Email/password auth
|
|
95
|
+
supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY);
|
|
96
|
+
|
|
37
97
|
const { data, error } = await supabase.auth.signInWithPassword({
|
|
38
98
|
email: MCP_EMAIL,
|
|
39
99
|
password: MCP_PASSWORD
|
package/package.json
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "projoflow-mcp-server",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "MCP server for
|
|
3
|
+
"version": "1.1.1",
|
|
4
|
+
"description": "MCP server for ProjoFlow project management - connect AI tools to your projects",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"bin": {
|
|
8
|
+
"projoflow-mcp-server": "./index.js",
|
|
8
9
|
"taskflow-mcp": "./index.js"
|
|
9
10
|
},
|
|
10
11
|
"scripts": {
|
|
11
12
|
"start": "node index.js"
|
|
12
13
|
},
|
|
13
|
-
"keywords": ["mcp", "project-management", "
|
|
14
|
-
"author": "
|
|
14
|
+
"keywords": ["mcp", "project-management", "projoflow", "ai", "claude", "cursor"],
|
|
15
|
+
"author": "ProjoFlow",
|
|
15
16
|
"license": "MIT",
|
|
16
17
|
"dependencies": {
|
|
17
18
|
"@modelcontextprotocol/sdk": "^1.0.0",
|