Files
kanban/backend/mcp_http.go
T
egutierrez c28ae7d3c0 chore: auto-commit (12 archivos)
- app.md
- backend/handlers.go
- backend/main.go
- frontend/src/App.tsx
- frontend/src/api.ts
- frontend/vite.config.ts
- backend/mcp_http.go
- backend/mcp_tokens.go
- backend/mcp_tokens_handlers.go
- backend/migrations/016_mcp_tokens.sql
- ...

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 14:38:17 +02:00

56 lines
1.4 KiB
Go

package main
import (
"context"
"encoding/json"
"errors"
"net/http"
"os"
"strings"
"fn-registry/functions/infra"
)
// mcpHTTPHandler builds the http.Handler that serves the MCP Streamable HTTP
// transport for remote Claude clients. Bearer-auth backed by the mcp_tokens
// table; tool dispatch reuses executeTool() — the same set of operations the
// chat assistant uses internally.
func mcpHTTPHandler(db *DB) http.Handler {
auth := func(r *http.Request) (context.Context, error) {
header := r.Header.Get("Authorization")
token := strings.TrimSpace(strings.TrimPrefix(header, "Bearer "))
if token == "" || token == header {
return nil, errors.New("missing bearer token")
}
userID, err := db.LookupMCPToken(token)
if err != nil {
return nil, err
}
if userID == "" {
return nil, errors.New("invalid or revoked token")
}
return context.WithValue(r.Context(), userCtxKey, userID), nil
}
handler := func(ctx context.Context, name string, input json.RawMessage) (any, bool, error) {
body := input
if len(body) == 0 {
body = json.RawMessage(`{}`)
}
res := executeTool(db, name, body)
if !res.OK {
return res.Error, true, nil
}
return res.Result, false, nil
}
return infra.MCPHTTPHandler(infra.MCPHTTPOpts{
Name: "kanban",
Version: Version,
Tools: mcpToolDefs(),
Handler: handler,
Auth: auth,
Logger: os.Stderr,
})
}