Skip to main content
Glama

Get tests

get_tests
Read-onlyIdempotent

Returns static scan details for up to 20 test IDs—location, tags, hooks, fixtures, retries, dependencies, and diagnostics—without running tests.

Instructions

Returns every key of the tests with the given ids, with the scan diagnostics about them, read from the test files without running them: location, describe path, state and where it is set, condition, reason, tags, annotations, comments above the test, parameters, the projects that run it, hooks around it, timeout and retries with where each is set (the test, a describe, the file or the config), fixtures, expect() counts, steps, body hash, and the files the test runs with dependencyHash. Use it after find_tests or test_summary, for the details of up to 20 tests. Ids come from find_tests and stay the same when a test moves to another line, but change when its title, describe or file changes; ids not in the current scan are returned in notFound. Example: {"ids": ["3f9a0c1d2e4b5a69"]}. An answer that would be too long returns the first tests and the other ids in remaining.

Tool call template

Replace each placeholder with a value matching the input schema. Only required parameters are included; add optional parameters as needed.

{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "arguments": {
      "ids": "<ids>"
    },
    "name": "get_tests"
  }
}

Input Schema

NameRequiredDescriptionDefault
idsYesTest ids, as find_tests returns them.
patternsNoGlobs of the test files, relative to `directory`, such as ["tests/**/*.spec.ts"]. Default: the ones the server was started with, or without them the files the configs in `directory` and below it run.
directoryNoA folder inside the project to scan, relative to its root, such as "packages/web". Default: the root.
frameworkNoThe test runner. Default: the one the server was started with, otherwise the one the project in `directory` uses.
expandCasesNoLists each case of a .each or .for table and each pass of a loop as its own test, with the name the runner gives it and caseIndex, as the runner registers them. Ids differ from those without it, so pass the same value to get_tests. Default: false, one test per declaration with caseCount.

Output Schema

