vscode MCP support is already available!
- Antonio Linares
- Site Admin
- Posts: 42836
- Joined: Thu Oct 06, 2005 5:47 pm
- Location: Spain
- Has thanked: 169 times
- Been thanked: 123 times
- Contact:
- Antonio Linares
- Site Admin
- Posts: 42836
- Joined: Thu Oct 06, 2005 5:47 pm
- Location: Spain
- Has thanked: 169 times
- Been thanked: 123 times
- Contact:
Re: vscode MCP support is already available!
Harbour MCP server 64 bits (must be 64 bits)
go64.bat
hbmcp.hbp
hbmcp.prg
go64.bat
Code: Select all | Expand
@setlocal
call "%ProgramFiles%\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvarsall.bat" amd64
c:\harbour\bin\win\msvc64\hbmk2 hbmcp.hbp -comp=msvc64
@endlocal
Code: Select all | Expand
hbmcp.prg
-lgdiplus
-lole32
-lOleDlg
-lversion
-lucrt
-luxtheme
xhb.hbc
hbct.hbc
hbwin.hbc
hbmzip.hbc
hbziparc.hbc
hbfoxpro.hbc
-ldflag=/NODEFAULTLIB:msvcrt
-ldflag+=/NODEFAULTLIB:libucrt
Code: Select all | Expand
PROCEDURE Main()
LOCAL cInput, cResponse
// Bucle para leer continuamente desde stdin
WHILE .T.
cInput := StdIn()
IF Empty( cInput )
EXIT // Salir si no hay entrada (EOF)
ENDIF
// Procesar el mensaje
hb_memoWrit( "c:\temp\stdin.txt", cInput )
cResponse := ProcessMessage( cInput )
IF !Empty( cResponse )
StdOut( cResponse )
ENDIF
END
RETURN
// Función para procesar mensajes JSON-RPC
FUNCTION ProcessMessage( cInput )
LOCAL cResponse := ""
LOCAL hJson, cId, cMethod, hParams, cToolName
// Decodificar el JSON para obtener el método y el ID
hJson := hb_jsonDecode( cInput )
IF HB_ISHASH( hJson ) .AND. "method" $ hJson .AND. "id" $ hJson
cMethod := hJson[ "method" ]
cId := ExtractId( cInput )
// Manejar el método "initialize"
IF cMethod == "initialize"
cResponse := ;
'{' + ;
'"jsonrpc":"2.0",' + ;
'"id":' + cId + ',' + ;
'"result":{' + ;
'"protocolVersion":"2025-03-26",' + ;
'"capabilities":{' + ;
'"tools":{},' + ;
'"resources":{},' + ;
'"prompts":{}' + ;
'}' + ;
'}' + ;
'}' + hb_eol()
// Manejar el método "tools/list"
ELSEIF cMethod == "tools/list"
cResponse := ;
'{' + ;
'"jsonrpc":"2.0",' + ;
'"id":' + cId + ',' + ;
'"result":{' + ;
'"tools": [' + ;
'{' + ;
'"name":"get_time",' + ;
'"description":"Returns the current system time in YYYY-MM-DD HH:MM:SS format",' + ;
'"schema":{' + ;
'"type":"object",' + ;
'"properties":{},' + ;
'"additionalProperties":false,' + ;
'"returns":{' + ;
'"type":"string"' + ;
'}' + ;
'}' + ;
'},' + ;
'{' + ;
'"name":"hb_version",' + ;
'"description":"Returns the version of the Harbour runtime environment",' + ;
'"schema":{' + ;
'"type":"object",' + ;
'"properties":{},' + ;
'"additionalProperties":false,' + ;
'"returns":{' + ;
'"type":"string"' + ;
'}' + ;
'}' + ;
'},' + ;
'{' + ;
'"name":"hb_compiler",' + ;
'"description":"Returns the name of the compiler used to build the Harbour runtime environment",' + ;
'"schema":{' + ;
'"type":"object",' + ;
'"properties":{},' + ;
'"additionalProperties":false,' + ;
'"returns":{' + ;
'"type":"string"' + ;
'}' + ;
'}' + ;
'}' + ;
']' + ;
'}' + ;
'}' + hb_eol()
// Manejar el método "tools/call"
ELSEIF cMethod == "tools/call"
hParams := hJson[ "params" ]
IF HB_ISHASH( hParams ) .AND. "name" $ hParams .AND. "arguments" $ hParams
cToolName := hParams[ "name" ]
IF cToolName == "get_time" .AND. HB_ISHASH( hParams[ "arguments" ] ) .AND. Empty( hParams[ "arguments" ] )
// Obtener la hora actual en formato "YYYY-MM-DD HH:MM:SS"
cResponse := ;
'{' + ;
'"jsonrpc":"2.0",' + ;
'"id":' + cId + ',' + ;
'"result":"' + hb_DateTime() + '"' + ;
'}' + hb_eol()
ELSEIF cToolName == "hb_version" .AND. HB_ISHASH( hParams[ "arguments" ] ) .AND. Empty( hParams[ "arguments" ] )
// Obtener la versión de Harbour
cResponse := ;
'{' + ;
'"jsonrpc":"2.0",' + ;
'"id":' + cId + ',' + ;
'"result":"' + StrTran( Version(), '"', '\"' ) + '"' + ;
'}' + hb_eol()
ELSEIF cToolName == "hb_compiler" .AND. HB_ISHASH( hParams[ "arguments" ] ) .AND. Empty( hParams[ "arguments" ] )
// Obtener el nombre del compilador
cResponse := ;
'{' + ;
'"jsonrpc":"2.0",' + ;
'"id":' + cId + ',' + ;
'"result":"' + StrTran( hb_Compiler(), '"', '\"' ) + '"' + ;
'}' + hb_eol()
ELSE
// Error: herramienta no encontrada o argumentos inválidos
cResponse := ;
'{' + ;
'"jsonrpc":"2.0",' + ;
'"id":' + cId + ',' + ;
'"error":{' + ;
'"code":-32602,' + ;
'"message":"Invalid params"' + ;
'}' + ;
'}' + hb_eol()
ENDIF
ELSE
// Error: parámetros inválidos
cResponse := ;
'{' + ;
'"jsonrpc":"2.0",' + ;
'"id":' + cId + ',' + ;
'"error":{' + ;
'"code":-32602,' + ;
'"message":"Invalid params"' + ;
'}' + ;
'}' + hb_eol()
ENDIF
// Manejar métodos no soportados
ELSE
cResponse := ;
'{' + ;
'"jsonrpc":"2.0",' + ;
'"id":' + cId + ',' + ;
'"error":{' + ;
'"code":-32601,' + ;
'"message":"Method not found"' + ;
'}' + ;
'}' + hb_eol()
ENDIF
ELSE
// JSON inválido o sin método/ID
cResponse := ;
'{' + ;
'"jsonrpc":"2.0",' + ;
'"id":null,' + ;
'"error":{' + ;
'"code":-32700,' + ;
'"message":"Parse error"' + ;
'}' + ;
'}' + hb_eol()
ENDIF
RETURN cResponse
// Función para extraer el ID parseando el JSON con hb_jsonDecode()
STATIC FUNCTION ExtractId( cInput )
LOCAL hJson, cId := '"1"' // Valor por defecto si falla el parseo
LOCAL xId
// Decodificar el JSON en un hash
hJson := hb_jsonDecode( cInput )
IF HB_ISHASH( hJson ) .AND. "id" $ hJson
xId := hJson[ "id" ]
IF HB_ISSTRING( xId )
// Si el id es string, incluir comillas
cId := '"' + xId + '"'
ELSEIF HB_ISNUMERIC( xId )
// Si el id es numérico, convertir a string sin comillas
cId := hb_ntos( xId )
ELSEIF xId == NIL
// Si el id es null, retornar "null"
cId := "null"
ENDIF
ENDIF
RETURN cId
#pragma BEGINDUMP
#include <hbapi.h>
HB_FUNC( STDIN )
{
char buffer[ 1024 ];
if( fgets( buffer, sizeof( buffer ), stdin ) != NULL )
{
// Eliminar salto de línea final, si existe
size_t len = strlen( buffer );
if( len > 0 && buffer[ len - 1 ] == '\n' )
buffer[ len - 1 ] = '\0';
hb_retc( buffer );
}
else
{
hb_retc( "" ); // Retornar cadena vacía en caso de EOF
}
}
HB_FUNC( STDOUT )
{
if( HB_ISCHAR( 1 ) )
{
fputs( hb_parc( 1 ), stdout );
fflush( stdout ); // Forzar la escritura inmediata
}
}
#pragma ENDDUMP
- Antonio Linares
- Site Admin
- Posts: 42836
- Joined: Thu Oct 06, 2005 5:47 pm
- Location: Spain
- Has thanked: 169 times
- Been thanked: 123 times
- Contact:
Re: vscode MCP support is already available!
Setting for vscode:

