A private MCP tool needs an authenticated caller before protocol dispatch.
mcpserver verifies no credentials and issues no tokens: keep admission in your
HTTP service. Tool availability decides which operations to offer after admission;
shared application services still authorize the records those operations use.
The first server intentionally exposes only a fixed public label on loopback. Do not replace that result with private data without adding the boundaries below.
Transport Boundary
Keep private tools on a private network or loopback listener, and use TLS whenever credentials cross a network. Before remote deployment, enforce allowed external Host values and validate Origin using your gateway or outer HTTP middleware. Bearer authentication does not replace Origin validation.
The pinned SDK enables localhost DNS-rebinding protection: requests arriving through a loopback local address with a non-localhost Host receive 403. This is not a public-host allowlist. The adapter does not enable the SDK’s optional cross-origin protection, so your outer Origin policy remains necessary.
With router imported from arkoren.dev/core/http/router, adapt your existing
boundary func(http.Handler) http.Handler before authentication and mounting:
routes := router.New()
routes.Use(router.HTTPMiddleware(boundary))
Here boundary is application-owned middleware enforcing the deployment’s
Host and Origin policy, not an Arkoren API. Behind a proxy, establish which
component validates the external values and trust forwarded headers only from
that proxy. A private proxy address alone does not make client headers trusted.
Typed Authentication
Use your existing bearer verifier to resolve
the application’s user, not merely decode claims. Assume User is your identity
type and verifyAccessToken has signature
func(context.Context, string) (User, error).
Import arkoren.dev/core/http/auth and add authentication to the router above
before mounting the checked endpoint from tool registration:
routes.Use(auth.Middleware(auth.Bearer(verifyAccessToken)))
routes.Use(auth.Require[User]())
routes.Mount("/mcp", endpoint)
auth.Middleware stores a verified User, but permits anonymous requests when
credentials are absent. auth.Require[User]() rejects those requests. Invalid
credentials fail authentication. Configure middleware before Mount and serve
the router through your existing HTTP lifecycle.
The mount and adapter preserve request context for policies and handlers.
auth.FromContext[User] must use the exact concrete type stored at admission:
User and *User occupy different slots. Mismatched lookups fail closed.
If existing net/http middleware already verifies callers, retain it. Reject
anonymous requests and inject the verified identity with auth.NewContext
before calling the endpoint rather than adding another MCP-specific bearer
parser.
Endpoint Admission
Authentication need not grant everyone access to MCP. If your application has
an endpoint-wide rule, import arkoren.dev/core/http/auth/gate and insert it
after authentication but before the mount:
routes.Use(gate.Require(canUseMCP))
canUseMCP is your existing func(context.Context, User) (bool, error) rule.
This admits a caller to the whole endpoint; it does not authorize individual
tools or records. Capability Access handles
those separate decisions.
Browser Access
For a trusted browser application on another origin, configure
CORS before authentication and mounting. With
cors from arkoren.dev/core/http/middleware/cors and standard net/http:
routes.Use(cors.Middleware(func(policy *cors.Builder) {
policy.AllowedOrigins("https://app.example.com")
policy.AllowedMethods(http.MethodPost)
policy.AllowedHeaders("Accept", "Content-Type", "Authorization", "MCP-Protocol-Version", "Mcp-Method", "Mcp-Name")
}))
This is inserted before the authentication block, not after the completed
mount. CORS answers preflights and lets the trusted browser read responses;
it does not reject requests from disallowed origins. Keep the outer Origin
policy. The Mcp-Method and Mcp-Name headers support newer protocol clients.
A bearer-only endpoint does not rely on browser-attached credentials, so it
does not need cookie CSRF protection. If the endpoint also accepts session
cookies, add CSRF protection before
authentication. Import arkoren.dev/core/http/middleware/csrf and trust only
the browser origin that needs access:
routes.Use(csrf.Middleware(func(protection *csrf.Builder) {
protection.TrustedOrigins("https://app.example.com")
}))
Cookies can accompany forged browser requests, so CORS alone does not prevent
their effects. If you intentionally permit credentialed cross-origin browser
requests, also configure policy.AllowCredentials(true) in the CORS callback
and an appropriate cookie policy; never combine credentials with a wildcard
origin.
Execution Bounds
Retain listener header/read/write/idle timeouts and set operation deadlines in outer middleware or application services. The adapter has no tool-duration option. Pass request context into dependencies: a write timeout or client disconnect is not a universal guarantee that work stops, and cancellation does not undo completed effects.
The transport contract specifies the 4 MiB body limit and protocol-dependent disconnect cancellation. Configure any stricter body limit at your gateway or HTTP boundary. Managed error redaction protects tool responses, not arbitrary admission responses or application logs.
Remote OAuth
The bearer example assumes a client already has a token. A remote MCP OAuth deployment also needs protected resource metadata, bearer challenges, and an authorization server issuing tokens for this resource. A login flow or a token verifier alone is not that complete integration.
oauthauth.Client.Verify from arkoren.dev/driver/oauth/oauthauth verifies
OIDC bearer access tokens with configured audiences and returns
oauthauth.Identity. Map it to your application User if your policies expect
that type; the OIDC bearer guide owns verifier
configuration and lifecycle. The driver is neither a token issuer nor a complete
MCP authorization server.
For native integration, the pinned SDK provides RequireBearerToken and
ProtectedResourceMetadataHandler in
github.com/modelcontextprotocol/go-sdk/auth. These are outer HTTP components,
not mcpserver.Builder settings. Configure a real token verifier, accurate public
resource metadata, and authorization-server URLs. Preserve required
WWW-Authenticate challenges rather than replacing them with ordinary JSON
authentication errors.
SDK TokenInfo is separate from Arkoren’s typed user context. Before managed
dispatch, read it with TokenInfoFromContext, resolve your application user,
and inject that user with core/http/auth.NewContext. Require the exact identity
type your tool policies use. The SDK requires nonzero token expiration by
default. Enforce endpoint scopes with RequireBearerTokenOptions.Scopes;
advertising supported scopes in metadata does not enforce them.
The SDK’s bearer middleware returns verifier error text in HTTP failure responses. Return only approved public errors from that verifier and retain private diagnostics in protected local logs. Managed ToolError redaction does not apply to this earlier boundary. Resource metadata is public configuration, not a place for credentials; the SDK metadata handler does not validate its fields.
Neither endpoint scopes nor metadata authorize a particular shipment or invoice. Keep resource checks in shared services. The CLI connection guide shows how to supply an existing token; the CLI does not log in or refresh it.
For endpoint settings, see the MCP server API; for tool policy declarations, see the core MCP API.