diff --git a/MCP-server.md b/MCP-server.md index e7f8ce3..f3f6d82 100644 --- a/MCP-server.md +++ b/MCP-server.md @@ -1,33 +1,234 @@ -# MCP Server +# Building an MCP Server Using Only Notepad -The MCP server feature is currently available **experimentally**. It can be executed using the built-in JavaScript engine without installing any additional components. +One day, a realization came to me. -## Setup +Recently, there has been growing interest in MCP (Model Context Protocol), but seeing setups that require installing Node.js, Python, VS Code, and similar tools felt unnecessarily heavy. More importantly, this is not what our enterprise customers want. -1. **Download the `dev` or `master` branch** +So I asked myself: _What if we could do this using only Notepad?_ -2. **Configure your MCP client (e.g., Claude)** +Yes! the default **Notepad** application that comes pre-installed on Windows. + +It was time to verify whether it is possible to build an MCP server using nothing but Notepad. + +*** + +## Leveraging Built-in Programming Engines + +As demonstrated by the WelsonJS framework, there are environments where the use of external development tools is severely restricted. + +In such cases, projects rely on **programming-capable engines already built into the operating system** and maximize their use for software development. + +Following this approach, we decided to implement a fully functional MCP server using only the **built-in JavaScript engine provided by the OS**, without any external tooling. + +*** + +## Understanding the MCP Protocol + +The primary communication method supported by MCP clients (e.g., Claude Desktop) is: + +* **Standard Input/Output (stdio)** +* **JSON-RPC 2.0** + +In other words, an MCP server can be implemented by satisfying just two requirements: + +1. A **stdio-based communication channel** +2. Compliance with the **JSON-RPC 2.0 specification** + +### Communication Flow + +* **Request** + MCP Client → Stdin (JSON-RPC 2.0 request) → MCP Server + +* **Response** + MCP Client ← Stdout (JSON-RPC 2.0 response) ← MCP Server + +*** + +## Handling stdio Constraints + +One important consideration is that stdio is often already used for console output (e.g., logs, debug messages). + +To safely use stdio as a communication channel, it is essential to prevent such messages from corrupting the data stream. + +In this implementation, the issue was resolved by introducing a **quiet mode option** (e.g., `/quiet`) to suppress auxiliary console output. + +*** + +## Implementing the MCP Server + +Using the WelsonJS framework, we can build an MCP server with the pre-implemented: + +* `StdioServer` +* `JsonRpc2` + +This example supports the following functions: + +* `add_both_numbers` — Adds two numbers +* `evaluate_js_es3` — Executes JavaScript (ES3 syntax) + +Save the following file as `mcploader.js`: + +```javascript +// mcploader.js +// Copyright 2019-2026, Namhyeon Go and the WelsonJS contributors. +// SPDX-License-Identifier: GPL-3.0-or-later +// https://github.com/gnh1201/welsonjs +// +var StdioServer = require("lib/stdio-server"); +var JsonRpc2 = require("lib/jsonrpc2"); + +function main(args) { + var server = StdioServer.create(); + + server.addEventListener("message", function(e) { + var message = e.target.receive(); + + e.target.send( + JsonRpc2.extract(message, function (method, params, id) { + var isError = false; + + if (method == "initialize") { + return { + "protocolVersion": "2025-11-25", + "capabilities": { + "extensions": { + "io.modelcontextprotocol/ui": { + "mimeTypes": ["text/html;profile=mcp-app"] + } + } + }, + "serverInfo": { + "name": "WelsonJS MCP", + "version": "1.0.0" + }, + "isError": isError + }; + } + + if (method === "notifications/initialized") { + return false; + } + + if (method == "tools/list") { + 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"] + } + }, + { + "name": "evaluate_js_es3", + "title": "Evaluate JavaScript ES3", + "description": "Evaluate JavaScript with ES3 syntax (use ES3 syntax strictly)", + "inputSchema": { + "type": "object", + "properties": { + "script": { "type": "string" } + }, + "required": ["script"] + } + } + ], + "isError": isError + }; + } + + 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": isError + }; + } + + if (function_calling_name == "evaluate_js_es3") { + return { + "content": [ + { + "type": "text", + "text": (function(script) { + try { + return String(eval(script)); + } catch (e) { + return "Error"; + isError = true; + } + })(params.arguments.script) + } + ] + } + } + } + + isError = true; + return { "isError": isError }; + }) + ); + }); + + server.listen(); +} + +exports.main = main; +``` + +*** + +## Registering the MCP Server in Claude Desktop + +Add the following configuration to `claude_desktop_config.json`: ```json -"mcpServers": { - "local-tools": { - "command": "cscript", - "args": [ - "/nologo", - "/app.js", - "mcploader", - "/quiet" - ] +{ + "mcpServers": { + "local-tools": { + "command": "C:/Windows/SysWOW64/cscript", + "args": [ + "/nologo", + "YOUR_INSTALLATION_PATH/welsonjs/app.js", + "mcploader", + "/quiet" + ] + } } } -```` +``` + +After restarting Claude Desktop, verify that `local-tools` is running via the Developer Settings menu. + +*** + +## Testing the MCP Server + +You can now test the server directly from the Claude Desktop chat interface: + +* Request: _“Add two numbers”_ → invokes `add_both_numbers` +* Request: _“Run a JavaScript ES3 example”_ → invokes `evaluate_js_es3` + +The corresponding results will be returned via the MCP server. -3. **Customize your functions**: You can modify the `mcploader.js` file to add your own custom functions. -4. **Start using MCP** ## Screenshots +Although Notepad++, a more advanced alternative to Windows Notepad, was used in the screenshot, the built in Windows Notepad alone is fully sufficient for practical use. :laughing: + \ No newline at end of file