@nataliapc/mcp-openmsx 1.1.15 → 1.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (190) hide show
  1. package/README.md +25 -14
  2. package/dist/server.js +73 -24
  3. package/dist/utils.js +10 -2
  4. package/dist/vectordb.js +60 -0
  5. package/package.json +8 -3
  6. package/resources/audio/msx-midi.md +872 -0
  7. package/resources/audio/psg_registers.md +281 -0
  8. package/resources/audio/sound_cartridge_scc.md +123 -0
  9. package/resources/audio/sound_cartridge_scci.md +250 -0
  10. package/resources/audio/toc.json +8 -4
  11. package/resources/book--msx2-technical-handbook/toc.json +1 -1
  12. package/resources/msx-unapi/toc.json +2 -2
  13. package/resources/programming/basic_wiki/ABS().md +36 -0
  14. package/resources/programming/basic_wiki/AND.md +71 -0
  15. package/resources/programming/basic_wiki/ASC().md +38 -0
  16. package/resources/programming/basic_wiki/ATN().md +36 -0
  17. package/resources/programming/basic_wiki/AUTO.md +39 -0
  18. package/resources/programming/basic_wiki/BASE().md +147 -0
  19. package/resources/programming/basic_wiki/BEEP.md +27 -0
  20. package/resources/programming/basic_wiki/BIN$().md +36 -0
  21. package/resources/programming/basic_wiki/BLOAD.md +63 -0
  22. package/resources/programming/basic_wiki/BSAVE.md +61 -0
  23. package/resources/programming/basic_wiki/CALL.md +391 -0
  24. package/resources/programming/basic_wiki/CALL_ADJUST.md +40 -0
  25. package/resources/programming/basic_wiki/CALL_IMPOSE.md +28 -0
  26. package/resources/programming/basic_wiki/CALL_OPTIONS.md +26 -0
  27. package/resources/programming/basic_wiki/CALL_PAUSE.md +119 -0
  28. package/resources/programming/basic_wiki/CALL_PCMPLAY.md +60 -0
  29. package/resources/programming/basic_wiki/CALL_PCMREC.md +70 -0
  30. package/resources/programming/basic_wiki/CDBL().md +36 -0
  31. package/resources/programming/basic_wiki/CHR$().md +51 -0
  32. package/resources/programming/basic_wiki/CINT().md +36 -0
  33. package/resources/programming/basic_wiki/CIRCLE.md +51 -0
  34. package/resources/programming/basic_wiki/CLEAR.md +39 -0
  35. package/resources/programming/basic_wiki/CLOAD.md +27 -0
  36. package/resources/programming/basic_wiki/CLOAD?.md +31 -0
  37. package/resources/programming/basic_wiki/CLOSE.md +44 -0
  38. package/resources/programming/basic_wiki/CLS.md +51 -0
  39. package/resources/programming/basic_wiki/COLOR.md +143 -0
  40. package/resources/programming/basic_wiki/COLOR=.md +93 -0
  41. package/resources/programming/basic_wiki/COLOR_SPRITE$().md +83 -0
  42. package/resources/programming/basic_wiki/COLOR_SPRITE().md +85 -0
  43. package/resources/programming/basic_wiki/CONT.md +23 -0
  44. package/resources/programming/basic_wiki/COPY.md +215 -0
  45. package/resources/programming/basic_wiki/COPY_SCREEN.md +61 -0
  46. package/resources/programming/basic_wiki/COS().md +37 -0
  47. package/resources/programming/basic_wiki/CSAVE.md +35 -0
  48. package/resources/programming/basic_wiki/CSNG().md +36 -0
  49. package/resources/programming/basic_wiki/CSRLIN.md +33 -0
  50. package/resources/programming/basic_wiki/DATA.md +47 -0
  51. package/resources/programming/basic_wiki/DEFDBL.md +40 -0
  52. package/resources/programming/basic_wiki/DEFINT.md +40 -0
  53. package/resources/programming/basic_wiki/DEFSNG.md +40 -0
  54. package/resources/programming/basic_wiki/DEFSTR.md +40 -0
  55. package/resources/programming/basic_wiki/DEF_FN.md +49 -0
  56. package/resources/programming/basic_wiki/DEF_USR.md +33 -0
  57. package/resources/programming/basic_wiki/DELETE.md +49 -0
  58. package/resources/programming/basic_wiki/DIM.md +59 -0
  59. package/resources/programming/basic_wiki/DRAW.md +77 -0
  60. package/resources/programming/basic_wiki/ELSE.md +45 -0
  61. package/resources/programming/basic_wiki/END.md +32 -0
  62. package/resources/programming/basic_wiki/EOF().md +36 -0
  63. package/resources/programming/basic_wiki/EQV.md +76 -0
  64. package/resources/programming/basic_wiki/ERASE.md +35 -0
  65. package/resources/programming/basic_wiki/ERL.md +34 -0
  66. package/resources/programming/basic_wiki/ERR.md +143 -0
  67. package/resources/programming/basic_wiki/ERROR.md +145 -0
  68. package/resources/programming/basic_wiki/EXP().md +38 -0
  69. package/resources/programming/basic_wiki/FIELD.md +48 -0
  70. package/resources/programming/basic_wiki/FIX().md +44 -0
  71. package/resources/programming/basic_wiki/FN.md +61 -0
  72. package/resources/programming/basic_wiki/FOR...NEXT.md +80 -0
  73. package/resources/programming/basic_wiki/FRE().md +66 -0
  74. package/resources/programming/basic_wiki/GET_DATE.md +60 -0
  75. package/resources/programming/basic_wiki/GET_TIME.md +34 -0
  76. package/resources/programming/basic_wiki/GOSUB.md +41 -0
  77. package/resources/programming/basic_wiki/GOTO.md +41 -0
  78. package/resources/programming/basic_wiki/HEX$().md +36 -0
  79. package/resources/programming/basic_wiki/IF...GOTO...ELSE.md +55 -0
  80. package/resources/programming/basic_wiki/IF...THEN...ELSE.md +50 -0
  81. package/resources/programming/basic_wiki/IMP.md +83 -0
  82. package/resources/programming/basic_wiki/INKEY$.md +65 -0
  83. package/resources/programming/basic_wiki/INP().md +33 -0
  84. package/resources/programming/basic_wiki/INPUT$().md +51 -0
  85. package/resources/programming/basic_wiki/INPUT.md +93 -0
  86. package/resources/programming/basic_wiki/INSTR().md +44 -0
  87. package/resources/programming/basic_wiki/INT().md +44 -0
  88. package/resources/programming/basic_wiki/INTERVAL.md +57 -0
  89. package/resources/programming/basic_wiki/KEY().md +51 -0
  90. package/resources/programming/basic_wiki/KEY.md +254 -0
  91. package/resources/programming/basic_wiki/LEFT$().md +39 -0
  92. package/resources/programming/basic_wiki/LEN().md +36 -0
  93. package/resources/programming/basic_wiki/LET.md +68 -0
  94. package/resources/programming/basic_wiki/LINE.md +74 -0
  95. package/resources/programming/basic_wiki/LINE_INPUT.md +79 -0
  96. package/resources/programming/basic_wiki/LIST.md +58 -0
  97. package/resources/programming/basic_wiki/LLIST.md +43 -0
  98. package/resources/programming/basic_wiki/LOAD.md +56 -0
  99. package/resources/programming/basic_wiki/LOCATE.md +67 -0
  100. package/resources/programming/basic_wiki/LOG().md +36 -0
  101. package/resources/programming/basic_wiki/LPOS().md +31 -0
  102. package/resources/programming/basic_wiki/LPRINT.md +46 -0
  103. package/resources/programming/basic_wiki/MAXFILES.md +39 -0
  104. package/resources/programming/basic_wiki/MERGE.md +54 -0
  105. package/resources/programming/basic_wiki/MID$().md +72 -0
  106. package/resources/programming/basic_wiki/MOD.md +39 -0
  107. package/resources/programming/basic_wiki/MOTOR.md +46 -0
  108. package/resources/programming/basic_wiki/NEW.md +27 -0
  109. package/resources/programming/basic_wiki/NOT.md +61 -0
  110. package/resources/programming/basic_wiki/OCT$().md +36 -0
  111. package/resources/programming/basic_wiki/ON...GOSUB.md +45 -0
  112. package/resources/programming/basic_wiki/ON...GOTO.md +42 -0
  113. package/resources/programming/basic_wiki/ON_ERROR_GOTO.md +61 -0
  114. package/resources/programming/basic_wiki/ON_INTERVAL_GOSUB.md +54 -0
  115. package/resources/programming/basic_wiki/ON_KEY_GOSUB.md +56 -0
  116. package/resources/programming/basic_wiki/ON_SPRITE_GOSUB.md +41 -0
  117. package/resources/programming/basic_wiki/ON_STOP_GOSUB.md +56 -0
  118. package/resources/programming/basic_wiki/ON_STRIG_GOSUB.md +70 -0
  119. package/resources/programming/basic_wiki/OPEN.md +103 -0
  120. package/resources/programming/basic_wiki/OR.md +75 -0
  121. package/resources/programming/basic_wiki/OUT.md +35 -0
  122. package/resources/programming/basic_wiki/PAD().md +110 -0
  123. package/resources/programming/basic_wiki/PAINT.md +66 -0
  124. package/resources/programming/basic_wiki/PDL().md +53 -0
  125. package/resources/programming/basic_wiki/PEEK().md +44 -0
  126. package/resources/programming/basic_wiki/PLAY().md +58 -0
  127. package/resources/programming/basic_wiki/PLAY.md +196 -0
  128. package/resources/programming/basic_wiki/POINT.md +52 -0
  129. package/resources/programming/basic_wiki/POKE.md +51 -0
  130. package/resources/programming/basic_wiki/POS().md +36 -0
  131. package/resources/programming/basic_wiki/PRESET.md +61 -0
  132. package/resources/programming/basic_wiki/PRINT.md +179 -0
  133. package/resources/programming/basic_wiki/PSET.md +82 -0
  134. package/resources/programming/basic_wiki/PUT_KANJI.md +93 -0
  135. package/resources/programming/basic_wiki/PUT_SPRITE.md +143 -0
  136. package/resources/programming/basic_wiki/READ.md +45 -0
  137. package/resources/programming/basic_wiki/REM.md +42 -0
  138. package/resources/programming/basic_wiki/RENUM.md +78 -0
  139. package/resources/programming/basic_wiki/RESTORE.md +52 -0
  140. package/resources/programming/basic_wiki/RESUME.md +45 -0
  141. package/resources/programming/basic_wiki/RETURN.md +47 -0
  142. package/resources/programming/basic_wiki/RIGHT$().md +39 -0
  143. package/resources/programming/basic_wiki/RND().md +51 -0
  144. package/resources/programming/basic_wiki/RUN.md +56 -0
  145. package/resources/programming/basic_wiki/SAVE.md +65 -0
  146. package/resources/programming/basic_wiki/SCREEN.md +164 -0
  147. package/resources/programming/basic_wiki/SET_ADJUST.md +66 -0
  148. package/resources/programming/basic_wiki/SET_BEEP.md +76 -0
  149. package/resources/programming/basic_wiki/SET_DATE.md +103 -0
  150. package/resources/programming/basic_wiki/SET_PAGE.md +52 -0
  151. package/resources/programming/basic_wiki/SET_PASSWORD.md +75 -0
  152. package/resources/programming/basic_wiki/SET_PROMPT.md +61 -0
  153. package/resources/programming/basic_wiki/SET_SCREEN.md +100 -0
  154. package/resources/programming/basic_wiki/SET_SCROLL.md +55 -0
  155. package/resources/programming/basic_wiki/SET_TIME.md +83 -0
  156. package/resources/programming/basic_wiki/SET_TITLE.md +87 -0
  157. package/resources/programming/basic_wiki/SET_VIDEO.md +49 -0
  158. package/resources/programming/basic_wiki/SGN().md +38 -0
  159. package/resources/programming/basic_wiki/SIN().md +36 -0
  160. package/resources/programming/basic_wiki/SOUND.md +188 -0
  161. package/resources/programming/basic_wiki/SPACE$().md +38 -0
  162. package/resources/programming/basic_wiki/SPC().md +34 -0
  163. package/resources/programming/basic_wiki/SPRITE$().md +50 -0
  164. package/resources/programming/basic_wiki/SPRITE.md +31 -0
  165. package/resources/programming/basic_wiki/SQR().md +32 -0
  166. package/resources/programming/basic_wiki/STICK().md +70 -0
  167. package/resources/programming/basic_wiki/STOP.md +70 -0
  168. package/resources/programming/basic_wiki/STR$().md +37 -0
  169. package/resources/programming/basic_wiki/STRIG().md +82 -0
  170. package/resources/programming/basic_wiki/STRING$().md +42 -0
  171. package/resources/programming/basic_wiki/SWAP.md +62 -0
  172. package/resources/programming/basic_wiki/TAB().md +38 -0
  173. package/resources/programming/basic_wiki/TAN().md +36 -0
  174. package/resources/programming/basic_wiki/TIME.md +59 -0
  175. package/resources/programming/basic_wiki/TROFF.md +21 -0
  176. package/resources/programming/basic_wiki/TRON.md +39 -0
  177. package/resources/programming/basic_wiki/USR().md +66 -0
  178. package/resources/programming/basic_wiki/VAL().md +36 -0
  179. package/resources/programming/basic_wiki/VARPTR().md +50 -0
  180. package/resources/programming/basic_wiki/VDP().md +103 -0
  181. package/resources/programming/basic_wiki/VPEEK().md +46 -0
  182. package/resources/programming/basic_wiki/VPOKE.md +48 -0
  183. package/resources/programming/basic_wiki/WAIT.md +38 -0
  184. package/resources/programming/basic_wiki/WIDTH.md +76 -0
  185. package/resources/programming/basic_wiki/XOR.md +72 -0
  186. package/resources/programming/basic_wiki/_toc.json +871 -0
  187. package/resources/sdcc/toc.json +1 -1
  188. package/vector-db/index.json +1 -0
  189. /package/resources/msx-unapi/{Ethernet_UNAPI_specification_1.1.md → Ethernet_UNAPI_specification_1_1.md} +0 -0
  190. /package/resources/msx-unapi/{MSX_UNAPI_specification_1.1.md → MSX_UNAPI_specification_1_1.md} +0 -0
package/README.md CHANGED
@@ -9,7 +9,6 @@
9
9
  [![NPM Version](https://img.shields.io/npm/v/%40nataliapc%2Fmcp-openmsx)](https://www.npmjs.com/package/@nataliapc/mcp-openmsx?activeTab=versions)
10
10
  [![NPM Downloads](https://img.shields.io/npm/dm/%40nataliapc%2Fmcp-openmsx?color=808000)]()
11
11
 
12
-
13
12
  A [Model Context Protocol](https://modelcontextprotocol.io/introduction) (MCP) server for automating [openMSX emulator](https://github.com/openMSX/openMSX) instances.
14
13
 
15
14
  This server provides comprehensive tools for MSX software development, testing, and automation through standardized MCP protocols.
@@ -25,7 +24,8 @@ This project creates a bridge between modern AI-assisted development (e.g. GitHu
25
24
  - **Video Control**: VDP register manipulation and screen capture.
26
25
  - **Memory Operations**: Read/write RAM, VRAM, and I/O port access.
27
26
  - **Automation**: Keyboard input simulation and savestate management.
28
- - **Dual Transport**: Support for both stdio and HTTP transports.
27
+ - **Vector DB Integration**: Query an embedded vector database with MSX resources for development support.
28
+ - **Hybrid Mode**: This MCP server supports hybrid access mode (_STDIO_ and _HTTP_ transports).
29
29
 
30
30
  ## 🏗️ Architecture
31
31
 
@@ -74,6 +74,10 @@ The MCP server translates high-level commands from your Copilot AI into `TCL` co
74
74
  - `screen_dump`: Export screen data as BASIC BSAVE instruction.
75
75
  - `msxdocs_resource_get`: Retrieve MCP resources for MCP clients that don't support MCP resources.
76
76
 
77
+ ### Documentation Tools
78
+ - `vector_db_query`: Query the Vector DB resources to obtain information about MSX systems, cartridges, and other development resources.
79
+ - `msxdocs_resource_get`: Retrieve MCP resources for MCP clients that don't support MCP resources.
80
+
77
81
  ## 📚 Available MCP Resources
78
82
 
79
83
  ### What are MCP Resources?
@@ -118,18 +122,19 @@ The rights to these resources belong to their respective authors and are distrib
118
122
 
119
123
  ## 🚀 Quick Start
120
124
 
121
- You can use this MCP server in this basic way with the [precompiled NPM package](https://www.npmjs.com/package/@nataliapc/mcp-openmsx). You may need to have `nodejs` installed for this to work.
125
+ You can use this MCP server in this basic way with the [precompiled NPM package](https://www.npmjs.com/package/@nataliapc/mcp-openmsx).
122
126
 
123
- ### 🟢 Basic Usage with VSCode
127
+ ### 🟢 Quick installation with VSCode
124
128
 
129
+ [![Install in VS Code](https://img.shields.io/badge/VS_Code-Install_MCP_Server-0098FF?style=flat&logo=visualstudiocode&logoColor=ffffff)](vscode:mcp/install?%7B%22name%22%3A%22mcp-openmsx%22%2C%22type%22%3A%22stdio%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40nataliapc%2Fmcp-openmsx%22%5D%7D)
130
+
131
+ Steps to install the MCP server in VSCode:
125
132
  * Install [Github Copilot extension](https://code.visualstudio.com/docs/copilot/overview)
126
- * Add to your workspace a file `.vscode/mcp.json` with:
133
+ * Use the **Install in VS Code** button above to install the MCP server in your VSCode workspace.
134
+ * Or add to your workspace a file `.vscode/mcp.json` with the json configuration below.
127
135
 
128
136
  ### STDIO mode (recommended)
129
137
 
130
- [![Install in VS Code](https://img.shields.io/badge/VS_Code-Install_Server-0098FF?logo=visualstudiocode&logoColor=white)](https://insiders.vscode.dev/redirect/mcp/install?name=github&config=%7B%22type%22%3A%20%22stdio%22%2C%22command%22%3A%20%22npx%22%2C%22args%22%3A%20%5B%22%40nataliapc%2Fmcp-openmsx%22%5D%2C%20%22env%22%3A%20%7B%22OPENMSX_SHARE_DIR%22%3A%20%22%2Fusr%2Fshare%2Fopenmsx%22%7D%7D)
131
- [![Install in VS Code Insiders](https://img.shields.io/badge/VS_Code_Insiders-Install_Server-24bfa5?logo=visualstudiocode&logoColor=white)](https://insiders.vscode.dev/redirect/mcp/install?name=github&config=%7B%22type%22%3A%20%22stdio%22%2C%22command%22%3A%20%22npx%22%2C%22args%22%3A%20%5B%22%40nataliapc%2Fmcp-openmsx%22%5D%2C%20%22env%22%3A%20%7B%22OPENMSX_SHARE_DIR%22%3A%20%22%2Fusr%2Fshare%2Fopenmsx%22%7D%7D&quality=insiders)
132
-
133
138
  ```json
134
139
  {
135
140
  "servers": {
@@ -137,7 +142,7 @@ You can use this MCP server in this basic way with the [precompiled NPM package]
137
142
  "command": "npx",
138
143
  "args": ["@nataliapc/mcp-openmsx"],
139
144
  "env": {
140
- "OPENMSX_SHARE_DIR": "/usr/share/openmsx"
145
+ "OPENMSX_SHARE_DIR": "C:\the\location\of\your\openmsx\share\folder"
141
146
  }
142
147
  }
143
148
  }
@@ -164,7 +169,9 @@ You can use this MCP server in this basic way with the [precompiled NPM package]
164
169
 
165
170
  ### 🟢 Basic Usage with Claude Desktop
166
171
 
167
- Add to your `claude_desktop_config.json`:
172
+ Follow [these instrutions](https://modelcontextprotocol.io/quickstart/user#for-claude-desktop-users) to access Claude's `claude_desktop_config.json` file.
173
+
174
+ Edit it to include the following JSON entry:
168
175
 
169
176
  ```json
170
177
  {
@@ -173,13 +180,15 @@ Add to your `claude_desktop_config.json`:
173
180
  "command": "npx",
174
181
  "args": ["@nataliapc/mcp-openmsx"],
175
182
  "env": {
176
- "OPENMSX_SHARE_DIR": "/usr/share/openmsx"
183
+ "OPENMSX_SHARE_DIR": "C:\the\location\of\your\openmsx\share\folder"
177
184
  }
178
185
  }
179
186
  }
180
187
  }
181
188
  ```
182
189
 
190
+ **Note:** Environment variables are optional. Customize them as you need.
191
+
183
192
  ### 🟢 Environment Variables
184
193
 
185
194
  | Variable | Description | Default Value | Example |
@@ -195,6 +204,8 @@ Add to your `claude_desktop_config.json`:
195
204
 
196
205
  ## 🧑‍💻 Advanced Manual Usage
197
206
 
207
+ This is not needed for using the MCP server, but if you want to install it manually, follow these steps.
208
+
198
209
  Currently, the MCP server requires Linux to be compiled. It has not been tested on Windows or macOS, although it will likely work on the latter as well.
199
210
 
200
211
  ### Manual installation
@@ -230,10 +241,11 @@ MCP_TRANSPORT=http mcp-openmsx
230
241
  mcp-openmsx http
231
242
  ```
232
243
 
233
-
234
244
  ## 💡 Development
235
245
 
236
- ### Prerequisites
246
+ This is not needed for using the MCP server, but if you want to contribute or modify the code, follow these steps.
247
+
248
+ ### Prerequisites to build
237
249
 
238
250
  - Node.js >= 18.0.0
239
251
  - TypeScript
@@ -254,7 +266,6 @@ npm run build
254
266
  npm run dev
255
267
  ```
256
268
 
257
-
258
269
  ## 🪪 License
259
270
 
260
271
  GPL2 License - see [LICENSE](LICENSE) file for details.
package/dist/server.js CHANGED
@@ -6,7 +6,6 @@
6
6
  * through TCL commands via stdio.
7
7
  *
8
8
  * @package @nataliapc/mcp-openmsx
9
- * @version 1.1.15
10
9
  * @author Natalia Pujol Cremades (@nataliapc)
11
10
  * @license GPL2
12
11
  */
@@ -20,10 +19,14 @@ import express from "express";
20
19
  import fs from "fs/promises";
21
20
  import path from "path";
22
21
  import { openMSXInstance } from "./openmsx.js";
22
+ import { VectorDB } from "./vectordb.js";
23
23
  import { fetchCleanWebpage, addFileExtension, listResourcesDirectory, encodeTypeText, isErrorResponse, getResponseContent } from "./utils.js";
24
- // Version info for CLI
25
- export const PACKAGE_VERSION = "1.1.15";
24
+ import { createRequire } from 'module';
25
+ // Dynamically obtain PACKAGE_VERSION from package.json at runtime
26
+ const require = createRequire(import.meta.url);
27
+ export const PACKAGE_VERSION = require('../package.json').version;
26
28
  const resourcesDir = path.join(path.dirname(new URL(import.meta.url).pathname), "../resources");
29
+ const vectorDbDir = path.join(path.dirname(new URL(import.meta.url).pathname), "../vector-db");
27
30
  // Defaults for openMSX paths
28
31
  var OPENMSX_EXECUTABLE = 'openmsx';
29
32
  var OPENMSX_SHARE_DIR = '/usr/share/openmsx';
@@ -861,16 +864,61 @@ The parameter scrbasename is the name of the filename (without path) to save the
861
864
  response !== undefined ? response : `Error: No response for command "${command}".`
862
865
  ]);
863
866
  });
867
+ server.registerTool(
868
+ // Name of the tool (used to call it)
869
+ "vector_db_query", {
870
+ title: "Vector DB query from resources",
871
+ // Description of the tool (what it does)
872
+ description: `Query the Vector DB resources to obtain information about MSX system, cartridges, programming, and other development resources.
873
+ The query is a string used to search within the Vector DB resources; it is case-insensitive and may contain spaces.
874
+ The response is the list of the top 10 result resources that match the query, including their score, title, and resource URI, and are sorted in descending order by proximity score to the query.
875
+ **Important Note**: The Vector DB resources are in english, japanese, or dutch.
876
+ `,
877
+ // Schema for the tool (input validation)
878
+ inputSchema: {
879
+ query: z.string().min(2).max(100).describe("Query string to search in the Vector DB resources, case-insensitive and may contain spaces."),
880
+ },
881
+ // outputSchema: {
882
+ // results: z.array(z.object({
883
+ // score: z.number().describe("Proximity score of the result to the query, higher is better."),
884
+ // title: z.string().describe("Title of the resource."),
885
+ // uri: z.string().describe("URI of the resource, which can be used to access the resource."),
886
+ // document: z.string().describe("Document chunk of the resource, retrieved from the Vector DB."),
887
+ // id: z.string().describe("Unique resource chunk ID, used internally by the Vector DB."),
888
+ // }))
889
+ // },
890
+ },
891
+ // Handler for the tool (function to be executed when the tool is called)
892
+ async ({ query }) => {
893
+ const results = await VectorDB.getInstance().query(query);
894
+ return {
895
+ content: [{
896
+ type: "text",
897
+ text: JSON.stringify(results),
898
+ }],
899
+ results: results,
900
+ isError: false,
901
+ };
902
+ });
864
903
  // ============================================================================
865
904
  // MSX Documentation resources
866
905
  const resdocs = (await listResourcesDirectory(resourcesDir)).sort();
867
906
  const regResources = [];
868
907
  for (let index = 0; index < resdocs.length; index++) {
908
+ // Read the toc.json file if exists, otherwise skip this section
869
909
  const sectionName = resdocs[index];
870
910
  const tocFile = path.join(resourcesDir, `${sectionName}/toc.json`);
871
- const tocContent = JSON.parse(await fs.readFile(tocFile, 'utf8'));
911
+ let tocContent = { toc: [] };
912
+ try {
913
+ tocContent = JSON.parse(await fs.readFile(tocFile, 'utf8'));
914
+ }
915
+ catch (error) {
916
+ // The toc.json file does not exist or is invalid, skip this section
917
+ continue;
918
+ }
919
+ // Register each item in the toc.json as a resource
872
920
  tocContent.toc.forEach((item, itemIndex) => {
873
- const itemName = path.parse(item.uri.split('/').pop()).name || '';
921
+ const itemName = path.parse(item.uri.split('/').pop()).base || '';
874
922
  let resource = {
875
923
  uri: item.uri,
876
924
  filename: '',
@@ -926,18 +974,18 @@ The parameter scrbasename is the name of the filename (without path) to save the
926
974
  ;
927
975
  // Source: https://www.msx.org/wiki/Category:MSX-BASIC_Instructions
928
976
  const basicInstructions = [
929
- "ABS()", "AND", "ASC()", "ATN()", "AUTO", "BASE()", "BEEP", "BIN$()", "BLOAD", "BSAVE", "CALL", "CALL ADJUST", "CALL PAUSE", "CALL PCMPLAY", "CALL PCMREC",
930
- "CDBL()", "CHR$()", "CINT()", "CIRCLE", "CLEAR", "CLOAD", "CLOAD?", "CLOSE", "CLS", "COLOR", "COLOR=", "COLOR SPRITE()", "COLOR SPRITE$()", "CONT", "COPY",
931
- "COPY SCREEN", "COS()", "CSAVE", "CSNG()", "CSRLIN", "DATA", "DEFDBL", "DEF FN", "DEFINT", "DEFSNG", "DEFSTR", "DEF USR", "DELETE", "DIM", "DRAW", "ELSE",
932
- "END", "EOF()", "EQV", "ERASE", "ERL", "ERR", "ERROR", "EXP()", "FIX()", "FN", "FOR...NEXT", "FRE()", "GET DATE", "GET TIME", "GOSUB", "GOTO", "HEX$()",
933
- "IF...GOTO...ELSE", "IF...THEN...ELSE", "IMP", "INKEY$", "INP()", "INPUT", "INPUT$()", "INSTR()", "INT()", "INTERVAL", "KEY", "KEY()", "LEFT$()", "LEN()",
934
- "LET", "LINE", "LINE INPUT", "LIST", "LLIST", "LOAD", "LOCATE", "LOG()", "LPOS()", "LPRINT", "MAXFILES", "MERGE", "MID$()", "MOD", "MOTOR", "NEW", "NOT",
935
- "OCT$()", "ON...GOSUB", "ON...GOTO", "ON ERROR GOTO", "ON INTERVAL GOSUB", "ON KEY GOSUB", "ON SPRITE GOSUB", "ON STOP GOSUB", "ON STRIG GOSUB", "OPEN",
936
- "OR", "OUT", "PAD()", "PAINT", "PDL()", "PEEK()", "PLAY", "PLAY()", "POINT", "POKE", "POS()", "PRESET", "PRINT", "PSET", "PUT KANJI", "PUT SPRITE", "READ",
937
- "REM", "RENUM", "RESTORE", "RESUME", "RETURN", "RIGHT$()", "RND()", "RUN", "SAVE", "SCREEN", "SET ADJUST", "SET BEEP", "SET DATE", "SET PAGE", "SET PASSWORD",
938
- "SET PROMPT", "SET SCREEN", "SET SCROLL", "SET TIME", "SET TITLE", "SET VIDEO", "SGN()", "SIN()", "SOUND", "SPACE$()", "SPC()", "SPRITE", "SPRITE$()",
939
- "SQR()", "STICK()", "STOP", "STR$()", "STRIG()", "STRING$()", "SWAP", "TAB()", "TAN()", "TIME", "TROFF", "TRON", "USR()", "VAL()", "VARPTR()", "VDP()",
940
- "VPEEK()", "VPOKE", "WAIT", "WIDTH", "XOR"
977
+ "ABS()", "AND", "ASC()", "ATN()", "AUTO", "BASE()", "BEEP", "BIN$()", "BLOAD", "BSAVE", "CALL", "CALL ADJUST", "CALL IMPOSE", "CALL OPTIONS", "CALL PAUSE",
978
+ "CALL PCMPLAY", "CALL PCMREC", "CDBL()", "CHR$()", "CINT()", "CIRCLE", "CLEAR", "CLOAD", "CLOAD?", "CLOSE", "CLS", "COLOR", "COLOR=", "COLOR SPRITE()",
979
+ "COLOR SPRITE$()", "CONT", "COPY", "COPY SCREEN", "COS()", "CSAVE", "CSNG()", "CSRLIN", "DATA", "DEFDBL", "DEF FN", "DEFINT", "DEFSNG", "DEFSTR", "DEF USR",
980
+ "DELETE", "DIM", "DRAW", "ELSE", "END", "EOF()", "EQV", "ERASE", "ERL", "ERR", "ERROR", "EXP()", "FIELD", "FIX()", "FN", "FOR...NEXT", "FRE()", "GET DATE",
981
+ "GET TIME", "GOSUB", "GOTO", "HEX$()", "IF...GOTO...ELSE", "IF...THEN...ELSE", "IMP", "INKEY$", "INP()", "INPUT", "INPUT$()", "INSTR()", "INT()", "INTERVAL",
982
+ "KEY", "KEY()", "LEFT$()", "LEN()", "LET", "LINE", "LINE INPUT", "LIST", "LLIST", "LOAD", "LOCATE", "LOG()", "LPOS()", "LPRINT", "MAXFILES", "MERGE",
983
+ "MID$()", "MOD", "MOTOR", "NEW", "NOT", "OCT$()", "ON...GOSUB", "ON...GOTO", "ON ERROR GOTO", "ON INTERVAL GOSUB", "ON KEY GOSUB", "ON SPRITE GOSUB",
984
+ "ON STOP GOSUB", "ON STRIG GOSUB", "OPEN", "OR", "OUT", "PAD()", "PAINT", "PDL()", "PEEK()", "PLAY", "PLAY()", "POINT", "POKE", "POS()", "PRESET", "PRINT",
985
+ "PSET", "PUT KANJI", "PUT SPRITE", "READ", "REM", "RENUM", "RESTORE", "RESUME", "RETURN", "RIGHT$()", "RND()", "RUN", "SAVE", "SCREEN", "SET ADJUST",
986
+ "SET BEEP", "SET DATE", "SET PAGE", "SET PASSWORD", "SET PROMPT", "SET SCREEN", "SET SCROLL", "SET TIME", "SET TITLE", "SET VIDEO", "SGN()", "SIN()",
987
+ "SOUND", "SPACE$()", "SPC()", "SPRITE", "SPRITE$()", "SQR()", "STICK()", "STOP", "STR$()", "STRIG()", "STRING$()", "SWAP", "TAB()", "TAN()", "TIME", "TROFF",
988
+ "TRON", "USR()", "VAL()", "VARPTR()", "VDP()", "VPEEK()", "VPOKE", "WAIT", "WIDTH", "XOR"
941
989
  ];
942
990
  server.resource("msxdocs_basic_wiki", new ResourceTemplate("msxdocs://basic_wiki/{instruction}", {
943
991
  list: undefined,
@@ -949,19 +997,19 @@ The parameter scrbasename is the name of the filename (without path) to save the
949
997
  description: "Documentation about all the standard MSX BASIC instructions from www.msx.org",
950
998
  mimeType: "text/html",
951
999
  }, async (uri, variables) => {
952
- const instruction = variables.instruction
953
- .replace(/ /g, '_')
954
- .replace(/\?/g, '%3F')
955
- .replace(/=/g, '%3D');
956
- const url = `https://www.msx.org/wiki/${instruction}`;
1000
+ let instruction = variables.instruction;
957
1001
  let resourceContent;
958
1002
  let mimeType;
1003
+ // urldecode the instruction to avoid issues with special characters
1004
+ instruction = decodeURIComponent(instruction).replaceAll(' ', '_');
959
1005
  try {
960
- [resourceContent, mimeType] = await fetchCleanWebpage(url);
1006
+ let resourceFile;
1007
+ [mimeType, resourceFile] = await addFileExtension(path.join(resourcesDir, 'programming', 'basic_wiki', instruction));
1008
+ resourceContent = await fs.readFile(resourceFile, 'utf8');
961
1009
  }
962
1010
  catch (error) {
963
1011
  // Throw exception (MCP protocol requirement)
964
- throw error;
1012
+ throw new Error(`Error reading resource programming/basic_wiki/${instruction}: ${error instanceof Error ? error.message : String(error)}`);
965
1013
  }
966
1014
  return {
967
1015
  contents: [{
@@ -1214,6 +1262,7 @@ async function main() {
1214
1262
  MACHINES_DIR = `${OPENMSX_SHARE_DIR}machines`;
1215
1263
  EXTENSIONS_DIR = `${OPENMSX_SHARE_DIR}extensions`;
1216
1264
  }
1265
+ VectorDB.setIndexDirectory(vectorDbDir);
1217
1266
  // Detect transport type from environment or command line
1218
1267
  const transportType = process.env.MCP_TRANSPORT || process.argv[2] || 'stdio';
1219
1268
  if (transportType === 'http') {
package/dist/utils.js CHANGED
@@ -54,13 +54,13 @@ export async function addFileExtension(filePath) {
54
54
  return ['text/plain', filePath];
55
55
  }
56
56
  /**
57
- * List all folders in the resources directory
57
+ * List all folders and subfolders in the resources directory
58
58
  * @param resourcesDir - Path to the resources directory
59
59
  * @returns Promise<string[]> - List of folder names in the resources directory
60
60
  */
61
61
  export async function listResourcesDirectory(resourcesDir) {
62
62
  try {
63
- const directories = await fs.readdir(resourcesDir, { withFileTypes: true });
63
+ const directories = await fs.readdir(resourcesDir, { withFileTypes: true, recursive: true });
64
64
  const folderNames = directories
65
65
  .filter(dirent => dirent.isDirectory())
66
66
  .map(dirent => dirent.name);
@@ -229,3 +229,11 @@ export function getResponseContent(response, isError = false) {
229
229
  isError: hasError
230
230
  };
231
231
  }
232
+ /*
233
+ * Sleep for a specified number of milliseconds
234
+ * @param ms - Number of milliseconds to sleep
235
+ * @returns Promise that resolves after the specified time
236
+ */
237
+ export function sleep(ms) {
238
+ return new Promise(resolve => setTimeout(resolve, ms));
239
+ }
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Vector Database wrapper class
3
+ *
4
+ * @author Natalia Pujol Cremades (@nataliapc)
5
+ * @license GPL2
6
+ */
7
+ import { LocalIndex } from 'vectra';
8
+ import embeddings from '@themaximalist/embeddings.js';
9
+ export class VectorDB {
10
+ static instance;
11
+ static vectorDbDir = '../vector-db';
12
+ index;
13
+ static getInstance() {
14
+ if (!VectorDB.instance) {
15
+ VectorDB.instance = new VectorDB();
16
+ }
17
+ return VectorDB.instance;
18
+ }
19
+ static setIndexDirectory(dbDir) {
20
+ VectorDB.vectorDbDir = dbDir;
21
+ }
22
+ constructor(dbDir = VectorDB.vectorDbDir) {
23
+ this.index = new LocalIndex(dbDir);
24
+ if (!this.initDatabase()) {
25
+ throw new Error('Failed to initialize VectorDB: Index does not exist');
26
+ }
27
+ }
28
+ async initDatabase() {
29
+ return await this.index.isIndexCreated();
30
+ }
31
+ async getVector(text) {
32
+ const response = await embeddings(text);
33
+ if (!response || !Array.isArray(response) || response.length === 0) {
34
+ throw new Error('Failed to generate embedding vector');
35
+ }
36
+ return response;
37
+ }
38
+ async query(text) {
39
+ const vector = await this.getVector(text);
40
+ let results = [];
41
+ try {
42
+ results = await this.index.queryItems(vector, text, 10);
43
+ if (results.length > 0) {
44
+ return results.map(result => {
45
+ return {
46
+ score: result.score.toFixed(4),
47
+ uri: result.item.metadata?.uri || 'unknown',
48
+ title: result.item.metadata?.title || 'unknown',
49
+ document: String(result.item.metadata?.document || ''),
50
+ id: result.item.metadata?.id || 'unknown',
51
+ };
52
+ });
53
+ }
54
+ }
55
+ catch (error) {
56
+ throw new Error(`Query failed: ${error}`);
57
+ }
58
+ return results;
59
+ }
60
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nataliapc/mcp-openmsx",
3
- "version": "1.1.15",
3
+ "version": "1.2.2",
4
4
  "description": "Model context protocol server for openMSX automation and control",
5
5
  "main": "dist/server.js",
6
6
  "type": "module",
@@ -38,17 +38,21 @@
38
38
  "test": "echo \"Error: no test specified\" && exit 1"
39
39
  },
40
40
  "dependencies": {
41
- "@modelcontextprotocol/sdk": "^1.15.1",
41
+ "@modelcontextprotocol/sdk": "^1.16.0",
42
+ "@themaximalist/embeddings.js": "^0.1.3",
42
43
  "@types/express": "^5.0.2",
44
+ "@xenova/transformers": "^2.17.2",
45
+ "debug": "^4.4.1",
43
46
  "express": "^5.1.0",
44
47
  "sanitize-html": "^2.17.0",
45
48
  "tsx": "^4.7.1",
49
+ "vectra": "^0.11.1",
46
50
  "zod": "^3.24.4"
47
51
  },
48
52
  "devDependencies": {
49
53
  "@modelcontextprotocol/inspector": "^0.15.0",
50
54
  "@types/mime-types": "^3.0.1",
51
- "@types/node": "^22.15.27",
55
+ "@types/node": "^24.0.15",
52
56
  "@types/sanitize-html": "^2.16.0",
53
57
  "shx": "^0.4.0",
54
58
  "typescript": "^5.8.3"
@@ -56,6 +60,7 @@
56
60
  "files": [
57
61
  "dist/**/*",
58
62
  "resources/**/*",
63
+ "vector-db/**/*",
59
64
  "README.md",
60
65
  "LICENSE"
61
66
  ],