codify-mcp 0.6.0 → 0.7.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.
@@ -9,6 +9,7 @@ const { ApifyClient } = require('apify-client');
9
9
  const { randomUUID } = require('node:crypto');
10
10
  const Ajv = require('ajv');
11
11
  const { performActorCall } = require('./actor_caller');
12
+ const { fetchScript } = require('../script-fetcher');
12
13
 
13
14
  const setupServer = async ({ tools, apifyToken }) => {
14
15
  // Configure logging to stderr to avoid protocol corruption
@@ -73,13 +74,30 @@ const setupServer = async ({ tools, apifyToken }) => {
73
74
  if (toolData.implementation?.type === 'apify-actor') {
74
75
  const client = new ApifyClient({ token: apifyToken });
75
76
  const actorId = toolData.implementation.actorId || 'cyberfly/apify-agent';
76
- const script = toolData.implementation.script;
77
-
78
- if (!script) {
77
+ let script;
78
+
79
+ // Determine script source: scriptUrl (KV store) or inline script
80
+ if (toolData.implementation.scriptUrl) {
81
+ // Fetch script from persistent KV store
82
+ try {
83
+ script = await fetchScript(toolData.implementation.scriptUrl, apifyToken);
84
+ } catch (error) {
85
+ return {
86
+ content: [{
87
+ type: 'text',
88
+ text: `[Script Loading Error] Failed to load automation script.\n\nError: ${error.message}\n\nThis means the script storage URL is invalid or your token doesn't have access.`
89
+ }],
90
+ isError: true
91
+ };
92
+ }
93
+ } else if (toolData.implementation.script) {
94
+ // Use inline script (backward compatibility)
95
+ script = toolData.implementation.script;
96
+ } else {
79
97
  return {
80
98
  content: [{
81
99
  type: 'text',
82
- text: 'Error: No script provided in tool implementation'
100
+ text: '[Configuration Error] No automation script found. Tool is missing both \'script\' and \'scriptUrl\'.'
83
101
  }],
84
102
  isError: true
85
103
  };
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Script Fetcher Utility
3
+ * Loads automation scripts from Apify KV store
4
+ */
5
+
6
+ const { ApifyClient } = require('apify-client');
7
+
8
+ const scriptCache = new Map();
9
+
10
+ /**
11
+ * Fetch script from Apify KV store
12
+ *
13
+ * @param {string} scriptUrl - Full URL to KV store record
14
+ * Format: https://api.apify.com/v2/key-value-stores/{storeId}/records/{key}
15
+ * @param {string} apifyToken - Apify API token
16
+ * @returns {Promise<string>} The automation script
17
+ */
18
+ const fetchScript = async (scriptUrl, apifyToken) => {
19
+ if (!scriptUrl || !apifyToken) {
20
+ throw new Error('scriptUrl and apifyToken are required to fetch script');
21
+ }
22
+
23
+ // Check cache first
24
+ if (scriptCache.has(scriptUrl)) {
25
+ return scriptCache.get(scriptUrl);
26
+ }
27
+
28
+ try {
29
+ // Extract store ID and record key from URL
30
+ // URL format: https://api.apify.com/v2/key-value-stores/{storeId}/records/{key}
31
+ const match = scriptUrl.match(/\/key-value-stores\/([^/]+)\/records\/(.+)$/);
32
+
33
+ if (!match) {
34
+ throw new Error(`Invalid script URL format: ${scriptUrl}`);
35
+ }
36
+
37
+ const [, storeId, recordKey] = match;
38
+
39
+ // Create Apify client and fetch from KV store
40
+ const client = new ApifyClient({ token: apifyToken });
41
+ const kvStore = client.keyValueStore(storeId);
42
+ const record = await kvStore.getRecord(recordKey);
43
+
44
+ if (!record) {
45
+ throw new Error(`Script not found at ${scriptUrl}`);
46
+ }
47
+
48
+ // Cache the script for future calls
49
+ scriptCache.set(scriptUrl, record.value);
50
+
51
+ return record.value;
52
+ } catch (error) {
53
+ throw new Error(`Failed to fetch script from KV store: ${error.message}`);
54
+ }
55
+ };
56
+
57
+ const clearScriptCache = () => {
58
+ scriptCache.clear();
59
+ };
60
+
61
+ const getCacheStats = () => {
62
+ return {
63
+ cachedScripts: scriptCache.size,
64
+ urls: Array.from(scriptCache.keys())
65
+ };
66
+ };
67
+
68
+ module.exports = {
69
+ fetchScript,
70
+ clearScriptCache,
71
+ getCacheStats
72
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codify-mcp",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "MCP server for custom automation tools using Apify Agent. Easily create reusable automations from casual browser actions.",
5
5
  "main": "lib/index.js",
6
6
  "bin": {