{"id":"5fa9da83-67f2-4d46-bf40-c6a61a78a0f7","slug":"go-foundation","kind":"mcp","name":"go-foundation","summary":"A collection of foundational Go primitives for building declarative, struct-tag-driven libraries.","owner":"mirkobrombin","repoUrl":"https://github.com/mirkobrombin/go-foundation","license":"MIT","licenseTier":"permissive","trust":"community","stars":3,"match":null,"fewStars":true,"format":"mcp","createdAt":"2026-01-14T21:55:28.000Z","addedAt":"2026-10-21T16:39:04.983Z","logoUrl":"https://avatars.githubusercontent.com/u/9479903?u=9dd7be66c316f101498c3232dcf75e4954690ddc&v=4","linkOnly":false,"collection":null,"skillPath":null,"categories":["utilities"],"tags":["building-block","declarative","go","golang","lib","library","primitives","shared-library"],"runtime":"go","local":true,"cloudCapable":false,"cloudCapability":"unknown","cloudReadyOnPlatform":false,"needsApiKey":false,"reviewed":false,"syncedAt":"2026-10-26T21:10:31.463Z","sample":false,"url":"https://conduits.dev/tools/go-foundation","language":"Go","transports":["stdio"],"install":{},"requirements":{"env":[],"upstreamMayCharge":false},"tools":null,"readme":"<div align=\"center\">\n  <img src=\"https://github.com/mirkobrombin/go-foundation/blob/main/logo.png?raw=true\" height=\"128\"/>\n  <h1>go-foundation v2</h1>\n  <p>A Go application foundation with development-time checks.</p>\n  <p>\n    <img src=\"https://img.shields.io/badge/Go-1.25+-00ADD8?logo=go\" alt=\"Go 1.25+\">\n    <img src=\"https://img.shields.io/badge/runtime_deps-wazero-success\" alt=\"wazero runtime dependency\">\n    <img src=\"https://img.shields.io/badge/license-MIT-blue\" alt=\"MIT\">\n  </p>\n</div>\n\nFoundation is the plumbing an application needs before it is an application:\ndependency injection, HTTP, actions, scheduling, configuration, caching,\nlogging, resiliency. What v2 changes is *when* a mistake surfaces.\n\nAn application built this way says things the Go compiler cannot check. A\ncontract is a type parameter, a route is a struct tag, an injected dependency is\na name in a string. In v1 those relationships were resolved by reflection while\nthe program ran, so a wrong one became a failed request. In v2 an analyzer reads\nthem while the file is open, a generator turns them into compile-time assertions\nand static registries, and the editor navigates them like ordinary symbols.\n\n## Install\n\n```sh\ngo get github.com/mirkobrombin/go-foundation/v2@latest\ngo install github.com/mirkobrombin/go-foundation/dev/v2/cmd/foundation@latest\n```\n\nThe runtime uses wazero for isolated WebAssembly plugins. It is pure Go and does\nnot require CGO. The analyzer, the generator, and the CLI live in a separate\nmodule, so an application that imports Foundation never pulls the analysis\npackages into its own build.\n\n## Static workflow\n\nDeclare contracts and application metadata in normal Go:\n\n```go\ntype UserStore interface {\n    Find(int) (User, bool)\n}\n\ntype MemoryUserStore struct {\n    contracts.Implements[UserStore]\n}\n\ntype GetUser struct {\n    _     struct{} `method:\"GET\" path:\"/users/{id:int}\"`\n    ID    int      `path:\"id\"`\n    Users UserStore `inject:\"users\"`\n}\n\nfunc build() (*app.App, error) {\n    application := app.New().Provide(\"users\", NewMemoryUserStore())\n    RegisterFoundation(application)\n    _, err := application.Build()\n    return application, err\n}\n```\n\nGenerate registration code and check the complete workspace:\n\n```sh\nfoundation generate ./...\nfoundation check ./...\ngo test ./...\n```\n\nGeneration writes one `zz_foundation.gen.go` per package that declares\nsomething, holding the contract assertions and the static constructors, and\nremoves the file again when the declarations are gone. Commit it: that is what\nmakes a broken contract a compile error on a machine that has never installed\nthe CLI.\n\nGeneration is a choice, not a toll. `RegisterHTTP` and `RegisterActionHandler`\nstill register by reflection, and `foundation check` reports the same problems\neither way, so a v1 application can move to v2 without a single generated file\nin its tree.\n\nSee the [quickstart example](examples/quickstart/quickstart.go), exercised by its\nown test.\n\nCalling `App.Listen(\"\")` binds to `127.0.0.1:8080`. Pass an explicit public\naddress only when the service is intended to accept remote traffic. Use\n`App.ListenTLS` for direct HTTPS, or terminate TLS at a trusted reverse proxy.\n\n## Layers\n\n| Layer | Purpose | Examples |\n|---|---|---|\n| `core` | Runtime building blocks with no application dependency | contracts, caching, validation, configuration, events, telemetry |\n| `app` | Application composition and boundaries | DI, HTTP, actions, dispatcher, hosting, testing |\n| `dev` | Development-only analysis and generation | `foundation check`, `foundation generate` |\n| `editors` | Editor-specific presentation | VS Code diagnostics, CodeLens, hover, contract and dependency navigation |\n\nThe analyzer enforces the dependency direction: `core` cannot import `app`, and\nruntime packages cannot import `dev`.\n\n## Development-time checks\n\n`foundation check` reports:\n\n- invalid `contracts.Implements[T]` declarations;\n- invalid DI implementation and constructor registrations;\n- duplicate or malformed routes and actions;\n- route parameters without matching fields;\n- locally missing or mistyped named dependencies;\n- dispatches to locally unknown actions;\n- invalid literal scheduler registrations;\n- ignored binding errors;\n- forbidden layer imports.\n\nThe compiler remains the authority for generated contract assertions. `go vet`,\ntests, and the race detector remain part of the expected verification path.\n\n## Editor navigation\n\nA contract is a type parameter and a dependency is a struct tag, so a Go editor\ncannot follow either on its own. The VS Code extension reads them and answers\nthe two questions that matter while writing code: what implements this, and\nwhere does this come from.\n\n![Implementations of a contract shown in the VS Code peek view](docs/images/vscode-implementations.png)\n\nThe screenshot is the quickstart example. `UserStore` carries a CodeLens with\nthe number of implementations found in the workspace, and clicking it opens the\npeek: the implementations on one side, the code of the selected one on the\nother. `MemoryUserStore` declares the relationship with\n`contracts.Implements[UserStore]`, which is also a CodeLens leading back to the\ninterface. The same navigation works between `inject:\"users\"` and\n`Provide(\"users\", ...)`, in both directions.\n\n## Assistants\n\n`foundation mcp` serves the same knowledge and the same tools over the Model\nContext Protocol, so an assistant answers from the API catalog of the version it\nis working with instead of from memory, and verifies with the real analyzer,\ngenerator, compiler and tests instead of asserting.\n\n```json\n{\n  \"mcpServers\": {\n    \"foundation\": { \"command\": \"foundation\", \"args\": [\"mcp\"] }\n  }\n}\n```\n\nThe catalog is extracted from the source and checked in the pipeline, so the\nanswers cannot drift from the code. See [the MCP server](docs/mcp.md).\n\n## Typed APIs\n\nNamed dependency keys can retain their Go type:\n\n```go\nvar usersKey = di.NewKey[UserStore](\"users\")\n\nbuilder := di.NewBuilder()\ndi.ProvideKey(builder, usersKey, store)\ncontainer, err := builder.Build()\nusers, ok := di.ResolveKey(container, usersKey)\n```\n\nActions also have a typed path:\n\n```go\nrouter := actions.New()\ncreate := actions.NewTyped[CreateUser, User](\"users.create\")\nerr := actions.HandleTyped(router, create, handler)\nresult, err := actions.DispatchTyped(ctx, router, create, payload)\n```\n\nUse strings where they are part of external metadata. Use typed APIs inside Go\ncode when the compiler can carry the relationship.\n\n## Plugins\n\nFoundation supports three plugin boundaries. Go shared objects load existing\nGo plugins that were built with the same toolchain and dependency graph.\n`ExecSandbox` keeps a plugin in a separate process with a JSON protocol.\nWebAssembly plugins use a stable Foundation ABI, run in-process through wazero,\nand can be written in any language that produces a core Wasm module.\n\n```go\nmodule, err := plugin.LoadWasmFile(ctx, \"report.wasm\",\n    plugin.WithWasmCapability(\"reports.store\", storeCapability),\n    plugin.WithWasmMemoryLimit(32<<20),\n)\nif err != nil {\n    return err\n}\ndefer module.Close(ctx)\n\nif err := module.StartContext(ctx); err != nil {\n    return err\n}\nresult, err := module.Call(ctx, \"render\", request)\n```\n\nA module inherits no filesystem, process environment, clock, stream, or network\naccess. Host functions are exposed as named capabilities and a plugin must both\ndeclare and receive each one before it can load. WASI Preview 1 is available as\nan explicit option for code that needs it. See [WebAssembly plugins](docs/plugins.md)\nfor the ABI, language contract, discovery, limits, and WASI configuration.\n\n## Documentation\n\n- [Project shape](docs/foundation-project.md)\n- [Development tools](docs/development-tools.md)\n- [MCP server](docs/mcp.md)\n- [WebAssembly plugins](docs/plugins.md)\n- [V2 migration](docs/v2-migration.md)\n- [Foundation Doctor](docs/foundation-doctor.md)\n- [go-module-router migration](docs/go-module-router-migration.md)\n- [VS Code extension](editors/vscode/README.md)\n\n## License\n\nMIT\n"}