mirror of
https://github.com/googleapis/genai-toolbox.git
synced 2026-01-10 07:58:12 -05:00
## Description Tool `invoke()` and `RequiresClientAuthorization()` takes a new input argument -- Resource Manager. Resource manager will be used to retrieve Source in the next step. In order to achieve the goal, this PR implements the follows: * move resource manager from the server package to a new package to prevent import cycles (between server and mcp) * added a new interface in `tools.go` to prevent import cycle (between resources and tools package) * add new input argument in all tools ## PR Checklist > Thank you for opening a Pull Request! Before submitting your PR, there are a > few things you can do to make sure it goes smoothly: - [x] Make sure you reviewed [CONTRIBUTING.md](https://github.com/googleapis/genai-toolbox/blob/main/CONTRIBUTING.md) - [x] Make sure to open an issue as a [bug/issue](https://github.com/googleapis/genai-toolbox/issues/new/choose) before writing your code! That way we can discuss the change, evaluate designs, and agree on the general idea - [x] Ensure the tests and linter pass - [x] Code coverage does not decrease (if any source code was changed) - [x] Appropriate docs were updated (if necessary) - [x] Make sure to add `!` if this involve a breaking change
118 lines
4.3 KiB
Go
118 lines
4.3 KiB
Go
// Copyright 2025 Google LLC
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package mcp
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
"slices"
|
|
|
|
"github.com/googleapis/genai-toolbox/internal/prompts"
|
|
"github.com/googleapis/genai-toolbox/internal/server/mcp/jsonrpc"
|
|
mcputil "github.com/googleapis/genai-toolbox/internal/server/mcp/util"
|
|
v20241105 "github.com/googleapis/genai-toolbox/internal/server/mcp/v20241105"
|
|
v20250326 "github.com/googleapis/genai-toolbox/internal/server/mcp/v20250326"
|
|
v20250618 "github.com/googleapis/genai-toolbox/internal/server/mcp/v20250618"
|
|
"github.com/googleapis/genai-toolbox/internal/server/resources"
|
|
"github.com/googleapis/genai-toolbox/internal/tools"
|
|
)
|
|
|
|
// LATEST_PROTOCOL_VERSION is the latest version of the MCP protocol supported.
|
|
// Update the version used in InitializeResponse when this value is updated.
|
|
const LATEST_PROTOCOL_VERSION = v20250618.PROTOCOL_VERSION
|
|
|
|
// SUPPORTED_PROTOCOL_VERSIONS is the MCP protocol versions that are supported.
|
|
var SUPPORTED_PROTOCOL_VERSIONS = []string{
|
|
v20241105.PROTOCOL_VERSION,
|
|
v20250326.PROTOCOL_VERSION,
|
|
v20250618.PROTOCOL_VERSION,
|
|
}
|
|
|
|
// InitializeResponse runs capability negotiation and protocol version agreement.
|
|
// This is the Initialization phase of the lifecycle for MCP client-server connections.
|
|
// Always start with the latest protocol version supported.
|
|
func InitializeResponse(ctx context.Context, id jsonrpc.RequestId, body []byte, toolboxVersion string) (any, string, error) {
|
|
var req mcputil.InitializeRequest
|
|
if err := json.Unmarshal(body, &req); err != nil {
|
|
err = fmt.Errorf("invalid mcp initialize request: %w", err)
|
|
return jsonrpc.NewError(id, jsonrpc.INVALID_REQUEST, err.Error(), nil), "", err
|
|
}
|
|
|
|
var protocolVersion string
|
|
v := req.Params.ProtocolVersion
|
|
if slices.Contains(SUPPORTED_PROTOCOL_VERSIONS, v) {
|
|
protocolVersion = v
|
|
} else {
|
|
protocolVersion = LATEST_PROTOCOL_VERSION
|
|
}
|
|
|
|
toolsListChanged := false
|
|
promptsListChanged := false
|
|
result := mcputil.InitializeResult{
|
|
ProtocolVersion: protocolVersion,
|
|
Capabilities: mcputil.ServerCapabilities{
|
|
Tools: &mcputil.ListChanged{
|
|
ListChanged: &toolsListChanged,
|
|
},
|
|
Prompts: &mcputil.ListChanged{
|
|
ListChanged: &promptsListChanged,
|
|
},
|
|
},
|
|
ServerInfo: mcputil.Implementation{
|
|
BaseMetadata: mcputil.BaseMetadata{
|
|
Name: mcputil.SERVER_NAME,
|
|
},
|
|
Version: toolboxVersion,
|
|
},
|
|
}
|
|
res := jsonrpc.JSONRPCResponse{
|
|
Jsonrpc: jsonrpc.JSONRPC_VERSION,
|
|
Id: id,
|
|
Result: result,
|
|
}
|
|
|
|
return res, protocolVersion, nil
|
|
}
|
|
|
|
// NotificationHandler process notifications request. It MUST NOT send a response.
|
|
// Currently Toolbox does not process any notifications.
|
|
func NotificationHandler(ctx context.Context, body []byte) error {
|
|
var notification jsonrpc.JSONRPCNotification
|
|
if err := json.Unmarshal(body, ¬ification); err != nil {
|
|
return fmt.Errorf("invalid notification request: %w", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// ProcessMethod returns a response for the request.
|
|
// This is the Operation phase of the lifecycle for MCP client-server connections.
|
|
func ProcessMethod(ctx context.Context, mcpVersion string, id jsonrpc.RequestId, method string, toolset tools.Toolset, promptset prompts.Promptset, resourceMgr *resources.ResourceManager, body []byte, header http.Header) (any, error) {
|
|
switch mcpVersion {
|
|
case v20250618.PROTOCOL_VERSION:
|
|
return v20250618.ProcessMethod(ctx, id, method, toolset, promptset, resourceMgr, body, header)
|
|
case v20250326.PROTOCOL_VERSION:
|
|
return v20250326.ProcessMethod(ctx, id, method, toolset, promptset, resourceMgr, body, header)
|
|
default:
|
|
return v20241105.ProcessMethod(ctx, id, method, toolset, promptset, resourceMgr, body, header)
|
|
}
|
|
}
|
|
|
|
// VerifyProtocolVersion verifies if the version string is valid.
|
|
func VerifyProtocolVersion(version string) bool {
|
|
return slices.Contains(SUPPORTED_PROTOCOL_VERSIONS, version)
|
|
}
|