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.
- package/lib/mcp/server_setup.js +22 -4
- package/lib/script-fetcher.js +72 -0
- package/package.json +1 -1
package/lib/mcp/server_setup.js
CHANGED
|
@@ -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
|
-
|
|
77
|
-
|
|
78
|
-
|
|
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
|
|
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