@selfagency/beans-mcp 0.1.4 → 0.4.2
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 +63 -6
- package/beans-mcp-server.cjs +268 -34
- package/index.cjs +268 -34
- package/index.d.ts +19 -1
- package/index.js +268 -34
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -22744,7 +22744,7 @@ var init_utils = __esm({
|
|
|
22744
22744
|
});
|
|
22745
22745
|
|
|
22746
22746
|
// src/internal/graphql.ts
|
|
22747
|
-
var LIST_BEANS_QUERY, CREATE_BEAN_MUTATION, UPDATE_BEAN_MUTATION, DELETE_BEAN_MUTATION;
|
|
22747
|
+
var LIST_BEANS_QUERY, CREATE_BEAN_MUTATION, UPDATE_BEAN_MUTATION, UPDATE_BEAN_MUTATION_WITH_IF_MATCH, DELETE_BEAN_MUTATION;
|
|
22748
22748
|
var init_graphql = __esm({
|
|
22749
22749
|
"src/internal/graphql.ts"() {
|
|
22750
22750
|
"use strict";
|
|
@@ -22762,6 +22762,11 @@ var init_graphql = __esm({
|
|
|
22762
22762
|
mutation($id: ID!, $input: UpdateBeanInput!) {
|
|
22763
22763
|
updateBean(id: $id, input: $input) { id slug path title body status type priority tags parentId blockingIds blockedByIds createdAt updatedAt etag }
|
|
22764
22764
|
}
|
|
22765
|
+
`;
|
|
22766
|
+
UPDATE_BEAN_MUTATION_WITH_IF_MATCH = `
|
|
22767
|
+
mutation($id: ID!, $input: UpdateBeanInput!, $ifMatch: String!) {
|
|
22768
|
+
updateBean(id: $id, input: $input, ifMatch: $ifMatch) { id slug path title body status type priority tags parentId blockingIds blockedByIds createdAt updatedAt etag }
|
|
22769
|
+
}
|
|
22765
22770
|
`;
|
|
22766
22771
|
DELETE_BEAN_MUTATION = `
|
|
22767
22772
|
mutation($id: ID!) {
|
|
@@ -22919,10 +22924,50 @@ Output: ${stdout.slice(0, 1e3)}`
|
|
|
22919
22924
|
if (updates.body !== void 0) {
|
|
22920
22925
|
updateInput.body = updates.body;
|
|
22921
22926
|
}
|
|
22922
|
-
const
|
|
22923
|
-
|
|
22924
|
-
|
|
22925
|
-
}
|
|
22927
|
+
const bodyMod = {};
|
|
22928
|
+
if (updates.bodyAppend !== void 0) {
|
|
22929
|
+
bodyMod.append = updates.bodyAppend;
|
|
22930
|
+
}
|
|
22931
|
+
if (Array.isArray(updates.bodyReplace) && updates.bodyReplace.length > 0) {
|
|
22932
|
+
bodyMod.replace = updates.bodyReplace;
|
|
22933
|
+
}
|
|
22934
|
+
if (Object.keys(bodyMod).length > 0) {
|
|
22935
|
+
updateInput.bodyMod = bodyMod;
|
|
22936
|
+
}
|
|
22937
|
+
let data;
|
|
22938
|
+
let errors;
|
|
22939
|
+
if (updates.ifMatch) {
|
|
22940
|
+
try {
|
|
22941
|
+
const res = await this.executeGraphQL(UPDATE_BEAN_MUTATION_WITH_IF_MATCH, {
|
|
22942
|
+
id: beanId,
|
|
22943
|
+
input: updateInput,
|
|
22944
|
+
ifMatch: updates.ifMatch
|
|
22945
|
+
});
|
|
22946
|
+
data = res.data;
|
|
22947
|
+
errors = res.errors;
|
|
22948
|
+
} catch (error48) {
|
|
22949
|
+
const message = error48.message || "";
|
|
22950
|
+
const unsupportedIfMatch = /unknown argument.*ifMatch|unknown field.*ifMatch|ifMatch.*not defined|field .*updateBean.* argument .*ifMatch/i.test(
|
|
22951
|
+
message
|
|
22952
|
+
);
|
|
22953
|
+
if (!unsupportedIfMatch) {
|
|
22954
|
+
throw error48;
|
|
22955
|
+
}
|
|
22956
|
+
const fallback = await this.executeGraphQL(UPDATE_BEAN_MUTATION, {
|
|
22957
|
+
id: beanId,
|
|
22958
|
+
input: updateInput
|
|
22959
|
+
});
|
|
22960
|
+
data = fallback.data;
|
|
22961
|
+
errors = fallback.errors;
|
|
22962
|
+
}
|
|
22963
|
+
} else {
|
|
22964
|
+
const res = await this.executeGraphQL(UPDATE_BEAN_MUTATION, {
|
|
22965
|
+
id: beanId,
|
|
22966
|
+
input: updateInput
|
|
22967
|
+
});
|
|
22968
|
+
data = res.data;
|
|
22969
|
+
errors = res.errors;
|
|
22970
|
+
}
|
|
22926
22971
|
if (errors && errors.length > 0) {
|
|
22927
22972
|
throw new Error(`GraphQL error: ${errors.map((e) => e.message).join(", ")}`);
|
|
22928
22973
|
}
|
|
@@ -22942,6 +22987,21 @@ Output: ${stdout.slice(0, 1e3)}`
|
|
|
22942
22987
|
const content = await readFile(configPath, "utf8");
|
|
22943
22988
|
return { configPath, content };
|
|
22944
22989
|
}
|
|
22990
|
+
async primeInstructions() {
|
|
22991
|
+
const { stdout } = await execFileAsync(this.cliPath, ["prime"], {
|
|
22992
|
+
cwd: this.workspaceRoot,
|
|
22993
|
+
env: this.getSafeEnv(),
|
|
22994
|
+
maxBuffer: 10 * 1024 * 1024,
|
|
22995
|
+
timeout: 3e4
|
|
22996
|
+
});
|
|
22997
|
+
return stdout.trim();
|
|
22998
|
+
}
|
|
22999
|
+
async writeInstructions(instructions) {
|
|
23000
|
+
const instructionsPath = join(this.workspaceRoot, ".github", "instructions", "beans-prime.instructions.md");
|
|
23001
|
+
await mkdir(dirname(instructionsPath), { recursive: true });
|
|
23002
|
+
await writeFile(instructionsPath, instructions, "utf8");
|
|
23003
|
+
return instructionsPath;
|
|
23004
|
+
}
|
|
22945
23005
|
async graphqlSchema() {
|
|
22946
23006
|
const { stdout } = await execFileAsync(this.cliPath, ["graphql", "--schema"], {
|
|
22947
23007
|
cwd: this.workspaceRoot,
|
|
@@ -31069,6 +31129,10 @@ var EMPTY_COMPLETION_RESULT = {
|
|
|
31069
31129
|
}
|
|
31070
31130
|
};
|
|
31071
31131
|
|
|
31132
|
+
// src/server/BeansMcpServer.ts
|
|
31133
|
+
import { execFile as execFile2 } from "child_process";
|
|
31134
|
+
import { promisify as promisify2 } from "util";
|
|
31135
|
+
|
|
31072
31136
|
// src/internal/queryHelpers.ts
|
|
31073
31137
|
function sortBeansInternal(beans, mode) {
|
|
31074
31138
|
const sorted = [...beans];
|
|
@@ -31124,15 +31188,23 @@ async function handleQueryOperation(backend, params) {
|
|
|
31124
31188
|
const { operation, mode, statuses, types, search, tags, writeToWorkspaceInstructions, includeClosed } = params;
|
|
31125
31189
|
if (operation === "llm_context") {
|
|
31126
31190
|
const graphqlSchema = typeof backend.graphqlSchema === "function" ? await backend.graphqlSchema() : "";
|
|
31127
|
-
|
|
31191
|
+
let generatedInstructions = "";
|
|
31192
|
+
if (typeof backend.primeInstructions === "function") {
|
|
31193
|
+
try {
|
|
31194
|
+
generatedInstructions = await backend.primeInstructions();
|
|
31195
|
+
} catch {
|
|
31196
|
+
generatedInstructions = "";
|
|
31197
|
+
}
|
|
31198
|
+
}
|
|
31199
|
+
const instructionsPath = writeToWorkspaceInstructions && typeof backend.writeInstructions === "function" ? await backend.writeInstructions(generatedInstructions) : null;
|
|
31128
31200
|
return {
|
|
31129
31201
|
content: [
|
|
31130
31202
|
{
|
|
31131
31203
|
type: "text",
|
|
31132
|
-
text: JSON.stringify({ graphqlSchema, generatedInstructions
|
|
31204
|
+
text: JSON.stringify({ graphqlSchema, generatedInstructions, instructionsPath }, null, 2)
|
|
31133
31205
|
}
|
|
31134
31206
|
],
|
|
31135
|
-
structuredContent: { graphqlSchema, generatedInstructions
|
|
31207
|
+
structuredContent: { graphqlSchema, generatedInstructions, instructionsPath }
|
|
31136
31208
|
};
|
|
31137
31209
|
}
|
|
31138
31210
|
if (operation === "open_config") {
|
|
@@ -31178,6 +31250,31 @@ async function handleQueryOperation(backend, params) {
|
|
|
31178
31250
|
structuredContent: { query: search, count: beans2.length, beans: beans2 }
|
|
31179
31251
|
};
|
|
31180
31252
|
}
|
|
31253
|
+
if (operation === "ready") {
|
|
31254
|
+
const allBeans = await backend.list();
|
|
31255
|
+
const byId = new Map(allBeans.map((bean) => [bean.id, bean]));
|
|
31256
|
+
const candidates = await backend.list({ status: normalizedStatuses, type: normalizedTypes, search });
|
|
31257
|
+
const readyBeans = candidates.filter((bean) => {
|
|
31258
|
+
if (bean.status !== "todo") {
|
|
31259
|
+
return false;
|
|
31260
|
+
}
|
|
31261
|
+
const blockedBy = bean.blockedByIds || [];
|
|
31262
|
+
if (blockedBy.length === 0) {
|
|
31263
|
+
return true;
|
|
31264
|
+
}
|
|
31265
|
+
return blockedBy.every((blockerId) => {
|
|
31266
|
+
const blocker = byId.get(blockerId);
|
|
31267
|
+
if (!blocker) {
|
|
31268
|
+
return false;
|
|
31269
|
+
}
|
|
31270
|
+
return blocker.status === "completed" || blocker.status === "scrapped";
|
|
31271
|
+
});
|
|
31272
|
+
});
|
|
31273
|
+
return {
|
|
31274
|
+
content: [{ type: "text", text: JSON.stringify({ count: readyBeans.length, beans: readyBeans }, null, 2) }],
|
|
31275
|
+
structuredContent: { count: readyBeans.length, beans: readyBeans }
|
|
31276
|
+
};
|
|
31277
|
+
}
|
|
31181
31278
|
const beans = await backend.list({ status: normalizedStatuses, type: normalizedTypes, search });
|
|
31182
31279
|
const sorted = sortBeansInternal(beans, mode ?? "status-priority-type-title");
|
|
31183
31280
|
return {
|
|
@@ -31200,7 +31297,7 @@ init_utils();
|
|
|
31200
31297
|
// package.json
|
|
31201
31298
|
var package_default = {
|
|
31202
31299
|
name: "@selfagency/beans-mcp",
|
|
31203
|
-
version: "0.
|
|
31300
|
+
version: "0.4.2",
|
|
31204
31301
|
private: false,
|
|
31205
31302
|
description: "MCP (Model Context Protocol) server for Beans issue tracker",
|
|
31206
31303
|
author: {
|
|
@@ -31255,18 +31352,18 @@ var package_default = {
|
|
|
31255
31352
|
devDependencies: {
|
|
31256
31353
|
"@modelcontextprotocol/sdk": "^1.27.1",
|
|
31257
31354
|
"@octokit/rest": "^22.0.1",
|
|
31258
|
-
"@types/node": "
|
|
31259
|
-
"@vitest/coverage-v8": "^4.0
|
|
31260
|
-
"@vitest/ui": "4.0
|
|
31355
|
+
"@types/node": "25.5.0",
|
|
31356
|
+
"@vitest/coverage-v8": "^4.1.0",
|
|
31357
|
+
"@vitest/ui": "4.1.0",
|
|
31261
31358
|
husky: "^9.1.7",
|
|
31262
|
-
"lint-staged": "^16.
|
|
31359
|
+
"lint-staged": "^16.3.3",
|
|
31263
31360
|
ora: "^9.3.0",
|
|
31264
|
-
oxfmt: "^0.
|
|
31265
|
-
oxlint: "^1.
|
|
31266
|
-
"oxlint-tsgolint": "^0.
|
|
31361
|
+
oxfmt: "^0.40.0",
|
|
31362
|
+
oxlint: "^1.55.0",
|
|
31363
|
+
"oxlint-tsgolint": "^0.16.0",
|
|
31267
31364
|
tsup: "8.5.1",
|
|
31268
31365
|
typescript: "^5.9.3",
|
|
31269
|
-
vitest: "4.0
|
|
31366
|
+
vitest: "4.1.0",
|
|
31270
31367
|
zod: "4.3.6",
|
|
31271
31368
|
zx: "^8.8.5"
|
|
31272
31369
|
},
|
|
@@ -31282,6 +31379,45 @@ var package_default = {
|
|
|
31282
31379
|
};
|
|
31283
31380
|
|
|
31284
31381
|
// src/server/BeansMcpServer.ts
|
|
31382
|
+
var execFileAsync2 = promisify2(execFile2);
|
|
31383
|
+
var PACKAGE_VERSION = package_default.version ?? "0.0.0-dev";
|
|
31384
|
+
function getSafeCliEnv(env) {
|
|
31385
|
+
const whitelist = ["PATH", "HOME", "USER", "LANG", "LC_ALL", "LC_CTYPE", "SHELL"];
|
|
31386
|
+
const safeEnv = {};
|
|
31387
|
+
for (const key of whitelist) {
|
|
31388
|
+
if (env[key]) {
|
|
31389
|
+
safeEnv[key] = env[key];
|
|
31390
|
+
}
|
|
31391
|
+
}
|
|
31392
|
+
for (const key in env) {
|
|
31393
|
+
if (key.startsWith("BEANS_")) {
|
|
31394
|
+
safeEnv[key] = env[key];
|
|
31395
|
+
}
|
|
31396
|
+
}
|
|
31397
|
+
return safeEnv;
|
|
31398
|
+
}
|
|
31399
|
+
function extractVersionFromOutput(output) {
|
|
31400
|
+
const trimmed = output.trim();
|
|
31401
|
+
if (!trimmed) {
|
|
31402
|
+
return null;
|
|
31403
|
+
}
|
|
31404
|
+
const match = trimmed.match(/(?:^|[^\d])v?(\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?)/);
|
|
31405
|
+
return match?.[1] ?? null;
|
|
31406
|
+
}
|
|
31407
|
+
async function detectBeansCliVersion(cliPath, workspaceRoot) {
|
|
31408
|
+
try {
|
|
31409
|
+
const { stdout, stderr } = await execFileAsync2(cliPath, ["version"], {
|
|
31410
|
+
cwd: workspaceRoot,
|
|
31411
|
+
env: getSafeCliEnv(process.env),
|
|
31412
|
+
maxBuffer: 1024 * 1024,
|
|
31413
|
+
timeout: 5e3
|
|
31414
|
+
});
|
|
31415
|
+
return extractVersionFromOutput(`${stdout}
|
|
31416
|
+
${stderr}`);
|
|
31417
|
+
} catch {
|
|
31418
|
+
return null;
|
|
31419
|
+
}
|
|
31420
|
+
}
|
|
31285
31421
|
async function getBeanById(backend, beanId) {
|
|
31286
31422
|
try {
|
|
31287
31423
|
const beans = await backend.list();
|
|
@@ -31301,7 +31437,35 @@ function initHandler(backend) {
|
|
|
31301
31437
|
};
|
|
31302
31438
|
}
|
|
31303
31439
|
function viewHandler(backend) {
|
|
31304
|
-
return async ({ beanId }) =>
|
|
31440
|
+
return async ({ beanId, beanIds }) => {
|
|
31441
|
+
const ids = Array.isArray(beanIds) && beanIds.length > 0 ? beanIds : beanId ? [beanId] : [];
|
|
31442
|
+
if (ids.length === 0) {
|
|
31443
|
+
throw new Error("Either beanId or beanIds must be provided");
|
|
31444
|
+
}
|
|
31445
|
+
if (ids.length === 1) {
|
|
31446
|
+
const bean = await getBeanById(backend, ids[0]);
|
|
31447
|
+
return makeTextAndStructured({ bean });
|
|
31448
|
+
}
|
|
31449
|
+
const beans = await backend.list();
|
|
31450
|
+
const byId = new Map(beans.map((b) => [b.id, b]));
|
|
31451
|
+
const found = ids.map((id) => byId.get(id)).filter(Boolean);
|
|
31452
|
+
const missingBeanIds = ids.filter((id) => !byId.has(id));
|
|
31453
|
+
return makeTextAndStructured({ beans: found, missingBeanIds, count: found.length, requestedCount: ids.length });
|
|
31454
|
+
};
|
|
31455
|
+
}
|
|
31456
|
+
async function checkVersionCompatibility(cliPath, workspaceRoot, detector) {
|
|
31457
|
+
const detectedBeansVersion = await detector(cliPath, workspaceRoot);
|
|
31458
|
+
if (!detectedBeansVersion) {
|
|
31459
|
+
console.error(
|
|
31460
|
+
`[beans-mcp] warning: unable to determine Beans CLI version from \`${cliPath}\`; proceeding without version compatibility checks.`
|
|
31461
|
+
);
|
|
31462
|
+
return;
|
|
31463
|
+
}
|
|
31464
|
+
if (detectedBeansVersion !== PACKAGE_VERSION) {
|
|
31465
|
+
console.error(
|
|
31466
|
+
`[beans-mcp] warning: version mismatch detected (beans=${detectedBeansVersion}, beans-mcp=${PACKAGE_VERSION}); continuing startup.`
|
|
31467
|
+
);
|
|
31468
|
+
}
|
|
31305
31469
|
}
|
|
31306
31470
|
function createHandler(backend) {
|
|
31307
31471
|
return async (input) => makeTextAndStructured({ bean: await backend.create(input) });
|
|
@@ -31337,17 +31501,56 @@ function updateHandler(backend) {
|
|
|
31337
31501
|
clearParent: input.clearParent,
|
|
31338
31502
|
blocking: input.blocking,
|
|
31339
31503
|
blockedBy: input.blockedBy,
|
|
31340
|
-
body: input.body
|
|
31504
|
+
body: input.body,
|
|
31505
|
+
bodyAppend: input.bodyAppend,
|
|
31506
|
+
bodyReplace: input.bodyReplace,
|
|
31507
|
+
ifMatch: input.ifMatch
|
|
31341
31508
|
})
|
|
31342
31509
|
});
|
|
31343
31510
|
}
|
|
31344
31511
|
function deleteHandler(backend) {
|
|
31345
|
-
return async ({ beanId, force }) => {
|
|
31346
|
-
const
|
|
31347
|
-
if (
|
|
31348
|
-
throw new Error("
|
|
31512
|
+
return async ({ beanId, beanIds, force }) => {
|
|
31513
|
+
const ids = Array.isArray(beanIds) && beanIds.length > 0 ? beanIds : beanId ? [beanId] : [];
|
|
31514
|
+
if (ids.length === 0) {
|
|
31515
|
+
throw new Error("Either beanId or beanIds must be provided");
|
|
31516
|
+
}
|
|
31517
|
+
if (ids.length === 1) {
|
|
31518
|
+
const bean = await getBeanById(backend, ids[0]);
|
|
31519
|
+
if (!force && bean.status !== "draft" && bean.status !== "scrapped") {
|
|
31520
|
+
throw new Error("Only draft and scrapped beans are deletable unless force=true");
|
|
31521
|
+
}
|
|
31522
|
+
return makeTextAndStructured(await backend.delete(ids[0]));
|
|
31349
31523
|
}
|
|
31350
|
-
|
|
31524
|
+
const beans = await backend.list();
|
|
31525
|
+
const byId = new Map(beans.map((b) => [b.id, b]));
|
|
31526
|
+
const results = [];
|
|
31527
|
+
for (const id of ids) {
|
|
31528
|
+
const bean = byId.get(id);
|
|
31529
|
+
if (!bean) {
|
|
31530
|
+
results.push({ beanId: id, deleted: false, error: "Bean not found" });
|
|
31531
|
+
continue;
|
|
31532
|
+
}
|
|
31533
|
+
if (!force && bean.status !== "draft" && bean.status !== "scrapped") {
|
|
31534
|
+
results.push({
|
|
31535
|
+
beanId: id,
|
|
31536
|
+
deleted: false,
|
|
31537
|
+
error: "Only draft and scrapped beans are deletable unless force=true"
|
|
31538
|
+
});
|
|
31539
|
+
continue;
|
|
31540
|
+
}
|
|
31541
|
+
try {
|
|
31542
|
+
await backend.delete(id);
|
|
31543
|
+
results.push({ beanId: id, deleted: true });
|
|
31544
|
+
} catch (error48) {
|
|
31545
|
+
results.push({ beanId: id, deleted: false, error: error48.message });
|
|
31546
|
+
}
|
|
31547
|
+
}
|
|
31548
|
+
return makeTextAndStructured({
|
|
31549
|
+
results,
|
|
31550
|
+
requestedCount: ids.length,
|
|
31551
|
+
deletedCount: results.filter((r) => r.deleted).length,
|
|
31552
|
+
failedCount: results.filter((r) => !r.deleted).length
|
|
31553
|
+
});
|
|
31351
31554
|
};
|
|
31352
31555
|
}
|
|
31353
31556
|
function queryHandler(backend) {
|
|
@@ -31408,7 +31611,12 @@ function registerTools(server, backend) {
|
|
|
31408
31611
|
{
|
|
31409
31612
|
title: "View Bean",
|
|
31410
31613
|
description: "Fetch full bean details by ID.",
|
|
31411
|
-
inputSchema: external_exports3.object({
|
|
31614
|
+
inputSchema: external_exports3.object({
|
|
31615
|
+
beanId: external_exports3.string().min(1).max(MAX_ID_LENGTH).optional(),
|
|
31616
|
+
beanIds: external_exports3.array(external_exports3.string().min(1).max(MAX_ID_LENGTH)).optional()
|
|
31617
|
+
}).refine((input) => Boolean(input.beanId) || Array.isArray(input.beanIds) && input.beanIds.length > 0, {
|
|
31618
|
+
message: "Either beanId or beanIds must be provided"
|
|
31619
|
+
}),
|
|
31412
31620
|
annotations: {
|
|
31413
31621
|
readOnlyHint: true,
|
|
31414
31622
|
destructiveHint: false,
|
|
@@ -31497,8 +31705,21 @@ function registerTools(server, backend) {
|
|
|
31497
31705
|
clearParent: external_exports3.boolean().optional(),
|
|
31498
31706
|
blocking: external_exports3.array(external_exports3.string().max(MAX_ID_LENGTH)).optional(),
|
|
31499
31707
|
blockedBy: external_exports3.array(external_exports3.string().max(MAX_ID_LENGTH)).optional(),
|
|
31500
|
-
body: external_exports3.string().max(MAX_DESCRIPTION_LENGTH).optional()
|
|
31501
|
-
|
|
31708
|
+
body: external_exports3.string().max(MAX_DESCRIPTION_LENGTH).optional(),
|
|
31709
|
+
bodyAppend: external_exports3.string().max(MAX_DESCRIPTION_LENGTH).optional(),
|
|
31710
|
+
bodyReplace: external_exports3.array(
|
|
31711
|
+
external_exports3.object({
|
|
31712
|
+
old: external_exports3.string().max(MAX_DESCRIPTION_LENGTH),
|
|
31713
|
+
new: external_exports3.string().max(MAX_DESCRIPTION_LENGTH)
|
|
31714
|
+
})
|
|
31715
|
+
).optional(),
|
|
31716
|
+
ifMatch: external_exports3.string().max(MAX_METADATA_LENGTH).optional()
|
|
31717
|
+
}).refine(
|
|
31718
|
+
(input) => !(input.body !== void 0 && (input.bodyAppend !== void 0 || input.bodyReplace !== void 0)),
|
|
31719
|
+
{
|
|
31720
|
+
message: "body cannot be combined with bodyAppend/bodyReplace"
|
|
31721
|
+
}
|
|
31722
|
+
),
|
|
31502
31723
|
annotations: {
|
|
31503
31724
|
readOnlyHint: false,
|
|
31504
31725
|
destructiveHint: false,
|
|
@@ -31514,8 +31735,11 @@ function registerTools(server, backend) {
|
|
|
31514
31735
|
title: "Delete Bean",
|
|
31515
31736
|
description: "Delete a bean (intended for draft/scrapped beans).",
|
|
31516
31737
|
inputSchema: external_exports3.object({
|
|
31517
|
-
beanId: external_exports3.string().min(1).max(MAX_ID_LENGTH),
|
|
31738
|
+
beanId: external_exports3.string().min(1).max(MAX_ID_LENGTH).optional(),
|
|
31739
|
+
beanIds: external_exports3.array(external_exports3.string().min(1).max(MAX_ID_LENGTH)).optional(),
|
|
31518
31740
|
force: external_exports3.boolean().default(false)
|
|
31741
|
+
}).refine((input) => Boolean(input.beanId) || Array.isArray(input.beanIds) && input.beanIds.length > 0, {
|
|
31742
|
+
message: "Either beanId or beanIds must be provided"
|
|
31519
31743
|
}),
|
|
31520
31744
|
annotations: {
|
|
31521
31745
|
readOnlyHint: false,
|
|
@@ -31532,7 +31756,7 @@ function registerTools(server, backend) {
|
|
|
31532
31756
|
title: "Query Beans",
|
|
31533
31757
|
description: "Unified query tool for refresh, filter, search, and sort operations.",
|
|
31534
31758
|
inputSchema: external_exports3.object({
|
|
31535
|
-
operation: external_exports3.enum(["refresh", "filter", "search", "sort", "llm_context", "open_config"]).default("refresh"),
|
|
31759
|
+
operation: external_exports3.enum(["refresh", "filter", "search", "sort", "ready", "llm_context", "open_config"]).default("refresh"),
|
|
31536
31760
|
mode: external_exports3.enum(["status-priority-type-title", "updated", "created", "id"]).optional(),
|
|
31537
31761
|
statuses: external_exports3.array(external_exports3.string().max(MAX_METADATA_LENGTH)).nullable().optional(),
|
|
31538
31762
|
types: external_exports3.array(external_exports3.string().max(MAX_METADATA_LENGTH)).nullable().optional(),
|
|
@@ -31614,6 +31838,12 @@ var MutableBackend = class {
|
|
|
31614
31838
|
openConfig() {
|
|
31615
31839
|
return this.inner.openConfig();
|
|
31616
31840
|
}
|
|
31841
|
+
primeInstructions() {
|
|
31842
|
+
return this.inner.primeInstructions?.() ?? Promise.resolve("");
|
|
31843
|
+
}
|
|
31844
|
+
writeInstructions(instructions) {
|
|
31845
|
+
return this.inner.writeInstructions?.(instructions) ?? Promise.resolve(null);
|
|
31846
|
+
}
|
|
31617
31847
|
graphqlSchema() {
|
|
31618
31848
|
return this.inner.graphqlSchema();
|
|
31619
31849
|
}
|
|
@@ -31651,7 +31881,7 @@ async function createBeansMcpServer(opts) {
|
|
|
31651
31881
|
const backend = opts.backend || new BeansCliBackend2(opts.workspaceRoot, opts.cliPath || "beans", opts.logDir);
|
|
31652
31882
|
const server = new McpServer({
|
|
31653
31883
|
name: opts.name || "beans-mcp-server",
|
|
31654
|
-
version: opts.version ||
|
|
31884
|
+
version: opts.version || PACKAGE_VERSION
|
|
31655
31885
|
});
|
|
31656
31886
|
registerTools(server, backend);
|
|
31657
31887
|
return { server, backend };
|
|
@@ -31723,17 +31953,17 @@ function parseCliArgs(argv) {
|
|
|
31723
31953
|
}
|
|
31724
31954
|
return { workspaceRoot, workspaceExplicit, cliPath, port, logDir };
|
|
31725
31955
|
}
|
|
31726
|
-
async function startBeansMcpServer(argv, _resolveRoots) {
|
|
31956
|
+
async function startBeansMcpServer(argv, _resolveRoots, _detectBeansVersion) {
|
|
31727
31957
|
const { BeansCliBackend: BeansCliBackend2 } = await Promise.resolve().then(() => (init_backend(), backend_exports));
|
|
31728
31958
|
const { StdioServerTransport: StdioServerTransport2 } = await Promise.resolve().then(() => (init_stdio2(), stdio_exports));
|
|
31729
31959
|
const { workspaceRoot, workspaceExplicit, cliPath, port, logDir } = parseCliArgs(argv);
|
|
31960
|
+
let effectiveWorkspaceRoot = workspaceRoot;
|
|
31730
31961
|
process.env.BEANS_VSCODE_MCP_PORT = String(port);
|
|
31731
31962
|
process.env.BEANS_MCP_PORT = String(port);
|
|
31732
31963
|
try {
|
|
31733
|
-
const version2 = package_default.version ?? "0.0.0-dev";
|
|
31734
31964
|
const workspaceLabel = workspaceExplicit ? workspaceRoot : "(auto from roots)";
|
|
31735
31965
|
console.error(
|
|
31736
|
-
`[beans-mcp] v${
|
|
31966
|
+
`[beans-mcp] v${PACKAGE_VERSION} starting (port=${port}, workspace=${workspaceLabel}, cli=${cliPath}, logDir=${logDir})`
|
|
31737
31967
|
);
|
|
31738
31968
|
} catch {
|
|
31739
31969
|
}
|
|
@@ -31750,13 +31980,17 @@ async function startBeansMcpServer(argv, _resolveRoots) {
|
|
|
31750
31980
|
const resolver = _resolveRoots ?? resolveWorkspaceFromRoots;
|
|
31751
31981
|
const rootPath = await resolver(server);
|
|
31752
31982
|
if (rootPath) {
|
|
31753
|
-
mutable.setInner(new BeansCliBackend2(rootPath, cliPath));
|
|
31983
|
+
mutable.setInner(new BeansCliBackend2(rootPath, cliPath, logDir));
|
|
31984
|
+
effectiveWorkspaceRoot = rootPath;
|
|
31754
31985
|
try {
|
|
31755
31986
|
console.error(`[beans-mcp] workspace resolved from roots: ${rootPath}`);
|
|
31756
31987
|
} catch {
|
|
31757
31988
|
}
|
|
31758
31989
|
}
|
|
31759
31990
|
}
|
|
31991
|
+
const beansVersionDetector = _detectBeansVersion ?? detectBeansCliVersion;
|
|
31992
|
+
void checkVersionCompatibility(cliPath, effectiveWorkspaceRoot, beansVersionDetector).catch(() => {
|
|
31993
|
+
});
|
|
31760
31994
|
}
|
|
31761
31995
|
|
|
31762
31996
|
// src/index.ts
|