NameRequiredDescriptionDefault
hintYes
testsYesThe tests found, in the order of ids.
notFoundYesIds that are not in this scan.
frameworkYes
remainingYesIds found but left out to keep the answer short; pass them again.
scanErrorsYesProblems of level error in the scan, which may leave tests out of the answer.
diagnosticsYesProblems the scan reports about these tests.
frameworkVersionYes

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed3 schema fields changedv0.9.0
    • addedInput schema / additionalProperties
      Added value: +false
    • changedOutput schema / definitions / TestRecord / properties / isNotLoaded / description
      Previous value: -"The runner refuses to load the file; a diagnostic at `stateLine` says why."New value: +"The runner did not load this test, possibly because its describe failed; a diagnostic at `stateLine` says why."
    • changedOutput schema / definitions / TestRecord / properties / isOnly / description
      Previous value: -"The test or a describe around it uses `.only`."New value: +"The test is selected by a `.only`, following the runner's focus rules."
  2. Changed12 schema fields changedv0.7.0
    • addedInput schema / properties / expandCases
      Added value: +{
      +  "description": "Lists each case of a .each or .for table and each pass of a loop as its own test, with the name the runner gives it and caseIndex, as the runner registers them. Ids differ from those without it, so pass the same value to get_tests. Default: false, one test per declaration with caseCount.",
      +  "type": "boolean"
      +}
    • changedInput schema / properties / framework / description
      Previous value: -"The test runner. Default: the one the server was started with."New value: +"The test runner. Default: the one the server was started with, otherwise the one the project in `directory` uses."
    • changedInput schema / properties / framework / enum
      Previous value: -[
      -  "playwright",
      -  "vitest"
      -]New value: +[
      +  "playwright",
      +  "vitest",
      +  "jest",
      +  "mocha",
      +  "jasmine",
      +  "cypress",
      +  "webdriverio",
      +  "node",
      +  "bun"
      +]
    • changedOutput schema / definitions / DiagnosticCode / anyOf
      Previous value: -[
      -  {
      -    "enum": [
      -      "unresolved-test-import",
      -      "parse-error",
      -      "read-error",
      -      "framework-mismatch",
      -      "unresolved-tag",
      -      "unresolved-annotation",
      -      "unresolved-cases",
      -      "test-in-loop",
      -      "dynamic-title",
      -      "duplicate-title",
      -      "duplicate-id",
      -      "internal-error",
      -      "invalid-chain",
      -      "skip-without-body",
      -      "test-without-body",
      -      "describe-not-called",
      -      "async-describe",
      -      "nested-test",
      -      "tag-without-at",
      -      "removed-api",
      -      "only-in-skipped-describe",
      -      "config-may-change-state",
      -      "undefined-tag",
      -      "symlink-ignored",
      -      "invalid-import",
      -      "globals-not-enabled",
      -      "unknown-framework-version",
      -      "unsupported-framework-version",
      -      "local-test-object",
      -      "state-in-helper",
      -      "unresolved-option",
      -      "dynamic-reason",
      -      "no-files-matched",
      -      "unsupported-file",
      -      "approximate-framework-version",
      -      "test-in-function",
      -      "empty-title",
      -      "bench-outside-benchmark-file",
      -      "config-value-unknown",
      -      "file-not-run",
      -      "forbidden-only",
      -      "dependency-not-followed"
      -    ],
      -    "type": "string"
      -  },
      -  {
      -    "type": "string"
      -  }
      -]New value: +[
      +  {
      +    "enum": [
      +      "unresolved-test-import",
      +      "parse-error",
      +      "read-error",
      +      "framework-mismatch",
      +      "unresolved-tag",
      +      "unresolved-annotation",
      +      "unresolved-cases",
      +      "cases-not-expanded",
      +      "test-in-loop",
      +      "dynamic-title",
      +      "duplicate-title",
      +      "duplicate-id",
      +      "internal-error",
      +      "invalid-chain",
      +      "skip-without-body",
      +      "test-without-body",
      +      "describe-not-called",
      +      "async-describe",
      +      "describe-throws",
      +      "nested-test",
      +      "tag-without-at",
      +      "removed-api",
      +      "invalid-fixture-argument",
      +      "only-in-skipped-describe",
      +      "config-may-change-state",
      +      "undefined-tag",
      +      "symlink-ignored",
      +      "invalid-import",
      +      "globals-not-enabled",
      +      "unknown-framework-version",
      +      "unsupported-framework-version",
      +      "local-test-object",
      +      "state-in-helper",
      +      "unresolved-option",
      +      "dynamic-reason",
      +      "no-files-matched",
      +      "unsupported-file",
      +      "approximate-framework-version",
      +      "test-in-function",
      +      "empty-title",
      +      "bench-outside-benchmark-file",
      +      "config-value-unknown",
      +      "file-not-run",
      +      "forbidden-only",
      +      "dependency-not-followed"
      +    ],
      +    "type": "string"
      +  },
      +  {
      +    "type": "string"
      +  }
      +]
    • changedOutput schema / definitions / Framework / anyOf
      Previous value: -[
      -  {
      -    "enum": [
      -      "playwright",
      -      "vitest"
      -    ],
      -    "type": "string"
      -  },
      -  {
      -    "type": "string"
      -  }
      -]New value: +[
      +  {
      +    "enum": [
      +      "playwright",
      +      "vitest",
      +      "jest",
      +      "mocha",
      +      "jasmine",
      +      "cypress",
      +      "webdriverio",
      +      "node",
      +      "bun"
      +    ],
      +    "type": "string"
      +  },
      +  {
      +    "type": "string"
      +  }
      +]
    • changedOutput schema / definitions / TestRecord / properties / caseCount / description
      Previous value: -"How many times the runner repeats the test: the cases of its own table times those of each describe table around it. Null when a table is not written out in the file, or the test is not parameterized."New value: +"How many times the runner repeats the test: the cases of its own table times those of each describe table and the passes of each loop around it. Null when the scan can't work out a table or a loop's values, or the test is neither parameterized nor in a loop."
    • addedOutput schema / definitions / TestRecord / properties / caseIndex
      Added value: +{
      +  "anyOf": [
      +    {
      +      "minimum": 0,
      +      "type": "integer"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "description": "With `expandCases`, which case of its own table, or pass of the innermost loop around it inside its describe, the test is, from 0, as Vitest's `%#` counts; null without `expandCases`, or when the test isn't one of several. The case of a describe table or loop around the describe is the describe's `caseIndex`."
      +}
    • addedOutput schema / definitions / TestRecord / properties / parentTestId
      Added value: +{
      +  "anyOf": [
      +    {
      +      "pattern": "^[0-9a-f]{16}$",
      +      "type": "string"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "description": "The test whose body declares this one as a subtest, which `node:test` runs while it runs that test; null for every other test."
      +}
    • changedOutput schema / definitions / TestRecord / properties / repeats / description
      Previous value: -"How many times the runner runs the test again after the first run: Vitest's `repeats`, or Playwright's `repeatEach` from the config less one."New value: +"How many times the runner runs the test again after the first run: Vitest's or Bun's `repeats`, or Playwright's `repeatEach` from the config less one."
    • changedOutput schema / definitions / TestRecord / properties / retryDelay / description
      Previous value: -"Vitest only: milliseconds between retries, from the `retry` object (4.1)."New value: +"Milliseconds between retries: Vitest's from the `retry` object (4.1), Jest's from `waitBeforeRetry` of `jest.retryTimes()` (30.0); null otherwise."
    • changedOutput schema / definitions / TestRecord / properties / suitePath / description
      Previous value: -"Titles of the describes around the test, outermost first."New value: +"Titles of the describes around the test, and of the tests a subtest is declared in, outermost first."
    • changedOutput schema / definitions / TestRecord / required
      Previous value: -[
      -  "id",
      -  "bodyHash",
      -  "dependencyHash",
      -  "dependencies",
      -  "hasUnfollowedDependencies",
      -  "suiteId",
      -  "suitePath",
      -  "relativeFilePath",
      -  "fileName",
      -  "lineStart",
      -  "lineEnd",
      -  "columnStart",
      -  "columnEnd",
      -  "declaredAt",
      -  "title",
      -  "titleWithoutTags",
      -  "hasDynamicTitle",
      -  "fullName",
      -  "isTypeTest",
      -  "state",
      -  "isActive",
      -  "isSkipped",
      -  "isFixme",
      -  "isTodo",
      -  "isExpectedToFail",
      -  "isNotLoaded",
      -  "isOnly",
      -  "isConditional",
      -  "condition",
      -  "reason",
      -  "hasDynamicReason",
      -  "stateSource",
      -  "stateLine",
      -  "isParallel",
      -  "isSerial",
      -  "tags",
      -  "annotations",
      -  "comments",
      -  "locks",
      -  "meta",
      -  "hooks",
      -  "timeout",
      -  "isSlow",
      -  "slowCondition",
      -  "retries",
      -  "retryDelay",
      -  "retryCondition",
      -  "repeats",
      -  "timeoutSource",
      -  "retriesSource",
      -  "repeatsSource",
      -  "timeoutConfigText",
      -  "retriesConfigText",
      -  "repeatsConfigText",
      -  "fixtures",
      -  "expectCount",
      -  "expectedAssertions",
      -  "expectsAssertions",
      -  "hasEmptyBody",
      -  "steps",
      -  "isBenchmark",
      -  "isParameterized",
      -  "caseCount",
      -  "isInLoop",
      -  "isInCondition",
      -  "isInFunction",
      -  "projects"
      -]New value: +[
      +  "id",
      +  "bodyHash",
      +  "dependencyHash",
      +  "dependencies",
      +  "hasUnfollowedDependencies",
      +  "suiteId",
      +  "parentTestId",
      +  "suitePath",
      +  "relativeFilePath",
      +  "fileName",
      +  "lineStart",
      +  "lineEnd",
      +  "columnStart",
      +  "columnEnd",
      +  "declaredAt",
      +  "title",
      +  "titleWithoutTags",
      +  "hasDynamicTitle",
      +  "fullName",
      +  "isTypeTest",
      +  "state",
      +  "isActive",
      +  "isSkipped",
      +  "isFixme",
      +  "isTodo",
      +  "isExpectedToFail",
      +  "isNotLoaded",
      +  "isOnly",
      +  "isConditional",
      +  "condition",
      +  "reason",
      +  "hasDynamicReason",
      +  "stateSource",
      +  "stateLine",
      +  "isParallel",
      +  "isSerial",
      +  "tags",
      +  "annotations",
      +  "comments",
      +  "locks",
      +  "meta",
      +  "hooks",
      +  "timeout",
      +  "isSlow",
      +  "slowCondition",
      +  "retries",
      +  "retryDelay",
      +  "retryCondition",
      +  "repeats",
      +  "timeoutSource",
      +  "retriesSource",
      +  "repeatsSource",
      +  "timeoutConfigText",
      +  "retriesConfigText",
      +  "repeatsConfigText",
      +  "fixtures",
      +  "expectCount",
      +  "expectedAssertions",
      +  "expectsAssertions",
      +  "hasEmptyBody",
      +  "steps",
      +  "isBenchmark",
      +  "isParameterized",
      +  "caseCount",
      +  "caseIndex",
      +  "isInLoop",
      +  "isInCondition",
      +  "isInFunction",
      +  "projects"
      +]
  3. Changed20 schema fields changedv0.4.1
    • changedInput schema / properties / patterns / description
      Previous value: -"Globs of the test files, relative to `directory`, such as [\"tests/**/*.spec.ts\"]. Default: the ones the server was started with."New value: +"Globs of the test files, relative to `directory`, such as [\"tests/**/*.spec.ts\"]. Default: the ones the server was started with, or without them the files the configs in `directory` and below it run."
    • changedOutput schema / definitions / DiagnosticCode / anyOf
      Previous value: -[
      -  {
      -    "enum": [
      -      "unresolved-test-import",
      -      "parse-error",
      -      "read-error",
      -      "framework-mismatch",
      -      "unresolved-tag",
      -      "unresolved-annotation",
      -      "unresolved-cases",
      -      "test-in-loop",
      -      "dynamic-title",
      -      "duplicate-title",
      -      "duplicate-id",
      -      "internal-error",
      -      "invalid-chain",
      -      "skip-without-body",
      -      "test-without-body",
      -      "describe-not-called",
      -      "async-describe",
      -      "nested-test",
      -      "tag-without-at",
      -      "removed-api",
      -      "only-in-skipped-describe",
      -      "config-may-change-state",
      -      "symlink-ignored",
      -      "invalid-import",
      -      "globals-not-enabled",
      -      "unknown-framework-version",
      -      "unsupported-framework-version",
      -      "local-test-object",
      -      "state-in-helper",
      -      "unresolved-option",
      -      "dynamic-reason",
      -      "no-files-matched",
      -      "unsupported-file",
      -      "approximate-framework-version",
      -      "test-in-function",
      -      "empty-title",
      -      "bench-outside-benchmark-file"
      -    ],
      -    "type": "string"
      -  },
      -  {
      -    "type": "string"
      -  }
      -]New value: +[
      +  {
      +    "enum": [
      +      "unresolved-test-import",
      +      "parse-error",
      +      "read-error",
      +      "framework-mismatch",
      +      "unresolved-tag",
      +      "unresolved-annotation",
      +      "unresolved-cases",
      +      "test-in-loop",
      +      "dynamic-title",
      +      "duplicate-title",
      +      "duplicate-id",
      +      "internal-error",
      +      "invalid-chain",
      +      "skip-without-body",
      +      "test-without-body",
      +      "describe-not-called",
      +      "async-describe",
      +      "nested-test",
      +      "tag-without-at",
      +      "removed-api",
      +      "only-in-skipped-describe",
      +      "config-may-change-state",
      +      "undefined-tag",
      +      "symlink-ignored",
      +      "invalid-import",
      +      "globals-not-enabled",
      +      "unknown-framework-version",
      +      "unsupported-framework-version",
      +      "local-test-object",
      +      "state-in-helper",
      +      "unresolved-option",
      +      "dynamic-reason",
      +      "no-files-matched",
      +      "unsupported-file",
      +      "approximate-framework-version",
      +      "test-in-function",
      +      "empty-title",
      +      "bench-outside-benchmark-file",
      +      "config-value-unknown",
      +      "file-not-run",
      +      "forbidden-only",
      +      "dependency-not-followed"
      +    ],
      +    "type": "string"
      +  },
      +  {
      +    "type": "string"
      +  }
      +]
    • addedOutput schema / definitions / SettingSource
      Added value: +{
      +  "anyOf": [
      +    {
      +      "enum": [
      +        "test",
      +        "suite",
      +        "file",
      +        "config"
      +      ],
      +      "type": "string"
      +    },
      +    {
      +      "type": "string"
      +    }
      +  ],
      +  "description": "Where a test's run setting comes from: the test, a describe around it, the file, or the config its file uses. Other values may be added in later releases."
      +}
    • changedOutput schema / definitions / StateSource / anyOf
      Previous value: -[
      -  {
      -    "enum": [
      -      "test",
      -      "suite",
      -      "file"
      -    ],
      -    "type": "string"
      -  },
      -  {
      -    "type": "string"
      -  }
      -]New value: +[
      +  {
      +    "enum": [
      +      "test",
      +      "suite",
      +      "file",
      +      "config"
      +    ],
      +    "type": "string"
      +  },
      +  {
      +    "type": "string"
      +  }
      +]
    • changedOutput schema / definitions / StateSource / description
      Previous value: -"Where a test's state is set: on the test, on a describe around it, or at file level. Other values may be added in later releases."New value: +"Where a test's state is set: on the test, on a describe around it, at file level, or by a Vitest tag the config defines. Other values may be added in later releases."
    • addedOutput schema / definitions / TestRecord / properties / dependencies
      Added value: +{
      +  "description": "The files that went into `dependencyHash`, the test's own included, sorted, with `/` separators.",
      +  "items": {
      +    "type": "string"
      +  },
      +  "type": "array"
      +}
    • addedOutput schema / definitions / TestRecord / properties / dependencyHash
      Added value: +{
      +  "description": "Hash of everything the test runs in the project: its call, the hooks, options and code of the file and of every describe around it, and the functions, classes, constants and modules these use, followed through imports. Ignores whitespace and comments. Installed packages are not in it.",
      +  "pattern": "^[0-9a-f]{16}$",
      +  "type": "string"
      +}
    • addedOutput schema / definitions / TestRecord / properties / hasUnfollowedDependencies
      Added value: +{
      +  "description": "Something the test reaches couldn't be followed, so a change there doesn't change `dependencyHash`.",
      +  "type": "boolean"
      +}
    • addedOutput schema / definitions / TestRecord / properties / projects
      Added value: +{
      +  "anyOf": [
      +    {
      +      "items": {
      +        "type": "string"
      +      },
      +      "type": "array"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "description": "Names of the projects that run the test, of the config its file uses, after each project's files and Playwright's `grep` and `grepInvert`. `[]` when no project runs it; null when there is no config, or the scan can't tell."
      +}
    • changedOutput schema / definitions / TestRecord / properties / repeats / description
      Previous value: -"Vitest only: how many times the runner runs the test again after the first run."New value: +"How many times the runner runs the test again after the first run: Vitest's `repeats`, or Playwright's `repeatEach` from the config less one."
    • addedOutput schema / definitions / TestRecord / properties / repeatsConfigText
      Added value: +{
      +  "description": "The config's source text for `repeats`, Playwright's `repeatEach`, read as `timeoutConfigText` is.",
      +  "type": [
      +    "string",
      +    "null"
      +  ]
      +}
    • addedOutput schema / definitions / TestRecord / properties / repeatsSource
      Added value: +{
      +  "anyOf": [
      +    {
      +      "$ref": "#/definitions/SettingSource"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "description": "Where `repeats` comes from, read as `timeoutSource` is."
      +}
    • addedOutput schema / definitions / TestRecord / properties / retriesConfigText
      Added value: +{
      +  "description": "The config's source text for `retries`, read as `timeoutConfigText` is.",
      +  "type": [
      +    "string",
      +    "null"
      +  ]
      +}
    • addedOutput schema / definitions / TestRecord / properties / retriesSource
      Added value: +{
      +  "anyOf": [
      +    {
      +      "$ref": "#/definitions/SettingSource"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "description": "Where `retries`, `retryDelay` and `retryCondition` come from, read as `timeoutSource` is."
      +}
    • changedOutput schema / definitions / TestRecord / properties / timeout / description
      Previous value: -"In milliseconds: the last `test.setTimeout()` in the body or a `beforeEach`, otherwise the nearest describe or file that sets one. Null when the file sets none, so the config's timeout applies."New value: +"In milliseconds: the last `test.setTimeout()` in the body or a `beforeEach`, otherwise the nearest describe or file that sets one, otherwise the config. Null when none sets it, so the runner's default applies."
    • addedOutput schema / definitions / TestRecord / properties / timeoutConfigText
      Added value: +{
      +  "description": "The config's source text for `timeout` when the config sets it under a condition, as in `process.env.CI ? 60_000 : 30_000`, shortened when long; null otherwise.",
      +  "type": [
      +    "string",
      +    "null"
      +  ]
      +}
    • addedOutput schema / definitions / TestRecord / properties / timeoutSource
      Added value: +{
      +  "anyOf": [
      +    {
      +      "$ref": "#/definitions/SettingSource"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "description": "Where `timeout` comes from; null when nothing sets it. A null `timeout` from the config means the config sets it, but its projects set different values or the value depends on a condition, as in `process.env.CI ? 2 : 0`."
      +}
    • changedOutput schema / definitions / TestRecord / required
      Previous value: -[
      -  "id",
      -  "bodyHash",
      -  "suiteId",
      -  "suitePath",
      -  "relativeFilePath",
      -  "fileName",
      -  "lineStart",
      -  "lineEnd",
      -  "columnStart",
      -  "columnEnd",
      -  "declaredAt",
      -  "title",
      -  "titleWithoutTags",
      -  "hasDynamicTitle",
      -  "fullName",
      -  "isTypeTest",
      -  "state",
      -  "isActive",
      -  "isSkipped",
      -  "isFixme",
      -  "isTodo",
      -  "isExpectedToFail",
      -  "isNotLoaded",
      -  "isOnly",
      -  "isConditional",
      -  "condition",
      -  "reason",
      -  "hasDynamicReason",
      -  "stateSource",
      -  "stateLine",
      -  "isParallel",
      -  "isSerial",
      -  "tags",
      -  "annotations",
      -  "comments",
      -  "locks",
      -  "meta",
      -  "hooks",
      -  "timeout",
      -  "isSlow",
      -  "slowCondition",
      -  "retries",
      -  "retryDelay",
      -  "retryCondition",
      -  "repeats",
      -  "fixtures",
      -  "expectCount",
      -  "expectedAssertions",
      -  "expectsAssertions",
      -  "hasEmptyBody",
      -  "steps",
      -  "isBenchmark",
      -  "isParameterized",
      -  "caseCount",
      -  "isInLoop",
      -  "isInCondition",
      -  "isInFunction"
      -]New value: +[
      +  "id",
      +  "bodyHash",
      +  "dependencyHash",
      +  "dependencies",
      +  "hasUnfollowedDependencies",
      +  "suiteId",
      +  "suitePath",
      +  "relativeFilePath",
      +  "fileName",
      +  "lineStart",
      +  "lineEnd",
      +  "columnStart",
      +  "columnEnd",
      +  "declaredAt",
      +  "title",
      +  "titleWithoutTags",
      +  "hasDynamicTitle",
      +  "fullName",
      +  "isTypeTest",
      +  "state",
      +  "isActive",
      +  "isSkipped",
      +  "isFixme",
      +  "isTodo",
      +  "isExpectedToFail",
      +  "isNotLoaded",
      +  "isOnly",
      +  "isConditional",
      +  "condition",
      +  "reason",
      +  "hasDynamicReason",
      +  "stateSource",
      +  "stateLine",
      +  "isParallel",
      +  "isSerial",
      +  "tags",
      +  "annotations",
      +  "comments",
      +  "locks",
      +  "meta",
      +  "hooks",
      +  "timeout",
      +  "isSlow",
      +  "slowCondition",
      +  "retries",
      +  "retryDelay",
      +  "retryCondition",
      +  "repeats",
      +  "timeoutSource",
      +  "retriesSource",
      +  "repeatsSource",
      +  "timeoutConfigText",
      +  "retriesConfigText",
      +  "repeatsConfigText",
      +  "fixtures",
      +  "expectCount",
      +  "expectedAssertions",
      +  "expectsAssertions",
      +  "hasEmptyBody",
      +  "steps",
      +  "isBenchmark",
      +  "isParameterized",
      +  "caseCount",
      +  "isInLoop",
      +  "isInCondition",
      +  "isInFunction",
      +  "projects"
      +]
    • addedOutput schema / properties / remaining
      Added value: +{
      +  "description": "Ids found but left out to keep the answer short; pass them again.",
      +  "items": {
      +    "type": "string"
      +  },
      +  "type": "array"
      +}
    • changedOutput schema / required
      Previous value: -[
      -  "framework",
      -  "frameworkVersion",
      -  "tests",
      -  "diagnostics",
      -  "notFound",
      -  "scanErrors",
      -  "hint"
      -]New value: +[
      +  "framework",
      +  "frameworkVersion",
      +  "tests",
      +  "diagnostics",
      +  "notFound",
      +  "remaining",
      +  "scanErrors",
      +  "hint"
      +]
  4. Changed19 schema fields changedv0.2.0
    • changedOutput schema / definitions / DiagnosticCode / anyOf
      Previous value: -[
      -  {
      -    "enum": [
      -      "unresolved-test-import",
      -      "parse-error",
      -      "read-error",
      -      "framework-mismatch",
      -      "unresolved-tag",
      -      "unresolved-annotation",
      -      "unresolved-cases",
      -      "test-in-loop",
      -      "dynamic-title",
      -      "duplicate-title",
      -      "duplicate-id",
      -      "internal-error",
      -      "invalid-chain",
      -      "skip-without-body",
      -      "test-without-body",
      -      "describe-not-called",
      -      "async-describe",
      -      "nested-test",
      -      "tag-without-at",
      -      "removed-api",
      -      "only-in-skipped-describe",
      -      "config-may-change-state",
      -      "symlink-ignored",
      -      "invalid-import",
      -      "globals-not-enabled",
      -      "unknown-framework-version",
      -      "unsupported-framework-version",
      -      "local-test-object",
      -      "state-in-helper",
      -      "unresolved-option",
      -      "dynamic-reason",
      -      "no-files-matched",
      -      "unsupported-file",
      -      "approximate-framework-version",
      -      "test-in-function"
      -    ],
      -    "type": "string"
      -  },
      -  {
      -    "type": "string"
      -  }
      -]New value: +[
      +  {
      +    "enum": [
      +      "unresolved-test-import",
      +      "parse-error",
      +      "read-error",
      +      "framework-mismatch",
      +      "unresolved-tag",
      +      "unresolved-annotation",
      +      "unresolved-cases",
      +      "test-in-loop",
      +      "dynamic-title",
      +      "duplicate-title",
      +      "duplicate-id",
      +      "internal-error",
      +      "invalid-chain",
      +      "skip-without-body",
      +      "test-without-body",
      +      "describe-not-called",
      +      "async-describe",
      +      "nested-test",
      +      "tag-without-at",
      +      "removed-api",
      +      "only-in-skipped-describe",
      +      "config-may-change-state",
      +      "symlink-ignored",
      +      "invalid-import",
      +      "globals-not-enabled",
      +      "unknown-framework-version",
      +      "unsupported-framework-version",
      +      "local-test-object",
      +      "state-in-helper",
      +      "unresolved-option",
      +      "dynamic-reason",
      +      "no-files-matched",
      +      "unsupported-file",
      +      "approximate-framework-version",
      +      "test-in-function",
      +      "empty-title",
      +      "bench-outside-benchmark-file"
      +    ],
      +    "type": "string"
      +  },
      +  {
      +    "type": "string"
      +  }
      +]
    • addedOutput schema / definitions / HookCounts
      Added value: +{
      +  "description": "How many hooks of each kind are registered, including by helper functions called there.",
      +  "properties": {
      +    "afterAll": {
      +      "minimum": 0,
      +      "type": "integer"
      +    },
      +    "afterEach": {
      +      "minimum": 0,
      +      "type": "integer"
      +    },
      +    "aroundAll": {
      +      "description": "Vitest only.",
      +      "minimum": 0,
      +      "type": "integer"
      +    },
      +    "aroundEach": {
      +      "description": "Vitest only.",
      +      "minimum": 0,
      +      "type": "integer"
      +    },
      +    "beforeAll": {
      +      "minimum": 0,
      +      "type": "integer"
      +    },
      +    "beforeEach": {
      +      "minimum": 0,
      +      "type": "integer"
      +    }
      +  },
      +  "required": [
      +    "beforeAll",
      +    "beforeEach",
      +    "afterEach",
      +    "afterAll",
      +    "aroundEach",
      +    "aroundAll"
      +  ],
      +  "type": "object"
      +}
    • addedOutput schema / definitions / Step
      Added value: +{
      +  "properties": {
      +    "depth": {
      +      "description": "0 for a step directly in the test, 1 for a step inside it, and so on.",
      +      "minimum": 0,
      +      "type": "integer"
      +    },
      +    "hasDynamicTitle": {
      +      "type": "boolean"
      +    },
      +    "isSkipped": {
      +      "description": "Declared with `test.step.skip()`.",
      +      "type": "boolean"
      +    },
      +    "lineStart": {
      +      "minimum": 1,
      +      "type": "integer"
      +    },
      +    "title": {
      +      "description": "The title, or its source text when it can't be worked out.",
      +      "type": "string"
      +    }
      +  },
      +  "required": [
      +    "title",
      +    "hasDynamicTitle",
      +    "lineStart",
      +    "depth",
      +    "isSkipped"
      +  ],
      +  "type": "object"
      +}
    • addedOutput schema / definitions / TestRecord / properties / expectCount
      Added value: +{
      +  "description": "Calls of `expect()`, `expect.soft()` and `expect.poll()` written in the body, each counted once.",
      +  "minimum": 0,
      +  "type": "integer"
      +}
    • addedOutput schema / definitions / TestRecord / properties / expectedAssertions
      Added value: +{
      +  "anyOf": [
      +    {
      +      "minimum": 0,
      +      "type": "integer"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "description": "Vitest `expect.assertions(n)` in the body."
      +}
    • addedOutput schema / definitions / TestRecord / properties / expectsAssertions
      Added value: +{
      +  "description": "Vitest `expect.hasAssertions()` in the body.",
      +  "type": "boolean"
      +}
    • addedOutput schema / definitions / TestRecord / properties / fixtures
      Added value: +{
      +  "description": "Names the test function takes from its context, then those of the `beforeEach`, `afterEach` and `aroundEach` hooks around it, once each. Vitest's own context keys, such as `expect` and `task`, are left out.",
      +  "items": {
      +    "type": "string"
      +  },
      +  "type": "array"
      +}
    • addedOutput schema / definitions / TestRecord / properties / hasEmptyBody
      Added value: +{
      +  "description": "The test function has no statements, comments aside.",
      +  "type": "boolean"
      +}
    • addedOutput schema / definitions / TestRecord / properties / hooks
      Added value: +{
      +  "$ref": "#/definitions/HookCounts",
      +  "description": "Every hook that runs around the test: those of the file and of each describe around it."
      +}
    • addedOutput schema / definitions / TestRecord / properties / isBenchmark
      Added value: +{
      +  "description": "Vitest 5 benchmark: in a benchmark file, or using the `bench` fixture. Plain `vitest` doesn't run it.",
      +  "type": "boolean"
      +}
    • addedOutput schema / definitions / TestRecord / properties / isSlow
      Added value: +{
      +  "description": "Playwright `test.slow()` applies: the runner triples the timeout.",
      +  "type": "boolean"
      +}
    • addedOutput schema / definitions / TestRecord / properties / repeats
      Added value: +{
      +  "anyOf": [
      +    {
      +      "minimum": 0,
      +      "type": "integer"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "description": "Vitest only: how many times the runner runs the test again after the first run."
      +}
    • addedOutput schema / definitions / TestRecord / properties / retries
      Added value: +{
      +  "anyOf": [
      +    {
      +      "minimum": 0,
      +      "type": "integer"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "description": "How many times the runner retries the test when it fails; null when the file sets none."
      +}
    • addedOutput schema / definitions / TestRecord / properties / retryCondition
      Added value: +{
      +  "description": "Vitest only: source text of the `retry` object's `condition`, a RegExp or a function.",
      +  "type": [
      +    "string",
      +    "null"
      +  ]
      +}
    • addedOutput schema / definitions / TestRecord / properties / retryDelay
      Added value: +{
      +  "anyOf": [
      +    {
      +      "minimum": 0,
      +      "type": "integer"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "description": "Vitest only: milliseconds between retries, from the `retry` object (4.1)."
      +}
    • addedOutput schema / definitions / TestRecord / properties / slowCondition
      Added value: +{
      +  "description": "Source text of the condition of the `test.slow()` that applies; null when unconditional or not slow.",
      +  "type": [
      +    "string",
      +    "null"
      +  ]
      +}
    • addedOutput schema / definitions / TestRecord / properties / steps
      Added value: +{
      +  "description": "Playwright `test.step()` and `test.step.skip()` calls in the body, in source order.",
      +  "items": {
      +    "$ref": "#/definitions/Step"
      +  },
      +  "type": "array"
      +}
    • addedOutput schema / definitions / TestRecord / properties / timeout
      Added value: +{
      +  "anyOf": [
      +    {
      +      "minimum": 0,
      +      "type": "integer"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "description": "In milliseconds: the last `test.setTimeout()` in the body or a `beforeEach`, otherwise the nearest describe or file that sets one. Null when the file sets none, so the config's timeout applies."
      +}
    • changedOutput schema / definitions / TestRecord / required
      Previous value: -[
      -  "id",
      -  "bodyHash",
      -  "suiteId",
      -  "suitePath",
      -  "relativeFilePath",
      -  "fileName",
      -  "lineStart",
      -  "lineEnd",
      -  "columnStart",
      -  "columnEnd",
      -  "declaredAt",
      -  "title",
      -  "titleWithoutTags",
      -  "hasDynamicTitle",
      -  "fullName",
      -  "isTypeTest",
      -  "state",
      -  "isActive",
      -  "isSkipped",
      -  "isFixme",
      -  "isTodo",
      -  "isExpectedToFail",
      -  "isNotLoaded",
      -  "isOnly",
      -  "isConditional",
      -  "condition",
      -  "reason",
      -  "hasDynamicReason",
      -  "stateSource",
      -  "stateLine",
      -  "isParallel",
      -  "isSerial",
      -  "tags",
      -  "annotations",
      -  "comments",
      -  "locks",
      -  "meta",
      -  "isParameterized",
      -  "caseCount",
      -  "isInLoop",
      -  "isInCondition",
      -  "isInFunction"
      -]New value: +[
      +  "id",
      +  "bodyHash",
      +  "suiteId",
      +  "suitePath",
      +  "relativeFilePath",
      +  "fileName",
      +  "lineStart",
      +  "lineEnd",
      +  "columnStart",
      +  "columnEnd",
      +  "declaredAt",
      +  "title",
      +  "titleWithoutTags",
      +  "hasDynamicTitle",
      +  "fullName",
      +  "isTypeTest",
      +  "state",
      +  "isActive",
      +  "isSkipped",
      +  "isFixme",
      +  "isTodo",
      +  "isExpectedToFail",
      +  "isNotLoaded",
      +  "isOnly",
      +  "isConditional",
      +  "condition",
      +  "reason",
      +  "hasDynamicReason",
      +  "stateSource",
      +  "stateLine",
      +  "isParallel",
      +  "isSerial",
      +  "tags",
      +  "annotations",
      +  "comments",
      +  "locks",
      +  "meta",
      +  "hooks",
      +  "timeout",
      +  "isSlow",
      +  "slowCondition",
      +  "retries",
      +  "retryDelay",
      +  "retryCondition",
      +  "repeats",
      +  "fixtures",
      +  "expectCount",
      +  "expectedAssertions",
      +  "expectsAssertions",
      +  "hasEmptyBody",
      +  "steps",
      +  "isBenchmark",
      +  "isParameterized",
      +  "caseCount",
      +  "isInLoop",
      +  "isInCondition",
      +  "isInFunction"
      +]
  5. First observedv0.1.0

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark this read-only, idempotent and closed-world; the description adds behavior the annotations cannot convey: it reads test files 'without running them', ids stay stable across line moves but change on title/describe/file changes, unknown ids are returned in notFound, and oversized answers truncate with the remaining ids listed. That is unusually rich disclosure for a read tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The purpose, usage and id semantics are front-loaded, but the long colon-delimited inventory of returned fields ('location, describe path, state and where it is set, condition, reason, tags, annotations…') is a single run-on sentence that duplicates what the output schema already provides.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a five-parameter read tool with an output schema, the description covers everything an agent needs before calling: prerequisites, batch cap, id lifecycle, missing-id handling, and truncation behavior. Nothing material is left to guess.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds id semantics beyond the schema's one-liner: provenance from find_tests, stability rules across edits versus line moves, and a concrete example payload. The other four parameters (patterns, directory, framework, expandCases) are left to the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource ('Returns every key of the tests with the given ids') and immediately scopes it against siblings: 'Use it after find_tests or test_summary, for the details of up to 20 tests.' An agent can tell this apart from find_tests and test_summary from the text alone.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It states the call sequence (after find_tests or test_summary), the batch limit (up to 20 tests), and where ids come from. It does not spell out when not to use it, e.g. when bulk summaries suffice, but the context is strong.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.