{
  "markdown": "# testlink-mcp\n\n[![M8ven Score](https://m8ven.ai/badge/mcp/eason0in-testlink-mcp-2jz0i7?v=e96821ddfbd23b20558c92581da614a4)](https://m8ven.ai/mcp/eason0in-testlink-mcp-2jz0i7)\n\nAn AI-friendly, safety-first Model Context Protocol server for TestLink 1.9.20. It exposes normalized discovery and analysis tools, bounded cursor pagination, structured output, and preview-before-apply writes over stdio.\n\nThis repository is a clean implementation based on TestLink's public XML-RPC interface and the public MCP SDK. It has no dependency on a private TestLink package or private source tree.\n\n## Highlights\n\n- Starts without credentials so MCP clients can discover all tools, resources, and prompts.\n- Explicit deterministic demo mode for evaluation and onboarding.\n- `structuredContent`, `outputSchema`, tool annotations, cursor pagination, and stable error codes.\n- Attachment metadata only; attachment content and base64 payloads are removed.\n- Writes disabled by default. There is no delete tool.\n- Every apply requires `confirm: true`, an unexpired single-use 10-minute preview, and an unchanged server snapshot.\n- Side-effect calls are never automatically retried; apply attempts are written to a redacted operation ledger.\n- Runtime guard blocks unsupported/EOL odd Node releases and security patch levels below the declared floor.\n\n## Safe write demo\n\n![TestLink MCP safe write flow: preview, inspect a diff, then explicitly confirm the apply](https://raw.githubusercontent.com/Eason0in/testlink-mcp/main/docs/assets/testlink-safety/testlink-mcp-safety-flow.gif)\n\nThe demo uses synthetic data only. It shows the required safety boundary:\n**Preview** a proposed change, **inspect** the bounded diff, then call apply\nwith the exact preview ID and `confirm: true`. No write happens during preview.\nThe editable source frames are in\n[`docs/assets/testlink-safety`](https://github.com/Eason0in/testlink-mcp/tree/main/docs/assets/testlink-safety).\n\n## Requirements\n\n- Node.js `^22.23.2 || ^24.18.1 || ^26.5.1`\n- TestLink 1.9.20 with its XML-RPC API enabled\n\nThe development and container baseline is Node 24.19.0 LTS. CI also runs Node 22.23.2 and 26.7.0.\n\n## Quick start\n\n```bash\nnvm use\nnpm ci\nnpm run build\nTESTLINK_DEMO_MODE=true node dist/cli.js\n```\n\nFuture npm invocation after publication:\n\n```bash\nnpx -y testlink-mcp@1.0.8\n```\n\nMCP client configuration:\n\n```json\n{\n  \"mcpServers\": {\n    \"testlink\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"testlink-mcp@1.0.8\"],\n      \"env\": {\n        \"TESTLINK_URL\": \"https://testlink.example.com/testlink\",\n        \"TESTLINK_DEV_KEY\": \"your-testlink-dev-key\"\n      }\n    }\n  }\n}\n```\n\nDo not put real credentials in tracked files. Copy `.env.example` to an ignored `.env`, or inject environment variables from your MCP client/secret manager.\n\n## Tools\n\n| Workflow | Tool | Purpose |\n| --- | --- | --- |\n| Start | `testlink_get_server_capabilities` | Check configuration, compatibility, demo mode, and write policy |\n| Explore | `testlink_list_projects` | List projects |\n| Explore | `testlink_list_test_plans` | List plans in a project |\n| Explore | `testlink_list_builds` | List builds in a plan |\n| Explore | `testlink_list_test_suites` | Walk one suite level |\n| Analyze | `testlink_search_test_cases` | Search cases in a bounded project/suite scope |\n| Analyze | `testlink_get_test_case` | Retrieve one normalized case |\n| Analyze | `testlink_list_test_case_attachments` | Retrieve safe attachment metadata |\n| Analyze | `testlink_get_traceability` | Inspect requirement links and membership in one required test plan |\n| Analyze | `testlink_get_execution_history` | Inspect recent execution evidence |\n| Validate | `testlink_validate_test_case` | Find incomplete or ambiguous case content |\n| Preview | `testlink_preview_test_case_sync` | Preview create/update and plan memberships |\n| Apply | `testlink_apply_test_case_sync` | Apply an unchanged confirmed sync preview |\n| Preview | `testlink_preview_execution_result` | Preview passed/failed/blocked reporting |\n| Apply | `testlink_apply_execution_result` | Apply an unchanged confirmed result preview |\n\nAll tools return:\n\n```json\n{\n  \"ok\": true,\n  \"data\": {},\n  \"meta\": {\n    \"source\": \"testlink\",\n    \"requestId\": \"...\"\n  }\n}\n```\n\nFailures use `ok: false` with `{ code, message, retryable, details? }`. Consumers should branch on `error.code`, not message text.\n\n## Safe write workflow\n\n1. Search for an existing case and retrieve its current version.\n2. Validate the desired test case.\n3. Call the relevant preview tool.\n4. For a create, provide the TestLink `authorLogin`; `desiredCase.suiteId`,\n   `summary`, and `steps` are also required by TestLink 1.9.20.\n5. Show `proposedChanges` to the user and obtain explicit confirmation.\n6. Call apply with the preview ID and `confirm: true` within 10 minutes.\n7. A confirmed apply consumes its preview before any side effect. After any\n   success, conflict, or failure, create and review a new preview before trying\n   again.\n8. If apply returns `OUTCOME_UNKNOWN`, do not retry. The remote write may have\n   succeeded; reconcile the TestLink case, plan membership, or execution result\n   first.\n\nEnable writes only in the server process that should perform them:\n\n```bash\nTESTLINK_WRITE_ENABLED=true npx -y testlink-mcp@1.0.8\n```\n\nThe default ledger path is `~/.local/state/testlink-mcp/operations.jsonl`. Override it with `TESTLINK_LEDGER_PATH`. Before a remote write, the server persists an `attempted` row; it then records `applied` or `outcome_unknown`. The ledger contains hashes and redacted outcomes, not developer keys.\n\n## Configuration\n\n| Variable | Default | Meaning |\n| --- | --- | --- |\n| `TESTLINK_URL` | unset | TestLink base URL or complete XML-RPC endpoint |\n| `TESTLINK_DEV_KEY` | unset | Personal TestLink API key |\n| `TESTLINK_DEMO_MODE` | `false` | Use deterministic local demo data |\n| `TESTLINK_WRITE_ENABLED` | `false` | Permit confirmed apply tools |\n| `TESTLINK_REQUEST_TIMEOUT_MS` | `30000` | Request timeout, 100–300000 ms |\n| `TESTLINK_MAX_RESPONSE_BYTES` | `5242880` | Maximum XML response size |\n| `TESTLINK_LEDGER_PATH` | user state directory | Redacted JSONL operation ledger |\n| `NODE_EXTRA_CA_CERTS` | unset | Optional additional CA bundle; TLS verification remains enabled |\n\nDemo mode is explicit and wins over remote configuration:\n\n```bash\nTESTLINK_DEMO_MODE=true TESTLINK_WRITE_ENABLED=true node dist/cli.js\n```\n\n## Development\n\n```bash\nnpm ci\nnpm run check\nnpm test\nnpm run eval\nnpm run build\nnpm audit --omit=dev --audit-level=high\nnpm pack --dry-run\n```\n\nThe offline tool-selection eval checks that common user intents select search, validation, preview, and apply tools distinctly. It is deterministic and does not send data to an external model.\n\n## Docker\n\nThe image runs as a non-root user and uses Node 24.19.0. Build without pushing:\n\n```bash\ndocker buildx build --platform linux/amd64,linux/arm64 --tag testlink-mcp:local --output type=oci,dest=testlink-mcp.oci.tar .\n```\n\nFuture image name after approval and publication: `ghcr.io/eason0in/testlink-mcp:1.0.8`.\n\n## Release policy\n\nVersion 1.0.8 is release-ready but publication remains an explicit action. The\nprotected release workflow requires a signed version tag, reruns the complete\ntest/eval/audit/SBOM/package gates, publishes npm with provenance, publishes a\nmulti-architecture GHCR image with SBOM and provenance, creates a GitHub\nRelease, and finally publishes the validated MCP Registry entry.\n\nA separate protected live-smoke workflow verifies the installed package against\na real TestLink 1.9.20 instance using read-only calls. Its URL and developer key\nmust be stored as environment secrets and are never written to logs.\n\nThe package manifest and `server.json` share the MCP name `io.github.Eason0in/testlink-mcp`. Registry validation can be run without publishing:\n\n```bash\nmcp-publisher validate server.json\n```\n\nThe account-side setup and submission data for npm, the MCP Registry, Glama,\nand MCP.so are tracked in [Marketplace submission checklist](docs/marketplace-submission.md).\n\n## Public references\n\n- [TestLink 1.9.20 source and release branch](https://github.com/TestLinkOpenSourceTRMS/testlink-code/tree/testlink_1_9_20_fixed)\n- [Model Context Protocol TypeScript SDK](https://github.com/modelcontextprotocol/typescript-sdk)\n- [Official MCP Registry publisher commands](https://github.com/modelcontextprotocol/registry/blob/main/docs/reference/cli/commands.md)\n\n## License\n\nMIT\n",
  "bytes": 8459,
  "sha": "0a910b6b26a70357a1c756d167fb1cbb695f9bab25f58d285b9a464a13dffed8",
  "repo_slug": "eason0in/testlink-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_eason0in_testlink_mcp_5b1f014d/readme"
}