package mcp import ( "context" "fmt" "github.com/kami/maven/internal/webfetch" ) // WebfetchDoor builds the PosterFactory used in production: one guarded // webfetch.Fetcher per url server, with that server's allow_private and the // shared host lists and limits. // // One fetcher PER server is the point. allow_private is a hole in the // private-address guard, and a hole punched for the Vikunja server on loopback // must not become a hole for some public endpoint that happens to redirect at // the LAN. Rate limiting is per fetcher too, which is the right shape here: // separate servers are separate hosts. func WebfetchDoor(limits webfetch.Config) PosterFactory { return func(cfg ServerConfig) (Poster, error) { c := limits c.AllowPrivate = cfg.AllowPrivate if c.Timeout <= 0 && cfg.Timeout > 0 { c.Timeout = cfg.Timeout } return fetcherPoster{webfetch.New(c)}, nil } } // fetcherPoster adapts webfetch.Fetcher to Poster. It exists so this package // does not have to know webfetch's Response type, and so a test can substitute // a fake without a listener. type fetcherPoster struct{ f *webfetch.Fetcher } func (p fetcherPoster) Post(ctx context.Context, rawURL, contentType string, body []byte, hdr map[string]string) (*PostResponse, error) { resp, err := p.f.Post(ctx, rawURL, contentType, body, hdr) if err != nil { return nil, fmt.Errorf("mcp: post %s: %w", rawURL, err) } return &PostResponse{ Status: resp.Status, ContentType: resp.ContentType, Body: resp.Body, Header: resp.Header, }, nil }