codify-mcp 0.2.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/README.md ADDED
@@ -0,0 +1,339 @@
1
+ # Codify MCP
2
+
3
+ **MCP server for custom automation tools using [Apify Agent](https://apify.com/cyberfly/apify-agent)**
4
+
5
+ > Part of [Project Codify](https://codify.codey.eu.org)
6
+
7
+ ## Project Codify
8
+ - [Login](https://apify.com/cyberfly) - reusable authentication sessions - TBD
9
+
10
+ - [Agent](https://apify.com/cyberfly) - turn scripts into browser actions
11
+ - [Coder](https://apify.com/cyberfly) - turn browser actions into scripts (TBD - currently integrated)
12
+ - [Robot](https://apify.com/cyberfly) - automation engine for scalability (TBD - currently integrated)
13
+
14
+ More is on the way... Give it a [shot](https://codify.codey.eu.org) 🎬 or join the list to follow the project! 🔔
15
+
16
+ ## What It Does
17
+
18
+ Model Context Protocol (MCP) server that lets AI assistants (e.g. Claude, Cursor, VS Code) execute browser automation tasks via Apify Agent. Tools are passed as clean JSON arguments — one per line. No manual setup or file creation.
19
+
20
+ ## Usage
21
+
22
+ Run directly using `npx`:
23
+
24
+ ```bash
25
+ npx codify-mcp {{MCP_TOOL_JSON}}
26
+ ```
27
+
28
+ Or install locally:
29
+
30
+ ```bash
31
+ npm install -g codify-mcp
32
+ ```
33
+
34
+ ## Quick Start
35
+
36
+ ### 1. Apify Token
37
+
38
+ Optional - you can also place the token inside the MCP server JSON later.
39
+
40
+ ```bash
41
+ apify login
42
+ ```
43
+
44
+ This saves your token to `~/.apify/auth.json`.
45
+
46
+ Alternatively, set the environment variable:
47
+
48
+ ```bash
49
+ export APIFY_TOKEN="your_token_here"
50
+ ```
51
+
52
+ ### 2. Create a Tool
53
+
54
+ [Apify Coder](https://apify.com/cyberfly) can turn casual browser actions into reusable AI tools.
55
+ Currently, this feature is also integrated in [Apify Agent](https://apify.com/cyberfly/apify-agent)
56
+
57
+ Export a tool and append the result as a JSON string to the MCP server `args` field or ask your AI to do it for you.
58
+
59
+ ```json
60
+ {
61
+ "name": "scrape_product",
62
+ "description": "Scrape product info from a page",
63
+ "inputSchema": {
64
+ "type": "object",
65
+ "properties": {
66
+ "url": {
67
+ "type": "string",
68
+ "description": "Product page URL"
69
+ }
70
+ },
71
+ "required": ["url"]
72
+ },
73
+ "implementation": {
74
+ "type": "apify-actor",
75
+ "actorId": "cyberfly/apify-agent",
76
+ "script": "await page.goto(inputs.url); const title = await page.textContent('h1'); return {title};"
77
+ }
78
+ }
79
+ ```
80
+
81
+ ### 3. Run the Server
82
+
83
+ ```bash
84
+ npx codify-mcp '{"name":"scrape_product","description":"...","inputSchema":{...},"implementation":{...}}'
85
+ ```
86
+
87
+ Or with multiple tools:
88
+
89
+ ```bash
90
+ npx codify-mcp \
91
+ '{"name":"tool1",...}' \
92
+ '{"name":"tool2",...}' \
93
+ '{"name":"tool3",...}'
94
+ ```
95
+
96
+ ### 4. Connect to Claude Desktop (or Cursor/VS Code)
97
+
98
+ Edit your Claude Desktop config:
99
+
100
+ **macOS/Linux:** `~/.config/Claude/claude_desktop_config.json`
101
+
102
+ **Windows:** `%APPDATA%\Claude\claude_desktop_config.json`
103
+
104
+ ```json
105
+ {
106
+ "mcpServers": {
107
+ "apify-agent": {
108
+ "command": "npx",
109
+ "args": [
110
+ "codify-mcp",
111
+ "{\"name\":\"scrape_product\",\"description\":\"...\",\"inputSchema\":{...},\"implementation\":{...}}"
112
+ ],
113
+ "env": {
114
+ "APIFY_TOKEN": "your_token_or_leave_empty_to_use_auth_file"
115
+ }
116
+ }
117
+ }
118
+ }
119
+ ```
120
+
121
+ Restart Claude. Your tools are now available to the AI assistant.
122
+
123
+ ## Tool Definition Reference
124
+
125
+ ### Basic Structure
126
+
127
+ ```javascript
128
+ {
129
+ // Required
130
+ "name": "tool_name", // alphanumeric + underscore/dash
131
+ "description": "What the tool does", // shown to AI
132
+ "inputSchema": {
133
+ "type": "object",
134
+ "properties": {
135
+ "paramName": {
136
+ "type": "string",
137
+ "description": "Parameter description"
138
+ }
139
+ },
140
+ "required": ["paramName"]
141
+ },
142
+ "implementation": {
143
+ "type": "apify-actor",
144
+ "actorId": "cyberfly/apify-agent", // actor to run
145
+ "script": "await page.goto(inputs.url); ..." // Playwright code
146
+ },
147
+
148
+ // Optional
149
+ "version": "1.0.0",
150
+ "metadata": { "custom": "fields" }
151
+ }
152
+ ```
153
+
154
+ ### Implementation Details
155
+
156
+ - **script**: Playwright automation code. Receives `inputs` object with user-provided parameters and `page` object for browser automation.
157
+ - **actorId**: Apify actor to execute. Defaults to `cyberfly/apify-agent`.
158
+
159
+ ### Input Schema Examples
160
+
161
+ **Simple text input:**
162
+ ```json
163
+ {
164
+ "url": {
165
+ "type": "string",
166
+ "description": "Website URL"
167
+ }
168
+ }
169
+ ```
170
+
171
+ **Optional field:**
172
+ ```json
173
+ {
174
+ "timeout": {
175
+ "type": "integer",
176
+ "description": "Timeout in seconds",
177
+ "default": 30
178
+ }
179
+ }
180
+ ```
181
+
182
+ **Enum (dropdown):**
183
+ ```json
184
+ {
185
+ "format": {
186
+ "type": "string",
187
+ "enum": ["json", "csv", "markdown"],
188
+ "description": "Output format"
189
+ }
190
+ }
191
+ ```
192
+
193
+ ## Usage Patterns
194
+
195
+ ### Single Tool (Development)
196
+
197
+ ```bash
198
+ npx codify-mcp '{"name":"test","description":"Test tool","inputSchema":{"type":"object","properties":{}},"implementation":{"type":"apify-actor","script":"console.log('hello')"}}'
199
+ ```
200
+
201
+ ### Multiple Tools (Production)
202
+
203
+ ```bash
204
+ npx codify-mcp \
205
+ "$(cat tools/scraper.json)" \
206
+ "$(cat tools/logger.json)" \
207
+ "$(cat tools/analyzer.json)"
208
+ ```
209
+
210
+ ### With Environment Variable
211
+
212
+ ```bash
213
+ APIFY_TOKEN="apk_..." npx codify-mcp '{"name":"...","description":"...","inputSchema":{},"implementation":{"type":"apify-actor","script":"..."}}'
214
+ ```
215
+
216
+ ### With npm link (Local Testing)
217
+
218
+ ```bash
219
+ cd /path/to/codify-mcp
220
+ npm link
221
+
222
+ # Now use anywhere
223
+ codify-mcp '{"name":"...","description":"...","inputSchema":{},"implementation":{"type":"apify-actor","script":"..."}}'
224
+ ```
225
+
226
+ ## Authentication
227
+
228
+ Token resolution order:
229
+
230
+ 1. **APIFY_TOKEN environment variable** (if set and not empty)
231
+ 2. **~/.apify/auth.json** (from `apify login` CLI command)
232
+ 3. **Error**: No token found, tool execution will fail with clear message
233
+
234
+ ## Troubleshooting
235
+
236
+ ### "No valid tools in arguments"
237
+
238
+ Ensure you're passing valid JSON strings as arguments:
239
+
240
+ ```bash
241
+ # ✓ Correct
242
+ npx codify-mcp '{"name":"test","description":"Test","inputSchema":{"type":"object","properties":{}},"implementation":{"type":"apify-actor","script":"return {ok:true}"}}'
243
+
244
+ # ✗ Wrong (missing quotes around JSON)
245
+ npx codify-mcp {name:"test"...}
246
+
247
+ # ✗ Wrong (single quotes around JSON on Linux/Mac may need escaping)
248
+ npx codify-mcp '{name:"test"...}' # Use double quotes inside
249
+ ```
250
+
251
+ ### "Invalid or missing Apify token"
252
+
253
+ Ensure authentication is set up:
254
+
255
+ ```bash
256
+ # Option 1: Login via CLI
257
+ apify login
258
+
259
+ # Option 2: Set environment variable
260
+ export APIFY_TOKEN="apk_your_token_here"
261
+ apify token
262
+ ```
263
+
264
+ ### "Tool execution failed"
265
+
266
+ Check your Playwright script syntax. The script must be valid JavaScript that:
267
+
268
+ - Has access to `inputs` (user-provided parameters)
269
+ - Has access to `page` (Playwright page object)
270
+ - Returns a value or object
271
+
272
+ ```javascript
273
+ // ✓ Valid
274
+ await page.goto(inputs.url);
275
+ const title = await page.textContent('h1');
276
+ return { title };
277
+
278
+ // ✗ Invalid (missing await)
279
+ page.goto(inputs.url);
280
+ ```
281
+
282
+ ### Large Tool Sets (50+ tools)
283
+
284
+ If you have many tools, consider splitting into multiple MCP servers:
285
+
286
+ ```json
287
+ {
288
+ "mcpServers": {
289
+ "apify-scraper": {
290
+ "command": "npx",
291
+ "args": ["codify-mcp", "...tool1...", "...tool2..."]
292
+ },
293
+ "apify-analyzer": {
294
+ "command": "npx",
295
+ "args": ["codify-mcp", "...tool3...", "...tool4..."]
296
+ }
297
+ }
298
+ }
299
+ ```
300
+
301
+ ## Development
302
+
303
+ ### Running Locally
304
+
305
+ ```bash
306
+ npm link
307
+ codify-mcp '{"name":"test",...}'
308
+ ```
309
+
310
+ ### Structure
311
+
312
+ ```
313
+ lib/
314
+ index.js # Main entry: assembleWrapperCode(), start()
315
+ mcp/
316
+ resolver.js # Module path bootstrapping
317
+ auth.js # Token resolution
318
+ actor_caller.js # Apify actor execution
319
+ server_setup.js # MCP server + tool registration
320
+
321
+ bin/
322
+ start.js # Executable entry point (bin field in package.json)
323
+ ```
324
+
325
+ ## Key Design Principles
326
+
327
+ - **No files**: Tools passed entirely via argv; no config files or manual setup.
328
+ - **No base64**: Clean, readable command lines; no obfuscation.
329
+ - **Self-contained**: All dependencies bundled; works offline once installed.
330
+ - **Stateless**: Each invocation is independent; easy horizontal scaling.
331
+ - **Token from env/CLI**: Seamless auth experience; respects Apify ecosystem conventions.
332
+
333
+ ## License
334
+
335
+ Apache-2.0
336
+
337
+ ## Contributing
338
+
339
+ Issues and PRs welcome at [github.com/cybairfly/apify-agent](https://github.com/cybairfly/apify-agent)
package/bin/start.js ADDED
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * codify-mcp executable entry point
5
+ * Starts MCP server with tools provided as command-line arguments
6
+ *
7
+ * Usage:
8
+ * codify-mcp '{"name":"tool1",...}'
9
+ *
10
+ * Environment:
11
+ * APIFY_TOKEN - Apify API token (optional, falls back to ~/.apify/auth.json)
12
+ */
13
+
14
+ const { start } = require('../lib/index.js');
15
+
16
+ start().catch(err => {
17
+ console.error('[Startup Error]', err.message);
18
+ process.exit(1);
19
+ });
package/lib/index.js ADDED
@@ -0,0 +1,70 @@
1
+ /**
2
+ * codify-mcp
3
+ * Standalone MCP server library for executing Apify Agent tools
4
+ *
5
+ * Usage:
6
+ * npx codify-mcp '{"name":"tool1",...}' '{"name":"tool2",...}'
7
+ *
8
+ * Requires:
9
+ * - APIFY_TOKEN env var OR ~/.apify/auth.json
10
+ */
11
+
12
+ const { getToken } = require('./mcp/auth');
13
+ const { fixModulePaths } = require('./mcp/resolver');
14
+ const { setupServer } = require('./mcp/server_setup');
15
+
16
+ /**
17
+ * Parse tools from process.argv
18
+ * @returns {Array} Array of tool objects
19
+ */
20
+ const parseToolsFromArgv = () => {
21
+ const tools = [];
22
+ const toolJsonArgs = process.argv.slice(2);
23
+
24
+ for (const arg of toolJsonArgs) {
25
+ try {
26
+ const tool = JSON.parse(arg);
27
+ tools.push(tool);
28
+ console.error('[MCP Parser] Loaded tool:', tool.name || 'unnamed');
29
+ } catch (e) {
30
+ console.error('[MCP Parser] Failed to parse tool arg:', e.message);
31
+ }
32
+ }
33
+
34
+ if (tools.length === 0) {
35
+ console.error('[MCP Error] No valid tools in arguments. Expected JSON strings.');
36
+ process.exit(1);
37
+ }
38
+
39
+ return tools;
40
+ };
41
+
42
+ /**
43
+ * Start the MCP server with tools from argv
44
+ * Initializes everything and connects to MCP client via stdio
45
+ */
46
+ const start = async () => {
47
+ try {
48
+ // 1. Fix module paths for npx environments
49
+ fixModulePaths();
50
+
51
+ // 2. Get Apify token
52
+ const apifyToken = getToken();
53
+ if (!apifyToken) {
54
+ console.error('[Auth Error] No Apify token found.');
55
+ console.error('Set APIFY_TOKEN env var or run: apify login');
56
+ process.exit(1);
57
+ }
58
+
59
+ // 3. Parse tools from command-line arguments
60
+ const tools = parseToolsFromArgv();
61
+
62
+ // 4. Setup and start MCP server
63
+ await setupServer({ tools, apifyToken });
64
+ } catch (e) {
65
+ console.error('[MCP Fatal Error]', e);
66
+ process.exit(1);
67
+ }
68
+ };
69
+
70
+ module.exports = { start, parseToolsFromArgv };
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Apify Actor Caller
3
+ * Executes actor and returns results
4
+ */
5
+
6
+ const performActorCall = async ({ client, actorId, input, server }) => {
7
+ // Save original stderr.write
8
+ const originalStderrWrite = process.stderr.write;
9
+
10
+ // Override to intercept actor logs
11
+ process.stderr.write = (chunk, encoding, callback) => {
12
+ const str = chunk.toString();
13
+
14
+ if (str.includes('apify-agent runId:')) {
15
+ // Extract log part after ' -> ' (preserves all original formatting)
16
+ const match = str.match(/apify-agent runId:[^>]+> (.+)/);
17
+ if (match) {
18
+ const logLine = match[1];
19
+ // Send as MCP logging message with original formatting intact
20
+ if (server && server.sendLoggingMessage) {
21
+ server.sendLoggingMessage('info', logLine);
22
+ }
23
+ }
24
+
25
+ // Don't write to stderr
26
+ if (callback) callback();
27
+ return true;
28
+ } else {
29
+ // Normal stderr output
30
+ return originalStderrWrite.call(process.stderr, chunk, encoding, callback);
31
+ }
32
+ };
33
+
34
+ try {
35
+ // Start the run
36
+ const run = await client.actor(actorId).call(input);
37
+
38
+ // Fetch results
39
+ const { items } = await client.dataset(run.defaultDatasetId).listItems();
40
+
41
+ return {
42
+ content: [
43
+ {
44
+ type: 'text',
45
+ text: JSON.stringify(items.length > 0 ? items : run, null, 2)
46
+ }
47
+ ]
48
+ };
49
+ } finally {
50
+ // Restore stderr
51
+ process.stderr.write = originalStderrWrite;
52
+ }
53
+ };
54
+
55
+ module.exports = { performActorCall };
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Authentication Helper
3
+ * Returns the Apify token from env or ~/.apify/auth.json
4
+ */
5
+
6
+ const fs = require('fs');
7
+ const os = require('os');
8
+ const path = require('path');
9
+
10
+ const getToken = () => {
11
+ // 1. Priority: Valid environment variable (not the placeholder)
12
+ if (process.env.APIFY_TOKEN &&
13
+ process.env.APIFY_TOKEN !== '{{Authorization}}' &&
14
+ process.env.APIFY_TOKEN !== 'YOUR_APIFY_TOKEN_OR_USE_ENV_VAR' &&
15
+ process.env.APIFY_TOKEN.trim() !== '') {
16
+ return process.env.APIFY_TOKEN;
17
+ }
18
+
19
+ // 2. Fallback: Apify CLI auth file
20
+ try {
21
+ const authPath = path.join(os.homedir(), '.apify', 'auth.json');
22
+ if (fs.existsSync(authPath)) {
23
+ const auth = JSON.parse(fs.readFileSync(authPath, 'utf8'));
24
+ if (auth.token) return auth.token;
25
+ }
26
+ } catch (e) {
27
+ // Silently ignore auth file read errors
28
+ }
29
+
30
+ return null;
31
+ };
32
+
33
+ module.exports = { getToken };
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Module Path Resolver
3
+ * Fixes NODE_PATH for npx environments
4
+ */
5
+
6
+ const path = require('path');
7
+ const fs = require('fs');
8
+
9
+ const fixModulePaths = () => {
10
+ process.env.PATH.split(path.delimiter).forEach(d => {
11
+ const b = path.join(d, '../');
12
+ if (d.includes('node_modules') || (fs.existsSync(b) && fs.readdirSync(b).includes('node_modules'))) {
13
+ const nm = d.includes('node_modules') ? d.split('node_modules')[0] + 'node_modules' : path.join(d, '../node_modules');
14
+ if (!module.paths.includes(nm)) module.paths.push(nm);
15
+ }
16
+ });
17
+ };
18
+
19
+ module.exports = { fixModulePaths };
@@ -0,0 +1,162 @@
1
+ /**
2
+ * MCP Server Setup and Connection
3
+ * Initializes the MCP server with tools and connects via stdio
4
+ */
5
+
6
+ const { ActorsMcpServer } = require('@apify/actors-mcp-server');
7
+ const { StdioServerTransport } = require('@modelcontextprotocol/sdk/server/stdio.js');
8
+ const { ApifyClient } = require('apify-client');
9
+ const { randomUUID } = require('node:crypto');
10
+ const Ajv = require('ajv');
11
+ const { performActorCall } = require('./actor_caller');
12
+
13
+ const setupServer = async ({ tools, apifyToken }) => {
14
+ // Configure logging to stderr to avoid protocol corruption
15
+ try {
16
+ const log = require('@apify/log');
17
+ if (log && log.setLevel) log.setLevel(log.LEVELS.ERROR);
18
+ } catch (e) {
19
+ // Ignore if @apify/log is not found
20
+ }
21
+ console.log = (...args) => console.error(...args);
22
+ console.info = (...args) => console.error(...args);
23
+
24
+ // Create AJV instance for JSON Schema validation
25
+ const ajv = new Ajv({ allErrors: true, strict: false });
26
+
27
+ // Create MCP server
28
+ const server = new ActorsMcpServer({
29
+ transportType: 'stdio',
30
+ token: apifyToken,
31
+ telemetry: { enabled: false }
32
+ });
33
+
34
+ // Register all tools
35
+ if (!Array.isArray(tools) || tools.length === 0) {
36
+ console.error('[Server Error] No tools provided to server');
37
+ process.exit(1);
38
+ }
39
+
40
+ // Reconstruct tools: Apify SDK expects tool objects with methods
41
+ const reconstructedTools = tools.map(toolData => {
42
+ const tool = {
43
+ name: toolData.name,
44
+ description: toolData.description,
45
+ inputSchema: toolData.inputSchema || { type: 'object', properties: {} },
46
+ type: 'internal',
47
+
48
+ // ajvValidate: required by Apify SDK for input validation
49
+ ajvValidate: (input) => {
50
+ if (!tool.inputSchema) {
51
+ // If no schema, accept any input
52
+ return { valid: true };
53
+ }
54
+ try {
55
+ const validate = ajv.compile(tool.inputSchema);
56
+ const valid = validate(input);
57
+ return {
58
+ valid,
59
+ errors: validate.errors
60
+ };
61
+ } catch (error) {
62
+ console.error('Schema compilation error:', error);
63
+ return {
64
+ valid: false,
65
+ errors: [{ message: `Schema compilation failed: ${error.message}` }]
66
+ };
67
+ }
68
+ },
69
+
70
+ // call: the actual tool handler
71
+ call: async (context) => {
72
+ // For tools with apify-actor implementation
73
+ if (toolData.implementation?.type === 'apify-actor') {
74
+ const client = new ApifyClient({ token: apifyToken });
75
+ const actorId = toolData.implementation.actorId || 'cyberfly/apify-agent';
76
+ const script = toolData.implementation.script;
77
+
78
+ if (!script) {
79
+ return {
80
+ content: [{
81
+ type: 'text',
82
+ text: 'Error: No script provided in tool implementation'
83
+ }],
84
+ isError: true
85
+ };
86
+ }
87
+
88
+ const input = {
89
+ ...context.args,
90
+ script: script
91
+ };
92
+
93
+ try {
94
+ return await performActorCall({ client, actorId, input, server });
95
+ } catch (e) {
96
+ console.error('[Tool Error]', e.message);
97
+ if (e.statusCode === 401 || (e.message && e.message.includes('token'))) {
98
+ return {
99
+ content: [{
100
+ type: 'text',
101
+ text: '[Authentication Required] Invalid or missing Apify token.'
102
+ }],
103
+ isError: true
104
+ };
105
+ }
106
+ return {
107
+ content: [{
108
+ type: 'text',
109
+ text: `Error: ${e.message}`
110
+ }],
111
+ isError: true
112
+ };
113
+ }
114
+ }
115
+
116
+ // Unsupported implementation type
117
+ return {
118
+ content: [{
119
+ type: 'text',
120
+ text: `Unsupported implementation type: ${toolData.implementation?.type}`
121
+ }],
122
+ isError: true
123
+ };
124
+ },
125
+
126
+ // Preserve optional fields
127
+ ...(toolData.metadata && { metadata: toolData.metadata }),
128
+ ...(toolData.version && { version: toolData.version }),
129
+ };
130
+ return tool;
131
+ });
132
+ server.upsertTools(reconstructedTools);
133
+ console.error(`[Server Setup] Registered ${reconstructedTools.length} tool(s)`);
134
+
135
+ // Connect server via stdio
136
+ try {
137
+ const transport = new StdioServerTransport();
138
+ const mcpSessionId = randomUUID();
139
+
140
+ // Wrap onmessage to inject mcpSessionId
141
+ const originalOnMessage = transport.onmessage;
142
+ transport.onmessage = (message) => {
143
+ if (message.method === 'initialize') {
144
+ server.options.initializeRequestData = message;
145
+ }
146
+ // Inject session ID into _meta
147
+ const params = message.params || {};
148
+ params._meta = params._meta || {};
149
+ params._meta.mcpSessionId = mcpSessionId;
150
+ message.params = params;
151
+
152
+ if (originalOnMessage) originalOnMessage(message);
153
+ };
154
+
155
+ await server.connect(transport);
156
+ } catch (e) {
157
+ console.error('[MCP Error]', e);
158
+ process.exit(1);
159
+ }
160
+ };
161
+
162
+ module.exports = { setupServer };
package/manifest.json ADDED
@@ -0,0 +1,74 @@
1
+ {
2
+ "manifest_version": "0.2",
3
+ "version": "0.1.0",
4
+ "name": "codify-mcp",
5
+ "icon": "media/icons/play.png",
6
+ "display_name": "Codify MCP Server",
7
+ "description": "MCP server for custom automation tools using Apify Agent. Easily create reusable automations from casual browser actions.",
8
+ "author": "Apify & Community",
9
+ "license": "Apache-2.0",
10
+ "resources": {
11
+ "readme": "README.md"
12
+ },
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "https://github.com/cybairfly/apify-agent"
16
+ },
17
+ "homepage": "https://codify.codey.eu.org",
18
+ "support": "https://github.com/cybairfly/apify-agent/issues",
19
+ "keywords": [
20
+ "ai",
21
+ "mcp",
22
+ "apify",
23
+ "agent",
24
+ "automation",
25
+ "claude",
26
+ "cursor",
27
+ "vscode",
28
+ "tools",
29
+ "model-context-protocol"
30
+ ],
31
+ "server": {
32
+ "type": "node",
33
+ "entry_point": "bin/start.js",
34
+ "mcp_config": {
35
+ "command": "node",
36
+ "args": [
37
+ "${__dirname}/bin/start.js",
38
+ "${user_config.tools}"
39
+ ],
40
+ "env": {
41
+ "APIFY_TOKEN": "${user_config.apify_token}"
42
+ }
43
+ }
44
+ },
45
+ "compatibility": {
46
+ "platforms": [
47
+ "darwin",
48
+ "linux",
49
+ "win32"
50
+ ],
51
+ "node_version": ">=20.0.0",
52
+ "clients": [
53
+ "claude_desktop",
54
+ "cursor"
55
+ ]
56
+ },
57
+ "user_config": {
58
+ "properties": {
59
+ "APIFY_TOKEN": {
60
+ "type": "string",
61
+ "description": "Apify API token for authentication",
62
+ "required": false,
63
+ "sensitive": true,
64
+ "masked": true
65
+ },
66
+ "tools": {
67
+ "type": "string",
68
+ "title": "Custom tools",
69
+ "description": "Export a tool and append the result as a JSON string to the MCP server `args` field or ask your AI to do it for you.",
70
+ "required": false
71
+ }
72
+ }
73
+ }
74
+ }
Binary file
package/package.json ADDED
@@ -0,0 +1,59 @@
1
+ {
2
+ "name": "codify-mcp",
3
+ "version": "0.2.0",
4
+ "description": "MCP server for custom automation tools using Apify Agent. Easily create reusable automations from casual browser actions.",
5
+ "main": "lib/index.js",
6
+ "bin": {
7
+ "codify-mcp": "bin/start.js"
8
+ },
9
+ "files": [
10
+ "bin/",
11
+ "lib/",
12
+ "media/",
13
+ "server.json",
14
+ "manifest.json",
15
+ "README.md"
16
+ ],
17
+ "scripts": {
18
+ "start": "node bin/start.js"
19
+ },
20
+ "keywords": [
21
+ "ai",
22
+ "mcp",
23
+ "apify",
24
+ "agent",
25
+ "apify-agent",
26
+ "automation",
27
+ "claude",
28
+ "cursor",
29
+ "vscode",
30
+ "tools",
31
+ "model-context-protocol"
32
+ ],
33
+ "author": "Apify & Community",
34
+ "license": "Apache-2.0",
35
+ "homepage": "https://codify.codey.eu.org",
36
+ "repository": {
37
+ "type": "git",
38
+ "url": "git+https://github.com/cybairfly/apify-agent.git",
39
+ "directory": "libraries/codify-mcp"
40
+ },
41
+ "engines": {
42
+ "node": ">=20.0.0"
43
+ },
44
+ "compatibility": {
45
+ "claude_desktop": ">=0.2.16",
46
+ "platforms": [
47
+ "darwin",
48
+ "win32",
49
+ "linux"
50
+ ]
51
+ },
52
+ "dependencies": {
53
+ "@apify/actors-mcp-server": "^0.7.1",
54
+ "@modelcontextprotocol/sdk": "^0.7.0",
55
+ "apify-client": "^2.1.0",
56
+ "@apify/log": "^1.0.0",
57
+ "ajv": "^8.12.0"
58
+ }
59
+ }
package/server.json ADDED
@@ -0,0 +1,24 @@
1
+ {
2
+ "$schema": "https://raw.githubusercontent.com/modelcontextprotocol/modelcontextprotocol/main/schema/2025-11-25/schema.json",
3
+ "name": "com.apify/codify-mcp",
4
+ "version": "0.1.0",
5
+ "description": "Easily create reusable automation tools from casual browser actions using Apify Agent",
6
+ "transport": {
7
+ "type": "stdio",
8
+ "command": "codify-mcp",
9
+ "args": []
10
+ },
11
+ "authentication": {
12
+ "type": "environment",
13
+ "env_var": "APIFY_TOKEN"
14
+ },
15
+ "capabilities": {
16
+ "tools": true,
17
+ "prompts": false,
18
+ "resources": false
19
+ },
20
+ "implementation": {
21
+ "name": "Codify MCP Server",
22
+ "version": "0.1.0"
23
+ }
24
+ }