# Expose Your Go App as an MCP Server With ToGO web-mcp

> web-mcp turns a ToGO app into a remote MCP server over Streamable HTTP: register tools in Go, protect them with bearer tokens, and let Claude, ChatGPT or Cursor call them. Setup, auth and limits.

*2026-10-12T12:32:37Z*

AI agents are becoming a second set of users for most apps. The Model Context Protocol (MCP) is how they call your app: you expose tools, and Claude, ChatGPT, Cursor or any MCP client can use them.

**The short answer:** install `togo-framework/web-mcp`, register tools in Go with `webmcp.AddTool`, and your ToGO app serves a remote MCP server at `/mcp` over Streamable HTTP (MCP revision 2025-06-18). Turn on bearer auth with one environment variable, issue personal access tokens, and run as many named servers as you need, each at `/mcp/{server}`.

## Install

```bash
togo install togo-framework/web-mcp
```

## Register a tool

```go
s := webmcp.FromKernel(k)

webmcp.AddTool(s.Default(), "ping", "health check",
    func(ctx context.Context, _ webmcp.NoArgs) (string, error) { return "pong", nil })
```

That tool is now available at `/mcp`. For a separate server, say one just for internal agents, with a scope check:

```go
agents := s.NewServer("agents", "1.0.0") // served at /mcp/agents

webmcp.AddTool(agents, "list_projects", "list projects",
    func(ctx context.Context, in ListArgs) (string, error) {
        id, _ := webmcp.IdentityFrom(ctx) // who is calling, and with which scopes
        if !id.Can("read") {
            return "", fmt.Errorf("forbidden")
        }
        return listProjects(ctx, in)
    })
```

`webmcp.IdentityFrom(ctx)` tells you who is calling, and `id.Can("read")` checks a scope, so a tool can refuse work the token isn't allowed to do. For resources, prompts or custom tool schemas, `srv.MCP` gives you the underlying MCP server.

## Auth

By default the endpoint is open, which is fine on your laptop and nowhere else. Configure it with environment variables:

| Variable | What it does |
|---|---|
| `WEBMCP_BASE_PATH` | Where servers mount (default `/mcp`) |
| `WEBMCP_AUTH` | `none` or `bearer` |
| `WEBMCP_TOKENS` | Static tokens, for simple setups |
| `WEBMCP_ADMIN_KEY` | Protects the token management API |
| `WEBMCP_AUTH_SERVER` | An OAuth authorization server to advertise |

With `WEBMCP_AUTH=bearer`, a request without a valid token gets a `401` with a `WWW-Authenticate` header, and `/.well-known/oauth-protected-resource` (RFC 9728) tells MCP clients where to get one. That's the discovery flow clients like Claude use to start sign-in on their own.

Personal access tokens look like `mcp_pat_…`. They're shown once when created and stored only as SHA-256 hashes. They're managed through `/api/web-mcp/tokens`, and `/api/web-mcp/servers` lists the servers. To keep tokens in your own database, implement `TokenStore` (or `ManagedTokenStore`) and set it with `Registry.SetTokenStore`.

## web-mcp vs the built-in `mcp`

ToGO already ships an `mcp` command. That one is a **stdio** server for development: it lets your coding agent run the framework's generators on your machine. **web-mcp** is for your users' agents: a remote HTTP server, with auth, that's part of your deployed app. Most apps want both.

## Honest limits

- **MCP is still moving.** web-mcp targets revision 2025-06-18; clients that only speak older transports may need an adapter.
- **Tools are an API.** Anything you expose can be called by an agent acting for a user, so scope tokens tightly and check `id.Can` in every tool that changes data.
- **ToGO is 0.x**, and the plugin follows it.

## FAQ

### How do I build an MCP server in Go?
With ToGO, install the web-mcp plugin and register tools with `webmcp.AddTool`. The app serves them at `/mcp` over Streamable HTTP, ready for any MCP client.

### Does web-mcp support authentication?
Yes. Set `WEBMCP_AUTH=bearer` to require tokens. It supports static tokens, hashed personal access tokens, and OAuth discovery through `/.well-known/oauth-protected-resource` (RFC 9728).

### Can one app expose more than one MCP server?
Yes. `s.NewServer("agents", "1.0.0")` creates another server at `/mcp/agents`, with its own tools.

### What's the difference between stdio and Streamable HTTP MCP?
A stdio server runs as a local process the client starts, which suits development tools. A Streamable HTTP server runs remotely behind a URL, so it can be deployed, shared and protected with auth.

## Next steps

- [web-mcp plugin](/en/plugins/web-mcp)
- [ToGO vs Gin, Echo and Fiber](/en/blog/togo-vs-gin-echo-fiber)
- [Get started with ToGO](/en/docs)

Want your product to be usable by AI agents, safely? I build MCP servers and agent integrations. [Get in touch](https://fadymondy.com/en/contact?utm_source=to-go&utm_medium=referral&utm_campaign=seo-content-oct26).

---

Source: https://to-go.dev/en/blog/go-mcp-server-togo-web-mcp
