#
tokens: 47095/50000 6/501 files (page 15/20)
lines: on (toggle) GitHub
raw markdown copy reset
This is page 15 of 20. Use http://codebase.md/fujitsu-ai/mcp-server-for-mas-developments?lines=true&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
│   ├── 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

--------------------------------------------------------------------------------
/agents/MCP-Client/Python/mcp_client.py:
--------------------------------------------------------------------------------

```python
  1 | # src/__main__.py
  2 | import argparse
  3 | import asyncio
  4 | import json
  5 | import logging
  6 | import os
  7 | import signal
  8 | import sys
  9 | from pathlib import Path
 10 | from typing import List
 11 | 
 12 | import anyio
 13 | # Rich imports
 14 | from rich import print
 15 | from rich.markdown import Markdown
 16 | from rich.panel import Panel
 17 | 
 18 | from .chat_handler import handle_chat_mode, get_input
 19 | from .config import load_config
 20 | from .messages.send_ping import send_ping
 21 | from .messages.send_prompts import send_prompts_list
 22 | from .messages.send_resources import send_resources_list
 23 | from .messages.send_initialize_message import send_initialize
 24 | from .messages.send_call_tool import send_call_tool
 25 | from .messages.send_tools_list import send_tools_list
 26 | from .transport.stdio.stdio_client import stdio_client
 27 | 
 28 | # Default path for the configuration file
 29 | DEFAULT_CONFIG_FILE = config_file = Path.absolute(Path(__file__).parent.parent / "server_config.json")
 30 | 
 31 | # Configure logging
 32 | logging.basicConfig(
 33 |     level=logging.CRITICAL,
 34 |     format="%(asctime)s - %(levelname)s - %(message)s",
 35 |     stream=sys.stderr,
 36 | )
 37 | 
 38 | def signal_handler(sig, frame):
 39 |     # Ignore subsequent SIGINT signals
 40 |     signal.signal(signal.SIGINT, signal.SIG_IGN)
 41 | 
 42 |     # pretty exit
 43 |     print("\n[bold red]Goodbye![/bold red]")
 44 | 
 45 |     # Immediately and forcibly kill the process
 46 |     os.kill(os.getpid(), signal.SIGKILL)
 47 | 
 48 | 
 49 | # signal handler
 50 | signal.signal(signal.SIGINT, signal_handler)
 51 | 
 52 | 
 53 | async def handle_command(command: str, server_streams: List[tuple]) -> bool:
 54 |     """Handle specific commands dynamically with multiple servers."""
 55 |     try:
 56 |         if command == "ping":
 57 |             print("[cyan]\nPinging Servers...[/cyan]")
 58 |             for i, (read_stream, write_stream) in enumerate(server_streams):
 59 |                 result = await send_ping(read_stream, write_stream)
 60 |                 server_num = i + 1
 61 |                 if result:
 62 |                     ping_md = f"## Server {server_num} Ping Result\n\n✅ **Server is up and running**"
 63 |                     print(Panel(Markdown(ping_md), style="bold green"))
 64 |                 else:
 65 |                     ping_md = f"## Server {server_num} Ping Result\n\n❌ **Server ping failed**"
 66 |                     print(Panel(Markdown(ping_md), style="bold red"))
 67 | 
 68 |         elif command == "list-tools":
 69 |             print("[cyan]\nFetching Tools List from all servers...[/cyan]")
 70 |             for i, (read_stream, write_stream) in enumerate(server_streams):
 71 |                 response = await send_tools_list(read_stream, write_stream)
 72 |                 tools_list = response.get("tools", [])
 73 |                 server_num = i + 1
 74 | 
 75 |                 if not tools_list:
 76 |                     tools_md = (
 77 |                         f"## Server {server_num} Tools List\n\nNo tools available."
 78 |                     )
 79 |                 else:
 80 |                     tools_md = f"## Server {server_num} Tools List\n\n" + "\n".join(
 81 |                         [
 82 |                             f"- **{t.get('name')}**: {t.get('description', 'No description')}"
 83 |                             for t in tools_list
 84 |                         ]
 85 |                     )
 86 |                 print(
 87 |                     Panel(
 88 |                         Markdown(tools_md),
 89 |                         title=f"Server {server_num} Tools",
 90 |                         style="bold cyan",
 91 |                     )
 92 |                 )
 93 | 
 94 |         elif command == "call-tool":
 95 |             tool_name = await get_input("[bold magenta]Enter tool name[/bold magenta]")
 96 |             if not tool_name:
 97 |                 print("[red]Tool name cannot be empty.[/red]")
 98 |                 return True
 99 | 
100 |             arguments_str = await get_input("[bold magenta]Enter tool arguments as JSON (e.g., {'key': 'value'})[/bold magenta]")
101 |             try:
102 |                 arguments = json.loads(arguments_str)
103 |             except json.JSONDecodeError as e:
104 |                 print(f"[red]Invalid JSON arguments format:[/red] {e}")
105 |                 return True
106 | 
107 |             print(f"[cyan]\nCalling tool '{tool_name}' with arguments:\n[/cyan]")
108 |             print(
109 |                 Panel(
110 |                     Markdown(f"```json\n{json.dumps(arguments, indent=2)}\n```"),
111 |                     style="dim",
112 |                 )
113 |             )
114 | 
115 |             for read_stream, write_stream in server_streams:
116 |                 result = await send_call_tool(tool_name, arguments, read_stream, write_stream)
117 |                 if result.get("isError"):
118 |                     # print(f"[red]Error calling tool:[/red] {result.get('error')}")
119 |                     continue
120 |                 response_content = result.get("content", "No content")
121 |                 try:
122 |                     if response_content[0]['text'].startswith('Error:'):
123 |                         continue
124 |                 except:
125 |                     pass
126 |                 print(
127 |                     Panel(
128 |                         Markdown(f"### Tool Response\n\n{response_content}"),
129 |                         style="green",
130 |                     )
131 |                 )
132 | 
133 |         elif command == "list-resources":
134 |             print("[cyan]\nFetching Resources List from all servers...[/cyan]")
135 |             for i, (read_stream, write_stream) in enumerate(server_streams):
136 |                 response = await send_resources_list(read_stream, write_stream)
137 |                 resources_list = response.get("resources", []) if response else None
138 |                 server_num = i + 1
139 | 
140 |                 if not resources_list:
141 |                     resources_md = f"## Server {server_num} Resources List\n\nNo resources available."
142 |                 else:
143 |                     resources_md = f"## Server {server_num} Resources List\n"
144 |                     for r in resources_list:
145 |                         if isinstance(r, dict):
146 |                             json_str = json.dumps(r, indent=2)
147 |                             resources_md += f"\n```json\n{json_str}\n```"
148 |                         else:
149 |                             resources_md += f"\n- {r}"
150 |                 print(
151 |                     Panel(
152 |                         Markdown(resources_md),
153 |                         title=f"Server {server_num} Resources",
154 |                         style="bold cyan",
155 |                     )
156 |                 )
157 | 
158 |         elif command == "list-prompts":
159 |             print("[cyan]\nFetching Prompts List from all servers...[/cyan]")
160 |             for i, (read_stream, write_stream) in enumerate(server_streams):
161 |                 response = await send_prompts_list(read_stream, write_stream)
162 |                 prompts_list = response.get("prompts", []) if response else None
163 |                 server_num = i + 1
164 | 
165 |                 if not prompts_list:
166 |                     prompts_md = (
167 |                         f"## Server {server_num} Prompts List\n\nNo prompts available."
168 |                     )
169 |                 else:
170 |                     prompts_md = f"## Server {server_num} Prompts List\n\n" + "\n".join(
171 |                         [f"- {p}" for p in prompts_list]
172 |                     )
173 |                 print(
174 |                     Panel(
175 |                         Markdown(prompts_md),
176 |                         title=f"Server {server_num} Prompts",
177 |                         style="bold cyan",
178 |                     )
179 |                 )
180 | 
181 |         elif command == "chat":
182 |             provider = os.getenv("LLM_PROVIDER", "openai")
183 |             model = os.getenv("LLM_MODEL", "gpt-4o-mini")
184 | 
185 |             # Clear the screen first
186 |             if sys.platform == "win32":
187 |                 os.system("cls")
188 |             else:
189 |                 os.system("clear")
190 | 
191 |             chat_info_text = (
192 |                 "Welcome to the Chat!\n\n"
193 |                 f"**Provider:** {provider}  |  **Model:** {model}\n\n"
194 |                 "Type 'exit' to quit."
195 |             )
196 | 
197 |             print(
198 |                 Panel(
199 |                     Markdown(chat_info_text),
200 |                     style="bold cyan",
201 |                     title="Chat Mode",
202 |                     title_align="center",
203 |                 )
204 |             )
205 |             await handle_chat_mode(server_streams, provider, model)
206 | 
207 |         elif command in ["quit", "exit"]:
208 |             print("\n[bold red]Goodbye![/bold red]")
209 |             return False
210 | 
211 |         elif command == "clear":
212 |             if sys.platform == "win32":
213 |                 os.system("cls")
214 |             else:
215 |                 os.system("clear")
216 | 
217 |         elif command == "help":
218 |             help_md = print_help()
219 |             print(Panel(help_md))
220 | 
221 |         else:
222 |             print(f"[red]\nUnknown command: {command}[/red]")
223 |             print("[yellow]Type 'help' for available commands[/yellow]")
224 |     except Exception as e:
225 |         print(f"\n[red]Error executing command:[/red] {e}")
226 | 
227 |     return True
228 | 
229 | def print_help():
230 |     return  Markdown(
231 | """
232 | # Available Commands
233 | 
234 | - **ping**: Check if server is responsive
235 | - **list-tools**: Display available tools
236 | - **list-resources**: Display available resources
237 | - **list-prompts**: Display available prompts
238 | - **chat**: Enter chat mode
239 | - **clear**: Clear the screen
240 | - **help**: Show this help message
241 | - **quit/exit**: Exit the program
242 | 
243 | **Note:** Commands use dashes (e.g., `list-tools` not `list tools`).
244 | """)
245 | 
246 | async def interactive_mode(server_streams: List[tuple]):
247 |     """Run the CLI in interactive mode with multiple servers."""
248 |     welcome_text = """
249 | # Welcome to the Interactive MCP Command-Line Tool (Multi-Server Mode)
250 | 
251 | Type 'help' for available commands or 'quit' to exit.
252 | """
253 |     print(Panel(Markdown(welcome_text), style="bold cyan"))
254 | 
255 |     help_md = print_help()
256 |     print(Panel(help_md, style="yellow"))
257 | 
258 |     while True:
259 |         try:
260 |             command = await get_input("[bold green]\n>[/bold green]")
261 |             command = command.lower()
262 |             if not command:
263 |                 continue
264 |             should_continue = await handle_command(command, server_streams)
265 |             if not should_continue:
266 |                 return
267 |         except EOFError:
268 |             break
269 |         except Exception as e:
270 |             print(f"\n[red]Error:[/red] {e}")
271 | 
272 | 
273 | class GracefulExit(Exception):
274 |     """Custom exception for handling graceful exits."""
275 | 
276 |     pass
277 | 
278 | 
279 | async def run(config_path: str, server_names: List[str], command: str = None) -> None:
280 |     """Main function to manage server initialization, communication, and shutdown."""
281 |     # Clear screen before rendering anything
282 |     if sys.platform == "win32":
283 |         os.system("cls")
284 |     else:
285 |         os.system("clear")
286 | 
287 |     # Load server configurations and establish connections for all servers
288 |     server_streams = []
289 |     context_managers = []
290 |     for server_name in server_names:
291 |         server_params = await load_config(config_path, server_name)
292 | 
293 |         # Establish stdio communication for each server
294 |         cm = stdio_client(server_params)
295 |         (read_stream, write_stream) = await cm.__aenter__()
296 |         context_managers.append(cm)
297 |         server_streams.append((read_stream, write_stream))
298 | 
299 |         init_result = await send_initialize(read_stream, write_stream)
300 |         if not init_result:
301 |             print(f"[red]Server initialization failed for {server_name}[/red]")
302 |             return
303 | 
304 |     try:
305 |         if command:
306 |             # Single command mode
307 |             await handle_command(command, server_streams)
308 |         else:
309 |             # Interactive mode
310 |             await interactive_mode(server_streams)
311 |     finally:
312 |         # Clean up all streams
313 |         for cm in context_managers:
314 |             with anyio.move_on_after(1):  # wait up to 1 second
315 |                 await cm.__aexit__()
316 | 
317 | def cli_main():
318 |     # setup the parser
319 |     parser = argparse.ArgumentParser(description="MCP Client")
320 | 
321 |     parser.add_argument(
322 |         "--config-file",
323 |         default=DEFAULT_CONFIG_FILE,
324 |         help="Path to the JSON configuration file containing server details.",
325 |     )
326 | 
327 |     parser.add_argument(
328 |         "--server",
329 |         action="append",
330 |         dest="servers",
331 |         help="Server configuration(s) to use. Can be specified multiple times.",
332 |         default=[],
333 |     )
334 | 
335 |     parser.add_argument(
336 |         "--all",
337 |         action="store_true",
338 |         dest="all",
339 |         default=False
340 |     )
341 | 
342 |     parser.add_argument(
343 |         "command",
344 |         nargs="?",
345 |         choices=["ping", "list-tools", "list-resources", "list-prompts"],
346 |         help="Command to execute (optional - if not provided, enters interactive mode).",
347 |     )
348 | 
349 |     parser.add_argument(
350 |         "--model",
351 |         help=(
352 |             "Model to use. Defaults to 'pgpt-mistral-nemo-12b'"),
353 |     )
354 | 
355 |     args = parser.parse_args()
356 | 
357 |     # Set default model based on provider
358 |     model = args.model or (
359 |         "pgpt-mistral-nemo-12b"
360 |     )
361 |     os.environ["LLM_PROVIDER"] = "pgpt"
362 |     os.environ["LLM_MODEL"] = model
363 | 
364 |     try:
365 |         if args.all:
366 |             with open(args.config_file,'r') as f:
367 |                 args.servers = list(json.load(f)['mcpServers'].keys())
368 |         result = anyio.run(run, args.config_file, args.servers, args.command)
369 |         sys.exit(result)
370 |     except Exception as e:
371 |         print(f"[red]Error occurred:[/red] {e}")
372 |         sys.exit(1)
373 | 
374 | 
375 | if __name__ == "__main__":
376 |     cli_main()
377 | 
378 | 
```