Code: Select all | Expand
"mcp": {
"servers": {
"Harbour": {
"type": "stdio",
"command": "c:\\temp\\hbmcp.exe",
"args": []
}
}
}

- Antonio Linares
- Site Admin
- Posts: 42836
- Joined: Thu Oct 06, 2005 5:47 pm
- Location: Spain
- Has thanked: 169 times
- Been thanked: 123 times
- Contact:
Re: vscode MCP support is already available!
Enhanced version:
hbmcp.prg
hbmcp.prg
Code: Select all | Expand
#define LogFile( cKey, cValue ) hb_memoWrit( "c:\temp\hbmcp.log", hb_memoRead( "c:\temp\hbmcp.log" ) + hb_eol() + cKey + cValue )
PROCEDURE Main()
LOCAL cInput, cResponse
// Bucle para leer continuamente desde stdin
WHILE .T.
cInput := StdIn()
IF Empty( cInput )
EXIT // Salir si no hay entrada (EOF)
ENDIF
// Procesar el mensaje
hb_memoWrit( "c:\temp\hbmcp.log", hb_memoRead( "c:\temp\hbmcp.log" ) + hb_eol() + "in: " + cInput )
cResponse := ProcessMessage( cInput )
IF ! Empty( cResponse )
hb_memoWrit( "c:\temp\hbmcp.log", hb_memoRead( "c:\temp\hbmcp.log" ) + hb_eol() + "out: " + cResponse )
StdOut( cResponse )
ENDIF
END
RETURN
// Función para procesar mensajes JSON-RPC
FUNCTION ProcessMessage( cInput )
LOCAL cResponse := ""
LOCAL hJson, cId := "1", cMethod, hParams, cToolName
// Decodificar el JSON para obtener el método y el ID
hb_jsonDecode( cInput, @hJson )
cMethod = hJson[ "method" ]
LogFile( "method: ", cMethod )
// if hb_HHasKey( hJson, "id" )
// cId = hJson[ "id" ]
// else
// cId = "null" // Si no hay id, asignar null
// endif
LogFile( "id: ", cId )
do case
case cMethod == "initialize"
LogFile( "initialize: ", cMethod )
cResponse := ;
'{' + ;
'"jsonrpc":"2.0",' + ;
'"id":' + cId + ',' + ;
'"result":{' + ;
'"protocolVersion":"2025-03-26",' + ;
'"capabilities":{' + ;
'"tools":{},' + ;
'"resources":{},' + ;
'"prompts":{}' + ;
'}' + ;
'}' + ;
'}' + hb_eol()
case cMethod == "notifications/initialized"
cResponse := ;
'{' + ;
'"jsonrpc":"2.0",' + ;
'"result":{' + ;
'"protocolVersion":"2025-03-26",' + ;
'"capabilities":{' + ;
'"tools":{},' + ;
'"resources":{},' + ;
'"prompts":{}' + ;
'}' + ;
'}' + ;
'}' + hb_eol()
case cMethod == "tools/list"
cResponse := ;
'{' + ;
'"jsonrpc":"2.0",' + ;
'"id":' + cId + ',' + ;
'"result":{' + ;
'"tools": [' + ;
'{' + ;
'"name":"get_time",' + ;
'"description":"Returns the current system time in YYYY-MM-DD HH:MM:SS format",' + ;
'"schema":{' + ;
'"type":"object",' + ;
'"properties":{},' + ;
'"additionalProperties":false,' + ;
'"returns":{' + ;
'"type":"string"' + ;
'}' + ;
'}' + ;
'},' + ;
'{' + ;
'"name":"hb_version",' + ;
'"description":"Returns the version of the Harbour runtime environment",' + ;
'"schema":{' + ;
'"type":"object",' + ;
'"properties":{},' + ;
'"additionalProperties":false,' + ;
'"returns":{' + ;
'"type":"string"' + ;
'}' + ;
'}' + ;
'},' + ;
'{' + ;
'"name":"hb_compiler",' + ;
'"description":"Returns the name of the compiler used to build the Harbour runtime environment",' + ;
'"schema":{' + ;
'"type":"object",' + ;
'"properties":{},' + ;
'"additionalProperties":false,' + ;
'"returns":{' + ;
'"type":"string"' + ;
'}' + ;
'}' + ;
'}' + ;
']' + ;
'}' + ;
'}' + hb_eol()
case cMethod == "tools/call"
hParams := hJson[ "params" ]
IF HB_ISHASH( hParams ) .AND. "name" $ hParams .AND. "arguments" $ hParams
cToolName := hParams[ "name" ]
IF cToolName == "get_time" .AND. HB_ISHASH( hParams[ "arguments" ] ) .AND. Empty( hParams[ "arguments" ] )
// Obtener la hora actual en formato "YYYY-MM-DD HH:MM:SS"
cResponse := ;
'{' + ;
'"jsonrpc":"2.0",' + ;
'"id":' + cId + ',' + ;
'"result":"' + hb_DateTime() + '"' + ;
'}' + hb_eol()
ELSEIF cToolName == "hb_version" .AND. HB_ISHASH( hParams[ "arguments" ] ) .AND. Empty( hParams[ "arguments" ] )
// Obtener la versión de Harbour
cResponse := ;
'{' + ;
'"jsonrpc":"2.0",' + ;
'"id":' + cId + ',' + ;
'"result":"' + StrTran( Version(), '"', '\"' ) + '"' + ;
'}' + hb_eol()
ELSEIF cToolName == "hb_compiler" .AND. HB_ISHASH( hParams[ "arguments" ] ) .AND. Empty( hParams[ "arguments" ] )
// Obtener el nombre del compilador
cResponse := ;
'{' + ;
'"jsonrpc":"2.0",' + ;
'"id":' + cId + ',' + ;
'"result":"' + StrTran( hb_Compiler(), '"', '\"' ) + '"' + ;
'}' + hb_eol()
ELSE
// Error: herramienta no encontrada o argumentos inválidos
cResponse := ;
'{' + ;
'"jsonrpc":"2.0",' + ;
'"id":' + cId + ',' + ;
'"error":{' + ;
'"code":-32602,' + ;
'"message":"Invalid params"' + ;
'}' + ;
'}' + hb_eol()
ENDIF
ELSE
// Error: parámetros inválidos
cResponse := ;
'{' + ;
'"jsonrpc":"2.0",' + ;
'"id":' + cId + ',' + ;
'"error":{' + ;
'"code":-32602,' + ;
'"message":"Invalid params"' + ;
'}' + ;
'}' + hb_eol()
ENDIF
// Manejar métodos no soportados
otherwise
cResponse := ;
'{' + ;
'"jsonrpc":"2.0",' + ;
'"id":' + cId + ',' + ;
'"error":{' + ;
'"code":-32601,' + ;
'"message":"Method not found"' + ;
'}' + ;
'}' + hb_eol()
endcase
hb_memoWrit( "c:\temp\hbmcp.log", hb_memoRead( "c:\temp\hbmcp.log" ) + hb_eol() + "response: " + cResponse )
RETURN cResponse
#pragma BEGINDUMP
#include <hbapi.h>
HB_FUNC( STDIN )
{
char buffer[ 1024 ];
if( fgets( buffer, sizeof( buffer ), stdin ) != NULL )
{
// Eliminar salto de línea final, si existe
size_t len = strlen( buffer );
if( len > 0 && buffer[ len - 1 ] == '\n' )
buffer[ len - 1 ] = '\0';
hb_retc( buffer );
}
else
{
hb_retc( "" ); // Retornar cadena vacía en caso de EOF
}
}
HB_FUNC( STDOUT )
{
if( HB_ISCHAR( 1 ) )
{
fputs( hb_parc( 1 ), stdout );
fflush( stdout ); // Forzar la escritura inmediata
}
}
#pragma ENDDUMP
- Antonio Linares
- Site Admin
- Posts: 42836
- Joined: Thu Oct 06, 2005 5:47 pm
- Location: Spain
- Has thanked: 169 times
- Been thanked: 123 times
- Contact:
Re: vscode MCP support is already available!
Working version !!!!
hbmcp.prg

