Go SDK

mcp-anything is library-first. You can embed the proxy in your own Go binary, register custom tool providers, and import only the auth strategies and upstream types you need.

Embedding the proxy

import (
    "context"
    mcpanything "github.com/gaarutyunov/mcp-anything/pkg/mcpanything"
    _ "github.com/gaarutyunov/mcp-anything/pkg/auth/inbound/all"   // all inbound strategies
    _ "github.com/gaarutyunov/mcp-anything/pkg/auth/outbound/all"  // all outbound strategies
    _ "github.com/gaarutyunov/mcp-anything/pkg/upstream/all"       // all upstream types
)

func main() {
    proxy, err := mcpanything.New(ctx, mcpanything.Options{
        ConfigPath: "/etc/mcp-anything/config.yaml",
    })
    if err != nil {
        log.Fatal(err)
    }
    if err := proxy.Start(ctx); err != nil {
        log.Fatal(err)
    }
}

Registry pattern

Every pluggable component — auth strategies, upstream types, embedding providers — follows the registry pattern. Components register themselves via init(), which runs only when the package is imported. If you don't import a package, its code is not linked into the binary.

Importing only what you need

// Import only JWT inbound auth and OAuth2 outbound auth
import (
    _ "github.com/gaarutyunov/mcp-anything/pkg/auth/inbound/jwt"
    _ "github.com/gaarutyunov/mcp-anything/pkg/auth/outbound/oauth2"
    // Lua and JavaScript strategies are NOT linked
)

// Import only HTTP upstream type
import (
    _ "github.com/gaarutyunov/mcp-anything/pkg/upstream/http"
    // command and script upstreams are NOT linked
)

All-in-one bundles

// Import everything
import _ "github.com/gaarutyunov/mcp-anything/pkg/auth/inbound/all"
import _ "github.com/gaarutyunov/mcp-anything/pkg/auth/outbound/all"
import _ "github.com/gaarutyunov/mcp-anything/pkg/upstream/all"

Registering a custom upstream type

package myupstream

import (
    "context"
    "github.com/gaarutyunov/mcp-anything/pkg/upstream"
    "github.com/gaarutyunov/mcp-anything/pkg/config"
)

func init() {
    upstream.Register("my-type", func(ctx context.Context, cfg *config.UpstreamConfig) (upstream.Provider, error) {
        return &MyProvider{cfg: cfg}, nil
    })
}

type MyProvider struct {
    cfg *config.UpstreamConfig
}

func (p *MyProvider) Tools(ctx context.Context) ([]mcp.Tool, error) {
    // return your custom tools
}

func (p *MyProvider) Call(ctx context.Context, name string, args map[string]any) (*mcp.CallToolResult, error) {
    // handle tool calls
}

Then import it in your binary:

import _ "github.com/myorg/myproject/myupstream"

Registering a custom inbound auth strategy

package myauth

import (
    "context"
    "github.com/gaarutyunov/mcp-anything/pkg/auth/inbound"
    "github.com/gaarutyunov/mcp-anything/pkg/config"
)

func init() {
    inbound.Register("my-strategy", func(ctx context.Context, cfg *config.InboundAuthConfig) (inbound.TokenValidator, string, error) {
        return &MyValidator{}, "my-strategy", nil
    })
}

Tree-shaking

Go's linker excludes packages that are never imported. The tests/treeshake/ directory contains build-tag-isolated programs that verify importing only specific sub-packages does not pull in unrelated heavy dependencies (e.g. Sobek JavaScript runtime, gopher-lua).

When adding a new strategy or upstream type, add a treeshake test to verify isolation.

Module

go get github.com/gaarutyunov/mcp-anything@latest

Module path: github.com/gaarutyunov/mcp-anything

See also