[B4J Server]
├─ REST API (optional)
├─ Database (inventory + customer)
└─ MCP WebSocket Server
├─ get_products
├─ search_items
├─ check_stock
├─ get_customer
├─ create_invoice
└─ sales_summary
# Project: Mini MCP WebSocket Server (B4J)
# Files included below. Copy each file into a new B4J project with the same filename.
---
File: Main.bas
' Main WebSocket MCP server
Sub Process_Globals
Private ws As WebSocketServer
Private ServerPort As Int = 8888
Private store As ProductStore
End Sub
Sub AppStart (Args() As String)
Log("Starting Mini MCP WebSocket Server...")
store.Initialize
ws.Initialize("ws")
ws.Start(ServerPort, "0.0.0.0")
Log($"🚀 MCP WebSocket server started on ws://0.0.0.0:${ServerPort}/")
End Sub
' New client connected
Sub ws_Connected (wsClient As WebSocket)
Log("Client connected: " & wsClient.GetRemoteAddress)
' Send an MCP-style "initialized" capabilities message (not strictly JSON-RPC)
Dim gen As JSONGenerator
Dim cap As Map = CreateMap("protocolVersion": "1.0", "capabilities": CreateMap("tools": Array As String("echo","get_products","search_items","create_invoice","check_stock","get_sales_summary","get_time","get_server_info")))
gen.Initialize(cap)
wsClient.SendText(gen.ToString)
End Sub
Sub ws_TextMessage (wsClient As WebSocket, msg As String)
Log("Received: " & msg)
Dim parser As JSONParser
parser.Initialize(msg)
Try
Dim req As Map = parser.NextObject
Dim method As String = req.GetDefault("method", "")
Dim id = req.GetDefault("id", Null)
Select method
Case "echo"
Handle_Echo(wsClient, id, req)
Case "get_products"
Handle_GetProducts(wsClient, id, req)
Case "search_items"
Handle_SearchItems(wsClient, id, req)
Case "create_invoice"
Handle_CreateInvoice(wsClient, id, req)
Case "check_stock"
Handle_CheckStock(wsClient, id, req)
Case "get_sales_summary"
Handle_GetSalesSummary(wsClient, id, req)
Case "get_time"
Handle_GetTime(wsClient, id, req)
Case "get_server_info"
Handle_GetServerInfo(wsClient, id, req)
Case Else
ReplyError(wsClient, id, -32601, "Method not found: " & method)
End Select
Catch
ReplyError(wsClient, Null, -32700, "Parse error or invalid JSON")
End Try
End Sub
Sub ws_Disconnected (wsClient As WebSocket)
Log("Client disconnected: " & wsClient.GetRemoteAddress)
End Sub
' ----------------------
' RPC helper / replies
Private Sub ReplyResult(wsClient As WebSocket, id, result As Object)
Dim resp As Map = CreateMap("jsonrpc": "2.0", "id": id, "result": result)
Dim gen As JSONGenerator
gen.Initialize(resp)
wsClient.SendText(gen.ToString)
End Sub
Private Sub ReplyError(wsClient As WebSocket, id, code As Int, message As String)
Dim resp As Map = CreateMap("jsonrpc": "2.0")
If id <> Null Then resp.Put("id", id)
resp.Put("error", CreateMap("code": code, "message": message))
Dim gen As JSONGenerator
gen.Initialize(resp)
wsClient.SendText(gen.ToString)
End Sub
' ----------------------
' Handlers (business / database tools)
Private Sub Handle_Echo(wsClient As WebSocket, id, req As Map)
Dim params As Map = req.GetDefault("params", CreateMap())
Dim text As String = params.GetDefault("text", "")
Dim result As Map = CreateMap("echo": text)
ReplyResult(wsClient, id, result)
End Sub
Private Sub Handle_GetProducts(wsClient As WebSocket, id, req As Map)
Dim list As List = store.GetAllProducts
ReplyResult(wsClient, id, list)
End Sub
Private Sub Handle_SearchItems(wsClient As WebSocket, id, req As Map)
Dim params As Map = req.GetDefault("params", CreateMap())
Dim q As String = params.GetDefault("query", "")
Dim list As List = store.Search(q)
ReplyResult(wsClient, id, list)
End Sub
Private Sub Handle_CreateInvoice(wsClient As WebSocket, id, req As Map)
Dim params As Map = req.GetDefault("params", CreateMap())
' params expected: items = Array of {product_id, qty}
Dim items As List = params.GetDefault("items", CreateList())
If items.Size = 0 Then
ReplyError(wsClient, id, -32602, "Missing or empty 'items' parameter")
Return
End If
Dim invoice As Map
invoice.Initialize
invoice.Put("id", DateTime.Now)
invoice.Put("created_at", DateTime.Now)
Dim lines As List
lines.Initialize
Dim total As Double = 0
For Each it As Map In items
Dim pid = it.Get("product_id")
Dim qty As Int = it.GetDefault("qty", 1)
Dim p As Map = store.GetById(pid)
If p = Null Then Continue
Dim line As Map = CreateMap("product_id": pid, "name": p.Get("name"), "unit_price": p.Get("price"), "qty": qty, "line_total": p.Get("price") * qty)
lines.Add(line)
total = total + line.Get("line_total")
' reduce stock
store.AdjustStock(pid, -qty)
Next
invoice.Put("lines", lines)
invoice.Put("total", total)
' For demo: just return invoice (no persistent DB)
ReplyResult(wsClient, id, invoice)
End Sub
Private Sub Handle_CheckStock(wsClient As WebSocket, id, req As Map)
Dim params As Map = req.GetDefault("params", CreateMap())
Dim pid = params.GetDefault("product_id", Null)
If pid = Null Then
ReplyError(wsClient, id, -32602, "Missing 'product_id' parameter")
Return
End If
Dim p As Map = store.GetById(pid)
If p = Null Then
ReplyError(wsClient, id, -32602, "Product not found: " & pid)
Return
End If
ReplyResult(wsClient, id, CreateMap("product_id": pid, "stock": p.Get("stock")))
End Sub
Private Sub Handle_GetSalesSummary(wsClient As WebSocket, id, req As Map)
' Demo summary computed from store's sales history (if enabled). For now return simple inventory summary.
Dim summary As Map
summary.Initialize
summary.Put("product_count", store.Count)
summary.Put("total_stock", store.TotalStock)
ReplyResult(wsClient, id, summary)
End Sub
Private Sub Handle_GetTime(wsClient As WebSocket, id, req As Map)
ReplyResult(wsClient, id, DateTime.Now)
End Sub
Private Sub Handle_GetServerInfo(wsClient As WebSocket, id, req As Map)
Dim info As Map = CreateMap("name": "Mini MCP B4J Server", "version": "0.1", "transport": "websocket")
ReplyResult(wsClient, id, info)
End Sub
' ----------------------
' Utilities for logging (optional)
Sub Log(s As String)
Dim t As String = DateTime.Now
Console.WriteLine(t & " | " & s)
End Sub
---
File: ProductStore.bas
' Lightweight in-memory product store for demo purposes.
Sub Class_Globals
Private products As List ' List of Map
End Sub
Public Sub Initialize
products.Initialize
SeedSampleData
End Sub
Private Sub SeedSampleData
products.Clear
AddProduct(1, "Apple iPhone 14", 2999.00, 10)
AddProduct(2, "Samsung Galaxy S23", 2499.00, 15)
AddProduct(3, "Wireless Mouse", 79.90, 50)
AddProduct(4, "Mechanical Keyboard", 199.90, 30)
End Sub
Public Sub AddProduct(id As Object, name As String, price As Double, stock As Int)
Dim m As Map
m.Initialize
m.Put("id", id)
m.Put("name", name)
m.Put("price", price)
m.Put("stock", stock)
products.Add(m)
End Sub
Public Sub GetAllProducts As List
' Return a shallow copy
Dim out As List
out.Initialize
For Each p As Map In products
out.Add(CloneMap(p))
Next
Return out
End Sub
Public Sub Search(q As String) As List
Dim out As List
out.Initialize
If q = Null Or q.Trim = "" Then Return out
q = q.ToLowerCase
For Each p As Map In products
If p.Get("name").ToString.ToLowerCase.Contains(q) Then
out.Add(CloneMap(p))
End If
Next
Return out
End Sub
Public Sub GetById(id As Object) As Map
For Each p As Map In products
If p.Get("id") = id Then
Return CloneMap(p)
End If
Next
Return Null
End Sub
Public Sub AdjustStock(id As Object, delta As Int) As Boolean
For i = 0 To products.Size - 1
Dim p As Map = products.Get(i)
If p.Get("id") = id Then
Dim newStock As Int = p.Get("stock") + delta
If newStock < 0 Then newStock = 0
p.Put("stock", newStock)
Return True
End If
Next
Return False
End Sub
Public Sub Count As Int
Return products.Size
End Sub
Public Sub TotalStock As Int
Dim s As Int = 0
For Each p As Map In products
s = s + p.Get("stock")
Next
Return s
End Sub
' Helper to clone a Map so we don't leak internal references
Private Sub CloneMap(original As Map) As Map
Dim m As Map
m.Initialize
For Each k As String In original.Keys
m.Put(k, original.Get(k))
Next
Return m
End Sub
---
File: README.txt
Quick start
1) Create a new B4J project.
2) Add three code modules and paste the contents above as files:
- Main.bas
- ProductStore.bas
- README.txt (optional)
3) Ensure you have the WebSocketServer library available (B4J core). The code uses the WebSocketServer type and WebSocket events (Connected, TextMessage, Disconnected).
4) Run the project. The console will show the server address (default ws://0.0.0.0:8888).
Example request (JSON-RPC over WebSocket):
{
"jsonrpc": "2.0",
"id": 1,
"method": "get_products",
"params": {}
}
Example response:
{
"jsonrpc": "2.0",
"id": 1,
"result": [ {"id":1,"name":"Apple iPhone 14","price":2999.0,"stock":10}, ... ]
}
Notes & next steps
- This demo uses an in-memory store. Replace ProductStore with a SQLite or JDBC-backed implementation for persistence.
- Add authentication, CORS or TLS if exposing to networks.
- Optionally implement MCP "initialize" messages strictly following the MCP spec if needed.
---
---
File: CustomerStore.bas
' Lightweight in-memory customer store
Sub Class_Globals
Private customers As List ' List of Map
End Sub
Public Sub Initialize
customers.Initialize
SeedSampleData
End Sub
Private Sub SeedSampleData
customers.Clear
AddCustomer(1, "John Doe", "john@example.com", "012-3456789")
AddCustomer(2, "Alice Tan", "alice@example.com", "013-9876543")
AddCustomer(3, "Michael Lee", "michael@example.com", "017-2223344")
End Sub
Public Sub AddCustomer(id As Object, name As String, email As String, phone As String)
Dim c As Map
c.Initialize
c.Put("id", id)
c.Put("name", name)
c.Put("email", email)
c.Put("phone", phone)
customers.Add(c)
End Sub
Public Sub GetAllCustomers As List
Dim out As List
out.Initialize
For Each c As Map In customers
out.Add(CloneMap(c))
Next
Return out
End Sub
Public Sub FindById(id As Object) As Map
For Each c As Map In customers
If c.Get("id") = id Then Return CloneMap(c)
Next
Return Null
End Sub
Public Sub SearchByName(q As String) As List
Dim out As List
out.Initialize
If q = Null Or q.Trim = "" Then Return out
q = q.ToLowerCase
For Each c As Map In customers
If c.Get("name").ToString.ToLowerCase.Contains(q) Then
out.Add(CloneMap(c))
End If
Next
Return out
End Sub
Private Sub CloneMap(original As Map) As Map
Dim m As Map
m.Initialize
For Each k As String In original.Keys
m.Put(k, original.Get(k))
Next
Return m
End Sub
---
[UPDATE] Main.bas additions below
Please paste these into Main.bas inside appropriate sections.
1) Add to Process_Globals:
Private cust As CustomerStore
2) In AppStart:
cust.Initialize
3) Add new handlers:
Private Sub Handle_GetCustomers(wsClient As WebSocket, id, req As Map)
ReplyResult(wsClient, id, cust.GetAllCustomers)
End Sub
Private Sub Handle_FindCustomer(wsClient As WebSocket, id, req As Map)
Dim params As Map = req.GetDefault("params", CreateMap())
Dim cid = params.GetDefault("customer_id", Null)
If cid = Null Then
ReplyError(wsClient, id, -32602, "Missing 'customer_id'")
Return
End If
Dim c As Map = cust.FindById(cid)
If c = Null Then
ReplyError(wsClient, id, -32602, "Customer not found: " & cid)
Return
End If
ReplyResult(wsClient, id, c)
End Sub
Private Sub Handle_SearchCustomer(wsClient As WebSocket, id, req As Map)
Dim params As Map = req.GetDefault("params", CreateMap())
Dim q As String = params.GetDefault("query", "")
ReplyResult(wsClient, id, cust.SearchByName(q))
End Sub
4) Add tool routing inside ws_TextMessage SELECT CASE:
Case "get_customers"
Handle_GetCustomers(wsClient, id, req)
Case "find_customer"
Handle_FindCustomer(wsClient, id, req)
Case "search_customer"
Handle_SearchCustomer(wsClient, id, req)
---
End of project files.
(chatGPT calls your MCP → get_products → provides list)“ChatGPT, which products are low stock today?”
(chatGPT calls → search_customer)“Find a customer named Michael and show his info.”
(chatGPT calls → get_sales_summary → formats report)“Generate today’s sales report using my database.”
(chatGPT calls → find_customer → create_invoice)“Create an invoice for John Doe: 2 iPhones + 1 Keyboard”
“ChatGPT found a new MCP tool: B4J Inventory MCP Server — Enable?”
{
"method": "search_customer",
"params": { "keyword": "Ali" }
}
Architecture:
B4X:[B4J Server] ├─ REST API (optional) ├─ Database (inventory + customer) └─ MCP WebSocket Server ├─ get_products ├─ search_items ├─ check_stock ├─ get_customer ├─ create_invoice └─ sales_summary
ChatGPT or any MCP client can:
Code:
- Query inventory
- Create invoices
- Update stock
- Look up customer history
- Generate reports
- Perform backend actions
B4X:# Project: Mini MCP WebSocket Server (B4J) # Files included below. Copy each file into a new B4J project with the same filename. --- File: Main.bas ' Main WebSocket MCP server Sub Process_Globals Private ws As WebSocketServer Private ServerPort As Int = 8888 Private store As ProductStore End Sub Sub AppStart (Args() As String) Log("Starting Mini MCP WebSocket Server...") store.Initialize ws.Initialize("ws") ws.Start(ServerPort, "0.0.0.0") Log($"🚀 MCP WebSocket server started on ws://0.0.0.0:${ServerPort}/") End Sub ' New client connected Sub ws_Connected (wsClient As WebSocket) Log("Client connected: " & wsClient.GetRemoteAddress) ' Send an MCP-style "initialized" capabilities message (not strictly JSON-RPC) Dim gen As JSONGenerator Dim cap As Map = CreateMap("protocolVersion": "1.0", "capabilities": CreateMap("tools": Array As String("echo","get_products","search_items","create_invoice","check_stock","get_sales_summary","get_time","get_server_info"))) gen.Initialize(cap) wsClient.SendText(gen.ToString) End Sub Sub ws_TextMessage (wsClient As WebSocket, msg As String) Log("Received: " & msg) Dim parser As JSONParser parser.Initialize(msg) Try Dim req As Map = parser.NextObject Dim method As String = req.GetDefault("method", "") Dim id = req.GetDefault("id", Null) Select method Case "echo" Handle_Echo(wsClient, id, req) Case "get_products" Handle_GetProducts(wsClient, id, req) Case "search_items" Handle_SearchItems(wsClient, id, req) Case "create_invoice" Handle_CreateInvoice(wsClient, id, req) Case "check_stock" Handle_CheckStock(wsClient, id, req) Case "get_sales_summary" Handle_GetSalesSummary(wsClient, id, req) Case "get_time" Handle_GetTime(wsClient, id, req) Case "get_server_info" Handle_GetServerInfo(wsClient, id, req) Case Else ReplyError(wsClient, id, -32601, "Method not found: " & method) End Select Catch ReplyError(wsClient, Null, -32700, "Parse error or invalid JSON") End Try End Sub Sub ws_Disconnected (wsClient As WebSocket) Log("Client disconnected: " & wsClient.GetRemoteAddress) End Sub ' ---------------------- ' RPC helper / replies Private Sub ReplyResult(wsClient As WebSocket, id, result As Object) Dim resp As Map = CreateMap("jsonrpc": "2.0", "id": id, "result": result) Dim gen As JSONGenerator gen.Initialize(resp) wsClient.SendText(gen.ToString) End Sub Private Sub ReplyError(wsClient As WebSocket, id, code As Int, message As String) Dim resp As Map = CreateMap("jsonrpc": "2.0") If id <> Null Then resp.Put("id", id) resp.Put("error", CreateMap("code": code, "message": message)) Dim gen As JSONGenerator gen.Initialize(resp) wsClient.SendText(gen.ToString) End Sub ' ---------------------- ' Handlers (business / database tools) Private Sub Handle_Echo(wsClient As WebSocket, id, req As Map) Dim params As Map = req.GetDefault("params", CreateMap()) Dim text As String = params.GetDefault("text", "") Dim result As Map = CreateMap("echo": text) ReplyResult(wsClient, id, result) End Sub Private Sub Handle_GetProducts(wsClient As WebSocket, id, req As Map) Dim list As List = store.GetAllProducts ReplyResult(wsClient, id, list) End Sub Private Sub Handle_SearchItems(wsClient As WebSocket, id, req As Map) Dim params As Map = req.GetDefault("params", CreateMap()) Dim q As String = params.GetDefault("query", "") Dim list As List = store.Search(q) ReplyResult(wsClient, id, list) End Sub Private Sub Handle_CreateInvoice(wsClient As WebSocket, id, req As Map) Dim params As Map = req.GetDefault("params", CreateMap()) ' params expected: items = Array of {product_id, qty} Dim items As List = params.GetDefault("items", CreateList()) If items.Size = 0 Then ReplyError(wsClient, id, -32602, "Missing or empty 'items' parameter") Return End If Dim invoice As Map invoice.Initialize invoice.Put("id", DateTime.Now) invoice.Put("created_at", DateTime.Now) Dim lines As List lines.Initialize Dim total As Double = 0 For Each it As Map In items Dim pid = it.Get("product_id") Dim qty As Int = it.GetDefault("qty", 1) Dim p As Map = store.GetById(pid) If p = Null Then Continue Dim line As Map = CreateMap("product_id": pid, "name": p.Get("name"), "unit_price": p.Get("price"), "qty": qty, "line_total": p.Get("price") * qty) lines.Add(line) total = total + line.Get("line_total") ' reduce stock store.AdjustStock(pid, -qty) Next invoice.Put("lines", lines) invoice.Put("total", total) ' For demo: just return invoice (no persistent DB) ReplyResult(wsClient, id, invoice) End Sub Private Sub Handle_CheckStock(wsClient As WebSocket, id, req As Map) Dim params As Map = req.GetDefault("params", CreateMap()) Dim pid = params.GetDefault("product_id", Null) If pid = Null Then ReplyError(wsClient, id, -32602, "Missing 'product_id' parameter") Return End If Dim p As Map = store.GetById(pid) If p = Null Then ReplyError(wsClient, id, -32602, "Product not found: " & pid) Return End If ReplyResult(wsClient, id, CreateMap("product_id": pid, "stock": p.Get("stock"))) End Sub Private Sub Handle_GetSalesSummary(wsClient As WebSocket, id, req As Map) ' Demo summary computed from store's sales history (if enabled). For now return simple inventory summary. Dim summary As Map summary.Initialize summary.Put("product_count", store.Count) summary.Put("total_stock", store.TotalStock) ReplyResult(wsClient, id, summary) End Sub Private Sub Handle_GetTime(wsClient As WebSocket, id, req As Map) ReplyResult(wsClient, id, DateTime.Now) End Sub Private Sub Handle_GetServerInfo(wsClient As WebSocket, id, req As Map) Dim info As Map = CreateMap("name": "Mini MCP B4J Server", "version": "0.1", "transport": "websocket") ReplyResult(wsClient, id, info) End Sub ' ---------------------- ' Utilities for logging (optional) Sub Log(s As String) Dim t As String = DateTime.Now Console.WriteLine(t & " | " & s) End Sub --- File: ProductStore.bas ' Lightweight in-memory product store for demo purposes. Sub Class_Globals Private products As List ' List of Map End Sub Public Sub Initialize products.Initialize SeedSampleData End Sub Private Sub SeedSampleData products.Clear AddProduct(1, "Apple iPhone 14", 2999.00, 10) AddProduct(2, "Samsung Galaxy S23", 2499.00, 15) AddProduct(3, "Wireless Mouse", 79.90, 50) AddProduct(4, "Mechanical Keyboard", 199.90, 30) End Sub Public Sub AddProduct(id As Object, name As String, price As Double, stock As Int) Dim m As Map m.Initialize m.Put("id", id) m.Put("name", name) m.Put("price", price) m.Put("stock", stock) products.Add(m) End Sub Public Sub GetAllProducts As List ' Return a shallow copy Dim out As List out.Initialize For Each p As Map In products out.Add(CloneMap(p)) Next Return out End Sub Public Sub Search(q As String) As List Dim out As List out.Initialize If q = Null Or q.Trim = "" Then Return out q = q.ToLowerCase For Each p As Map In products If p.Get("name").ToString.ToLowerCase.Contains(q) Then out.Add(CloneMap(p)) End If Next Return out End Sub Public Sub GetById(id As Object) As Map For Each p As Map In products If p.Get("id") = id Then Return CloneMap(p) End If Next Return Null End Sub Public Sub AdjustStock(id As Object, delta As Int) As Boolean For i = 0 To products.Size - 1 Dim p As Map = products.Get(i) If p.Get("id") = id Then Dim newStock As Int = p.Get("stock") + delta If newStock < 0 Then newStock = 0 p.Put("stock", newStock) Return True End If Next Return False End Sub Public Sub Count As Int Return products.Size End Sub Public Sub TotalStock As Int Dim s As Int = 0 For Each p As Map In products s = s + p.Get("stock") Next Return s End Sub ' Helper to clone a Map so we don't leak internal references Private Sub CloneMap(original As Map) As Map Dim m As Map m.Initialize For Each k As String In original.Keys m.Put(k, original.Get(k)) Next Return m End Sub --- File: README.txt Quick start 1) Create a new B4J project. 2) Add three code modules and paste the contents above as files: - Main.bas - ProductStore.bas - README.txt (optional) 3) Ensure you have the WebSocketServer library available (B4J core). The code uses the WebSocketServer type and WebSocket events (Connected, TextMessage, Disconnected). 4) Run the project. The console will show the server address (default ws://0.0.0.0:8888). Example request (JSON-RPC over WebSocket): { "jsonrpc": "2.0", "id": 1, "method": "get_products", "params": {} } Example response: { "jsonrpc": "2.0", "id": 1, "result": [ {"id":1,"name":"Apple iPhone 14","price":2999.0,"stock":10}, ... ] } Notes & next steps - This demo uses an in-memory store. Replace ProductStore with a SQLite or JDBC-backed implementation for persistence. - Add authentication, CORS or TLS if exposing to networks. - Optionally implement MCP "initialize" messages strictly following the MCP spec if needed. --- --- File: CustomerStore.bas ' Lightweight in-memory customer store Sub Class_Globals Private customers As List ' List of Map End Sub Public Sub Initialize customers.Initialize SeedSampleData End Sub Private Sub SeedSampleData customers.Clear AddCustomer(1, "John Doe", "john@example.com", "012-3456789") AddCustomer(2, "Alice Tan", "alice@example.com", "013-9876543") AddCustomer(3, "Michael Lee", "michael@example.com", "017-2223344") End Sub Public Sub AddCustomer(id As Object, name As String, email As String, phone As String) Dim c As Map c.Initialize c.Put("id", id) c.Put("name", name) c.Put("email", email) c.Put("phone", phone) customers.Add(c) End Sub Public Sub GetAllCustomers As List Dim out As List out.Initialize For Each c As Map In customers out.Add(CloneMap(c)) Next Return out End Sub Public Sub FindById(id As Object) As Map For Each c As Map In customers If c.Get("id") = id Then Return CloneMap(c) Next Return Null End Sub Public Sub SearchByName(q As String) As List Dim out As List out.Initialize If q = Null Or q.Trim = "" Then Return out q = q.ToLowerCase For Each c As Map In customers If c.Get("name").ToString.ToLowerCase.Contains(q) Then out.Add(CloneMap(c)) End If Next Return out End Sub Private Sub CloneMap(original As Map) As Map Dim m As Map m.Initialize For Each k As String In original.Keys m.Put(k, original.Get(k)) Next Return m End Sub --- [UPDATE] Main.bas additions below Please paste these into Main.bas inside appropriate sections. 1) Add to Process_Globals: Private cust As CustomerStore 2) In AppStart: cust.Initialize 3) Add new handlers: Private Sub Handle_GetCustomers(wsClient As WebSocket, id, req As Map) ReplyResult(wsClient, id, cust.GetAllCustomers) End Sub Private Sub Handle_FindCustomer(wsClient As WebSocket, id, req As Map) Dim params As Map = req.GetDefault("params", CreateMap()) Dim cid = params.GetDefault("customer_id", Null) If cid = Null Then ReplyError(wsClient, id, -32602, "Missing 'customer_id'") Return End If Dim c As Map = cust.FindById(cid) If c = Null Then ReplyError(wsClient, id, -32602, "Customer not found: " & cid) Return End If ReplyResult(wsClient, id, c) End Sub Private Sub Handle_SearchCustomer(wsClient As WebSocket, id, req As Map) Dim params As Map = req.GetDefault("params", CreateMap()) Dim q As String = params.GetDefault("query", "") ReplyResult(wsClient, id, cust.SearchByName(q)) End Sub 4) Add tool routing inside ws_TextMessage SELECT CASE: Case "get_customers" Handle_GetCustomers(wsClient, id, req) Case "find_customer" Handle_FindCustomer(wsClient, id, req) Case "search_customer" Handle_SearchCustomer(wsClient, id, req) --- End of project files.
Imagine you're running POS + Inventory + Customer system.
Real-world example for you
You connect this MCP server to ChatGPT desktop.
Now ChatGPT can do things like:
Example 1 — Stock Check
(chatGPT calls your MCP → get_products → provides list)
Example 2 — Customer Lookup
(chatGPT calls → search_customer)
Example 3 — Automatic Sales Report
(chatGPT calls → get_sales_summary → formats report)
Example 4 — Auto Invoice
(chatGPT calls → find_customer → create_invoice)
Filename: inventory-mcp.json
Generic MCP Manifest File for B4J
File content:
{
"name": "B4J Inventory MCP Server",
"type": "websocket",
"url": "ws://localhost:9999/ws"
}
Where to put this file Windows
%LOCALAPPDATA%\ChatGPT\plugins\mcp\inventory-mcp.json
macOS
~/Library/Application Support/ChatGPT/plugins/mcp/inventory-mcp.json
Linux
~/.config/ChatGPT/plugins/mcp/inventory-mcp.json
What will happen next?
- Start your B4J server on: ws://localhost:9999/ws
- Open ChatGPT Desktop.
- ChatGPT will automatically detect your server and show a popup:
- Click Enable.
- ChatGPT can now call your MCP tools automatically:
- get_products
- search_items
- get_customers
- find_customer
- create_invoice
- etc.
JSON:{ "method": "search_customer", "params": { "keyword": "Ali" } }
{
"jsonrpc": "2.0",
"method": "get_current_weather",
"params": {
"city": "Piraeus",
"unit": "celsius"
},
"id": 167825345
}
{
"jsonrpc": "2.0",
"result": {
"temperature": 18,
"unit": "celsius",
"description": "Clear skies"
},
"id": 167825345
}
{
"jsonrpc": "2.0",
"error": {
"code": -32601,
"message": "Method not found: get_current_weather"
},
"id": 167825345
}
| Code Ranges | Description |
| -32768 to -32000 | Pre-defined Errors |
| -32000 to -32099 | Server Error |
| Other Integers | Application Error |
Sounds easy the way it is described. I was disappointed when I was searching for the same thing before some time. The jsonrpc protocol it describes has completely disappointed me because I believed that it has to be implemented in full. F.e.
Request:
B4X:{ "jsonrpc": "2.0", "method": "get_current_weather", "params": { "city": "Piraeus", "unit": "celsius" }, "id": 167825345 }
Response success (so far so good):
B4X:{ "jsonrpc": "2.0", "result": { "temperature": 18, "unit": "celsius", "description": "Clear skies" }, "id": 167825345 }
Response Error (here we have a problem - error codes {f.e. -32601} are defined strictly and have to be implemented fully or at least that is what I thought):
B4X:{ "jsonrpc": "2.0", "error": { "code": -32601, "message": "Method not found: get_current_weather" }, "id": 167825345 }
Code Ranges Description -32768 to -32000 Pre-defined Errors -32000 to -32099 Server Error Other Integers Application Error
| 1.0 (draft 1) | Initial draft release |
| 1.0 (draft 2) | Adding reserved range for implementation specific errors and differentiating between unknown encoding and incorrect char for encoding |
| 20010516 | changed system.interopFaultCodes to system.getCapabilities. changed version to date based integer which is useful for comparisons |
How if we can integrate a web UI or server handler connect to Gemini API inside the MCP server as a client?
Question is which AI client do you use to connect to the MCP Server?I am not sure I have understood the question. You mean if we use a web UI for the LLM or a server handler that incorporates the LLM how to connect to the MCP Server through the LLM as a client of the server handler or the Web UI? All the videos I have seen connect the LLM directly to the LLM client and use the MCP server through the LLM. But then you could easily ask Gemini for it. I did it and it makes obvious that you use the tools section of the JSON request and if it wants to use a tool it returns it to you along with the parameters and then by your backend or the Web UI you use jsonrpc 2.0 to connect to the mcp server.
I am only aware of Gradio for python as an AI Client and Web UI for ollama. Though, given that now we know how to do it, we could easily implement a client even without a front end (just by using a server handler).
Is there any AI client can discover TOON format?...Hi there... guys... you can use any AI client, ofcourse the results may be different!
also check the TOON (vs JSON, yaml) - tokens using are extremely low... (is something like csv... so simple)
until today, i ve used OpenAI, Perplexity Models, gemini... I think openAI is extremely good, but i think claudie is for us... (developers... understand us very well)
Hmmm I am just loose the interesting discussion... you ve mean AI Client for MCP.Is there any AI client can discover TOON format?
yes, but not straight forward.Is it possible to integrate it with Jrdc2?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?