hbmcp.prg
Code: Select all | Expand
#define LogFile( cKey, cValue ) hb_memoWrit( "c:\temp\hbmcp.log", hb_memoRead( "c:\temp\hbmcp.log" ) + hb_eol() + cKey + cValue )
PROCEDURE Main()
LOCAL cInput, cResponse
// Bucle para leer continuamente desde stdin
WHILE .T.
cInput := StdIn()
IF Empty( cInput )
EXIT // Salir si no hay entrada (EOF)
ENDIF
// Procesar el mensaje
LogFile( "in: ", cInput )
cResponse := ProcessMessage( cInput )
IF ! Empty( cResponse )
LogFile( "out: ", cResponse )
StdOut( cResponse )
ENDIF
END
LogFile( "exit: ", "termina" )
RETURN
// Función para procesar mensajes JSON-RPC
FUNCTION ProcessMessage( cInput )
LOCAL cResponse := ""
LOCAL hJson, cId, cMethod, hParams, cToolName
// Decodificar el JSON para obtener el método y el ID
hb_jsonDecode( cInput, @hJson )
cMethod = hJson[ "method" ]
LogFile( "method: ", cMethod )
if hb_HHasKey( hJson, "id" )
cId = AllTrim( Str( hJson[ "id" ] ) )
endif
do case
case cMethod == "initialize"
LogFile( "initialize: ", cMethod )
cResponse := ;
'{' + ;
'"jsonrpc":"2.0",' + ;
'"id":' + cId + ',' + ;
'"result":{' + ;
'"protocolVersion":"2025-03-26",' + ;
'"capabilities":{' + ;
'"tools":{},' + ;
'"resources":{},' + ;
'"prompts":{}' + ;
'}' + ;
'}' + ;
'}' + hb_eol()
case cMethod == "notifications/initialized"
cResponse := ;
'{' + ;
'"jsonrpc":"2.0",' + ;
'"result":{' + ;
'"protocolVersion":"2025-03-26",' + ;
'"capabilities":{' + ;
'"tools":{},' + ;
'"resources":{},' + ;
'"prompts":{}' + ;
'}' + ;
'}' + ;
'}' + hb_eol()
case cMethod == "tools/list"
cResponse := ;
'{' + ;
'"jsonrpc":"2.0",' + ;
'"id":' + cId + ',' + ;
'"result":{' + ;
'"tools": [' + ;
'{' + ;
'"name":"get_time",' + ;
'"description":"Returns the current system time in YYYY-MM-DD HH:MM:SS format",' + ;
'"schema":{' + ;
'"type":"object",' + ;
'"properties":{},' + ;
'"additionalProperties":false,' + ;
'"returns":{' + ;
'"type":"string"' + ;
'}' + ;
'}' + ;
'},' + ;
'{' + ;
'"name":"hb_version",' + ;
'"description":"Returns the version of the Harbour runtime environment",' + ;
'"schema":{' + ;
'"type":"object",' + ;
'"properties":{},' + ;
'"additionalProperties":false,' + ;
'"returns":{' + ;
'"type":"string"' + ;
'}' + ;
'}' + ;
'},' + ;
'{' + ;
'"name":"hb_compiler",' + ;
'"description":"Returns the name of the compiler used to build the Harbour runtime environment",' + ;
'"schema":{' + ;
'"type":"object",' + ;
'"properties":{},' + ;
'"additionalProperties":false,' + ;
'"returns":{' + ;
'"type":"string"' + ;
'}' + ;
'}' + ;
'}' + ;
']' + ;
'}' + ;
'}' + hb_eol()
case cMethod == "tools/call"
cToolName = hJson[ "params" ][ "name" ]
IF cToolName == "get_time"
// Obtener la hora actual en formato "YYYY-MM-DD HH:MM:SS"
cResponse := ;
'{' + ;
'"jsonrpc":"2.0",' + ;
'"id":' + cId + ',' + ;
'"result":{"content":[{"type":"text","text":"' + Time() + '"}]}' + ;
'}' + hb_eol()
ELSEIF cToolName == "hb_version"
// Obtener la versión de Harbour
cResponse := ;
'{' + ;
'"jsonrpc":"2.0",' + ;
'"id":' + cId + ',' + ;
'"result":{"content":[{"type":"text","text":"' + Version() + '"}]}' + ;
'}' + hb_eol()
ELSEIF cToolName == "hb_compiler"
// Obtener el nombre del compilador
cResponse := ;
'{' + ;
'"jsonrpc":"2.0",' + ;
'"id":' + cId + ',' + ;
'"result":{"content":[{"type":"text","text":"' + hb_Compiler() + '"}]}' + ;
'}' + hb_eol()
ELSE
// Error: herramienta no encontrada o argumentos inválidos
cResponse := ;
'{' + ;
'"jsonrpc":"2.0",' + ;
'"id":' + cId + ',' + ;
'"error":{' + ;
'"code":-32602,' + ;
'"message":"Invalid params"' + ;
'}' + ;
'}' + hb_eol()
ENDIF
// Manejar métodos no soportados
otherwise
cResponse := ;
'{' + ;
'"jsonrpc":"2.0",' + ;
'"id":' + cId + ',' + ;
'"error":{' + ;
'"code":-32604,' + ;
'"message":"Method not found"' + cMethod +;
' }' + ;
'}' + hb_eol()
endcase
RETURN cResponse
#pragma BEGINDUMP
#include <hbapi.h>
HB_FUNC( STDIN )
{
char buffer[ 1024 ];
if( fgets( buffer, sizeof( buffer ), stdin ) != NULL )
{
// Eliminar salto de línea final, si existe
size_t len = strlen( buffer );
if( len > 0 && buffer[ len - 1 ] == '\n' )
buffer[ len - 1 ] = '\0';
hb_retc( buffer );
}
else
{
hb_retc( "" ); // Retornar cadena vacía en caso de EOF
}
}
HB_FUNC( STDOUT )
{
if( HB_ISCHAR( 1 ) )
{
fputs( hb_parc( 1 ), stdout );
fflush( stdout ); // Forzar la escritura inmediata
}
}
#pragma ENDDUMP
- Antonio Linares
- Site Admin
- Posts: 42836
- Joined: Thu Oct 06, 2005 5:47 pm
- Location: Spain
- Has thanked: 169 times
- Been thanked: 123 times
- Contact:
Re: vscode MCP support is already available!
Enhanced version:
hbmcp.prg
hbmcp.prg
Code: Select all | Expand
#include "fileio.ch"
PROCEDURE Main()
LOCAL cInput, cResponse
WHILE .T.
cInput := StdIn()
IF Empty( cInput )
EXIT // Salir si no hay entrada (EOF)
ENDIF
LogFile( "in: ", cInput )
cResponse := ProcessMessage( cInput )
IF ! Empty( cResponse )
LogFile( "out: ", cResponse )
StdOut( cResponse )
ENDIF
END
LogFile( "exit: ", "termina" )
RETURN
// Función para procesar mensajes JSON-RPC
FUNCTION ProcessMessage( cInput )
LOCAL cResponse := ""
LOCAL hJson, cId, cMethod, hParams, cToolName
// Decodificar el JSON para obtener el método y el ID
hb_jsonDecode( cInput, @hJson )
cMethod = hJson[ "method" ]
if hb_HHasKey( hJson, "id" )
cId = AllTrim( Str( hJson[ "id" ] ) )
endif
do case
case cMethod == "initialize"
cResponse := ;
'{' + ;
'"jsonrpc":"2.0",' + ;
'"id":' + cId + ',' + ;
'"result":{' + ;
'"protocolVersion":"2025-03-26",' + ;
'"capabilities":{' + ;
'"tools":{},' + ;
'"resources":{},' + ;
'"prompts":{}' + ;
'}' + ;
'}' + ;
'}' + hb_eol()
case cMethod == "notifications/initialized"
cResponse := ;
'{' + ;
'"jsonrpc":"2.0",' + ;
'"result":{' + ;
'"protocolVersion":"2025-03-26",' + ;
'"capabilities":{' + ;
'"tools":{},' + ;
'"resources":{},' + ;
'"prompts":{}' + ;
'}' + ;
'}' + ;
'}' + hb_eol()
case cMethod == "tools/list"
cResponse := ;
'{' + ;
'"jsonrpc":"2.0",' + ;
'"id":' + cId + ',' + ;
'"result":{' + ;
'"tools": [' + ;
'{' + ;
'"name":"get_time",' + ;
'"description":"Returns the current system time in YYYY-MM-DD HH:MM:SS format",' + ;
'"schema":{' + ;
'"type":"object",' + ;
'"properties":{},' + ;
'"additionalProperties":false,' + ;
'"returns":{' + ;
'"type":"string"' + ;
'}' + ;
'}' + ;
'},' + ;
'{' + ;
'"name":"hb_version",' + ;
'"description":"Returns the version of the Harbour runtime environment",' + ;
'"schema":{' + ;
'"type":"object",' + ;
'"properties":{},' + ;
'"additionalProperties":false,' + ;
'"returns":{' + ;
'"type":"string"' + ;
'}' + ;
'}' + ;
'},' + ;
'{' + ;
'"name":"hb_compiler",' + ;
'"description":"Returns the name of the compiler used to build the Harbour runtime environment",' + ;
'"schema":{' + ;
'"type":"object",' + ;
'"properties":{},' + ;
'"additionalProperties":false,' + ;
'"returns":{' + ;
'"type":"string"' + ;
'}' + ;
'}' + ;
'}' + ;
']' + ;
'}' + ;
'}' + hb_eol()
case cMethod == "tools/call"
cToolName = hJson[ "params" ][ "name" ]
IF cToolName == "get_time"
// Obtener la hora actual en formato "YYYY-MM-DD HH:MM:SS"
cResponse := ;
'{' + ;
'"jsonrpc":"2.0",' + ;
'"id":' + cId + ',' + ;
'"result":{"content":[{"type":"text","text":"' + Time() + '"}]}' + ;
'}' + hb_eol()
ELSEIF cToolName == "hb_version"
// Obtener la versión de Harbour
cResponse := ;
'{' + ;
'"jsonrpc":"2.0",' + ;
'"id":' + cId + ',' + ;
'"result":{"content":[{"type":"text","text":"' + Version() + '"}]}' + ;
'}' + hb_eol()
ELSEIF cToolName == "hb_compiler"
// Obtener el nombre del compilador
cResponse := ;
'{' + ;
'"jsonrpc":"2.0",' + ;
'"id":' + cId + ',' + ;
'"result":{"content":[{"type":"text","text":"' + hb_Compiler() + '"}]}' + ;
'}' + hb_eol()
ELSE
// Error: herramienta no encontrada o argumentos inválidos
cResponse := ;
'{' + ;
'"jsonrpc":"2.0",' + ;
'"id":' + cId + ',' + ;
'"error":{' + ;
'"code":-32602,' + ;
'"message":"Invalid params"' + ;
'}' + ;
'}' + hb_eol()
ENDIF
// Manejar métodos no soportados
otherwise
cResponse := ;
'{' + ;
'"jsonrpc":"2.0",' + ;
'"id":' + cId + ',' + ;
'"error":{' + ;
'"code":-32604,' + ;
'"message":"Method not found"' + cMethod +;
' }' + ;
'}' + hb_eol()
endcase
RETURN cResponse
FUNCTION LogFile( cKey, cValue )
LOCAL nHandle, lSuccess
// Considerar hacer la ruta configurable
if ! File( "c:\temp\hbmcp.log" )
// Crear el archivo si no existe
nHandle := fopen( "c:\temp\hbmcp.log", FO_WRITE + FO_CREAT )
else
// Abrir el archivo para añadir contenido
nHandle := fopen( "c:\temp\hbmcp.log", FO_WRITE )
endif
IF nHandle > 0
FSeek( nHandle, 0, FS_END ) // Mover el puntero al final del archivo
lSuccess = fWrite( nHandle, cKey + cValue + hb_eol() )
fclose( nHandle )
RETURN lSuccess // Opcional: retornar éxito/fallo
ENDIF
RETURN .F.
#pragma BEGINDUMP
#include <hbapi.h>
HB_FUNC( STDIN )
{
char buffer[ 1024 ];
if( fgets( buffer, sizeof( buffer ), stdin ) != NULL )
{
// Eliminar salto de línea final, si existe
size_t len = strlen( buffer );
if( len > 0 && buffer[ len - 1 ] == '\n' )
buffer[ len - 1 ] = '\0';
hb_retc( buffer );
}
else
{
hb_retc( "" ); // Retornar cadena vacía en caso de EOF
}
}
HB_FUNC( STDOUT )
{
if( HB_ISCHAR( 1 ) )
{
fputs( hb_parc( 1 ), stdout );
fflush( stdout ); // Forzar la escritura inmediata
}
}
#pragma ENDDUMP
- Antonio Linares
- Site Admin
- Posts: 42836
- Joined: Thu Oct 06, 2005 5:47 pm
- Location: Spain
- Has thanked: 169 times
- Been thanked: 123 times
- Contact:
Re: vscode MCP support is already available!
No errors with Claude desktop !!! Still we need some fine tunning but it properly loads !
hbmcp.prg

