Skip to content

refactor(mcp): migrate server to official go-sdk#366

Merged
pocky merged 1 commit into
mainfrom
feature/F104-mcp-server-migration-to-the-official-go-
Jun 5, 2026
Merged

refactor(mcp): migrate server to official go-sdk#366
pocky merged 1 commit into
mainfrom
feature/F104-mcp-server-migration-to-the-official-go-

Conversation

@pocky
Copy link
Copy Markdown
Contributor

@pocky pocky commented Jun 4, 2026

Summary

  • Replaces the custom pkg/mcpserver JSON-RPC 2.0 implementation (~1270 LOC) with the official github.com/modelcontextprotocol/go-sdk, reducing protocol maintenance burden and enabling future spec extensions (F108)
  • Wraps the SDK in a new internal/infrastructure/mcp/ adapter that preserves hexagonal architecture — the CLI layer only depends on domain ports, not SDK types
  • Hardens related infrastructure: mcp_proxy_purge now distinguishes timeout/not-installed/error failure modes with actionable log levels, and mcp_serve.go treats a failed os.Getwd() as a fatal error rather than silently disabling the sandbox
  • Documents the migration decision in ADR 019 and adds SDK-level integration tests that exercise the real transport layer

Changes

Deleted: Custom MCP server package

  • pkg/mcpserver/server.go: Deleted — custom JSON-RPC 2.0 server implementation
  • pkg/mcpserver/protocol.go: Deleted — custom wire-protocol types and constants
  • pkg/mcpserver/types.go: Deleted — custom type definitions
  • pkg/mcpserver/doc.go: Deleted — package documentation
  • pkg/mcpserver/architecture_test.go: Deleted — AST import constraint tests
  • pkg/mcpserver/protocol_test.go: Deleted — protocol serialization tests
  • pkg/mcpserver/server_test.go: Deleted — server behavior tests

New: Official SDK adapter

  • internal/infrastructure/mcp/server.go: RegisterProvider now uses a two-pass (validate-then-commit) pattern for atomicity; extracted serve() helper shared by ServeStdio and new ServeIO
  • internal/infrastructure/mcp/handler.go: Added nil-result guard and malformed-JSON fallback; removed redundant err = nil in panic recovery
  • internal/infrastructure/mcp/mapping.go: Removed schemaFromMap and jsonschema-go dependency; toolToMCP passes InputSchema raw map directly to SDK
  • internal/infrastructure/mcp/doc.go: Updated to reflect removal of schemaFromMap and jsonschema-go import
  • internal/infrastructure/mcp/architecture_test.go: Removed github.com/google/jsonschema-go/ from allowed import list
  • internal/infrastructure/mcp/testhelpers_test.go: Extracted shared fakeProvider and recordingProvider test doubles (previously duplicated across test files)
  • internal/infrastructure/mcp/mcp_test.go: Added TestServeIO_* parallel-safe tests using in-memory pipes; added atomicity assertion for duplicate-tool registration; documented SDK non-deterministic error behavior on context cancellation
  • internal/infrastructure/mcp/handler_test.go: Refactored to use shared test doubles; added TestHandlerFor_NilResult, TestHandlerFor_NilParams, TestHandlerFor_MalformedJSONArgs
  • internal/infrastructure/mcp/mapping_test.go: Removed TestSchemaFromMap_* tests (function deleted); cleaned up wantErr fields

CLI interface

  • internal/interfaces/cli/mcp_serve.go: os.Getwd() failure is now a fatal ExitSystem error instead of silently leaving rootDir empty (sandbox bypass)
  • internal/interfaces/cli/mcp_serve_plugin_test.go: Extracted requestToolsList helper; added TestArchitecture_MCPServe_NewUsesVersion (AST enforcement that inframcp.New(Version) is called); strengthened TestResolveOperationProvider_EmptyDepsInitializes assertions
  • internal/interfaces/cli/mcp_serve_helpers_test.go: Deleted (empty file)

Infrastructure: MCP proxy purge

  • internal/infrastructure/agents/mcp_proxy_purge.go: Extracted named constants (mcpListDefaultTimeout, mcpRemoveTimeout, exitCodeCommandNotFound); added resolveListTimeout with env-var override; distinguished timeout (WARN), execution error (DEBUG), exit-127 (DEBUG), and non-zero exit (DEBUG) failure modes; added firstLine helper for single-line stderr in logs
  • internal/infrastructure/agents/mcp_proxy_purge_test.go: Added warnCalls to log capture; added TestResolveListTimeout, TestPurgeOrphanMCPRegistrations_TimeoutLogsWarn, TestPurgeOrphanMCPRegistrations_NotInstalledIsQuiet

Domain ports

  • internal/domain/ports/tool_provider.go: Added doc comment to ToolProvider interface specifying nil/empty-args equivalence, non-nil success result requirement, and dual error-reporting contract

Integration tests

  • tests/integration/mcp/sdk_client_test.go: New — end-to-end tests exercising the SDK transport layer with a real MCP client
  • tests/integration/mcp/plugin_bridge_test.go: Minor import/assertion updates for SDK adapter

Documentation & config

  • docs/ADR/019-mcp-server-sdk-adapter.md: New ADR documenting the migration decision, rationale, alternatives, and trade-offs
  • docs/ADR/017-mcp-proxy-stdio-subprocess-for-tool-interception.md: Updated implementation note to reference F104/ADR 019
  • docs/ADR/README.md: Added ADR 019 entry
  • docs/development/architecture.md: Added mcp/ entry to infrastructure layer
  • docs/reference/package-documentation.md: Added internal/infrastructure/mcp to documented packages (28 total)
  • .go-arch-lint.yml: Removed go-jsonschema vendor and its canUse entry; added explanatory comment
  • go.mod: Marked github.com/google/jsonschema-go as // indirect

Test plan

  • make build && make lint pass with zero violations
  • make test and make test-race pass, including new sdk_client_test.go integration tests
  • awf mcp-serve subprocess correctly lists and invokes builtin tools over stdio when exercised via mcp_proxy in a real workflow run
  • pkg/mcpserver has zero remaining importers: grep -r "pkg/mcpserver" --include="*.go" . returns no results

Closes #365


Generated with awf commit workflow

- `.go-arch-lint.yml`: remove go-jsonschema vendor alias; guard against accidental direct import
- `docs/ADR/017-mcp-proxy-stdio-subprocess-for-tool-interception.md`: update public-package note to reflect migration
- `docs/ADR/019-mcp-server-sdk-adapter.md`: add ADR documenting migration decision, rationale, and trade-offs
- `docs/ADR/README.md`: register ADR 019
- `docs/development/architecture.md`: document internal/infrastructure/mcp in infra layer
- `docs/reference/package-documentation.md`: add internal/infrastructure/mcp (28 total packages)
- `go.mod`: mark github.com/google/jsonschema-go as indirect
- `internal/domain/ports/tool_provider.go`: document ToolProvider contract for nil args, nil result, and dual error reporting
- `internal/infrastructure/agents/mcp_proxy_purge.go`: classify timeout as WARN, exit 127 as DEBUG; add resolveListTimeout with AWF_MCP_PROXY_LIST_TIMEOUT; extract firstLine helper
- `internal/infrastructure/agents/mcp_proxy_purge_test.go`: add timeout WARN, exit 127 quiet, and env-var resolution tests
- `internal/infrastructure/mcp/architecture_test.go`: remove jsonschema-go from allowed import prefixes
- `internal/infrastructure/mcp/doc.go`: update to reflect schemaFromMap removal and transitive-only jsonschema dependency
- `internal/infrastructure/mcp/handler.go`: add nil result guard and nil params guard; annotate malformed JSON fallback
- `internal/infrastructure/mcp/handler_test.go`: migrate to shared fakeProvider; add NilResult, NilParams, MalformedJSONArgs tests
- `internal/infrastructure/mcp/mapping.go`: remove schemaFromMap and jsonschema-go import; simplify toolToMCP
- `internal/infrastructure/mcp/mapping_test.go`: remove TestSchemaFromMap_* and TestPackageCoverageSample; clean unused wantErr fields
- `internal/infrastructure/mcp/mcp_test.go`: migrate to testhelpers; add parallel-safe ServeIO tests; assert atomicity on duplicate registration
- `internal/infrastructure/mcp/server.go`: split RegisterProvider into validate+commit passes; extract serve() helper; wrap ListTools error
- `internal/infrastructure/mcp/testhelpers_test.go`: add shared fakeProvider and recordingProvider test doubles
- `internal/interfaces/cli/mcp_serve.go`: make os.Getwd() failure fatal (ExitSystem) instead of silently disabling sandbox
- `internal/interfaces/cli/mcp_serve_helpers_test.go`: delete empty placeholder file
- `internal/interfaces/cli/mcp_serve_plugin_test.go`: extract requestToolsList helper; add TestArchitecture_MCPServe_NewUsesVersion AST test; strengthen TestResolveOperationProvider assertions
- `pkg/mcpserver/architecture_test.go`: delete (package removed)
- `pkg/mcpserver/doc.go`: delete (package removed)
- `pkg/mcpserver/protocol.go`: delete (package removed)
- `pkg/mcpserver/protocol_test.go`: delete (package removed)
- `pkg/mcpserver/server.go`: delete (package removed)
- `pkg/mcpserver/server_test.go`: delete (package removed)
- `pkg/mcpserver/types.go`: delete (package removed)
- `tests/integration/mcp/plugin_bridge_test.go`: update imports for migration
- `tests/integration/mcp/sdk_client_test.go`: add SDK client integration tests over in-memory transport

Closes #365
@pocky pocky force-pushed the feature/F104-mcp-server-migration-to-the-official-go- branch from b6a671d to 9740292 Compare June 4, 2026 23:45
@pocky pocky marked this pull request as ready for review June 5, 2026 07:06
@pocky pocky merged commit b7090f9 into main Jun 5, 2026
5 checks passed
@pocky pocky deleted the feature/F104-mcp-server-migration-to-the-official-go- branch June 5, 2026 07:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

F104: MCP server migration to the official go-sdk

1 participant