Connecting Go Service to AI via MCP Adapter Without Domain Changes
How to add Model Context Protocol (MCP) to a Go service using v1.8.0 without modifying internal domain code, complete with CI checks.

Stock photo for illustration only, not from the actual event
- Add a Model Context Protocol (MCP) channel without touching internal domain code.
- Use the official MCP Go SDK v1.8.0 to build a dedicated adapter.
- Handle errors so AI models can understand and self-correct.
- Implement CI checks to prevent inner packages from importing external SDKs.
When the ticket states to make refunds callable from an AI assistant, your refund service likely already has two entry points: support staff invoking POST /orders/{id}/refund and on-call engineers running a terminal command. Now, a coding agent or chat client requires a third entry point supporting the Model Context Protocol (MCP).
This scenario typically diverges into two approaches. In the first approach, someone adds jsonschema tags to domain structs and threads a pointer to *mcp.CallToolRequest into the service layer just for metadata, forcing refund rules to import an SDK. In the second approach, you write a brand new package alongside the HTTP handler, ensuring a git diff --stat reports zero lines of production code changed under internal/domain and internal/app.

Stock photo for illustration only, not from the actual event
This post demonstrates the second approach using the official MCP Go SDK at version v1.8.0, complete with a CI check that fails if inner packages ever import it. The domain understands what a refund is and when it is permitted, importing nothing except standard errors.
An MCP server exposes tools that a client lists, allowing the model to pick one and send requests with JSON arguments. In the Go SDK, mcp.AddTool registers a typed handler where input schemas are inferred from the In type, descriptions are derived from jsonschema struct tags, and inputs undergo validation before execution.
Hexagonal Architecture (Ports and Adapters) shines in scenarios like this. When a new protocol arrives, the cost is restricted to building a single adapter because the use case is already accessible through an interface oblivious to HTTP. This design pattern ensures the codebase remains maintainable and easily extensible for future integrations.
Regarding error handling, the specification defines two failure types: protocol errors as JSON-RPC errors for unknown tools or malformed requests, and tool execution errors returned as normal results with isError: true, covering business logic errors such as orders already being refunded. The specification advises clients to forward these execution errors to the model for self-correction.
"Refund must be between 1 cent and the amount paid"
Original Article
The final step involves proving the domain remains pristine. The command go list -deps walks through package dependencies to ensure no unauthorized imports exist, while a strict unit test using go list -json asserts that the domain package depends on nothing outside the standard library.
Source: Dev.to
Found something wrong in this article? Report an issue with this article
Comments
Leave a Comment