--------------------------------------------------------------------------------
/agents/OpenAI_Compatible_API_Agent/Python/privategpt_api.py:
--------------------------------------------------------------------------------

```python
  1 | import json
  2 | import re
  3 | from pathlib import Path
  4 | 
  5 | import requests
  6 | import urllib3
  7 | import base64
  8 | 
  9 | from httpcore import NetworkError
 10 | 
 11 | from ...AgentInterface.Python.config import Config
 12 | 
 13 | urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
 14 | 
 15 | 
 16 | def initialize_session(proxy_user, proxy_password, access_header):
 17 |     """Set up the session with proxy authentication."""
 18 |     session = requests.Session()
 19 |     session.verify = False
 20 |     headers = {
 21 |         'Accept': 'application/json',
 22 |         'Content-Type': 'application/json',
 23 |     }
 24 |     if access_header is not None:
 25 |         headers['X-Custom-Header'] = access_header
 26 |     elif proxy_user is not None and proxy_password is not None:
 27 |             auth = base64.b64encode(f"{proxy_user}:{proxy_password}".encode()).decode()
 28 |             headers['Authorization'] = f'Basic {auth}'
 29 |     session.headers.update(headers)
 30 |     return session
 31 | 
 32 | 
 33 | class PrivateGPTAPI:
 34 |     def __init__(self, config, client_api_key=None):
 35 |         """Initialize the chat client with proxy authentication."""
 36 |         self.token = None
 37 |         self.chat_id = None
 38 | 
 39 |         self.base_url = config.get("base_url")
 40 |         self.proxy_user = config.get("proxy_user", None)
 41 |         if self.proxy_user == "":
 42 |             self.proxy_user = None
 43 |         self.proxy_password = config.get("proxy_password", None)
 44 |         if self.proxy_password == "":
 45 |             self.proxy_password = None
 46 |         self.access_header = config.get("access_header", None)
 47 |         if self.access_header == "":
 48 |             self.access_header = None
 49 | 
 50 |         self.chosen_groups = config.data["groups"] or []
 51 |         self.language = config.get("language", "en")
 52 |         self.use_public = config.get("use_public", True)
 53 |         self.whitelist_keys = config.get("whitelist_keys", [])
 54 |         self.logged_in = False
 55 | 
 56 | 
 57 |         if client_api_key is not None:
 58 |             self.email, self.password = decrypt_api_key(client_api_key)
 59 |             if len(self.whitelist_keys) > 0:
 60 |                 if client_api_key not in self.whitelist_keys:
 61 |                     print("not authorized")
 62 | 
 63 |         self.session = initialize_session(self.proxy_user, self.proxy_password, self.access_header)
 64 |         if self.login():
 65 |             self.logged_in = True
 66 | 
 67 | 
 68 |     def login(self):
 69 |         """Authenticate the user and retrieve the token."""
 70 |         url = f"{self.base_url}/login"
 71 |         payload = {"email": self.email, "password": self.password}
 72 |         try:
 73 |             response = self.session.post(url, json=payload)
 74 |             print(response.content)
 75 |             response.raise_for_status()
 76 |             data = response.json()
 77 |             self.token = data['data']['token']
 78 |             
 79 |             # Prüfen, ob der Header bereits existiert
 80 |             if 'Authorization' in self.session.headers:
 81 |                 self.session.headers['Authorization'] += f', Bearer {self.token}'
 82 |             else:
 83 |                 self.session.headers['Authorization'] = f'Bearer {self.token}'
 84 |             self.chat_id = None
 85 |             print("✅ Login successful.")
 86 |             return True
 87 |         except requests.exceptions.RequestException as e:
 88 |             print(f"❌ Login failed: {e}")
 89 |         return False
 90 | 
 91 |     def create_chat(self, user_input):
 92 |         """Start a new chat session.
 93 | 
 94 |         This method sends a POST request to the '/chats' endpoint with the provided parameters.
 95 |         It initializes a new chat session and stores the chat ID for future use.
 96 |         """
 97 |         url = f"{self.base_url}/chats"
 98 |         payload = {
 99 |             "language": self.language,
100 |             "question": user_input,  # Initial question to start the chat
101 |             "usePublic": self.use_public,
102 |             "groups": self.chosen_groups
103 |         }
104 |         try:
105 |             response = self.session.post(url, json=payload)
106 |             response.raise_for_status()  # Raise an exception if the response was not successful
107 |             data = response.json()
108 |             self.chat_id = data['data']['chatId']  # Store the chat ID for future use
109 |             print("✅ Chat initialized.")
110 |             resp = response.json()
111 |             try:
112 |                 answer = resp.get('data', None).get('answer', "error")
113 |             except:
114 |                 print(response.json())
115 |                 resp = {"data":
116 |                             {"answer": "error"}
117 |                         }
118 |                 answer = "error"
119 | 
120 |             if answer.startswith("{\"role\":"):
121 |                 answerj = json.loads(answer)
122 |                 resp["data"]["answer"] = answerj["content"]
123 |                 resp["data"]["chatId"] = "0"
124 | 
125 |             print(f"💡 Response: {answer}")
126 |             return resp
127 |         except requests.exceptions.RequestException as e:
128 |             # It seems we get disconnections from time to time..
129 |             # print(f"⚠️ Failed to get response on first try, trying again..: {e}")
130 |             try:
131 |                 response = self.session.patch(url, json=payload)
132 |                 response.raise_for_status()
133 |                 data = response.json()
134 |                 answer = data.get('data', {}).get('answer', "No answer provided.")
135 |                 print(f"💡 Response: {answer}")
136 |                 return data
137 |             except:
138 |                 print(f"❌ Failed to get response: {e}")
139 |                 return {"error": f"❌ Failed to get response: {e}"}
140 | 
141 |     def list_personal_groups(self):
142 |         url = f"{self.base_url}/groups"
143 |         try:
144 |             resp = self.session.get(url)
145 |             data_block = resp.content.get("data")
146 |             if not data_block:
147 |                 return []
148 | 
149 |             if data_block.get("status") == 200 and data_block.get("message") == "success":
150 |                 personal = data_block.get("personalGroups", [])
151 |                 return personal
152 |             else:
153 |                 return []
154 |         except NetworkError as e:
155 |             return []
156 | 
157 |     def query_private_gpt(self, user_input) -> json:
158 |         """Send a question to the chat and retrieve the response."""
159 |         if not self.chat_id:
160 |             print("❌ Chat session not initialized.")
161 |             return False
162 |         url = f"{self.base_url}/chats/{self.chat_id}"
163 |         payload = {"question": user_input}
164 |         try:
165 |             response = self.session.patch(url, json=payload)
166 |             #response.raise_for_status()
167 |             resp = response.json()
168 |             try:
169 |                 answer = resp.get('data', None).get('answer', "error")
170 |             except:
171 |                 print(response.json())
172 |                 resp = {"data" :
173 |                         {"answer": "error"}
174 |                         }
175 |                 answer = "error"
176 | 
177 |             if answer.startswith("{\"role\":"):
178 |                  answerj = json.loads(answer)
179 |                  resp["data"]["answer"] = answerj["content"]
180 |                  resp["data"]["chatId"] = "0"
181 | 
182 |             print(f"💡 Response: {answer}")
183 |             return resp
184 |         except requests.exceptions.RequestException as e:
185 |             # It seems we get disconnections from time to time..
186 |             #print(f"⚠️ Failed to get response on first try, trying again..: {e}")
187 |             try:
188 |                 response = self.session.patch(url, json=payload)
189 |                 response.raise_for_status()
190 |                 data = response.json()
191 |                 answer = data.get('data', {}).get('answer', "No answer provided.")
192 |                 print(f"💡 Response: {answer}")
193 |                 return data
194 |             except:
195 |                 print(f"❌ Failed to get response: {e}")
196 |                 return {"error": f"❌ Failed to get response: {e}"}
197 | 
198 | 
199 |     def get_document_info(self, source_id):
200 |         """Send a source id to retrieve details. Working with version 1.3.3 and newer"""
201 |         url = f"{self.base_url}/sources/{source_id}"
202 |         try:
203 |             response = self.session.get(url)
204 |             data = response.json()
205 |             info = data.get('data', {})
206 |             print(f"💡 Response: {str(info)}")
207 |             return data
208 |         except requests.exceptions.RequestException as e:
209 |             print(f"❌ Failed to get response: {e}")
210 |             return {"error": f"❌ Failed to get response: {e}"}
211 | 
212 | 
213 |     def respond_with_context(self, messages, response_format=None, request_tools=None):
214 |         last_user_message = next((p for p in reversed(messages) if p.role == "user"), None)
215 |         user_input = ""
216 | 
217 | 
218 |         for message in messages:
219 |             if message.role == "system":
220 |                 user_input = str(message) + "\n"
221 | 
222 |         if last_user_message is not None:
223 |             user_input += last_user_message.content
224 | 
225 |         last_assistant_message = next((p for p in reversed(messages) if p.role == "assistant"), None)
226 |         last_tool_message = next((p for p in reversed(messages) if p.role == "tool"), None)
227 | 
228 |         hastoolresult = False
229 |         if last_tool_message is not None and last_assistant_message is not None and last_assistant_message.tool_calls is not None and len(last_assistant_message.tool_calls) > 0:
230 |             user_input += "\nYou called the tool: " + str(last_assistant_message.tool_calls[0]) + ". The result was: " + last_tool_message.content
231 |             hastoolresult = True
232 | 
233 | 
234 |         print(f"💁 Request: " + user_input)
235 | 
236 |         # PGPT manages history and context itself so we don't need to forward the history.
237 |         add_context = False
238 |         if add_context:
239 |             messages.pop()
240 |             user_input += "\nHere is some context about the previous conversation:\n"
241 |             for message in messages:
242 |                 user_input += f"{message.role}: {message.content}\n"
243 | 
244 |         if response_format is not None:
245 |             print("Response format: " + str(response_format))
246 |             user_input += add_response_format(response_format)
247 | 
248 |         if request_tools is not None and not hastoolresult:
249 |             user_input += add_tools(request_tools, last_tool_message)
250 | 
251 |         if not self.logged_in:
252 |             self.login()
253 |         else:
254 |             if self.chat_id is None:
255 |                 result = self.create_chat(user_input)
256 |             else:
257 |                 result = self.query_private_gpt(user_input)
258 | 
259 |             if 'data' in result:
260 |                 response_data = result.get("data")
261 |                 if request_tools is not None and not hastoolresult and is_json(clean_response(response_data.get("answer"))):
262 |                     response_data["tool_call"] = clean_response(response_data.get("answer", ""))
263 |                 return response_data
264 |             elif 'error' in result:
265 |                 # Try to login again and send the query once more on error.
266 |                 if self.login():
267 |                     if self.chat_id is None:
268 |                         result = self.create_chat(user_input)
269 |                     else:
270 |                         result = self.query_private_gpt(user_input)
271 | 
272 |                     if 'data' in result:
273 |                         return result['data']
274 |                     else:
275 |                         return result
276 | 
277 |             else:
278 |                 return result
279 | 
280 | def is_json(myjson):
281 |   try:
282 |     json.loads(myjson)
283 |   except ValueError as e:
284 |     return False
285 |   return True
286 | 
287 | def add_response_format(response_format):
288 |     #prompt = "\nPlease fill in the following template with realistic and appropriate information. Be creative. The field 'type' defines the output format. In your reply, only return the generated json\n"
289 |     prompt = "\nPlease fill in the following json template with realistic and appropriate information. In your reply, only return the generated json. If you can't answer return an empty json.\n"
290 |     prompt += json.dumps(response_format)
291 |     return prompt
292 | 
293 | 
294 | def add_tools(response_tools, last_tool_message):
295 | 
296 |     prompt = "\nPlease select the fitting provided tool to create your answer. Only return the generated result of the tool. Do not describe what you are doing, just return the json.\n"
297 |     index = 1
298 |     for tool in response_tools:
299 |         prompt += "\n" + json.dumps(tool) + "\n"
300 |         index += 1
301 | 
302 |     return prompt
303 | 
304 | def clean_response(response):
305 |     # Remove artefacts from reply here
306 |     response = response.replace("[TOOL_CALLS]", "")
307 |     return response
308 | 
309 | def decrypt_api_key(api_key):
310 |     """
311 |     This is PoC code and methods should be replaced with a more secure way to deal with credentials (e.g. in a db)
312 |     """
313 |     try:
314 |         base64_bytes = api_key.encode("ascii")
315 |         decoded_string_bytes = base64.b64decode(base64_bytes)
316 |         decoded_key = decoded_string_bytes.decode("ascii")
317 |     except Exception as e:
318 |         print(e)
319 |         decoded_key = "invalid:invalid"
320 | 
321 |     return decoded_key.split(":")[0], decoded_key.split(":")[1]
322 | 
323 | 
324 | def main():
325 |     """Main function to run the chat application."""
326 |     config_file = Path.absolute(Path(__file__).parent.parent / "pgpt_openai_api_proxy.json")
327 |     config = Config(config_file=config_file, required_fields=["base_url"])
328 |     chat = PrivateGPTAPI(config)
329 | 
330 |     print("Type your questions below. Type 'quit' to exit.")
331 |     while True:
332 |         try:
333 |             question = input("❓ Question: ").strip()
334 |             if question.lower() == 'quit':
335 |                 break
336 |             if question:
337 |                  chat.query_private_gpt(question)
338 |         except KeyboardInterrupt:
339 |             print("\nExiting chat...")
340 |             break
341 |         except Exception as e:
342 |             print(f"❌ Error: {str(e)}")
343 |             break
344 | 
345 | 
346 | if __name__ == "__main__":
347 |     main()
```

