Skip to content

Add --dump-tools flag + regenerate tools.json (port from KooshaPari/phenotype-ops-mcp) #6

Description

@kilo-code-bot

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

  1. 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.
  2. Is invopop/jsonschema an acceptable dep? It's the same library metoro-io/mcp-golang already uses internally, so the dependency tree is small.
  3. 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

  • Source implementation ready in fork
  • Drift fix ready (single-line schema change in 2 tools)
  • Upstream maintainer review
  • PR opened
  • Merged
  • KooshaPari/phenotype-ops-mcp rebases 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions