· 3 min read

FineMCP Public Beta is Open

We're opening FineMCP to the public for beta testing. Here's what's ready, what's rough, and how you can help shape it.

Today we’re opening FineMCP to public beta.

If you’re building Go services that need to expose AI-friendly interfaces — or if you’re integrating MCP into an existing backend — this is the right time to kick the tires and give us feedback.

What beta means

The API is stable for the core primitives: server.New, server.AddTool, server.AddResource, server.AddPrompt, and the middleware chain. We will not break these without a deprecation cycle.

Everything marked Experimental in the docs may change. If you use it, pin your version and watch the changelog.

What’s ready today

Tools

Define typed tool handlers with struct-based input validation. FineMCP derives JSON Schema from Go struct tags automatically — no manual schema writing.

type SearchInput struct {
    Query  string `json:"query"  jsonschema:"required,description=Search query"`
    Limit  int    `json:"limit"  jsonschema:"default=10,minimum=1,maximum=100"`
}

server.AddTool(mcp.Tool{
    Name:        "search",
    Description: "Search documents by keyword",
}, func(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
    var in SearchInput
    req.BindArguments(&in)
    results := db.Search(ctx, in.Query, in.Limit)
    return mcp.NewToolResultText(results.Format()), nil
})

Resources & Templates

Expose dynamic data as MCP resources. Use URI templates to let clients browse parameterised resource spaces — think /users/{id}/profile or /repos/{owner}/{repo}/issues.

Streaming

Long-running tools can stream partial results back as they become available. No polling, no custom protocols — just send tokens as you produce them.

16 middleware, out of the box

CategoryMiddleware
ReliabilityRecover, Timeout, Retry, CircuitBreaker
SecurityAuth, RBAC, IPAllowlist
ObservabilityLogger, Metrics, Tracing (OpenTelemetry)
ControlRateLimit, Concurrency, Cache, Dedup
DXValidator, RequestID, Audit

5 transports

  • stdio — pipe-based, perfect for Claude Desktop and local agents
  • HTTP/SSE — standard for cloud deployments
  • HTTP Streaming — chunked streaming over plain HTTP
  • WebSocket — bidirectional, real-time
  • In-process — embed a server inside your binary, no network hop

Testing

func TestMyTool(t *testing.T) {
    client := testutil.NewInProcessClient(srv)
    result, err := client.CallTool(ctx, "search", map[string]any{
        "query": "golang middleware",
        "limit": 5,
    })
    require.NoError(t, err)
    assert.Contains(t, result.Text(), "middleware")
}

No ports, no subprocess, no mocks. Just call the tool.

What’s rough

We’re honest about this:

  • Docs coverage is uneven. The middleware reference is complete. Some advanced topics (gateway mode, plugin system) have stubs.
  • Error messages could be better in a few middleware edge cases — we’re working through them.
  • Windows CI is passing but less battle-tested than Linux/macOS.

How to help

The most valuable thing you can do right now is build something real with it and tell us where you hit friction.

Open a GitHub issue for bugs. Start a discussion for API questions. If something feels unnecessarily complicated, that’s signal worth sharing — we want the happy path to feel obvious.

Read the docs
Browse the tutorials
Open an issue
Join Slack

We’ll be shipping weekly updates throughout the beta. Thank you for being early.