--------------------------------------------------------------------------------
/clients/Gradio/logos/Logo_dark.svg:
--------------------------------------------------------------------------------

```
 1 | <svg width="2227" height="1024" viewBox="0 0 600 1024" fill="none" xmlns="http://www.w3.org/2000/svg">
 2 | <path d="M2811.31 775.828V157.115H2568.68V19.2558H3220.48V157.115H2976.74V775.828H2811.31Z" fill="url(#paint0_linear_3311_10229)" fill-opacity="0.9"/>
 3 | <path d="M1881.39 775.828V19.2558H2275.12C2329.52 19.2558 2374.74 29.5493 2410.77 50.1363C2447.53 69.988 2475.1 98.2952 2493.48 135.058C2512.6 171.085 2522.16 214.097 2522.16 264.094C2522.16 314.091 2512.23 357.839 2492.38 395.336C2473.27 432.099 2444.96 460.774 2407.46 481.361C2369.96 501.948 2324.01 512.241 2269.6 512.241H2045.72V775.828H1881.39ZM2045.72 377.69H2247.54C2282.1 377.69 2308.57 367.764 2326.95 347.913C2346.07 328.061 2355.63 300.489 2355.63 265.197C2355.63 240.934 2351.58 220.714 2343.49 204.539C2335.41 188.363 2323.27 175.864 2307.1 167.041C2291.66 158.218 2271.81 153.807 2247.54 153.807H2045.72V377.69Z" fill="url(#paint1_linear_3311_10229)" fill-opacity="0.9"/>
 4 | <path d="M1353.48 789.065C1234.37 789.065 1142.47 757.449 1077.76 694.217C1013.8 630.25 981.814 531.359 981.814 397.544C981.814 308.579 997.254 235.421 1028.13 178.072C1059.01 119.987 1103.86 76.9747 1162.69 49.0352C1221.51 20.3604 1292.09 6.02307 1374.44 6.02307C1423.7 6.02307 1470.02 11.5374 1513.4 22.5662C1556.78 33.5949 1595.01 50.5057 1628.1 73.2984C1661.92 96.0912 1688.02 124.766 1706.4 159.323C1725.52 193.144 1735.08 233.583 1735.08 280.639H1568.54C1568.54 257.846 1563.4 237.627 1553.1 219.981C1543.54 202.335 1529.94 187.63 1512.3 175.866C1494.65 164.102 1474.43 155.279 1451.64 149.397C1428.85 143.515 1404.95 140.574 1379.95 140.574C1341.72 140.574 1308.26 145.721 1279.59 156.014C1250.92 165.572 1227.02 180.645 1207.9 201.232C1189.52 221.084 1175.55 246.082 1165.99 276.228C1156.44 306.373 1151.66 341.297 1151.66 381.001V414.087C1151.66 469.231 1159.74 514.449 1175.92 549.741C1192.1 585.033 1216.36 611.502 1248.71 629.148C1281.06 646.058 1321.13 654.514 1368.92 654.514C1408.63 654.514 1443.55 648.632 1473.7 636.868C1504.58 624.369 1528.47 606.723 1545.38 583.93C1563.03 561.137 1571.85 533.198 1571.85 500.111V492.391H1345.76V366.663H1735.08V775.83H1627L1612.66 694.217C1590.6 715.539 1566.71 733.186 1540.97 747.155C1515.97 761.125 1488.03 771.419 1457.15 778.036C1426.27 785.388 1391.72 789.065 1353.48 789.065Z" fill="url(#paint2_linear_3311_10229)" fill-opacity="0.9"/>
 5 | <path fill-rule="evenodd" clip-rule="evenodd" d="M6.02344 89.6842C6.02344 50.135 37.9352 18.074 77.3003 18.074H481.202C691.15 18.074 861.346 189.066 861.346 399.995C861.346 610.924 691.15 781.916 481.202 781.916H250.986L47.4726 1009.97C32.9221 1026.28 6.02344 1015.94 6.02344 994.04V89.6842ZM218.262 247.835C218.262 238.435 225.864 230.815 235.241 230.815H480.672C573.696 230.815 649.107 306.405 649.107 399.649C649.107 492.893 573.696 568.483 480.672 568.483H355.38L246.959 686.671C228.889 698.718 218.262 685.675 218.262 674.629V247.835Z" fill="url(#paint3_linear_3311_10229)"/>
 6 | <path fill-rule="evenodd" clip-rule="evenodd" d="M1374.44 12.0468C1292.77 12.0468 1223.14 26.2657 1165.32 54.4498L1165.27 54.4763C1107.63 81.8548 1063.73 123.944 1033.45 180.899L1033.44 180.928C1003.17 237.137 987.837 309.228 987.837 397.544C987.837 530.507 1019.62 627.541 1082 689.935C1145.25 751.736 1235.45 783.042 1353.48 783.042C1391.34 783.042 1425.42 779.401 1455.76 772.177L1455.89 772.145C1486.24 765.641 1513.61 755.546 1538.03 741.898L1538.1 741.862C1563.33 728.165 1586.79 710.848 1608.47 689.887L1616.63 682.003L1632.05 769.807H1729.05V372.687H1351.79V486.368H1577.88V500.112C1577.88 534.302 1568.74 563.575 1550.19 587.566C1532.51 611.369 1507.66 629.618 1475.96 642.452L1475.89 642.479C1444.9 654.57 1409.21 660.538 1368.92 660.538C1320.45 660.538 1279.36 651.965 1245.92 634.486L1245.82 634.437C1212.27 616.134 1187.13 588.657 1170.44 552.251C1153.79 515.913 1145.63 469.759 1145.63 414.087V381.001C1145.63 340.83 1150.47 305.269 1160.25 274.407C1170.03 243.559 1184.41 217.744 1203.48 197.14C1223.32 175.773 1248.09 160.176 1277.62 150.322C1307.07 139.759 1341.22 134.551 1379.95 134.551C1405.43 134.551 1429.83 137.548 1453.14 143.565C1476.52 149.597 1497.37 158.677 1515.64 170.854C1534.03 183.113 1548.31 198.51 1558.36 217.032C1568.29 234.088 1573.61 253.327 1574.45 274.616H1729C1728.22 230.974 1718.86 193.6 1701.16 162.287L1701.08 162.153C1683.18 128.504 1657.77 100.559 1624.73 78.2938L1624.68 78.2591C1592.25 55.9144 1554.68 39.2771 1511.92 28.4042C1469.07 17.5104 1423.25 12.0468 1374.44 12.0468ZM1160.07 43.6073C1219.9 14.4512 1291.42 0 1374.44 0C1424.15 0 1470.97 5.56508 1514.88 16.7288C1558.86 27.9096 1597.75 45.0862 1631.48 68.3154C1666.06 91.6183 1692.82 120.997 1711.68 156.424C1731.38 191.309 1741.1 232.793 1741.1 280.639V286.663H1562.52V280.639C1562.52 258.787 1557.6 239.638 1547.9 223.016L1547.85 222.934L1547.81 222.85C1538.74 206.116 1525.83 192.129 1508.96 180.878C1491.93 169.527 1472.34 160.961 1450.13 155.23C1427.86 149.482 1404.47 146.598 1379.95 146.598C1342.24 146.598 1309.5 151.676 1281.62 161.684L1281.5 161.73C1253.71 170.993 1230.7 185.537 1212.32 205.325C1194.64 224.425 1181.07 248.607 1171.74 278.048C1162.4 307.477 1157.68 341.765 1157.68 381.001V414.087C1157.68 468.703 1165.7 512.985 1181.4 547.231C1197.05 581.393 1220.42 606.846 1251.55 623.835C1282.81 640.162 1321.84 648.491 1368.92 648.491C1408.03 648.491 1442.17 642.699 1471.47 631.271C1501.49 619.115 1524.41 602.092 1540.55 580.341L1540.62 580.242C1557.33 558.657 1565.83 532.07 1565.83 500.112V498.415H1339.74V360.64H1741.1V781.854H1621.94L1608.65 706.226C1588.53 724.502 1566.94 739.91 1543.88 752.433C1518.33 766.704 1489.85 777.184 1458.48 783.911C1427.08 791.382 1392.07 795.088 1353.48 795.088C1233.31 795.088 1139.7 763.171 1073.55 698.525L1073.5 698.477C1007.96 632.937 975.79 532.196 975.79 397.544C975.79 307.931 991.336 233.707 1022.83 175.218M0 89.6845C0 46.8352 34.582 12.0509 77.3003 12.0509H481.202C694.503 12.0509 867.369 185.766 867.369 399.995C867.369 614.225 694.503 787.94 481.202 787.94H253.684L51.9667 1013.98C33.6916 1034.46 0 1021.41 0 994.04V89.6845ZM77.3003 24.0977C41.2882 24.0977 12.0468 53.4354 12.0468 89.6845V994.04C12.0468 1010.47 32.1526 1018.1 42.9784 1005.96L248.288 775.893H481.202C687.797 775.893 855.322 607.625 855.322 399.995C855.322 192.366 687.797 24.0977 481.202 24.0977H77.3003ZM1875.37 13.2327H2275.12C2330.22 13.2327 2376.53 23.6501 2413.69 44.8695C2451.47 65.286 2479.91 94.4615 2498.84 132.299C2518.49 169.358 2528.18 213.362 2528.18 264.094C2528.18 314.894 2518.09 359.637 2497.71 398.144C2497.71 398.147 2497.71 398.151 2497.71 398.155L2492.38 395.337L2497.73 398.116C2497.72 398.125 2497.72 398.134 2497.71 398.144C2478.03 435.986 2448.86 465.505 2410.36 486.641C2371.76 507.831 2324.75 518.265 2269.6 518.265H2051.74V512.241H2045.72V518.265H2051.74V781.852H1875.37V13.2327ZM1887.41 25.2795V769.805H2039.69V506.218H2269.6C2323.27 506.218 2368.16 496.065 2404.56 476.081C2441.05 456.048 2468.49 428.227 2487.04 392.558L2487.06 392.518C2506.38 356.032 2516.14 313.284 2516.14 264.094C2516.14 214.862 2506.73 172.864 2488.16 137.881L2488.1 137.753C2470.28 102.117 2443.6 74.7103 2407.91 55.4366L2407.78 55.3679C2372.9 35.4384 2328.79 25.2795 2275.12 25.2795H1887.41ZM2562.65 13.2327H3226.5V163.139H2982.76V781.852H2805.29V163.139H2562.65V13.2327ZM2574.7 25.2795V151.092H2817.33V769.805H2970.72V151.092H3214.45V25.2795H2574.7ZM2039.69 147.784H2247.54C2272.46 147.784 2293.42 152.303 2310.03 161.781C2327.24 171.18 2340.24 184.565 2348.88 201.845C2357.5 219.093 2361.65 240.304 2361.65 265.197C2361.65 301.566 2351.78 330.785 2331.33 352.045C2311.52 373.422 2283.26 383.714 2247.54 383.714H2039.69V147.784ZM2051.74 159.83V371.667H2247.54C2280.92 371.667 2305.59 362.12 2322.53 343.821L2322.61 343.735C2340.37 325.296 2349.6 299.387 2349.6 265.197C2349.6 241.564 2345.66 222.337 2338.11 207.233C2330.58 192.179 2319.33 180.575 2304.21 172.329L2304.11 172.271C2289.85 164.124 2271.12 159.83 2247.54 159.83H2051.74ZM212.239 247.835C212.239 235.122 222.524 224.792 235.241 224.792H480.672C577.036 224.792 655.13 303.092 655.13 399.649C655.13 496.207 577.036 574.507 480.672 574.507H358.029L250.906 691.279L250.3 691.683C239.904 698.614 230.088 699.168 222.595 694.389C215.629 689.945 212.239 681.805 212.239 674.629V247.835ZM235.241 236.839C229.204 236.839 224.286 241.749 224.286 247.835V674.629C224.286 678.501 226.208 682.404 229.074 684.232C231.351 685.685 235.713 686.721 243.031 682.043L352.732 562.46H480.672C570.356 562.46 643.083 489.58 643.083 399.649C643.083 309.718 570.356 236.839 480.672 236.839H235.241Z" fill="url(#paint4_linear_3311_10229)" fill-opacity="0.6"/>
 7 | <path fill-rule="evenodd" clip-rule="evenodd" d="M1374.44 12.0468C1292.77 12.0468 1223.14 26.2657 1165.32 54.4498L1165.27 54.4763C1107.63 81.8548 1063.73 123.944 1033.45 180.899L1033.44 180.928C1003.17 237.137 987.837 309.228 987.837 397.544C987.837 530.507 1019.62 627.541 1082 689.935C1145.25 751.736 1235.45 783.042 1353.48 783.042C1391.34 783.042 1425.42 779.401 1455.76 772.177L1455.89 772.145C1486.24 765.641 1513.61 755.546 1538.03 741.898L1538.1 741.862C1563.33 728.165 1586.79 710.848 1608.47 689.887L1616.63 682.003L1632.05 769.807H1729.05V372.687H1351.79V486.368H1577.88V500.112C1577.88 534.302 1568.74 563.575 1550.19 587.566C1532.51 611.369 1507.66 629.618 1475.96 642.452L1475.89 642.479C1444.9 654.57 1409.21 660.538 1368.92 660.538C1320.45 660.538 1279.36 651.965 1245.92 634.486L1245.82 634.437C1212.27 616.134 1187.13 588.657 1170.44 552.251C1153.79 515.913 1145.63 469.759 1145.63 414.087V381.001C1145.63 340.83 1150.47 305.269 1160.25 274.407C1170.03 243.559 1184.41 217.744 1203.48 197.14C1223.32 175.773 1248.09 160.176 1277.62 150.322C1307.07 139.759 1341.22 134.551 1379.95 134.551C1405.43 134.551 1429.83 137.548 1453.14 143.565C1476.52 149.597 1497.37 158.677 1515.64 170.854C1534.03 183.113 1548.31 198.51 1558.36 217.032C1568.29 234.088 1573.61 253.327 1574.45 274.616H1729C1728.22 230.974 1718.86 193.6 1701.16 162.287L1701.08 162.153C1683.18 128.504 1657.77 100.559 1624.73 78.2938L1624.68 78.2591C1592.25 55.9144 1554.68 39.2771 1511.92 28.4042C1469.07 17.5104 1423.25 12.0468 1374.44 12.0468ZM1160.07 43.6073C1219.9 14.4512 1291.42 0 1374.44 0C1424.15 0 1470.97 5.56508 1514.88 16.7288C1558.86 27.9096 1597.75 45.0862 1631.48 68.3154C1666.06 91.6183 1692.82 120.997 1711.68 156.424C1731.38 191.309 1741.1 232.793 1741.1 280.639V286.663H1562.52V280.639C1562.52 258.787 1557.6 239.638 1547.9 223.016L1547.85 222.934L1547.81 222.85C1538.74 206.116 1525.83 192.129 1508.96 180.878C1491.93 169.527 1472.34 160.961 1450.13 155.23C1427.86 149.482 1404.47 146.598 1379.95 146.598C1342.24 146.598 1309.5 151.676 1281.62 161.684L1281.5 161.73C1253.71 170.993 1230.7 185.537 1212.32 205.325C1194.64 224.425 1181.07 248.607 1171.74 278.048C1162.4 307.477 1157.68 341.765 1157.68 381.001V414.087C1157.68 468.703 1165.7 512.985 1181.4 547.231C1197.05 581.393 1220.42 606.846 1251.55 623.835C1282.81 640.162 1321.84 648.491 1368.92 648.491C1408.03 648.491 1442.17 642.699 1471.47 631.271C1501.49 619.115 1524.41 602.092 1540.55 580.341L1540.62 580.242C1557.33 558.657 1565.83 532.07 1565.83 500.112V498.415H1339.74V360.64H1741.1V781.854H1621.94L1608.65 706.226C1588.53 724.502 1566.94 739.91 1543.88 752.433C1518.33 766.704 1489.85 777.184 1458.48 783.911C1427.08 791.382 1392.07 795.088 1353.48 795.088C1233.31 795.088 1139.7 763.171 1073.55 698.525L1073.5 698.477C1007.96 632.937 975.79 532.196 975.79 397.544C975.79 307.931 991.336 233.707 1022.83 175.218M0 89.6845C0 46.8352 34.582 12.0509 77.3003 12.0509H481.202C694.503 12.0509 867.369 185.766 867.369 399.995C867.369 614.225 694.503 787.94 481.202 787.94H253.684L51.9667 1013.98C33.6916 1034.46 0 1021.41 0 994.04V89.6845ZM77.3003 24.0977C41.2882 24.0977 12.0468 53.4354 12.0468 89.6845V994.04C12.0468 1010.47 32.1526 1018.1 42.9784 1005.96L248.288 775.893H481.202C687.797 775.893 855.322 607.625 855.322 399.995C855.322 192.366 687.797 24.0977 481.202 24.0977H77.3003ZM1875.37 13.2327H2275.12C2330.22 13.2327 2376.53 23.6501 2413.69 44.8695C2451.47 65.286 2479.91 94.4615 2498.84 132.299C2518.49 169.358 2528.18 213.362 2528.18 264.094C2528.18 314.894 2518.09 359.637 2497.71 398.144C2497.71 398.147 2497.71 398.151 2497.71 398.155L2492.38 395.337L2497.73 398.116C2497.72 398.125 2497.72 398.134 2497.71 398.144C2478.03 435.986 2448.86 465.505 2410.36 486.641C2371.76 507.831 2324.75 518.265 2269.6 518.265H2051.74V512.241H2045.72V518.265H2051.74V781.852H1875.37V13.2327ZM1887.41 25.2795V769.805H2039.69V506.218H2269.6C2323.27 506.218 2368.16 496.065 2404.56 476.081C2441.05 456.048 2468.49 428.227 2487.04 392.558L2487.06 392.518C2506.38 356.032 2516.14 313.284 2516.14 264.094C2516.14 214.862 2506.73 172.864 2488.16 137.881L2488.1 137.753C2470.28 102.117 2443.6 74.7103 2407.91 55.4366L2407.78 55.3679C2372.9 35.4384 2328.79 25.2795 2275.12 25.2795H1887.41ZM2562.65 13.2327H3226.5V163.139H2982.76V781.852H2805.29V163.139H2562.65V13.2327ZM2574.7 25.2795V151.092H2817.33V769.805H2970.72V151.092H3214.45V25.2795H2574.7ZM2039.69 147.784H2247.54C2272.46 147.784 2293.42 152.303 2310.03 161.781C2327.24 171.18 2340.24 184.565 2348.88 201.845C2357.5 219.093 2361.65 240.304 2361.65 265.197C2361.65 301.566 2351.78 330.785 2331.33 352.045C2311.52 373.422 2283.26 383.714 2247.54 383.714H2039.69V147.784ZM2051.74 159.83V371.667H2247.54C2280.92 371.667 2305.59 362.12 2322.53 343.821L2322.61 343.735C2340.37 325.296 2349.6 299.387 2349.6 265.197C2349.6 241.564 2345.66 222.337 2338.11 207.233C2330.58 192.179 2319.33 180.575 2304.21 172.329L2304.11 172.271C2289.85 164.124 2271.12 159.83 2247.54 159.83H2051.74ZM212.239 247.835C212.239 235.122 222.524 224.792 235.241 224.792H480.672C577.036 224.792 655.13 303.092 655.13 399.649C655.13 496.207 577.036 574.507 480.672 574.507H358.029L250.906 691.279L250.3 691.683C239.904 698.614 230.088 699.168 222.595 694.389C215.629 689.945 212.239 681.805 212.239 674.629V247.835ZM235.241 236.839C229.204 236.839 224.286 241.749 224.286 247.835V674.629C224.286 678.501 226.208 682.404 229.074 684.232C231.351 685.685 235.713 686.721 243.031 682.043L352.732 562.46H480.672C570.356 562.46 643.083 489.58 643.083 399.649C643.083 309.718 570.356 236.839 480.672 236.839H235.241Z" fill="url(#paint5_linear_3311_10229)" fill-opacity="0.15"/>
 8 | <defs>
 9 | 
10 | <linearGradient id="paint3_linear_3311_10229" x1="6.02342" y1="1017.95" x2="886.292" y2="40.5368" gradientUnits="userSpaceOnUse">
11 | <stop stop-color="#3333FF"/>
12 | <stop offset="0.5" stop-color="#980194"/>
13 | <stop offset="1" stop-color="#FE0100"/>
14 | </linearGradient>
15 | 
16 | </defs>
17 | </svg>
18 | 
```

