MCPcopy
hub / github.com/Doorman11991/smallcode / handleMCPToolCall

Function handleMCPToolCall

bin/smallcode.js:2884–2955  ·  view source on GitHub ↗
(id, params)

Source from the content-addressed store, hash-verified

2882}
2883
2884async function handleMCPToolCall(id, params) {
2885 const { name, arguments: args } = params;
2886 const { safeResolvePath, escapeShellArg, sanitizeToolOutput } = require('../src/security/sanitize');
2887 const cwd = process.cwd();
2888 let result = '';
2889
2890 switch (name) {
2891 case 'smallcode_read_file': {
2892 const safe = safeResolvePath(args.path, cwd);
2893 if (!safe.ok) return { jsonrpc: '2.0', id, result: { content: [{ type: 'text', text: `Error: ${safe.reason}` }], isError: true }};
2894 try { result = sanitizeToolOutput(fs.readFileSync(safe.fullPath, 'utf-8')); }
2895 catch (e) { return { jsonrpc: '2.0', id, result: { content: [{ type: 'text', text: `Error: ${e.message}` }], isError: true }}; }
2896 break;
2897 }
2898 case 'smallcode_bash': {
2899 const { execSync } = require('child_process');
2900 const command = String(args.command || '');
2901 // Apply same blocked-command checks as the agent's bash tool
2902 if (/rm\s+-rf\s+\/[^.]/.test(command) || /format\s+c:/i.test(command)) {
2903 return { jsonrpc: '2.0', id, result: { content: [{ type: 'text', text: 'Error: destructive command blocked' }], isError: true }};
2904 }
2905 try {
2906 const output = execSync(command, { encoding: 'utf-8', timeout: 30000, cwd, maxBuffer: 1024 * 1024 });
2907 result = sanitizeToolOutput(output).slice(0, 4000);
2908 } catch (e) { result = sanitizeToolOutput((e.stdout || '') + (e.stderr || e.message || '')).slice(0, 2000); }
2909 break;
2910 }
2911 case 'smallcode_search': {
2912 const { execSync } = require('child_process');
2913 const pattern = String(args.pattern || '');
2914 const searchPath = args.path ? safeResolvePath(args.path, cwd) : { ok: true, fullPath: '.' };
2915 if (!searchPath.ok) { result = `Error: ${searchPath.reason}`; break; }
2916 try {
2917 const cmd = 'rg --line-number --max-count 10 ' + escapeShellArg(pattern) + ' ' + escapeShellArg(searchPath.fullPath || '.');
2918 result = sanitizeToolOutput(execSync(cmd, { encoding: 'utf-8', timeout: 10000, cwd })).slice(0, 3000);
2919 } catch { result = 'No matches'; }
2920 break;
2921 }
2922 case 'smallcode_patch': {
2923 const safe = safeResolvePath(args.path, cwd);
2924 if (!safe.ok) { result = `Error: ${safe.reason}`; break; }
2925 try {
2926 let content = fs.readFileSync(safe.fullPath, 'utf-8');
2927 if (!content.includes(args.old_str)) { result = 'Error: old_str not found'; break; }
2928 const count = content.split(args.old_str).length - 1;
2929 if (count > 1) { result = `Error: old_str matches ${count} locations`; break; }
2930 content = content.replace(args.old_str, args.new_str);
2931 fs.writeFileSync(safe.fullPath, content);
2932 result = `Patched ${args.path}`;
2933 } catch (e) { result = `Error: ${e.message}`; }
2934 break;
2935 }
2936 case 'smallcode_memory_load': {
2937 const objects = memoryStore.loadForTask(args.task || '', 2000);
2938 // Handle both array return (MemoryStore in memory.js) and {objects} return
2939 const items = Array.isArray(objects) ? objects : (objects?.objects || []);
2940 result = items.length > 0
2941 ? items.map(o => `[${o.type}] ${o.title}: ${o.content}`).join('\n\n')

Callers 1

handleMCPRequestFunction · 0.85

Calls 5

safeResolvePathFunction · 0.85
sanitizeToolOutputFunction · 0.85
escapeShellArgFunction · 0.85
loadForTaskMethod · 0.80
rememberMethod · 0.80

Tested by

no test coverage detected