mirror of
https://github.com/gnh1201/welsonjs.git
synced 2026-04-18 18:18:42 +00:00
Add MCP JSON-RPC handlers and stdio fixes
Implement MCP JSON-RPC handling and related I/O fixes: mcploader now handles initialize, tools/list and tools/call (implements add_both_numbers) and returns JSON-RPC responses; stdio-server.send serializes object messages before writing; console logging on WScript now writes muted messages to StdErr; bump jsonrpc2 version to 0.1.7 and reformat extract(). These changes enable proper MCP capability negotiation, tool discovery and invocation over stdio.
This commit is contained in:
parent
43d945055f
commit
c22ca660ec
4
app.js
4
app.js
|
|
@ -48,6 +48,10 @@ var console = {
|
||||||
if (this._muted) return;
|
if (this._muted) return;
|
||||||
|
|
||||||
if (typeof WScript !== "undefined") {
|
if (typeof WScript !== "undefined") {
|
||||||
|
if (this._muted) {
|
||||||
|
WScript.StdErr.WriteLine("[*] " + params.message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
WScript.StdOut.WriteLine("[*] " + params.message);
|
WScript.StdOut.WriteLine("[*] " + params.message);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -39,52 +39,52 @@ function JsonRpc2(url) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function extract(message, callback) {
|
function extract(message, callback) {
|
||||||
var data;
|
var data;
|
||||||
|
|
||||||
if (typeof callback !== "function") {
|
if (typeof callback !== "function") {
|
||||||
throw new Error("Invalid callback");
|
throw new Error("Invalid callback");
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
data = JSON.parse(message);
|
data = JSON.parse(message);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
throw new Error("Invalid JSON: " + e.message);
|
throw new Error("Invalid JSON: " + e.message);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!data || typeof data !== "object") {
|
if (!data || typeof data !== "object") {
|
||||||
throw new Error("Invalid request object");
|
throw new Error("Invalid request object");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.jsonrpc !== "2.0") {
|
if (data.jsonrpc !== "2.0") {
|
||||||
throw new Error("Invalid JSON-RPC version");
|
throw new Error("Invalid JSON-RPC version");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!data.method || typeof data.method !== "string") {
|
if (!data.method || typeof data.method !== "string") {
|
||||||
throw new Error("Missing or invalid method");
|
throw new Error("Missing or invalid method");
|
||||||
}
|
}
|
||||||
|
|
||||||
var params = data.params !== undefined ? data.params : null;
|
var params = data.params !== undefined ? data.params : null;
|
||||||
var id = data.id !== undefined ? data.id : null;
|
var id = data.id !== undefined ? data.id : null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
var result = callback(data.method, params, id);
|
var result = callback(data.method, params, id);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
jsonrpc: "2.0",
|
jsonrpc: "2.0",
|
||||||
result: result === undefined ? null : result,
|
result: result === undefined ? null : result,
|
||||||
id: id
|
id: id
|
||||||
};
|
};
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return {
|
return {
|
||||||
jsonrpc: "2.0",
|
jsonrpc: "2.0",
|
||||||
error: {
|
error: {
|
||||||
code: -32603,
|
code: -32603,
|
||||||
message: e && e.message ? e.message : "Internal error"
|
message: e && e.message ? e.message : "Internal error"
|
||||||
},
|
},
|
||||||
id: id
|
id: id
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function wrap(method, params, id) {
|
function wrap(method, params, id) {
|
||||||
|
|
@ -108,7 +108,7 @@ exports.create = create;
|
||||||
|
|
||||||
exports.DEFAULT_JSONRPC2_URL = DEFAULT_JSONRPC2_URL;
|
exports.DEFAULT_JSONRPC2_URL = DEFAULT_JSONRPC2_URL;
|
||||||
|
|
||||||
exports.VERSIONINFO = "JSON-RPC 2.0 wrapper (jsonrpc2.js) version 0.1.6";
|
exports.VERSIONINFO = "JSON-RPC 2.0 wrapper (jsonrpc2.js) version 0.1.7";
|
||||||
exports.AUTHOR = "gnh1201@catswords.re.kr";
|
exports.AUTHOR = "gnh1201@catswords.re.kr";
|
||||||
exports.global = global;
|
exports.global = global;
|
||||||
exports.require = global.require;
|
exports.require = global.require;
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,13 @@ function StdioServer() {
|
||||||
};
|
};
|
||||||
|
|
||||||
this.send = function (message) {
|
this.send = function (message) {
|
||||||
|
if (typeof message === "object") {
|
||||||
|
try {
|
||||||
|
var _serialized = JSON.stringify(message);
|
||||||
|
message = _serialized;
|
||||||
|
} catch (e) { /* ignore */ };
|
||||||
|
}
|
||||||
|
|
||||||
WScript.StdOut.WriteLine(message);
|
WScript.StdOut.WriteLine(message);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
82
mcploader.js
82
mcploader.js
|
|
@ -7,24 +7,78 @@ var StdioServer = require("lib/stdio-server");
|
||||||
var JsonRpc2 = require("lib/jsonrpc2");
|
var JsonRpc2 = require("lib/jsonrpc2");
|
||||||
|
|
||||||
function main(args) {
|
function main(args) {
|
||||||
var server = StdioServer.create();
|
var server = StdioServer.create();
|
||||||
|
|
||||||
server.addEventListener("message", function(e) {
|
server.addEventListener("message", function(e) {
|
||||||
var message = e.target.receive();
|
var message = e.target.receive();
|
||||||
|
|
||||||
try {
|
e.target.send(
|
||||||
JsonRpc2.extract(message, function(method, params, id) {
|
JsonRpc2.extract(message, function (method, params, id) {
|
||||||
console.log("Received method: " + method);
|
if (method == "initialize") {
|
||||||
});
|
return {
|
||||||
} catch (e) {
|
"protocolVersion": "2025-11-25",
|
||||||
console.log("Ignored");
|
"capabilities": {
|
||||||
}
|
"extensions": {
|
||||||
|
"io.modelcontextprotocol/ui": {
|
||||||
|
"mimeTypes": ["text/html;profile=mcp-app"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"serverInfo": {
|
||||||
|
"name": "WelsonJS MCP",
|
||||||
|
"version": "1.0.0"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// send message
|
if (method == "tools/list") {
|
||||||
e.target.send("Hello world");
|
return {
|
||||||
});
|
"tools": [
|
||||||
|
{
|
||||||
|
"name": "add_both_numbers",
|
||||||
|
"title": "add both_numbers (add A and B)",
|
||||||
|
"description": "add two numbers (add A and B)",
|
||||||
|
"inputSchema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"a": {
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
"b": {
|
||||||
|
"type": "number"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["a", "b"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
server.listen();
|
if (method == "tools/call") {
|
||||||
|
var function_calling_name = params.name;
|
||||||
|
|
||||||
|
if (function_calling_name == "add_both_numbers") {
|
||||||
|
return {
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"text": "Result is " + (parseFloat(params.arguments.a) + parseFloat(params.arguments.b))
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"isError": false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
"isError": true
|
||||||
|
};
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
server.listen();
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.main = main;
|
exports.main = main;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user