--------------------------------------------------------------------------------
/examples/dynamic_sources/rss_reader/Api.py:
--------------------------------------------------------------------------------

```python
  1 | import json
  2 | from pathlib import Path
  3 | 
  4 | import requests
  5 | import urllib3
  6 | import base64
  7 | 
  8 | from httpcore import NetworkError
  9 | 
 10 | from .config import Config
 11 | 
 12 | urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
 13 | 
 14 | 
 15 | def initialize_session(proxy_user, proxy_password, access_header):
 16 |     """Set up the session with proxy authentication."""
 17 |     session = requests.Session()
 18 |     session.verify = False
 19 |     headers = {
 20 |         'Accept': 'application/json',
 21 |         'Content-Type': 'application/json',
 22 |     }
 23 |     if access_header is not None:
 24 |         headers['X-Custom-Header'] = access_header
 25 |     elif proxy_user is not None and proxy_password is not None:
 26 |         auth = base64.b64encode(f"{proxy_user}:{proxy_password}".encode()).decode()
 27 |         headers['Authorization'] = f'Basic {auth}'
 28 |     session.headers.update(headers)
 29 |     return session
 30 | 
 31 | 
 32 | class PrivateGPTAPI:
 33 |     def __init__(self, config, client_api_key=None):
 34 |         """Initialize the chat client with proxy authentication."""
 35 |         self.token = None
 36 |         self.chat_id = None
 37 | 
 38 |         self.base_url = config.get("base_url")
 39 |         self.proxy_user = config.get("proxy_user", None)
 40 |         if self.proxy_user == "":
 41 |             self.proxy_user = None
 42 |         self.proxy_password = config.get("proxy_password", None)
 43 |         if self.proxy_password == "":
 44 |             self.proxy_password = None
 45 |         self.access_header = config.get("access_header", None)
 46 |         if self.access_header == "":
 47 |             self.access_header = None
 48 | 
 49 |         self.chosen_groups = config.get("groups", [])
 50 |         self.language = config.get("language", "en")
 51 |         self.use_public = config.get("use_public", True)
 52 |         self.whitelist_keys = config.get("whitelist_keys", [])
 53 |         self.logged_in = False
 54 | 
 55 |         if client_api_key is not None:
 56 |             self.email, self.password = decrypt_api_key(client_api_key)
 57 |             if len(self.whitelist_keys) > 0:
 58 |                 if client_api_key not in self.whitelist_keys:
 59 |                     print("not authorized")
 60 |         else:
 61 |             self.email =  config.get("email", None)
 62 |             self.password =  config.get("password", None)
 63 | 
 64 |         self.session = initialize_session(self.proxy_user, self.proxy_password, self.access_header)
 65 |         if self.login():
 66 |             self.logged_in = True
 67 | 
 68 |     def login(self):
 69 |         """Authenticate the user and retrieve the token."""
 70 |         url = f"{self.base_url}/login"
 71 |         payload = {"email": self.email, "password": self.password}
 72 |         try:
 73 |             response = self.session.post(url, json=payload)
 74 |             print(response.content)
 75 |             response.raise_for_status()
 76 |             data = response.json()
 77 |             self.token = data['data']['token']
 78 | 
 79 |             # Prüfen, ob der Header bereits existiert
 80 |             if 'Authorization' in self.session.headers:
 81 |                 self.session.headers['Authorization'] += f', Bearer {self.token}'
 82 |             else:
 83 |                 self.session.headers['Authorization'] = f'Bearer {self.token}'
 84 |             self.chat_id = None
 85 |             print("✅ Login successful.")
 86 |             return True
 87 |         except requests.exceptions.RequestException as e:
 88 |             print(f"❌ Login failed: {e}")
 89 |         return False
 90 | 
 91 |     def create_chat(self, user_input):
 92 |         """Start a new chat session.
 93 | 
 94 |         This method sends a POST request to the '/chats' endpoint with the provided parameters.
 95 |         It initializes a new chat session and stores the chat ID for future use.
 96 |         """
 97 |         url = f"{self.base_url}/chats"
 98 |         payload = {
 99 |             "language": self.language,
100 |             "question": user_input,  # Initial question to start the chat
101 |             "usePublic": self.use_public,
102 |             "groups": self.chosen_groups
103 |         }
104 |         try:
105 |             response = self.session.post(url, json=payload)
106 |             response.raise_for_status()  # Raise an exception if the response was not successful
107 |             data = response.json()
108 |             self.chat_id = data['data']['chatId']  # Store the chat ID for future use
109 |             print("✅ Chat initialized.")
110 |             resp = response.json()
111 |             try:
112 |                 answer = resp.get('data', None).get('answer', "error")
113 |             except:
114 |                 print(response.json())
115 |                 resp = {"data":
116 |                             {"answer": "error"}
117 |                         }
118 |                 answer = "error"
119 | 
120 |             if answer.startswith("{\"role\":"):
121 |                 answerj = json.loads(answer)
122 |                 resp["data"]["answer"] = answerj["content"]
123 |                 resp["data"]["chatId"] = "0"
124 | 
125 |             print(f"💡 Response: {answer}")
126 |             return resp
127 |         except requests.exceptions.RequestException as e:
128 |             # It seems we get disconnections from time to time..
129 |             # print(f"⚠️ Failed to get response on first try, trying again..: {e}")
130 |             try:
131 |                 response = self.session.patch(url, json=payload)
132 |                 response.raise_for_status()
133 |                 data = response.json()
134 |                 answer = data.get('data', {}).get('answer', "No answer provided.")
135 |                 print(f"💡 Response: {answer}")
136 |                 return data
137 |             except:
138 |                 print(f"❌ Failed to get response: {e}")
139 |                 return {"error": f"❌ Failed to get response: {e}"}
140 | 
141 |     def list_personal_groups(self):
142 |         url = f"{self.base_url}/groups"
143 |         try:
144 |             resp = self.session.get(url)
145 |             j = json.loads(resp.content)
146 |             data_block = j["data"]
147 |             if not data_block:
148 |                 return []
149 | 
150 |             personal = data_block.get("personalGroups", [])
151 |             return personal
152 | 
153 |         except NetworkError as e:
154 |             return []
155 | 
156 |     def get_document_info(self, id):
157 |         url = f"{self.base_url}/sources/{id }"
158 |         try:
159 |             resp = self.session.get(url)
160 |             j = json.loads(resp.content)
161 |             data_block = j["data"]
162 |             if not data_block:
163 |                 return []
164 | 
165 |             return data_block
166 | 
167 |         except NetworkError as e:
168 |             return []
169 | 
170 |     def query_private_gpt(self, user_input) -> json:
171 |         """Send a question to the chat and retrieve the response."""
172 |         if not self.chat_id:
173 |             print("❌ Chat session not initialized.")
174 |             return False
175 |         url = f"{self.base_url}/chats/{self.chat_id}"
176 |         payload = {"question": user_input}
177 |         try:
178 |             response = self.session.patch(url, json=payload)
179 |             # response.raise_for_status()
180 |             resp = response.json()
181 |             try:
182 |                 answer = resp.get('data', None).get('answer', "error")
183 |             except:
184 |                 print(response.json())
185 |                 resp = {"data":
186 |                             {"answer": "error"}
187 |                         }
188 |                 answer = "error"
189 | 
190 |             if answer.startswith("{\"role\":"):
191 |                 answerj = json.loads(answer)
192 |                 resp["data"]["answer"] = answerj["content"]
193 |                 resp["data"]["chatId"] = "0"
194 | 
195 |             print(f"💡 Response: {answer}")
196 |             return resp
197 |         except requests.exceptions.RequestException as e:
198 |             # It seems we get disconnections from time to time..
199 |             # print(f"⚠️ Failed to get response on first try, trying again..: {e}")
200 |             try:
201 |                 response = self.session.patch(url, json=payload)
202 |                 response.raise_for_status()
203 |                 data = response.json()
204 |                 answer = data.get('data', {}).get('answer', "No answer provided.")
205 |                 print(f"💡 Response: {answer}")
206 |                 return data
207 |             except:
208 |                 print(f"❌ Failed to get response: {e}")
209 |                 return {"error": f"❌ Failed to get response: {e}"}
210 | 
211 | 
212 |     def add_source(self, markdown, groups, name):
213 |         """Send a source id to retrieve details. Working with version 1.3.3 and newer"""
214 |         url = f"{self.base_url}/sources"
215 |         try:
216 | 
217 |             payload = {
218 |                 "name": name,
219 |                 "groups": groups,
220 |                 "content": markdown
221 |             }
222 | 
223 |             resp = self.session.post(url, json=payload)
224 |             j = json.loads(resp.content)
225 |             data_block = j["data"]
226 |             if not data_block:
227 |                 return []
228 | 
229 |             return data_block
230 | 
231 |         except requests.exceptions.RequestException as e:
232 |             print(f"❌ Failed to get response: {e}")
233 |             return {"error": f"❌ Failed to get response: {e}"}
234 | 
235 |     def update_source(self, source_id, markdown=None, groups=None, name=None):
236 |         """Edit an existing Source"""
237 |         url = f"{self.base_url}/sources/{source_id}"
238 | 
239 |         try:
240 |             payload = {}
241 |             if groups is None:
242 |                 existing_groups = self.get_document_info(source_id)["groups"]
243 |                 payload["groups"] = existing_groups
244 |             else:
245 |                 payload["groups"] = groups
246 | 
247 |             if markdown is not None:
248 |                 payload["content"] = markdown
249 |             if name is not None:
250 |                 payload["name"] = name
251 | 
252 |             resp = self.session.patch(url, json=payload)
253 | 
254 |             j = json.loads(resp.content)
255 |             data_block = j["data"]
256 |             if not data_block:
257 |                 return []
258 | 
259 |             return data_block
260 | 
261 |         except requests.exceptions.RequestException as e:
262 |             print(f"❌ Failed to get response: {e}")
263 |             return {"error": f"❌ Failed to get response: {e}"}
264 | 
265 |     def delete_source(self, source_id):
266 |         """Send a source id to retrieve details. Working with version 1.3.3 and newer"""
267 |         url = f"{self.base_url}/sources/{source_id}"
268 |         try:
269 | 
270 |             resp = self.session.delete(url)
271 |             j = json.loads(resp.content)
272 |             message = j["message"]
273 |             if not message:
274 |                 return "failed"
275 | 
276 |             return message
277 | 
278 | 
279 |         except requests.exceptions.RequestException as e:
280 |             print(f"❌ Failed to get response: {e}")
281 |             return {"error": f"❌ Failed to get response: {e}"}
282 | 
283 | 
284 |     def get_sources_from_group(self, group):
285 |         """Send a source id to retrieve details. Working with version 1.3.3 and newer"""
286 |         url = f"{self.base_url}/sources/groups"
287 |         try:
288 | 
289 |             payload = {
290 |                 "groupName": group
291 |             }
292 | 
293 |             resp = self.session.post(url, json=payload)
294 |             j = json.loads(resp.content)
295 |             data_block = j["data"]
296 |             if not data_block:
297 |                 return []
298 | 
299 |             sources = []
300 |             for source in data_block["sources"]:
301 |                 doc = self.get_document_info(source)
302 |                 sources.append(doc)
303 | 
304 | 
305 |             return sources
306 | 
307 | 
308 |         except requests.exceptions.RequestException as e:
309 |             print(f"❌ Failed to get response: {e}")
310 |             return {"error": f"❌ Failed to get response: {e}"}
311 | 
312 |     def respond_with_context(self, messages, response_format=None, request_tools=None):
313 |         last_user_message = next((p for p in reversed(messages) if p["role"] == "user"), None)
314 |         user_input = ""
315 | 
316 |         for message in messages:
317 |             if message["role"] == "system":
318 |                 user_input = str(message) + "\n"
319 | 
320 |         if last_user_message is not None:
321 |             user_input += last_user_message["content"]
322 | 
323 |         last_assistant_message = next((p for p in reversed(messages) if p["role"] == "assistant"), None)
324 |         last_tool_message = next((p for p in reversed(messages) if p["role"] == "tool"), None)
325 | 
326 |         hastoolresult = False
327 |         if last_tool_message is not None and last_assistant_message is not None and last_assistant_message.tool_calls is not None and len(
328 |                 last_assistant_message.tool_calls) > 0:
329 |             user_input += "\nYou called the tool: " + str(
330 |                 last_assistant_message.tool_calls[0]) + ". The result was: " + last_tool_message.content
331 |             hastoolresult = True
332 | 
333 |         print(f"💁 Request: " + user_input)
334 | 
335 |         # PGPT manages history and context itself so we don't need to forward the history.
336 |         add_context = False
337 |         if add_context:
338 |             messages.pop()
339 |             user_input += "\nHere is some context about the previous conversation:\n"
340 |             for message in messages:
341 |                 user_input += f"{message.role}: {message.content}\n"
342 | 
343 |         if response_format is not None:
344 |             print("Response format: " + str(response_format))
345 |             user_input += add_response_format(response_format)
346 | 
347 |         if request_tools is not None and not hastoolresult:
348 |             user_input += add_tools(request_tools, last_tool_message)
349 | 
350 |         if not self.logged_in:
351 |             self.login()
352 |         else:
353 |             if self.chat_id is None:
354 |                 result = self.create_chat(user_input)
355 |             else:
356 |                 result = self.query_private_gpt(user_input)
357 | 
358 |             if 'data' in result:
359 |                 response_data = result.get("data")
360 |                 if request_tools is not None and not hastoolresult and is_json(
361 |                         clean_response(response_data.get("answer"))):
362 |                     response_data["tool_call"] = clean_response(response_data.get("answer", ""))
363 |                 return response_data
364 |             elif 'error' in result:
365 |                 # Try to login again and send the query once more on error.
366 |                 if self.login():
367 |                     if self.chat_id is None:
368 |                         result = self.create_chat(user_input)
369 |                     else:
370 |                         result = self.query_private_gpt(user_input)
371 | 
372 |                     if 'data' in result:
373 |                         return result['data']
374 |                     else:
375 |                         return result
376 | 
377 |             else:
378 |                 return result
379 | 
380 | 
381 | def is_json(myjson):
382 |     try:
383 |         json.loads(myjson)
384 |     except ValueError as e:
385 |         return False
386 |     return True
387 | 
388 | 
389 | def add_response_format(response_format):
390 |     # prompt = "\nPlease fill in the following template with realistic and appropriate information. Be creative. The field 'type' defines the output format. In your reply, only return the generated json\n"
391 |     prompt = "\nPlease fill in the following json template with realistic and appropriate information. In your reply, only return the generated json. If you can't answer return an empty json.\n"
392 |     prompt += json.dumps(response_format)
393 |     return prompt
394 | 
395 | 
396 | def add_tools(response_tools, last_tool_message):
397 |     prompt = "\nPlease select the fitting provided tool to create your answer. Only return the generated result of the tool. Do not describe what you are doing, just return the json.\n"
398 |     index = 1
399 |     for tool in response_tools:
400 |         prompt += "\n" + json.dumps(tool) + "\n"
401 |         index += 1
402 | 
403 |     return prompt
404 | 
405 | 
406 | def clean_response(response):
407 |     # Remove artefacts from reply here
408 |     response = response.replace("[TOOL_CALLS]", "")
409 |     return response
410 | 
411 | 
412 | def decrypt_api_key(api_key):
413 |     """
414 |     This is PoC code and methods should be replaced with a more secure way to deal with credentials (e.g. in a db)
415 |     """
416 |     try:
417 |         base64_bytes = api_key.encode("ascii")
418 |         decoded_string_bytes = base64.b64decode(base64_bytes)
419 |         decoded_key = decoded_string_bytes.decode("ascii")
420 |     except Exception as e:
421 |         print(e)
422 |         decoded_key = "invalid:invalid"
423 | 
424 |     return decoded_key.split(":")[0], decoded_key.split(":")[1]
425 | 
426 | 
427 | def main():
428 |     """Main function to run the chat application."""
429 |     config_file = Path.absolute(Path(__file__).parent.parent / "pgpt_openai_api_proxy.json")
430 |     config = Config(config_file=config_file, required_fields=["base_url"])
431 |     chat = PrivateGPTAPI(config)
432 | 
433 |     print("Type your questions below. Type 'quit' to exit.")
434 |     while True:
435 |         try:
436 |             question = input("❓ Question: ").strip()
437 |             if question.lower() == 'quit':
438 |                 break
439 |             if question:
440 |                 chat.query_private_gpt(question)
441 |         except KeyboardInterrupt:
442 |             print("\nExiting chat...")
443 |             break
444 |         except Exception as e:
445 |             print(f"❌ Error: {str(e)}")
446 |             break
447 | 
448 | 
449 | if __name__ == "__main__":
450 |     main()
```

