Skip to content

Commit 4544287

Browse files
authored
MCP: add tool calling support (#228)
1 parent c095e50 commit 4544287

File tree

4 files changed

+361
-26
lines changed

4 files changed

+361
-26
lines changed

go.mod

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,15 @@ require (
99
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.1
1010
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.2
1111
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azsecrets v1.3.1
12+
github.com/anthropics/anthropic-sdk-go v1.17.0
1213
github.com/coder/websocket v1.8.14
1314
github.com/google/uuid v1.6.0
1415
github.com/iancoleman/strcase v0.3.0
16+
github.com/openai/openai-go v0.1.0-alpha.61
1517
github.com/shopspring/decimal v1.4.0
1618
github.com/stretchr/testify v1.10.0
1719
github.com/testcontainers/testcontainers-go v0.37.0
18-
golang.org/x/mod v0.17.0
20+
golang.org/x/mod v0.25.0
1921
google.golang.org/grpc v1.72.0
2022
google.golang.org/protobuf v1.36.6
2123
)
@@ -62,6 +64,10 @@ require (
6264
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
6365
github.com/shirou/gopsutil/v4 v4.25.1 // indirect
6466
github.com/sirupsen/logrus v1.9.3 // indirect
67+
github.com/tidwall/gjson v1.18.0 // indirect
68+
github.com/tidwall/match v1.1.1 // indirect
69+
github.com/tidwall/pretty v1.2.1 // indirect
70+
github.com/tidwall/sjson v1.2.5 // indirect
6571
github.com/tklauser/go-sysconf v0.3.12 // indirect
6672
github.com/tklauser/numcpus v0.6.1 // indirect
6773
github.com/yusufpapurcu/wmi v1.2.4 // indirect
@@ -73,15 +79,15 @@ require (
7379
go.opentelemetry.io/otel/trace v1.35.0 // indirect
7480
go.opentelemetry.io/proto/otlp v1.6.0 // indirect
7581
go.uber.org/multierr v1.11.0 // indirect
76-
golang.org/x/crypto v0.37.0 // indirect
82+
golang.org/x/crypto v0.40.0 // indirect
7783
gopkg.in/yaml.v3 v3.0.1 // indirect
7884
)
7985

8086
require (
8187
go.uber.org/zap v1.27.0
82-
golang.org/x/net v0.39.0 // indirect
83-
golang.org/x/sys v0.32.0 // indirect
84-
golang.org/x/text v0.24.0 // indirect
88+
golang.org/x/net v0.41.0 // indirect
89+
golang.org/x/sys v0.34.0 // indirect
90+
golang.org/x/text v0.27.0 // indirect
8591
google.golang.org/genproto/googleapis/rpc v0.0.0-20250505200425-f936aa4a68b2 // indirect
8692
gopkg.in/yaml.v2 v2.4.0
8793
)

go.sum

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ github.com/AzureAD/microsoft-authentication-library-for-go v1.3.3 h1:H5xDQaE3Xow
2424
github.com/AzureAD/microsoft-authentication-library-for-go v1.3.3/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI=
2525
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
2626
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
27+
github.com/anthropics/anthropic-sdk-go v1.17.0 h1:BwK8ApcmaAUkvZTiQE0yi3R9XneEFskDIjLTmOAFZxQ=
28+
github.com/anthropics/anthropic-sdk-go v1.17.0/go.mod h1:WTz31rIUHUHqai2UslPpw5CwXrQP3geYBioRV4WOLvE=
2729
github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM=
2830
github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
2931
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
@@ -107,6 +109,8 @@ github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
107109
github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
108110
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
109111
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
112+
github.com/openai/openai-go v0.1.0-alpha.61 h1:dLJW1Dk15VAwm76xyPsiPt/Ky94NNGoMLETAI1ISoBY=
113+
github.com/openai/openai-go v0.1.0-alpha.61/go.mod h1:3SdE6BffOX9HPEQv8IL/fi3LYZ5TUpRYaqGQZbyk11A=
110114
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
111115
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
112116
github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040=
@@ -137,6 +141,16 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf
137141
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
138142
github.com/testcontainers/testcontainers-go v0.37.0 h1:L2Qc0vkTw2EHWQ08djon0D2uw7Z/PtHS/QzZZ5Ra/hg=
139143
github.com/testcontainers/testcontainers-go v0.37.0/go.mod h1:QPzbxZhQ6Bclip9igjLFj6z0hs01bU8lrl2dHQmgFGM=
144+
github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
145+
github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY=
146+
github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
147+
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
148+
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
149+
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
150+
github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
151+
github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
152+
github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY=
153+
github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28=
140154
github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU=
141155
github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI=
142156
github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk=
@@ -174,18 +188,18 @@ go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
174188
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
175189
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
176190
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
177-
golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE=
178-
golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc=
191+
golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM=
192+
golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY=
179193
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
180194
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
181-
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
182-
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
195+
golang.org/x/mod v0.25.0 h1:n7a+ZbQKQA/Ysbyb0/6IbB1H/X41mKgbhfv7AfG/44w=
196+
golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
183197
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
184198
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
185199
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
186200
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
187-
golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY=
188-
golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E=
201+
golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw=
202+
golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA=
189203
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
190204
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
191205
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -199,14 +213,14 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc
199213
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
200214
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
201215
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
202-
golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
203-
golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
204-
golang.org/x/term v0.31.0 h1:erwDkOK1Msy6offm1mOgvspSkslFnIGsFnxOKoufg3o=
205-
golang.org/x/term v0.31.0/go.mod h1:R4BeIy7D95HzImkxGkTW1UQTtP54tio2RyHz7PwK0aw=
216+
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
217+
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
218+
golang.org/x/term v0.33.0 h1:NuFncQrRcaRvVmgRkvM3j/F00gWIAlcmlB8ACEKmGIg=
219+
golang.org/x/term v0.33.0/go.mod h1:s18+ql9tYWp1IfpV9DmCtQDDSRBUjKaw9M1eAv5UeF0=
206220
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
207221
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
208-
golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0=
209-
golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU=
222+
golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
223+
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
210224
golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0=
211225
golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
212226
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=

pkg/sharedtypes/llmhandler.go

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ type HandlerRequest struct {
3030
ModelCategory []string `json:"modelCategory"` // optional model category; define one or more categories to filter models; models of the specified categories from first to last will be used for this request if available
3131
Data interface{} `json:"data"` // for embeddings, this can be a string or []string; for chat, only string is allowed
3232
Images []string `json:"images"` // List of images in base64 format
33+
MCPTools []interface{} `json:"mcpTools,omitempty"` // MCP tool definitions for tool calling support
3334
ChatRequestType string `json:"chatRequestType"` // "summary", "code", "keywords", "general"; only relevant if "adapter" is "chat"
3435
DataStream bool `json:"dataStream"` // only relevant if "adapter" is "chat"
3536
MaxNumberOfKeywords uint32 `json:"maxNumberOfKeywords"` // only relevant if "chatRequestType" is "keywords"
@@ -49,11 +50,12 @@ type HandlerResponse struct {
4950
Type string `json:"type"` // "info", "error", "chat", "embeddings"
5051

5152
// Chat properties
52-
IsLast *bool `json:"isLast,omitempty"`
53-
Position *uint32 `json:"position,omitempty"`
54-
InputTokenCount *int `json:"inputTokenCount,omitempty"`
55-
OutputTokenCount *int `json:"outputTokenCount,omitempty"`
56-
ChatData *string `json:"chatData,omitempty"`
53+
IsLast *bool `json:"isLast,omitempty"`
54+
Position *uint32 `json:"position,omitempty"`
55+
InputTokenCount *int `json:"inputTokenCount,omitempty"`
56+
OutputTokenCount *int `json:"outputTokenCount,omitempty"`
57+
ChatData *string `json:"chatData,omitempty"`
58+
ToolCalls []ToolCall `json:"toolCalls,omitempty"` // Structured tool calls from LLM
5759

5860
// Embeddings properties
5961
EmbeddedData interface{} `json:"embeddedData,omitempty"` // []float32 or [][]float32; for BAAI/bge-m3 these are dense vectors
@@ -79,11 +81,12 @@ type TransferDetails struct {
7981
RequestChannel chan HandlerRequest
8082
}
8183

82-
// HistoricMessage represents a past chat messages.
84+
// HistoricMessage represents a past chat message.
8385
type HistoricMessage struct {
84-
Role string `json:"role"`
85-
Content string `json:"content"`
86-
Images []string `json:"images"` // image in base64 format
86+
Role string `json:"role"`
87+
Content string `json:"content"`
88+
Images []string `json:"images"` // image in base64 format
89+
ToolCallId *string `json:"toolCallId,omitempty"` // Tool call ID for OpenAI-style tool responses
8790
}
8891

8992
// OpenAIOption represents an option for an OpenAI API call.
@@ -114,3 +117,18 @@ type EmbeddingResult struct {
114117
Dense []float32
115118
Sparse map[uint]float32
116119
}
120+
121+
// ToolCall represents a tool invocation from the LLM (follows OpenAI/Anthropic spec)
122+
type ToolCall struct {
123+
ID string `json:"id"`
124+
Type string `json:"type"`
125+
Name string `json:"name"`
126+
Input map[string]interface{} `json:"input"`
127+
}
128+
129+
// ToolResult represents a tool execution result (follows Anthropic spec)
130+
type ToolResult struct {
131+
ToolCallID string `json:"tool_call_id"`
132+
Content string `json:"content"`
133+
IsError bool `json:"is_error"`
134+
}

0 commit comments

Comments
 (0)