agentloopkit 0.25.0 → 0.26.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/README.md CHANGED
@@ -60,8 +60,8 @@ npx agentloopkit init --local-only
60
60
  Pin the current version when you need repeatable CI or team setup:
61
61
 
62
62
  ```bash
63
- npx --yes agentloopkit@0.25.0 version
64
- npx --yes agentloopkit@0.25.0 init
63
+ npx --yes agentloopkit@0.26.0 version
64
+ npx --yes agentloopkit@0.26.0 init
65
65
  ```
66
66
 
67
67
  Run the CLI after install:
@@ -84,6 +84,7 @@ npx agentloopkit badge
84
84
  npx agentloopkit ci-summary
85
85
  npx agentloopkit release-notes
86
86
  npx agentloopkit npm-status
87
+ npx agentloopkit mcp-server
87
88
  npx agentloopkit policy list
88
89
  npx agentloopkit policy show security
89
90
  npx agentloopkit policy status
@@ -146,6 +147,7 @@ pnpm build
146
147
  | `agentloop ci-summary` | Summarize CI context and local AgentLoop evidence |
147
148
  | `agentloop release-notes` | Draft local release notes from changelog, git, task, and verification evidence |
148
149
  | `agentloop npm-status` | Check npm registry status without publishing |
150
+ | `agentloop mcp-server` | Start a read-only MCP stdio server for local AgentLoopKit state |
149
151
  | `agentloop policy list` | List local safety policy files |
150
152
  | `agentloop policy show <policy>` | Print a local safety policy without mutating files |
151
153
  | `agentloop policy status` | Compare local policy files with bundled templates |
@@ -393,7 +395,7 @@ See `docs/ci-summary.md`.
393
395
  ```bash
394
396
  agentloop release-notes
395
397
  agentloop release-notes --from v0.19.0 --to HEAD
396
- agentloop release-notes --release-version 0.25.0
398
+ agentloop release-notes --release-version 0.26.0
397
399
  agentloop release-notes --json
398
400
  agentloop release-notes --write
399
401
  ```
@@ -417,6 +419,18 @@ Use it after a publish attempt before saying npm has caught up. It runs `npm vie
417
419
 
418
420
  See `docs/npm-status.md`.
419
421
 
422
+ ## MCP Server
423
+
424
+ AgentLoopKit can expose existing repo evidence to MCP clients through a read-only stdio server:
425
+
426
+ ```bash
427
+ npx --yes agentloopkit@0.26.0 mcp-server
428
+ ```
429
+
430
+ The server provides tools for status, next action, task contracts, active task, policies, latest verification report, and handoff summaries. It does not run verification commands, edit files, call external APIs, read `.env` contents, or upload data.
431
+
432
+ See `docs/mcp.md` for client configuration, tool names, and registry notes.
433
+
420
434
  <p align="center">
421
435
  <img src="https://raw.githubusercontent.com/abhiyoheswaran1/AgentLoopKit/main/docs/assets/readme/agentloopkit-verification.png" alt="AgentLoopKit verification report screenshot showing task context, passing command results, and reviewer handoff sections" width="100%">
422
436
  </p>
@@ -459,7 +473,19 @@ Use `agentloop check-gates --strict` as a review-evidence gate in pull request C
459
473
 
460
474
  CI-generated verification reports include GitHub Actions provenance when available, so reviewers can trace an artifact back to the workflow run that created it.
461
475
 
462
- See `docs/github-actions.md`, `examples/github-actions/`, `examples/gitlab-ci/`, and `examples/buildkite/` for copy-pasteable workflows. Pin `agentloopkit@0.25.0` or a newer vetted release when reproducibility matters.
476
+ See `docs/github-actions.md`, `examples/github-actions/`, `examples/gitlab-ci/`, and `examples/buildkite/` for copy-pasteable workflows. Pin `agentloopkit@0.26.0` or a newer vetted release when reproducibility matters.
477
+
478
+ ## Other Install Channels
479
+
480
+ npm and npx remain the primary install path. AgentLoopKit also ships release assets and maintainer artifacts for:
481
+
482
+ - GitHub Releases: versioned tarballs for provenance and rollback.
483
+ - GitHub Action: a thin wrapper for `agentloop` commands in CI.
484
+ - Docker/GHCR: a minimal image that runs `agentloop`.
485
+ - Homebrew: a formula under `packaging/homebrew/` for the tap release flow.
486
+ - MCP Registry: read-only server metadata for MCP clients once the matching npm package is published.
487
+
488
+ See `docs/distribution-channels.md` for current commands and maintainer release steps.
463
489
 
464
490
  ## PR Summaries
465
491
 
package/dist/cli/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/cli/index.ts
4
- import { Command as Command20 } from "commander";
4
+ import { Command as Command21 } from "commander";
5
5
 
6
6
  // src/cli/commands/init.ts
7
7
  import { Command } from "commander";
@@ -2210,6 +2210,7 @@ var topLevelCommands = [
2210
2210
  ["ci-summary", "Summarize CI context and AgentLoop evidence"],
2211
2211
  ["release-notes", "Generate deterministic release notes"],
2212
2212
  ["npm-status", "Check npm registry catch-up status"],
2213
+ ["mcp-server", "Start the read-only MCP stdio server"],
2213
2214
  ["policy", "List or inspect local AgentLoopKit policies"],
2214
2215
  ["task", "List, inspect, update, or archive task contracts"],
2215
2216
  ["install-agent", "Install agent-specific instructions"],
@@ -3902,8 +3903,261 @@ function npmStatusCommand() {
3902
3903
  );
3903
3904
  }
3904
3905
 
3906
+ // src/cli/commands/mcp-server.ts
3907
+ import { Command as Command20 } from "commander";
3908
+
3909
+ // src/mcp/server.ts
3910
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
3911
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3912
+ import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
3913
+
3914
+ // src/core/mcp-tools.ts
3915
+ import path23 from "path";
3916
+ import { readdir as readdir9, readFile as readFile18, stat as stat9 } from "fs/promises";
3917
+ var emptyInputSchema = {
3918
+ type: "object",
3919
+ properties: {},
3920
+ additionalProperties: false
3921
+ };
3922
+ var tools = [
3923
+ {
3924
+ name: "agentloop_status",
3925
+ description: "Read AgentLoopKit status, active task, latest verification, git state, and next action.",
3926
+ inputSchema: emptyInputSchema
3927
+ },
3928
+ {
3929
+ name: "agentloop_next",
3930
+ description: "Read only the next recommended AgentLoopKit action and reason.",
3931
+ inputSchema: emptyInputSchema
3932
+ },
3933
+ {
3934
+ name: "agentloop_list_tasks",
3935
+ description: "List local task contracts under the configured AgentLoopKit task directory.",
3936
+ inputSchema: emptyInputSchema
3937
+ },
3938
+ {
3939
+ name: "agentloop_show_active_task",
3940
+ description: "Read the active task contract content when one is pinned.",
3941
+ inputSchema: emptyInputSchema
3942
+ },
3943
+ {
3944
+ name: "agentloop_list_policies",
3945
+ description: "List local AgentLoopKit safety policy files.",
3946
+ inputSchema: emptyInputSchema
3947
+ },
3948
+ {
3949
+ name: "agentloop_read_policy",
3950
+ description: "Read one local AgentLoopKit policy by policy name.",
3951
+ inputSchema: {
3952
+ type: "object",
3953
+ properties: {
3954
+ policyName: {
3955
+ type: "string",
3956
+ description: 'Policy name, for example "security" or "security-policy.md".'
3957
+ }
3958
+ },
3959
+ required: ["policyName"],
3960
+ additionalProperties: false
3961
+ }
3962
+ },
3963
+ {
3964
+ name: "agentloop_latest_verification_report",
3965
+ description: "Read the latest local verification report metadata and Markdown content.",
3966
+ inputSchema: emptyInputSchema
3967
+ },
3968
+ {
3969
+ name: "agentloop_list_handoffs",
3970
+ description: "List recent local reviewer handoff summaries.",
3971
+ inputSchema: {
3972
+ type: "object",
3973
+ properties: {
3974
+ limit: {
3975
+ type: "number",
3976
+ minimum: 1,
3977
+ maximum: 50,
3978
+ description: "Maximum handoff summaries to return. Defaults to 20."
3979
+ }
3980
+ },
3981
+ additionalProperties: false
3982
+ }
3983
+ },
3984
+ {
3985
+ name: "agentloop_latest_handoff",
3986
+ description: "Read the latest local reviewer handoff summary Markdown content.",
3987
+ inputSchema: emptyInputSchema
3988
+ }
3989
+ ];
3990
+ function listMcpTools() {
3991
+ return [...tools];
3992
+ }
3993
+ function textResult(payload) {
3994
+ return {
3995
+ payload,
3996
+ content: [
3997
+ {
3998
+ type: "text",
3999
+ text: JSON.stringify(payload, null, 2)
4000
+ }
4001
+ ]
4002
+ };
4003
+ }
4004
+ function extractHeading7(markdown, fallback) {
4005
+ return markdown.match(/^#\s+(.+)$/m)?.[1]?.trim() || fallback;
4006
+ }
4007
+ function toStoredPath3(cwd, absolutePath) {
4008
+ return path23.relative(cwd, absolutePath).split(path23.sep).join("/");
4009
+ }
4010
+ async function readMarkdownArtifact(cwd, filePath, key) {
4011
+ if (!filePath) return { [key]: null };
4012
+ const content = await readFile18(filePath, "utf8");
4013
+ const fileStat = await stat9(filePath);
4014
+ return {
4015
+ [key]: {
4016
+ path: toStoredPath3(cwd, filePath),
4017
+ title: extractHeading7(content, path23.basename(filePath, ".md")),
4018
+ modifiedAt: fileStat.mtime.toISOString(),
4019
+ content
4020
+ }
4021
+ };
4022
+ }
4023
+ async function listHandoffs(cwd, handoffsDir, limit) {
4024
+ if (!await pathExists(handoffsDir)) return [];
4025
+ const entries = await readdir9(handoffsDir, { withFileTypes: true });
4026
+ const handoffs = await Promise.all(
4027
+ entries.filter((entry) => entry.isFile() && prSummaryPattern.test(entry.name)).map(async (entry) => {
4028
+ const filePath = path23.join(handoffsDir, entry.name);
4029
+ const [content, fileStat] = await Promise.all([readFile18(filePath, "utf8"), stat9(filePath)]);
4030
+ return {
4031
+ path: toStoredPath3(cwd, filePath),
4032
+ title: extractHeading7(content, path23.basename(filePath, ".md")),
4033
+ modifiedAt: fileStat.mtime.toISOString(),
4034
+ modifiedMs: fileStat.mtimeMs
4035
+ };
4036
+ })
4037
+ );
4038
+ return handoffs.sort((left, right) => {
4039
+ if (left.modifiedMs !== right.modifiedMs) return right.modifiedMs - left.modifiedMs;
4040
+ return left.path.localeCompare(right.path);
4041
+ }).slice(0, limit).map((handoff) => ({
4042
+ path: handoff.path,
4043
+ title: handoff.title,
4044
+ modifiedAt: handoff.modifiedAt
4045
+ }));
4046
+ }
4047
+ function readStringArgument(args, key) {
4048
+ const value = args?.[key];
4049
+ if (typeof value !== "string" || !value.trim()) {
4050
+ throw new AgentLoopError(`MCP tool argument "${key}" must be a non-empty string.`);
4051
+ }
4052
+ return value;
4053
+ }
4054
+ function readLimitArgument(args) {
4055
+ const value = args?.limit;
4056
+ if (value === void 0) return 20;
4057
+ if (typeof value !== "number" || !Number.isInteger(value) || value < 1 || value > 50) {
4058
+ throw new AgentLoopError('MCP tool argument "limit" must be an integer from 1 to 50.');
4059
+ }
4060
+ return value;
4061
+ }
4062
+ async function callMcpTool(options) {
4063
+ const config = await loadAgentLoopConfig(options.cwd);
4064
+ switch (options.name) {
4065
+ case "agentloop_status": {
4066
+ const status = await getAgentLoopStatus({ cwd: options.cwd, config });
4067
+ return textResult(status);
4068
+ }
4069
+ case "agentloop_next": {
4070
+ const status = await getAgentLoopStatus({ cwd: options.cwd, config });
4071
+ return textResult(status.nextAction);
4072
+ }
4073
+ case "agentloop_list_tasks": {
4074
+ return textResult({ tasks: await listTasks({ cwd: options.cwd, config }) });
4075
+ }
4076
+ case "agentloop_show_active_task": {
4077
+ const activeTask = await getActiveTask({ cwd: options.cwd, config });
4078
+ if (!activeTask) return textResult({ task: null });
4079
+ const task = await readTaskContract({ cwd: options.cwd, config, taskPath: activeTask.path });
4080
+ return textResult({ task });
4081
+ }
4082
+ case "agentloop_list_policies": {
4083
+ return textResult({ policies: await listPolicies({ cwd: options.cwd, config }) });
4084
+ }
4085
+ case "agentloop_read_policy": {
4086
+ const policyName = readStringArgument(options.arguments, "policyName");
4087
+ return textResult({
4088
+ policy: await readPolicy({ cwd: options.cwd, config, policyName })
4089
+ });
4090
+ }
4091
+ case "agentloop_latest_verification_report": {
4092
+ const reportPath = await latestMarkdownFile(
4093
+ path23.join(options.cwd, config.paths.reportsDir),
4094
+ {
4095
+ pattern: verificationReportPattern
4096
+ }
4097
+ );
4098
+ return textResult(await readMarkdownArtifact(options.cwd, reportPath, "report"));
4099
+ }
4100
+ case "agentloop_list_handoffs": {
4101
+ const limit = readLimitArgument(options.arguments);
4102
+ return textResult({
4103
+ handoffs: await listHandoffs(
4104
+ options.cwd,
4105
+ path23.join(options.cwd, config.paths.handoffsDir),
4106
+ limit
4107
+ )
4108
+ });
4109
+ }
4110
+ case "agentloop_latest_handoff": {
4111
+ const handoffPath = await latestMarkdownFile(
4112
+ path23.join(options.cwd, config.paths.handoffsDir),
4113
+ {
4114
+ pattern: prSummaryPattern
4115
+ }
4116
+ );
4117
+ return textResult(await readMarkdownArtifact(options.cwd, handoffPath, "handoff"));
4118
+ }
4119
+ default:
4120
+ throw new AgentLoopError(`Unknown MCP tool: ${options.name}`);
4121
+ }
4122
+ }
4123
+
4124
+ // src/mcp/server.ts
4125
+ async function startAgentLoopMcpServer(options) {
4126
+ const server = new Server(
4127
+ {
4128
+ name: "agentloopkit",
4129
+ version: getPackageVersion()
4130
+ },
4131
+ {
4132
+ capabilities: {
4133
+ tools: {}
4134
+ },
4135
+ instructions: "Read-only AgentLoopKit server. Exposes local task contracts, policies, verification reports, handoffs, status, and next action. It does not run verification commands, read env file contents, call external APIs, upload files, or mutate repository files."
4136
+ }
4137
+ );
4138
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({
4139
+ tools: listMcpTools()
4140
+ }));
4141
+ server.setRequestHandler(
4142
+ CallToolRequestSchema,
4143
+ async (request) => callMcpTool({
4144
+ cwd: options.cwd,
4145
+ name: request.params.name,
4146
+ arguments: request.params.arguments
4147
+ })
4148
+ );
4149
+ await server.connect(new StdioServerTransport());
4150
+ }
4151
+
4152
+ // src/cli/commands/mcp-server.ts
4153
+ function mcpServerCommand() {
4154
+ return new Command20("mcp-server").description("Start the read-only AgentLoopKit MCP stdio server").action(async () => {
4155
+ await startAgentLoopMcpServer({ cwd: process.cwd() });
4156
+ });
4157
+ }
4158
+
3905
4159
  // src/cli/index.ts
3906
- var program = new Command20();
4160
+ var program = new Command21();
3907
4161
  program.name("agentloop").description("A drop-in engineering loop for coding agents.").version(getPackageVersion(), "-V, --version", "print CLI version");
3908
4162
  program.addCommand(initCommand());
3909
4163
  program.addCommand(doctorCommand());
@@ -3919,6 +4173,7 @@ program.addCommand(badgeCommand());
3919
4173
  program.addCommand(ciSummaryCommand());
3920
4174
  program.addCommand(releaseNotesCommand());
3921
4175
  program.addCommand(npmStatusCommand());
4176
+ program.addCommand(mcpServerCommand());
3922
4177
  program.addCommand(policyCommand());
3923
4178
  program.addCommand(taskCommand());
3924
4179
  program.addCommand(installAgentCommand());