--------------------------------------------------------------------------------
/clients/Gradio/mcp_servers/pgpt/Api.py:
--------------------------------------------------------------------------------

```python
  1 | import json
  2 | from pathlib import Path
  3 | 
  4 | import requests
  5 | import urllib3
  6 | import base64
  7 | 
  8 | from httpcore import NetworkError
  9 | 
 10 | from config import Config
 11 | 
 12 | urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
 13 | 
 14 | 
 15 | def initialize_session(proxy_user, proxy_password, access_header):
 16 |     """Set up the session with proxy authentication."""
 17 |     session = requests.Session()
 18 |     session.verify = False
 19 |     headers = {
 20 |         'Accept': 'application/json',
 21 |         'Content-Type': 'application/json',
 22 |     }
 23 |     if access_header is not None:
 24 |         headers['X-Custom-Header'] = access_header
 25 |     elif proxy_user is not None and proxy_password is not None:
 26 |         auth = base64.b64encode(f"{proxy_user}:{proxy_password}".encode()).decode()
 27 |         headers['Authorization'] = f'Basic {auth}'
 28 |     session.headers.update(headers)
 29 |     return session
 30 | 
 31 | 
 32 | class PrivateGPTAPI:
 33 |     def __init__(self, config, client_api_key=None):
 34 |         """Initialize the chat client with proxy authentication."""
 35 |         self.token = None
 36 |         self.chat_id = None
 37 | 
 38 |         self.base_url = config.get("base_url")
 39 |         self.proxy_user = config.get("proxy_user", None)
 40 |         if self.proxy_user == "":
 41 |             self.proxy_user = None
 42 |         self.proxy_password = config.get("proxy_password", None)
 43 |         if self.proxy_password == "":
 44 |             self.proxy_password = None
 45 |         self.access_header = config.get("access_header", None)
 46 |         if self.access_header == "":
 47 |             self.access_header = None
 48 | 
 49 |         self.chosen_groups = config.get("groups", [])
 50 |         self.language = config.get("language", "en")
 51 |         self.use_public = config.get("use_public", True)
 52 |         self.whitelist_keys = config.get("whitelist_keys", [])
 53 |         self.logged_in = False
 54 | 
 55 |         if client_api_key is not None:
 56 |             self.email, self.password = decrypt_api_key(client_api_key)
 57 |             if len(self.whitelist_keys) > 0:
 58 |                 if client_api_key not in self.whitelist_keys:
 59 |                     print("not authorized")
 60 |         else:
 61 |             self.email =  config.get("email", None)
 62 |             self.password =  config.get("password", None)
 63 | 
 64 |         self.session = initialize_session(self.proxy_user, self.proxy_password, self.access_header)
 65 |         if self.login():
 66 |             self.logged_in = True
 67 | 
 68 |     def login(self):
 69 |         """Authenticate the user and retrieve the token."""
 70 |         url = f"{self.base_url}/login"
 71 |         payload = {"email": self.email, "password": self.password}
 72 |         try:
 73 |             response = self.session.post(url, json=payload)
 74 |             print(response.content)
 75 |             response.raise_for_status()
 76 |             data = response.json()
 77 |             self.token = data['data']['token']
 78 | 
 79 |             # Prüfen, ob der Header bereits existiert
 80 |             if 'Authorization' in self.session.headers:
 81 |                 self.session.headers['Authorization'] += f', Bearer {self.token}'
 82 |             else:
 83 |                 self.session.headers['Authorization'] = f'Bearer {self.token}'
 84 |             self.chat_id = None
 85 |             print("✅ Login successful.")
 86 |             return True
 87 |         except requests.exceptions.RequestException as e:
 88 |             print(f"❌ Login failed: {e}")
 89 |         return False
 90 | 
 91 |     def create_chat(self, user_input):
 92 |         """Start a new chat session.
 93 | 
 94 |         This method sends a POST request to the '/chats' endpoint with the provided parameters.
 95 |         It initializes a new chat session and stores the chat ID for future use.
 96 |         """
 97 |         url = f"{self.base_url}/chats"
 98 |         payload = {
 99 |             "language": self.language,
100 |             "question": user_input,  # Initial question to start the chat
101 |             "usePublic": self.use_public,
102 |             "groups": self.chosen_groups
103 |         }
104 |         try:
105 |             response = self.session.post(url, json=payload)
106 |             response.raise_for_status()  # Raise an exception if the response was not successful
107 |             data = response.json()
108 |             self.chat_id = data['data']['chatId']  # Store the chat ID for future use
109 |             print("✅ Chat initialized.")
110 |             resp = response.json()
111 |             try:
112 |                 answer = resp.get('data', None).get('answer', "error")
113 |             except:
114 |                 print(response.json())
115 |                 resp = {"data":
116 |                             {"answer": "error"}
117 |                         }
118 |                 answer = "error"
119 | 
120 |             if answer.startswith("{\"role\":"):
121 |                 answerj = json.loads(answer)
122 |                 resp["data"]["answer"] = answerj["content"]
123 |                 resp["data"]["chatId"] = "0"
124 | 
125 |             print(f"💡 Response: {answer}")
126 |             return resp
127 |         except requests.exceptions.RequestException as e:
128 |             # It seems we get disconnections from time to time..
129 |             # print(f"⚠️ Failed to get response on first try, trying again..: {e}")
130 |             try:
131 |                 response = self.session.patch(url, json=payload)
132 |                 response.raise_for_status()
133 |                 data = response.json()
134 |                 answer = data.get('data', {}).get('answer', "No answer provided.")
135 |                 print(f"💡 Response: {answer}")
136 |                 return data
137 |             except:
138 |                 print(f"❌ Failed to get response: {e}")
139 |                 return {"error": f"❌ Failed to get response: {e}"}
140 | 
141 |     def list_personal_groups(self):
142 |         url = f"{self.base_url}/groups"
143 |         try:
144 |             resp = self.session.get(url)
145 |             try:
146 |                 j = json.loads(resp.content)
147 |                 data_block = j["data"]
148 |                 if not data_block:
149 |                     return []
150 | 
151 |                 personal = data_block.get("personalGroups", [])
152 |                 return personal
153 |             except:
154 |                 return []
155 | 
156 |         except NetworkError as e:
157 |             return []
158 | 
159 |     def get_document_info(self, id):
160 |         url = f"{self.base_url}/sources/{id }"
161 |         try:
162 |             resp = self.session.get(url)
163 |             j = json.loads(resp.content)
164 |             data_block = j["data"]
165 |             if not data_block:
166 |                 return []
167 | 
168 |             return data_block
169 | 
170 |         except NetworkError as e:
171 |             return []
172 | 
173 |     def query_private_gpt(self, user_input) -> json:
174 |         """Send a question to the chat and retrieve the response."""
175 |         if not self.chat_id:
176 |             print("❌ Chat session not initialized.")
177 |             return False
178 |         url = f"{self.base_url}/chats/{self.chat_id}"
179 |         payload = {"question": user_input}
180 |         try:
181 |             response = self.session.patch(url, json=payload)
182 |             # response.raise_for_status()
183 |             resp = response.json()
184 |             try:
185 |                 answer = resp.get('data', None).get('answer', "error")
186 |             except:
187 |                 print(response.json())
188 |                 resp = {"data":
189 |                             {"answer": "error"}
190 |                         }
191 |                 answer = "error"
192 | 
193 |             if answer.startswith("{\"role\":"):
194 |                 answerj = json.loads(answer)
195 |                 resp["data"]["answer"] = answerj["content"]
196 |                 resp["data"]["chatId"] = "0"
197 | 
198 |             print(f"💡 Response: {answer}")
199 |             return resp
200 |         except requests.exceptions.RequestException as e:
201 |             # It seems we get disconnections from time to time..
202 |             # print(f"⚠️ Failed to get response on first try, trying again..: {e}")
203 |             try:
204 |                 response = self.session.patch(url, json=payload)
205 |                 response.raise_for_status()
206 |                 data = response.json()
207 |                 answer = data.get('data', {}).get('answer', "No answer provided.")
208 |                 print(f"💡 Response: {answer}")
209 |                 return data
210 |             except:
211 |                 print(f"❌ Failed to get response: {e}")
212 |                 return {"error": f"❌ Failed to get response: {e}"}
213 | 
214 |     def add_user(self, userName, userEmail, userPassword, userGroups):
215 |         """Add a user"""
216 |         url = f"{self.base_url}/users"
217 |         try:
218 | 
219 |             payload = {  # necessary name, email, password, usePublic
220 |                 "name": userName,
221 |                 "email": userEmail,
222 |                 "password": userPassword,
223 |                 "usePublic": False,
224 |                 "language": "en",  # optional - defaults to "en"
225 |                 # "timezone": "UTC", # optional - defaults to "Europe/Berlin"
226 |                 "groups": userGroups,
227 |                 "roles": ["documents"]
228 |                 # "activateFtp": true,
229 |                 # "ftpPassword": "myFTP-Password1337"
230 |             }
231 | 
232 |             resp = self.session.post(url, json=payload)
233 |             j = json.loads(resp.content)
234 |             data_block = j["message"]
235 |             if not data_block:
236 |                 return "failed"
237 | 
238 |             return data_block
239 | 
240 | 
241 |         except requests.exceptions.RequestException as e:
242 |             print(f"❌ Failed to get response: {e}")
243 |             return {"error": f"❌ Failed to get response: {e}"}
244 | 
245 |     def add_source(self, markdown, groups, name):
246 |         """Send a source id to retrieve details. Working with version 1.3.3 and newer"""
247 |         url = f"{self.base_url}/sources"
248 |         try:
249 | 
250 |             payload = {
251 |                 "name": name,
252 |                 "groups": groups,
253 |                 "content": markdown
254 |             }
255 | 
256 |             resp = self.session.post(url, json=payload)
257 |             j = json.loads(resp.content)
258 |             data_block = j["data"]
259 |             if not data_block:
260 |                 return []
261 | 
262 |             return data_block
263 | 
264 | 
265 |         except requests.exceptions.RequestException as e:
266 |             print(f"❌ Failed to get response: {e}")
267 |             return {"error": f"❌ Failed to get response: {e}"}
268 | 
269 |     def delete_source(self, source_id):
270 |         """Send a source id to retrieve details. Working with version 1.3.3 and newer"""
271 |         url = f"{self.base_url}/sources/{source_id}"
272 |         try:
273 | 
274 |             resp = self.session.delete(url)
275 |             j = json.loads(resp.content)
276 |             message = j["message"]
277 |             if not message:
278 |                 return "failed"
279 | 
280 |             return message
281 | 
282 | 
283 |         except requests.exceptions.RequestException as e:
284 |             print(f"❌ Failed to get response: {e}")
285 |             return {"error": f"❌ Failed to get response: {e}"}
286 | 
287 | 
288 |     def get_sources_from_group(self, group):
289 |         """Send a source id to retrieve details. Working with version 1.3.3 and newer"""
290 |         url = f"{self.base_url}/sources/groups"
291 |         try:
292 | 
293 |             payload = {
294 |                 "groupName": group
295 |             }
296 | 
297 |             resp = self.session.post(url, json=payload)
298 |             j = json.loads(resp.content)
299 |             data_block = j["data"]
300 |             if not data_block:
301 |                 return []
302 | 
303 |             sources = []
304 |             for source in data_block["sources"]:
305 |                 doc = self.get_document_info(source)
306 |                 sources.append(doc)
307 | 
308 | 
309 |             return sources
310 | 
311 | 
312 |         except requests.exceptions.RequestException as e:
313 |             print(f"❌ Failed to get response: {e}")
314 |             return []
315 | 
316 |     def respond_with_context(self, messages, response_format=None, request_tools=None):
317 |         last_user_message = next((p for p in reversed(messages) if p["role"] == "user"), None)
318 |         user_input = ""
319 | 
320 |         for message in messages:
321 |             if message["role"] == "system":
322 |                 user_input = str(message) + "\n"
323 | 
324 |         if last_user_message is not None:
325 |             user_input += last_user_message["content"]
326 | 
327 |         last_assistant_message = next((p for p in reversed(messages) if p["role"] == "assistant"), None)
328 |         last_tool_message = next((p for p in reversed(messages) if p["role"] == "tool"), None)
329 | 
330 |         hastoolresult = False
331 |         if last_tool_message is not None and last_assistant_message is not None and last_assistant_message.tool_calls is not None and len(
332 |                 last_assistant_message.tool_calls) > 0:
333 |             user_input += "\nYou called the tool: " + str(
334 |                 last_assistant_message.tool_calls[0]) + ". The result was: " + last_tool_message.content
335 |             hastoolresult = True
336 | 
337 |         print(f"💁 Request: " + user_input)
338 | 
339 |         # PGPT manages history and context itself so we don't need to forward the history.
340 |         add_context = False
341 |         if add_context:
342 |             messages.pop()
343 |             user_input += "\nHere is some context about the previous conversation:\n"
344 |             for message in messages:
345 |                 user_input += f"{message.role}: {message.content}\n"
346 | 
347 |         if response_format is not None:
348 |             print("Response format: " + str(response_format))
349 |             user_input += add_response_format(response_format)
350 | 
351 |         if request_tools is not None and not hastoolresult:
352 |             user_input += add_tools(request_tools, last_tool_message)
353 | 
354 |         if not self.logged_in:
355 |             self.login()
356 |         else:
357 |             if self.chat_id is None:
358 |                 result = self.create_chat(user_input)
359 |             else:
360 |                 result = self.query_private_gpt(user_input)
361 | 
362 |             if 'data' in result:
363 |                 response_data = result.get("data")
364 |                 if request_tools is not None and not hastoolresult and is_json(
365 |                         clean_response(response_data.get("answer"))):
366 |                     response_data["tool_call"] = clean_response(response_data.get("answer", ""))
367 |                 return response_data
368 |             elif 'error' in result:
369 |                 # Try to login again and send the query once more on error.
370 |                 if self.login():
371 |                     if self.chat_id is None:
372 |                         result = self.create_chat(user_input)
373 |                     else:
374 |                         result = self.query_private_gpt(user_input)
375 | 
376 |                     if 'data' in result:
377 |                         return result['data']
378 |                     else:
379 |                         return result
380 | 
381 |             else:
382 |                 return result
383 | 
384 | 
385 | def is_json(myjson):
386 |     try:
387 |         json.loads(myjson)
388 |     except ValueError as e:
389 |         return False
390 |     return True
391 | 
392 | 
393 | def add_response_format(response_format):
394 |     # prompt = "\nPlease fill in the following template with realistic and appropriate information. Be creative. The field 'type' defines the output format. In your reply, only return the generated json\n"
395 |     prompt = "\nPlease fill in the following json template with realistic and appropriate information. In your reply, only return the generated json. If you can't answer return an empty json.\n"
396 |     prompt += json.dumps(response_format)
397 |     return prompt
398 | 
399 | 
400 | def add_tools(response_tools, last_tool_message):
401 |     prompt = "\nPlease select the fitting provided tool to create your answer. Only return the generated result of the tool. Do not describe what you are doing, just return the json.\n"
402 |     index = 1
403 |     for tool in response_tools:
404 |         prompt += "\n" + json.dumps(tool) + "\n"
405 |         index += 1
406 | 
407 |     return prompt
408 | 
409 | 
410 | def clean_response(response):
411 |     # Remove artefacts from reply here
412 |     response = response.replace("[TOOL_CALLS]", "")
413 |     return response
414 | 
415 | 
416 | def decrypt_api_key(api_key):
417 |     """
418 |     This is PoC code and methods should be replaced with a more secure way to deal with credentials (e.g. in a db)
419 |     """
420 |     try:
421 |         base64_bytes = api_key.encode("ascii")
422 |         decoded_string_bytes = base64.b64decode(base64_bytes)
423 |         decoded_key = decoded_string_bytes.decode("ascii")
424 |     except Exception as e:
425 |         print(e)
426 |         decoded_key = "invalid:invalid"
427 | 
428 |     return decoded_key.split(":")[0], decoded_key.split(":")[1]
429 | 
430 | 
431 | def main():
432 |     """Main function to run the chat application."""
433 |     config_file = Path.absolute(Path(__file__).parent.parent / "pgpt_openai_api_proxy.json")
434 |     config = Config(config_file=config_file, required_fields=["base_url"])
435 |     chat = PrivateGPTAPI(config)
436 | 
437 |     print("Type your questions below. Type 'quit' to exit.")
438 |     while True:
439 |         try:
440 |             question = input("❓ Question: ").strip()
441 |             if question.lower() == 'quit':
442 |                 break
443 |             if question:
444 |                 chat.query_private_gpt(question)
445 |         except KeyboardInterrupt:
446 |             print("\nExiting chat...")
447 |             break
448 |         except Exception as e:
449 |             print(f"❌ Error: {str(e)}")
450 |             break
451 | 
452 | 
453 | if __name__ == "__main__":
454 |     main()
```

