@nataliapc/mcp-openmsx 1.1.15 → 1.2.3

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 (216) hide show
  1. package/README.md +84 -37
  2. package/dist/server.js +101 -40
  3. package/dist/utils.js +42 -2
  4. package/dist/vectordb.js +61 -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-dos/MSX-DOS_2_Environment_Variables.md +1368 -0
  13. package/resources/msx-dos/MSX-DOS_File_extensions.md +154 -0
  14. package/resources/msx-dos/toc.json +13 -0
  15. package/resources/msx-unapi/toc.json +2 -2
  16. package/resources/others/keyboard_matrices.md +243 -0
  17. package/resources/others/toc.json +6 -0
  18. package/resources/programming/asm_callbios.md +79 -0
  19. package/resources/programming/asm_docopy.md +115 -0
  20. package/resources/programming/asm_fast_loops.md +200 -0
  21. package/resources/programming/asm_getslot.md +143 -0
  22. package/resources/programming/asm_interrupts.md +202 -0
  23. package/resources/programming/asm_load_screen.md +240 -0
  24. package/resources/programming/asm_mult_div_shifts.md +487 -0
  25. package/resources/programming/asm_raminpage1.md +56 -0
  26. package/resources/programming/asm_vdp_detection.md +78 -0
  27. package/resources/programming/asm_vdp_routines.md +343 -0
  28. package/resources/programming/asm_z80_routines_collection.md +810 -0
  29. package/resources/programming/basic_wiki/ABS().md +36 -0
  30. package/resources/programming/basic_wiki/AND.md +71 -0
  31. package/resources/programming/basic_wiki/ASC().md +38 -0
  32. package/resources/programming/basic_wiki/ATN().md +36 -0
  33. package/resources/programming/basic_wiki/AUTO.md +39 -0
  34. package/resources/programming/basic_wiki/BASE().md +147 -0
  35. package/resources/programming/basic_wiki/BEEP.md +27 -0
  36. package/resources/programming/basic_wiki/BIN$().md +36 -0
  37. package/resources/programming/basic_wiki/BLOAD.md +63 -0
  38. package/resources/programming/basic_wiki/BSAVE.md +61 -0
  39. package/resources/programming/basic_wiki/CALL.md +391 -0
  40. package/resources/programming/basic_wiki/CALL_ADJUST.md +40 -0
  41. package/resources/programming/basic_wiki/CALL_IMPOSE.md +28 -0
  42. package/resources/programming/basic_wiki/CALL_OPTIONS.md +26 -0
  43. package/resources/programming/basic_wiki/CALL_PAUSE.md +119 -0
  44. package/resources/programming/basic_wiki/CALL_PCMPLAY.md +60 -0
  45. package/resources/programming/basic_wiki/CALL_PCMREC.md +70 -0
  46. package/resources/programming/basic_wiki/CDBL().md +36 -0
  47. package/resources/programming/basic_wiki/CHR$().md +51 -0
  48. package/resources/programming/basic_wiki/CINT().md +36 -0
  49. package/resources/programming/basic_wiki/CIRCLE.md +51 -0
  50. package/resources/programming/basic_wiki/CLEAR.md +39 -0
  51. package/resources/programming/basic_wiki/CLOAD.md +27 -0
  52. package/resources/programming/basic_wiki/CLOAD?.md +31 -0
  53. package/resources/programming/basic_wiki/CLOSE.md +44 -0
  54. package/resources/programming/basic_wiki/CLS.md +51 -0
  55. package/resources/programming/basic_wiki/COLOR.md +143 -0
  56. package/resources/programming/basic_wiki/COLOR=.md +93 -0
  57. package/resources/programming/basic_wiki/COLOR_SPRITE$().md +83 -0
  58. package/resources/programming/basic_wiki/COLOR_SPRITE().md +85 -0
  59. package/resources/programming/basic_wiki/CONT.md +23 -0
  60. package/resources/programming/basic_wiki/COPY.md +215 -0
  61. package/resources/programming/basic_wiki/COPY_SCREEN.md +61 -0
  62. package/resources/programming/basic_wiki/COS().md +37 -0
  63. package/resources/programming/basic_wiki/CSAVE.md +35 -0
  64. package/resources/programming/basic_wiki/CSNG().md +36 -0
  65. package/resources/programming/basic_wiki/CSRLIN.md +33 -0
  66. package/resources/programming/basic_wiki/DATA.md +47 -0
  67. package/resources/programming/basic_wiki/DEFDBL.md +40 -0
  68. package/resources/programming/basic_wiki/DEFINT.md +40 -0
  69. package/resources/programming/basic_wiki/DEFSNG.md +40 -0
  70. package/resources/programming/basic_wiki/DEFSTR.md +40 -0
  71. package/resources/programming/basic_wiki/DEF_FN.md +49 -0
  72. package/resources/programming/basic_wiki/DEF_USR.md +33 -0
  73. package/resources/programming/basic_wiki/DELETE.md +49 -0
  74. package/resources/programming/basic_wiki/DIM.md +59 -0
  75. package/resources/programming/basic_wiki/DRAW.md +77 -0
  76. package/resources/programming/basic_wiki/ELSE.md +45 -0
  77. package/resources/programming/basic_wiki/END.md +32 -0
  78. package/resources/programming/basic_wiki/EOF().md +36 -0
  79. package/resources/programming/basic_wiki/EQV.md +76 -0
  80. package/resources/programming/basic_wiki/ERASE.md +35 -0
  81. package/resources/programming/basic_wiki/ERL.md +34 -0
  82. package/resources/programming/basic_wiki/ERR.md +143 -0
  83. package/resources/programming/basic_wiki/ERROR.md +145 -0
  84. package/resources/programming/basic_wiki/EXP().md +38 -0
  85. package/resources/programming/basic_wiki/FIELD.md +48 -0
  86. package/resources/programming/basic_wiki/FIX().md +44 -0
  87. package/resources/programming/basic_wiki/FN.md +61 -0
  88. package/resources/programming/basic_wiki/FOR...NEXT.md +80 -0
  89. package/resources/programming/basic_wiki/FRE().md +66 -0
  90. package/resources/programming/basic_wiki/GET_DATE.md +60 -0
  91. package/resources/programming/basic_wiki/GET_TIME.md +34 -0
  92. package/resources/programming/basic_wiki/GOSUB.md +41 -0
  93. package/resources/programming/basic_wiki/GOTO.md +41 -0
  94. package/resources/programming/basic_wiki/HEX$().md +36 -0
  95. package/resources/programming/basic_wiki/IF...GOTO...ELSE.md +55 -0
  96. package/resources/programming/basic_wiki/IF...THEN...ELSE.md +50 -0
  97. package/resources/programming/basic_wiki/IMP.md +83 -0
  98. package/resources/programming/basic_wiki/INKEY$.md +65 -0
  99. package/resources/programming/basic_wiki/INP().md +33 -0
  100. package/resources/programming/basic_wiki/INPUT$().md +51 -0
  101. package/resources/programming/basic_wiki/INPUT.md +93 -0
  102. package/resources/programming/basic_wiki/INSTR().md +44 -0
  103. package/resources/programming/basic_wiki/INT().md +44 -0
  104. package/resources/programming/basic_wiki/INTERVAL.md +57 -0
  105. package/resources/programming/basic_wiki/KEY().md +51 -0
  106. package/resources/programming/basic_wiki/KEY.md +254 -0
  107. package/resources/programming/basic_wiki/LEFT$().md +39 -0
  108. package/resources/programming/basic_wiki/LEN().md +36 -0
  109. package/resources/programming/basic_wiki/LET.md +68 -0
  110. package/resources/programming/basic_wiki/LINE.md +74 -0
  111. package/resources/programming/basic_wiki/LINE_INPUT.md +79 -0
  112. package/resources/programming/basic_wiki/LIST.md +58 -0
  113. package/resources/programming/basic_wiki/LLIST.md +43 -0
  114. package/resources/programming/basic_wiki/LOAD.md +56 -0
  115. package/resources/programming/basic_wiki/LOCATE.md +67 -0
  116. package/resources/programming/basic_wiki/LOG().md +36 -0
  117. package/resources/programming/basic_wiki/LPOS().md +31 -0
  118. package/resources/programming/basic_wiki/LPRINT.md +46 -0
  119. package/resources/programming/basic_wiki/MAXFILES.md +39 -0
  120. package/resources/programming/basic_wiki/MERGE.md +54 -0
  121. package/resources/programming/basic_wiki/MID$().md +72 -0
  122. package/resources/programming/basic_wiki/MOD.md +39 -0
  123. package/resources/programming/basic_wiki/MOTOR.md +46 -0
  124. package/resources/programming/basic_wiki/NEW.md +27 -0
  125. package/resources/programming/basic_wiki/NOT.md +61 -0
  126. package/resources/programming/basic_wiki/OCT$().md +36 -0
  127. package/resources/programming/basic_wiki/ON...GOSUB.md +45 -0
  128. package/resources/programming/basic_wiki/ON...GOTO.md +42 -0
  129. package/resources/programming/basic_wiki/ON_ERROR_GOTO.md +61 -0
  130. package/resources/programming/basic_wiki/ON_INTERVAL_GOSUB.md +54 -0
  131. package/resources/programming/basic_wiki/ON_KEY_GOSUB.md +56 -0
  132. package/resources/programming/basic_wiki/ON_SPRITE_GOSUB.md +41 -0
  133. package/resources/programming/basic_wiki/ON_STOP_GOSUB.md +56 -0
  134. package/resources/programming/basic_wiki/ON_STRIG_GOSUB.md +70 -0
  135. package/resources/programming/basic_wiki/OPEN.md +103 -0
  136. package/resources/programming/basic_wiki/OR.md +75 -0
  137. package/resources/programming/basic_wiki/OUT.md +35 -0
  138. package/resources/programming/basic_wiki/PAD().md +110 -0
  139. package/resources/programming/basic_wiki/PAINT.md +66 -0
  140. package/resources/programming/basic_wiki/PDL().md +53 -0
  141. package/resources/programming/basic_wiki/PEEK().md +44 -0
  142. package/resources/programming/basic_wiki/PLAY().md +58 -0
  143. package/resources/programming/basic_wiki/PLAY.md +196 -0
  144. package/resources/programming/basic_wiki/POINT.md +52 -0
  145. package/resources/programming/basic_wiki/POKE.md +51 -0
  146. package/resources/programming/basic_wiki/POS().md +36 -0
  147. package/resources/programming/basic_wiki/PRESET.md +61 -0
  148. package/resources/programming/basic_wiki/PRINT.md +179 -0
  149. package/resources/programming/basic_wiki/PSET.md +82 -0
  150. package/resources/programming/basic_wiki/PUT_KANJI.md +93 -0
  151. package/resources/programming/basic_wiki/PUT_SPRITE.md +143 -0
  152. package/resources/programming/basic_wiki/READ.md +45 -0
  153. package/resources/programming/basic_wiki/REM.md +42 -0
  154. package/resources/programming/basic_wiki/RENUM.md +78 -0
  155. package/resources/programming/basic_wiki/RESTORE.md +52 -0
  156. package/resources/programming/basic_wiki/RESUME.md +45 -0
  157. package/resources/programming/basic_wiki/RETURN.md +47 -0
  158. package/resources/programming/basic_wiki/RIGHT$().md +39 -0
  159. package/resources/programming/basic_wiki/RND().md +51 -0
  160. package/resources/programming/basic_wiki/RUN.md +56 -0
  161. package/resources/programming/basic_wiki/SAVE.md +65 -0
  162. package/resources/programming/basic_wiki/SCREEN.md +164 -0
  163. package/resources/programming/basic_wiki/SET_ADJUST.md +66 -0
  164. package/resources/programming/basic_wiki/SET_BEEP.md +76 -0
  165. package/resources/programming/basic_wiki/SET_DATE.md +103 -0
  166. package/resources/programming/basic_wiki/SET_PAGE.md +52 -0
  167. package/resources/programming/basic_wiki/SET_PASSWORD.md +75 -0
  168. package/resources/programming/basic_wiki/SET_PROMPT.md +61 -0
  169. package/resources/programming/basic_wiki/SET_SCREEN.md +100 -0
  170. package/resources/programming/basic_wiki/SET_SCROLL.md +55 -0
  171. package/resources/programming/basic_wiki/SET_TIME.md +83 -0
  172. package/resources/programming/basic_wiki/SET_TITLE.md +87 -0
  173. package/resources/programming/basic_wiki/SET_VIDEO.md +49 -0
  174. package/resources/programming/basic_wiki/SGN().md +38 -0
  175. package/resources/programming/basic_wiki/SIN().md +36 -0
  176. package/resources/programming/basic_wiki/SOUND.md +188 -0
  177. package/resources/programming/basic_wiki/SPACE$().md +38 -0
  178. package/resources/programming/basic_wiki/SPC().md +34 -0
  179. package/resources/programming/basic_wiki/SPRITE$().md +50 -0
  180. package/resources/programming/basic_wiki/SPRITE.md +31 -0
  181. package/resources/programming/basic_wiki/SQR().md +32 -0
  182. package/resources/programming/basic_wiki/STICK().md +70 -0
  183. package/resources/programming/basic_wiki/STOP.md +70 -0
  184. package/resources/programming/basic_wiki/STR$().md +37 -0
  185. package/resources/programming/basic_wiki/STRIG().md +82 -0
  186. package/resources/programming/basic_wiki/STRING$().md +42 -0
  187. package/resources/programming/basic_wiki/SWAP.md +62 -0
  188. package/resources/programming/basic_wiki/TAB().md +38 -0
  189. package/resources/programming/basic_wiki/TAN().md +36 -0
  190. package/resources/programming/basic_wiki/TIME.md +59 -0
  191. package/resources/programming/basic_wiki/TROFF.md +21 -0
  192. package/resources/programming/basic_wiki/TRON.md +39 -0
  193. package/resources/programming/basic_wiki/USR().md +66 -0
  194. package/resources/programming/basic_wiki/VAL().md +36 -0
  195. package/resources/programming/basic_wiki/VARPTR().md +50 -0
  196. package/resources/programming/basic_wiki/VDP().md +103 -0
  197. package/resources/programming/basic_wiki/VPEEK().md +46 -0
  198. package/resources/programming/basic_wiki/VPOKE.md +48 -0
  199. package/resources/programming/basic_wiki/WAIT.md +38 -0
  200. package/resources/programming/basic_wiki/WIDTH.md +76 -0
  201. package/resources/programming/basic_wiki/XOR.md +72 -0
  202. package/resources/programming/basic_wiki/_toc.json +871 -0
  203. package/resources/programming/dos_error_handling.md +85 -0
  204. package/resources/programming/toc.json +51 -36
  205. package/resources/programming/vdp_commands_speed.md +147 -0
  206. package/resources/programming/vdp_programming_faq.md +55 -0
  207. package/resources/programming/vdp_programming_tutorial.md +390 -0
  208. package/resources/programming/vdp_screensplit_programming_guide.md +166 -0
  209. package/resources/programming/vdp_scrolling_on_msx.md +124 -0
  210. package/resources/programming/vdp_the_yjk_screen_modes.md +227 -0
  211. package/resources/programming/vdp_v9938_vram_timings.md +539 -0
  212. package/resources/programming/vdp_v9938_vram_timings_part_2.md +281 -0
  213. package/resources/sdcc/toc.json +1 -1
  214. package/vector-db/index.json +1 -0
  215. /package/resources/msx-unapi/{Ethernet_UNAPI_specification_1.1.md → Ethernet_UNAPI_specification_1_1.md} +0 -0
  216. /package/resources/msx-unapi/{MSX_UNAPI_specification_1.1.md → MSX_UNAPI_specification_1_1.md} +0 -0
