Files
Joe ElliottandGitHub 1cf4361605 Tempo MCP Server 🤖 (#5212)
* MCP Server

Signed-off-by: Joe Elliott <[email protected]>

* docs

Signed-off-by: Joe Elliott <[email protected]>

* tests

Signed-off-by: Joe Elliott <[email protected]>

* logs

Signed-off-by: Joe Elliott <[email protected]>

* changelog

Signed-off-by: Joe Elliott <[email protected]>

* manifest

Signed-off-by: Joe Elliott <[email protected]>

* lint

Signed-off-by: Joe Elliott <[email protected]>

* lint

Signed-off-by: Joe Elliott <[email protected]>

* use tools error return

Signed-off-by: Joe Elliott <[email protected]>

* add meta info about response types

Signed-off-by: Joe Elliott <[email protected]>

* made constants and split the metrics meta types

Signed-off-by: Joe Elliott <[email protected]>

* update path from /mcp to /api/mcp

Signed-off-by: Joe Elliott <[email protected]>

* mcp integration tset

Signed-off-by: Joe Elliott <[email protected]>

* review

Signed-off-by: Joe Elliott <[email protected]>

* Removed httptest.Recorder

Signed-off-by: Joe Elliott <[email protected]>

* Use new jaeger client

Signed-off-by: Joe Elliott <[email protected]>

---------

Signed-off-by: Joe Elliott <[email protected]>
2025-07-14 13:25:36 -04:00

533 lines
18 KiB
Go

// Code generated by `go generate`. DO NOT EDIT.
// source: server/internal/gen/hooks.go.tmpl
package server
import (
"context"
"github.com/mark3labs/mcp-go/mcp"
)
// OnRegisterSessionHookFunc is a hook that will be called when a new session is registered.
type OnRegisterSessionHookFunc func(ctx context.Context, session ClientSession)
// OnUnregisterSessionHookFunc is a hook that will be called when a session is being unregistered.
type OnUnregisterSessionHookFunc func(ctx context.Context, session ClientSession)
// BeforeAnyHookFunc is a function that is called after the request is
// parsed but before the method is called.
type BeforeAnyHookFunc func(ctx context.Context, id any, method mcp.MCPMethod, message any)
// OnSuccessHookFunc is a hook that will be called after the request
// successfully generates a result, but before the result is sent to the client.
type OnSuccessHookFunc func(ctx context.Context, id any, method mcp.MCPMethod, message any, result any)
// OnErrorHookFunc is a hook that will be called when an error occurs,
// either during the request parsing or the method execution.
//
// Example usage:
// ```
//
// hooks.AddOnError(func(ctx context.Context, id any, method mcp.MCPMethod, message any, err error) {
// // Check for specific error types using errors.Is
// if errors.Is(err, ErrUnsupported) {
// // Handle capability not supported errors
// log.Printf("Capability not supported: %v", err)
// }
//
// // Use errors.As to get specific error types
// var parseErr = &UnparsableMessageError{}
// if errors.As(err, &parseErr) {
// // Access specific methods/fields of the error type
// log.Printf("Failed to parse message for method %s: %v",
// parseErr.GetMethod(), parseErr.Unwrap())
// // Access the raw message that failed to parse
// rawMsg := parseErr.GetMessage()
// }
//
// // Check for specific resource/prompt/tool errors
// switch {
// case errors.Is(err, ErrResourceNotFound):
// log.Printf("Resource not found: %v", err)
// case errors.Is(err, ErrPromptNotFound):
// log.Printf("Prompt not found: %v", err)
// case errors.Is(err, ErrToolNotFound):
// log.Printf("Tool not found: %v", err)
// }
// })
type OnErrorHookFunc func(ctx context.Context, id any, method mcp.MCPMethod, message any, err error)
// OnRequestInitializationFunc is a function that called before handle diff request method
// Should any errors arise during func execution, the service will promptly return the corresponding error message.
type OnRequestInitializationFunc func(ctx context.Context, id any, message any) error
type OnBeforeInitializeFunc func(ctx context.Context, id any, message *mcp.InitializeRequest)
type OnAfterInitializeFunc func(ctx context.Context, id any, message *mcp.InitializeRequest, result *mcp.InitializeResult)
type OnBeforePingFunc func(ctx context.Context, id any, message *mcp.PingRequest)
type OnAfterPingFunc func(ctx context.Context, id any, message *mcp.PingRequest, result *mcp.EmptyResult)
type OnBeforeSetLevelFunc func(ctx context.Context, id any, message *mcp.SetLevelRequest)
type OnAfterSetLevelFunc func(ctx context.Context, id any, message *mcp.SetLevelRequest, result *mcp.EmptyResult)
type OnBeforeListResourcesFunc func(ctx context.Context, id any, message *mcp.ListResourcesRequest)
type OnAfterListResourcesFunc func(ctx context.Context, id any, message *mcp.ListResourcesRequest, result *mcp.ListResourcesResult)
type OnBeforeListResourceTemplatesFunc func(ctx context.Context, id any, message *mcp.ListResourceTemplatesRequest)
type OnAfterListResourceTemplatesFunc func(ctx context.Context, id any, message *mcp.ListResourceTemplatesRequest, result *mcp.ListResourceTemplatesResult)
type OnBeforeReadResourceFunc func(ctx context.Context, id any, message *mcp.ReadResourceRequest)
type OnAfterReadResourceFunc func(ctx context.Context, id any, message *mcp.ReadResourceRequest, result *mcp.ReadResourceResult)
type OnBeforeListPromptsFunc func(ctx context.Context, id any, message *mcp.ListPromptsRequest)
type OnAfterListPromptsFunc func(ctx context.Context, id any, message *mcp.ListPromptsRequest, result *mcp.ListPromptsResult)
type OnBeforeGetPromptFunc func(ctx context.Context, id any, message *mcp.GetPromptRequest)
type OnAfterGetPromptFunc func(ctx context.Context, id any, message *mcp.GetPromptRequest, result *mcp.GetPromptResult)
type OnBeforeListToolsFunc func(ctx context.Context, id any, message *mcp.ListToolsRequest)
type OnAfterListToolsFunc func(ctx context.Context, id any, message *mcp.ListToolsRequest, result *mcp.ListToolsResult)
type OnBeforeCallToolFunc func(ctx context.Context, id any, message *mcp.CallToolRequest)
type OnAfterCallToolFunc func(ctx context.Context, id any, message *mcp.CallToolRequest, result *mcp.CallToolResult)
type Hooks struct {
OnRegisterSession []OnRegisterSessionHookFunc
OnUnregisterSession []OnUnregisterSessionHookFunc
OnBeforeAny []BeforeAnyHookFunc
OnSuccess []OnSuccessHookFunc
OnError []OnErrorHookFunc
OnRequestInitialization []OnRequestInitializationFunc
OnBeforeInitialize []OnBeforeInitializeFunc
OnAfterInitialize []OnAfterInitializeFunc
OnBeforePing []OnBeforePingFunc
OnAfterPing []OnAfterPingFunc
OnBeforeSetLevel []OnBeforeSetLevelFunc
OnAfterSetLevel []OnAfterSetLevelFunc
OnBeforeListResources []OnBeforeListResourcesFunc
OnAfterListResources []OnAfterListResourcesFunc
OnBeforeListResourceTemplates []OnBeforeListResourceTemplatesFunc
OnAfterListResourceTemplates []OnAfterListResourceTemplatesFunc
OnBeforeReadResource []OnBeforeReadResourceFunc
OnAfterReadResource []OnAfterReadResourceFunc
OnBeforeListPrompts []OnBeforeListPromptsFunc
OnAfterListPrompts []OnAfterListPromptsFunc
OnBeforeGetPrompt []OnBeforeGetPromptFunc
OnAfterGetPrompt []OnAfterGetPromptFunc
OnBeforeListTools []OnBeforeListToolsFunc
OnAfterListTools []OnAfterListToolsFunc
OnBeforeCallTool []OnBeforeCallToolFunc
OnAfterCallTool []OnAfterCallToolFunc
}
func (c *Hooks) AddBeforeAny(hook BeforeAnyHookFunc) {
c.OnBeforeAny = append(c.OnBeforeAny, hook)
}
func (c *Hooks) AddOnSuccess(hook OnSuccessHookFunc) {
c.OnSuccess = append(c.OnSuccess, hook)
}
// AddOnError registers a hook function that will be called when an error occurs.
// The error parameter contains the actual error object, which can be interrogated
// using Go's error handling patterns like errors.Is and errors.As.
//
// Example:
// ```
// // Create a channel to receive errors for testing
// errChan := make(chan error, 1)
//
// // Register hook to capture and inspect errors
// hooks := &Hooks{}
//
// hooks.AddOnError(func(ctx context.Context, id any, method mcp.MCPMethod, message any, err error) {
// // For capability-related errors
// if errors.Is(err, ErrUnsupported) {
// // Handle capability not supported
// errChan <- err
// return
// }
//
// // For parsing errors
// var parseErr = &UnparsableMessageError{}
// if errors.As(err, &parseErr) {
// // Handle unparsable message errors
// fmt.Printf("Failed to parse %s request: %v\n",
// parseErr.GetMethod(), parseErr.Unwrap())
// errChan <- parseErr
// return
// }
//
// // For resource/prompt/tool not found errors
// if errors.Is(err, ErrResourceNotFound) ||
// errors.Is(err, ErrPromptNotFound) ||
// errors.Is(err, ErrToolNotFound) {
// // Handle not found errors
// errChan <- err
// return
// }
//
// // For other errors
// errChan <- err
// })
//
// server := NewMCPServer("test-server", "1.0.0", WithHooks(hooks))
// ```
func (c *Hooks) AddOnError(hook OnErrorHookFunc) {
c.OnError = append(c.OnError, hook)
}
func (c *Hooks) beforeAny(ctx context.Context, id any, method mcp.MCPMethod, message any) {
if c == nil {
return
}
for _, hook := range c.OnBeforeAny {
hook(ctx, id, method, message)
}
}
func (c *Hooks) onSuccess(ctx context.Context, id any, method mcp.MCPMethod, message any, result any) {
if c == nil {
return
}
for _, hook := range c.OnSuccess {
hook(ctx, id, method, message, result)
}
}
// onError calls all registered error hooks with the error object.
// The err parameter contains the actual error that occurred, which implements
// the standard error interface and may be a wrapped error or custom error type.
//
// This allows consumer code to use Go's error handling patterns:
// - errors.Is(err, ErrUnsupported) to check for specific sentinel errors
// - errors.As(err, &customErr) to extract custom error types
//
// Common error types include:
// - ErrUnsupported: When a capability is not enabled
// - UnparsableMessageError: When request parsing fails
// - ErrResourceNotFound: When a resource is not found
// - ErrPromptNotFound: When a prompt is not found
// - ErrToolNotFound: When a tool is not found
func (c *Hooks) onError(ctx context.Context, id any, method mcp.MCPMethod, message any, err error) {
if c == nil {
return
}
for _, hook := range c.OnError {
hook(ctx, id, method, message, err)
}
}
func (c *Hooks) AddOnRegisterSession(hook OnRegisterSessionHookFunc) {
c.OnRegisterSession = append(c.OnRegisterSession, hook)
}
func (c *Hooks) RegisterSession(ctx context.Context, session ClientSession) {
if c == nil {
return
}
for _, hook := range c.OnRegisterSession {
hook(ctx, session)
}
}
func (c *Hooks) AddOnUnregisterSession(hook OnUnregisterSessionHookFunc) {
c.OnUnregisterSession = append(c.OnUnregisterSession, hook)
}
func (c *Hooks) UnregisterSession(ctx context.Context, session ClientSession) {
if c == nil {
return
}
for _, hook := range c.OnUnregisterSession {
hook(ctx, session)
}
}
func (c *Hooks) AddOnRequestInitialization(hook OnRequestInitializationFunc) {
c.OnRequestInitialization = append(c.OnRequestInitialization, hook)
}
func (c *Hooks) onRequestInitialization(ctx context.Context, id any, message any) error {
if c == nil {
return nil
}
for _, hook := range c.OnRequestInitialization {
err := hook(ctx, id, message)
if err != nil {
return err
}
}
return nil
}
func (c *Hooks) AddBeforeInitialize(hook OnBeforeInitializeFunc) {
c.OnBeforeInitialize = append(c.OnBeforeInitialize, hook)
}
func (c *Hooks) AddAfterInitialize(hook OnAfterInitializeFunc) {
c.OnAfterInitialize = append(c.OnAfterInitialize, hook)
}
func (c *Hooks) beforeInitialize(ctx context.Context, id any, message *mcp.InitializeRequest) {
c.beforeAny(ctx, id, mcp.MethodInitialize, message)
if c == nil {
return
}
for _, hook := range c.OnBeforeInitialize {
hook(ctx, id, message)
}
}
func (c *Hooks) afterInitialize(ctx context.Context, id any, message *mcp.InitializeRequest, result *mcp.InitializeResult) {
c.onSuccess(ctx, id, mcp.MethodInitialize, message, result)
if c == nil {
return
}
for _, hook := range c.OnAfterInitialize {
hook(ctx, id, message, result)
}
}
func (c *Hooks) AddBeforePing(hook OnBeforePingFunc) {
c.OnBeforePing = append(c.OnBeforePing, hook)
}
func (c *Hooks) AddAfterPing(hook OnAfterPingFunc) {
c.OnAfterPing = append(c.OnAfterPing, hook)
}
func (c *Hooks) beforePing(ctx context.Context, id any, message *mcp.PingRequest) {
c.beforeAny(ctx, id, mcp.MethodPing, message)
if c == nil {
return
}
for _, hook := range c.OnBeforePing {
hook(ctx, id, message)
}
}
func (c *Hooks) afterPing(ctx context.Context, id any, message *mcp.PingRequest, result *mcp.EmptyResult) {
c.onSuccess(ctx, id, mcp.MethodPing, message, result)
if c == nil {
return
}
for _, hook := range c.OnAfterPing {
hook(ctx, id, message, result)
}
}
func (c *Hooks) AddBeforeSetLevel(hook OnBeforeSetLevelFunc) {
c.OnBeforeSetLevel = append(c.OnBeforeSetLevel, hook)
}
func (c *Hooks) AddAfterSetLevel(hook OnAfterSetLevelFunc) {
c.OnAfterSetLevel = append(c.OnAfterSetLevel, hook)
}
func (c *Hooks) beforeSetLevel(ctx context.Context, id any, message *mcp.SetLevelRequest) {
c.beforeAny(ctx, id, mcp.MethodSetLogLevel, message)
if c == nil {
return
}
for _, hook := range c.OnBeforeSetLevel {
hook(ctx, id, message)
}
}
func (c *Hooks) afterSetLevel(ctx context.Context, id any, message *mcp.SetLevelRequest, result *mcp.EmptyResult) {
c.onSuccess(ctx, id, mcp.MethodSetLogLevel, message, result)
if c == nil {
return
}
for _, hook := range c.OnAfterSetLevel {
hook(ctx, id, message, result)
}
}
func (c *Hooks) AddBeforeListResources(hook OnBeforeListResourcesFunc) {
c.OnBeforeListResources = append(c.OnBeforeListResources, hook)
}
func (c *Hooks) AddAfterListResources(hook OnAfterListResourcesFunc) {
c.OnAfterListResources = append(c.OnAfterListResources, hook)
}
func (c *Hooks) beforeListResources(ctx context.Context, id any, message *mcp.ListResourcesRequest) {
c.beforeAny(ctx, id, mcp.MethodResourcesList, message)
if c == nil {
return
}
for _, hook := range c.OnBeforeListResources {
hook(ctx, id, message)
}
}
func (c *Hooks) afterListResources(ctx context.Context, id any, message *mcp.ListResourcesRequest, result *mcp.ListResourcesResult) {
c.onSuccess(ctx, id, mcp.MethodResourcesList, message, result)
if c == nil {
return
}
for _, hook := range c.OnAfterListResources {
hook(ctx, id, message, result)
}
}
func (c *Hooks) AddBeforeListResourceTemplates(hook OnBeforeListResourceTemplatesFunc) {
c.OnBeforeListResourceTemplates = append(c.OnBeforeListResourceTemplates, hook)
}
func (c *Hooks) AddAfterListResourceTemplates(hook OnAfterListResourceTemplatesFunc) {
c.OnAfterListResourceTemplates = append(c.OnAfterListResourceTemplates, hook)
}
func (c *Hooks) beforeListResourceTemplates(ctx context.Context, id any, message *mcp.ListResourceTemplatesRequest) {
c.beforeAny(ctx, id, mcp.MethodResourcesTemplatesList, message)
if c == nil {
return
}
for _, hook := range c.OnBeforeListResourceTemplates {
hook(ctx, id, message)
}
}
func (c *Hooks) afterListResourceTemplates(ctx context.Context, id any, message *mcp.ListResourceTemplatesRequest, result *mcp.ListResourceTemplatesResult) {
c.onSuccess(ctx, id, mcp.MethodResourcesTemplatesList, message, result)
if c == nil {
return
}
for _, hook := range c.OnAfterListResourceTemplates {
hook(ctx, id, message, result)
}
}
func (c *Hooks) AddBeforeReadResource(hook OnBeforeReadResourceFunc) {
c.OnBeforeReadResource = append(c.OnBeforeReadResource, hook)
}
func (c *Hooks) AddAfterReadResource(hook OnAfterReadResourceFunc) {
c.OnAfterReadResource = append(c.OnAfterReadResource, hook)
}
func (c *Hooks) beforeReadResource(ctx context.Context, id any, message *mcp.ReadResourceRequest) {
c.beforeAny(ctx, id, mcp.MethodResourcesRead, message)
if c == nil {
return
}
for _, hook := range c.OnBeforeReadResource {
hook(ctx, id, message)
}
}
func (c *Hooks) afterReadResource(ctx context.Context, id any, message *mcp.ReadResourceRequest, result *mcp.ReadResourceResult) {
c.onSuccess(ctx, id, mcp.MethodResourcesRead, message, result)
if c == nil {
return
}
for _, hook := range c.OnAfterReadResource {
hook(ctx, id, message, result)
}
}
func (c *Hooks) AddBeforeListPrompts(hook OnBeforeListPromptsFunc) {
c.OnBeforeListPrompts = append(c.OnBeforeListPrompts, hook)
}
func (c *Hooks) AddAfterListPrompts(hook OnAfterListPromptsFunc) {
c.OnAfterListPrompts = append(c.OnAfterListPrompts, hook)
}
func (c *Hooks) beforeListPrompts(ctx context.Context, id any, message *mcp.ListPromptsRequest) {
c.beforeAny(ctx, id, mcp.MethodPromptsList, message)
if c == nil {
return
}
for _, hook := range c.OnBeforeListPrompts {
hook(ctx, id, message)
}
}
func (c *Hooks) afterListPrompts(ctx context.Context, id any, message *mcp.ListPromptsRequest, result *mcp.ListPromptsResult) {
c.onSuccess(ctx, id, mcp.MethodPromptsList, message, result)
if c == nil {
return
}
for _, hook := range c.OnAfterListPrompts {
hook(ctx, id, message, result)
}
}
func (c *Hooks) AddBeforeGetPrompt(hook OnBeforeGetPromptFunc) {
c.OnBeforeGetPrompt = append(c.OnBeforeGetPrompt, hook)
}
func (c *Hooks) AddAfterGetPrompt(hook OnAfterGetPromptFunc) {
c.OnAfterGetPrompt = append(c.OnAfterGetPrompt, hook)
}
func (c *Hooks) beforeGetPrompt(ctx context.Context, id any, message *mcp.GetPromptRequest) {
c.beforeAny(ctx, id, mcp.MethodPromptsGet, message)
if c == nil {
return
}
for _, hook := range c.OnBeforeGetPrompt {
hook(ctx, id, message)
}
}
func (c *Hooks) afterGetPrompt(ctx context.Context, id any, message *mcp.GetPromptRequest, result *mcp.GetPromptResult) {
c.onSuccess(ctx, id, mcp.MethodPromptsGet, message, result)
if c == nil {
return
}
for _, hook := range c.OnAfterGetPrompt {
hook(ctx, id, message, result)
}
}
func (c *Hooks) AddBeforeListTools(hook OnBeforeListToolsFunc) {
c.OnBeforeListTools = append(c.OnBeforeListTools, hook)
}
func (c *Hooks) AddAfterListTools(hook OnAfterListToolsFunc) {
c.OnAfterListTools = append(c.OnAfterListTools, hook)
}
func (c *Hooks) beforeListTools(ctx context.Context, id any, message *mcp.ListToolsRequest) {
c.beforeAny(ctx, id, mcp.MethodToolsList, message)
if c == nil {
return
}
for _, hook := range c.OnBeforeListTools {
hook(ctx, id, message)
}
}
func (c *Hooks) afterListTools(ctx context.Context, id any, message *mcp.ListToolsRequest, result *mcp.ListToolsResult) {
c.onSuccess(ctx, id, mcp.MethodToolsList, message, result)
if c == nil {
return
}
for _, hook := range c.OnAfterListTools {
hook(ctx, id, message, result)
}
}
func (c *Hooks) AddBeforeCallTool(hook OnBeforeCallToolFunc) {
c.OnBeforeCallTool = append(c.OnBeforeCallTool, hook)
}
func (c *Hooks) AddAfterCallTool(hook OnAfterCallToolFunc) {
c.OnAfterCallTool = append(c.OnAfterCallTool, hook)
}
func (c *Hooks) beforeCallTool(ctx context.Context, id any, message *mcp.CallToolRequest) {
c.beforeAny(ctx, id, mcp.MethodToolsCall, message)
if c == nil {
return
}
for _, hook := range c.OnBeforeCallTool {
hook(ctx, id, message)
}
}
func (c *Hooks) afterCallTool(ctx context.Context, id any, message *mcp.CallToolRequest, result *mcp.CallToolResult) {
c.onSuccess(ctx, id, mcp.MethodToolsCall, message, result)
if c == nil {
return
}
for _, hook := range c.OnAfterCallTool {
hook(ctx, id, message, result)
}
}