hbmcp.prg
Code: Select all | Expand
#include "fileio.ch"
PROCEDURE Main()
LOCAL cInput, cResponse
ErrorBlock( { | oError| LogFile( "error: ", oError:Description ) } )
WHILE .T.
cInput := StdIn()
IF Empty( cInput )
EXIT // Salir si no hay entrada (EOF)
ENDIF
LogFile( "in: ", cInput )
cResponse := ProcessMessage( cInput )
IF ! Empty( cResponse )
LogFile( "out: ", cResponse )
StdOut( cResponse )
ENDIF
END
LogFile( "exit: ", "termina" )
RETURN
// Función para procesar mensajes JSON-RPC
FUNCTION ProcessMessage( cInput )
LOCAL cResponse := ""
LOCAL hJson, cId, cMethod, hParams, cToolName
// Decodificar el JSON para obtener el método y el ID
hb_jsonDecode( cInput, @hJson )
cMethod = hJson[ "method" ]
if hb_HHasKey( hJson, "id" )
cId = AllTrim( Str( hJson[ "id" ] ) )
endif
do case
case cMethod == "initialize"
cResponse := ;
'{' + ;
'"jsonrpc":"2.0",' + ;
'"id":' + cId + ',' + ;
'"result":{' + ;
'"protocolVersion":"2024-11-05",' + ;
'"capabilities":{' + ;
'"tools":{},' + ;
'"resources":{},' + ;
'"prompts":{}' + ;
'},' + ;
'"serverInfo":{"name":"Harbour-xbase","version":"0.0.2"}' + ;
'}' + ;
'}' + hb_eol()
case cMethod == "notifications/initialized"
cResponse := hb_eol()
case cMethod == "resources/list"
cResponse := ;
'{' + ;
'"jsonrpc":"2.0",' + ;
'"id":' + cId + ',' + ;
'"result":{' + ;
'"protocolVersion":"2024-11-05",' + ;
'"capabilities":{' + ;
'"tools":{},' + ;
'"resources":{},' + ;
'"prompts":{}' + ;
'},' + ;
'"serverInfo":{"name":"Harbour-xbase","version":"0.0.2"}' + ;
'}' + ;
'}' + hb_eol()
case cMethod == "prompts/list"
cResponse := ;
'{' + ;
'"jsonrpc":"2.0",' + ;
'"id":' + cId + ',' + ;
'"result":{' + ;
'"prompts":{}' + ;
'}' + ;
'}' + hb_eol()
case cMethod == "tools/list"
cResponse := ;
'{' + ;
'"jsonrpc":"2.0",' + ;
'"id":' + cId + ',' + ;
'"result":{' + ;
'"tools": [' + ;
'{' + ;
'"name":"get_time",' + ;
'"description":"Returns the current system time in YYYY-MM-DD HH:MM:SS format",' + ;
'"schema":{' + ;
'"type":"object",' + ;
'"properties":{},' + ;
'"additionalProperties":false,' + ;
'"returns":{' + ;
'"type":"string"' + ;
'}' + ;
'}' + ;
'},' + ;
'{' + ;
'"name":"hb_version",' + ;
'"description":"Returns the version of the Harbour runtime environment",' + ;
'"schema":{' + ;
'"type":"object",' + ;
'"properties":{},' + ;
'"additionalProperties":false,' + ;
'"returns":{' + ;
'"type":"string"' + ;
'}' + ;
'}' + ;
'},' + ;
'{' + ;
'"name":"hb_compiler",' + ;
'"description":"Returns the name of the compiler used to build the Harbour runtime environment",' + ;
'"schema":{' + ;
'"type":"object",' + ;
'"properties":{},' + ;
'"additionalProperties":false,' + ;
'"returns":{' + ;
'"type":"string"' + ;
'}' + ;
'}' + ;
'}' + ;
']' + ;
'}' + ;
'}' + hb_eol()
case cMethod == "tools/call"
cToolName = hJson[ "params" ][ "name" ]
IF cToolName == "get_time"
// Obtener la hora actual en formato "YYYY-MM-DD HH:MM:SS"
cResponse := ;
'{' + ;
'"jsonrpc":"2.0",' + ;
'"id":' + cId + ',' + ;
'"result":{"content":[{"type":"text","text":"' + Time() + '"}]}' + ;
'}' + hb_eol()
ELSEIF cToolName == "hb_version"
// Obtener la versión de Harbour
cResponse := ;
'{' + ;
'"jsonrpc":"2.0",' + ;
'"id":' + cId + ',' + ;
'"result":{"content":[{"type":"text","text":"' + Version() + '"}]}' + ;
'}' + hb_eol()
ELSEIF cToolName == "hb_compiler"
// Obtener el nombre del compilador
cResponse := ;
'{' + ;
'"jsonrpc":"2.0",' + ;
'"id":' + cId + ',' + ;
'"result":{"content":[{"type":"text","text":"' + hb_Compiler() + '"}]}' + ;
'}' + hb_eol()
ELSE
// Error: herramienta no encontrada o argumentos inválidos
cResponse := ;
'{' + ;
'"jsonrpc":"2.0",' + ;
'"id":' + cId + ',' + ;
'"error":{' + ;
'"code":-32602,' + ;
'"message":"Invalid params"' + ;
'}' + ;
'}' + hb_eol()
ENDIF
// Manejar métodos no soportados
otherwise
cResponse := ;
'{' + ;
'"jsonrpc":"2.0",' + ;
'"id":' + cId + ',' + ;
'"error":{' + ;
'"code":-32604,' + ;
'"message":"Method not found"' + cMethod +;
' }' + ;
'}' + hb_eol()
endcase
RETURN cResponse
FUNCTION LogFile( cKey, cValue )
LOCAL nHandle, lSuccess
// Considerar hacer la ruta configurable
if ! File( "c:\temp\hbmcp.log" )
// Crear el archivo si no existe
nHandle := fopen( "c:\temp\hbmcp.log", FO_WRITE + FO_CREAT )
else
// Abrir el archivo para añadir contenido
nHandle := fopen( "c:\temp\hbmcp.log", FO_WRITE )
endif
IF nHandle > 0
FSeek( nHandle, 0, FS_END ) // Mover el puntero al final del archivo
lSuccess = fWrite( nHandle, cKey + cValue + hb_eol() )
fclose( nHandle )
RETURN lSuccess // Opcional: retornar éxito/fallo
ENDIF
RETURN .F.
#pragma BEGINDUMP
#include <hbapi.h>
HB_FUNC( STDIN )
{
char buffer[ 1024 ];
if( fgets( buffer, sizeof( buffer ), stdin ) != NULL )
{
// Eliminar salto de línea final, si existe
size_t len = strlen( buffer );
if( len > 0 && buffer[ len - 1 ] == '\n' )
buffer[ len - 1 ] = '\0';
hb_retc( buffer );
}
else
{
hb_retc( "" ); // Retornar cadena vacía en caso de EOF
}
}
HB_FUNC( STDOUT )
{
if( HB_ISCHAR( 1 ) )
{
fputs( hb_parc( 1 ), stdout );
fflush( stdout ); // Forzar la escritura inmediata
}
}
#pragma ENDDUMP
- Antonio Linares
- Site Admin
- Posts: 42836
- Joined: Thu Oct 06, 2005 5:47 pm
- Location: Spain
- Has thanked: 169 times
- Been thanked: 123 times
- Contact:
Re: vscode MCP support is already available!
Working fine with Claude Desktop !!!!!!!!!
hbmcp.prg



