MCPcopy Create free account
hub / github.com/modelcontextprotocol/go-sdk / AddTool

Method AddTool

mcp/server.go:238–283  ·  view source on GitHub ↗

AddTool adds a [Tool] to the server, or replaces one with the same name. The Tool argument must not be modified after this call. The tool's input schema must be non-nil and have the type "object". For a tool that takes no input, or one where any input is valid, set [Tool.InputSchema] to `{"type": "

(t *Tool, h ToolHandler)

Source from the content-addressed store, hash-verified

236// Most users should use the top-level function [AddTool], which handles all these
237// responsibilities.
238func (s *Server) AddTool(t *Tool, h ToolHandler) {
239 if err := validateToolName(t.Name); err != nil {
240 s.opts.Logger.Error(fmt.Sprintf("AddTool: invalid tool name %q: %v", t.Name, err))
241 }
242 if t.InputSchema == nil {
243 // This prevents the tool author from forgetting to write a schema where
244 // one should be provided. If we papered over this by supplying the empty
245 // schema, then every input would be validated and the problem wouldn't be
246 // discovered until runtime, when the LLM sent bad data.
247 panic(fmt.Errorf("AddTool %q: missing input schema", t.Name))
248 }
249 if s, ok := t.InputSchema.(*jsonschema.Schema); ok {
250 if s.Type != "object" {
251 panic(fmt.Errorf(`AddTool %q: input schema must have type "object"`, t.Name))
252 }
253 } else {
254 var m map[string]any
255 if err := remarshal(t.InputSchema, &m); err != nil {
256 panic(fmt.Errorf("AddTool %q: can't marshal input schema to a JSON object: %v", t.Name, err))
257 }
258 if typ := m["type"]; typ != "object" {
259 panic(fmt.Errorf(`AddTool %q: input schema must have type "object" (got %v)`, t.Name, typ))
260 }
261 }
262 if t.OutputSchema != nil {
263 if s, ok := t.OutputSchema.(*jsonschema.Schema); ok {
264 if s.Type != "object" {
265 panic(fmt.Errorf(`AddTool %q: output schema must have type "object"`, t.Name))
266 }
267 } else {
268 var m map[string]any
269 if err := remarshal(t.OutputSchema, &m); err != nil {
270 panic(fmt.Errorf("AddTool %q: can't marshal output schema to a JSON object: %v", t.Name, err))
271 }
272 if typ := m["type"]; typ != "object" {
273 panic(fmt.Errorf(`AddTool %q: output schema must have type "object" (got %v)`, t.Name, typ))
274 }
275 }
276 }
277 st := &serverTool{tool: t, handler: h}
278 // Assume there was a change, since add replaces existing tools.
279 // (It's possible a tool was replaced with an identical one, but not worth checking.)
280 // TODO: Batch these changes by size and time? The typescript SDK doesn't.
281 // TODO: Surface notify error here? best not, in case we need to batch.
282 s.changeAndNotify(notificationToolListChanged, func() bool { s.tools.add(st); return true })
283}
284
285func toolForErr[In, Out any](t *Tool, h ToolHandlerFor[In, Out], cache *SchemaCache) (*Tool, ToolHandler, error) {
286 tt := *t

Calls 5

changeAndNotifyMethod · 0.95
validateToolNameFunction · 0.85
remarshalFunction · 0.85
addMethod · 0.80
ErrorMethod · 0.45