--------------------------------------------------------------------------------
/examples/sftp_upload_with_id/Api.py:
--------------------------------------------------------------------------------

```python
  1 | import json
  2 | import os
  3 | import posixpath
  4 | from pathlib import Path
  5 | from time import sleep
  6 | 
  7 | import paramiko
  8 | import requests
  9 | import urllib3
 10 | import base64
 11 | 
 12 | from httpcore import NetworkError
 13 | 
 14 | from .config import Config
 15 | 
 16 | urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
 17 | 
 18 | 
 19 | def initialize_session(proxy_user, proxy_password, access_header):
 20 |     """Set up the session with proxy authentication."""
 21 |     session = requests.Session()
 22 |     session.verify = False
 23 |     headers = {
 24 |         'Accept': 'application/json',
 25 |         'Content-Type': 'application/json',
 26 |     }
 27 |     if access_header is not None:
 28 |         headers['X-Custom-Header'] = access_header
 29 |     elif proxy_user is not None and proxy_password is not None:
 30 |         auth = base64.b64encode(f"{proxy_user}:{proxy_password}".encode()).decode()
 31 |         headers['Authorization'] = f'Basic {auth}'
 32 |     session.headers.update(headers)
 33 |     return session
 34 | 
 35 | 
 36 | class PrivateGPTAPI:
 37 |     def __init__(self, config, client_api_key=None):
 38 |         """Initialize the chat client with proxy authentication."""
 39 |         self.token = None
 40 |         self.chat_id = None
 41 | 
 42 |         self.base_url = config.get("base_url")
 43 |         self.proxy_user = config.get("proxy_user", None)
 44 |         if self.proxy_user == "":
 45 |             self.proxy_user = None
 46 |         self.proxy_password = config.get("proxy_password", None)
 47 |         if self.proxy_password == "":
 48 |             self.proxy_password = None
 49 |         self.access_header = config.get("access_header", None)
 50 |         if self.access_header == "":
 51 |             self.access_header = None
 52 | 
 53 |         self.chosen_groups = config.get("groups", [])
 54 |         self.language = config.get("language", "en")
 55 |         self.use_public = config.get("use_public", True)
 56 |         self.whitelist_keys = config.get("whitelist_keys", [])
 57 |         self.logged_in = False
 58 | 
 59 |         if client_api_key is not None:
 60 |             self.email, self.password = decrypt_api_key(client_api_key)
 61 |             if len(self.whitelist_keys) > 0:
 62 |                 if client_api_key not in self.whitelist_keys:
 63 |                     print("not authorized")
 64 |         else:
 65 |             self.email =  config.get("email", None)
 66 |             self.password =  config.get("password", None)
 67 |             self.ftp_password = config.get("ftp_password", None)
 68 | 
 69 | 
 70 |         self.session = initialize_session(self.proxy_user, self.proxy_password, self.access_header)
 71 |         if self.login():
 72 |             self.logged_in = True
 73 | 
 74 |         if self.ftp_password is not None:
 75 |             self.ftp_host = config.get("ftp_host", None)
 76 |             self.ftp_port = config.get("ftp_port", None)
 77 |             self.ftp_folder = config.get("ftp_folder", "/")
 78 |             self.ftp_subfolder = config.get("ftp_subfolder", "temp")
 79 | 
 80 |     def login(self):
 81 |         """Authenticate the user and retrieve the token."""
 82 |         url = f"{self.base_url}/login"
 83 |         payload = {"email": self.email, "password": self.password}
 84 |         try:
 85 |             response = self.session.post(url, json=payload)
 86 |             print(response.content)
 87 |             response.raise_for_status()
 88 |             data = response.json()
 89 |             self.token = data['data']['token']
 90 | 
 91 |             # Prüfen, ob der Header bereits existiert
 92 |             if 'Authorization' in self.session.headers:
 93 |                 self.session.headers['Authorization'] += f', Bearer {self.token}'
 94 |             else:
 95 |                 self.session.headers['Authorization'] = f'Bearer {self.token}'
 96 |             self.chat_id = None
 97 |             print("✅ Login successful.")
 98 |             return True
 99 |         except requests.exceptions.RequestException as e:
100 |             print(f"❌ Login failed: {e}")
101 |         return False
102 | 
103 |     def create_chat(self, user_input):
104 |         """Start a new chat session.
105 | 
106 |         This method sends a POST request to the '/chats' endpoint with the provided parameters.
107 |         It initializes a new chat session and stores the chat ID for future use.
108 |         """
109 |         url = f"{self.base_url}/chats"
110 |         payload = {
111 |             "language": self.language,
112 |             "question": user_input,  # Initial question to start the chat
113 |             "usePublic": self.use_public,
114 |             "groups": self.chosen_groups
115 |         }
116 |         try:
117 |             response = self.session.post(url, json=payload)
118 |             response.raise_for_status()  # Raise an exception if the response was not successful
119 |             data = response.json()
120 |             self.chat_id = data['data']['chatId']  # Store the chat ID for future use
121 |             print("✅ Chat initialized.")
122 |             resp = response.json()
123 |             try:
124 |                 answer = resp.get('data', None).get('answer', "error")
125 |             except:
126 |                 print(response.json())
127 |                 resp = {"data":
128 |                             {"answer": "error"}
129 |                         }
130 |                 answer = "error"
131 | 
132 |             if answer.startswith("{\"role\":"):
133 |                 answerj = json.loads(answer)
134 |                 resp["data"]["answer"] = answerj["content"]
135 |                 resp["data"]["chatId"] = "0"
136 | 
137 |             print(f"💡 Response: {answer}")
138 |             return resp
139 |         except requests.exceptions.RequestException as e:
140 |             # It seems we get disconnections from time to time..
141 |             # print(f"⚠️ Failed to get response on first try, trying again..: {e}")
142 |             try:
143 |                 response = self.session.patch(url, json=payload)
144 |                 response.raise_for_status()
145 |                 data = response.json()
146 |                 answer = data.get('data', {}).get('answer', "No answer provided.")
147 |                 print(f"💡 Response: {answer}")
148 |                 return data
149 |             except:
150 |                 print(f"❌ Failed to get response: {e}")
151 |                 return {"error": f"❌ Failed to get response: {e}"}
152 | 
153 |     def list_personal_groups(self):
154 |         url = f"{self.base_url}/groups"
155 |         try:
156 |             resp = self.session.get(url)
157 |             try:
158 |                 j = json.loads(resp.content)
159 |                 data_block = j["data"]
160 |                 if not data_block:
161 |                     return []
162 | 
163 |                 personal = data_block.get("personalGroups", [])
164 |                 return personal
165 |             except:
166 |                 return []
167 | 
168 |         except NetworkError as e:
169 |             return []
170 | 
171 |     def get_document_info(self, id):
172 |         url = f"{self.base_url}/sources/{id }"
173 |         try:
174 |             resp = self.session.get(url)
175 |             j = json.loads(resp.content)
176 |             data_block = j["data"]
177 |             if not data_block:
178 |                 return []
179 | 
180 |             return data_block
181 | 
182 |         except NetworkError as e:
183 |             return []
184 | 
185 |     def query_private_gpt(self, user_input) -> json:
186 |         """Send a question to the chat and retrieve the response."""
187 |         if not self.chat_id:
188 |             print("❌ Chat session not initialized.")
189 |             return False
190 |         url = f"{self.base_url}/chats/{self.chat_id}"
191 |         payload = {"question": user_input}
192 |         try:
193 |             response = self.session.patch(url, json=payload)
194 |             # response.raise_for_status()
195 |             resp = response.json()
196 |             try:
197 |                 answer = resp.get('data', None).get('answer', "error")
198 |             except:
199 |                 print(response.json())
200 |                 resp = {"data":
201 |                             {"answer": "error"}
202 |                         }
203 |                 answer = "error"
204 | 
205 |             if answer.startswith("{\"role\":"):
206 |                 answerj = json.loads(answer)
207 |                 resp["data"]["answer"] = answerj["content"]
208 |                 resp["data"]["chatId"] = "0"
209 | 
210 |             print(f"💡 Response: {answer}")
211 |             return resp
212 |         except requests.exceptions.RequestException as e:
213 |             # It seems we get disconnections from time to time..
214 |             # print(f"⚠️ Failed to get response on first try, trying again..: {e}")
215 |             try:
216 |                 response = self.session.patch(url, json=payload)
217 |                 response.raise_for_status()
218 |                 data = response.json()
219 |                 answer = data.get('data', {}).get('answer', "No answer provided.")
220 |                 print(f"💡 Response: {answer}")
221 |                 return data
222 |             except:
223 |                 print(f"❌ Failed to get response: {e}")
224 |                 return {"error": f"❌ Failed to get response: {e}"}
225 | 
226 | 
227 |     def add_source(self, markdown, groups, name):
228 |         """Send a source id to retrieve details. Working with version 1.3.3 and newer"""
229 |         url = f"{self.base_url}/sources"
230 |         try:
231 | 
232 |             payload = {
233 |                 "name": name,
234 |                 "groups": groups,
235 |                 "content": markdown
236 |             }
237 | 
238 |             resp = self.session.post(url, json=payload)
239 |             j = json.loads(resp.content)
240 |             data_block = j["data"]
241 |             if not data_block:
242 |                 return []
243 | 
244 |             return data_block
245 | 
246 | 
247 |         except requests.exceptions.RequestException as e:
248 |             print(f"❌ Failed to get response: {e}")
249 |             return {"error": f"❌ Failed to get response: {e}"}
250 | 
251 | 
252 |     def update_source(self, source_id, markdown=None, groups=None, name=None):
253 |         """Edit an existing Source"""
254 |         url = f"{self.base_url}/sources/{source_id}"
255 | 
256 |         try:
257 |             payload = {}
258 |             if groups is None:
259 |                 existing_groups = self.get_document_info(source_id)["groups"]
260 |                 payload["groups"] = existing_groups
261 |             else:
262 |                 payload["groups"] = groups
263 | 
264 |             if markdown is not None:
265 |                 payload["content"] = markdown
266 |             if name is not None:
267 |                 payload["name"] = name
268 | 
269 |             resp = self.session.patch(url, json=payload)
270 | 
271 |             j = json.loads(resp.content)
272 |             data_block = j["data"]
273 |             if not data_block:
274 |                 return []
275 | 
276 |             return data_block
277 | 
278 |         except requests.exceptions.RequestException as e:
279 |             print(f"❌ Failed to get response: {e}")
280 |             return {"error": f"❌ Failed to get response: {e}"}
281 | 
282 |     def delete_source(self, source_id):
283 |         """Send a source id to retrieve details. Working with version 1.3.3 and newer"""
284 |         url = f"{self.base_url}/sources/{source_id}"
285 |         try:
286 | 
287 |             resp = self.session.delete(url)
288 |             j = json.loads(resp.content)
289 |             message = j["message"]
290 |             if not message:
291 |                 return "failed"
292 | 
293 |             return message
294 | 
295 | 
296 |         except requests.exceptions.RequestException as e:
297 |             print(f"❌ Failed to get response: {e}")
298 |             return {"error": f"❌ Failed to get response: {e}"}
299 | 
300 | 
301 | 
302 |     def upload_sftp(self, file_path):
303 |         # Connect to SFTP to determine existing suffixes
304 |         transport = paramiko.Transport((self.ftp_host, self.ftp_port))
305 |         transport.connect(username=self.email, password=self.ftp_password)
306 |         sftp = paramiko.SFTPClient.from_transport(transport)
307 |         remote_base_dir = posixpath.join(self.ftp_folder, self.ftp_subfolder)
308 | 
309 |         # Ensure the remote directory exists
310 |         try:
311 |             sftp.chdir(remote_base_dir)
312 |         except IOError:
313 |             # Create remote dirs if missing
314 |             parts = remote_base_dir.strip("/").split("/")
315 |             path = ""
316 |             for part in parts:
317 |                 path = posixpath.join(path, part)
318 |                 try:
319 |                     sftp.chdir(path)
320 |                 except IOError:
321 |                     sftp.mkdir(path)
322 |                     sftp.chdir(path)
323 | 
324 |             # Determine remote file name
325 |         remote_filename = os.path.basename(file_path)
326 |         remote_path = posixpath.join(remote_base_dir, remote_filename)
327 | 
328 |         # Upload the file
329 |         try:
330 |             sftp.put(file_path, remote_path)
331 |             print(f"Uploaded {file_path} to {remote_path} successfully.")
332 |         except Exception as e:
333 |             print(e)
334 | 
335 |         finally:
336 |             sftp.close()
337 |             transport.close()
338 |             print(f"Connection closed")
339 |             sources = []
340 | 
341 |             while len(sources) == 0:
342 |                print(f"Checking file status")
343 |                sleep(2)
344 |                sources = self.get_sources_from_group("temp")
345 | 
346 |             return sources
347 | 
348 | 
349 | 
350 |     def get_sources_from_group(self, group):
351 |         """Send a source id to retrieve details. Working with version 1.3.3 and newer"""
352 |         url = f"{self.base_url}/sources/groups"
353 |         try:
354 | 
355 |             payload = {
356 |                 "groupName": group
357 |             }
358 | 
359 |             resp = self.session.post(url, json=payload)
360 |             j = json.loads(resp.content)
361 |             data_block = j["data"]
362 |             if not data_block:
363 |                 return []
364 | 
365 |             sources = []
366 |             for source in data_block["sources"]:
367 |                 doc = self.get_document_info(source)
368 |                 sources.append(doc)
369 | 
370 | 
371 |             return sources
372 | 
373 | 
374 |         except requests.exceptions.RequestException as e:
375 |             print(f"❌ Failed to get response: {e}")
376 |             return []
377 | 
378 |     def respond_with_context(self, messages, response_format=None, request_tools=None):
379 |         last_user_message = next((p for p in reversed(messages) if p["role"] == "user"), None)
380 |         user_input = ""
381 | 
382 |         for message in messages:
383 |             if message["role"] == "system":
384 |                 user_input = str(message) + "\n"
385 | 
386 |         if last_user_message is not None:
387 |             user_input += last_user_message["content"]
388 | 
389 |         last_assistant_message = next((p for p in reversed(messages) if p["role"] == "assistant"), None)
390 |         last_tool_message = next((p for p in reversed(messages) if p["role"] == "tool"), None)
391 | 
392 |         hastoolresult = False
393 |         if last_tool_message is not None and last_assistant_message is not None and last_assistant_message.tool_calls is not None and len(
394 |                 last_assistant_message.tool_calls) > 0:
395 |             user_input += "\nYou called the tool: " + str(
396 |                 last_assistant_message.tool_calls[0]) + ". The result was: " + last_tool_message.content
397 |             hastoolresult = True
398 | 
399 |         print(f"💁 Request: " + user_input)
400 | 
401 |         # PGPT manages history and context itself so we don't need to forward the history.
402 |         add_context = False
403 |         if add_context:
404 |             messages.pop()
405 |             user_input += "\nHere is some context about the previous conversation:\n"
406 |             for message in messages:
407 |                 user_input += f"{message.role}: {message.content}\n"
408 | 
409 |         if response_format is not None:
410 |             print("Response format: " + str(response_format))
411 |             user_input += add_response_format(response_format)
412 | 
413 |         if request_tools is not None and not hastoolresult:
414 |             user_input += add_tools(request_tools, last_tool_message)
415 | 
416 |         if not self.logged_in:
417 |             self.login()
418 |         else:
419 |             if self.chat_id is None:
420 |                 result = self.create_chat(user_input)
421 |             else:
422 |                 result = self.query_private_gpt(user_input)
423 | 
424 |             if 'data' in result:
425 |                 response_data = result.get("data")
426 |                 if request_tools is not None and not hastoolresult and is_json(
427 |                         clean_response(response_data.get("answer"))):
428 |                     response_data["tool_call"] = clean_response(response_data.get("answer", ""))
429 |                 return response_data
430 |             elif 'error' in result:
431 |                 # Try to login again and send the query once more on error.
432 |                 if self.login():
433 |                     if self.chat_id is None:
434 |                         result = self.create_chat(user_input)
435 |                     else:
436 |                         result = self.query_private_gpt(user_input)
437 | 
438 |                     if 'data' in result:
439 |                         return result['data']
440 |                     else:
441 |                         return result
442 | 
443 |             else:
444 |                 return result
445 | 
446 | 
447 | def is_json(myjson):
448 |     try:
449 |         json.loads(myjson)
450 |     except ValueError as e:
451 |         return False
452 |     return True
453 | 
454 | 
455 | def add_response_format(response_format):
456 |     # prompt = "\nPlease fill in the following template with realistic and appropriate information. Be creative. The field 'type' defines the output format. In your reply, only return the generated json\n"
457 |     prompt = "\nPlease fill in the following json template with realistic and appropriate information. In your reply, only return the generated json. If you can't answer return an empty json.\n"
458 |     prompt += json.dumps(response_format)
459 |     return prompt
460 | 
461 | 
462 | def add_tools(response_tools, last_tool_message):
463 |     prompt = "\nPlease select the fitting provided tool to create your answer. Only return the generated result of the tool. Do not describe what you are doing, just return the json.\n"
464 |     index = 1
465 |     for tool in response_tools:
466 |         prompt += "\n" + json.dumps(tool) + "\n"
467 |         index += 1
468 | 
469 |     return prompt
470 | 
471 | 
472 | def clean_response(response):
473 |     # Remove artefacts from reply here
474 |     response = response.replace("[TOOL_CALLS]", "")
475 |     return response
476 | 
477 | 
478 | def decrypt_api_key(api_key):
479 |     """
480 |     This is PoC code and methods should be replaced with a more secure way to deal with credentials (e.g. in a db)
481 |     """
482 |     try:
483 |         base64_bytes = api_key.encode("ascii")
484 |         decoded_string_bytes = base64.b64decode(base64_bytes)
485 |         decoded_key = decoded_string_bytes.decode("ascii")
486 |     except Exception as e:
487 |         print(e)
488 |         decoded_key = "invalid:invalid"
489 | 
490 |     return decoded_key.split(":")[0], decoded_key.split(":")[1]
491 | 
492 | 
493 | def main():
494 |     """Main function to run the chat application."""
495 |     config_file = Path.absolute(Path(__file__).parent.parent / "pgpt_openai_api_proxy.json")
496 |     config = Config(config_file=config_file, required_fields=["base_url"])
497 |     chat = PrivateGPTAPI(config)
498 | 
499 |     print("Type your questions below. Type 'quit' to exit.")
500 |     while True:
501 |         try:
502 |             question = input("❓ Question: ").strip()
503 |             if question.lower() == 'quit':
504 |                 break
505 |             if question:
506 |                 chat.query_private_gpt(question)
507 |         except KeyboardInterrupt:
508 |             print("\nExiting chat...")
509 |             break
510 |         except Exception as e:
511 |             print(f"❌ Error: {str(e)}")
512 |             break
513 | 
514 | 
515 | if __name__ == "__main__":
516 |     main()
```
Page 15/20FirstPrevNextLast