@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.
- package/README.md +84 -37
- package/dist/server.js +101 -40
- package/dist/utils.js +42 -2
- package/dist/vectordb.js +61 -0
- package/package.json +8 -3
- package/resources/audio/msx-midi.md +872 -0
- package/resources/audio/psg_registers.md +281 -0
- package/resources/audio/sound_cartridge_scc.md +123 -0
- package/resources/audio/sound_cartridge_scci.md +250 -0
- package/resources/audio/toc.json +8 -4
- package/resources/book--msx2-technical-handbook/toc.json +1 -1
- package/resources/msx-dos/MSX-DOS_2_Environment_Variables.md +1368 -0
- package/resources/msx-dos/MSX-DOS_File_extensions.md +154 -0
- package/resources/msx-dos/toc.json +13 -0
- package/resources/msx-unapi/toc.json +2 -2
- package/resources/others/keyboard_matrices.md +243 -0
- package/resources/others/toc.json +6 -0
- package/resources/programming/asm_callbios.md +79 -0
- package/resources/programming/asm_docopy.md +115 -0
- package/resources/programming/asm_fast_loops.md +200 -0
- package/resources/programming/asm_getslot.md +143 -0
- package/resources/programming/asm_interrupts.md +202 -0
- package/resources/programming/asm_load_screen.md +240 -0
- package/resources/programming/asm_mult_div_shifts.md +487 -0
- package/resources/programming/asm_raminpage1.md +56 -0
- package/resources/programming/asm_vdp_detection.md +78 -0
- package/resources/programming/asm_vdp_routines.md +343 -0
- package/resources/programming/asm_z80_routines_collection.md +810 -0
- package/resources/programming/basic_wiki/ABS().md +36 -0
- package/resources/programming/basic_wiki/AND.md +71 -0
- package/resources/programming/basic_wiki/ASC().md +38 -0
- package/resources/programming/basic_wiki/ATN().md +36 -0
- package/resources/programming/basic_wiki/AUTO.md +39 -0
- package/resources/programming/basic_wiki/BASE().md +147 -0
- package/resources/programming/basic_wiki/BEEP.md +27 -0
- package/resources/programming/basic_wiki/BIN$().md +36 -0
- package/resources/programming/basic_wiki/BLOAD.md +63 -0
- package/resources/programming/basic_wiki/BSAVE.md +61 -0
- package/resources/programming/basic_wiki/CALL.md +391 -0
- package/resources/programming/basic_wiki/CALL_ADJUST.md +40 -0
- package/resources/programming/basic_wiki/CALL_IMPOSE.md +28 -0
- package/resources/programming/basic_wiki/CALL_OPTIONS.md +26 -0
- package/resources/programming/basic_wiki/CALL_PAUSE.md +119 -0
- package/resources/programming/basic_wiki/CALL_PCMPLAY.md +60 -0
- package/resources/programming/basic_wiki/CALL_PCMREC.md +70 -0
- package/resources/programming/basic_wiki/CDBL().md +36 -0
- package/resources/programming/basic_wiki/CHR$().md +51 -0
- package/resources/programming/basic_wiki/CINT().md +36 -0
- package/resources/programming/basic_wiki/CIRCLE.md +51 -0
- package/resources/programming/basic_wiki/CLEAR.md +39 -0
- package/resources/programming/basic_wiki/CLOAD.md +27 -0
- package/resources/programming/basic_wiki/CLOAD?.md +31 -0
- package/resources/programming/basic_wiki/CLOSE.md +44 -0
- package/resources/programming/basic_wiki/CLS.md +51 -0
- package/resources/programming/basic_wiki/COLOR.md +143 -0
- package/resources/programming/basic_wiki/COLOR=.md +93 -0
- package/resources/programming/basic_wiki/COLOR_SPRITE$().md +83 -0
- package/resources/programming/basic_wiki/COLOR_SPRITE().md +85 -0
- package/resources/programming/basic_wiki/CONT.md +23 -0
- package/resources/programming/basic_wiki/COPY.md +215 -0
- package/resources/programming/basic_wiki/COPY_SCREEN.md +61 -0
- package/resources/programming/basic_wiki/COS().md +37 -0
- package/resources/programming/basic_wiki/CSAVE.md +35 -0
- package/resources/programming/basic_wiki/CSNG().md +36 -0
- package/resources/programming/basic_wiki/CSRLIN.md +33 -0
- package/resources/programming/basic_wiki/DATA.md +47 -0
- package/resources/programming/basic_wiki/DEFDBL.md +40 -0
- package/resources/programming/basic_wiki/DEFINT.md +40 -0
- package/resources/programming/basic_wiki/DEFSNG.md +40 -0
- package/resources/programming/basic_wiki/DEFSTR.md +40 -0
- package/resources/programming/basic_wiki/DEF_FN.md +49 -0
- package/resources/programming/basic_wiki/DEF_USR.md +33 -0
- package/resources/programming/basic_wiki/DELETE.md +49 -0
- package/resources/programming/basic_wiki/DIM.md +59 -0
- package/resources/programming/basic_wiki/DRAW.md +77 -0
- package/resources/programming/basic_wiki/ELSE.md +45 -0
- package/resources/programming/basic_wiki/END.md +32 -0
- package/resources/programming/basic_wiki/EOF().md +36 -0
- package/resources/programming/basic_wiki/EQV.md +76 -0
- package/resources/programming/basic_wiki/ERASE.md +35 -0
- package/resources/programming/basic_wiki/ERL.md +34 -0
- package/resources/programming/basic_wiki/ERR.md +143 -0
- package/resources/programming/basic_wiki/ERROR.md +145 -0
- package/resources/programming/basic_wiki/EXP().md +38 -0
- package/resources/programming/basic_wiki/FIELD.md +48 -0
- package/resources/programming/basic_wiki/FIX().md +44 -0
- package/resources/programming/basic_wiki/FN.md +61 -0
- package/resources/programming/basic_wiki/FOR...NEXT.md +80 -0
- package/resources/programming/basic_wiki/FRE().md +66 -0
- package/resources/programming/basic_wiki/GET_DATE.md +60 -0
- package/resources/programming/basic_wiki/GET_TIME.md +34 -0
- package/resources/programming/basic_wiki/GOSUB.md +41 -0
- package/resources/programming/basic_wiki/GOTO.md +41 -0
- package/resources/programming/basic_wiki/HEX$().md +36 -0
- package/resources/programming/basic_wiki/IF...GOTO...ELSE.md +55 -0
- package/resources/programming/basic_wiki/IF...THEN...ELSE.md +50 -0
- package/resources/programming/basic_wiki/IMP.md +83 -0
- package/resources/programming/basic_wiki/INKEY$.md +65 -0
- package/resources/programming/basic_wiki/INP().md +33 -0
- package/resources/programming/basic_wiki/INPUT$().md +51 -0
- package/resources/programming/basic_wiki/INPUT.md +93 -0
- package/resources/programming/basic_wiki/INSTR().md +44 -0
- package/resources/programming/basic_wiki/INT().md +44 -0
- package/resources/programming/basic_wiki/INTERVAL.md +57 -0
- package/resources/programming/basic_wiki/KEY().md +51 -0
- package/resources/programming/basic_wiki/KEY.md +254 -0
- package/resources/programming/basic_wiki/LEFT$().md +39 -0
- package/resources/programming/basic_wiki/LEN().md +36 -0
- package/resources/programming/basic_wiki/LET.md +68 -0
- package/resources/programming/basic_wiki/LINE.md +74 -0
- package/resources/programming/basic_wiki/LINE_INPUT.md +79 -0
- package/resources/programming/basic_wiki/LIST.md +58 -0
- package/resources/programming/basic_wiki/LLIST.md +43 -0
- package/resources/programming/basic_wiki/LOAD.md +56 -0
- package/resources/programming/basic_wiki/LOCATE.md +67 -0
- package/resources/programming/basic_wiki/LOG().md +36 -0
- package/resources/programming/basic_wiki/LPOS().md +31 -0
- package/resources/programming/basic_wiki/LPRINT.md +46 -0
- package/resources/programming/basic_wiki/MAXFILES.md +39 -0
- package/resources/programming/basic_wiki/MERGE.md +54 -0
- package/resources/programming/basic_wiki/MID$().md +72 -0
- package/resources/programming/basic_wiki/MOD.md +39 -0
- package/resources/programming/basic_wiki/MOTOR.md +46 -0
- package/resources/programming/basic_wiki/NEW.md +27 -0
- package/resources/programming/basic_wiki/NOT.md +61 -0
- package/resources/programming/basic_wiki/OCT$().md +36 -0
- package/resources/programming/basic_wiki/ON...GOSUB.md +45 -0
- package/resources/programming/basic_wiki/ON...GOTO.md +42 -0
- package/resources/programming/basic_wiki/ON_ERROR_GOTO.md +61 -0
- package/resources/programming/basic_wiki/ON_INTERVAL_GOSUB.md +54 -0
- package/resources/programming/basic_wiki/ON_KEY_GOSUB.md +56 -0
- package/resources/programming/basic_wiki/ON_SPRITE_GOSUB.md +41 -0
- package/resources/programming/basic_wiki/ON_STOP_GOSUB.md +56 -0
- package/resources/programming/basic_wiki/ON_STRIG_GOSUB.md +70 -0
- package/resources/programming/basic_wiki/OPEN.md +103 -0
- package/resources/programming/basic_wiki/OR.md +75 -0
- package/resources/programming/basic_wiki/OUT.md +35 -0
- package/resources/programming/basic_wiki/PAD().md +110 -0
- package/resources/programming/basic_wiki/PAINT.md +66 -0
- package/resources/programming/basic_wiki/PDL().md +53 -0
- package/resources/programming/basic_wiki/PEEK().md +44 -0
- package/resources/programming/basic_wiki/PLAY().md +58 -0
- package/resources/programming/basic_wiki/PLAY.md +196 -0
- package/resources/programming/basic_wiki/POINT.md +52 -0
- package/resources/programming/basic_wiki/POKE.md +51 -0
- package/resources/programming/basic_wiki/POS().md +36 -0
- package/resources/programming/basic_wiki/PRESET.md +61 -0
- package/resources/programming/basic_wiki/PRINT.md +179 -0
- package/resources/programming/basic_wiki/PSET.md +82 -0
- package/resources/programming/basic_wiki/PUT_KANJI.md +93 -0
- package/resources/programming/basic_wiki/PUT_SPRITE.md +143 -0
- package/resources/programming/basic_wiki/READ.md +45 -0
- package/resources/programming/basic_wiki/REM.md +42 -0
- package/resources/programming/basic_wiki/RENUM.md +78 -0
- package/resources/programming/basic_wiki/RESTORE.md +52 -0
- package/resources/programming/basic_wiki/RESUME.md +45 -0
- package/resources/programming/basic_wiki/RETURN.md +47 -0
- package/resources/programming/basic_wiki/RIGHT$().md +39 -0
- package/resources/programming/basic_wiki/RND().md +51 -0
- package/resources/programming/basic_wiki/RUN.md +56 -0
- package/resources/programming/basic_wiki/SAVE.md +65 -0
- package/resources/programming/basic_wiki/SCREEN.md +164 -0
- package/resources/programming/basic_wiki/SET_ADJUST.md +66 -0
- package/resources/programming/basic_wiki/SET_BEEP.md +76 -0
- package/resources/programming/basic_wiki/SET_DATE.md +103 -0
- package/resources/programming/basic_wiki/SET_PAGE.md +52 -0
- package/resources/programming/basic_wiki/SET_PASSWORD.md +75 -0
- package/resources/programming/basic_wiki/SET_PROMPT.md +61 -0
- package/resources/programming/basic_wiki/SET_SCREEN.md +100 -0
- package/resources/programming/basic_wiki/SET_SCROLL.md +55 -0
- package/resources/programming/basic_wiki/SET_TIME.md +83 -0
- package/resources/programming/basic_wiki/SET_TITLE.md +87 -0
- package/resources/programming/basic_wiki/SET_VIDEO.md +49 -0
- package/resources/programming/basic_wiki/SGN().md +38 -0
- package/resources/programming/basic_wiki/SIN().md +36 -0
- package/resources/programming/basic_wiki/SOUND.md +188 -0
- package/resources/programming/basic_wiki/SPACE$().md +38 -0
- package/resources/programming/basic_wiki/SPC().md +34 -0
- package/resources/programming/basic_wiki/SPRITE$().md +50 -0
- package/resources/programming/basic_wiki/SPRITE.md +31 -0
- package/resources/programming/basic_wiki/SQR().md +32 -0
- package/resources/programming/basic_wiki/STICK().md +70 -0
- package/resources/programming/basic_wiki/STOP.md +70 -0
- package/resources/programming/basic_wiki/STR$().md +37 -0
- package/resources/programming/basic_wiki/STRIG().md +82 -0
- package/resources/programming/basic_wiki/STRING$().md +42 -0
- package/resources/programming/basic_wiki/SWAP.md +62 -0
- package/resources/programming/basic_wiki/TAB().md +38 -0
- package/resources/programming/basic_wiki/TAN().md +36 -0
- package/resources/programming/basic_wiki/TIME.md +59 -0
- package/resources/programming/basic_wiki/TROFF.md +21 -0
- package/resources/programming/basic_wiki/TRON.md +39 -0
- package/resources/programming/basic_wiki/USR().md +66 -0
- package/resources/programming/basic_wiki/VAL().md +36 -0
- package/resources/programming/basic_wiki/VARPTR().md +50 -0
- package/resources/programming/basic_wiki/VDP().md +103 -0
- package/resources/programming/basic_wiki/VPEEK().md +46 -0
- package/resources/programming/basic_wiki/VPOKE.md +48 -0
- package/resources/programming/basic_wiki/WAIT.md +38 -0
- package/resources/programming/basic_wiki/WIDTH.md +76 -0
- package/resources/programming/basic_wiki/XOR.md +72 -0
- package/resources/programming/basic_wiki/_toc.json +871 -0
- package/resources/programming/dos_error_handling.md +85 -0
- package/resources/programming/toc.json +51 -36
- package/resources/programming/vdp_commands_speed.md +147 -0
- package/resources/programming/vdp_programming_faq.md +55 -0
- package/resources/programming/vdp_programming_tutorial.md +390 -0
- package/resources/programming/vdp_screensplit_programming_guide.md +166 -0
- package/resources/programming/vdp_scrolling_on_msx.md +124 -0
- package/resources/programming/vdp_the_yjk_screen_modes.md +227 -0
- package/resources/programming/vdp_v9938_vram_timings.md +539 -0
- package/resources/programming/vdp_v9938_vram_timings_part_2.md +281 -0
- package/resources/sdcc/toc.json +1 -1
- package/vector-db/index.json +1 -0
- /package/resources/msx-unapi/{Ethernet_UNAPI_specification_1.1.md → Ethernet_UNAPI_specification_1_1.md} +0 -0
- /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
|
[](https://www.npmjs.com/package/@nataliapc/mcp-openmsx?activeTab=versions)
|
|
10
10
|
[]()
|
|
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
|
-
##
|
|
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
|
-
- **
|
|
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
|
-
##
|
|
46
|
+
## Architecture
|
|
31
47
|
|
|
32
48
|
```mermaid
|
|
33
49
|
flowchart TB
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
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
|
-
|
|
39
|
-
|
|
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> protocol _"--> MCP
|
|
66
|
+
MCP <--> TOOLS & RESOURCES
|
|
67
|
+
TOOLS <--"_ Query _"--> VECTORDB
|
|
68
|
+
TOOLS <--"_ Console commands _"---> EMU
|
|
69
|
+
RESOURCES <--_ http _---> EXTDATA
|
|
70
|
+
RESOURCES <--> LOCALDATA
|
|
40
71
|
end
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
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
|
|
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
|
-
##
|
|
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
|
-
|
|
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
|
-
##
|
|
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).
|
|
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
|
-
###
|
|
163
|
+
### Quick installation with VSCode
|
|
124
164
|
|
|
165
|
+
[](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
|
-
*
|
|
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
|
-
[](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
|
-
[](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": "
|
|
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
|
-
###
|
|
206
|
+
### Basic Installation with Claude Desktop
|
|
166
207
|
|
|
167
|
-
|
|
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": "
|
|
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
|
-
|
|
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
|
-
##
|
|
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
|
-
|
|
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
|
-
##
|
|
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
|
-
##
|
|
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 {
|
|
24
|
-
|
|
25
|
-
|
|
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 = '
|
|
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 =
|
|
34
|
-
var EXTENSIONS_DIR =
|
|
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 =
|
|
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 =
|
|
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}
|
|
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
|
|
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
|
-
|
|
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()).
|
|
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
|
|
930
|
-
"CDBL()", "CHR$()", "CINT()", "CIRCLE", "CLEAR", "CLOAD", "CLOAD?", "CLOSE", "CLS", "COLOR", "COLOR=", "COLOR SPRITE()",
|
|
931
|
-
"COPY SCREEN", "COS()", "CSAVE", "CSNG()", "CSRLIN", "DATA", "DEFDBL", "DEF FN", "DEFINT", "DEFSNG", "DEFSTR", "DEF USR",
|
|
932
|
-
"END", "EOF()", "EQV", "ERASE", "ERL", "ERR", "ERROR", "EXP()", "FIX()", "FN", "FOR...NEXT", "FRE()", "GET DATE",
|
|
933
|
-
"IF...GOTO...ELSE", "IF...THEN...ELSE", "IMP", "INKEY$", "INP()", "INPUT", "INPUT$()", "INSTR()", "INT()", "INTERVAL",
|
|
934
|
-
"
|
|
935
|
-
"
|
|
936
|
-
"OR", "OUT", "PAD()", "PAINT", "PDL()", "PEEK()", "PLAY", "PLAY()", "POINT", "POKE", "POS()", "PRESET", "PRINT",
|
|
937
|
-
"REM", "RENUM", "RESTORE", "RESUME", "RETURN", "RIGHT$()", "RND()", "RUN", "SAVE", "SCREEN", "SET ADJUST",
|
|
938
|
-
"SET
|
|
939
|
-
"
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
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
|
+
}
|
package/dist/vectordb.js
ADDED
|
@@ -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.
|
|
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.
|
|
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": "^
|
|
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
|
],
|