hbmcp.prg
Code: Select all | Expand
#include "fileio.ch"
PROCEDURE Main()
LOCAL cInput, cResponse
ErrorBlock( { | oError| LogFile( "error: ", oError:Description ) } )
WHILE .T.
cInput := StdIn()
IF Empty( cInput )
EXIT // Salir si no hay entrada (EOF)
ENDIF
LogFile( "in: ", cInput )
cResponse := ProcessMessage( cInput )
IF ! Empty( cResponse )
LogFile( "out: ", cResponse )
StdOut( cResponse )
ENDIF
END
LogFile( "exit: ", "termina" )
RETURN
// Función para procesar mensajes JSON-RPC
FUNCTION ProcessMessage( cInput )
LOCAL cResponse := ""
LOCAL hJson, cId, cMethod, hParams, cToolName
// Decodificar el JSON para obtener el método y el ID
hb_jsonDecode( cInput, @hJson )
cMethod = hJson[ "method" ]
if hb_HHasKey( hJson, "id" )
cId = AllTrim( Str( hJson[ "id" ] ) )
endif
do case
case cMethod == "initialize"
cResponse := ;
'{' + ;
'"jsonrpc":"2.0",' + ;
'"id":' + cId + ',' + ;
'"result":{' + ;
'"protocolVersion":"2024-11-05",' + ;
'"capabilities":{' + ;
'"tools":{},' + ;
'"resources":{},' + ;
'"prompts":{}' + ;
'},' + ;
'"serverInfo":{"name":"Harbour-xbase","version":"0.0.2"}' + ;
'}' + ;
'}' + hb_eol()
case cMethod == "notifications/initialized"
cResponse := hb_eol()
case cMethod == "resources/list"
cResponse := ;
'{' + ;
'"jsonrpc":"2.0",' + ;
'"id":' + cId + ',' + ;
'"error":{"code":-32601,"message":"Method not found"}' + ;
'}' + hb_eol()
case cMethod == "prompts/list"
cResponse := ;
'{' + ;
'"jsonrpc":"2.0",' + ;
'"id":' + cId + ',' + ;
'"error":{"code":-32601,"message":"Method not found"}' + ;
'}' + hb_eol()
case cMethod == "tools/list"
cResponse := ;
'{' + ;
'"jsonrpc":"2.0",' + ;
'"id":' + cId + ',' + ;
'"result":{' + ;
'"tools": [' + ;
'{' + ;
'"name":"get_time",' + ;
'"description":"Returns the current system time in YYYY-MM-DD HH:MM:SS format. Useful for logging or timestamping operations within the Harbour runtime environment.",' + ;
'"inputSchema":{' + ;
'"type":"object",' + ;
'"properties":{},' + ;
'"required":[],' + ;
'"additionalProperties":false,' + ;
'"$schema":"http://json-schema.org/draft-07/schema#"' + ;
'}' + ;
'},' + ;
'{' + ;
'"name":"hb_version",' + ;
'"description":"Returns the version of the Harbour runtime environment. Use this to verify compatibility or for debugging purposes.",' + ;
'"inputSchema":{' + ;
'"type":"object",' + ;
'"properties":{},' + ;
'"required":[],' + ;
'"additionalProperties":false,' + ;
'"$schema":"http://json-schema.org/draft-07/schema#"' + ;
'}' + ;
'},' + ;
'{' + ;
'"name":"hb_compiler",' + ;
'"description":"Returns the name of the compiler used to build the Harbour runtime environment. Helpful for diagnosing build-related issues.",' + ;
'"inputSchema":{' + ;
'"type":"object",' + ;
'"properties":{},' + ;
'"required":[],' + ;
'"additionalProperties":false,' + ;
'"$schema":"http://json-schema.org/draft-07/schema#"' + ;
'}' + ;
'}' + ;
']' + ;
'}' + ;
'}' + hb_eol()
case cMethod == "tools/call"
cToolName = hJson[ "params" ][ "name" ]
IF cToolName == "get_time"
// Obtener la hora actual en formato "YYYY-MM-DD HH:MM:SS"
cResponse := ;
'{' + ;
'"jsonrpc":"2.0",' + ;
'"id":' + cId + ',' + ;
'"result":{"content":[{"type":"text","text":"' + Time() + '"}]}' + ;
'}' + hb_eol()
ELSEIF cToolName == "hb_version"
// Obtener la versión de Harbour
cResponse := ;
'{' + ;
'"jsonrpc":"2.0",' + ;
'"id":' + cId + ',' + ;
'"result":{"content":[{"type":"text","text":"' + Version() + '"}]}' + ;
'}' + hb_eol()
ELSEIF cToolName == "hb_compiler"
// Obtener el nombre del compilador
cResponse := ;
'{' + ;
'"jsonrpc":"2.0",' + ;
'"id":' + cId + ',' + ;
'"result":{"content":[{"type":"text","text":"' + hb_Compiler() + '"}]}' + ;
'}' + hb_eol()
ELSE
// Error: herramienta no encontrada o argumentos inválidos
cResponse := ;
'{' + ;
'"jsonrpc":"2.0",' + ;
'"id":' + cId + ',' + ;
'"error":{' + ;
'"code":-32602,' + ;
'"message":"Invalid params"' + ;
'}' + ;
'}' + hb_eol()
ENDIF
// Manejar métodos no soportados
otherwise
cResponse := ;
'{' + ;
'"jsonrpc":"2.0",' + ;
'"id":' + cId + ',' + ;
'"error":{' + ;
'"code":-32604,' + ;
'"message":"Method not found"' + cMethod +;
' }' + ;
'}' + hb_eol()
endcase
RETURN cResponse
FUNCTION LogFile( cKey, cValue )
LOCAL nHandle, lSuccess
// Considerar hacer la ruta configurable
if ! File( "c:\temp\hbmcp.log" )
// Crear el archivo si no existe
nHandle := fopen( "c:\temp\hbmcp.log", FO_WRITE + FO_CREAT )
else
// Abrir el archivo para añadir contenido
nHandle := fopen( "c:\temp\hbmcp.log", FO_WRITE )
endif
IF nHandle > 0
FSeek( nHandle, 0, FS_END ) // Mover el puntero al final del archivo
lSuccess = fWrite( nHandle, cKey + cValue + hb_eol() )
fclose( nHandle )
RETURN lSuccess // Opcional: retornar éxito/fallo
ENDIF
RETURN .F.
#pragma BEGINDUMP
#include <hbapi.h>
HB_FUNC( STDIN )
{
char buffer[ 1024 ];
if( fgets( buffer, sizeof( buffer ), stdin ) != NULL )
{
// Eliminar salto de línea final, si existe
size_t len = strlen( buffer );
if( len > 0 && buffer[ len - 1 ] == '\n' )
buffer[ len - 1 ] = '\0';
hb_retc( buffer );
}
else
{
hb_retc( "" ); // Retornar cadena vacía en caso de EOF
}
}
HB_FUNC( STDOUT )
{
if( HB_ISCHAR( 1 ) )
{
fputs( hb_parc( 1 ), stdout );
fflush( stdout ); // Forzar la escritura inmediata
}
}
#pragma ENDDUMP
- Antonio Linares
- Site Admin
- Posts: 42836
- Joined: Thu Oct 06, 2005 5:47 pm
- Location: Spain
- Has thanked: 169 times
- Been thanked: 123 times
- Contact:
- Antonio Linares
- Site Admin
- Posts: 42836
- Joined: Thu Oct 06, 2005 5:47 pm
- Location: Spain
- Has thanked: 169 times
- Been thanked: 123 times
- Contact:
Re: vscode MCP support is already available!
New hb_macro implemented tool:
hbmcp.prg
hbmcp.prg
Code: Select all | Expand
#include "fileio.ch"
PROCEDURE Main()
LOCAL cInput, cResponse
ErrorBlock( { | oError| LogFile( "error: ", oError:Description ) } )
WHILE .T.
cInput := StdIn()
IF Empty( cInput )
EXIT // Salir si no hay entrada (EOF)
ENDIF
LogFile( "in: ", cInput )
cResponse := ProcessMessage( cInput )
IF ! Empty( cResponse )
LogFile( "out: ", cResponse )
StdOut( cResponse )
ENDIF
END
LogFile( "exit: ", "termina" )
RETURN
// Función para procesar mensajes JSON-RPC
FUNCTION ProcessMessage( cInput )
LOCAL cResponse := ""
LOCAL hJson, cId, cMethod, hParams, cToolName
LOCAL cCode, xResult, cResult
// Decodificar el JSON para obtener el método y el ID
hb_jsonDecode( cInput, @hJson )
cMethod = hJson[ "method" ]
if hb_HHasKey( hJson, "id" )
cId = AllTrim( Str( hJson[ "id" ] ) )
endif
do case
case cMethod == "initialize"
cResponse := ;
'{' + ;
'"jsonrpc":"2.0",' + ;
'"id":' + cId + ',' + ;
'"result":{' + ;
'"protocolVersion":"2024-11-05",' + ;
'"capabilities":{' + ;
'"tools":{},' + ;
'"resources":{},' + ;
'"prompts":{}' + ;
'},' + ;
'"serverInfo":{"name":"Harbour-xbase","version":"0.0.2"}' + ;
'}' + ;
'}' + hb_eol()
case cMethod == "notifications/initialized"
cResponse := hb_eol()
case cMethod == "resources/list"
cResponse := ;
'{' + ;
'"jsonrpc":"2.0",' + ;
'"id":' + cId + ',' + ;
'"error":{"code":-32601,"message":"Method not found"}' + ;
'}' + hb_eol()
case cMethod == "prompts/list"
cResponse := ;
'{' + ;
'"jsonrpc":"2.0",' + ;
'"id":' + cId + ',' + ;
'"error":{"code":-32601,"message":"Method not found"}' + ;
'}' + hb_eol()
case cMethod == "tools/list"
cResponse := ;
'{' + ;
'"jsonrpc":"2.0",' + ;
'"id":' + cId + ',' + ;
'"result":{' + ;
'"tools": [' + ;
'{' + ;
'"name":"get_time",' + ;
'"description":"Returns the current system time in HH:MM:SS format. Useful for logging or timestamping operations within the Harbour runtime environment.",' + ;
'"inputSchema":{' + ;
'"type":"object",' + ;
'"properties":{},' + ;
'"required":[],' + ;
'"additionalProperties":false,' + ;
'"$schema":"http://json-schema.org/draft-07/schema#"' + ;
'}' + ;
'},' + ;
'{' + ;
'"name":"hb_version",' + ;
'"description":"Returns the version of the Harbour runtime environment. Use this to verify compatibility or for debugging purposes.",' + ;
'"inputSchema":{' + ;
'"type":"object",' + ;
'"properties":{},' + ;
'"required":[],' + ;
'"additionalProperties":false,' + ;
'"$schema":"http://json-schema.org/draft-07/schema#"' + ;
'}' + ;
'},' + ;
'{' + ;
'"name":"hb_compiler",' + ;
'"description":"Returns the name of the compiler used to build the Harbour runtime environment. Helpful for diagnosing build-related issues.",' + ;
'"inputSchema":{' + ;
'"type":"object",' + ;
'"properties":{},' + ;
'"required":[],' + ;
'"additionalProperties":false,' + ;
'"$schema":"http://json-schema.org/draft-07/schema#"' + ;
'}' + ;
'},' + ;
'{' + ; // Nueva herramienta hb_macro
'"name":"hb_macro",' + ;
'"description":"Executes a Harbour macro expression provided as a string and returns the result as a string. Useful for dynamic code execution within the Harbour runtime environment.",' + ;
'"inputSchema":{' + ;
'"type":"object",' + ;
'"properties":{"code":{"type":"string"}},' + ;
'"required":["code"],' + ;
'"additionalProperties":false,' + ;
'"$schema":"http://json-schema.org/draft-07/schema#"' + ;
'}' + ;
'}' + ;
']' + ;
'}' + ;
'}' + hb_eol()
case cMethod == "tools/call"
cToolName = hJson[ "params" ][ "name" ]
IF cToolName == "get_time"
// Obtener la hora actual en formato "HH:MM:SS"
cResponse := ;
'{' + ;
'"jsonrpc":"2.0",' + ;
'"id":' + cId + ',' + ;
'"result":{"content":[{"type":"text","text":"' + Time() + '"}]}' + ;
'}' + hb_eol()
ELSEIF cToolName == "hb_version"
// Obtener la versión de Harbour
cResponse := ;
'{' + ;
'"jsonrpc":"2.0",' + ;
'"id":' + cId + ',' + ;
'"result":{"content":[{"type":"text","text":"' + Version() + '"}]}' + ;
'}' + hb_eol()
ELSEIF cToolName == "hb_compiler"
// Obtener el nombre del compilador
cResponse := ;
'{' + ;
'"jsonrpc":"2.0",' + ;
'"id":' + cId + ',' + ;
'"result":{"content":[{"type":"text","text":"' + hb_Compiler() + '"}]}' + ;
'}' + hb_eol()
ELSEIF cToolName == "hb_macro"
// Nueva herramienta: ejecutar macro y devolver resultado como cadena
// Verificar que el parámetro "code" existe y es una cadena
IF hb_HHasKey( hJson[ "params" ], "arguments" ) .AND. ;
hb_HHasKey( hJson[ "params" ][ "arguments" ], "code" ) .AND. ;
ValType( hJson[ "params" ][ "arguments" ][ "code" ] ) == "C"
cCode := hJson[ "params" ][ "arguments" ][ "code" ]
// Ejecutar la macro y convertir el resultado a cadena
BEGIN SEQUENCE
xResult := &( cCode )
cResult := hb_ValToExp( xResult )
cResponse := ;
'{' + ;
'"jsonrpc":"2.0",' + ;
'"id":' + cId + ',' + ;
'"result":{"content":[{"type":"text","text":"' + cResult + '"}]}' + ;
'}' + hb_eol()
cResponse := StrTran( cResponse, '""', '"' )
RECOVER
// En caso de error en la macro, devolver un error JSON-RPC
cResponse := ;
'{' + ;
'"jsonrpc":"2.0",' + ;
'"id":' + cId + ',' + ;
'"error":{"code":-32602,"message":"Invalid macro expression"}' + ;
'}' + hb_eol()
END SEQUENCE
ELSE
// Error: parámetro "code" no proporcionado o inválido
cResponse := ;
'{' + ;
'"jsonrpc":"2.0",' + ;
'"id":' + cId + ',' + ;
'"error":{"code":-32602,"message":"Missing or invalid code parameter"}' + ;
'}' + hb_eol()
ENDIF
ELSE
// Error: herramienta no encontrada o argumentos inválidos
cResponse := ;
'{' + ;
'"jsonrpc":"2.0",' + ;
'"id":' + cId + ',' + ;
'"error":{' + ;
'"code":-32602,' + ;
'"message":"Invalid params"' + ;
'}' + ;
'}' + hb_eol()
ENDIF
// Manejar métodos no soportados
otherwise
cResponse := ;
'{' + ;
'"jsonrpc":"2.0",' + ;
'"id":' + cId + ',' + ;
'"error":{' + ;
'"code":-32604,' + ;
'"message":"Method not found"' + cMethod +;
' }' + ;
'}' + hb_eol()
endcase
RETURN cResponse
FUNCTION LogFile( cKey, cValue )
LOCAL nHandle, lSuccess
// Considerar hacer la ruta configurable
if ! File( "c:\temp\hbmcp.log" )
// Crear el archivo si no existe
nHandle := fopen( "c:\temp\hbmcp.log", FO_WRITE + FO_CREAT )
else
// Abrir el archivo para añadir contenido
nHandle := fopen( "c:\temp\hbmcp.log", FO_WRITE )
endif
IF nHandle > 0
FSeek( nHandle, 0, FS_END ) // Mover el puntero al final del archivo
lSuccess = fWrite( nHandle, cKey + cValue + hb_eol() )
fclose( nHandle )
RETURN lSuccess // Opcional: retornar éxito/fallo
ENDIF
RETURN .F.
#pragma BEGINDUMP
#include <hbapi.h>
HB_FUNC( STDIN )
{
char buffer[ 1024 ];
if( fgets( buffer, sizeof( buffer ), stdin ) != NULL )
{
// Eliminar salto de línea final, si existe
size_t len = strlen( buffer );
if( len > 0 && buffer[ len - 1 ] == '\n' )
buffer[ len - 1 ] = '\0';
hb_retc( buffer );
}
else
{
hb_retc( "" ); // Retornar cadena vacía en caso de EOF
}
}
HB_FUNC( STDOUT )
{
if( HB_ISCHAR( 1 ) )
{
fputs( hb_parc( 1 ), stdout );
fflush( stdout ); // Forzar la escritura inmediata
}
}
#pragma ENDDUMP