Integrate MCP-go and add command prompt

This commit is contained in:
giongto35 2025-06-13 01:29:05 -07:00
parent aca9b84020
commit b62b410dca
7 changed files with 56 additions and 18 deletions

9
go.mod
View file

@ -17,10 +17,11 @@ require (
github.com/pion/logging v0.2.3
github.com/pion/webrtc/v4 v4.1.0
github.com/rs/xid v1.6.0
github.com/rs/zerolog v1.34.0
github.com/veandco/go-sdl2 v0.4.40
golang.org/x/crypto v0.37.0
golang.org/x/image v0.25.0
github.com/rs/zerolog v1.34.0
github.com/veandco/go-sdl2 v0.4.40
github.com/mark3labs/mcp-go v0.1.0
golang.org/x/crypto v0.37.0
golang.org/x/image v0.25.0
gopkg.in/yaml.v3 v3.0.1
)

View file

@ -2,22 +2,15 @@ package mcp
import (
"encoding/binary"
"encoding/json"
mcpg "github.com/mark3labs/mcp-go"
)
type Action struct {
Key string `json:"key"`
Press bool `json:"press"`
}
type Action = mcpg.Action
type Message struct {
Actions []Action `json:"actions"`
}
type Message = mcpg.Message
func Parse(data []byte) (Message, error) {
var m Message
err := json.Unmarshal(data, &m)
return m, err
return mcpg.Parse(data)
}
func actionBytes(a Action) []byte {
@ -26,7 +19,6 @@ func actionBytes(a Action) []byte {
if a.Press {
buf[4] = 1
}
// last two bytes are modifier flags, not used
return buf
}

View file

@ -103,6 +103,7 @@
class="record-user" aria-label="">
<div id="btn-rec" class="btn" data-key="rec"></div>
{{end}}
<input id="mcp-cmd" type="text" placeholder="enter command" aria-label="mcp command">
</div>
<div class="source"><span>Cloudretro (ɔ) 2025</span>
<a rel="noopener noreferrer" target="_blank" href="https://github.com/giongto35/cloud-game">
@ -121,7 +122,8 @@
"log": "./js/log.js?v=3",
"network": "./js/network/network.js?v=3",
"settings": "./js/settings.js?v=3",
"utils": "./js/utils.js?v=3"
"utils": "./js/utils.js?v=3",
"mcp": "./js/mcp.js?v=3"
}
}
</script>

View file

@ -29,6 +29,9 @@ let transport = {
},
mouse: (packet) => {
log.warn('Default transport is used! Change it with the api.transport variable.', packet)
},
mcp: (packet) => {
log.warn('Default transport is used! Change it with the api.transport variable.', packet)
}
}
@ -116,6 +119,10 @@ const mousePress = (() => {
}
})()
const mcpSend = (cmd = '') => {
transport.mcp(cmd)
}
const libretro = function () {// RETRO_KEYBOARD
const retro = {
@ -317,7 +324,8 @@ export const api = {
mouse: {
move: mouseMove,
press: mousePress,
}
},
mcp: mcpSend
},
load: () => packet(endpoints.GAME_LOAD),
reset: (roomId) => packet(endpoints.GAME_RESET, {room_id: roomId}),

View file

@ -55,6 +55,7 @@ import {screen} from './screen.js?v=3';
import {stats} from './stats.js?v=3';
import {stream} from './stream.js?v=3';
import {workerManager} from "./workerManager.js?v=3";
import {mcp} from './mcp.js?v=3';
settings.init();
log.level = settings.loadOr(opts.LOG_LEVEL, log.DEFAULT);
@ -539,6 +540,7 @@ sub(SETTINGS_CHANGED, () => {
setState(app.state.eden);
input.init()
mcp.init()
stream.init();
screen.init();
@ -552,6 +554,7 @@ api.transport = {
send: socket.send,
keyboard: webrtc.keyboard,
mouse: webrtc.mouse,
mcp: webrtc.mcp,
}
// stats

21
web/js/mcp.js Normal file
View file

@ -0,0 +1,21 @@
import {pub, KEYBOARD_TOGGLE_FILTER_MODE} from 'event';
import {webrtc} from 'network';
import {log} from 'log';
const inputEl = document.getElementById('mcp-cmd');
export const mcp = {
init: () => {
if (!inputEl) return;
inputEl.addEventListener('focus', () => pub(KEYBOARD_TOGGLE_FILTER_MODE));
inputEl.addEventListener('blur', () => pub(KEYBOARD_TOGGLE_FILTER_MODE, {mode: true}));
inputEl.addEventListener('keydown', e => {
if (e.key === 'Enter') {
e.preventDefault();
webrtc.mcp(inputEl.value);
inputEl.value = '';
}
});
log.info('[mcp] initialized');
}
};

View file

@ -12,6 +12,7 @@ let connection;
let dataChannel
let keyboardChannel
let mouseChannel
let mcpChannel
let mediaStream;
let candidates = [];
let isAnswered = false;
@ -42,6 +43,11 @@ const start = (iceservers) => {
return
}
if (e.channel.label === 'mcp') {
mcpChannel = e.channel
return
}
dataChannel = e.channel;
dataChannel.onopen = () => {
log.info('[rtc] the input channel has been opened');
@ -88,6 +94,10 @@ const stop = () => {
mouseChannel?.close()
mouseChannel = null
}
if (mcpChannel) {
mcpChannel?.close()
mcpChannel = null
}
candidates = [];
log.info('[rtc] WebRTC has been closed');
}
@ -187,6 +197,7 @@ export const webrtc = {
},
keyboard: (data) => keyboardChannel?.send(data),
mouse: (data) => mouseChannel?.send(data),
mcp: (data) => mcpChannel?.send(data),
input: (data) => inputReady && dataChannel.send(data),
isConnected: () => connected,
isInputReady: () => inputReady,