This is page 8 of 16. Use http://codebase.md/fujitsu-ai/mcp-server-for-mas-developments?lines=false&page={x} to view the full context.
# Directory Structure
```
├── .gitattributes
├── .gitignore
├── agents
│ ├── __init__.py
│ ├── AgentInterface
│ │ ├── __init__.py
│ │ ├── Python
│ │ │ ├── __init__.py
│ │ │ ├── agent.py
│ │ │ ├── color.py
│ │ │ ├── config.py
│ │ │ ├── language.py
│ │ │ ├── local_file_handler.py
│ │ │ └── network.py
│ │ └── requirements.txt
│ ├── AgentMonitoring
│ │ ├── ChatBot-Agent Dashboard Example - Grafana.json
│ │ ├── images
│ │ │ ├── Grafana.png
│ │ │ └── Prometheus.png
│ │ ├── IoT-Agent Dashboard Example - Grafana.json
│ │ ├── OpenAI compatible API - Agent Dashboard Example - Grafana.json
│ │ ├── prometheus Example.yml
│ │ └── README.md
│ ├── ChatBotAgent
│ │ ├── __init__.py
│ │ ├── config.json.example
│ │ ├── html
│ │ │ ├── favicon.ico
│ │ │ ├── index_de.html
│ │ │ ├── index.html
│ │ │ ├── Logo_light.svg
│ │ │ ├── start_http_server.ps1
│ │ │ └── start_http_server.sh
│ │ ├── Python
│ │ │ ├── __init__.py
│ │ │ └── chatbot_agent.py
│ │ ├── README.md
│ │ └── requirements.txt
│ ├── IoTAgent
│ │ ├── config_example.json
│ │ ├── Python
│ │ │ ├── iot_mqtt_agent.py
│ │ │ └── language.py
│ │ ├── README.md
│ │ └── requirements.txt
│ ├── ISMAgent
│ │ ├── config_example.json
│ │ ├── PGPT Scenario Prompts
│ │ │ ├── ISM System Prompt - Detecting Error State.txt
│ │ │ ├── ISM User Post-Prompt - Detecting Error State.txt
│ │ │ ├── ISM User Pre-Prompt - Detecting Error State.txt
│ │ │ └── README.md
│ │ ├── Python
│ │ │ ├── ism_agent.py
│ │ │ └── language.py
│ │ ├── README.md
│ │ ├── requirements.txt
│ │ └── start_ism_agent.ps1
│ ├── MCP-Client
│ │ ├── __init__.py
│ │ ├── .env.example
│ │ ├── Python
│ │ │ ├── __init__.py
│ │ │ ├── chat_handler.py
│ │ │ ├── config.py
│ │ │ ├── environment.py
│ │ │ ├── llm_client.py
│ │ │ ├── mcp_client_sse.py
│ │ │ ├── mcp_client.py
│ │ │ ├── messages
│ │ │ │ ├── __init__.py
│ │ │ │ ├── message_types
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── incrementing_id_message.py
│ │ │ │ │ ├── initialize_message.py
│ │ │ │ │ ├── json_rpc_message.py
│ │ │ │ │ ├── ping_message.py
│ │ │ │ │ ├── prompts_messages.py
│ │ │ │ │ ├── prompts_models.py
│ │ │ │ │ ├── resources_messages.py
│ │ │ │ │ └── tools_messages.py
│ │ │ │ ├── send_call_tool.py
│ │ │ │ ├── send_initialize_message.py
│ │ │ │ ├── send_message.py
│ │ │ │ ├── send_ping.py
│ │ │ │ ├── send_prompts.py
│ │ │ │ ├── send_resources.py
│ │ │ │ └── send_tools_list.py
│ │ │ ├── system_prompt_generator.py
│ │ │ ├── tools_handler.py
│ │ │ └── transport
│ │ │ ├── __init__.py
│ │ │ └── stdio
│ │ │ ├── __init__.py
│ │ │ ├── stdio_client.py
│ │ │ ├── stdio_server_parameters.py
│ │ │ └── stdio_server_shutdown.py
│ │ ├── README.md
│ │ ├── requirements.txt
│ │ └── server_config.json
│ ├── OpenAI_Compatible_API_Agent
│ │ ├── __init__.py
│ │ ├── docker-compose.yml
│ │ ├── Dockerfile
│ │ ├── pgpt_openai_api_mcp.json.example
│ │ ├── pgpt_openai_api_proxy.json.example
│ │ ├── Python
│ │ │ ├── __init__.py
│ │ │ ├── client_tests
│ │ │ │ ├── __init__.py
│ │ │ │ ├── openai_test_client_structured.py
│ │ │ │ ├── openai_test_client_tools.py
│ │ │ │ ├── openai_test_client.py
│ │ │ │ ├── vllm_client_multimodal.py
│ │ │ │ ├── vllm_client.py
│ │ │ │ ├── vllm_structured.py
│ │ │ │ └── vllm_structured2.py
│ │ │ ├── generate_api_key.py
│ │ │ ├── open_ai_helper.py
│ │ │ ├── openai_compatible_api.py
│ │ │ ├── openai_mcp_api.py
│ │ │ ├── pgpt_api.py
│ │ │ ├── privategpt_api.py
│ │ │ └── vllmproxy.py
│ │ ├── README.md
│ │ └── requirements.txt
│ └── SourceManagerAgent
│ ├── __init__.py
│ ├── config.json.example
│ └── Python
│ ├── __init__.py
│ ├── file_tools
│ │ └── loader_factory.py
│ ├── file_upload_agent.py
│ └── local_db.py
├── clients
│ ├── __init__.py
│ ├── C# .Net
│ │ ├── 1.0 mcp_login
│ │ │ ├── bin
│ │ │ │ └── Debug
│ │ │ │ └── net9.0
│ │ │ │ ├── mcp_login.deps.json
│ │ │ │ ├── mcp_login.dll
│ │ │ │ ├── mcp_login.exe
│ │ │ │ ├── mcp_login.pdb
│ │ │ │ ├── mcp_login.runtimeconfig.json
│ │ │ │ └── Newtonsoft.Json.dll
│ │ │ ├── mcp_login.csproj
│ │ │ ├── obj
│ │ │ │ ├── Debug
│ │ │ │ │ └── net9.0
│ │ │ │ │ ├── .NETCoreApp,Version=v9.0.AssemblyAttributes.cs
│ │ │ │ │ ├── apphost.exe
│ │ │ │ │ ├── mcp_login.AssemblyInfo.cs
│ │ │ │ │ ├── mcp_login.AssemblyInfoInputs.cache
│ │ │ │ │ ├── mcp_login.assets.cache
│ │ │ │ │ ├── mcp_login.csproj.AssemblyReference.cache
│ │ │ │ │ ├── mcp_login.csproj.CoreCompileInputs.cache
│ │ │ │ │ ├── mcp_login.csproj.FileListAbsolute.txt
│ │ │ │ │ ├── mcp_login.csproj.Up2Date
│ │ │ │ │ ├── mcp_login.dll
│ │ │ │ │ ├── mcp_login.GeneratedMSBuildEditorConfig.editorconfig
│ │ │ │ │ ├── mcp_login.genruntimeconfig.cache
│ │ │ │ │ ├── mcp_login.GlobalUsings.g.cs
│ │ │ │ │ ├── mcp_login.pdb
│ │ │ │ │ ├── ref
│ │ │ │ │ │ └── mcp_login.dll
│ │ │ │ │ └── refint
│ │ │ │ │ └── mcp_login.dll
│ │ │ │ ├── mcp_login.csproj.nuget.dgspec.json
│ │ │ │ ├── mcp_login.csproj.nuget.g.props
│ │ │ │ ├── mcp_login.csproj.nuget.g.targets
│ │ │ │ ├── project.assets.json
│ │ │ │ └── project.nuget.cache
│ │ │ └── Program.cs
│ │ ├── 1.1 mcp_logout
│ │ │ ├── bin
│ │ │ │ └── Debug
│ │ │ │ └── net9.0
│ │ │ │ ├── mcp_logout.deps.json
│ │ │ │ ├── mcp_logout.dll
│ │ │ │ ├── mcp_logout.exe
│ │ │ │ ├── mcp_logout.pdb
│ │ │ │ ├── mcp_logout.runtimeconfig.json
│ │ │ │ └── Newtonsoft.Json.dll
│ │ │ ├── mcp_logout.csproj
│ │ │ ├── obj
│ │ │ │ ├── Debug
│ │ │ │ │ └── net9.0
│ │ │ │ │ ├── .NETCoreApp,Version=v9.0.AssemblyAttributes.cs
│ │ │ │ │ ├── apphost.exe
│ │ │ │ │ ├── mcp_logout.AssemblyInfo.cs
│ │ │ │ │ ├── mcp_logout.AssemblyInfoInputs.cache
│ │ │ │ │ ├── mcp_logout.assets.cache
│ │ │ │ │ ├── mcp_logout.csproj.AssemblyReference.cache
│ │ │ │ │ ├── mcp_logout.csproj.CoreCompileInputs.cache
│ │ │ │ │ ├── mcp_logout.csproj.FileListAbsolute.txt
│ │ │ │ │ ├── mcp_logout.csproj.Up2Date
│ │ │ │ │ ├── mcp_logout.dll
│ │ │ │ │ ├── mcp_logout.GeneratedMSBuildEditorConfig.editorconfig
│ │ │ │ │ ├── mcp_logout.genruntimeconfig.cache
│ │ │ │ │ ├── mcp_logout.GlobalUsings.g.cs
│ │ │ │ │ ├── mcp_logout.pdb
│ │ │ │ │ ├── ref
│ │ │ │ │ │ └── mcp_logout.dll
│ │ │ │ │ └── refint
│ │ │ │ │ └── mcp_logout.dll
│ │ │ │ ├── mcp_logout.csproj.nuget.dgspec.json
│ │ │ │ ├── mcp_logout.csproj.nuget.g.props
│ │ │ │ ├── mcp_logout.csproj.nuget.g.targets
│ │ │ │ ├── project.assets.json
│ │ │ │ └── project.nuget.cache
│ │ │ └── Program.cs
│ │ ├── 2.0 mcp_chat
│ │ │ ├── bin
│ │ │ │ └── Debug
│ │ │ │ └── net9.0
│ │ │ │ ├── mcp_chat.deps.json
│ │ │ │ ├── mcp_chat.dll
│ │ │ │ ├── mcp_chat.exe
│ │ │ │ ├── mcp_chat.pdb
│ │ │ │ ├── mcp_chat.runtimeconfig.json
│ │ │ │ └── Newtonsoft.Json.dll
│ │ │ ├── mcp_chat.csproj
│ │ │ ├── obj
│ │ │ │ ├── Debug
│ │ │ │ │ └── net9.0
│ │ │ │ │ ├── .NETCoreApp,Version=v9.0.AssemblyAttributes.cs
│ │ │ │ │ ├── apphost.exe
│ │ │ │ │ ├── mcp_chat.AssemblyInfo.cs
│ │ │ │ │ ├── mcp_chat.AssemblyInfoInputs.cache
│ │ │ │ │ ├── mcp_chat.assets.cache
│ │ │ │ │ ├── mcp_chat.csproj.AssemblyReference.cache
│ │ │ │ │ ├── mcp_chat.csproj.CoreCompileInputs.cache
│ │ │ │ │ ├── mcp_chat.csproj.FileListAbsolute.txt
│ │ │ │ │ ├── mcp_chat.csproj.Up2Date
│ │ │ │ │ ├── mcp_chat.dll
│ │ │ │ │ ├── mcp_chat.GeneratedMSBuildEditorConfig.editorconfig
│ │ │ │ │ ├── mcp_chat.genruntimeconfig.cache
│ │ │ │ │ ├── mcp_chat.GlobalUsings.g.cs
│ │ │ │ │ ├── mcp_chat.pdb
│ │ │ │ │ ├── ref
│ │ │ │ │ │ └── mcp_chat.dll
│ │ │ │ │ └── refint
│ │ │ │ │ └── mcp_chat.dll
│ │ │ │ ├── mcp_chat.csproj.nuget.dgspec.json
│ │ │ │ ├── mcp_chat.csproj.nuget.g.props
│ │ │ │ ├── mcp_chat.csproj.nuget.g.targets
│ │ │ │ ├── project.assets.json
│ │ │ │ └── project.nuget.cache
│ │ │ └── Program.cs
│ │ ├── 2.1 mcp_continue_chat
│ │ │ ├── bin
│ │ │ │ └── Debug
│ │ │ │ └── net9.0
│ │ │ │ ├── mcp_continue_chat.deps.json
│ │ │ │ ├── mcp_continue_chat.dll
│ │ │ │ ├── mcp_continue_chat.exe
│ │ │ │ ├── mcp_continue_chat.pdb
│ │ │ │ ├── mcp_continue_chat.runtimeconfig.json
│ │ │ │ └── Newtonsoft.Json.dll
│ │ │ ├── mcp_continue_chat.csproj
│ │ │ ├── obj
│ │ │ │ ├── Debug
│ │ │ │ │ └── net9.0
│ │ │ │ │ ├── .NETCoreApp,Version=v9.0.AssemblyAttributes.cs
│ │ │ │ │ ├── apphost.exe
│ │ │ │ │ ├── mcp_cont.EF178231.Up2Date
│ │ │ │ │ ├── mcp_continue_chat.AssemblyInfo.cs
│ │ │ │ │ ├── mcp_continue_chat.AssemblyInfoInputs.cache
│ │ │ │ │ ├── mcp_continue_chat.assets.cache
│ │ │ │ │ ├── mcp_continue_chat.csproj.AssemblyReference.cache
│ │ │ │ │ ├── mcp_continue_chat.csproj.CoreCompileInputs.cache
│ │ │ │ │ ├── mcp_continue_chat.csproj.FileListAbsolute.txt
│ │ │ │ │ ├── mcp_continue_chat.dll
│ │ │ │ │ ├── mcp_continue_chat.GeneratedMSBuildEditorConfig.editorconfig
│ │ │ │ │ ├── mcp_continue_chat.genruntimeconfig.cache
│ │ │ │ │ ├── mcp_continue_chat.GlobalUsings.g.cs
│ │ │ │ │ ├── mcp_continue_chat.pdb
│ │ │ │ │ ├── ref
│ │ │ │ │ │ └── mcp_continue_chat.dll
│ │ │ │ │ └── refint
│ │ │ │ │ └── mcp_continue_chat.dll
│ │ │ │ ├── mcp_continue_chat.csproj.nuget.dgspec.json
│ │ │ │ ├── mcp_continue_chat.csproj.nuget.g.props
│ │ │ │ ├── mcp_continue_chat.csproj.nuget.g.targets
│ │ │ │ ├── project.assets.json
│ │ │ │ └── project.nuget.cache
│ │ │ └── Program.cs
│ │ ├── 2.2 mcp_get_chat_info
│ │ │ ├── bin
│ │ │ │ └── Debug
│ │ │ │ └── net9.0
│ │ │ │ ├── mcp_get_chat_info.deps.json
│ │ │ │ ├── mcp_get_chat_info.dll
│ │ │ │ ├── mcp_get_chat_info.exe
│ │ │ │ ├── mcp_get_chat_info.pdb
│ │ │ │ ├── mcp_get_chat_info.runtimeconfig.json
│ │ │ │ └── Newtonsoft.Json.dll
│ │ │ ├── Dokumente - Verknüpfung.lnk
│ │ │ ├── mcp_get_chat_info.csproj
│ │ │ ├── obj
│ │ │ │ ├── Debug
│ │ │ │ │ └── net9.0
│ │ │ │ │ ├── .NETCoreApp,Version=v9.0.AssemblyAttributes.cs
│ │ │ │ │ ├── apphost.exe
│ │ │ │ │ ├── mcp_get_.DFF47B4E.Up2Date
│ │ │ │ │ ├── mcp_get_chat_info.AssemblyInfo.cs
│ │ │ │ │ ├── mcp_get_chat_info.AssemblyInfoInputs.cache
│ │ │ │ │ ├── mcp_get_chat_info.assets.cache
│ │ │ │ │ ├── mcp_get_chat_info.csproj.AssemblyReference.cache
│ │ │ │ │ ├── mcp_get_chat_info.csproj.CoreCompileInputs.cache
│ │ │ │ │ ├── mcp_get_chat_info.csproj.FileListAbsolute.txt
│ │ │ │ │ ├── mcp_get_chat_info.dll
│ │ │ │ │ ├── mcp_get_chat_info.GeneratedMSBuildEditorConfig.editorconfig
│ │ │ │ │ ├── mcp_get_chat_info.genruntimeconfig.cache
│ │ │ │ │ ├── mcp_get_chat_info.GlobalUsings.g.cs
│ │ │ │ │ ├── mcp_get_chat_info.pdb
│ │ │ │ │ ├── ref
│ │ │ │ │ │ └── mcp_get_chat_info.dll
│ │ │ │ │ └── refint
│ │ │ │ │ └── mcp_get_chat_info.dll
│ │ │ │ ├── mcp_get_chat_info.csproj.nuget.dgspec.json
│ │ │ │ ├── mcp_get_chat_info.csproj.nuget.g.props
│ │ │ │ ├── mcp_get_chat_info.csproj.nuget.g.targets
│ │ │ │ ├── project.assets.json
│ │ │ │ └── project.nuget.cache
│ │ │ └── Program.cs
│ │ ├── 3.0 mcp_create_source
│ │ │ ├── bin
│ │ │ │ └── Debug
│ │ │ │ └── net9.0
│ │ │ │ ├── mcp_create_source.deps.json
│ │ │ │ ├── mcp_create_source.dll
│ │ │ │ ├── mcp_create_source.exe
│ │ │ │ ├── mcp_create_source.pdb
│ │ │ │ ├── mcp_create_source.runtimeconfig.json
│ │ │ │ └── Newtonsoft.Json.dll
│ │ │ ├── mcp_create_source.csproj
│ │ │ ├── obj
│ │ │ │ ├── Debug
│ │ │ │ │ └── net9.0
│ │ │ │ │ ├── .NETCoreApp,Version=v9.0.AssemblyAttributes.cs
│ │ │ │ │ ├── apphost.exe
│ │ │ │ │ ├── mcp_crea.CB4ED912.Up2Date
│ │ │ │ │ ├── mcp_create_source.AssemblyInfo.cs
│ │ │ │ │ ├── mcp_create_source.AssemblyInfoInputs.cache
│ │ │ │ │ ├── mcp_create_source.assets.cache
│ │ │ │ │ ├── mcp_create_source.csproj.AssemblyReference.cache
│ │ │ │ │ ├── mcp_create_source.csproj.CoreCompileInputs.cache
│ │ │ │ │ ├── mcp_create_source.csproj.FileListAbsolute.txt
│ │ │ │ │ ├── mcp_create_source.dll
│ │ │ │ │ ├── mcp_create_source.GeneratedMSBuildEditorConfig.editorconfig
│ │ │ │ │ ├── mcp_create_source.genruntimeconfig.cache
│ │ │ │ │ ├── mcp_create_source.GlobalUsings.g.cs
│ │ │ │ │ ├── mcp_create_source.pdb
│ │ │ │ │ ├── ref
│ │ │ │ │ │ └── mcp_create_source.dll
│ │ │ │ │ └── refint
│ │ │ │ │ └── mcp_create_source.dll
│ │ │ │ ├── mcp_create_source.csproj.nuget.dgspec.json
│ │ │ │ ├── mcp_create_source.csproj.nuget.g.props
│ │ │ │ ├── mcp_create_source.csproj.nuget.g.targets
│ │ │ │ ├── project.assets.json
│ │ │ │ └── project.nuget.cache
│ │ │ └── Program.cs
│ │ ├── 3.1 mcp_get_source
│ │ │ ├── bin
│ │ │ │ └── Debug
│ │ │ │ └── net9.0
│ │ │ │ ├── mcp_get_source.deps.json
│ │ │ │ ├── mcp_get_source.dll
│ │ │ │ ├── mcp_get_source.exe
│ │ │ │ ├── mcp_get_source.pdb
│ │ │ │ ├── mcp_get_source.runtimeconfig.json
│ │ │ │ └── Newtonsoft.Json.dll
│ │ │ ├── mcp_get_source.csproj
│ │ │ ├── obj
│ │ │ │ ├── Debug
│ │ │ │ │ └── net9.0
│ │ │ │ │ ├── .NETCoreApp,Version=v9.0.AssemblyAttributes.cs
│ │ │ │ │ ├── apphost.exe
│ │ │ │ │ ├── mcp_get_.4E61956F.Up2Date
│ │ │ │ │ ├── mcp_get_source.AssemblyInfo.cs
│ │ │ │ │ ├── mcp_get_source.AssemblyInfoInputs.cache
│ │ │ │ │ ├── mcp_get_source.assets.cache
│ │ │ │ │ ├── mcp_get_source.csproj.AssemblyReference.cache
│ │ │ │ │ ├── mcp_get_source.csproj.CoreCompileInputs.cache
│ │ │ │ │ ├── mcp_get_source.csproj.FileListAbsolute.txt
│ │ │ │ │ ├── mcp_get_source.dll
│ │ │ │ │ ├── mcp_get_source.GeneratedMSBuildEditorConfig.editorconfig
│ │ │ │ │ ├── mcp_get_source.genruntimeconfig.cache
│ │ │ │ │ ├── mcp_get_source.GlobalUsings.g.cs
│ │ │ │ │ ├── mcp_get_source.pdb
│ │ │ │ │ ├── ref
│ │ │ │ │ │ └── mcp_get_source.dll
│ │ │ │ │ └── refint
│ │ │ │ │ └── mcp_get_source.dll
│ │ │ │ ├── mcp_get_source.csproj.nuget.dgspec.json
│ │ │ │ ├── mcp_get_source.csproj.nuget.g.props
│ │ │ │ ├── mcp_get_source.csproj.nuget.g.targets
│ │ │ │ ├── project.assets.json
│ │ │ │ └── project.nuget.cache
│ │ │ └── Program.cs
│ │ ├── 3.2 mcp_list_sources
│ │ │ ├── bin
│ │ │ │ └── Debug
│ │ │ │ └── net9.0
│ │ │ │ ├── mcp_list_sources.deps.json
│ │ │ │ ├── mcp_list_sources.dll
│ │ │ │ ├── mcp_list_sources.exe
│ │ │ │ ├── mcp_list_sources.pdb
│ │ │ │ ├── mcp_list_sources.runtimeconfig.json
│ │ │ │ └── Newtonsoft.Json.dll
│ │ │ ├── mcp_list_sources.csproj
│ │ │ ├── obj
│ │ │ │ ├── Debug
│ │ │ │ │ └── net9.0
│ │ │ │ │ ├── .NETCoreApp,Version=v9.0.AssemblyAttributes.cs
│ │ │ │ │ ├── apphost.exe
│ │ │ │ │ ├── mcp_list_sources.AssemblyInfo.cs
│ │ │ │ │ ├── mcp_list_sources.AssemblyInfoInputs.cache
│ │ │ │ │ ├── mcp_list_sources.assets.cache
│ │ │ │ │ ├── mcp_list_sources.csproj.AssemblyReference.cache
│ │ │ │ │ ├── mcp_list_sources.csproj.CoreCompileInputs.cache
│ │ │ │ │ ├── mcp_list_sources.csproj.FileListAbsolute.txt
│ │ │ │ │ ├── mcp_list_sources.dll
│ │ │ │ │ ├── mcp_list_sources.GeneratedMSBuildEditorConfig.editorconfig
│ │ │ │ │ ├── mcp_list_sources.genruntimeconfig.cache
│ │ │ │ │ ├── mcp_list_sources.GlobalUsings.g.cs
│ │ │ │ │ ├── mcp_list_sources.pdb
│ │ │ │ │ ├── mcp_list.A720E197.Up2Date
│ │ │ │ │ ├── ref
│ │ │ │ │ │ └── mcp_list_sources.dll
│ │ │ │ │ └── refint
│ │ │ │ │ └── mcp_list_sources.dll
│ │ │ │ ├── mcp_list_sources.csproj.nuget.dgspec.json
│ │ │ │ ├── mcp_list_sources.csproj.nuget.g.props
│ │ │ │ ├── mcp_list_sources.csproj.nuget.g.targets
│ │ │ │ ├── project.assets.json
│ │ │ │ └── project.nuget.cache
│ │ │ └── Program.cs
│ │ ├── 3.3 mcp_edit_source
│ │ │ ├── bin
│ │ │ │ └── Debug
│ │ │ │ └── net9.0
│ │ │ │ ├── mcp_edit_source.deps.json
│ │ │ │ ├── mcp_edit_source.dll
│ │ │ │ ├── mcp_edit_source.exe
│ │ │ │ ├── mcp_edit_source.pdb
│ │ │ │ ├── mcp_edit_source.runtimeconfig.json
│ │ │ │ └── Newtonsoft.Json.dll
│ │ │ ├── mcp_edit_source.csproj
│ │ │ ├── obj
│ │ │ │ ├── Debug
│ │ │ │ │ └── net9.0
│ │ │ │ │ ├── .NETCoreApp,Version=v9.0.AssemblyAttributes.cs
│ │ │ │ │ ├── apphost.exe
│ │ │ │ │ ├── mcp_edit_source.AssemblyInfo.cs
│ │ │ │ │ ├── mcp_edit_source.AssemblyInfoInputs.cache
│ │ │ │ │ ├── mcp_edit_source.assets.cache
│ │ │ │ │ ├── mcp_edit_source.csproj.AssemblyReference.cache
│ │ │ │ │ ├── mcp_edit_source.csproj.CoreCompileInputs.cache
│ │ │ │ │ ├── mcp_edit_source.csproj.FileListAbsolute.txt
│ │ │ │ │ ├── mcp_edit_source.dll
│ │ │ │ │ ├── mcp_edit_source.GeneratedMSBuildEditorConfig.editorconfig
│ │ │ │ │ ├── mcp_edit_source.genruntimeconfig.cache
│ │ │ │ │ ├── mcp_edit_source.GlobalUsings.g.cs
│ │ │ │ │ ├── mcp_edit_source.pdb
│ │ │ │ │ ├── mcp_edit.7303BE3B.Up2Date
│ │ │ │ │ ├── ref
│ │ │ │ │ │ └── mcp_edit_source.dll
│ │ │ │ │ └── refint
│ │ │ │ │ └── mcp_edit_source.dll
│ │ │ │ ├── mcp_edit_source.csproj.nuget.dgspec.json
│ │ │ │ ├── mcp_edit_source.csproj.nuget.g.props
│ │ │ │ ├── mcp_edit_source.csproj.nuget.g.targets
│ │ │ │ ├── project.assets.json
│ │ │ │ └── project.nuget.cache
│ │ │ └── Program.cs
│ │ ├── 3.4 mcp_delete_source
│ │ │ ├── bin
│ │ │ │ └── Debug
│ │ │ │ └── net9.0
│ │ │ │ ├── mcp_delete_source.deps.json
│ │ │ │ ├── mcp_delete_source.dll
│ │ │ │ ├── mcp_delete_source.exe
│ │ │ │ ├── mcp_delete_source.pdb
│ │ │ │ ├── mcp_delete_source.runtimeconfig.json
│ │ │ │ └── Newtonsoft.Json.dll
│ │ │ ├── mcp_delete_source.csproj
│ │ │ ├── obj
│ │ │ │ ├── Debug
│ │ │ │ │ └── net9.0
│ │ │ │ │ ├── .NETCoreApp,Version=v9.0.AssemblyAttributes.cs
│ │ │ │ │ ├── apphost.exe
│ │ │ │ │ ├── mcp_dele.67DD13F9.Up2Date
│ │ │ │ │ ├── mcp_delete_source.AssemblyInfo.cs
│ │ │ │ │ ├── mcp_delete_source.AssemblyInfoInputs.cache
│ │ │ │ │ ├── mcp_delete_source.assets.cache
│ │ │ │ │ ├── mcp_delete_source.csproj.AssemblyReference.cache
│ │ │ │ │ ├── mcp_delete_source.csproj.CoreCompileInputs.cache
│ │ │ │ │ ├── mcp_delete_source.csproj.FileListAbsolute.txt
│ │ │ │ │ ├── mcp_delete_source.dll
│ │ │ │ │ ├── mcp_delete_source.GeneratedMSBuildEditorConfig.editorconfig
│ │ │ │ │ ├── mcp_delete_source.genruntimeconfig.cache
│ │ │ │ │ ├── mcp_delete_source.GlobalUsings.g.cs
│ │ │ │ │ ├── mcp_delete_source.pdb
│ │ │ │ │ ├── ref
│ │ │ │ │ │ └── mcp_delete_source.dll
│ │ │ │ │ └── refint
│ │ │ │ │ └── mcp_delete_source.dll
│ │ │ │ ├── mcp_delete_source.csproj.nuget.dgspec.json
│ │ │ │ ├── mcp_delete_source.csproj.nuget.g.props
│ │ │ │ ├── mcp_delete_source.csproj.nuget.g.targets
│ │ │ │ ├── project.assets.json
│ │ │ │ └── project.nuget.cache
│ │ │ └── Program.cs
│ │ ├── 4.0 mcp_list_groups
│ │ │ ├── bin
│ │ │ │ └── Debug
│ │ │ │ └── net9.0
│ │ │ │ ├── mcp_list_groups.deps.json
│ │ │ │ ├── mcp_list_groups.dll
│ │ │ │ ├── mcp_list_groups.exe
│ │ │ │ ├── mcp_list_groups.pdb
│ │ │ │ ├── mcp_list_groups.runtimeconfig.json
│ │ │ │ └── Newtonsoft.Json.dll
│ │ │ ├── mcp_list_groups.csproj
│ │ │ ├── obj
│ │ │ │ ├── Debug
│ │ │ │ │ └── net9.0
│ │ │ │ │ ├── .NETCoreApp,Version=v9.0.AssemblyAttributes.cs
│ │ │ │ │ ├── apphost.exe
│ │ │ │ │ ├── mcp_list_groups.AssemblyInfo.cs
│ │ │ │ │ ├── mcp_list_groups.AssemblyInfoInputs.cache
│ │ │ │ │ ├── mcp_list_groups.assets.cache
│ │ │ │ │ ├── mcp_list_groups.csproj.AssemblyReference.cache
│ │ │ │ │ ├── mcp_list_groups.csproj.CoreCompileInputs.cache
│ │ │ │ │ ├── mcp_list_groups.csproj.FileListAbsolute.txt
│ │ │ │ │ ├── mcp_list_groups.dll
│ │ │ │ │ ├── mcp_list_groups.GeneratedMSBuildEditorConfig.editorconfig
│ │ │ │ │ ├── mcp_list_groups.genruntimeconfig.cache
│ │ │ │ │ ├── mcp_list_groups.GlobalUsings.g.cs
│ │ │ │ │ ├── mcp_list_groups.pdb
│ │ │ │ │ ├── mcp_list.EBD5E0D2.Up2Date
│ │ │ │ │ ├── ref
│ │ │ │ │ │ └── mcp_list_groups.dll
│ │ │ │ │ └── refint
│ │ │ │ │ └── mcp_list_groups.dll
│ │ │ │ ├── mcp_list_groups.csproj.nuget.dgspec.json
│ │ │ │ ├── mcp_list_groups.csproj.nuget.g.props
│ │ │ │ ├── mcp_list_groups.csproj.nuget.g.targets
│ │ │ │ ├── project.assets.json
│ │ │ │ └── project.nuget.cache
│ │ │ └── Program.cs
│ │ ├── 4.1 mcp_store_group
│ │ │ ├── bin
│ │ │ │ └── Debug
│ │ │ │ └── net9.0
│ │ │ │ ├── mcp_store_group.deps.json
│ │ │ │ ├── mcp_store_group.dll
│ │ │ │ ├── mcp_store_group.exe
│ │ │ │ ├── mcp_store_group.pdb
│ │ │ │ ├── mcp_store_group.runtimeconfig.json
│ │ │ │ └── Newtonsoft.Json.dll
│ │ │ ├── mcp_store_group.csproj
│ │ │ ├── obj
│ │ │ │ ├── Debug
│ │ │ │ │ └── net9.0
│ │ │ │ │ ├── .NETCoreApp,Version=v9.0.AssemblyAttributes.cs
│ │ │ │ │ ├── apphost.exe
│ │ │ │ │ ├── mcp_stor.AFB4AA35.Up2Date
│ │ │ │ │ ├── mcp_store_group.AssemblyInfo.cs
│ │ │ │ │ ├── mcp_store_group.AssemblyInfoInputs.cache
│ │ │ │ │ ├── mcp_store_group.assets.cache
│ │ │ │ │ ├── mcp_store_group.csproj.AssemblyReference.cache
│ │ │ │ │ ├── mcp_store_group.csproj.CoreCompileInputs.cache
│ │ │ │ │ ├── mcp_store_group.csproj.FileListAbsolute.txt
│ │ │ │ │ ├── mcp_store_group.dll
│ │ │ │ │ ├── mcp_store_group.GeneratedMSBuildEditorConfig.editorconfig
│ │ │ │ │ ├── mcp_store_group.genruntimeconfig.cache
│ │ │ │ │ ├── mcp_store_group.GlobalUsings.g.cs
│ │ │ │ │ ├── mcp_store_group.pdb
│ │ │ │ │ ├── ref
│ │ │ │ │ │ └── mcp_store_group.dll
│ │ │ │ │ └── refint
│ │ │ │ │ └── mcp_store_group.dll
│ │ │ │ ├── mcp_store_group.csproj.nuget.dgspec.json
│ │ │ │ ├── mcp_store_group.csproj.nuget.g.props
│ │ │ │ ├── mcp_store_group.csproj.nuget.g.targets
│ │ │ │ ├── project.assets.json
│ │ │ │ └── project.nuget.cache
│ │ │ └── Program.cs
│ │ ├── 4.2 mcp_delete_group
│ │ │ ├── bin
│ │ │ │ └── Debug
│ │ │ │ └── net9.0
│ │ │ │ ├── mcp_delete_group.deps.json
│ │ │ │ ├── mcp_delete_group.dll
│ │ │ │ ├── mcp_delete_group.exe
│ │ │ │ ├── mcp_delete_group.pdb
│ │ │ │ ├── mcp_delete_group.runtimeconfig.json
│ │ │ │ └── Newtonsoft.Json.dll
│ │ │ ├── mcp_delete_group.csproj
│ │ │ ├── obj
│ │ │ │ ├── Debug
│ │ │ │ │ └── net9.0
│ │ │ │ │ ├── .NETCoreApp,Version=v9.0.AssemblyAttributes.cs
│ │ │ │ │ ├── apphost.exe
│ │ │ │ │ ├── mcp_dele.FE1C6298.Up2Date
│ │ │ │ │ ├── mcp_delete_group.AssemblyInfo.cs
│ │ │ │ │ ├── mcp_delete_group.AssemblyInfoInputs.cache
│ │ │ │ │ ├── mcp_delete_group.assets.cache
│ │ │ │ │ ├── mcp_delete_group.csproj.AssemblyReference.cache
│ │ │ │ │ ├── mcp_delete_group.csproj.CoreCompileInputs.cache
│ │ │ │ │ ├── mcp_delete_group.csproj.FileListAbsolute.txt
│ │ │ │ │ ├── mcp_delete_group.dll
│ │ │ │ │ ├── mcp_delete_group.GeneratedMSBuildEditorConfig.editorconfig
│ │ │ │ │ ├── mcp_delete_group.genruntimeconfig.cache
│ │ │ │ │ ├── mcp_delete_group.GlobalUsings.g.cs
│ │ │ │ │ ├── mcp_delete_group.pdb
│ │ │ │ │ ├── ref
│ │ │ │ │ │ └── mcp_delete_group.dll
│ │ │ │ │ └── refint
│ │ │ │ │ └── mcp_delete_group.dll
│ │ │ │ ├── mcp_delete_group.csproj.nuget.dgspec.json
│ │ │ │ ├── mcp_delete_group.csproj.nuget.g.props
│ │ │ │ ├── mcp_delete_group.csproj.nuget.g.targets
│ │ │ │ ├── project.assets.json
│ │ │ │ └── project.nuget.cache
│ │ │ └── Program.cs
│ │ ├── 5.0 mcp_store_user
│ │ │ ├── bin
│ │ │ │ └── Debug
│ │ │ │ └── net9.0
│ │ │ │ ├── mcp_store_user.deps.json
│ │ │ │ ├── mcp_store_user.dll
│ │ │ │ ├── mcp_store_user.exe
│ │ │ │ ├── mcp_store_user.pdb
│ │ │ │ ├── mcp_store_user.runtimeconfig.json
│ │ │ │ └── Newtonsoft.Json.dll
│ │ │ ├── mcp_store_user.csproj
│ │ │ ├── obj
│ │ │ │ ├── Debug
│ │ │ │ │ └── net9.0
│ │ │ │ │ ├── .NETCoreApp,Version=v9.0.AssemblyAttributes.cs
│ │ │ │ │ ├── apphost.exe
│ │ │ │ │ ├── mcp_stor.6C0F0C8A.Up2Date
│ │ │ │ │ ├── mcp_store_user.AssemblyInfo.cs
│ │ │ │ │ ├── mcp_store_user.AssemblyInfoInputs.cache
│ │ │ │ │ ├── mcp_store_user.assets.cache
│ │ │ │ │ ├── mcp_store_user.csproj.AssemblyReference.cache
│ │ │ │ │ ├── mcp_store_user.csproj.CoreCompileInputs.cache
│ │ │ │ │ ├── mcp_store_user.csproj.FileListAbsolute.txt
│ │ │ │ │ ├── mcp_store_user.dll
│ │ │ │ │ ├── mcp_store_user.GeneratedMSBuildEditorConfig.editorconfig
│ │ │ │ │ ├── mcp_store_user.genruntimeconfig.cache
│ │ │ │ │ ├── mcp_store_user.GlobalUsings.g.cs
│ │ │ │ │ ├── mcp_store_user.pdb
│ │ │ │ │ ├── ref
│ │ │ │ │ │ └── mcp_store_user.dll
│ │ │ │ │ └── refint
│ │ │ │ │ └── mcp_store_user.dll
│ │ │ │ ├── mcp_store_user.csproj.nuget.dgspec.json
│ │ │ │ ├── mcp_store_user.csproj.nuget.g.props
│ │ │ │ ├── mcp_store_user.csproj.nuget.g.targets
│ │ │ │ ├── project.assets.json
│ │ │ │ └── project.nuget.cache
│ │ │ └── Program.cs
│ │ ├── 5.1 mcp_edit_user
│ │ │ ├── bin
│ │ │ │ └── Debug
│ │ │ │ └── net9.0
│ │ │ │ ├── mcp_edit_user.deps.json
│ │ │ │ ├── mcp_edit_user.dll
│ │ │ │ ├── mcp_edit_user.exe
│ │ │ │ ├── mcp_edit_user.pdb
│ │ │ │ ├── mcp_edit_user.runtimeconfig.json
│ │ │ │ └── Newtonsoft.Json.dll
│ │ │ ├── mcp_edit_user.csproj
│ │ │ ├── obj
│ │ │ │ ├── Debug
│ │ │ │ │ └── net9.0
│ │ │ │ │ ├── .NETCoreApp,Version=v9.0.AssemblyAttributes.cs
│ │ │ │ │ ├── apphost.exe
│ │ │ │ │ ├── mcp_edit_user.AssemblyInfo.cs
│ │ │ │ │ ├── mcp_edit_user.AssemblyInfoInputs.cache
│ │ │ │ │ ├── mcp_edit_user.assets.cache
│ │ │ │ │ ├── mcp_edit_user.csproj.AssemblyReference.cache
│ │ │ │ │ ├── mcp_edit_user.csproj.CoreCompileInputs.cache
│ │ │ │ │ ├── mcp_edit_user.csproj.FileListAbsolute.txt
│ │ │ │ │ ├── mcp_edit_user.dll
│ │ │ │ │ ├── mcp_edit_user.GeneratedMSBuildEditorConfig.editorconfig
│ │ │ │ │ ├── mcp_edit_user.genruntimeconfig.cache
│ │ │ │ │ ├── mcp_edit_user.GlobalUsings.g.cs
│ │ │ │ │ ├── mcp_edit_user.pdb
│ │ │ │ │ ├── mcp_edit.94A30270.Up2Date
│ │ │ │ │ ├── ref
│ │ │ │ │ │ └── mcp_edit_user.dll
│ │ │ │ │ └── refint
│ │ │ │ │ └── mcp_edit_user.dll
│ │ │ │ ├── mcp_edit_user.csproj.nuget.dgspec.json
│ │ │ │ ├── mcp_edit_user.csproj.nuget.g.props
│ │ │ │ ├── mcp_edit_user.csproj.nuget.g.targets
│ │ │ │ ├── project.assets.json
│ │ │ │ └── project.nuget.cache
│ │ │ └── Program.cs
│ │ ├── 5.2 mcp_delete_user
│ │ │ ├── bin
│ │ │ │ └── Debug
│ │ │ │ └── net9.0
│ │ │ │ ├── mcp_delete_user.deps.json
│ │ │ │ ├── mcp_delete_user.dll
│ │ │ │ ├── mcp_delete_user.exe
│ │ │ │ ├── mcp_delete_user.pdb
│ │ │ │ ├── mcp_delete_user.runtimeconfig.json
│ │ │ │ └── Newtonsoft.Json.dll
│ │ │ ├── mcp_delete_user.csproj
│ │ │ ├── obj
│ │ │ │ ├── Debug
│ │ │ │ │ └── net9.0
│ │ │ │ │ ├── .NETCoreApp,Version=v9.0.AssemblyAttributes.cs
│ │ │ │ │ ├── apphost.exe
│ │ │ │ │ ├── mcp_dele.CEB7E33D.Up2Date
│ │ │ │ │ ├── mcp_delete_user.AssemblyInfo.cs
│ │ │ │ │ ├── mcp_delete_user.AssemblyInfoInputs.cache
│ │ │ │ │ ├── mcp_delete_user.assets.cache
│ │ │ │ │ ├── mcp_delete_user.csproj.AssemblyReference.cache
│ │ │ │ │ ├── mcp_delete_user.csproj.CoreCompileInputs.cache
│ │ │ │ │ ├── mcp_delete_user.csproj.FileListAbsolute.txt
│ │ │ │ │ ├── mcp_delete_user.dll
│ │ │ │ │ ├── mcp_delete_user.GeneratedMSBuildEditorConfig.editorconfig
│ │ │ │ │ ├── mcp_delete_user.genruntimeconfig.cache
│ │ │ │ │ ├── mcp_delete_user.GlobalUsings.g.cs
│ │ │ │ │ ├── mcp_delete_user.pdb
│ │ │ │ │ ├── ref
│ │ │ │ │ │ └── mcp_delete_user.dll
│ │ │ │ │ └── refint
│ │ │ │ │ └── mcp_delete_user.dll
│ │ │ │ ├── mcp_delete_user.csproj.nuget.dgspec.json
│ │ │ │ ├── mcp_delete_user.csproj.nuget.g.props
│ │ │ │ ├── mcp_delete_user.csproj.nuget.g.targets
│ │ │ │ ├── project.assets.json
│ │ │ │ └── project.nuget.cache
│ │ │ └── Program.cs
│ │ ├── Code Archiv
│ │ │ ├── mcp_chat.cs
│ │ │ ├── mcp_continue_chat.cs
│ │ │ ├── mcp_create_source.cs
│ │ │ ├── mcp_delete_group.cs
│ │ │ ├── mcp_delete_source.cs
│ │ │ ├── mcp_delete_user.cs
│ │ │ ├── mcp_edit_source.cs
│ │ │ ├── mcp_edit_user.cs
│ │ │ ├── mcp_get_chat_info.cs
│ │ │ ├── mcp_get_source.cs
│ │ │ ├── mcp_list_groups.cs
│ │ │ ├── mcp_list_sources.cs
│ │ │ ├── mcp_login.cs
│ │ │ ├── mcp_logout.cs
│ │ │ ├── mcp_store_group.cs
│ │ │ └── mcp_store_user.cs
│ │ └── README.md
│ ├── C++
│ │ ├── .vscode
│ │ │ └── launch.json
│ │ ├── 1.0 mcp_login
│ │ │ ├── MCPLoginClient.cpp
│ │ │ └── Non-TLS version
│ │ │ ├── MCPLoginClient.cpp
│ │ │ └── MCPLoginClient.exe
│ │ ├── 1.1 mcp_logout
│ │ │ ├── MCPLogoutClient.cpp
│ │ │ └── MCPLogoutClient.exe
│ │ ├── 2.0 mcp_chat
│ │ │ ├── MCPChatClient.cpp
│ │ │ └── MCPChatClient.exe
│ │ ├── 2.1 mcp_continue_chat
│ │ │ ├── MCPChatContinuationClient.cpp
│ │ │ └── MCPChatContinuationClient.exe
│ │ ├── 2.2 mcp_get_chat_info
│ │ │ ├── MCPGetChatInfoClient.cpp
│ │ │ └── MCPGetChatInfoClient.exe
│ │ ├── 3.0 mcp_create_source
│ │ │ ├── MCPCreateSourceClient.cpp
│ │ │ └── MCPCreateSourceClient.exe
│ │ ├── 3.1 mcp_get_source
│ │ │ ├── MCPGetSourceClient.cpp
│ │ │ └── MCPGetSourceClient.exe
│ │ ├── 3.2 mcp_list_sources
│ │ │ ├── MCPListSourcesClient.cpp
│ │ │ └── MCPListSourcesClient.exe
│ │ ├── 3.3 mcp_edit_source
│ │ │ ├── MCPEditSourceClient.cpp
│ │ │ └── MCPEditSourceClient.exe
│ │ ├── 3.4 mcp_delete_source
│ │ │ ├── MCPDeleteSourceClient.cpp
│ │ │ └── MCPDeleteSourceClient.exe
│ │ ├── 4.0 mcp_list_groups
│ │ │ ├── MCPListGroupsClient.cpp
│ │ │ └── MCPListGroupsClient.exe
│ │ ├── 4.1 mcp_store_group
│ │ │ ├── MCPStoreGroupClient.cpp
│ │ │ └── MCPStoreGroupClient.exe
│ │ ├── 4.2 mcp_delete_group
│ │ │ ├── MPCDeleteGroupClient.cpp
│ │ │ └── MPCDeleteGroupClient.exe
│ │ ├── 5.0 mcp_store_user
│ │ │ ├── MCPStoreUserClient.cpp
│ │ │ └── MCPStoreUserClient.exe
│ │ ├── 5.1 mcp_edit_user
│ │ │ ├── MCPEditUserClient.cpp
│ │ │ └── MCPEditUserClient.exe
│ │ ├── 5.2 mcp_delete_user
│ │ │ ├── MCPDeleteUserClient.cpp
│ │ │ └── MCPDeleteUserClient.exe
│ │ ├── 9.0 mcp_keygen
│ │ │ ├── MCPKeygenClient.cpp
│ │ │ └── MCPKeygenClient.exe
│ │ └── README.md
│ ├── Go
│ │ ├── 1.0 mcp_login
│ │ │ ├── go.mod
│ │ │ ├── MCPLoginClient.exe
│ │ │ └── MCPLoginClient.go
│ │ ├── 1.1 mcp_logout
│ │ │ ├── MCPLogoutClient.exe
│ │ │ └── MCPLogoutClient.go
│ │ ├── 2.0 mcp_chat
│ │ │ ├── MCPChatClient.exe
│ │ │ └── MCPChatClient.go
│ │ ├── 2.1 mcp_continue_chat
│ │ │ ├── MCPChatContinuationClient.exe
│ │ │ └── MCPChatContinuationClient.go
│ │ ├── 2.2 mcp_get_chat_info
│ │ │ ├── MCPGetChatInfoClient.exe
│ │ │ └── MCPGetChatInfoClient.go
│ │ ├── 3.0 mcp_create_source
│ │ │ ├── MCPCreateSourceClient.exe
│ │ │ └── MCPCreateSourceClient.go
│ │ ├── 3.1 mcp_get_source
│ │ │ ├── MCPGetSourceClient.exe
│ │ │ └── MCPGetSourceClient.go
│ │ ├── 3.2 mcp_list_sources
│ │ │ ├── MCPListSourcesClient.exe
│ │ │ └── MCPListSourcesClient.go
│ │ ├── 3.3 mcp_edit_source
│ │ │ ├── MCPEditSourceClient.exe
│ │ │ └── MCPEditSourceClient.go
│ │ ├── 3.4 mcp_delete_source
│ │ │ ├── MCPDeleteSourceClient.exe
│ │ │ └── MCPDeleteSourceClient.go
│ │ ├── 4.0 mcp_list_groups
│ │ │ ├── MCPListGroupsClient.exe
│ │ │ └── MCPListGroupsClient.go
│ │ ├── 4.1 mcp_store_group
│ │ │ ├── MCPStoreGroupClient.exe
│ │ │ └── MCPStoreGroupClient.go
│ │ ├── 4.2 mcp_delete_group
│ │ │ ├── MCPDeleteGroupClient.exe
│ │ │ └── MCPDeleteGroupClient.go
│ │ ├── 5.0 mcp_store_user
│ │ │ ├── MCPStoreUserClient.exe
│ │ │ └── MCPStoreUserClient.go
│ │ ├── 5.1 mcp_edit_user
│ │ │ ├── MCPEditUserClient.exe
│ │ │ └── MCPEditUserClient.go
│ │ ├── 5.2 mcp_delete_user
│ │ │ ├── MCPDeleteUserClient.exe
│ │ │ └── MCPDeleteUserClient.go
│ │ ├── 9.0 mcp_keygen
│ │ │ ├── MCPKeygenClient.exe
│ │ │ └── MCPKeygenClient.go
│ │ └── README.md
│ ├── Gradio
│ │ ├── Api.py
│ │ ├── config.json.example
│ │ ├── config.py
│ │ ├── favicon.ico
│ │ ├── file_tools
│ │ │ └── loader_factory.py
│ │ ├── language.py
│ │ ├── logos
│ │ │ ├── fsas.png
│ │ │ └── Logo_dark.svg
│ │ ├── main.py
│ │ ├── mcp_client.py
│ │ ├── mcp_servers
│ │ │ ├── arxiv
│ │ │ │ ├── arxiv-stdio.js
│ │ │ │ ├── package.json
│ │ │ │ ├── README.md
│ │ │ │ ├── requirements.txt
│ │ │ │ └── server_config.example.json
│ │ │ ├── demo-mcp-server
│ │ │ │ ├── demo-tools-sse.js
│ │ │ │ ├── demo-tools-stdio.js
│ │ │ │ └── tools
│ │ │ │ ├── assets.js
│ │ │ │ ├── calculator.js
│ │ │ │ └── weather.js
│ │ │ ├── filesystem
│ │ │ │ ├── Dockerfile
│ │ │ │ ├── index.ts
│ │ │ │ ├── package.json
│ │ │ │ ├── README.md
│ │ │ │ ├── test
│ │ │ │ │ └── new.txt
│ │ │ │ └── tsconfig.json
│ │ │ ├── moondream
│ │ │ │ └── server.py
│ │ │ ├── pgpt
│ │ │ │ ├── __init__.py
│ │ │ │ ├── Api.py
│ │ │ │ ├── config.json.example
│ │ │ │ ├── config.py
│ │ │ │ ├── language.py
│ │ │ │ ├── pyproject.toml
│ │ │ │ ├── README.md
│ │ │ │ └── server.py
│ │ │ ├── replicate_flux
│ │ │ │ └── server.py
│ │ │ └── sqlite
│ │ │ ├── .python-version
│ │ │ ├── Dockerfile
│ │ │ ├── pyproject.toml
│ │ │ ├── README.md
│ │ │ └── src
│ │ │ └── mcp_server_sqlite
│ │ │ ├── __init__.py
│ │ │ └── server.py
│ │ ├── messages
│ │ │ ├── __init__.py
│ │ │ ├── message_types
│ │ │ │ ├── __init__.py
│ │ │ │ ├── incrementing_id_message.py
│ │ │ │ ├── initialize_message.py
│ │ │ │ ├── json_rpc_message.py
│ │ │ │ ├── ping_message.py
│ │ │ │ ├── prompts_messages.py
│ │ │ │ ├── prompts_models.py
│ │ │ │ ├── resources_messages.py
│ │ │ │ └── tools_messages.py
│ │ │ ├── send_call_tool.py
│ │ │ ├── send_initialize_message.py
│ │ │ ├── send_message.py
│ │ │ ├── send_ping.py
│ │ │ ├── send_prompts.py
│ │ │ ├── send_resources.py
│ │ │ └── send_tools_list.py
│ │ ├── README.md
│ │ ├── requirements.txt
│ │ ├── server_config.json
│ │ ├── SourceManagement.py
│ │ ├── transport
│ │ │ ├── __init__.py
│ │ │ └── stdio
│ │ │ ├── __init__.py
│ │ │ ├── stdio_client.py
│ │ │ ├── stdio_server_parameters.py
│ │ │ └── stdio_server_shutdown.py
│ │ ├── tsconfig.json
│ │ └── UserManagement.py
│ ├── Java
│ │ ├── 1.0 mcp_login
│ │ │ ├── json-20241224.jar
│ │ │ ├── MCPLoginClient.class
│ │ │ └── MCPLoginClient.java
│ │ ├── 1.1 mcp_logout
│ │ │ ├── json-20241224.jar
│ │ │ ├── MCPLogoutClient.class
│ │ │ └── MCPLogoutClient.java
│ │ ├── 2.0 mcp_chat
│ │ │ ├── json-20241224.jar
│ │ │ ├── MCPChatClient.class
│ │ │ └── MCPChatClient.java
│ │ ├── 2.1 mcp_continue_chat
│ │ │ ├── json-20241224.jar
│ │ │ ├── MCPContinueChatClient.class
│ │ │ └── MCPContinueChatClient.java
│ │ ├── 2.2 mcp_get_chat_info
│ │ │ ├── json-20241224.jar
│ │ │ ├── MCPGetChatInfoClient.class
│ │ │ └── MCPGetChatInfoClient.java
│ │ ├── 3.0 mcp_create_source
│ │ │ ├── json-20241224.jar
│ │ │ ├── MCPCreateSourceClient.class
│ │ │ └── MCPCreateSourceClient.java
│ │ ├── 3.1 mcp_get_source
│ │ │ ├── json-20241224.jar
│ │ │ ├── MCPGetSourceClient.class
│ │ │ └── MCPGetSourceClient.java
│ │ ├── 3.2 mcp_list_sources
│ │ │ ├── json-20241224.jar
│ │ │ ├── MCPListSourcesClient.class
│ │ │ └── MCPListSourcesClient.java
│ │ ├── 3.3 mcp_edit_source
│ │ │ ├── json-20241224.jar
│ │ │ ├── MCPEditSourceClient.class
│ │ │ └── MCPEditSourceClient.java
│ │ ├── 3.4 mcp_delete_source
│ │ │ ├── json-20241224.jar
│ │ │ ├── MCPDeleteSourceClient.class
│ │ │ └── MCPDeleteSourceClient.java
│ │ ├── 4.0 mcp_list_groups
│ │ │ ├── json-20241224.jar
│ │ │ ├── MCPListGroupsClient.class
│ │ │ └── MCPListGroupsClient.java
│ │ ├── 4.1 mcp_store_group
│ │ │ ├── json-20241224.jar
│ │ │ ├── MCPStoreGroupClient.class
│ │ │ └── MCPStoreGroupClient.java
│ │ ├── 4.2 mcp_delete_group
│ │ │ ├── json-20241224.jar
│ │ │ ├── MCPDeleteGroupClient.class
│ │ │ └── MCPDeleteGroupClient.java
│ │ ├── 5.0 mcp_store_user
│ │ │ ├── json-20241224.jar
│ │ │ ├── MCPStoreUserClient.class
│ │ │ └── MCPStoreUserClient.java
│ │ ├── 5.1 mcp_edit_user
│ │ │ ├── json-20241224.jar
│ │ │ ├── MCPEditUserClient.class
│ │ │ └── MCPEditUserClient.java
│ │ ├── 5.2 mcp_delete_user
│ │ │ ├── json-20241224.jar
│ │ │ ├── MCPDeleteUserClient.class
│ │ │ └── MCPDeleteUserClient.java
│ │ └── README.md
│ ├── JavaScript
│ │ ├── 1.0 mcp_login
│ │ │ └── MCPLoginClient.js
│ │ ├── 1.1 mcp_logout
│ │ │ └── MCPLogoutClient.js
│ │ ├── 2.0 mcp_chat
│ │ │ └── MCPChatClient.js
│ │ ├── 2.1 mcp_continue_chat
│ │ │ └── MCPContinueChatClient.js
│ │ ├── 2.2 mcp_get_chat_info
│ │ │ └── MCPGetChatInfoClient.js
│ │ ├── 3.0 mcp_create_source
│ │ │ └── MCPCreateSourceClient.js
│ │ ├── 3.1 mcp_get_source
│ │ │ └── MCPGetSourceClient.js
│ │ ├── 3.2 mcp_list_sources
│ │ │ └── MCPListSourcesClient.js
│ │ ├── 3.3 mcp_edit_source
│ │ │ └── MCPEditSourceClient.js
│ │ ├── 3.4 mcp_delete_source
│ │ │ └── MCPDeleteSourceClient.js
│ │ ├── 4.0 mcp_list_groups
│ │ │ └── MCPListGroupsClient.js
│ │ ├── 4.1 mcp_store_group
│ │ │ └── MCPStoreGroupClient.js
│ │ ├── 4.2 mcp_delete_group
│ │ │ └── MCPDeleteGroupClient.js
│ │ ├── 5.0 mcp_store_user
│ │ │ └── MCPStoreUserClient.js
│ │ ├── 5.1 mcp_edit_user
│ │ │ └── MCPEditUserClient.js
│ │ ├── 5.2 mcp_delete_user
│ │ │ └── MCPDeleteUserClient.js
│ │ ├── 9.0 mcp_keygen
│ │ │ └── MCPKeygenClient.js
│ │ └── README.md
│ ├── PHP
│ │ ├── 1.0 mcp_login
│ │ │ └── MCPLoginClient.php
│ │ ├── 1.1 mcp_logout
│ │ │ └── MCPLogoutClient.php
│ │ ├── 2.0 mcp_chat
│ │ │ └── MCPChatClient.php
│ │ ├── 2.1 mcp_continue_chat
│ │ │ └── MCPContinueChatClient.php
│ │ ├── 2.2 mcp_get_chat_info
│ │ │ └── MCPGetChatInfoClient.php
│ │ ├── 3.0 mcp_create_source
│ │ │ └── MCPCreateSourceClient.php
│ │ ├── 3.1 mcp_get_source
│ │ │ └── MCPGetSourceClient.php
│ │ ├── 3.2 mcp_list_sources
│ │ │ └── MCPListSourcesClient.php
│ │ ├── 3.3 mcp_edit_source
│ │ │ └── MCPEditSourceClient.php
│ │ ├── 3.4 mcp_delete_source
│ │ │ └── MCPDeleteSourceClient.php
│ │ ├── 4.0 mcp_list_groups
│ │ │ └── MCPListGroupsClient.php
│ │ ├── 4.1 mcp_store_group
│ │ │ └── MCPStoreGroupClient.php
│ │ ├── 4.2 mcp_delete_group
│ │ │ └── MCPDeleteGroupClient.php
│ │ ├── 5.0 mcp_store_user
│ │ │ └── MCPStoreUserClient.php
│ │ ├── 5.1 mcp_edit_user
│ │ │ └── MCPEditUserClient.php
│ │ ├── 5.2 mcp_delete_user
│ │ │ └── MCPDeleteUserClient.php
│ │ ├── 9.0 mcp_keygen
│ │ │ └── MCPKeygenClient.php
│ │ └── README.md
│ └── Python
│ ├── __init__.py
│ ├── 1.0 mcp_login
│ │ └── MCPLoginClient.py
│ ├── 1.1 mcp_logout
│ │ └── MCPLogoutClient.py
│ ├── 2.0 mcp_chat
│ │ └── MCPChatClient.py
│ ├── 2.1 mcp_continue_chat
│ │ └── MCPContinueChatClient.py
│ ├── 2.2 mcp_get_chat_info
│ │ └── MCPGetChatInfoClient.py
│ ├── 2.3 mcp_delete_all_chats
│ │ └── MCPDeleteAllChatsClient.py
│ ├── 2.4 mcp_delete_chat
│ │ └── MCPDeleteChatClient.py
│ ├── 3.0 mcp_create_source
│ │ └── MCPCreateSourceClient.py
│ ├── 3.1 mcp_get_source
│ │ └── MCPGetSourceClient.py
│ ├── 3.2 mcp_list_sources
│ │ └── MCPListSourcesClient.py
│ ├── 3.3 mcp_edit_source
│ │ └── MCPEditSourceClient.py
│ ├── 3.4 mcp_delete_source
│ │ └── MCPDeleteSourceClient.py
│ ├── 4.0 mcp_list_groups
│ │ └── MCPListGroupsClient.py
│ ├── 4.1 mcp_store_group
│ │ └── MCPStoreGroupClient.py
│ ├── 4.2 mcp_delete_group
│ │ └── MCPDeleteGroupClient.py
│ ├── 5.0 mcp_store_user
│ │ └── MCPStoreUserClient.py
│ ├── 5.1 mcp_edit_user
│ │ └── MCPEditUserClient.py
│ ├── 5.2 mcp_delete_user
│ │ └── MCPDeleteUserClient.py
│ ├── 9.0 mcp_keygen
│ │ └── MCPKeygenClient.py
│ ├── Gradio
│ │ ├── __init__.py
│ │ └── server_config.json
│ └── README.md
├── examples
│ ├── create_users_from_csv
│ │ ├── config.json.example
│ │ ├── config.py
│ │ ├── create_users_from_csv.py
│ │ └── language.py
│ ├── dynamic_sources
│ │ └── rss_reader
│ │ ├── Api.py
│ │ ├── config.json.example
│ │ ├── config.py
│ │ ├── demo_dynamic_sources.py
│ │ └── rss_parser.py
│ ├── example_users_to_add_no_tz.csv
│ └── sftp_upload_with_id
│ ├── Api.py
│ ├── config_ftp.json.example
│ ├── config.py
│ ├── demo_upload.py
│ ├── language.py
│ └── requirements.txt
├── images
│ ├── alternative mcp client.png
│ ├── favicon
│ │ ├── android-chrome-192x192.png
│ │ ├── android-chrome-512x512.png
│ │ ├── apple-touch-icon.png
│ │ ├── favicon-16x16.png
│ │ ├── favicon-32x32.png
│ │ ├── favicon.ico
│ │ └── site.webmanifest
│ ├── mcp-general-architecture.png
│ ├── privateGPT-MCP.png
│ └── privateGPT.png
├── InstallMPCServer.sh
├── jest.config.js
├── LICENSE
├── package.json
├── pgpt.env.json.example
├── README.md
├── security
│ ├── generate_decrypted_password.js
│ └── generate_encrypted_password.js
├── src
│ ├── helper.js
│ ├── index.js
│ ├── logger.js
│ ├── pgpt-messages.js
│ ├── public
│ │ ├── index.html
│ │ └── pgpt-mcp-logo.png
│ ├── services
│ │ └── pgpt-service.ts
│ └── types
│ └── api.ts
├── start_chatbot_agent.ps1
├── start_chatbot_agent.sh
├── start_iot_agent.ps1
├── start_iot_agent.sh
├── start_openai_compatible_api_agent.ps1
├── start_openai_compatible_api_agent.sh
├── tsconfig.json
├── ver
│ ├── index_np.js
│ └── index_proxy_np.js
└── WORKLOG.md
```
# Files
--------------------------------------------------------------------------------
/clients/Python/5.1 mcp_edit_user/MCPEditUserClient.py:
--------------------------------------------------------------------------------
```python
import socket
import ssl
import json
import argparse
import sys
def send_edit_user_request(server_ip, server_port, token, name=None, email=None, password=None, language=None,
timezone=None, roles=None, groups=None, use_public=False, activate_ftp=False, ftp_password=None,
use_ssl=True, accept_self_signed=False):
"""
Sends a request to edit an existing user to the MCP server.
"""
payload = {
"command": "edit_user",
"token": token,
"arguments": {
"name": name,
"email": email,
"password": password,
"language": language,
"timezone": timezone,
"roles": roles or [],
"groups": groups or [],
"usePublic": use_public,
"activateFtp": activate_ftp,
"ftpPassword": ftp_password
}
}
# Remove keys with None values
payload["arguments"] = {k: v for k, v in payload["arguments"].items() if v is not None}
payload_json = json.dumps(payload)
raw_socket = None
client_socket = None
try:
raw_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
raw_socket.settimeout(10)
if use_ssl:
context = ssl.create_default_context()
if accept_self_signed:
context.check_hostname = False
context.verify_mode = ssl.CERT_NONE
client_socket = context.wrap_socket(raw_socket, server_hostname=server_ip)
else:
client_socket = raw_socket
client_socket.connect((server_ip, server_port))
client_socket.sendall(payload_json.encode('utf-8'))
response = b""
while True:
part = client_socket.recv(4096)
if not part:
break
response += part
return response.decode('utf-8')
except ssl.SSLError:
return "Error: Server and/or client may require TLS encryption. Please enable SSL/TLS."
except Exception as e:
return f"Error: {e}"
finally:
if client_socket is not None:
try:
client_socket.shutdown(socket.SHUT_RDWR)
except:
pass
client_socket.close()
if __name__ == "__main__":
parser = argparse.ArgumentParser(
description="Send a request to edit an existing user to the MCP server.",
formatter_class=argparse.RawTextHelpFormatter
)
parser.add_argument("--server-ip", required=True, help="IP address of the MCP server")
parser.add_argument("--server-port", required=True, type=int, help="Port number of the MCP server")
parser.add_argument("--token", required=True, help="Authentication token")
parser.add_argument("--name", help="New name of the user")
parser.add_argument("--email", help="New email of the user")
parser.add_argument("--password", help="New password of the user")
parser.add_argument("--language", help="Preferred language of the user")
parser.add_argument("--timezone", help="Timezone of the user")
parser.add_argument("--roles", nargs="*", help="List of roles to assign to the user")
parser.add_argument("--groups", nargs="*", help="List of groups to assign to the user")
parser.add_argument("--usePublic", action="store_true", help="Enable public knowledge base access")
parser.add_argument("--activateFtp", action="store_true", help="Activate FTP access")
parser.add_argument("--ftpPassword", help="Password for FTP access")
parser.add_argument("--use-ssl", action="store_true", help="Connect using SSL/TLS")
parser.add_argument("--accept-self-signed", action="store_true", help="Accept self-signed certificates (disable certificate verification)")
if len(sys.argv) == 1:
parser.print_help(sys.stderr)
sys.exit(1)
args = parser.parse_args()
response = send_edit_user_request(
args.server_ip,
args.server_port,
args.token,
name=args.name,
email=args.email,
password=args.password,
language=args.language,
timezone=args.timezone,
roles=args.roles,
groups=args.groups,
use_public=args.usePublic,
activate_ftp=args.activateFtp,
ftp_password=args.ftpPassword,
use_ssl=args.use_ssl,
accept_self_signed=args.accept_self_signed
)
print("Response from server:", response)
```
--------------------------------------------------------------------------------
/clients/JavaScript/2.0 mcp_chat/MCPChatClient.js:
--------------------------------------------------------------------------------
```javascript
const net = require('net');
const readline = require('readline');
const { argv, exit } = require('process');
// Funktion zum Parsen der Kommandozeilenargumente
function parseArguments(args) {
const parsedArgs = {};
for (let i = 2; i < args.length; i++) {
switch (args[i]) {
case '--server-ip':
parsedArgs.serverIp = args[++i];
break;
case '--server-port':
parsedArgs.serverPort = parseInt(args[++i], 10);
break;
case '--token':
parsedArgs.token = args[++i];
break;
case '--question':
parsedArgs.question = args[++i];
break;
case '--use-public':
parsedArgs.usePublic = true;
break;
case '--groups':
// Sammle alle Gruppenargumente bis zum nächsten Flag oder Ende
parsedArgs.groups = [];
while (i + 1 < args.length && !args[i + 1].startsWith('--')) {
parsedArgs.groups.push(args[++i]);
}
break;
case '--language':
parsedArgs.language = args[++i];
break;
default:
console.warn(`Unbekanntes Argument: ${args[i]}`);
}
}
return parsedArgs;
}
// Funktion zum interaktiven Abfragen eines Parameters (optional)
function askQuestion(query) {
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
terminal: true
});
return new Promise((resolve) => {
rl.question(query, (answer) => {
rl.close();
resolve(answer);
});
});
}
// Funktion zum Senden einer Chat-Anfrage über eine TCP-Verbindung
function sendChatRequest(serverIp, serverPort, payload) {
return new Promise((resolve, reject) => {
const client = new net.Socket();
let responseData = '';
client.connect(serverPort, serverIp, () => {
console.log('🔗 Verbindung zum Server hergestellt.');
const payloadString = JSON.stringify(payload);
console.log(`📤 Sende Payload: ${payloadString}`);
client.write(payloadString);
});
client.on('data', (data) => {
console.log(`📥 Empfangene Daten: ${data}`);
responseData += data.toString();
try {
const parsedData = JSON.parse(responseData);
console.log('✅ JSON-Antwort erfolgreich geparst.');
resolve(parsedData);
client.destroy(); // Verbindung schließen
} catch (err) {
console.warn('⚠️ Antwort noch nicht vollständig oder ungültiges JSON. Weitere Daten werden erwartet.');
// Antwort noch nicht vollständig, weiter empfangen
}
});
client.on('close', () => {
console.log('🔒 Verbindung zum Server geschlossen.');
});
client.on('error', (err) => {
console.error('❌ Verbindungsfehler:', err.message);
reject(err);
});
});
}
// Hauptfunktion
async function main() {
const args = argv;
const parsedArgs = parseArguments(args);
const { serverIp, serverPort, token, question, usePublic, groups, language } = parsedArgs;
// Überprüfen, ob alle erforderlichen Parameter vorhanden sind
if (!serverIp || !serverPort || !token || !question) {
console.error('❌ ERROR: Fehlende erforderliche Parameter.');
console.log('Verwendung: node MCPChatClient.js --server-ip <IP> --server-port <Port> --token <Token> --question <Frage> [--use-public] [--groups <Gruppe1> <Gruppe2> ...] [--language <Sprache>]');
exit(1);
}
// Optional: Fallback für optionale Parameter
const finalLanguage = language || 'de';
const finalGroups = groups || [];
const payload = {
command: "chat",
token: token,
arguments: {
question: question,
usePublic: usePublic || false,
groups: finalGroups,
language: finalLanguage
}
};
try {
console.log('💬 Sende Chat-Anfrage...');
const response = await sendChatRequest(serverIp, serverPort, payload);
console.log('✅ Server Response:');
console.log(JSON.stringify(response, null, 2));
} catch (err) {
console.error('❌ ERROR:', err.message);
}
}
main();
```
--------------------------------------------------------------------------------
/src/services/pgpt-service.ts:
--------------------------------------------------------------------------------
```typescript
import axios, { AxiosInstance } from 'axios';
import { ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js';
import { ChatArgs, SourceArgs, ListSourcesArgs, GetSourceArgs } from '../types/api.js';
export class PGPTService {
private api: AxiosInstance;
private token: string | null = null;
constructor() {
// Initialize axios instance with base configuration
this.api = axios.create({
baseURL: process.env.PGPT_API_URL || 'http://localhost:3000',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
});
}
private async ensureAuthenticated(): Promise<void> {
if (!this.token) {
const email = process.env.PGPT_EMAIL;
const password = process.env.PGPT_PASSWORD;
if (!email || !password) {
throw new McpError(
ErrorCode.InvalidRequest,
'Missing authentication credentials'
);
}
try {
const response = await this.api.post('/api/v1/login', {
email,
password,
});
this.token = response.data.data.token;
this.api.defaults.headers.common['Authorization'] = `Bearer ${this.token}`;
} catch (error) {
throw new McpError(
ErrorCode.InvalidRequest,
'Authentication failed'
);
}
}
}
async chat(args: ChatArgs) {
await this.ensureAuthenticated();
try {
const response = await this.api.post('/api/v1/chats', {
language: args.language || 'en',
question: args.question,
usePublic: args.usePublic || false,
groups: args.groups || [],
});
return {
content: [
{
type: 'text',
text: response.data.data.answer,
},
],
};
} catch (error) {
if (axios.isAxiosError(error)) {
throw new McpError(
ErrorCode.InternalError,
`Chat failed: ${error.response?.data?.message || error.message}`
);
}
throw error;
}
}
async createSource(args: SourceArgs) {
await this.ensureAuthenticated();
try {
const response = await this.api.post('/api/v1/sources', {
name: args.name,
content: args.content,
groups: args.groups || [],
});
return {
content: [
{
type: 'text',
text: JSON.stringify(response.data.data, null, 2),
},
],
};
} catch (error) {
if (axios.isAxiosError(error)) {
throw new McpError(
ErrorCode.InternalError,
`Source creation failed: ${error.response?.data?.message || error.message}`
);
}
throw error;
}
}
async listGroups() {
await this.ensureAuthenticated();
try {
const response = await this.api.get('/api/v1/groups');
return {
content: [
{
type: 'text',
text: JSON.stringify(response.data.data, null, 2),
},
],
};
} catch (error) {
if (axios.isAxiosError(error)) {
throw new McpError(
ErrorCode.InternalError,
`Group listing failed: ${error.response?.data?.message || error.message}`
);
}
throw error;
}
}
async listSources(args: ListSourcesArgs) {
await this.ensureAuthenticated();
try {
const response = await this.api.post('/api/v1/sources/groups', {
groupName: args.groupName,
});
return {
content: [
{
type: 'text',
text: JSON.stringify(response.data.data, null, 2),
},
],
};
} catch (error) {
if (axios.isAxiosError(error)) {
throw new McpError(
ErrorCode.InternalError,
`Source listing failed: ${error.response?.data?.message || error.message}`
);
}
throw error;
}
}
async getSource(args: GetSourceArgs) {
await this.ensureAuthenticated();
try {
const response = await this.api.get(`/api/v1/sources/${args.sourceId}`);
return {
content: [
{
type: 'text',
text: JSON.stringify(response.data.data, null, 2),
},
],
};
} catch (error) {
if (axios.isAxiosError(error)) {
throw new McpError(
ErrorCode.InternalError,
`Source retrieval failed: ${error.response?.data?.message || error.message}`
);
}
throw error;
}
}
}
```
--------------------------------------------------------------------------------
/clients/C++/3.3 mcp_edit_source/MCPEditSourceClient.cpp:
--------------------------------------------------------------------------------
```cpp
#include <iostream>
#include <string>
#include <map>
#include <vector>
#include <sstream>
#include <stdexcept>
#include <json/json.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#pragma comment(lib, "ws2_32.lib") // Winsock-Bibliothek verlinken
// Funktion zum Argument-Parsing
std::map<std::string, std::string> parseArguments(int argc, char* argv[], std::vector<std::string>& groups) {
std::map<std::string, std::string> args;
for (int i = 1; i < argc; ++i) {
std::string key = argv[i];
if (i + 1 < argc && key.rfind("--", 0) == 0) {
if (key == "--groups") {
while (++i < argc && argv[i][0] != '-') {
groups.push_back(argv[i]);
}
--i; // Rückgängigmachen des letzten Schritts
} else {
args[key] = argv[++i];
}
}
}
return args;
}
// Funktion zum Senden der Anfrage
std::string sendRequest(const std::string& serverIp, int serverPort, const Json::Value& payload) {
Json::StreamWriterBuilder writer;
std::string payloadJson = Json::writeString(writer, payload);
// Winsock initialisieren
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
throw std::runtime_error("Failed to initialize Winsock.");
}
// Socket erstellen
SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == INVALID_SOCKET) {
WSACleanup();
throw std::runtime_error("Failed to create socket.");
}
// Server-Adresse konfigurieren
sockaddr_in serverAddr;
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(serverPort);
if (inet_pton(AF_INET, serverIp.c_str(), &serverAddr.sin_addr) <= 0) {
closesocket(sock);
WSACleanup();
throw std::runtime_error("Invalid server IP address.");
}
// Verbindung herstellen
if (connect(sock, (sockaddr*)&serverAddr, sizeof(serverAddr)) < 0) {
closesocket(sock);
WSACleanup();
throw std::runtime_error("Connection failed.");
}
// Daten senden
if (send(sock, payloadJson.c_str(), payloadJson.size(), 0) < 0) {
closesocket(sock);
WSACleanup();
throw std::runtime_error("Failed to send data.");
}
// Antwort empfangen
char buffer[4096];
int bytesRead;
std::ostringstream response;
do {
bytesRead = recv(sock, buffer, sizeof(buffer) - 1, 0);
if (bytesRead > 0) {
buffer[bytesRead] = '\0'; // Null-terminieren
response << buffer;
}
} while (bytesRead == sizeof(buffer) - 1);
// Socket schließen
closesocket(sock);
WSACleanup();
return response.str();
}
int main(int argc, char* argv[]) {
try {
std::vector<std::string> groups;
auto args = parseArguments(argc, argv, groups);
// Argumente extrahieren
std::string serverIp = args["--server-ip"];
int serverPort = std::stoi(args["--server-port"]);
std::string token = args["--token"];
std::string sourceId = args["--source-id"];
std::string title = args["--title"];
std::string content = args["--content"];
// Überprüfen, ob alle erforderlichen Parameter angegeben sind
if (serverIp.empty() || serverPort == 0 || token.empty() || sourceId.empty()) {
std::cerr << "Usage: MCPEditSourceClient --server-ip <IP> --server-port <PORT> --token <TOKEN> --source-id <SOURCE_ID> [--title <TITLE>] [--content <CONTENT>] [--groups <GROUP1 GROUP2 ...>]\n";
return 1;
}
std::cout << "📤 Sending request to edit the source...\n";
// JSON-Payload erstellen
Json::Value payload;
payload["command"] = "edit_source";
payload["token"] = token;
Json::Value arguments;
arguments["sourceId"] = sourceId;
if (!title.empty()) {
arguments["title"] = title;
}
if (!content.empty()) {
arguments["content"] = content;
}
Json::Value groupsJson(Json::arrayValue);
for (const auto& group : groups) {
groupsJson.append(group);
}
arguments["groups"] = groupsJson;
payload["arguments"] = arguments;
// Anfrage senden und Antwort erhalten
std::string response = sendRequest(serverIp, serverPort, payload);
std::cout << "✔️ Response from server:\n" << response << "\n";
} catch (const std::exception& e) {
std::cerr << "❌ ERROR: " << e.what() << "\n";
return 1;
}
return 0;
}
```
--------------------------------------------------------------------------------
/clients/C++/2.0 mcp_chat/MCPChatClient.cpp:
--------------------------------------------------------------------------------
```cpp
#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <sstream>
#include <stdexcept>
#include <json/json.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#pragma comment(lib, "ws2_32.lib") // Winsock-Bibliothek verlinken
// Funktion zum Argument-Parsing
std::map<std::string, std::string> parseArguments(int argc, char* argv[]) {
std::map<std::string, std::string> args;
for (int i = 1; i < argc; ++i) {
std::string key = argv[i];
if (i + 1 < argc && key.rfind("--", 0) == 0) {
args[key] = argv[++i];
}
}
return args;
}
// Funktion zum Senden der MCP-Anfrage
std::string sendMCPRequest(const std::string& serverIp, int serverPort, const std::string& token,
const std::string& question, bool usePublic, const std::vector<std::string>& groups,
const std::string& language) {
// JSON-Payload erstellen
Json::Value payload;
payload["command"] = "chat";
payload["token"] = token;
payload["arguments"]["question"] = question;
payload["arguments"]["usePublic"] = usePublic;
payload["arguments"]["language"] = language;
Json::Value groupsJson(Json::arrayValue);
for (const auto& group : groups) {
groupsJson.append(group);
}
payload["arguments"]["groups"] = groupsJson;
Json::StreamWriterBuilder writer;
std::string payloadJson = Json::writeString(writer, payload);
// Winsock initialisieren
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
throw std::runtime_error("Failed to initialize Winsock.");
}
// Socket erstellen
SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == INVALID_SOCKET) {
WSACleanup();
throw std::runtime_error("Failed to create socket.");
}
// Server-Adresse konfigurieren
sockaddr_in serverAddr;
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(serverPort);
if (inet_pton(AF_INET, serverIp.c_str(), &serverAddr.sin_addr) <= 0) {
closesocket(sock);
WSACleanup();
throw std::runtime_error("Invalid server IP address.");
}
// Verbindung herstellen
if (connect(sock, (sockaddr*)&serverAddr, sizeof(serverAddr)) < 0) {
closesocket(sock);
WSACleanup();
throw std::runtime_error("Connection failed.");
}
// Daten senden
if (send(sock, payloadJson.c_str(), payloadJson.size(), 0) < 0) {
closesocket(sock);
WSACleanup();
throw std::runtime_error("Failed to send data.");
}
// Antwort empfangen
char buffer[4096];
int bytesRead;
std::ostringstream response;
do {
bytesRead = recv(sock, buffer, sizeof(buffer) - 1, 0);
if (bytesRead > 0) {
buffer[bytesRead] = '\0'; // Null-terminieren
response << buffer;
}
} while (bytesRead == sizeof(buffer) - 1);
// Socket schließen
closesocket(sock);
WSACleanup();
return response.str();
}
int main(int argc, char* argv[]) {
try {
auto args = parseArguments(argc, argv);
// Argumente extrahieren
std::string serverIp = args["--server-ip"];
int serverPort = std::stoi(args["--server-port"]);
std::string token = args["--token"];
std::string question = args["--question"];
bool usePublic = args.find("--use-public") != args.end();
std::string language = args.count("--language") ? args["--language"] : "de";
// Gruppen extrahieren
std::vector<std::string> groups;
if (args.count("--groups")) {
std::istringstream groupStream(args["--groups"]);
std::string group;
while (std::getline(groupStream, group, ',')) {
groups.push_back(group);
}
}
// Überprüfen, ob alle erforderlichen Parameter angegeben sind
if (serverIp.empty() || serverPort == 0 || token.empty() || question.empty()) {
std::cerr << "Usage: --server-ip <IP> --server-port <PORT> --token <TOKEN> --question <QUESTION> [--use-public] [--groups <GROUPS>] [--language <LANGUAGE>]\n";
return 1;
}
std::cout << "🔒 Sending MCP chat request...\n";
// MCP-Anfrage senden und Antwort erhalten
std::string response = sendMCPRequest(serverIp, serverPort, token, question, usePublic, groups, language);
std::cout << "Response from server:\n" << response << "\n";
} catch (const std::exception& e) {
std::cerr << "❌ ERROR: " << e.what() << "\n";
return 1;
}
return 0;
}
```
--------------------------------------------------------------------------------
/clients/JavaScript/3.0 mcp_create_source/MCPCreateSourceClient.js:
--------------------------------------------------------------------------------
```javascript
const net = require('net');
const readline = require('readline');
const { argv, exit } = require('process');
// Funktion zum Parsen der Kommandozeilenargumente
function parseArguments(args) {
const parsedArgs = {};
for (let i = 2; i < args.length; i++) {
switch (args[i]) {
case '--server-ip':
parsedArgs.serverIp = args[++i];
break;
case '--server-port':
parsedArgs.serverPort = parseInt(args[++i], 10);
break;
case '--token':
parsedArgs.token = args[++i];
break;
case '--name':
parsedArgs.name = args[++i];
break;
case '--content':
parsedArgs.content = args[++i];
break;
case '--groups':
// Sammle alle Gruppenargumente bis zum nächsten Flag oder Ende
parsedArgs.groups = [];
while (i + 1 < args.length && !args[i + 1].startsWith('--')) {
parsedArgs.groups.push(args[++i]);
}
break;
default:
console.warn(`⚠️ Unbekanntes Argument: ${args[i]}`);
}
}
return parsedArgs;
}
// Funktion zum interaktiven Abfragen eines Parameters (optional)
function askQuestion(query) {
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
terminal: true
});
return new Promise((resolve) => {
rl.question(query, (answer) => {
rl.close();
resolve(answer);
});
});
}
// Funktion zum Senden einer Create-Source-Anfrage über eine TCP-Verbindung
function sendCreateSourceRequest(serverIp, serverPort, payload) {
return new Promise((resolve, reject) => {
const client = new net.Socket();
let responseData = '';
client.connect(serverPort, serverIp, () => {
console.log(`🔗 Verbindung zum Server (${serverIp}:${serverPort}) hergestellt.`);
const payloadString = JSON.stringify(payload);
console.log(`📤 Sende Payload: ${payloadString}`);
client.write(payloadString);
});
client.on('data', (data) => {
console.log(`📥 Empfangene Daten: ${data}`);
responseData += data.toString();
try {
const parsedData = JSON.parse(responseData);
console.log('✅ JSON-Antwort erfolgreich geparst.');
resolve(parsedData);
client.destroy(); // Verbindung schließen
} catch (err) {
console.warn('⚠️ Antwort noch nicht vollständig oder ungültiges JSON. Weitere Daten werden erwartet.');
// Antwort noch nicht vollständig, weiter empfangen
}
});
client.on('close', () => {
console.log('🔒 Verbindung zum Server geschlossen.');
});
client.on('error', (err) => {
console.error('❌ Verbindungsfehler:', err.message);
reject(err);
});
});
}
// Hauptfunktion
async function main() {
const args = argv;
const parsedArgs = parseArguments(args);
let { serverIp, serverPort, token, name, content, groups } = parsedArgs;
// Überprüfen, ob alle erforderlichen Parameter vorhanden sind, sonst interaktiv abfragen
if (!serverIp) {
serverIp = await askQuestion('🔗 Bitte gib die Server-IP ein: ');
}
if (!serverPort) {
const portInput = await askQuestion('🔗 Bitte gib den Server-Port ein: ');
serverPort = parseInt(portInput, 10);
}
if (!token) {
token = await askQuestion('🔒 Bitte gib dein Authentifizierungstoken ein: ');
}
if (!name) {
name = await askQuestion('📛 Bitte gib den Namen der neuen Quelle ein: ');
}
if (!content) {
content = await askQuestion('📝 Bitte gib den Inhalt der neuen Quelle (Markdown) ein: ');
}
if (!groups) {
const groupsInput = await askQuestion('👥 Bitte gib die Gruppen an (getrennt durch Leerzeichen, optional): ');
groups = groupsInput ? groupsInput.split(' ') : [];
}
const payload = {
command: "create_source",
token: token,
arguments: {
name: name,
content: content,
groups: groups
}
};
try {
console.log('🛠️ Sende Create-Source-Anfrage...');
const response = await sendCreateSourceRequest(serverIp, serverPort, payload);
console.log('✅ Server Response:');
console.log(JSON.stringify(response, null, 2));
} catch (err) {
console.error('❌ ERROR:', err.message);
}
}
main();
```
--------------------------------------------------------------------------------
/clients/PHP/1.0 mcp_login/MCPLoginClient.php:
--------------------------------------------------------------------------------
```php
<?php
// Functions for parsing command line arguments
function parseArguments($args) {
$parsedArgs = [];
$argc = count($args);
for ($i = 1; $i < $argc; $i++) {
switch ($args[$i]) {
case '--server-ip':
if (isset($args[$i + 1])) {
$parsedArgs['serverIp'] = $args[++$i];
} else {
fwrite(STDERR, "Error: --server-ip expects a value.\n");
exit(1);
}
break;
case '--server-port':
if (isset($args[$i + 1])) {
$parsedArgs['serverPort'] = intval($args[++$i]);
} else {
fwrite(STDERR, "Error: --server-port expects a value.\n");
exit(1);
}
break;
case '--email':
if (isset($args[$i + 1])) {
$parsedArgs['email'] = $args[++$i];
} else {
fwrite(STDERR, "Error: --email expects a value.\n");
exit(1);
}
break;
case '--password':
if (isset($args[$i + 1])) {
$parsedArgs['password'] = $args[++$i];
} else {
fwrite(STDERR, "Error: --password expects a value.\n");
exit(1);
}
break;
default:
fwrite(STDERR, "Warning: Unknown argument: {$args[$i]}\n");
}
}
return $parsedArgs;
}
// Function for sending a request over a TCP connection
function sendRequest($serverIp, $serverPort, $payload) {
$jsonPayload = json_encode($payload);
if ($jsonPayload === false) {
throw new Exception("Error encoding JSON payload.");
}
$errno = 0;
$errstr = '';
$timeout = 30; // seconds
$client = fsockopen($serverIp, $serverPort, $errno, $errstr, $timeout);
if (!$client) {
throw new Exception("Connection error: $errstr ($errno)");
}
echo "🔗 Connection to server established.\n";
fwrite($client, $jsonPayload);
$responseData = '';
stream_set_timeout($client, $timeout);
while (!feof($client)) {
$data = fread($client, 1024);
if ($data === false) {
throw new Exception("Error reading data from server.");
}
$responseData .= $data;
// Attempt to parse the received data as JSON
$parsedData = json_decode($responseData, true);
if ($parsedData !== null) {
fclose($client);
return $parsedData;
}
// Check if the stream timed out
$info = stream_get_meta_data($client);
if ($info['timed_out']) {
throw new Exception("Timeout waiting for data from server.");
}
}
fclose($client);
throw new Exception("Connection to the server was closed before a complete response was received.");
}
// Function for interactively asking for a password (optional)
function askPassword($prompt) {
if (preg_match('/^win/i', PHP_OS)) {
// Windows-specific password prompt
$vbscript = sys_get_temp_dir() . 'prompt_password.vbs';
file_put_contents($vbscript, 'wscript.echo(InputBox("' . addslashes($prompt) . '", "", "password here"))');
$password = shell_exec("cscript //nologo " . escapeshellarg($vbscript));
unlink($vbscript);
return trim($password);
} else {
// Unix/Linux password prompt
echo $prompt;
system('stty -echo');
$password = rtrim(fgets(STDIN), "\n");
system('stty echo');
echo "\n";
return $password;
}
}
// Main function
function main($argv) {
$args = parseArguments($argv);
$serverIp = $args['serverIp'] ?? null;
$serverPort = $args['serverPort'] ?? null;
$email = $args['email'] ?? null;
$password = $args['password'] ?? null;
// Check if all required parameters are present
if (!$serverIp || !$serverPort || !$email || !$password) {
fwrite(STDERR, "❌ ERROR: Missing required parameters.\n");
fwrite(STDOUT, "Usage: php MCPLoginClient.php --server-ip <IP> --server-port <Port> --email <Email> --password <Password>\n");
exit(1);
}
$payload = [
"command" => "login",
"arguments" => [
"email" => $email,
"password" => $password
]
];
try {
echo "🔐 Logging in...\n";
$response = sendRequest($serverIp, $serverPort, $payload);
echo "✅ Server Response:\n";
echo json_encode($response, JSON_PRETTY_PRINT) . "\n";
} catch (Exception $e) {
fwrite(STDERR, "❌ ERROR: " . $e->getMessage() . "\n");
}
}
main($argv);
?>
```
--------------------------------------------------------------------------------
/clients/PHP/1.1 mcp_logout/MCPLogoutClient.php:
--------------------------------------------------------------------------------
```php
<?php
// Functions for parsing command line arguments
function parseArguments($args) {
$parsedArgs = [];
$argc = count($args);
for ($i = 1; $i < $argc; $i++) {
switch ($args[$i]) {
case '--server-ip':
if (isset($args[$i + 1])) {
$parsedArgs['serverIp'] = $args[++$i];
} else {
fwrite(STDERR, "Error: --server-ip expects a value.\n");
exit(1);
}
break;
case '--server-port':
if (isset($args[$i + 1])) {
$parsedArgs['serverPort'] = intval($args[++$i]);
} else {
fwrite(STDERR, "Error: --server-port expects a value.\n");
exit(1);
}
break;
case '--token':
if (isset($args[$i + 1])) {
$parsedArgs['token'] = $args[++$i];
} else {
fwrite(STDERR, "Error: --token expects a value.\n");
exit(1);
}
break;
default:
fwrite(STDERR, "Warning: Unknown argument: {$args[$i]}\n");
}
}
return $parsedArgs;
}
// Function for interactively asking for a token (optional)
function askToken($prompt) {
if (preg_match('/^win/i', PHP_OS)) {
// Windows-specific token prompt
$vbscript = sys_get_temp_dir() . 'prompt_token.vbs';
file_put_contents($vbscript, 'wscript.echo(InputBox("' . addslashes($prompt) . '", "", "token here"))');
$token = shell_exec("cscript //nologo " . escapeshellarg($vbscript));
unlink($vbscript);
return trim($token);
} else {
// Unix/Linux token prompt
echo $prompt;
// Token input typically without echo
if (shell_exec('which stty')) {
system('stty -echo');
$token = rtrim(fgets(STDIN), "\n");
system('stty echo');
echo "\n";
return $token;
} else {
// Fallback if stty is unavailable
return rtrim(fgets(STDIN), "\n");
}
}
}
// Function for sending a logout request over a TCP connection
function sendLogoutRequest($serverIp, $serverPort, $payload) {
$jsonPayload = json_encode($payload);
if ($jsonPayload === false) {
throw new Exception("Error encoding JSON payload.");
}
$errno = 0;
$errstr = '';
$timeout = 30; // seconds
$client = fsockopen($serverIp, $serverPort, $errno, $errstr, $timeout);
if (!$client) {
throw new Exception("Connection error: $errstr ($errno)");
}
echo "🔗 Connection to server established.\n";
fwrite($client, $jsonPayload);
$responseData = '';
stream_set_timeout($client, $timeout);
while (!feof($client)) {
$data = fread($client, 1024);
if ($data === false) {
throw new Exception("Error reading data from server.");
}
$responseData .= $data;
// Attempt to parse the received data as JSON
$parsedData = json_decode($responseData, true);
if ($parsedData !== null) {
fclose($client);
return $parsedData;
}
// Check if the stream timed out
$info = stream_get_meta_data($client);
if ($info['timed_out']) {
throw new Exception("Timeout waiting for data from server.");
}
}
fclose($client);
throw new Exception("Connection to the server was closed before a complete response was received.");
}
// Main function
function main($argv) {
$args = parseArguments($argv);
$serverIp = $args['serverIp'] ?? null;
$serverPort = $args['serverPort'] ?? null;
$token = $args['token'] ?? null;
// Check if all required parameters except token are present
if (!$serverIp || !$serverPort) {
fwrite(STDERR, "❌ ERROR: Missing required parameters.\n");
fwrite(STDOUT, "Usage: php MCPLogoutClient.php --server-ip <IP> --server-port <Port> --token <Token>\n");
exit(1);
}
// Interactively ask for token if not provided in arguments
$authToken = $token;
if (!$authToken) {
$authToken = askToken('🔒 Please enter your authentication token: ');
}
if (empty($authToken)) {
fwrite(STDERR, "❌ ERROR: Authentication token must not be empty.\n");
exit(1);
}
$payload = [
"command" => "logout",
"token" => $authToken
];
try {
echo "🚪 Logging out...\n";
$response = sendLogoutRequest($serverIp, $serverPort, $payload);
echo "✅ Server Response:\n";
echo json_encode($response, JSON_PRETTY_PRINT) . "\n";
} catch (Exception $e) {
fwrite(STDERR, "❌ ERROR: " . $e->getMessage() . "\n");
}
}
main($argv);
?>
```
--------------------------------------------------------------------------------
/clients/C++/5.0 mcp_store_user/MCPStoreUserClient.cpp:
--------------------------------------------------------------------------------
```cpp
#include <iostream>
#include <string>
#include <map>
#include <vector>
#include <sstream>
#include <stdexcept>
#include <json/json.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#pragma comment(lib, "ws2_32.lib") // Verlinkung mit der Winsock-Bibliothek
// Funktion zum Parsen von Argumenten
std::map<std::string, std::string> parseArguments(int argc, char* argv[]) {
std::map<std::string, std::string> args;
for (int i = 1; i < argc; ++i) {
std::string key = argv[i];
if (i + 1 < argc && key.rfind("--", 0) == 0) {
args[key] = argv[++i];
}
}
return args;
}
// Funktion zum Parsen von Listen-Argumenten
std::vector<std::string> parseListArgument(int argc, char* argv[], const std::string& key) {
std::vector<std::string> values;
for (int i = 1; i < argc; ++i) {
if (argv[i] == key && i + 1 < argc) {
for (int j = i + 1; j < argc && std::string(argv[j]).rfind("--", 0) != 0; ++j) {
values.push_back(argv[j]);
}
}
}
return values;
}
// Funktion zum Senden der Anfrage
std::string sendRequest(const std::string& serverIp, int serverPort, const Json::Value& payload) {
Json::StreamWriterBuilder writer;
std::string payloadJson = Json::writeString(writer, payload);
// Winsock initialisieren
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
throw std::runtime_error("Failed to initialize Winsock.");
}
// Socket erstellen
SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == INVALID_SOCKET) {
WSACleanup();
throw std::runtime_error("Failed to create socket.");
}
// Server-Adresse konfigurieren
sockaddr_in serverAddr;
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(serverPort);
if (inet_pton(AF_INET, serverIp.c_str(), &serverAddr.sin_addr) <= 0) {
closesocket(sock);
WSACleanup();
throw std::runtime_error("Invalid server IP address.");
}
// Verbindung herstellen
if (connect(sock, (sockaddr*)&serverAddr, sizeof(serverAddr)) < 0) {
closesocket(sock);
WSACleanup();
throw std::runtime_error("Connection failed.");
}
// Daten senden
if (send(sock, payloadJson.c_str(), payloadJson.size(), 0) < 0) {
closesocket(sock);
WSACleanup();
throw std::runtime_error("Failed to send data.");
}
// Antwort empfangen
char buffer[4096];
int bytesRead;
std::ostringstream response;
do {
bytesRead = recv(sock, buffer, sizeof(buffer) - 1, 0);
if (bytesRead > 0) {
buffer[bytesRead] = '\0'; // Null-terminieren
response << buffer;
}
} while (bytesRead == sizeof(buffer) - 1);
// Socket schließen
closesocket(sock);
WSACleanup();
return response.str();
}
int main(int argc, char* argv[]) {
try {
auto args = parseArguments(argc, argv);
// Argumente auslesen
std::string serverIp = args["--server-ip"];
int serverPort = std::stoi(args["--server-port"]);
std::string token = args["--token"];
std::string name = args["--name"];
std::string email = args["--email"];
std::string password = args["--password"];
std::string language = args.count("--language") ? args["--language"] : "en";
std::string timezone = args.count("--timezone") ? args["--timezone"] : "Europe/Berlin";
auto roles = parseListArgument(argc, argv, "--roles");
auto groups = parseListArgument(argc, argv, "--groups");
bool usePublic = args.count("--usePublic");
bool activateFtp = args.count("--activateFtp");
std::string ftpPassword = args.count("--ftpPassword") ? args["--ftpPassword"] : "";
// JSON-Payload erstellen
Json::Value payload;
payload["command"] = "store_user";
payload["token"] = token;
payload["arguments"]["name"] = name;
payload["arguments"]["email"] = email;
payload["arguments"]["password"] = password;
payload["arguments"]["language"] = language;
payload["arguments"]["timezone"] = timezone;
for (const auto& role : roles) {
payload["arguments"]["roles"].append(role);
}
for (const auto& group : groups) {
payload["arguments"]["groups"].append(group);
}
payload["arguments"]["usePublic"] = usePublic;
payload["arguments"]["activateFtp"] = activateFtp;
payload["arguments"]["ftpPassword"] = ftpPassword;
std::cout << "📤 Sending store user request...\n";
// Anfrage senden und Antwort erhalten
std::string response = sendRequest(serverIp, serverPort, payload);
std::cout << "✔️ Response from server:\n" << response << "\n";
} catch (const std::exception& e) {
std::cerr << "❌ ERROR: " << e.what() << "\n";
return 1;
}
return 0;
}
```
--------------------------------------------------------------------------------
/agents/IoTAgent/Python/language.py:
--------------------------------------------------------------------------------
```python
# language.py
languages = {
"en": {
"configuration_loaded": "Configuration loaded from {config_path}.",
"error_loading_config": "Error loading configuration: {e}",
"welcome": "Connected to MQTT broker successfully.",
"chatbot_error_status": "Chatbot returned error status {status_code}.",
"start_uploading_file": "Starting upload for file: {file_path}.",
"error_sftp_upload": "Error uploading file {file_path}: {e}",
"file_archived": "File {file_path} archived as {archive_name}.",
"error_archiving_file": "Error archiving file {file_path}: {e}",
"file_size": "File {file_path} size: {file_size} bytes.",
"file_limit_reached": "File {file_path} reached size limit of {size_limit} bytes.",
"new_file_created": "New file created at {file_path}.",
"cannot_create_new_file": "Cannot create new file of type {file_type} for language {language}.",
"error_getting_suffixes": "Error getting suffixes: {e}",
"record_added": "Record added to {file_path}.",
"invalid_group": "Invalid group type: {groups}.",
"error_writing_file": "Error writing to file {file_path}: {e}",
"file_empty_or_corrupted": "File {file_path} is empty or corrupted.",
"language_sentence_generated": "Language: {language_full} | Sentence: {sentence}",
"no_translation_file_config": "No translation file configured for language {language}.",
"no_file_handler_found": "No file handler found for language {language}.",
"no_translation_file_in_config": "No translation file configured in config for language {language}.",
"empty_answer_field": "Warning: 'answer' field is empty in the chatbot response.",
"max_retries_reached": "Maximum retry attempts reached.",
"communication_error": "Communication error: {e} | Attempt {attempt} of {max_retries}.",
"waiting_before_retry": "Waiting {wait_seconds} seconds before retrying...",
"error_in_interpret_and_output": "Error in interpret_and_output: {e}",
"sending_request_to_chatbot": "Sending request to chatbot (Attempt {attempt}).",
"chatbot_response": "Chatbot response: {response}",
"unknown_language": "Unknown language: {language}.",
"no_sentence_generated": "No sentence generated for language {language_full}.",
"user_exit": "User initiated exit."
},
"de": {
"configuration_loaded": "Konfiguration geladen von {config_path}.",
"error_loading_config": "Fehler beim Laden der Konfiguration: {e}",
"welcome": "Erfolgreich mit dem MQTT-Broker verbunden.",
"chatbot_error_status": "Chatbot hat Fehlerstatus {status_code} zurückgegeben.",
"start_uploading_file": "Starte Upload für Datei: {file_path}.",
"error_sftp_upload": "Fehler beim Hochladen der Datei {file_path}: {e}",
"file_archived": "Datei {file_path} archiviert als {archive_name}.",
"error_archiving_file": "Fehler beim Archivieren der Datei {file_path}: {e}",
"file_size": "Datei {file_path} Größe: {file_size} Bytes.",
"file_limit_reached": "Datei {file_path} hat das Größenlimit von {size_limit} Bytes erreicht.",
"new_file_created": "Neue Datei erstellt unter {file_path}.",
"cannot_create_new_file": "Kann keine neue Datei vom Typ {file_type} für Sprache {language} erstellen.",
"error_getting_suffixes": "Fehler beim Abrufen der Suffixe: {e}",
"record_added": "Datensatz hinzugefügt zu {file_path}.",
"invalid_group": "Ungültiger Gruppentyp: {groups}.",
"error_writing_file": "Fehler beim Schreiben in die Datei {file_path}: {e}",
"file_empty_or_corrupted": "Datei {file_path} ist leer oder beschädigt.",
"language_sentence_generated": "Sprache: {language_full} | Satz: {sentence}",
"no_translation_file_config": "Keine Übersetzungsdatei für Sprache {language} konfiguriert.",
"no_file_handler_found": "Kein Dateihandler für Sprache {language} gefunden.",
"no_translation_file_in_config": "Keine Übersetzungsdatei in der Konfiguration für Sprache {language} konfiguriert.",
"empty_answer_field": "Warnung: 'answer'-Feld ist in der Chatbot-Antwort leer.",
"max_retries_reached": "Maximale Anzahl an Wiederholungsversuchen erreicht.",
"communication_error": "Kommunikationsfehler: {e} | Versuch {attempt} von {max_retries}.",
"waiting_before_retry": "Warte {wait_seconds} Sekunden bevor erneut versucht wird...",
"error_in_interpret_and_output": "Fehler in interpret_and_output: {e}",
"sending_request_to_chatbot": "Sende Anfrage an Chatbot (Versuch {attempt}).",
"chatbot_response": "Chatbot-Antwort: {response}",
"unknown_language": "Unbekannte Sprache: {language}.",
"no_sentence_generated": "Kein Satz für Sprache {language_full} generiert.",
"user_exit": "Benutzer hat die Anwendung beendet."
}
}
```
--------------------------------------------------------------------------------
/agents/ISMAgent/Python/language.py:
--------------------------------------------------------------------------------
```python
# language.py
languages = {
"en": {
"configuration_loaded": "Configuration loaded from {config_path}.",
"error_loading_config": "Error loading configuration: {e}",
"welcome": "Connected to MQTT broker successfully.",
"chatbot_error_status": "Chatbot returned error status {status_code}.",
"start_uploading_file": "Starting upload for file: {file_path}.",
"error_sftp_upload": "Error uploading file {file_path}: {e}",
"file_archived": "File {file_path} archived as {archive_name}.",
"error_archiving_file": "Error archiving file {file_path}: {e}",
"file_size": "File {file_path} size: {file_size} bytes.",
"file_limit_reached": "File {file_path} reached size limit of {size_limit} bytes.",
"new_file_created": "New file created at {file_path}.",
"cannot_create_new_file": "Cannot create new file of type {file_type} for language {language}.",
"error_getting_suffixes": "Error getting suffixes: {e}",
"record_added": "Record added to {file_path}.",
"invalid_group": "Invalid group type: {groups}.",
"error_writing_file": "Error writing to file {file_path}: {e}",
"file_empty_or_corrupted": "File {file_path} is empty or corrupted.",
"language_sentence_generated": "Language: {language_full} | Sentence: {sentence}",
"no_translation_file_config": "No translation file configured for language {language}.",
"no_file_handler_found": "No file handler found for language {language}.",
"no_translation_file_in_config": "No translation file configured in config for language {language}.",
"empty_answer_field": "Warning: 'answer' field is empty in the chatbot response.",
"max_retries_reached": "Maximum retry attempts reached.",
"communication_error": "Communication error: {e} | Attempt {attempt} of {max_retries}.",
"waiting_before_retry": "Waiting {wait_seconds} seconds before retrying...",
"error_in_interpret_and_output": "Error in interpret_and_output: {e}",
"sending_request_to_chatbot": "Sending request to chatbot (Attempt {attempt}).",
"chatbot_response": "Chatbot response: {response}",
"unknown_language": "Unknown language: {language}.",
"no_sentence_generated": "No sentence generated for language {language_full}.",
"user_exit": "User initiated exit."
},
"de": {
"configuration_loaded": "Konfiguration geladen von {config_path}.",
"error_loading_config": "Fehler beim Laden der Konfiguration: {e}",
"welcome": "Erfolgreich mit dem MQTT-Broker verbunden.",
"chatbot_error_status": "Chatbot hat Fehlerstatus {status_code} zurückgegeben.",
"start_uploading_file": "Starte Upload für Datei: {file_path}.",
"error_sftp_upload": "Fehler beim Hochladen der Datei {file_path}: {e}",
"file_archived": "Datei {file_path} archiviert als {archive_name}.",
"error_archiving_file": "Fehler beim Archivieren der Datei {file_path}: {e}",
"file_size": "Datei {file_path} Größe: {file_size} Bytes.",
"file_limit_reached": "Datei {file_path} hat das Größenlimit von {size_limit} Bytes erreicht.",
"new_file_created": "Neue Datei erstellt unter {file_path}.",
"cannot_create_new_file": "Kann keine neue Datei vom Typ {file_type} für Sprache {language} erstellen.",
"error_getting_suffixes": "Fehler beim Abrufen der Suffixe: {e}",
"record_added": "Datensatz hinzugefügt zu {file_path}.",
"invalid_group": "Ungültiger Gruppentyp: {groups}.",
"error_writing_file": "Fehler beim Schreiben in die Datei {file_path}: {e}",
"file_empty_or_corrupted": "Datei {file_path} ist leer oder beschädigt.",
"language_sentence_generated": "Sprache: {language_full} | Satz: {sentence}",
"no_translation_file_config": "Keine Übersetzungsdatei für Sprache {language} konfiguriert.",
"no_file_handler_found": "Kein Dateihandler für Sprache {language} gefunden.",
"no_translation_file_in_config": "Keine Übersetzungsdatei in der Konfiguration für Sprache {language} konfiguriert.",
"empty_answer_field": "Warnung: 'answer'-Feld ist in der Chatbot-Antwort leer.",
"max_retries_reached": "Maximale Anzahl an Wiederholungsversuchen erreicht.",
"communication_error": "Kommunikationsfehler: {e} | Versuch {attempt} von {max_retries}.",
"waiting_before_retry": "Warte {wait_seconds} Sekunden bevor erneut versucht wird...",
"error_in_interpret_and_output": "Fehler in interpret_and_output: {e}",
"sending_request_to_chatbot": "Sende Anfrage an Chatbot (Versuch {attempt}).",
"chatbot_response": "Chatbot-Antwort: {response}",
"unknown_language": "Unbekannte Sprache: {language}.",
"no_sentence_generated": "Kein Satz für Sprache {language_full} generiert.",
"user_exit": "Benutzer hat die Anwendung beendet."
}
}
```
--------------------------------------------------------------------------------
/clients/Java/3.0 mcp_create_source/MCPCreateSourceClient.java:
--------------------------------------------------------------------------------
```java
import org.json.JSONArray;
import org.json.JSONObject;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
public class MCPCreateSourceClient {
public static void main(String[] args) {
// Entspricht dem Minimalcheck (8 Parameter) wie im C#-Code.
if (args.length < 8) {
printUsage();
return;
}
String serverIp = getArgument(args, "--server-ip");
String portStr = getArgument(args, "--server-port");
String token = getArgument(args, "--token");
String name = getArgument(args, "--name");
String content = getArgument(args, "--content");
List<String> groups = getArgumentList(args, "--groups");
// Falls wichtige Argumente fehlen, direkt Usage anzeigen
if (serverIp == null || portStr == null || token == null
|| name == null || content == null) {
printUsage();
return;
}
int serverPort = Integer.parseInt(portStr);
System.out.println("📤 Sending request to create a new source...");
// JSON-Payload erstellen
JSONObject payload = new JSONObject();
payload.put("command", "create_source");
payload.put("token", token);
// "arguments" Objekt
JSONObject arguments = new JSONObject();
arguments.put("name", name);
arguments.put("content", content);
// "groups" als JSONArray hinzufügen
JSONArray groupsJsonArray = new JSONArray(groups);
arguments.put("groups", groupsJsonArray);
payload.put("arguments", arguments);
// Request an den MCP-Server senden
String response = sendRequest(serverIp, serverPort, payload);
System.out.println("✔️ Response from server:");
System.out.println(response);
}
/**
* Gibt einen einzelnen Argumentwert für das gegebene Schlüsselwort zurück,
* oder null, wenn keiner gefunden wurde.
*/
private static String getArgument(String[] args, String key) {
for (int i = 0; i < args.length - 1; i++) {
if (args[i].equals(key)) {
return args[i + 1];
}
}
return null;
}
/**
* Sucht im args-Array nach dem Schlüssel 'key' und liest dann solange
* weiter, bis das nächste Argument wieder mit "--" beginnt (oder das Array endet).
* So können mehrere Gruppenwerte nacheinander gelesen werden.
*/
private static List<String> getArgumentList(String[] args, String key) {
List<String> values = new ArrayList<>();
for (int i = 0; i < args.length; i++) {
if (args[i].equals(key)) {
// Ab hier die folgenden Einträge sammeln, bis "--" oder Ende
for (int j = i + 1; j < args.length; j++) {
if (args[j].startsWith("--")) {
break;
}
values.add(args[j]);
}
break; // Suche beenden, sobald wir die Liste gefunden haben
}
}
return values;
}
/**
* Baut eine Socket-Verbindung zum Server auf, sendet das JSON-Payload
* und empfängt die Antwort.
*/
private static String sendRequest(String serverIp, int serverPort, JSONObject payload) {
String payloadJson = payload.toString();
try (Socket client = new Socket(serverIp, serverPort)) {
// Daten senden
OutputStream out = client.getOutputStream();
byte[] data = payloadJson.getBytes(StandardCharsets.UTF_8);
out.write(data);
out.flush();
// Antwort empfangen
InputStream in = client.getInputStream();
byte[] buffer = new byte[4096];
StringBuilder responseBuilder = new StringBuilder();
int bytesRead;
do {
bytesRead = in.read(buffer);
if (bytesRead > 0) {
responseBuilder.append(new String(buffer, 0, bytesRead, StandardCharsets.UTF_8));
}
} while (bytesRead == buffer.length);
return responseBuilder.toString();
} catch (IOException e) {
return "Error: " + e.getMessage();
}
}
private static void printUsage() {
System.out.println("Usage:");
System.out.println(" --server-ip <IP> --server-port <PORT> --token <TOKEN> "
+ "--name <NAME> --content <CONTENT> [--groups <GROUP1 GROUP2 ...>]");
System.out.println();
System.out.println("Example:");
System.out.println(" java -cp .;json-20241224.jar MCPCreateSourceClient "
+ "--server-ip 127.0.0.1 --server-port 1234 --token MyToken "
+ "--name \"Test Source\" --content \"This is some content\" "
+ "--groups dev hr admin");
}
}
```
--------------------------------------------------------------------------------
/WORKLOG.md:
--------------------------------------------------------------------------------
```markdown
# PrivateGPT MCP Server Development Log
## ⚠️ Warning: User Management Implementation
**HANDLE WITH CARE**: The user management endpoints have significant impact and can potentially delete all users if not handled properly. While the API functionality has been tested successfully, implementation in the pgpt-mcp-server is pending due to these security considerations.
The following user management endpoints require careful implementation:
### Create User (POST /api/v1/users)
Required functionality:
- Create new user with name, email, and password
- Set optional language and timezone
- Configure public access and group assignments
- Assign user roles
- Set up FTP access if needed
- Handle all required fields:
```json
{
"name": "User Name",
"email": "[email protected]",
"password": "UserPassword123",
"language": "en",
"timezone": "UTC",
"usePublic": true,
"groups": ["Group A"],
"roles": ["Sources"],
"activateFtp": true,
"ftpPassword": "FTPPassword!"
}
```
### Edit User (PATCH /api/v1/users)
Required functionality:
- Update user details by email
- Modify name, language, and group assignments
- Handle partial updates
- Fields that can be updated:
```json
{
"email": "[email protected]",
"name": "Updated Name",
"language": "en",
"groups": ["Updated Group"]
}
```
### Delete User (DELETE /api/v1/users)
⚠️ **Critical Operation**
Required functionality:
- Remove user by email
- Clean up associated data
- Handle dependencies:
```json
{
"email": "[email protected]"
}
```
## Implementation Status
### Core Server Structure
- ✅ Basic MCP server setup with stdio transport
- ✅ Error handling and graceful shutdown
- ✅ Type-safe request handling
- ✅ Input validation for all tools
### API Integration
- ✅ Authentication with Bearer tokens
- ✅ Automatic token refresh
- ✅ Error mapping to MCP error codes
- ✅ JSON response formatting
### Tools Implementation
1. Chat Tool
- ✅ Chat creation with knowledge base selection
- ✅ Support for public and document knowledge bases
- ✅ Group-based access control
- ✅ Language support
- ✅ Chat continuation support
2. Source Management
- ✅ Source creation with markdown formatting
- ✅ Group assignment for private sources
- ✅ Source listing by group
- ✅ Source details retrieval
- ✅ Source deletion
- ✅ Source editing
3. Group Management
- ✅ List personal and assignable groups
- ✅ Group-based visibility control
- ✅ Personal group handling
- ✅ Group creation
- ✅ Group deletion
## API Behavior Notes
### Authentication
- Uses Bearer token authentication via `/api/v1/login`
- Token required for all authenticated endpoints
- Token invalidation via `/api/v1/logout`
### Group Management
- GET `/api/v1/groups` returns personalGroups and assignableGroups arrays
- Personal group appears in both arrays
- Groups control access to sources and knowledge base
- Full CRUD operations implemented and tested
### Source Management
- Sources can be public or private
- Private sources require group assignment
- Sources are vectorized asynchronously
- Source states: creation → vectorized
- Source operations:
- POST `/api/v1/sources` for creation
- DELETE `/api/v1/sources/{sourceId}` for removal
- PATCH `/api/v1/sources/{sourceId}` for editing
- Can list sources by group
- Can verify source state and visibility
- All operations tested and verified
### Chat System
- Two knowledge base types:
- Public (usePublic: true)
- Document (specific groups)
- Chat operations:
- Initial creation: POST `/api/v1/chats`
- Continuation: PATCH `/api/v1/chats/{chatId}`
- Details: GET `/api/v1/chats/{chatId}`
- Chat features:
- Preserves complete message history
- Context-aware responses
- Group-based access control
- Language support
## Implementation Details
### Type Safety
- Comprehensive TypeScript interfaces for all API interactions
- Runtime validation for all tool inputs
- Error type mapping between API and MCP
### Error Handling
- API errors mapped to appropriate MCP error codes
- Detailed error messages preserved
- Authentication errors handled gracefully
### Resource Management
- No direct resource exposure currently
- All data access through tools
- Future potential for direct resource access
## Future Improvements
1. Performance Optimizations:
- Add caching layer
- Optimize API requests
- Improve response times
2. Monitoring and Observability:
- Add comprehensive logging
- Add metrics collection
- Add performance tracking
3. Documentation:
- Add API reference documentation
- Add deployment guides
- Add troubleshooting guides
4. Security Enhancements:
- Add rate limiting
- Implement request validation
- Add security headers
- Enhance token management
- Add user session management
## Testing Notes
- ✅ All major API endpoints tested
- ✅ Group-based access control verified
- ✅ Chat system behavior documented
- ✅ Source visibility rules confirmed
- ✅ Error handling validated
- ✅ Source CRUD operations verified
- ✅ Group CRUD operations verified
- ✅ User management API functionality tested
```
--------------------------------------------------------------------------------
/clients/C++/1.0 mcp_login/MCPLoginClient.cpp:
--------------------------------------------------------------------------------
```cpp
#include <iostream>
#include <string>
#include <map>
#include <cstring>
#include <cstdlib>
#include <sstream>
#include <stdexcept>
#include <json/json.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#pragma comment(lib, "ws2_32.lib")
#pragma comment(lib, "libssl.lib")
#pragma comment(lib, "libcrypto.lib")
#else
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#endif
// Function to parse command-line arguments
std::map<std::string, std::string> parseArguments(int argc, char* argv[]) {
std::map<std::string, std::string> args;
for (int i = 1; i < argc; i++) {
std::string key = argv[i];
if (i + 1 < argc) {
args[key] = argv[++i];
}
}
return args;
}
void init_openssl() {
SSL_load_error_strings();
OpenSSL_add_ssl_algorithms();
}
void cleanup_openssl() {
EVP_cleanup();
}
SSL_CTX* create_context() {
const SSL_METHOD* method;
SSL_CTX* ctx;
method = TLS_client_method();
ctx = SSL_CTX_new(method);
if (!ctx) {
perror("Unable to create SSL context");
ERR_print_errors_fp(stderr);
exit(EXIT_FAILURE);
}
return ctx;
}
std::string sendRequest(const std::string& serverIp, int serverPort, const Json::Value& payload) {
init_openssl();
SSL_CTX* ctx = create_context();
#ifdef _WIN32
WSADATA wsaData;
WSAStartup(MAKEWORD(2,2), &wsaData);
#endif
int sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
SSL_CTX_free(ctx);
#ifdef _WIN32
WSACleanup();
#endif
throw std::runtime_error("Failed to create socket");
}
struct sockaddr_in serverAddr;
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(serverPort);
if (inet_pton(AF_INET, serverIp.c_str(), &serverAddr.sin_addr) <= 0) {
#ifdef _WIN32
closesocket(sock);
WSACleanup();
#else
close(sock);
#endif
SSL_CTX_free(ctx);
throw std::runtime_error("Invalid server IP address");
}
if (connect(sock, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) < 0) {
#ifdef _WIN32
closesocket(sock);
WSACleanup();
#else
close(sock);
#endif
SSL_CTX_free(ctx);
throw std::runtime_error("Connection failed");
}
SSL* ssl = SSL_new(ctx);
SSL_set_fd(ssl, sock);
if (SSL_connect(ssl) <= 0) {
ERR_print_errors_fp(stderr);
#ifdef _WIN32
closesocket(sock);
WSACleanup();
#else
close(sock);
#endif
SSL_free(ssl);
SSL_CTX_free(ctx);
throw std::runtime_error("Failed to create SSL connection");
}
// Serialize the JSON payload to a string
Json::StreamWriterBuilder writer;
std::string payloadJson = Json::writeString(writer, payload);
// Send the payload
if (SSL_write(ssl, payloadJson.c_str(), payloadJson.size()) <= 0) {
#ifdef _WIN32
closesocket(sock);
WSACleanup();
#else
close(sock);
#endif
SSL_free(ssl);
SSL_CTX_free(ctx);
throw std::runtime_error("Failed to send data");
}
// Receive the response
char buffer[4096];
int bytesRead = SSL_read(ssl, buffer, sizeof(buffer) - 1);
if (bytesRead < 0) {
#ifdef _WIN32
closesocket(sock);
WSACleanup();
#else
close(sock);
#endif
SSL_free(ssl);
SSL_CTX_free(ctx);
throw std::runtime_error("Failed to receive data");
}
buffer[bytesRead] = '\0'; // Null-terminate the received data
SSL_free(ssl);
#ifdef _WIN32
closesocket(sock);
WSACleanup();
#else
close(sock);
#endif
SSL_CTX_free(ctx);
cleanup_openssl();
return std::string(buffer);
}
int main(int argc, char* argv[]) {
try {
auto args = parseArguments(argc, argv);
// Extract required parameters
std::string serverIp = args["--server-ip"];
int serverPort = std::stoi(args["--server-port"]);
std::string email = args["--email"];
std::string password = args["--password"];
if (serverIp.empty() || serverPort == 0 || email.empty() || password.empty()) {
std::cerr << "❌ ERROR: Missing required parameters.\n";
return 1;
}
std::cout << "🔐 Logging in...\n";
// Build the payload
Json::Value payload;
payload["command"] = "login";
payload["arguments"]["email"] = email;
payload["arguments"]["password"] = password;
// Send request and get response
std::string responseJson = sendRequest(serverIp, serverPort, payload);
// Parse and print the server response
Json::CharReaderBuilder reader;
Json::Value response;
std::istringstream responseStream(responseJson);
std::string errs;
if (!Json::parseFromStream(reader, responseStream, &response, &errs)) {
throw std::runtime_error("Failed to parse server response: " + errs);
}
std::cout << "✅ Server Response:\n" << response.toStyledString();
} catch (const std::exception& e) {
std::cerr << "❌ ERROR: " << e.what() << '\n';
return 1;
}
return 0;
}
```
--------------------------------------------------------------------------------
/src/logger.js:
--------------------------------------------------------------------------------
```javascript
// logger.js
import winston from 'winston';
import chalk from 'chalk';
import stripAnsi from 'strip-ansi';
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
// ESM-Äquivalent von __dirname
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// Bestimmen Sie den Pfad zur Log-Datei relativ zu `logger.js`
const LOG_FILE_PATH = path.join(__dirname, '../logs/server.log'); // Passen Sie den Pfad nach Bedarf an
// Hilfsfunktionen für Symbole und Farben
function getLevelSymbol(level) {
const symbols = {
info: 'ℹ️',
warn: '⚠️',
error: '❌',
debug: '🐞',
};
return symbols[level] || '';
}
function chalkForLevel(level) {
const levels = {
info: chalk.blue,
warn: chalk.yellow,
error: chalk.red,
debug: chalk.green,
};
return levels[level] || chalk.white;
}
// Variable zur Steuerung der Dateiausgabe
let allowWrittenLogfile = false;
// Initialisieren der Transports mit nur der Konsolenausgabe
const transports = [
new winston.transports.Console({
format: winston.format.combine(
winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }),
winston.format.printf(({ timestamp, level, message }) => {
const symbol = getLevelSymbol(level);
const coloredMessage = `${chalkForLevel(level)(symbol)} ${message}`;
return `${timestamp} | ${coloredMessage}`;
})
),
}),
];
// Erstellen des Winston-Loggers
const logger = winston.createLogger({
level: 'info',
transports: transports,
});
/**
* Funktion zum Hinzufügen des File-Transports
*/
function addFileTransport() {
const logDir = path.dirname(LOG_FILE_PATH);
if (!fs.existsSync(logDir)) {
fs.mkdirSync(logDir, { recursive: true });
}
const fileTransport = new winston.transports.File({
filename: LOG_FILE_PATH,
level: 'info', // Stellen Sie sicher, dass der Level ausreichend niedrig ist
maxsize: 10485760, // 10 MB pro Datei
maxFiles: 5, // Maximal 5 Dateien
format: winston.format.combine(
winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }),
winston.format.printf(({ timestamp, level, message }) => {
const symbol = getLevelSymbol(level);
const plainMessage = stripAnsi(`${symbol} ${message}`); // ANSI-Codes entfernen
return `${timestamp} | ${plainMessage}`;
})
),
});
// Fehler-Handler hinzufügen
fileTransport.on('error', (error) => {
console.error(chalk.red('File-Transport Fehler:'), error);
});
// Prüfen, ob der Transport bereits hinzugefügt wurde, um Duplikate zu vermeiden
if (!logger.transports.some(t => t instanceof winston.transports.File)) {
logger.add(fileTransport);
}
}
/**
* Funktion zum Entfernen des File-Transports
*/
function removeFileTransport() {
const fileTransport = logger.transports.find(
(t) => t instanceof winston.transports.File
);
if (fileTransport) {
logger.remove(fileTransport);
}
}
/**
* Funktion zum Setzen von allowWrittenLogfile
* @param {boolean} value - true, um Dateilogs zu erlauben; false, um sie zu deaktivieren
*/
function setAllowWrittenLogfile(value) {
allowWrittenLogfile = value;
if (allowWrittenLogfile) {
addFileTransport();
logEvent('system', 'wrlog', 'File logs activated.', 'File logs are now activated.', 'info');
// Überprüfen, ob der File-Transport hinzugefügt wurde
const fileTransport = logger.transports.find(t => t instanceof winston.transports.File);
if (fileTransport) {
// console.log(chalk.green('File-Transport erfolgreich hinzugefügt.'));
} else {
console.log(chalk.red('Error: File transport could not be added.'));
}
} else {
removeFileTransport();
logEvent('system', 'wrlog', 'File logs deactivated.', 'File logs are now deactivated.', 'info');
}
}
/**
* Zentrale Logging-Funktion
* @param {string} clientIP - IP-Adresse des Clients
* @param {number|string} clientPort - Port des Clients
* @param {string} functionName - Name der aufgerufenen Funktion
* @param {string|object} status - Status der Rückmeldung
* @param {string} level - Log-Level ('info', 'warn', 'error', 'debug')
*/
function logEvent(clientIP, clientPort, functionName, status, level = 'info') {
// Kürzen und formatieren der Felder
const ip = String(clientIP || 'N/A').padEnd(23).substring(0, 23); // Mindestens 8 Zeichen für die IP
const port = String(clientPort || 'N/A').padEnd(5).substring(0, 5); // 5 Zeichen für den Port
const func = String(functionName || 'N/A').padEnd(26).substring(0, 26); // 20 Zeichen für den Funktionsnamen
const stat = String(status || '').padEnd(120).substring(0, 120); // 100 Zeichen für den Status
// Formatierte Logzeile
const logLine = `${ip}:${port} | ${func} | ${stat}`;
// Log-Ausgabe basierend auf dem Level
logger.log({ level, message: logLine });
}
export { logger, logEvent, setAllowWrittenLogfile, LOG_FILE_PATH };
```
--------------------------------------------------------------------------------
/clients/C++/5.1 mcp_edit_user/MCPEditUserClient.cpp:
--------------------------------------------------------------------------------
```cpp
#include <iostream>
#include <string>
#include <map>
#include <vector>
#include <sstream>
#include <stdexcept>
#include <json/json.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#pragma comment(lib, "ws2_32.lib") // Verlinkung mit der Winsock-Bibliothek
// Funktion zum Parsen von Argumenten
std::map<std::string, std::string> parseArguments(int argc, char* argv[]) {
std::map<std::string, std::string> args;
for (int i = 1; i < argc; ++i) {
std::string key = argv[i];
if (i + 1 < argc && key.rfind("--", 0) == 0) {
args[key] = argv[++i];
}
}
return args;
}
// Funktion zum Parsen von Listen-Argumenten
std::vector<std::string> parseListArgument(int argc, char* argv[], const std::string& key) {
std::vector<std::string> values;
for (int i = 1; i < argc; ++i) {
if (argv[i] == key && i + 1 < argc) {
for (int j = i + 1; j < argc && std::string(argv[j]).rfind("--", 0) != 0; ++j) {
values.push_back(argv[j]);
}
}
}
return values;
}
// Funktion zum Senden der Anfrage
std::string sendRequest(const std::string& serverIp, int serverPort, const Json::Value& payload) {
Json::StreamWriterBuilder writer;
std::string payloadJson = Json::writeString(writer, payload);
// Winsock initialisieren
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
throw std::runtime_error("Failed to initialize Winsock.");
}
// Socket erstellen
SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == INVALID_SOCKET) {
WSACleanup();
throw std::runtime_error("Failed to create socket.");
}
// Server-Adresse konfigurieren
sockaddr_in serverAddr;
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(serverPort);
if (inet_pton(AF_INET, serverIp.c_str(), &serverAddr.sin_addr) <= 0) {
closesocket(sock);
WSACleanup();
throw std::runtime_error("Invalid server IP address.");
}
// Verbindung herstellen
if (connect(sock, (sockaddr*)&serverAddr, sizeof(serverAddr)) < 0) {
closesocket(sock);
WSACleanup();
throw std::runtime_error("Connection failed.");
}
// Daten senden
if (send(sock, payloadJson.c_str(), payloadJson.size(), 0) < 0) {
closesocket(sock);
WSACleanup();
throw std::runtime_error("Failed to send data.");
}
// Antwort empfangen
char buffer[4096];
int bytesRead;
std::ostringstream response;
do {
bytesRead = recv(sock, buffer, sizeof(buffer) - 1, 0);
if (bytesRead > 0) {
buffer[bytesRead] = '\0'; // Null-terminieren
response << buffer;
}
} while (bytesRead == sizeof(buffer) - 1);
// Socket schließen
closesocket(sock);
WSACleanup();
return response.str();
}
int main(int argc, char* argv[]) {
try {
auto args = parseArguments(argc, argv);
// Pflichtargumente überprüfen
if (args["--server-ip"].empty() || args["--server-port"].empty() || args["--token"].empty() || args["--email"].empty() || args["--name"].empty()) {
std::cerr << "Usage: --server-ip <IP> --server-port <PORT> --token <TOKEN> --email <EMAIL> --name <NAME> [optional parameters]\n";
return 1;
}
// Argumente auslesen
std::string serverIp = args["--server-ip"];
int serverPort = std::stoi(args["--server-port"]);
std::string token = args["--token"];
std::string email = args["--email"];
std::string name = args["--name"];
std::string language = args.count("--language") ? args["--language"] : "en";
std::string timezone = args.count("--timezone") ? args["--timezone"] : "UTC";
std::string password = args["--password"];
bool publicUpload = args.count("--publicUpload") > 0;
auto groups = parseListArgument(argc, argv, "--groups");
auto roles = parseListArgument(argc, argv, "--roles");
bool activateFtp = args.count("--activateFtp") > 0;
std::string ftpPassword = args["--ftpPassword"];
// JSON-Payload erstellen
Json::Value payload;
payload["command"] = "edit_user";
payload["token"] = token;
payload["arguments"]["email"] = email;
payload["arguments"]["name"] = name;
payload["arguments"]["language"] = language;
payload["arguments"]["timezone"] = timezone;
if (!password.empty()) payload["arguments"]["password"] = password;
payload["arguments"]["publicUpload"] = publicUpload;
for (const auto& group : groups) {
payload["arguments"]["groups"].append(group);
}
for (const auto& role : roles) {
payload["arguments"]["roles"].append(role);
}
payload["arguments"]["activateFtp"] = activateFtp;
if (!ftpPassword.empty()) payload["arguments"]["ftpPassword"] = ftpPassword;
std::cout << "📤 Sending edit user request...\n";
// Anfrage senden und Antwort erhalten
std::string response = sendRequest(serverIp, serverPort, payload);
std::cout << "✔️ Response from server:\n" << response << "\n";
} catch (const std::exception& e) {
std::cerr << "❌ ERROR: " << e.what() << "\n";
return 1;
}
return 0;
}
```
--------------------------------------------------------------------------------
/clients/JavaScript/3.3 mcp_edit_source/MCPEditSourceClient.js:
--------------------------------------------------------------------------------
```javascript
const net = require('net');
const readline = require('readline');
const { argv, exit } = require('process');
// Funktion zum Parsen der Kommandozeilenargumente
function parseArguments(args) {
const parsedArgs = {};
for (let i = 2; i < args.length; i++) {
switch (args[i]) {
case '--server-ip':
parsedArgs.serverIp = args[++i];
break;
case '--server-port':
parsedArgs.serverPort = parseInt(args[++i], 10);
break;
case '--token':
parsedArgs.token = args[++i];
break;
case '--source-id':
parsedArgs.sourceId = args[++i];
break;
case '--title':
parsedArgs.title = args[++i];
break;
case '--content':
parsedArgs.content = args[++i];
break;
case '--groups':
// Sammle alle Gruppenargumente bis zum nächsten Flag oder Ende
parsedArgs.groups = [];
while (i + 1 < args.length && !args[i + 1].startsWith('--')) {
parsedArgs.groups.push(args[++i]);
}
break;
default:
console.warn(`⚠️ Unbekanntes Argument: ${args[i]}`);
}
}
return parsedArgs;
}
// Funktion zum interaktiven Abfragen eines Parameters (optional)
function askQuestion(query) {
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
terminal: true
});
return new Promise((resolve) => {
rl.question(query, (answer) => {
rl.close();
resolve(answer);
});
});
}
// Funktion zum Senden einer Edit-Source-Anfrage über eine TCP-Verbindung
function sendEditSourceRequest(serverIp, serverPort, payload) {
return new Promise((resolve, reject) => {
const client = new net.Socket();
let responseData = '';
client.connect(serverPort, serverIp, () => {
console.log(`🔗 Verbindung zum Server (${serverIp}:${serverPort}) hergestellt.`);
const payloadString = JSON.stringify(payload);
console.log(`📤 Sende Payload: ${payloadString}`);
client.write(payloadString);
});
client.on('data', (data) => {
console.log(`📥 Empfangene Daten: ${data}`);
responseData += data.toString();
try {
const parsedData = JSON.parse(responseData);
console.log('✅ JSON-Antwort erfolgreich geparst.');
resolve(parsedData);
client.destroy(); // Verbindung schließen
} catch (err) {
console.warn('⚠️ Antwort noch nicht vollständig oder ungültiges JSON. Weitere Daten werden erwartet.');
// Antwort noch nicht vollständig, weiter empfangen
}
});
client.on('close', () => {
console.log('🔒 Verbindung zum Server geschlossen.');
});
client.on('error', (err) => {
console.error('❌ Verbindungsfehler:', err.message);
reject(err);
});
});
}
// Hauptfunktion
async function main() {
const args = argv;
const parsedArgs = parseArguments(args);
let { serverIp, serverPort, token, sourceId, title, content, groups } = parsedArgs;
// Überprüfen, ob alle erforderlichen Parameter vorhanden sind, sonst interaktiv abfragen
if (!serverIp) {
serverIp = await askQuestion('🔗 Bitte gib die Server-IP ein: ');
}
if (!serverPort) {
const portInput = await askQuestion('🔗 Bitte gib den Server-Port ein: ');
serverPort = parseInt(portInput, 10);
}
if (!token) {
token = await askQuestion('🔒 Bitte gib dein Authentifizierungstoken ein: ');
}
if (!sourceId) {
sourceId = await askQuestion('📁 Bitte gib die Source-ID ein: ');
}
// Überprüfen, ob mindestens eines der optionalen Parameter vorhanden ist
if (title === undefined && content === undefined && (groups === undefined || groups.length === 0)) {
console.warn('⚠️ Keine Änderungsparameter angegeben. Es werden mindestens eines der folgenden benötigt: --title, --content, --groups.');
exit(1);
}
// Optional: Abfrage fehlender optionaler Parameter, wenn entsprechende Flags gesetzt sind
// Hier gehen wir davon aus, dass --title, --content und --groups bereits korrekt geparst wurden
// und entweder definiert sind oder nicht angegeben wurden.
// Entferne unerwünschte Schlüssel mit undefined oder null Werten
const filteredArguments = {};
if (sourceId) filteredArguments.sourceId = sourceId;
if (title) filteredArguments.title = title;
if (content) filteredArguments.content = content;
if (groups && groups.length > 0) filteredArguments.groups = groups;
const payload = {
command: "edit_source",
token: token,
arguments: filteredArguments
};
try {
console.log('🛠️ Sende Edit-Source-Anfrage...');
const response = await sendEditSourceRequest(serverIp, serverPort, payload);
console.log('✅ Server Response:');
console.log(JSON.stringify(response, null, 2));
} catch (err) {
console.error('❌ ERROR:', err.message);
}
}
main();
```
--------------------------------------------------------------------------------
/clients/JavaScript/4.1 mcp_store_group/MCPStoreGroupClient.js:
--------------------------------------------------------------------------------
```javascript
const net = require('net');
const readline = require('readline');
const { argv, exit } = require('process');
/**
* Funktion zum Parsen der Kommandozeilenargumente
* @param {string[]} args - Array von Kommandozeilenargumenten
* @returns {Object} - Objekt mit geparsten Argumenten
*/
function parseArguments(args) {
const parsedArgs = {};
for (let i = 2; i < args.length; i++) {
switch (args[i]) {
case '--server-ip':
parsedArgs.serverIp = args[++i];
break;
case '--server-port':
parsedArgs.serverPort = parseInt(args[++i], 10);
break;
case '--group-name':
parsedArgs.groupName = args[++i];
break;
case '--token':
parsedArgs.token = args[++i];
break;
case '--description':
parsedArgs.description = args[++i];
break;
default:
console.warn(`⚠️ Unbekanntes Argument: ${args[i]}`);
}
}
return parsedArgs;
}
/**
* Funktion zum interaktiven Abfragen eines Parameters (optional)
* @param {string} query - Frage an den Benutzer
* @returns {Promise<string>} - Antwort des Benutzers
*/
function askQuestion(query) {
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
terminal: true
});
return new Promise((resolve) => {
rl.question(query, (answer) => {
rl.close();
resolve(answer);
});
});
}
/**
* Sendet eine Anfrage an den MCP-Server, um eine neue Gruppe zu speichern.
*
* @param {string} serverIp - IP-Adresse des MCP-Servers
* @param {number} serverPort - Portnummer des MCP-Servers
* @param {string} groupName - Name der zu speichernden Gruppe
* @param {string} token - Authentifizierungstoken
* @param {string} description - Beschreibung der Gruppe (optional)
* @returns {Promise<Object>} - Antwort vom Server
*/
function sendStoreGroupRequest(serverIp, serverPort, groupName, token, description) {
return new Promise((resolve, reject) => {
const client = new net.Socket();
const payload = {
command: "store_group",
token: token,
arguments: {
groupName: groupName,
description: description
}
};
const payloadString = JSON.stringify(payload);
// Timeout setzen (optional)
const TIMEOUT_DURATION = 10000; // 10 Sekunden
const timeout = setTimeout(() => {
client.destroy(); // Verbindung zerstören
reject(new Error('Verbindungs-Timeout: Der Server hat nicht rechtzeitig geantwortet.'));
}, TIMEOUT_DURATION);
client.connect(serverPort, serverIp, () => {
console.log(`🔗 Verbindung zum Server (${serverIp}:${serverPort}) hergestellt.`);
console.log(`📤 Sende Payload: ${payloadString}`);
client.write(payloadString);
});
let responseData = '';
client.on('data', (data) => {
console.log(`📥 Empfangene Daten: ${data}`);
responseData += data.toString();
try {
const parsedData = JSON.parse(responseData);
console.log('✅ JSON-Antwort erfolgreich geparst.');
clearTimeout(timeout);
resolve(parsedData);
client.destroy(); // Verbindung schließen
} catch (err) {
console.warn('⚠️ Antwort noch nicht vollständig oder ungültiges JSON. Weitere Daten werden erwartet.');
// Weiter empfangen
}
});
client.on('close', () => {
console.log('🔒 Verbindung zum Server geschlossen.');
clearTimeout(timeout);
});
client.on('error', (err) => {
console.error('❌ Verbindungsfehler:', err.message);
clearTimeout(timeout);
reject(err);
});
});
}
// Hauptfunktion
async function main() {
const args = argv;
const parsedArgs = parseArguments(args);
let { serverIp, serverPort, groupName, token, description } = parsedArgs;
// Überprüfen, ob alle erforderlichen Parameter vorhanden sind, sonst interaktiv abfragen
if (!serverIp) {
serverIp = await askQuestion('🔗 Bitte gib die Server-IP ein: ');
}
if (!serverPort) {
const portInput = await askQuestion('🔗 Bitte gib den Server-Port ein: ');
serverPort = parseInt(portInput, 10);
}
if (!groupName) {
groupName = await askQuestion('📛 Bitte gib den Gruppennamen ein: ');
}
if (!token) {
token = await askQuestion('🔒 Bitte gib dein Authentifizierungstoken ein: ');
}
// Beschreibung ist optional, kein Abfrage notwendig
const payload = {
command: "store_group",
token: token,
arguments: {
groupName: groupName,
description: description || ""
}
};
try {
console.log('🗃️ Sende Store-Group-Anfrage...');
const response = await sendStoreGroupRequest(serverIp, serverPort, groupName, token, description);
console.log('✔️ Antwort vom Server:', JSON.stringify(response, null, 2));
} catch (err) {
console.error('❌ Fehler:', err.message);
}
}
main();
```
--------------------------------------------------------------------------------
/clients/JavaScript/5.1 mcp_edit_user/MCPEditUserClient.js:
--------------------------------------------------------------------------------
```javascript
const net = require('net');
const readline = require('readline');
const { argv } = require('process');
/**
* Funktion zum Parsen der Kommandozeilenargumente
* @param {string[]} args - Array von Kommandozeilenargumenten
* @returns {Object} - Objekt mit geparsten Argumenten
*/
function parseArguments(args) {
const parsedArgs = {};
for (let i = 2; i < args.length; i++) {
switch (args[i]) {
case '--server-ip':
parsedArgs.serverIp = args[++i];
break;
case '--server-port':
parsedArgs.serverPort = parseInt(args[++i], 10);
break;
case '--token':
parsedArgs.token = args[++i];
break;
case '--name':
parsedArgs.name = args[++i];
break;
case '--email':
parsedArgs.email = args[++i];
break;
case '--password':
parsedArgs.password = args[++i];
break;
case '--language':
parsedArgs.language = args[++i];
break;
case '--timezone':
parsedArgs.timezone = args[++i];
break;
case '--roles':
parsedArgs.roles = [];
while (i + 1 < args.length && !args[i + 1].startsWith('--')) {
parsedArgs.roles.push(args[++i]);
}
break;
case '--groups':
parsedArgs.groups = [];
while (i + 1 < args.length && !args[i + 1].startsWith('--')) {
parsedArgs.groups.push(args[++i]);
}
break;
case '--usePublic':
parsedArgs.usePublic = true;
break;
case '--activateFtp':
parsedArgs.activateFtp = true;
break;
case '--ftpPassword':
parsedArgs.ftpPassword = args[++i];
break;
default:
console.warn(`⚠️ Unbekanntes Argument: ${args[i]}`);
}
}
return parsedArgs;
}
/**
* Sendet eine Anfrage an den MCP-Server, um einen Benutzer zu bearbeiten.
*
* @param {string} serverIp - IP-Adresse des MCP-Servers
* @param {number} serverPort - Portnummer des MCP-Servers
* @param {string} token - Authentifizierungstoken
* @param {Object} args - Argumente für den zu bearbeitenden Benutzer
* @returns {Promise<string>} - Antwort vom Server
*/
function sendEditUserRequest(serverIp, serverPort, token, args) {
return new Promise((resolve, reject) => {
const client = new net.Socket();
const payload = {
command: "edit_user",
token: token,
arguments: {
name: args.name,
email: args.email,
password: args.password,
language: args.language,
timezone: args.timezone,
roles: args.roles || [],
groups: args.groups || [],
usePublic: args.usePublic || false,
activateFtp: args.activateFtp || false,
ftpPassword: args.ftpPassword
}
};
// Entferne Null- oder undefined-Werte
payload.arguments = Object.fromEntries(Object.entries(payload.arguments).filter(([_, v]) => v != null));
const payloadString = JSON.stringify(payload);
// Timeout setzen
const TIMEOUT_DURATION = 10000; // 10 Sekunden
const timeout = setTimeout(() => {
client.destroy();
reject(new Error('Verbindungs-Timeout: Der Server hat nicht rechtzeitig geantwortet.'));
}, TIMEOUT_DURATION);
client.connect(serverPort, serverIp, () => {
console.log(`🔗 Verbindung zum Server (${serverIp}:${serverPort}) hergestellt.`);
console.log(`📤 Sende Payload: ${payloadString}`);
client.write(payloadString);
});
let responseData = '';
client.on('data', (data) => {
responseData += data.toString();
try {
const parsedData = JSON.parse(responseData);
clearTimeout(timeout);
resolve(parsedData);
client.destroy();
} catch (e) {
// Weiter empfangen, falls JSON unvollständig ist
}
});
client.on('close', () => {
console.log('🔒 Verbindung zum Server geschlossen.');
});
client.on('error', (err) => {
clearTimeout(timeout);
reject(err);
});
});
}
// Hauptfunktion
async function main() {
const args = parseArguments(argv);
if (!args.serverIp || !args.serverPort || !args.token) {
console.error('❌ Fehler: --server-ip, --server-port und --token sind erforderlich.');
console.log('📖 Beispiel: node MCPEditUserClient.js --server-ip 192.168.0.1 --server-port 5000 --token YOUR_AUTH_TOKEN');
process.exit(1);
}
try {
console.log('🧑💻 Sende Edit-User-Anfrage...');
const response = await sendEditUserRequest(
args.serverIp,
args.serverPort,
args.token,
args
);
console.log('✔️ Antwort vom Server:', JSON.stringify(response, null, 2));
} catch (err) {
console.error('❌ Fehler beim Bearbeiten des Benutzers:', err.message);
}
}
main();
```
--------------------------------------------------------------------------------
/clients/Java/2.0 mcp_chat/MCPChatClient.java:
--------------------------------------------------------------------------------
```java
import org.json.JSONArray;
import org.json.JSONObject;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class MCPChatClient {
public static void main(String[] args) {
// Minimalprüfung, ob genug Argumente für --server-ip, --server-port, --token, --question vorliegen.
// (Die eigentliche Prüfung machen wir etwas weiter unten ausführlicher.)
if (args.length < 5) {
printUsage();
return;
}
// Argumente auslesen
String serverIp = getArgument(args, "--server-ip");
String serverPortStr = getArgument(args, "--server-port");
String token = getArgument(args, "--token");
String question = getArgument(args, "--question");
boolean usePublic = Arrays.asList(args).contains("--use-public");
String language = getArgument(args, "--language");
if (language == null) {
language = "de"; // Defaultwert wie im Original
}
// Groups (kommagetrennt)
List<String> groups = new ArrayList<>();
String groupsArgument = getArgument(args, "--groups");
if (groupsArgument != null) {
// Zerlege den String an Kommas
String[] groupArray = groupsArgument.split(",");
groups.addAll(Arrays.asList(groupArray));
}
// Vollständige Prüfung
if (serverIp == null || serverPortStr == null || token == null || question == null) {
printUsage();
return;
}
int serverPort = Integer.parseInt(serverPortStr);
// Anfrage an den Server stellen
String response = sendMCPRequest(serverIp, serverPort, token, question, usePublic, groups, language);
System.out.println("Response from server:");
System.out.println(response);
}
/**
* Liest den Wert eines Arguments aus (z.B. --server-ip 127.0.0.1).
* Gibt null zurück, wenn der Schlüssel nicht gefunden wurde.
*/
private static String getArgument(String[] args, String key) {
for (int i = 0; i < args.length - 1; i++) {
if (args[i].equals(key)) {
// Gib das nächste Element zurück, sofern vorhanden
return args[i + 1];
}
}
return null;
}
/**
* Stellt eine Socket-Verbindung her, sendet das JSON-Payload und empfängt die Antwort.
*/
private static String sendMCPRequest(String serverIp,
int serverPort,
String token,
String question,
boolean usePublic,
List<String> groups,
String language) {
// Payload aufbauen
JSONObject payload = new JSONObject();
payload.put("command", "chat");
payload.put("token", token);
// arguments
JSONObject arguments = new JSONObject();
arguments.put("question", question);
arguments.put("usePublic", usePublic);
arguments.put("language", language);
// Falls du lieber ein reines Array statt List speichern möchtest,
// kannst du direkt new JSONArray(groups) verwenden.
// Hier konvertieren wir die Java-Liste in ein JSONArray:
JSONArray groupsArray = new JSONArray(groups);
arguments.put("groups", groupsArray);
payload.put("arguments", arguments);
// Konvertiere das JSON-Objekt in einen String
String payloadJson = payload.toString();
try (Socket client = new Socket(serverIp, serverPort)) {
// Sende das JSON-Payload
OutputStream outputStream = client.getOutputStream();
byte[] data = payloadJson.getBytes(StandardCharsets.UTF_8);
outputStream.write(data);
outputStream.flush();
// Antwort empfangen
InputStream inputStream = client.getInputStream();
byte[] buffer = new byte[4096];
StringBuilder responseBuilder = new StringBuilder();
int bytesRead;
do {
bytesRead = inputStream.read(buffer);
if (bytesRead > 0) {
responseBuilder.append(new String(buffer, 0, bytesRead, StandardCharsets.UTF_8));
}
} while (bytesRead == buffer.length);
return responseBuilder.toString();
} catch (IOException e) {
// Fehler in ein JSON-Objekt packen, wie im Original
JSONObject errorResponse = new JSONObject();
errorResponse.put("status", "error");
errorResponse.put("message", e.getMessage());
return errorResponse.toString();
}
}
private static void printUsage() {
System.out.println("Usage: ");
System.out.println(" --server-ip <IP> --server-port <PORT> --token <TOKEN> --question <QUESTION>");
System.out.println(" [--use-public] [--groups <GROUPS>] [--language <LANGUAGE>]");
System.out.println();
System.out.println("Example:");
System.out.println(" java -cp .;json-20241224.jar MCPChatClient --server-ip 127.0.0.1 --server-port 1234 \\");
System.out.println(" --token 12345 --question \"Hallo Welt?\" --use-public --groups \"devops,hr\"");
}
}
```
--------------------------------------------------------------------------------
/clients/Gradio/transport/stdio/stdio_client.py:
--------------------------------------------------------------------------------
```python
# transport/stdio/stdio_client.py
import json
import logging
import sys
import traceback
from contextlib import asynccontextmanager
import anyio
from anyio.streams.text import TextReceiveStream
from ...mcp_client import get_default_environment
from ...messages.message_types.json_rpc_message import JSONRPCMessage
from ...transport.stdio.stdio_server_parameters import StdioServerParameters
@asynccontextmanager
async def stdio_client(server: StdioServerParameters):
# ensure we have a server command
if not server.command:
raise ValueError("Server command must not be empty.")
# ensure we have server arguments as a list or tuple
if not isinstance(server.args, (list, tuple)):
raise ValueError("Server arguments must be a list or tuple.")
# create the the read and write streams
read_stream_writer, read_stream = anyio.create_memory_object_stream(0)
write_stream, write_stream_reader = anyio.create_memory_object_stream(0)
# start the subprocess
process = await anyio.open_process(
[server.command, *server.args],
env={**get_default_environment(), **(server.env or {})},
stderr=sys.stderr,
)
# started server
logging.debug(
f"Subprocess started with PID {process.pid}, command: {server.command}"
)
# create a task to read from the subprocess' stdout
async def process_json_line(line: str, writer):
try:
logging.debug(f"Processing line: {line.strip()}")
data = json.loads(line)
# parse the json
logging.debug(f"Parsed JSON data: {data}")
# validate the jsonrpc message
message = JSONRPCMessage.model_validate(data)
logging.debug(f"Validated JSONRPCMessage: {message}")
# send the message
await writer.send(message)
except json.JSONDecodeError as exc:
# not valid json
logging.error(f"JSON decode error: {exc}. Line: {line.strip()}")
except Exception as exc:
# other exception
logging.error(f"Error processing message: {exc}. Line: {line.strip()}")
logging.debug(f"Traceback:\n{traceback.format_exc()}")
async def stdout_reader():
"""Read JSON-RPC messages from the server's stdout."""
assert process.stdout, "Opened process is missing stdout"
buffer = ""
logging.debug("Starting stdout_reader")
try:
async with read_stream_writer:
async for chunk in TextReceiveStream(process.stdout):
lines = (buffer + chunk).split("\n")
buffer = lines.pop()
for line in lines:
if line.strip():
await process_json_line(line, read_stream_writer)
if buffer.strip():
await process_json_line(buffer, read_stream_writer)
except anyio.ClosedResourceError:
logging.debug("Read stream closed.")
except Exception as exc:
logging.error(f"Unexpected error in stdout_reader: {exc}")
logging.debug(f"Traceback:\n{traceback.format_exc()}")
raise
finally:
logging.debug("Exiting stdout_reader")
async def stdin_writer():
"""Send JSON-RPC messages from the write stream to the server's stdin."""
assert process.stdin, "Opened process is missing stdin"
logging.debug("Starting stdin_writer")
try:
async with write_stream_reader:
async for message in write_stream_reader:
json_str = message.model_dump_json(exclude_none=True)
logging.debug(f"Sending: {json_str}")
await process.stdin.send((json_str + "\n").encode())
except anyio.ClosedResourceError:
logging.debug("Write stream closed.")
except Exception as exc:
logging.error(f"Unexpected error in stdin_writer: {exc}")
logging.debug(f"Traceback:\n{traceback.format_exc()}")
raise
finally:
logging.debug("Exiting stdin_writer")
async def terminate_process():
"""Gracefully terminate the subprocess."""
try:
if process.returncode is None: # Process is still running
logging.debug("Terminating subprocess...")
process.terminate()
with anyio.fail_after(5):
await process.wait()
else:
logging.info("Process already terminated.")
except TimeoutError:
logging.warning(
"Process did not terminate gracefully. Forcefully killing it."
)
try:
process.kill()
except Exception as kill_exc:
logging.error(f"Error killing process: {kill_exc}")
except Exception as exc:
logging.error(f"Error during process termination: {exc}")
try:
async with anyio.create_task_group() as tg, process:
tg.start_soon(stdout_reader)
tg.start_soon(stdin_writer)
yield read_stream, write_stream
# exit the task group
exit_code = await process.wait()
logging.info(f"Process exited with code {exit_code}")
except Exception as exc:
# other exception
logging.error(f"Unhandled error in TaskGroup: {exc}")
logging.debug(f"Traceback:\n{traceback.format_exc()}")
if hasattr(exc, "__cause__") and exc.__cause__:
logging.debug(f"TaskGroup exception cause: {exc.__cause__}")
raise
finally:
await terminate_process()
```
--------------------------------------------------------------------------------
/agents/MCP-Client/Python/transport/stdio/stdio_client.py:
--------------------------------------------------------------------------------
```python
# transport/stdio/stdio_client.py
import json
import logging
import sys
import traceback
from contextlib import asynccontextmanager
import anyio
from anyio.streams.text import TextReceiveStream
from ...environment import get_default_environment
from ...messages.message_types.json_rpc_message import JSONRPCMessage
from ...transport.stdio.stdio_server_parameters import StdioServerParameters
@asynccontextmanager
async def stdio_client(server: StdioServerParameters):
# ensure we have a server command
if not server.command:
raise ValueError("Server command must not be empty.")
# ensure we have server arguments as a list or tuple
if not isinstance(server.args, (list, tuple)):
raise ValueError("Server arguments must be a list or tuple.")
# create the the read and write streams
read_stream_writer, read_stream = anyio.create_memory_object_stream(0)
write_stream, write_stream_reader = anyio.create_memory_object_stream(0)
# start the subprocess
process = await anyio.open_process(
[server.command, *server.args],
env={**get_default_environment(), **(server.env or {})},
stderr=sys.stderr,
)
# started server
logging.debug(
f"Subprocess started with PID {process.pid}, command: {server.command}"
)
# create a task to read from the subprocess' stdout
async def process_json_line(line: str, writer):
try:
logging.debug(f"Processing line: {line.strip()}")
data = json.loads(line)
# parse the json
logging.debug(f"Parsed JSON data: {data}")
# validate the jsonrpc message
message = JSONRPCMessage.model_validate(data)
logging.debug(f"Validated JSONRPCMessage: {message}")
# send the message
await writer.send(message)
except json.JSONDecodeError as exc:
# not valid json
logging.error(f"JSON decode error: {exc}. Line: {line.strip()}")
except Exception as exc:
# other exception
logging.error(f"Error processing message: {exc}. Line: {line.strip()}")
logging.debug(f"Traceback:\n{traceback.format_exc()}")
async def stdout_reader():
"""Read JSON-RPC messages from the server's stdout."""
assert process.stdout, "Opened process is missing stdout"
buffer = ""
logging.debug("Starting stdout_reader")
try:
async with read_stream_writer:
async for chunk in TextReceiveStream(process.stdout):
lines = (buffer + chunk).split("\n")
buffer = lines.pop()
for line in lines:
if line.strip():
await process_json_line(line, read_stream_writer)
if buffer.strip():
await process_json_line(buffer, read_stream_writer)
except anyio.ClosedResourceError:
logging.debug("Read stream closed.")
except Exception as exc:
logging.error(f"Unexpected error in stdout_reader: {exc}")
logging.debug(f"Traceback:\n{traceback.format_exc()}")
raise
finally:
logging.debug("Exiting stdout_reader")
async def stdin_writer():
"""Send JSON-RPC messages from the write stream to the server's stdin."""
assert process.stdin, "Opened process is missing stdin"
logging.debug("Starting stdin_writer")
try:
async with write_stream_reader:
async for message in write_stream_reader:
json_str = message.model_dump_json(exclude_none=True)
logging.debug(f"Sending: {json_str}")
await process.stdin.send((json_str + "\n").encode())
except anyio.ClosedResourceError:
logging.debug("Write stream closed.")
except Exception as exc:
logging.error(f"Unexpected error in stdin_writer: {exc}")
logging.debug(f"Traceback:\n{traceback.format_exc()}")
raise
finally:
logging.debug("Exiting stdin_writer")
async def terminate_process():
"""Gracefully terminate the subprocess."""
try:
if process.returncode is None: # Process is still running
logging.debug("Terminating subprocess...")
process.terminate()
with anyio.fail_after(5):
await process.wait()
else:
logging.info("Process already terminated.")
except TimeoutError:
logging.warning(
"Process did not terminate gracefully. Forcefully killing it."
)
try:
process.kill()
except Exception as kill_exc:
logging.error(f"Error killing process: {kill_exc}")
except Exception as exc:
logging.error(f"Error during process termination: {exc}")
try:
async with anyio.create_task_group() as tg, process:
tg.start_soon(stdout_reader)
tg.start_soon(stdin_writer)
yield read_stream, write_stream
# exit the task group
exit_code = await process.wait()
logging.info(f"Process exited with code {exit_code}")
except Exception as exc:
# other exception
logging.error(f"Unhandled error in TaskGroup: {exc}")
logging.debug(f"Traceback:\n{traceback.format_exc()}")
if hasattr(exc, "__cause__") and exc.__cause__:
logging.debug(f"TaskGroup exception cause: {exc.__cause__}")
raise
finally:
await terminate_process()
```
--------------------------------------------------------------------------------
/clients/JavaScript/4.2 mcp_delete_group/MCPDeleteGroupClient.js:
--------------------------------------------------------------------------------
```javascript
const net = require('net');
const readline = require('readline');
const { argv, exit } = require('process');
/**
* Funktion zum Parsen der Kommandozeilenargumente
* @param {string[]} args - Array von Kommandozeilenargumenten
* @returns {Object} - Objekt mit geparsten Argumenten
*/
function parseArguments(args) {
const parsedArgs = {};
for (let i = 2; i < args.length; i++) {
switch (args[i]) {
case '--server-ip':
if (i + 1 < args.length) {
parsedArgs.serverIp = args[++i];
} else {
console.warn('⚠️ Kein Wert für --server-ip angegeben.');
}
break;
case '--server-port':
if (i + 1 < args.length) {
parsedArgs.serverPort = parseInt(args[++i], 10);
} else {
console.warn('⚠️ Kein Wert für --server-port angegeben.');
}
break;
case '--token':
if (i + 1 < args.length) {
parsedArgs.token = args[++i];
} else {
console.warn('⚠️ Kein Wert für --token angegeben.');
}
break;
case '--group-name':
if (i + 1 < args.length) {
parsedArgs.groupName = args[++i];
} else {
console.warn('⚠️ Kein Wert für --group-name angegeben.');
}
break;
default:
console.warn(`⚠️ Unbekanntes Argument: ${args[i]}`);
}
}
return parsedArgs;
}
/**
* Funktion zum interaktiven Abfragen eines Parameters (optional)
* @param {string} query - Frage an den Benutzer
* @returns {Promise<string>} - Antwort des Benutzers
*/
function askQuestion(query) {
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
terminal: true
});
return new Promise((resolve) => {
rl.question(query, (answer) => {
rl.close();
resolve(answer);
});
});
}
/**
* Sendet eine Anfrage an den MCP-Server, um eine bestehende Gruppe zu löschen.
*
* @param {string} serverIp - IP-Adresse des MCP-Servers
* @param {number} serverPort - Portnummer des MCP-Servers
* @param {string} token - Authentifizierungstoken
* @param {string} groupName - Name der zu löschenden Gruppe
* @returns {Promise<Object>} - Antwort vom Server
*/
function sendDeleteGroupRequest(serverIp, serverPort, token, groupName) {
return new Promise((resolve, reject) => {
const client = new net.Socket();
const payload = {
command: "delete_group",
token: token,
arguments: {
groupName: groupName
}
};
const payloadString = JSON.stringify(payload);
// Timeout setzen (optional)
const TIMEOUT_DURATION = 10000; // 10 Sekunden
const timeout = setTimeout(() => {
client.destroy(); // Verbindung zerstören
reject(new Error('Verbindungs-Timeout: Der Server hat nicht rechtzeitig geantwortet.'));
}, TIMEOUT_DURATION);
client.connect(serverPort, serverIp, () => {
console.log(`🔗 Verbindung zum Server (${serverIp}:${serverPort}) hergestellt.`);
console.log(`📤 Sende Payload: ${payloadString}`);
client.write(payloadString);
});
let responseData = '';
client.on('data', (data) => {
console.log(`📥 Empfangene Daten: ${data}`);
responseData += data.toString();
try {
const parsedData = JSON.parse(responseData);
console.log('✅ JSON-Antwort erfolgreich geparst.');
clearTimeout(timeout);
resolve(parsedData);
client.destroy(); // Verbindung schließen
} catch (err) {
console.warn('⚠️ Antwort noch nicht vollständig oder ungültiges JSON. Weitere Daten werden erwartet.');
// Weiter empfangen
}
});
client.on('close', () => {
console.log('🔒 Verbindung zum Server geschlossen.');
clearTimeout(timeout);
});
client.on('error', (err) => {
console.error('❌ Verbindungsfehler:', err.message);
clearTimeout(timeout);
reject(err);
});
});
}
// Hauptfunktion
async function main() {
const args = argv;
const parsedArgs = parseArguments(args);
let { serverIp, serverPort, token, groupName } = parsedArgs;
// Überprüfen, ob alle erforderlichen Parameter vorhanden sind, sonst interaktiv abfragen
if (!serverIp) {
serverIp = await askQuestion('🔗 Bitte gib die Server-IP ein: ');
}
if (!serverPort) {
const portInput = await askQuestion('🔗 Bitte gib den Server-Port ein: ');
serverPort = parseInt(portInput, 10);
}
if (!token) {
token = await askQuestion('🔒 Bitte gib dein Authentifizierungstoken ein: ');
}
if (!groupName) {
groupName = await askQuestion('👥 Bitte gib den Namen der Gruppe ein: ');
}
const payload = {
command: "delete_group",
token: token,
arguments: {
groupName: groupName
}
};
try {
console.log('🗑️ Sende Delete-Group-Anfrage...');
const response = await sendDeleteGroupRequest(serverIp, serverPort, token, groupName);
console.log('✔️ Antwort vom Server:', JSON.stringify(response, null, 2));
} catch (err) {
console.error('❌ Fehler:', err.message);
}
}
main();
```
--------------------------------------------------------------------------------
/agents/OpenAI_Compatible_API_Agent/Python/openai_compatible_api.py:
--------------------------------------------------------------------------------
```python
import json
from pathlib import Path
from starlette.responses import StreamingResponse
from fastapi import FastAPI, Request, HTTPException
from threading import local
from agents.OpenAI_Compatible_API_Agent.Python.open_ai_helper import ChatInstance, \
ChatCompletionRequest, CompletionRequest, _resp_sync, _resp_async_generator, models, Message, _resp_async_generator_completions, _resp_sync_completions
from .privategpt_api import PrivateGPTAPI
from ...AgentInterface.Python.config import Config, ConfigError
import uvicorn
app = FastAPI(title="OpenAI-compatible API for PrivateGPT")
request_context = local()
instances = []
# Konfiguration laden
try:
config_file = Path.absolute(Path(__file__).parent.parent / "pgpt_openai_api_proxy.json")
config = Config(config_file=config_file, required_fields=["base_url"])
default_groups = config.get("groups", [])
except ConfigError as e:
print(f"Configuration Error: {e}")
exit(1)
@app.middleware("http")
async def store_request_headers(request: Request, call_next):
request_context.headers = dict(request.headers)
response = await call_next(request)
return response
@app.post("/chat/completions")
async def chat_completions(request: ChatCompletionRequest):
headers = getattr(request_context, "headers", {})
client_api_key = str(headers['authorization']).split(" ")[1]
groups = default_groups
force_new_session = False
if request.groups:
groups = request.groups
if request.newSession:
force_new_session = True
print("Groups: " + str(groups))
if request.messages:
#Check if this api-key already has a running instance
indices = [i for i, x in enumerate(instances) if
x.api_key == client_api_key]
index = -1
if len(indices) > 0:
index = indices[0]
if index > -1:
# if we already have an instance, just reuse it. No need to open new connection
if instances[index].agent.chosen_groups != groups:
print("⚠️ New Groups requested, switching to new Chat..")
config.set_value("groups", groups)
instances[index].agent.chat_id = None
elif force_new_session:
print("⚠️ New Session Requested, switching to new Chat..")
config.set_value("groups", groups)
instances[index].agent.chat_id = None
pgpt = instances[index].agent
else:
#otherwise connect via api-key
config.set_value("groups", groups)
pgpt = PrivateGPTAPI(config, client_api_key=client_api_key)
# remember that we already have an instance for the api key
instance = ChatInstance(client_api_key, pgpt)
instances.append(instance)
if pgpt.logged_in:
response = pgpt.respond_with_context(request.messages, request.response_format, request.tools)
if response is not None:
if "answer" not in response:
response["answer"] = "No Response received"
if response is None or ("answer" in response and response["answer"] == "error"):
pgpt.login()
else:
response = {
"chatId": "0",
"answer": "API Key not valid",
}
else:
response = {
"chatId": "0",
"answer": "No Input given",
}
if request.stream:
return StreamingResponse(
_resp_async_generator(response, request), media_type="application/x-ndjson"
)
else:
return _resp_sync(response, request)
# legacy completions API
@app.post("/completions")
async def completions(request: CompletionRequest):
headers = getattr(request_context, "headers", {})
client_api_key = str(headers['authorization']).split(" ")[1]
groups = default_groups
if request.groups:
groups = request.groups
print("Groups: " + str(groups))
if request.prompt:
#otherwise connect via api-key
config.set_value("groups", groups)
pgpt = PrivateGPTAPI(config, client_api_key=client_api_key)
# remember that we already have an instance for the api key
if pgpt.logged_in:
response = pgpt.respond_with_context([Message(role="user", content=request.prompt)], request.response_format, request.tools)
if "answer" not in response:
response["answer"] = "No Response received"
if "answer" in response and response["answer"] == "error":
if pgpt.login():
pgpt.create_chat()
else:
response = {
"chatId": "0",
"answer": "API Key not valid",
}
else:
response = {
"chatId": "0",
"answer": "No Input given",
}
if request.stream :
return StreamingResponse(
_resp_async_generator_completions(response, request), media_type="application/x-ndjson"
)
else:
return _resp_sync_completions(response, request)
@app.get("/models")
def return_models():
return {
"object": "list",
"data": models
}
@app.get('/models/{model_id}')
async def get_model(model_id: str):
filtered_entries = list(filter(lambda item: item["id"] == model_id, models))
entry = filtered_entries[0] if filtered_entries else None
print(entry)
if entry is None:
raise HTTPException(status_code=404, detail="Model not found")
return entry
if __name__ == "__main__":
api_ip = config.get("api_ip", "0.0.0.0")
api_port = config.get("api_port", 8001)
uvicorn.run(app, host=api_ip, port=int(api_port))
```
--------------------------------------------------------------------------------
/agents/ChatBotAgent/html/index.html:
--------------------------------------------------------------------------------
```html
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ChatBot Agent Interface</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 20px;
padding: 0;
background-color: #f4f4f9;
}
.container {
max-width: 600px;
margin: 0 auto;
background: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
text-align: center; /* Zentriert den Inhalt */
}
.logo {
display: block;
margin: 0 auto 20px; /* Zentriert das Logo und fügt Abstand ein */
width: 150px;
height: auto;
}
h1 {
text-align: center;
color: #333;
}
textarea, select, input, button {
width: 100%;
margin: 10px 0;
padding: 10px;
font-size: 16px;
border: 1px solid #ccc;
border-radius: 5px;
box-sizing: border-box;
}
button {
background-color: #007BFF;
color: white;
border: none;
cursor: pointer;
font-size: 16px;
}
button:hover {
background-color: #0056b3;
}
.response-box {
margin-top: 20px;
padding: 15px;
border: 1px solid #ccc;
border-radius: 5px;
background-color: #f9f9f9;
white-space: pre-wrap;
font-family: monospace;
}
</style>
</head>
<body>
<div class="container">
<!-- Logo einfügen -->
<img src="Logo_light.svg" alt="Logo" class="logo">
<h1>ChatBot Agent</h1>
<form id="queryForm">
<label for="question">Question:</label>
<textarea id="question" rows="3" placeholder="Enter your question here..." required></textarea>
<label for="language">Language:</label>
<select id="language">
<option value="en" selected>English</option>
<option value="de">German</option>
</select>
<label for="groups">Groups (optional, separated by commas):</label>
<input type="text" id="groups" placeholder="Example: Group1, Group2">
<label>
<input type="checkbox" id="usePublic" checked>
Use general knowledge
</label>
<button type="submit">Send Request</button>
</form>
<div class="response-box" id="responseBox">
The response will be displayed here...
</div>
</div>
<script>
const apiUrl = "http://127.0.0.1:5001/ask"; // URL der API
const apiKey = "IhrSichererAPIKey123"; // API-Key
document.getElementById("queryForm").addEventListener("submit", async function(event) {
event.preventDefault();
// Eingaben aus dem Formular abrufen
const question = document.getElementById("question").value.trim();
const language = document.getElementById("language").value;
const groupsInput = document.getElementById("groups").value;
const groups = groupsInput
.split(",")
.map(group => group.trim())
.filter(group => group); // Leere Gruppen entfernen
const usePublic = document.getElementById("usePublic").checked;
if (!question) {
alert("Please enter a question.");
return;
}
// JSON-Body für die Anfrage erstellen
const body = {
question: question,
usePublic: usePublic,
groups: groups,
language: language
};
// Anzeige der Anfrage im Response-Box (optional)
document.getElementById("responseBox").textContent = "Sending request...";
// Anfrage senden
try {
const response = await fetch(apiUrl, {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-KEY": apiKey // Korrigierter Header
},
body: JSON.stringify(body)
});
if (response.ok) {
const data = await response.json();
// Extrahiere das 'answer'-Feld und entferne mögliche Anführungszeichen
let answer = data.answer || "";
if (answer.startsWith('"') && answer.endsWith('"')) {
answer = answer.substring(1, answer.length - 1);
}
// Optional: Entschlüsselung von Unicode-Zeichen
try {
answer = decodeURIComponent(escape(answer));
} catch (e) {
console.warn("Unicode decoding failed:", e);
}
// Anzeige der Antwort
document.getElementById("responseBox").textContent = answer;
} else {
// Fehlerbehandlung bei HTTP-Fehlern
const errorText = await response.text();
document.getElementById("responseBox").textContent = `Error: ${response.status} ${response.statusText}\n${errorText}`;
}
} catch (error) {
// Fehlerbehandlung bei Netzwerk- oder anderen Fehlern
document.getElementById("responseBox").textContent = `Request failed: ${error.message}`;
}
});
</script>
</body>
</html>
```
--------------------------------------------------------------------------------
/agents/ChatBotAgent/html/index_de.html:
--------------------------------------------------------------------------------
```html
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ChatBot Agent Interface</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 20px;
padding: 0;
background-color: #f4f4f9;
}
.container {
max-width: 600px;
margin: 0 auto;
background: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
text-align: center; /* Zentriert den Inhalt */
}
.logo {
display: block;
margin: 0 auto 20px; /* Zentriert das Logo und fügt Abstand ein */
width: 150px;
height: auto;
}
h1 {
text-align: center;
color: #333;
}
textarea, select, input, button {
width: 100%;
margin: 10px 0;
padding: 10px;
font-size: 16px;
border: 1px solid #ccc;
border-radius: 5px;
box-sizing: border-box;
}
button {
background-color: #007BFF;
color: white;
border: none;
cursor: pointer;
font-size: 16px;
}
button:hover {
background-color: #0056b3;
}
.response-box {
margin-top: 20px;
padding: 15px;
border: 1px solid #ccc;
border-radius: 5px;
background-color: #f9f9f9;
white-space: pre-wrap;
font-family: monospace;
}
</style>
</head>
<body>
<div class="container">
<!-- Logo einfügen -->
<img src="Logo_light.svg" alt="Logo" class="logo">
<h1>ChatBot Agent</h1>
<form id="queryForm">
<label for="question">Frage:</label>
<textarea id="question" rows="3" placeholder="Geben Sie Ihre Frage ein..." required></textarea>
<label for="language">Sprache:</label>
<select id="language">
<option value="de" selected>Deutsch</option>
<option value="en">Englisch</option>
</select>
<label for="groups">Gruppen (optional, getrennt durch Kommas):</label>
<input type="text" id="groups" placeholder="Beispiel: Gruppe1, Gruppe2">
<label>
<input type="checkbox" id="usePublic" checked>
Öffentliche Daten verwenden
</label>
<button type="submit">Anfrage senden</button>
</form>
<div class="response-box" id="responseBox">
Antwort wird hier angezeigt...
</div>
</div>
<script>
const apiUrl = "http://192.168.100.185:5001/ask"; // URL der API
const apiKey = "IhrSichererAPIKey123"; // API-Key
document.getElementById("queryForm").addEventListener("submit", async function(event) {
event.preventDefault();
// Eingaben aus dem Formular abrufen
const question = document.getElementById("question").value.trim();
const language = document.getElementById("language").value;
const groupsInput = document.getElementById("groups").value;
const groups = groupsInput
.split(",")
.map(group => group.trim())
.filter(group => group); // Leere Gruppen entfernen
const usePublic = document.getElementById("usePublic").checked;
if (!question) {
alert("Bitte geben Sie eine Frage ein.");
return;
}
// JSON-Body für die Anfrage erstellen
const body = {
question: question,
usePublic: usePublic,
groups: groups,
language: language
};
// Anzeige der Anfrage im Response-Box (optional)
document.getElementById("responseBox").textContent = "Anfrage wird gesendet...";
// Anfrage senden
try {
const response = await fetch(apiUrl, {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-KEY": apiKey // Korrigierter Header
},
body: JSON.stringify(body)
});
if (response.ok) {
const data = await response.json();
// Extrahiere das 'answer'-Feld und entferne mögliche Anführungszeichen
let answer = data.answer || "";
if (answer.startsWith('"') && answer.endsWith('"')) {
answer = answer.substring(1, answer.length - 1);
}
// Optional: Entschlüsselung von Unicode-Zeichen
try {
answer = decodeURIComponent(escape(answer));
} catch (e) {
console.warn("Unicode-Entschlüsselung fehlgeschlagen:", e);
}
// Anzeige der Antwort
document.getElementById("responseBox").textContent = answer;
} else {
// Fehlerbehandlung bei HTTP-Fehlern
const errorText = await response.text();
document.getElementById("responseBox").textContent = `Fehler: ${response.status} ${response.statusText}\n${errorText}`;
}
} catch (error) {
// Fehlerbehandlung bei Netzwerk- oder anderen Fehlern
document.getElementById("responseBox").textContent = `Fehler bei der Anfrage: ${error.message}`;
}
});
</script>
</body>
</html>
```