polydev-ai 1.8.63 → 1.8.71
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 +20 -0
- package/mcp/manifest.json +133 -1
- package/mcp/server.js +594 -5
- package/mcp/stdio-wrapper.js +55 -15
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -24,6 +24,26 @@ Get insights from GPT 5.2, Claude Opus 4.5, Gemini 3, and Grok 4.1 — all throu
|
|
|
24
24
|
|
|
25
25
|
---
|
|
26
26
|
|
|
27
|
+
## 🔑 Key Advantage: Use Your Existing Subscriptions
|
|
28
|
+
|
|
29
|
+
**Already paying for ChatGPT Plus, Claude Pro, or Gemini Advanced?** Use those subscriptions directly through your CLI tools — no API keys needed.
|
|
30
|
+
|
|
31
|
+
| Subscription | CLI Tool | How to Use |
|
|
32
|
+
|--------------|----------|------------|
|
|
33
|
+
| Claude Pro ($20/mo) | Claude Code | `claude login` with your Anthropic account |
|
|
34
|
+
| ChatGPT Plus ($20/mo) | Codex CLI | `codex login` with your OpenAI account |
|
|
35
|
+
| Gemini Advanced ($20/mo) | Gemini CLI | `gemini login` with your Google account |
|
|
36
|
+
|
|
37
|
+
**How it works:**
|
|
38
|
+
1. Login to your CLI tool with your subscription account (no API keys!)
|
|
39
|
+
2. Add Polydev as an MCP server to your CLI
|
|
40
|
+
3. Polydev queries models through your authenticated CLI sessions
|
|
41
|
+
4. Your subscription quota is used — no extra costs
|
|
42
|
+
|
|
43
|
+
**No API keys. No double-paying.** Your existing subscriptions just work.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
27
47
|
## Quick Start
|
|
28
48
|
|
|
29
49
|
### 1. Get your free API token
|
package/mcp/manifest.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "polydev-perspectives",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "Multi-model AI perspectives - query GPT 5.2, Claude Opus 4.5, Gemini 3, and Grok 4.1 simultaneously. Get diverse perspectives when stuck or need enhanced reasoning. Achieved 74.6% on SWE-bench Verified.",
|
|
5
5
|
"author": "Polydev AI",
|
|
6
6
|
"license": "MIT",
|
|
@@ -12,6 +12,138 @@
|
|
|
12
12
|
"prompts": false
|
|
13
13
|
},
|
|
14
14
|
"tools": [
|
|
15
|
+
{
|
|
16
|
+
"name": "get_auth_status",
|
|
17
|
+
"description": "Check Polydev authentication status and get setup instructions. Use this first to verify your token is valid or get help setting up Polydev. Works in all IDEs (Claude Desktop, Cursor, Continue, Windsurf, VSCode, etc.).",
|
|
18
|
+
"inputSchema": {
|
|
19
|
+
"type": "object",
|
|
20
|
+
"properties": {
|
|
21
|
+
"user_token": {
|
|
22
|
+
"type": "string",
|
|
23
|
+
"description": "Polydev user authentication token (optional - checks if provided, shows setup instructions if not)"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"outputSchema": {
|
|
28
|
+
"type": "object",
|
|
29
|
+
"properties": {
|
|
30
|
+
"authenticated": {
|
|
31
|
+
"type": "boolean",
|
|
32
|
+
"description": "Whether the user is authenticated"
|
|
33
|
+
},
|
|
34
|
+
"user_email": {
|
|
35
|
+
"type": "string",
|
|
36
|
+
"description": "User email if authenticated"
|
|
37
|
+
},
|
|
38
|
+
"credits_remaining": {
|
|
39
|
+
"type": "integer",
|
|
40
|
+
"description": "Credits remaining if authenticated"
|
|
41
|
+
},
|
|
42
|
+
"subscription_tier": {
|
|
43
|
+
"type": "string",
|
|
44
|
+
"description": "Current subscription tier"
|
|
45
|
+
},
|
|
46
|
+
"setup_instructions": {
|
|
47
|
+
"type": "object",
|
|
48
|
+
"description": "Setup instructions if not authenticated"
|
|
49
|
+
},
|
|
50
|
+
"message": {
|
|
51
|
+
"type": "string",
|
|
52
|
+
"description": "Human-readable status message"
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
"examples": [
|
|
57
|
+
{
|
|
58
|
+
"description": "Check auth status without token",
|
|
59
|
+
"input": {},
|
|
60
|
+
"output": {
|
|
61
|
+
"authenticated": false,
|
|
62
|
+
"setup_instructions": {
|
|
63
|
+
"step_1": "Visit https://polydev.ai to create your free account",
|
|
64
|
+
"step_2": "Go to https://polydev.ai/dashboard/mcp-tools",
|
|
65
|
+
"step_3": "Generate your MCP access token",
|
|
66
|
+
"step_4": "Add the token to your IDE configuration"
|
|
67
|
+
},
|
|
68
|
+
"message": "Welcome to Polydev! Get started in 2 minutes."
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
"description": "Check auth status with valid token",
|
|
73
|
+
"input": { "user_token": "polydev_abc123..." },
|
|
74
|
+
"output": {
|
|
75
|
+
"authenticated": true,
|
|
76
|
+
"user_email": "user@example.com",
|
|
77
|
+
"credits_remaining": 9500,
|
|
78
|
+
"subscription_tier": "Premium",
|
|
79
|
+
"message": "Ready to use Polydev! You have 9,500 credits remaining."
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
]
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
"name": "login",
|
|
86
|
+
"description": "Authenticate with Polydev by opening your browser. Automatically configures your MCP token after successful login. Use this for a seamless signup/login experience - no manual token copying required.",
|
|
87
|
+
"inputSchema": {
|
|
88
|
+
"type": "object",
|
|
89
|
+
"properties": {
|
|
90
|
+
"open_browser": {
|
|
91
|
+
"type": "boolean",
|
|
92
|
+
"description": "Whether to automatically open the browser (default: true)",
|
|
93
|
+
"default": true
|
|
94
|
+
},
|
|
95
|
+
"timeout_seconds": {
|
|
96
|
+
"type": "integer",
|
|
97
|
+
"description": "How long to wait for authentication (default: 300 = 5 minutes)",
|
|
98
|
+
"minimum": 30,
|
|
99
|
+
"maximum": 600,
|
|
100
|
+
"default": 300
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
"outputSchema": {
|
|
105
|
+
"type": "object",
|
|
106
|
+
"properties": {
|
|
107
|
+
"success": {
|
|
108
|
+
"type": "boolean",
|
|
109
|
+
"description": "Whether authentication was successful"
|
|
110
|
+
},
|
|
111
|
+
"user_email": {
|
|
112
|
+
"type": "string",
|
|
113
|
+
"description": "Authenticated user's email"
|
|
114
|
+
},
|
|
115
|
+
"token": {
|
|
116
|
+
"type": "string",
|
|
117
|
+
"description": "MCP access token (save this for future use)"
|
|
118
|
+
},
|
|
119
|
+
"credits_remaining": {
|
|
120
|
+
"type": "integer",
|
|
121
|
+
"description": "Available credits"
|
|
122
|
+
},
|
|
123
|
+
"message": {
|
|
124
|
+
"type": "string",
|
|
125
|
+
"description": "Human-readable status message"
|
|
126
|
+
},
|
|
127
|
+
"auth_url": {
|
|
128
|
+
"type": "string",
|
|
129
|
+
"description": "URL to open if browser didn't open automatically"
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
},
|
|
133
|
+
"examples": [
|
|
134
|
+
{
|
|
135
|
+
"description": "Login with browser auto-open",
|
|
136
|
+
"input": {},
|
|
137
|
+
"output": {
|
|
138
|
+
"success": true,
|
|
139
|
+
"user_email": "user@example.com",
|
|
140
|
+
"token": "polydev_abc123...",
|
|
141
|
+
"credits_remaining": 500,
|
|
142
|
+
"message": "Successfully authenticated! Token has been saved."
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
]
|
|
146
|
+
},
|
|
15
147
|
{
|
|
16
148
|
"name": "get_perspectives",
|
|
17
149
|
"description": "When stuck in agentic workflows, get diverse perspectives from multiple LLMs to overcome roadblocks. All models use Polydev-managed API keys - just configure once in dashboard.",
|
package/mcp/server.js
CHANGED
|
@@ -145,6 +145,14 @@ class MCPServer {
|
|
|
145
145
|
let result;
|
|
146
146
|
|
|
147
147
|
switch (name) {
|
|
148
|
+
case 'get_auth_status':
|
|
149
|
+
result = await this.getAuthStatus(args);
|
|
150
|
+
break;
|
|
151
|
+
|
|
152
|
+
case 'login':
|
|
153
|
+
result = await this.login(args);
|
|
154
|
+
break;
|
|
155
|
+
|
|
148
156
|
case 'get_perspectives':
|
|
149
157
|
result = await this.callPerspectivesAPI(args);
|
|
150
158
|
break;
|
|
@@ -262,10 +270,31 @@ class MCPServer {
|
|
|
262
270
|
console.error(`[Polydev MCP] Debug - final userToken: ${userToken ? 'present' : 'missing'}`);
|
|
263
271
|
|
|
264
272
|
if (!userToken || typeof userToken !== 'string') {
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
273
|
+
// Return helpful setup instructions instead of just throwing an error
|
|
274
|
+
const detectedIDE = this.detectIDE();
|
|
275
|
+
const setupInstructions = this.getSetupInstructions(detectedIDE);
|
|
276
|
+
|
|
277
|
+
throw new Error(
|
|
278
|
+
'═══════════════════════════════════════════════════════════════\n' +
|
|
279
|
+
' POLYDEV SETUP REQUIRED\n' +
|
|
280
|
+
'═══════════════════════════════════════════════════════════════\n\n' +
|
|
281
|
+
'To use Polydev, you need an authentication token.\n\n' +
|
|
282
|
+
'QUICK SETUP (2 minutes):\n' +
|
|
283
|
+
'1. Create free account: https://polydev.ai/signup\n' +
|
|
284
|
+
'2. Get your token: https://polydev.ai/dashboard/mcp-tools\n' +
|
|
285
|
+
'3. Add token to your MCP configuration\n\n' +
|
|
286
|
+
'FREE TIER INCLUDES:\n' +
|
|
287
|
+
'• 500 credits/month (no credit card needed)\n' +
|
|
288
|
+
'• Access to GLM-4.7, Gemini 3 Flash, Grok 4.1, GPT-5 Mini\n' +
|
|
289
|
+
'• 1 credit per request (all models)\n\n' +
|
|
290
|
+
'CONFIGURATION:\n' +
|
|
291
|
+
'Set POLYDEV_USER_TOKEN in your MCP server env, or\n' +
|
|
292
|
+
'Pass user_token parameter with each request.\n\n' +
|
|
293
|
+
'NEED HELP?\n' +
|
|
294
|
+
'• Setup guide: https://polydev.ai/docs/mcp-integration\n' +
|
|
295
|
+
'• Use get_auth_status tool for personalized instructions\n' +
|
|
296
|
+
'═══════════════════════════════════════════════════════════════'
|
|
297
|
+
);
|
|
269
298
|
}
|
|
270
299
|
|
|
271
300
|
console.error(`[Polydev MCP] Getting perspectives for: "${args.prompt.substring(0, 60)}${args.prompt.length > 60 ? '...' : ''}"`);
|
|
@@ -307,7 +336,24 @@ class MCPServer {
|
|
|
307
336
|
}
|
|
308
337
|
|
|
309
338
|
if (response.status === 401) {
|
|
310
|
-
throw new Error(
|
|
339
|
+
throw new Error(
|
|
340
|
+
'═══════════════════════════════════════════════════════════════\n' +
|
|
341
|
+
' AUTHENTICATION FAILED\n' +
|
|
342
|
+
'═══════════════════════════════════════════════════════════════\n\n' +
|
|
343
|
+
`Error: ${errorMessage}\n\n` +
|
|
344
|
+
'YOUR TOKEN MAY BE:\n' +
|
|
345
|
+
'• Expired (tokens last 30 days)\n' +
|
|
346
|
+
'• Invalid or mistyped\n' +
|
|
347
|
+
'• From a different account\n\n' +
|
|
348
|
+
'TO FIX:\n' +
|
|
349
|
+
'1. Go to: https://polydev.ai/dashboard/mcp-tools\n' +
|
|
350
|
+
'2. Generate a new token\n' +
|
|
351
|
+
'3. Update your MCP configuration\n\n' +
|
|
352
|
+
'QUICK CHECK:\n' +
|
|
353
|
+
'• Use get_auth_status tool to verify your setup\n' +
|
|
354
|
+
'• Token should start with "polydev_"\n' +
|
|
355
|
+
'═══════════════════════════════════════════════════════════════'
|
|
356
|
+
);
|
|
311
357
|
}
|
|
312
358
|
|
|
313
359
|
throw new Error(`Polydev API error: ${errorMessage}`);
|
|
@@ -328,8 +374,551 @@ class MCPServer {
|
|
|
328
374
|
return result;
|
|
329
375
|
}
|
|
330
376
|
|
|
377
|
+
/**
|
|
378
|
+
* Get authentication status and setup instructions
|
|
379
|
+
* Works universally across all IDEs (Claude Desktop, Cursor, Continue, Windsurf, VSCode, etc.)
|
|
380
|
+
*/
|
|
381
|
+
async getAuthStatus(args) {
|
|
382
|
+
const serverUrl = 'https://www.polydev.ai/api/mcp/auth-status';
|
|
383
|
+
const userToken = args.user_token || process.env.POLYDEV_USER_TOKEN;
|
|
384
|
+
|
|
385
|
+
console.error('[Polydev MCP] Checking authentication status...');
|
|
386
|
+
|
|
387
|
+
// Detect IDE from environment
|
|
388
|
+
const detectedIDE = this.detectIDE();
|
|
389
|
+
|
|
390
|
+
// If no token provided, return setup instructions
|
|
391
|
+
if (!userToken) {
|
|
392
|
+
return {
|
|
393
|
+
authenticated: false,
|
|
394
|
+
detected_ide: detectedIDE,
|
|
395
|
+
setup_instructions: this.getSetupInstructions(detectedIDE),
|
|
396
|
+
quick_links: {
|
|
397
|
+
signup: 'https://polydev.ai/signup',
|
|
398
|
+
login: 'https://polydev.ai/login',
|
|
399
|
+
dashboard: 'https://polydev.ai/dashboard',
|
|
400
|
+
mcp_tools: 'https://polydev.ai/dashboard/mcp-tools',
|
|
401
|
+
documentation: 'https://polydev.ai/docs/mcp-integration'
|
|
402
|
+
},
|
|
403
|
+
available_models: ['GLM-4.7', 'Gemini 3 Flash', 'Grok 4.1 Fast Reasoning', 'GPT-5 Mini'],
|
|
404
|
+
pricing: {
|
|
405
|
+
free_tier: '500 credits/month (no credit card required)',
|
|
406
|
+
premium_tier: '$10/month for 10,000 credits',
|
|
407
|
+
credit_cost: '1 credit per request (all models)'
|
|
408
|
+
},
|
|
409
|
+
message: 'Welcome to Polydev! Create your free account to get started.',
|
|
410
|
+
timestamp: new Date().toISOString()
|
|
411
|
+
};
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
// Validate token with the server
|
|
415
|
+
try {
|
|
416
|
+
const response = await fetch(serverUrl, {
|
|
417
|
+
method: 'POST',
|
|
418
|
+
headers: {
|
|
419
|
+
'Content-Type': 'application/json',
|
|
420
|
+
'Authorization': `Bearer ${userToken}`,
|
|
421
|
+
'User-Agent': 'polydev-mcp/1.4.0'
|
|
422
|
+
},
|
|
423
|
+
body: JSON.stringify({ action: 'check_status' })
|
|
424
|
+
});
|
|
425
|
+
|
|
426
|
+
if (response.ok) {
|
|
427
|
+
const data = await response.json();
|
|
428
|
+
return {
|
|
429
|
+
authenticated: true,
|
|
430
|
+
user_email: data.email,
|
|
431
|
+
credits_remaining: data.credits_remaining,
|
|
432
|
+
credits_used_today: data.credits_used_today || 0,
|
|
433
|
+
subscription_tier: data.subscription_tier || 'Free',
|
|
434
|
+
token_expires_at: data.token_expires_at,
|
|
435
|
+
enabled_models: data.enabled_models || ['GLM-4.7', 'Gemini 3 Flash', 'Grok 4.1 Fast Reasoning', 'GPT-5 Mini'],
|
|
436
|
+
cli_subscriptions: data.cli_subscriptions || [],
|
|
437
|
+
quick_links: {
|
|
438
|
+
dashboard: 'https://polydev.ai/dashboard',
|
|
439
|
+
usage: 'https://polydev.ai/dashboard/usage',
|
|
440
|
+
settings: 'https://polydev.ai/dashboard/settings',
|
|
441
|
+
upgrade: 'https://polydev.ai/dashboard/subscription'
|
|
442
|
+
},
|
|
443
|
+
message: `Ready to use Polydev! You have ${data.credits_remaining?.toLocaleString() || 0} credits remaining.`,
|
|
444
|
+
timestamp: new Date().toISOString()
|
|
445
|
+
};
|
|
446
|
+
} else if (response.status === 401) {
|
|
447
|
+
return {
|
|
448
|
+
authenticated: false,
|
|
449
|
+
error: 'invalid_token',
|
|
450
|
+
detected_ide: detectedIDE,
|
|
451
|
+
setup_instructions: this.getSetupInstructions(detectedIDE),
|
|
452
|
+
quick_links: {
|
|
453
|
+
regenerate_token: 'https://polydev.ai/dashboard/mcp-tools',
|
|
454
|
+
login: 'https://polydev.ai/login'
|
|
455
|
+
},
|
|
456
|
+
message: 'Your token is invalid or expired. Please generate a new one.',
|
|
457
|
+
timestamp: new Date().toISOString()
|
|
458
|
+
};
|
|
459
|
+
} else {
|
|
460
|
+
const errorText = await response.text();
|
|
461
|
+
return {
|
|
462
|
+
authenticated: false,
|
|
463
|
+
error: 'server_error',
|
|
464
|
+
error_details: errorText,
|
|
465
|
+
message: 'Unable to verify authentication. Please try again.',
|
|
466
|
+
timestamp: new Date().toISOString()
|
|
467
|
+
};
|
|
468
|
+
}
|
|
469
|
+
} catch (error) {
|
|
470
|
+
console.error('[Polydev MCP] Auth status check error:', error);
|
|
471
|
+
return {
|
|
472
|
+
authenticated: false,
|
|
473
|
+
error: 'connection_error',
|
|
474
|
+
error_details: error.message,
|
|
475
|
+
offline_mode: true,
|
|
476
|
+
message: 'Unable to connect to Polydev servers. Check your internet connection.',
|
|
477
|
+
timestamp: new Date().toISOString()
|
|
478
|
+
};
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
/**
|
|
483
|
+
* Detect the IDE/MCP client from environment
|
|
484
|
+
*/
|
|
485
|
+
detectIDE() {
|
|
486
|
+
// Check common environment variables and process info
|
|
487
|
+
const env = process.env;
|
|
488
|
+
|
|
489
|
+
if (env.CURSOR_CHANNEL || env.CURSOR_VERSION) return 'cursor';
|
|
490
|
+
if (env.CONTINUE_EXTENSION_ID) return 'continue';
|
|
491
|
+
if (env.VSCODE_PID || env.VSCODE_CWD) return 'vscode';
|
|
492
|
+
if (env.CLAUDE_DESKTOP) return 'claude-desktop';
|
|
493
|
+
if (env.WINDSURF_VERSION) return 'windsurf';
|
|
494
|
+
if (env.CLINE_VERSION) return 'cline';
|
|
495
|
+
|
|
496
|
+
// Check process title/args for hints
|
|
497
|
+
const processTitle = process.title || '';
|
|
498
|
+
const args = process.argv.join(' ').toLowerCase();
|
|
499
|
+
|
|
500
|
+
if (args.includes('cursor') || processTitle.includes('cursor')) return 'cursor';
|
|
501
|
+
if (args.includes('claude') || processTitle.includes('claude')) return 'claude-desktop';
|
|
502
|
+
if (args.includes('continue')) return 'continue';
|
|
503
|
+
if (args.includes('windsurf')) return 'windsurf';
|
|
504
|
+
|
|
505
|
+
return 'unknown';
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
/**
|
|
509
|
+
* Get IDE-specific setup instructions
|
|
510
|
+
*/
|
|
511
|
+
getSetupInstructions(ide) {
|
|
512
|
+
const baseSteps = {
|
|
513
|
+
step_1: 'Create your free Polydev account at https://polydev.ai/signup',
|
|
514
|
+
step_2: 'Go to https://polydev.ai/dashboard/mcp-tools',
|
|
515
|
+
step_3: 'Click "Generate Token" to create your MCP access token',
|
|
516
|
+
step_4: 'Copy the token (it starts with "polydev_")'
|
|
517
|
+
};
|
|
518
|
+
|
|
519
|
+
const ideConfigs = {
|
|
520
|
+
'cursor': {
|
|
521
|
+
...baseSteps,
|
|
522
|
+
step_5: 'Open Cursor Settings (Cmd/Ctrl + ,)',
|
|
523
|
+
step_6: 'Search for "MCP" in settings',
|
|
524
|
+
step_7: 'Add Polydev server with your token',
|
|
525
|
+
config_example: `{
|
|
526
|
+
"mcpServers": {
|
|
527
|
+
"polydev": {
|
|
528
|
+
"command": "npx",
|
|
529
|
+
"args": ["-y", "polydev-mcp"],
|
|
530
|
+
"env": { "POLYDEV_USER_TOKEN": "polydev_your_token_here" }
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
}`
|
|
534
|
+
},
|
|
535
|
+
'claude-desktop': {
|
|
536
|
+
...baseSteps,
|
|
537
|
+
step_5: 'Open Claude Desktop settings',
|
|
538
|
+
step_6: 'Navigate to Developer > MCP Servers',
|
|
539
|
+
step_7: 'Add the Polydev server configuration',
|
|
540
|
+
config_example: `{
|
|
541
|
+
"mcpServers": {
|
|
542
|
+
"polydev": {
|
|
543
|
+
"command": "npx",
|
|
544
|
+
"args": ["-y", "polydev-mcp"],
|
|
545
|
+
"env": { "POLYDEV_USER_TOKEN": "polydev_your_token_here" }
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
}`
|
|
549
|
+
},
|
|
550
|
+
'continue': {
|
|
551
|
+
...baseSteps,
|
|
552
|
+
step_5: 'Open Continue extension settings in VSCode',
|
|
553
|
+
step_6: 'Add Polydev to your config.json',
|
|
554
|
+
config_example: `{
|
|
555
|
+
"mcpServers": [{
|
|
556
|
+
"name": "polydev",
|
|
557
|
+
"command": "npx",
|
|
558
|
+
"args": ["-y", "polydev-mcp"],
|
|
559
|
+
"env": { "POLYDEV_USER_TOKEN": "polydev_your_token_here" }
|
|
560
|
+
}]
|
|
561
|
+
}`
|
|
562
|
+
},
|
|
563
|
+
'windsurf': {
|
|
564
|
+
...baseSteps,
|
|
565
|
+
step_5: 'Open Windsurf Settings',
|
|
566
|
+
step_6: 'Navigate to MCP Configuration',
|
|
567
|
+
step_7: 'Add Polydev server with your token',
|
|
568
|
+
config_example: `{
|
|
569
|
+
"mcp": {
|
|
570
|
+
"servers": {
|
|
571
|
+
"polydev": {
|
|
572
|
+
"command": "npx",
|
|
573
|
+
"args": ["-y", "polydev-mcp"],
|
|
574
|
+
"env": { "POLYDEV_USER_TOKEN": "polydev_your_token_here" }
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
}`
|
|
579
|
+
},
|
|
580
|
+
'vscode': {
|
|
581
|
+
...baseSteps,
|
|
582
|
+
step_5: 'Install an MCP-compatible extension (Continue, Cline, etc.)',
|
|
583
|
+
step_6: 'Configure the extension with Polydev',
|
|
584
|
+
step_7: 'Add your token to the configuration'
|
|
585
|
+
},
|
|
586
|
+
'unknown': {
|
|
587
|
+
...baseSteps,
|
|
588
|
+
step_5: 'Configure your MCP client with the Polydev server',
|
|
589
|
+
step_6: 'Set POLYDEV_USER_TOKEN environment variable with your token',
|
|
590
|
+
note: 'Visit https://polydev.ai/docs/mcp-integration for detailed setup guides'
|
|
591
|
+
}
|
|
592
|
+
};
|
|
593
|
+
|
|
594
|
+
return ideConfigs[ide] || ideConfigs['unknown'];
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
/**
|
|
598
|
+
* Format authentication status response for beautiful output
|
|
599
|
+
*/
|
|
600
|
+
formatAuthStatusResponse(result) {
|
|
601
|
+
let formatted = '';
|
|
602
|
+
|
|
603
|
+
if (result.authenticated) {
|
|
604
|
+
formatted += `# Polydev Authentication Status\n\n`;
|
|
605
|
+
formatted += `## Account\n`;
|
|
606
|
+
formatted += `Email: ${result.user_email}\n`;
|
|
607
|
+
formatted += `Tier: ${result.subscription_tier}\n\n`;
|
|
608
|
+
|
|
609
|
+
formatted += `## Credits\n`;
|
|
610
|
+
formatted += `Remaining: ${result.credits_remaining?.toLocaleString() || 0}\n`;
|
|
611
|
+
if (result.credits_used_today !== undefined) {
|
|
612
|
+
formatted += `Used Today: ${result.credits_used_today}\n`;
|
|
613
|
+
}
|
|
614
|
+
formatted += `\n`;
|
|
615
|
+
|
|
616
|
+
formatted += `## Available Models (1 credit each)\n`;
|
|
617
|
+
if (result.enabled_models && result.enabled_models.length > 0) {
|
|
618
|
+
result.enabled_models.forEach(model => {
|
|
619
|
+
formatted += `- ${model}\n`;
|
|
620
|
+
});
|
|
621
|
+
}
|
|
622
|
+
formatted += `\n`;
|
|
623
|
+
|
|
624
|
+
if (result.cli_subscriptions && result.cli_subscriptions.length > 0) {
|
|
625
|
+
formatted += `## Connected CLI Subscriptions (no credit cost)\n`;
|
|
626
|
+
result.cli_subscriptions.forEach(cli => {
|
|
627
|
+
formatted += `- ${cli}\n`;
|
|
628
|
+
});
|
|
629
|
+
formatted += `\n`;
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
formatted += `## Quick Links\n`;
|
|
633
|
+
formatted += `- Dashboard: ${result.quick_links.dashboard}\n`;
|
|
634
|
+
formatted += `- Usage History: ${result.quick_links.usage}\n`;
|
|
635
|
+
formatted += `- Settings: ${result.quick_links.settings}\n`;
|
|
636
|
+
|
|
637
|
+
if (result.subscription_tier === 'Free') {
|
|
638
|
+
formatted += `\n## Upgrade to Premium\n`;
|
|
639
|
+
formatted += `Get 10,000 credits/month for $10: ${result.quick_links.upgrade}\n`;
|
|
640
|
+
}
|
|
641
|
+
} else {
|
|
642
|
+
formatted += `# Welcome to Polydev\n\n`;
|
|
643
|
+
formatted += `Multi-model AI that helps when you're stuck. Query GPT-5, Claude, Gemini, and Grok simultaneously.\n\n`;
|
|
644
|
+
|
|
645
|
+
if (result.error === 'invalid_token') {
|
|
646
|
+
formatted += `## Token Issue\n`;
|
|
647
|
+
formatted += `Your token is invalid or expired.\n`;
|
|
648
|
+
formatted += `Generate a new one: ${result.quick_links.regenerate_token}\n\n`;
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
formatted += `## Get Started (Free)\n\n`;
|
|
652
|
+
|
|
653
|
+
if (result.setup_instructions) {
|
|
654
|
+
Object.entries(result.setup_instructions).forEach(([key, value]) => {
|
|
655
|
+
if (key.startsWith('step_')) {
|
|
656
|
+
const stepNum = key.replace('step_', '');
|
|
657
|
+
formatted += `${stepNum}. ${value}\n`;
|
|
658
|
+
}
|
|
659
|
+
});
|
|
660
|
+
|
|
661
|
+
if (result.setup_instructions.config_example) {
|
|
662
|
+
formatted += `\n## Configuration Example\n`;
|
|
663
|
+
formatted += `\`\`\`json\n${result.setup_instructions.config_example}\n\`\`\`\n`;
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
if (result.setup_instructions.note) {
|
|
667
|
+
formatted += `\nNote: ${result.setup_instructions.note}\n`;
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
formatted += `\n## Pricing\n`;
|
|
672
|
+
if (result.pricing) {
|
|
673
|
+
formatted += `- Free Tier: ${result.pricing.free_tier}\n`;
|
|
674
|
+
formatted += `- Premium: ${result.pricing.premium_tier}\n`;
|
|
675
|
+
formatted += `- Cost: ${result.pricing.credit_cost}\n`;
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
formatted += `\n## Available Models\n`;
|
|
679
|
+
if (result.available_models) {
|
|
680
|
+
result.available_models.forEach(model => {
|
|
681
|
+
formatted += `- ${model}\n`;
|
|
682
|
+
});
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
if (result.detected_ide && result.detected_ide !== 'unknown') {
|
|
686
|
+
formatted += `\n## Detected IDE\n`;
|
|
687
|
+
formatted += `${result.detected_ide.charAt(0).toUpperCase() + result.detected_ide.slice(1)}\n`;
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
return formatted;
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
/**
|
|
695
|
+
* Browser-based login with automatic token retrieval
|
|
696
|
+
* Implements OAuth Device Authorization Grant (RFC 8628)
|
|
697
|
+
*/
|
|
698
|
+
async login(args) {
|
|
699
|
+
const { open_browser = true, timeout_seconds = 300 } = args;
|
|
700
|
+
const deviceAuthUrl = 'https://www.polydev.ai/api/mcp/device-auth';
|
|
701
|
+
|
|
702
|
+
console.error('[Polydev MCP] Initiating browser-based login...');
|
|
703
|
+
|
|
704
|
+
try {
|
|
705
|
+
// Step 1: Request device code from server
|
|
706
|
+
const initResponse = await fetch(deviceAuthUrl, {
|
|
707
|
+
method: 'POST',
|
|
708
|
+
headers: {
|
|
709
|
+
'Content-Type': 'application/json',
|
|
710
|
+
'User-Agent': 'polydev-mcp/1.4.0'
|
|
711
|
+
},
|
|
712
|
+
body: JSON.stringify({ action: 'init' })
|
|
713
|
+
});
|
|
714
|
+
|
|
715
|
+
if (!initResponse.ok) {
|
|
716
|
+
const errorText = await initResponse.text();
|
|
717
|
+
throw new Error(`Failed to initiate login: ${errorText}`);
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
const deviceData = await initResponse.json();
|
|
721
|
+
const { device_code, user_code, verification_url, expires_in, interval } = deviceData;
|
|
722
|
+
|
|
723
|
+
console.error(`[Polydev MCP] Device code obtained. User code: ${user_code}`);
|
|
724
|
+
console.error(`[Polydev MCP] Verification URL: ${verification_url}`);
|
|
725
|
+
|
|
726
|
+
// Step 2: Open browser if requested
|
|
727
|
+
if (open_browser) {
|
|
728
|
+
const browserOpened = await this.openBrowser(verification_url);
|
|
729
|
+
if (!browserOpened) {
|
|
730
|
+
console.error('[Polydev MCP] Could not open browser automatically');
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
// Step 3: Poll for token
|
|
735
|
+
const pollInterval = (interval || 5) * 1000; // Convert to ms
|
|
736
|
+
const maxPollTime = Math.min(timeout_seconds, expires_in || 300) * 1000;
|
|
737
|
+
const startTime = Date.now();
|
|
738
|
+
|
|
739
|
+
console.error(`[Polydev MCP] Polling for token (timeout: ${maxPollTime / 1000}s)...`);
|
|
740
|
+
|
|
741
|
+
while (Date.now() - startTime < maxPollTime) {
|
|
742
|
+
await this.sleep(pollInterval);
|
|
743
|
+
|
|
744
|
+
const pollResponse = await fetch(deviceAuthUrl, {
|
|
745
|
+
method: 'POST',
|
|
746
|
+
headers: {
|
|
747
|
+
'Content-Type': 'application/json',
|
|
748
|
+
'User-Agent': 'polydev-mcp/1.4.0'
|
|
749
|
+
},
|
|
750
|
+
body: JSON.stringify({
|
|
751
|
+
action: 'poll',
|
|
752
|
+
device_code
|
|
753
|
+
})
|
|
754
|
+
});
|
|
755
|
+
|
|
756
|
+
if (pollResponse.ok) {
|
|
757
|
+
const pollData = await pollResponse.json();
|
|
758
|
+
|
|
759
|
+
if (pollData.status === 'completed' && pollData.token) {
|
|
760
|
+
console.error('[Polydev MCP] Authentication successful!');
|
|
761
|
+
|
|
762
|
+
// Store token in environment for this session
|
|
763
|
+
process.env.POLYDEV_USER_TOKEN = pollData.token;
|
|
764
|
+
|
|
765
|
+
return {
|
|
766
|
+
success: true,
|
|
767
|
+
user_email: pollData.email,
|
|
768
|
+
token: pollData.token,
|
|
769
|
+
credits_remaining: pollData.credits_remaining || 500,
|
|
770
|
+
subscription_tier: pollData.subscription_tier || 'Free',
|
|
771
|
+
message: 'Successfully authenticated! Your token has been configured for this session.',
|
|
772
|
+
next_steps: [
|
|
773
|
+
'Your token is now active for this session',
|
|
774
|
+
'Add POLYDEV_USER_TOKEN to your MCP config for persistent access',
|
|
775
|
+
'Use get_perspectives to query multiple AI models'
|
|
776
|
+
],
|
|
777
|
+
timestamp: new Date().toISOString()
|
|
778
|
+
};
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
if (pollData.status === 'pending') {
|
|
782
|
+
console.error('[Polydev MCP] Waiting for user to complete authentication...');
|
|
783
|
+
continue;
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
if (pollData.status === 'expired') {
|
|
787
|
+
throw new Error('Login session expired. Please try again.');
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
if (pollData.error) {
|
|
791
|
+
throw new Error(pollData.error);
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
|
|
796
|
+
// Timeout reached
|
|
797
|
+
return {
|
|
798
|
+
success: false,
|
|
799
|
+
error: 'timeout',
|
|
800
|
+
message: `Login timed out after ${timeout_seconds} seconds. Please try again.`,
|
|
801
|
+
auth_url: verification_url,
|
|
802
|
+
user_code: user_code,
|
|
803
|
+
instructions: 'Open the URL above and enter the user code to complete authentication.',
|
|
804
|
+
timestamp: new Date().toISOString()
|
|
805
|
+
};
|
|
806
|
+
|
|
807
|
+
} catch (error) {
|
|
808
|
+
console.error('[Polydev MCP] Login error:', error);
|
|
809
|
+
return {
|
|
810
|
+
success: false,
|
|
811
|
+
error: error.message,
|
|
812
|
+
message: 'Login failed. Please try again or use manual token setup.',
|
|
813
|
+
manual_setup_url: 'https://polydev.ai/dashboard/mcp-tools',
|
|
814
|
+
timestamp: new Date().toISOString()
|
|
815
|
+
};
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
/**
|
|
820
|
+
* Open browser to a URL (cross-platform)
|
|
821
|
+
*/
|
|
822
|
+
async openBrowser(url) {
|
|
823
|
+
const { exec } = require('child_process');
|
|
824
|
+
const platform = process.platform;
|
|
825
|
+
|
|
826
|
+
let command;
|
|
827
|
+
if (platform === 'darwin') {
|
|
828
|
+
command = `open "${url}"`;
|
|
829
|
+
} else if (platform === 'win32') {
|
|
830
|
+
command = `start "" "${url}"`;
|
|
831
|
+
} else {
|
|
832
|
+
// Linux and others
|
|
833
|
+
command = `xdg-open "${url}" || sensible-browser "${url}" || x-www-browser "${url}"`;
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
return new Promise((resolve) => {
|
|
837
|
+
exec(command, (error) => {
|
|
838
|
+
if (error) {
|
|
839
|
+
console.error('[Polydev MCP] Browser open error:', error.message);
|
|
840
|
+
resolve(false);
|
|
841
|
+
} else {
|
|
842
|
+
console.error('[Polydev MCP] Browser opened successfully');
|
|
843
|
+
resolve(true);
|
|
844
|
+
}
|
|
845
|
+
});
|
|
846
|
+
});
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
/**
|
|
850
|
+
* Sleep utility for polling
|
|
851
|
+
*/
|
|
852
|
+
sleep(ms) {
|
|
853
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
/**
|
|
857
|
+
* Format login response for beautiful output
|
|
858
|
+
*/
|
|
859
|
+
formatLoginResponse(result) {
|
|
860
|
+
let formatted = '';
|
|
861
|
+
|
|
862
|
+
if (result.success) {
|
|
863
|
+
formatted += `# Polydev Login Successful\n\n`;
|
|
864
|
+
formatted += `## Account\n`;
|
|
865
|
+
formatted += `Email: ${result.user_email}\n`;
|
|
866
|
+
formatted += `Tier: ${result.subscription_tier}\n`;
|
|
867
|
+
formatted += `Credits: ${result.credits_remaining?.toLocaleString() || 'N/A'}\n\n`;
|
|
868
|
+
|
|
869
|
+
formatted += `## Token\n`;
|
|
870
|
+
formatted += `\`\`\`\n${result.token}\n\`\`\`\n\n`;
|
|
871
|
+
|
|
872
|
+
formatted += `## Next Steps\n`;
|
|
873
|
+
if (result.next_steps) {
|
|
874
|
+
result.next_steps.forEach((step, i) => {
|
|
875
|
+
formatted += `${i + 1}. ${step}\n`;
|
|
876
|
+
});
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
formatted += `\n## Save Token for Persistent Access\n`;
|
|
880
|
+
formatted += `Add this to your MCP configuration:\n`;
|
|
881
|
+
formatted += `\`\`\`json\n`;
|
|
882
|
+
formatted += `{\n`;
|
|
883
|
+
formatted += ` "env": { "POLYDEV_USER_TOKEN": "${result.token}" }\n`;
|
|
884
|
+
formatted += `}\n`;
|
|
885
|
+
formatted += `\`\`\`\n`;
|
|
886
|
+
} else {
|
|
887
|
+
formatted += `# Polydev Login\n\n`;
|
|
888
|
+
|
|
889
|
+
if (result.error === 'timeout') {
|
|
890
|
+
formatted += `## Timeout\n`;
|
|
891
|
+
formatted += `${result.message}\n\n`;
|
|
892
|
+
|
|
893
|
+
if (result.auth_url) {
|
|
894
|
+
formatted += `## Complete Manually\n`;
|
|
895
|
+
formatted += `1. Open: ${result.auth_url}\n`;
|
|
896
|
+
formatted += `2. Enter code: **${result.user_code}**\n`;
|
|
897
|
+
formatted += `3. Run login again after completing\n`;
|
|
898
|
+
}
|
|
899
|
+
} else {
|
|
900
|
+
formatted += `## Error\n`;
|
|
901
|
+
formatted += `${result.message}\n\n`;
|
|
902
|
+
|
|
903
|
+
if (result.manual_setup_url) {
|
|
904
|
+
formatted += `## Manual Setup\n`;
|
|
905
|
+
formatted += `Visit: ${result.manual_setup_url}\n`;
|
|
906
|
+
formatted += `Generate a token and add it to your MCP configuration.\n`;
|
|
907
|
+
}
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
return formatted;
|
|
912
|
+
}
|
|
913
|
+
|
|
331
914
|
formatResponse(toolName, result) {
|
|
332
915
|
switch (toolName) {
|
|
916
|
+
case 'get_auth_status':
|
|
917
|
+
return this.formatAuthStatusResponse(result);
|
|
918
|
+
|
|
919
|
+
case 'login':
|
|
920
|
+
return this.formatLoginResponse(result);
|
|
921
|
+
|
|
333
922
|
case 'get_perspectives':
|
|
334
923
|
return this.formatPerspectivesResponse(result);
|
|
335
924
|
|
package/mcp/stdio-wrapper.js
CHANGED
|
@@ -1712,25 +1712,65 @@ if (require.main === module) {
|
|
|
1712
1712
|
* This allows Smithery to discover tools/resources without real credentials
|
|
1713
1713
|
*/
|
|
1714
1714
|
function createSandboxServer() {
|
|
1715
|
-
//
|
|
1716
|
-
//
|
|
1717
|
-
const fs = require('fs');
|
|
1718
|
-
const path = require('path');
|
|
1719
|
-
|
|
1720
|
-
const manifestPath = path.join(__dirname, 'manifest.json');
|
|
1721
|
-
const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
|
|
1722
|
-
|
|
1715
|
+
// Embed manifest directly to work with Smithery bundling
|
|
1716
|
+
// (file paths don't resolve in bundled context)
|
|
1723
1717
|
return {
|
|
1724
1718
|
serverInfo: {
|
|
1725
|
-
name:
|
|
1726
|
-
version:
|
|
1719
|
+
name: 'polydev-perspectives',
|
|
1720
|
+
version: '1.8.70'
|
|
1727
1721
|
},
|
|
1728
1722
|
capabilities: { tools: {} },
|
|
1729
|
-
tools:
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1723
|
+
tools: [
|
|
1724
|
+
{
|
|
1725
|
+
name: 'get_perspectives',
|
|
1726
|
+
description: 'Query GPT 5.2, Claude Opus 4.5, Gemini 3, and Grok 4.1 simultaneously for diverse AI perspectives when debugging, making architecture decisions, or reviewing code.',
|
|
1727
|
+
inputSchema: {
|
|
1728
|
+
type: 'object',
|
|
1729
|
+
properties: {
|
|
1730
|
+
prompt: {
|
|
1731
|
+
type: 'string',
|
|
1732
|
+
description: 'The prompt to get perspectives on'
|
|
1733
|
+
},
|
|
1734
|
+
user_token: {
|
|
1735
|
+
type: 'string',
|
|
1736
|
+
description: 'Polydev user authentication token'
|
|
1737
|
+
}
|
|
1738
|
+
},
|
|
1739
|
+
required: ['prompt']
|
|
1740
|
+
}
|
|
1741
|
+
},
|
|
1742
|
+
{
|
|
1743
|
+
name: 'get_cli_status',
|
|
1744
|
+
description: 'Check status of local CLI tools (Claude Code, Codex CLI, Gemini CLI)',
|
|
1745
|
+
inputSchema: {
|
|
1746
|
+
type: 'object',
|
|
1747
|
+
properties: {
|
|
1748
|
+
provider_id: {
|
|
1749
|
+
type: 'string',
|
|
1750
|
+
description: 'Optional specific provider to check'
|
|
1751
|
+
}
|
|
1752
|
+
}
|
|
1753
|
+
}
|
|
1754
|
+
},
|
|
1755
|
+
{
|
|
1756
|
+
name: 'force_cli_detection',
|
|
1757
|
+
description: 'Force re-detection of installed local CLI tools',
|
|
1758
|
+
inputSchema: { type: 'object', properties: {} }
|
|
1759
|
+
},
|
|
1760
|
+
{
|
|
1761
|
+
name: 'send_cli_prompt',
|
|
1762
|
+
description: 'Send prompt to local CLI with perspectives fallback',
|
|
1763
|
+
inputSchema: {
|
|
1764
|
+
type: 'object',
|
|
1765
|
+
properties: {
|
|
1766
|
+
provider_id: { type: 'string', description: 'CLI provider ID' },
|
|
1767
|
+
prompt: { type: 'string', description: 'Prompt to send' },
|
|
1768
|
+
mode: { type: 'string', enum: ['args', 'stdin'], default: 'args' }
|
|
1769
|
+
},
|
|
1770
|
+
required: ['provider_id', 'prompt']
|
|
1771
|
+
}
|
|
1772
|
+
}
|
|
1773
|
+
]
|
|
1734
1774
|
};
|
|
1735
1775
|
}
|
|
1736
1776
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "polydev-ai",
|
|
3
|
-
"version": "1.8.
|
|
3
|
+
"version": "1.8.71",
|
|
4
4
|
"engines": {
|
|
5
5
|
"node": ">=20.x <=22.x"
|
|
6
6
|
},
|
|
@@ -22,7 +22,8 @@
|
|
|
22
22
|
"private": false,
|
|
23
23
|
"main": "mcp/stdio-wrapper.js",
|
|
24
24
|
"bin": {
|
|
25
|
-
"polydev-stdio": "mcp/stdio-wrapper.js"
|
|
25
|
+
"polydev-stdio": "mcp/stdio-wrapper.js",
|
|
26
|
+
"polydev-ai": "mcp/stdio-wrapper.js"
|
|
26
27
|
},
|
|
27
28
|
"files": [
|
|
28
29
|
"mcp/",
|