Source
Fork: KooshaPari/phenotype-ops-mcp is a maintained fork of nanovms/ops-mcp (forked 2026-04-24). Two upstream-grade improvements are ready to merge back.
What we're proposing
1. Add --dump-tools flag + tools.json manifest generator
Source: KooshaPari/phenotype-ops-mcp/main.go lines 81-92 (the dumpTools flag handling) and lines 48-79 (the dumpManifest function).
The fork already uses the same metoro-io/mcp-golang SDK and invopop/jsonschema library as upstream. The dump logic:
- Iterates over a single
toolRegistrations() source of truth (avoids hitting the SDK's private tools map)
- Reflects on each tool's arg struct via
invopop/jsonschema (the same library the SDK uses internally) to derive JSON Schema
- Writes
tools.json with the canonical MCP tools/list shape: [{name, description, inputSchema}]
Currently the upstream has no machine-readable manifest. Adding --dump-tools would give MCP clients / registry tooling (e.g. KooshaPari/PhenoMCPServers catalog, IDE plugins) a stable surface to consume.
2. Fix tools.json field-name drift
KooshaPari/phenotype-ops-mcp PR #6 (commit 24c14ca, 2026-04-25) changed the InstanceArguments struct from json:"longitude" to json:"image_name". The Go struct is correct in the fork, but the pre-existing dump of tools.json still has the stale longitude field for the instance_logs and instance_create tools.
The fix: regenerate tools.json (or hand-fix the two field names) and add the regenerated manifest to the repo root, with the manifest-check CI workflow that fails the build if tools.json drifts from the Go structs.
Why these are useful upstream
- The current MCP ecosystem has no standard way to introspect a server's tool surface.
--dump-tools + tools.json is a small, low-risk addition that helps every MCP consumer.
- The drift fix is a no-op correctness improvement; the existing struct tags are already correct.
Patch outline (not a full PR — happy to send one if maintainers agree)
// In main.go
var dumpTools = flag.Bool("dump-tools", false, "write tools.json manifest and exit")
var dumpPath = flag.String("dump-tools-path", "tools.json", "path for the emitted manifest")
func dumpManifest(path string) error {
reflector := &jsonschema.Reflector{
DoNotReference: true,
AllowAdditionalProperties: true,
RequiredFromJSONSchemaTags: false,
ExpandedStruct: true,
}
regs := toolRegistrations() // already a method in upstream main.go
var tools []map[string]interface{}
for _, r := range regs {
schema := reflector.ReflectFromType(r.ArgType)
tools = append(tools, map[string]interface{}{
"name": r.Name,
"description": r.Description,
"inputSchema": schema,
})
}
out := map[string]interface{}{"tools": tools}
f, err := os.Create(path)
if err != nil { return err }
defer f.Close()
enc := json.NewEncoder(f)
enc.SetIndent("", " ")
return enc.Encode(out)
}
This requires:
- Adding
github.com/invopop/jsonschema to go.mod
- Adding the import to
main.go
- A
.github/workflows/manifest-check.yml that runs go run . -dump-tools and git diff --exit-code tools.json to fail on drift
What the maintainer gets to decide
- Is
--dump-tools a feature upstream wants? The fork is the only consumer. If maintainers prefer a different mechanism (e.g. an HTTP /tools endpoint, or just documenting the surface in README), we can adapt.
- Is
invopop/jsonschema an acceptable dep? It's the same library metoro-io/mcp-golang already uses internally, so the dependency tree is small.
- Should
tools.json be committed or gitignored? Fork commits it; CI regenerates and diffs to catch drift. Other pattern: gitignore + regenerate in go generate.
Status
Related
Source
Fork:
KooshaPari/phenotype-ops-mcpis a maintained fork ofnanovms/ops-mcp(forked 2026-04-24). Two upstream-grade improvements are ready to merge back.What we're proposing
1. Add
--dump-toolsflag +tools.jsonmanifest generatorSource:
KooshaPari/phenotype-ops-mcp/main.golines 81-92 (thedumpToolsflag handling) and lines 48-79 (thedumpManifestfunction).The fork already uses the same
metoro-io/mcp-golangSDK andinvopop/jsonschemalibrary as upstream. The dump logic:toolRegistrations()source of truth (avoids hitting the SDK's privatetoolsmap)invopop/jsonschema(the same library the SDK uses internally) to derive JSON Schematools.jsonwith the canonical MCPtools/listshape:[{name, description, inputSchema}]Currently the upstream has no machine-readable manifest. Adding
--dump-toolswould give MCP clients / registry tooling (e.g. KooshaPari/PhenoMCPServers catalog, IDE plugins) a stable surface to consume.2. Fix
tools.jsonfield-name driftKooshaPari/phenotype-ops-mcpPR #6 (commit24c14ca, 2026-04-25) changed theInstanceArgumentsstruct fromjson:"longitude"tojson:"image_name". The Go struct is correct in the fork, but the pre-existing dump oftools.jsonstill has the stalelongitudefield for theinstance_logsandinstance_createtools.The fix: regenerate
tools.json(or hand-fix the two field names) and add the regenerated manifest to the repo root, with the manifest-check CI workflow that fails the build iftools.jsondrifts from the Go structs.Why these are useful upstream
--dump-tools+tools.jsonis a small, low-risk addition that helps every MCP consumer.Patch outline (not a full PR — happy to send one if maintainers agree)
This requires:
github.com/invopop/jsonschematogo.modmain.go.github/workflows/manifest-check.ymlthat runsgo run . -dump-toolsandgit diff --exit-code tools.jsonto fail on driftWhat the maintainer gets to decide
--dump-toolsa feature upstream wants? The fork is the only consumer. If maintainers prefer a different mechanism (e.g. an HTTP/toolsendpoint, or just documenting the surface in README), we can adapt.invopop/jsonschemaan acceptable dep? It's the same librarymetoro-io/mcp-golangalready uses internally, so the dependency tree is small.tools.jsonbe committed or gitignored? Fork commits it; CI regenerates and diffs to catch drift. Other pattern: gitignore + regenerate ingo generate.Status
KooshaPari/phenotype-ops-mcprebases and the fork can be archived (it currently vendors upstream Go code unchanged; once upstream has--dump-tools, the fork's only added value is the cheap-llm merge, which is also being absorbed — see phenotype-registry#127)Related
KooshaPari/phenotype-ops-mcp(will be archived after all 4 absorptions complete)