@vitest-agent/mcp 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +44 -0
- package/bin/vitest-agent-mcp.js +93 -0
- package/context.js +72 -0
- package/index.d.ts +1577 -0
- package/index.js +19 -0
- package/layers/McpLive.js +30 -0
- package/middleware/idempotency.js +128 -0
- package/package.json +58 -0
- package/prompts/explain-failure.js +27 -0
- package/prompts/index.js +89 -0
- package/prompts/regression-since-pass.js +28 -0
- package/prompts/tdd-resume.js +28 -0
- package/prompts/triage.js +24 -0
- package/prompts/why-flaky.js +30 -0
- package/prompts/wrapup.js +19 -0
- package/resources/index.js +155 -0
- package/resources/indexes.js +77 -0
- package/resources/manifest-schema.js +46 -0
- package/resources/paths.js +20 -0
- package/resources/patterns.js +22 -0
- package/resources/upstream-docs.js +22 -0
- package/router.js +74 -0
- package/server.js +838 -0
- package/tools/_tdd-error-envelope.js +98 -0
- package/tools/acceptance-metrics.js +75 -0
- package/tools/cache-health.js +83 -0
- package/tools/commit-changes.js +64 -0
- package/tools/configure.js +107 -0
- package/tools/coverage.js +76 -0
- package/tools/errors.js +151 -0
- package/tools/failure-signature-get.js +73 -0
- package/tools/file-coverage.js +106 -0
- package/tools/help.js +146 -0
- package/tools/history.js +121 -0
- package/tools/hypothesis.js +127 -0
- package/tools/inventory.js +377 -0
- package/tools/note.js +208 -0
- package/tools/overview.js +92 -0
- package/tools/ping.js +22 -0
- package/tools/register-agent.js +135 -0
- package/tools/run-tests.js +359 -0
- package/tools/settings-list.js +48 -0
- package/tools/status.js +74 -0
- package/tools/tdd-artifact.js +101 -0
- package/tools/tdd-behavior.js +177 -0
- package/tools/tdd-goal.js +147 -0
- package/tools/tdd-phase-transition-request.js +212 -0
- package/tools/tdd-task.js +278 -0
- package/tools/test.js +281 -0
- package/tools/trends.js +112 -0
- package/tools/triage-brief.js +42 -0
- package/tools/turn-search.js +60 -0
- package/tools/wrapup-prompt.js +49 -0
- package/tsdoc-metadata.json +11 -0
- package/utils/effect-to-zod.js +81 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 C. Spencer Beggs
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# @vitest-agent/mcp
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@vitest-agent/mcp)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
[](https://www.typescriptlang.org/)
|
|
6
|
+
|
|
7
|
+
> **Part of the [vitest-agent](https://vitest-agent.dev) ecosystem.** Most users want **[@vitest-agent/plugin](https://www.npmjs.com/package/@vitest-agent/plugin)**, which pulls this package in automatically. Install `@vitest-agent/mcp` directly only if you run the MCP server standalone.
|
|
8
|
+
|
|
9
|
+
The `vitest-agent-mcp` MCP server bin. Exposes action-keyed tools over stdio that give LLM agents structured access to test data, coverage, history, failure signatures, TDD lifecycle state and more. Also surfaces four MCP resources (vendored Vitest docs and curated testing patterns) and six framing-only prompts.
|
|
10
|
+
|
|
11
|
+
## Features
|
|
12
|
+
|
|
13
|
+
- **29 action-keyed tools** — per-CRUD families collapse into single tools dispatching on an `action` discriminator; covers `test_status`, `test_overview`, `test_coverage`, `test_errors`, `run_tests`, `note`, `hypothesis`, `tdd_task`, `tdd_goal`, `tdd_behavior` and more
|
|
14
|
+
- **Four MCP resources** — vendored Vitest documentation (`vitest://docs/`) and curated testing patterns (`vitest-agent://patterns/`) with per-page titles, descriptions and `audience`/`priority` annotations
|
|
15
|
+
- **Six framing prompts** — `triage`, `why-flaky`, `regression-since-pass`, `explain-failure`, `tdd-resume`, `wrapup`
|
|
16
|
+
- **Idempotency middleware** — `tdd_task`, `tdd_goal`, `tdd_behavior` and `hypothesis` create-actions are idempotent on derived keys
|
|
17
|
+
|
|
18
|
+
## Install
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm install --save-dev @vitest-agent/mcp
|
|
22
|
+
# or
|
|
23
|
+
pnpm add -D @vitest-agent/mcp
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
`@vitest-agent/mcp` is a required peer of `@vitest-agent/plugin` and arrives automatically with modern pnpm and npm.
|
|
27
|
+
|
|
28
|
+
## Quick start
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
npx vitest-agent-mcp
|
|
32
|
+
# starts the MCP server over stdio
|
|
33
|
+
# example output (varies by environment)
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
The server reads the SQLite database written by `AgentPlugin` via the same XDG-derived path, so a single test run populates data for all tools.
|
|
37
|
+
|
|
38
|
+
## Documentation
|
|
39
|
+
|
|
40
|
+
MCP reference and tool catalog at [vitest-agent.dev/mcp](https://vitest-agent.dev/mcp).
|
|
41
|
+
|
|
42
|
+
## License
|
|
43
|
+
|
|
44
|
+
[MIT](LICENSE)
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createCurrentSessionIdRef, createSessionContextRef, sessionContextFromEnv } from "../context.js";
|
|
3
|
+
import { McpLive } from "../layers/McpLive.js";
|
|
4
|
+
import { startMcpServer } from "../server.js";
|
|
5
|
+
import { CURRENT_MCP_VERSION } from "../index.js";
|
|
6
|
+
import { NodeContext } from "@effect/platform-node";
|
|
7
|
+
import { CURRENT_SDK_VERSION, PathResolutionLive, formatFatalError, resolveDataPath, resolveLogFile, resolveLogLevel } from "@vitest-agent/sdk";
|
|
8
|
+
import { Effect, ManagedRuntime } from "effect";
|
|
9
|
+
|
|
10
|
+
//#region src/bin.ts
|
|
11
|
+
/**
|
|
12
|
+
* Cross-package version drift check. Compares this MCP package's version
|
|
13
|
+
* against @vitest-agent/sdk and writes a single stderr line on mismatch.
|
|
14
|
+
* Observation-only — never throws. The `"0.0.0"` fallback marks a dev
|
|
15
|
+
* build (rslib-builder did not substitute the literal); skip the check
|
|
16
|
+
* to avoid spurious warnings during local source-loaded runs. See the
|
|
17
|
+
* root CLAUDE.md "Cross-package version drift" section.
|
|
18
|
+
*
|
|
19
|
+
* @internal
|
|
20
|
+
*/
|
|
21
|
+
function checkVersionDrift() {
|
|
22
|
+
if ("1.0.0" === "0.0.0") return;
|
|
23
|
+
if (CURRENT_SDK_VERSION !== "1.0.0") process.stderr.write(`[@vitest-agent/mcp] version drift: @vitest-agent/mcp@${CURRENT_MCP_VERSION} with @vitest-agent/sdk@${CURRENT_SDK_VERSION}. Reinstall @vitest-agent/* packages so versions match.\n`);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Resolve the user's project directory.
|
|
27
|
+
*
|
|
28
|
+
* Precedence (most explicit wins):
|
|
29
|
+
*
|
|
30
|
+
* 1. `VITEST_AGENT_REPORTER_PROJECT_DIR` — set by the Claude Code plugin
|
|
31
|
+
* loader (`plugin/bin/mcp-server.mjs`) to the resolved project root.
|
|
32
|
+
* The loader controls this end-to-end so the value is reliable when
|
|
33
|
+
* set.
|
|
34
|
+
* 2. `CLAUDE_PROJECT_DIR` — exported by Claude Code for hook scripts and
|
|
35
|
+
* (per docs hints) MCP server subprocesses. Used when the loader is
|
|
36
|
+
* bypassed (e.g. someone wires the MCP binary up manually).
|
|
37
|
+
* 3. `process.cwd()` — fall-through for direct invocation outside Claude
|
|
38
|
+
* Code, where the user is presumably running from their project root.
|
|
39
|
+
*/
|
|
40
|
+
function resolveProjectDir() {
|
|
41
|
+
return process.env.VITEST_AGENT_REPORTER_PROJECT_DIR ?? process.env.CLAUDE_PROJECT_DIR ?? process.cwd();
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Optional first positional argument: an initial Claude Code chat UUID
|
|
45
|
+
* (the host's `chatId`) to seed the MCP server's session association.
|
|
46
|
+
*
|
|
47
|
+
* The plugin manifest (`plugin/.claude-plugin/plugin.json`) can pass this
|
|
48
|
+
* via Claude Code variable substitution if such a variable exists for
|
|
49
|
+
* sessions (the documented substitutions are `${CLAUDE_PLUGIN_ROOT}` and
|
|
50
|
+
* `${CLAUDE_PLUGIN_DATA}`; testing whether `${CLAUDE_SESSION_ID}` or a
|
|
51
|
+
* similar name is honored in `mcpServers.args` is part of the reason
|
|
52
|
+
* this seed path exists). When the seed is empty the agent is expected
|
|
53
|
+
* to recover the chat id at boot. The legacy `set_current_session_id`
|
|
54
|
+
* MCP tool was removed in Phase 3.
|
|
55
|
+
*/
|
|
56
|
+
function resolveInitialSessionId() {
|
|
57
|
+
const argv = process.argv[2];
|
|
58
|
+
if (argv === void 0) return null;
|
|
59
|
+
const trimmed = argv.trim();
|
|
60
|
+
if (trimmed.length === 0) return null;
|
|
61
|
+
if (trimmed.startsWith("${") && trimmed.endsWith("}")) return null;
|
|
62
|
+
return trimmed;
|
|
63
|
+
}
|
|
64
|
+
async function main() {
|
|
65
|
+
const projectDir = resolveProjectDir();
|
|
66
|
+
checkVersionDrift();
|
|
67
|
+
const initialSessionId = resolveInitialSessionId();
|
|
68
|
+
const dbPath = await Effect.runPromise(resolveDataPath(projectDir).pipe(Effect.provide(PathResolutionLive(projectDir)), Effect.provide(NodeContext.layer)));
|
|
69
|
+
const logLevel = resolveLogLevel();
|
|
70
|
+
const logFile = resolveLogFile();
|
|
71
|
+
const runtime = ManagedRuntime.make(McpLive(dbPath, logLevel, logFile));
|
|
72
|
+
const recoveredContext = sessionContextFromEnv(process.env);
|
|
73
|
+
const ctx = {
|
|
74
|
+
runtime,
|
|
75
|
+
cwd: projectDir,
|
|
76
|
+
currentSessionId: createCurrentSessionIdRef(initialSessionId ?? recoveredContext?.chatId ?? null),
|
|
77
|
+
sessionContext: createSessionContextRef(recoveredContext)
|
|
78
|
+
};
|
|
79
|
+
const chatIdResolved = initialSessionId ?? recoveredContext?.chatId ?? null;
|
|
80
|
+
console.error("[vitest-agent-mcp] Starting...");
|
|
81
|
+
console.error(`[vitest-agent-mcp] Project: ${projectDir}`);
|
|
82
|
+
console.error(`[vitest-agent-mcp] Database: ${dbPath}`);
|
|
83
|
+
console.error(`[vitest-agent-mcp] Initial chat id: ${chatIdResolved !== null ? "(set)" : "(none — SessionStart hook had not written CLAUDE_ENV_FILE yet)"}`);
|
|
84
|
+
if (recoveredContext !== null) console.error("[vitest-agent-mcp] Recovered session context: agent=(set) conversation=(set)");
|
|
85
|
+
await startMcpServer(ctx);
|
|
86
|
+
}
|
|
87
|
+
main().catch((err) => {
|
|
88
|
+
process.stderr.write(`vitest-agent-mcp: ${formatFatalError(err)}\n`);
|
|
89
|
+
process.exit(1);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
//#endregion
|
|
93
|
+
export { };
|
package/context.js
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { initTRPC } from "@trpc/server";
|
|
2
|
+
|
|
3
|
+
//#region src/context.ts
|
|
4
|
+
/**
|
|
5
|
+
* Creates a new {@link CurrentSessionIdRef} with an optional initial value.
|
|
6
|
+
*
|
|
7
|
+
* @param initial - the starting chat id, or `null` when unknown at construction time
|
|
8
|
+
* @returns a mutable ref holding the current session id
|
|
9
|
+
* @public
|
|
10
|
+
*/
|
|
11
|
+
const createCurrentSessionIdRef = (initial = null) => {
|
|
12
|
+
let value = initial;
|
|
13
|
+
return {
|
|
14
|
+
get: () => value,
|
|
15
|
+
set: (id) => {
|
|
16
|
+
value = id;
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Creates a new {@link SessionContextRef} with an optional initial value.
|
|
22
|
+
*
|
|
23
|
+
* @param initial - the starting session context, or `null` when not yet recovered
|
|
24
|
+
* @returns a mutable ref holding the current session context
|
|
25
|
+
* @public
|
|
26
|
+
*/
|
|
27
|
+
const createSessionContextRef = (initial = null) => {
|
|
28
|
+
let value = initial;
|
|
29
|
+
return {
|
|
30
|
+
get: () => value,
|
|
31
|
+
set: (ctx) => {
|
|
32
|
+
value = ctx;
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Resolve the boot-time SessionContext from `process.env` (the
|
|
38
|
+
* primary path: SessionStart wrote the exports to `CLAUDE_ENV_FILE`
|
|
39
|
+
* and Claude Code auto-sources that file into the MCP server child).
|
|
40
|
+
*
|
|
41
|
+
* Returns `null` when any required value is absent — callers can
|
|
42
|
+
* still attempt the session-map fallback before giving up.
|
|
43
|
+
*/
|
|
44
|
+
const sessionContextFromEnv = (env = process.env) => {
|
|
45
|
+
const chatId = env.VITEST_AGENT_CHAT_ID;
|
|
46
|
+
const conversationId = env.VITEST_AGENT_CONVERSATION_ID;
|
|
47
|
+
const mainAgentId = env.VITEST_AGENT_MAIN_AGENT_ID ?? env.VITEST_AGENT_AGENT_ID;
|
|
48
|
+
if (chatId === void 0 || conversationId === void 0 || mainAgentId === void 0) return null;
|
|
49
|
+
if (chatId.length === 0 || conversationId.length === 0 || mainAgentId.length === 0) return null;
|
|
50
|
+
return {
|
|
51
|
+
chatId,
|
|
52
|
+
conversationId,
|
|
53
|
+
mainAgentId
|
|
54
|
+
};
|
|
55
|
+
};
|
|
56
|
+
const t = initTRPC.context().create();
|
|
57
|
+
const router = t.router;
|
|
58
|
+
const publicProcedure = t.procedure;
|
|
59
|
+
/**
|
|
60
|
+
* Factory for creating server-side tRPC callers for the MCP router.
|
|
61
|
+
*
|
|
62
|
+
* Use with {@link appRouter} in tests or programmatic contexts to invoke
|
|
63
|
+
* tool procedures without starting the MCP server.
|
|
64
|
+
*
|
|
65
|
+
* @public
|
|
66
|
+
*/
|
|
67
|
+
const createCallerFactory = t.createCallerFactory;
|
|
68
|
+
/** Exported so middleware modules can attach to the same tRPC instance. */
|
|
69
|
+
const middleware = t.middleware;
|
|
70
|
+
|
|
71
|
+
//#endregion
|
|
72
|
+
export { createCallerFactory, createCurrentSessionIdRef, createSessionContextRef, middleware, publicProcedure, router, sessionContextFromEnv };
|