pomerium/authorize/evaluator/mcp.go
Denis Mishin 9363457849
mcp: add mcp method and tool logging to authorize (#5668)
## Summary

Adds support for extending authorization log with Model Context Protocol
details.

i.e. 
```json
{
  "level": "info",
  "server-name": "all",
  "service": "authorize",
  "mcp-method": "tools/call",
  "mcp-tool": "describe_table",
  "mcp-tool-parameters": { "table_name": "Categories" },
  "allow": true,
  "allow-why-true": ["email-ok", "mcp-tool-ok"],
  "deny": false,
  "deny-why-false": [],
  "time": "2025-06-24T17:40:41-04:00",
  "message": "authorize check"
}
```

## Related issues

Fixes
https://linear.app/pomerium/issue/ENG-2393/mcp-authorize-each-incoming-request-to-an-mcp-route

## User Explanation

<!-- How would you explain this change to the user? If this
change doesn't create any user-facing changes, you can leave
this blank. If filled out, add the `docs` label -->

## Checklist

- [x] reference any related issues
- [x] updated unit tests
- [x] add appropriate label (`enhancement`, `bug`, `breaking`,
`dependencies`, `ci`)
- [x] ready for review
2025-06-24 20:58:51 -04:00

53 lines
1.3 KiB
Go

package evaluator
import (
"encoding/json"
envoy_service_auth_v3 "github.com/envoyproxy/go-control-plane/envoy/service/auth/v3"
)
// RequestMCP is the MCP field in the request.
type RequestMCP struct {
Method string `json:"method,omitempty"`
ToolCall *RequestMCPToolCall `json:"tool_call,omitempty"`
}
// RequestMCPToolCall represents a tool call within an MCP request.
type RequestMCPToolCall struct {
Name string `json:"name"`
Arguments map[string]any `json:"arguments"`
}
// RequestMCPFromCheckRequest populates a RequestMCP from an Envoy CheckRequest proto for MCP routes.
func RequestMCPFromCheckRequest(
in *envoy_service_auth_v3.CheckRequest,
) (RequestMCP, bool) {
var mcpReq RequestMCP
body := in.GetAttributes().GetRequest().GetHttp().GetBody()
if body == "" {
return mcpReq, false
}
var jsonRPCReq struct {
Method string `json:"method"`
Params json.RawMessage `json:"params,omitempty"`
}
if err := json.Unmarshal([]byte(body), &jsonRPCReq); err != nil {
return mcpReq, false
}
mcpReq.Method = jsonRPCReq.Method
if jsonRPCReq.Method == "tools/call" {
var toolCall RequestMCPToolCall
err := json.Unmarshal(jsonRPCReq.Params, &toolCall)
if err != nil {
return mcpReq, false
}
mcpReq.ToolCall = &toolCall
}
return mcpReq, true
}