@easyfunnel/mcp 0.1.8 → 0.1.9

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.
Files changed (2) hide show
  1. package/dist/index.js +61 -46
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -211,25 +211,25 @@ var frameworkConfigs = {
211
211
  nextjs: {
212
212
  envFile: ".env.local",
213
213
  envVarName: "NEXT_PUBLIC_EASYFUNNEL_KEY",
214
- envAccessor: "process.env.NEXT_PUBLIC_EASYFUNNEL_KEY!",
214
+ envAccessor: (apiKey2) => `process.env.NEXT_PUBLIC_EASYFUNNEL_KEY || "${apiKey2}"`,
215
215
  layoutPaths: ["app/layout.tsx", "app/layout.jsx", "src/app/layout.tsx", "src/app/layout.jsx"]
216
216
  },
217
217
  vite: {
218
218
  envFile: ".env",
219
219
  envVarName: "VITE_EASYFUNNEL_KEY",
220
- envAccessor: "import.meta.env.VITE_EASYFUNNEL_KEY",
220
+ envAccessor: (apiKey2) => `import.meta.env.VITE_EASYFUNNEL_KEY || "${apiKey2}"`,
221
221
  layoutPaths: ["src/App.tsx", "src/App.jsx", "src/main.tsx", "src/main.jsx"]
222
222
  },
223
223
  cra: {
224
224
  envFile: ".env",
225
225
  envVarName: "REACT_APP_EASYFUNNEL_KEY",
226
- envAccessor: "process.env.REACT_APP_EASYFUNNEL_KEY!",
226
+ envAccessor: (apiKey2) => `process.env.REACT_APP_EASYFUNNEL_KEY || "${apiKey2}"`,
227
227
  layoutPaths: ["src/App.tsx", "src/App.jsx", "src/index.tsx", "src/index.jsx"]
228
228
  },
229
229
  sveltekit: {
230
230
  envFile: ".env",
231
231
  envVarName: "PUBLIC_EASYFUNNEL_KEY",
232
- envAccessor: "import.meta.env.PUBLIC_EASYFUNNEL_KEY",
232
+ envAccessor: (apiKey2) => `import.meta.env.PUBLIC_EASYFUNNEL_KEY || "${apiKey2}"`,
233
233
  layoutPaths: ["src/routes/+layout.svelte"]
234
234
  }
235
235
  };
