SimpleSallap:ToolMCP: Initial skeletons at mcpish client
Add logic to fetch tools/list from mcp server and pass it to tools manager.
This commit is contained in:
parent
5f895b8abf
commit
091262d8cf
|
|
@ -1,18 +1,14 @@
|
||||||
//@ts-check
|
//@ts-check
|
||||||
// ALERT - Simple Stupid flow - Using from a discardable VM is better
|
// ALERT - Simple Stupid flow - Using from a discardable VM is better
|
||||||
// Helpers to handle tools/functions calling related to local/web access, pdf, etal
|
// simple mcpish client to handle tool/function calling provided by bundled simplemcp.py server logic.
|
||||||
// which work in sync with the bundled simpleproxy.py server logic.
|
// Currently it provides tool calls related to local/web access, pdf, etal
|
||||||
// Uses the js specific web worker path.
|
|
||||||
// by Humans for All
|
// by Humans for All
|
||||||
//
|
//
|
||||||
|
|
||||||
//
|
//
|
||||||
// The simpleproxy.py server is expected to provide the below services
|
// The simplemcp.py mcpish server is expected to provide the below on /mcp service path
|
||||||
// urlraw - fetch the request url content as is
|
// tools/list - to get the meta of list of functions supported through simplemcp
|
||||||
// htmltext - fetch the requested html content and provide plain text version
|
// tools/call - to run the specified tool call
|
||||||
// after stripping it of tag blocks like head, script, style, header, footer, nav, ...
|
|
||||||
// pdftext - fetch the requested pdf and provide the plain text version
|
|
||||||
// xmlfiltered - fetch the requested xml content and provide a optionally filtered version of same
|
|
||||||
//
|
//
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -75,140 +71,51 @@ async function proxyserver_get_anyargs(chatid, toolcallid, toolname, objSearchPa
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Setup a proxy server dependent tool call
|
* fetch supported tool calls meta data.
|
||||||
* NOTE: Currently the logic is setup for the bundled simpleproxy.py
|
* NOTE: Currently the logic is setup for the bundled simplemcp.py
|
||||||
* @param {string} tag
|
* @param {string} tag
|
||||||
* @param {string} chatId
|
* @param {string} chatId
|
||||||
* @param {string} tcPath
|
|
||||||
* @param {string} tcName
|
|
||||||
* @param {{ [x: string]: any; }} tcsData
|
|
||||||
* @param {mToolsMgr.TCSwitch} tcs
|
* @param {mToolsMgr.TCSwitch} tcs
|
||||||
*/
|
*/
|
||||||
async function proxyserver_tc_setup(tag, chatId, tcPath, tcName, tcsData, tcs) {
|
async function mcpserver_toolslist(tag, chatId, tcs) {
|
||||||
tag = `${tag}:${chatId}`
|
tag = `${tag}:${chatId}`
|
||||||
let chat = gMe.multiChat.simpleChats[chatId]
|
try {
|
||||||
await fetch(`${chat.cfg.tools.proxyUrl}/aum?url=${tcPath}.jambudweepe.akashaganga.multiverse.987654321123456789`).then(resp=>{
|
let chat = gMe.multiChat.simpleChats[chatId]
|
||||||
if (resp.statusText != 'bharatavarshe') {
|
|
||||||
console.log(`WARN:ToolWeb:${tag}:Dont forget to run the bundled local.tools/simpleproxy.py to enable me`)
|
let id = new Date().getTime()
|
||||||
|
let ibody = {
|
||||||
|
jsonrpc: "2.0",
|
||||||
|
id: id,
|
||||||
|
method: "tools/list"
|
||||||
|
}
|
||||||
|
let headers = new Headers();
|
||||||
|
headers.append("Content-Type", "application/json")
|
||||||
|
let resp = await fetch(`${chat.cfg.tools.proxyUrl}/mcp`, {
|
||||||
|
method: "POST",
|
||||||
|
headers: headers,
|
||||||
|
body: JSON.stringify(ibody),
|
||||||
|
});
|
||||||
|
if (resp.status != 200) {
|
||||||
|
console.log`WARN:${tag}:ToolsList:MCP server says:${resp.status}:${resp.statusText}`
|
||||||
return
|
return
|
||||||
} else {
|
|
||||||
console.log(`INFO:ToolWeb:${tag}:Enabling...`)
|
|
||||||
}
|
}
|
||||||
tcs[tcName] = tcsData;
|
let obody = await resp.json()
|
||||||
}).catch(err=>console.log(`WARN:ToolWeb:${tag}:ProxyServer missing?:${err}\nDont forget to run the bundled local.tools/simpleproxy.py`))
|
if ((obody.results) && (obody.results.tools)) {
|
||||||
}
|
for(const tcmeta of obody.results.tools) {
|
||||||
|
if (!tcmeta.function) {
|
||||||
|
continue
|
||||||
//
|
}
|
||||||
// Fetch Url Raw
|
console.log`INFO:${tag}:ToolsList:${tcmeta.function.name}`
|
||||||
//
|
tcs[tcmeta.function.name] = {
|
||||||
|
"handler": mcpserver_toolcall,
|
||||||
|
"meta": tcmeta,
|
||||||
let fetchurlraw_meta = {
|
"result": ""
|
||||||
"type": "function",
|
}
|
||||||
"function": {
|
|
||||||
"name": "fetch_url_raw",
|
|
||||||
"description": "Fetch contents of the requested url (local file path / web based) through a proxy server and return the got content as is, in few seconds. Mainly useful for getting textual non binary contents",
|
|
||||||
"parameters": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"url":{
|
|
||||||
"type":"string",
|
|
||||||
"description":"url of the local file / web content to fetch"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": ["url"]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.log(`ERRR:${tag}:ToolsList:MCP server hs failed:${err}\nDont forget to run bundled local.tools/simplemcp.py`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Implementation of the fetch url raw logic.
|
|
||||||
* Expects a simple minded proxy server to be running locally
|
|
||||||
* * listening on a configured port
|
|
||||||
* * expecting http requests
|
|
||||||
* * with a query token named url wrt the path urlraw
|
|
||||||
* which gives the actual url to fetch
|
|
||||||
* 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 fetchurlraw_run(chatid, toolcallid, toolname, obj) {
|
|
||||||
// maybe filter out any key other than 'url' in obj
|
|
||||||
return proxyserver_get_anyargs(chatid, toolcallid, toolname, obj, 'urlraw');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Setup fetch_url_raw for tool calling
|
|
||||||
* NOTE: Currently the logic is setup for the bundled simpleproxy.py
|
|
||||||
* @param {mToolsMgr.TCSwitch} tcs
|
|
||||||
* @param {string} chatId
|
|
||||||
*/
|
|
||||||
async function fetchurlraw_setup(tcs, chatId) {
|
|
||||||
return proxyserver_tc_setup('FetchUrlRaw', chatId, 'urlraw', 'fetch_url_raw', {
|
|
||||||
"handler": fetchurlraw_run,
|
|
||||||
"meta": fetchurlraw_meta,
|
|
||||||
"result": ""
|
|
||||||
}, tcs);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// Fetch html Text
|
|
||||||
//
|
|
||||||
|
|
||||||
|
|
||||||
let fetchhtmltext_meta = {
|
|
||||||
"type": "function",
|
|
||||||
"function": {
|
|
||||||
"name": "fetch_html_text",
|
|
||||||
"description": "Fetch html content from given url through a proxy server and return its text content after stripping away the html tags as well as head, script, style, header, footer, nav blocks, in few seconds",
|
|
||||||
"parameters": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"url":{
|
|
||||||
"type":"string",
|
|
||||||
"description":"url of the html page that needs to be fetched and inturn unwanted stuff stripped from its contents to some extent"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": ["url"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Implementation of the fetch html text logic.
|
|
||||||
* Expects the simple minded simpleproxy server to be running locally,
|
|
||||||
* providing service for htmltext path.
|
|
||||||
* 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 fetchhtmltext_run(chatid, toolcallid, toolname, obj) {
|
|
||||||
// maybe filter out any key other than 'url' in obj
|
|
||||||
return proxyserver_get_anyargs(chatid, toolcallid, toolname, obj, 'htmltext');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Setup fetch_html_text for tool calling
|
|
||||||
* NOTE: Currently the logic is setup for the bundled simpleproxy.py
|
|
||||||
* @param {mToolsMgr.TCSwitch} tcs
|
|
||||||
* @param {string} chatId
|
|
||||||
*/
|
|
||||||
async function fetchhtmltext_setup(tcs, chatId) {
|
|
||||||
return proxyserver_tc_setup('FetchHtmlText', chatId, 'htmltext', 'fetch_html_text', {
|
|
||||||
"handler": fetchhtmltext_run,
|
|
||||||
"meta": fetchhtmltext_meta,
|
|
||||||
"result": ""
|
|
||||||
}, tcs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -272,52 +179,6 @@ async function searchwebtext_setup(tcs, chatId) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// FetchPdfText
|
|
||||||
//
|
|
||||||
|
|
||||||
|
|
||||||
let fetchpdftext_meta = {
|
|
||||||
"type": "function",
|
|
||||||
"function": {
|
|
||||||
"name": "fetch_pdf_as_text",
|
|
||||||
"description": "Fetch pdf from requested local file path / web url through a proxy server and return its text content after converting pdf to text, in few seconds. One is allowed to get a part of the pdf by specifying the starting and ending page numbers",
|
|
||||||
"parameters": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"url":{
|
|
||||||
"type":"string",
|
|
||||||
"description":"local file path (file://) / web (http/https) based url of the pdf that will be got and inturn converted to text"
|
|
||||||
},
|
|
||||||
"startPageNumber":{
|
|
||||||
"type":"integer",
|
|
||||||
"description":"Specify the starting page number within the pdf, this is optional. If not specified set to first page."
|
|
||||||
},
|
|
||||||
"endPageNumber":{
|
|
||||||
"type":"integer",
|
|
||||||
"description":"Specify the ending page number within the pdf, this is optional. If not specified set to the last page."
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"required": ["url"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Implementation of the fetch pdf as text logic.
|
|
||||||
* Expects a simple minded proxy server to be running locally
|
|
||||||
* * listening on a configured port
|
|
||||||
* * expecting http requests
|
|
||||||
* * with a query token named url wrt pdftext path,
|
|
||||||
* which gives the actual url to fetch
|
|
||||||
* * gets the requested pdf and converts to text, before returning same.
|
|
||||||
* 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 fetchpdftext_run(chatid, toolcallid, toolname, obj) {
|
function fetchpdftext_run(chatid, toolcallid, toolname, obj) {
|
||||||
return proxyserver_get_anyargs(chatid, toolcallid, toolname, obj, 'pdftext');
|
return proxyserver_get_anyargs(chatid, toolcallid, toolname, obj, 'pdftext');
|
||||||
}
|
}
|
||||||
|
|
@ -338,86 +199,14 @@ async function fetchpdftext_setup(tcs, chatId) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// Fetch XML Filtered
|
|
||||||
//
|
|
||||||
|
|
||||||
|
|
||||||
let gRSSTagDropsDefault = [
|
|
||||||
"^rss:channel:item:guid:.*",
|
|
||||||
"^rss:channel:item:link:.*",
|
|
||||||
"^rss:channel:item:description:.*",
|
|
||||||
".*:image:.*",
|
|
||||||
".*:enclosure:.*"
|
|
||||||
];
|
|
||||||
|
|
||||||
let fetchxmlfiltered_meta = {
|
|
||||||
"type": "function",
|
|
||||||
"function": {
|
|
||||||
"name": "fetch_xml_filtered",
|
|
||||||
"description": "Fetch requested xml url through a proxy server that can optionally filter out unwanted tags and their contents. Will take few seconds",
|
|
||||||
"parameters": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"url":{
|
|
||||||
"type":"string",
|
|
||||||
"description":"url of the xml file that will be fetched"
|
|
||||||
},
|
|
||||||
"tagDropREs":{
|
|
||||||
"type":"string",
|
|
||||||
"description":`Optionally specify a json stringified list of xml tag heirarchies to drop.
|
|
||||||
For each tag that needs to be dropped, one needs to specify regular expression of the heirarchy of tags involved,
|
|
||||||
where the tag names are always mentioned in lower case along with a : as suffix.
|
|
||||||
For example for rss feeds one could use ${JSON.stringify(gRSSTagDropsDefault)} and so...`
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": ["url"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Implementation of the fetch xml filtered logic.
|
|
||||||
* Expects simpleproxy to be running at specified url and providing xmltext service
|
|
||||||
* 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 fetchxmlfiltered_run(chatid, toolcallid, toolname, obj) {
|
|
||||||
let tagDropREs = obj.tagDropREs
|
|
||||||
if (tagDropREs == undefined) {
|
|
||||||
tagDropREs = JSON.stringify([]) // JSON.stringify(gRSSTagDropsDefault)
|
|
||||||
}
|
|
||||||
let headers = { 'xmlfiltered-tagdrop-res': tagDropREs }
|
|
||||||
return proxyserver_get_anyargs(chatid, toolcallid, toolname, obj, 'xmlfiltered', headers);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Setup fetch_xml_filtered for tool calling
|
|
||||||
* NOTE: Currently the logic is setup for the bundled simpleproxy.py
|
|
||||||
* @param {mToolsMgr.TCSwitch} tcs
|
|
||||||
* @param {string} chatId
|
|
||||||
*/
|
|
||||||
async function fetchxmlfiltered_setup(tcs, chatId) {
|
|
||||||
return proxyserver_tc_setup('FetchXmlFiltered', chatId, 'xmlfiltered', 'fetch_xml_filtered', {
|
|
||||||
"handler": fetchxmlfiltered_run,
|
|
||||||
"meta": fetchxmlfiltered_meta,
|
|
||||||
"result": ""
|
|
||||||
}, tcs);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Entry point
|
// Entry point
|
||||||
//
|
//
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to get hold of the web worker to use for running tool/function call related code.
|
* Used to get hold of the global Me instance, and through it
|
||||||
|
* the toolsManager and chat settings ...
|
||||||
* @param {mChatMagic.Me} me
|
* @param {mChatMagic.Me} me
|
||||||
*/
|
*/
|
||||||
export async function init(me) {
|
export async function init(me) {
|
||||||
|
|
@ -429,7 +218,7 @@ export async function init(me) {
|
||||||
* Return the tool call switch with supported / enabled / available tool calls
|
* Return the tool call switch with supported / enabled / available tool calls
|
||||||
* Allows to verify / setup tool calls, which need to cross check things at runtime
|
* Allows to verify / setup tool calls, which need to cross check things at runtime
|
||||||
* before getting allowed, like maybe bcas they depend on a config wrt specified
|
* before getting allowed, like maybe bcas they depend on a config wrt specified
|
||||||
* chat session.
|
* chat session or handshake with mcpish server in this case and so...
|
||||||
* @param {string} chatId
|
* @param {string} chatId
|
||||||
*/
|
*/
|
||||||
export async function setup(chatId) {
|
export async function setup(chatId) {
|
||||||
|
|
@ -437,10 +226,6 @@ export async function setup(chatId) {
|
||||||
* @type {mToolsMgr.TCSwitch} tcs
|
* @type {mToolsMgr.TCSwitch} tcs
|
||||||
*/
|
*/
|
||||||
let tc_switch = {}
|
let tc_switch = {}
|
||||||
await fetchurlraw_setup(tc_switch, chatId)
|
await mcpserver_toolslist("ToolMCP", chatId, tc_switch)
|
||||||
await fetchhtmltext_setup(tc_switch, chatId)
|
|
||||||
await searchwebtext_setup(tc_switch, chatId)
|
|
||||||
await fetchpdftext_setup(tc_switch, chatId)
|
|
||||||
await fetchxmlfiltered_setup(tc_switch, chatId)
|
|
||||||
return tc_switch
|
return tc_switch
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue