Skip to content

Generated CLI: object-type parameters not JSON-parsed (inferType + optionParser missing 'object' case) #113

@v2nic

Description

@v2nic

Context

This issue was discovered by v2nic using the pi coding agent while working with the Atlassian MCP server and the atlassian CLI generated by mcporter.

Problem

When an MCP tool schema declares a parameter with "type": "object" (e.g. editJiraIssue's fields parameter), the generated CLI passes the value as a raw string instead of parsing it as JSON. This causes MCP validation errors like:

MCP error -32602: Invalid arguments for tool editJiraIssue: [
  {
    "code": "invalid_type",
    "expected": "object",
    "received": "string",
    "path": ["fields"],
    "message": "Expected object, received string"
  }
]

Root cause

Two places in the code generator silently drop object types:

1. src/cli/generate/tools.jsinferType()

The resolveType inner function only recognizes a whitelist of types:

const resolveType = (value) => {
    if (value === "integer") return "number";
    if (value === "string" || value === "number" || value === "boolean" || value === "array") {
        return value;
    }
    return undefined;  // ← "object" falls through here
};

When the schema says "type": "object", resolveType returns undefined, and inferType returns "unknown".

2. src/cli/generate/template.jsoptionParser()

The switch statement has no case for object:

function optionParser(option) {
    switch (option.type) {
        case "number":  return "(value) => parseFloat(value)";
        case "boolean": return "(value) => value !== 'false'";
        case "array":   return "(value) => value.split(',').map((v) => v.trim())";
        default:        return undefined;  // ← unknown/object falls through
    }
}

So even if inferType returned "object", optionParser would still return undefined, generating:

.requiredOption("--fields <fields>", "Set fields.")
// no parser — value stays as a raw string

Reproduction

  1. Generate a CLI from any MCP server with an object-type parameter:
npx mcporter generate-cli --server https://mcp.atlassian.com/v1/mcp --compile
  1. The generated CLI will have:
.requiredOption("--fields <fields>", "Set fields.")  // no JSON.parse
  1. Running:
atlassian editJiraIssue --cloud-id <id> --issue-id-or-key NVR-526 --fields '{"description":"test"}'

...sends fields as a string to the MCP server, which rejects it.

Fix

tools.js — add "object" to the whitelist:

const resolveType = (value) => {
    if (value === "integer") return "number";
    if (value === "string" || value === "number" || value === "boolean" || value === "array" || value === "object") {
        return value;
    }
    return undefined;
};

template.js — add case "object" to optionParser:

function optionParser(option) {
    switch (option.type) {
        case "number":  return "(value) => parseFloat(value)";
        case "boolean": return "(value) => value !== 'false'";
        case "object":  return "(value) => JSON.parse(value)";  // ← add this
        case "array":   return "(value) => value.split(',').map((v) => v.trim())";
        default:        return undefined;
    }
}

Related issues

Environment

  • mcporter version: npx (latest as of 2026-03-16)
  • MCP server: Atlassian (https://mcp.atlassian.com/v1/mcp)
  • Generated CLI: atlassian (Bun-compiled binary)
  • Node.js: v20.20.0
  • macOS arm64

Pull request

#114

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions