@perceptdot/vercel 0.1.0 → 0.1.2
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 +44 -6
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/smithery.yaml +28 -0
- package/src/index.ts +46 -6
package/dist/index.js
CHANGED
|
@@ -8,7 +8,7 @@ import { CallToolRequestSchema, ListToolsRequestSchema, McpError, ErrorCode, } f
|
|
|
8
8
|
const TOKENS_SAVED_PER_CALL = 200;
|
|
9
9
|
const TOKEN_PRICE_PER_MILLION = 3.0;
|
|
10
10
|
const metrics = {
|
|
11
|
-
tool_name: "@
|
|
11
|
+
tool_name: "@perceptdot/vercel",
|
|
12
12
|
tokens_saved_estimate: 0,
|
|
13
13
|
time_saved_ms: 0,
|
|
14
14
|
calls_count: 0,
|
|
@@ -18,10 +18,41 @@ function trackCall(duration_ms) {
|
|
|
18
18
|
metrics.tokens_saved_estimate += TOKENS_SAVED_PER_CALL;
|
|
19
19
|
metrics.time_saved_ms += duration_ms;
|
|
20
20
|
}
|
|
21
|
+
// ─── 플랜 검증 ────────────────────────────────────────────────────────────────
|
|
22
|
+
const PERCEPT_API_KEY = process.env.PERCEPT_API_KEY;
|
|
23
|
+
const PERCEPT_API_BASE = "https://perceptdot-api.perceptdot.workers.dev";
|
|
24
|
+
const FREE_CALL_LIMIT = 10;
|
|
25
|
+
let planCache = null;
|
|
26
|
+
async function getValidatedPlan() {
|
|
27
|
+
if (!PERCEPT_API_KEY)
|
|
28
|
+
return "free";
|
|
29
|
+
if (planCache && Date.now() < planCache.expires)
|
|
30
|
+
return planCache.plan;
|
|
31
|
+
try {
|
|
32
|
+
const res = await fetch(`${PERCEPT_API_BASE}/v1/validate?key=${PERCEPT_API_KEY}`);
|
|
33
|
+
if (res.ok) {
|
|
34
|
+
const data = await res.json();
|
|
35
|
+
const plan = (data.valid ? data.plan : "free");
|
|
36
|
+
planCache = { plan, expires: Date.now() + 5 * 60 * 1000 };
|
|
37
|
+
return plan;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
catch { }
|
|
41
|
+
return "free";
|
|
42
|
+
}
|
|
43
|
+
function makeUpgradeMessage() {
|
|
44
|
+
const usd = (metrics.tokens_saved_estimate / 1_000_000) * 3.0;
|
|
45
|
+
return [
|
|
46
|
+
"PERCEPT FREE LIMIT REACHED (10 calls/session).",
|
|
47
|
+
`This session: ${metrics.calls_count} calls, ~${metrics.tokens_saved_estimate} tokens saved ($${usd.toFixed(4)}).`,
|
|
48
|
+
"Upgrade to Pro ($19/mo) → https://perceptdot.com",
|
|
49
|
+
"Set PERCEPT_API_KEY in your MCP config after purchase.",
|
|
50
|
+
].join("\n");
|
|
51
|
+
}
|
|
21
52
|
function getRoiSummary() {
|
|
22
53
|
const usd_saved = (metrics.tokens_saved_estimate / 1_000_000) * TOKEN_PRICE_PER_MILLION;
|
|
23
54
|
return [
|
|
24
|
-
`[
|
|
55
|
+
`[perceptdot ROI — @perceptdot/vercel]`,
|
|
25
56
|
`calls: ${metrics.calls_count}`,
|
|
26
57
|
`tokens saved: ${metrics.tokens_saved_estimate.toLocaleString()}`,
|
|
27
58
|
`cost saved: $${usd_saved.toFixed(4)}`,
|
|
@@ -33,7 +64,7 @@ function getRoiSummary() {
|
|
|
33
64
|
// ─── 환경 변수 검증 ────────────────────────────────────────────────────────────
|
|
34
65
|
const VERCEL_TOKEN = process.env.VERCEL_TOKEN;
|
|
35
66
|
if (!VERCEL_TOKEN) {
|
|
36
|
-
process.stderr.write("[
|
|
67
|
+
process.stderr.write("[perceptdot/vercel] ERROR: VERCEL_TOKEN 환경 변수가 필요합니다.\n" +
|
|
37
68
|
"발급 방법: vercel.com/account/tokens\n");
|
|
38
69
|
process.exit(1);
|
|
39
70
|
}
|
|
@@ -55,7 +86,7 @@ async function vercelFetch(path) {
|
|
|
55
86
|
return response.json();
|
|
56
87
|
}
|
|
57
88
|
// ─── MCP 서버 ─────────────────────────────────────────────────────────────────
|
|
58
|
-
const server = new Server({ name: "@
|
|
89
|
+
const server = new Server({ name: "@perceptdot/vercel", version: "0.1.0" }, { capabilities: { tools: {} } });
|
|
59
90
|
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
60
91
|
tools: [
|
|
61
92
|
{
|
|
@@ -110,7 +141,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
|
110
141
|
},
|
|
111
142
|
{
|
|
112
143
|
name: "percept_roi_summary",
|
|
113
|
-
description: "이 세션에서 @
|
|
144
|
+
description: "이 세션에서 @perceptdot/vercel이 절감한 토큰·비용을 보고합니다.",
|
|
114
145
|
inputSchema: {
|
|
115
146
|
type: "object",
|
|
116
147
|
properties: {},
|
|
@@ -123,6 +154,13 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
123
154
|
const { name, arguments: args } = request.params;
|
|
124
155
|
const startTime = Date.now();
|
|
125
156
|
try {
|
|
157
|
+
// 플랜 체크 (percept_roi_summary는 항상 허용)
|
|
158
|
+
if (name !== "percept_roi_summary") {
|
|
159
|
+
const plan = await getValidatedPlan();
|
|
160
|
+
if (plan === "free" && metrics.calls_count >= FREE_CALL_LIMIT) {
|
|
161
|
+
return { content: [{ type: "text", text: makeUpgradeMessage() }] };
|
|
162
|
+
}
|
|
163
|
+
}
|
|
126
164
|
if (name === "percept_roi_summary") {
|
|
127
165
|
return { content: [{ type: "text", text: getRoiSummary() }] };
|
|
128
166
|
}
|
|
@@ -240,5 +278,5 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
240
278
|
});
|
|
241
279
|
const transport = new StdioServerTransport();
|
|
242
280
|
await server.connect(transport);
|
|
243
|
-
process.stderr.write("[
|
|
281
|
+
process.stderr.write("[perceptdot/vercel] v0.1.0 실행 중 — perceptdot.com\n");
|
|
244
282
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EACL,qBAAqB,EACrB,sBAAsB,EACtB,QAAQ,EACR,SAAS,GACV,MAAM,oCAAoC,CAAC;AAE5C,+EAA+E;AAC/E,oDAAoD;AACpD,wCAAwC;AACxC,MAAM,qBAAqB,GAAG,GAAG,CAAC;AAClC,MAAM,uBAAuB,GAAG,GAAG,CAAC;AASpC,MAAM,OAAO,GAAmB;IAC9B,SAAS,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/smithery.yaml
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Smithery configuration — @perceptdot/vercel
|
|
2
|
+
# AI agent vision for Vercel deployments with ROI measurement
|
|
3
|
+
# https://smithery.ai/docs/config#smitheryyaml
|
|
4
|
+
|
|
5
|
+
startCommand:
|
|
6
|
+
type: stdio
|
|
7
|
+
|
|
8
|
+
configSchema:
|
|
9
|
+
type: object
|
|
10
|
+
required:
|
|
11
|
+
- vercelToken
|
|
12
|
+
properties:
|
|
13
|
+
vercelToken:
|
|
14
|
+
type: string
|
|
15
|
+
description: "Vercel API 토큰. vercel.com/account/tokens 에서 발급."
|
|
16
|
+
vercelTeamId:
|
|
17
|
+
type: string
|
|
18
|
+
description: "Vercel 팀 ID (선택). 팀 프로젝트 조회 시 필요."
|
|
19
|
+
|
|
20
|
+
commandFunction: |-
|
|
21
|
+
config => ({
|
|
22
|
+
command: 'npx',
|
|
23
|
+
args: ['-y', '@perceptdot/vercel'],
|
|
24
|
+
env: {
|
|
25
|
+
VERCEL_TOKEN: config.vercelToken,
|
|
26
|
+
...(config.vercelTeamId ? { VERCEL_TEAM_ID: config.vercelTeamId } : {})
|
|
27
|
+
}
|
|
28
|
+
})
|
package/src/index.ts
CHANGED
|
@@ -22,7 +22,7 @@ interface PerceptMetrics {
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
const metrics: PerceptMetrics = {
|
|
25
|
-
tool_name: "@
|
|
25
|
+
tool_name: "@perceptdot/vercel",
|
|
26
26
|
tokens_saved_estimate: 0,
|
|
27
27
|
time_saved_ms: 0,
|
|
28
28
|
calls_count: 0,
|
|
@@ -34,11 +34,43 @@ function trackCall(duration_ms: number): void {
|
|
|
34
34
|
metrics.time_saved_ms += duration_ms;
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
+
// ─── 플랜 검증 ────────────────────────────────────────────────────────────────
|
|
38
|
+
const PERCEPT_API_KEY = process.env.PERCEPT_API_KEY;
|
|
39
|
+
const PERCEPT_API_BASE = "https://perceptdot-api.perceptdot.workers.dev";
|
|
40
|
+
const FREE_CALL_LIMIT = 10;
|
|
41
|
+
|
|
42
|
+
let planCache: { plan: "free" | "pro" | "team"; expires: number } | null = null;
|
|
43
|
+
|
|
44
|
+
async function getValidatedPlan(): Promise<"free" | "pro" | "team"> {
|
|
45
|
+
if (!PERCEPT_API_KEY) return "free";
|
|
46
|
+
if (planCache && Date.now() < planCache.expires) return planCache.plan;
|
|
47
|
+
try {
|
|
48
|
+
const res = await fetch(`${PERCEPT_API_BASE}/v1/validate?key=${PERCEPT_API_KEY}`);
|
|
49
|
+
if (res.ok) {
|
|
50
|
+
const data = await res.json() as { valid: boolean; plan: string };
|
|
51
|
+
const plan = (data.valid ? data.plan : "free") as "free" | "pro" | "team";
|
|
52
|
+
planCache = { plan, expires: Date.now() + 5 * 60 * 1000 };
|
|
53
|
+
return plan;
|
|
54
|
+
}
|
|
55
|
+
} catch {}
|
|
56
|
+
return "free";
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function makeUpgradeMessage(): string {
|
|
60
|
+
const usd = (metrics.tokens_saved_estimate / 1_000_000) * 3.0;
|
|
61
|
+
return [
|
|
62
|
+
"PERCEPT FREE LIMIT REACHED (10 calls/session).",
|
|
63
|
+
`This session: ${metrics.calls_count} calls, ~${metrics.tokens_saved_estimate} tokens saved ($${usd.toFixed(4)}).`,
|
|
64
|
+
"Upgrade to Pro ($19/mo) → https://perceptdot.com",
|
|
65
|
+
"Set PERCEPT_API_KEY in your MCP config after purchase.",
|
|
66
|
+
].join("\n");
|
|
67
|
+
}
|
|
68
|
+
|
|
37
69
|
function getRoiSummary(): string {
|
|
38
70
|
const usd_saved =
|
|
39
71
|
(metrics.tokens_saved_estimate / 1_000_000) * TOKEN_PRICE_PER_MILLION;
|
|
40
72
|
return [
|
|
41
|
-
`[
|
|
73
|
+
`[perceptdot ROI — @perceptdot/vercel]`,
|
|
42
74
|
`calls: ${metrics.calls_count}`,
|
|
43
75
|
`tokens saved: ${metrics.tokens_saved_estimate.toLocaleString()}`,
|
|
44
76
|
`cost saved: $${usd_saved.toFixed(4)}`,
|
|
@@ -52,7 +84,7 @@ function getRoiSummary(): string {
|
|
|
52
84
|
const VERCEL_TOKEN = process.env.VERCEL_TOKEN;
|
|
53
85
|
if (!VERCEL_TOKEN) {
|
|
54
86
|
process.stderr.write(
|
|
55
|
-
"[
|
|
87
|
+
"[perceptdot/vercel] ERROR: VERCEL_TOKEN 환경 변수가 필요합니다.\n" +
|
|
56
88
|
"발급 방법: vercel.com/account/tokens\n"
|
|
57
89
|
);
|
|
58
90
|
process.exit(1);
|
|
@@ -104,7 +136,7 @@ interface VercelProject {
|
|
|
104
136
|
|
|
105
137
|
// ─── MCP 서버 ─────────────────────────────────────────────────────────────────
|
|
106
138
|
const server = new Server(
|
|
107
|
-
{ name: "@
|
|
139
|
+
{ name: "@perceptdot/vercel", version: "0.1.0" },
|
|
108
140
|
{ capabilities: { tools: {} } }
|
|
109
141
|
);
|
|
110
142
|
|
|
@@ -166,7 +198,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
|
166
198
|
{
|
|
167
199
|
name: "percept_roi_summary",
|
|
168
200
|
description:
|
|
169
|
-
"이 세션에서 @
|
|
201
|
+
"이 세션에서 @perceptdot/vercel이 절감한 토큰·비용을 보고합니다.",
|
|
170
202
|
inputSchema: {
|
|
171
203
|
type: "object",
|
|
172
204
|
properties: {},
|
|
@@ -181,6 +213,14 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
181
213
|
const startTime = Date.now();
|
|
182
214
|
|
|
183
215
|
try {
|
|
216
|
+
// 플랜 체크 (percept_roi_summary는 항상 허용)
|
|
217
|
+
if (name !== "percept_roi_summary") {
|
|
218
|
+
const plan = await getValidatedPlan();
|
|
219
|
+
if (plan === "free" && metrics.calls_count >= FREE_CALL_LIMIT) {
|
|
220
|
+
return { content: [{ type: "text", text: makeUpgradeMessage() }] };
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
184
224
|
if (name === "percept_roi_summary") {
|
|
185
225
|
return { content: [{ type: "text", text: getRoiSummary() }] };
|
|
186
226
|
}
|
|
@@ -323,4 +363,4 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
323
363
|
|
|
324
364
|
const transport = new StdioServerTransport();
|
|
325
365
|
await server.connect(transport);
|
|
326
|
-
process.stderr.write("[
|
|
366
|
+
process.stderr.write("[perceptdot/vercel] v0.1.0 실행 중 — perceptdot.com\n");
|