modelcontextprotocol / modelcontextprotocol/conformance

test: programmatic CLI harness for src/index.ts action handlers

Open
#363 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
127
Forks
101
Avg merge
6d 1h
Merged PRs (30d)
7

Description

src/index.ts currently has zero test coverage of its commander action handlers — all testing happens at the scenario/runner layer. This came up in #360: we wanted to test that authorization --file <path> rejects an invalid settings file, but there's no way to exercise the real codepath without either spawning a child process or duplicating the merge logic in the test (which can drift).

Proposed approach

Refactor src/index.ts so the Command can be constructed without auto-parsing:

// src/index.ts
export function createProgram(): Command { /* register all subcommands */ }

// only parse when run as the bin entrypoint
if (require.main === module) createProgram().parse();

Tests then drive it in-process:

const exit = vi.spyOn(process, 'exit').mockImplementation(((c) => {
  throw new Error(`exit:${c}`);
}) as never);
const stderr = vi.spyOn(console, 'error').mockImplementation(() => {});
vi.mock('./runner/authorization-server');  // stub the network layer

await expect(
  createProgram().exitOverride().parseAsync(
    ['node', 'x', 'authorization', '--file', tmpInvalidJson]
  )
).rejects.toThrow('exit:1');
expect(stderr.mock.calls.join('\n')).toContain("Invalid settings file");

Why not spawn the binary

execa against dist/ is the strongest guarantee but is slow (process per case) and depends on a build step. Programmatic .parseAsync() is fast enough to cover every flag/validation path and matches how commander's own suite tests itself.

Scope

  • Extract createProgram(); gate program.parse() on require.main === module (or move to a bin.ts shim)
  • Shared test helpers: process.exit / console.error spies, temp-file fixture writer
  • Initial coverage: authorization --file (valid file, missing url, unknown key, bad JSON, neither --url nor --file)
  • Follow-on: extend to server / client flag validation as needed

Related: #360, #225

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with src/index.ts and trace how Commander registers and parses the action handlers. Extract createProgram(), add the process.exit and console.error test helpers, and stub runner/authorization-server as described. Done means in-process tests cover authorization --file with valid, missing-url, unknown-key, bad-JSON, and missing-source cases.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
cli, testing
Issue type
Refactor
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
67/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.