package/README.md CHANGED
@@ -9,12 +9,27 @@
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.
16
15
 
17
- ## 🎯 Project Overview
16
+ ## Table of Contents
17
+
18
+ - [Project overview](#project-overview)
19
+ - [Architecture](#architecture)
20
+ - [Available MCP Tools](#available-mcp-tools)
21
+ - [Available MCP Resources](#available-mcp-resources)
22
+ - [**Quick Start**](#quick-start)
23
+ - [Quick installation with **VSCode**](#quick-installation-with-vscode)
24
+ - [Basic installation with **Claude Desktop**](#basic-installation-with-claude-desktop)
25
+ - [Environment Variables](#environment-variables)
26
+ - [Advanced manual usage](#advanced-manual-usage)
27
+ - [Development](#development)
28
+ - [License](#license)
29
+ - [Support](#support)
30
+ - [Contributing](#contributing)
31
+
32
+ ## Project Overview
18
33
 
19
34
  This project creates a bridge between modern AI-assisted development (e.g. GitHub Copilot, Claude Desktop) and retro computing (MSX systems) by providing:
20
35
 
@@ -25,30 +40,51 @@ This project creates a bridge between modern AI-assisted development (e.g. GitHu
25
40
  - **Video Control**: VDP register manipulation and screen capture.
26
41
  - **Memory Operations**: Read/write RAM, VRAM, and I/O port access.
27
42
  - **Automation**: Keyboard input simulation and savestate management.
28
- - **Dual Transport**: Support for both stdio and HTTP transports.
43
+ - **Vector DB Integration**: Query an embedded vector database with MSX resources for development support.
44
+ - **Hybrid Mode**: This MCP server supports hybrid access mode (_STDIO_ and _HTTP_ transports).
29
45
 
30
- ## 🏗️ Architecture
46
+ ## Architecture
31
47
 
32
48
  ```mermaid
33
49
  flowchart TB
34
- subgraph subGraph0["Your computer for develop"]
35
- HOST["Your AI dev companion<br>(mcp client support)"]
36
- MCP(["mcp-openmsx<br>(mcp server)"])
50
+ %%{init: {'flowchart': {'curve':'monotoneX' }}}%%
51
+
52
+ subgraph yourComputerGroup[" "]
53
+ HOST["Your AI dev companion<br>(MCP Client support)"]
37
54
  EMU["openMSX emulator<br>(local instance)"]
38
- HOST <--&nbsp;MCP&nbsp;<br>&nbsp;protocol&nbsp;--> MCP
39
- MCP <--&nbsp;stdio&nbsp;--> EMU
55
+
56
+ subgraph mcpGroup["**mcp-openmsx**"]
57
+ MCP["MCP Server<br>stdio / http"]
58
+ TOOLS["MCP Tools"]
59
+ VECTORDB[("Embeddings RAG<br>(Vector Database)")]
60
+ RESOURCES["MCP Resources"]
61
+ LOCALDATA["Local data<br>(inner documentation)"]
62
+ end
63
+ EXTDATA["External data<br>(webpages)"]
64
+
65
+ HOST <--"_MCP<br>&nbsp;protocol&nbsp;_"--> MCP
66
+ MCP <--> TOOLS & RESOURCES
67
+ TOOLS <--"_&nbsp;Query&nbsp;_"--> VECTORDB
68
+ TOOLS <--"_&nbsp;Console commands&nbsp;_"---> EMU
69
+ RESOURCES <--_&nbsp;http&nbsp;_---> EXTDATA
70
+ RESOURCES <--> LOCALDATA
40
71
  end
41
- HOST@{ shape: rounded}
42
- EMU@{ shape: rounded}
43
- style subGraph0 color:#fff,fill:#5555
44
- style HOST color:#000000,fill:#BBDEFB,stroke-width:4px,stroke-dasharray:0
45
- style MCP color:#000000,fill:#FFF9C4
46
- style EMU color:#FFFFFF,fill:#0000FF,stroke-width:4px,stroke-dasharray:0
72
+
73
+ HOST@{ shape: rounded }
74
+ MCP@{ shape: rounded }
75
+ EMU@{ shape: rounded }
76
+ LOCALDATA@{ shape: docs }
77
+ EXTDATA@{ shape: docs }
78
+ style yourComputerGroup color:#fff,fill:#4444,text-align:left
79
+ style mcpGroup color:#fff,fill:#4444
80
+ style HOST color:#000000,fill:#BBDEFB,stroke-width:4px,stroke-dasharray:0
81
+ style MCP color:#000000,fill:#FFF9C4
82
+ style EMU color:#FFFFFF,fill:#0000FF,stroke-width:4px,stroke-dasharray:0
47
83
  ```
48
84
 
49
- The MCP server translates high-level commands from your Copilot AI into `TCL` commands to control `openMSX`, enabling automated MSX software _testing_ and _debugging_.
85
+ The MCP server translates high-level natural language commands from your Copilot AI into `TCL` commands to control `openMSX`, enabling automated MSX software testing and debugging.
50
86
 
51
- ## 🛠️ Available MCP Tools
87
+ ## Available MCP Tools
52
88
 
53
89
  ### Emulator Control Tools
54
90
  - `emu_control`: Controls an openMSX emulator: _`launch`, `close`, `powerOn`, `powerOff`, `reset`, `getEmulatorSpeed`, `setEmulatorSpeed`, `machineList`, `extensionList`, `wait`_.
@@ -74,7 +110,11 @@ The MCP server translates high-level commands from your Copilot AI into `TCL` co
74
110
  - `screen_dump`: Export screen data as BASIC BSAVE instruction.
75
111
  - `msxdocs_resource_get`: Retrieve MCP resources for MCP clients that don't support MCP resources.
76
112
 
77
- ## 📚 Available MCP Resources
113
+ ### Documentation Tools
114
+ - `vector_db_query`: Query the Vector DB resources to obtain information about MSX systems, cartridges, and other development resources.
115
+ - `msxdocs_resource_get`: Retrieve MCP resources for MCP clients that don't support MCP resources.
116
+
117
+ ## Available MCP Resources
78
118
 
79
119
  ### What are MCP Resources?
80
120
 
@@ -116,20 +156,21 @@ Thanks to the authors of these resources, who have made them available under var
116
156
 
117
157
  The rights to these resources belong to their respective authors and are distributed under the licenses they have defined.
118
158
 
119
- ## 🚀 Quick Start
159
+ ## Quick Start
120
160
 
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.
161
+ You can use this MCP server in this basic way with the [precompiled NPM package](https://www.npmjs.com/package/@nataliapc/mcp-openmsx).
122
162
 
123
- ### 🟢 Basic Usage with VSCode
163
+ ### Quick installation with VSCode
124
164
 
165
+ [![Install in VS Code](https://img.shields.io/badge/VS_Code-Install_MCP_Server-0098FF?style=flat&logo=visualstudiocode&logoColor=ffffff)](https://insiders.vscode.dev/redirect/mcp/install?name=mcp-openmsx&config=%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)
166
+
167
+ Steps to install the MCP server in VSCode:
125
168
  * Install [Github Copilot extension](https://code.visualstudio.com/docs/copilot/overview)
126
- * Add to your workspace a file `.vscode/mcp.json` with:
169
+ * Use the **Install MCP Server** button above to install the MCP server in your VSCode settings.
170
+ * Or add to your workspace a file `.vscode/mcp.json` with the json configuration below.
127
171
 
128
172
  ### STDIO mode (recommended)
129
173
 
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
174
  ```json
134
175
  {
135
176
  "servers": {
@@ -137,7 +178,7 @@ You can use this MCP server in this basic way with the [precompiled NPM package]
137
178
  "command": "npx",
138
179
  "args": ["@nataliapc/mcp-openmsx"],
139
180
  "env": {
140
- "OPENMSX_SHARE_DIR": "/usr/share/openmsx"
181
+ "OPENMSX_SHARE_DIR": "C:\\the\\location\\of\\your\\openmsx\\share\\folder"
141
182
  }
142
183
  }
143
184
  }
@@ -162,9 +203,11 @@ You can use this MCP server in this basic way with the [precompiled NPM package]
162
203
 
163
204
  **Note:** The MCP HTTP Server must be running standalone in the same computer or in another (`make run_http`).
164
205
 
165
- ### 🟢 Basic Usage with Claude Desktop
206
+ ### Basic Installation with Claude Desktop
166
207
 
167
- Add to your `claude_desktop_config.json`:
208
+ Follow [these instrutions](https://modelcontextprotocol.io/quickstart/user#for-claude-desktop-users) to access Claude's `claude_desktop_config.json` file.
209
+
210
+ Edit it to include the following JSON entry:
168
211
 
169
212
  ```json
170
213
  {
@@ -173,14 +216,16 @@ Add to your `claude_desktop_config.json`:
173
216
  "command": "npx",
174
217
  "args": ["@nataliapc/mcp-openmsx"],
175
218
  "env": {
176
- "OPENMSX_SHARE_DIR": "/usr/share/openmsx"
219
+ "OPENMSX_SHARE_DIR": "C:\\the\\location\\of\\your\\openmsx\\share\\folder"
177
220
  }
178
221
  }
179
222
  }
180
223
  }
181
224
  ```
182
225
 
183
- ### 🟢 Environment Variables
226
+ **Note:** Environment variables are optional. Customize them as you need.
227
+
228
+ ### Environment Variables
184
229
 
185
230
  | Variable | Description | Default Value | Example |
186
231
  |----------|-------------|---------------|---------|
@@ -193,7 +238,9 @@ Add to your `claude_desktop_config.json`:
193
238
  | `MCP_HTTP_PORT` | Port number for HTTP transport mode | `3000` | `8080` |
194
239
 
195
240
 
196
- ## 🧑‍💻 Advanced Manual Usage
241
+ ## Advanced Manual Usage
242
+
243
+ This is not needed for using the MCP server, but if you want to install it manually, follow these steps.
197
244
 
198
245
  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
246
 
@@ -230,10 +277,11 @@ MCP_TRANSPORT=http mcp-openmsx
230
277
  mcp-openmsx http
231
278
  ```
232
279
 
280
+ ## Development
233
281
 
234
- ## 💡 Development
282
+ This is not needed for using the MCP server, but if you want to contribute or modify the code, follow these steps.
235
283
 
236
- ### Prerequisites
284
+ ### Prerequisites to build
237
285
 
238
286
  - Node.js >= 18.0.0
239
287
  - TypeScript
@@ -254,18 +302,17 @@ npm run build
254
302
  npm run dev
255
303
  ```
256
304
 
257
-
258
- ## 🪪 License
305
+ ## License
259
306
 
260
307
  GPL2 License - see [LICENSE](LICENSE) file for details.
261
308
 
262
309
 
263
- ## 🆘 Support
310
+ ## Support
264
311
 
265
312
  If you need help, or have questions or suggestions, please open an issue on the [GitHub Issues](https://github.com/nataliapc/mcp-openmsx/issues) page or check the project discussions.
266
313
 
267
314
 
268
- ## 🤝 Contributing
315
+ ## Contributing
269
316
 
270
317
  Contributions are welcome! Please feel free to submit a Pull Request.
271
318
 
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,18 +19,22 @@ import express from "express";
20
19
  import fs from "fs/promises";
21
20
  import path from "path";
22
21
  import { openMSXInstance } from "./openmsx.js";
23
- import { fetchCleanWebpage, addFileExtension, listResourcesDirectory, encodeTypeText, isErrorResponse, getResponseContent } from "./utils.js";
24
- // Version info for CLI
25
- export const PACKAGE_VERSION = "1.1.15";
22
+ import { VectorDB } from "./vectordb.js";
23
+ import { createRequire } from 'module';
24
+ import { detectOpenMSXShareDir, fetchCleanWebpage, addFileExtension, listResourcesDirectory, encodeTypeText, isErrorResponse, getResponseContent } from "./utils.js";
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
- var OPENMSX_SHARE_DIR = '/usr/share/openmsx';
32
+ var OPENMSX_SHARE_DIR = '';
30
33
  var OPENMSX_REPLAYS_DIR = '';
31
34
  var OPENMSX_SCREENSHOT_DIR = '';
32
35
  var OPENMSX_SCREENDUMP_DIR = '';
33
- var MACHINES_DIR = `${OPENMSX_SHARE_DIR}/machines`;
34
- var EXTENSIONS_DIR = `${OPENMSX_SHARE_DIR}/extensions`;
36
+ var MACHINES_DIR = '';
37
+ var EXTENSIONS_DIR = '';
35
38
  // ============================================================================
36
39
  // Tools available in the MCP server
37
40
  // https://modelcontextprotocol.io/docs/concepts/tools#tool-definition-structure
@@ -625,12 +628,12 @@ async function registerAllTools(server) {
625
628
  break;
626
629
  case "saveReplay":
627
630
  if (filename)
628
- filename = `"${OPENMSX_REPLAYS_DIR}${filename}"`;
631
+ filename = path.join(OPENMSX_REPLAYS_DIR, filename);
629
632
  tclCommand = `reverse savereplay ${filename || ''}`;
630
633
  break;
631
634
  case "loadReplay":
632
635
  if (filename)
633
- filename = `"${OPENMSX_REPLAYS_DIR}${filename}"`;
636
+ filename = path.join(OPENMSX_REPLAYS_DIR, filename);
634
637
  tclCommand = `reverse loadreplay ${filename}`;
635
638
  break;
636
639
  default:
@@ -692,7 +695,7 @@ async function registerAllTools(server) {
692
695
  },
693
696
  // Handler for the tool (function to be executed when the tool is called)
694
697
  async ({ command }) => {
695
- const openmsxCommand = `screenshot -raw -prefix "${OPENMSX_SCREENSHOT_DIR}mcp_"`;
698
+ const openmsxCommand = `screenshot -raw -prefix "${path.join(OPENMSX_SCREENSHOT_DIR, 'mcp_')}"`;
696
699
  const response = await openMSXInstance.sendCommand(openmsxCommand);
697
700
  switch (command) {
698
701
  case "as_image":
@@ -748,7 +751,7 @@ The parameter scrbasename is the name of the filename (without path) to save the
748
751
  },
749
752
  // Handler for the tool (function to be executed when the tool is called)
750
753
  async ({ scrbasename }) => {
751
- const openmsxCommand = `save_msx_screen "${OPENMSX_SCREENDUMP_DIR + scrbasename}"`;
754
+ const openmsxCommand = `save_msx_screen "${path.join(OPENMSX_SCREENDUMP_DIR, scrbasename)}"`;
752
755
  const response = await openMSXInstance.sendCommand(openmsxCommand);
753
756
  return getResponseContent([
754
757
  isErrorResponse(response) ? 'Fail:' : 'Screendump file saved as:',
@@ -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: [{
@@ -1101,7 +1149,8 @@ Environment variables:
1101
1149
  OPENMSX_SHARE_DIR openMSX share directory
1102
1150
  OPENMSX_SCREENSHOT_DIR Screenshot output directory
1103
1151
  OPENMSX_SCREENDUMP_DIR Screen dump output directory
1104
- MCP_HTTP_PORT HTTP server port (default: 3000)
1152
+ OPENMSX_REPLAYS_DIR Replay output directory
1153
+ MCP_HTTP_PORT HTTP server port (default: 3000)
1105
1154
 
1106
1155
  Examples:
1107
1156
  mcp-openmsx # stdio transport
@@ -1201,19 +1250,31 @@ async function main() {
1201
1250
  OPENMSX_EXECUTABLE = process.env.OPENMSX_EXECUTABLE;
1202
1251
  }
1203
1252
  if (process.env.OPENMSX_SCREENSHOT_DIR && process.env.OPENMSX_SCREENSHOT_DIR !== '') {
1204
- OPENMSX_SCREENSHOT_DIR = process.env.OPENMSX_SCREENSHOT_DIR + path.sep;
1253
+ OPENMSX_SCREENSHOT_DIR = process.env.OPENMSX_SCREENSHOT_DIR;
1205
1254
  }
1206
1255
  if (process.env.OPENMSX_SCREENDUMP_DIR && process.env.OPENMSX_SCREENDUMP_DIR !== '') {
1207
- OPENMSX_SCREENDUMP_DIR = process.env.OPENMSX_SCREENDUMP_DIR + path.sep;
1256
+ OPENMSX_SCREENDUMP_DIR = process.env.OPENMSX_SCREENDUMP_DIR;
1208
1257
  }
1209
1258
  if (process.env.OPENMSX_REPLAYS_DIR && process.env.OPENMSX_REPLAYS_DIR !== '') {
1210
- OPENMSX_REPLAYS_DIR = process.env.OPENMSX_REPLAYS_DIR + path.sep;
1259
+ OPENMSX_REPLAYS_DIR = process.env.OPENMSX_REPLAYS_DIR;
1260
+ }
1261
+ if (process.env.OPENMSX_SHARE_DIR && process.env.OPENMSX_SHARE_DIR !== '') {
1262
+ OPENMSX_SHARE_DIR = process.env.OPENMSX_SHARE_DIR;
1211
1263
  }
1212
- if (process.env.OPENMSX_SHARE_DIR) {
1213
- OPENMSX_SHARE_DIR = process.env.OPENMSX_SHARE_DIR + path.sep;
1214
- MACHINES_DIR = `${OPENMSX_SHARE_DIR}machines`;
1215
- EXTENSIONS_DIR = `${OPENMSX_SHARE_DIR}extensions`;
1264
+ else {
1265
+ // Auto-detect openMSX share directory if not set
1266
+ const detectedShareDir = detectOpenMSXShareDir();
1267
+ if (detectedShareDir) {
1268
+ OPENMSX_SHARE_DIR = detectedShareDir;
1269
+ console.warn(`Auto-detected openMSX share folder: ${OPENMSX_SHARE_DIR}`);
1270
+ }
1271
+ else {
1272
+ console.error("Error: OPENMSX_SHARE_DIR environment variable is not set and could not be auto-detected.");
1273
+ }
1216
1274
  }
1275
+ MACHINES_DIR = path.join(OPENMSX_SHARE_DIR, 'machines');
1276
+ EXTENSIONS_DIR = path.join(OPENMSX_SHARE_DIR, 'extensions');
1277
+ VectorDB.setIndexDirectory(vectorDbDir);
1217
1278
  // Detect transport type from environment or command line
1218
1279
  const transportType = process.env.MCP_TRANSPORT || process.argv[2] || 'stdio';
1219
1280
  if (transportType === 'http') {
package/dist/utils.js CHANGED
@@ -10,6 +10,38 @@ import mime from 'mime-types';
10
10
  import { gunzipSync } from 'zlib';
11
11
  import { PACKAGE_VERSION } from "./server.js";
12
12
  import sanitizeHtml from 'sanitize-html';
13
+ import { existsSync } from "fs";
14
+ import os from "os";
15
+ /**
16
+ * Detect the openMSX share directory by checking various methods
17
+ * @returns string - The detected share directory or an empty string if not found
18
+ */
19
+ export function detectOpenMSXShareDir() {
20
+ try {
21
+ // Check standard locations
22
+ const possiblePaths = [
23
+ // Linux paths
24
+ path.join(os.homedir(), '.openMSX', 'share'),
25
+ '/usr/local/share/openmsx',
26
+ '/usr/share/openmsx',
27
+ // Windows paths
28
+ path.join(os.homedir(), 'Documents', 'openMSX', 'share'),
29
+ path.join(process.env.PROGRAMFILES || 'C:\\Program Files', 'openMSX', 'share'),
30
+ // macOS paths
31
+ path.join(os.homedir(), 'Library', 'Application Support', 'openMSX', 'share'),
32
+ '/Applications/openMSX.app/Contents/Resources/share',
33
+ ];
34
+ for (const dirPath of possiblePaths) {
35
+ if (existsSync(dirPath) && existsSync(path.join(dirPath, 'machines'))) {
36
+ return dirPath;
37
+ }
38
+ }
39
+ }
40
+ catch (error) {
41
+ console.error('Error detecting openMSX share directory:', error);
42
+ }
43
+ return '';
44
+ }
13
45
  /**
14
46
  * Extract description from XML file
15
47
  * @param filePath - Full path to the XML file
@@ -54,13 +86,13 @@ export async function addFileExtension(filePath) {
54
86
  return ['text/plain', filePath];
55
87
  }
56
88
  /**
57
- * List all folders in the resources directory
89
+ * List all folders and subfolders in the resources directory
58
90
  * @param resourcesDir - Path to the resources directory
59
91
  * @returns Promise<string[]> - List of folder names in the resources directory
60
92
  */
61
93
  export async function listResourcesDirectory(resourcesDir) {
62
94
  try {
63
- const directories = await fs.readdir(resourcesDir, { withFileTypes: true });
95
+ const directories = await fs.readdir(resourcesDir, { withFileTypes: true, recursive: true });
64
96
  const folderNames = directories
65
97
  .filter(dirent => dirent.isDirectory())
66
98
  .map(dirent => dirent.name);
@@ -229,3 +261,11 @@ export function getResponseContent(response, isError = false) {
229
261
  isError: hasError
230
262
  };
231
263
  }
264
+ /*
265
+ * Sleep for a specified number of milliseconds
266
+ * @param ms - Number of milliseconds to sleep
267
+ * @returns Promise that resolves after the specified time
268
+ */
269
+ export function sleep(ms) {
270
+ return new Promise(resolve => setTimeout(resolve, ms));
271
+ }
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Vector Database wrapper class
3
+ *
4
+ * @author Natalia Pujol Cremades (@nataliapc)
5
+ * @license GPL2
6
+ */
7
+ import path from 'path';
8
+ import { LocalIndex } from 'vectra';
9
+ import embeddings from '@themaximalist/embeddings.js';
10
+ export class VectorDB {
11
+ static instance;
12
+ static vectorDbDir = path.join('..', 'vector-db');
13
+ index;
14
+ static getInstance() {
15
+ if (!VectorDB.instance) {
16
+ VectorDB.instance = new VectorDB();
17
+ }
18
+ return VectorDB.instance;
19
+ }
20
+ static setIndexDirectory(dbDir) {
21
+ VectorDB.vectorDbDir = dbDir;
22
+ }
23
+ constructor(dbDir = VectorDB.vectorDbDir) {
24
+ this.index = new LocalIndex(dbDir);
25
+ if (!this.initDatabase()) {
26
+ throw new Error('Failed to initialize VectorDB: Index does not exist');
27
+ }
28
+ }
29
+ async initDatabase() {
30
+ return await this.index.isIndexCreated();
31
+ }
32
+ async getVector(text) {
33
+ const response = await embeddings(text);
34
+ if (!response || !Array.isArray(response) || response.length === 0) {
35
+ throw new Error('Failed to generate embedding vector');
36
+ }
37
+ return response;
38
+ }
39
+ async query(text) {
40
+ const vector = await this.getVector(text);
41
+ let results = [];
42
+ try {
43
+ results = await this.index.queryItems(vector, text, 10);
44
+ if (results.length > 0) {
45
+ return results.map(result => {
46
+ return {
47
+ score: result.score.toFixed(4),
48
+ uri: result.item.metadata?.uri || 'unknown',
49
+ title: result.item.metadata?.title || 'unknown',
50
+ document: String(result.item.metadata?.document || ''),
51
+ id: result.item.metadata?.id || 'unknown',
52
+ };
53
+ });
54
+ }
55
+ }
56
+ catch (error) {
57
+ throw new Error(`Query failed: ${error}`);
58
+ }
59
+ return results;
60
+ }
61
+ }
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.3",
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
  ],