@@ -374,7 +374,7 @@ Next: After adding the script, I'll verify everything works with a test event.`
374
374
  if (content.includes("{children}")) {
375
375
  content = content.replace(
376
376
  /(\{children\})/,
377
- `<EasyFunnelProvider apiKey={${config.envAccessor}}>
377
+ `<EasyFunnelProvider apiKey={${config.envAccessor(project_api_key)}}>
378
378
  $1
379
379
  </EasyFunnelProvider>`
380
380
  );
@@ -416,10 +416,12 @@ Project API Key: ${project_api_key}
416
416
  output += `(This is the PROJECT key for the SDK \u2014 not the account key used by the MCP server.)
417
417
  `;
418
418
  output += `
419
- IMPORTANT: Restart your dev server for the env var to take effect.
419
+ The API key is hardcoded in your layout file \u2014 no env var configuration needed.
420
+ `;
421
+ output += `If you prefer, you can override it via ${config.envVarName} in ${config.envFile}.
420
422
  `;
421
423
  output += `
422
- Next: After restarting, I'll verify everything works with a test event.`;
424
+ Next: I'll verify everything works with a test event.`;
423
425
  return {
424
426
  content: [{ type: "text", text: output }]
425
427
  };
@@ -1636,18 +1638,18 @@ function readEnvFile(projectRoot) {
1636
1638
  }
1637
1639
  return null;
1638
1640
  }
1641
+ var layoutCandidates = [
1642
+ "app/layout.tsx",
1643
+ "app/layout.jsx",
1644
+ "src/app/layout.tsx",
1645
+ "src/app/layout.jsx",
1646
+ "src/App.tsx",
1647
+ "src/App.jsx",
1648
+ "src/main.tsx",
1649
+ "src/main.jsx"
1650
+ ];
1639
1651
  function findProviderFile(projectRoot) {
1640
- const candidates = [
1641
- "app/layout.tsx",
1642
- "app/layout.jsx",
1643
- "src/app/layout.tsx",
1644
- "src/app/layout.jsx",
1645
- "src/App.tsx",
1646
- "src/App.jsx",
1647
- "src/main.tsx",
1648
- "src/main.jsx"
1649
- ];
1650
- for (const relPath of candidates) {
1652
+ for (const relPath of layoutCandidates) {
1651
1653
  const fullPath = (0, import_path4.join)(projectRoot, relPath);
1652
1654
  if ((0, import_fs6.existsSync)(fullPath)) {
1653
1655
  const content = (0, import_fs6.readFileSync)(fullPath, "utf-8");
@@ -1658,37 +1660,50 @@ function findProviderFile(projectRoot) {
1658
1660
  }
1659
1661
  return null;
1660
1662
  }
1663
+ function findHardcodedKey(projectRoot) {
1664
+ for (const relPath of layoutCandidates) {
1665
+ const fullPath = (0, import_path4.join)(projectRoot, relPath);
1666
+ if (!(0, import_fs6.existsSync)(fullPath)) continue;
1667
+ const content = (0, import_fs6.readFileSync)(fullPath, "utf-8");
1668
+ if (!content.includes("EasyFunnelProvider")) continue;
1669
+ const match = content.match(/apiKey[=:].*?(ef_[a-f0-9]+)/);
1670
+ if (match) {
1671
+ return { file: relPath, key: match[1] };
1672
+ }
1673
+ }
1674
+ return null;
1675
+ }
1661
1676
  async function validateSetup(client2, args) {
1662
1677
  const { project_root, project_id } = args;
1663
1678
  const checks = [];
1664
1679
  const envResult = readEnvFile(project_root);
1680
+ const hardcodedResult = findHardcodedKey(project_root);
1665
1681
  let apiKey2 = args.project_api_key || "";
1666
- if (envResult) {
1682
+ if (envResult && envResult.value && envResult.value.startsWith("ef_")) {
1667
1683
  apiKey2 = apiKey2 || envResult.value;
1668
- if (envResult.value && envResult.value.startsWith("ef_")) {
1669
- checks.push({
1670
- name: `${envResult.file} contains ${envResult.varName}`,
1671
- passed: true,
1672
- detail: `${envResult.varName}=${envResult.value.slice(0, 8)}...`
1673
- });
1674
- } else if (envResult.value) {
1675
- checks.push({
1676
- name: `${envResult.file} contains ${envResult.varName}`,
1677
- passed: false,
1678
- detail: `Value doesn't start with "ef_". Got: ${envResult.value.slice(0, 20)}`
1679
- });
1680
- } else {
1681
- checks.push({
1682
- name: `${envResult.file} contains ${envResult.varName}`,
1683
- passed: false,
1684
- detail: `${envResult.varName} is empty`
1685
- });
1686
- }
1684
+ checks.push({
1685
+ name: `${envResult.file} contains ${envResult.varName}`,
1686
+ passed: true,
1687
+ detail: `${envResult.varName}=${envResult.value.slice(0, 8)}...`
1688
+ });
1689
+ } else if (hardcodedResult) {
1690
+ apiKey2 = apiKey2 || hardcodedResult.key;
1691
+ checks.push({
1692
+ name: `API key found in ${hardcodedResult.file}`,
1693
+ passed: true,
1694
+ detail: `Hardcoded key: ${hardcodedResult.key.slice(0, 8)}... (recommended for static deployments)`
1695
+ });
1696
+ } else if (envResult && envResult.value) {
1697
+ checks.push({
1698
+ name: `${envResult.file} contains ${envResult.varName}`,
1699
+ passed: false,
1700
+ detail: `Value doesn't start with "ef_". Got: ${envResult.value.slice(0, 20)}`
1701
+ });
1687
1702
  } else {
1688
1703
  checks.push({
1689
- name: "Env file contains API key",
1704
+ name: "API key configured",
1690
1705
  passed: false,
1691
- detail: "No EasyFunnel API key found in .env.local or .env"
1706
+ detail: "No EasyFunnel API key found in env file or hardcoded in layout. Run setup_sdk to add it."
1692
1707
  });
1693
1708
  }
1694
1709
  const providerFile = findProviderFile(project_root);
@@ -1789,14 +1804,14 @@ Next: Let me suggest conversion funnels based on what I found in your codebase.`
1789
1804
  output += `
1790
1805
  `;
1791
1806
  for (const check of failedChecks) {
1792
- if (check.name.includes("Env file") || check.name.includes("API key")) {
1793
- const varName = envResult?.varName || "NEXT_PUBLIC_EASYFUNNEL_KEY";
1794
- const envFile = envResult?.file || ".env.local";
1795
- output += `To fix: Add your project API key to ${envFile}:
1807
+ if (check.name.includes("API key") || check.name.includes("Env file")) {
1808
+ output += `To fix: Run setup_sdk to hardcode the API key in your layout file.
1796
1809
  `;
1797
- output += ` ${varName}=ef_your_key_here
1810
+ output += `Alternatively, add it to an env file:
1798
1811
  `;
1799
- output += `Then restart your dev server.
1812
+ const varName = envResult?.varName || "NEXT_PUBLIC_EASYFUNNEL_KEY";
1813
+ const envFile = envResult?.file || ".env.local";
1814
+ output += ` ${varName}=ef_your_key_here (in ${envFile})
1800
1815
 
1801
1816
  `;
1802
1817
  } else if (check.name.includes("Provider")) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@easyfunnel/mcp",
3
- "version": "0.1.8",
3
+ "version": "0.1.9",
4
4
  "description": "MCP server for easyfunnel.co — AI-powered analytics tools for Claude/Cursor",
5
5
  "main": "dist/index.js",
6
6
  "bin": {