From 00adebe208dc78496c83758902dec332bc7fc801 Mon Sep 17 00:00:00 2001 From: hanishkvc Date: Sun, 7 Dec 2025 22:25:33 +0530 Subject: [PATCH] SimpleSallap:ToolMCP:McpishClient:P2:Initial go wrt tools/call Also fix some minor oversights wrt tools/list --- tools/server/public_simplechat/toolmcp.mjs | 165 +++++++-------------- 1 file changed, 53 insertions(+), 112 deletions(-) diff --git a/tools/server/public_simplechat/toolmcp.mjs b/tools/server/public_simplechat/toolmcp.mjs index b10487a6e1..b034d03c4b 100644 --- a/tools/server/public_simplechat/toolmcp.mjs +++ b/tools/server/public_simplechat/toolmcp.mjs @@ -1,6 +1,6 @@ //@ts-check -// ALERT - Simple Stupid flow - Using from a discardable VM is better -// simple mcpish client to handle tool/function calling provided by bundled simplemcp.py server logic. +// ALERT - Simple minded flow - Using from a discardable VM is better. +// Simple mcpish client to handle tool/function calling provided by bundled simplemcp.py server logic. // Currently it provides tool calls related to local/web access, pdf, etal // by Humans for All // @@ -32,47 +32,66 @@ async function bearer_transform(chat) { return Array.from(new Uint8Array(ab)).map(b => b.toString(16).padStart(2, '0')).join(''); } + /** - * Helper http get logic wrt the bundled SimpleProxy server, - * which helps execute a given proxy dependent tool call. - * Expects the simple minded proxy server to be running locally - * * listening on a configured port - * * expecting http requests - * * with a predefined query token and value wrt a predefined path - * NOTE: Initial go, handles textual data type. - * ALERT: Accesses a seperate/external web proxy/caching server, be aware and careful + * Implements tool call execution through a mcpish server. Initial go. + * NOTE: Currently only uses textual contents in the result. + * NOTE: Currently the logic is setup to work with bundled simplemcp.py + * ALERT: Accesses a seperate/external mcpish server, be aware and careful * @param {string} chatid * @param {string} toolcallid * @param {string} toolname - * @param {any} objSearchParams - * @param {string} path - * @param {any} objHeaders + * @param {any} obj */ -async function proxyserver_get_anyargs(chatid, toolcallid, toolname, objSearchParams, path, objHeaders={}) { +async function mcpserver_toolcall(chatid, toolcallid, toolname, obj) { let chat = gMe.multiChat.simpleChats[chatid] - if (gMe.toolsMgr.workers.js.onmessage != null) { - let params = new URLSearchParams(objSearchParams) - let newUrl = `${chat.cfg.tools.proxyUrl}/${path}?${params}` - let headers = new Headers(objHeaders) + if (gMe.toolsMgr.workers.js.onmessage == null) { + return + } + try { + let newUrl = `${chat.cfg.tools.proxyUrl}/mcp` + let headers = new Headers(); let btoken = await bearer_transform(chat) headers.append('Authorization', `Bearer ${btoken}`) - fetch(newUrl, { headers: headers}).then(resp => { - if (!resp.ok) { - throw new Error(`${resp.status}:${resp.statusText}`); + headers.append("Content-Type", "application/json") + let ibody = { + jsonrpc: "2.0", + id: toolcallid, + method: "tools/call", + params: { + name: toolname, + arguments: obj } - return resp.text() - }).then(data => { - gMe.toolsMgr.workers_postmessage_for_main(gMe.toolsMgr.workers.js, chatid, toolcallid, toolname, data); - }).catch((err)=>{ - gMe.toolsMgr.workers_postmessage_for_main(gMe.toolsMgr.workers.js, chatid, toolcallid, toolname, `Error:${err}`); - }) + } + let resp = await fetch(newUrl, { + method: "POST", + headers: headers, + body: JSON.stringify(ibody), + }); + if (!resp.ok) { + throw new Error(`${resp.status}:${resp.statusText}`); + } + let obody = await resp.json() + let textResult = "" + if ((obody.result) && (obody.result.content)) { + for(const tcr of obody.result.content) { + if (!tcr.text) { + continue + } + textResult += `\n\n${tcr.text}` + } + } + gMe.toolsMgr.workers_postmessage_for_main(gMe.toolsMgr.workers.js, chatid, toolcallid, toolname, textResult); + } catch (err) { + gMe.toolsMgr.workers_postmessage_for_main(gMe.toolsMgr.workers.js, chatid, toolcallid, toolname, `Error:${err}`); } } /** - * fetch supported tool calls meta data. - * NOTE: Currently the logic is setup for the bundled simplemcp.py + * Fetch supported tool calls meta data from a mcpish server. + * NOTE: Currently the logic is setup to work with bundled simplemcp.py + * ALERT: Accesses a seperate/external mcpish server, be aware and careful * @param {string} tag * @param {string} chatId * @param {mToolsMgr.TCSwitch} tcs @@ -89,6 +108,8 @@ async function mcpserver_toolslist(tag, chatId, tcs) { method: "tools/list" } let headers = new Headers(); + let btoken = await bearer_transform(chat) + headers.append('Authorization', `Bearer ${btoken}`) headers.append("Content-Type", "application/json") let resp = await fetch(`${chat.cfg.tools.proxyUrl}/mcp`, { method: "POST", @@ -100,8 +121,8 @@ async function mcpserver_toolslist(tag, chatId, tcs) { return } let obody = await resp.json() - if ((obody.results) && (obody.results.tools)) { - for(const tcmeta of obody.results.tools) { + if ((obody.result) && (obody.result.tools)) { + for(const tcmeta of obody.result.tools) { if (!tcmeta.function) { continue } @@ -119,86 +140,6 @@ async function mcpserver_toolslist(tag, chatId, tcs) { } -// -// Search Web Text -// - - -let searchwebtext_meta = { - "type": "function", - "function": { - "name": "search_web_text", - "description": "search web for given words and return the plain text content after stripping the html tags as well as head, script, style, header, footer, nav blocks from got html result page, in few seconds", - "parameters": { - "type": "object", - "properties": { - "words":{ - "type":"string", - "description":"the words to search for on the web" - } - }, - "required": ["words"] - } - } - } - - -/** - * Implementation of the search web text logic. Initial go. - * Builds on htmltext path service of the bundled simpleproxy.py. - * ALERT: Accesses a seperate/external web proxy/caching server, be aware and careful - * @param {string} chatid - * @param {string} toolcallid - * @param {string} toolname - * @param {any} obj - */ -function searchwebtext_run(chatid, toolcallid, toolname, obj) { - let chat = gMe.multiChat.simpleChats[chatid] - /** @type {string} */ - let searchUrl = chat.cfg.tools.searchUrl; - searchUrl = searchUrl.replace("SEARCHWORDS", encodeURIComponent(obj.words)); - delete(obj.words) - obj['url'] = searchUrl - let headers = { 'htmltext-tag-drops': JSON.stringify(chat.cfg.tools.searchDrops) } - return proxyserver_get_anyargs(chatid, toolcallid, toolname, obj, 'htmltext', headers); -} - - -/** - * Setup search_web_text for tool calling - * NOTE: Currently the logic is setup for the bundled simpleproxy.py - * @param {mToolsMgr.TCSwitch} tcs - * @param {string} chatId - */ -async function searchwebtext_setup(tcs, chatId) { - return proxyserver_tc_setup('SearchWebText', chatId, 'htmltext', 'search_web_text', { - "handler": searchwebtext_run, - "meta": searchwebtext_meta, - "result": "" - }, tcs); -} - - -function fetchpdftext_run(chatid, toolcallid, toolname, obj) { - return proxyserver_get_anyargs(chatid, toolcallid, toolname, obj, 'pdftext'); -} - - -/** - * Setup fetchpdftext for tool calling - * NOTE: Currently the logic is setup for the bundled simpleproxy.py - * @param {mToolsMgr.TCSwitch} tcs - * @param {string} chatId - */ -async function fetchpdftext_setup(tcs, chatId) { - return proxyserver_tc_setup('FetchPdfAsText', chatId, 'pdftext', 'fetch_pdf_as_text', { - "handler": fetchpdftext_run, - "meta": fetchpdftext_meta, - "result": "" - }, tcs); -} - - // // Entry point // @@ -223,7 +164,7 @@ export async function init(me) { */ export async function setup(chatId) { /** - * @type {mToolsMgr.TCSwitch} tcs + * @type {mToolsMgr.TCSwitch} */ let tc_switch = {} await mcpserver_toolslist("ToolMCP", chatId, tc_switch)