#!/usr/bin/env node
/**
* Generate MCP examples for every tool by invoking the unified server.
* Writes docs/reference/mcp_examples.md with request/response samples.
*/
const { spawn } = require('child_process');
const fs = require('fs');
const os = require('os');
const path = require('path');
function startServer(workspaceRoot) {
const serverPath = path.join(__dirname, '..', '..', 'bin', 'agentic-control-framework-mcp');
const child = spawn('node', [serverPath, '--workspaceRoot', workspaceRoot], {
env: { ...process.env, WORKSPACE_ROOT: workspaceRoot },
stdio: ['pipe', 'pipe', 'pipe']
});
return child;
}
function sendRequest(proc, req, timeoutMs = 6000) {
return new Promise((resolve, reject) => {
const id = req.id || Math.floor(Math.random() * 1e9);
req.id = id;
let out = '';
let err = '';
const onOut = (d) => {
out += d.toString();
const lines = out.split('\n').filter(Boolean);
for (const line of lines) {
try {
const json = JSON.parse(line);
if (json.id === id) {
cleanup();
return resolve(json);
}
} catch (_) {}
}
};
const onErr = (d) => { err += d.toString(); };
const cleanup = () => {
proc.stdout.off('data', onOut);
proc.stderr.off('data', onErr);
clearTimeout(to);
};
const to = setTimeout(() => { cleanup(); reject(new Error(`Timeout waiting for response. Stderr: ${err}`)); }, timeoutMs);
proc.stdout.on('data', onOut);
proc.stderr.on('data', onErr);
proc.stdin.write(JSON.stringify(req) + '\n');
});
}
async function main() {
const ENABLE_BROWSER = process.env.ACF_ENABLE_BROWSER_TOOLS === '1' && process.platform === 'darwin';
const ENABLE_APPLESCRIPT = process.env.ACF_ENABLE_APPLESCRIPT === '1' && process.platform === 'darwin';
const ENABLE_AI = !!process.env.GEMINI_API_KEY;
const workspace = fs.mkdtempSync(path.join(os.tmpdir(), 'acf-mcp-docs-'));
const proc = startServer(workspace);
const lines = [];
const push = (s = '') => lines.push(s);
push('# MCP Tools — Request/Response Examples');
push('');
push('This file is generated by `scripts/testing/generate-mcp-examples.js`.');
push(`- Workspace: ${workspace}`);
push(`- Platform: ${process.platform}`);
push(`- Browser tools: ${ENABLE_BROWSER ? 'enabled' : 'disabled'}`);
push(`- AppleScript: ${ENABLE_APPLESCRIPT ? 'enabled' : 'disabled'}`);
push(`- AI tools: ${ENABLE_AI ? 'enabled' : 'disabled'}`);
push('');
function reqBlock(obj) { return '```json\n' + JSON.stringify(obj, null, 2) + '\n```'; }
function resBlock(obj) { return '```json\n' + JSON.stringify(obj, null, 2) + '\n```'; }
// initialize
await sendRequest(proc, { jsonrpc:'2.0', method:'initialize', params:{ protocolVersion: '2025-03-26', capabilities:{}, clientInfo:{ name:'docs-generator', version:'1.0.0' } } });
const toolArgs = (name) => {
switch (name) {
// Core task ops
case 'initProject': return { projectName: 'Docs', projectDescription: 'MCP examples' };
case 'addTask': return { title: 'Example task', description: 'docs', priority: '600' };
case 'addSubtask': return { parentId: 1, title: 'Example subtask' };
case 'listTasks': return { status:'todo' };
case 'updateStatus': return { id: '1', newStatus: 'inprogress', message:'start' };
case 'getNextTask': return { random_string:'x' };
case 'updateTask': return { id: '1', title:'Example task (renamed)' };
case 'removeTask': return { id: '1.1' };
case 'getContext': return { id: '1' };
case 'generateTaskFiles': return {};
// Filesystem
case 'read_file': return { path: path.join(workspace, 'a.txt') };
case 'read_multiple_files': return { paths: [path.join(workspace, 'a.txt')] };
case 'write_file': return { path: path.join(workspace, 'a.txt'), content: 'hello' };
case 'copy_file': return { source: path.join(workspace, 'a.txt'), destination: path.join(workspace, 'b.txt') };
case 'move_file': return { source: path.join(workspace, 'b.txt'), destination: path.join(workspace, 'c.txt') };
case 'delete_file': return { path: path.join(workspace, 'c.txt') };
case 'list_directory': return { path: workspace };
case 'create_directory': return { path: path.join(workspace, 'sub') };
case 'tree': return { path: workspace, depth: 2 };
case 'search_files': return { path: workspace, pattern: 'a.txt' };
case 'get_file_info': return { path: path.join(workspace, 'a.txt') };
case 'list_allowed_directories': return { random_string:'x' };
case 'get_filesystem_status': return { random_string:'x' };
// Terminal
case 'get_config': return { random_string:'x' };
case 'set_config_value': return { key:'commandTimeout', value: 8000 };
case 'execute_command': return { command: process.platform==='win32' ? 'echo hello' : 'echo hello', waitForCompletion: true, shell: process.platform==='win32'? undefined : '/bin/sh' };
case 'read_output': return { pid: 0 }; // replaced dynamically
case 'force_terminate': return { pid: 0 }; // replaced dynamically
case 'list_sessions': return { random_string:'x' };
case 'list_processes': return { random_string:'x' };
case 'kill_process': return { pid: 0 }; // replaced dynamically
// Search & Edit
case 'search_code': return { path: workspace, pattern: 'hello' };
case 'edit_block': return { file_path: path.join(workspace, 'a.txt'), old_string: 'hello', new_string: 'world', normalize_whitespace: true };
// Enhanced FS
case 'read_url': return { path: 'http://example.com' };
// Browser (gated)
case 'browser_tab_new': return { url: 'data:text/html,<html><body>Hi</body></html>' };
case 'browser_snapshot': return {};
case 'browser_close': return {};
// AppleScript (gated)
case 'applescript_execute': return { code_snippet: 'return "ok"', timeout: 5 };
// Priority wrappers
case 'bump_task_priority': return { id:'1', amount: 25 };
case 'defer_task_priority': return { id:'1', amount: 10 };
case 'prioritize_task': return { id:'1', priority: 880 };
case 'deprioritize_task': return { id:'1', priority: 150 };
// Algorithm config
case 'configure_time_decay': return { enabled:true, halfLifeDays: 7 };
case 'configure_effort_weighting': return { enabled:true, weight: 0.5 };
case 'show_algorithm_config': return {};
// Watcher
case 'start_file_watcher': return { debounceDelay: 100 };
case 'file_watcher_status': return {};
case 'stop_file_watcher': return {};
// Extra core
case 'generateTaskTable': return {};
// AI (gated)
case 'parsePrd': return { filePath: path.join(workspace, 'prd.md') };
case 'expandTask': return { taskId: '1' };
case 'reviseTasks': return { fromTaskId: '1', prompt:'Trim scope' };
default: return {};
}
};
async function callTool(name, args, opts = {}) {
if (opts.skip) return { skipped: true };
const req = { jsonrpc:'2.0', method:'tools/call', params:{ name, arguments: args } };
const res = await sendRequest(proc, req, opts.timeoutMs || 6000);
const text = res.result && res.result.content && res.result.content[0] ? res.result.content[0].text : '';
let obj; try { obj = JSON.parse(text); } catch(_) { obj = { raw: text }; }
return { req, res: obj };
}
// Ensure base files
fs.writeFileSync(path.join(workspace, 'a.txt'), 'hello');
// init project and create baseline task
await callTool('initProject', toolArgs('initProject'));
await callTool('addTask', toolArgs('addTask'));
// list tools
const toolsList = await sendRequest(proc, { jsonrpc:'2.0', method:'tools/list', params: {} });
const tools = toolsList.result.tools || [];
for (const t of tools) {
const name = t.name;
const isBrowser = name.startsWith('browser_');
const isApple = name === 'applescript_execute';
const isAI = name === 'parsePrd' || name === 'expandTask' || name === 'reviseTasks';
const skip = (isBrowser && !ENABLE_BROWSER) || (isApple && !ENABLE_APPLESCRIPT) || (isAI && !ENABLE_AI);
const args = toolArgs(name);
// For terminal session actions, seed a session first if needed
if ((name === 'read_output' || name === 'force_terminate' || name === 'kill_process') && args.pid === 0) {
try {
const started = await callTool('execute_command', toolArgs('execute_command'));
if (started && started.res && (started.res.pid || started.res.sessionId)) {
args.pid = started.res.pid;
}
} catch(_) {}
}
let info = { skipped: false, ok: false, req: null, res: null };
try {
const out = await callTool(name, args, { skip });
info = { skipped: !!out.skipped, ok: true, req: out.req, res: out.res };
} catch (e) {
info = { skipped: false, ok: false, req: { name, args }, res: { error: e.message } };
}
push(`## ${name}`);
if (skip) {
push('Skipped (gated by platform or missing credentials).');
push('');
continue;
}
push('Request');
push(reqBlock({ jsonrpc: '2.0', method:'tools/call', params: { name, arguments: args } }));
push('Response (truncated)');
push(resBlock(info.res));
push('');
}
const outPath = path.join(__dirname, '..', '..', 'docs', 'reference', 'mcp_examples.md');
fs.mkdirSync(path.dirname(outPath), { recursive: true });
fs.writeFileSync(outPath, lines.join('\n'));
try { proc.kill('SIGKILL'); } catch(_) {}
console.log(`[mcp-examples] Wrote ${outPath}`);
}
main().catch(err => { console.error('Generator failed:', err); process.exit(1); });